From 169d1338ed4ed91412761a77095a13b9992993ba Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 19 Jun 2012 09:13:35 +0300 Subject: mei: make mei_write_message more readable 1. reduce hairy casting 2. replace open code with mei_count_empty_write_slots 4. include header size in check for overflow 3. use concise for loop instead of a while loop Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interface.c | 49 ++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 31 deletions(-) (limited to 'drivers/misc/mei/interface.c') diff --git a/drivers/misc/mei/interface.c b/drivers/misc/mei/interface.c index 428d21e36416..6c0569177646 100644 --- a/drivers/misc/mei/interface.c +++ b/drivers/misc/mei/interface.c @@ -127,52 +127,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_count_empty_write_slots(dev); + dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots); - if (dw_to_write > empty_slots) + dw_cnt = (length + sizeof(*header) + 3) / 4; + 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(®, &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); -- cgit v1.2.3 From 24aadc809f270857743e62d0882865fb3ba195d9 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 25 Jun 2012 23:46:27 +0300 Subject: mei: don't query HCSR for host buffer depth 1. We record host (write) buffer depth during reset so we don't need to query HCSR register later on. The host buffer depth doesn't change after the reset 2. Use mei_hbuf_max_data function to compute payload size in bytes Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/init.c | 3 +++ drivers/misc/mei/interface.c | 7 +++---- drivers/misc/mei/interface.h | 6 ++++++ drivers/misc/mei/interrupt.c | 6 +++--- drivers/misc/mei/iorw.c | 8 ++------ drivers/misc/mei/main.c | 9 ++------- drivers/misc/mei/mei_dev.h | 6 +++++- 7 files changed, 24 insertions(+), 21 deletions(-) (limited to 'drivers/misc/mei/interface.c') diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index a7d0bb0880ec..d39b2774535b 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"); diff --git a/drivers/misc/mei/interface.c b/drivers/misc/mei/interface.c index 6c0569177646..784a60626fa1 100644 --- a/drivers/misc/mei/interface.c +++ b/drivers/misc/mei/interface.c @@ -103,15 +103,14 @@ int mei_host_buffer_is_empty(struct mei_device *dev) */ int mei_count_empty_write_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; + 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; diff --git a/drivers/misc/mei/interface.h b/drivers/misc/mei/interface.h index ddff5d16616f..8723d8880149 100644 --- a/drivers/misc/mei/interface.h +++ b/drivers/misc/mei/interface.h @@ -49,6 +49,12 @@ int mei_count_empty_write_slots(struct mei_device *dev); int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl); +static inline size_t mei_hbuf_max_data(const struct mei_device *dev) +{ + return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr); +} + + 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 8e4dd74b96e5..4ad6a6bab5a3 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -951,7 +951,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; @@ -1046,8 +1046,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; 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..aaf2683ea154 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; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 4fe653392a49..d60250d663c6 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 */ -- cgit v1.2.3 From 726917f052e62d8012f63a763884957610399afb Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 25 Jun 2012 23:46:28 +0300 Subject: mei: revamp host buffer interface function 1. Use unified _hbuf_ prefix for host/write buffer functions. 2. Cleanup the code w/o functional changes. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interface.c | 31 ++++++++++++------------------- drivers/misc/mei/interface.h | 14 ++++++++------ drivers/misc/mei/interrupt.c | 8 ++++---- 3 files changed, 24 insertions(+), 29 deletions(-) (limited to 'drivers/misc/mei/interface.c') diff --git a/drivers/misc/mei/interface.c b/drivers/misc/mei/interface.c index 784a60626fa1..88ada64c0b54 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,38 +77,29 @@ 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 filled_slots, empty_slots; - dev->host_hw_state = mei_hcsr_read(dev); - filled_slots = _host_get_filled_slots(dev); + filled_slots = mei_hbuf_filled_slots(dev); empty_slots = dev->hbuf_depth - filled_slots; /* check for overflow */ @@ -139,7 +132,7 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, "mei_write_message header=%08x.\n", *((u32 *) header)); - empty_slots = mei_count_empty_write_slots(dev); + empty_slots = mei_hbuf_empty_slots(dev); dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots); dw_cnt = (length + sizeof(*header) + 3) / 4; diff --git a/drivers/misc/mei/interface.h b/drivers/misc/mei/interface.h index 8723d8880149..cd9b778e8dc5 100644 --- a/drivers/misc/mei/interface.h +++ b/drivers/misc/mei/interface.h @@ -41,19 +41,21 @@ 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_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_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); } +int mei_count_full_read_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); diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 4ad6a6bab5a3..1872a2a760e5 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -280,7 +280,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; } @@ -1199,11 +1199,11 @@ 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; @@ -1558,7 +1558,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)) { -- cgit v1.2.3 From 7bdf72d3d8059a50214069ea4b87c2174645f40f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 4 Jul 2012 19:24:52 +0300 Subject: mei: introduce mei_data2slots wrapper Introduce mei_data2slots wrapper for sake of readability. This wrapper close up the open code for computing slots from a message length: rond up dwords count from payload and header byte size Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interface.c | 2 +- drivers/misc/mei/interface.h | 6 ++++++ drivers/misc/mei/interrupt.c | 33 +++++++++++---------------------- 3 files changed, 18 insertions(+), 23 deletions(-) (limited to 'drivers/misc/mei/interface.c') diff --git a/drivers/misc/mei/interface.c b/drivers/misc/mei/interface.c index 88ada64c0b54..509c3957ff45 100644 --- a/drivers/misc/mei/interface.c +++ b/drivers/misc/mei/interface.c @@ -135,7 +135,7 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, empty_slots = mei_hbuf_empty_slots(dev); dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots); - dw_cnt = (length + sizeof(*header) + 3) / 4; + dw_cnt = mei_data2slots(length); if (empty_slots < 0 || dw_cnt > empty_slots) return -EIO; diff --git a/drivers/misc/mei/interface.h b/drivers/misc/mei/interface.h index cd9b778e8dc5..fb5c7db4723b 100644 --- a/drivers/misc/mei/interface.h +++ b/drivers/misc/mei/interface.h @@ -50,6 +50,12 @@ 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); diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 4c1afcf6f4e9..92d762100268 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; @@ -302,8 +301,7 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots, { 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; + *slots -= mei_data2slots(sizeof(struct hbm_client_disconnect_request)); if (mei_disconnect(dev, cl)) { cl->status = 0; @@ -841,8 +839,8 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots, 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; @@ -874,8 +872,7 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots, 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; + *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); if (mei_connect(dev, cl)) { cl->status = -ENODEV; cb_pos->information = 0; @@ -931,8 +928,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 + @@ -959,9 +955,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 + @@ -1020,8 +1014,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 + @@ -1055,8 +1048,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 + @@ -1266,12 +1258,9 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, dev->wd_pending = false; if (dev->wd_timeout) - *slots -= (sizeof(struct mei_msg_hdr) + - MEI_START_WD_DATA_SIZE + 3) / 4; + *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); else - *slots -= (sizeof(struct mei_msg_hdr) + - MEI_WD_PARAMS_SIZE + 3) / 4; - + *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); } } if (dev->stop) -- cgit v1.2.3