summaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei')
-rw-r--r--drivers/misc/mei/init.c4
-rw-r--r--drivers/misc/mei/interface.c85
-rw-r--r--drivers/misc/mei/interface.h18
-rw-r--r--drivers/misc/mei/interrupt.c171
-rw-r--r--drivers/misc/mei/iorw.c8
-rw-r--r--drivers/misc/mei/main.c59
-rw-r--r--drivers/misc/mei/mei_dev.h24
-rw-r--r--drivers/misc/mei/wd.c8
8 files changed, 150 insertions, 227 deletions
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index a7d0bb0880ec..e77f86e69fb5 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -162,6 +162,9 @@ int mei_hw_init(struct mei_device *dev)
if ((dev->host_hw_state & H_IS) == H_IS)
mei_reg_write(dev, H_CSR, dev->host_hw_state);
+ /* Doesn't change in runtime */
+ dev->hbuf_depth = (dev->host_hw_state & H_CBD) >> 24;
+
dev->recvd_msg = false;
dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
@@ -303,7 +306,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
dev->iamthif_cl.host_client_id);
mei_reset_iamthif_params(dev);
- dev->wd_due_counter = 0;
dev->extra_write_index = 0;
}
diff --git a/drivers/misc/mei/interface.c b/drivers/misc/mei/interface.c
index 428d21e36416..509c3957ff45 100644
--- a/drivers/misc/mei/interface.c
+++ b/drivers/misc/mei/interface.c
@@ -58,16 +58,18 @@ void mei_disable_interrupts(struct mei_device *dev)
}
/**
- * _host_get_filled_slots - gets number of device filled buffer slots
+ * mei_hbuf_filled_slots - gets number of device filled buffer slots
*
* @device: the device structure
*
* returns number of filled slots
*/
-static unsigned char _host_get_filled_slots(const struct mei_device *dev)
+static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
{
char read_ptr, write_ptr;
+ dev->host_hw_state = mei_hcsr_read(dev);
+
read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8);
write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16);
@@ -75,43 +77,33 @@ static unsigned char _host_get_filled_slots(const struct mei_device *dev)
}
/**
- * mei_host_buffer_is_empty - checks if host buffer is empty.
+ * mei_hbuf_is_empty - checks if host buffer is empty.
*
* @dev: the device structure
*
- * returns 1 if empty, 0 - otherwise.
+ * returns true if empty, false - otherwise.
*/
-int mei_host_buffer_is_empty(struct mei_device *dev)
+bool mei_hbuf_is_empty(struct mei_device *dev)
{
- unsigned char filled_slots;
-
- dev->host_hw_state = mei_hcsr_read(dev);
- filled_slots = _host_get_filled_slots(dev);
-
- if (filled_slots == 0)
- return 1;
-
- return 0;
+ return mei_hbuf_filled_slots(dev) == 0;
}
/**
- * mei_count_empty_write_slots - counts write empty slots.
+ * mei_hbuf_empty_slots - counts write empty slots.
*
* @dev: the device structure
*
* returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count
*/
-int mei_count_empty_write_slots(struct mei_device *dev)
+int mei_hbuf_empty_slots(struct mei_device *dev)
{
- unsigned char buffer_depth, filled_slots, empty_slots;
+ unsigned char filled_slots, empty_slots;
- dev->host_hw_state = mei_hcsr_read(dev);
- buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24);
- filled_slots = _host_get_filled_slots(dev);
- empty_slots = buffer_depth - filled_slots;
+ filled_slots = mei_hbuf_filled_slots(dev);
+ empty_slots = dev->hbuf_depth - filled_slots;
/* check for overflow */
- if (filled_slots > buffer_depth)
+ if (filled_slots > dev->hbuf_depth)
return -EOVERFLOW;
return empty_slots;
@@ -127,52 +119,39 @@ int mei_count_empty_write_slots(struct mei_device *dev)
*
* This function returns -EIO if write has failed
*/
-int mei_write_message(struct mei_device *dev,
- struct mei_msg_hdr *header,
- unsigned char *write_buffer,
- unsigned long write_length)
+int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header,
+ unsigned char *buf, unsigned long length)
{
- u32 temp_msg = 0;
- unsigned long bytes_written = 0;
- unsigned char buffer_depth, filled_slots, empty_slots;
- unsigned long dw_to_write;
-
- dev->host_hw_state = mei_hcsr_read(dev);
+ unsigned long rem, dw_cnt;
+ u32 *reg_buf = (u32 *)buf;
+ int i;
+ int empty_slots;
- dev_dbg(&dev->pdev->dev,
- "host_hw_state = 0x%08x.\n",
- dev->host_hw_state);
dev_dbg(&dev->pdev->dev,
"mei_write_message header=%08x.\n",
*((u32 *) header));
- buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24);
- filled_slots = _host_get_filled_slots(dev);
- empty_slots = buffer_depth - filled_slots;
- dev_dbg(&dev->pdev->dev,
- "filled = %hu, empty = %hu.\n",
- filled_slots, empty_slots);
-
- dw_to_write = ((write_length + 3) / 4);
+ empty_slots = mei_hbuf_empty_slots(dev);
+ dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots);
- if (dw_to_write > empty_slots)
+ dw_cnt = mei_data2slots(length);
+ if (empty_slots < 0 || dw_cnt > empty_slots)
return -EIO;
mei_reg_write(dev, H_CB_WW, *((u32 *) header));
- while (write_length >= 4) {
- mei_reg_write(dev, H_CB_WW,
- *(u32 *) (write_buffer + bytes_written));
- bytes_written += 4;
- write_length -= 4;
- }
+ for (i = 0; i < length / 4; i++)
+ mei_reg_write(dev, H_CB_WW, reg_buf[i]);
- if (write_length > 0) {
- memcpy(&temp_msg, &write_buffer[bytes_written], write_length);
- mei_reg_write(dev, H_CB_WW, temp_msg);
+ rem = length & 0x3;
+ if (rem > 0) {
+ u32 reg = 0;
+ memcpy(&reg, &buf[length - rem], rem);
+ mei_reg_write(dev, H_CB_WW, reg);
}
+ dev->host_hw_state = mei_hcsr_read(dev);
dev->host_hw_state |= H_IG;
mei_hcsr_set(dev);
dev->me_hw_state = mei_mecsr_read(dev);
diff --git a/drivers/misc/mei/interface.h b/drivers/misc/mei/interface.h
index ddff5d16616f..fb5c7db4723b 100644
--- a/drivers/misc/mei/interface.h
+++ b/drivers/misc/mei/interface.h
@@ -41,14 +41,28 @@ int mei_write_message(struct mei_device *dev,
unsigned char *write_buffer,
unsigned long write_length);
-int mei_host_buffer_is_empty(struct mei_device *dev);
+bool mei_hbuf_is_empty(struct mei_device *dev);
+
+int mei_hbuf_empty_slots(struct mei_device *dev);
+
+static inline size_t mei_hbuf_max_data(const struct mei_device *dev)
+{
+ return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr);
+}
+
+/* get slots (dwords) from a message length + header (bytes) */
+static inline unsigned char mei_data2slots(size_t length)
+{
+ return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4);
+}
int mei_count_full_read_slots(struct mei_device *dev);
-int mei_count_empty_write_slots(struct mei_device *dev);
int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl);
+
+
int mei_wd_send(struct mei_device *dev);
int mei_wd_stop(struct mei_device *dev, bool preserve);
int mei_wd_host_init(struct mei_device *dev);
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 93936f1b75eb..c6ffbbe5a6c0 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -267,8 +267,7 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
+ sizeof(struct hbm_flow_control))) {
return -EMSGSIZE;
}
- *slots -= (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_flow_control) + 3) / 4;
+ *slots -= mei_data2slots(sizeof(struct hbm_flow_control));
if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
return -EIO;
@@ -280,7 +279,7 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
dev->iamthif_msg_buf_index = 0;
dev->iamthif_msg_buf_size = 0;
dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
- dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev);
+ dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
return 0;
}
@@ -300,28 +299,25 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
struct mei_cl *cl,
struct mei_io_list *cmpl_list)
{
- if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_client_disconnect_request))) {
- *slots -= (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_client_disconnect_request) + 3) / 4;
+ if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
+ sizeof(struct hbm_client_disconnect_request)))
+ return -EBADMSG;
- if (mei_disconnect(dev, cl)) {
- cl->status = 0;
- cb_pos->information = 0;
- list_move_tail(&cb_pos->cb_list,
- &cmpl_list->mei_cb.cb_list);
- return -EMSGSIZE;
- } else {
- cl->state = MEI_FILE_DISCONNECTING;
- cl->status = 0;
- cb_pos->information = 0;
- list_move_tail(&cb_pos->cb_list,
- &dev->ctrl_rd_list.mei_cb.cb_list);
- cl->timer_count = MEI_CONNECT_TIMEOUT;
- }
+ *slots -= mei_data2slots(sizeof(struct hbm_client_disconnect_request));
+
+ if (mei_disconnect(dev, cl)) {
+ cl->status = 0;
+ cb_pos->information = 0;
+ list_move_tail(&cb_pos->cb_list,
+ &cmpl_list->mei_cb.cb_list);
+ return -EMSGSIZE;
} else {
- /* return the cancel routine */
- return -EBADMSG;
+ cl->state = MEI_FILE_DISCONNECTING;
+ cl->status = 0;
+ cb_pos->information = 0;
+ list_move_tail(&cb_pos->cb_list,
+ &dev->ctrl_rd_list.mei_cb.cb_list);
+ cl->timer_count = MEI_CONNECT_TIMEOUT;
}
return 0;
@@ -575,10 +571,9 @@ static void mei_client_disconnect_request(struct mei_device *dev,
disconnect_req->me_addr);
cl_pos->state = MEI_FILE_DISCONNECTED;
cl_pos->timer_count = 0;
- if (cl_pos == &dev->wd_cl) {
- dev->wd_due_counter = 0;
+ if (cl_pos == &dev->wd_cl)
dev->wd_pending = false;
- } else if (cl_pos == &dev->iamthif_cl)
+ else if (cl_pos == &dev->iamthif_cl)
dev->iamthif_timer = 0;
/* prepare disconnect response */
@@ -835,15 +830,15 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
struct mei_cl *cl,
struct mei_io_list *cmpl_list)
{
- if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
+ if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
sizeof(struct hbm_flow_control))) {
/* return the cancel routine */
list_del(&cb_pos->cb_list);
return -EBADMSG;
}
- *slots -= (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_flow_control) + 3) / 4;
+ *slots -= mei_data2slots(sizeof(struct hbm_flow_control));
+
if (mei_send_flow_control(dev, cl)) {
cl->status = -ENODEV;
cb_pos->information = 0;
@@ -872,27 +867,25 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
struct mei_cl *cl,
struct mei_io_list *cmpl_list)
{
- if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
+ if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
sizeof(struct hbm_client_connect_request))) {
- cl->state = MEI_FILE_CONNECTING;
- *slots -= (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_client_connect_request) + 3) / 4;
- if (mei_connect(dev, cl)) {
- cl->status = -ENODEV;
- cb_pos->information = 0;
- list_del(&cb_pos->cb_list);
- return -ENODEV;
- } else {
- list_move_tail(&cb_pos->cb_list,
- &dev->ctrl_rd_list.mei_cb.cb_list);
- cl->timer_count = MEI_CONNECT_TIMEOUT;
- }
- } else {
/* return the cancel routine */
list_del(&cb_pos->cb_list);
return -EBADMSG;
}
+ cl->state = MEI_FILE_CONNECTING;
+ *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
+ if (mei_connect(dev, cl)) {
+ cl->status = -ENODEV;
+ cb_pos->information = 0;
+ list_del(&cb_pos->cb_list);
+ return -ENODEV;
+ } else {
+ list_move_tail(&cb_pos->cb_list,
+ &dev->ctrl_rd_list.mei_cb.cb_list);
+ cl->timer_count = MEI_CONNECT_TIMEOUT;
+ }
return 0;
}
@@ -932,8 +925,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
cb_pos->information);
dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
mei_hdr->length);
- *slots -= (sizeof(struct mei_msg_hdr) +
- mei_hdr->length + 3) / 4;
+ *slots -= mei_data2slots(mei_hdr->length);
if (mei_write_message(dev, mei_hdr,
(unsigned char *)
(cb_pos->request_buffer.data +
@@ -951,7 +943,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
list_move_tail(&cb_pos->cb_list,
&dev->write_waiting_list.mei_cb.cb_list);
}
- } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
+ } else if (*slots == dev->hbuf_depth) {
/* buffer is still empty */
mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
mei_hdr->host_addr = cl->host_client_id;
@@ -960,9 +952,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
(*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
mei_hdr->msg_complete = 0;
mei_hdr->reserved = 0;
-
- (*slots) -= (sizeof(struct mei_msg_hdr) +
- mei_hdr->length + 3) / 4;
+ *slots -= mei_data2slots(mei_hdr->length);
if (mei_write_message(dev, mei_hdr,
(unsigned char *)
(cb_pos->request_buffer.data +
@@ -1021,8 +1011,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
mei_hdr->msg_complete = 1;
mei_hdr->reserved = 0;
- *slots -= (sizeof(struct mei_msg_hdr) +
- mei_hdr->length + 3) / 4;
+ *slots -= mei_data2slots(mei_hdr->length);
if (mei_write_message(dev, mei_hdr,
(dev->iamthif_msg_buf +
@@ -1046,8 +1035,8 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
&dev->write_waiting_list.mei_cb.cb_list);
}
- } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
- /* buffer is still empty */
+ } else if (*slots == dev->hbuf_depth) {
+ /* buffer is still empty */
mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
mei_hdr->host_addr = cl->host_client_id;
mei_hdr->me_addr = cl->me_client_id;
@@ -1056,8 +1045,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
mei_hdr->msg_complete = 0;
mei_hdr->reserved = 0;
- *slots -= (sizeof(struct mei_msg_hdr) +
- mei_hdr->length + 3) / 4;
+ *slots -= mei_data2slots(mei_hdr->length);
if (mei_write_message(dev, mei_hdr,
(dev->iamthif_msg_buf +
@@ -1199,17 +1187,19 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
struct mei_io_list *list;
int ret;
- if (!mei_host_buffer_is_empty(dev)) {
+ if (!mei_hbuf_is_empty(dev)) {
dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
return 0;
}
- *slots = mei_count_empty_write_slots(dev);
+ *slots = mei_hbuf_empty_slots(dev);
+ if (*slots <= 0)
+ return -EMSGSIZE;
+
/* complete all waiting for write CB */
dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
list = &dev->write_waiting_list;
- list_for_each_entry_safe(pos, next,
- &list->mei_cb.cb_list, cb_list) {
+ list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
cl = (struct mei_cl *)pos->file_private;
if (cl == NULL)
continue;
@@ -1219,17 +1209,15 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
if (MEI_WRITING == cl->writing_state &&
(pos->major_file_operations == MEI_WRITE) &&
(cl != &dev->iamthif_cl)) {
- dev_dbg(&dev->pdev->dev,
- "MEI WRITE COMPLETE\n");
+ dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
cl->writing_state = MEI_WRITE_COMPLETE;
list_add_tail(&pos->cb_list,
- &cmpl_list->mei_cb.cb_list);
+ &cmpl_list->mei_cb.cb_list);
}
if (cl == &dev->iamthif_cl) {
dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
if (dev->iamthif_flow_control_pending) {
- ret = _mei_irq_thread_iamthif_read(
- dev, slots);
+ ret = _mei_irq_thread_iamthif_read(dev, slots);
if (ret)
return ret;
}
@@ -1254,25 +1242,18 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
}
if (dev->mei_state == MEI_ENABLED) {
if (dev->wd_pending &&
- mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
+ mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
if (mei_wd_send(dev))
dev_dbg(&dev->pdev->dev, "wd send failed.\n");
- else
- if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
- return -ENODEV;
+ else if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
+ return -ENODEV;
dev->wd_pending = false;
- if (dev->wd_timeout) {
- *slots -= (sizeof(struct mei_msg_hdr) +
- MEI_START_WD_DATA_SIZE + 3) / 4;
- dev->wd_due_counter = 2;
- } else {
- *slots -= (sizeof(struct mei_msg_hdr) +
- MEI_WD_PARAMS_SIZE + 3) / 4;
- dev->wd_due_counter = 0;
- }
-
+ if (dev->wd_timeout)
+ *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE);
+ else
+ *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE);
}
}
if (dev->stop)
@@ -1320,42 +1301,34 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
/* complete write list CB */
dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
list_for_each_entry_safe(pos, next,
- &dev->write_list.mei_cb.cb_list, cb_list) {
+ &dev->write_list.mei_cb.cb_list, cb_list) {
cl = (struct mei_cl *)pos->file_private;
if (cl == NULL)
continue;
if (cl != &dev->iamthif_cl) {
- if (!mei_flow_ctrl_creds(dev, cl)) {
+ if (mei_flow_ctrl_creds(dev, cl) <= 0) {
dev_dbg(&dev->pdev->dev,
- "No flow control"
- " credentials for client"
- " %d, not sending.\n",
- cl->host_client_id);
+ "No flow control credentials for client %d, not sending.\n",
+ cl->host_client_id);
continue;
}
- ret = _mei_irq_thread_cmpl(dev, slots,
- pos,
- cl, cmpl_list);
+ ret = _mei_irq_thread_cmpl(dev, slots, pos,
+ cl, cmpl_list);
if (ret)
return ret;
} else if (cl == &dev->iamthif_cl) {
/* IAMTHIF IOCTL */
dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n");
- if (!mei_flow_ctrl_creds(dev, cl)) {
+ if (mei_flow_ctrl_creds(dev, cl) <= 0) {
dev_dbg(&dev->pdev->dev,
- "No flow control"
- " credentials for amthi"
- " client %d.\n",
- cl->host_client_id);
+ "No flow control credentials for amthi client %d.\n",
+ cl->host_client_id);
continue;
}
- ret = _mei_irq_thread_cmpl_iamthif(dev,
- slots,
- pos,
- cl,
- cmpl_list);
+ ret = _mei_irq_thread_cmpl_iamthif(dev, slots, pos,
+ cl, cmpl_list);
if (ret)
return ret;
@@ -1555,7 +1528,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
end:
dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
dev->host_hw_state = mei_hcsr_read(dev);
- dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev);
+ dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
bus_message_received = false;
if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
diff --git a/drivers/misc/mei/iorw.c b/drivers/misc/mei/iorw.c
index f9cced69b65e..50f52e21f587 100644
--- a/drivers/misc/mei/iorw.c
+++ b/drivers/misc/mei/iorw.c
@@ -481,12 +481,8 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
if (ret && dev->mei_host_buffer_is_empty) {
ret = 0;
dev->mei_host_buffer_is_empty = false;
- if (cb->request_buffer.size >
- (((dev->host_hw_state & H_CBD) >> 24) * sizeof(u32))
- -sizeof(struct mei_msg_hdr)) {
- mei_hdr.length =
- (((dev->host_hw_state & H_CBD) >> 24) *
- sizeof(u32)) - sizeof(struct mei_msg_hdr);
+ if (cb->request_buffer.size > mei_hbuf_max_data(dev)) {
+ mei_hdr.length = mei_hbuf_max_data(dev);
mei_hdr.msg_complete = 0;
} else {
mei_hdr.length = cb->request_buffer.size;
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index c70333228337..092330208869 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -714,13 +714,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
if (rets && dev->mei_host_buffer_is_empty) {
rets = 0;
dev->mei_host_buffer_is_empty = false;
- if (length > ((((dev->host_hw_state & H_CBD) >> 24) *
- sizeof(u32)) - sizeof(struct mei_msg_hdr))) {
-
- mei_hdr.length =
- (((dev->host_hw_state & H_CBD) >> 24) *
- sizeof(u32)) -
- sizeof(struct mei_msg_hdr);
+ if (length > mei_hbuf_max_data(dev)) {
+ mei_hdr.length = mei_hbuf_max_data(dev);
mei_hdr.msg_complete = 0;
} else {
mei_hdr.length = length;
@@ -982,7 +977,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
err = request_threaded_irq(pdev->irq,
NULL,
mei_interrupt_thread_handler,
- 0, mei_driver_name, dev);
+ IRQF_ONESHOT, mei_driver_name, dev);
else
err = request_threaded_irq(pdev->irq,
mei_interrupt_quick_handler,
@@ -992,7 +987,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
if (err) {
dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
pdev->irq);
- goto unmap_memory;
+ goto disable_msi;
}
INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
if (mei_hw_init(dev)) {
@@ -1023,8 +1018,8 @@ release_irq:
mei_disable_interrupts(dev);
flush_scheduled_work();
free_irq(pdev->irq, dev);
+disable_msi:
pci_disable_msi(pdev);
-unmap_memory:
pci_iounmap(pdev, dev->mem_addr);
free_device:
kfree(dev);
@@ -1101,6 +1096,8 @@ static void __devexit mei_remove(struct pci_dev *pdev)
pci_release_regions(pdev);
pci_disable_device(pdev);
+
+ misc_deregister(&mei_misc_device);
}
#ifdef CONFIG_PM
static int mei_pci_suspend(struct device *device)
@@ -1145,7 +1142,7 @@ static int mei_pci_resume(struct device *device)
err = request_threaded_irq(pdev->irq,
NULL,
mei_interrupt_thread_handler,
- 0, mei_driver_name, dev);
+ IRQF_ONESHOT, mei_driver_name, dev);
else
err = request_threaded_irq(pdev->irq,
mei_interrupt_quick_handler,
@@ -1185,45 +1182,7 @@ static struct pci_driver mei_driver = {
.driver.pm = MEI_PM_OPS,
};
-/**
- * mei_init_module - Driver Registration Routine
- *
- * mei_init_module is the first routine called when the driver is
- * loaded. All it does is to register with the PCI subsystem.
- *
- * returns 0 on success, <0 on failure.
- */
-static int __init mei_init_module(void)
-{
- int ret;
-
- pr_debug("loading.\n");
- /* init pci module */
- ret = pci_register_driver(&mei_driver);
- if (ret < 0)
- pr_err("error registering driver.\n");
-
- return ret;
-}
-
-module_init(mei_init_module);
-
-/**
- * mei_exit_module - Driver Exit Cleanup Routine
- *
- * mei_exit_module is called just before the driver is removed
- * from memory.
- */
-static void __exit mei_exit_module(void)
-{
- misc_deregister(&mei_misc_device);
- pci_unregister_driver(&mei_driver);
-
- pr_debug("unloaded successfully.\n");
-}
-
-module_exit(mei_exit_module);
-
+module_pci_driver(mei_driver);
MODULE_AUTHOR("Intel Corporation");
MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 63d7ee97c5fb..d61c4ddfc80c 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -167,7 +167,10 @@ struct mei_io_list {
struct mei_cl_cb mei_cb;
};
-/* MEI private device struct */
+/**
+ * struct mei_deive - MEI private device struct
+ * @hbuf_depth - depth of host(write) buffer
+ */
struct mei_device {
struct pci_dev *pdev; /* pointer to pci device struct */
/*
@@ -205,6 +208,7 @@ struct mei_device {
*/
u32 host_hw_state;
u32 me_hw_state;
+ u8 hbuf_depth;
/*
* waiting queue for receive message from FW
*/
@@ -237,15 +241,14 @@ struct mei_device {
bool mei_host_buffer_is_empty;
struct mei_cl wd_cl;
+ bool wd_interface_reg;
bool wd_pending;
bool wd_stopped;
bool wd_bypass; /* if false, don't refresh watchdog ME client */
u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */
- u16 wd_due_counter;
unsigned char wd_data[MEI_START_WD_DATA_SIZE];
-
struct file *iamthif_file_object;
struct mei_cl iamthif_cl;
struct mei_cl_cb *iamthif_current_cb;
@@ -259,8 +262,6 @@ struct mei_device {
bool iamthif_flow_control_pending;
bool iamthif_ioctl;
bool iamthif_canceled;
-
- bool wd_interface_reg;
};
@@ -361,7 +362,8 @@ int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid);
*
* returns register value (u32)
*/
-static inline u32 mei_reg_read(struct mei_device *dev, unsigned long offset)
+static inline u32 mei_reg_read(const struct mei_device *dev,
+ unsigned long offset)
{
return ioread32(dev->mem_addr + offset);
}
@@ -373,8 +375,8 @@ static inline u32 mei_reg_read(struct mei_device *dev, unsigned long offset)
* @offset: offset from which to write the data
* @value: register value to write (u32)
*/
-static inline void mei_reg_write(struct mei_device *dev,
- unsigned long offset, u32 value)
+static inline void mei_reg_write(const struct mei_device *dev,
+ unsigned long offset, u32 value)
{
iowrite32(value, dev->mem_addr + offset);
}
@@ -386,7 +388,7 @@ static inline void mei_reg_write(struct mei_device *dev,
*
* returns the byte read.
*/
-static inline u32 mei_hcsr_read(struct mei_device *dev)
+static inline u32 mei_hcsr_read(const struct mei_device *dev)
{
return mei_reg_read(dev, H_CSR);
}
@@ -398,7 +400,7 @@ static inline u32 mei_hcsr_read(struct mei_device *dev)
*
* returns ME_CSR_HA register value (u32)
*/
-static inline u32 mei_mecsr_read(struct mei_device *dev)
+static inline u32 mei_mecsr_read(const struct mei_device *dev)
{
return mei_reg_read(dev, ME_CSR_HA);
}
@@ -410,7 +412,7 @@ static inline u32 mei_mecsr_read(struct mei_device *dev)
*
* returns ME_CB_RW register value (u32)
*/
-static inline u32 mei_mecbrw_read(struct mei_device *dev)
+static inline u32 mei_mecbrw_read(const struct mei_device *dev)
{
return mei_reg_read(dev, ME_CB_RW);
}
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c
index 6be5605707b4..5133fd77b91c 100644
--- a/drivers/misc/mei/wd.c
+++ b/drivers/misc/mei/wd.c
@@ -53,11 +53,12 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
}
/**
- * host_init_wd - mei initialization wd.
+ * mei_wd_host_init - connect to the watchdog client
*
* @dev: the device structure
* returns -ENENT if wd client cannot be found
* -EIO if write has failed
+ * 0 on success
*/
int mei_wd_host_init(struct mei_device *dev)
{
@@ -137,7 +138,6 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
return 0;
dev->wd_timeout = 0;
- dev->wd_due_counter = 0;
memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE);
dev->stop = true;
@@ -341,7 +341,7 @@ static const struct watchdog_ops wd_ops = {
};
static const struct watchdog_info wd_info = {
.identity = INTEL_AMT_WATCHDOG_ID,
- .options = WDIOF_KEEPALIVEPING,
+ .options = WDIOF_KEEPALIVEPING | WDIOF_ALARMONLY,
};
static struct watchdog_device amt_wd_dev = {
@@ -357,8 +357,6 @@ void mei_watchdog_register(struct mei_device *dev)
{
dev_dbg(&dev->pdev->dev, "dev->wd_timeout =%d.\n", dev->wd_timeout);
- dev->wd_due_counter = !!dev->wd_timeout;
-
if (watchdog_register_device(&amt_wd_dev)) {
dev_err(&dev->pdev->dev,
"wd: unable to register watchdog device.\n");