diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-04-04 10:53:00 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-04-04 10:53:00 -0700 |
commit | 89db993763d7241db3f0b8760c71dcb0cf6e5d91 (patch) | |
tree | f5c163b34e79c4cf4317758bef9da95f3ad88b61 /pci | |
parent | d39fbab34cc47f08bbc206ac10f5b61b32227da6 (diff) | |
download | patches-89db993763d7241db3f0b8760c71dcb0cf6e5d91.tar.gz |
new pci and usb patches
Diffstat (limited to 'pci')
9 files changed, 1099 insertions, 0 deletions
diff --git a/pci/acpiphp-configure-_prt-v3.patch b/pci/acpiphp-configure-_prt-v3.patch new file mode 100644 index 0000000000000..5524b97ef6bcd --- /dev/null +++ b/pci/acpiphp-configure-_prt-v3.patch @@ -0,0 +1,128 @@ +From muneda.takahiro@jp.fujitsu.com Tue Mar 21 21:49:23 2006 +Date: Wed, 22 Mar 2006 14:49:09 +0900 +Message-ID: <87lkv3c9m2.wl%muneda.takahiro@jp.fujitsu.com> +From: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> +To: Greg KH <greg@kroah.com> +Cc: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> +Subject: acpiphp: configure _PRT - V3 + +Current acpiphp does not free acpi_device structs when the +PCI devices are removed. When the PCI device is added, +acpi_bus_add() fails because acpi_device struct has already +exists. So, _PRT method does not evaluate. + +This patch fixes this issue. + +Signed-off-by: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/pci/hotplug/acpiphp_glue.c | 71 +++++++++++++++++-------------------- + 1 file changed, 33 insertions(+), 38 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/acpiphp_glue.c ++++ gregkh-2.6/drivers/pci/hotplug/acpiphp_glue.c +@@ -797,36 +797,6 @@ static unsigned char acpiphp_max_busnr(s + } + + +- +-/** +- * get_func - get a pointer to acpiphp_func given a slot, device +- * @slot: slot to search +- * @dev: pci_dev struct to match. +- * +- * This function will increase the reference count of pci_dev, +- * so callers should call pci_dev_put when complete. +- * +- */ +-static struct acpiphp_func * +-get_func(struct acpiphp_slot *slot, struct pci_dev *dev) +-{ +- struct acpiphp_func *func = NULL; +- struct pci_bus *bus = slot->bridge->pci_bus; +- struct pci_dev *pdev; +- +- list_for_each_entry(func, &slot->funcs, sibling) { +- pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, +- func->function)); +- if (pdev) { +- if (pdev == dev) +- break; +- pci_dev_put(pdev); +- } +- } +- return func; +-} +- +- + /** + * acpiphp_bus_add - add a new bus to acpi subsystem + * @func: acpiphp_func of the bridge +@@ -872,6 +842,28 @@ acpiphp_bus_add_out: + } + + ++/** ++ * acpiphp_bus_trim - trim a bus from acpi subsystem ++ * @handle: handle to acpi namespace ++ * ++ */ ++int acpiphp_bus_trim(acpi_handle handle) ++{ ++ struct acpi_device *device; ++ int retval; ++ ++ retval = acpi_bus_get_device(handle, &device); ++ if (retval) { ++ dbg("acpi_device not found\n"); ++ return retval; ++ } ++ ++ retval = acpi_bus_trim(device, 1); ++ if (retval) ++ err("cannot remove from acpi list\n"); ++ ++ return retval; ++} + + /** + * enable_device - enable, configure a slot +@@ -918,19 +910,17 @@ static int enable_device(struct acpiphp_ + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || + dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { + max = pci_scan_bridge(bus, dev, max, pass); +- if (pass && dev->subordinate) { ++ if (pass && dev->subordinate) + pci_bus_size_bridges(dev->subordinate); +- func = get_func(slot, dev); +- if (func) { +- acpiphp_bus_add(func); +- /* side effect of get_func */ +- pci_dev_put(dev); +- } +- } + } + } + } + ++ list_for_each (l, &slot->funcs) { ++ func = list_entry(l, struct acpiphp_func, sibling); ++ acpiphp_bus_add(func); ++ } ++ + pci_bus_assign_resources(bus); + acpiphp_sanitize_bus(bus); + pci_enable_bridges(bus); +@@ -967,6 +957,11 @@ static int disable_device(struct acpiphp + + list_for_each (l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); ++ ++ acpiphp_bus_trim(func->handle); ++ /* try to remove anyway. ++ * acpiphp_bus_add might have been failed */ ++ + if (!func->pci_dev) + continue; + diff --git a/pci/acpiphp-host-and-p2p-hotplug.patch b/pci/acpiphp-host-and-p2p-hotplug.patch new file mode 100644 index 0000000000000..526cdb3d2122b --- /dev/null +++ b/pci/acpiphp-host-and-p2p-hotplug.patch @@ -0,0 +1,31 @@ +From muneda.takahiro@jp.fujitsu.com Tue Mar 21 21:49:45 2006 +Date: Wed, 22 Mar 2006 14:49:27 +0900 +Message-ID: <87irq7c9lk.wl%muneda.takahiro@jp.fujitsu.com> +From: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> +To: Greg KH <greg@kroah.com> +Cc: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> +Subject: acpiphp: host and p2p hotplug + +I encountered the problem that when there are some hotplug +slots are under the host bridge, the hotplug slots under the +p2p bridge are not treated as hotpluggable. + +This patch fixes this BUG. + +Signed-off-by: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/pci/hotplug/acpiphp_glue.c | 1 - + 1 file changed, 1 deletion(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/acpiphp_glue.c ++++ gregkh-2.6/drivers/pci/hotplug/acpiphp_glue.c +@@ -546,7 +546,6 @@ static int add_bridge(acpi_handle handle + if (detect_ejectable_slots(handle) > 0) { + dbg("found PCI host-bus bridge with hot-pluggable slots\n"); + add_host_bridge(handle, pci_bus); +- return 0; + } + + /* search P2P bridges under this host bridge */ diff --git a/pci/acpiphp-hotplug-slot-hotplug.patch b/pci/acpiphp-hotplug-slot-hotplug.patch new file mode 100644 index 0000000000000..9d67d21fba4bd --- /dev/null +++ b/pci/acpiphp-hotplug-slot-hotplug.patch @@ -0,0 +1,268 @@ +From muneda.takahiro@jp.fujitsu.com Tue Mar 21 21:49:43 2006 +Date: Wed, 22 Mar 2006 14:49:20 +0900 +Message-ID: <87k6anc9lr.wl%muneda.takahiro@jp.fujitsu.com> +From: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> +To: Greg KH <greg@kroah.com> +Cc: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> +Subject: acpiphp: hotplug slot hotplug + +o hotplug slots add + When the hot-added PCI device is p2p bridge, acpiphp calls + find_p2p_bridge() to add hotplug slots. + +o hotplug slots remove + When the hot-removing PCI device is p2p bridge, acpiphp + calls cleanup_p2p_bridge() to remove hotplug slots. + +o notify handler exchange + When the p2p bridge is added, acpiphp changes the notify + hanlder. + If no bridge device is inserted into the hotpluggable PCI + slot, acpiphp installs the notify handler for function. + After the p2p bridge hot-add, acpiphp has to install the + notify handler for bridge. Because, the role of the + handlers are not same. The hot-remove case is ditto. + +Signed-off-by: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/pci/hotplug/acpiphp.h | 5 + + drivers/pci/hotplug/acpiphp_glue.c | 126 ++++++++++++++++++++++++++++++++++--- + 2 files changed, 122 insertions(+), 9 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/acpiphp.h ++++ gregkh-2.6/drivers/pci/hotplug/acpiphp.h +@@ -75,6 +75,10 @@ struct acpiphp_bridge { + struct list_head list; + acpi_handle handle; + struct acpiphp_slot *slots; ++ ++ /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ ++ struct acpiphp_func *func; ++ + int type; + int nr_slots; + +@@ -122,6 +126,7 @@ struct acpiphp_slot { + */ + struct acpiphp_func { + struct acpiphp_slot *slot; /* parent */ ++ struct acpiphp_bridge *bridge; /* Ejectable PCI-to-PCI bridge */ + + struct list_head sibling; + struct pci_dev *pci_dev; +--- gregkh-2.6.orig/drivers/pci/hotplug/acpiphp_glue.c ++++ gregkh-2.6/drivers/pci/hotplug/acpiphp_glue.c +@@ -319,6 +319,13 @@ static void init_bridge_misc(struct acpi + + /* install notify handler */ + if (bridge->type != BRIDGE_TYPE_HOST) { ++ if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { ++ status = acpi_remove_notify_handler(bridge->func->handle, ++ ACPI_SYSTEM_NOTIFY, ++ handle_hotplug_event_func); ++ if (ACPI_FAILURE(status)) ++ err("failed to remove notify handler\n"); ++ } + status = acpi_install_notify_handler(bridge->handle, + ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_bridge, +@@ -331,6 +338,66 @@ static void init_bridge_misc(struct acpi + } + + ++/* find acpiphp_func from acpiphp_bridge */ ++static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle) ++{ ++ struct list_head *node, *l; ++ struct acpiphp_bridge *bridge; ++ struct acpiphp_slot *slot; ++ struct acpiphp_func *func; ++ ++ list_for_each(node, &bridge_list) { ++ bridge = list_entry(node, struct acpiphp_bridge, list); ++ for (slot = bridge->slots; slot; slot = slot->next) { ++ list_for_each(l, &slot->funcs) { ++ func = list_entry(l, struct acpiphp_func, ++ sibling); ++ if (func->handle == handle) ++ return func; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++ ++static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) ++{ ++ acpi_handle dummy_handle; ++ ++ if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, ++ "_STA", &dummy_handle))) ++ bridge->flags |= BRIDGE_HAS_STA; ++ ++ if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, ++ "_EJ0", &dummy_handle))) ++ bridge->flags |= BRIDGE_HAS_EJ0; ++ ++ if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, ++ "_PS0", &dummy_handle))) ++ bridge->flags |= BRIDGE_HAS_PS0; ++ ++ if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, ++ "_PS3", &dummy_handle))) ++ bridge->flags |= BRIDGE_HAS_PS3; ++ ++ /* is this ejectable p2p bridge? */ ++ if (bridge->flags & BRIDGE_HAS_EJ0) { ++ struct acpiphp_func *func; ++ ++ dbg("found ejectable p2p bridge\n"); ++ ++ /* make link between PCI bridge and PCI function */ ++ func = acpiphp_bridge_handle_to_function(bridge->handle); ++ if (!func) ++ return; ++ bridge->func = func; ++ func->bridge = bridge; ++ } ++} ++ ++ + /* allocate and initialize host bridge data structure */ + static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) + { +@@ -364,6 +431,7 @@ static void add_p2p_bridge(acpi_handle * + + bridge->type = BRIDGE_TYPE_P2P; + bridge->handle = handle; ++ config_p2p_bridge_flags(bridge); + + bridge->pci_dev = pci_dev_get(pci_dev); + bridge->pci_bus = pci_dev->subordinate; +@@ -423,7 +491,7 @@ find_p2p_bridge(acpi_handle handle, u32 + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + find_p2p_bridge, dev->subordinate, NULL); + if (ACPI_FAILURE(status)) +- warn("find_p2p_bridge faied (error code = 0x%x)\n", status); ++ warn("find_p2p_bridge failed (error code = 0x%x)\n", status); + + out: + pci_dev_put(dev); +@@ -486,7 +554,7 @@ static int add_bridge(acpi_handle handle + find_p2p_bridge, pci_bus, NULL); + + if (ACPI_FAILURE(status)) +- warn("find_p2p_bridge faied (error code = 0x%x)\n",status); ++ warn("find_p2p_bridge failed (error code = 0x%x)\n", status); + + return 0; + } +@@ -516,6 +584,16 @@ static void cleanup_bridge(struct acpiph + if (ACPI_FAILURE(status)) + err("failed to remove notify handler\n"); + ++ if ((bridge->type != BRIDGE_TYPE_HOST) && ++ ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) { ++ status = acpi_install_notify_handler(bridge->func->handle, ++ ACPI_SYSTEM_NOTIFY, ++ handle_hotplug_event_func, ++ bridge->func); ++ if (ACPI_FAILURE(status)) ++ err("failed to install interrupt notify handler\n"); ++ } ++ + slot = bridge->slots; + while (slot) { + struct acpiphp_slot *next = slot->next; +@@ -549,6 +627,11 @@ cleanup_p2p_bridge(acpi_handle handle, u + { + struct acpiphp_bridge *bridge; + ++ /* cleanup p2p bridges under this P2P bridge ++ in a depth-first manner */ ++ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, ++ cleanup_p2p_bridge, NULL, NULL); ++ + if (!(bridge = acpiphp_handle_to_bridge(handle))) + return AE_OK; + cleanup_bridge(bridge); +@@ -559,15 +642,14 @@ static void remove_bridge(acpi_handle ha + { + struct acpiphp_bridge *bridge; + ++ /* cleanup p2p bridges under this host bridge ++ in a depth-first manner */ ++ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ++ (u32)1, cleanup_p2p_bridge, NULL, NULL); ++ + bridge = acpiphp_handle_to_bridge(handle); +- if (bridge) { ++ if (bridge) + cleanup_bridge(bridge); +- } else { +- /* clean-up p2p bridges under this host bridge */ +- acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, +- ACPI_UINT32_MAX, cleanup_p2p_bridge, +- NULL, NULL); +- } + } + + static struct pci_dev * get_apic_pci_info(acpi_handle handle) +@@ -881,6 +963,7 @@ static int enable_device(struct acpiphp_ + struct acpiphp_func *func; + int retval = 0; + int num, max, pass; ++ acpi_status status; + + if (slot->flags & SLOT_ENABLED) + goto err_exit; +@@ -933,6 +1016,17 @@ static int enable_device(struct acpiphp_ + func = list_entry(l, struct acpiphp_func, sibling); + func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device, + func->function)); ++ if (!func->pci_dev) ++ continue; ++ ++ if (func->pci_dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && ++ func->pci_dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) ++ continue; ++ ++ status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); ++ if (ACPI_FAILURE(status)) ++ warn("find_p2p_bridge failed (error code = 0x%x)\n", ++ status); + } + + slot->flags |= SLOT_ENABLED; +@@ -958,6 +1052,13 @@ static int disable_device(struct acpiphp + list_for_each (l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); + ++ if (func->bridge) { ++ /* cleanup p2p bridges under this P2P bridge */ ++ cleanup_p2p_bridge(func->bridge->handle, ++ (u32)1, NULL, NULL); ++ func->bridge = NULL; ++ } ++ + acpiphp_bus_trim(func->handle); + /* try to remove anyway. + * acpiphp_bus_add might have been failed */ +@@ -1292,6 +1393,13 @@ static void handle_hotplug_event_bridge( + case ACPI_NOTIFY_EJECT_REQUEST: + /* request device eject */ + dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname); ++ if ((bridge->type != BRIDGE_TYPE_HOST) && ++ (bridge->flags & BRIDGE_HAS_EJ0)) { ++ struct acpiphp_slot *slot; ++ slot = bridge->func->slot; ++ if (!acpiphp_disable_slot(slot)) ++ acpiphp_eject_slot(slot); ++ } + break; + + case ACPI_NOTIFY_FREQUENCY_MISMATCH: diff --git a/pci/acpiphp-turn-off-slot-power-at-error-case.patch b/pci/acpiphp-turn-off-slot-power-at-error-case.patch new file mode 100644 index 0000000000000..1dd792b0fdc2d --- /dev/null +++ b/pci/acpiphp-turn-off-slot-power-at-error-case.patch @@ -0,0 +1,41 @@ +From muneda.takahiro@jp.fujitsu.com Tue Mar 21 21:49:53 2006 +Date: Wed, 22 Mar 2006 14:49:33 +0900 +Message-ID: <87hd5rc9le.wl%muneda.takahiro@jp.fujitsu.com> +From: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> +To: Greg KH <greg@kroah.com> +Cc: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> +Subject: acpiphp: turn off slot power at error case + +When acpiphp_enable_slot() is failed, acpiphp does not change +the slot->flags. Therefore, when user tries to read power +status, acpiphp_get_power_status() returns the enable status +whether the slot is not really enabled. + +This patch fixes this BUG. + +Signed-off-by: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/pci/hotplug/acpiphp_glue.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/acpiphp_glue.c ++++ gregkh-2.6/drivers/pci/hotplug/acpiphp_glue.c +@@ -1592,9 +1592,15 @@ int acpiphp_enable_slot(struct acpiphp_s + if (retval) + goto err_exit; + +- if (get_slot_status(slot) == ACPI_STA_ALL) ++ if (get_slot_status(slot) == ACPI_STA_ALL) { + /* configure all functions */ + retval = enable_device(slot); ++ if (retval) ++ power_off_slot(slot); ++ } else { ++ dbg("%s: Slot status is not ACPI_STA_ALL\n", __FUNCTION__); ++ power_off_slot(slot); ++ } + + err_exit: + mutex_unlock(&slot->crit_sect); diff --git a/pci/pci-hotplug-tollhouse-hp-sgi-hotplug-driver-changes.patch b/pci/pci-hotplug-tollhouse-hp-sgi-hotplug-driver-changes.patch new file mode 100644 index 0000000000000..6c79547130ad1 --- /dev/null +++ b/pci/pci-hotplug-tollhouse-hp-sgi-hotplug-driver-changes.patch @@ -0,0 +1,123 @@ +From prarit@sgi.com Tue Apr 4 06:26:54 2006 +Date: Tue, 4 Apr 2006 09:26:46 -0400 +From: Prarit Bhargava <prarit@sgi.com> +To: <edwardsg@sgi.com> +Cc: Prarit Bhargava <prarit@sgi.com> +Message-Id: <20060404132641.10912.44536.sendpatchset@prarit.boston.redhat.com> +Subject: PCI Hotplug: Tollhouse HP: SGI hotplug driver changes + +SGI hotplug driver changes required to support Tollhouse system PCI +hotplug, and implements the PRF_HOTPLUG_SUPPORT feature bit. + +Signed-off-by: Prarit Bhargava <prarit@sgi.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/pci/hotplug/sgi_hotplug.c | 42 +++++++++++++++++++------------------- + 1 file changed, 21 insertions(+), 21 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/sgi_hotplug.c ++++ gregkh-2.6/drivers/pci/hotplug/sgi_hotplug.c +@@ -18,11 +18,13 @@ + #include <linux/mutex.h> + + #include <asm/sn/addrs.h> ++#include <asm/sn/geo.h> + #include <asm/sn/l1.h> + #include <asm/sn/module.h> + #include <asm/sn/pcibr_provider.h> + #include <asm/sn/pcibus_provider_defs.h> + #include <asm/sn/pcidev.h> ++#include <asm/sn/sn_feature_sets.h> + #include <asm/sn/sn_sal.h> + #include <asm/sn/types.h> + +@@ -102,8 +104,7 @@ static struct hotplug_slot_attribute sn_ + static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device) + { + struct pcibus_info *pcibus_info; +- int bricktype; +- int bus_num; ++ u16 busnum, segment, ioboard_type; + + pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); + +@@ -111,12 +112,14 @@ static int sn_pci_slot_valid(struct pci_ + if (!(pcibus_info->pbi_valid_devices & (1 << device))) + return -EPERM; + +- bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid); +- bus_num = pcibus_info->pbi_buscommon.bs_persist_busnum & 0xf; ++ ioboard_type = sn_ioboard_to_pci_bus(pci_bus); ++ busnum = pcibus_info->pbi_buscommon.bs_persist_busnum; ++ segment = pci_domain_nr(pci_bus) & 0xf; + + /* Do not allow hotplug operations on base I/O cards */ +- if ((bricktype == L1_BRICKTYPE_IX || bricktype == L1_BRICKTYPE_IA) && +- (bus_num == 1 && device != 1)) ++ if ((ioboard_type == L1_BRICKTYPE_IX || ++ ioboard_type == L1_BRICKTYPE_IA) && ++ (segment == 1 && busnum == 0 && device != 1)) + return -EPERM; + + return 1; +@@ -125,23 +128,23 @@ static int sn_pci_slot_valid(struct pci_ + static int sn_pci_bus_valid(struct pci_bus *pci_bus) + { + struct pcibus_info *pcibus_info; +- int asic_type; +- int bricktype; +- +- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); ++ u32 asic_type; ++ u16 ioboard_type; + + /* Don't register slots hanging off the TIOCA bus */ ++ pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); + asic_type = pcibus_info->pbi_buscommon.bs_asic_type; + if (asic_type == PCIIO_ASIC_TYPE_TIOCA) + return -EPERM; + + /* Only register slots in I/O Bricks that support hotplug */ +- bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid); +- switch (bricktype) { ++ ioboard_type = sn_ioboard_to_pci_bus(pci_bus); ++ switch (ioboard_type) { + case L1_BRICKTYPE_IX: + case L1_BRICKTYPE_PX: + case L1_BRICKTYPE_IA: + case L1_BRICKTYPE_PA: ++ case L1_BOARDTYPE_PCIX3SLOT: + return 1; + break; + default: +@@ -175,14 +178,11 @@ static int sn_hp_slot_private_alloc(stru + slot->pci_bus = pci_bus; + sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x", + pci_domain_nr(pci_bus), +- ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf, ++ ((u16)pcibus_info->pbi_buscommon.bs_persist_busnum), + device + 1); +- sprintf(slot->physical_path, "module_%c%c%c%c%.2d", +- '0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), +- '0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), +- '0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), +- MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid), +- MODULE_GET_BPOS(pcibus_info->pbi_moduleid)); ++ ++ sn_generate_path(pci_bus, slot->physical_path); ++ + slot->hotplug_slot = bss_hotplug_slot; + list_add(&slot->hp_list, &sn_hp_list); + +@@ -553,8 +553,8 @@ static int sn_pci_hotplug_init(void) + int rc; + int registered = 0; + +- if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) { +- printk(KERN_ERR "%s: PROM version must be greater than 4.30\n", ++ if (!sn_prom_feature_available(PRF_HOTPLUG_SUPPORT)) { ++ printk(KERN_ERR "%s: PROM version does not support hotplug.\n", + __FUNCTION__); + return -EPERM; + } diff --git a/pci/pci-legacy-i-o-port-free-driver-changes-to-generic-pci-code.patch b/pci/pci-legacy-i-o-port-free-driver-changes-to-generic-pci-code.patch new file mode 100644 index 0000000000000..1ba3a760d752f --- /dev/null +++ b/pci/pci-legacy-i-o-port-free-driver-changes-to-generic-pci-code.patch @@ -0,0 +1,186 @@ +From kaneshige.kenji@jp.fujitsu.com Sun Mar 26 21:37:51 2006 +Message-ID: <4427799E.1070902@jp.fujitsu.com> +Date: Mon, 27 Mar 2006 14:35:26 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Andrew Morton <akpm@osdl.org> +CC: greg@kroah.com, linux-kernel@vger.kernel.org, linux-pci@atrey.karlin.mff.cuni.cz +Subject: PCI: legacy I/O port free driver - Changes to generic PCI code + +This patch adds the following changes into generic PCI code especially +for PCI legacy free drivers. + + - Moved the following two things from pci_enable_device() into + pci_enable_device_bars(). By this change, we can use + pci_enable_device_bars() to enable only the specific regions. + + o Call pci_fixup_device() on the device + o Set dev->is_enabled + + - Added new field 'bars_enabled' into struct pci_device to + remember which BARs already enabled. This new field is + initialized at pci_enable_device_bars() time and cleared + at pci_disable_device() time. + + - Changed pci_request_regions()/pci_release_regions() to + request/release only the regions which have already been + enabled. + + - Added helper routine pci_select_bars() which makes proper mask + of BARs from the specified resource type. This would be very + helpful for users of pci_enable_device_bars(). + +Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/pci/pci-driver.c | 3 ++- + drivers/pci/pci.c | 47 ++++++++++++++++++++++++++++++++++++++++------- + include/linux/pci.h | 2 ++ + 3 files changed, 44 insertions(+), 8 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/pci-driver.c ++++ gregkh-2.6/drivers/pci/pci-driver.c +@@ -291,7 +291,8 @@ static void pci_default_resume(struct pc + pci_restore_state(pci_dev); + /* if the device was enabled before suspend, reenable */ + if (pci_dev->is_enabled) +- retval = pci_enable_device(pci_dev); ++ retval = pci_enable_device_bars(pci_dev, ++ pci_dev->bars_enabled); + /* if the device was busmaster before the suspend, make it busmaster again */ + if (pci_dev->is_busmaster) + pci_set_master(pci_dev); +--- gregkh-2.6.orig/drivers/pci/pci.c ++++ gregkh-2.6/drivers/pci/pci.c +@@ -488,6 +488,9 @@ pci_enable_device_bars(struct pci_dev *d + err = pcibios_enable_device(dev, bars); + if (err < 0) + return err; ++ pci_fixup_device(pci_fixup_enable, dev); ++ dev->is_enabled = 1; ++ dev->bars_enabled = bars; + return 0; + } + +@@ -505,8 +508,6 @@ pci_enable_device(struct pci_dev *dev) + int err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); + if (err) + return err; +- pci_fixup_device(pci_fixup_enable, dev); +- dev->is_enabled = 1; + return 0; + } + +@@ -541,6 +542,7 @@ pci_disable_device(struct pci_dev *dev) + + pcibios_disable_device(dev); + dev->is_enabled = 0; ++ dev->bars_enabled = 0; + } + + /** +@@ -623,6 +625,12 @@ void pci_release_region(struct pci_dev * + { + if (pci_resource_len(pdev, bar) == 0) + return; ++ if (!(pdev->bars_enabled & (1 << bar))) { ++ dev_warn(&pdev->dev, ++ "Trying to release region #%d that is not enabled\n", ++ bar + 1); ++ return; ++ } + if (pci_resource_flags(pdev, bar) & IORESOURCE_IO) + release_region(pci_resource_start(pdev, bar), + pci_resource_len(pdev, bar)); +@@ -649,7 +657,12 @@ int pci_request_region(struct pci_dev *p + { + if (pci_resource_len(pdev, bar) == 0) + return 0; +- ++ if (!(pdev->bars_enabled & (1 << bar))) { ++ dev_warn(&pdev->dev, ++ "Trying to request region #%d that is not enabled\n", ++ bar + 1); ++ goto err_out; ++ } + if (pci_resource_flags(pdev, bar) & IORESOURCE_IO) { + if (!request_region(pci_resource_start(pdev, bar), + pci_resource_len(pdev, bar), res_name)) +@@ -687,7 +700,8 @@ void pci_release_regions(struct pci_dev + int i; + + for (i = 0; i < 6; i++) +- pci_release_region(pdev, i); ++ if (pdev->bars_enabled & (1 << i)) ++ pci_release_region(pdev, i); + } + + /** +@@ -708,13 +722,15 @@ int pci_request_regions(struct pci_dev * + int i; + + for (i = 0; i < 6; i++) +- if(pci_request_region(pdev, i, res_name)) +- goto err_out; ++ if (pdev->bars_enabled & (1 << i)) ++ if(pci_request_region(pdev, i, res_name)) ++ goto err_out; + return 0; + + err_out: + while(--i >= 0) +- pci_release_region(pdev, i); ++ if (pdev->bars_enabled & (1 << i)) ++ pci_release_region(pdev, i); + + return -EBUSY; + } +@@ -889,6 +905,22 @@ pci_set_consistent_dma_mask(struct pci_d + } + #endif + ++/** ++ * pci_select_bars - Make BAR mask from the type of resource ++ * @pdev: the PCI device for which BAR mask is made ++ * @flags: resource type mask to be selected ++ * ++ * This helper routine makes bar mask from the type of resource. ++ */ ++int pci_select_bars(struct pci_dev *dev, unsigned long flags) ++{ ++ int i, bars = 0; ++ for (i = 0; i < PCI_NUM_RESOURCES; i++) ++ if (pci_resource_flags(dev, i) & flags) ++ bars |= (1 << i); ++ return bars; ++} ++ + static int __devinit pci_init(void) + { + struct pci_dev *dev = NULL; +@@ -946,6 +978,7 @@ EXPORT_SYMBOL(pci_set_dma_mask); + EXPORT_SYMBOL(pci_set_consistent_dma_mask); + EXPORT_SYMBOL(pci_assign_resource); + EXPORT_SYMBOL(pci_find_parent_resource); ++EXPORT_SYMBOL(pci_select_bars); + + EXPORT_SYMBOL(pci_set_power_state); + EXPORT_SYMBOL(pci_save_state); +--- gregkh-2.6.orig/include/linux/pci.h ++++ gregkh-2.6/include/linux/pci.h +@@ -169,6 +169,7 @@ struct pci_dev { + struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */ + int rom_attr_enabled; /* has display of the rom attribute been enabled? */ + struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ ++ int bars_enabled; /* BARs enabled */ + }; + + #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list) +@@ -497,6 +498,7 @@ int pci_set_consistent_dma_mask(struct p + void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); + int pci_assign_resource(struct pci_dev *dev, int i); + void pci_restore_bars(struct pci_dev *dev); ++int pci_select_bars(struct pci_dev *dev, unsigned long flags); + + /* ROM control related routines */ + void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size); diff --git a/pci/pci-legacy-i-o-port-free-driver-make-emulex-lpfc-driver-legacy-i-o-port-free.patch b/pci/pci-legacy-i-o-port-free-driver-make-emulex-lpfc-driver-legacy-i-o-port-free.patch new file mode 100644 index 0000000000000..57e07c0570898 --- /dev/null +++ b/pci/pci-legacy-i-o-port-free-driver-make-emulex-lpfc-driver-legacy-i-o-port-free.patch @@ -0,0 +1,30 @@ +From kaneshige.kenji@jp.fujitsu.com Thu Mar 23 21:43:15 2006 +Message-ID: <44238546.6080401@jp.fujitsu.com> +Date: Fri, 24 Mar 2006 14:36:06 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <greg@kroah.com> +CC: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>, Andrew Morton <akpm@osdl.org> +Subject: PCI: legacy I/O port free driver - Make Emulex lpfc driver legacy I/O port free + +This patch makes Emulex lpfc driver legacy I/O port free. + +Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/scsi/lpfc/lpfc_init.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- gregkh-2.6.orig/drivers/scsi/lpfc/lpfc_init.c ++++ gregkh-2.6/drivers/scsi/lpfc/lpfc_init.c +@@ -1434,8 +1434,9 @@ lpfc_pci_probe_one(struct pci_dev *pdev, + int error = -ENODEV, retval; + int i; + uint16_t iotag; ++ int bars = pci_select_bars(pdev, IORESOURCE_MEM); + +- if (pci_enable_device(pdev)) ++ if (pci_enable_device_bars(pdev, bars)) + goto out; + if (pci_request_regions(pdev, LPFC_DRIVER_NAME)) + goto out_disable_device; diff --git a/pci/pci-legacy-i-o-port-free-driver-make-intel-e1000-driver-legacy-i-o-port-free.patch b/pci/pci-legacy-i-o-port-free-driver-make-intel-e1000-driver-legacy-i-o-port-free.patch new file mode 100644 index 0000000000000..b7c2bb66a63ba --- /dev/null +++ b/pci/pci-legacy-i-o-port-free-driver-make-intel-e1000-driver-legacy-i-o-port-free.patch @@ -0,0 +1,200 @@ +From kaneshige.kenji@jp.fujitsu.com Thu Mar 23 21:41:53 2006 +Message-ID: <442384EA.60606@jp.fujitsu.com> +Date: Fri, 24 Mar 2006 14:34:34 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <greg@kroah.com> +CC: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>, Andrew Morton <akpm@osdl.org> +Subject: PCI: legacy I/O port free driver - Make Intel e1000 driver legacy I/O port free + +This patch makes Intel e1000 driver legacy I/O port free. + +Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/net/e1000/e1000.h | 6 +- + drivers/net/e1000/e1000_main.c | 123 ++++++++++++++++++++++------------------- + 2 files changed, 71 insertions(+), 58 deletions(-) + +--- gregkh-2.6.orig/drivers/net/e1000/e1000.h ++++ gregkh-2.6/drivers/net/e1000/e1000.h +@@ -77,8 +77,9 @@ + #define BAR_1 1 + #define BAR_5 5 + +-#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\ +- PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} ++#define E1000_NO_IOPORT (1 << 0) ++#define INTEL_E1000_ETHERNET_DEVICE(device_id, flags) {\ ++ PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id), .driver_data = flags} + + struct e1000_adapter; + +@@ -338,6 +339,7 @@ struct e1000_adapter { + #ifdef NETIF_F_TSO + boolean_t tso_force; + #endif ++ int bars; /* BARs to be enabled */ + }; + + +--- gregkh-2.6.orig/drivers/net/e1000/e1000_main.c ++++ gregkh-2.6/drivers/net/e1000/e1000_main.c +@@ -86,54 +86,54 @@ static char e1000_copyright[] = "Copyrig + * {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} + */ + static struct pci_device_id e1000_pci_tbl[] = { +- INTEL_E1000_ETHERNET_DEVICE(0x1000), +- INTEL_E1000_ETHERNET_DEVICE(0x1001), +- INTEL_E1000_ETHERNET_DEVICE(0x1004), +- INTEL_E1000_ETHERNET_DEVICE(0x1008), +- INTEL_E1000_ETHERNET_DEVICE(0x1009), +- INTEL_E1000_ETHERNET_DEVICE(0x100C), +- INTEL_E1000_ETHERNET_DEVICE(0x100D), +- INTEL_E1000_ETHERNET_DEVICE(0x100E), +- INTEL_E1000_ETHERNET_DEVICE(0x100F), +- INTEL_E1000_ETHERNET_DEVICE(0x1010), +- INTEL_E1000_ETHERNET_DEVICE(0x1011), +- INTEL_E1000_ETHERNET_DEVICE(0x1012), +- INTEL_E1000_ETHERNET_DEVICE(0x1013), +- INTEL_E1000_ETHERNET_DEVICE(0x1014), +- INTEL_E1000_ETHERNET_DEVICE(0x1015), +- INTEL_E1000_ETHERNET_DEVICE(0x1016), +- INTEL_E1000_ETHERNET_DEVICE(0x1017), +- INTEL_E1000_ETHERNET_DEVICE(0x1018), +- INTEL_E1000_ETHERNET_DEVICE(0x1019), +- INTEL_E1000_ETHERNET_DEVICE(0x101A), +- INTEL_E1000_ETHERNET_DEVICE(0x101D), +- INTEL_E1000_ETHERNET_DEVICE(0x101E), +- INTEL_E1000_ETHERNET_DEVICE(0x1026), +- INTEL_E1000_ETHERNET_DEVICE(0x1027), +- INTEL_E1000_ETHERNET_DEVICE(0x1028), +- INTEL_E1000_ETHERNET_DEVICE(0x105E), +- INTEL_E1000_ETHERNET_DEVICE(0x105F), +- INTEL_E1000_ETHERNET_DEVICE(0x1060), +- INTEL_E1000_ETHERNET_DEVICE(0x1075), +- INTEL_E1000_ETHERNET_DEVICE(0x1076), +- INTEL_E1000_ETHERNET_DEVICE(0x1077), +- INTEL_E1000_ETHERNET_DEVICE(0x1078), +- INTEL_E1000_ETHERNET_DEVICE(0x1079), +- INTEL_E1000_ETHERNET_DEVICE(0x107A), +- INTEL_E1000_ETHERNET_DEVICE(0x107B), +- INTEL_E1000_ETHERNET_DEVICE(0x107C), +- INTEL_E1000_ETHERNET_DEVICE(0x107D), +- INTEL_E1000_ETHERNET_DEVICE(0x107E), +- INTEL_E1000_ETHERNET_DEVICE(0x107F), +- INTEL_E1000_ETHERNET_DEVICE(0x108A), +- INTEL_E1000_ETHERNET_DEVICE(0x108B), +- INTEL_E1000_ETHERNET_DEVICE(0x108C), +- INTEL_E1000_ETHERNET_DEVICE(0x1096), +- INTEL_E1000_ETHERNET_DEVICE(0x1098), +- INTEL_E1000_ETHERNET_DEVICE(0x1099), +- INTEL_E1000_ETHERNET_DEVICE(0x109A), +- INTEL_E1000_ETHERNET_DEVICE(0x10B5), +- INTEL_E1000_ETHERNET_DEVICE(0x10B9), ++ INTEL_E1000_ETHERNET_DEVICE(0x1000, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x1001, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x1004, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x1008, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1009, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x100C, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x100D, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x100E, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x100F, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1010, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1011, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1012, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1013, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1014, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x1015, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1016, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1017, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1018, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1019, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x101A, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x101D, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x101E, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1026, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x1027, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x1028, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x105E, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x105F, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x1060, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x1075, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x1076, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1077, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1078, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1079, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x107A, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x107B, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x107C, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x107D, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x107E, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x107F, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x108A, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x108B, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x108C, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x1096, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1098, 0), ++ INTEL_E1000_ETHERNET_DEVICE(0x1099, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x109A, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x10B5, E1000_NO_IOPORT), ++ INTEL_E1000_ETHERNET_DEVICE(0x10B9, 0), + /* required last entry */ + {0,} + }; +@@ -619,7 +619,14 @@ e1000_probe(struct pci_dev *pdev, + int i, err, pci_using_dac; + uint16_t eeprom_data; + uint16_t eeprom_apme_mask = E1000_EEPROM_APME; +- if ((err = pci_enable_device(pdev))) ++ int bars; ++ ++ if (ent->driver_data & E1000_NO_IOPORT) ++ bars = pci_select_bars(pdev, IORESOURCE_MEM); ++ else ++ bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO); ++ ++ if ((err = pci_enable_device_bars(pdev, bars))) + return err; + + if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { +@@ -652,6 +659,7 @@ e1000_probe(struct pci_dev *pdev, + adapter->pdev = pdev; + adapter->hw.back = adapter; + adapter->msg_enable = (1 << debug) - 1; ++ adapter->bars = bars; + + mmio_start = pci_resource_start(pdev, BAR_0); + mmio_len = pci_resource_len(pdev, BAR_0); +@@ -662,12 +670,15 @@ e1000_probe(struct pci_dev *pdev, + goto err_ioremap; + } + +- for (i = BAR_1; i <= BAR_5; i++) { +- if (pci_resource_len(pdev, i) == 0) +- continue; +- if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { +- adapter->hw.io_base = pci_resource_start(pdev, i); +- break; ++ if (!(ent->driver_data & E1000_NO_IOPORT)) { ++ for (i = BAR_1; i <= BAR_5; i++) { ++ if (pci_resource_len(pdev, i) == 0) ++ continue; ++ if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { ++ adapter->hw.io_base = ++ pci_resource_start(pdev, i); ++ break; ++ } + } + } + +@@ -4574,7 +4585,7 @@ e1000_resume(struct pci_dev *pdev) + if (retval) + DPRINTK(PROBE, ERR, "Error in setting power state\n"); + e1000_pci_restore_state(adapter); +- ret_val = pci_enable_device(pdev); ++ ret_val = pci_enable_device_bars(pdev, adapter->bars); + pci_set_master(pdev); + + retval = pci_enable_wake(pdev, PCI_D3hot, 0); diff --git a/pci/pci-legacy-i-o-port-free-driver-update-documentation-pci.txt.patch b/pci/pci-legacy-i-o-port-free-driver-update-documentation-pci.txt.patch new file mode 100644 index 0000000000000..7956dc154be83 --- /dev/null +++ b/pci/pci-legacy-i-o-port-free-driver-update-documentation-pci.txt.patch @@ -0,0 +1,92 @@ +From kaneshige.kenji@jp.fujitsu.com Thu Mar 23 21:39:19 2006 +Message-ID: <44238469.8080009@jp.fujitsu.com> +Date: Fri, 24 Mar 2006 14:32:25 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <greg@kroah.com> +CC: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>, Andrew Morton <akpm@osdl.org> +Subject: PCI: legacy I/O port free driver - Update Documentation/pci.txt + +This patch adds the description about legacy I/O port free driver into +Documentation/pci.txt. + +Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Signed-off-by: Grant Grundler <grundler@parisc-linux.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + Documentation/pci.txt | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 67 insertions(+) + +--- gregkh-2.6.orig/Documentation/pci.txt ++++ gregkh-2.6/Documentation/pci.txt +@@ -269,3 +269,70 @@ 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() ++ ++ ++9. Legacy I/O port free driver ++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++Large servers may not be able to provide I/O port resources to all PCI ++devices. I/O Port space is only 64KB on Intel Architecture[1] and is ++likely also fragmented since the I/O base register of PCI-to-PCI ++bridge will usually be aligned to a 4KB boundary[2]. On such systems, ++pci_enable_device() and pci_request_regions() will fail when ++attempting to enable I/O Port regions that don't have I/O Port ++resources assigned. ++ ++Fortunately, many PCI devices which request I/O Port resources also ++provide access to the same registers via MMIO BARs. These devices can ++be handled without using I/O port space and the drivers typically ++offer a CONFIG_ option to only use MMIO regions ++(e.g. CONFIG_TULIP_MMIO). PCI devices typically provide I/O port ++interface for legacy OSs and will work when I/O port resources are not ++assigned. The "PCI Local Bus Specification Revision 3.0" discusses ++this on p.44, "IMPLEMENTATION NOTE". ++ ++If your PCI device driver doesn't need I/O port resources assigned to ++I/O Port BARs, you should use pci_enable_device_bars() instead of ++pci_enable_device() in order not to enable I/O port regions for the ++corresponding devices. ++ ++[1] Some systems support 64KB I/O port space per PCI segment. ++[2] Some PCI-to-PCI bridges support optional 1KB aligned I/O base. ++ ++ ++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. Most drivers (e.g. tg3, acenic, sym53c8xx_2) ++already do. I/O Port space guarantees write transactions reach the PCI ++device before the CPU can continue. Writes to MMIO space allow to CPU ++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 it's 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 (aka "Soft Fail") and return garbage ++(e.g. ~0). But many RISC platforms will crash (aka "Hard Fail"). |