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 diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 082462e..7ae89b4 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 45a7652..6fe0235 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 4b9495f..dd7f15a 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 f7c8dfd..9a9c248 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 bf745e0..5a4893c 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 397ae2b..1169fd9 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 e85bb37..f3ffd88 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 v0.10.2