Commit 41f63c53 authored by Tejun Heo's avatar Tejun Heo
Browse files

workqueue: use mod_delayed_work() instead of cancel + queue



Convert delayed_work users doing cancel_delayed_work() followed by
queue_delayed_work() to mod_delayed_work().

Most conversions are straight-forward.  Ones worth mentioning are,

* drivers/edac/edac_mc.c: edac_mc_workq_setup() converted to always
  use mod_delayed_work() and cancel loop in
  edac_mc_reset_delay_period() is dropped.

* drivers/platform/x86/thinkpad_acpi.c: No need to remember whether
  watchdog is active or not.  @fan_watchdog_active and related code
  dropped.

* drivers/power/charger-manager.c: Seemingly a lot of
  delayed_work_pending() abuse going on here.
  [delayed_]work_pending() are unsynchronized and racy when used like
  this.  I converted one instance in fullbatt_handler().  Please
  conver the rest so that it invokes workqueue APIs for the intended
  target state rather than trying to game work item pending state
  transitions.  e.g. if timer should be modified - call
  mod_delayed_work(), canceled - call cancel_delayed_work[_sync]().

* drivers/thermal/thermal_sys.c: thermal_zone_device_set_polling()
  simplified.  Note that round_jiffies() calls in this function are
  meaningless.  round_jiffies() work on absolute jiffies not delta
  delay used by delayed_work.

v2: Tomi pointed out that __cancel_delayed_work() users can't be
    safely converted to mod_delayed_work().  They could be calling it
    from irq context and if that happens while delayed_work_timer_fn()
    is running, it could deadlock.  __cancel_delayed_work() users are
    dropped.

Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
Acked-by: default avatarAnton Vorontsov <cbouatmailru@gmail.com>
Acked-by: default avatarDavid Howells <dhowells@redhat.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Doug Thompson <dougthompson@xmission.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Roland Dreier <roland@kernel.org>
Cc: "John W. Linville" <linville@tuxdriver.com>
Cc: Zhang Rui <rui.zhang@intel.com>
Cc: Len Brown <len.brown@intel.com>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
Cc: Johannes Berg <johannes@sipsolutions.net>
parent 8376fe22
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -1534,10 +1534,8 @@ void disk_flush_events(struct gendisk *disk, unsigned int mask)

	spin_lock_irq(&ev->lock);
	ev->clearing |= mask;
	if (!ev->block) {
		cancel_delayed_work(&ev->dwork);
		queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
	}
	if (!ev->block)
		mod_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
	spin_unlock_irq(&ev->lock);
}

+1 −16
Original line number Diff line number Diff line
@@ -538,7 +538,7 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec)
		return;

	INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
	queue_delayed_work(edac_workqueue, &mci->work, msecs_to_jiffies(msec));
	mod_delayed_work(edac_workqueue, &mci->work, msecs_to_jiffies(msec));
}

/*
@@ -578,21 +578,6 @@ void edac_mc_reset_delay_period(int value)

	mutex_lock(&mem_ctls_mutex);

	/* scan the list and turn off all workq timers, doing so under lock
	 */
	list_for_each(item, &mc_devices) {
		mci = list_entry(item, struct mem_ctl_info, link);

		if (mci->op_state == OP_RUNNING_POLL)
			cancel_delayed_work(&mci->work);
	}

	mutex_unlock(&mem_ctls_mutex);


	/* re-walk the list, and reset the poll delay */
	mutex_lock(&mem_ctls_mutex);

	list_for_each(item, &mc_devices) {
		mci = list_entry(item, struct mem_ctl_info, link);

+1 −3
Original line number Diff line number Diff line
@@ -152,13 +152,11 @@ static void set_timeout(unsigned long time)
{
	unsigned long delay;

	cancel_delayed_work(&work);

	delay = time - jiffies;
	if ((long)delay <= 0)
		delay = 1;

	queue_delayed_work(addr_wq, &work, delay);
	mod_delayed_work(addr_wq, &work, delay);
}

static void queue_req(struct addr_req *req)
+2 −4
Original line number Diff line number Diff line
@@ -2679,10 +2679,8 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
			}
		}
		if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_SFP_D) {
			if (nesdev->link_recheck)
				cancel_delayed_work(&nesdev->work);
			nesdev->link_recheck = 1;
			schedule_delayed_work(&nesdev->work,
			mod_delayed_work(system_wq, &nesdev->work,
					 NES_LINK_RECHECK_DELAY);
		}
	}
+2 −3
Original line number Diff line number Diff line
@@ -243,10 +243,9 @@ static int nes_netdev_open(struct net_device *netdev)

	spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);
	if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_SFP_D) {
		if (nesdev->link_recheck)
			cancel_delayed_work(&nesdev->work);
		nesdev->link_recheck = 1;
		schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY);
		mod_delayed_work(system_wq, &nesdev->work,
				 NES_LINK_RECHECK_DELAY);
	}
	spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);

Loading