aboutsummaryrefslogtreecommitdiffstats
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2008-03-13 13:54:38 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2008-03-13 13:54:38 -0700
commit9abc65f8c4c95fd809f8d9e8c911d2e077c449bf (patch)
tree92a9798dc7f63e0098740574f953426b1e1e3731
parent1e68a850ab158ff9d4886402ab3d76f21c4ac27a (diff)
downloadpatches-9abc65f8c4c95fd809f8d9e8c911d2e077c449bf.tar.gz
more patch fun
-rw-r--r--driver-core/driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch75
-rw-r--r--driver-core/driver-core-replace-remaining-__function__-occurrences.patch12
-rw-r--r--driver-core/ib-rename-dev-to-srp_dev-in-srp_host-structure.patch2
-rw-r--r--driver-core/pm-handle-device-registrations-during-suspend-resume.patch253
-rw-r--r--driver-core/pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch156
-rw-r--r--driver-core/sysdev-detect-multiple-driver-registrations.patch22
-rw-r--r--driver-core/uio-implement-a-uio-interface-for-the-smx-cryptengine.patch227
-rw-r--r--pci/pci-arm-use-generic-pci_enable_resources.patch1
-rw-r--r--pci/pci-doc-pci-create-documentation-pci-and-move-files-into-it.patch3141
-rw-r--r--series8
-rw-r--r--usb/drivers-usb-core-devio.c-suppress-warning-with-64k-page_size.patch43
-rw-r--r--usb/usb-add-usb-serial-spcp8x5-driver.patch13
-rw-r--r--usb/usb-enable-usb-persist-by-default.patch2
-rw-r--r--usb/usb-new-quirk-flag-to-avoid-set-interface.patch59
-rw-r--r--usb/usb-remove-config_usb_persist-setting.patch2
-rw-r--r--usb/usb-remove-dev-power.power_state.patch2
-rw-r--r--usb/usb-replace-remaining-__function__-occurrences.patch4
17 files changed, 3997 insertions, 25 deletions
diff --git a/driver-core/driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch b/driver-core/driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch
new file mode 100644
index 00000000000000..683a99f79ff106
--- /dev/null
+++ b/driver-core/driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch
@@ -0,0 +1,75 @@
+From rjw@sisk.pl Thu Mar 13 13:45:38 2008
+From: "Rafael J. Wysocki" <rjw@sisk.pl>
+Date: Wed, 12 Mar 2008 00:59:38 +0100
+Subject: Driver core: Call device_pm_add() after bus_add_device() in device_add()
+To: Greg KH <greg@kroah.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>, Andrew Morton <akpm@linux-foundation.org>, David Brownell <david-b@pacbell.net>, LKML <linux-kernel@vger.kernel.org>, Pavel Machek <pavel@ucw.cz>, pm list <linux-pm@lists.linux-foundation.org>
+Message-ID: <200803120059.39902.rjw@sisk.pl>
+Content-Disposition: inline
+
+
+From: Rafael J. Wysocki <rjw@sisk.pl>
+
+Include dpm_sysfs_add() into device_pm_add(), in analogy with
+device_pm_remove(), and modify device_add() to call the latter after
+bus_add_device(), to avoid situations in which the PM core may
+attempt to suspend a device the registration of which has not been
+successful.
+
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+Acked-by: Pavel Machek <pavel@ucw.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/base/core.c | 15 +++++----------
+ drivers/base/power/main.c | 4 +++-
+ 2 files changed, 8 insertions(+), 11 deletions(-)
+
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -817,17 +817,12 @@ int device_add(struct device *dev)
+ error = device_add_attrs(dev);
+ if (error)
+ goto AttrsError;
+- error = dpm_sysfs_add(dev);
+- if (error)
+- goto PMError;
+- error = device_pm_add(dev);
+- if (error) {
+- dpm_sysfs_remove(dev);
+- goto PMError;
+- }
+ error = bus_add_device(dev);
+ if (error)
+ goto BusError;
++ error = device_pm_add(dev);
++ if (error)
++ goto PMError;
+ kobject_uevent(&dev->kobj, KOBJ_ADD);
+ bus_attach_device(dev);
+ if (parent)
+@@ -847,9 +842,9 @@ int device_add(struct device *dev)
+ Done:
+ put_device(dev);
+ return error;
+- BusError:
+- device_pm_remove(dev);
+ PMError:
++ bus_remove_device(dev);
++ BusError:
+ if (dev->bus)
+ blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+ BUS_NOTIFY_DEL_DEVICE, dev);
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -81,7 +81,9 @@ int device_pm_add(struct device *dev)
+ WARN_ON(true);
+ error = -EBUSY;
+ } else {
+- list_add_tail(&dev->power.entry, &dpm_active);
++ error = dpm_sysfs_add(dev);
++ if (!error)
++ list_add_tail(&dev->power.entry, &dpm_active);
+ }
+ mutex_unlock(&dpm_list_mtx);
+ return error;
diff --git a/driver-core/driver-core-replace-remaining-__function__-occurrences.patch b/driver-core/driver-core-replace-remaining-__function__-occurrences.patch
index 7377a431bd29b1..47c94fe68c98da 100644
--- a/driver-core/driver-core-replace-remaining-__function__-occurrences.patch
+++ b/driver-core/driver-core-replace-remaining-__function__-occurrences.patch
@@ -130,7 +130,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
parent = get_device(dev->parent);
setup_parent(dev, parent);
-@@ -981,7 +981,7 @@ void device_del(struct device *dev)
+@@ -980,7 +980,7 @@ void device_del(struct device *dev)
*/
void device_unregister(struct device *dev)
{
@@ -139,7 +139,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
device_del(dev);
put_device(dev);
}
-@@ -1076,7 +1076,7 @@ EXPORT_SYMBOL_GPL(device_remove_file);
+@@ -1075,7 +1075,7 @@ EXPORT_SYMBOL_GPL(device_remove_file);
static void device_create_release(struct device *dev)
{
@@ -148,7 +148,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
kfree(dev);
}
-@@ -1210,7 +1210,7 @@ int device_rename(struct device *dev, ch
+@@ -1209,7 +1209,7 @@ int device_rename(struct device *dev, ch
return -EINVAL;
pr_debug("device: '%s': %s: renaming to '%s'\n", dev->bus_id,
@@ -157,7 +157,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
#ifdef CONFIG_SYSFS_DEPRECATED
if ((dev->class) && (dev->parent))
-@@ -1249,7 +1249,7 @@ int device_rename(struct device *dev, ch
+@@ -1248,7 +1248,7 @@ int device_rename(struct device *dev, ch
dev->bus_id);
if (error) {
dev_err(dev, "%s: sysfs_create_symlink failed (%d)\n",
@@ -166,7 +166,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
}
#endif
-@@ -1325,7 +1325,7 @@ int device_move(struct device *dev, stru
+@@ -1324,7 +1324,7 @@ int device_move(struct device *dev, stru
new_parent_kobj = get_device_parent(dev, new_parent);
pr_debug("device: '%s': %s: moving to '%s'\n", dev->bus_id,
@@ -336,7 +336,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
-@@ -183,7 +183,7 @@ int sysdev_driver_register(struct sysdev
+@@ -195,7 +195,7 @@ int sysdev_driver_register(struct sysdev
}
} else {
err = -EINVAL;
diff --git a/driver-core/ib-rename-dev-to-srp_dev-in-srp_host-structure.patch b/driver-core/ib-rename-dev-to-srp_dev-in-srp_host-structure.patch
index cd0cac0b7e50a3..87be800e815ed3 100644
--- a/driver-core/ib-rename-dev-to-srp_dev-in-srp_host-structure.patch
+++ b/driver-core/ib-rename-dev-to-srp_dev-in-srp_host-structure.patch
@@ -12,7 +12,7 @@ by Greg.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
-Cc: Roland Dreier <rolandd@cisco.com>
+Reviewed-by: Roland Dreier <rolandd@cisco.com>
Cc: Sean Hefty <sean.hefty@intel.com>
Cc: Hal Rosenstock <hal.rosenstock@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/driver-core/pm-handle-device-registrations-during-suspend-resume.patch b/driver-core/pm-handle-device-registrations-during-suspend-resume.patch
new file mode 100644
index 00000000000000..c0eb9685a1d61b
--- /dev/null
+++ b/driver-core/pm-handle-device-registrations-during-suspend-resume.patch
@@ -0,0 +1,253 @@
+From rjw@sisk.pl Thu Mar 13 13:44:50 2008
+From: "Rafael J. Wysocki" <rjw@sisk.pl>
+Date: Wed, 12 Mar 2008 00:57:22 +0100
+Subject: PM: Handle device registrations during suspend/resume
+To: Greg KH <greg@kroah.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>, Andrew Morton <akpm@linux-foundation.org>, David Brownell <david-b@pacbell.net>, LKML <linux-kernel@vger.kernel.org>, Pavel Machek <pavel@ucw.cz>, pm list <linux-pm@lists.linux-foundation.org>
+Message-ID: <200803120057.23101.rjw@sisk.pl>
+Content-Disposition: inline
+
+
+From: Rafael J. Wysocki <rjw@sisk.pl>
+
+Modify the PM core to protect its data structures, specifically the
+dpm_active list, from being corrupted if a child of the currently
+suspending device is registered concurrently with its ->suspend()
+callback. In that case, since the new device (the child) is added
+to dpm_active after its parent, the PM core will attempt to
+suspend it after the parent, which is wrong.
+
+Introduce a new member of struct dev_pm_info, called 'sleeping',
+and use it to check if the parent of the device being added to
+dpm_active has been suspended, in which case the device registration
+fails. Also, use 'sleeping' for checking if the ordering of devices
+on dpm_active is correct.
+
+Introduce variable 'all_sleeping' that will be set to 'true' once all
+devices have been suspended and make new device registrations fail
+until 'all_sleeping' is reset to 'false', in order to avoid having
+unsuspended devices around while the system is going into a sleep state.
+
+Remove pm_sleep_rwsem which is not necessary any more.
+
+Special thanks to Alan Stern for discussions and suggestions that
+lead to the creation of this patch.
+
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+Acked-by: Pavel Machek <pavel@ucw.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/power/devices.txt | 5 +++
+ drivers/base/core.c | 6 +++-
+ drivers/base/power/main.c | 57 ++++++++++++++++++----------------------
+ drivers/base/power/power.h | 23 ++--------------
+ include/linux/pm.h | 1
+ 5 files changed, 40 insertions(+), 52 deletions(-)
+
+--- a/Documentation/power/devices.txt
++++ b/Documentation/power/devices.txt
+@@ -196,6 +196,11 @@ its parent; and can't be removed or susp
+
+ The policy is that the device tree should match hardware bus topology.
+ (Or at least the control bus, for devices which use multiple busses.)
++In particular, this means that a device registration may fail if the parent of
++the device is suspending (ie. has been chosen by the PM core as the next
++device to suspend) or has already suspended, as well as after all of the other
++devices have been suspended. Device drivers must be prepared to cope with such
++situations.
+
+
+ Suspending Devices
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -820,7 +820,11 @@ int device_add(struct device *dev)
+ error = dpm_sysfs_add(dev);
+ if (error)
+ goto PMError;
+- device_pm_add(dev);
++ error = device_pm_add(dev);
++ if (error) {
++ dpm_sysfs_remove(dev);
++ goto PMError;
++ }
+ error = bus_add_device(dev);
+ if (error)
+ goto BusError;
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -54,7 +54,8 @@ static LIST_HEAD(dpm_destroy);
+
+ static DEFINE_MUTEX(dpm_list_mtx);
+
+-static DECLARE_RWSEM(pm_sleep_rwsem);
++/* 'true' if all devices have been suspended, protected by dpm_list_mtx */
++static bool all_sleeping;
+
+ int (*platform_enable_wakeup)(struct device *dev, int is_on);
+
+@@ -62,14 +63,28 @@ int (*platform_enable_wakeup)(struct dev
+ * device_pm_add - add a device to the list of active devices
+ * @dev: Device to be added to the list
+ */
+-void device_pm_add(struct device *dev)
++int device_pm_add(struct device *dev)
+ {
++ int error = 0;
++
+ pr_debug("PM: Adding info for %s:%s\n",
+ dev->bus ? dev->bus->name : "No Bus",
+ kobject_name(&dev->kobj));
+ mutex_lock(&dpm_list_mtx);
+- list_add_tail(&dev->power.entry, &dpm_active);
++ if ((dev->parent && dev->parent->power.sleeping) || all_sleeping) {
++ if (dev->parent->power.sleeping)
++ dev_warn(dev,
++ "parent %s is sleeping, will not add\n",
++ dev->parent->bus_id);
++ else
++ dev_warn(dev, "devices are sleeping, will not add\n");
++ WARN_ON(true);
++ error = -EBUSY;
++ } else {
++ list_add_tail(&dev->power.entry, &dpm_active);
++ }
+ mutex_unlock(&dpm_list_mtx);
++ return error;
+ }
+
+ /**
+@@ -107,32 +122,6 @@ void device_pm_schedule_removal(struct d
+ }
+ EXPORT_SYMBOL_GPL(device_pm_schedule_removal);
+
+-/**
+- * pm_sleep_lock - mutual exclusion for registration and suspend
+- *
+- * Returns 0 if no suspend is underway and device registration
+- * may proceed, otherwise -EBUSY.
+- */
+-int pm_sleep_lock(void)
+-{
+- if (down_read_trylock(&pm_sleep_rwsem))
+- return 0;
+-
+- return -EBUSY;
+-}
+-
+-/**
+- * pm_sleep_unlock - mutual exclusion for registration and suspend
+- *
+- * This routine undoes the effect of device_pm_add_lock
+- * when a device's registration is complete.
+- */
+-void pm_sleep_unlock(void)
+-{
+- up_read(&pm_sleep_rwsem);
+-}
+-
+-
+ /*------------------------- Resume routines -------------------------*/
+
+ /**
+@@ -242,11 +231,13 @@ static int resume_device(struct device *
+ static void dpm_resume(void)
+ {
+ mutex_lock(&dpm_list_mtx);
++ all_sleeping = false;
+ while(!list_empty(&dpm_off)) {
+ struct list_head *entry = dpm_off.next;
+ struct device *dev = to_device(entry);
+
+ list_move_tail(entry, &dpm_active);
++ dev->power.sleeping = false;
+ mutex_unlock(&dpm_list_mtx);
+ resume_device(dev);
+ mutex_lock(&dpm_list_mtx);
+@@ -285,7 +276,6 @@ void device_resume(void)
+ might_sleep();
+ dpm_resume();
+ unregister_dropped_devices();
+- up_write(&pm_sleep_rwsem);
+ }
+ EXPORT_SYMBOL_GPL(device_resume);
+
+@@ -421,6 +411,9 @@ static int dpm_suspend(pm_message_t stat
+ struct list_head *entry = dpm_active.prev;
+ struct device *dev = to_device(entry);
+
++ WARN_ON(dev->parent && dev->parent->power.sleeping);
++
++ dev->power.sleeping = true;
+ mutex_unlock(&dpm_list_mtx);
+ error = suspend_device(dev, state);
+ mutex_lock(&dpm_list_mtx);
+@@ -432,11 +425,14 @@ static int dpm_suspend(pm_message_t stat
+ (error == -EAGAIN ?
+ " (please convert to suspend_late)" :
+ ""));
++ dev->power.sleeping = false;
+ break;
+ }
+ if (!list_empty(&dev->power.entry))
+ list_move(&dev->power.entry, &dpm_off);
+ }
++ if (!error)
++ all_sleeping = true;
+ mutex_unlock(&dpm_list_mtx);
+
+ return error;
+@@ -454,7 +450,6 @@ int device_suspend(pm_message_t state)
+ int error;
+
+ might_sleep();
+- down_write(&pm_sleep_rwsem);
+ error = dpm_suspend(state);
+ if (error)
+ device_resume();
+--- a/drivers/base/power/power.h
++++ b/drivers/base/power/power.h
+@@ -11,30 +11,13 @@ static inline struct device *to_device(s
+ return container_of(entry, struct device, power.entry);
+ }
+
+-extern void device_pm_add(struct device *);
++extern int device_pm_add(struct device *);
+ extern void device_pm_remove(struct device *);
+-extern int pm_sleep_lock(void);
+-extern void pm_sleep_unlock(void);
+
+ #else /* CONFIG_PM_SLEEP */
+
+-
+-static inline void device_pm_add(struct device *dev)
+-{
+-}
+-
+-static inline void device_pm_remove(struct device *dev)
+-{
+-}
+-
+-static inline int pm_sleep_lock(void)
+-{
+- return 0;
+-}
+-
+-static inline void pm_sleep_unlock(void)
+-{
+-}
++static inline int device_pm_add(struct device *dev) { return 0; }
++static inline void device_pm_remove(struct device *dev) {}
+
+ #endif
+
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -183,6 +183,7 @@ typedef struct pm_message {
+ struct dev_pm_info {
+ pm_message_t power_state;
+ unsigned can_wakeup:1;
++ bool sleeping:1; /* Owned by the PM core */
+ #ifdef CONFIG_PM_SLEEP
+ unsigned should_wakeup:1;
+ struct list_head entry;
diff --git a/driver-core/pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch b/driver-core/pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch
new file mode 100644
index 00000000000000..fb1621b0727261
--- /dev/null
+++ b/driver-core/pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch
@@ -0,0 +1,156 @@
+From rjw@sisk.pl Thu Mar 13 13:46:04 2008
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Wed, 12 Mar 2008 01:01:47 +0100
+Subject: PM: make wakeup flags available whenever CONFIG_PM is set
+To: Greg KH <greg@kroah.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>, Andrew Morton <akpm@linux-foundation.org>, David Brownell <david-b@pacbell.net>, LKML <linux-kernel@vger.kernel.org>, Pavel Machek <pavel@ucw.cz>, pm list <linux-pm@lists.linux-foundation.org>
+Message-ID: <200803120101.48805.rjw@sisk.pl>
+Content-Disposition: inline
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+The various wakeup flags and their accessor macros in struct
+dev_pm_info should be available whenever CONFIG_PM is enabled, not
+just when CONFIG_PM_SLEEP is on. Otherwise remote wakeup won't always
+be configurable for runtime power management. This patch (as1056)
+fixes the oversight.
+
+[rjw: rebased the patch on top of the previous two.]
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+CC: David Brownell <david-b@pacbell.net>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+Acked-by: Pavel Machek <pavel@ucw.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/base/power/main.c | 2 -
+ drivers/base/power/sysfs.c | 2 +
+ include/linux/pm.h | 64 +++++++++++++++++++++++++--------------------
+ 3 files changed, 38 insertions(+), 30 deletions(-)
+
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -57,8 +57,6 @@ static DEFINE_MUTEX(dpm_list_mtx);
+ /* 'true' if all devices have been suspended, protected by dpm_list_mtx */
+ static bool all_sleeping;
+
+-int (*platform_enable_wakeup)(struct device *dev, int is_on);
+-
+ /**
+ * device_pm_add - add a device to the list of active devices
+ * @dev: Device to be added to the list
+--- a/drivers/base/power/sysfs.c
++++ b/drivers/base/power/sysfs.c
+@@ -6,6 +6,8 @@
+ #include <linux/string.h>
+ #include "power.h"
+
++int (*platform_enable_wakeup)(struct device *dev, int is_on);
++
+
+ /*
+ * wakeup - Report/change current wakeup option for device
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -183,9 +183,9 @@ typedef struct pm_message {
+ struct dev_pm_info {
+ pm_message_t power_state;
+ unsigned can_wakeup:1;
++ unsigned should_wakeup:1;
+ bool sleeping:1; /* Owned by the PM core */
+ #ifdef CONFIG_PM_SLEEP
+- unsigned should_wakeup:1;
+ struct list_head entry;
+ #endif
+ };
+@@ -198,11 +198,6 @@ extern void device_resume(void);
+ extern int device_suspend(pm_message_t state);
+ extern int device_prepare_suspend(pm_message_t state);
+
+-#define device_set_wakeup_enable(dev,val) \
+- ((dev)->power.should_wakeup = !!(val))
+-#define device_may_wakeup(dev) \
+- (device_can_wakeup(dev) && (dev)->power.should_wakeup)
+-
+ extern void __suspend_report_result(const char *function, void *fn, int ret);
+
+ #define suspend_report_result(fn, ret) \
+@@ -210,6 +205,35 @@ extern void __suspend_report_result(cons
+ __suspend_report_result(__FUNCTION__, fn, ret); \
+ } while (0)
+
++#else /* !CONFIG_PM_SLEEP */
++
++static inline int device_suspend(pm_message_t state)
++{
++ return 0;
++}
++
++#define suspend_report_result(fn, ret) do {} while (0)
++
++#endif /* !CONFIG_PM_SLEEP */
++
++#ifdef CONFIG_PM
++
++/* changes to device_may_wakeup take effect on the next pm state change.
++ * by default, devices should wakeup if they can.
++ */
++#define device_can_wakeup(dev) \
++ ((dev)->power.can_wakeup)
++#define device_init_wakeup(dev,val) \
++ do { \
++ device_can_wakeup(dev) = !!(val); \
++ device_set_wakeup_enable(dev,val); \
++ } while(0)
++
++#define device_set_wakeup_enable(dev,val) \
++ ((dev)->power.should_wakeup = !!(val))
++#define device_may_wakeup(dev) \
++ (device_can_wakeup(dev) && (dev)->power.should_wakeup)
++
+ /*
+ * Platform hook to activate device wakeup capability, if that's not already
+ * handled by enable_irq_wake() etc.
+@@ -224,35 +248,19 @@ static inline int call_platform_enable_w
+ return 0;
+ }
+
+-#else /* !CONFIG_PM_SLEEP */
+-
+-static inline int device_suspend(pm_message_t state)
+-{
+- return 0;
+-}
+-
+-#define device_set_wakeup_enable(dev,val) do{}while(0)
+-#define device_may_wakeup(dev) (0)
++#else /* !CONFIG_PM */
+
+-#define suspend_report_result(fn, ret) do { } while (0)
++#define device_can_wakeup(dev) 0
++#define device_init_wakeup(dev,val) do {} while (0)
++#define device_set_wakeup_enable(dev,val) do {} while (0)
++#define device_may_wakeup(dev) 0
+
+ static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
+ {
+ return 0;
+ }
+
+-#endif /* !CONFIG_PM_SLEEP */
+-
+-/* changes to device_may_wakeup take effect on the next pm state change.
+- * by default, devices should wakeup if they can.
+- */
+-#define device_can_wakeup(dev) \
+- ((dev)->power.can_wakeup)
+-#define device_init_wakeup(dev,val) \
+- do { \
+- device_can_wakeup(dev) = !!(val); \
+- device_set_wakeup_enable(dev,val); \
+- } while(0)
++#endif /* !CONFIG_PM */
+
+ /*
+ * Global Power Management flags
diff --git a/driver-core/sysdev-detect-multiple-driver-registrations.patch b/driver-core/sysdev-detect-multiple-driver-registrations.patch
index 45d19a57be0f5a..9175c37e30c022 100644
--- a/driver-core/sysdev-detect-multiple-driver-registrations.patch
+++ b/driver-core/sysdev-detect-multiple-driver-registrations.patch
@@ -23,18 +23,30 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
- drivers/base/sys.c | 4 ++++
- 1 file changed, 4 insertions(+)
+ drivers/base/sys.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
-@@ -167,6 +167,10 @@ int sysdev_driver_register(struct sysdev
+@@ -167,6 +167,22 @@ int sysdev_driver_register(struct sysdev
{
int err = 0;
++ if (!cls) {
++ printk(KERN_WARNING "sysdev: invalid class passed to "
++ "sysdev_driver_register!\n");
++ WARN_ON(1);
++ return -EINVAL;
++ }
++
+ /* Check whether this driver has already been added to a class. */
-+ WARN_ON(drv->entry.next != drv->entry.prev);
-+ WARN_ON(drv->entry.next != NULL);
++ if ((drv->entry.next != drv->entry.prev) ||
++ (drv->entry.next != NULL)) {
++ printk(KERN_WARNING "sysdev: class %s: driver (%p) has already"
++ " been registered to a class, something is wrong, but "
++ "will forge on!\n", cls->name, drv);
++ WARN_ON(1);
++ }
+
mutex_lock(&sysdev_drivers_lock);
if (cls && kset_get(&cls->kset)) {
diff --git a/driver-core/uio-implement-a-uio-interface-for-the-smx-cryptengine.patch b/driver-core/uio-implement-a-uio-interface-for-the-smx-cryptengine.patch
new file mode 100644
index 00000000000000..cccd500a6475c4
--- /dev/null
+++ b/driver-core/uio-implement-a-uio-interface-for-the-smx-cryptengine.patch
@@ -0,0 +1,227 @@
+From bn@niasdigital.com Thu Mar 13 13:40:45 2008
+From: Ben Nizette <bn@niasdigital.com>
+Date: Thu, 13 Mar 2008 22:27:30 +1100
+Subject: UIO: Implement a UIO interface for the SMX Cryptengine
+To: Hans-J�rgen Koch <hjk@linutronix.de>
+Cc: Paul Mundt <lethal@linux-sh.org>, gregkh <gregkh@suse.de>, linux-kernel <linux-kernel@vger.kernel.org>
+Message-ID: <1205407650.3735.19.camel@moss.renham>
+
+From: Ben Nizette <bn@niasdigital.com>
+
+This patch implements a UIO interface for the SMX Cryptengine.
+
+The Cryptengine found on the Nias Digital SMX board is best suited
+for a UIO interface. It is not wired in to the cryptographic API
+as the engine handles it's own keys, algorithms, everything. All
+that we know about is that if there's room in the buffer, you can
+write data to it and when there's data ready, you read it out again.
+
+There isn't necessarily even any direct correlation between data
+going in and data coming out again, the engine may consume or
+generate data all on its own.
+
+This driver is for proprietary hardware but we're always told to
+submit the drivers anyway; here you are. :-)
+
+This is version 4 of this patch and addresses all issues raised by
+Hans-Jürgen Koch and Paul Mundt in their reviews. Slightly altered
+is Paul's suggestion to use DRV_NAME and DRV_VERSION as the UIO
+version and name. While at the moment they are the same, there
+is no reason for them to stay that way. Nevertheless we now at
+least provide a MODULE_VERSION macro to keep modinfo happy.
+
+Signed-off-by: Ben Nizette <bn@niasdigital.com>
+Acked-by: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Hans J Koch <hjk@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ MAINTAINERS | 5 +
+ drivers/uio/Kconfig | 13 ++++
+ drivers/uio/Makefile | 1
+ drivers/uio/uio_smx.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 159 insertions(+)
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -3583,6 +3583,11 @@ M: mhoffman@lightlink.com
+ L: lm-sensors@lm-sensors.org
+ S: Maintained
+
++SMX UIO Interface
++P: Ben Nizette
++M: bn@niasdigital.com
++S: Maintained
++
+ SOFTMAC LAYER (IEEE 802.11)
+ P: Daniel Drake
+ M: dsd@gentoo.org
+--- a/drivers/uio/Kconfig
++++ b/drivers/uio/Kconfig
+@@ -26,4 +26,17 @@ config UIO_CIF
+ To compile this driver as a module, choose M here: the module
+ will be called uio_cif.
+
++config UIO_SMX
++ tristate "SMX cryptengine UIO interface"
++ depends on UIO
++ default n
++ help
++ Userspace IO interface to the Cryptography engine found on the
++ Nias Digital SMX boards. These will be available from Q4 2008
++ from http://www.niasdigital.com. The userspace part of this
++ driver will be released under the GPL at the same time as the
++ hardware and will be able to be downloaded from the same site.
++
++ If you compile this as a module, it will be called uio_smx.
++
+ endif
+--- a/drivers/uio/Makefile
++++ b/drivers/uio/Makefile
+@@ -1,2 +1,3 @@
+ obj-$(CONFIG_UIO) += uio.o
+ obj-$(CONFIG_UIO_CIF) += uio_cif.o
++obj-$(CONFIG_UIO_SMX) += uio_smx.o
+--- /dev/null
++++ b/drivers/uio/uio_smx.c
+@@ -0,0 +1,140 @@
++/*
++ * UIO SMX Cryptengine driver.
++ *
++ * (C) 2008 Nias Digital P/L <bn@niasdigital.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/uio_driver.h>
++#include <linux/io.h>
++
++#define DRV_NAME "smx-ce"
++#define DRV_VERSION "0.03"
++
++#define SMX_CSR 0x00000000
++#define SMX_EnD 0x00000001
++#define SMX_RUN 0x00000002
++#define SMX_DRDY 0x00000004
++#define SMX_ERR 0x00000008
++
++static irqreturn_t smx_handler(int irq, struct uio_info *dev_info)
++{
++ void __iomem *csr = dev_info->mem[0].internal_addr + SMX_CSR;
++
++ u32 status = ioread32(csr);
++
++ if (!(status & SMX_DRDY))
++ return IRQ_NONE;
++
++ /* Disable interrupt */
++ iowrite32(status & ~SMX_DRDY, csr);
++ return IRQ_HANDLED;
++}
++
++static int __devinit smx_ce_probe(struct platform_device *dev)
++{
++
++ int ret = -ENODEV;
++ struct uio_info *info;
++ struct resource *regs;
++
++ info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
++ if (!info)
++ return -ENOMEM;
++
++ regs = platform_get_resource(dev, IORESOURCE_MEM, 0);
++ if (!regs) {
++ dev_err(&dev->dev, "No memory resource specified\n");
++ goto out_free;
++ }
++
++ info->mem[0].addr = regs->start;
++ if (!info->mem[0].addr) {
++ dev_err(&dev->dev, "Invalid memory resource\n");
++ goto out_free;
++ }
++
++ info->mem[0].size = regs->end - regs->start + 1;
++ info->mem[0].internal_addr = ioremap(regs->start, info->mem[0].size);
++
++ if (!info->mem[0].internal_addr) {
++ dev_err(&dev->dev, "Can't remap memory address range\n");
++ goto out_free;
++ }
++
++ info->mem[0].memtype = UIO_MEM_PHYS;
++
++ info->name = "smx-ce";
++ info->version = "0.03";
++
++ info->irq = platform_get_irq(dev, 0);
++ if (info->irq < 0) {
++ ret = info->irq;
++ dev_err(&dev->dev, "No (or invalid) IRQ resource specified\n");
++ goto out_unmap;
++ }
++
++ info->irq_flags = IRQF_SHARED;
++ info->handler = smx_handler;
++
++ platform_set_drvdata(dev, info);
++
++ ret = uio_register_device(&dev->dev, info);
++
++ if (ret)
++ goto out_unmap;
++
++ return 0;
++
++out_unmap:
++ iounmap(info->mem[0].internal_addr);
++out_free:
++ kfree(info);
++
++ return ret;
++}
++
++static int __devexit smx_ce_remove(struct platform_device *dev)
++{
++ struct uio_info *info = platform_get_drvdata(dev);
++
++ uio_unregister_device(info);
++ platform_set_drvdata(dev, NULL);
++ iounmap(info->mem[0].internal_addr);
++
++ kfree(info);
++
++ return 0;
++}
++
++static struct platform_driver smx_ce_driver = {
++ .probe = smx_ce_probe,
++ .remove = __devexit_p(smx_ce_remove),
++ .driver = {
++ .name = DRV_NAME,
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init smx_ce_init_module(void)
++{
++ return platform_driver_register(&smx_ce_driver);
++}
++module_init(smx_ce_init_module);
++
++static void __exit smx_ce_exit_module(void)
++{
++ platform_driver_unregister(&smx_ce_driver);
++}
++module_exit(smx_ce_exit_module);
++
++MODULE_LICENSE("GPL v2");
++MODULE_VERSION(DRV_VERSION);
++MODULE_AUTHOR("Ben Nizette <bn@niasdigital.com>");
diff --git a/pci/pci-arm-use-generic-pci_enable_resources.patch b/pci/pci-arm-use-generic-pci_enable_resources.patch
index 114b59af23cd85..31ac7c920c6566 100644
--- a/pci/pci-arm-use-generic-pci_enable_resources.patch
+++ b/pci/pci-arm-use-generic-pci_enable_resources.patch
@@ -26,6 +26,7 @@ Unlike this arch-specific code, the generic version:
- checks for resource collisions with "!r->parent"
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
+Acked-by: Russell King <rmk@arm.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
diff --git a/pci/pci-doc-pci-create-documentation-pci-and-move-files-into-it.patch b/pci/pci-doc-pci-create-documentation-pci-and-move-files-into-it.patch
new file mode 100644
index 00000000000000..10658a220d9ba5
--- /dev/null
+++ b/pci/pci-doc-pci-create-documentation-pci-and-move-files-into-it.patch
@@ -0,0 +1,3141 @@
+From randy.dunlap@oracle.com Thu Mar 13 13:47:45 2008
+From: Randy Dunlap <randy.dunlap@oracle.com>
+Date: Mon, 10 Mar 2008 17:16:32 -0700
+Subject: PCI: doc/pci: create Documentation/PCI/ and move files into it
+To: Jesse Barnes <jbarnes@virtuousgeek.org>, gregkh <greg@kroah.com>
+Cc: linux-pci@atrey.karlin.mff.cuni.cz
+Message-ID: <20080310171632.cd4c9c31.randy.dunlap@oracle.com>
+
+From: Randy Dunlap <randy.dunlap@oracle.com>
+
+Create Documentation/PCI/ and move PCI-related files to it.
+Fix a few instances of trailing whitespace.
+Update references to the new file locations.
+
+Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
+Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/00-INDEX | 10
+ Documentation/PCI/00-INDEX | 12
+ Documentation/PCI/PCIEBUS-HOWTO.txt | 217 ++++++++++
+ Documentation/PCI/pci-error-recovery.txt | 396 +++++++++++++++++++
+ Documentation/PCI/pci.txt | 646 +++++++++++++++++++++++++++++++
+ Documentation/PCI/pcieaer-howto.txt | 253 ++++++++++++
+ Documentation/PCIEBUS-HOWTO.txt | 217 ----------
+ Documentation/memory-barriers.txt | 4
+ Documentation/pci-error-recovery.txt | 396 -------------------
+ Documentation/pci.txt | 646 -------------------------------
+ Documentation/pcieaer-howto.txt | 253 ------------
+ 11 files changed, 1526 insertions(+), 1524 deletions(-)
+
+--- a/Documentation/00-INDEX
++++ b/Documentation/00-INDEX
+@@ -25,8 +25,6 @@ DMA-API.txt
+ - DMA API, pci_ API & extensions for non-consistent memory machines.
+ DMA-ISA-LPC.txt
+ - How to do DMA with ISA (and LPC) devices.
+-DMA-mapping.txt
+- - info for PCI drivers using DMA portably across all platforms.
+ DocBook/
+ - directory with DocBook templates etc. for kernel documentation.
+ HOWTO
+@@ -43,8 +41,6 @@ ManagementStyle
+ - how to (attempt to) manage kernel hackers.
+ MSI-HOWTO.txt
+ - the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
+-PCIEBUS-HOWTO.txt
+- - a guide describing the PCI Express Port Bus driver.
+ RCU/
+ - directory with info on RCU (read-copy update).
+ README.DAC960
+@@ -291,12 +287,6 @@ parport.txt
+ - how to use the parallel-port driver.
+ parport-lowlevel.txt
+ - description and usage of the low level parallel port functions.
+-pci-error-recovery.txt
+- - info on PCI error recovery.
+-pci.txt
+- - info on the PCI subsystem for device driver authors.
+-pcieaer-howto.txt
+- - the PCI Express Advanced Error Reporting Driver Guide HOWTO.
+ pcmcia/
+ - info on the Linux PCMCIA driver.
+ pi-futex.txt
+--- /dev/null
++++ b/Documentation/PCI/00-INDEX
+@@ -0,0 +1,12 @@
++00-INDEX
++ - this file
++PCI-DMA-mapping.txt
++ - info for PCI drivers using DMA portably across all platforms
++PCIEBUS-HOWTO.txt
++ - a guide describing the PCI Express Port Bus driver
++pci-error-recovery.txt
++ - info on PCI error recovery
++pci.txt
++ - info on the PCI subsystem for device driver authors
++pcieaer-howto.txt
++ - the PCI Express Advanced Error Reporting Driver Guide HOWTO
+--- /dev/null
++++ b/Documentation/PCI/PCIEBUS-HOWTO.txt
+@@ -0,0 +1,217 @@
++ The PCI Express Port Bus Driver Guide HOWTO
++ Tom L Nguyen tom.l.nguyen@intel.com
++ 11/03/2004
++
++1. About this guide
++
++This guide describes the basics of the PCI Express Port Bus driver
++and provides information on how to enable the service drivers to
++register/unregister with the PCI Express Port Bus Driver.
++
++2. Copyright 2004 Intel Corporation
++
++3. What is the PCI Express Port Bus Driver
++
++A PCI Express Port is a logical PCI-PCI Bridge structure. There
++are two types of PCI Express Port: the Root Port and the Switch
++Port. The Root Port originates a PCI Express link from a PCI Express
++Root Complex and the Switch Port connects PCI Express links to
++internal logical PCI buses. The Switch Port, which has its secondary
++bus representing the switch's internal routing logic, is called the
++switch's Upstream Port. The switch's Downstream Port is bridging from
++switch's internal routing bus to a bus representing the downstream
++PCI Express link from the PCI Express Switch.
++
++A PCI Express Port can provide up to four distinct functions,
++referred to in this document as services, depending on its port type.
++PCI Express Port's services include native hotplug support (HP),
++power management event support (PME), advanced error reporting
++support (AER), and virtual channel support (VC). These services may
++be handled by a single complex driver or be individually distributed
++and handled by corresponding service drivers.
++
++4. Why use the PCI Express Port Bus Driver?
++
++In existing Linux kernels, the Linux Device Driver Model allows a
++physical device to be handled by only a single driver. The PCI
++Express Port is a PCI-PCI Bridge device with multiple distinct
++services. To maintain a clean and simple solution each service
++may have its own software service driver. In this case several
++service drivers will compete for a single PCI-PCI Bridge device.
++For example, if the PCI Express Root Port native hotplug service
++driver is loaded first, it claims a PCI-PCI Bridge Root Port. The
++kernel therefore does not load other service drivers for that Root
++Port. In other words, it is impossible to have multiple service
++drivers load and run on a PCI-PCI Bridge device simultaneously
++using the current driver model.
++
++To enable multiple service drivers running simultaneously requires
++having a PCI Express Port Bus driver, which manages all populated
++PCI Express Ports and distributes all provided service requests
++to the corresponding service drivers as required. Some key
++advantages of using the PCI Express Port Bus driver are listed below:
++
++ - Allow multiple service drivers to run simultaneously on
++ a PCI-PCI Bridge Port device.
++
++ - Allow service drivers implemented in an independent
++ staged approach.
++
++ - Allow one service driver to run on multiple PCI-PCI Bridge
++ Port devices.
++
++ - Manage and distribute resources of a PCI-PCI Bridge Port
++ device to requested service drivers.
++
++5. Configuring the PCI Express Port Bus Driver vs. Service Drivers
++
++5.1 Including the PCI Express Port Bus Driver Support into the Kernel
++
++Including the PCI Express Port Bus driver depends on whether the PCI
++Express support is included in the kernel config. The kernel will
++automatically include the PCI Express Port Bus driver as a kernel
++driver when the PCI Express support is enabled in the kernel.
++
++5.2 Enabling Service Driver Support
++
++PCI device drivers are implemented based on Linux Device Driver Model.
++All service drivers are PCI device drivers. As discussed above, it is
++impossible to load any service driver once the kernel has loaded the
++PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver
++Model requires some minimal changes on existing service drivers that
++imposes no impact on the functionality of existing service drivers.
++
++A service driver is required to use the two APIs shown below to
++register its service with the PCI Express Port Bus driver (see
++section 5.2.1 & 5.2.2). It is important that a service driver
++initializes the pcie_port_service_driver data structure, included in
++header file /include/linux/pcieport_if.h, before calling these APIs.
++Failure to do so will result an identity mismatch, which prevents
++the PCI Express Port Bus driver from loading a service driver.
++
++5.2.1 pcie_port_service_register
++
++int pcie_port_service_register(struct pcie_port_service_driver *new)
++
++This API replaces the Linux Driver Model's pci_module_init API. A
++service driver should always calls pcie_port_service_register at
++module init. Note that after service driver being loaded, calls
++such as pci_enable_device(dev) and pci_set_master(dev) are no longer
++necessary since these calls are executed by the PCI Port Bus driver.
++
++5.2.2 pcie_port_service_unregister
++
++void pcie_port_service_unregister(struct pcie_port_service_driver *new)
++
++pcie_port_service_unregister replaces the Linux Driver Model's
++pci_unregister_driver. It's always called by service driver when a
++module exits.
++
++5.2.3 Sample Code
++
++Below is sample service driver code to initialize the port service
++driver data structure.
++
++static struct pcie_port_service_id service_id[] = { {
++ .vendor = PCI_ANY_ID,
++ .device = PCI_ANY_ID,
++ .port_type = PCIE_RC_PORT,
++ .service_type = PCIE_PORT_SERVICE_AER,
++ }, { /* end: all zeroes */ }
++};
++
++static struct pcie_port_service_driver root_aerdrv = {
++ .name = (char *)device_name,
++ .id_table = &service_id[0],
++
++ .probe = aerdrv_load,
++ .remove = aerdrv_unload,
++
++ .suspend = aerdrv_suspend,
++ .resume = aerdrv_resume,
++};
++
++Below is a sample code for registering/unregistering a service
++driver.
++
++static int __init aerdrv_service_init(void)
++{
++ int retval = 0;
++
++ retval = pcie_port_service_register(&root_aerdrv);
++ if (!retval) {
++ /*
++ * FIX ME
++ */
++ }
++ return retval;
++}
++
++static void __exit aerdrv_service_exit(void)
++{
++ pcie_port_service_unregister(&root_aerdrv);
++}
++
++module_init(aerdrv_service_init);
++module_exit(aerdrv_service_exit);
++
++6. Possible Resource Conflicts
++
++Since all service drivers of a PCI-PCI Bridge Port device are
++allowed to run simultaneously, below lists a few of possible resource
++conflicts with proposed solutions.
++
++6.1 MSI Vector Resource
++
++The MSI capability structure enables a device software driver to call
++pci_enable_msi to request MSI based interrupts. Once MSI interrupts
++are enabled on a device, it stays in this mode until a device driver
++calls pci_disable_msi to disable MSI interrupts and revert back to
++INTx emulation mode. Since service drivers of the same PCI-PCI Bridge
++port share the same physical device, if an individual service driver
++calls pci_enable_msi/pci_disable_msi it may result unpredictable
++behavior. For example, two service drivers run simultaneously on the
++same physical Root Port. Both service drivers call pci_enable_msi to
++request MSI based interrupts. A service driver may not know whether
++any other service drivers have run on this Root Port. If either one
++of them calls pci_disable_msi, it puts the other service driver
++in a wrong interrupt mode.
++
++To avoid this situation all service drivers are not permitted to
++switch interrupt mode on its device. The PCI Express Port Bus driver
++is responsible for determining the interrupt mode and this should be
++transparent to service drivers. Service drivers need to know only
++the vector IRQ assigned to the field irq of struct pcie_device, which
++is passed in when the PCI Express Port Bus driver probes each service
++driver. Service drivers should use (struct pcie_device*)dev->irq to
++call request_irq/free_irq. In addition, the interrupt mode is stored
++in the field interrupt_mode of struct pcie_device.
++
++6.2 MSI-X Vector Resources
++
++Similar to the MSI a device driver for an MSI-X capable device can
++call pci_enable_msix to request MSI-X interrupts. All service drivers
++are not permitted to switch interrupt mode on its device. The PCI
++Express Port Bus driver is responsible for determining the interrupt
++mode and this should be transparent to service drivers. Any attempt
++by service driver to call pci_enable_msix/pci_disable_msix may
++result unpredictable behavior. Service drivers should use
++(struct pcie_device*)dev->irq and call request_irq/free_irq.
++
++6.3 PCI Memory/IO Mapped Regions
++
++Service drivers for PCI Express Power Management (PME), Advanced
++Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access
++PCI configuration space on the PCI Express port. In all cases the
++registers accessed are independent of each other. This patch assumes
++that all service drivers will be well behaved and not overwrite
++other service driver's configuration settings.
++
++6.4 PCI Config Registers
++
++Each service driver runs its PCI config operations on its own
++capability structure except the PCI Express capability structure, in
++which Root Control register and Device Control register are shared
++between PME and AER. This patch assumes that all service drivers
++will be well behaved and not overwrite other service driver's
++configuration settings.
+--- /dev/null
++++ b/Documentation/PCI/pci-error-recovery.txt
+@@ -0,0 +1,396 @@
++
++ PCI Error Recovery
++ ------------------
++ February 2, 2006
++
++ Current document maintainer:
++ Linas Vepstas <linas@austin.ibm.com>
++
++
++Many PCI bus controllers are able to detect a variety of hardware
++PCI errors on the bus, such as parity errors on the data and address
++busses, as well as SERR and PERR errors. Some of the more advanced
++chipsets are able to deal with these errors; these include PCI-E chipsets,
++and the PCI-host bridges found on IBM Power4 and Power5-based pSeries
++boxes. A typical action taken is to disconnect the affected device,
++halting all I/O to it. The goal of a disconnection is to avoid system
++corruption; for example, to halt system memory corruption due to DMA's
++to "wild" addresses. Typically, a reconnection mechanism is also
++offered, so that the affected PCI device(s) are reset and put back
++into working condition. The reset phase requires coordination
++between the affected device drivers and the PCI controller chip.
++This document describes a generic API for notifying device drivers
++of a bus disconnection, and then performing error recovery.
++This API is currently implemented in the 2.6.16 and later kernels.
++
++Reporting and recovery is performed in several steps. First, when
++a PCI hardware error has resulted in a bus disconnect, that event
++is reported as soon as possible to all affected device drivers,
++including multiple instances of a device driver on multi-function
++cards. This allows device drivers to avoid deadlocking in spinloops,
++waiting for some i/o-space register to change, when it never will.
++It also gives the drivers a chance to defer incoming I/O as
++needed.
++
++Next, recovery is performed in several stages. Most of the complexity
++is forced by the need to handle multi-function devices, that is,
++devices that have multiple device drivers associated with them.
++In the first stage, each driver is allowed to indicate what type
++of reset it desires, the choices being a simple re-enabling of I/O
++or requesting a hard reset (a full electrical #RST of the PCI card).
++If any driver requests a full reset, that is what will be done.
++
++After a full reset and/or a re-enabling of I/O, all drivers are
++again notified, so that they may then perform any device setup/config
++that may be required. After these have all completed, a final
++"resume normal operations" event is sent out.
++
++The biggest reason for choosing a kernel-based implementation rather
++than a user-space implementation was the need to deal with bus
++disconnects of PCI devices attached to storage media, and, in particular,
++disconnects from devices holding the root file system. If the root
++file system is disconnected, a user-space mechanism would have to go
++through a large number of contortions to complete recovery. Almost all
++of the current Linux file systems are not tolerant of disconnection
++from/reconnection to their underlying block device. By contrast,
++bus errors are easy to manage in the device driver. Indeed, most
++device drivers already handle very similar recovery procedures;
++for example, the SCSI-generic layer already provides significant
++mechanisms for dealing with SCSI bus errors and SCSI bus resets.
++
++
++Detailed Design
++---------------
++Design and implementation details below, based on a chain of
++public email discussions with Ben Herrenschmidt, circa 5 April 2005.
++
++The error recovery API support is exposed to the driver in the form of
++a structure of function pointers pointed to by a new field in struct
++pci_driver. A driver that fails to provide the structure is "non-aware",
++and the actual recovery steps taken are platform dependent. The
++arch/powerpc implementation will simulate a PCI hotplug remove/add.
++
++This structure has the form:
++struct pci_error_handlers
++{
++ int (*error_detected)(struct pci_dev *dev, enum pci_channel_state);
++ int (*mmio_enabled)(struct pci_dev *dev);
++ int (*link_reset)(struct pci_dev *dev);
++ int (*slot_reset)(struct pci_dev *dev);
++ void (*resume)(struct pci_dev *dev);
++};
++
++The possible channel states are:
++enum pci_channel_state {
++ pci_channel_io_normal, /* I/O channel is in normal state */
++ pci_channel_io_frozen, /* I/O to channel is blocked */
++ pci_channel_io_perm_failure, /* PCI card is dead */
++};
++
++Possible return values are:
++enum pci_ers_result {
++ PCI_ERS_RESULT_NONE, /* no result/none/not supported in device driver */
++ PCI_ERS_RESULT_CAN_RECOVER, /* Device driver can recover without slot reset */
++ PCI_ERS_RESULT_NEED_RESET, /* Device driver wants slot to be reset. */
++ PCI_ERS_RESULT_DISCONNECT, /* Device has completely failed, is unrecoverable */
++ PCI_ERS_RESULT_RECOVERED, /* Device driver is fully recovered and operational */
++};
++
++A driver does not have to implement all of these callbacks; however,
++if it implements any, it must implement error_detected(). If a callback
++is not implemented, the corresponding feature is considered unsupported.
++For example, if mmio_enabled() and resume() aren't there, then it
++is assumed that the driver is not doing any direct recovery and requires
++a reset. If link_reset() is not implemented, the card is assumed as
++not care about link resets. Typically a driver will want to know about
++a slot_reset().
++
++The actual steps taken by a platform to recover from a PCI error
++event will be platform-dependent, but will follow the general
++sequence described below.
++
++STEP 0: Error Event
++-------------------
++PCI bus error is detect by the PCI hardware. On powerpc, the slot
++is isolated, in that all I/O is blocked: all reads return 0xffffffff,
++all writes are ignored.
++
++
++STEP 1: Notification
++--------------------
++Platform calls the error_detected() callback on every instance of
++every driver affected by the error.
++
++At this point, the device might not be accessible anymore, depending on
++the platform (the slot will be isolated on powerpc). The driver may
++already have "noticed" the error because of a failing I/O, but this
++is the proper "synchronization point", that is, it gives the driver
++a chance to cleanup, waiting for pending stuff (timers, whatever, etc...)
++to complete; it can take semaphores, schedule, etc... everything but
++touch the device. Within this function and after it returns, the driver
++shouldn't do any new IOs. Called in task context. This is sort of a
++"quiesce" point. See note about interrupts at the end of this doc.
++
++All drivers participating in this system must implement this call.
++The driver must return one of the following result codes:
++ - PCI_ERS_RESULT_CAN_RECOVER:
++ Driver returns this if it thinks it might be able to recover
++ the HW by just banging IOs or if it wants to be given
++ a chance to extract some diagnostic information (see
++ mmio_enable, below).
++ - PCI_ERS_RESULT_NEED_RESET:
++ Driver returns this if it can't recover without a hard
++ slot reset.
++ - PCI_ERS_RESULT_DISCONNECT:
++ Driver returns this if it doesn't want to recover at all.
++
++The next step taken will depend on the result codes returned by the
++drivers.
++
++If all drivers on the segment/slot return PCI_ERS_RESULT_CAN_RECOVER,
++then the platform should re-enable IOs on the slot (or do nothing in
++particular, if the platform doesn't isolate slots), and recovery
++proceeds to STEP 2 (MMIO Enable).
++
++If any driver requested a slot reset (by returning PCI_ERS_RESULT_NEED_RESET),
++then recovery proceeds to STEP 4 (Slot Reset).
++
++If the platform is unable to recover the slot, the next step
++is STEP 6 (Permanent Failure).
++
++>>> The current powerpc implementation assumes that a device driver will
++>>> *not* schedule or semaphore in this routine; the current powerpc
++>>> implementation uses one kernel thread to notify all devices;
++>>> thus, if one device sleeps/schedules, all devices are affected.
++>>> Doing better requires complex multi-threaded logic in the error
++>>> recovery implementation (e.g. waiting for all notification threads
++>>> to "join" before proceeding with recovery.) This seems excessively
++>>> complex and not worth implementing.
++
++>>> The current powerpc implementation doesn't much care if the device
++>>> attempts I/O at this point, or not. I/O's will fail, returning
++>>> a value of 0xff on read, and writes will be dropped. If the device
++>>> driver attempts more than 10K I/O's to a frozen adapter, it will
++>>> assume that the device driver has gone into an infinite loop, and
++>>> it will panic the kernel. There doesn't seem to be any other
++>>> way of stopping a device driver that insists on spinning on I/O.
++
++STEP 2: MMIO Enabled
++-------------------
++The platform re-enables MMIO to the device (but typically not the
++DMA), and then calls the mmio_enabled() callback on all affected
++device drivers.
++
++This is the "early recovery" call. IOs are allowed again, but DMA is
++not (hrm... to be discussed, I prefer not), with some restrictions. This
++is NOT a callback for the driver to start operations again, only to
++peek/poke at the device, extract diagnostic information, if any, and
++eventually do things like trigger a device local reset or some such,
++but not restart operations. This is callback is made if all drivers on
++a segment agree that they can try to recover and if no automatic link reset
++was performed by the HW. If the platform can't just re-enable IOs without
++a slot reset or a link reset, it wont call this callback, and instead
++will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
++
++>>> The following is proposed; no platform implements this yet:
++>>> Proposal: All I/O's should be done _synchronously_ from within
++>>> this callback, errors triggered by them will be returned via
++>>> the normal pci_check_whatever() API, no new error_detected()
++>>> callback will be issued due to an error happening here. However,
++>>> such an error might cause IOs to be re-blocked for the whole
++>>> segment, and thus invalidate the recovery that other devices
++>>> on the same segment might have done, forcing the whole segment
++>>> into one of the next states, that is, link reset or slot reset.
++
++The driver should return one of the following result codes:
++ - PCI_ERS_RESULT_RECOVERED
++ Driver returns this if it thinks the device is fully
++ functional and thinks it is ready to start
++ normal driver operations again. There is no
++ guarantee that the driver will actually be
++ allowed to proceed, as another driver on the
++ same segment might have failed and thus triggered a
++ slot reset on platforms that support it.
++
++ - PCI_ERS_RESULT_NEED_RESET
++ Driver returns this if it thinks the device is not
++ recoverable in it's current state and it needs a slot
++ reset to proceed.
++
++ - PCI_ERS_RESULT_DISCONNECT
++ Same as above. Total failure, no recovery even after
++ reset driver dead. (To be defined more precisely)
++
++The next step taken depends on the results returned by the drivers.
++If all drivers returned PCI_ERS_RESULT_RECOVERED, then the platform
++proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations).
++
++If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform
++proceeds to STEP 4 (Slot Reset)
++
++>>> The current powerpc implementation does not implement this callback.
++
++
++STEP 3: Link Reset
++------------------
++The platform resets the link, and then calls the link_reset() callback
++on all affected device drivers. This is a PCI-Express specific state
++and is done whenever a non-fatal error has been detected that can be
++"solved" by resetting the link. This call informs the driver of the
++reset and the driver should check to see if the device appears to be
++in working condition.
++
++The driver is not supposed to restart normal driver I/O operations
++at this point. It should limit itself to "probing" the device to
++check it's recoverability status. If all is right, then the platform
++will call resume() once all drivers have ack'd link_reset().
++
++ Result codes:
++ (identical to STEP 3 (MMIO Enabled)
++
++The platform then proceeds to either STEP 4 (Slot Reset) or STEP 5
++(Resume Operations).
++
++>>> The current powerpc implementation does not implement this callback.
++
++
++STEP 4: Slot Reset
++------------------
++The platform performs a soft or hard reset of the device, and then
++calls the slot_reset() callback.
++
++A soft reset consists of asserting the adapter #RST line and then
++restoring the PCI BAR's and PCI configuration header to a state
++that is equivalent to what it would be after a fresh system
++power-on followed by power-on BIOS/system firmware initialization.
++If the platform supports PCI hotplug, then the reset might be
++performed by toggling the slot electrical power off/on.
++
++It is important for the platform to restore the PCI config space
++to the "fresh poweron" state, rather than the "last state". After
++a slot reset, the device driver will almost always use its standard
++device initialization routines, and an unusual config space setup
++may result in hung devices, kernel panics, or silent data corruption.
++
++This call gives drivers the chance to re-initialize the hardware
++(re-download firmware, etc.). At this point, the driver may assume
++that he card is in a fresh state and is fully functional. In
++particular, interrupt generation should work normally.
++
++Drivers should not yet restart normal I/O processing operations
++at this point. If all device drivers report success on this
++callback, the platform will call resume() to complete the sequence,
++and let the driver restart normal I/O processing.
++
++A driver can still return a critical failure for this function if
++it can't get the device operational after reset. If the platform
++previously tried a soft reset, it might now try a hard reset (power
++cycle) and then call slot_reset() again. It the device still can't
++be recovered, there is nothing more that can be done; the platform
++will typically report a "permanent failure" in such a case. The
++device will be considered "dead" in this case.
++
++Drivers for multi-function cards will need to coordinate among
++themselves as to which driver instance will perform any "one-shot"
++or global device initialization. For example, the Symbios sym53cxx2
++driver performs device init only from PCI function 0:
++
+++ if (PCI_FUNC(pdev->devfn) == 0)
+++ sym_reset_scsi_bus(np, 0);
++
++ Result codes:
++ - PCI_ERS_RESULT_DISCONNECT
++ Same as above.
++
++Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent
++Failure).
++
++>>> The current powerpc implementation does not currently try a
++>>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
++>>> However, it probably should.
++
++
++STEP 5: Resume Operations
++-------------------------
++The platform will call the resume() callback on all affected device
++drivers if all drivers on the segment have returned
++PCI_ERS_RESULT_RECOVERED from one of the 3 previous callbacks.
++The goal of this callback is to tell the driver to restart activity,
++that everything is back and running. This callback does not return
++a result code.
++
++At this point, if a new error happens, the platform will restart
++a new error recovery sequence.
++
++STEP 6: Permanent Failure
++-------------------------
++A "permanent failure" has occurred, and the platform cannot recover
++the device. The platform will call error_detected() with a
++pci_channel_state value of pci_channel_io_perm_failure.
++
++The device driver should, at this point, assume the worst. It should
++cancel all pending I/O, refuse all new I/O, returning -EIO to
++higher layers. The device driver should then clean up all of its
++memory and remove itself from kernel operations, much as it would
++during system shutdown.
++
++The platform will typically notify the system operator of the
++permanent failure in some way. If the device is hotplug-capable,
++the operator will probably want to remove and replace the device.
++Note, however, not all failures are truly "permanent". Some are
++caused by over-heating, some by a poorly seated card. Many
++PCI error events are caused by software bugs, e.g. DMA's to
++wild addresses or bogus split transactions due to programming
++errors. See the discussion in powerpc/eeh-pci-error-recovery.txt
++for additional detail on real-life experience of the causes of
++software errors.
++
++
++Conclusion; General Remarks
++---------------------------
++The way those callbacks are called is platform policy. A platform with
++no slot reset capability may want to just "ignore" drivers that can't
++recover (disconnect them) and try to let other cards on the same segment
++recover. Keep in mind that in most real life cases, though, there will
++be only one driver per segment.
++
++Now, a note about interrupts. If you get an interrupt and your
++device is dead or has been isolated, there is a problem :)
++The current policy is to turn this into a platform policy.
++That is, the recovery API only requires that:
++
++ - There is no guarantee that interrupt delivery can proceed from any
++device on the segment starting from the error detection and until the
++resume callback is sent, at which point interrupts are expected to be
++fully operational.
++
++ - There is no guarantee that interrupt delivery is stopped, that is,
++a driver that gets an interrupt after detecting an error, or that detects
++an error within the interrupt handler such that it prevents proper
++ack'ing of the interrupt (and thus removal of the source) should just
++return IRQ_NOTHANDLED. It's up to the platform to deal with that
++condition, typically by masking the IRQ source during the duration of
++the error handling. It is expected that the platform "knows" which
++interrupts are routed to error-management capable slots and can deal
++with temporarily disabling that IRQ number during error processing (this
++isn't terribly complex). That means some IRQ latency for other devices
++sharing the interrupt, but there is simply no other way. High end
++platforms aren't supposed to share interrupts between many devices
++anyway :)
++
++>>> Implementation details for the powerpc platform are discussed in
++>>> the file Documentation/powerpc/eeh-pci-error-recovery.txt
++
++>>> As of this writing, there are six device drivers with patches
++>>> implementing error recovery. Not all of these patches are in
++>>> mainline yet. These may be used as "examples":
++>>>
++>>> drivers/scsi/ipr.c
++>>> drivers/scsi/sym53cxx_2
++>>> drivers/next/e100.c
++>>> drivers/net/e1000
++>>> drivers/net/ixgb
++>>> drivers/net/s2io.c
++
++The End
++-------
+--- /dev/null
++++ b/Documentation/PCI/pci.txt
+@@ -0,0 +1,646 @@
++
++ How To Write Linux PCI Drivers
++
++ by Martin Mares <mj@ucw.cz> on 07-Feb-2000
++ updated by Grant Grundler <grundler@parisc-linux.org> on 23-Dec-2006
++
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++The world of PCI is vast and full of (mostly unpleasant) surprises.
++Since each CPU architecture implements different chip-sets and PCI devices
++have different requirements (erm, "features"), the result is the PCI support
++in the Linux kernel is not as trivial as one would wish. This short paper
++tries to introduce all potential driver authors to Linux APIs for
++PCI device drivers.
++
++A more complete resource is the third edition of "Linux Device Drivers"
++by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman.
++LDD3 is available for free (under Creative Commons License) from:
++
++ http://lwn.net/Kernel/LDD3/
++
++However, keep in mind that all documents are subject to "bit rot".
++Refer to the source code if things are not working as described here.
++
++Please send questions/comments/patches about Linux PCI API to the
++"Linux PCI" <linux-pci@atrey.karlin.mff.cuni.cz> mailing list.
++
++
++
++0. Structure of PCI drivers
++~~~~~~~~~~~~~~~~~~~~~~~~~~~
++PCI drivers "discover" PCI devices in a system via pci_register_driver().
++Actually, it's the other way around. When the PCI generic code discovers
++a new device, the driver with a matching "description" will be notified.
++Details on this below.
++
++pci_register_driver() leaves most of the probing for devices to
++the PCI layer and supports online insertion/removal of devices [thus
++supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver].
++pci_register_driver() call requires passing in a table of function
++pointers and thus dictates the high level structure of a driver.
++
++Once the driver knows about a PCI device and takes ownership, the
++driver generally needs to perform the following initialization:
++
++ Enable the device
++ Request MMIO/IOP resources
++ Set the DMA mask size (for both coherent and streaming DMA)
++ Allocate and initialize shared control data (pci_allocate_coherent())
++ Access device configuration space (if needed)
++ Register IRQ handler (request_irq())
++ Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
++ Enable DMA/processing engines
++
++When done using the device, and perhaps the module needs to be unloaded,
++the driver needs to take the follow steps:
++ Disable the device from generating IRQs
++ Release the IRQ (free_irq())
++ Stop all DMA activity
++ Release DMA buffers (both streaming and coherent)
++ Unregister from other subsystems (e.g. scsi or netdev)
++ Release MMIO/IOP resources
++ Disable the device
++
++Most of these topics are covered in the following sections.
++For the rest look at LDD3 or <linux/pci.h> .
++
++If the PCI subsystem is not configured (CONFIG_PCI is not set), most of
++the PCI functions described below are defined as inline functions either
++completely empty or just returning an appropriate error codes to avoid
++lots of ifdefs in the drivers.
++
++
++
++1. pci_register_driver() call
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++PCI device drivers call pci_register_driver() during their
++initialization with a pointer to a structure describing the driver
++(struct pci_driver):
++
++ field name Description
++ ---------- ------------------------------------------------------
++ id_table Pointer to table of device ID's the driver is
++ interested in. Most drivers should export this
++ table using MODULE_DEVICE_TABLE(pci,...).
++
++ probe This probing function gets called (during execution
++ of pci_register_driver() for already existing
++ devices or later if a new device gets inserted) for
++ all PCI devices which match the ID table and are not
++ "owned" by the other drivers yet. This function gets
++ passed a "struct pci_dev *" for each device whose
++ entry in the ID table matches the device. The probe
++ function returns zero when the driver chooses to
++ take "ownership" of the device or an error code
++ (negative number) otherwise.
++ The probe function always gets called from process
++ context, so it can sleep.
++
++ remove The remove() function gets called whenever a device
++ being handled by this driver is removed (either during
++ deregistration of the driver or when it's manually
++ pulled out of a hot-pluggable slot).
++ The remove function always gets called from process
++ context, so it can sleep.
++
++ suspend Put device into low power state.
++ suspend_late Put device into low power state.
++
++ resume_early Wake device from low power state.
++ resume Wake device from low power state.
++
++ (Please see Documentation/power/pci.txt for descriptions
++ of PCI Power Management and the related functions.)
++
++ shutdown Hook into reboot_notifier_list (kernel/sys.c).
++ Intended to stop any idling DMA operations.
++ Useful for enabling wake-on-lan (NIC) or changing
++ the power state of a device before reboot.
++ e.g. drivers/net/e100.c.
++
++ err_handler See Documentation/PCI/pci-error-recovery.txt
++
++
++The ID table is an array of struct pci_device_id entries ending with an
++all-zero entry; use of the macro DEFINE_PCI_DEVICE_TABLE is the preferred
++method of declaring the table. Each entry consists of:
++
++ vendor,device Vendor and device ID to match (or PCI_ANY_ID)
++
++ subvendor, Subsystem vendor and device ID to match (or PCI_ANY_ID)
++ subdevice,
++
++ class Device class, subclass, and "interface" to match.
++ See Appendix D of the PCI Local Bus Spec or
++ include/linux/pci_ids.h for a full list of classes.
++ Most drivers do not need to specify class/class_mask
++ as vendor/device is normally sufficient.
++
++ class_mask limit which sub-fields of the class field are compared.
++ See drivers/scsi/sym53c8xx_2/ for example of usage.
++
++ driver_data Data private to the driver.
++ Most drivers don't need to use driver_data field.
++ Best practice is to use driver_data as an index
++ into a static list of equivalent device types,
++ instead of using it as a pointer.
++
++
++Most drivers only need PCI_DEVICE() or PCI_DEVICE_CLASS() to set up
++a pci_device_id table.
++
++New PCI IDs may be added to a device driver pci_ids table at runtime
++as shown below:
++
++echo "vendor device subvendor subdevice class class_mask driver_data" > \
++/sys/bus/pci/drivers/{driver}/new_id
++
++All fields are passed in as hexadecimal values (no leading 0x).
++The vendor and device fields are mandatory, the others are optional. Users
++need pass only as many optional fields as necessary:
++ o subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)
++ o class and classmask fields default to 0
++ o driver_data defaults to 0UL.
++
++Once added, the driver probe routine will be invoked for any unclaimed
++PCI devices listed in its (newly updated) pci_ids list.
++
++When the driver exits, it just calls pci_unregister_driver() and the PCI layer
++automatically calls the remove hook for all devices handled by the driver.
++
++
++1.1 "Attributes" for driver functions/data
++
++Please mark the initialization and cleanup functions where appropriate
++(the corresponding macros are defined in <linux/init.h>):
++
++ __init Initialization code. Thrown away after the driver
++ initializes.
++ __exit Exit code. Ignored for non-modular drivers.
++
++
++ __devinit Device initialization code.
++ Identical to __init if the kernel is not compiled
++ with CONFIG_HOTPLUG, normal function otherwise.
++ __devexit The same for __exit.
++
++Tips on when/where to use the above attributes:
++ o The module_init()/module_exit() functions (and all
++ initialization functions called _only_ from these)
++ should be marked __init/__exit.
++
++ o Do not mark the struct pci_driver.
++
++ o The ID table array should be marked __devinitconst; this is done
++ automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE().
++
++ o The probe() and remove() functions should be marked __devinit
++ and __devexit respectively. All initialization functions
++ exclusively called by the probe() routine, can be marked __devinit.
++ Ditto for remove() and __devexit.
++
++ o If mydriver_remove() is marked with __devexit(), then all address
++ references to mydriver_remove must use __devexit_p(mydriver_remove)
++ (in the struct pci_driver declaration for example).
++ __devexit_p() will generate the function name _or_ NULL if the
++ function will be discarded. For an example, see drivers/net/tg3.c.
++
++ o Do NOT mark a function if you are not sure which mark to use.
++ Better to not mark the function than mark the function wrong.
++
++
++
++2. How to find PCI devices manually
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++PCI drivers should have a really good reason for not using the
++pci_register_driver() interface to search for PCI devices.
++The main reason PCI devices are controlled by multiple drivers
++is because one PCI device implements several different HW services.
++E.g. combined serial/parallel port/floppy controller.
++
++A manual search may be performed using the following constructs:
++
++Searching by vendor and device ID:
++
++ struct pci_dev *dev = NULL;
++ while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev))
++ configure_device(dev);
++
++Searching by class ID (iterate in a similar way):
++
++ pci_get_class(CLASS_ID, dev)
++
++Searching by both vendor/device and subsystem vendor/device ID:
++
++ pci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
++
++You can use the constant PCI_ANY_ID as a wildcard replacement for
++VENDOR_ID or DEVICE_ID. This allows searching for any device from a
++specific vendor, for example.
++
++These functions are hotplug-safe. They increment the reference count on
++the pci_dev that they return. You must eventually (possibly at module unload)
++decrement the reference count on these devices by calling pci_dev_put().
++
++
++
++3. Device Initialization Steps
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++As noted in the introduction, most PCI drivers need the following steps
++for device initialization:
++
++ Enable the device
++ Request MMIO/IOP resources
++ Set the DMA mask size (for both coherent and streaming DMA)
++ Allocate and initialize shared control data (pci_allocate_coherent())
++ Access device configuration space (if needed)
++ Register IRQ handler (request_irq())
++ Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
++ Enable DMA/processing engines.
++
++The driver can access PCI config space registers at any time.
++(Well, almost. When running BIST, config space can go away...but
++that will just result in a PCI Bus Master Abort and config reads
++will return garbage).
++
++
++3.1 Enable the PCI device
++~~~~~~~~~~~~~~~~~~~~~~~~~
++Before touching any device registers, the driver needs to enable
++the PCI device by calling pci_enable_device(). This will:
++ o wake up the device if it was in suspended state,
++ o allocate I/O and memory regions of the device (if BIOS did not),
++ o allocate an IRQ (if BIOS did not).
++
++NOTE: pci_enable_device() can fail! Check the return value.
++
++[ OS BUG: we don't check resource allocations before enabling those
++ resources. The sequence would make more sense if we called
++ pci_request_resources() before calling pci_enable_device().
++ Currently, the device drivers can't detect the bug when when two
++ devices have been allocated the same range. This is not a common
++ problem and unlikely to get fixed soon.
++
++ This has been discussed before but not changed as of 2.6.19:
++ http://lkml.org/lkml/2006/3/2/194
++]
++
++pci_set_master() will enable DMA by setting the bus master bit
++in the PCI_COMMAND register. It also fixes the latency timer value if
++it's set to something bogus by the BIOS.
++
++If the PCI device can use the PCI Memory-Write-Invalidate transaction,
++call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval
++and also ensures that the cache line size register is set correctly.
++Check the return value of pci_set_mwi() as not all architectures
++or chip-sets may support Memory-Write-Invalidate. Alternatively,
++if Mem-Wr-Inval would be nice to have but is not required, call
++pci_try_set_mwi() to have the system do its best effort at enabling
++Mem-Wr-Inval.
++
++
++3.2 Request MMIO/IOP resources
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Memory (MMIO), and I/O port addresses should NOT be read directly
++from the PCI device config space. Use the values in the pci_dev structure
++as the PCI "bus address" might have been remapped to a "host physical"
++address by the arch/chip-set specific kernel support.
++
++See Documentation/IO-mapping.txt for how to access device registers
++or device memory.
++
++The device driver needs to call pci_request_region() to verify
++no other device is already using the same address resource.
++Conversely, drivers should call pci_release_region() AFTER
++calling pci_disable_device().
++The idea is to prevent two devices colliding on the same address range.
++
++[ See OS BUG comment above. Currently (2.6.19), The driver can only
++ determine MMIO and IO Port resource availability _after_ calling
++ pci_enable_device(). ]
++
++Generic flavors of pci_request_region() are request_mem_region()
++(for MMIO ranges) and request_region() (for IO Port ranges).
++Use these for address resources that are not described by "normal" PCI
++BARs.
++
++Also see pci_request_selected_regions() below.
++
++
++3.3 Set the DMA mask size
++~~~~~~~~~~~~~~~~~~~~~~~~~
++[ If anything below doesn't make sense, please refer to
++ Documentation/DMA-API.txt. This section is just a reminder that
++ drivers need to indicate DMA capabilities of the device and is not
++ an authoritative source for DMA interfaces. ]
++
++While all drivers should explicitly indicate the DMA capability
++(e.g. 32 or 64 bit) of the PCI bus master, devices with more than
++32-bit bus master capability for streaming data need the driver
++to "register" this capability by calling pci_set_dma_mask() with
++appropriate parameters. In general this allows more efficient DMA
++on systems where System RAM exists above 4G _physical_ address.
++
++Drivers for all PCI-X and PCIe compliant devices must call
++pci_set_dma_mask() as they are 64-bit DMA devices.
++
++Similarly, drivers must also "register" this capability if the device
++can directly address "consistent memory" in System RAM above 4G physical
++address by calling pci_set_consistent_dma_mask().
++Again, this includes drivers for all PCI-X and PCIe compliant devices.
++Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are
++64-bit DMA capable for payload ("streaming") data but not control
++("consistent") data.
++
++
++3.4 Setup shared control data
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Once the DMA masks are set, the driver can allocate "consistent" (a.k.a. shared)
++memory. See Documentation/DMA-API.txt for a full description of
++the DMA APIs. This section is just a reminder that it needs to be done
++before enabling DMA on the device.
++
++
++3.5 Initialize device registers
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Some drivers will need specific "capability" fields programmed
++or other "vendor specific" register initialized or reset.
++E.g. clearing pending interrupts.
++
++
++3.6 Register IRQ handler
++~~~~~~~~~~~~~~~~~~~~~~~~
++While calling request_irq() is the last step described here,
++this is often just another intermediate step to initialize a device.
++This step can often be deferred until the device is opened for use.
++
++All interrupt handlers for IRQ lines should be registered with IRQF_SHARED
++and use the devid to map IRQs to devices (remember that all PCI IRQ lines
++can be shared).
++
++request_irq() will associate an interrupt handler and device handle
++with an interrupt number. Historically interrupt numbers represent
++IRQ lines which run from the PCI device to the Interrupt controller.
++With MSI and MSI-X (more below) the interrupt number is a CPU "vector".
++
++request_irq() also enables the interrupt. Make sure the device is
++quiesced and does not have any interrupts pending before registering
++the interrupt handler.
++
++MSI and MSI-X are PCI capabilities. Both are "Message Signaled Interrupts"
++which deliver interrupts to the CPU via a DMA write to a Local APIC.
++The fundamental difference between MSI and MSI-X is how multiple
++"vectors" get allocated. MSI requires contiguous blocks of vectors
++while MSI-X can allocate several individual ones.
++
++MSI capability can be enabled by calling pci_enable_msi() or
++pci_enable_msix() before calling request_irq(). This causes
++the PCI support to program CPU vector data into the PCI device
++capability registers.
++
++If your PCI device supports both, try to enable MSI-X first.
++Only one can be enabled at a time. Many architectures, chip-sets,
++or BIOSes do NOT support MSI or MSI-X and the call to pci_enable_msi/msix
++will fail. This is important to note since many drivers have
++two (or more) interrupt handlers: one for MSI/MSI-X and another for IRQs.
++They choose which handler to register with request_irq() based on the
++return value from pci_enable_msi/msix().
++
++There are (at least) two really good reasons for using MSI:
++1) MSI is an exclusive interrupt vector by definition.
++ This means the interrupt handler doesn't have to verify
++ its device caused the interrupt.
++
++2) MSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed
++ to be visible to the host CPU(s) when the MSI is delivered. This
++ is important for both data coherency and avoiding stale control data.
++ This guarantee allows the driver to omit MMIO reads to flush
++ the DMA stream.
++
++See drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples
++of MSI/MSI-X usage.
++
++
++
++4. PCI device shutdown
++~~~~~~~~~~~~~~~~~~~~~~~
++
++When a PCI device driver is being unloaded, most of the following
++steps need to be performed:
++
++ Disable the device from generating IRQs
++ Release the IRQ (free_irq())
++ Stop all DMA activity
++ Release DMA buffers (both streaming and consistent)
++ Unregister from other subsystems (e.g. scsi or netdev)
++ Disable device from responding to MMIO/IO Port addresses
++ Release MMIO/IO Port resource(s)
++
++
++4.1 Stop IRQs on the device
++~~~~~~~~~~~~~~~~~~~~~~~~~~~
++How to do this is chip/device specific. If it's not done, it opens
++the possibility of a "screaming interrupt" if (and only if)
++the IRQ is shared with another device.
++
++When the shared IRQ handler is "unhooked", the remaining devices
++using the same IRQ line will still need the IRQ enabled. Thus if the
++"unhooked" device asserts IRQ line, the system will respond assuming
++it was one of the remaining devices asserted the IRQ line. Since none
++of the other devices will handle the IRQ, the system will "hang" until
++it decides the IRQ isn't going to get handled and masks the IRQ (100,000
++iterations later). Once the shared IRQ is masked, the remaining devices
++will stop functioning properly. Not a nice situation.
++
++This is another reason to use MSI or MSI-X if it's available.
++MSI and MSI-X are defined to be exclusive interrupts and thus
++are not susceptible to the "screaming interrupt" problem.
++
++
++4.2 Release the IRQ
++~~~~~~~~~~~~~~~~~~~
++Once the device is quiesced (no more IRQs), one can call free_irq().
++This function will return control once any pending IRQs are handled,
++"unhook" the drivers IRQ handler from that IRQ, and finally release
++the IRQ if no one else is using it.
++
++
++4.3 Stop all DMA activity
++~~~~~~~~~~~~~~~~~~~~~~~~~
++It's extremely important to stop all DMA operations BEFORE attempting
++to deallocate DMA control data. Failure to do so can result in memory
++corruption, hangs, and on some chip-sets a hard crash.
++
++Stopping DMA after stopping the IRQs can avoid races where the
++IRQ handler might restart DMA engines.
++
++While this step sounds obvious and trivial, several "mature" drivers
++didn't get this step right in the past.
++
++
++4.4 Release DMA buffers
++~~~~~~~~~~~~~~~~~~~~~~~
++Once DMA is stopped, clean up streaming DMA first.
++I.e. unmap data buffers and return buffers to "upstream"
++owners if there is one.
++
++Then clean up "consistent" buffers which contain the control data.
++
++See Documentation/DMA-API.txt for details on unmapping interfaces.
++
++
++4.5 Unregister from other subsystems
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Most low level PCI device drivers support some other subsystem
++like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your
++driver isn't losing resources from that other subsystem.
++If this happens, typically the symptom is an Oops (panic) when
++the subsystem attempts to call into a driver that has been unloaded.
++
++
++4.6 Disable Device from responding to MMIO/IO Port addresses
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++io_unmap() MMIO or IO Port resources and then call pci_disable_device().
++This is the symmetric opposite of pci_enable_device().
++Do not access device registers after calling pci_disable_device().
++
++
++4.7 Release MMIO/IO Port Resource(s)
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Call pci_release_region() to mark the MMIO or IO Port range as available.
++Failure to do so usually results in the inability to reload the driver.
++
++
++
++5. How to access PCI config space
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++You can use pci_(read|write)_config_(byte|word|dword) to access the config
++space of a device represented by struct pci_dev *. All these functions return 0
++when successful or an error code (PCIBIOS_...) which can be translated to a text
++string by pcibios_strerror. Most drivers expect that accesses to valid PCI
++devices don't fail.
++
++If you don't have a struct pci_dev available, you can call
++pci_bus_(read|write)_config_(byte|word|dword) to access a given device
++and function on that bus.
++
++If you access fields in the standard portion of the config header, please
++use symbolic names of locations and bits declared in <linux/pci.h>.
++
++If you need to access Extended PCI Capability registers, just call
++pci_find_capability() for the particular capability and it will find the
++corresponding register block for you.
++
++
++
++6. Other interesting functions
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++pci_find_slot() Find pci_dev corresponding to given bus and
++ slot numbers.
++pci_set_power_state() Set PCI Power Management state (0=D0 ... 3=D3)
++pci_find_capability() Find specified capability in device's capability
++ list.
++pci_resource_start() Returns bus start address for a given PCI region
++pci_resource_end() Returns bus end address for a given PCI region
++pci_resource_len() Returns the byte length of a PCI region
++pci_set_drvdata() Set private driver data pointer for a pci_dev
++pci_get_drvdata() Return private driver data pointer for a pci_dev
++pci_set_mwi() Enable Memory-Write-Invalidate transactions.
++pci_clear_mwi() Disable Memory-Write-Invalidate transactions.
++
++
++
++7. Miscellaneous hints
++~~~~~~~~~~~~~~~~~~~~~~
++
++When displaying PCI device names to the user (for example when a driver wants
++to tell the user what card has it found), please use pci_name(pci_dev).
++
++Always refer to the PCI devices by a pointer to the pci_dev structure.
++All PCI layer functions use this identification and it's the only
++reasonable one. Don't use bus/slot/function numbers except for very
++special purposes -- on systems with multiple primary buses their semantics
++can be pretty complex.
++
++Don't try to turn on Fast Back to Back writes in your driver. All devices
++on the bus need to be capable of doing it, so this is something which needs
++to be handled by platform and generic code, not individual drivers.
++
++
++
++8. Vendor and device identifications
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++One is not not required to add new device ids to include/linux/pci_ids.h.
++Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids.
++
++PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary
++hex numbers (vendor controlled) and normally used only in a single
++location, the pci_device_id table.
++
++Please DO submit new vendor/device ids to pciids.sourceforge.net project.
++
++
++
++9. Obsolete functions
++~~~~~~~~~~~~~~~~~~~~~
++
++There are several functions which you might come across when trying to
++port an old driver to the new PCI interface. They are no longer present
++in the kernel as they aren't compatible with hotplug or PCI domains or
++having sane locking.
++
++pci_find_device() Superseded by pci_get_device()
++pci_find_subsys() Superseded by pci_get_subsys()
++pci_find_slot() Superseded by pci_get_slot()
++
++
++The alternative is the traditional PCI device driver that walks PCI
++device lists. This is still possible but discouraged.
++
++
++
++10. MMIO Space and "Write Posting"
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++Converting a driver from using I/O Port space to using MMIO space
++often requires some additional changes. Specifically, "write posting"
++needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2)
++already do this. I/O Port space guarantees write transactions reach the PCI
++device before the CPU can continue. Writes to MMIO space allow the CPU
++to continue before the transaction reaches the PCI device. HW weenies
++call this "Write Posting" because the write completion is "posted" to
++the CPU before the transaction has reached its destination.
++
++Thus, timing sensitive code should add readl() where the CPU is
++expected to wait before doing other work. The classic "bit banging"
++sequence works fine for I/O Port space:
++
++ for (i = 8; --i; val >>= 1) {
++ outb(val & 1, ioport_reg); /* write bit */
++ udelay(10);
++ }
++
++The same sequence for MMIO space should be:
++
++ for (i = 8; --i; val >>= 1) {
++ writeb(val & 1, mmio_reg); /* write bit */
++ readb(safe_mmio_reg); /* flush posted write */
++ udelay(10);
++ }
++
++It is important that "safe_mmio_reg" not have any side effects that
++interferes with the correct operation of the device.
++
++Another case to watch out for is when resetting a PCI device. Use PCI
++Configuration space reads to flush the writel(). This will gracefully
++handle the PCI master abort on all platforms if the PCI device is
++expected to not respond to a readl(). Most x86 platforms will allow
++MMIO reads to master abort (a.k.a. "Soft Fail") and return garbage
++(e.g. ~0). But many RISC platforms will crash (a.k.a."Hard Fail").
++
+--- /dev/null
++++ b/Documentation/PCI/pcieaer-howto.txt
+@@ -0,0 +1,253 @@
++ The PCI Express Advanced Error Reporting Driver Guide HOWTO
++ T. Long Nguyen <tom.l.nguyen@intel.com>
++ Yanmin Zhang <yanmin.zhang@intel.com>
++ 07/29/2006
++
++
++1. Overview
++
++1.1 About this guide
++
++This guide describes the basics of the PCI Express Advanced Error
++Reporting (AER) driver and provides information on how to use it, as
++well as how to enable the drivers of endpoint devices to conform with
++PCI Express AER driver.
++
++1.2 Copyright � Intel Corporation 2006.
++
++1.3 What is the PCI Express AER Driver?
++
++PCI Express error signaling can occur on the PCI Express link itself
++or on behalf of transactions initiated on the link. PCI Express
++defines two error reporting paradigms: the baseline capability and
++the Advanced Error Reporting capability. The baseline capability is
++required of all PCI Express components providing a minimum defined
++set of error reporting requirements. Advanced Error Reporting
++capability is implemented with a PCI Express advanced error reporting
++extended capability structure providing more robust error reporting.
++
++The PCI Express AER driver provides the infrastructure to support PCI
++Express Advanced Error Reporting capability. The PCI Express AER
++driver provides three basic functions:
++
++- Gathers the comprehensive error information if errors occurred.
++- Reports error to the users.
++- Performs error recovery actions.
++
++AER driver only attaches root ports which support PCI-Express AER
++capability.
++
++
++2. User Guide
++
++2.1 Include the PCI Express AER Root Driver into the Linux Kernel
++
++The PCI Express AER Root driver is a Root Port service driver attached
++to the PCI Express Port Bus driver. If a user wants to use it, the driver
++has to be compiled. Option CONFIG_PCIEAER supports this capability. It
++depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and
++CONFIG_PCIEAER = y.
++
++2.2 Load PCI Express AER Root Driver
++There is a case where a system has AER support in BIOS. Enabling the AER
++Root driver and having AER support in BIOS may result unpredictable
++behavior. To avoid this conflict, a successful load of the AER Root driver
++requires ACPI _OSC support in the BIOS to allow the AER Root driver to
++request for native control of AER. See the PCI FW 3.0 Specification for
++details regarding OSC usage. Currently, lots of firmwares don't provide
++_OSC support while they use PCI Express. To support such firmwares,
++forceload, a parameter of type bool, could enable AER to continue to
++be initiated although firmwares have no _OSC support. To enable the
++walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
++when booting kernel. Note that forceload=n by default.
++
++2.3 AER error output
++When a PCI-E AER error is captured, an error message will be outputed to
++console. If it's a correctable error, it is outputed as a warning.
++Otherwise, it is printed as an error. So users could choose different
++log level to filter out correctable error messages.
++
++Below shows an example.
+++------ PCI-Express Device Error -----+
++Error Severity : Uncorrected (Fatal)
++PCIE Bus Error type : Transaction Layer
++Unsupported Request : First
++Requester ID : 0500
++VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h
++TLB Header:
++04000001 00200a03 05010000 00050100
++
++In the example, 'Requester ID' means the ID of the device who sends
++the error message to root port. Pls. refer to pci express specs for
++other fields.
++
++
++3. Developer Guide
++
++To enable AER aware support requires a software driver to configure
++the AER capability structure within its device and to provide callbacks.
++
++To support AER better, developers need understand how AER does work
++firstly.
++
++PCI Express errors are classified into two types: correctable errors
++and uncorrectable errors. This classification is based on the impacts
++of those errors, which may result in degraded performance or function
++failure.
++
++Correctable errors pose no impacts on the functionality of the
++interface. The PCI Express protocol can recover without any software
++intervention or any loss of data. These errors are detected and
++corrected by hardware. Unlike correctable errors, uncorrectable
++errors impact functionality of the interface. Uncorrectable errors
++can cause a particular transaction or a particular PCI Express link
++to be unreliable. Depending on those error conditions, uncorrectable
++errors are further classified into non-fatal errors and fatal errors.
++Non-fatal errors cause the particular transaction to be unreliable,
++but the PCI Express link itself is fully functional. Fatal errors, on
++the other hand, cause the link to be unreliable.
++
++When AER is enabled, a PCI Express device will automatically send an
++error message to the PCIE root port above it when the device captures
++an error. The Root Port, upon receiving an error reporting message,
++internally processes and logs the error message in its PCI Express
++capability structure. Error information being logged includes storing
++the error reporting agent's requestor ID into the Error Source
++Identification Registers and setting the error bits of the Root Error
++Status Register accordingly. If AER error reporting is enabled in Root
++Error Command Register, the Root Port generates an interrupt if an
++error is detected.
++
++Note that the errors as described above are related to the PCI Express
++hierarchy and links. These errors do not include any device specific
++errors because device specific errors will still get sent directly to
++the device driver.
++
++3.1 Configure the AER capability structure
++
++AER aware drivers of PCI Express component need change the device
++control registers to enable AER. They also could change AER registers,
++including mask and severity registers. Helper function
++pci_enable_pcie_error_reporting could be used to enable AER. See
++section 3.3.
++
++3.2. Provide callbacks
++
++3.2.1 callback reset_link to reset pci express link
++
++This callback is used to reset the pci express physical link when a
++fatal error happens. The root port aer service driver provides a
++default reset_link function, but different upstream ports might
++have different specifications to reset pci express link, so all
++upstream ports should provide their own reset_link functions.
++
++In struct pcie_port_service_driver, a new pointer, reset_link, is
++added.
++
++pci_ers_result_t (*reset_link) (struct pci_dev *dev);
++
++Section 3.2.2.2 provides more detailed info on when to call
++reset_link.
++
++3.2.2 PCI error-recovery callbacks
++
++The PCI Express AER Root driver uses error callbacks to coordinate
++with downstream device drivers associated with a hierarchy in question
++when performing error recovery actions.
++
++Data struct pci_driver has a pointer, err_handler, to point to
++pci_error_handlers who consists of a couple of callback function
++pointers. AER driver follows the rules defined in
++pci-error-recovery.txt except pci express specific parts (e.g.
++reset_link). Pls. refer to pci-error-recovery.txt for detailed
++definitions of the callbacks.
++
++Below sections specify when to call the error callback functions.
++
++3.2.2.1 Correctable errors
++
++Correctable errors pose no impacts on the functionality of
++the interface. The PCI Express protocol can recover without any
++software intervention or any loss of data. These errors do not
++require any recovery actions. The AER driver clears the device's
++correctable error status register accordingly and logs these errors.
++
++3.2.2.2 Non-correctable (non-fatal and fatal) errors
++
++If an error message indicates a non-fatal error, performing link reset
++at upstream is not required. The AER driver calls error_detected(dev,
++pci_channel_io_normal) to all drivers associated within a hierarchy in
++question. for example,
++EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort.
++If Upstream port A captures an AER error, the hierarchy consists of
++Downstream port B and EndPoint.
++
++A driver may return PCI_ERS_RESULT_CAN_RECOVER,
++PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on
++whether it can recover or the AER driver calls mmio_enabled as next.
++
++If an error message indicates a fatal error, kernel will broadcast
++error_detected(dev, pci_channel_io_frozen) to all drivers within
++a hierarchy in question. Then, performing link reset at upstream is
++necessary. As different kinds of devices might use different approaches
++to reset link, AER port service driver is required to provide the
++function to reset link. Firstly, kernel looks for if the upstream
++component has an aer driver. If it has, kernel uses the reset_link
++callback of the aer driver. If the upstream component has no aer driver
++and the port is downstream port, we will use the aer driver of the
++root port who reports the AER error. As for upstream ports,
++they should provide their own aer service drivers with reset_link
++function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and
++reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
++to mmio_enabled.
++
++3.3 helper functions
++
++3.3.1 int pci_find_aer_capability(struct pci_dev *dev);
++pci_find_aer_capability locates the PCI Express AER capability
++in the device configuration space. If the device doesn't support
++PCI-Express AER, the function returns 0.
++
++3.3.2 int pci_enable_pcie_error_reporting(struct pci_dev *dev);
++pci_enable_pcie_error_reporting enables the device to send error
++messages to root port when an error is detected. Note that devices
++don't enable the error reporting by default, so device drivers need
++call this function to enable it.
++
++3.3.3 int pci_disable_pcie_error_reporting(struct pci_dev *dev);
++pci_disable_pcie_error_reporting disables the device to send error
++messages to root port when an error is detected.
++
++3.3.4 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
++pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable
++error status register.
++
++3.4 Frequent Asked Questions
++
++Q: What happens if a PCI Express device driver does not provide an
++error recovery handler (pci_driver->err_handler is equal to NULL)?
++
++A: The devices attached with the driver won't be recovered. If the
++error is fatal, kernel will print out warning messages. Please refer
++to section 3 for more information.
++
++Q: What happens if an upstream port service driver does not provide
++callback reset_link?
++
++A: Fatal error recovery will fail if the errors are reported by the
++upstream ports who are attached by the service driver.
++
++Q: How does this infrastructure deal with driver that is not PCI
++Express aware?
++
++A: This infrastructure calls the error callback functions of the
++driver when an error happens. But if the driver is not aware of
++PCI Express, the device might not report its own errors to root
++port.
++
++Q: What modifications will that driver need to make it compatible
++with the PCI Express AER Root driver?
++
++A: It could call the helper functions to enable AER in devices and
++cleanup uncorrectable status register. Pls. refer to section 3.3.
++
+--- a/Documentation/PCIEBUS-HOWTO.txt
++++ /dev/null
+@@ -1,217 +0,0 @@
+- The PCI Express Port Bus Driver Guide HOWTO
+- Tom L Nguyen tom.l.nguyen@intel.com
+- 11/03/2004
+-
+-1. About this guide
+-
+-This guide describes the basics of the PCI Express Port Bus driver
+-and provides information on how to enable the service drivers to
+-register/unregister with the PCI Express Port Bus Driver.
+-
+-2. Copyright 2004 Intel Corporation
+-
+-3. What is the PCI Express Port Bus Driver
+-
+-A PCI Express Port is a logical PCI-PCI Bridge structure. There
+-are two types of PCI Express Port: the Root Port and the Switch
+-Port. The Root Port originates a PCI Express link from a PCI Express
+-Root Complex and the Switch Port connects PCI Express links to
+-internal logical PCI buses. The Switch Port, which has its secondary
+-bus representing the switch's internal routing logic, is called the
+-switch's Upstream Port. The switch's Downstream Port is bridging from
+-switch's internal routing bus to a bus representing the downstream
+-PCI Express link from the PCI Express Switch.
+-
+-A PCI Express Port can provide up to four distinct functions,
+-referred to in this document as services, depending on its port type.
+-PCI Express Port's services include native hotplug support (HP),
+-power management event support (PME), advanced error reporting
+-support (AER), and virtual channel support (VC). These services may
+-be handled by a single complex driver or be individually distributed
+-and handled by corresponding service drivers.
+-
+-4. Why use the PCI Express Port Bus Driver?
+-
+-In existing Linux kernels, the Linux Device Driver Model allows a
+-physical device to be handled by only a single driver. The PCI
+-Express Port is a PCI-PCI Bridge device with multiple distinct
+-services. To maintain a clean and simple solution each service
+-may have its own software service driver. In this case several
+-service drivers will compete for a single PCI-PCI Bridge device.
+-For example, if the PCI Express Root Port native hotplug service
+-driver is loaded first, it claims a PCI-PCI Bridge Root Port. The
+-kernel therefore does not load other service drivers for that Root
+-Port. In other words, it is impossible to have multiple service
+-drivers load and run on a PCI-PCI Bridge device simultaneously
+-using the current driver model.
+-
+-To enable multiple service drivers running simultaneously requires
+-having a PCI Express Port Bus driver, which manages all populated
+-PCI Express Ports and distributes all provided service requests
+-to the corresponding service drivers as required. Some key
+-advantages of using the PCI Express Port Bus driver are listed below:
+-
+- - Allow multiple service drivers to run simultaneously on
+- a PCI-PCI Bridge Port device.
+-
+- - Allow service drivers implemented in an independent
+- staged approach.
+-
+- - Allow one service driver to run on multiple PCI-PCI Bridge
+- Port devices.
+-
+- - Manage and distribute resources of a PCI-PCI Bridge Port
+- device to requested service drivers.
+-
+-5. Configuring the PCI Express Port Bus Driver vs. Service Drivers
+-
+-5.1 Including the PCI Express Port Bus Driver Support into the Kernel
+-
+-Including the PCI Express Port Bus driver depends on whether the PCI
+-Express support is included in the kernel config. The kernel will
+-automatically include the PCI Express Port Bus driver as a kernel
+-driver when the PCI Express support is enabled in the kernel.
+-
+-5.2 Enabling Service Driver Support
+-
+-PCI device drivers are implemented based on Linux Device Driver Model.
+-All service drivers are PCI device drivers. As discussed above, it is
+-impossible to load any service driver once the kernel has loaded the
+-PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver
+-Model requires some minimal changes on existing service drivers that
+-imposes no impact on the functionality of existing service drivers.
+-
+-A service driver is required to use the two APIs shown below to
+-register its service with the PCI Express Port Bus driver (see
+-section 5.2.1 & 5.2.2). It is important that a service driver
+-initializes the pcie_port_service_driver data structure, included in
+-header file /include/linux/pcieport_if.h, before calling these APIs.
+-Failure to do so will result an identity mismatch, which prevents
+-the PCI Express Port Bus driver from loading a service driver.
+-
+-5.2.1 pcie_port_service_register
+-
+-int pcie_port_service_register(struct pcie_port_service_driver *new)
+-
+-This API replaces the Linux Driver Model's pci_module_init API. A
+-service driver should always calls pcie_port_service_register at
+-module init. Note that after service driver being loaded, calls
+-such as pci_enable_device(dev) and pci_set_master(dev) are no longer
+-necessary since these calls are executed by the PCI Port Bus driver.
+-
+-5.2.2 pcie_port_service_unregister
+-
+-void pcie_port_service_unregister(struct pcie_port_service_driver *new)
+-
+-pcie_port_service_unregister replaces the Linux Driver Model's
+-pci_unregister_driver. It's always called by service driver when a
+-module exits.
+-
+-5.2.3 Sample Code
+-
+-Below is sample service driver code to initialize the port service
+-driver data structure.
+-
+-static struct pcie_port_service_id service_id[] = { {
+- .vendor = PCI_ANY_ID,
+- .device = PCI_ANY_ID,
+- .port_type = PCIE_RC_PORT,
+- .service_type = PCIE_PORT_SERVICE_AER,
+- }, { /* end: all zeroes */ }
+-};
+-
+-static struct pcie_port_service_driver root_aerdrv = {
+- .name = (char *)device_name,
+- .id_table = &service_id[0],
+-
+- .probe = aerdrv_load,
+- .remove = aerdrv_unload,
+-
+- .suspend = aerdrv_suspend,
+- .resume = aerdrv_resume,
+-};
+-
+-Below is a sample code for registering/unregistering a service
+-driver.
+-
+-static int __init aerdrv_service_init(void)
+-{
+- int retval = 0;
+-
+- retval = pcie_port_service_register(&root_aerdrv);
+- if (!retval) {
+- /*
+- * FIX ME
+- */
+- }
+- return retval;
+-}
+-
+-static void __exit aerdrv_service_exit(void)
+-{
+- pcie_port_service_unregister(&root_aerdrv);
+-}
+-
+-module_init(aerdrv_service_init);
+-module_exit(aerdrv_service_exit);
+-
+-6. Possible Resource Conflicts
+-
+-Since all service drivers of a PCI-PCI Bridge Port device are
+-allowed to run simultaneously, below lists a few of possible resource
+-conflicts with proposed solutions.
+-
+-6.1 MSI Vector Resource
+-
+-The MSI capability structure enables a device software driver to call
+-pci_enable_msi to request MSI based interrupts. Once MSI interrupts
+-are enabled on a device, it stays in this mode until a device driver
+-calls pci_disable_msi to disable MSI interrupts and revert back to
+-INTx emulation mode. Since service drivers of the same PCI-PCI Bridge
+-port share the same physical device, if an individual service driver
+-calls pci_enable_msi/pci_disable_msi it may result unpredictable
+-behavior. For example, two service drivers run simultaneously on the
+-same physical Root Port. Both service drivers call pci_enable_msi to
+-request MSI based interrupts. A service driver may not know whether
+-any other service drivers have run on this Root Port. If either one
+-of them calls pci_disable_msi, it puts the other service driver
+-in a wrong interrupt mode.
+-
+-To avoid this situation all service drivers are not permitted to
+-switch interrupt mode on its device. The PCI Express Port Bus driver
+-is responsible for determining the interrupt mode and this should be
+-transparent to service drivers. Service drivers need to know only
+-the vector IRQ assigned to the field irq of struct pcie_device, which
+-is passed in when the PCI Express Port Bus driver probes each service
+-driver. Service drivers should use (struct pcie_device*)dev->irq to
+-call request_irq/free_irq. In addition, the interrupt mode is stored
+-in the field interrupt_mode of struct pcie_device.
+-
+-6.2 MSI-X Vector Resources
+-
+-Similar to the MSI a device driver for an MSI-X capable device can
+-call pci_enable_msix to request MSI-X interrupts. All service drivers
+-are not permitted to switch interrupt mode on its device. The PCI
+-Express Port Bus driver is responsible for determining the interrupt
+-mode and this should be transparent to service drivers. Any attempt
+-by service driver to call pci_enable_msix/pci_disable_msix may
+-result unpredictable behavior. Service drivers should use
+-(struct pcie_device*)dev->irq and call request_irq/free_irq.
+-
+-6.3 PCI Memory/IO Mapped Regions
+-
+-Service drivers for PCI Express Power Management (PME), Advanced
+-Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access
+-PCI configuration space on the PCI Express port. In all cases the
+-registers accessed are independent of each other. This patch assumes
+-that all service drivers will be well behaved and not overwrite
+-other service driver's configuration settings.
+-
+-6.4 PCI Config Registers
+-
+-Each service driver runs its PCI config operations on its own
+-capability structure except the PCI Express capability structure, in
+-which Root Control register and Device Control register are shared
+-between PME and AER. This patch assumes that all service drivers
+-will be well behaved and not overwrite other service driver's
+-configuration settings.
+--- a/Documentation/memory-barriers.txt
++++ b/Documentation/memory-barriers.txt
+@@ -430,8 +430,8 @@ There are certain things that the Linux
+
+ [*] For information on bus mastering DMA and coherency please read:
+
+- Documentation/pci.txt
+- Documentation/DMA-mapping.txt
++ Documentation/PCI/pci.txt
++ Documentation/PCI/PCI-DMA-mapping.txt
+ Documentation/DMA-API.txt
+
+
+--- a/Documentation/pci-error-recovery.txt
++++ /dev/null
+@@ -1,396 +0,0 @@
+-
+- PCI Error Recovery
+- ------------------
+- February 2, 2006
+-
+- Current document maintainer:
+- Linas Vepstas <linas@austin.ibm.com>
+-
+-
+-Many PCI bus controllers are able to detect a variety of hardware
+-PCI errors on the bus, such as parity errors on the data and address
+-busses, as well as SERR and PERR errors. Some of the more advanced
+-chipsets are able to deal with these errors; these include PCI-E chipsets,
+-and the PCI-host bridges found on IBM Power4 and Power5-based pSeries
+-boxes. A typical action taken is to disconnect the affected device,
+-halting all I/O to it. The goal of a disconnection is to avoid system
+-corruption; for example, to halt system memory corruption due to DMA's
+-to "wild" addresses. Typically, a reconnection mechanism is also
+-offered, so that the affected PCI device(s) are reset and put back
+-into working condition. The reset phase requires coordination
+-between the affected device drivers and the PCI controller chip.
+-This document describes a generic API for notifying device drivers
+-of a bus disconnection, and then performing error recovery.
+-This API is currently implemented in the 2.6.16 and later kernels.
+-
+-Reporting and recovery is performed in several steps. First, when
+-a PCI hardware error has resulted in a bus disconnect, that event
+-is reported as soon as possible to all affected device drivers,
+-including multiple instances of a device driver on multi-function
+-cards. This allows device drivers to avoid deadlocking in spinloops,
+-waiting for some i/o-space register to change, when it never will.
+-It also gives the drivers a chance to defer incoming I/O as
+-needed.
+-
+-Next, recovery is performed in several stages. Most of the complexity
+-is forced by the need to handle multi-function devices, that is,
+-devices that have multiple device drivers associated with them.
+-In the first stage, each driver is allowed to indicate what type
+-of reset it desires, the choices being a simple re-enabling of I/O
+-or requesting a hard reset (a full electrical #RST of the PCI card).
+-If any driver requests a full reset, that is what will be done.
+-
+-After a full reset and/or a re-enabling of I/O, all drivers are
+-again notified, so that they may then perform any device setup/config
+-that may be required. After these have all completed, a final
+-"resume normal operations" event is sent out.
+-
+-The biggest reason for choosing a kernel-based implementation rather
+-than a user-space implementation was the need to deal with bus
+-disconnects of PCI devices attached to storage media, and, in particular,
+-disconnects from devices holding the root file system. If the root
+-file system is disconnected, a user-space mechanism would have to go
+-through a large number of contortions to complete recovery. Almost all
+-of the current Linux file systems are not tolerant of disconnection
+-from/reconnection to their underlying block device. By contrast,
+-bus errors are easy to manage in the device driver. Indeed, most
+-device drivers already handle very similar recovery procedures;
+-for example, the SCSI-generic layer already provides significant
+-mechanisms for dealing with SCSI bus errors and SCSI bus resets.
+-
+-
+-Detailed Design
+----------------
+-Design and implementation details below, based on a chain of
+-public email discussions with Ben Herrenschmidt, circa 5 April 2005.
+-
+-The error recovery API support is exposed to the driver in the form of
+-a structure of function pointers pointed to by a new field in struct
+-pci_driver. A driver that fails to provide the structure is "non-aware",
+-and the actual recovery steps taken are platform dependent. The
+-arch/powerpc implementation will simulate a PCI hotplug remove/add.
+-
+-This structure has the form:
+-struct pci_error_handlers
+-{
+- int (*error_detected)(struct pci_dev *dev, enum pci_channel_state);
+- int (*mmio_enabled)(struct pci_dev *dev);
+- int (*link_reset)(struct pci_dev *dev);
+- int (*slot_reset)(struct pci_dev *dev);
+- void (*resume)(struct pci_dev *dev);
+-};
+-
+-The possible channel states are:
+-enum pci_channel_state {
+- pci_channel_io_normal, /* I/O channel is in normal state */
+- pci_channel_io_frozen, /* I/O to channel is blocked */
+- pci_channel_io_perm_failure, /* PCI card is dead */
+-};
+-
+-Possible return values are:
+-enum pci_ers_result {
+- PCI_ERS_RESULT_NONE, /* no result/none/not supported in device driver */
+- PCI_ERS_RESULT_CAN_RECOVER, /* Device driver can recover without slot reset */
+- PCI_ERS_RESULT_NEED_RESET, /* Device driver wants slot to be reset. */
+- PCI_ERS_RESULT_DISCONNECT, /* Device has completely failed, is unrecoverable */
+- PCI_ERS_RESULT_RECOVERED, /* Device driver is fully recovered and operational */
+-};
+-
+-A driver does not have to implement all of these callbacks; however,
+-if it implements any, it must implement error_detected(). If a callback
+-is not implemented, the corresponding feature is considered unsupported.
+-For example, if mmio_enabled() and resume() aren't there, then it
+-is assumed that the driver is not doing any direct recovery and requires
+-a reset. If link_reset() is not implemented, the card is assumed as
+-not care about link resets. Typically a driver will want to know about
+-a slot_reset().
+-
+-The actual steps taken by a platform to recover from a PCI error
+-event will be platform-dependent, but will follow the general
+-sequence described below.
+-
+-STEP 0: Error Event
+--------------------
+-PCI bus error is detect by the PCI hardware. On powerpc, the slot
+-is isolated, in that all I/O is blocked: all reads return 0xffffffff,
+-all writes are ignored.
+-
+-
+-STEP 1: Notification
+---------------------
+-Platform calls the error_detected() callback on every instance of
+-every driver affected by the error.
+-
+-At this point, the device might not be accessible anymore, depending on
+-the platform (the slot will be isolated on powerpc). The driver may
+-already have "noticed" the error because of a failing I/O, but this
+-is the proper "synchronization point", that is, it gives the driver
+-a chance to cleanup, waiting for pending stuff (timers, whatever, etc...)
+-to complete; it can take semaphores, schedule, etc... everything but
+-touch the device. Within this function and after it returns, the driver
+-shouldn't do any new IOs. Called in task context. This is sort of a
+-"quiesce" point. See note about interrupts at the end of this doc.
+-
+-All drivers participating in this system must implement this call.
+-The driver must return one of the following result codes:
+- - PCI_ERS_RESULT_CAN_RECOVER:
+- Driver returns this if it thinks it might be able to recover
+- the HW by just banging IOs or if it wants to be given
+- a chance to extract some diagnostic information (see
+- mmio_enable, below).
+- - PCI_ERS_RESULT_NEED_RESET:
+- Driver returns this if it can't recover without a hard
+- slot reset.
+- - PCI_ERS_RESULT_DISCONNECT:
+- Driver returns this if it doesn't want to recover at all.
+-
+-The next step taken will depend on the result codes returned by the
+-drivers.
+-
+-If all drivers on the segment/slot return PCI_ERS_RESULT_CAN_RECOVER,
+-then the platform should re-enable IOs on the slot (or do nothing in
+-particular, if the platform doesn't isolate slots), and recovery
+-proceeds to STEP 2 (MMIO Enable).
+-
+-If any driver requested a slot reset (by returning PCI_ERS_RESULT_NEED_RESET),
+-then recovery proceeds to STEP 4 (Slot Reset).
+-
+-If the platform is unable to recover the slot, the next step
+-is STEP 6 (Permanent Failure).
+-
+->>> The current powerpc implementation assumes that a device driver will
+->>> *not* schedule or semaphore in this routine; the current powerpc
+->>> implementation uses one kernel thread to notify all devices;
+->>> thus, if one device sleeps/schedules, all devices are affected.
+->>> Doing better requires complex multi-threaded logic in the error
+->>> recovery implementation (e.g. waiting for all notification threads
+->>> to "join" before proceeding with recovery.) This seems excessively
+->>> complex and not worth implementing.
+-
+->>> The current powerpc implementation doesn't much care if the device
+->>> attempts I/O at this point, or not. I/O's will fail, returning
+->>> a value of 0xff on read, and writes will be dropped. If the device
+->>> driver attempts more than 10K I/O's to a frozen adapter, it will
+->>> assume that the device driver has gone into an infinite loop, and
+->>> it will panic the kernel. There doesn't seem to be any other
+->>> way of stopping a device driver that insists on spinning on I/O.
+-
+-STEP 2: MMIO Enabled
+--------------------
+-The platform re-enables MMIO to the device (but typically not the
+-DMA), and then calls the mmio_enabled() callback on all affected
+-device drivers.
+-
+-This is the "early recovery" call. IOs are allowed again, but DMA is
+-not (hrm... to be discussed, I prefer not), with some restrictions. This
+-is NOT a callback for the driver to start operations again, only to
+-peek/poke at the device, extract diagnostic information, if any, and
+-eventually do things like trigger a device local reset or some such,
+-but not restart operations. This is callback is made if all drivers on
+-a segment agree that they can try to recover and if no automatic link reset
+-was performed by the HW. If the platform can't just re-enable IOs without
+-a slot reset or a link reset, it wont call this callback, and instead
+-will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
+-
+->>> The following is proposed; no platform implements this yet:
+->>> Proposal: All I/O's should be done _synchronously_ from within
+->>> this callback, errors triggered by them will be returned via
+->>> the normal pci_check_whatever() API, no new error_detected()
+->>> callback will be issued due to an error happening here. However,
+->>> such an error might cause IOs to be re-blocked for the whole
+->>> segment, and thus invalidate the recovery that other devices
+->>> on the same segment might have done, forcing the whole segment
+->>> into one of the next states, that is, link reset or slot reset.
+-
+-The driver should return one of the following result codes:
+- - PCI_ERS_RESULT_RECOVERED
+- Driver returns this if it thinks the device is fully
+- functional and thinks it is ready to start
+- normal driver operations again. There is no
+- guarantee that the driver will actually be
+- allowed to proceed, as another driver on the
+- same segment might have failed and thus triggered a
+- slot reset on platforms that support it.
+-
+- - PCI_ERS_RESULT_NEED_RESET
+- Driver returns this if it thinks the device is not
+- recoverable in it's current state and it needs a slot
+- reset to proceed.
+-
+- - PCI_ERS_RESULT_DISCONNECT
+- Same as above. Total failure, no recovery even after
+- reset driver dead. (To be defined more precisely)
+-
+-The next step taken depends on the results returned by the drivers.
+-If all drivers returned PCI_ERS_RESULT_RECOVERED, then the platform
+-proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations).
+-
+-If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform
+-proceeds to STEP 4 (Slot Reset)
+-
+->>> The current powerpc implementation does not implement this callback.
+-
+-
+-STEP 3: Link Reset
+-------------------
+-The platform resets the link, and then calls the link_reset() callback
+-on all affected device drivers. This is a PCI-Express specific state
+-and is done whenever a non-fatal error has been detected that can be
+-"solved" by resetting the link. This call informs the driver of the
+-reset and the driver should check to see if the device appears to be
+-in working condition.
+-
+-The driver is not supposed to restart normal driver I/O operations
+-at this point. It should limit itself to "probing" the device to
+-check it's recoverability status. If all is right, then the platform
+-will call resume() once all drivers have ack'd link_reset().
+-
+- Result codes:
+- (identical to STEP 3 (MMIO Enabled)
+-
+-The platform then proceeds to either STEP 4 (Slot Reset) or STEP 5
+-(Resume Operations).
+-
+->>> The current powerpc implementation does not implement this callback.
+-
+-
+-STEP 4: Slot Reset
+-------------------
+-The platform performs a soft or hard reset of the device, and then
+-calls the slot_reset() callback.
+-
+-A soft reset consists of asserting the adapter #RST line and then
+-restoring the PCI BAR's and PCI configuration header to a state
+-that is equivalent to what it would be after a fresh system
+-power-on followed by power-on BIOS/system firmware initialization.
+-If the platform supports PCI hotplug, then the reset might be
+-performed by toggling the slot electrical power off/on.
+-
+-It is important for the platform to restore the PCI config space
+-to the "fresh poweron" state, rather than the "last state". After
+-a slot reset, the device driver will almost always use its standard
+-device initialization routines, and an unusual config space setup
+-may result in hung devices, kernel panics, or silent data corruption.
+-
+-This call gives drivers the chance to re-initialize the hardware
+-(re-download firmware, etc.). At this point, the driver may assume
+-that he card is in a fresh state and is fully functional. In
+-particular, interrupt generation should work normally.
+-
+-Drivers should not yet restart normal I/O processing operations
+-at this point. If all device drivers report success on this
+-callback, the platform will call resume() to complete the sequence,
+-and let the driver restart normal I/O processing.
+-
+-A driver can still return a critical failure for this function if
+-it can't get the device operational after reset. If the platform
+-previously tried a soft reset, it might now try a hard reset (power
+-cycle) and then call slot_reset() again. It the device still can't
+-be recovered, there is nothing more that can be done; the platform
+-will typically report a "permanent failure" in such a case. The
+-device will be considered "dead" in this case.
+-
+-Drivers for multi-function cards will need to coordinate among
+-themselves as to which driver instance will perform any "one-shot"
+-or global device initialization. For example, the Symbios sym53cxx2
+-driver performs device init only from PCI function 0:
+-
+-+ if (PCI_FUNC(pdev->devfn) == 0)
+-+ sym_reset_scsi_bus(np, 0);
+-
+- Result codes:
+- - PCI_ERS_RESULT_DISCONNECT
+- Same as above.
+-
+-Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent
+-Failure).
+-
+->>> The current powerpc implementation does not currently try a
+->>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
+->>> However, it probably should.
+-
+-
+-STEP 5: Resume Operations
+--------------------------
+-The platform will call the resume() callback on all affected device
+-drivers if all drivers on the segment have returned
+-PCI_ERS_RESULT_RECOVERED from one of the 3 previous callbacks.
+-The goal of this callback is to tell the driver to restart activity,
+-that everything is back and running. This callback does not return
+-a result code.
+-
+-At this point, if a new error happens, the platform will restart
+-a new error recovery sequence.
+-
+-STEP 6: Permanent Failure
+--------------------------
+-A "permanent failure" has occurred, and the platform cannot recover
+-the device. The platform will call error_detected() with a
+-pci_channel_state value of pci_channel_io_perm_failure.
+-
+-The device driver should, at this point, assume the worst. It should
+-cancel all pending I/O, refuse all new I/O, returning -EIO to
+-higher layers. The device driver should then clean up all of its
+-memory and remove itself from kernel operations, much as it would
+-during system shutdown.
+-
+-The platform will typically notify the system operator of the
+-permanent failure in some way. If the device is hotplug-capable,
+-the operator will probably want to remove and replace the device.
+-Note, however, not all failures are truly "permanent". Some are
+-caused by over-heating, some by a poorly seated card. Many
+-PCI error events are caused by software bugs, e.g. DMA's to
+-wild addresses or bogus split transactions due to programming
+-errors. See the discussion in powerpc/eeh-pci-error-recovery.txt
+-for additional detail on real-life experience of the causes of
+-software errors.
+-
+-
+-Conclusion; General Remarks
+----------------------------
+-The way those callbacks are called is platform policy. A platform with
+-no slot reset capability may want to just "ignore" drivers that can't
+-recover (disconnect them) and try to let other cards on the same segment
+-recover. Keep in mind that in most real life cases, though, there will
+-be only one driver per segment.
+-
+-Now, a note about interrupts. If you get an interrupt and your
+-device is dead or has been isolated, there is a problem :)
+-The current policy is to turn this into a platform policy.
+-That is, the recovery API only requires that:
+-
+- - There is no guarantee that interrupt delivery can proceed from any
+-device on the segment starting from the error detection and until the
+-resume callback is sent, at which point interrupts are expected to be
+-fully operational.
+-
+- - There is no guarantee that interrupt delivery is stopped, that is,
+-a driver that gets an interrupt after detecting an error, or that detects
+-an error within the interrupt handler such that it prevents proper
+-ack'ing of the interrupt (and thus removal of the source) should just
+-return IRQ_NOTHANDLED. It's up to the platform to deal with that
+-condition, typically by masking the IRQ source during the duration of
+-the error handling. It is expected that the platform "knows" which
+-interrupts are routed to error-management capable slots and can deal
+-with temporarily disabling that IRQ number during error processing (this
+-isn't terribly complex). That means some IRQ latency for other devices
+-sharing the interrupt, but there is simply no other way. High end
+-platforms aren't supposed to share interrupts between many devices
+-anyway :)
+-
+->>> Implementation details for the powerpc platform are discussed in
+->>> the file Documentation/powerpc/eeh-pci-error-recovery.txt
+-
+->>> As of this writing, there are six device drivers with patches
+->>> implementing error recovery. Not all of these patches are in
+->>> mainline yet. These may be used as "examples":
+->>>
+->>> drivers/scsi/ipr.c
+->>> drivers/scsi/sym53cxx_2
+->>> drivers/next/e100.c
+->>> drivers/net/e1000
+->>> drivers/net/ixgb
+->>> drivers/net/s2io.c
+-
+-The End
+--------
+--- a/Documentation/pci.txt
++++ /dev/null
+@@ -1,646 +0,0 @@
+-
+- How To Write Linux PCI Drivers
+-
+- by Martin Mares <mj@ucw.cz> on 07-Feb-2000
+- updated by Grant Grundler <grundler@parisc-linux.org> on 23-Dec-2006
+-
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-The world of PCI is vast and full of (mostly unpleasant) surprises.
+-Since each CPU architecture implements different chip-sets and PCI devices
+-have different requirements (erm, "features"), the result is the PCI support
+-in the Linux kernel is not as trivial as one would wish. This short paper
+-tries to introduce all potential driver authors to Linux APIs for
+-PCI device drivers.
+-
+-A more complete resource is the third edition of "Linux Device Drivers"
+-by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman.
+-LDD3 is available for free (under Creative Commons License) from:
+-
+- http://lwn.net/Kernel/LDD3/
+-
+-However, keep in mind that all documents are subject to "bit rot".
+-Refer to the source code if things are not working as described here.
+-
+-Please send questions/comments/patches about Linux PCI API to the
+-"Linux PCI" <linux-pci@atrey.karlin.mff.cuni.cz> mailing list.
+-
+-
+-
+-0. Structure of PCI drivers
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-PCI drivers "discover" PCI devices in a system via pci_register_driver().
+-Actually, it's the other way around. When the PCI generic code discovers
+-a new device, the driver with a matching "description" will be notified.
+-Details on this below.
+-
+-pci_register_driver() leaves most of the probing for devices to
+-the PCI layer and supports online insertion/removal of devices [thus
+-supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver].
+-pci_register_driver() call requires passing in a table of function
+-pointers and thus dictates the high level structure of a driver.
+-
+-Once the driver knows about a PCI device and takes ownership, the
+-driver generally needs to perform the following initialization:
+-
+- Enable the device
+- Request MMIO/IOP resources
+- Set the DMA mask size (for both coherent and streaming DMA)
+- Allocate and initialize shared control data (pci_allocate_coherent())
+- Access device configuration space (if needed)
+- Register IRQ handler (request_irq())
+- Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
+- Enable DMA/processing engines
+-
+-When done using the device, and perhaps the module needs to be unloaded,
+-the driver needs to take the follow steps:
+- Disable the device from generating IRQs
+- Release the IRQ (free_irq())
+- Stop all DMA activity
+- Release DMA buffers (both streaming and coherent)
+- Unregister from other subsystems (e.g. scsi or netdev)
+- Release MMIO/IOP resources
+- Disable the device
+-
+-Most of these topics are covered in the following sections.
+-For the rest look at LDD3 or <linux/pci.h> .
+-
+-If the PCI subsystem is not configured (CONFIG_PCI is not set), most of
+-the PCI functions described below are defined as inline functions either
+-completely empty or just returning an appropriate error codes to avoid
+-lots of ifdefs in the drivers.
+-
+-
+-
+-1. pci_register_driver() call
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-PCI device drivers call pci_register_driver() during their
+-initialization with a pointer to a structure describing the driver
+-(struct pci_driver):
+-
+- field name Description
+- ---------- ------------------------------------------------------
+- id_table Pointer to table of device ID's the driver is
+- interested in. Most drivers should export this
+- table using MODULE_DEVICE_TABLE(pci,...).
+-
+- probe This probing function gets called (during execution
+- of pci_register_driver() for already existing
+- devices or later if a new device gets inserted) for
+- all PCI devices which match the ID table and are not
+- "owned" by the other drivers yet. This function gets
+- passed a "struct pci_dev *" for each device whose
+- entry in the ID table matches the device. The probe
+- function returns zero when the driver chooses to
+- take "ownership" of the device or an error code
+- (negative number) otherwise.
+- The probe function always gets called from process
+- context, so it can sleep.
+-
+- remove The remove() function gets called whenever a device
+- being handled by this driver is removed (either during
+- deregistration of the driver or when it's manually
+- pulled out of a hot-pluggable slot).
+- The remove function always gets called from process
+- context, so it can sleep.
+-
+- suspend Put device into low power state.
+- suspend_late Put device into low power state.
+-
+- resume_early Wake device from low power state.
+- resume Wake device from low power state.
+-
+- (Please see Documentation/power/pci.txt for descriptions
+- of PCI Power Management and the related functions.)
+-
+- shutdown Hook into reboot_notifier_list (kernel/sys.c).
+- Intended to stop any idling DMA operations.
+- Useful for enabling wake-on-lan (NIC) or changing
+- the power state of a device before reboot.
+- e.g. drivers/net/e100.c.
+-
+- err_handler See Documentation/pci-error-recovery.txt
+-
+-
+-The ID table is an array of struct pci_device_id entries ending with an
+-all-zero entry; use of the macro DEFINE_PCI_DEVICE_TABLE is the preferred
+-method of declaring the table. Each entry consists of:
+-
+- vendor,device Vendor and device ID to match (or PCI_ANY_ID)
+-
+- subvendor, Subsystem vendor and device ID to match (or PCI_ANY_ID)
+- subdevice,
+-
+- class Device class, subclass, and "interface" to match.
+- See Appendix D of the PCI Local Bus Spec or
+- include/linux/pci_ids.h for a full list of classes.
+- Most drivers do not need to specify class/class_mask
+- as vendor/device is normally sufficient.
+-
+- class_mask limit which sub-fields of the class field are compared.
+- See drivers/scsi/sym53c8xx_2/ for example of usage.
+-
+- driver_data Data private to the driver.
+- Most drivers don't need to use driver_data field.
+- Best practice is to use driver_data as an index
+- into a static list of equivalent device types,
+- instead of using it as a pointer.
+-
+-
+-Most drivers only need PCI_DEVICE() or PCI_DEVICE_CLASS() to set up
+-a pci_device_id table.
+-
+-New PCI IDs may be added to a device driver pci_ids table at runtime
+-as shown below:
+-
+-echo "vendor device subvendor subdevice class class_mask driver_data" > \
+-/sys/bus/pci/drivers/{driver}/new_id
+-
+-All fields are passed in as hexadecimal values (no leading 0x).
+-The vendor and device fields are mandatory, the others are optional. Users
+-need pass only as many optional fields as necessary:
+- o subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)
+- o class and classmask fields default to 0
+- o driver_data defaults to 0UL.
+-
+-Once added, the driver probe routine will be invoked for any unclaimed
+-PCI devices listed in its (newly updated) pci_ids list.
+-
+-When the driver exits, it just calls pci_unregister_driver() and the PCI layer
+-automatically calls the remove hook for all devices handled by the driver.
+-
+-
+-1.1 "Attributes" for driver functions/data
+-
+-Please mark the initialization and cleanup functions where appropriate
+-(the corresponding macros are defined in <linux/init.h>):
+-
+- __init Initialization code. Thrown away after the driver
+- initializes.
+- __exit Exit code. Ignored for non-modular drivers.
+-
+-
+- __devinit Device initialization code.
+- Identical to __init if the kernel is not compiled
+- with CONFIG_HOTPLUG, normal function otherwise.
+- __devexit The same for __exit.
+-
+-Tips on when/where to use the above attributes:
+- o The module_init()/module_exit() functions (and all
+- initialization functions called _only_ from these)
+- should be marked __init/__exit.
+-
+- o Do not mark the struct pci_driver.
+-
+- o The ID table array should be marked __devinitconst; this is done
+- automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE().
+-
+- o The probe() and remove() functions should be marked __devinit
+- and __devexit respectively. All initialization functions
+- exclusively called by the probe() routine, can be marked __devinit.
+- Ditto for remove() and __devexit.
+-
+- o If mydriver_remove() is marked with __devexit(), then all address
+- references to mydriver_remove must use __devexit_p(mydriver_remove)
+- (in the struct pci_driver declaration for example).
+- __devexit_p() will generate the function name _or_ NULL if the
+- function will be discarded. For an example, see drivers/net/tg3.c.
+-
+- o Do NOT mark a function if you are not sure which mark to use.
+- Better to not mark the function than mark the function wrong.
+-
+-
+-
+-2. How to find PCI devices manually
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-PCI drivers should have a really good reason for not using the
+-pci_register_driver() interface to search for PCI devices.
+-The main reason PCI devices are controlled by multiple drivers
+-is because one PCI device implements several different HW services.
+-E.g. combined serial/parallel port/floppy controller.
+-
+-A manual search may be performed using the following constructs:
+-
+-Searching by vendor and device ID:
+-
+- struct pci_dev *dev = NULL;
+- while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev))
+- configure_device(dev);
+-
+-Searching by class ID (iterate in a similar way):
+-
+- pci_get_class(CLASS_ID, dev)
+-
+-Searching by both vendor/device and subsystem vendor/device ID:
+-
+- pci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
+-
+-You can use the constant PCI_ANY_ID as a wildcard replacement for
+-VENDOR_ID or DEVICE_ID. This allows searching for any device from a
+-specific vendor, for example.
+-
+-These functions are hotplug-safe. They increment the reference count on
+-the pci_dev that they return. You must eventually (possibly at module unload)
+-decrement the reference count on these devices by calling pci_dev_put().
+-
+-
+-
+-3. Device Initialization Steps
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-As noted in the introduction, most PCI drivers need the following steps
+-for device initialization:
+-
+- Enable the device
+- Request MMIO/IOP resources
+- Set the DMA mask size (for both coherent and streaming DMA)
+- Allocate and initialize shared control data (pci_allocate_coherent())
+- Access device configuration space (if needed)
+- Register IRQ handler (request_irq())
+- Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
+- Enable DMA/processing engines.
+-
+-The driver can access PCI config space registers at any time.
+-(Well, almost. When running BIST, config space can go away...but
+-that will just result in a PCI Bus Master Abort and config reads
+-will return garbage).
+-
+-
+-3.1 Enable the PCI device
+-~~~~~~~~~~~~~~~~~~~~~~~~~
+-Before touching any device registers, the driver needs to enable
+-the PCI device by calling pci_enable_device(). This will:
+- o wake up the device if it was in suspended state,
+- o allocate I/O and memory regions of the device (if BIOS did not),
+- o allocate an IRQ (if BIOS did not).
+-
+-NOTE: pci_enable_device() can fail! Check the return value.
+-
+-[ OS BUG: we don't check resource allocations before enabling those
+- resources. The sequence would make more sense if we called
+- pci_request_resources() before calling pci_enable_device().
+- Currently, the device drivers can't detect the bug when when two
+- devices have been allocated the same range. This is not a common
+- problem and unlikely to get fixed soon.
+-
+- This has been discussed before but not changed as of 2.6.19:
+- http://lkml.org/lkml/2006/3/2/194
+-]
+-
+-pci_set_master() will enable DMA by setting the bus master bit
+-in the PCI_COMMAND register. It also fixes the latency timer value if
+-it's set to something bogus by the BIOS.
+-
+-If the PCI device can use the PCI Memory-Write-Invalidate transaction,
+-call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval
+-and also ensures that the cache line size register is set correctly.
+-Check the return value of pci_set_mwi() as not all architectures
+-or chip-sets may support Memory-Write-Invalidate. Alternatively,
+-if Mem-Wr-Inval would be nice to have but is not required, call
+-pci_try_set_mwi() to have the system do its best effort at enabling
+-Mem-Wr-Inval.
+-
+-
+-3.2 Request MMIO/IOP resources
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Memory (MMIO), and I/O port addresses should NOT be read directly
+-from the PCI device config space. Use the values in the pci_dev structure
+-as the PCI "bus address" might have been remapped to a "host physical"
+-address by the arch/chip-set specific kernel support.
+-
+-See Documentation/IO-mapping.txt for how to access device registers
+-or device memory.
+-
+-The device driver needs to call pci_request_region() to verify
+-no other device is already using the same address resource.
+-Conversely, drivers should call pci_release_region() AFTER
+-calling pci_disable_device().
+-The idea is to prevent two devices colliding on the same address range.
+-
+-[ See OS BUG comment above. Currently (2.6.19), The driver can only
+- determine MMIO and IO Port resource availability _after_ calling
+- pci_enable_device(). ]
+-
+-Generic flavors of pci_request_region() are request_mem_region()
+-(for MMIO ranges) and request_region() (for IO Port ranges).
+-Use these for address resources that are not described by "normal" PCI
+-BARs.
+-
+-Also see pci_request_selected_regions() below.
+-
+-
+-3.3 Set the DMA mask size
+-~~~~~~~~~~~~~~~~~~~~~~~~~
+-[ If anything below doesn't make sense, please refer to
+- Documentation/DMA-API.txt. This section is just a reminder that
+- drivers need to indicate DMA capabilities of the device and is not
+- an authoritative source for DMA interfaces. ]
+-
+-While all drivers should explicitly indicate the DMA capability
+-(e.g. 32 or 64 bit) of the PCI bus master, devices with more than
+-32-bit bus master capability for streaming data need the driver
+-to "register" this capability by calling pci_set_dma_mask() with
+-appropriate parameters. In general this allows more efficient DMA
+-on systems where System RAM exists above 4G _physical_ address.
+-
+-Drivers for all PCI-X and PCIe compliant devices must call
+-pci_set_dma_mask() as they are 64-bit DMA devices.
+-
+-Similarly, drivers must also "register" this capability if the device
+-can directly address "consistent memory" in System RAM above 4G physical
+-address by calling pci_set_consistent_dma_mask().
+-Again, this includes drivers for all PCI-X and PCIe compliant devices.
+-Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are
+-64-bit DMA capable for payload ("streaming") data but not control
+-("consistent") data.
+-
+-
+-3.4 Setup shared control data
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Once the DMA masks are set, the driver can allocate "consistent" (a.k.a. shared)
+-memory. See Documentation/DMA-API.txt for a full description of
+-the DMA APIs. This section is just a reminder that it needs to be done
+-before enabling DMA on the device.
+-
+-
+-3.5 Initialize device registers
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Some drivers will need specific "capability" fields programmed
+-or other "vendor specific" register initialized or reset.
+-E.g. clearing pending interrupts.
+-
+-
+-3.6 Register IRQ handler
+-~~~~~~~~~~~~~~~~~~~~~~~~
+-While calling request_irq() is the last step described here,
+-this is often just another intermediate step to initialize a device.
+-This step can often be deferred until the device is opened for use.
+-
+-All interrupt handlers for IRQ lines should be registered with IRQF_SHARED
+-and use the devid to map IRQs to devices (remember that all PCI IRQ lines
+-can be shared).
+-
+-request_irq() will associate an interrupt handler and device handle
+-with an interrupt number. Historically interrupt numbers represent
+-IRQ lines which run from the PCI device to the Interrupt controller.
+-With MSI and MSI-X (more below) the interrupt number is a CPU "vector".
+-
+-request_irq() also enables the interrupt. Make sure the device is
+-quiesced and does not have any interrupts pending before registering
+-the interrupt handler.
+-
+-MSI and MSI-X are PCI capabilities. Both are "Message Signaled Interrupts"
+-which deliver interrupts to the CPU via a DMA write to a Local APIC.
+-The fundamental difference between MSI and MSI-X is how multiple
+-"vectors" get allocated. MSI requires contiguous blocks of vectors
+-while MSI-X can allocate several individual ones.
+-
+-MSI capability can be enabled by calling pci_enable_msi() or
+-pci_enable_msix() before calling request_irq(). This causes
+-the PCI support to program CPU vector data into the PCI device
+-capability registers.
+-
+-If your PCI device supports both, try to enable MSI-X first.
+-Only one can be enabled at a time. Many architectures, chip-sets,
+-or BIOSes do NOT support MSI or MSI-X and the call to pci_enable_msi/msix
+-will fail. This is important to note since many drivers have
+-two (or more) interrupt handlers: one for MSI/MSI-X and another for IRQs.
+-They choose which handler to register with request_irq() based on the
+-return value from pci_enable_msi/msix().
+-
+-There are (at least) two really good reasons for using MSI:
+-1) MSI is an exclusive interrupt vector by definition.
+- This means the interrupt handler doesn't have to verify
+- its device caused the interrupt.
+-
+-2) MSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed
+- to be visible to the host CPU(s) when the MSI is delivered. This
+- is important for both data coherency and avoiding stale control data.
+- This guarantee allows the driver to omit MMIO reads to flush
+- the DMA stream.
+-
+-See drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples
+-of MSI/MSI-X usage.
+-
+-
+-
+-4. PCI device shutdown
+-~~~~~~~~~~~~~~~~~~~~~~~
+-
+-When a PCI device driver is being unloaded, most of the following
+-steps need to be performed:
+-
+- Disable the device from generating IRQs
+- Release the IRQ (free_irq())
+- Stop all DMA activity
+- Release DMA buffers (both streaming and consistent)
+- Unregister from other subsystems (e.g. scsi or netdev)
+- Disable device from responding to MMIO/IO Port addresses
+- Release MMIO/IO Port resource(s)
+-
+-
+-4.1 Stop IRQs on the device
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-How to do this is chip/device specific. If it's not done, it opens
+-the possibility of a "screaming interrupt" if (and only if)
+-the IRQ is shared with another device.
+-
+-When the shared IRQ handler is "unhooked", the remaining devices
+-using the same IRQ line will still need the IRQ enabled. Thus if the
+-"unhooked" device asserts IRQ line, the system will respond assuming
+-it was one of the remaining devices asserted the IRQ line. Since none
+-of the other devices will handle the IRQ, the system will "hang" until
+-it decides the IRQ isn't going to get handled and masks the IRQ (100,000
+-iterations later). Once the shared IRQ is masked, the remaining devices
+-will stop functioning properly. Not a nice situation.
+-
+-This is another reason to use MSI or MSI-X if it's available.
+-MSI and MSI-X are defined to be exclusive interrupts and thus
+-are not susceptible to the "screaming interrupt" problem.
+-
+-
+-4.2 Release the IRQ
+-~~~~~~~~~~~~~~~~~~~
+-Once the device is quiesced (no more IRQs), one can call free_irq().
+-This function will return control once any pending IRQs are handled,
+-"unhook" the drivers IRQ handler from that IRQ, and finally release
+-the IRQ if no one else is using it.
+-
+-
+-4.3 Stop all DMA activity
+-~~~~~~~~~~~~~~~~~~~~~~~~~
+-It's extremely important to stop all DMA operations BEFORE attempting
+-to deallocate DMA control data. Failure to do so can result in memory
+-corruption, hangs, and on some chip-sets a hard crash.
+-
+-Stopping DMA after stopping the IRQs can avoid races where the
+-IRQ handler might restart DMA engines.
+-
+-While this step sounds obvious and trivial, several "mature" drivers
+-didn't get this step right in the past.
+-
+-
+-4.4 Release DMA buffers
+-~~~~~~~~~~~~~~~~~~~~~~~
+-Once DMA is stopped, clean up streaming DMA first.
+-I.e. unmap data buffers and return buffers to "upstream"
+-owners if there is one.
+-
+-Then clean up "consistent" buffers which contain the control data.
+-
+-See Documentation/DMA-API.txt for details on unmapping interfaces.
+-
+-
+-4.5 Unregister from other subsystems
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Most low level PCI device drivers support some other subsystem
+-like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your
+-driver isn't losing resources from that other subsystem.
+-If this happens, typically the symptom is an Oops (panic) when
+-the subsystem attempts to call into a driver that has been unloaded.
+-
+-
+-4.6 Disable Device from responding to MMIO/IO Port addresses
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-io_unmap() MMIO or IO Port resources and then call pci_disable_device().
+-This is the symmetric opposite of pci_enable_device().
+-Do not access device registers after calling pci_disable_device().
+-
+-
+-4.7 Release MMIO/IO Port Resource(s)
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Call pci_release_region() to mark the MMIO or IO Port range as available.
+-Failure to do so usually results in the inability to reload the driver.
+-
+-
+-
+-5. How to access PCI config space
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-You can use pci_(read|write)_config_(byte|word|dword) to access the config
+-space of a device represented by struct pci_dev *. All these functions return 0
+-when successful or an error code (PCIBIOS_...) which can be translated to a text
+-string by pcibios_strerror. Most drivers expect that accesses to valid PCI
+-devices don't fail.
+-
+-If you don't have a struct pci_dev available, you can call
+-pci_bus_(read|write)_config_(byte|word|dword) to access a given device
+-and function on that bus.
+-
+-If you access fields in the standard portion of the config header, please
+-use symbolic names of locations and bits declared in <linux/pci.h>.
+-
+-If you need to access Extended PCI Capability registers, just call
+-pci_find_capability() for the particular capability and it will find the
+-corresponding register block for you.
+-
+-
+-
+-6. Other interesting functions
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-pci_find_slot() Find pci_dev corresponding to given bus and
+- slot numbers.
+-pci_set_power_state() Set PCI Power Management state (0=D0 ... 3=D3)
+-pci_find_capability() Find specified capability in device's capability
+- list.
+-pci_resource_start() Returns bus start address for a given PCI region
+-pci_resource_end() Returns bus end address for a given PCI region
+-pci_resource_len() Returns the byte length of a PCI region
+-pci_set_drvdata() Set private driver data pointer for a pci_dev
+-pci_get_drvdata() Return private driver data pointer for a pci_dev
+-pci_set_mwi() Enable Memory-Write-Invalidate transactions.
+-pci_clear_mwi() Disable Memory-Write-Invalidate transactions.
+-
+-
+-
+-7. Miscellaneous hints
+-~~~~~~~~~~~~~~~~~~~~~~
+-
+-When displaying PCI device names to the user (for example when a driver wants
+-to tell the user what card has it found), please use pci_name(pci_dev).
+-
+-Always refer to the PCI devices by a pointer to the pci_dev structure.
+-All PCI layer functions use this identification and it's the only
+-reasonable one. Don't use bus/slot/function numbers except for very
+-special purposes -- on systems with multiple primary buses their semantics
+-can be pretty complex.
+-
+-Don't try to turn on Fast Back to Back writes in your driver. All devices
+-on the bus need to be capable of doing it, so this is something which needs
+-to be handled by platform and generic code, not individual drivers.
+-
+-
+-
+-8. Vendor and device identifications
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-One is not not required to add new device ids to include/linux/pci_ids.h.
+-Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids.
+-
+-PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary
+-hex numbers (vendor controlled) and normally used only in a single
+-location, the pci_device_id table.
+-
+-Please DO submit new vendor/device ids to pciids.sourceforge.net project.
+-
+-
+-
+-9. Obsolete functions
+-~~~~~~~~~~~~~~~~~~~~~
+-
+-There are several functions which you might come across when trying to
+-port an old driver to the new PCI interface. They are no longer present
+-in the kernel as they aren't compatible with hotplug or PCI domains or
+-having sane locking.
+-
+-pci_find_device() Superseded by pci_get_device()
+-pci_find_subsys() Superseded by pci_get_subsys()
+-pci_find_slot() Superseded by pci_get_slot()
+-
+-
+-The alternative is the traditional PCI device driver that walks PCI
+-device lists. This is still possible but discouraged.
+-
+-
+-
+-10. MMIO Space and "Write Posting"
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-Converting a driver from using I/O Port space to using MMIO space
+-often requires some additional changes. Specifically, "write posting"
+-needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2)
+-already do this. I/O Port space guarantees write transactions reach the PCI
+-device before the CPU can continue. Writes to MMIO space allow the CPU
+-to continue before the transaction reaches the PCI device. HW weenies
+-call this "Write Posting" because the write completion is "posted" to
+-the CPU before the transaction has reached its destination.
+-
+-Thus, timing sensitive code should add readl() where the CPU is
+-expected to wait before doing other work. The classic "bit banging"
+-sequence works fine for I/O Port space:
+-
+- for (i = 8; --i; val >>= 1) {
+- outb(val & 1, ioport_reg); /* write bit */
+- udelay(10);
+- }
+-
+-The same sequence for MMIO space should be:
+-
+- for (i = 8; --i; val >>= 1) {
+- writeb(val & 1, mmio_reg); /* write bit */
+- readb(safe_mmio_reg); /* flush posted write */
+- udelay(10);
+- }
+-
+-It is important that "safe_mmio_reg" not have any side effects that
+-interferes with the correct operation of the device.
+-
+-Another case to watch out for is when resetting a PCI device. Use PCI
+-Configuration space reads to flush the writel(). This will gracefully
+-handle the PCI master abort on all platforms if the PCI device is
+-expected to not respond to a readl(). Most x86 platforms will allow
+-MMIO reads to master abort (a.k.a. "Soft Fail") and return garbage
+-(e.g. ~0). But many RISC platforms will crash (a.k.a."Hard Fail").
+-
+--- a/Documentation/pcieaer-howto.txt
++++ /dev/null
+@@ -1,253 +0,0 @@
+- The PCI Express Advanced Error Reporting Driver Guide HOWTO
+- T. Long Nguyen <tom.l.nguyen@intel.com>
+- Yanmin Zhang <yanmin.zhang@intel.com>
+- 07/29/2006
+-
+-
+-1. Overview
+-
+-1.1 About this guide
+-
+-This guide describes the basics of the PCI Express Advanced Error
+-Reporting (AER) driver and provides information on how to use it, as
+-well as how to enable the drivers of endpoint devices to conform with
+-PCI Express AER driver.
+-
+-1.2 Copyright © Intel Corporation 2006.
+-
+-1.3 What is the PCI Express AER Driver?
+-
+-PCI Express error signaling can occur on the PCI Express link itself
+-or on behalf of transactions initiated on the link. PCI Express
+-defines two error reporting paradigms: the baseline capability and
+-the Advanced Error Reporting capability. The baseline capability is
+-required of all PCI Express components providing a minimum defined
+-set of error reporting requirements. Advanced Error Reporting
+-capability is implemented with a PCI Express advanced error reporting
+-extended capability structure providing more robust error reporting.
+-
+-The PCI Express AER driver provides the infrastructure to support PCI
+-Express Advanced Error Reporting capability. The PCI Express AER
+-driver provides three basic functions:
+-
+-- Gathers the comprehensive error information if errors occurred.
+-- Reports error to the users.
+-- Performs error recovery actions.
+-
+-AER driver only attaches root ports which support PCI-Express AER
+-capability.
+-
+-
+-2. User Guide
+-
+-2.1 Include the PCI Express AER Root Driver into the Linux Kernel
+-
+-The PCI Express AER Root driver is a Root Port service driver attached
+-to the PCI Express Port Bus driver. If a user wants to use it, the driver
+-has to be compiled. Option CONFIG_PCIEAER supports this capability. It
+-depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and
+-CONFIG_PCIEAER = y.
+-
+-2.2 Load PCI Express AER Root Driver
+-There is a case where a system has AER support in BIOS. Enabling the AER
+-Root driver and having AER support in BIOS may result unpredictable
+-behavior. To avoid this conflict, a successful load of the AER Root driver
+-requires ACPI _OSC support in the BIOS to allow the AER Root driver to
+-request for native control of AER. See the PCI FW 3.0 Specification for
+-details regarding OSC usage. Currently, lots of firmwares don't provide
+-_OSC support while they use PCI Express. To support such firmwares,
+-forceload, a parameter of type bool, could enable AER to continue to
+-be initiated although firmwares have no _OSC support. To enable the
+-walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
+-when booting kernel. Note that forceload=n by default.
+-
+-2.3 AER error output
+-When a PCI-E AER error is captured, an error message will be outputed to
+-console. If it's a correctable error, it is outputed as a warning.
+-Otherwise, it is printed as an error. So users could choose different
+-log level to filter out correctable error messages.
+-
+-Below shows an example.
+-+------ PCI-Express Device Error -----+
+-Error Severity : Uncorrected (Fatal)
+-PCIE Bus Error type : Transaction Layer
+-Unsupported Request : First
+-Requester ID : 0500
+-VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h
+-TLB Header:
+-04000001 00200a03 05010000 00050100
+-
+-In the example, 'Requester ID' means the ID of the device who sends
+-the error message to root port. Pls. refer to pci express specs for
+-other fields.
+-
+-
+-3. Developer Guide
+-
+-To enable AER aware support requires a software driver to configure
+-the AER capability structure within its device and to provide callbacks.
+-
+-To support AER better, developers need understand how AER does work
+-firstly.
+-
+-PCI Express errors are classified into two types: correctable errors
+-and uncorrectable errors. This classification is based on the impacts
+-of those errors, which may result in degraded performance or function
+-failure.
+-
+-Correctable errors pose no impacts on the functionality of the
+-interface. The PCI Express protocol can recover without any software
+-intervention or any loss of data. These errors are detected and
+-corrected by hardware. Unlike correctable errors, uncorrectable
+-errors impact functionality of the interface. Uncorrectable errors
+-can cause a particular transaction or a particular PCI Express link
+-to be unreliable. Depending on those error conditions, uncorrectable
+-errors are further classified into non-fatal errors and fatal errors.
+-Non-fatal errors cause the particular transaction to be unreliable,
+-but the PCI Express link itself is fully functional. Fatal errors, on
+-the other hand, cause the link to be unreliable.
+-
+-When AER is enabled, a PCI Express device will automatically send an
+-error message to the PCIE root port above it when the device captures
+-an error. The Root Port, upon receiving an error reporting message,
+-internally processes and logs the error message in its PCI Express
+-capability structure. Error information being logged includes storing
+-the error reporting agent's requestor ID into the Error Source
+-Identification Registers and setting the error bits of the Root Error
+-Status Register accordingly. If AER error reporting is enabled in Root
+-Error Command Register, the Root Port generates an interrupt if an
+-error is detected.
+-
+-Note that the errors as described above are related to the PCI Express
+-hierarchy and links. These errors do not include any device specific
+-errors because device specific errors will still get sent directly to
+-the device driver.
+-
+-3.1 Configure the AER capability structure
+-
+-AER aware drivers of PCI Express component need change the device
+-control registers to enable AER. They also could change AER registers,
+-including mask and severity registers. Helper function
+-pci_enable_pcie_error_reporting could be used to enable AER. See
+-section 3.3.
+-
+-3.2. Provide callbacks
+-
+-3.2.1 callback reset_link to reset pci express link
+-
+-This callback is used to reset the pci express physical link when a
+-fatal error happens. The root port aer service driver provides a
+-default reset_link function, but different upstream ports might
+-have different specifications to reset pci express link, so all
+-upstream ports should provide their own reset_link functions.
+-
+-In struct pcie_port_service_driver, a new pointer, reset_link, is
+-added.
+-
+-pci_ers_result_t (*reset_link) (struct pci_dev *dev);
+-
+-Section 3.2.2.2 provides more detailed info on when to call
+-reset_link.
+-
+-3.2.2 PCI error-recovery callbacks
+-
+-The PCI Express AER Root driver uses error callbacks to coordinate
+-with downstream device drivers associated with a hierarchy in question
+-when performing error recovery actions.
+-
+-Data struct pci_driver has a pointer, err_handler, to point to
+-pci_error_handlers who consists of a couple of callback function
+-pointers. AER driver follows the rules defined in
+-pci-error-recovery.txt except pci express specific parts (e.g.
+-reset_link). Pls. refer to pci-error-recovery.txt for detailed
+-definitions of the callbacks.
+-
+-Below sections specify when to call the error callback functions.
+-
+-3.2.2.1 Correctable errors
+-
+-Correctable errors pose no impacts on the functionality of
+-the interface. The PCI Express protocol can recover without any
+-software intervention or any loss of data. These errors do not
+-require any recovery actions. The AER driver clears the device's
+-correctable error status register accordingly and logs these errors.
+-
+-3.2.2.2 Non-correctable (non-fatal and fatal) errors
+-
+-If an error message indicates a non-fatal error, performing link reset
+-at upstream is not required. The AER driver calls error_detected(dev,
+-pci_channel_io_normal) to all drivers associated within a hierarchy in
+-question. for example,
+-EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort.
+-If Upstream port A captures an AER error, the hierarchy consists of
+-Downstream port B and EndPoint.
+-
+-A driver may return PCI_ERS_RESULT_CAN_RECOVER,
+-PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on
+-whether it can recover or the AER driver calls mmio_enabled as next.
+-
+-If an error message indicates a fatal error, kernel will broadcast
+-error_detected(dev, pci_channel_io_frozen) to all drivers within
+-a hierarchy in question. Then, performing link reset at upstream is
+-necessary. As different kinds of devices might use different approaches
+-to reset link, AER port service driver is required to provide the
+-function to reset link. Firstly, kernel looks for if the upstream
+-component has an aer driver. If it has, kernel uses the reset_link
+-callback of the aer driver. If the upstream component has no aer driver
+-and the port is downstream port, we will use the aer driver of the
+-root port who reports the AER error. As for upstream ports,
+-they should provide their own aer service drivers with reset_link
+-function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and
+-reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
+-to mmio_enabled.
+-
+-3.3 helper functions
+-
+-3.3.1 int pci_find_aer_capability(struct pci_dev *dev);
+-pci_find_aer_capability locates the PCI Express AER capability
+-in the device configuration space. If the device doesn't support
+-PCI-Express AER, the function returns 0.
+-
+-3.3.2 int pci_enable_pcie_error_reporting(struct pci_dev *dev);
+-pci_enable_pcie_error_reporting enables the device to send error
+-messages to root port when an error is detected. Note that devices
+-don't enable the error reporting by default, so device drivers need
+-call this function to enable it.
+-
+-3.3.3 int pci_disable_pcie_error_reporting(struct pci_dev *dev);
+-pci_disable_pcie_error_reporting disables the device to send error
+-messages to root port when an error is detected.
+-
+-3.3.4 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
+-pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable
+-error status register.
+-
+-3.4 Frequent Asked Questions
+-
+-Q: What happens if a PCI Express device driver does not provide an
+-error recovery handler (pci_driver->err_handler is equal to NULL)?
+-
+-A: The devices attached with the driver won't be recovered. If the
+-error is fatal, kernel will print out warning messages. Please refer
+-to section 3 for more information.
+-
+-Q: What happens if an upstream port service driver does not provide
+-callback reset_link?
+-
+-A: Fatal error recovery will fail if the errors are reported by the
+-upstream ports who are attached by the service driver.
+-
+-Q: How does this infrastructure deal with driver that is not PCI
+-Express aware?
+-
+-A: This infrastructure calls the error callback functions of the
+-driver when an error happens. But if the driver is not aware of
+-PCI Express, the device might not report its own errors to root
+-port.
+-
+-Q: What modifications will that driver need to make it compatible
+-with the PCI Express AER Root driver?
+-
+-A: It could call the helper functions to enable AER in devices and
+-cleanup uncorrectable status register. Pls. refer to section 3.3.
+-
diff --git a/series b/series
index 7fa4855604306d..38fb02539ffce2 100644
--- a/series
+++ b/series
@@ -11,6 +11,7 @@ driver-core/uio-kconfig-improvements.patch
driver-core/uio-mark-pci_device_id-hilscher_pci_ids-__devinitdata.patch
driver-core/uio-arch-arm-kconfig-make-uio-available-on-arm-architecture.patch
driver-core/uio-remove-needless-pci_device_id-definition-from-uio_cif.c.patch
+driver-core/uio-implement-a-uio-interface-for-the-smx-cryptengine.patch
driver-core/driver-core-memory-semaphore-to-mutex.patch
driver-core/driver-core-register_memory-unregister_memory-clean-ups-and-bugfix.patch
driver-core/sysfs-small-header-file-cleanup-for-sysfs-n.patch
@@ -23,6 +24,9 @@ driver-core/driver-core-cpu-fix-section-mismatch-in-cpu.c-store_online.patch
driver-core/sysdev-detect-multiple-driver-registrations.patch
driver-core/driver-core-debug-for-bad-dev_attr_show-return-value.patch
driver-core/block-send-disk-change-event-for-rescan_partitions.patch
+driver-core/pm-handle-device-registrations-during-suspend-resume.patch
+driver-core/driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch
+driver-core/pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch
driver-core/net-convert-the-phy_device-file-to-use-bus_find_device_by_name.patch
@@ -46,6 +50,7 @@ driver-core/sysfs-crash-debugging.patch
pci/pci-fix-issue-with-busses-registering-multiple-times-in-sysfs.patch
# pci patches for after 2.6.25 is out
+pci/pci-doc-pci-create-documentation-pci-and-move-files-into-it.patch
pci/pci-if-0-pci_assign_resource_fixed.patch
pci/pci-remove-pci_find_present.patch
@@ -95,6 +100,7 @@ pci/pci-replace-remaining-__function__-occurrences.patch
# usb patches queued for 2.6.25 (bugfixes, new ids, etc.)
usb/usb-fix-gadgetfs-class-request-delegation.patch
+usb/usb-new-quirk-flag-to-avoid-set-interface.patch
# resume rework
usb/usb-ehci-carry-out-port-handover-during-each-root-hub-resume.patch
@@ -144,6 +150,7 @@ usb/usb-ipaq-fix-devices-having-more-than-one-endpoint.patch
usb/usb-remove-dev-power.power_state.patch
usb/usb-ehci-paranoia-reject-large-control-transfers.patch
usb/usb-cypress_m8-speed-handling.patch
+usb/drivers-usb-core-devio.c-suppress-warning-with-64k-page_size.patch
usb/usb-add-usb-serial-spcp8x5-driver.patch
@@ -172,6 +179,5 @@ driver-core/video-add-the-go7007-driver.patch
#pending/greg-debugobjects-add-documentation.patch
#pending/greg-debugobjects-add-timer-specific-object-debugging-code.patch
-
firmware-add-kconfig-and-makefile-to-build-the-firmware-samples.patch
f2.patch
diff --git a/usb/drivers-usb-core-devio.c-suppress-warning-with-64k-page_size.patch b/usb/drivers-usb-core-devio.c-suppress-warning-with-64k-page_size.patch
new file mode 100644
index 00000000000000..025e06f603135c
--- /dev/null
+++ b/usb/drivers-usb-core-devio.c-suppress-warning-with-64k-page_size.patch
@@ -0,0 +1,43 @@
+From akpm@linux-foundation.org Thu Mar 13 13:43:17 2008
+From: Andrew Morton <akpm@linux-foundation.org>
+Date: Wed, 12 Mar 2008 13:32:24 -0700
+Subject: drivers/usb/core/devio.c: suppress warning with 64k PAGE_SIZE
+To: mm-commits@vger.kernel.org
+Cc: akpm@linux-foundation.org, gregkh@suse.de, oliver@neukum.org, stern@rowland.harvard.edu, zaitcev@redhat.com
+Message-ID: <200803122041.m2CKfxNN012309@imap1.linux-foundation.org>
+
+From: Andrew Morton <akpm@linux-foundation.org>
+
+drivers/usb/core/devio.c: In function 'proc_control':
+drivers/usb/core/devio.c:657: warning: comparison is always false due to limited range of data type
+
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Pete Zaitcev <zaitcev@redhat.com>
+Cc: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/devio.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -647,6 +647,7 @@ static int proc_control(struct dev_state
+ struct usbdevfs_ctrltransfer ctrl;
+ unsigned int tmo;
+ unsigned char *tbuf;
++ unsigned wLength;
+ int i, j, ret;
+
+ if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+@@ -654,7 +655,8 @@ static int proc_control(struct dev_state
+ ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex);
+ if (ret)
+ return ret;
+- if (ctrl.wLength > PAGE_SIZE)
++ wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */
++ if (wLength > PAGE_SIZE)
+ return -EINVAL;
+ tbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
+ if (!tbuf)
diff --git a/usb/usb-add-usb-serial-spcp8x5-driver.patch b/usb/usb-add-usb-serial-spcp8x5-driver.patch
index 422d8d48eea116..265ee94c4ed1c9 100644
--- a/usb/usb-add-usb-serial-spcp8x5-driver.patch
+++ b/usb/usb-add-usb-serial-spcp8x5-driver.patch
@@ -14,8 +14,8 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/usb/serial/Kconfig | 10
drivers/usb/serial/Makefile | 3
- drivers/usb/serial/spcp8x5.c | 1076 +++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 1088 insertions(+), 1 deletion(-)
+ drivers/usb/serial/spcp8x5.c | 1075 +++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 1087 insertions(+), 1 deletion(-)
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -58,7 +58,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
--- /dev/null
+++ b/drivers/usb/serial/spcp8x5.c
-@@ -0,0 +1,1076 @@
+@@ -0,0 +1,1075 @@
+/*
+ * spcp8x5 USB to serial adaptor driver
+ *
@@ -475,11 +475,10 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ GET_UART_STATUS, GET_UART_STATUS_TYPE,
+ 0, GET_UART_STATUS_MSR, status_buffer, 1, 100);
+ if (ret < 0)
-+ dev_dbg(&dev->dev, "Get MSR = %#x failed (error = %d)",
-+ (int)status_buffer, (int)ret);
++ dev_dbg(&dev->dev, "Get MSR = 0x%p failed (error = %d)",
++ status_buffer, ret);
+
-+ dev_dbg(&dev->dev, "0xc0:0x22:0:6 %d - %x ", (int)ret,
-+ (int)status_buffer);
++ dev_dbg(&dev->dev, "0xc0:0x22:0:6 %d - 0x%p ", ret, status_buffer);
+ status[0] = status_buffer[0];
+ kfree(status_buffer);
+
diff --git a/usb/usb-enable-usb-persist-by-default.patch b/usb/usb-enable-usb-persist-by-default.patch
index 28e8a1b898d192..17ca2b993444bf 100644
--- a/usb/usb-enable-usb-persist-by-default.patch
+++ b/usb/usb-enable-usb-persist-by-default.patch
@@ -29,7 +29,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
-@@ -95,12 +95,14 @@ void usb_detect_quirks(struct usb_device
+@@ -98,12 +98,14 @@ void usb_detect_quirks(struct usb_device
udev->autosuspend_disabled = 1;
#endif
diff --git a/usb/usb-new-quirk-flag-to-avoid-set-interface.patch b/usb/usb-new-quirk-flag-to-avoid-set-interface.patch
new file mode 100644
index 00000000000000..426cfd25eef63a
--- /dev/null
+++ b/usb/usb-new-quirk-flag-to-avoid-set-interface.patch
@@ -0,0 +1,59 @@
+From stern@rowland.harvard.edu Thu Mar 13 13:46:50 2008
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Tue, 11 Mar 2008 10:20:12 -0400 (EDT)
+Subject: USB: new quirk flag to avoid Set-Interface
+To: Greg KH <greg@kroah.com>
+Cc: Graeme Gill <graeme2@argyllcms.com>, USB list <linux-usb@vger.kernel.org>
+Message-ID: <Pine.LNX.4.44L0.0803111018560.3587-100000@iolanthe.rowland.org>
+
+
+This patch (as1057) fixes a problem with the Gretag-Macbeth Huey display
+colorimeter; the device crashes when it receives a Set-Interface
+request. A new quirk (USB_QUIRK_NO_SET_INTF) is introduced and a
+quirks entry is created for this device.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/message.c | 5 ++++-
+ drivers/usb/core/quirks.c | 3 +++
+ include/linux/usb/quirks.h | 3 +++
+ 3 files changed, 10 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1206,7 +1206,10 @@ int usb_set_interface(struct usb_device
+ return -EINVAL;
+ }
+
+- ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++ if (dev->quirks & USB_QUIRK_NO_SET_INTF)
++ ret = -EPIPE;
++ else
++ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
+ alternate, interface, NULL, 0, 5000);
+
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -50,6 +50,9 @@ static const struct usb_device_id usb_qu
+ /* M-Systems Flash Disk Pioneers */
+ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
+
++ /* Gretag-Macbeth Huey display colorimeter */
++ { USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF },
++
+ /* Action Semiconductor flash disk */
+ { USB_DEVICE(0x10d6, 0x2200), .driver_info =
+ USB_QUIRK_STRING_FETCH_255 },
+--- a/include/linux/usb/quirks.h
++++ b/include/linux/usb/quirks.h
+@@ -9,3 +9,6 @@
+
+ /* device can't resume correctly so reset it instead */
+ #define USB_QUIRK_RESET_RESUME 0x00000002
++
++/* device can't handle Set-Interface requests */
++#define USB_QUIRK_NO_SET_INTF 0x00000004
diff --git a/usb/usb-remove-config_usb_persist-setting.patch b/usb/usb-remove-config_usb_persist-setting.patch
index 59dbd1396b4af9..bfb11c6df8bb11 100644
--- a/usb/usb-remove-config_usb_persist-setting.patch
+++ b/usb/usb-remove-config_usb_persist-setting.patch
@@ -226,7 +226,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
{
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
-@@ -94,4 +94,16 @@ void usb_detect_quirks(struct usb_device
+@@ -97,4 +97,16 @@ void usb_detect_quirks(struct usb_device
if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
udev->autosuspend_disabled = 1;
#endif
diff --git a/usb/usb-remove-dev-power.power_state.patch b/usb/usb-remove-dev-power.power_state.patch
index d5f5456c56616b..01697d71ffc730 100644
--- a/usb/usb-remove-dev-power.power_state.patch
+++ b/usb/usb-remove-dev-power.power_state.patch
@@ -16,7 +16,7 @@ Part of this patch was written by Pavel Machek.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Cc: David Brownell <david-b@pacbell.net>
-Cc: Pavel Machek <pavel@ucw.cz>
+Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/usb/usb-replace-remaining-__function__-occurrences.patch b/usb/usb-replace-remaining-__function__-occurrences.patch
index 85edaaefd0c92e..55321111be1d35 100644
--- a/usb/usb-replace-remaining-__function__-occurrences.patch
+++ b/usb/usb-replace-remaining-__function__-occurrences.patch
@@ -148,7 +148,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
/* data interface returns incoming bytes, or we got unthrottled */
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
-@@ -1509,60 +1509,60 @@ static int usbdev_ioctl(struct inode *in
+@@ -1511,60 +1511,60 @@ static int usbdev_ioctl(struct inode *in
switch (cmd) {
case USBDEVFS_CONTROL:
@@ -219,7 +219,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
ret = proc_submiturb(ps, p);
if (ret >= 0)
inode->i_mtime = CURRENT_TIME;
-@@ -1571,60 +1571,60 @@ static int usbdev_ioctl(struct inode *in
+@@ -1573,60 +1573,60 @@ static int usbdev_ioctl(struct inode *in
#ifdef CONFIG_COMPAT
case USBDEVFS_SUBMITURB32: