summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNrithya Kanakasabapathy <nrithya@google.com>2020-11-04 09:40:50 -0800
committerNrithya Kanakasabapathy <nrithya@google.com>2020-11-04 09:40:50 -0800
commit087f6adaf5ef59d7345aab63bb7350f6b52bccf7 (patch)
tree5d7d31f201153a831fa117806b9b853bf2352fd4
parent6ae73bd8c343b409fe317b7a4c56e5ee89ec75e7 (diff)
downloadabrolhos-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.c90
-rw-r--r--drivers/edgetpu/edgetpu-firmware.c2
-rw-r--r--drivers/edgetpu/edgetpu-internal.h12
-rw-r--r--drivers/edgetpu/edgetpu-kci.h5
-rw-r--r--drivers/edgetpu/edgetpu.h32
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__ */