Merge tag 'char-misc-4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 29 Oct 2016 18:19:02 +0000 (11:19 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 29 Oct 2016 18:19:02 +0000 (11:19 -0700)
Pull char/misc driver fixes from Greg KH:
 "Here are a few small char/misc driver fixes for reported issues.

  The "biggest" are two binder fixes for reported issues that have been
  shipping in Android phones for a while now, the others are various
  fixes for reported problems.

  And there's a MAINTAINERS update for good measure.

  All have been in linux-next with no reported issues"

* tag 'char-misc-4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  MAINTAINERS: Add entry for genwqe driver
  VMCI: Doorbell create and destroy fixes
  GenWQE: Fix bad page access during abort of resource allocation
  vme: vme_get_size potentially returning incorrect value on failure
  extcon: qcom-spmi-misc: Sync the extcon state on interrupt
  hv: do not lose pending heartbeat vmbus packets
  mei: txe: don't clean an unprocessed interrupt cause.
  ANDROID: binder: Clear binder and cookie when setting handle in flat binder struct
  ANDROID: binder: Add strong ref checks

MAINTAINERS
drivers/android/binder.c
drivers/extcon/extcon-qcom-spmi-misc.c
drivers/hv/hv_util.c
drivers/misc/genwqe/card_utils.c
drivers/misc/mei/hw-txe.c
drivers/misc/vmw_vmci/vmci_doorbell.c
drivers/misc/vmw_vmci/vmci_driver.c
drivers/vme/vme.c

index f30b8ea..464d2c8 100644 (file)
@@ -5287,6 +5287,12 @@ M:       Joe Perches <joe@perches.com>
 S:     Maintained
 F:     scripts/get_maintainer.pl
 
+GENWQE (IBM Generic Workqueue Card)
+M:     Frank Haverkamp <haver@linux.vnet.ibm.com>
+M:     Gabriel Krisman Bertazi <krisman@linux.vnet.ibm.com>
+S:     Supported
+F:     drivers/misc/genwqe/
+
 GFS2 FILE SYSTEM
 M:     Steven Whitehouse <swhiteho@redhat.com>
 M:     Bob Peterson <rpeterso@redhat.com>
index 562af94..3c71b98 100644 (file)
@@ -1002,7 +1002,7 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal)
 
 
 static struct binder_ref *binder_get_ref(struct binder_proc *proc,
-                                        uint32_t desc)
+                                        u32 desc, bool need_strong_ref)
 {
        struct rb_node *n = proc->refs_by_desc.rb_node;
        struct binder_ref *ref;
@@ -1010,12 +1010,16 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc,
        while (n) {
                ref = rb_entry(n, struct binder_ref, rb_node_desc);
 
-               if (desc < ref->desc)
+               if (desc < ref->desc) {
                        n = n->rb_left;
-               else if (desc > ref->desc)
+               } else if (desc > ref->desc) {
                        n = n->rb_right;
-               else
+               } else if (need_strong_ref && !ref->strong) {
+                       binder_user_error("tried to use weak ref as strong ref\n");
+                       return NULL;
+               } else {
                        return ref;
+               }
        }
        return NULL;
 }
