summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRafael J. Wysocki2015-07-29 23:49:22 +0200
committerRafael J. Wysocki2015-07-29 23:49:22 +0200
commit5af310a8ee70dd6a588c8ee1d4487a230a7b7b65 (patch)
tree38ba23a3b51ab577ea1ddc09772a8556d8957df9 /lib
parentACPI / PM: Update the copyright notice and description of power.c (diff)
parentmfd: Add support for Intel Sunrisepoint LPSS devices (diff)
downloadkernel-qcow2-linux-5af310a8ee70dd6a588c8ee1d4487a230a7b7b65.tar.gz
kernel-qcow2-linux-5af310a8ee70dd6a588c8ee1d4487a230a7b7b65.tar.xz
kernel-qcow2-linux-5af310a8ee70dd6a588c8ee1d4487a230a7b7b65.zip
Merge tag 'ib-mfd-base-acpi-dma-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd into acpi-pm
Pull MFD-related material including ACPI device power management changes (in addition to MFD, driver core and DMA changes) for v4.3 from Lee Jones. * tag 'ib-mfd-base-acpi-dma-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: mfd: Add support for Intel Sunrisepoint LPSS devices dmaengine: add a driver for Intel integrated DMA 64-bit mfd: make mfd_remove_devices() iterate in reverse order driver core: implement device_for_each_child_reverse() klist: implement klist_prev() Driver core: wakeup the parent device before trying probe ACPI / PM: Attach ACPI power domain only once PM / QoS: Make it possible to expose device latency tolerance to userspace
Diffstat (limited to 'lib')
-rw-r--r--lib/klist.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/lib/klist.c b/lib/klist.c
index 89b485a2a58d..d74cf7a29afd 100644
--- a/lib/klist.c
+++ b/lib/klist.c
@@ -324,6 +324,47 @@ static struct klist_node *to_klist_node(struct list_head *n)
}
/**
+ * klist_prev - Ante up prev node in list.
+ * @i: Iterator structure.
+ *
+ * First grab list lock. Decrement the reference count of the previous
+ * node, if there was one. Grab the prev node, increment its reference
+ * count, drop the lock, and return that prev node.
+ */
+struct klist_node *klist_prev(struct klist_iter *i)
+{
+ void (*put)(struct klist_node *) = i->i_klist->put;
+ struct klist_node *last = i->i_cur;
+ struct klist_node *prev;
+
+ spin_lock(&i->i_klist->k_lock);
+
+ if (last) {
+ prev = to_klist_node(last->n_node.prev);
+ if (!klist_dec_and_del(last))
+ put = NULL;
+ } else
+ prev = to_klist_node(i->i_klist->k_list.prev);
+
+ i->i_cur = NULL;
+ while (prev != to_klist_node(&i->i_klist->k_list)) {
+ if (likely(!knode_dead(prev))) {
+ kref_get(&prev->n_ref);
+ i->i_cur = prev;
+ break;
+ }
+ prev = to_klist_node(prev->n_node.prev);
+ }
+
+ spin_unlock(&i->i_klist->k_lock);
+
+ if (put && last)
+ put(last);
+ return i->i_cur;
+}
+EXPORT_SYMBOL_GPL(klist_prev);
+
+/**
* klist_next - Ante up next node in list.
* @i: Iterator structure.
*