diff options
author | Nrithya Kanakasabapathy <nrithya@google.com> | 2020-11-04 09:40:50 -0800 |
---|---|---|
committer | Nrithya Kanakasabapathy <nrithya@google.com> | 2020-11-04 09:40:50 -0800 |
commit | 087f6adaf5ef59d7345aab63bb7350f6b52bccf7 (patch) | |
tree | 5d7d31f201153a831fa117806b9b853bf2352fd4 | |
parent | 6ae73bd8c343b409fe317b7a4c56e5ee89ec75e7 (diff) | |
download | abrolhos-087f6adaf5ef59d7345aab63bb7350f6b52bccf7.tar.gz |
Merge branch 'whitechapel' into android-gs-pixel-mainline
* whitechapel:
edgetpu: add missing "static" keyword to ioctl
edgetpu: unittests ioctl firmware version
edgetpu: add firmware version ioctl handler
edgetpu: remove EDGETPU_CREATE_GROUP_COMPAT
edgetpu: unittests fix UAF in debugfs tests
edgetpu: allow connection to edgetpu fops from wrapper drivers
Signed-off-by: Nrithya Kanakasabapathy <nrithya@google.com>
Change-Id: Iaa7b5543d930687bf42505e63b3f5726cc2bc156
-rw-r--r-- | drivers/edgetpu/edgetpu-direct.c | 90 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-firmware.c | 2 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-internal.h | 12 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-kci.h | 5 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu.h | 32 |
5 files changed, 73 insertions, 68 deletions
diff --git a/drivers/edgetpu/edgetpu-direct.c b/drivers/edgetpu/edgetpu-direct.c index bdb6445..a552e95 100644 --- a/drivers/edgetpu/edgetpu-direct.c +++ b/drivers/edgetpu/edgetpu-direct.c @@ -49,16 +49,8 @@ static atomic_t char_minor = ATOMIC_INIT(-1); static struct dentry *edgetpu_debugfs_dir; -static const struct file_operations edgetpu_fops; - -/* - * Switch device file private_data to point to the client after open, - * providing for multiple clients. - */ -static int edgetpu_open(struct inode *inode, struct file *file) +int edgetpu_open(struct edgetpu_dev *etdev, struct file *file) { - struct edgetpu_dev *etdev = - container_of(inode->i_cdev, struct edgetpu_dev, cdev); struct edgetpu_client *client; int res; @@ -86,6 +78,14 @@ static int edgetpu_open(struct inode *inode, struct file *file) return 0; } +static int edgetpu_dev_open(struct inode *inode, struct file *file) +{ + struct edgetpu_dev *etdev = + container_of(inode->i_cdev, struct edgetpu_dev, cdev); + + return edgetpu_open(etdev, file); +} + static int etdirect_release(struct inode *inode, struct file *file) { struct edgetpu_client *client = file->private_data; @@ -185,11 +185,6 @@ static int etdirect_join_group(struct edgetpu_client *client, u64 leader_fd) ret = -EBADF; goto out; } - if (file->f_op != &edgetpu_fops) { - ret = -EINVAL; - goto out; - } - leader = file->private_data; if (!leader) { ret = -EINVAL; @@ -229,32 +224,6 @@ static int edgetpu_ioctl_create_group(struct edgetpu_client *client, return 0; } -/* TODO(b/167151866): remove me */ -static int -etdirect_create_group(struct edgetpu_client *client, - struct edgetpu_mailbox_attr_compat __user *argp) -{ - struct edgetpu_mailbox_attr_compat attr_c; - struct edgetpu_mailbox_attr attr; - struct edgetpu_device_group *group; - - if (copy_from_user(&attr_c, argp, sizeof(attr_c))) - return -EFAULT; - - attr.cmd_queue_size = attr_c.cmd_queue_size; - attr.resp_queue_size = attr_c.resp_queue_size; - attr.sizeof_cmd = EDGETPU_SIZEOF_VII_CMD_ELEMENT; - attr.sizeof_resp = EDGETPU_SIZEOF_VII_RESP_ELEMENT; - attr.priority = attr_c.priority; - attr.cmdq_tail_doorbell = attr_c.cmdq_tail_doorbell; - group = edgetpu_device_group_alloc(client, &attr); - if (IS_ERR(group)) - return PTR_ERR(group); - - edgetpu_device_group_put(group); - return 0; -} - static int etdirect_map_buffer(struct edgetpu_device_group *group, struct edgetpu_map_ioctl __user *argp) { @@ -451,6 +420,16 @@ static int edgetpu_ioctl_sync_fence_status( return ret; } +static int edgetpu_ioctl_fw_version(struct edgetpu_dev *etdev, + struct edgetpu_fw_version __user *argp) +{ + if (etdev->fw_version.kci_version == EDGETPU_INVALID_KCI_VERSION) + return -ENODEV; + if (copy_to_user(argp, &etdev->fw_version, sizeof(*argp))) + return -EFAULT; + return 0; +} + static bool etdirect_ioctl_check_permissions(struct file *file, uint cmd) { return file->f_mode & FMODE_WRITE; @@ -463,9 +442,9 @@ static bool etdirect_ioctl_check_permissions(struct file *file, uint cmd) static bool etdirect_ioctl_check_group(struct edgetpu_client *client, uint cmd) { /* @client must not belong to any group */ - if (cmd == EDGETPU_CREATE_GROUP_COMPAT || cmd == EDGETPU_CREATE_GROUP || - cmd == EDGETPU_JOIN_GROUP_COMPAT || cmd == EDGETPU_JOIN_GROUP || - cmd == EDGETPU_CREATE_GROUP_COMPAT_2) + if (cmd == EDGETPU_CREATE_GROUP || + cmd == EDGETPU_CREATE_GROUP_COMPAT_2 || + cmd == EDGETPU_JOIN_GROUP_COMPAT || cmd == EDGETPU_JOIN_GROUP) return !client->group; /* Valid for any @client */ @@ -480,7 +459,8 @@ static bool etdirect_ioctl_check_group(struct edgetpu_client *client, uint cmd) cmd == EDGETPU_SIGNAL_SYNC_FENCE_COMPAT || cmd == EDGETPU_SYNC_FENCE_STATUS || cmd == EDGETPU_RELEASE_WAKE_LOCK || - cmd == EDGETPU_ACQUIRE_WAKE_LOCK) + cmd == EDGETPU_ACQUIRE_WAKE_LOCK || + cmd == EDGETPU_FIRMWARE_VERSION) return true; if (!client->group) @@ -555,7 +535,7 @@ static int etdirect_ioctl_acquire_wakelock(struct edgetpu_client *client) return 0; } -static long etdirect_ioctl(struct file *file, uint cmd, ulong arg) +long edgetpu_ioctl(struct file *file, uint cmd, ulong arg) { struct edgetpu_client *client = file->private_data; void __user *argp = (void __user *)arg; @@ -627,9 +607,6 @@ static long etdirect_ioctl(struct file *file, uint cmd, ulong arg) case EDGETPU_CREATE_GROUP_COMPAT_2: ret = edgetpu_ioctl_create_group(client, argp); break; - case EDGETPU_CREATE_GROUP_COMPAT: - ret = etdirect_create_group(client, argp); - break; case EDGETPU_JOIN_GROUP: case EDGETPU_JOIN_GROUP_COMPAT: ret = etdirect_join_group(client, (u64)argp); @@ -662,6 +639,9 @@ static long etdirect_ioctl(struct file *file, uint cmd, ulong arg) case EDGETPU_ACQUIRE_WAKE_LOCK: ret = etdirect_ioctl_acquire_wakelock(client); break; + case EDGETPU_FIRMWARE_VERSION: + ret = edgetpu_ioctl_fw_version(client->etdev, argp); + break; default: return -ENOTTY; /* unknown command */ } @@ -669,6 +649,14 @@ static long etdirect_ioctl(struct file *file, uint cmd, ulong arg) return ret; } +static long edgetpu_dev_ioctl(struct file *file, uint cmd, ulong arg) +{ + if (file->f_op != &edgetpu_fops) + return -ENOTTY; + + return edgetpu_ioctl(file, cmd, arg); +} + /* Map a region of device/coherent memory. */ static int etdirect_mmap(struct file *file, struct vm_area_struct *vma) { @@ -889,13 +877,13 @@ static void edgetpu_dev_setup_debugfs(struct edgetpu_dev *etdev) &statusregs_ops); } -static const struct file_operations edgetpu_fops = { +const struct file_operations edgetpu_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .mmap = etdirect_mmap, - .open = edgetpu_open, + .open = edgetpu_dev_open, .release = etdirect_release, - .unlocked_ioctl = etdirect_ioctl, + .unlocked_ioctl = edgetpu_dev_ioctl, }; /* Called from edgetpu core to add a new edgetpu device. */ diff --git a/drivers/edgetpu/edgetpu-firmware.c b/drivers/edgetpu/edgetpu-firmware.c index 60b2827..b3b1f4f 100644 --- a/drivers/edgetpu/edgetpu-firmware.c +++ b/drivers/edgetpu/edgetpu-firmware.c @@ -367,6 +367,8 @@ int edgetpu_firmware_run(struct edgetpu_dev *etdev, const char *name, mutex_unlock(&etdev->state_lock); return ret; } + /* will be overwritten when we successfully parse the f/w header */ + etdev->fw_version.kci_version = EDGETPU_INVALID_KCI_VERSION; /* * Prevent platform-specific code from trying to run the previous * firmware diff --git a/drivers/edgetpu/edgetpu-internal.h b/drivers/edgetpu/edgetpu-internal.h index 26000b1..e3e8e20 100644 --- a/drivers/edgetpu/edgetpu-internal.h +++ b/drivers/edgetpu/edgetpu-internal.h @@ -12,6 +12,7 @@ #include <linux/device.h> #include <linux/dma-direction.h> #include <linux/firmware.h> +#include <linux/fs.h> #include <linux/io.h> #include <linux/irqreturn.h> #include <linux/mm_types.h> @@ -138,6 +139,9 @@ enum edgetpu_dev_state { ETDEV_STATE_BAD = 3, /* firmware/device is in unusable state. */ }; +/* a mark to know whether we read valid versions from the firmware header */ +#define EDGETPU_INVALID_KCI_VERSION (~0u) + struct edgetpu_dev { struct device *dev; /* platform/pci bus device */ struct device *etcdev; /* edgetpu class char device */ @@ -170,8 +174,12 @@ struct edgetpu_dev { u8 mcp_pkg_type; /* multichip pkg type */ struct edgetpu_sw_wdt *etdev_sw_wdt; /* software watchdog */ u64 mcp_serial_num; /* multichip serial number */ + /* version read from the firmware binary file */ + struct edgetpu_fw_version fw_version; }; +extern const struct file_operations edgetpu_fops; + /* Status regs dump. */ struct edgetpu_dumpregs_range { u32 firstreg; @@ -229,6 +237,10 @@ static inline void edgetpu_dev_write_64(struct edgetpu_dev *etdev, writeq_relaxed(value, etdev->regs.mem + reg_offset); } +/* External drivers can hook up to edgetpu driver using these calls. */ +int edgetpu_open(struct edgetpu_dev *etdev, struct file *file); +long edgetpu_ioctl(struct file *file, uint cmd, ulong arg); + /* Bus (Platform/PCI) <-> Core API */ int __init edgetpu_init(void); diff --git a/drivers/edgetpu/edgetpu-kci.h b/drivers/edgetpu/edgetpu-kci.h index d2e0559..7db571b 100644 --- a/drivers/edgetpu/edgetpu-kci.h +++ b/drivers/edgetpu/edgetpu-kci.h @@ -76,11 +76,6 @@ struct edgetpu_vii_response_element { u64 retval; } __packed; -/* TODO(b/167151866): remove these two constants */ -/* KCI and VII command elements are the same size */ -#define EDGETPU_SIZEOF_VII_CMD_ELEMENT sizeof(struct edgetpu_command_element) -#define EDGETPU_SIZEOF_VII_RESP_ELEMENT sizeof(struct edgetpu_vii_response_element) - /* * Definition of code in command elements. * Code for KCI is a 16-bit unsigned integer. diff --git a/drivers/edgetpu/edgetpu.h b/drivers/edgetpu/edgetpu.h index c77bf58..cd5c262 100644 --- a/drivers/edgetpu/edgetpu.h +++ b/drivers/edgetpu/edgetpu.h @@ -128,18 +128,6 @@ struct edgetpu_event_register { #define EDGETPU_SET_EVENTFD_COMPAT \ _IOR(EDGETPU_IOCTL_BASE, 5, struct edgetpu_event_register) -/* TODO(b/167151866): remove this structure and EDGETPU_CREATE_GROUP_COMPAT */ -struct edgetpu_mailbox_attr_compat { - __u32 cmd_queue_size : 10; /* size of cmd queue in KB */ - __u32 resp_queue_size : 10; /* size of response queue in KB */ - __u32 priority : 4; /* mailbox service priority */ - __u32 cmdq_tail_doorbell: 1; /* auto doorbell on cmd queue tail move */ -}; - -/* Create a new device group with the caller as the master. */ -#define EDGETPU_CREATE_GROUP_COMPAT \ - _IOR(EDGETPU_IOCTL_BASE, 6, struct edgetpu_mailbox_attr_compat) - struct edgetpu_mailbox_attr { /* * There are limitations on these size fields, see the error cases in @@ -500,4 +488,24 @@ struct edgetpu_sync_fence_status { */ #define EDGETPU_ACQUIRE_WAKE_LOCK _IO(EDGETPU_IOCTL_BASE, 26) +struct edgetpu_fw_version { + __u32 major_version; /* Returned firmware major version number */ + __u32 minor_version; /* Returned firmware minor version number */ + __u32 vii_version; /* Returned firmware VII version number */ + __u32 kci_version; /* Returned firmware KCI version number */ +}; + +/* + * Query the version information of the firmware currently loaded. + * + * When there is an attempt to load firmware, its version numbers are recorded + * by the kernel and will be returned on the following EDGETPU_FIRMWARE_VERSION + * calls. If the latest firmware attempted to load didn't exist or had an + * invalid header, this call returns -ENODEV. + * + * Returns 0 on success, -errno on error. + */ +#define EDGETPU_FIRMWARE_VERSION \ + _IOR(EDGETPU_IOCTL_BASE, 27, struct edgetpu_fw_version) + #endif /* __EDGETPU_H__ */ |