@@ -1285,7 +1289,10 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
                } break;
                case BINDER_TYPE_HANDLE:
                case BINDER_TYPE_WEAK_HANDLE: {
-                       struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+                       struct binder_ref *ref;
+
+                       ref = binder_get_ref(proc, fp->handle,
+                                            fp->type == BINDER_TYPE_HANDLE);
 
                        if (ref == NULL) {
                                pr_err("transaction release %d bad handle %d\n",
@@ -1380,7 +1387,7 @@ static void binder_transaction(struct binder_proc *proc,
                if (tr->target.handle) {
                        struct binder_ref *ref;
 
-                       ref = binder_get_ref(proc, tr->target.handle);
+                       ref = binder_get_ref(proc, tr->target.handle, true);
                        if (ref == NULL) {
                                binder_user_error("%d:%d got transaction to invalid handle\n",
                                        proc->pid, thread->pid);
@@ -1577,7 +1584,9 @@ static void binder_transaction(struct binder_proc *proc,
                                fp->type = BINDER_TYPE_HANDLE;
                        else
                                fp->type = BINDER_TYPE_WEAK_HANDLE;
+                       fp->binder = 0;
                        fp->handle = ref->desc;
+                       fp->cookie = 0;
                        binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
                                       &thread->todo);
 
@@ -1589,7 +1598,10 @@ static void binder_transaction(struct binder_proc *proc,
                } break;
                case BINDER_TYPE_HANDLE:
                case BINDER_TYPE_WEAK_HANDLE: {
-                       struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+                       struct binder_ref *ref;
+
+                       ref = binder_get_ref(proc, fp->handle,
+                                            fp->type == BINDER_TYPE_HANDLE);
 
                        if (ref == NULL) {
                                binder_user_error("%d:%d got transaction with invalid handle, %d\n",
@@ -1624,7 +1636,9 @@ static void binder_transaction(struct binder_proc *proc,
                                        return_error = BR_FAILED_REPLY;
                                        goto err_binder_get_ref_for_node_failed;
                                }
+                               fp->binder = 0;
                                fp->handle = new_ref->desc;
+                               fp->cookie = 0;
                                binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
                                trace_binder_transaction_ref_to_ref(t, ref,
                                                                    new_ref);
@@ -1678,6 +1692,7 @@ static void binder_transaction(struct binder_proc *proc,
                        binder_debug(BINDER_DEBUG_TRANSACTION,
                                     "        fd %d -> %d\n", fp->handle, target_fd);
                        /* TODO: fput? */
+                       fp->binder = 0;
                        fp->handle = target_fd;
                } break;
 
@@ -1800,7 +1815,9 @@ static int binder_thread_write(struct binder_proc *proc,
                                                ref->desc);
                                }
                        } else
-                               ref = binder_get_ref(proc, target);
+                               ref = binder_get_ref(proc, target,
+                                                    cmd == BC_ACQUIRE ||
+                                                    cmd == BC_RELEASE);
                        if (ref == NULL) {
                                binder_user_error("%d:%d refcount change on invalid ref %d\n",
                                        proc->pid, thread->pid, target);
@@ -1996,7 +2013,7 @@ static int binder_thread_write(struct binder_proc *proc,
                        if (get_user(cookie, (binder_uintptr_t __user *)ptr))
                                return -EFAULT;
                        ptr += sizeof(binder_uintptr_t);
-                       ref = binder_get_ref(proc, target);
+                       ref = binder_get_ref(proc, target, false);
                        if (ref == NULL) {
                                binder_user_error("%d:%d %s invalid ref %d\n",
                                        proc->pid, thread->pid,
index ca957a5..b8cde09 100644 (file)
@@ -51,7 +51,7 @@ static void qcom_usb_extcon_detect_cable(struct work_struct *work)
        if (ret)
                return;
 
-       extcon_set_state(info->edev, EXTCON_USB_HOST, !id);
+       extcon_set_state_sync(info->edev, EXTCON_USB_HOST, !id);
 }
 
 static irqreturn_t qcom_usb_irq_handler(int irq, void *dev_id)
index 4aa3cb6..bcd0630 100644 (file)
@@ -314,10 +314,14 @@ static void heartbeat_onchannelcallback(void *context)
        u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
        struct icmsg_negotiate *negop = NULL;
 
-       vmbus_recvpacket(channel, hbeat_txf_buf,
-                        PAGE_SIZE, &recvlen, &requestid);
+       while (1) {
+
+               vmbus_recvpacket(channel, hbeat_txf_buf,
+                                PAGE_SIZE, &recvlen, &requestid);
+
+               if (!recvlen)
+                       break;
 
-       if (recvlen > 0) {
                icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
                                sizeof(struct vmbuspipe_hdr)];
 
index 8a679ec..fc2794b 100644 (file)
@@ -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;
 }
 
index e6e5e55..60415a2 100644 (file)
@@ -981,11 +981,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) ||
index a8cee33..b3fa738 100644 (file)
@@ -431,6 +431,12 @@ int vmci_doorbell_create(struct vmci_handle *handle,
        if (vmci_handle_is_invalid(*handle)) {
                u32 context_id = vmci_get_context_id();
 
+               if (context_id == VMCI_INVALID_ID) {
+                       pr_warn("Failed to get context ID\n");
+                       result = VMCI_ERROR_NO_RESOURCES;
+                       goto free_mem;
+               }
+
                /* Let resource code allocate a free ID for us */
                new_handle = vmci_make_handle(context_id, VMCI_INVALID_ID);
        } else {
@@ -525,7 +531,7 @@ int vmci_doorbell_destroy(struct vmci_handle handle)
 
        entry = container_of(resource, struct dbell_entry, resource);
 
-       if (vmci_guest_code_active()) {
+       if (!hlist_unhashed(&entry->node)) {
                int result;
 
                dbell_index_table_remove(entry);
index 896be15..d7eaf1e 100644 (file)
@@ -113,5 +113,5 @@ module_exit(vmci_drv_exit);
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface.");
-MODULE_VERSION("1.1.4.0-k");
+MODULE_VERSION("1.1.5.0-k");
 MODULE_LICENSE("GPL v2");
index 15b6407..bdbadaa 100644 (file)
@@ -156,12 +156,16 @@ size_t vme_get_size(struct vme_resource *resource)
        case VME_MASTER:
                retval = vme_master_get(resource, &enabled, &base, &size,
                        &aspace, &cycle, &dwidth);
+               if (retval)
+                       return 0;
 
                return size;
                break;
        case VME_SLAVE:
                retval = vme_slave_get(resource, &enabled, &base, &size,
                        &buf_base, &aspace, &cycle);
+               if (retval)
+                       return 0;
 
                return size;
                break;