PCI fixes and PCI Express drivers for 2.6.11-rc1
Subsystems (2)
PATCH 1/1 PCI: add PCI Express Port Bus Driver subsystem
In reply to Greg KHChangeSet 1.2329.2.1, 2005/01/14 15:56:18-08:00, [email protected]
[PATCH] PCI: add PCI Express Port Bus Driver subsystem
Documentation/PCIEBUS-HOWTO.txt | 217 ++++++++++++++++++ arch/i386/Kconfig | 2 drivers/Makefile | 1 drivers/pci/hotplug/Kconfig | 21 - drivers/pci/hotplug/pciehp.h | 3 drivers/pci/hotplug/pciehp_core.c | 83 ++++-- drivers/pci/hotplug/pciehp_hpc.c | 21 - drivers/pci/pcie/Kconfig | 38 +++ drivers/pci/pcie/Makefile | 7 drivers/pci/pcie/portdrv.h | 42 +++ drivers/pci/pcie/portdrv_bus.c | 88 +++++++ drivers/pci/pcie/portdrv_core.c | 453 ++++++++++++++++++++++++++++++++++++++ drivers/pci/pcie/portdrv_pci.c | 138 +++++++++++ include/linux/pcieport_if.h | 74 ++++++ 14 files changed, 1123 insertions(+), 65 deletions(-)
Documentation/PCIEBUS-HOWTO.txt new file +217 -0
@@ -0,0 +1,217 @@ + The PCI Express Port Bus Driver Guide HOWTO + Tom L Nguyen [email protected] + 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.
arch/i386/Kconfig +2 -0
@@ -1132,6 +1132,8 @@ select ACPI_BOOT default y +source "drivers/pci/pcie/Kconfig" + source "drivers/pci/Kconfig" config ISA
drivers/Makefile +1 -0
@@ -55,6 +55,7 @@ obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_MD) += md/ obj-$(CONFIG_BT) += bluetooth/ +obj-$(CONFIG_PCIEPORTBUS) += pci/pcie/ obj-$(CONFIG_ISDN) += isdn/ obj-$(CONFIG_MCA) += mca/ obj-$(CONFIG_EISA) += eisa/
drivers/pci/hotplug/Kconfig +0 -21
@@ -134,27 +134,6 @@ When in doubt, say N. -config HOTPLUG_PCI_PCIE - tristate "PCI Express Hotplug driver" - depends on HOTPLUG_PCI - help - Say Y here if you have a motherboard that supports PCI Express Native - Hotplug - - To compile this driver as a module, choose M here: the - module will be called pciehp. - - When in doubt, say N. - -config HOTPLUG_PCI_PCIE_POLL_EVENT_MODE - bool "Use polling mechanism for hot-plug events (for testing purpose)" - depends on HOTPLUG_PCI_PCIE - help - Say Y here if you want to use the polling mechanism for hot-plug - events for early platform testing. - - When in doubt, say N. - config HOTPLUG_PCI_SHPC tristate "SHPC PCI Hotplug driver" depends on HOTPLUG_PCI
drivers/pci/hotplug/pciehp.h +2 -1
@@ -34,6 +34,7 @@#include <linux/delay.h> #include <asm/semaphore.h> #include <asm/io.h> +#include <linux/pcieport_if.h> #include "pci_hotplug.h" #define MY_NAME "pciehp"
@@ -311,7 +312,7 @@typedef u8 (*php_intr_callback_t ) (unsigned int change_id,void *instance_id); -int pcie_init(struct controller *ctrl, struct pci_dev *pdev, +int pcie_init(struct controller *ctrl, struct pcie_device *dev, php_intr_callback_t attention_button_callback, php_intr_callback_t switch_change_callback, php_intr_callback_t presence_change_callback,
drivers/pci/hotplug/pciehp_core.c +55 -28
132 lines not on this page · raw message
drivers/pci/hotplug/pciehp_hpc.c +6 -15
@@ -1249,7 +1249,7 @@ }; int pcie_init(struct controller * ctrl, - struct pci_dev *pdev, + struct pcie_device *dev, php_intr_callback_t attention_button_callback, php_intr_callback_t switch_change_callback, php_intr_callback_t presence_change_callback,
@@ -1265,6 +1265,7 @@u32 slot_cap;int cap_base, saved_cap_base;u16 slot_status, slot_ctrl; +struct pci_dev *pdev;DBG_ENTER_ROUTINE
@@ -1277,7 +1278,8 @@ }memset (php_ctlr,0 ,sizeof (struct php_ctlr_state_s )); - + + pdev = dev->port; php_ctlr->pci_dev = pdev;/* save pci_dev in context */ dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__,
@@ -1338,7 +1340,7 @@ }dbg ("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n" , pdev, pdev->bus->number, -PCI_SLOT (pdev->devfn),PCI_FUNC (pdev->devfn), pdev->irq); +PCI_SLOT (pdev->devfn),PCI_FUNC (pdev->devfn), dev->irq);for ( rc =0 ; rc <DEVICE_COUNT_RESOURCE ; rc++)if (pci_resource_len (pdev, rc) >0 ) dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc,
@@ -1355,7 +1357,7 @@init_waitqueue_head (&ctrl->queue);/* find the IRQ */ - php_ctlr->irq = pdev->irq; + php_ctlr->irq = dev->irq;dbg ("HPC interrupt = %d\n" , php_ctlr->irq);/* Save interrupt callback info */
@@ -1407,17 +1409,6 @@start_int_poll_timer ( php_ctlr,10 );/* start with 10 second delay */ }else {/* Installs the interrupt handler */ -dbg ("%s: pcie_mch_quirk = %x\n" , __FUNCTION__, pcie_mch_quirk); -if (!pcie_mch_quirk) { - rc =pci_enable_msi (pdev); -if (rc) { -info ("Can't get msi for the hotplug controller\n" ); -info ("Use INTx for the hotplug controller\n" ); -dbg ("%s: rc = %x\n" , __FUNCTION__, rc); - }else - php_ctlr->irq = pdev->irq; - } - rc =request_irq (php_ctlr->irq, pcie_isr,SA_SHIRQ ,MY_NAME , (void *) ctrl);dbg ("%s: request_irq %d for hpc%d (returns %d)\n" , __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);if (rc) {
drivers/pci/pcie/Kconfig new file +38 -0
@@ -0,0 +1,38 @@ +# +# PCI Express Port Bus Configuration +# +config PCIEPORTBUS + bool "PCI Express support" + depends on PCI_GOMMCONFIG || PCI_GOANY + default n + + ---help--- + This automatically enables PCI Express Port Bus support. Users can + choose Native Hot-Plug support, Advanced Error Reporting support, + Power Management Event support and Virtual Channel support to run + on PCI Express Ports (Root or Switch). + +# +# Include service Kconfig here +# +config HOTPLUG_PCI_PCIE + tristate "PCI Express Hotplug driver" + depends on HOTPLUG_PCI && PCIEPORTBUS + help + Say Y here if you have a motherboard that supports PCI Express Native + Hotplug + + To compile this driver as a module, choose M here: the + module will be called pciehp. + + When in doubt, say N. + +config HOTPLUG_PCI_PCIE_POLL_EVENT_MODE + bool "Use polling mechanism for hot-plug events (for testing purpose)" + depends on HOTPLUG_PCI_PCIE + help + Say Y here if you want to use the polling mechanism for hot-plug + events for early platform testing. + + When in doubt, say N. +
drivers/pci/pcie/Makefile new file +7 -0
@@ -0,0 +1,7 @@ +# +# Makefile for PCI-Express PORT Driver +# + +pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o + +obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
drivers/pci/pcie/portdrv.h new file +42 -0
42 lines not on this page · raw message
drivers/pci/pcie/portdrv_bus.c new file +88 -0
88 lines not on this page · raw message
drivers/pci/pcie/portdrv_core.c new file +453 -0
453 lines not on this page · raw message
drivers/pci/pcie/portdrv_pci.c new file +138 -0
138 lines not on this page · raw message
include/linux/pcieport_if.h new file +74 -0
74 lines not on this page · raw message
PCI: move pcie build into the drivers/pci/ subdirectory
In reply to Greg KHChangeSet 1.2329.2.9, 2005/01/17 10:06:44-08:00, [email protected]
PCI: move pcie build into the drivers/pci/ subdirectory
drivers/Makefile | 1 - drivers/pci/Makefile | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-)
drivers/Makefile +0 -1
@@ -55,7 +55,6 @@ obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_MD) += md/ obj-$(CONFIG_BT) += bluetooth/ -obj-$(CONFIG_PCIEPORTBUS) += pci/pcie/ obj-$(CONFIG_ISDN) += isdn/ obj-$(CONFIG_MCA) += mca/ obj-$(CONFIG_EISA) += eisa/
drivers/pci/Makefile +2 -0
@@ -56,4 +56,6 @@ # Files generated that shall be removed upon make clean clean-files := devlist.h classlist.h +# Build PCI Express stuff if needed +obj-$(CONFIG_PCIEPORTBUS) += pcie/
PATCH 1/1 PCI: Lock initializer cleanup - batch 4
In reply to Greg KHChangeSet 1.2329.2.7, 2005/01/14 15:58:57-08:00, [email protected]
[PATCH] PCI: Lock initializer cleanup - batch 4
Use the new lock initializers DEFINE_SPIN_LOCK and DEFINE_RW_LOCK
drivers/pci/access.c | 2 +- drivers/pci/msi.c | 2 +- drivers/pci/search.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
drivers/pci/access.c +1 -1
@@ -7,7 +7,7 @@* configuration space. */ -static spinlock_t pci_lock =SPIN_LOCK_UNLOCKED ; +static DEFINE_SPINLOCK (pci_lock);/* * Wrappers for all PCI configuration access functions. They just check
drivers/pci/msi.c +1 -1
@@ -22,7 +22,7 @@#include "msi.h" -static spinlock_t msi_lock =SPIN_LOCK_UNLOCKED ; +static DEFINE_SPINLOCK (msi_lock);static struct msi_desc * msi_desc[NR_IRQS ] = { [0 ...NR_IRQS -1 ] =NULL };static kmem_cache_t * msi_cachep;
drivers/pci/search.c +1 -1
@@ -13,7 +13,7 @@#include <linux/interrupt.h> #include "pci.h" -spinlock_t pci_bus_lock =SPIN_LOCK_UNLOCKED ; +DEFINE_SPINLOCK (pci_bus_lock);static struct pci_bus *__devinit pci_do_find_bus (struct pci_bus * bus,unsigned char busnr)
PATCH 1/1 PCI: rom.c cleanups
In reply to Greg KHChangeSet 1.2329.2.5, 2005/01/14 15:58:13-08:00, [email protected]
[PATCH] PCI: rom.c cleanups
Greg, here's some whitespace and long line cleanup I wanted to do last time I touched rom.c, but forgot. Does it look ok to you, Jon?
drivers/pci/rom.c | 80 +++++++++++++++++++++++++++--------------------------- 1 files changed, 41 insertions(+), 39 deletions(-)
drivers/pci/rom.c +41 -39
@@ -5,10 +5,7 @@* (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <[email protected]> * * PCI ROM access routines -* */ - -#include <linux/config.h> #include <linux/kernel.h> #include <linux/pci.h>
@@ -24,11 +21,10 @@* between the ROM and other resources, so enabling it may disable access * to MMIO registers or other card memory. */ -static void -pci_enable_rom (struct pci_dev *pdev) +static void pci_enable_rom (struct pci_dev *pdev) {u32 rom_addr; - +pci_read_config_dword (pdev, pdev->rom_base_reg, &rom_addr); rom_addr |=PCI_ROM_ADDRESS_ENABLE ;pci_write_config_dword (pdev, pdev->rom_base_reg, rom_addr);
@@ -41,8 +37,7 @@* Disable ROM decoding on a PCI device by turning off the last bit in the * ROM BAR. */ -static void -pci_disable_rom (struct pci_dev *pdev) +static void pci_disable_rom (struct pci_dev *pdev) {u32 rom_addr;pci_read_config_dword (pdev, pdev->rom_base_reg, &rom_addr);
@@ -57,7 +52,7 @@* @return: kernel virtual pointer to image of ROM * * Map a PCI ROM into kernel space. If ROM is boot video ROM, -* the shadow BIOS copy will be returned instead of the +* the shadow BIOS copy will be returned instead of the * actual ROM. */ void __iomem *pci_map_rom (struct pci_dev *pdev,size_t *size)
@@ -67,10 +62,12 @@void __iomem *rom;void __iomem *image;int last_image; - -if (res->flags &IORESOURCE_ROM_SHADOW ) {/* IORESOURCE_ROM_SHADOW only set on x86 */ - start = (loff_t )0xC0000 ;/* primary video rom always starts here */ - *size =0x20000 ;/* cover C000:0 through E000:0 */ + +/* IORESOURCE_ROM_SHADOW only set on x86 */ +if (res->flags &IORESOURCE_ROM_SHADOW ) { +/* primary video rom always starts here */ + start = (loff_t )0xC0000 ; + *size =0x20000 ;/* cover C000:0 through E000:0 */ }else {if (res->flags &IORESOURCE_ROM_COPY ) { *size =pci_resource_len (pdev,PCI_ROM_RESOURCE );
@@ -79,28 +76,32 @@/* assign the ROM an address if it doesn't have one */ if (res->parent ==NULL )pci_assign_resource (pdev,PCI_ROM_RESOURCE ); - + start =pci_resource_start (pdev,PCI_ROM_RESOURCE ); *size =pci_resource_len (pdev,PCI_ROM_RESOURCE );if (*size ==0 )return NULL ; - +/* Enable ROM space decodes */ pci_enable_rom (pdev); } } - + rom =ioremap (start, *size);if (!rom) {/* restore enable if ioremap fails */ -if (!(res->flags & (IORESOURCE_ROM_ENABLE |IORESOURCE_ROM_SHADOW |IORESOURCE_ROM_COPY ))) +if (!(res->flags & (IORESOURCE_ROM_ENABLE | +IORESOURCE_ROM_SHADOW | +IORESOURCE_ROM_COPY )))pci_disable_rom (pdev);return NULL ; - } + } -/* Try to find the true size of the ROM since sometimes the PCI window */ -/* size is much larger than the actual size of the ROM. */ -/* True size is important if the ROM is going to be copied. */ +/* +* Try to find the true size of the ROM since sometimes the PCI window +* size is much larger than the actual size of the ROM. +* True size is important if the ROM is going to be copied. +*/ image = rom; do { void __iomem *pds;
@@ -136,30 +137,30 @@* @return: kernel virtual pointer to image of ROM * * Map a PCI ROM into kernel space. If ROM is boot video ROM, -* the shadow BIOS copy will be returned instead of the +* the shadow BIOS copy will be returned instead of the * actual ROM. */ void __iomem *pci_map_rom_copy (struct pci_dev *pdev,size_t *size) {struct resource *res = &pdev->resource[PCI_ROM_RESOURCE ];void __iomem *rom; - + rom =pci_map_rom (pdev, size);if (!rom)return NULL ; - +if (res->flags & (IORESOURCE_ROM_COPY |IORESOURCE_ROM_SHADOW ))return rom; - + res->start = (unsigned long )kmalloc (*size,GFP_KERNEL ); -if (!res->start) +if (!res->start)return rom; - res->end = res->start + *size; + res->end = res->start + *size;memcpy_fromio ((void *)res->start, rom, *size);pci_unmap_rom (pdev, rom); res->flags |=IORESOURCE_ROM_COPY ; - +return (void __iomem *)res->start; }
@@ -170,16 +171,15 @@* * Remove a mapping of a previously mapped ROM */ -void -pci_unmap_rom (struct pci_dev *pdev,void __iomem *rom) +void pci_unmap_rom (struct pci_dev *pdev,void __iomem *rom) {struct resource *res = &pdev->resource[PCI_ROM_RESOURCE ];if (res->flags &IORESOURCE_ROM_COPY )return ; - +iounmap (rom); - +/* Disable again before continuing, leave enabled if pci=rom */ if (!(res->flags & (IORESOURCE_ROM_ENABLE |IORESOURCE_ROM_SHADOW )))pci_disable_rom (pdev);
@@ -189,26 +189,28 @@* pci_remove_rom - disable the ROM and remove its sysfs attribute * @dev: pointer to pci device struct * +* Remove the rom file in sysfs and disable ROM decoding. */ -void -pci_remove_rom (struct pci_dev *pdev) +void pci_remove_rom (struct pci_dev *pdev) {struct resource *res = &pdev->resource[PCI_ROM_RESOURCE ]; - +if (pci_resource_len (pdev,PCI_ROM_RESOURCE ))sysfs_remove_bin_file (&pdev->dev.kobj, pdev->rom_attr); -if (!(res->flags & (IORESOURCE_ROM_ENABLE |IORESOURCE_ROM_SHADOW |IORESOURCE_ROM_COPY ))) +if (!(res->flags & (IORESOURCE_ROM_ENABLE | +IORESOURCE_ROM_SHADOW | +IORESOURCE_ROM_COPY )))pci_disable_rom (pdev); }/** -* pci_cleanup_rom - internal routine for freeing the ROM copy created +* pci_cleanup_rom - internal routine for freeing the ROM copy created * by pci_map_rom_copy called from remove.c * @dev: pointer to pci device struct * +* Free the copied ROM if we allocated one. */ -void -pci_cleanup_rom (struct pci_dev *pdev) +void pci_cleanup_rom (struct pci_dev *pdev) {struct resource *res = &pdev->resource[PCI_ROM_RESOURCE ];if (res->flags &IORESOURCE_ROM_COPY ) {
PATCH 1/1 PCI: Downgrade printk that complains about unsupported PCI PM caps
ChangeSet 1.2329.2.6, 2005/01/14 15:58:36-08:00, [email protected]
[PATCH] PCI: Downgrade printk that complains about unsupported PCI PM caps
The attached patch downgrades to KERN_DEBUG level the printk that issues a notification that an unsupported version of the PCI power management registers has been encountered by pci_set_power_state().
drivers/pci/pci.c | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-)
drivers/pci/pci.c +1 -1
@@ -269,7 +269,7 @@pci_read_config_word (dev,pm +PCI_PM_PMC ,&pmc);if ((pmc &PCI_PM_CAP_VER_MASK ) !=2 ) { -printk (KERN_WARNING +printk (KERN_DEBUG "PCI: %s has unsupported PM cap regs version (%u)\n" , dev->slot_name, pmc &PCI_PM_CAP_VER_MASK );return -EIO ;
PATCH 1/1 PCI: pci_ids.h correction for Intel ICH7 - 2.6.10-bk13
In reply to Greg KHChangeSet 1.2329.2.3, 2005/01/14 15:57:26-08:00, [email protected]
[PATCH] PCI: pci_ids.h correction for Intel ICH7 - 2.6.10-bk13
This patch corrects the ICH7 LPC controller DID in pci_ids.h from x27B0 to x27B8. This patch was build against 2.6.10-bk13.
include/linux/pci_ids.h | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-)
include/linux/pci_ids.h +1 -1
@@ -2244,7 +2244,7 @@#define PCI_DEVICE_ID_INTEL_ICH6_17 0x266d#define PCI_DEVICE_ID_INTEL_ICH6_18 0x266e#define PCI_DEVICE_ID_INTEL_ICH6_19 0x266f -#define PCI_DEVICE_ID_INTEL_ICH7_0 0x27b0 +#define PCI_DEVICE_ID_INTEL_ICH7_0 0x27b8#define PCI_DEVICE_ID_INTEL_ICH7_1 0x27b1#define PCI_DEVICE_ID_INTEL_ICH7_2 0x27c0#define PCI_DEVICE_ID_INTEL_ICH7_3 0x27c1
PATCH 1/1 PCI fixes and PCI Express drivers for 2.6.11-rc1
Hi,
Here are some small PCI patches for 2.6.11-rc1, and the addition of a new PCI Express subsystem (it's self contained, if you don't have PCI Express, or select it, the code never gets built.) All of these patches have been in the past few -mm releases.
Please pull from:
bk://kernel.bkbits.net/gregkh/linux/pci-2.6
thanks,
greg k-h
p.s. I'll send these as patches in response to this email to lkml for those who want to see them.
Documentation/PCIEBUS-HOWTO.txt | 217 ++++++++++++++++++ arch/i386/Kconfig | 4 arch/i386/pci/pcbios.c | 4 drivers/Makefile | 2 drivers/pci/Makefile | 2 drivers/pci/access.c | 2 drivers/pci/hotplug/Kconfig | 21 - drivers/pci/hotplug/pciehp.h | 3 drivers/pci/hotplug/pciehp_core.c | 83 ++++-- drivers/pci/hotplug/pciehp_hpc.c | 21 - drivers/pci/msi.c | 39 +-- drivers/pci/pci.c | 2 drivers/pci/pci.h | 2 drivers/pci/pcie/Kconfig | 38 +++ drivers/pci/pcie/Makefile | 7 drivers/pci/pcie/portdrv.h | 42 +++ drivers/pci/pcie/portdrv_bus.c | 88 +++++++ drivers/pci/pcie/portdrv_core.c | 453 ++++++++++++++++++++++++++++++++++++++ drivers/pci/pcie/portdrv_pci.c | 138 +++++++++++ drivers/pci/probe.c | 10 drivers/pci/remove.c | 13 - drivers/pci/rom.c | 80 +++--- drivers/pci/search.c | 2 include/linux/pci_ids.h | 4 include/linux/pcieport_if.h | 74 ++++++ 25 files changed, 1209 insertions(+), 142 deletions(-)
-----
<jason.d.gaston:intel.com>:
o PCI: pci_ids.h correction for Intel ICH7 - 2.6.10-bk13
Bjorn Helgaas:
o PCI: use modern format for PCI addresses
David Howells:
o PCI: Downgrade printk that complains about unsupported PCI PM caps
Greg Kroah-Hartman:
o PCI: move pcie build into the drivers/pci/ subdirectory
Jesse Barnes:
o PCI: rom.c cleanups
John Rose:
o PCI: fix release_pcibus_dev() crash
Roland Dreier:
o PCI: Clean up printks in msi.c
Thomas Gleixner:
o PCI: Lock initializer cleanup - batch 4
Tom L. Nguyen:
o PCI: add PCI Express Port Bus Driver subsystem
PATCH 1/1 PCI: fix release_pcibus_dev() crash
In reply to Greg KHChangeSet 1.2329.2.8, 2005/01/14 15:59:20-08:00, [email protected]
[PATCH] PCI: fix release_pcibus_dev() crash
During the course of a hotplug removal of a PCI bus, release_pcibus_dev() attempts to remove attribute files from a kobject directory that no longer exists. This patch moves these calls to pci_remove_bus(), where they can work as intended.
drivers/pci/pci.h | 2 ++ drivers/pci/probe.c | 10 +++------- drivers/pci/remove.c | 13 ++++++++----- 3 files changed, 13 insertions(+), 12 deletions(-)
drivers/pci/pci.h +2 -0
@@ -59,12 +59,14 @@extern int pci_visit_dev (struct pci_visit *fn,struct pci_dev_wrapped *wrapped_dev,struct pci_bus_wrapped *wrapped_parent); +extern void pci_remove_legacy_files (struct pci_bus *bus);/* Lock for read/write access to pci device and bus lists */ extern spinlock_t pci_bus_lock;extern int pcie_mch_quirk;extern struct device_attribute pci_dev_attrs[]; +extern struct class_device_attribute class_device_attr_cpuaffinity;/** * pci_match_one_device - Tell if a PCI device structure has a matching
drivers/pci/probe.c +3 -7
@@ -62,7 +62,7 @@ } } -static void pci_remove_legacy_files (struct pci_bus *b) +void pci_remove_legacy_files (struct pci_bus *b) {class_device_remove_bin_file (&b->class_dev, b->legacy_io);class_device_remove_bin_file (&b->class_dev, b->legacy_mem);
@@ -70,7 +70,7 @@ }#else /* !HAVE_PCI_LEGACY */ static inline void pci_create_legacy_files (struct pci_bus *bus) {return ; } -static inline void pci_remove_legacy_files (struct pci_bus *bus) {return ; } +void pci_remove_legacy_files (struct pci_bus *bus) {return ; }#endif /* HAVE_PCI_LEGACY */ /*
@@ -86,7 +86,7 @@ buf[ret++] ='\n' ;return ret; } -static CLASS_DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL); +CLASS_DEVICE_ATTR (cpuaffinity,S_IRUGO , pci_bus_show_cpuaffinity,NULL );/* * PCI Bus Class
@@ -95,10 +95,6 @@ {struct pci_bus *pci_bus =to_pci_bus (class_dev); -pci_remove_legacy_files (pci_bus); -class_device_remove_file (&pci_bus->class_dev, - &class_device_attr_cpuaffinity); -sysfs_remove_link (&pci_bus->class_dev.kobj,"bridge" );if (pci_bus->bridge)put_device (pci_bus->bridge);kfree (pci_bus);
drivers/pci/remove.c +8 -5
@@ -61,15 +61,18 @@ }EXPORT_SYMBOL (pci_remove_device_safe); -void pci_remove_bus (struct pci_bus *b) +void pci_remove_bus (struct pci_bus *pci_bus) { -pci_proc_detach_bus (b); +pci_proc_detach_bus (pci_bus);spin_lock (&pci_bus_lock); -list_del (&b->node); +list_del (&pci_bus->node);spin_unlock (&pci_bus_lock); - -class_device_unregister (&b->class_dev); +pci_remove_legacy_files (pci_bus); +class_device_remove_file (&pci_bus->class_dev, + &class_device_attr_cpuaffinity); +sysfs_remove_link (&pci_bus->class_dev.kobj,"bridge" ); +class_device_unregister (&pci_bus->class_dev); }EXPORT_SYMBOL (pci_remove_bus);
PATCH 1/1 PCI: use modern format for PCI addresses
In reply to Greg KHChangeSet 1.2329.2.2, 2005/01/14 15:56:59-08:00, [email protected]
[PATCH] PCI: use modern format for PCI addresses
Use pci_name() rather than "%02x:%02x" when printing PCI address information.
arch/i386/pci/pcbios.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
arch/i386/pci/pcbios.c +2 -2
@@ -385,8 +385,8 @@ } }if (!found) { -printk (KERN_WARNING "PCI: Device %02x:%02x not found by BIOS\n" , - dev->bus->number, dev->devfn); +printk (KERN_WARNING "PCI: Device %s not found by BIOS\n" , +pci_name (dev));list_del (&dev->global_list);list_add_tail (&dev->global_list, &sorted_devices); }
PATCH 1/1 PCI: Clean up printks in msi.c
In reply to Greg KHChangeSet 1.2329.2.4, 2005/01/14 15:57:49-08:00, [email protected]
[PATCH] PCI: Clean up printks in msi.c
Add "PCI:" prefixes and fix up the formatting and grammar of printks in drivers/pci/msi.c. The main motivation was to fix the shouting "MSI INIT SUCCESS" message printed when an MSI-using driver is first started, but while we're at it we might as well tidy up all the messages.
drivers/pci/msi.c | 37 ++++++++++++++++++++----------------- 1 files changed, 20 insertions(+), 17 deletions(-)
drivers/pci/msi.c +20 -17
@@ -374,19 +374,18 @@if ((status =msi_cache_init ()) <0 ) { pci_msi_enable =0 ; -printk (KERN_INFO "WARNING: MSI INIT FAILURE\n" ); +printk (KERN_WARNING "PCI: MSI cache init failed\n" );return status; } last_alloc_vector =assign_irq_vector (AUTO_ASSIGN );if (last_alloc_vector <0 ) { pci_msi_enable =0 ; -printk (KERN_INFO "WARNING: ALL VECTORS ARE BUSY\n" ); +printk (KERN_WARNING "PCI: No interrupt vectors available for MSI\n" ); status = -EBUSY ;return status; } vector_irq[last_alloc_vector] =0 ; nr_released_vectors++; -printk (KERN_INFO "MSI INIT SUCCESS\n" );return status; }
@@ -736,7 +735,9 @@/* Check whether driver already requested for MSI-X vectors */ if ((pos =pci_find_capability (dev,PCI_CAP_ID_MSIX )) >0 && !msi_lookup_vector (dev,PCI_CAP_ID_MSIX )) { -printk (KERN_INFO "Can't enable MSI. Device already had MSI-X vectors assigned\n" ); +printk (KERN_INFO "PCI: %s: Can't enable MSI. " +"Device already has MSI-X vectors assigned\n" , +pci_name (dev)); dev->irq = temp;return -EINVAL ; }
@@ -774,9 +775,9 @@ }if (entry->msi_attrib.state) {spin_unlock_irqrestore (&msi_lock, flags); -printk (KERN_DEBUG "Driver[%d:%d:%d] unloaded wo doing free_irq on vector->%d\n" , - dev->bus->number,PCI_SLOT (dev->devfn),PCI_FUNC (dev->devfn), - dev->irq); +printk (KERN_WARNING "PCI: %s: pci_disable_msi() called without " +"free_irq() on MSI vector %d\n" , +pci_name (dev), dev->irq);BUG_ON (entry->msi_attrib.state >0 ); }else { vector_irq[dev->irq] =0 ;/* free it */
@@ -982,7 +983,9 @@/* Check whether driver already requested for MSI vector */ if (pci_find_capability (dev,PCI_CAP_ID_MSI ) >0 && !msi_lookup_vector (dev,PCI_CAP_ID_MSI )) { -printk (KERN_INFO "Can't enable MSI-X. Device already had MSI vector assigned\n" ); +printk (KERN_INFO "PCI: %s: Can't enable MSI-X. " +"Device already has an MSI vector assigned\n" , +pci_name (dev)); dev->irq = temp;return -EINVAL ; }
@@ -1050,9 +1053,9 @@spin_unlock_irqrestore (&msi_lock, flags);if (warning) { dev->irq = temp; -printk (KERN_DEBUG "Driver[%d:%d:%d] unloaded wo doing free_irq on all vectors\n" , - dev->bus->number,PCI_SLOT (dev->devfn), -PCI_FUNC (dev->devfn)); +printk (KERN_WARNING "PCI: %s: pci_disable_msix() called without " +"free_irq() on all MSI-X vectors\n" , +pci_name (dev));BUG_ON (warning >0 ); }else { dev->irq = temp;
@@ -1088,9 +1091,9 @@ state = msi_desc[dev->irq]->msi_attrib.state;spin_unlock_irqrestore (&msi_lock, flags);if (state) { -printk (KERN_DEBUG "Driver[%d:%d:%d] unloaded wo doing free_irq on vector->%d\n" , - dev->bus->number,PCI_SLOT (dev->devfn), -PCI_FUNC (dev->devfn), dev->irq); +printk (KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " +"called without free_irq() on MSI vector %d\n" , +pci_name (dev), dev->irq);BUG_ON (state >0 ); }else /* Release MSI vector assigned to this device */ msi_free_vector (dev, dev->irq,0 );
@@ -1132,9 +1135,9 @@iounmap (base);release_mem_region (phys_addr,PCI_MSIX_ENTRY_SIZE *multi_msix_capable (control)); -printk (KERN_DEBUG "Driver[%d:%d:%d] unloaded wo doing free_irq on all vectors\n" , - dev->bus->number,PCI_SLOT (dev->devfn), -PCI_FUNC (dev->devfn)); +printk (KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " +"called without free_irq() on all MSI-X vectors\n" , +pci_name (dev));BUG_ON (warning >0 ); } dev->irq = temp;/* Restore IOAPIC IRQ */
Re: [PATCH] PCI: add PCI Express Port Bus Driver subsystem
In reply to Greg KHQuoted 17 lines · Greg KH
drivers/pci/pcie/portdrv_core.c new file +17
-0+int pcie_port_device_register (struct pci_dev *dev) +{ +struct pcie_device *parent; +int status, type, capabilities, irq_mode, i; +int vectors[PCIE_PORT_DEVICE_MAXSERVICES ]; +u16 reg16; + +/* Get port type */ +pci_read_config_word (dev, +pci_find_capability (dev,PCI_CAP_ID_EXP ) + +PCIE_CAPABILITIES_REG , ®16); + type = (reg16 >>4 ) &PORT_TYPE_MASK ; + +/* Now get port services */ + capabilities =get_port_device_capability (dev); + irq_mode =assign_interrupt_mode (dev, vectors, capabilities); +
drivers/pci/pcie/portdrv_core.c line 318
Quoted 10 lines
drivers/pci/pcie/portdrv_core.c new file +10
-0+/* Allocate parent */ + parent =alloc_pcie_device (NULL , dev, type,0 , dev->irq, irq_mode); +if (!parent) +return -ENOMEM ; + + status =device_register (&parent->device); +if (status) { +kfree (parent); +return status; + }
This puts all of the pcie "port" structures in /sys/devices/ Shouldn't you make the parent of the device you create point to the pci_dev structure that's passed into this function? That would make the sysfs tree a lot saner I think.
thanks,
greg k-h