diff options
author | Yunhong Jiang <yunhong.jiang@linux.intel.com> | 2017-03-08 23:13:28 -0800 |
---|---|---|
committer | Yunhong Jiang <yunhong.jiang@linux.intel.com> | 2017-03-08 23:36:15 -0800 |
commit | 52f993b8e89487ec9ee15a7fb4979e0f09a45b27 (patch) | |
tree | d65304486afe0bea4a311c783c0d72791c8c0aa2 /kernel/drivers/misc | |
parent | c189ccac5702322ed843fe17057035b7222a59b6 (diff) |
Upgrade to 4.4.50-rt62
The current kernel is based on rt kernel v4.4.6-rt14. We will upgrade it
to 4.4.50-rt62.
The command to achieve it is:
a) Clone a git repo from
git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git
b) Get the diff between this two changesets:
git diff 640eca2901f3435e616157b11379d3223a44b391
705619beeea1b0b48219a683fd1a901a86fdaf5e
where the two commits are:
[yjiang5@jnakajim-build linux-stable-rt]$ git show --oneline --name-only
640eca2901f3435e616157b11379d3223a44b391
640eca2901f3 v4.4.6-rt14
localversion-rt
[yjiang5@jnakajim-build linux-stable-rt]$ git show --oneline --name-only
705619beeea1b0b48219a683fd1a901a86fdaf5e
705619beeea1 Linux 4.4.50-rt62
localversion-rt
c) One patch has been backported thus revert the patch before applying.
filterdiff -p1 -x scripts/package/Makefile
~/tmp/v4.4.6-rt14-4.4.50-rt62.diff |patch -p1 --dry-run
Upstream status: backport
Change-Id: I244d57a32f6066e5a5b9915f9fbf99e7bbca6e01
Signed-off-by: Yunhong Jiang <yunhong.jiang@linux.intel.com>
Diffstat (limited to 'kernel/drivers/misc')
24 files changed, 218 insertions, 79 deletions
diff --git a/kernel/drivers/misc/Kconfig b/kernel/drivers/misc/Kconfig index 3540f684f..6f7e99ad6 100644 --- a/kernel/drivers/misc/Kconfig +++ b/kernel/drivers/misc/Kconfig @@ -477,7 +477,7 @@ config ARM_CHARLCD still useful. config BMP085 - bool + tristate depends on SYSFS config BMP085_I2C diff --git a/kernel/drivers/misc/ad525x_dpot.c b/kernel/drivers/misc/ad525x_dpot.c index 15e88078b..f1a0b99f5 100644 --- a/kernel/drivers/misc/ad525x_dpot.c +++ b/kernel/drivers/misc/ad525x_dpot.c @@ -216,7 +216,7 @@ static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg) */ value = swab16(value); - if (dpot->uid == DPOT_UID(AD5271_ID)) + if (dpot->uid == DPOT_UID(AD5274_ID)) value = value >> 2; return value; default: diff --git a/kernel/drivers/misc/cxl/Makefile b/kernel/drivers/misc/cxl/Makefile index 6982f603f..ab6f392d3 100644 --- a/kernel/drivers/misc/cxl/Makefile +++ b/kernel/drivers/misc/cxl/Makefile @@ -1,4 +1,4 @@ -ccflags-y := -Werror -Wno-unused-const-variable +ccflags-y := -Werror $(call cc-disable-warning, unused-const-variable) cxl-y += main.o file.o irq.o fault.o native.o cxl-y += context.o sysfs.o debugfs.o pci.o trace.o diff --git a/kernel/drivers/misc/cxl/api.c b/kernel/drivers/misc/cxl/api.c index 103baf0e0..ea3eeb701 100644 --- a/kernel/drivers/misc/cxl/api.c +++ b/kernel/drivers/misc/cxl/api.c @@ -25,7 +25,6 @@ struct cxl_context *cxl_dev_context_init(struct pci_dev *dev) afu = cxl_pci_to_afu(dev); - get_device(&afu->dev); ctx = cxl_context_alloc(); if (IS_ERR(ctx)) { rc = PTR_ERR(ctx); @@ -61,7 +60,6 @@ err_mapping: err_ctx: kfree(ctx); err_dev: - put_device(&afu->dev); return ERR_PTR(rc); } EXPORT_SYMBOL_GPL(cxl_dev_context_init); @@ -87,8 +85,6 @@ int cxl_release_context(struct cxl_context *ctx) if (ctx->status >= STARTED) return -EBUSY; - put_device(&ctx->afu->dev); - cxl_context_free(ctx); return 0; @@ -176,7 +172,7 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed, if (task) { ctx->pid = get_task_pid(task, PIDTYPE_PID); - get_pid(ctx->pid); + ctx->glpid = get_task_pid(task->group_leader, PIDTYPE_PID); kernel = false; } diff --git a/kernel/drivers/misc/cxl/context.c b/kernel/drivers/misc/cxl/context.c index 2faa1270d..262b88eac 100644 --- a/kernel/drivers/misc/cxl/context.c +++ b/kernel/drivers/misc/cxl/context.c @@ -42,7 +42,7 @@ int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master, spin_lock_init(&ctx->sste_lock); ctx->afu = afu; ctx->master = master; - ctx->pid = NULL; /* Set in start work ioctl */ + ctx->pid = ctx->glpid = NULL; /* Set in start work ioctl */ mutex_init(&ctx->mapping_lock); ctx->mapping = mapping; @@ -97,6 +97,12 @@ int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master, ctx->pe = i; ctx->elem = &ctx->afu->spa[i]; ctx->pe_inserted = false; + + /* + * take a ref on the afu so that it stays alive at-least till + * this context is reclaimed inside reclaim_ctx. + */ + cxl_afu_get(afu); return 0; } @@ -211,7 +217,11 @@ int __detach_context(struct cxl_context *ctx) WARN_ON(cxl_detach_process(ctx) && cxl_adapter_link_ok(ctx->afu->adapter)); flush_work(&ctx->fault_work); /* Only needed for dedicated process */ + + /* release the reference to the group leader and mm handling pid */ put_pid(ctx->pid); + put_pid(ctx->glpid); + cxl_ctx_put(); return 0; } @@ -278,6 +288,9 @@ static void reclaim_ctx(struct rcu_head *rcu) if (ctx->irq_bitmap) kfree(ctx->irq_bitmap); + /* Drop ref to the afu device taken during cxl_context_init */ + cxl_afu_put(ctx->afu); + kfree(ctx); } diff --git a/kernel/drivers/misc/cxl/cxl.h b/kernel/drivers/misc/cxl/cxl.h index 0cfb9c129..a521bc72c 100644 --- a/kernel/drivers/misc/cxl/cxl.h +++ b/kernel/drivers/misc/cxl/cxl.h @@ -403,6 +403,18 @@ struct cxl_afu { bool enabled; }; +/* AFU refcount management */ +static inline struct cxl_afu *cxl_afu_get(struct cxl_afu *afu) +{ + + return (get_device(&afu->dev) == NULL) ? NULL : afu; +} + +static inline void cxl_afu_put(struct cxl_afu *afu) +{ + put_device(&afu->dev); +} + struct cxl_irq_name { struct list_head list; @@ -433,6 +445,9 @@ struct cxl_context { unsigned int sst_size, sst_lru; wait_queue_head_t wq; + /* pid of the group leader associated with the pid */ + struct pid *glpid; + /* use mm context associated with this pid for ds faults */ struct pid *pid; spinlock_t lock; /* Protects pending_irq_mask, pending_fault and fault_addr */ /* Only used in PR mode */ diff --git a/kernel/drivers/misc/cxl/fault.c b/kernel/drivers/misc/cxl/fault.c index 25a5418c5..81c3f75b7 100644 --- a/kernel/drivers/misc/cxl/fault.c +++ b/kernel/drivers/misc/cxl/fault.c @@ -166,13 +166,92 @@ static void cxl_handle_page_fault(struct cxl_context *ctx, cxl_ack_irq(ctx, CXL_PSL_TFC_An_R, 0); } +/* + * Returns the mm_struct corresponding to the context ctx via ctx->pid + * In case the task has exited we use the task group leader accessible + * via ctx->glpid to find the next task in the thread group that has a + * valid mm_struct associated with it. If a task with valid mm_struct + * is found the ctx->pid is updated to use the task struct for subsequent + * translations. In case no valid mm_struct is found in the task group to + * service the fault a NULL is returned. + */ +static struct mm_struct *get_mem_context(struct cxl_context *ctx) +{ + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *old_pid = ctx->pid; + + if (old_pid == NULL) { + pr_warn("%s: Invalid context for pe=%d\n", + __func__, ctx->pe); + return NULL; + } + + task = get_pid_task(old_pid, PIDTYPE_PID); + + /* + * pid_alive may look racy but this saves us from costly + * get_task_mm when the task is a zombie. In worst case + * we may think a task is alive, which is about to die + * but get_task_mm will return NULL. + */ + if (task != NULL && pid_alive(task)) + mm = get_task_mm(task); + + /* release the task struct that was taken earlier */ + if (task) + put_task_struct(task); + else + pr_devel("%s: Context owning pid=%i for pe=%i dead\n", + __func__, pid_nr(old_pid), ctx->pe); + + /* + * If we couldn't find the mm context then use the group + * leader to iterate over the task group and find a task + * that gives us mm_struct. + */ + if (unlikely(mm == NULL && ctx->glpid != NULL)) { + + rcu_read_lock(); + task = pid_task(ctx->glpid, PIDTYPE_PID); + if (task) + do { + mm = get_task_mm(task); + if (mm) { + ctx->pid = get_task_pid(task, + PIDTYPE_PID); + break; + } + task = next_thread(task); + } while (task && !thread_group_leader(task)); + rcu_read_unlock(); + + /* check if we switched pid */ + if (ctx->pid != old_pid) { + if (mm) + pr_devel("%s:pe=%i switch pid %i->%i\n", + __func__, ctx->pe, pid_nr(old_pid), + pid_nr(ctx->pid)); + else + pr_devel("%s:Cannot find mm for pid=%i\n", + __func__, pid_nr(old_pid)); + + /* drop the reference to older pid */ + put_pid(old_pid); + } + } + + return mm; +} + + + void cxl_handle_fault(struct work_struct *fault_work) { struct cxl_context *ctx = container_of(fault_work, struct cxl_context, fault_work); u64 dsisr = ctx->dsisr; u64 dar = ctx->dar; - struct task_struct *task = NULL; struct mm_struct *mm = NULL; if (cxl_p2n_read(ctx->afu, CXL_PSL_DSISR_An) != dsisr || @@ -195,17 +274,17 @@ void cxl_handle_fault(struct work_struct *fault_work) "DSISR: %#llx DAR: %#llx\n", ctx->pe, dsisr, dar); if (!ctx->kernel) { - if (!(task = get_pid_task(ctx->pid, PIDTYPE_PID))) { - pr_devel("cxl_handle_fault unable to get task %i\n", - pid_nr(ctx->pid)); + + mm = get_mem_context(ctx); + /* indicates all the thread in task group have exited */ + if (mm == NULL) { + pr_devel("%s: unable to get mm for pe=%d pid=%i\n", + __func__, ctx->pe, pid_nr(ctx->pid)); cxl_ack_ae(ctx); return; - } - if (!(mm = get_task_mm(task))) { - pr_devel("cxl_handle_fault unable to get mm %i\n", - pid_nr(ctx->pid)); - cxl_ack_ae(ctx); - goto out; + } else { + pr_devel("Handling page fault for pe=%d pid=%i\n", + ctx->pe, pid_nr(ctx->pid)); } } @@ -218,33 +297,22 @@ void cxl_handle_fault(struct work_struct *fault_work) if (mm) mmput(mm); -out: - if (task) - put_task_struct(task); } static void cxl_prefault_one(struct cxl_context *ctx, u64 ea) { - int rc; - struct task_struct *task; struct mm_struct *mm; - if (!(task = get_pid_task(ctx->pid, PIDTYPE_PID))) { - pr_devel("cxl_prefault_one unable to get task %i\n", - pid_nr(ctx->pid)); - return; - } - if (!(mm = get_task_mm(task))) { + mm = get_mem_context(ctx); + if (mm == NULL) { pr_devel("cxl_prefault_one unable to get mm %i\n", pid_nr(ctx->pid)); - put_task_struct(task); return; } - rc = cxl_fault_segment(ctx, mm, ea); + cxl_fault_segment(ctx, mm, ea); mmput(mm); - put_task_struct(task); } static u64 next_segment(u64 ea, u64 vsid) @@ -263,18 +331,13 @@ static void cxl_prefault_vma(struct cxl_context *ctx) struct copro_slb slb; struct vm_area_struct *vma; int rc; - struct task_struct *task; struct mm_struct *mm; - if (!(task = get_pid_task(ctx->pid, PIDTYPE_PID))) { - pr_devel("cxl_prefault_vma unable to get task %i\n", - pid_nr(ctx->pid)); - return; - } - if (!(mm = get_task_mm(task))) { + mm = get_mem_context(ctx); + if (mm == NULL) { pr_devel("cxl_prefault_vm unable to get mm %i\n", pid_nr(ctx->pid)); - goto out1; + return; } down_read(&mm->mmap_sem); @@ -295,8 +358,6 @@ static void cxl_prefault_vma(struct cxl_context *ctx) up_read(&mm->mmap_sem); mmput(mm); -out1: - put_task_struct(task); } void cxl_prefault(struct cxl_context *ctx, u64 wed) diff --git a/kernel/drivers/misc/cxl/file.c b/kernel/drivers/misc/cxl/file.c index 7ccd2998b..783337d22 100644 --- a/kernel/drivers/misc/cxl/file.c +++ b/kernel/drivers/misc/cxl/file.c @@ -67,7 +67,13 @@ static int __afu_open(struct inode *inode, struct file *file, bool master) spin_unlock(&adapter->afu_list_lock); goto err_put_adapter; } - get_device(&afu->dev); + + /* + * taking a ref to the afu so that it doesn't go away + * for rest of the function. This ref is released before + * we return. + */ + cxl_afu_get(afu); spin_unlock(&adapter->afu_list_lock); if (!afu->current_mode) @@ -90,13 +96,12 @@ static int __afu_open(struct inode *inode, struct file *file, bool master) file->private_data = ctx; cxl_ctx_get(); - /* Our ref on the AFU will now hold the adapter */ - put_device(&adapter->dev); - - return 0; + /* indicate success */ + rc = 0; err_put_afu: - put_device(&afu->dev); + /* release the ref taken earlier */ + cxl_afu_put(afu); err_put_adapter: put_device(&adapter->dev); return rc; @@ -131,8 +136,6 @@ int afu_release(struct inode *inode, struct file *file) mutex_unlock(&ctx->mapping_lock); } - put_device(&ctx->afu->dev); - /* * At this this point all bottom halfs have finished and we should be * getting no more IRQs from the hardware for this context. Once it's @@ -198,8 +201,12 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, * where a process (master, some daemon, etc) has opened the chardev on * behalf of another process, so the AFU's mm gets bound to the process * that performs this ioctl and not the process that opened the file. + * Also we grab the PID of the group leader so that if the task that + * has performed the attach operation exits the mm context of the + * process is still accessible. */ - ctx->pid = get_pid(get_task_pid(current, PIDTYPE_PID)); + ctx->pid = get_task_pid(current, PIDTYPE_PID); + ctx->glpid = get_task_pid(current->group_leader, PIDTYPE_PID); trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); diff --git a/kernel/drivers/misc/cxl/irq.c b/kernel/drivers/misc/cxl/irq.c index 09a406058..efbb6945e 100644 --- a/kernel/drivers/misc/cxl/irq.c +++ b/kernel/drivers/misc/cxl/irq.c @@ -288,7 +288,6 @@ unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq, void cxl_unmap_irq(unsigned int virq, void *cookie) { free_irq(virq, cookie); - irq_dispose_mapping(virq); } static int cxl_register_one_irq(struct cxl *adapter, diff --git a/kernel/drivers/misc/cxl/pci.c b/kernel/drivers/misc/cxl/pci.c index be2c8e248..0c6c17a1c 100644 --- a/kernel/drivers/misc/cxl/pci.c +++ b/kernel/drivers/misc/cxl/pci.c @@ -138,6 +138,7 @@ static const struct pci_device_id cxl_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0477), }, { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x044b), }, { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x04cf), }, + { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0601), }, { PCI_DEVICE_CLASS(0x120000, ~0), }, { } diff --git a/kernel/drivers/misc/genwqe/card_utils.c b/kernel/drivers/misc/genwqe/card_utils.c index 222367cc8..524660510 100644 --- a/kernel/drivers/misc/genwqe/card_utils.c +++ b/kernel/drivers/misc/genwqe/card_utils.c @@ -352,17 +352,27 @@ int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, if (copy_from_user(sgl->lpage, user_addr + user_size - sgl->lpage_size, sgl->lpage_size)) { rc = -EFAULT; - goto err_out1; + goto err_out2; } } return 0; + err_out2: + __genwqe_free_consistent(cd, PAGE_SIZE, sgl->lpage, + sgl->lpage_dma_addr); + sgl->lpage = NULL; + sgl->lpage_dma_addr = 0; err_out1: __genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage, sgl->fpage_dma_addr); + sgl->fpage = NULL; + sgl->fpage_dma_addr = 0; err_out: __genwqe_free_consistent(cd, sgl->sgl_size, sgl->sgl, sgl->sgl_dma_addr); + sgl->sgl = NULL; + sgl->sgl_dma_addr = 0; + sgl->sgl_size = 0; return -ENOMEM; } diff --git a/kernel/drivers/misc/mei/amthif.c b/kernel/drivers/misc/mei/amthif.c index cd0403f09..e79c0371e 100644 --- a/kernel/drivers/misc/mei/amthif.c +++ b/kernel/drivers/misc/mei/amthif.c @@ -417,8 +417,10 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, dev = cl->dev; - if (dev->iamthif_state != MEI_IAMTHIF_READING) + if (dev->iamthif_state != MEI_IAMTHIF_READING) { + mei_irq_discard_msg(dev, mei_hdr); return 0; + } ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list); if (ret) diff --git a/kernel/drivers/misc/mei/bus-fixup.c b/kernel/drivers/misc/mei/bus-fixup.c index 020de5919..bdc7fcd80 100644 --- a/kernel/drivers/misc/mei/bus-fixup.c +++ b/kernel/drivers/misc/mei/bus-fixup.c @@ -151,7 +151,7 @@ static int mei_nfc_if_version(struct mei_cl *cl, ret = 0; bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length); - if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) { + if (bytes_recv < if_version_length) { dev_err(bus->dev, "Could not read IF version\n"); ret = -EIO; goto err; diff --git a/kernel/drivers/misc/mei/bus.c b/kernel/drivers/misc/mei/bus.c index 0b05aa938..be74a2570 100644 --- a/kernel/drivers/misc/mei/bus.c +++ b/kernel/drivers/misc/mei/bus.c @@ -53,6 +53,11 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, bus = cl->dev; mutex_lock(&bus->device_lock); + if (bus->dev_state != MEI_DEV_ENABLED) { + rets = -ENODEV; + goto out; + } + if (!mei_cl_is_connected(cl)) { rets = -ENODEV; goto out; @@ -109,6 +114,10 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) bus = cl->dev; mutex_lock(&bus->device_lock); + if (bus->dev_state != MEI_DEV_ENABLED) { + rets = -ENODEV; + goto out; + } cb = mei_cl_read_cb(cl, NULL); if (cb) @@ -135,7 +144,7 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) mutex_lock(&bus->device_lock); if (!mei_cl_is_connected(cl)) { - rets = -EBUSY; + rets = -ENODEV; goto out; } } @@ -213,17 +222,23 @@ EXPORT_SYMBOL_GPL(mei_cldev_recv); static void mei_cl_bus_event_work(struct work_struct *work) { struct mei_cl_device *cldev; + struct mei_device *bus; cldev = container_of(work, struct mei_cl_device, event_work); + bus = cldev->bus; + if (cldev->event_cb) cldev->event_cb(cldev, cldev->events, cldev->event_context); cldev->events = 0; /* Prepare for the next read */ - if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) + if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) { + mutex_lock(&bus->device_lock); mei_cl_read_start(cldev->cl, 0, NULL); + mutex_unlock(&bus->device_lock); + } } /** @@ -287,6 +302,7 @@ int mei_cldev_register_event_cb(struct mei_cl_device *cldev, unsigned long events_mask, mei_cldev_event_cb_t event_cb, void *context) { + struct mei_device *bus = cldev->bus; int ret; if (cldev->event_cb) @@ -299,15 +315,17 @@ int mei_cldev_register_event_cb(struct mei_cl_device *cldev, INIT_WORK(&cldev->event_work, mei_cl_bus_event_work); if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) { + mutex_lock(&bus->device_lock); ret = mei_cl_read_start(cldev->cl, 0, NULL); + mutex_unlock(&bus->device_lock); if (ret && ret != -EBUSY) return ret; } if (cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)) { - mutex_lock(&cldev->cl->dev->device_lock); + mutex_lock(&bus->device_lock); ret = mei_cl_notify_request(cldev->cl, NULL, event_cb ? 1 : 0); - mutex_unlock(&cldev->cl->dev->device_lock); + mutex_unlock(&bus->device_lock); if (ret) return ret; } @@ -381,7 +399,7 @@ bool mei_cldev_enabled(struct mei_cl_device *cldev) EXPORT_SYMBOL_GPL(mei_cldev_enabled); /** - * mei_cldev_enable_device - enable me client device + * mei_cldev_enable - enable me client device * create connection with me client * * @cldev: me client device diff --git a/kernel/drivers/misc/mei/client.c b/kernel/drivers/misc/mei/client.c index a6c87c713..2ff39fbc7 100644 --- a/kernel/drivers/misc/mei/client.c +++ b/kernel/drivers/misc/mei/client.c @@ -698,7 +698,7 @@ void mei_host_client_init(struct work_struct *work) pm_runtime_mark_last_busy(dev->dev); dev_dbg(dev->dev, "rpm: autosuspend\n"); - pm_runtime_autosuspend(dev->dev); + pm_request_autosuspend(dev->dev); } /** @@ -1735,6 +1735,10 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb) wake_up(&cl->wait); break; + case MEI_FOP_DISCONNECT_RSP: + mei_io_cb_free(cb); + mei_cl_set_disconnected(cl); + break; default: BUG_ON(0); } diff --git a/kernel/drivers/misc/mei/hbm.c b/kernel/drivers/misc/mei/hbm.c index e7b7aad09..fd8a9f057 100644 --- a/kernel/drivers/misc/mei/hbm.c +++ b/kernel/drivers/misc/mei/hbm.c @@ -873,8 +873,7 @@ static int mei_hbm_fw_disconnect_req(struct mei_device *dev, cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT_RSP, NULL); if (!cb) return -ENOMEM; - cl_dbg(dev, cl, "add disconnect response as first\n"); - list_add(&cb->list, &dev->ctrl_wr_list.list); + list_add_tail(&cb->list, &dev->ctrl_wr_list.list); } return 0; } diff --git a/kernel/drivers/misc/mei/hw-me-regs.h b/kernel/drivers/misc/mei/hw-me-regs.h index a8a68acd3..a2661381d 100644 --- a/kernel/drivers/misc/mei/hw-me-regs.h +++ b/kernel/drivers/misc/mei/hw-me-regs.h @@ -121,6 +121,10 @@ #define MEI_DEV_ID_SPT_2 0x9D3B /* Sunrise Point 2 */ #define MEI_DEV_ID_SPT_H 0xA13A /* Sunrise Point H */ #define MEI_DEV_ID_SPT_H_2 0xA13B /* Sunrise Point H 2 */ + +#define MEI_DEV_ID_KBP 0xA2BA /* Kaby Point */ +#define MEI_DEV_ID_KBP_2 0xA2BB /* Kaby Point 2 */ + /* * MEI HW Section */ diff --git a/kernel/drivers/misc/mei/hw-me.c b/kernel/drivers/misc/mei/hw-me.c index 25b1997a6..36333750c 100644 --- a/kernel/drivers/misc/mei/hw-me.c +++ b/kernel/drivers/misc/mei/hw-me.c @@ -1258,8 +1258,14 @@ static bool mei_me_fw_type_nm(struct pci_dev *pdev) static bool mei_me_fw_type_sps(struct pci_dev *pdev) { u32 reg; - /* Read ME FW Status check for SPS Firmware */ - pci_read_config_dword(pdev, PCI_CFG_HFS_1, ®); + unsigned int devfn; + + /* + * Read ME FW Status register to check for SPS Firmware + * The SPS FW is only signaled in pci function 0 + */ + devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0); + pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_1, ®); /* if bits [19:16] = 15, running SPS Firmware */ return (reg & 0xf0000) == 0xf0000; } diff --git a/kernel/drivers/misc/mei/hw-txe.c b/kernel/drivers/misc/mei/hw-txe.c index bae680c64..396d75d9f 100644 --- a/kernel/drivers/misc/mei/hw-txe.c +++ b/kernel/drivers/misc/mei/hw-txe.c @@ -972,11 +972,13 @@ static bool mei_txe_check_and_ack_intrs(struct mei_device *dev, bool do_ack) hisr = mei_txe_br_reg_read(hw, HISR_REG); aliveness = mei_txe_aliveness_get(dev); - if (hhisr & IPC_HHIER_SEC && aliveness) + if (hhisr & IPC_HHIER_SEC && aliveness) { ipc_isr = mei_txe_sec_reg_read_silent(hw, SEC_IPC_HOST_INT_STATUS_REG); - else + } else { ipc_isr = 0; + hhisr &= ~IPC_HHIER_SEC; + } generated = generated || (hisr & HISR_INT_STS_MSK) || diff --git a/kernel/drivers/misc/mei/interrupt.c b/kernel/drivers/misc/mei/interrupt.c index 64b568a02..d1df797c7 100644 --- a/kernel/drivers/misc/mei/interrupt.c +++ b/kernel/drivers/misc/mei/interrupt.c @@ -76,7 +76,6 @@ static inline int mei_cl_hbm_equal(struct mei_cl *cl, * @dev: mei device * @hdr: message header */ -static inline void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr) { /* @@ -184,10 +183,7 @@ static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb, return -EMSGSIZE; ret = mei_hbm_cl_disconnect_rsp(dev, cl); - mei_cl_set_disconnected(cl); - mei_io_cb_free(cb); - mei_me_cl_put(cl->me_cl); - cl->me_cl = NULL; + list_move_tail(&cb->list, &cmpl_list->list); return ret; } diff --git a/kernel/drivers/misc/mei/main.c b/kernel/drivers/misc/mei/main.c index 80f9afcb1..4ef189a7a 100644 --- a/kernel/drivers/misc/mei/main.c +++ b/kernel/drivers/misc/mei/main.c @@ -207,7 +207,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, mutex_lock(&dev->device_lock); if (!mei_cl_is_connected(cl)) { - rets = -EBUSY; + rets = -ENODEV; goto out; } } diff --git a/kernel/drivers/misc/mei/mei_dev.h b/kernel/drivers/misc/mei/mei_dev.h index 4250555d5..1b06e2fd6 100644 --- a/kernel/drivers/misc/mei/mei_dev.h +++ b/kernel/drivers/misc/mei/mei_dev.h @@ -782,6 +782,8 @@ bool mei_hbuf_acquire(struct mei_device *dev); bool mei_write_is_idle(struct mei_device *dev); +void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr); + #if IS_ENABLED(CONFIG_DEBUG_FS) int mei_dbgfs_register(struct mei_device *dev, const char *name); void mei_dbgfs_deregister(struct mei_device *dev); diff --git a/kernel/drivers/misc/mei/pci-me.c b/kernel/drivers/misc/mei/pci-me.c index 27678d815..01e20384a 100644 --- a/kernel/drivers/misc/mei/pci-me.c +++ b/kernel/drivers/misc/mei/pci-me.c @@ -84,8 +84,11 @@ static const struct pci_device_id mei_me_pci_tbl[] = { {MEI_PCI_DEVICE(MEI_DEV_ID_SPT, mei_me_pch8_cfg)}, {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, mei_me_pch8_cfg)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, mei_me_pch8_sps_cfg)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, mei_me_pch8_sps_cfg)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, mei_me_pch8_cfg)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, mei_me_pch8_cfg)}, /* required last entry */ {0, } diff --git a/kernel/drivers/misc/mic/scif/scif_rma.c b/kernel/drivers/misc/mic/scif/scif_rma.c index 8310b4dbf..6a451bd65 100644 --- a/kernel/drivers/misc/mic/scif/scif_rma.c +++ b/kernel/drivers/misc/mic/scif/scif_rma.c @@ -1511,7 +1511,7 @@ off_t scif_register_pinned_pages(scif_epd_t epd, if ((map_flags & SCIF_MAP_FIXED) && ((ALIGN(offset, PAGE_SIZE) != offset) || (offset < 0) || - (offset + (off_t)len < offset))) + (len > LONG_MAX - offset))) return -EINVAL; might_sleep(); @@ -1614,7 +1614,7 @@ off_t scif_register(scif_epd_t epd, void *addr, size_t len, off_t offset, if ((map_flags & SCIF_MAP_FIXED) && ((ALIGN(offset, PAGE_SIZE) != offset) || (offset < 0) || - (offset + (off_t)len < offset))) + (len > LONG_MAX - offset))) return -EINVAL; /* Unsupported protection requested */ @@ -1732,7 +1732,8 @@ scif_unregister(scif_epd_t epd, off_t offset, size_t len) /* Offset is not page aligned or offset+len wraps around */ if ((ALIGN(offset, PAGE_SIZE) != offset) || - (offset + (off_t)len < offset)) + (offset < 0) || + (len > LONG_MAX - offset)) return -EINVAL; err = scif_verify_epd(ep); |