#include <linux/fs.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
+#include <linux/pm_runtime.h>
#include <linux/mei.h>
static inline int mei_cl_hbm_equal(struct mei_cl *cl,
struct mei_msg_hdr *mei_hdr)
{
- return cl->host_client_id == mei_hdr->host_addr &&
- cl->me_client_id == mei_hdr->me_addr;
+ return mei_cl_host_addr(cl) == mei_hdr->host_addr &&
+ mei_cl_me_id(cl) == mei_hdr->me_addr;
}
/**
* @dev: mei device
* @hdr: message header
*/
-static inline
void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr)
{
/*
cb->read_time = jiffies;
cl_dbg(dev, cl, "completed read length = %lu\n", cb->buf_idx);
list_move_tail(&cb->list, &complete_list->list);
+ } else {
+ pm_runtime_mark_last_busy(dev->dev);
+ pm_request_autosuspend(dev->dev);
}
out:
return -EMSGSIZE;
ret = mei_hbm_cl_disconnect_rsp(dev, cl);
-
- cl->state = MEI_FILE_DISCONNECTED;
- cl->status = 0;
- mei_io_cb_free(cb);
+ list_move_tail(&cb->list, &cmpl_list->list);
return ret;
}
-
-
-/**
- * mei_cl_irq_disconnect - processes close related operation from
- * interrupt thread context - send disconnect request
- *
- * @cl: client
- * @cb: callback block.
- * @cmpl_list: complete list.
- *
- * Return: 0, OK; otherwise, error.
- */
-static int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb,
- struct mei_cl_cb *cmpl_list)
-{
- struct mei_device *dev = cl->dev;
- u32 msg_slots;
- int slots;
-
- msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
- slots = mei_hbuf_empty_slots(dev);
-
- if (slots < msg_slots)
- return -EMSGSIZE;
-
- if (mei_hbm_cl_disconnect_req(dev, cl)) {
- cl->status = 0;
- cb->buf_idx = 0;
- list_move_tail(&cb->list, &cmpl_list->list);
- return -EIO;
- }
-
- cl->state = MEI_FILE_DISCONNECTING;
- cl->status = 0;
- cb->buf_idx = 0;
- list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
- cl->timer_count = MEI_CONNECT_TIMEOUT;
-
- return 0;
-}
-
-
/**
* mei_cl_irq_read - processes client read related operation from the
* interrupt thread context - request for flow control credits
return 0;
}
-
-/**
- * mei_cl_irq_connect - send connect request in irq_thread context
- *
- * @cl: client
- * @cb: callback block.
- * @cmpl_list: complete list.
- *
- * Return: 0, OK; otherwise, error.
- */
-static int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
- struct mei_cl_cb *cmpl_list)
-{
- struct mei_device *dev = cl->dev;
- u32 msg_slots;
- int slots;
- int ret;
-
- msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
- slots = mei_hbuf_empty_slots(dev);
-
- if (mei_cl_is_other_connecting(cl))
- return 0;
-
- if (slots < msg_slots)
- return -EMSGSIZE;
-
- cl->state = MEI_FILE_CONNECTING;
-
- ret = mei_hbm_cl_connect_req(dev, cl);
- if (ret) {
- cl->status = ret;
- cb->buf_idx = 0;
- list_del_init(&cb->list);
- return ret;
- }
-
- list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
- cl->timer_count = MEI_CONNECT_TIMEOUT;
- return 0;
-}
-
-
/**
* mei_irq_read_handler - bottom half read routine after ISR to
* handle the read processing.
if (ret)
return ret;
break;
+
+ case MEI_FOP_NOTIFY_START:
+ case MEI_FOP_NOTIFY_STOP:
+ ret = mei_cl_irq_notify(cl, cb, cmpl_list);
+ if (ret)
+ return ret;
+ break;
default:
BUG();
}
EXPORT_SYMBOL_GPL(mei_irq_write_handler);
+/**
+ * mei_connect_timeout - connect/disconnect timeouts
+ *
+ * @cl: host client
+ */
+static void mei_connect_timeout(struct mei_cl *cl)
+{
+ struct mei_device *dev = cl->dev;
+
+ if (cl->state == MEI_FILE_CONNECTING) {
+ if (dev->hbm_f_dot_supported) {
+ cl->state = MEI_FILE_DISCONNECT_REQUIRED;
+ wake_up(&cl->wait);
+ return;
+ }
+ }
+ mei_reset(dev);
+}
/**
* mei_timer - timer function.
if (cl->timer_count) {
if (--cl->timer_count == 0) {
dev_err(dev->dev, "timer: connect/disconnect timeout.\n");
- mei_reset(dev);
+ mei_connect_timeout(cl);
goto out;
}
}