Re: [PATCH v7 2/8] firmware: add offset to request_firmware_into_buf

2020-06-09 Thread Matthew Wilcox
On Fri, Jun 05, 2020 at 10:04:52PM -0700, Scott Branden wrote:
>  static struct fw_priv *__allocate_fw_priv(const char *fw_name,
> struct firmware_cache *fwc,
> -   void *dbuf, size_t size)
> +   void *dbuf, size_t size,
> +   size_t offset,
> +   enum kernel_pread_opt opt)
>  {

Your types are screwed up.  size_t is the size of something in memory.
loff_t is an offset in a file.  This should be an loff_t.  One of the
other patches has the opposite problem.

(this is kind of a minor problem compared to all the complexity
problems, but it's worth mentioning)


[PATCH v7 2/8] firmware: add offset to request_firmware_into_buf

2020-06-05 Thread Scott Branden
Add offset to request_firmware_into_buf to allow for portions
of firmware file to be read into a buffer.  Necessary where firmware
needs to be loaded in portions from file in memory constrained systems.

Signed-off-by: Scott Branden 
---
 drivers/base/firmware_loader/firmware.h |  5 +++
 drivers/base/firmware_loader/main.c | 53 +
 drivers/i2c/i2c-slave-eeprom.c  |  4 +-
 drivers/soc/qcom/mdt_loader.c   |  7 +++-
 include/linux/firmware.h|  8 +++-
 lib/test_firmware.c |  4 +-
 6 files changed, 59 insertions(+), 22 deletions(-)

diff --git a/drivers/base/firmware_loader/firmware.h 
b/drivers/base/firmware_loader/firmware.h
index 933e2192fbe8..c9b6ba8d29d8 100644
--- a/drivers/base/firmware_loader/firmware.h
+++ b/drivers/base/firmware_loader/firmware.h
@@ -32,6 +32,8 @@
  * @FW_OPT_FALLBACK_PLATFORM: Enable fallback to device fw copy embedded in
  * the platform's main firmware. If both this fallback and the sysfs
  *  fallback are enabled, then this fallback will be tried first.
+ * @FW_OPT_PARTIAL: Allow partial read of firmware instead of needing to read
+ * entire file.
  */
 enum fw_opt {
FW_OPT_UEVENT   = BIT(0),
@@ -41,6 +43,7 @@ enum fw_opt {
FW_OPT_NOCACHE  = BIT(4),
FW_OPT_NOFALLBACK_SYSFS = BIT(5),
FW_OPT_FALLBACK_PLATFORM= BIT(6),
+   FW_OPT_PARTIAL  = BIT(7),
 };
 
 enum fw_status {
@@ -68,6 +71,8 @@ struct fw_priv {
void *data;
size_t size;
size_t allocated_size;
+   size_t offset;
+   enum kernel_pread_opt opt;
 #ifdef CONFIG_FW_LOADER_PAGED_BUF
bool is_paged_buf;
struct page **pages;
diff --git a/drivers/base/firmware_loader/main.c 
b/drivers/base/firmware_loader/main.c
index ca871b13524e..93e7fee42cd4 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -167,7 +167,9 @@ static int fw_cache_piggyback_on_request(const char *name);
 
 static struct fw_priv *__allocate_fw_priv(const char *fw_name,
  struct firmware_cache *fwc,
- void *dbuf, size_t size)
+ void *dbuf, size_t size,
+ size_t offset,
+ enum kernel_pread_opt opt)
 {
struct fw_priv *fw_priv;
 
@@ -185,6 +187,8 @@ static struct fw_priv *__allocate_fw_priv(const char 
*fw_name,
fw_priv->fwc = fwc;
fw_priv->data = dbuf;
fw_priv->allocated_size = size;
+   fw_priv->offset = offset;
+   fw_priv->opt = opt;
fw_state_init(fw_priv);
 #ifdef CONFIG_FW_LOADER_USER_HELPER
INIT_LIST_HEAD(_priv->pending_list);
@@ -210,9 +214,11 @@ static struct fw_priv *__lookup_fw_priv(const char 
*fw_name)
 static int alloc_lookup_fw_priv(const char *fw_name,
struct firmware_cache *fwc,
struct fw_priv **fw_priv, void *dbuf,
-   size_t size, u32 opt_flags)
+   size_t size, u32 opt_flags,
+   size_t offset)
 {
struct fw_priv *tmp;
+   enum kernel_pread_opt pread_opt;
 
spin_lock(>lock);
if (!(opt_flags & FW_OPT_NOCACHE)) {
@@ -226,7 +232,12 @@ static int alloc_lookup_fw_priv(const char *fw_name,
}
}
 
-   tmp = __allocate_fw_priv(fw_name, fwc, dbuf, size);
+   if (opt_flags & FW_OPT_PARTIAL)
+   pread_opt = KERNEL_PREAD_PART;
+   else
+   pread_opt = KERNEL_PREAD_WHOLE;
+
+   tmp = __allocate_fw_priv(fw_name, fwc, dbuf, size, offset, pread_opt);
if (tmp) {
INIT_LIST_HEAD(>list);
if (!(opt_flags & FW_OPT_NOCACHE))
@@ -495,8 +506,10 @@ fw_get_filesystem_firmware(struct device *device, struct 
fw_priv *fw_priv,
fw_priv->size = 0;
 
/* load firmware files from the mount namespace of init */
-   rc = kernel_read_file_from_path_initns(path, ,
-  , msize, id);
+   rc = kernel_pread_file_from_path_initns(path, ,
+   , fw_priv->offset,
+   msize,
+   fw_priv->opt, id);
if (rc) {
if (rc != -ENOENT)
dev_warn(device, "loading %s failed with error 
%d\n",
@@ -683,7 +696,7 @@ int assign_fw(struct firmware *fw, struct device *device, 
u32 opt_flags)
 static int
 _request_firmware_prepare(struct firmware **firmware_p, const char *name,
  struct device *device, void *dbuf, size_t size,
- u32 opt_flags)