Commit f317ff9e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull workqueue changes from Tejun Heo:
 "Surprisingly, Lai and I didn't break too many things implementing
  custom pools and stuff last time around and there aren't any follow-up
  changes necessary at this point.

  The only change in this pull request is Viresh's patches to make some
  per-cpu workqueues to behave as unbound workqueues dependent on a boot
  param whose default can be configured via a config option.  This leads
  to higher processing overhead / lower bandwidth as more work items are
  bounced across CPUs; however, it can lead to noticeable powersave in
  certain configurations - ~10% w/ idlish constant workload on a
  big.LITTLE configuration according to Viresh.

  This is because per-cpu workqueues interfere with how the scheduler
  perceives whether or not each CPU is idle by forcing pinned tasks on
  them, which makes the scheduler's power-aware scheduling decisions
  less effective.

  Its effectiveness is likely less pronounced on homogenous
  configurations and this type of optimization can probably be made
  automatic; however, the changes are pretty minimal and the affected
  workqueues are clearly marked, so it's an easy gain for some
  configurations for the time being with pretty unintrusive changes."

* 'for-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq:
  fbcon: queue work on power efficient wq
  block: queue work on power efficient wq
  PHYLIB: queue work on system_power_efficient_wq
  workqueue: Add system wide power_efficient workqueues
  workqueues: Introduce new flag WQ_POWER_EFFICIENT for power oriented workqueues
parents 13cc5601 a85f1a41
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -3341,6 +3341,21 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
			that this also can be controlled per-workqueue for
			workqueues visible under /sys/bus/workqueue/.

	workqueue.power_efficient
			Per-cpu workqueues are generally preferred because
			they show better performance thanks to cache
			locality; unfortunately, per-cpu workqueues tend to
			be more power hungry than unbound workqueues.

			Enabling this makes the per-cpu workqueues which
			were observed to contribute significantly to power
			consumption unbound, leading to measurably lower
			power usage at the cost of small performance
			overhead.

			The default value of this parameter is determined by
			the config option CONFIG_WQ_POWER_EFFICIENT_DEFAULT.

	x2apic_phys	[X86-64,APIC] Use x2apic physical mode instead of
			default x2apic cluster mode on platforms
			supporting x2apic.
+2 −1
Original line number Diff line number Diff line
@@ -3180,7 +3180,8 @@ int __init blk_dev_init(void)

	/* used for unplugging and affects IO latency/throughput - HIGHPRI */
	kblockd_workqueue = alloc_workqueue("kblockd",
					    WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
					    WQ_MEM_RECLAIM | WQ_HIGHPRI |
					    WQ_POWER_EFFICIENT, 0);
	if (!kblockd_workqueue)
		panic("Failed to create kblockd\n");

+2 −1
Original line number Diff line number Diff line
@@ -144,7 +144,8 @@ void put_io_context(struct io_context *ioc)
	if (atomic_long_dec_and_test(&ioc->refcount)) {
		spin_lock_irqsave(&ioc->lock, flags);
		if (!hlist_empty(&ioc->icq_list))
			schedule_work(&ioc->release_work);
			queue_work(system_power_efficient_wq,
					&ioc->release_work);
		else
			free_ioc = true;
		spin_unlock_irqrestore(&ioc->lock, flags);
+8 −4
Original line number Diff line number Diff line
@@ -1489,9 +1489,11 @@ static void __disk_unblock_events(struct gendisk *disk, bool check_now)
	intv = disk_events_poll_jiffies(disk);
	set_timer_slack(&ev->dwork.timer, intv / 4);
	if (check_now)
		queue_delayed_work(system_freezable_wq, &ev->dwork, 0);
		queue_delayed_work(system_freezable_power_efficient_wq,
				&ev->dwork, 0);
	else if (intv)
		queue_delayed_work(system_freezable_wq, &ev->dwork, intv);
		queue_delayed_work(system_freezable_power_efficient_wq,
				&ev->dwork, intv);
out_unlock:
	spin_unlock_irqrestore(&ev->lock, flags);
}
@@ -1534,7 +1536,8 @@ void disk_flush_events(struct gendisk *disk, unsigned int mask)
	spin_lock_irq(&ev->lock);
	ev->clearing |= mask;
	if (!ev->block)
		mod_delayed_work(system_freezable_wq, &ev->dwork, 0);
		mod_delayed_work(system_freezable_power_efficient_wq,
				&ev->dwork, 0);
	spin_unlock_irq(&ev->lock);
}

@@ -1627,7 +1630,8 @@ static void disk_check_events(struct disk_events *ev,

	intv = disk_events_poll_jiffies(disk);
	if (!ev->block && intv)
		queue_delayed_work(system_freezable_wq, &ev->dwork, intv);
		queue_delayed_work(system_freezable_power_efficient_wq,
				&ev->dwork, intv);

	spin_unlock_irq(&ev->lock);

+5 −4
Original line number Diff line number Diff line
@@ -439,7 +439,7 @@ void phy_start_machine(struct phy_device *phydev,
{
	phydev->adjust_state = handler;

	schedule_delayed_work(&phydev->state_queue, HZ);
	queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, HZ);
}

/**
@@ -500,7 +500,7 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
	disable_irq_nosync(irq);
	atomic_inc(&phydev->irq_disable);

	schedule_work(&phydev->phy_queue);
	queue_work(system_power_efficient_wq, &phydev->phy_queue);

	return IRQ_HANDLED;
}
@@ -655,7 +655,7 @@ static void phy_change(struct work_struct *work)

	/* reschedule state queue work to run as soon as possible */
	cancel_delayed_work_sync(&phydev->state_queue);
	schedule_delayed_work(&phydev->state_queue, 0);
	queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, 0);

	return;

@@ -918,7 +918,8 @@ void phy_state_machine(struct work_struct *work)
	if (err < 0)
		phy_error(phydev);

	schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ);
	queue_delayed_work(system_power_efficient_wq, &phydev->state_queue,
			PHY_STATE_TIME * HZ);
}

static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
Loading