diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/genwqe/card_base.h | 1 | ||||
-rw-r--r-- | drivers/misc/genwqe/card_utils.c | 12 | ||||
-rw-r--r-- | drivers/misc/lkdtm_perms.c | 7 | ||||
-rw-r--r-- | drivers/misc/mei/amthif.c | 2 | ||||
-rw-r--r-- | drivers/misc/mei/bus-fixup.c | 98 | ||||
-rw-r--r-- | drivers/misc/mei/bus.c | 18 | ||||
-rw-r--r-- | drivers/misc/mei/client.c | 6 | ||||
-rw-r--r-- | drivers/misc/mei/client.h | 2 | ||||
-rw-r--r-- | drivers/misc/mei/main.c | 45 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 15 |
10 files changed, 175 insertions, 31 deletions
diff --git a/drivers/misc/genwqe/card_base.h b/drivers/misc/genwqe/card_base.h index cb851c14ca4b..5813b5f25006 100644 --- a/drivers/misc/genwqe/card_base.h +++ b/drivers/misc/genwqe/card_base.h @@ -41,7 +41,6 @@ #include "genwqe_driver.h" #define GENWQE_MSI_IRQS 4 /* Just one supported, no MSIx */ -#define GENWQE_FLAG_MSI_ENABLED (1 << 0) #define GENWQE_MAX_VFS 15 /* maximum 15 VFs are possible */ #define GENWQE_MAX_FUNCS 16 /* 1 PF and 15 VFs */ diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c index fc2794b513fa..147b83011b58 100644 --- a/drivers/misc/genwqe/card_utils.c +++ b/drivers/misc/genwqe/card_utils.c @@ -740,13 +740,10 @@ int genwqe_read_softreset(struct genwqe_dev *cd) int genwqe_set_interrupt_capability(struct genwqe_dev *cd, int count) { int rc; - struct pci_dev *pci_dev = cd->pci_dev; - rc = pci_enable_msi_range(pci_dev, 1, count); + rc = pci_alloc_irq_vectors(cd->pci_dev, 1, count, PCI_IRQ_MSI); if (rc < 0) return rc; - - cd->flags |= GENWQE_FLAG_MSI_ENABLED; return 0; } @@ -756,12 +753,7 @@ int genwqe_set_interrupt_capability(struct genwqe_dev *cd, int count) */ void genwqe_reset_interrupt_capability(struct genwqe_dev *cd) { - struct pci_dev *pci_dev = cd->pci_dev; - - if (cd->flags & GENWQE_FLAG_MSI_ENABLED) { - pci_disable_msi(pci_dev); - cd->flags &= ~GENWQE_FLAG_MSI_ENABLED; - } + pci_free_irq_vectors(cd->pci_dev); } /** diff --git a/drivers/misc/lkdtm_perms.c b/drivers/misc/lkdtm_perms.c index 45f1c0f96612..c7635a79341f 100644 --- a/drivers/misc/lkdtm_perms.c +++ b/drivers/misc/lkdtm_perms.c @@ -60,15 +60,18 @@ static noinline void execute_location(void *dst, bool write) static void execute_user_location(void *dst) { + int copied; + /* Intentionally crossing kernel/user memory boundary. */ void (*func)(void) = dst; pr_info("attempting ok execution at %p\n", do_nothing); do_nothing(); - if (copy_to_user((void __user *)dst, do_nothing, EXEC_SIZE)) + copied = access_process_vm(current, (unsigned long)dst, do_nothing, + EXEC_SIZE, FOLL_WRITE); + if (copied < EXEC_SIZE) return; - flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE); pr_info("attempting bad execution at %p\n", func); func(); } diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 7ae89b4a21d5..466afb2611c6 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -144,7 +144,7 @@ int mei_amthif_run_next_cmd(struct mei_device *dev) dev->iamthif_state = MEI_IAMTHIF_WRITING; cl->fp = cb->fp; - ret = mei_cl_write(cl, cb, false); + ret = mei_cl_write(cl, cb); if (ret < 0) return ret; diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index 75b9d4ac8b1e..7f2cef9011ae 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -38,6 +38,9 @@ static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO; #define MEI_UUID_WD UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, \ 0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB) +#define MEI_UUID_MKHIF_FIX UUID_LE(0x55213584, 0x9a29, 0x4916, \ + 0xba, 0xdf, 0xf, 0xb7, 0xed, 0x68, 0x2a, 0xeb) + #define MEI_UUID_ANY NULL_UUID_LE /** @@ -69,6 +72,97 @@ static void blacklist(struct mei_cl_device *cldev) cldev->do_match = 0; } +#define OSTYPE_LINUX 2 +struct mei_os_ver { + __le16 build; + __le16 reserved1; + u8 os_type; + u8 major; + u8 minor; + u8 reserved2; +} __packed; + +#define MKHI_FEATURE_PTT 0x10 + +struct mkhi_rule_id { + __le16 rule_type; + u8 feature_id; + u8 reserved; +} __packed; + +struct mkhi_fwcaps { + struct mkhi_rule_id id; + u8 len; + u8 data[0]; +} __packed; + +#define MKHI_FWCAPS_GROUP_ID 0x3 +#define MKHI_FWCAPS_SET_OS_VER_APP_RULE_CMD 6 +struct mkhi_msg_hdr { + u8 group_id; + u8 command; + u8 reserved; + u8 result; +} __packed; + +struct mkhi_msg { + struct mkhi_msg_hdr hdr; + u8 data[0]; +} __packed; + +static int mei_osver(struct mei_cl_device *cldev) +{ + int ret; + const size_t size = sizeof(struct mkhi_msg_hdr) + + sizeof(struct mkhi_fwcaps) + + sizeof(struct mei_os_ver); + size_t length = 8; + char buf[size]; + struct mkhi_msg *req; + struct mkhi_fwcaps *fwcaps; + struct mei_os_ver *os_ver; + unsigned int mode = MEI_CL_IO_TX_BLOCKING | MEI_CL_IO_TX_INTERNAL; + + memset(buf, 0, size); + + req = (struct mkhi_msg *)buf; + req->hdr.group_id = MKHI_FWCAPS_GROUP_ID; + req->hdr.command = MKHI_FWCAPS_SET_OS_VER_APP_RULE_CMD; + + fwcaps = (struct mkhi_fwcaps *)req->data; + + fwcaps->id.rule_type = 0x0; + fwcaps->id.feature_id = MKHI_FEATURE_PTT; + fwcaps->len = sizeof(*os_ver); + os_ver = (struct mei_os_ver *)fwcaps->data; + os_ver->os_type = OSTYPE_LINUX; + + ret = __mei_cl_send(cldev->cl, buf, size, mode); + if (ret < 0) + return ret; + + ret = __mei_cl_recv(cldev->cl, buf, length); + if (ret < 0) + return ret; + + return 0; +} + +static void mei_mkhi_fix(struct mei_cl_device *cldev) +{ + int ret; + + ret = mei_cldev_enable(cldev); + if (ret) + return; + + ret = mei_osver(cldev); + if (ret) + dev_err(&cldev->dev, "OS version command failed %d\n", ret); + + mei_cldev_disable(cldev); +} + /** * mei_wd - wd client on the bus, change protocol version * as the API has changed. @@ -162,7 +256,8 @@ static int mei_nfc_if_version(struct mei_cl *cl, WARN_ON(mutex_is_locked(&bus->device_lock)); - ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd), 1); + ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd), + MEI_CL_IO_TX_BLOCKING); if (ret < 0) { dev_err(bus->dev, "Could not send IF version cmd\n"); return ret; @@ -309,6 +404,7 @@ static struct mei_fixup { MEI_FIXUP(MEI_UUID_NFC_INFO, blacklist), MEI_FIXUP(MEI_UUID_NFC_HCI, mei_nfc), MEI_FIXUP(MEI_UUID_WD, mei_wd), + MEI_FIXUP(MEI_UUID_MKHIF_FIX, mei_mkhi_fix), }; /** diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 8cac7ef9ad0d..7c075e9b25e5 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -36,12 +36,12 @@ * @cl: host client * @buf: buffer to send * @length: buffer length - * @blocking: wait for write completion + * @mode: sending mode * * Return: written size bytes or < 0 on error */ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, - bool blocking) + unsigned int mode) { struct mei_device *bus; struct mei_cl_cb *cb; @@ -80,9 +80,11 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, goto out; } + cb->internal = !!(mode & MEI_CL_IO_TX_INTERNAL); + cb->blocking = !!(mode & MEI_CL_IO_TX_BLOCKING); memcpy(cb->buf.data, buf, length); - rets = mei_cl_write(cl, cb, blocking); + rets = mei_cl_write(cl, cb); out: mutex_unlock(&bus->device_lock); @@ -188,7 +190,7 @@ ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length) if (cl == NULL) return -ENODEV; - return __mei_cl_send(cl, buf, length, 1); + return __mei_cl_send(cl, buf, length, MEI_CL_IO_TX_BLOCKING); } EXPORT_SYMBOL_GPL(mei_cldev_send); @@ -228,7 +230,7 @@ static void mei_cl_bus_event_work(struct work_struct *work) bus = cldev->bus; if (cldev->event_cb) - cldev->event_cb(cldev, cldev->events, cldev->event_context); + cldev->event_cb(cldev, cldev->events); cldev->events = 0; @@ -301,7 +303,6 @@ bool mei_cl_bus_rx_event(struct mei_cl *cl) * @cldev: me client devices * @event_cb: callback function * @events_mask: requested events bitmask - * @context: driver context data * * Return: 0 on success * -EALREADY if an callback is already registered @@ -309,7 +310,7 @@ bool mei_cl_bus_rx_event(struct mei_cl *cl) */ int mei_cldev_register_event_cb(struct mei_cl_device *cldev, unsigned long events_mask, - mei_cldev_event_cb_t event_cb, void *context) + mei_cldev_event_cb_t event_cb) { struct mei_device *bus = cldev->bus; int ret; @@ -320,7 +321,6 @@ int mei_cldev_register_event_cb(struct mei_cl_device *cldev, cldev->events = 0; cldev->events_mask = events_mask; cldev->event_cb = event_cb; - cldev->event_context = context; INIT_WORK(&cldev->event_work, mei_cl_bus_event_work); if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) { @@ -483,7 +483,7 @@ int mei_cldev_disable(struct mei_cl_device *cldev) mutex_lock(&bus->device_lock); if (!mei_cl_is_connected(cl)) { - dev_err(bus->dev, "Already disconnected"); + dev_dbg(bus->dev, "Already disconnected"); err = 0; goto out; } diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 6fe02350578d..beb942e6c248 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1598,18 +1598,17 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, * * @cl: host client * @cb: write callback with filled data - * @blocking: block until completed * * Return: number of bytes sent on success, <0 on failure. */ -int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking) +int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb) { struct mei_device *dev; struct mei_msg_data *buf; struct mei_msg_hdr mei_hdr; int size; int rets; - + bool blocking; if (WARN_ON(!cl || !cl->dev)) return -ENODEV; @@ -1621,6 +1620,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking) buf = &cb->buf; size = buf->size; + blocking = cb->blocking; cl_dbg(dev, cl, "size=%d\n", size); diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index d2bfabecd882..f2545af9be7b 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -219,7 +219,7 @@ int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb, int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp); int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr, struct mei_cl_cb *cmpl_list); -int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking); +int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb); int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index fa50635512e8..e1bf54481fd6 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -322,7 +322,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, goto out; } - rets = mei_cl_write(cl, cb, false); + rets = mei_cl_write(cl, cb); out: mutex_unlock(&dev->device_lock); return rets; @@ -653,7 +653,7 @@ static int mei_fasync(int fd, struct file *file, int band) } /** - * fw_status_show - mei device attribute show method + * fw_status_show - mei device fw_status attribute show method * * @device: device pointer * @attr: attribute pointer @@ -684,8 +684,49 @@ static ssize_t fw_status_show(struct device *device, } static DEVICE_ATTR_RO(fw_status); +/** + * hbm_ver_show - display HBM protocol version negotiated with FW + * + * @device: device pointer + * @attr: attribute pointer + * @buf: char out buffer + * + * Return: number of the bytes printed into buf or error + */ +static ssize_t hbm_ver_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct mei_device *dev = dev_get_drvdata(device); + struct hbm_version ver; + + mutex_lock(&dev->device_lock); + ver = dev->version; + mutex_unlock(&dev->device_lock); + + return sprintf(buf, "%u.%u\n", ver.major_version, ver.minor_version); +} +static DEVICE_ATTR_RO(hbm_ver); + +/** + * hbm_ver_drv_show - display HBM protocol version advertised by driver + * + * @device: device pointer + * @attr: attribute pointer + * @buf: char out buffer + * + * Return: number of the bytes printed into buf or error + */ +static ssize_t hbm_ver_drv_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%u.%u\n", HBM_MAJOR_VERSION, HBM_MINOR_VERSION); +} +static DEVICE_ATTR_RO(hbm_ver_drv); + static struct attribute *mei_attrs[] = { &dev_attr_fw_status.attr, + &dev_attr_hbm_ver.attr, + &dev_attr_hbm_ver_drv.attr, NULL }; ATTRIBUTE_GROUPS(mei); diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 1169fd9e7d02..d50f70b4a05e 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -109,6 +109,17 @@ enum mei_cb_file_ops { MEI_FOP_NOTIFY_STOP, }; +/** + * enum mei_cl_io_mode - io mode between driver and fw + * + * @MEI_CL_IO_TX_BLOCKING: send is blocking + * @MEI_CL_IO_TX_INTERNAL: internal communication between driver and FW + */ +enum mei_cl_io_mode { + MEI_CL_IO_TX_BLOCKING = BIT(0), + MEI_CL_IO_TX_INTERNAL = BIT(1), +}; + /* * Intel MEI message data struct */ @@ -169,6 +180,7 @@ struct mei_cl; * @fp: pointer to file structure * @status: io status of the cb * @internal: communication between driver and FW flag + * @blocking: transmission blocking mode * @completed: the transfer or reception has completed */ struct mei_cl_cb { @@ -180,6 +192,7 @@ struct mei_cl_cb { const struct file *fp; int status; u32 internal:1; + u32 blocking:1; u32 completed:1; }; @@ -304,7 +317,7 @@ void mei_cl_bus_rescan(struct mei_device *bus); void mei_cl_bus_rescan_work(struct work_struct *work); void mei_cl_bus_dev_fixup(struct mei_cl_device *dev); ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, - bool blocking); + unsigned int mode); ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length); bool mei_cl_bus_rx_event(struct mei_cl *cl); bool mei_cl_bus_notify_event(struct mei_cl *cl); |