firmware: add request_partial_firmware_into_buf
Subsystems (13)
Scott Branden
maintainerv8 cover firmware: add request_partial_firmware_into_buf
This patch series adds partial read support via a new call request_partial_firmware_into_buf.
Such support is needed when the whole file is not needed and/or only a smaller portion of the file will fit into allocated memory at any one time.
In order to accept the enhanced API it has been requested that kernel selftests and upstreamed driver utilize the API enhancement and so are included in this patch series.
Also in this patch series is the addition of a new Broadcom VK driver utilizing the new request_firmware_into_buf enhanced API.
Further comment followed to add IMA support of the partial reads originating from request_firmware_into_buf calls.
Changes from v8:
- removed swiss army knife kernel_pread_* style approach
and simply add offset parameter in addition to those needed in kernel_read_* functions thus removing need for kernel_pread enum
Changes from v6:
- update ima_post_read_file check on IMA_FIRMWARE_PARTIAL_READ
- adjust new driver i2c-slave-eeprom.c use of request_firmware_into_buf
- remove an extern
Changes from v5:
- add IMA FIRMWARE_PARTIAL_READ support
- change kernel pread flags to enum
- removed legacy support from driver
- driver fixes
Changes from v4:
- handle reset issues if card crashes
- allow driver to have min required msix
- add card utilization information
Changes from v3:
- fix sparse warnings
- fix printf format specifiers for size_t
- fix 32-bit cross-compiling reports 32-bit shifts
- use readl/writel,_relaxed to access pci ioremap memory, removed memory barriers and volatile keyword with such change
- driver optimizations for interrupt/poll functionalities
Changes from v2:
- remove unnecessary code and mutex locks in lib/test_firmware.c
- remove VK_IOCTL_ACCESS_BAR support from driver and use pci sysfs instead
- remove bitfields
- remove Kconfig default m
- adjust formatting and some naming based on feedback
- fix error handling conditions
- use appropriate return codes
- use memcpy_toio instead of direct access to PCIE bar
Scott Branden (8):
fs: introduce kernel_pread_file* support
firmware: add offset to request_firmware_into_buf
test_firmware: add partial read support for request_firmware_into_buf
firmware: test partial file reads of request_firmware_into_buf
bcm-vk: add bcm_vk UAPI
misc: bcm-vk: add Broadcom VK driver
MAINTAINERS: bcm-vk: add maintainer for Broadcom VK Driver
ima: add FIRMWARE_PARTIAL_READ support
MAINTAINERS | 7 + drivers/base/firmware_loader/firmware.h | 5 + drivers/base/firmware_loader/main.c | 79 +- drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/bcm-vk/Kconfig | 29 + drivers/misc/bcm-vk/Makefile | 11 + drivers/misc/bcm-vk/bcm_vk.h | 407 +++++ drivers/misc/bcm-vk/bcm_vk_dev.c | 1310 +++++++++++++++ drivers/misc/bcm-vk/bcm_vk_msg.c | 1440 +++++++++++++++++ drivers/misc/bcm-vk/bcm_vk_msg.h | 202 +++ drivers/misc/bcm-vk/bcm_vk_sg.c | 271 ++++ drivers/misc/bcm-vk/bcm_vk_sg.h | 60 + drivers/misc/bcm-vk/bcm_vk_tty.c | 352 ++++ fs/exec.c | 93 +- include/linux/firmware.h | 12 + include/linux/fs.h | 15 + include/uapi/linux/misc/bcm_vk.h | 99 ++ lib/test_firmware.c | 154 +- security/integrity/ima/ima_main.c | 24 +- .../selftests/firmware/fw_filesystem.sh | 80 + 21 files changed, 4599 insertions(+), 53 deletions(-) create mode 100644 drivers/misc/bcm-vk/Kconfig create mode 100644 drivers/misc/bcm-vk/Makefile create mode 100644 drivers/misc/bcm-vk/bcm_vk.h create mode 100644 drivers/misc/bcm-vk/bcm_vk_dev.c create mode 100644 drivers/misc/bcm-vk/bcm_vk_msg.c create mode 100644 drivers/misc/bcm-vk/bcm_vk_msg.h create mode 100644 drivers/misc/bcm-vk/bcm_vk_sg.c create mode 100644 drivers/misc/bcm-vk/bcm_vk_sg.h create mode 100644 drivers/misc/bcm-vk/bcm_vk_tty.c create mode 100644 include/uapi/linux/misc/bcm_vk.h
Signature · 1 line
2.17.1
Scott Branden
maintainerPATCH v8 1/8 fs: introduce kernel_pread_file* support
Add kernel_pread_file* support to kernel to allow for partial read of files with an offset into the file.
--- fs/exec.c | 93 ++++++++++++++++++++++++++++++++++------------ include/linux/fs.h | 15 ++++++++ 2 files changed, 85 insertions(+), 23 deletions(-)
fs/exec.c +70 -23
@@ -927,10 +927,14 @@ struct file *open_exec(const char *name) }EXPORT_SYMBOL (open_exec); -int kernel_read_file (struct file *file,void **buf,loff_t *size, -loff_t max_size,enum kernel_read_file_id id) -{ -loff_t i_size, pos; +int kernel_pread_file (struct file *file,void **buf,loff_t *size, +loff_t max_size,loff_t pos, +enum kernel_read_file_id id) +{ +loff_t alloc_size; +loff_t buf_pos; +loff_t read_end; +loff_t i_size;ssize_t bytes =0 ;int ret;
@@ -950,21 +954,32 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, ret = -EINVAL ; goto out; } -if (i_size >SIZE_MAX || (max_size >0 && i_size > max_size)) { + +/* Default read to end of file */ + read_end = i_size; + +/* Allow reading partial portion of file */ +if ((id ==READING_FIRMWARE_PARTIAL_READ ) && + (i_size > (pos + max_size))) + read_end = pos + max_size; + + alloc_size = read_end - pos; +if (i_size >SIZE_MAX || (max_size >0 && alloc_size > max_size)) { ret = -EFBIG ; goto out; } -if (id !=READING_FIRMWARE_PREALLOC_BUFFER ) - *buf =vmalloc (i_size); +if ((id !=READING_FIRMWARE_PARTIAL_READ ) && + (id !=READING_FIRMWARE_PREALLOC_BUFFER )) + *buf =vmalloc (alloc_size);if (!*buf) { ret = -ENOMEM ; goto out; } - pos =0 ; -while (pos < i_size) { - bytes =kernel_read (file, *buf + pos, i_size - pos, &pos); + buf_pos =0 ; +while (pos < read_end) { + bytes =kernel_read (file, *buf + buf_pos, read_end - pos, &pos);if (bytes <0 ) { ret = bytes; goto out_free;
@@ -972,20 +987,23 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,if (bytes ==0 )break ; + + buf_pos += bytes; } -if (pos != i_size) { +if (pos != read_end) { ret = -EIO ; goto out_free; } - ret =security_kernel_post_read_file (file, *buf, i_size, id); + ret =security_kernel_post_read_file (file, *buf, alloc_size, id);if (!ret) *size = pos; out_free:if (ret <0 ) { -if (id !=READING_FIRMWARE_PREALLOC_BUFFER ) { +if ((id !=READING_FIRMWARE_PARTIAL_READ ) && + (id !=READING_FIRMWARE_PREALLOC_BUFFER )) {vfree (*buf); *buf =NULL ; }
@@ -995,10 +1013,18 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,allow_write_access (file);return ret; } + +int kernel_read_file (struct file *file,void **buf,loff_t *size, +loff_t max_size,enum kernel_read_file_id id) +{ +return kernel_pread_file (file, buf, size, max_size,0 , id); +}EXPORT_SYMBOL_GPL (kernel_read_file); -int kernel_read_file_from_path (const char *path,void **buf,loff_t *size, -loff_t max_size,enum kernel_read_file_id id) +int kernel_pread_file_from_path (const char *path,void **buf, +loff_t *size, +loff_t max_size,loff_t pos, +enum kernel_read_file_id id) {struct file *file;int ret;
@@ -1010,15 +1036,22 @@ int kernel_read_file_from_path(const char *path, void **buf, loff_t *size,if (IS_ERR (file))return PTR_ERR (file); - ret =kernel_read_file (file, buf, size, max_size, id); + ret =kernel_pread_file (file, buf, size, max_size, pos, id);fput (file);return ret; } + +int kernel_read_file_from_path (const char *path,void **buf,loff_t *size, +loff_t max_size,enum kernel_read_file_id id) +{ +return kernel_pread_file_from_path (path, buf, size, max_size,0 , id); +}EXPORT_SYMBOL_GPL (kernel_read_file_from_path); -int kernel_read_file_from_path_initns (const char *path,void **buf, -loff_t *size,loff_t max_size, -enum kernel_read_file_id id) +int kernel_pread_file_from_path_initns (const char *path,void **buf, +loff_t *size, +loff_t max_size,loff_t pos, +enum kernel_read_file_id id) {struct file *file;struct path root;
@@ -1036,14 +1069,22 @@ int kernel_read_file_from_path_initns(const char *path, void **buf,if (IS_ERR (file))return PTR_ERR (file); - ret =kernel_read_file (file, buf, size, max_size, id); + ret =kernel_pread_file (file, buf, size, max_size, pos, id);fput (file);return ret; } + +int kernel_read_file_from_path_initns (const char *path,void **buf, +loff_t *size,loff_t max_size, +enum kernel_read_file_id id) +{ +return kernel_pread_file_from_path_initns (path, buf, size, max_size,0 , id); +}EXPORT_SYMBOL_GPL (kernel_read_file_from_path_initns); -int kernel_read_file_from_fd (int fd,void **buf,loff_t *size,loff_t max_size, -enum kernel_read_file_id id) +int kernel_pread_file_from_fd (int fd,void **buf,loff_t *size, +loff_t max_size,loff_t pos, +enum kernel_read_file_id id) {struct fd f =fdget (fd);int ret = -EBADF ;
@@ -1051,11 +1092,17 @@ int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,if (!f.file) goto out; - ret =kernel_read_file (f.file, buf, size, max_size, id); + ret =kernel_pread_file (f.file, buf, size, max_size, pos, id); out:fdput (f);return ret; } + +int kernel_read_file_from_fd (int fd,void **buf,loff_t *size,loff_t max_size, +enum kernel_read_file_id id) +{ +return kernel_pread_file_from_fd (fd, buf, size, max_size,0 , id); +}EXPORT_SYMBOL_GPL (kernel_read_file_from_fd); #if defined(CONFIG_HAVE_AOUT) || defined(CONFIG_BINFMT_FLAT) || \
include/linux/fs.h +15 -0
@@ -3012,6 +3012,7 @@ extern int do_pipe_flags(int *, int);#define __kernel_read_file_id (id) \ id(UNKNOWN, unknown) \ id(FIRMWARE, firmware) \ + id(FIRMWARE_PARTIAL_READ, firmware) \ id(FIRMWARE_PREALLOC_BUFFER, firmware) \ id(FIRMWARE_EFI_EMBEDDED, firmware) \ id(MODULE, kernel-module) \
@@ -3040,12 +3041,26 @@ static inline const char *kernel_read_file_id_str(enum kernel_read_file_id id)return kernel_read_file_str[id]; } +int kernel_pread_file (struct file *file,void **buf,loff_t *size, +loff_t pos,loff_t max_size, +enum kernel_read_file_id id);extern int kernel_read_file (struct file *,void **,loff_t *,loff_t ,enum kernel_read_file_id ); +int kernel_pread_file_from_path (const char *path,void **buf, +loff_t *size,loff_t pos, +loff_t max_size, +enum kernel_read_file_id id);extern int kernel_read_file_from_path (const char *,void **,loff_t *,loff_t ,enum kernel_read_file_id ); +int kernel_pread_file_from_path_initns (const char *path,void **buf, +loff_t *size,loff_t pos, +loff_t max_size, +enum kernel_read_file_id id);extern int kernel_read_file_from_path_initns (const char *,void **,loff_t *,loff_t ,enum kernel_read_file_id ); +int kernel_pread_file_from_fd (int fd,void **buf,loff_t *size, +loff_t pos,loff_t max_size, +enum kernel_read_file_id id);extern int kernel_read_file_from_fd (int ,void **,loff_t *,loff_t ,enum kernel_read_file_id );extern ssize_t kernel_read (struct file *,void *,size_t ,loff_t *);
Signature · 1 line
2.17.1
Scott Branden
maintainerPATCH v8 2/8 firmware: add offset to request_firmware_into_buf
In reply to Scott BrandenAdd 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.
--- drivers/base/firmware_loader/firmware.h | 5 ++ drivers/base/firmware_loader/main.c | 79 +++++++++++++++++++------ include/linux/firmware.h | 12 ++++ 3 files changed, 79 insertions(+), 17 deletions(-)
drivers/base/firmware_loader/firmware.h +5 -0
@@ -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; +u32 opt_flags;#ifdef CONFIG_FW_LOADER_PAGED_BUF bool is_paged_buf;struct page **pages;
drivers/base/firmware_loader/main.c +62 -17
181 lines not on this page · raw message
include/linux/firmware.h +12 -0
@@ -53,6 +53,9 @@ int request_firmware_direct(const struct firmware **fw, const char *name, struct device *device);int request_firmware_into_buf (const struct firmware **firmware_p,const char *name,struct device *device,void *buf,size_t size); +int request_partial_firmware_into_buf (const struct firmware **firmware_p, +const char *name,struct device *device, +void *buf,size_t size,size_t offset);void release_firmware (const struct firmware *fw);#else
@@ -102,6 +105,15 @@ static inline int request_firmware_into_buf(const struct firmware **firmware_p, return -EINVAL; } +static inline int request_partial_firmware_into_buf + (const struct firmware **firmware_p, +const char *name, +struct device *device, +void *buf,size_t size,offset ) +{ +return -EINVAL ; +} +#endif int firmware_request_cache (struct device *device,const char *name);
Signature · 1 line
2.17.1
kernel test robot
build botRe: [PATCH v8 2/8] firmware: add offset to request_firmware_into_buf
I love your patch! Yet something to improve:
Hi Scott,
I love your patch! Yet something to improve:
[auto build test ERROR on driver-core/driver-core-testing]
[also build test ERROR on linus/master next-20200611]
[cannot apply to char-misc/char-misc-testing kselftest/next integrity/next-integrity v5.7] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Scott-Branden/firmware-add-request_partial_firmware_into_buf/20200610-070056 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git abfbb29297c27e3f101f348dc9e467b0fe70f919 config: nios2-randconfig-r015-20200612 (attached as .config) compiler: nios2-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=nios2
If you fix the issue, kindly add following tag as appropriate
All errors (new ones prefixed by >>, old ones prefixed by <<):
In file included from drivers/staging/gs_fpgaboot/gs_fpgaboot.c:15:
>> include/linux/firmware.h:112:31: error: unknown type name 'offset'; did you mean 'off_t'? 112 | void *buf, size_t size, offset) | ^~~~~~ | off_t
vim +112 include/linux/firmware.h
107
108 static inline int request_partial_firmware_into_buf
109 (const struct firmware **firmware_p,
110 const char *name,
111 struct device *device,
> 112 void *buf, size_t size, offset)
113 {
114 return -EINVAL;
115 }
116
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
Scott Branden
maintainerPATCH v8 3/8 test_firmware: add partial read support for request_firmware_into_buf
In reply to Scott BrandenAdd additional hooks to test_firmware to pass in support for partial file read using request_firmware_into_buf.buf_size: size of buffer to request firmware into
partial: indicates that a partial file request is being madefile_offset: to indicate offset into file to request
--- lib/test_firmware.c | 154 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 142 insertions(+), 12 deletions(-)
lib/test_firmware.c +142 -12
@@ -50,6 +50,9 @@ struct test_batched_req {* @name: the name of the firmware file to look for * @into_buf: when the into_buf is used if this is true * request_firmware_into_buf() will be used instead. +* @buf_size: size of buf to allocate when into_buf is true +* @file_offset: file offset to request when calling request_firmware_into_buf +* @partial: partial read opt when calling request_firmware_into_buf * @sync_direct: when the sync trigger is used if this is true * request_firmware_direct() will be used instead. * @send_uevent: whether or not to send a uevent for async requests
@@ -89,6 +92,9 @@ struct test_batched_req {struct test_config {char *name;bool into_buf; +size_t buf_size; +size_t file_offset; +bool partial;bool sync_direct;bool send_uevent;u8 num_requests;
@@ -183,6 +189,9 @@ static int __test_firmware_config_init(void) test_fw_config->num_requests =TEST_FIRMWARE_NUM_REQS ; test_fw_config->send_uevent = true; test_fw_config->into_buf = false; + test_fw_config->buf_size =TEST_FIRMWARE_BUF_SIZE ; + test_fw_config->file_offset =0 ; + test_fw_config->partial = false; test_fw_config->sync_direct = false; test_fw_config->req_firmware = request_firmware; test_fw_config->test_result =0 ;
@@ -236,28 +245,35 @@ static ssize_t config_show(struct device *dev, dev_name(dev));if (test_fw_config->name) - len +=scnprintf (buf+len,PAGE_SIZE - len, + len +=scnprintf (buf + len,PAGE_SIZE - len,"name:\t%s\n" , test_fw_config->name);else - len +=scnprintf (buf+len,PAGE_SIZE - len, + len +=scnprintf (buf + len,PAGE_SIZE - len,"name:\tEMTPY\n" ); - len +=scnprintf (buf+len,PAGE_SIZE - len, + len +=scnprintf (buf + len,PAGE_SIZE - len,"num_requests:\t%u\n" , test_fw_config->num_requests); - len +=scnprintf (buf+len,PAGE_SIZE - len, + len +=scnprintf (buf + len,PAGE_SIZE - len,"send_uevent:\t\t%s\n" , test_fw_config->send_uevent ?"FW_ACTION_HOTPLUG" :"FW_ACTION_NOHOTPLUG" ); - len +=scnprintf (buf+len,PAGE_SIZE - len, + len +=scnprintf (buf + len,PAGE_SIZE - len,"into_buf:\t\t%s\n" , test_fw_config->into_buf ?"true" :"false" ); - len +=scnprintf (buf+len,PAGE_SIZE - len, + len +=scnprintf (buf + len,PAGE_SIZE - len, +"buf_size:\t%zu\n" , test_fw_config->buf_size); + len +=scnprintf (buf + len,PAGE_SIZE - len, +"file_offset:\t%zu\n" , test_fw_config->file_offset); + len +=scnprintf (buf + len,PAGE_SIZE - len, +"partial:\t\t%s\n" , + test_fw_config->partial ?"true" :"false" ); + len +=scnprintf (buf + len,PAGE_SIZE - len,"sync_direct:\t\t%s\n" , test_fw_config->sync_direct ?"true" :"false" ); - len +=scnprintf (buf+len,PAGE_SIZE - len, + len +=scnprintf (buf + len,PAGE_SIZE - len,"read_fw_idx:\t%u\n" , test_fw_config->read_fw_idx);mutex_unlock (&test_fw_mutex);
@@ -315,6 +331,30 @@ static ssize_t test_dev_config_show_bool(char *buf, bool val)return snprintf (buf,PAGE_SIZE ,"%d\n" , val); } +static int test_dev_config_update_size_t (const char *buf, +size_t size, +size_t *cfg) +{ +int ret; +long new; + + ret =kstrtol (buf,10 , &new); +if (ret) +return ret; + +mutex_lock (&test_fw_mutex); + *(size_t *)cfg = new; +mutex_unlock (&test_fw_mutex); + +/* Always return full write size even if we didn't consume all */ +return size; +} + +static ssize_t test_dev_config_show_size_t (char *buf,size_t val) +{ +return snprintf (buf,PAGE_SIZE ,"%zu\n" , val); +} +static ssize_t test_dev_config_show_int (char *buf,int val) {return snprintf (buf,PAGE_SIZE ,"%d\n" , val);
@@ -400,6 +440,83 @@ static ssize_t config_into_buf_show(struct device *dev, }static DEVICE_ATTR_RW (config_into_buf); +static ssize_t config_buf_size_store (struct device *dev, +struct device_attribute *attr, +const char *buf,size_t count) +{ +int rc; + +mutex_lock (&test_fw_mutex); +if (test_fw_config->reqs) { +pr_err ("Must call release_all_firmware prior to changing config\n" ); + rc = -EINVAL ; +mutex_unlock (&test_fw_mutex); + goto out; + } +mutex_unlock (&test_fw_mutex); + + rc =test_dev_config_update_size_t (buf, count, + &test_fw_config->buf_size); + +out: +return rc; +} + +static ssize_t config_buf_size_show (struct device *dev, +struct device_attribute *attr, +char *buf) +{ +return test_dev_config_show_size_t (buf, test_fw_config->buf_size); +} +static DEVICE_ATTR_RW (config_buf_size); + +static ssize_t config_file_offset_store (struct device *dev, +struct device_attribute *attr, +const char *buf,size_t count) +{ +int rc; + +mutex_lock (&test_fw_mutex); +if (test_fw_config->reqs) { +pr_err ("Must call release_all_firmware prior to changing config\n" ); + rc = -EINVAL ; +mutex_unlock (&test_fw_mutex); + goto out; + } +mutex_unlock (&test_fw_mutex); + + rc =test_dev_config_update_size_t (buf, count, + &test_fw_config->file_offset); + +out: +return rc; +} + +static ssize_t config_file_offset_show (struct device *dev, +struct device_attribute *attr, +char *buf) +{ +return test_dev_config_show_size_t (buf, test_fw_config->file_offset); +} +static DEVICE_ATTR_RW (config_file_offset); + +static ssize_t config_partial_store (struct device *dev, +struct device_attribute *attr, +const char *buf,size_t count) +{ +return test_dev_config_update_bool (buf, + count, + &test_fw_config->partial); +} + +static ssize_t config_partial_show (struct device *dev, +struct device_attribute *attr, +char *buf) +{ +return test_dev_config_show_bool (buf, test_fw_config->partial); +} +static DEVICE_ATTR_RW (config_partial); +static ssize_t config_sync_direct_store (struct device *dev,struct device_attribute *attr,const char *buf,size_t count)
@@ -650,11 +767,21 @@ static int test_fw_run_batch_request(void *data)if (!test_buf)return -ENOSPC ; - req->rc =request_firmware_into_buf (&req->fw, - req->name, - req->dev, - test_buf, -TEST_FIRMWARE_BUF_SIZE ); +if (test_fw_config->partial) + req->rc =request_partial_firmware_into_buf + (&req->fw, + req->name, + req->dev, + test_buf, + test_fw_config->buf_size, + test_fw_config->file_offset); +else + req->rc =request_firmware_into_buf + (&req->fw, + req->name, + req->dev, + test_buf, + test_fw_config->buf_size);if (!req->fw)kfree (test_buf); }else {
@@ -927,6 +1054,9 @@ static struct attribute *test_dev_attrs[] = {TEST_FW_DEV_ATTR (config_name),TEST_FW_DEV_ATTR (config_num_requests),TEST_FW_DEV_ATTR (config_into_buf), +TEST_FW_DEV_ATTR (config_buf_size), +TEST_FW_DEV_ATTR (config_file_offset), +TEST_FW_DEV_ATTR (config_partial),TEST_FW_DEV_ATTR (config_sync_direct),TEST_FW_DEV_ATTR (config_send_uevent), TEST_FW_DEV_ATTR(config_read_fw_idx),
Signature · 1 line
2.17.1
Scott Branden
maintainerPATCH v8 4/8 firmware: test partial file reads of request_firmware_into_buf
In reply to Scott BrandenAdd firmware tests for partial file reads of request_firmware_into_buf.
--- .../selftests/firmware/fw_filesystem.sh | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+)
tools/testing/selftests/firmware/fw_filesystem.sh +80 -0
@@ -149,6 +149,26 @@ config_unset_into_buf() echo 0 > $DIR/config_into_buf } +config_set_buf_size() +{ + echo $1 > $DIR/config_buf_size +} + +config_set_file_offset() +{ + echo $1 > $DIR/config_file_offset +} + +config_set_partial() +{ + echo 1 > $DIR/config_partial +} + +config_unset_partial() +{ + echo 0 > $DIR/config_partial +} + config_set_sync_direct() { echo 1 > $DIR/config_sync_direct
@@ -207,6 +227,35 @@ read_firmwares() done } +read_partial_firmwares() +{ + if [ "$(cat $DIR/config_into_buf)" == "1" ]; then + fwfile="${FW_INTO_BUF}" + else + fwfile="${FW}" + fi + + if [ "$1" = "xzonly" ]; then + fwfile="${fwfile}-orig" + fi + + # Strip fwfile down to match partial offset and length + partial_data="$(cat $fwfile)" + partial_data="${partial_data:$2:$3}" + + for i in $(seq 0 3); do + config_set_read_fw_idx $i + + read_firmware="$(cat $DIR/read_firmware)" + + # Verify the contents are what we expect. + if [ $read_firmware != $partial_data ]; then + echo "request #$i: partial firmware was not loaded" >&2 + exit 1 + fi + done +} + read_firmwares_expect_nofile() { for i in $(seq 0 3); do
@@ -319,6 +368,21 @@ test_batched_request_firmware_into_buf() echo "OK" } +test_batched_request_partial_firmware_into_buf() +{ + echo -n "Batched request_partial_firmware_into_buf() $2 off=$3 size=$4 try #$1: " + config_reset + config_set_name $TEST_FIRMWARE_INTO_BUF_FILENAME + config_set_into_buf + config_set_partial + config_set_buf_size $4 + config_set_file_offset $3 + config_trigger_sync + read_partial_firmwares $2 $3 $4 + release_all_firmware + echo "OK" +} + test_batched_request_firmware_direct() { echo -n "Batched request_firmware_direct() $2 try #$1: "
@@ -371,6 +435,22 @@ for i in $(seq 1 5); do test_batched_request_firmware_into_buf $i normal done +for i in $(seq 1 5); do + test_batched_request_partial_firmware_into_buf $i normal 0 10 +done + +for i in $(seq 1 5); do + test_batched_request_partial_firmware_into_buf $i normal 0 5 +done + +for i in $(seq 1 5); do + test_batched_request_partial_firmware_into_buf $i normal 1 6 +done + +for i in $(seq 1 5); do + test_batched_request_partial_firmware_into_buf $i normal 2 10 +done + for i in $(seq 1 5); do test_batched_request_firmware_direct $i normal done
Signature · 1 line
2.17.1
Scott Branden
maintainerPATCH v8 5/8 bcm-vk: add bcm_vk UAPI
In reply to Scott BrandenAdd user space api for bcm-vk driver.
--- include/uapi/linux/misc/bcm_vk.h | 99 ++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 include/uapi/linux/misc/bcm_vk.h
include/uapi/linux/misc/bcm_vk.h new file +99 -0
@@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) */ +/* +* Copyright 2018-2020 Broadcom. +*/ + +#ifndef __UAPI_LINUX_MISC_BCM_VK_H +#define __UAPI_LINUX_MISC_BCM_VK_H + +#include <linux/ioctl.h> +#include <linux/types.h> + +#define BCM_VK_MAX_FILENAME 64 + +struct vk_image { +__u32 type;/* Type of image */ +#define VK_IMAGE_TYPE_BOOT1 1/* 1st stage (load to SRAM) */ +#define VK_IMAGE_TYPE_BOOT2 2/* 2nd stage (load to DDR) */ +char filename[BCM_VK_MAX_FILENAME ];/* Filename of image */ +}; + +struct vk_reset { +__u32 arg1; +__u32 arg2; +}; + +#define VK_MAGIC 0x5e + +/* Load image to Valkyrie */ +#define VK_IOCTL_LOAD_IMAGE _IOW(VK_MAGIC, 0x2, struct vk_image) + +/* Send Reset to Valkyrie */ +#define VK_IOCTL_RESET _IOW(VK_MAGIC, 0x4, struct vk_reset) + +/* +* message block - basic unit in the message where a message's size is always +* N x sizeof(basic_block) +*/ +struct vk_msg_blk { +__u8 function_id; +#define VK_FID_TRANS_BUF 5 +#define VK_FID_SHUTDOWN 8 +__u8 size; +__u16 trans_id;/* transport id, queue & msg_id */ +__u32 context_id; +__u32 args[2 ]; +#define VK_CMD_PLANES_MASK 0x000f/* number of planes to up/download */ +#define VK_CMD_UPLOAD 0x0400/* memory transfer to vk */ +#define VK_CMD_DOWNLOAD 0x0500/* memory transfer from vk */ +#define VK_CMD_MASK 0x0f00/* command mask */ +}; + +#define VK_BAR_FWSTS 0x41c +#define VK_BAR_COP_FWSTS 0x428 +/* VK_FWSTS definitions */ +#define VK_FWSTS_RELOCATION_ENTRY BIT(0) +#define VK_FWSTS_RELOCATION_EXIT BIT(1) +#define VK_FWSTS_INIT_START BIT(2) +#define VK_FWSTS_ARCH_INIT_DONE BIT(3) +#define VK_FWSTS_PRE_KNL1_INIT_DONE BIT(4) +#define VK_FWSTS_PRE_KNL2_INIT_DONE BIT(5) +#define VK_FWSTS_POST_KNL_INIT_DONE BIT(6) +#define VK_FWSTS_INIT_DONE BIT(7) +#define VK_FWSTS_APP_INIT_START BIT(8) +#define VK_FWSTS_APP_INIT_DONE BIT(9) +#define VK_FWSTS_MASK 0xffffffff +#define VK_FWSTS_READY (VK_FWSTS_INIT_START | \ + VK_FWSTS_ARCH_INIT_DONE | \ + VK_FWSTS_PRE_KNL1_INIT_DONE | \ + VK_FWSTS_PRE_KNL2_INIT_DONE | \ + VK_FWSTS_POST_KNL_INIT_DONE | \ + VK_FWSTS_INIT_DONE | \ + VK_FWSTS_APP_INIT_START | \ + VK_FWSTS_APP_INIT_DONE) +/* Deinit */ +#define VK_FWSTS_APP_DEINIT_START BIT(23) +#define VK_FWSTS_APP_DEINIT_DONE BIT(24) +#define VK_FWSTS_DRV_DEINIT_START BIT(25) +#define VK_FWSTS_DRV_DEINIT_DONE BIT(26) +#define VK_FWSTS_RESET_DONE BIT(27) +#define VK_FWSTS_DEINIT_TRIGGERED (VK_FWSTS_APP_DEINIT_START | \ + VK_FWSTS_APP_DEINIT_DONE | \ + VK_FWSTS_DRV_DEINIT_START | \ + VK_FWSTS_DRV_DEINIT_DONE) +/* Last nibble for reboot reason */ +#define VK_FWSTS_RESET_REASON_SHIFT 28 +#define VK_FWSTS_RESET_REASON_MASK (0xf << VK_FWSTS_RESET_REASON_SHIFT) +#define VK_FWSTS_RESET_SYS_PWRUP (0x0 << VK_FWSTS_RESET_REASON_SHIFT) +#define VK_FWSTS_RESET_MBOX_DB (0x1 << VK_FWSTS_RESET_REASON_SHIFT) +#define VK_FWSTS_RESET_M7_WDOG (0x2 << VK_FWSTS_RESET_REASON_SHIFT) +#define VK_FWSTS_RESET_TEMP (0x3 << VK_FWSTS_RESET_REASON_SHIFT) +#define VK_FWSTS_RESET_PCI_FLR (0x4 << VK_FWSTS_RESET_REASON_SHIFT) +#define VK_FWSTS_RESET_PCI_HOT (0x5 << VK_FWSTS_RESET_REASON_SHIFT) +#define VK_FWSTS_RESET_PCI_WARM (0x6 << VK_FWSTS_RESET_REASON_SHIFT) +#define VK_FWSTS_RESET_PCI_COLD (0x7 << VK_FWSTS_RESET_REASON_SHIFT) +#define VK_FWSTS_RESET_L1 (0x8 << VK_FWSTS_RESET_REASON_SHIFT) +#define VK_FWSTS_RESET_L0 (0x9 << VK_FWSTS_RESET_REASON_SHIFT) +#define VK_FWSTS_RESET_UNKNOWN (0xf << VK_FWSTS_RESET_REASON_SHIFT) + +#endif /* __UAPI_LINUX_MISC_BCM_VK_H */
Signature · 1 line
2.17.1
Scott Branden
maintainerPATCH v8 6/8 misc: bcm-vk: add Broadcom VK driver
In reply to Scott BrandenAdd Broadcom VK driver offload engine.
This driver interfaces to the VK PCIe offload engine to perform should offload functions as video transcoding on multiple streams in parallel. VK device is booted from files loaded using request_firmware_into_buf mechanism. After booted card status is updated and messages can then be sent to the card.
Such messages contain scatter gather list of addresses
to pull data from the host to perform operations on.
--- drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/bcm-vk/Kconfig | 29 + drivers/misc/bcm-vk/Makefile | 11 + drivers/misc/bcm-vk/bcm_vk.h | 407 +++++++++ drivers/misc/bcm-vk/bcm_vk_dev.c | 1310 +++++++++++++++++++++++++++ drivers/misc/bcm-vk/bcm_vk_msg.c | 1440 ++++++++++++++++++++++++++++++ drivers/misc/bcm-vk/bcm_vk_msg.h | 202 +++++ drivers/misc/bcm-vk/bcm_vk_sg.c | 271 ++++++ drivers/misc/bcm-vk/bcm_vk_sg.h | 60 ++ drivers/misc/bcm-vk/bcm_vk_tty.c | 352 ++++++++ 11 files changed, 4084 insertions(+) create mode 100644 drivers/misc/bcm-vk/Kconfig create mode 100644 drivers/misc/bcm-vk/Makefile create mode 100644 drivers/misc/bcm-vk/bcm_vk.h create mode 100644 drivers/misc/bcm-vk/bcm_vk_dev.c create mode 100644 drivers/misc/bcm-vk/bcm_vk_msg.c create mode 100644 drivers/misc/bcm-vk/bcm_vk_msg.h create mode 100644 drivers/misc/bcm-vk/bcm_vk_sg.c create mode 100644 drivers/misc/bcm-vk/bcm_vk_sg.h create mode 100644 drivers/misc/bcm-vk/bcm_vk_tty.c
drivers/misc/Kconfig +1 -0
@@ -469,6 +469,7 @@ source "drivers/misc/genwqe/Kconfig" source "drivers/misc/echo/Kconfig" source "drivers/misc/cxl/Kconfig" source "drivers/misc/ocxl/Kconfig" +source "drivers/misc/bcm-vk/Kconfig" source "drivers/misc/cardreader/Kconfig" source "drivers/misc/habanalabs/Kconfig" source "drivers/misc/uacce/Kconfig"
drivers/misc/Makefile +1 -0
@@ -52,6 +52,7 @@ obj-$(CONFIG_ECHO) += echo/ obj-$(CONFIG_CXL_BASE) += cxl/ obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o obj-$(CONFIG_OCXL) += ocxl/ +obj-$(CONFIG_BCM_VK) += bcm-vk/ obj-y += cardreader/ obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_HABANA_AI) += habanalabs/
drivers/misc/bcm-vk/Kconfig new file +29 -0
@@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Broadcom VK device +# +config BCM_VK + tristate "Support for Broadcom VK Accelerators" + depends on PCI_MSI + help + Select this option to enable support for Broadcom + VK Accelerators. VK is used for performing + specific offload processing. + This driver enables userspace programs to access these + accelerators via /dev/bcm-vk.N devices. + + If unsure, say N. + +if BCM_VK + +config BCM_VK_QSTATS + bool "VK Queue Statistics" + help + Turn on to enable Queue Statistics. + These are useful for debugging purposes. + Some performance loss by enabling this debug config. + For properly operating PCIe hardware no need to enable this. + + If unsure, say N. + +endif
drivers/misc/bcm-vk/Makefile new file +11 -0
@@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for Broadcom VK driver +# + +obj-$(CONFIG_BCM_VK) += bcm_vk.o +bcm_vk-objs := \ + bcm_vk_dev.o \ + bcm_vk_msg.o \ + bcm_vk_sg.o \ + bcm_vk_tty.o
drivers/misc/bcm-vk/bcm_vk.h new file +407 -0
407 lines not on this page · raw message
drivers/misc/bcm-vk/bcm_vk_dev.c new file +1310 -0
1,310 lines not on this page · raw message
drivers/misc/bcm-vk/bcm_vk_msg.c new file +1440 -0
1,229 lines not on this page · raw message
drivers/misc/bcm-vk/bcm_vk_msg.h new file +202 -0
202 lines not on this page · raw message
drivers/misc/bcm-vk/bcm_vk_sg.c new file +271 -0
271 lines not on this page · raw message
drivers/misc/bcm-vk/bcm_vk_sg.h new file +60 -0
60 lines not on this page · raw message
drivers/misc/bcm-vk/bcm_vk_tty.c new file +352 -0
352 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.17.1
Part of the diff is not shown here. View the raw message.
Scott Branden
maintainerPATCH v8 7/8 MAINTAINERS: bcm-vk: add maintainer for Broadcom VK Driver
In reply to Scott BrandenAdd maintainer entry for new Broadcom VK Driver
--- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+)
MAINTAINERS +7 -0
@@ -3656,6 +3656,13 @@ L: [email protected] S: Supported F: drivers/net/ethernet/broadcom/tg3.* +BROADCOM VK DRIVER +M: Scott Branden <[email protected]> +L: [email protected] +S: Supported +F: drivers/misc/bcm-vk/ +F: include/uapi/linux/misc/bcm_vk.h + BROCADE BFA FC SCSI DRIVER M: Anil Gurumurthy <[email protected]> M: Sudarsana Kalluru <[email protected]>
Signature · 1 line
2.17.1
Scott Branden
maintainerPATCH v8 8/8 ima: add FIRMWARE_PARTIAL_READ support
In reply to Scott BrandenAdd FIRMWARE_PARTIAL_READ support for integrity
measurement on partial reads of firmware files.
--- security/integrity/ima/ima_main.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
security/integrity/ima/ima_main.c +23 -1
@@ -609,6 +609,9 @@ void ima_post_path_mknod(struct dentry *dentry)*/ int ima_read_file (struct file *file,enum kernel_read_file_id read_id) { +enum ima_hooks func; +u32 secid; +/* * READING_FIRMWARE_PREALLOC_BUFFER *
@@ -617,11 +620,27 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id)* of IMA's signature verification any more than when using two * buffers? */ -return 0 ; +if (read_id !=READING_FIRMWARE_PARTIAL_READ ) +return 0 ; + +if (!file) { +if ((ima_appraise &IMA_APPRAISE_FIRMWARE ) && + (ima_appraise &IMA_APPRAISE_ENFORCE )) { +pr_err ("Prevent firmware loading_store.\n" ); +return -EACCES ;/* INTEGRITY_UNKNOWN */ + } +return 0 ; + } + + func = read_idmap[read_id] ?:FILE_CHECK ; +security_task_getsecid (current, &secid); +return process_measurement (file,current_cred (), secid,NULL , +0 ,MAY_READ , func); }const int read_idmap[READING_MAX_ID ] = { [READING_FIRMWARE ] =FIRMWARE_CHECK , + [READING_FIRMWARE_PARTIAL_READ ] =FIRMWARE_CHECK , [READING_FIRMWARE_PREALLOC_BUFFER ] =FIRMWARE_CHECK , [READING_MODULE ] =MODULE_CHECK , [READING_KEXEC_IMAGE ] =KEXEC_KERNEL_CHECK ,
@@ -648,6 +667,9 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,enum ima_hooks func;u32 secid; +if (read_id ==READING_FIRMWARE_PARTIAL_READ ) +return 0 ; +if (!file && read_id ==READING_FIRMWARE ) {if ((ima_appraise &IMA_APPRAISE_FIRMWARE ) && (ima_appraise &IMA_APPRAISE_ENFORCE )) {
Signature · 1 line
2.17.1