From ca455fafc2ef6a26089ba082b89e5d6e89cb2f8f Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 24 May 2016 16:03:35 -0400 Subject: mei: amthif: drop READ_COMPLETE state AMTHIF code now uses read completed queue to store replies from the FW. It is possible to send the next request as soon as a read from the FW is completed. With these changes we don't need the READ_COMPLETE state. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 34 +++++++++++----------------------- drivers/misc/mei/main.c | 2 +- drivers/misc/mei/mei_dev.h | 5 +---- 3 files changed, 13 insertions(+), 28 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index a039a5df6f21..13d89043ad76 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -299,8 +299,7 @@ int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb) /* * The previous request is still in processing, queue this one. */ - if (dev->iamthif_state > MEI_IAMTHIF_IDLE && - dev->iamthif_state < MEI_IAMTHIF_READ_COMPLETE) + if (dev->iamthif_state != MEI_IAMTHIF_IDLE) return 0; return mei_amthif_run_next_cmd(dev); @@ -309,7 +308,6 @@ int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb) /** * mei_amthif_poll - the amthif poll function * - * @dev: the device structure * @file: pointer to file structure * @wait: pointer to poll_table structure * @@ -317,26 +315,19 @@ int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb) * * Locking: called under "dev->device_lock" lock */ - -unsigned int mei_amthif_poll(struct mei_device *dev, - struct file *file, poll_table *wait) +unsigned int mei_amthif_poll(struct file *file, poll_table *wait) { + struct mei_cl *cl = file->private_data; + struct mei_cl_cb *cb = mei_cl_read_cb(cl, file); unsigned int mask = 0; - poll_wait(file, &dev->iamthif_cl.rx_wait, wait); - - if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && - dev->iamthif_fp == file) { - + poll_wait(file, &cl->rx_wait, wait); + if (cb) mask |= POLLIN | POLLRDNORM; - mei_amthif_run_next_cmd(dev); - } return mask; } - - /** * mei_amthif_irq_write - write iamthif command in irq thread context. * @@ -393,7 +384,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, return 0; dev_dbg(dev->dev, "completed amthif read.\n "); - dev->iamthif_current_cb = NULL; dev->iamthif_stall_timer = 0; return 0; @@ -425,14 +415,16 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) } if (!dev->iamthif_canceled) { - dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE; - dev->iamthif_stall_timer = 0; list_add_tail(&cb->list, &cl->rd_completed); dev_dbg(dev->dev, "amthif read completed\n"); } else { - mei_amthif_run_next_cmd(dev); + mei_io_cb_free(cb); } + dev->iamthif_current_cb = NULL; + dev->iamthif_stall_timer = 0; + mei_amthif_run_next_cmd(dev); + dev_dbg(dev->dev, "completing amthif call back.\n"); wake_up_interruptible(&cl->rx_wait); } @@ -539,10 +531,6 @@ int mei_amthif_release(struct mei_device *dev, struct file *file) dev_dbg(dev->dev, "amthif canceled iamthif state %d\n", dev->iamthif_state); dev->iamthif_canceled = true; - if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) { - dev_dbg(dev->dev, "run next amthif iamthif cb\n"); - mei_amthif_run_next_cmd(dev); - } } if (mei_clear_lists(dev, file)) diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 52635b063873..622ff19864df 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -610,7 +610,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) } if (cl == &dev->iamthif_cl) { - mask = mei_amthif_poll(dev, file, wait); + mask = mei_amthif_poll(file, wait); goto out; } diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index e5e32503d4bc..fa6007707048 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -80,9 +80,7 @@ const char *mei_dev_state_str(int state); enum iamthif_states { MEI_IAMTHIF_IDLE, MEI_IAMTHIF_WRITING, - MEI_IAMTHIF_FLOW_CONTROL, MEI_IAMTHIF_READING, - MEI_IAMTHIF_READ_COMPLETE }; enum mei_file_transaction_states { @@ -572,8 +570,7 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl); int mei_amthif_read(struct mei_device *dev, struct file *file, char __user *ubuf, size_t length, loff_t *offset); -unsigned int mei_amthif_poll(struct mei_device *dev, - struct file *file, poll_table *wait); +unsigned int mei_amthif_poll(struct file *file, poll_table *wait); int mei_amthif_release(struct mei_device *dev, struct file *file); -- cgit v1.2.3 From 32a1dc1d02eb41196903278f40d6a4aef66ce535 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 24 May 2016 16:03:36 -0400 Subject: mei: amthif: fix request cancel Currently, all requests cancelled by the user are immediately removed from the queues. Such removal can cause unexpected behavior in the case when a request is partially written or a reply is received after the request is cancelled. To resolve this a request is always fully processed and the result is discarded in case the request was canceled. This completes the partial fix in commit: 9d04ee1 ("mei: amthif: discard not read messages") Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 111 +++++++++++++++---------------------------- drivers/misc/mei/interrupt.c | 2 - 2 files changed, 38 insertions(+), 75 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 13d89043ad76..0cded8aa72c0 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -399,34 +399,44 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) { struct mei_device *dev = cl->dev; - if (cb->fop_type == MEI_FOP_WRITE) { + dev_dbg(dev->dev, "completing amthif call back.\n"); + switch (cb->fop_type) { + case MEI_FOP_WRITE: if (!cb->status) { dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER; mei_io_cb_free(cb); return; } - /* - * in case of error enqueue the write cb to complete read list - * so it can be propagated to the reader - */ - list_add_tail(&cb->list, &cl->rd_completed); - wake_up_interruptible(&cl->rx_wait); - return; - } + dev->iamthif_current_cb = NULL; + dev->iamthif_state = MEI_IAMTHIF_IDLE; + dev->iamthif_fp = NULL; + if (!dev->iamthif_canceled) { + /* + * in case of error enqueue the write cb to complete + * read list so it can be propagated to the reader + */ + list_add_tail(&cb->list, &cl->rd_completed); + wake_up_interruptible(&cl->rx_wait); + } else { + mei_io_cb_free(cb); + } + break; + case MEI_FOP_READ: + if (!dev->iamthif_canceled) { + list_add_tail(&cb->list, &cl->rd_completed); + dev_dbg(dev->dev, "amthif read completed\n"); + wake_up_interruptible(&cl->rx_wait); + } else { + mei_io_cb_free(cb); + } - if (!dev->iamthif_canceled) { - list_add_tail(&cb->list, &cl->rd_completed); - dev_dbg(dev->dev, "amthif read completed\n"); - } else { - mei_io_cb_free(cb); + dev->iamthif_current_cb = NULL; + dev->iamthif_stall_timer = 0; + mei_amthif_run_next_cmd(dev); + break; + default: + WARN_ON(1); } - - dev->iamthif_current_cb = NULL; - dev->iamthif_stall_timer = 0; - mei_amthif_run_next_cmd(dev); - - dev_dbg(dev->dev, "completing amthif call back.\n"); - wake_up_interruptible(&cl->rx_wait); } /** @@ -439,32 +449,15 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) * * mei_clear_list is called to clear resources associated with file * when application calls close function or Ctrl-C was pressed - * - * Return: true if callback removed from the list, false otherwise */ -static bool mei_clear_list(struct mei_device *dev, +static void mei_clear_list(struct mei_device *dev, const struct file *file, struct list_head *mei_cb_list) { - struct mei_cl *cl = &dev->iamthif_cl; struct mei_cl_cb *cb, *next; - bool removed = false; - - /* list all list member */ - list_for_each_entry_safe(cb, next, mei_cb_list, list) { - /* check if list member associated with a file */ - if (file == cb->fp) { - /* check if cb equal to current iamthif cb */ - if (dev->iamthif_current_cb == cb) { - dev->iamthif_current_cb = NULL; - /* send flow control to iamthif client */ - mei_hbm_cl_flow_control_req(dev, cl); - } - /* free all allocated buffers */ + + list_for_each_entry_safe(cb, next, mei_cb_list, list) + if (file == cb->fp) mei_io_cb_free(cb); - removed = true; - } - } - return removed; } /** @@ -475,41 +468,14 @@ static bool mei_clear_list(struct mei_device *dev, * * mei_clear_lists is called to clear resources associated with file * when application calls close function or Ctrl-C was pressed - * - * Return: true if callback removed from the list, false otherwise */ -static bool mei_clear_lists(struct mei_device *dev, const struct file *file) +static void mei_clear_lists(struct mei_device *dev, const struct file *file) { - bool removed = false; struct mei_cl *cl = &dev->iamthif_cl; - /* remove callbacks associated with a file */ mei_clear_list(dev, file, &dev->amthif_cmd_list.list); - if (mei_clear_list(dev, file, &cl->rd_completed)) - removed = true; - + mei_clear_list(dev, file, &cl->rd_completed); mei_clear_list(dev, file, &dev->ctrl_rd_list.list); - - if (mei_clear_list(dev, file, &dev->ctrl_wr_list.list)) - removed = true; - - if (mei_clear_list(dev, file, &dev->write_waiting_list.list)) - removed = true; - - if (mei_clear_list(dev, file, &dev->write_list.list)) - removed = true; - - /* check if iamthif_current_cb not NULL */ - if (dev->iamthif_current_cb && !removed) { - /* check file and iamthif current cb association */ - if (dev->iamthif_current_cb->fp == file) { - /* remove cb */ - mei_io_cb_free(dev->iamthif_current_cb); - dev->iamthif_current_cb = NULL; - removed = true; - } - } - return removed; } /** @@ -533,8 +499,7 @@ int mei_amthif_release(struct mei_device *dev, struct file *file) dev->iamthif_canceled = true; } - if (mei_clear_lists(dev, file)) - dev->iamthif_state = MEI_IAMTHIF_IDLE; + mei_clear_lists(dev, file); return 0; } diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 3831a7ba2531..38db1c3d4f14 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -514,8 +514,6 @@ void mei_timer(struct work_struct *work) if (--dev->iamthif_stall_timer == 0) { dev_err(dev->dev, "timer: amthif hanged.\n"); mei_reset(dev); - dev->iamthif_canceled = false; - dev->iamthif_state = MEI_IAMTHIF_IDLE; mei_io_cb_free(dev->iamthif_current_cb); dev->iamthif_current_cb = NULL; -- cgit v1.2.3 From bca7dbacfd4c7f1f069a70e241e39aea5bd85808 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 24 May 2016 16:03:37 -0400 Subject: mei: amthif: drop iamthif_current_cb iamthif_current_cb was used in request cancel in amthif code. Now a canceled request is discarded only at the end of the processing and the variable lost its purpose and can be safely removed. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 5 ----- drivers/misc/mei/interrupt.c | 3 --- drivers/misc/mei/mei_dev.h | 2 -- 3 files changed, 10 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 0cded8aa72c0..b602fd3b914c 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -47,7 +47,6 @@ const uuid_le mei_amthif_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, void mei_amthif_reset_params(struct mei_device *dev) { /* reset iamthif parameters. */ - dev->iamthif_current_cb = NULL; dev->iamthif_canceled = false; dev->iamthif_state = MEI_IAMTHIF_IDLE; dev->iamthif_stall_timer = 0; @@ -213,7 +212,6 @@ static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file) dev->iamthif_state = MEI_IAMTHIF_READING; dev->iamthif_fp = cb->fp; - dev->iamthif_current_cb = cb; return 0; err: @@ -240,7 +238,6 @@ static int mei_amthif_send_cmd(struct mei_cl *cl, struct mei_cl_cb *cb) dev = cl->dev; dev->iamthif_state = MEI_IAMTHIF_WRITING; - dev->iamthif_current_cb = cb; dev->iamthif_fp = cb->fp; dev->iamthif_canceled = false; @@ -407,7 +404,6 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) mei_io_cb_free(cb); return; } - dev->iamthif_current_cb = NULL; dev->iamthif_state = MEI_IAMTHIF_IDLE; dev->iamthif_fp = NULL; if (!dev->iamthif_canceled) { @@ -430,7 +426,6 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) mei_io_cb_free(cb); } - dev->iamthif_current_cb = NULL; dev->iamthif_stall_timer = 0; mei_amthif_run_next_cmd(dev); break; diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 38db1c3d4f14..436ecda3935e 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -515,9 +515,6 @@ void mei_timer(struct work_struct *work) dev_err(dev->dev, "timer: amthif hanged.\n"); mei_reset(dev); - mei_io_cb_free(dev->iamthif_current_cb); - dev->iamthif_current_cb = NULL; - dev->iamthif_fp = NULL; mei_amthif_run_next_cmd(dev); } diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index fa6007707048..d7b68063ace1 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -400,7 +400,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @amthif_cmd_list : amthif list for cmd waiting * @iamthif_fp : file for current amthif operation * @iamthif_cl : amthif host client - * @iamthif_current_cb : amthif current operation callback * @iamthif_open_count : number of opened amthif connections * @iamthif_stall_timer : timer to detect amthif hang * @iamthif_state : amthif processor state @@ -485,7 +484,6 @@ struct mei_device { /* driver managed amthif list for reading completed amthif cmd data */ const struct file *iamthif_fp; struct mei_cl iamthif_cl; - struct mei_cl_cb *iamthif_current_cb; long iamthif_open_count; u32 iamthif_stall_timer; enum iamthif_states iamthif_state; -- cgit v1.2.3 From 9fa0be8bb66a42a5f75e00a54732c92f3772aa6e Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 24 May 2016 16:03:38 -0400 Subject: mei: amthif: enable poll for async events Currently the poll function is bailing early for amthif client and ignores requests for async events notifications. Move async event processing before amthif to enable async events notifications on amthif client. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 622ff19864df..a8d0471f817f 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -609,17 +609,17 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) goto out; } - if (cl == &dev->iamthif_cl) { - mask = mei_amthif_poll(file, wait); - goto out; - } - if (notify_en) { poll_wait(file, &cl->ev_wait, wait); if (cl->notify_ev) mask |= POLLPRI; } + if (cl == &dev->iamthif_cl) { + mask |= mei_amthif_poll(file, wait); + goto out; + } + if (req_events & (POLLIN | POLLRDNORM)) { poll_wait(file, &cl->rx_wait, wait); -- cgit v1.2.3 From 22393381a489e61b87d85184c02cf070a410c80d Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 24 May 2016 16:03:39 -0400 Subject: mei: amthif: drop mei_amthif_send_cmd Incorporate the mei_amthif_send_cmd code into its only caller: mei_amthif_run_next_cmd Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 52 +++++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 36 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index b602fd3b914c..9885fa40a120 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -219,38 +219,6 @@ err: return rets; } -/** - * mei_amthif_send_cmd - send amthif command to the ME - * - * @cl: the host client - * @cb: mei call back struct - * - * Return: 0 on success, <0 on failure. - */ -static int mei_amthif_send_cmd(struct mei_cl *cl, struct mei_cl_cb *cb) -{ - struct mei_device *dev; - int ret; - - if (!cl->dev || !cb) - return -ENODEV; - - dev = cl->dev; - - dev->iamthif_state = MEI_IAMTHIF_WRITING; - dev->iamthif_fp = cb->fp; - dev->iamthif_canceled = false; - - ret = mei_cl_write(cl, cb, false); - if (ret < 0) - return ret; - - if (cb->completed) - cb->status = mei_amthif_read_start(cl, cb->fp); - - return 0; -} - /** * mei_amthif_run_next_cmd - send next amt command from queue * @@ -262,20 +230,32 @@ int mei_amthif_run_next_cmd(struct mei_device *dev) { struct mei_cl *cl = &dev->iamthif_cl; struct mei_cl_cb *cb; + int ret; dev->iamthif_canceled = false; - dev->iamthif_state = MEI_IAMTHIF_IDLE; - dev->iamthif_fp = NULL; dev_dbg(dev->dev, "complete amthif cmd_list cb.\n"); cb = list_first_entry_or_null(&dev->amthif_cmd_list.list, typeof(*cb), list); - if (!cb) + if (!cb) { + dev->iamthif_state = MEI_IAMTHIF_IDLE; + dev->iamthif_fp = NULL; return 0; + } list_del_init(&cb->list); - return mei_amthif_send_cmd(cl, cb); + dev->iamthif_state = MEI_IAMTHIF_WRITING; + dev->iamthif_fp = cb->fp; + + ret = mei_cl_write(cl, cb, false); + if (ret < 0) + return ret; + + if (cb->completed) + cb->status = mei_amthif_read_start(cl, cb->fp); + + return 0; } /** -- cgit v1.2.3 From 35eda92afa467232ab2a01422b813fa4a14542c5 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 24 May 2016 16:03:40 -0400 Subject: mei: amthif: use mei_cl_alloc_cb for allocating cbs Use mei_cl_alloc_cb wrapper instead of open code steps Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 9885fa40a120..14b454143c81 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -196,17 +196,10 @@ static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file) { struct mei_device *dev = cl->dev; struct mei_cl_cb *cb; - int rets; - - cb = mei_io_cb_init(cl, MEI_FOP_READ, file); - if (!cb) { - rets = -ENOMEM; - goto err; - } - rets = mei_io_cb_alloc_buf(cb, mei_cl_mtu(cl)); - if (rets) - goto err; + cb = mei_cl_alloc_cb(cl, mei_cl_mtu(cl), MEI_FOP_READ, file); + if (!cb) + return -ENOMEM; list_add_tail(&cb->list, &dev->ctrl_wr_list.list); @@ -214,9 +207,6 @@ static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file) dev->iamthif_fp = cb->fp; return 0; -err: - mei_io_cb_free(cb); - return rets; } /** -- cgit v1.2.3 From aab3b1a34ae376a80ebb05a217d950df13db5156 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 24 May 2016 16:03:41 -0400 Subject: mei: drop mei_io_cb_alloc_buf mei_io_cb_alloc_buf have a single caller :mei_cl_alloc_cb. After amthif stopped using it, the code can be integrated into the caller and the function can be dropped. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 32 ++++++-------------------------- drivers/misc/mei/client.h | 2 -- 2 files changed, 6 insertions(+), 28 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 641c1a566687..6658917be64f 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -419,31 +419,6 @@ static inline void mei_io_list_free(struct mei_cl_cb *list, struct mei_cl *cl) __mei_io_list_flush(list, cl, true); } -/** - * mei_io_cb_alloc_buf - allocate callback buffer - * - * @cb: io callback structure - * @length: size of the buffer - * - * Return: 0 on success - * -EINVAL if cb is NULL - * -ENOMEM if allocation failed - */ -int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length) -{ - if (!cb) - return -EINVAL; - - if (length == 0) - return 0; - - cb->buf.data = kmalloc(length, GFP_KERNEL); - if (!cb->buf.data) - return -ENOMEM; - cb->buf.size = length; - return 0; -} - /** * mei_cl_alloc_cb - a convenient wrapper for allocating read cb * @@ -464,10 +439,15 @@ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, if (!cb) return NULL; - if (mei_io_cb_alloc_buf(cb, length)) { + if (length == 0) + return cb; + + cb->buf.data = kmalloc(length, GFP_KERNEL); + if (!cb->buf.data) { mei_io_cb_free(cb); return NULL; } + cb->buf.size = length; return cb; } diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 0d7a3a1fef78..16466aa40cbd 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -85,8 +85,6 @@ static inline u8 mei_me_cl_ver(const struct mei_me_client *me_cl) struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type, const struct file *fp); void mei_io_cb_free(struct mei_cl_cb *priv_cb); -int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length); - /** * mei_io_list_init - Sets up a queue list. -- cgit v1.2.3 From 77537ad2917bbca0a73ee6ebd44fc0ce5416d590 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 16 Jun 2016 17:58:52 +0300 Subject: mei: recover after errors in runtime pm flow Schedule link reset if failed to perform runtime suspend or resume. Set active runtime pm stte on link reset to clean runtimr pm error, if present. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 3 +++ drivers/misc/mei/hw-txe.c | 3 +++ drivers/misc/mei/pci-me.c | 6 ++++++ drivers/misc/mei/pci-txe.c | 7 +++++++ 4 files changed, 19 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index e2fb44cc5c37..c2d70d2dd112 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -18,6 +18,7 @@ #include #include +#include #include "mei_dev.h" #include "hbm.h" @@ -1063,6 +1064,8 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable) } } + pm_runtime_set_active(dev->dev); + hcsr = mei_hcsr_read(dev); /* H_RST may be found lit before reset is started, * for example if preceding reset flow hasn't completed. diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c index 4a6c1b85f11e..e6e5e55a12ed 100644 --- a/drivers/misc/mei/hw-txe.c +++ b/drivers/misc/mei/hw-txe.c @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -935,6 +936,8 @@ static int mei_txe_hw_start(struct mei_device *dev) return ret; } + pm_runtime_set_active(dev->dev); + /* enable input ready interrupts: * SEC_IPC_HOST_INT_MASK.IPC_INPUT_READY_INT_MASK */ diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 64e64da6da44..718addfa9fb0 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -400,6 +400,9 @@ static int mei_me_pm_runtime_suspend(struct device *device) dev_dbg(&pdev->dev, "rpm: me: runtime suspend ret=%d\n", ret); + if (ret && ret != -EAGAIN) + schedule_work(&dev->reset_work); + return ret; } @@ -423,6 +426,9 @@ static int mei_me_pm_runtime_resume(struct device *device) dev_dbg(&pdev->dev, "rpm: me: runtime resume ret = %d\n", ret); + if (ret) + schedule_work(&dev->reset_work); + return ret; } diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c index 30cc30683c07..58ffd30dcc91 100644 --- a/drivers/misc/mei/pci-txe.c +++ b/drivers/misc/mei/pci-txe.c @@ -347,6 +347,10 @@ static int mei_txe_pm_runtime_suspend(struct device *device) dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret); mutex_unlock(&dev->device_lock); + + if (ret && ret != -EAGAIN) + schedule_work(&dev->reset_work); + return ret; } @@ -372,6 +376,9 @@ static int mei_txe_pm_runtime_resume(struct device *device) dev_dbg(&pdev->dev, "rpm: txe: runtime resume ret = %d\n", ret); + if (ret) + schedule_work(&dev->reset_work); + return ret; } -- cgit v1.2.3 From 041330d9c33e975791f4d543db3f25d9a6c474c9 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 16 Jun 2016 17:58:53 +0300 Subject: mei: hbm: add missing argument in the kdoc In mei_hbm_cl_hdr buf argument was not described Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hbm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 085f3aafe6fa..b1697a329af1 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -161,6 +161,7 @@ void mei_hbm_cl_hdr(struct mei_cl *cl, u8 hbm_cmd, void *buf, size_t len) * @dev: the device structure * @cl: client * @hbm_cmd: host bus message command + * @buf: message buffer * @len: buffer length * * Return: 0 on success, <0 on failure. -- cgit v1.2.3 From 1eb5bd4d83f566e5ea8521b6020d0cfcb8f1c3ef Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 16 Jun 2016 17:58:54 +0300 Subject: mei: drop read complete queue emptiness check In the course of the read flow we want to wait for read completion only if the read queue is empty. However the calling list_empty(&cl->rd_completed) is a duplication as the same check was performed by mei_cl_read_cb() and the waiting is skipped if it returns not NULL. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 3 ++- drivers/misc/mei/main.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 1f33fea9299f..63411ddfb83d 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -126,7 +126,8 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) goto out; /* wait on event only if there is no other waiter */ - if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) { + /* synchronized under device mutex */ + if (!waitqueue_active(&cl->rx_wait)) { mutex_unlock(&bus->device_lock); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index a8d0471f817f..3326bde7fba1 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -183,7 +183,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, goto out; } - if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) { + /* synchronized under device mutex */ + if (!waitqueue_active(&cl->rx_wait)) { if (file->f_flags & O_NONBLOCK) { rets = -EAGAIN; goto out; -- cgit v1.2.3 From 2d4d5481e2d6f93b25fcfb13a9f20bbfbf54266a Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 23 Jun 2016 00:25:31 +0300 Subject: mei: fix return value on disconnection Correct errno on client disconnection is -ENODEV not -EBUSY Cc: #4.3+ Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 2 +- drivers/misc/mei/bus.c | 2 +- drivers/misc/mei/main.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 14b454143c81..3cf54ca051ea 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -132,7 +132,7 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, return -ERESTARTSYS; if (!mei_cl_is_connected(cl)) { - rets = -EBUSY; + rets = -ENODEV; goto out; } diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 63411ddfb83d..9c404dc8eada 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -143,7 +143,7 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) mutex_lock(&bus->device_lock); if (!mei_cl_is_connected(cl)) { - rets = -EBUSY; + rets = -ENODEV; goto out; } } diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 3326bde7fba1..d62e89c80beb 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -203,7 +203,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, mutex_lock(&dev->device_lock); if (!mei_cl_is_connected(cl)) { - rets = -EBUSY; + rets = -ENODEV; goto out; } } -- cgit v1.2.3 From a03c608f25fbe2eb5f2862a4dab1791948496215 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 16 Jun 2016 17:58:56 +0300 Subject: mei: move read cb to complete queue if not connected Move read cb to the completion queue if a read finds out that client is not connected. This expedite user space reader wake on error condition. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interrupt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 436ecda3935e..412229e7bb7c 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -113,6 +113,7 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, if (!mei_cl_is_connected(cl)) { cl_dbg(dev, cl, "not connected\n"); + list_move_tail(&cb->list, &complete_list->list); cb->status = -ENODEV; goto out; } -- cgit v1.2.3 From 97d549b4d5fca22ebde0798cb8c16c19b4ae837a Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 16 Jun 2016 17:58:57 +0300 Subject: mei: add file pointer to the host client structure Store the file associated with a client in the host client structure, this enables dropping the special amthif client file pointer from struct mei_device, and this is also a preparation for changing the way rx packet allocation for fixed_address clients Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 13 +++++++------ drivers/misc/mei/interrupt.c | 1 - drivers/misc/mei/main.c | 1 + drivers/misc/mei/mei_dev.h | 5 ++--- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 3cf54ca051ea..e346af17d9f4 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -204,7 +204,7 @@ static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file) list_add_tail(&cb->list, &dev->ctrl_wr_list.list); dev->iamthif_state = MEI_IAMTHIF_READING; - dev->iamthif_fp = cb->fp; + cl->fp = cb->fp; return 0; } @@ -230,13 +230,13 @@ int mei_amthif_run_next_cmd(struct mei_device *dev) typeof(*cb), list); if (!cb) { dev->iamthif_state = MEI_IAMTHIF_IDLE; - dev->iamthif_fp = NULL; + cl->fp = NULL; return 0; } list_del_init(&cb->list); dev->iamthif_state = MEI_IAMTHIF_WRITING; - dev->iamthif_fp = cb->fp; + cl->fp = cb->fp; ret = mei_cl_write(cl, cb, false); if (ret < 0) @@ -375,7 +375,7 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) return; } dev->iamthif_state = MEI_IAMTHIF_IDLE; - dev->iamthif_fp = NULL; + cl->fp = NULL; if (!dev->iamthif_canceled) { /* * in case of error enqueue the write cb to complete @@ -453,11 +453,12 @@ static void mei_clear_lists(struct mei_device *dev, const struct file *file) */ int mei_amthif_release(struct mei_device *dev, struct file *file) { + struct mei_cl *cl = file->private_data; + if (dev->iamthif_open_count > 0) dev->iamthif_open_count--; - if (dev->iamthif_fp == file && - dev->iamthif_state != MEI_IAMTHIF_IDLE) { + if (cl->fp == file && dev->iamthif_state != MEI_IAMTHIF_IDLE) { dev_dbg(dev->dev, "amthif canceled iamthif state %d\n", dev->iamthif_state); diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 412229e7bb7c..8b5e4b4c4c15 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -516,7 +516,6 @@ void mei_timer(struct work_struct *work) dev_err(dev->dev, "timer: amthif hanged.\n"); mei_reset(dev); - dev->iamthif_fp = NULL; mei_amthif_run_next_cmd(dev); } } diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index d62e89c80beb..d7ef5edf044a 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -71,6 +71,7 @@ static int mei_open(struct inode *inode, struct file *file) goto err_unlock; } + cl->fp = file; file->private_data = cl; mutex_unlock(&dev->device_lock); diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index d7b68063ace1..aaefbc87c2fc 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -200,6 +200,7 @@ struct mei_cl_cb { * @ev_async: event async notification * @status: connection status * @me_cl: fw client connected + * @fp: file associated with client * @host_client_id: host id * @mei_flow_ctrl_creds: transmit flow credentials * @timer_count: watchdog timer for operation completion @@ -223,6 +224,7 @@ struct mei_cl { struct fasync_struct *ev_async; int status; struct mei_me_client *me_cl; + const struct file *fp; u8 host_client_id; u8 mei_flow_ctrl_creds; u8 timer_count; @@ -398,7 +400,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @override_fixed_address: force allow fixed address behavior * * @amthif_cmd_list : amthif list for cmd waiting - * @iamthif_fp : file for current amthif operation * @iamthif_cl : amthif host client * @iamthif_open_count : number of opened amthif connections * @iamthif_stall_timer : timer to detect amthif hang @@ -481,8 +482,6 @@ struct mei_device { /* amthif list for cmd waiting */ struct mei_cl_cb amthif_cmd_list; - /* driver managed amthif list for reading completed amthif cmd data */ - const struct file *iamthif_fp; struct mei_cl iamthif_cl; long iamthif_open_count; u32 iamthif_stall_timer; -- cgit v1.2.3 From a808c80cdaa83939b220176fcdffca8385d88ba6 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 16 Jun 2016 17:58:58 +0300 Subject: mei: add read callback on demand for fixed_address clients The Fixed address clients do not work with the flow control, and the packet RX callback was allocated upon TX with anticipation of a following RX. This won't work if the clients with unsolicited Rx. Rather than preparing read callback upon a write we allocate one directly on the reciev path if one doesn't exists. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 15 ++++----------- drivers/misc/mei/interrupt.c | 10 ++++++++-- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 6658917be64f..2a09db86e50e 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1145,26 +1145,19 @@ err: * mei_cl_flow_ctrl_creds - checks flow_control credits for cl. * * @cl: host client - * @fp: the file pointer associated with the pointer * * Return: 1 if mei_flow_ctrl_creds >0, 0 - otherwise. */ -static int mei_cl_flow_ctrl_creds(struct mei_cl *cl, const struct file *fp) +static int mei_cl_flow_ctrl_creds(struct mei_cl *cl) { - int rets; - if (WARN_ON(!cl || !cl->me_cl)) return -EINVAL; if (cl->mei_flow_ctrl_creds > 0) return 1; - if (mei_cl_is_fixed_address(cl)) { - rets = mei_cl_read_start(cl, mei_cl_mtu(cl), fp); - if (rets && rets != -EBUSY) - return rets; + if (mei_cl_is_fixed_address(cl)) return 1; - } if (mei_cl_is_single_recv_buf(cl)) { if (cl->me_cl->mei_flow_ctrl_creds > 0) @@ -1537,7 +1530,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, first_chunk = cb->buf_idx == 0; - rets = first_chunk ? mei_cl_flow_ctrl_creds(cl, cb->fp) : 1; + rets = first_chunk ? mei_cl_flow_ctrl_creds(cl) : 1; if (rets < 0) return rets; @@ -1643,7 +1636,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking) mei_hdr.msg_complete = 0; mei_hdr.internal = cb->internal; - rets = mei_cl_flow_ctrl_creds(cl, cb->fp); + rets = mei_cl_flow_ctrl_creds(cl); if (rets < 0) goto err; diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 8b5e4b4c4c15..44ba90140725 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -107,8 +107,14 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, cb = list_first_entry_or_null(&cl->rd_pending, struct mei_cl_cb, list); if (!cb) { - cl_err(dev, cl, "pending read cb not found\n"); - goto out; + if (!mei_cl_is_fixed_address(cl)) { + cl_err(dev, cl, "pending read cb not found\n"); + goto out; + } + cb = mei_cl_alloc_cb(cl, mei_cl_mtu(cl), MEI_FOP_READ, cl->fp); + if (!cb) + goto out; + list_add_tail(&cb->list, &cl->rd_pending); } if (!mei_cl_is_connected(cl)) { -- cgit v1.2.3 From c85dba9e87376aa8e08fa7b024df562d0fda189b Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 16 Jun 2016 17:58:59 +0300 Subject: mei: amthif: drop mei_clear_lists function Open code mei_clear_lists into its only caller mei_amthif_releas and drop unused parameter 'dev' form from mei_clear_list function. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index e346af17d9f4..26568c5beb25 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -408,15 +408,14 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) * mei_clear_list - removes all callbacks associated with file * from mei_cb_list * - * @dev: device structure. * @file: file structure * @mei_cb_list: callbacks list * * mei_clear_list is called to clear resources associated with file * when application calls close function or Ctrl-C was pressed */ -static void mei_clear_list(struct mei_device *dev, - const struct file *file, struct list_head *mei_cb_list) +static void mei_clear_list(const struct file *file, + struct list_head *mei_cb_list) { struct mei_cl_cb *cb, *next; @@ -425,24 +424,6 @@ static void mei_clear_list(struct mei_device *dev, mei_io_cb_free(cb); } -/** - * mei_clear_lists - removes all callbacks associated with file - * - * @dev: device structure - * @file: file structure - * - * mei_clear_lists is called to clear resources associated with file - * when application calls close function or Ctrl-C was pressed - */ -static void mei_clear_lists(struct mei_device *dev, const struct file *file) -{ - struct mei_cl *cl = &dev->iamthif_cl; - - mei_clear_list(dev, file, &dev->amthif_cmd_list.list); - mei_clear_list(dev, file, &cl->rd_completed); - mei_clear_list(dev, file, &dev->ctrl_rd_list.list); -} - /** * mei_amthif_release - the release function * @@ -465,7 +446,9 @@ int mei_amthif_release(struct mei_device *dev, struct file *file) dev->iamthif_canceled = true; } - mei_clear_lists(dev, file); + mei_clear_list(file, &dev->amthif_cmd_list.list); + mei_clear_list(file, &cl->rd_completed); + mei_clear_list(file, &dev->ctrl_rd_list.list); return 0; } -- cgit v1.2.3 From dfe5f753d06a4eaf362872a7f30aabe5f5fc968c Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 26 Jul 2016 01:06:01 +0300 Subject: mei: drop redundant krealloc and checks in irq read The read callback is always prepared with MTU-sized buffer and the FW can't send more than the MTU in one message. Checking for buffer existence and krealloc to increase receive buffer size are redundant and may be safely discarded. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interrupt.c | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 44ba90140725..36382d782e20 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -102,18 +102,17 @@ 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) { if (!mei_cl_is_fixed_address(cl)) { cl_err(dev, cl, "pending read cb not found\n"); - goto out; + goto discard; } cb = mei_cl_alloc_cb(cl, mei_cl_mtu(cl), MEI_FOP_READ, cl->fp); if (!cb) - goto out; + goto discard; list_add_tail(&cb->list, &cl->rd_pending); } @@ -121,14 +120,7 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, cl_dbg(dev, cl, "not connected\n"); list_move_tail(&cb->list, &complete_list->list); cb->status = -ENODEV; - goto out; - } - - if (cb->buf.size == 0 || cb->buf.data == NULL) { - cl_err(dev, cl, "response buffer is not allocated.\n"); - list_move_tail(&cb->list, &complete_list->list); - cb->status = -ENOMEM; - goto out; + goto discard; } buf_sz = mei_hdr->length + cb->buf_idx; @@ -139,25 +131,19 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, list_move_tail(&cb->list, &complete_list->list); cb->status = -EMSGSIZE; - goto out; + goto discard; } 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, buf_sz, GFP_KERNEL); - if (!buffer) { - cb->status = -ENOMEM; - list_move_tail(&cb->list, &complete_list->list); - goto out; - } - cb->buf.data = buffer; - cb->buf.size = buf_sz; + list_move_tail(&cb->list, &complete_list->list); + cb->status = -EMSGSIZE; + goto discard; } - buffer = cb->buf.data + cb->buf_idx; - mei_read_slots(dev, buffer, mei_hdr->length); + mei_read_slots(dev, cb->buf.data + cb->buf_idx, mei_hdr->length); cb->buf_idx += mei_hdr->length; @@ -169,10 +155,10 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, pm_request_autosuspend(dev->dev); } -out: - if (!buffer) - mei_irq_discard_msg(dev, mei_hdr); + return 0; +discard: + mei_irq_discard_msg(dev, mei_hdr); return 0; } -- cgit v1.2.3 From e51dfa5a7f89b2c96371559b0c9772fd41376464 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 26 Jul 2016 01:06:02 +0300 Subject: mei: prepare read cb for fixed address clients on the receive path only. The read callbacks for the fixed address clients, that don't have flow control are built now on the receive path. In order to have a single allocation place we remove the allocation from the read request. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 2a09db86e50e..05cacc3e718f 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1459,17 +1459,15 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp) return -ENOTTY; } + if (mei_cl_is_fixed_address(cl)) + return 0; + /* always allocate at least client max message */ length = max_t(size_t, length, mei_cl_mtu(cl)); cb = mei_cl_alloc_cb(cl, length, MEI_FOP_READ, fp); if (!cb) return -ENOMEM; - if (mei_cl_is_fixed_address(cl)) { - list_add_tail(&cb->list, &cl->rd_pending); - return 0; - } - rets = pm_runtime_get(dev->dev); if (rets < 0 && rets != -EINPROGRESS) { pm_runtime_put_noidle(dev->dev); -- cgit v1.2.3 From 46978ada7dc669bf13f860798664b587dbc05ce5 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 26 Jul 2016 01:06:03 +0300 Subject: mei: rx flow control counter Use RX flow control counter in the host client structure to track the number of simultaneous outstanding reads. This eliminates search in queues and makes ground for enabling for parallel read. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 1 + drivers/misc/mei/client.c | 40 +++++++++++++--------------------------- drivers/misc/mei/mei_dev.h | 4 ++-- 3 files changed, 16 insertions(+), 29 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 26568c5beb25..227fd5a816a6 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -202,6 +202,7 @@ static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file) return -ENOMEM; list_add_tail(&cb->list, &dev->ctrl_wr_list.list); + cl->rx_flow_ctrl_creds++; dev->iamthif_state = MEI_IAMTHIF_READING; cl->fp = cb->fp; diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 05cacc3e718f..ded11de90a26 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -735,6 +735,7 @@ void mei_cl_set_disconnected(struct mei_cl *cl) mei_io_list_flush(&dev->ctrl_wr_list, cl); mei_cl_wake_all(cl); cl->mei_flow_ctrl_creds = 0; + cl->rx_flow_ctrl_creds = 0; cl->timer_count = 0; if (!cl->me_cl) @@ -1408,25 +1409,6 @@ out: return 0; } -/** - * mei_cl_is_read_fc_cb - check if read cb is waiting for flow control - * for given host client - * - * @cl: host client - * - * Return: true, if found at least one cb. - */ -static bool mei_cl_is_read_fc_cb(struct mei_cl *cl) -{ - struct mei_device *dev = cl->dev; - struct mei_cl_cb *cb; - - list_for_each_entry(cb, &dev->ctrl_wr_list.list, list) - if (cb->fop_type == MEI_FOP_READ && cb->cl == cl) - return true; - return false; -} - /** * mei_cl_read_start - the start read client message function. * @@ -1450,10 +1432,6 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp) if (!mei_cl_is_connected(cl)) return -ENODEV; - /* HW currently supports only one pending read */ - if (!list_empty(&cl->rd_pending) || mei_cl_is_read_fc_cb(cl)) - return -EBUSY; - if (!mei_me_cl_is_active(cl->me_cl)) { cl_err(dev, cl, "no such me client\n"); return -ENOTTY; @@ -1462,12 +1440,18 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp) if (mei_cl_is_fixed_address(cl)) return 0; + /* HW currently supports only one pending read */ + if (cl->rx_flow_ctrl_creds) + return -EBUSY; + /* always allocate at least client max message */ length = max_t(size_t, length, mei_cl_mtu(cl)); cb = mei_cl_alloc_cb(cl, length, MEI_FOP_READ, fp); if (!cb) return -ENOMEM; + list_add_tail(&cb->list, &dev->ctrl_wr_list.list); + rets = pm_runtime_get(dev->dev); if (rets < 0 && rets != -EINPROGRESS) { pm_runtime_put_noidle(dev->dev); @@ -1475,16 +1459,15 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp) goto nortpm; } + rets = 0; if (mei_hbuf_acquire(dev)) { rets = mei_hbm_cl_flow_control_req(dev, cl); if (rets < 0) goto out; - list_add_tail(&cb->list, &cl->rd_pending); - } else { - rets = 0; - list_add_tail(&cb->list, &dev->ctrl_wr_list.list); + list_move_tail(&cb->list, &cl->rd_pending); } + cl->rx_flow_ctrl_creds++; out: cl_dbg(dev, cl, "rpm: autosuspend\n"); @@ -1732,6 +1715,9 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb) case MEI_FOP_READ: list_add_tail(&cb->list, &cl->rd_completed); + if (!mei_cl_is_fixed_address(cl) && + !WARN_ON(!cl->rx_flow_ctrl_creds)) + cl->rx_flow_ctrl_creds--; if (!mei_cl_bus_rx_event(cl)) wake_up_interruptible(&cl->rx_wait); break; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index aaefbc87c2fc..8bdb28054423 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -203,8 +203,8 @@ struct mei_cl_cb { * @fp: file associated with client * @host_client_id: host id * @mei_flow_ctrl_creds: transmit flow credentials + * @rx_flow_ctrl_creds: receive flow credentials * @timer_count: watchdog timer for operation completion - * @reserved: reserved for alignment * @notify_en: notification - enabled/disabled * @notify_ev: pending notification event * @writing_state: state of the tx @@ -227,8 +227,8 @@ struct mei_cl { const struct file *fp; u8 host_client_id; u8 mei_flow_ctrl_creds; + u8 rx_flow_ctrl_creds; u8 timer_count; - u8 reserved; u8 notify_en; u8 notify_ev; enum mei_file_transaction_states writing_state; -- cgit v1.2.3 From 4034b81ba38967ad0056781572a9d9a95d39f02e Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 26 Jul 2016 01:06:04 +0300 Subject: mei: use consistent naming for TX control flow credits With the introduction of the receive control flow credits prefixed with rx_ we add tx_ prefix to the variables and function used for tracking the transmit control flow credits. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 39 +++++++++++++++++++-------------------- drivers/misc/mei/hbm.c | 41 ++++++++++++++++++++--------------------- drivers/misc/mei/mei_dev.h | 8 ++++---- 3 files changed, 43 insertions(+), 45 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index ded11de90a26..89425a8795a8 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -734,8 +734,8 @@ void mei_cl_set_disconnected(struct mei_cl *cl) mei_io_list_flush(&dev->ctrl_rd_list, cl); mei_io_list_flush(&dev->ctrl_wr_list, cl); mei_cl_wake_all(cl); - cl->mei_flow_ctrl_creds = 0; cl->rx_flow_ctrl_creds = 0; + cl->tx_flow_ctrl_creds = 0; cl->timer_count = 0; if (!cl->me_cl) @@ -745,7 +745,7 @@ void mei_cl_set_disconnected(struct mei_cl *cl) cl->me_cl->connect_count--; if (cl->me_cl->connect_count == 0) - cl->me_cl->mei_flow_ctrl_creds = 0; + cl->me_cl->tx_flow_ctrl_creds = 0; mei_me_cl_put(cl->me_cl); cl->me_cl = NULL; @@ -1140,43 +1140,42 @@ err: return ERR_PTR(ret); } - - /** - * mei_cl_flow_ctrl_creds - checks flow_control credits for cl. + * mei_cl_tx_flow_ctrl_creds - checks flow_control credits for cl. * * @cl: host client * - * Return: 1 if mei_flow_ctrl_creds >0, 0 - otherwise. + * Return: 1 if tx_flow_ctrl_creds >0, 0 - otherwise. */ -static int mei_cl_flow_ctrl_creds(struct mei_cl *cl) +static int mei_cl_tx_flow_ctrl_creds(struct mei_cl *cl) { if (WARN_ON(!cl || !cl->me_cl)) return -EINVAL; - if (cl->mei_flow_ctrl_creds > 0) + if (cl->tx_flow_ctrl_creds > 0) return 1; if (mei_cl_is_fixed_address(cl)) return 1; if (mei_cl_is_single_recv_buf(cl)) { - if (cl->me_cl->mei_flow_ctrl_creds > 0) + if (cl->me_cl->tx_flow_ctrl_creds > 0) return 1; } return 0; } /** - * mei_cl_flow_ctrl_reduce - reduces flow_control. + * mei_cl_tx_flow_ctrl_creds_reduce - reduces transmit flow control credits + * for a client * - * @cl: private data of the file object + * @cl: host client * * Return: * 0 on success * -EINVAL when ctrl credits are <= 0 */ -static int mei_cl_flow_ctrl_reduce(struct mei_cl *cl) +static int mei_cl_tx_flow_ctrl_creds_reduce(struct mei_cl *cl) { if (WARN_ON(!cl || !cl->me_cl)) return -EINVAL; @@ -1185,13 +1184,13 @@ static int mei_cl_flow_ctrl_reduce(struct mei_cl *cl) return 0; if (mei_cl_is_single_recv_buf(cl)) { - if (WARN_ON(cl->me_cl->mei_flow_ctrl_creds <= 0)) + if (WARN_ON(cl->me_cl->tx_flow_ctrl_creds <= 0)) return -EINVAL; - cl->me_cl->mei_flow_ctrl_creds--; + cl->me_cl->tx_flow_ctrl_creds--; } else { - if (WARN_ON(cl->mei_flow_ctrl_creds <= 0)) + if (WARN_ON(cl->tx_flow_ctrl_creds <= 0)) return -EINVAL; - cl->mei_flow_ctrl_creds--; + cl->tx_flow_ctrl_creds--; } return 0; } @@ -1511,7 +1510,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, first_chunk = cb->buf_idx == 0; - rets = first_chunk ? mei_cl_flow_ctrl_creds(cl) : 1; + rets = first_chunk ? mei_cl_tx_flow_ctrl_creds(cl) : 1; if (rets < 0) return rets; @@ -1559,7 +1558,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, cb->completed = mei_hdr.msg_complete == 1; if (first_chunk) { - if (mei_cl_flow_ctrl_reduce(cl)) + if (mei_cl_tx_flow_ctrl_creds_reduce(cl)) return -EIO; } @@ -1617,7 +1616,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking) mei_hdr.msg_complete = 0; mei_hdr.internal = cb->internal; - rets = mei_cl_flow_ctrl_creds(cl); + rets = mei_cl_tx_flow_ctrl_creds(cl); if (rets < 0) goto err; @@ -1645,7 +1644,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking) if (rets) goto err; - rets = mei_cl_flow_ctrl_reduce(cl); + rets = mei_cl_tx_flow_ctrl_creds_reduce(cl); if (rets) goto err; diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index b1697a329af1..c8e8a8d22019 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -340,7 +340,7 @@ static int mei_hbm_me_cl_add(struct mei_device *dev, me_cl->props = res->client_properties; me_cl->client_id = res->me_addr; - me_cl->mei_flow_ctrl_creds = 0; + me_cl->tx_flow_ctrl_creds = 0; mei_me_cl_add(dev, me_cl); @@ -637,23 +637,22 @@ int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl) } /** - * mei_hbm_add_single_flow_creds - adds single buffer credentials. + * mei_hbm_add_single_tx_flow_ctrl_creds - adds single buffer credentials. * * @dev: the device structure - * @flow: flow control. + * @fctrl: flow control response bus message * * Return: 0 on success, < 0 otherwise */ -static int mei_hbm_add_single_flow_creds(struct mei_device *dev, - struct hbm_flow_control *flow) +static int mei_hbm_add_single_tx_flow_ctrl_creds(struct mei_device *dev, + struct hbm_flow_control *fctrl) { struct mei_me_client *me_cl; int rets; - me_cl = mei_me_cl_by_id(dev, flow->me_addr); + me_cl = mei_me_cl_by_id(dev, fctrl->me_addr); if (!me_cl) { - dev_err(dev->dev, "no such me client %d\n", - flow->me_addr); + dev_err(dev->dev, "no such me client %d\n", fctrl->me_addr); return -ENOENT; } @@ -662,9 +661,9 @@ static int mei_hbm_add_single_flow_creds(struct mei_device *dev, goto out; } - me_cl->mei_flow_ctrl_creds++; + me_cl->tx_flow_ctrl_creds++; dev_dbg(dev->dev, "recv flow ctrl msg ME %d (single) creds = %d.\n", - flow->me_addr, me_cl->mei_flow_ctrl_creds); + fctrl->me_addr, me_cl->tx_flow_ctrl_creds); rets = 0; out: @@ -676,24 +675,24 @@ out: * mei_hbm_cl_flow_control_res - flow control response from me * * @dev: the device structure - * @flow_control: flow control response bus message + * @fctrl: flow control response bus message */ -static void mei_hbm_cl_flow_control_res(struct mei_device *dev, - struct hbm_flow_control *flow_control) +static void mei_hbm_cl_tx_flow_ctrl_creds_res(struct mei_device *dev, + struct hbm_flow_control *fctrl) { struct mei_cl *cl; - if (!flow_control->host_addr) { + if (!fctrl->host_addr) { /* single receive buffer */ - mei_hbm_add_single_flow_creds(dev, flow_control); + mei_hbm_add_single_tx_flow_ctrl_creds(dev, fctrl); return; } - cl = mei_hbm_cl_find_by_cmd(dev, flow_control); + cl = mei_hbm_cl_find_by_cmd(dev, fctrl); if (cl) { - cl->mei_flow_ctrl_creds++; + cl->tx_flow_ctrl_creds++; cl_dbg(dev, cl, "flow control creds = %d.\n", - cl->mei_flow_ctrl_creds); + cl->tx_flow_ctrl_creds); } } @@ -1023,7 +1022,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) struct mei_hbm_cl_cmd *cl_cmd; struct hbm_client_connect_request *disconnect_req; - struct hbm_flow_control *flow_control; + struct hbm_flow_control *fctrl; /* read the message to our buffer */ BUG_ON(hdr->length >= sizeof(dev->rd_msg_buf)); @@ -1103,8 +1102,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) case MEI_FLOW_CONTROL_CMD: dev_dbg(dev->dev, "hbm: client flow control response: message received.\n"); - flow_control = (struct hbm_flow_control *) mei_msg; - mei_hbm_cl_flow_control_res(dev, flow_control); + fctrl = (struct hbm_flow_control *)mei_msg; + mei_hbm_cl_tx_flow_ctrl_creds_res(dev, fctrl); break; case MEI_PG_ISOLATION_ENTRY_RES_CMD: diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 8bdb28054423..7c8fa8d70e11 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -144,7 +144,7 @@ struct mei_fw_status { * @refcnt: struct reference count * @props: client properties * @client_id: me client id - * @mei_flow_ctrl_creds: flow control credits + * @tx_flow_ctrl_creds: flow control credits * @connect_count: number connections to this client * @bus_added: added to bus */ @@ -153,7 +153,7 @@ struct mei_me_client { struct kref refcnt; struct mei_client_properties props; u8 client_id; - u8 mei_flow_ctrl_creds; + u8 tx_flow_ctrl_creds; u8 connect_count; u8 bus_added; }; @@ -202,7 +202,7 @@ struct mei_cl_cb { * @me_cl: fw client connected * @fp: file associated with client * @host_client_id: host id - * @mei_flow_ctrl_creds: transmit flow credentials + * @tx_flow_ctrl_creds: transmit flow credentials * @rx_flow_ctrl_creds: receive flow credentials * @timer_count: watchdog timer for operation completion * @notify_en: notification - enabled/disabled @@ -226,7 +226,7 @@ struct mei_cl { struct mei_me_client *me_cl; const struct file *fp; u8 host_client_id; - u8 mei_flow_ctrl_creds; + u8 tx_flow_ctrl_creds; u8 rx_flow_ctrl_creds; u8 timer_count; u8 notify_en; -- cgit v1.2.3 From 3030dc056459439d756d81a920e135893076a348 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 26 Jul 2016 01:06:05 +0300 Subject: mei: add wrapper for queuing control commands. Enclose the boiler plate code of allocating a control/hbm command cb and enqueueing it onto ctrl_wr.list in a convenient wrapper mei_cl_enqueue_ctrl_wr_cb(). This is a preparatory patch for enabling consecutive reads. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 7 ++--- drivers/misc/mei/bus.c | 4 +-- drivers/misc/mei/client.c | 78 ++++++++++++++++++++++++++++++----------------- drivers/misc/mei/client.h | 5 +-- drivers/misc/mei/hbm.c | 4 +-- drivers/misc/mei/main.c | 2 +- 6 files changed, 61 insertions(+), 39 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 227fd5a816a6..e8029235504d 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -188,20 +188,19 @@ out: * mei_amthif_read_start - queue message for sending read credential * * @cl: host client - * @file: file pointer of message recipient + * @fp: file pointer of message recipient * * Return: 0 on success, <0 on failure. */ -static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file) +static int mei_amthif_read_start(struct mei_cl *cl, const struct file *fp) { struct mei_device *dev = cl->dev; struct mei_cl_cb *cb; - cb = mei_cl_alloc_cb(cl, mei_cl_mtu(cl), MEI_FOP_READ, file); + cb = mei_cl_enqueue_ctrl_wr_cb(cl, mei_cl_mtu(cl), MEI_FOP_READ, fp); if (!cb) return -ENOMEM; - list_add_tail(&cb->list, &dev->ctrl_wr_list.list); cl->rx_flow_ctrl_creds++; dev->iamthif_state = MEI_IAMTHIF_READING; diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 9c404dc8eada..cdf13f6d2697 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -235,7 +235,7 @@ static void mei_cl_bus_event_work(struct work_struct *work) /* Prepare for the next read */ if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) { mutex_lock(&bus->device_lock); - mei_cl_read_start(cldev->cl, 0, NULL); + mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL); mutex_unlock(&bus->device_lock); } } @@ -325,7 +325,7 @@ int mei_cldev_register_event_cb(struct mei_cl_device *cldev, if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) { mutex_lock(&bus->device_lock); - ret = mei_cl_read_start(cldev->cl, 0, NULL); + ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL); mutex_unlock(&bus->device_lock); if (ret && ret != -EBUSY) return ret; diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 89425a8795a8..c924ba92c834 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -358,8 +358,9 @@ void mei_io_cb_free(struct mei_cl_cb *cb) * * Return: mei_cl_cb pointer or NULL; */ -struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type, - const struct file *fp) +static struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, + enum mei_cb_file_ops type, + const struct file *fp) { struct mei_cl_cb *cb; @@ -430,12 +431,12 @@ static inline void mei_io_list_free(struct mei_cl_cb *list, struct mei_cl *cl) * Return: cb on success and NULL on failure */ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, - enum mei_cb_file_ops type, + enum mei_cb_file_ops fop_type, const struct file *fp) { struct mei_cl_cb *cb; - cb = mei_io_cb_init(cl, type, fp); + cb = mei_io_cb_init(cl, fop_type, fp); if (!cb) return NULL; @@ -452,6 +453,36 @@ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, return cb; } +/** + * mei_cl_enqueue_ctrl_wr_cb - a convenient wrapper for allocating + * and enqueuing of the control commands cb + * + * @cl: host client + * @length: size of the buffer + * @type: operation type + * @fp: associated file pointer (might be NULL) + * + * Return: cb on success and NULL on failure + * Locking: called under "dev->device_lock" lock + */ +struct mei_cl_cb *mei_cl_enqueue_ctrl_wr_cb(struct mei_cl *cl, size_t length, + enum mei_cb_file_ops fop_type, + const struct file *fp) +{ + struct mei_cl_cb *cb; + + /* for RX always allocate at least client's mtu */ + if (length) + length = max_t(size_t, length, mei_cl_mtu(cl)); + + cb = mei_cl_alloc_cb(cl, length, fop_type, fp); + if (!cb) + return NULL; + + list_add_tail(&cb->list, &cl->dev->ctrl_wr_list.list); + return cb; +} + /** * mei_cl_read_cb - find this cl's callback in the read list * for a specific file @@ -848,13 +879,11 @@ static int __mei_cl_disconnect(struct mei_cl *cl) cl->state = MEI_FILE_DISCONNECTING; - cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT, NULL); - rets = cb ? 0 : -ENOMEM; - if (rets) + cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_DISCONNECT, NULL); + if (!cb) { + rets = -ENOMEM; goto out; - - cl_dbg(dev, cl, "add disconnect cb to control write list\n"); - list_add_tail(&cb->list, &dev->ctrl_wr_list.list); + } if (mei_hbuf_acquire(dev)) { rets = mei_cl_send_disconnect(cl, cb); @@ -1023,14 +1052,14 @@ int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb, * * @cl: host client * @me_cl: me client - * @file: pointer to file structure + * @fp: pointer to file structure * * Locking: called under "dev->device_lock" lock * * Return: 0 on success, <0 on failure. */ int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl, - const struct file *file) + const struct file *fp) { struct mei_device *dev; struct mei_cl_cb *cb; @@ -1057,12 +1086,11 @@ int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl, goto nortpm; } - cb = mei_io_cb_init(cl, MEI_FOP_CONNECT, file); - rets = cb ? 0 : -ENOMEM; - if (rets) + cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_CONNECT, fp); + if (!cb) { + rets = -ENOMEM; goto out; - - list_add_tail(&cb->list, &dev->ctrl_wr_list.list); + } /* run hbuf acquire last so we don't have to undo */ if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) { @@ -1265,7 +1293,7 @@ int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb, * mei_cl_notify_request - send notification stop/start request * * @cl: host client - * @file: associate request with file + * @fp: associate request with file * @request: 1 for start or 0 for stop * * Locking: called under "dev->device_lock" lock @@ -1273,7 +1301,7 @@ int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb, * Return: 0 on such and error otherwise. */ int mei_cl_notify_request(struct mei_cl *cl, - const struct file *file, u8 request) + const struct file *fp, u8 request) { struct mei_device *dev; struct mei_cl_cb *cb; @@ -1298,7 +1326,7 @@ int mei_cl_notify_request(struct mei_cl *cl, } fop_type = mei_cl_notify_req2fop(request); - cb = mei_io_cb_init(cl, fop_type, file); + cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, fop_type, fp); if (!cb) { rets = -ENOMEM; goto out; @@ -1309,9 +1337,7 @@ int mei_cl_notify_request(struct mei_cl *cl, rets = -ENODEV; goto out; } - list_add_tail(&cb->list, &dev->ctrl_rd_list.list); - } else { - list_add_tail(&cb->list, &dev->ctrl_wr_list.list); + list_move_tail(&cb->list, &dev->ctrl_rd_list.list); } mutex_unlock(&dev->device_lock); @@ -1443,14 +1469,10 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp) if (cl->rx_flow_ctrl_creds) return -EBUSY; - /* always allocate at least client max message */ - length = max_t(size_t, length, mei_cl_mtu(cl)); - cb = mei_cl_alloc_cb(cl, length, MEI_FOP_READ, fp); + cb = mei_cl_enqueue_ctrl_wr_cb(cl, length, MEI_FOP_READ, fp); if (!cb) return -ENOMEM; - list_add_tail(&cb->list, &dev->ctrl_wr_list.list); - rets = pm_runtime_get(dev->dev); if (rets < 0 && rets != -EINPROGRESS) { pm_runtime_put_noidle(dev->dev); diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 16466aa40cbd..d2bfabecd882 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -82,8 +82,6 @@ static inline u8 mei_me_cl_ver(const struct mei_me_client *me_cl) /* * MEI IO Functions */ -struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type, - const struct file *fp); void mei_io_cb_free(struct mei_cl_cb *priv_cb); /** @@ -116,6 +114,9 @@ void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp); struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, enum mei_cb_file_ops type, const struct file *fp); +struct mei_cl_cb *mei_cl_enqueue_ctrl_wr_cb(struct mei_cl *cl, size_t length, + enum mei_cb_file_ops type, + const struct file *fp); int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp); /* diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index c8e8a8d22019..4b9495f0394c 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -871,10 +871,10 @@ static int mei_hbm_fw_disconnect_req(struct mei_device *dev, cl->state = MEI_FILE_DISCONNECTING; cl->timer_count = 0; - cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT_RSP, NULL); + cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_DISCONNECT_RSP, + NULL); if (!cb) return -ENOMEM; - list_add_tail(&cb->list, &dev->ctrl_wr_list.list); } return 0; } diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index d7ef5edf044a..d698ba32357c 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -628,7 +628,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) if (!list_empty(&cl->rd_completed)) mask |= POLLIN | POLLRDNORM; else - mei_cl_read_start(cl, 0, file); + mei_cl_read_start(cl, mei_cl_mtu(cl), file); } out: -- cgit v1.2.3 From ff1586a7ea57a4758a3f10ad7c9cdb26edcbd7f3 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 26 Jul 2016 01:06:06 +0300 Subject: mei: enqueue consecutive reads The FW supports only one pending read per host client, in order to support issuing of consecutive reads the driver queues read requests internally and send them to the firmware after pending one has completed. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interrupt.c | 3 +++ drivers/misc/mei/main.c | 39 +++++++++++++++++++-------------------- 2 files changed, 22 insertions(+), 20 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 36382d782e20..bf745e03f21e 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -209,6 +209,9 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb, int slots; int ret; + if (!list_empty(&cl->rd_pending)) + return 0; + msg_slots = mei_data2slots(sizeof(struct hbm_flow_control)); slots = mei_hbuf_empty_slots(dev); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index d698ba32357c..650061b6ab9b 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -139,9 +139,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, struct mei_cl *cl = file->private_data; struct mei_device *dev; struct mei_cl_cb *cb = NULL; + bool nonblock = !!(file->f_flags & O_NONBLOCK); int rets; - int err; - if (WARN_ON(!cl || !cl->dev)) return -ENODEV; @@ -177,25 +176,29 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, if (*offset > 0) *offset = 0; - err = mei_cl_read_start(cl, length, file); - if (err && err != -EBUSY) { - cl_dbg(dev, cl, "mei start read failure status = %d\n", err); - rets = err; + rets = mei_cl_read_start(cl, length, file); + if (rets && rets != -EBUSY) { + cl_dbg(dev, cl, "mei start read failure status = %d\n", rets); goto out; } - /* synchronized under device mutex */ - if (!waitqueue_active(&cl->rx_wait)) { - if (file->f_flags & O_NONBLOCK) { - rets = -EAGAIN; - goto out; - } + if (nonblock) { + rets = -EAGAIN; + goto out; + } + + if (rets == -EBUSY && + !mei_cl_enqueue_ctrl_wr_cb(cl, length, MEI_FOP_READ, file)) { + rets = -ENOMEM; + goto out; + } + do { mutex_unlock(&dev->device_lock); if (wait_event_interruptible(cl->rx_wait, - (!list_empty(&cl->rd_completed)) || - (!mei_cl_is_connected(cl)))) { + (!list_empty(&cl->rd_completed)) || + (!mei_cl_is_connected(cl)))) { if (signal_pending(current)) return -EINTR; @@ -207,13 +210,9 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, rets = -ENODEV; goto out; } - } - cb = mei_cl_read_cb(cl, file); - if (!cb) { - rets = 0; - goto out; - } + cb = mei_cl_read_cb(cl, file); + } while (!cb); copy_buffer: /* now copy the data to user space */ -- cgit v1.2.3 From 9d27e73c1897c17e535987a4758fddb7a2fe1fd3 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 26 Jul 2016 01:06:07 +0300 Subject: mei: amthif: drop mei_amthif_read mei_amthif_read have only one difference from mei_read, it is not calling mei_read_start(). Make mei_read_start return immediately for amthif client and drop the special mei_amthif_read function. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 100 --------------------------------------------- drivers/misc/mei/client.c | 2 +- drivers/misc/mei/main.c | 5 --- drivers/misc/mei/mei_dev.h | 3 -- 4 files changed, 1 insertion(+), 109 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index e8029235504d..2222b60e9208 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -84,106 +84,6 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) return ret; } -/** - * mei_amthif_read - read data from AMTHIF client - * - * @dev: the device structure - * @file: pointer to file object - * @ubuf: pointer to user data in user space - * @length: data length to read - * @offset: data read offset - * - * Locking: called under "dev->device_lock" lock - * - * Return: - * returned data length on success, - * zero if no data to read, - * negative on failure. - */ -int mei_amthif_read(struct mei_device *dev, struct file *file, - char __user *ubuf, size_t length, loff_t *offset) -{ - struct mei_cl *cl = file->private_data; - struct mei_cl_cb *cb; - int rets; - int wait_ret; - - dev_dbg(dev->dev, "checking amthif data\n"); - cb = mei_cl_read_cb(cl, file); - - /* Check for if we can block or not*/ - if (cb == NULL && file->f_flags & O_NONBLOCK) - return -EAGAIN; - - - dev_dbg(dev->dev, "waiting for amthif data\n"); - while (cb == NULL) { - /* unlock the Mutex */ - mutex_unlock(&dev->device_lock); - - wait_ret = wait_event_interruptible(cl->rx_wait, - !list_empty(&cl->rd_completed) || - !mei_cl_is_connected(cl)); - - /* Locking again the Mutex */ - mutex_lock(&dev->device_lock); - - if (wait_ret) - return -ERESTARTSYS; - - if (!mei_cl_is_connected(cl)) { - rets = -ENODEV; - goto out; - } - - cb = mei_cl_read_cb(cl, file); - } - - if (cb->status) { - rets = cb->status; - dev_dbg(dev->dev, "read operation failed %d\n", rets); - goto free; - } - - dev_dbg(dev->dev, "Got amthif data\n"); - /* if the whole message will fit remove it from the list */ - if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset)) - list_del_init(&cb->list); - else if (cb->buf_idx <= *offset) { - /* end of the message has been reached */ - list_del_init(&cb->list); - rets = 0; - goto free; - } - /* else means that not full buffer will be read and do not - * remove message from deletion list - */ - - dev_dbg(dev->dev, "amthif cb->buf.size - %zu cb->buf_idx - %zu\n", - cb->buf.size, cb->buf_idx); - - /* length is being truncated to PAGE_SIZE, however, - * the buf_idx may point beyond */ - length = min_t(size_t, length, (cb->buf_idx - *offset)); - - if (copy_to_user(ubuf, cb->buf.data + *offset, length)) { - dev_dbg(dev->dev, "failed to copy data to userland\n"); - rets = -EFAULT; - } else { - rets = length; - if ((*offset + length) < cb->buf_idx) { - *offset += length; - goto out; - } - } -free: - dev_dbg(dev->dev, "free amthif cb memory.\n"); - *offset = 0; - mei_io_cb_free(cb); -out: - return rets; -} - /** * mei_amthif_read_start - queue message for sending read credential * diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index c924ba92c834..45a7652820cf 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1462,7 +1462,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp) return -ENOTTY; } - if (mei_cl_is_fixed_address(cl)) + if (mei_cl_is_fixed_address(cl) || cl == &dev->iamthif_cl) return 0; /* HW currently supports only one pending read */ diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 650061b6ab9b..fa50635512e8 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -164,11 +164,6 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, goto out; } - if (cl == &dev->iamthif_cl) { - rets = mei_amthif_read(dev, file, ubuf, length, offset); - goto out; - } - cb = mei_cl_read_cb(cl, file); if (cb) goto copy_buffer; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 7c8fa8d70e11..2ef1ad6c391a 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -564,9 +564,6 @@ void mei_amthif_reset_params(struct mei_device *dev); int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl); -int mei_amthif_read(struct mei_device *dev, struct file *file, - char __user *ubuf, size_t length, loff_t *offset); - unsigned int mei_amthif_poll(struct file *file, poll_table *wait); int mei_amthif_release(struct mei_device *dev, struct file *file); -- cgit v1.2.3 From 80293c47a6774848c72a2f79816b7de1769c5e85 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 26 Jul 2016 01:06:08 +0300 Subject: mei: drop unused file transaction states Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/mei_dev.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 2ef1ad6c391a..397ae2b45c9e 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -87,9 +87,6 @@ enum mei_file_transaction_states { MEI_IDLE, MEI_WRITING, MEI_WRITE_COMPLETE, - MEI_FLOW_CONTROL, - MEI_READING, - MEI_READ_COMPLETE }; /** -- cgit v1.2.3 From e728ae271f4cf71218ec06a6daf61b79466cb466 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 26 Jul 2016 01:06:09 +0300 Subject: mei: amthif: fix deadlock in initialization during a reset The device lock was unnecessary obtained in bus rescan work before the amthif client search. That causes incorrect lock ordering and task hang: ... [88004.613213] INFO: task kworker/1:14:21832 blocked for more than 120 seconds. ... [88004.645934] Workqueue: events mei_cl_bus_rescan_work ... The correct lock order is cl_bus_lock device_lock me_clients_rwsem Move device_lock into amthif init function that called after me_clients_rwsem is released. This fixes regression introduced by commit: commit 025fb792bac3 ("mei: split amthif client init from end of clients enumeration") Cc: # 4.6+ Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 12 +++++++++--- drivers/misc/mei/bus.c | 2 -- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 2222b60e9208..082462ea90c9 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -66,8 +66,12 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) struct mei_cl *cl = &dev->iamthif_cl; int ret; - if (mei_cl_is_connected(cl)) - return 0; + mutex_lock(&dev->device_lock); + + if (mei_cl_is_connected(cl)) { + ret = 0; + goto out; + } dev->iamthif_state = MEI_IAMTHIF_IDLE; @@ -76,11 +80,13 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) ret = mei_cl_link(cl); if (ret < 0) { dev_err(dev->dev, "amthif: failed cl_link %d\n", ret); - return ret; + goto out; } ret = mei_cl_connect(cl, me_cl, NULL); +out: + mutex_unlock(&dev->device_lock); return ret; } diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index cdf13f6d2697..8cac7ef9ad0d 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -984,12 +984,10 @@ void mei_cl_bus_rescan_work(struct work_struct *work) container_of(work, struct mei_device, bus_rescan_work); struct mei_me_client *me_cl; - mutex_lock(&bus->device_lock); me_cl = mei_me_cl_by_uuid(bus, &mei_amthif_guid); if (me_cl) mei_amthif_host_init(bus, me_cl); mei_me_cl_put(me_cl); - mutex_unlock(&bus->device_lock); mei_cl_bus_rescan(bus); } -- cgit v1.2.3 From 9d32f82e040a823a584446cd9a7066390bf911fa Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 16 Jun 2016 13:38:24 +0200 Subject: mic: remove unused function arg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building with W=1, the __scif_rma_destroy_tcw function causes a harmless warning about an argument variable that is modified but not used: drivers/misc/mic/scif/scif_dma.c: In function ‘__scif_rma_destroy_tcw’: drivers/misc/mic/scif/scif_dma.c:118:27: error: parameter ‘ep’ set but not used [-Werror=unused-but-set-parameter] In this case, we can just remove the argument, since all callers are in the same file. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/scif/scif_dma.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mic/scif/scif_dma.c b/drivers/misc/mic/scif/scif_dma.c index cd01a0efda6b..64d5760d069a 100644 --- a/drivers/misc/mic/scif/scif_dma.c +++ b/drivers/misc/mic/scif/scif_dma.c @@ -115,7 +115,6 @@ int scif_reserve_dma_chan(struct scif_endpt *ep) */ static void __scif_rma_destroy_tcw(struct scif_mmu_notif *mmn, - struct scif_endpt *ep, u64 start, u64 len) { struct list_head *item, *tmp; @@ -128,7 +127,6 @@ void __scif_rma_destroy_tcw(struct scif_mmu_notif *mmn, list_for_each_safe(item, tmp, &mmn->tc_reg_list) { window = list_entry(item, struct scif_window, list); - ep = (struct scif_endpt *)window->ep; if (!len) break; start_va = window->va_for_temp; @@ -146,7 +144,7 @@ static void scif_rma_destroy_tcw(struct scif_mmu_notif *mmn, u64 start, u64 len) struct scif_endpt *ep = mmn->ep; spin_lock(&ep->rma_info.tc_lock); - __scif_rma_destroy_tcw(mmn, ep, start, len); + __scif_rma_destroy_tcw(mmn, start, len); spin_unlock(&ep->rma_info.tc_lock); } @@ -169,7 +167,7 @@ static void __scif_rma_destroy_tcw_ep(struct scif_endpt *ep) spin_lock(&ep->rma_info.tc_lock); list_for_each_safe(item, tmp, &ep->rma_info.mmn_list) { mmn = list_entry(item, struct scif_mmu_notif, list); - __scif_rma_destroy_tcw(mmn, ep, 0, ULONG_MAX); + __scif_rma_destroy_tcw(mmn, 0, ULONG_MAX); } spin_unlock(&ep->rma_info.tc_lock); } -- cgit v1.2.3 From acde785e492d6ce838f50937f7547124e0837a55 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Sat, 21 May 2016 18:41:38 +0530 Subject: misc: mic: scif: use vma_pages(). Replace explicit computation of vma page count by a call to vma_pages() Signed-off-by: Muhammad Falak R Wani Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/scif/scif_mmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mic/scif/scif_mmap.c b/drivers/misc/mic/scif/scif_mmap.c index 49cb8f7b4672..928211677079 100644 --- a/drivers/misc/mic/scif/scif_mmap.c +++ b/drivers/misc/mic/scif/scif_mmap.c @@ -552,7 +552,7 @@ static void scif_munmap(struct vm_area_struct *vma) { struct scif_endpt *ep; struct vma_pvt *vmapvt = vma->vm_private_data; - int nr_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + int nr_pages = vma_pages(vma); s64 offset; struct scif_rma_req req; struct scif_window *window = NULL; @@ -614,7 +614,7 @@ int scif_mmap(struct vm_area_struct *vma, scif_epd_t epd) struct scif_window *window = NULL; struct scif_endpt *ep = (struct scif_endpt *)epd; s64 start_offset = vma->vm_pgoff << PAGE_SHIFT; - int nr_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + int nr_pages = vma_pages(vma); int err; struct vma_pvt *vmapvt; -- cgit v1.2.3 From 655745b0d1ebeceb0453f1c6adca154a4fac0ad5 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Fri, 20 May 2016 17:48:56 +0530 Subject: VMCI: use memdup_user(). Use memdup_user to duplicate a memory region from user-space to kernel-space, instead of open coding using kmalloc & copy_from_user. Signed-off-by: Muhammad Falak R Wani Signed-off-by: Greg Kroah-Hartman --- drivers/misc/vmw_vmci/vmci_host.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c index 9ec262a52656..ec090105eb4b 100644 --- a/drivers/misc/vmw_vmci/vmci_host.c +++ b/drivers/misc/vmw_vmci/vmci_host.c @@ -381,18 +381,12 @@ static int vmci_host_do_send_datagram(struct vmci_host_dev *vmci_host_dev, return -EINVAL; } - dg = kmalloc(send_info.len, GFP_KERNEL); - if (!dg) { + dg = memdup_user((void __user *)(uintptr_t)send_info.addr, + send_info.len); + if (IS_ERR(dg)) { vmci_ioctl_err( "cannot allocate memory to dispatch datagram\n"); - return -ENOMEM; - } - - if (copy_from_user(dg, (void __user *)(uintptr_t)send_info.addr, - send_info.len)) { - vmci_ioctl_err("error getting datagram\n"); - kfree(dg); - return -EFAULT; + return PTR_ERR(dg); } if (VMCI_DG_SIZE(dg) != send_info.len) { -- cgit v1.2.3 From 832c8232dd7be4977ae9fb9c7cbc4decce19a8fc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 24 Aug 2016 16:38:52 +0200 Subject: misc: retire the old BMP085 driver Patches merged to the IIO BMP085 driver makes it fully compliant with all features found in this old misc driver. Retire this old driver in favor of the new one in the proper subsystem. Cc: Jonathan Cameron Cc: Marek Belisko Acked-by: H. Nikolaus Schaller Signed-off-by: Linus Walleij Acked-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-i2c-bmp085 | 31 -- drivers/iio/pressure/Kconfig | 2 - drivers/misc/Kconfig | 28 -- drivers/misc/Makefile | 3 - drivers/misc/bmp085-i2c.c | 83 ----- drivers/misc/bmp085-spi.c | 79 ----- drivers/misc/bmp085.c | 506 ----------------------------- drivers/misc/bmp085.h | 33 -- 8 files changed, 765 deletions(-) delete mode 100644 Documentation/ABI/testing/sysfs-i2c-bmp085 delete mode 100644 drivers/misc/bmp085-i2c.c delete mode 100644 drivers/misc/bmp085-spi.c delete mode 100644 drivers/misc/bmp085.c delete mode 100644 drivers/misc/bmp085.h (limited to 'drivers/misc') diff --git a/Documentation/ABI/testing/sysfs-i2c-bmp085 b/Documentation/ABI/testing/sysfs-i2c-bmp085 deleted file mode 100644 index 585962ad0465..000000000000 --- a/Documentation/ABI/testing/sysfs-i2c-bmp085 +++ /dev/null @@ -1,31 +0,0 @@ -What: /sys/bus/i2c/devices/-/pressure0_input -Date: June 2010 -Contact: Christoph Mair -Description: Start a pressure measurement and read the result. Values - represent the ambient air pressure in pascal (0.01 millibar). - - Reading: returns the current air pressure. - - -What: /sys/bus/i2c/devices/-/temp0_input -Date: June 2010 -Contact: Christoph Mair -Description: Measure the ambient temperature. The returned value represents - the ambient temperature in units of 0.1 degree celsius. - - Reading: returns the current temperature. - - -What: /sys/bus/i2c/devices/-/oversampling -Date: June 2010 -Contact: Christoph Mair -Description: Tell the bmp085 to use more samples to calculate a pressure - value. When writing to this file the chip will use 2^x samples - to calculate the next pressure value with x being the value - written. Using this feature will decrease RMS noise and - increase the measurement time. - - Reading: returns the current oversampling setting. - - Writing: sets a new oversampling setting. - Accepted values: 0..3. diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index d130cdc78f43..7fa65ab664fb 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -8,8 +8,6 @@ menu "Pressure sensors" config BMP280 tristate "Bosch Sensortec BMP180/BMP280 pressure sensor I2C driver" depends on (I2C || SPI_MASTER) - depends on !(BMP085_I2C=y || BMP085_I2C=m) - depends on !(BMP085_SPI=y || BMP085_SPI=m) select REGMAP select BMP280_I2C if (I2C) select BMP280_SPI if (SPI_MASTER) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index a216b4667742..09f6f84a6a7f 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -439,34 +439,6 @@ config ARM_CHARLCD line and the Linux version on the second line, but that's still useful. -config BMP085 - tristate - depends on SYSFS - -config BMP085_I2C - tristate "BMP085 digital pressure sensor on I2C" - select BMP085 - select REGMAP_I2C - depends on I2C && SYSFS - help - Say Y here if you want to support Bosch Sensortec's digital pressure - sensor hooked to an I2C bus. - - To compile this driver as a module, choose M here: the - module will be called bmp085-i2c. - -config BMP085_SPI - tristate "BMP085 digital pressure sensor on SPI" - select BMP085 - select REGMAP_SPI - depends on SPI_MASTER && SYSFS - help - Say Y here if you want to support Bosch Sensortec's digital pressure - sensor hooked to an SPI bus. - - To compile this driver as a module, choose M here: the - module will be called bmp085-spi. - config PCH_PHUB tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB" select GENERIC_NET_UTILS diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 7410c6d9a34d..9d588215a06d 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -9,9 +9,6 @@ obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o obj-$(CONFIG_INTEL_MID_PTI) += pti.o obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o -obj-$(CONFIG_BMP085) += bmp085.o -obj-$(CONFIG_BMP085_I2C) += bmp085-i2c.o -obj-$(CONFIG_BMP085_SPI) += bmp085-spi.o obj-$(CONFIG_DUMMY_IRQ) += dummy-irq.o obj-$(CONFIG_ICS932S401) += ics932s401.o obj-$(CONFIG_LKDTM) += lkdtm.o diff --git a/drivers/misc/bmp085-i2c.c b/drivers/misc/bmp085-i2c.c deleted file mode 100644 index f35c218aaa1a..000000000000 --- a/drivers/misc/bmp085-i2c.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2012 Bosch Sensortec GmbH - * Copyright (c) 2012 Unixphere AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include "bmp085.h" - -#define BMP085_I2C_ADDRESS 0x77 - -static const unsigned short normal_i2c[] = { BMP085_I2C_ADDRESS, - I2C_CLIENT_END }; - -static int bmp085_i2c_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - if (client->addr != BMP085_I2C_ADDRESS) - return -ENODEV; - - return bmp085_detect(&client->dev); -} - -static int bmp085_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int err; - struct regmap *regmap = devm_regmap_init_i2c(client, - &bmp085_regmap_config); - - if (IS_ERR(regmap)) { - err = PTR_ERR(regmap); - dev_err(&client->dev, "Failed to init regmap: %d\n", err); - return err; - } - - return bmp085_probe(&client->dev, regmap, client->irq); -} - -static int bmp085_i2c_remove(struct i2c_client *client) -{ - return bmp085_remove(&client->dev); -} - -static const struct i2c_device_id bmp085_id[] = { - { BMP085_NAME, 0 }, - { "bmp180", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, bmp085_id); - -static struct i2c_driver bmp085_i2c_driver = { - .driver = { - .name = BMP085_NAME, - }, - .id_table = bmp085_id, - .probe = bmp085_i2c_probe, - .remove = bmp085_i2c_remove, - - .detect = bmp085_i2c_detect, - .address_list = normal_i2c -}; - -module_i2c_driver(bmp085_i2c_driver); - -MODULE_AUTHOR("Eric Andersson "); -MODULE_DESCRIPTION("BMP085 I2C bus driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/misc/bmp085-spi.c b/drivers/misc/bmp085-spi.c deleted file mode 100644 index 17ecbf95ff15..000000000000 --- a/drivers/misc/bmp085-spi.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2012 Bosch Sensortec GmbH - * Copyright (c) 2012 Unixphere AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include "bmp085.h" - -static int bmp085_spi_probe(struct spi_device *client) -{ - int err; - struct regmap *regmap; - - client->bits_per_word = 8; - err = spi_setup(client); - if (err < 0) { - dev_err(&client->dev, "spi_setup failed!\n"); - return err; - } - - regmap = devm_regmap_init_spi(client, &bmp085_regmap_config); - if (IS_ERR(regmap)) { - err = PTR_ERR(regmap); - dev_err(&client->dev, "Failed to init regmap: %d\n", err); - return err; - } - - return bmp085_probe(&client->dev, regmap, client->irq); -} - -static int bmp085_spi_remove(struct spi_device *client) -{ - return bmp085_remove(&client->dev); -} - -static const struct of_device_id bmp085_of_match[] = { - { .compatible = "bosch,bmp085", }, - { }, -}; -MODULE_DEVICE_TABLE(of, bmp085_of_match); - -static const struct spi_device_id bmp085_id[] = { - { "bmp180", 0 }, - { "bmp181", 0 }, - { } -}; -MODULE_DEVICE_TABLE(spi, bmp085_id); - -static struct spi_driver bmp085_spi_driver = { - .driver = { - .name = BMP085_NAME, - .of_match_table = bmp085_of_match - }, - .id_table = bmp085_id, - .probe = bmp085_spi_probe, - .remove = bmp085_spi_remove -}; - -module_spi_driver(bmp085_spi_driver); - -MODULE_AUTHOR("Eric Andersson "); -MODULE_DESCRIPTION("BMP085 SPI bus driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c deleted file mode 100644 index 9b313f7810f5..000000000000 --- a/drivers/misc/bmp085.c +++ /dev/null @@ -1,506 +0,0 @@ -/* Copyright (c) 2010 Christoph Mair - * Copyright (c) 2012 Bosch Sensortec GmbH - * Copyright (c) 2012 Unixphere AB - * - * This driver supports the bmp085 and bmp18x digital barometric pressure - * and temperature sensors from Bosch Sensortec. The datasheets - * are available from their website: - * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf - * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP180-DS000-07.pdf - * - * A pressure measurement is issued by reading from pressure0_input. - * The return value ranges from 30000 to 110000 pascal with a resulution - * of 1 pascal (0.01 millibar) which enables measurements from 9000m above - * to 500m below sea level. - * - * The temperature can be read from temp0_input. Values range from - * -400 to 850 representing the ambient temperature in degree celsius - * multiplied by 10.The resolution is 0.1 celsius. - * - * Because ambient pressure is temperature dependent, a temperature - * measurement will be executed automatically even if the user is reading - * from pressure0_input. This happens if the last temperature measurement - * has been executed more then one second ago. - * - * To decrease RMS noise from pressure measurements, the bmp085 can - * autonomously calculate the average of up to eight samples. This is - * set up by writing to the oversampling sysfs file. Accepted values - * are 0, 1, 2 and 3. 2^x when x is the value written to this file - * specifies the number of samples used to calculate the ambient pressure. - * RMS noise is specified with six pascal (without averaging) and decreases - * down to 3 pascal when using an oversampling setting of 3. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include "bmp085.h" -#include -#include -#include - -#define BMP085_CHIP_ID 0x55 -#define BMP085_CALIBRATION_DATA_START 0xAA -#define BMP085_CALIBRATION_DATA_LENGTH 11 /* 16 bit values */ -#define BMP085_CHIP_ID_REG 0xD0 -#define BMP085_CTRL_REG 0xF4 -#define BMP085_TEMP_MEASUREMENT 0x2E -#define BMP085_PRESSURE_MEASUREMENT 0x34 -#define BMP085_CONVERSION_REGISTER_MSB 0xF6 -#define BMP085_CONVERSION_REGISTER_LSB 0xF7 -#define BMP085_CONVERSION_REGISTER_XLSB 0xF8 -#define BMP085_TEMP_CONVERSION_TIME 5 - -struct bmp085_calibration_data { - s16 AC1, AC2, AC3; - u16 AC4, AC5, AC6; - s16 B1, B2; - s16 MB, MC, MD; -}; - -struct bmp085_data { - struct device *dev; - struct regmap *regmap; - struct mutex lock; - struct bmp085_calibration_data calibration; - u8 oversampling_setting; - u32 raw_temperature; - u32 raw_pressure; - u32 temp_measurement_period; - unsigned long last_temp_measurement; - u8 chip_id; - s32 b6; /* calculated temperature correction coefficient */ - int irq; - struct completion done; -}; - -static irqreturn_t bmp085_eoc_isr(int irq, void *devid) -{ - struct bmp085_data *data = devid; - - complete(&data->done); - - return IRQ_HANDLED; -} - -static s32 bmp085_read_calibration_data(struct bmp085_data *data) -{ - u16 tmp[BMP085_CALIBRATION_DATA_LENGTH]; - struct bmp085_calibration_data *cali = &(data->calibration); - s32 status = regmap_bulk_read(data->regmap, - BMP085_CALIBRATION_DATA_START, (u8 *)tmp, - (BMP085_CALIBRATION_DATA_LENGTH << 1)); - if (status < 0) - return status; - - cali->AC1 = be16_to_cpu(tmp[0]); - cali->AC2 = be16_to_cpu(tmp[1]); - cali->AC3 = be16_to_cpu(tmp[2]); - cali->AC4 = be16_to_cpu(tmp[3]); - cali->AC5 = be16_to_cpu(tmp[4]); - cali->AC6 = be16_to_cpu(tmp[5]); - cali->B1 = be16_to_cpu(tmp[6]); - cali->B2 = be16_to_cpu(tmp[7]); - cali->MB = be16_to_cpu(tmp[8]); - cali->MC = be16_to_cpu(tmp[9]); - cali->MD = be16_to_cpu(tmp[10]); - return 0; -} - -static s32 bmp085_update_raw_temperature(struct bmp085_data *data) -{ - u16 tmp; - s32 status; - - mutex_lock(&data->lock); - - init_completion(&data->done); - - status = regmap_write(data->regmap, BMP085_CTRL_REG, - BMP085_TEMP_MEASUREMENT); - if (status < 0) { - dev_err(data->dev, - "Error while requesting temperature measurement.\n"); - goto exit; - } - wait_for_completion_timeout(&data->done, 1 + msecs_to_jiffies( - BMP085_TEMP_CONVERSION_TIME)); - - status = regmap_bulk_read(data->regmap, BMP085_CONVERSION_REGISTER_MSB, - &tmp, sizeof(tmp)); - if (status < 0) { - dev_err(data->dev, - "Error while reading temperature measurement result\n"); - goto exit; - } - data->raw_temperature = be16_to_cpu(tmp); - data->last_temp_measurement = jiffies; - status = 0; /* everything ok, return 0 */ - -exit: - mutex_unlock(&data->lock); - return status; -} - -static s32 bmp085_update_raw_pressure(struct bmp085_data *data) -{ - u32 tmp = 0; - s32 status; - - mutex_lock(&data->lock); - - init_completion(&data->done); - - status = regmap_write(data->regmap, BMP085_CTRL_REG, - BMP085_PRESSURE_MEASUREMENT + - (data->oversampling_setting << 6)); - if (status < 0) { - dev_err(data->dev, - "Error while requesting pressure measurement.\n"); - goto exit; - } - - /* wait for the end of conversion */ - wait_for_completion_timeout(&data->done, 1 + msecs_to_jiffies( - 2+(3 << data->oversampling_setting))); - /* copy data into a u32 (4 bytes), but skip the first byte. */ - status = regmap_bulk_read(data->regmap, BMP085_CONVERSION_REGISTER_MSB, - ((u8 *)&tmp)+1, 3); - if (status < 0) { - dev_err(data->dev, - "Error while reading pressure measurement results\n"); - goto exit; - } - data->raw_pressure = be32_to_cpu((tmp)); - data->raw_pressure >>= (8-data->oversampling_setting); - status = 0; /* everything ok, return 0 */ - -exit: - mutex_unlock(&data->lock); - return status; -} - -/* - * This function starts the temperature measurement and returns the value - * in tenth of a degree celsius. - */ -static s32 bmp085_get_temperature(struct bmp085_data *data, int *temperature) -{ - struct bmp085_calibration_data *cali = &data->calibration; - long x1, x2; - int status; - - status = bmp085_update_raw_temperature(data); - if (status < 0) - goto exit; - - x1 = ((data->raw_temperature - cali->AC6) * cali->AC5) >> 15; - x2 = (cali->MC << 11) / (x1 + cali->MD); - data->b6 = x1 + x2 - 4000; - /* if NULL just update b6. Used for pressure only measurements */ - if (temperature != NULL) - *temperature = (x1+x2+8) >> 4; - -exit: - return status; -} - -/* - * This function starts the pressure measurement and returns the value - * in millibar. Since the pressure depends on the ambient temperature, - * a temperature measurement is executed according to the given temperature - * measurement period (default is 1 sec boundary). This period could vary - * and needs to be adjusted according to the sensor environment, i.e. if big - * temperature variations then the temperature needs to be read out often. - */ -static s32 bmp085_get_pressure(struct bmp085_data *data, int *pressure) -{ - struct bmp085_calibration_data *cali = &data->calibration; - s32 x1, x2, x3, b3; - u32 b4, b7; - s32 p; - int status; - - /* alt least every second force an update of the ambient temperature */ - if ((data->last_temp_measurement == 0) || - time_is_before_jiffies(data->last_temp_measurement + 1*HZ)) { - status = bmp085_get_temperature(data, NULL); - if (status < 0) - return status; - } - - status = bmp085_update_raw_pressure(data); - if (status < 0) - return status; - - x1 = (data->b6 * data->b6) >> 12; - x1 *= cali->B2; - x1 >>= 11; - - x2 = cali->AC2 * data->b6; - x2 >>= 11; - - x3 = x1 + x2; - - b3 = (((((s32)cali->AC1) * 4 + x3) << data->oversampling_setting) + 2); - b3 >>= 2; - - x1 = (cali->AC3 * data->b6) >> 13; - x2 = (cali->B1 * ((data->b6 * data->b6) >> 12)) >> 16; - x3 = (x1 + x2 + 2) >> 2; - b4 = (cali->AC4 * (u32)(x3 + 32768)) >> 15; - - b7 = ((u32)data->raw_pressure - b3) * - (50000 >> data->oversampling_setting); - p = ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2)); - - x1 = p >> 8; - x1 *= x1; - x1 = (x1 * 3038) >> 16; - x2 = (-7357 * p) >> 16; - p += (x1 + x2 + 3791) >> 4; - - *pressure = p; - - return 0; -} - -/* - * This function sets the chip-internal oversampling. Valid values are 0..3. - * The chip will use 2^oversampling samples for internal averaging. - * This influences the measurement time and the accuracy; larger values - * increase both. The datasheet gives an overview on how measurement time, - * accuracy and noise correlate. - */ -static void bmp085_set_oversampling(struct bmp085_data *data, - unsigned char oversampling) -{ - if (oversampling > 3) - oversampling = 3; - data->oversampling_setting = oversampling; -} - -/* - * Returns the currently selected oversampling. Range: 0..3 - */ -static unsigned char bmp085_get_oversampling(struct bmp085_data *data) -{ - return data->oversampling_setting; -} - -/* sysfs callbacks */ -static ssize_t set_oversampling(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bmp085_data *data = dev_get_drvdata(dev); - unsigned long oversampling; - int err = kstrtoul(buf, 10, &oversampling); - - if (err == 0) { - mutex_lock(&data->lock); - bmp085_set_oversampling(data, oversampling); - mutex_unlock(&data->lock); - return count; - } - - return err; -} - -static ssize_t show_oversampling(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct bmp085_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", bmp085_get_oversampling(data)); -} -static DEVICE_ATTR(oversampling, S_IWUSR | S_IRUGO, - show_oversampling, set_oversampling); - - -static ssize_t show_temperature(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int temperature; - int status; - struct bmp085_data *data = dev_get_drvdata(dev); - - status = bmp085_get_temperature(data, &temperature); - if (status < 0) - return status; - else - return sprintf(buf, "%d\n", temperature); -} -static DEVICE_ATTR(temp0_input, S_IRUGO, show_temperature, NULL); - - -static ssize_t show_pressure(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int pressure; - int status; - struct bmp085_data *data = dev_get_drvdata(dev); - - status = bmp085_get_pressure(data, &pressure); - if (status < 0) - return status; - else - return sprintf(buf, "%d\n", pressure); -} -static DEVICE_ATTR(pressure0_input, S_IRUGO, show_pressure, NULL); - - -static struct attribute *bmp085_attributes[] = { - &dev_attr_temp0_input.attr, - &dev_attr_pressure0_input.attr, - &dev_attr_oversampling.attr, - NULL -}; - -static const struct attribute_group bmp085_attr_group = { - .attrs = bmp085_attributes, -}; - -int bmp085_detect(struct device *dev) -{ - struct bmp085_data *data = dev_get_drvdata(dev); - unsigned int id; - int ret; - - ret = regmap_read(data->regmap, BMP085_CHIP_ID_REG, &id); - if (ret < 0) - return ret; - - if (id != data->chip_id) - return -ENODEV; - - return 0; -} -EXPORT_SYMBOL_GPL(bmp085_detect); - -static void bmp085_get_of_properties(struct bmp085_data *data) -{ -#ifdef CONFIG_OF - struct device_node *np = data->dev->of_node; - u32 prop; - - if (!np) - return; - - if (!of_property_read_u32(np, "chip-id", &prop)) - data->chip_id = prop & 0xff; - - if (!of_property_read_u32(np, "temp-measurement-period", &prop)) - data->temp_measurement_period = (prop/100)*HZ; - - if (!of_property_read_u32(np, "default-oversampling", &prop)) - data->oversampling_setting = prop & 0xff; -#endif -} - -static int bmp085_init_client(struct bmp085_data *data) -{ - int status = bmp085_read_calibration_data(data); - - if (status < 0) - return status; - - /* default settings */ - data->chip_id = BMP085_CHIP_ID; - data->last_temp_measurement = 0; - data->temp_measurement_period = 1*HZ; - data->oversampling_setting = 3; - - bmp085_get_of_properties(data); - - mutex_init(&data->lock); - - return 0; -} - -struct regmap_config bmp085_regmap_config = { - .reg_bits = 8, - .val_bits = 8 -}; -EXPORT_SYMBOL_GPL(bmp085_regmap_config); - -int bmp085_probe(struct device *dev, struct regmap *regmap, int irq) -{ - struct bmp085_data *data; - int err = 0; - - data = kzalloc(sizeof(struct bmp085_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - dev_set_drvdata(dev, data); - data->dev = dev; - data->regmap = regmap; - data->irq = irq; - - if (data->irq > 0) { - err = devm_request_irq(dev, data->irq, bmp085_eoc_isr, - IRQF_TRIGGER_RISING, "bmp085", - data); - if (err < 0) - goto exit_free; - } - - /* Initialize the BMP085 chip */ - err = bmp085_init_client(data); - if (err < 0) - goto exit_free; - - err = bmp085_detect(dev); - if (err < 0) { - dev_err(dev, "%s: chip_id failed!\n", BMP085_NAME); - goto exit_free; - } - - /* Register sysfs hooks */ - err = sysfs_create_group(&dev->kobj, &bmp085_attr_group); - if (err) - goto exit_free; - - dev_info(dev, "Successfully initialized %s!\n", BMP085_NAME); - - return 0; - -exit_free: - kfree(data); -exit: - return err; -} -EXPORT_SYMBOL_GPL(bmp085_probe); - -int bmp085_remove(struct device *dev) -{ - struct bmp085_data *data = dev_get_drvdata(dev); - - sysfs_remove_group(&data->dev->kobj, &bmp085_attr_group); - kfree(data); - - return 0; -} -EXPORT_SYMBOL_GPL(bmp085_remove); - -MODULE_AUTHOR("Christoph Mair "); -MODULE_DESCRIPTION("BMP085 driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/misc/bmp085.h b/drivers/misc/bmp085.h deleted file mode 100644 index 8b8e3b1f5ca5..000000000000 --- a/drivers/misc/bmp085.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2012 Bosch Sensortec GmbH - * Copyright (c) 2012 Unixphere AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _BMP085_H -#define _BMP085_H - -#include - -#define BMP085_NAME "bmp085" - -extern struct regmap_config bmp085_regmap_config; - -int bmp085_probe(struct device *dev, struct regmap *regmap, int irq); -int bmp085_remove(struct device *dev); -int bmp085_detect(struct device *dev); - -#endif -- cgit v1.2.3 From 5ed22cebbacc3d434fe4df5e7178cb2b79042d41 Mon Sep 17 00:00:00 2001 From: Frank Haverkamp Date: Wed, 29 Jun 2016 15:47:43 +0200 Subject: GenWQE: Change default access rights for device node Since it should always be ok for normal users to operate the accelerator, it makes sense to change it in our driver, rather than adding udev rules for all Linux distributions. Signed-off-by: Frank Haverkamp Reviewed-by: Gabriel Krisman Bertazi Signed-off-by: Greg Kroah-Hartman --- drivers/misc/genwqe/card_base.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/genwqe/card_base.c b/drivers/misc/genwqe/card_base.c index a70b853fa2c9..6c1f49a85023 100644 --- a/drivers/misc/genwqe/card_base.c +++ b/drivers/misc/genwqe/card_base.c @@ -1350,6 +1350,19 @@ static struct pci_driver genwqe_driver = { .err_handler = &genwqe_err_handler, }; +/** + * genwqe_devnode() - Set default access mode for genwqe devices. + * + * Default mode should be rw for everybody. Do not change default + * device name. + */ +static char *genwqe_devnode(struct device *dev, umode_t *mode) +{ + if (mode) + *mode = 0666; + return NULL; +} + /** * genwqe_init_module() - Driver registration and initialization */ @@ -1363,6 +1376,8 @@ static int __init genwqe_init_module(void) return -ENOMEM; } + class_genwqe->devnode = genwqe_devnode; + debugfs_genwqe = debugfs_create_dir(GENWQE_DEVNAME, NULL); if (!debugfs_genwqe) { rc = -ENOMEM; -- cgit v1.2.3 From 549ce8f134bd95a1d4bf1a62215a62f1e9408a96 Mon Sep 17 00:00:00 2001 From: Zubair Lutfullah Kakakhel Date: Fri, 12 Aug 2016 12:48:52 +0100 Subject: misc: pch_phub: Read prefetch value from device tree if passed The default prefetch value for the eg20t device is hard coded to 0x000affaa. Add support for an alternative to be read from DT if available Signed-off-by: Zubair Lutfullah Kakakhel Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pch_phub.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index 4810e039bbec..1dd18f500730 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c @@ -28,6 +28,7 @@ #include #include #include +#include #define PHUB_STATUS 0x00 /* Status Register offset */ #define PHUB_CONTROL 0x04 /* Control Register offset */ @@ -711,6 +712,12 @@ static int pch_phub_probe(struct pci_dev *pdev, if (id->driver_data == 1) { /* EG20T PCH */ const char *board_name; + unsigned int prefetch = 0x000affaa; + + if (pdev->dev.of_node) + of_property_read_u32(pdev->dev.of_node, + "intel,eg20t-prefetch", + &prefetch); ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); @@ -736,7 +743,7 @@ static int pch_phub_probe(struct pci_dev *pdev, CLKCFG_UART_MASK); /* set the prefech value */ - iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14); + iowrite32(prefetch, chip->pch_phub_base_address + 0x14); /* set the interrupt delay value */ iowrite32(0x25, chip->pch_phub_base_address + 0x44); chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T; -- cgit v1.2.3 From bed3d7babafda16cf2e095366dec3f64143b370a Mon Sep 17 00:00:00 2001 From: Zubair Lutfullah Kakakhel Date: Fri, 12 Aug 2016 12:48:53 +0100 Subject: misc: pch_phub: Add UART_CLK quirk for Boston platform The EG20T has 4 UART blocks. The clock source for the UART block is configured to receive a clock from an external pin by default. An internal 25MHz clock in the EG20T can also be used as a clock source for the clock. The MIPS based Boston platform ties the external clock pin down and relies on the internal clock source for the UART to function. Boston is based on device tree. Add a quirk to allow Boston to be detected via device tree and set the correct clock source for UART. Signed-off-by: Zubair Lutfullah Kakakhel Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pch_phub.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index 1dd18f500730..e42bdc90fa27 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c @@ -58,6 +58,7 @@ /* CM-iTC */ #define CLKCFG_UART_48MHZ (1 << 16) +#define CLKCFG_UART_25MHZ (2 << 16) #define CLKCFG_BAUDDIV (2 << 20) #define CLKCFG_PLL2VCO (8 << 9) #define CLKCFG_UARTCLKSEL (1 << 18) @@ -748,6 +749,16 @@ static int pch_phub_probe(struct pci_dev *pdev, iowrite32(0x25, chip->pch_phub_base_address + 0x44); chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T; chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T; + + /* quirk for MIPS Boston platform */ + if (pdev->dev.of_node) { + if (of_machine_is_compatible("img,boston")) { + pch_phub_read_modify_write_reg(chip, + (unsigned int)CLKCFG_REG_OFFSET, + CLKCFG_UART_25MHZ, + CLKCFG_UART_MASK); + } + } } else if (id->driver_data == 2) { /* ML7213 IOH */ ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); if (ret) -- cgit v1.2.3 From ac182e8abc6f93c1c4cc12f042af64c9d7be0d1e Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Mon, 12 Sep 2016 16:21:43 +0300 Subject: mei: me: add kaby point device ids Add device ids for Intel Kabypoint PCH (Kabylake) Cc: #4.6+ Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me-regs.h | 3 +++ drivers/misc/mei/pci-me.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index 0dcb854b4bfc..7ad15d678878 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -125,6 +125,9 @@ #define MEI_DEV_ID_BXT_M 0x1A9A /* Broxton M */ #define MEI_DEV_ID_APL_I 0x5A9A /* Apollo Lake I */ +#define MEI_DEV_ID_KBP 0xA2BA /* Kaby Point */ +#define MEI_DEV_ID_KBP_2 0xA2BB /* Kaby Point 2 */ + /* * MEI HW Section */ diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 031e7c92fcc7..e85bb371c87d 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -91,6 +91,9 @@ static const struct pci_device_id mei_me_pci_tbl[] = { {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, mei_me_pch8_cfg)}, {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, mei_me_pch8_cfg)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, mei_me_pch8_cfg)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, mei_me_pch8_cfg)}, + /* required last entry */ {0, } }; -- cgit v1.2.3 From 1892fc2ee4c08d7ac17adb93f1341d9c3d7bdaf6 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 25 Sep 2016 13:25:31 +0300 Subject: mei: stop the stall timer worker if not needed The stall timer worker checks periodically if there is a stalled i/o transaction. The issue with the current implementation is that the timer is ticking also when there is no pending i/o transaction. This patch provides a simple change that prevents rescheduling of the delayed work when there is no pending i/o. Cc: Andy Lutomirski Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 1 + drivers/misc/mei/client.c | 2 ++ drivers/misc/mei/hbm.c | 3 +++ drivers/misc/mei/init.c | 2 +- drivers/misc/mei/interrupt.c | 25 +++++++++++++++++++++---- drivers/misc/mei/mei_dev.h | 1 + drivers/misc/mei/pci-me.c | 2 -- 7 files changed, 29 insertions(+), 7 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 082462ea90c9..7ae89b4a21d5 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -277,6 +277,7 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) case MEI_FOP_WRITE: if (!cb->status) { dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER; + mei_schedule_stall_timer(dev); mei_io_cb_free(cb); return; } diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 45a7652820cf..6fe02350578d 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -826,6 +826,7 @@ static int mei_cl_send_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb) list_move_tail(&cb->list, &dev->ctrl_rd_list.list); cl->timer_count = MEI_CONNECT_TIMEOUT; + mei_schedule_stall_timer(dev); return 0; } @@ -1011,6 +1012,7 @@ static int mei_cl_send_connect(struct mei_cl *cl, struct mei_cl_cb *cb) list_move_tail(&cb->list, &dev->ctrl_rd_list.list); cl->timer_count = MEI_CONNECT_TIMEOUT; + mei_schedule_stall_timer(dev); return 0; } diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 4b9495f0394c..dd7f15a65eed 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -277,6 +277,7 @@ int mei_hbm_start_req(struct mei_device *dev) dev->hbm_state = MEI_HBM_STARTING; dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; + mei_schedule_stall_timer(dev); return 0; } @@ -312,6 +313,7 @@ static int mei_hbm_enum_clients_req(struct mei_device *dev) } dev->hbm_state = MEI_HBM_ENUM_CLIENTS; dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; + mei_schedule_stall_timer(dev); return 0; } @@ -562,6 +564,7 @@ static int mei_hbm_prop_req(struct mei_device *dev, unsigned long start_idx) } dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; + mei_schedule_stall_timer(dev); return 0; } diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index f7c8dfdb6a12..9a9c2484d107 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -94,7 +94,7 @@ void mei_cancel_work(struct mei_device *dev) cancel_work_sync(&dev->reset_work); cancel_work_sync(&dev->bus_rescan_work); - cancel_delayed_work(&dev->timer_work); + cancel_delayed_work_sync(&dev->timer_work); } EXPORT_SYMBOL_GPL(mei_cancel_work); diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index bf745e03f21e..5a4893ce9c24 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -459,6 +459,19 @@ static void mei_connect_timeout(struct mei_cl *cl) mei_reset(dev); } +#define MEI_STALL_TIMER_FREQ (2 * HZ) +/** + * mei_schedule_stall_timer - re-arm stall_timer work + * + * Schedule stall timer + * + * @dev: the device structure + */ +void mei_schedule_stall_timer(struct mei_device *dev) +{ + schedule_delayed_work(&dev->timer_work, MEI_STALL_TIMER_FREQ); +} + /** * mei_timer - timer function. * @@ -468,10 +481,9 @@ static void mei_connect_timeout(struct mei_cl *cl) void mei_timer(struct work_struct *work) { struct mei_cl *cl; - struct mei_device *dev = container_of(work, struct mei_device, timer_work.work); - + bool reschedule_timer = false; mutex_lock(&dev->device_lock); @@ -486,6 +498,7 @@ void mei_timer(struct work_struct *work) mei_reset(dev); goto out; } + reschedule_timer = true; } } @@ -500,6 +513,7 @@ void mei_timer(struct work_struct *work) mei_connect_timeout(cl); goto out; } + reschedule_timer = true; } } @@ -512,11 +526,14 @@ void mei_timer(struct work_struct *work) mei_reset(dev); mei_amthif_run_next_cmd(dev); + goto out; } + reschedule_timer = true; } out: - if (dev->dev_state != MEI_DEV_DISABLED) - schedule_delayed_work(&dev->timer_work, 2 * HZ); + if (dev->dev_state != MEI_DEV_DISABLED && reschedule_timer) + mei_schedule_stall_timer(dev); + mutex_unlock(&dev->device_lock); } diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 397ae2b45c9e..1169fd9e7d02 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -548,6 +548,7 @@ void mei_cancel_work(struct mei_device *dev); */ void mei_timer(struct work_struct *work); +void mei_schedule_stall_timer(struct mei_device *dev); int mei_irq_read_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list, s32 *slots); diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index e85bb371c87d..f3ffd883b232 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -220,8 +220,6 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, dev); - schedule_delayed_work(&dev->timer_work, HZ); - /* * For not wake-able HW runtime pm framework * can't be used on pci device level. -- cgit v1.2.3 From 13decfb4383b13b0f75e88709f4fad9138bd243b Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 12 Sep 2016 20:09:40 +0200 Subject: misc/genwqe: ensure zero initialization Genwqe uses dma_alloc_coherent and depends on zero initialized memory. On one occasion it ueses an explicit memset on others it uses un-initialized memory. This bug was covered because some archs actually return zero initialized memory when using dma_alloc_coherent but this is by no means guaranteed. Simply switch to dma_zalloc_coherent. Signed-off-by: Sebastian Ott Signed-off-by: Frank Haverkamp Signed-off-by: Greg Kroah-Hartman --- drivers/misc/genwqe/card_ddcb.c | 2 -- drivers/misc/genwqe/card_utils.c | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/genwqe/card_ddcb.c b/drivers/misc/genwqe/card_ddcb.c index 353ee0cc733d..ddfeefe39540 100644 --- a/drivers/misc/genwqe/card_ddcb.c +++ b/drivers/misc/genwqe/card_ddcb.c @@ -1048,8 +1048,6 @@ static int setup_ddcb_queue(struct genwqe_dev *cd, struct ddcb_queue *queue) "[%s] **err: could not allocate DDCB **\n", __func__); return -ENOMEM; } - memset(queue->ddcb_vaddr, 0, queue_size); - queue->ddcb_req = kzalloc(sizeof(struct ddcb_requ *) * queue->ddcb_max, GFP_KERNEL); if (!queue->ddcb_req) { diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c index 222367cc8c81..8a679ecc8fd1 100644 --- a/drivers/misc/genwqe/card_utils.c +++ b/drivers/misc/genwqe/card_utils.c @@ -220,8 +220,8 @@ void *__genwqe_alloc_consistent(struct genwqe_dev *cd, size_t size, if (get_order(size) > MAX_ORDER) return NULL; - return dma_alloc_coherent(&cd->pci_dev->dev, size, dma_handle, - GFP_KERNEL); + return dma_zalloc_coherent(&cd->pci_dev->dev, size, dma_handle, + GFP_KERNEL); } void __genwqe_free_consistent(struct genwqe_dev *cd, size_t size, -- cgit v1.2.3 From 3936e4c8db2095af5e6c704a3e4b2b500f568ae5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 11 Sep 2016 14:58:26 +0300 Subject: at25: fix debug and error messaging The patch does the following: - fixes specifiers and removes explicit casting of the parameters - joins literals to one line - increases readability of the parameters Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/at25.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index 2c6c7c8e3ead..5afe4cd16569 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -121,9 +121,8 @@ static int at25_ee_read(void *priv, unsigned int offset, * this chip is clocked very slowly */ status = spi_sync(at25->spi, &m); - dev_dbg(&at25->spi->dev, - "read %Zd bytes at %d --> %d\n", - count, offset, (int) status); + dev_dbg(&at25->spi->dev, "read %zu bytes at %d --> %zd\n", + count, offset, status); mutex_unlock(&at25->lock); return status; @@ -167,8 +166,7 @@ static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count) *cp = AT25_WREN; status = spi_write(at25->spi, cp, 1); if (status < 0) { - dev_dbg(&at25->spi->dev, "WREN --> %d\n", - (int) status); + dev_dbg(&at25->spi->dev, "WREN --> %d\n", status); break; } @@ -196,9 +194,8 @@ static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count) memcpy(cp, buf, segment); status = spi_write(at25->spi, bounce, segment + at25->addrlen + 1); - dev_dbg(&at25->spi->dev, - "write %u bytes at %u --> %d\n", - segment, offset, (int) status); + dev_dbg(&at25->spi->dev, "write %u bytes at %u --> %d\n", + segment, offset, status); if (status < 0) break; @@ -225,8 +222,7 @@ static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count) if ((sr < 0) || (sr & AT25_SR_nRDY)) { dev_err(&at25->spi->dev, - "write %d bytes offset %d, " - "timeout after %u msecs\n", + "write %u bytes offset %u, timeout after %u msecs\n", segment, offset, jiffies_to_msecs(jiffies - (timeout - EE_TIMEOUT))); @@ -368,9 +364,7 @@ static int at25_probe(struct spi_device *spi) return PTR_ERR(at25->nvmem); dev_info(&spi->dev, "%d %s %s eeprom%s, pagesize %u\n", - (chip.byte_len < 1024) - ? chip.byte_len - : (chip.byte_len / 1024), + (chip.byte_len < 1024) ? chip.byte_len : (chip.byte_len / 1024), (chip.byte_len < 1024) ? "Byte" : "KByte", at25->chip.name, (chip.flags & EE_READONLY) ? " (readonly)" : "", -- cgit v1.2.3 From c9fef1cc3dd3677633e6fd6ea5bd7ef3b741fab3 Mon Sep 17 00:00:00 2001 From: "Rusk, Mark" Date: Mon, 19 Sep 2016 19:50:01 +0000 Subject: drivers/misc/hpilo: Changes to support new security states in iLO5 FW Changes to support new security states of the iLO5 firmware. - use BAR5 for CCB's for iLO5 - simplification of error handling Signed-off-by: Mark Rusk Signed-off-by: David Altobelli Signed-off-by: Greg Kroah-Hartman --- drivers/misc/hpilo.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index d6a901cd4222..fea8ff40440f 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c @@ -688,7 +688,8 @@ static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw) static int ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw) { - int error = -ENOMEM; + int bar; + unsigned long off; /* map the memory mapped i/o registers */ hw->mmio_vaddr = pci_iomap(pdev, 1, 0); @@ -698,7 +699,15 @@ static int ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw) } /* map the adapter shared memory region */ - hw->ram_vaddr = pci_iomap(pdev, 2, max_ccb * ILOHW_CCB_SZ); + if (pdev->subsystem_device == 0x00E4) { + bar = 5; + /* Last 8k is reserved for CCBs */ + off = pci_resource_len(pdev, bar) - 0x2000; + } else { + bar = 2; + off = 0; + } + hw->ram_vaddr = pci_iomap_range(pdev, bar, off, max_ccb * ILOHW_CCB_SZ); if (hw->ram_vaddr == NULL) { dev_err(&pdev->dev, "Error mapping shared mem\n"); goto mmio_free; @@ -717,7 +726,7 @@ ram_free: mmio_free: pci_iounmap(pdev, hw->mmio_vaddr); out: - return error; + return -ENOMEM; } static void ilo_remove(struct pci_dev *pdev) @@ -899,7 +908,7 @@ static void __exit ilo_exit(void) class_destroy(ilo_class); } -MODULE_VERSION("1.4.1"); +MODULE_VERSION("1.5.0"); MODULE_ALIAS(ILO_NAME); MODULE_DESCRIPTION(ILO_NAME); MODULE_AUTHOR("David Altobelli "); -- cgit v1.2.3