Merge tag 'tag-sh-for-4.6' of git://git.libc.org/linux-sh
[deliverable/linux.git] / drivers / misc / mei / interrupt.c
index 64b568a0268d7026d7305f3233c378900e5669f4..1e5cb1f704f809d56c350969953567e091203227 100644 (file)
@@ -48,7 +48,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
 
                dev_dbg(dev->dev, "completing call back.\n");
                if (cl == &dev->iamthif_cl)
-                       mei_amthif_complete(dev, cb);
+                       mei_amthif_complete(cl, cb);
                else
                        mei_cl_complete(cl, cb);
        }
@@ -104,6 +104,7 @@ int mei_cl_irq_read_msg(struct mei_cl *cl,
        struct mei_device *dev = cl->dev;
        struct mei_cl_cb *cb;
        unsigned char *buffer = NULL;
+       size_t buf_sz;
 
        cb = list_first_entry_or_null(&cl->rd_pending, struct mei_cl_cb, list);
        if (!cb) {
@@ -124,11 +125,21 @@ int mei_cl_irq_read_msg(struct mei_cl *cl,
                goto out;
        }
 
-       if (cb->buf.size < mei_hdr->length + cb->buf_idx) {
-               cl_dbg(dev, cl, "message overflow. size %d len %d idx %ld\n",
+       buf_sz = mei_hdr->length + cb->buf_idx;
+       /* catch for integer overflow */
+       if (buf_sz < cb->buf_idx) {
+               cl_err(dev, cl, "message is too big len %d idx %zu\n",
+                      mei_hdr->length, cb->buf_idx);
+
+               list_move_tail(&cb->list, &complete_list->list);
+               cb->status = -EMSGSIZE;
+               goto out;
+       }
+
+       if (cb->buf.size < buf_sz) {
+               cl_dbg(dev, cl, "message overflow. size %zu len %d idx %zu\n",
                        cb->buf.size, mei_hdr->length, cb->buf_idx);
-               buffer = krealloc(cb->buf.data, mei_hdr->length + cb->buf_idx,
-                                 GFP_KERNEL);
+               buffer = krealloc(cb->buf.data, buf_sz, GFP_KERNEL);
 
                if (!buffer) {
                        cb->status = -ENOMEM;
@@ -136,7 +147,7 @@ int mei_cl_irq_read_msg(struct mei_cl *cl,
                        goto out;
                }
                cb->buf.data = buffer;
-               cb->buf.size = mei_hdr->length + cb->buf_idx;
+               cb->buf.size = buf_sz;
        }
 
        buffer = cb->buf.data + cb->buf_idx;
@@ -145,8 +156,7 @@ int mei_cl_irq_read_msg(struct mei_cl *cl,
        cb->buf_idx += mei_hdr->length;
 
        if (mei_hdr->msg_complete) {
-               cb->read_time = jiffies;
-               cl_dbg(dev, cl, "completed read length = %lu\n", cb->buf_idx);
+               cl_dbg(dev, cl, "completed read length = %zu\n", cb->buf_idx);
                list_move_tail(&cb->list, &complete_list->list);
        } else {
                pm_runtime_mark_last_busy(dev->dev);
@@ -229,6 +239,16 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
        return 0;
 }
 
+static inline bool hdr_is_hbm(struct mei_msg_hdr *mei_hdr)
+{
+       return mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0;
+}
+
+static inline bool hdr_is_fixed(struct mei_msg_hdr *mei_hdr)
+{
+       return mei_hdr->host_addr == 0 && mei_hdr->me_addr != 0;
+}
+
 /**
  * mei_irq_read_handler - bottom half read routine after ISR to
  * handle the read processing.
@@ -270,7 +290,7 @@ int mei_irq_read_handler(struct mei_device *dev,
        }
 
        /*  HBM message */
-       if (mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0) {
+       if (hdr_is_hbm(mei_hdr)) {
                ret = mei_hbm_dispatch(dev, mei_hdr);
                if (ret) {
                        dev_dbg(dev->dev, "mei_hbm_dispatch failed ret = %d\n",
@@ -290,6 +310,14 @@ int mei_irq_read_handler(struct mei_device *dev,
 
        /* if no recipient cl was found we assume corrupted header */
        if (&cl->link == &dev->file_list) {
+               /* A message for not connected fixed address clients
+                * should be silently discarded
+                */
+               if (hdr_is_fixed(mei_hdr)) {
+                       mei_irq_discard_msg(dev, mei_hdr);
+                       ret = 0;
+                       goto reset_slots;
+               }
                dev_err(dev->dev, "no destination client found 0x%08X\n",
                                dev->rd_msg_hdr);
                ret = -EBADMSG;
@@ -360,21 +388,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
                list_move_tail(&cb->list, &cmpl_list->list);
        }
 
-       if (dev->wd_state == MEI_WD_STOPPING) {
-               dev->wd_state = MEI_WD_IDLE;
-               wake_up(&dev->wait_stop_wd);
-       }
-
-       if (mei_cl_is_connected(&dev->wd_cl)) {
-               if (dev->wd_pending &&
-                   mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
-                       ret = mei_wd_send(dev);
-                       if (ret)
-                               return ret;
-                       dev->wd_pending = false;
-               }
-       }
-
        /* complete control write list CB */
        dev_dbg(dev->dev, "complete control write list cb.\n");
        list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) {
@@ -462,7 +475,6 @@ static void mei_connect_timeout(struct mei_cl *cl)
  */
 void mei_timer(struct work_struct *work)
 {
-       unsigned long timeout;
        struct mei_cl *cl;
 
        struct mei_device *dev = container_of(work,
@@ -508,45 +520,15 @@ void mei_timer(struct work_struct *work)
                        mei_reset(dev);
                        dev->iamthif_canceled = false;
                        dev->iamthif_state = MEI_IAMTHIF_IDLE;
-                       dev->iamthif_timer = 0;
 
                        mei_io_cb_free(dev->iamthif_current_cb);
                        dev->iamthif_current_cb = NULL;
 
-                       dev->iamthif_file_object = NULL;
+                       dev->iamthif_fp = NULL;
                        mei_amthif_run_next_cmd(dev);
                }
        }
 
-       if (dev->iamthif_timer) {
-
-               timeout = dev->iamthif_timer +
-                       mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
-
-               dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n",
-                               dev->iamthif_timer);
-               dev_dbg(dev->dev, "timeout = %ld\n", timeout);
-               dev_dbg(dev->dev, "jiffies = %ld\n", jiffies);
-               if (time_after(jiffies, timeout)) {
-                       /*
-                        * User didn't read the AMTHI data on time (15sec)
-                        * freeing AMTHI for other requests
-                        */
-
-                       dev_dbg(dev->dev, "freeing AMTHI for other requests\n");
-
-                       mei_io_list_flush(&dev->amthif_rd_complete_list,
-                               &dev->iamthif_cl);
-                       mei_io_cb_free(dev->iamthif_current_cb);
-                       dev->iamthif_current_cb = NULL;
-
-                       dev->iamthif_file_object->private_data = NULL;
-                       dev->iamthif_file_object = NULL;
-                       dev->iamthif_timer = 0;
-                       mei_amthif_run_next_cmd(dev);
-
-               }
-       }
 out:
        if (dev->dev_state != MEI_DEV_DISABLED)
                schedule_delayed_work(&dev->timer_work, 2 * HZ);
This page took 0.026543 seconds and 5 git commands to generate.