diff options
Diffstat (limited to 'drivers/pci')
43 files changed, 1419 insertions, 849 deletions
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 4b47f4e..af3bfe2 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -3,7 +3,8 @@ # obj-y += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \ - pci-driver.o search.o pci-sysfs.o rom.o setup-res.o + pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ + irq.o obj-$(CONFIG_PROC_FS) += proc.o # Build PCI Express stuff if needed diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 8b29c30..691b3ad 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -188,8 +188,7 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header) return 0; } -static int __init -dmar_parse_dev(struct dmar_drhd_unit *dmaru) +static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru) { struct acpi_dmar_hardware_unit *drhd; static int include_all; @@ -277,14 +276,15 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header) drhd = (struct acpi_dmar_hardware_unit *)header; printk (KERN_INFO PREFIX "DRHD (flags: 0x%08x)base: 0x%016Lx\n", - drhd->flags, drhd->address); + drhd->flags, (unsigned long long)drhd->address); break; case ACPI_DMAR_TYPE_RESERVED_MEMORY: rmrr = (struct acpi_dmar_reserved_memory *)header; printk (KERN_INFO PREFIX "RMRR base: 0x%016Lx end: 0x%016Lx\n", - rmrr->base_address, rmrr->end_address); + (unsigned long long)rmrr->base_address, + (unsigned long long)rmrr->end_address); break; } } @@ -328,7 +328,7 @@ parse_dmar_table(void) if (!dmar) return -ENODEV; - if (dmar->width < PAGE_SHIFT_4K - 1) { + if (dmar->width < PAGE_SHIFT - 1) { printk(KERN_WARNING PREFIX "Invalid DMAR haw\n"); return -EINVAL; } @@ -460,8 +460,8 @@ void __init detect_intel_iommu(void) ret = dmar_table_detect(); -#ifdef CONFIG_DMAR { +#ifdef CONFIG_INTR_REMAP struct acpi_table_dmar *dmar; /* * for now we will disable dma-remapping when interrupt @@ -470,29 +470,17 @@ void __init detect_intel_iommu(void) * is added, we will not need this any more. */ dmar = (struct acpi_table_dmar *) dmar_tbl; - if (ret && cpu_has_x2apic && dmar->flags & 0x1) { + if (ret && cpu_has_x2apic && dmar->flags & 0x1) printk(KERN_INFO "Queued invalidation will be enabled to support " "x2apic and Intr-remapping.\n"); - printk(KERN_INFO - "Disabling IOMMU detection, because of missing " - "queued invalidation support for IOTLB " - "invalidation\n"); - printk(KERN_INFO - "Use \"nox2apic\", if you want to use Intel " - " IOMMU for DMA-remapping and don't care about " - " x2apic support\n"); - - dmar_disabled = 1; - goto end; - } - +#endif +#ifdef CONFIG_DMAR if (ret && !no_iommu && !iommu_detected && !swiotlb && !dmar_disabled) iommu_detected = 1; - } -end: #endif + } dmar_tbl = NULL; } @@ -510,7 +498,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) iommu->seq_id = iommu_allocated++; - iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K); + iommu->reg = ioremap(drhd->reg_base_addr, VTD_PAGE_SIZE); if (!iommu->reg) { printk(KERN_ERR "IOMMU: can't map the region\n"); goto error; @@ -521,8 +509,8 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) /* the registers might be more than one page */ map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), cap_max_fault_reg_offset(iommu->cap)); - map_size = PAGE_ALIGN_4K(map_size); - if (map_size > PAGE_SIZE_4K) { + map_size = VTD_PAGE_ALIGN(map_size); + if (map_size > VTD_PAGE_SIZE) { iounmap(iommu->reg); iommu->reg = ioremap(drhd->reg_base_addr, map_size); if (!iommu->reg) { @@ -533,8 +521,10 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) ver = readl(iommu->reg + DMAR_VER_REG); pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", - drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), - iommu->cap, iommu->ecap); + (unsigned long long)drhd->reg_base_addr, + DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), + (unsigned long long)iommu->cap, + (unsigned long long)iommu->ecap); spin_lock_init(&iommu->register_lock); @@ -587,11 +577,11 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) hw = qi->desc; - spin_lock(&qi->q_lock); + spin_lock_irqsave(&qi->q_lock, flags); while (qi->free_cnt < 3) { - spin_unlock(&qi->q_lock); + spin_unlock_irqrestore(&qi->q_lock, flags); cpu_relax(); - spin_lock(&qi->q_lock); + spin_lock_irqsave(&qi->q_lock, flags); } index = qi->free_head; @@ -612,15 +602,22 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) qi->free_head = (qi->free_head + 2) % QI_LENGTH; qi->free_cnt -= 2; - spin_lock_irqsave(&iommu->register_lock, flags); + spin_lock(&iommu->register_lock); /* * update the HW tail register indicating the presence of * new descriptors. */ writel(qi->free_head << 4, iommu->reg + DMAR_IQT_REG); - spin_unlock_irqrestore(&iommu->register_lock, flags); + spin_unlock(&iommu->register_lock); while (qi->desc_status[wait_index] != QI_DONE) { + /* + * We will leave the interrupts disabled, to prevent interrupt + * context to queue another cmd while a cmd is already submitted + * and waiting for completion on this cpu. This is to avoid + * a deadlock where the interrupt context can wait indefinitely + * for free slots in the queue. + */ spin_unlock(&qi->q_lock); cpu_relax(); spin_lock(&qi->q_lock); @@ -629,7 +626,7 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) qi->desc_status[index] = QI_DONE; reclaim_free_desc(qi); - spin_unlock(&qi->q_lock); + spin_unlock_irqrestore(&qi->q_lock, flags); } /* @@ -645,6 +642,62 @@ void qi_global_iec(struct intel_iommu *iommu) qi_submit_sync(&desc, iommu); } +int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm, + u64 type, int non_present_entry_flush) +{ + + struct qi_desc desc; + + if (non_present_entry_flush) { + if (!cap_caching_mode(iommu->cap)) + return 1; + else + did = 0; + } + + desc.low = QI_CC_FM(fm) | QI_CC_SID(sid) | QI_CC_DID(did) + | QI_CC_GRAN(type) | QI_CC_TYPE; + desc.high = 0; + + qi_submit_sync(&desc, iommu); + + return 0; + +} + +int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, + unsigned int size_order, u64 type, + int non_present_entry_flush) +{ + u8 dw = 0, dr = 0; + + struct qi_desc desc; + int ih = 0; + + if (non_present_entry_flush) { + if (!cap_caching_mode(iommu->cap)) + return 1; + else + did = 0; + } + + if (cap_write_drain(iommu->cap)) + dw = 1; + + if (cap_read_drain(iommu->cap)) + dr = 1; + + desc.low = QI_IOTLB_DID(did) | QI_IOTLB_DR(dr) | QI_IOTLB_DW(dw) + | QI_IOTLB_GRAN(type) | QI_IOTLB_TYPE; + desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih) + | QI_IOTLB_AM(size_order); + + qi_submit_sync(&desc, iommu); + + return 0; + +} + /* * Enable Queued Invalidation interface. This is a must to support * interrupt-remapping. Also used by DMA-remapping, which replaces diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 5a58b07..9bcb6cb 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -50,9 +50,6 @@ #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) -/* name size which is used for entries in pcihpfs */ -#define SLOT_NAME_SIZE 20 /* {_SUN} */ - struct acpiphp_bridge; struct acpiphp_slot; @@ -63,9 +60,13 @@ struct slot { struct hotplug_slot *hotplug_slot; struct acpiphp_slot *acpi_slot; struct hotplug_slot_info info; - char name[SLOT_NAME_SIZE]; }; +static inline const char *slot_name(struct slot *slot) +{ + return hotplug_slot_name(slot->hotplug_slot); +} + /* * struct acpiphp_bridge - PCI bridge information * @@ -112,7 +113,7 @@ struct acpiphp_slot { u8 device; /* pci device# */ - u32 sun; /* ACPI _SUN (slot unique number) */ + unsigned long long sun; /* ACPI _SUN (slot unique number) */ u32 flags; /* see below */ }; diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 0e496e8..43c10bd 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -44,6 +44,9 @@ #define MY_NAME "acpiphp" +/* name size which is used for entries in pcihpfs */ +#define SLOT_NAME_SIZE 21 /* {_SUN} */ + static int debug; int acpiphp_debug; @@ -84,7 +87,6 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = { .get_adapter_status = get_adapter_status, }; - /** * acpiphp_register_attention - set attention LED callback * @info: must be completely filled with LED callbacks @@ -136,7 +138,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); /* enable the specified slot */ return acpiphp_enable_slot(slot->acpi_slot); @@ -154,7 +156,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) struct slot *slot = hotplug_slot->private; int retval; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); /* disable the specified slot */ retval = acpiphp_disable_slot(slot->acpi_slot); @@ -177,7 +179,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) { int retval = -ENODEV; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot)); if (attention_info && try_module_get(attention_info->owner)) { retval = attention_info->set_attn(hotplug_slot, status); @@ -200,7 +202,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = acpiphp_get_power_status(slot->acpi_slot); @@ -222,7 +224,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) { int retval = -EINVAL; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot)); if (attention_info && try_module_get(attention_info->owner)) { retval = attention_info->get_attn(hotplug_slot, value); @@ -245,7 +247,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = acpiphp_get_latch_status(slot->acpi_slot); @@ -265,7 +267,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = acpiphp_get_adapter_status(slot->acpi_slot); @@ -299,7 +301,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); kfree(slot->hotplug_slot); kfree(slot); @@ -310,6 +312,7 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) { struct slot *slot; int retval = -ENOMEM; + char name[SLOT_NAME_SIZE]; slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) @@ -321,8 +324,6 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) slot->hotplug_slot->info = &slot->info; - slot->hotplug_slot->name = slot->name; - slot->hotplug_slot->private = slot; slot->hotplug_slot->release = &release_slot; slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; @@ -336,11 +337,12 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; acpiphp_slot->slot = slot; - snprintf(slot->name, sizeof(slot->name), "%u", slot->acpi_slot->sun); + snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun); retval = pci_hp_register(slot->hotplug_slot, acpiphp_slot->bridge->pci_bus, - acpiphp_slot->device); + acpiphp_slot->device, + name); if (retval == -EBUSY) goto error_hpslot; if (retval) { @@ -348,7 +350,7 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) goto error_hpslot; } - info("Slot [%s] registered\n", slot->hotplug_slot->name); + info("Slot [%s] registered\n", slot_name(slot)); return 0; error_hpslot: @@ -365,7 +367,7 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot) struct slot *slot = acpiphp_slot->slot; int retval = 0; - info ("Slot [%s] unregistered\n", slot->hotplug_slot->name); + info("Slot [%s] unregistered\n", slot_name(slot)); retval = pci_hp_deregister(slot->hotplug_slot); if (retval) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a3e4705..3affc64 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -169,7 +169,9 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val, } - +static struct acpi_dock_ops acpiphp_dock_ops = { + .handler = handle_hotplug_event_func, +}; /* callback routine to register each ACPI PCI slot object */ static acpi_status @@ -180,7 +182,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) struct acpiphp_func *newfunc; acpi_handle tmp; acpi_status status = AE_OK; - unsigned long adr, sun; + unsigned long long adr, sun; int device, function, retval; status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); @@ -253,13 +255,13 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) bridge->nr_slots++; - dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n", + dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", slot->sun, pci_domain_nr(bridge->pci_bus), bridge->pci_bus->number, slot->device); retval = acpiphp_register_hotplug_slot(slot); if (retval) { if (retval == -EBUSY) - warn("Slot %d already registered by another " + warn("Slot %llu already registered by another " "hotplug driver\n", slot->sun); else warn("acpiphp_register_hotplug_slot failed " @@ -285,7 +287,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) */ newfunc->flags &= ~FUNC_HAS_EJ0; if (register_hotplug_dock_device(handle, - handle_hotplug_event_func, newfunc)) + &acpiphp_dock_ops, newfunc)) dbg("failed to register dock device\n"); /* we need to be notified when dock events happen @@ -528,7 +530,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_status status; acpi_handle dummy_handle; - unsigned long tmp; + unsigned long long tmp; int device, function; struct pci_dev *dev; struct pci_bus *pci_bus = context; @@ -573,7 +575,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) static int add_bridge(acpi_handle handle) { acpi_status status; - unsigned long tmp; + unsigned long long tmp; int seg, bus; acpi_handle dummy_handle; struct pci_bus *pci_bus; @@ -767,7 +769,7 @@ static int get_gsi_base(acpi_handle handle, u32 *gsi_base) { acpi_status status; int result = -1; - unsigned long gsb; + unsigned long long gsb; struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *obj; void *table; @@ -808,7 +810,7 @@ static acpi_status ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_status status; - unsigned long sta; + unsigned long long sta; acpi_handle tmp; struct pci_dev *pdev; u32 gsi_base; @@ -872,7 +874,7 @@ static acpi_status ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_status status; - unsigned long sta; + unsigned long long sta; acpi_handle tmp; u32 gsi_base; struct acpiphp_ioapic *pos, *n, *ioapic = NULL; @@ -1264,7 +1266,7 @@ static int disable_device(struct acpiphp_slot *slot) static unsigned int get_slot_status(struct acpiphp_slot *slot) { acpi_status status; - unsigned long sta = 0; + unsigned long long sta = 0; u32 dvid; struct list_head *l; struct acpiphp_func *func; diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 2b7c45e..881fdd2 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -183,7 +183,7 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status) union acpi_object args[2]; struct acpi_object_list params = { .pointer = args, .count = 2 }; acpi_status stat; - unsigned long rc; + unsigned long long rc; union apci_descriptor *ibm_slot; ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot)); @@ -204,7 +204,7 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status) err("APLS evaluation failed: 0x%08x\n", stat); return -ENODEV; } else if (!rc) { - err("APLS method failed: 0x%08lx\n", rc); + err("APLS method failed: 0x%08llx\n", rc); return -ERANGE; } return 0; diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h index d9769b3..9fff878 100644 --- a/drivers/pci/hotplug/cpci_hotplug.h +++ b/drivers/pci/hotplug/cpci_hotplug.h @@ -30,6 +30,7 @@ #include <linux/types.h> #include <linux/pci.h> +#include <linux/pci_hotplug.h> /* PICMG 2.1 R2.0 HS CSR bits: */ #define HS_CSR_INS 0x0080 @@ -69,6 +70,11 @@ struct cpci_hp_controller { struct cpci_hp_controller_ops *ops; }; +static inline const char *slot_name(struct slot *slot) +{ + return hotplug_slot_name(slot->hotplug_slot); +} + extern int cpci_hp_register_controller(struct cpci_hp_controller *controller); extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller); extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last); diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index 9359479..de94f4f 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c @@ -108,7 +108,7 @@ enable_slot(struct hotplug_slot *hotplug_slot) struct slot *slot = hotplug_slot->private; int retval = 0; - dbg("%s - physical_slot = %s", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s", __func__, slot_name(slot)); if (controller->ops->set_power) retval = controller->ops->set_power(slot, 1); @@ -121,25 +121,23 @@ disable_slot(struct hotplug_slot *hotplug_slot) struct slot *slot = hotplug_slot->private; int retval = 0; - dbg("%s - physical_slot = %s", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s", __func__, slot_name(slot)); down_write(&list_rwsem); /* Unconfigure device */ - dbg("%s - unconfiguring slot %s", - __func__, slot->hotplug_slot->name); + dbg("%s - unconfiguring slot %s", __func__, slot_name(slot)); if ((retval = cpci_unconfigure_slot(slot))) { err("%s - could not unconfigure slot %s", - __func__, slot->hotplug_slot->name); + __func__, slot_name(slot)); goto disable_error; } - dbg("%s - finished unconfiguring slot %s", - __func__, slot->hotplug_slot->name); + dbg("%s - finished unconfiguring slot %s", __func__, slot_name(slot)); /* Clear EXT (by setting it) */ if (cpci_clear_ext(slot)) { err("%s - could not clear EXT for slot %s", - __func__, slot->hotplug_slot->name); + __func__, slot_name(slot)); retval = -ENODEV; goto disable_error; } @@ -214,7 +212,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot) struct slot *slot = hotplug_slot->private; kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); if (slot->dev) pci_dev_put(slot->dev); @@ -222,12 +219,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot) } #define SLOT_NAME_SIZE 6 -static void -make_slot_name(struct slot *slot) -{ - snprintf(slot->hotplug_slot->name, - SLOT_NAME_SIZE, "%02x:%02x", slot->bus->number, slot->number); -} int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) @@ -235,7 +226,7 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) struct slot *slot; struct hotplug_slot *hotplug_slot; struct hotplug_slot_info *info; - char *name; + char name[SLOT_NAME_SIZE]; int status = -ENOMEM; int i; @@ -262,34 +253,31 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) goto error_hpslot; hotplug_slot->info = info; - name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!name) - goto error_info; - hotplug_slot->name = name; - slot->bus = bus; slot->number = i; slot->devfn = PCI_DEVFN(i, 0); + snprintf(name, SLOT_NAME_SIZE, "%02x:%02x", bus->number, i); + hotplug_slot->private = slot; hotplug_slot->release = &release_slot; - make_slot_name(slot); hotplug_slot->ops = &cpci_hotplug_slot_ops; /* * Initialize the slot info structure with some known * good values. */ - dbg("initializing slot %s", slot->hotplug_slot->name); + dbg("initializing slot %s", name); info->power_status = cpci_get_power_status(slot); info->attention_status = cpci_get_attention_status(slot); - dbg("registering slot %s", slot->hotplug_slot->name); - status = pci_hp_register(slot->hotplug_slot, bus, i); + dbg("registering slot %s", name); + status = pci_hp_register(slot->hotplug_slot, bus, i, name); if (status) { err("pci_hp_register failed with error %d", status); - goto error_name; + goto error_info; } + dbg("slot registered with name: %s", slot_name(slot)); /* Add slot to our internal list */ down_write(&list_rwsem); @@ -298,8 +286,6 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) up_write(&list_rwsem); } return 0; -error_name: - kfree(name); error_info: kfree(info); error_hpslot: @@ -327,7 +313,7 @@ cpci_hp_unregister_bus(struct pci_bus *bus) list_del(&slot->slot_list); slots--; - dbg("deregistering slot %s", slot->hotplug_slot->name); + dbg("deregistering slot %s", slot_name(slot)); status = pci_hp_deregister(slot->hotplug_slot); if (status) { err("pci_hp_deregister failed with error %d", @@ -379,11 +365,10 @@ init_slots(int clear_ins) return -1; } list_for_each_entry(slot, &slot_list, slot_list) { - dbg("%s - looking at slot %s", - __func__, slot->hotplug_slot->name); + dbg("%s - looking at slot %s", __func__, slot_name(slot)); if (clear_ins && cpci_check_and_clear_ins(slot)) dbg("%s - cleared INS for slot %s", - __func__, slot->hotplug_slot->name); + __func__, slot_name(slot)); dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0)); if (dev) { if (update_adapter_status(slot->hotplug_slot, 1)) @@ -414,8 +399,7 @@ check_slots(void) } extracted = inserted = 0; list_for_each_entry(slot, &slot_list, slot_list) { - dbg("%s - looking at slot %s", - __func__, slot->hotplug_slot->name); + dbg("%s - looking at slot %s", __func__, slot_name(slot)); if (cpci_check_and_clear_ins(slot)) { /* * Some broken hardware (e.g. PLX 9054AB) asserts @@ -423,35 +407,34 @@ check_slots(void) */ if (slot->dev) { warn("slot %s already inserted", - slot->hotplug_slot->name); + slot_name(slot)); inserted++; continue; } /* Process insertion */ - dbg("%s - slot %s inserted", - __func__, slot->hotplug_slot->name); + dbg("%s - slot %s inserted", __func__, slot_name(slot)); /* GSM, debug */ hs_csr = cpci_get_hs_csr(slot); dbg("%s - slot %s HS_CSR (1) = %04x", - __func__, slot->hotplug_slot->name, hs_csr); + __func__, slot_name(slot), hs_csr); /* Configure device */ dbg("%s - configuring slot %s", - __func__, slot->hotplug_slot->name); + __func__, slot_name(slot)); if (cpci_configure_slot(slot)) { err("%s - could not configure slot %s", - __func__, slot->hotplug_slot->name); + __func__, slot_name(slot)); continue; } dbg("%s - finished configuring slot %s", - __func__, slot->hotplug_slot->name); + __func__, slot_name(slot)); /* GSM, debug */ hs_csr = cpci_get_hs_csr(slot); dbg("%s - slot %s HS_CSR (2) = %04x", - __func__, slot->hotplug_slot->name, hs_csr); + __func__, slot_name(slot), hs_csr); if (update_latch_status(slot->hotplug_slot, 1)) warn("failure to update latch file"); @@ -464,18 +447,18 @@ check_slots(void) /* GSM, debug */ hs_csr = cpci_get_hs_csr(slot); dbg("%s - slot %s HS_CSR (3) = %04x", - __func__, slot->hotplug_slot->name, hs_csr); + __func__, slot_name(slot), hs_csr); inserted++; } else if (cpci_check_ext(slot)) { /* Process extraction request */ dbg("%s - slot %s extracted", - __func__, slot->hotplug_slot->name); + __func__, slot_name(slot)); /* GSM, debug */ hs_csr = cpci_get_hs_csr(slot); dbg("%s - slot %s HS_CSR = %04x", - __func__, slot->hotplug_slot->name, hs_csr); + __func__, slot_name(slot), hs_csr); if (!slot->extracting) { if (update_latch_status(slot->hotplug_slot, 0)) { @@ -493,7 +476,7 @@ check_slots(void) * bother trying to tell the driver or not? */ err("card in slot %s was improperly removed", - slot->hotplug_slot->name); + slot_name(slot)); if (update_adapter_status(slot->hotplug_slot, 0)) warn("failure to update adapter file"); slot->extracting = 0; diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index df82b95..829c327 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -209,7 +209,7 @@ int cpci_led_on(struct slot* slot) hs_cap + 2, hs_csr)) { err("Could not set LOO for slot %s", - slot->hotplug_slot->name); + hotplug_slot_name(slot->hotplug_slot)); return -ENODEV; } } @@ -238,7 +238,7 @@ int cpci_led_off(struct slot* slot) hs_cap + 2, hs_csr)) { err("Could not clear LOO for slot %s", - slot->hotplug_slot->name); + hotplug_slot_name(slot->hotplug_slot)); return -ENODEV; } } diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index b1decfa..afaf8f6 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h @@ -449,6 +449,11 @@ extern u8 cpqhp_disk_irq; /* inline functions */ +static inline char *slot_name(struct slot *slot) +{ + return hotplug_slot_name(slot->hotplug_slot); +} + /* * return_resource * @@ -696,14 +701,6 @@ static inline int get_presence_status(struct controller *ctrl, struct slot *slot return presence_save; } -#define SLOT_NAME_SIZE 10 - -static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) -{ - snprintf(buffer, buffer_size, "%d", slot->number); -} - - static inline int wait_for_ctrl_irq(struct controller *ctrl) { DECLARE_WAITQUEUE(wait, current); diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 54defec..8514c3a 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -315,14 +315,15 @@ static void release_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } +#define SLOT_NAME_SIZE 10 + static int ctrl_slot_setup(struct controller *ctrl, void __iomem *smbios_start, void __iomem *smbios_table) @@ -335,6 +336,7 @@ static int ctrl_slot_setup(struct controller *ctrl, u8 slot_number; u8 ctrl_slot; u32 tempdword; + char name[SLOT_NAME_SIZE]; void __iomem *slot_entry= NULL; int result = -ENOMEM; @@ -363,16 +365,12 @@ static int ctrl_slot_setup(struct controller *ctrl, if (!hotplug_slot->info) goto error_hpslot; hotplug_slot_info = hotplug_slot->info; - hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); - - if (!hotplug_slot->name) - goto error_info; slot->ctrl = ctrl; slot->bus = ctrl->bus; slot->device = slot_device; slot->number = slot_number; - dbg("slot->number = %d\n", slot->number); + dbg("slot->number = %u\n", slot->number); slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, slot_entry); @@ -418,9 +416,9 @@ static int ctrl_slot_setup(struct controller *ctrl, /* register this slot with the hotplug pci core */ hotplug_slot->release = &release_slot; hotplug_slot->private = slot; - make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot); + snprintf(name, SLOT_NAME_SIZE, "%u", slot->number); hotplug_slot->ops = &cpqphp_hotplug_slot_ops; - + hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot); hotplug_slot_info->attention_status = cpq_get_attention_status(ctrl, slot); @@ -435,11 +433,12 @@ static int ctrl_slot_setup(struct controller *ctrl, slot->number, ctrl->slot_device_offset, slot_number); result = pci_hp_register(hotplug_slot, - ctrl->pci_dev->subordinate, - slot->device); + ctrl->pci_dev->bus, + slot->device, + name); if (result) { err("pci_hp_register failed with error %d\n", result); - goto error_name; + goto error_info; } slot->next = ctrl->slot; @@ -451,8 +450,6 @@ static int ctrl_slot_setup(struct controller *ctrl, } return 0; -error_name: - kfree(hotplug_slot->name); error_info: kfree(hotplug_slot_info); error_hpslot: @@ -638,7 +635,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) u8 device; u8 function; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) return -ENODEV; @@ -665,7 +662,7 @@ static int process_SI(struct hotplug_slot *hotplug_slot) u8 device; u8 function; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) return -ENODEV; @@ -697,7 +694,7 @@ static int process_SS(struct hotplug_slot *hotplug_slot) u8 device; u8 function; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) return -ENODEV; @@ -720,7 +717,7 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value) struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); return cpqhp_hardware_test(ctrl, value); } @@ -731,7 +728,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = get_slot_enabled(ctrl, slot); return 0; @@ -742,7 +739,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = cpq_get_attention_status(ctrl, slot); return 0; @@ -753,7 +750,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = cpq_get_latch_status(ctrl, slot); @@ -765,7 +762,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = get_presence_status(ctrl, slot); @@ -777,7 +774,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = ctrl->speed_capability; @@ -789,7 +786,7 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = ctrl->speed; diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index ef041ca..a60a252 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -1139,7 +1139,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ for(slot = ctrl->slot; slot; slot = slot->next) { if (slot->device == (hp_slot + ctrl->slot_device_offset)) continue; - if (!slot->hotplug_slot && !slot->hotplug_slot->info) + if (!slot->hotplug_slot || !slot->hotplug_slot->info) continue; if (slot->hotplug_slot->info->adapter_status == 0) continue; diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 146ca9c..3a2637a 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -66,10 +66,10 @@ struct dummy_slot { struct pci_dev *dev; struct work_struct remove_work; unsigned long removed; - char name[8]; }; static int debug; +static int dup_slots; static LIST_HEAD(slot_list); static struct workqueue_struct *dummyphp_wq; @@ -96,10 +96,13 @@ static void dummy_release(struct hotplug_slot *slot) kfree(dslot); } +#define SLOT_NAME_SIZE 8 + static int add_slot(struct pci_dev *dev) { struct dummy_slot *dslot; struct hotplug_slot *slot; + char name[SLOT_NAME_SIZE]; int retval = -ENOMEM; static int count = 1; @@ -119,19 +122,22 @@ static int add_slot(struct pci_dev *dev) if (!dslot) goto error_info; - slot->name = dslot->name; - snprintf(slot->name, sizeof(dslot->name), "fake%d", count++); - dbg("slot->name = %s\n", slot->name); + if (dup_slots) + snprintf(name, SLOT_NAME_SIZE, "fake"); + else + snprintf(name, SLOT_NAME_SIZE, "fake%d", count++); + dbg("slot->name = %s\n", name); slot->ops = &dummy_hotplug_slot_ops; slot->release = &dummy_release; slot->private = dslot; - retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn)); + retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn), name); if (retval) { err("pci_hp_register failed with error %d\n", retval); goto error_dslot; } + dbg("slot->name = %s\n", hotplug_slot_name(slot)); dslot->slot = slot; dslot->dev = pci_dev_get(dev); list_add (&dslot->node, &slot_list); @@ -167,10 +173,11 @@ static void remove_slot(struct dummy_slot *dslot) { int retval; - dbg("removing slot %s\n", dslot->slot->name); + dbg("removing slot %s\n", hotplug_slot_name(dslot->slot)); retval = pci_hp_deregister(dslot->slot); if (retval) - err("Problem unregistering a slot %s\n", dslot->slot->name); + err("Problem unregistering a slot %s\n", + hotplug_slot_name(dslot->slot)); } /* called from the single-threaded workqueue handler to remove a slot */ @@ -308,7 +315,7 @@ static int disable_slot(struct hotplug_slot *slot) return -ENODEV; dslot = slot->private; - dbg("%s - physical_slot = %s\n", __func__, slot->name); + dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(slot)); for (func = 7; func >= 0; func--) { dev = pci_get_slot(dslot->dev->bus, dslot->dev->devfn + func); @@ -373,4 +380,5 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); - +module_param(dup_slots, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(dup_slots, "Force duplicate slot names for debugging"); diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h index 612d963..a8d391a 100644 --- a/drivers/pci/hotplug/ibmphp.h +++ b/drivers/pci/hotplug/ibmphp.h @@ -707,17 +707,16 @@ struct slot { u8 device; u8 number; u8 real_physical_slot_num; - char name[100]; u32 capabilities; u8 supported_speed; u8 supported_bus_mode; + u8 flag; /* this is for disable slot and polling */ + u8 ctlr_index; struct hotplug_slot *hotplug_slot; struct controller *ctrl; struct pci_func *func; u8 irq[4]; - u8 flag; /* this is for disable slot and polling */ int bit_mode; /* 0 = 32, 1 = 64 */ - u8 ctlr_index; struct bus_info *bus_on; struct list_head ibm_slot_list; u8 status; diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index c892daa..633e743 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -1402,10 +1402,6 @@ static int __init ibmphp_init(void) goto error; } - /* lock ourselves into memory with a module - * count of -1 so that no one can unload us. */ - module_put(THIS_MODULE); - exit: return rc; @@ -1423,4 +1419,3 @@ static void __exit ibmphp_exit(void) } module_init(ibmphp_init); -module_exit(ibmphp_exit); diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index 8cfd1c4..c1abac8 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c @@ -587,11 +587,14 @@ static u8 calculate_first_slot (u8 slot_num) return first_slot + 1; } + +#define SLOT_NAME_SIZE 30 + static char *create_file_name (struct slot * slot_cur) { struct opt_rio *opt_vg_ptr = NULL; struct opt_rio_lo *opt_lo_ptr = NULL; - static char str[30]; + static char str[SLOT_NAME_SIZE]; int which = 0; /* rxe = 1, chassis = 0 */ u8 number = 1; /* either chassis or rxe # */ u8 first_slot = 1; @@ -703,7 +706,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot) slot = hotplug_slot->private; kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); slot->ctrl = NULL; slot->bus_on = NULL; @@ -734,6 +736,7 @@ static int __init ebda_rsrc_controller (void) struct bus_info *bus_info_ptr1, *bus_info_ptr2; int rc; struct slot *tmp_slot; + char name[SLOT_NAME_SIZE]; addr = hpc_list_ptr->phys_addr; for (ctlr = 0; ctlr < hpc_list_ptr->num_ctlrs; ctlr++) { @@ -897,12 +900,6 @@ static int __init ebda_rsrc_controller (void) goto error_no_hp_info; } - hp_slot_ptr->name = kmalloc(30, GFP_KERNEL); - if (!hp_slot_ptr->name) { - rc = -ENOMEM; - goto error_no_hp_name; - } - tmp_slot = kzalloc(sizeof(*tmp_slot), GFP_KERNEL); if (!tmp_slot) { rc = -ENOMEM; @@ -964,9 +961,9 @@ static int __init ebda_rsrc_controller (void) } /* each hpc */ list_for_each_entry(tmp_slot, &ibmphp_slot_head, ibm_slot_list) { - snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot)); + snprintf(name, SLOT_NAME_SIZE, "%s", create_file_name(tmp_slot)); pci_hp_register(tmp_slot->hotplug_slot, - pci_find_bus(0, tmp_slot->bus), tmp_slot->device); + pci_find_bus(0, tmp_slot->bus), tmp_slot->device, name); } print_ebda_hpc (); @@ -976,8 +973,6 @@ static int __init ebda_rsrc_controller (void) error: kfree (hp_slot_ptr->private); error_no_slot: - kfree (hp_slot_ptr->name); -error_no_hp_name: kfree (hp_slot_ptr->info); error_no_hp_info: kfree (hp_slot_ptr); diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 2e6c447..535fce0f 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -37,6 +37,7 @@ #include <linux/init.h> #include <linux/mount.h> #include <linux/namei.h> +#include <linux/mutex.h> #include <linux/pci.h> #include <linux/pci_hotplug.h> #include <asm/uaccess.h> @@ -61,7 +62,7 @@ static int debug; ////////////////////////////////////////////////////////////////// static LIST_HEAD(pci_hotplug_slot_list); -static DEFINE_SPINLOCK(pci_hotplug_slot_list_lock); +static DEFINE_MUTEX(pci_hp_mutex); /* these strings match up with the values in pci_bus_speed */ static char *pci_bus_speed_strings[] = { @@ -530,16 +531,12 @@ static struct hotplug_slot *get_slot_from_name (const char *name) struct hotplug_slot *slot; struct list_head *tmp; - spin_lock(&pci_hotplug_slot_list_lock); list_for_each (tmp, &pci_hotplug_slot_list) { slot = list_entry (tmp, struct hotplug_slot, slot_list); - if (strcmp(slot->name, name) == 0) - goto out; + if (strcmp(hotplug_slot_name(slot), name) == 0) + return slot; } - slot = NULL; -out: - spin_unlock(&pci_hotplug_slot_list_lock); - return slot; + return NULL; } /** @@ -547,13 +544,15 @@ out: * @bus: bus this slot is on * @slot: pointer to the &struct hotplug_slot to register * @slot_nr: slot number + * @name: name registered with kobject core * * Registers a hotplug slot with the pci hotplug subsystem, which will allow * userspace interaction to the slot. * * Returns 0 if successful, anything else for an error. */ -int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr) +int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr, + const char *name) { int result; struct pci_slot *pci_slot; @@ -568,48 +567,29 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr) return -EINVAL; } - /* Check if we have already registered a slot with the same name. */ - if (get_slot_from_name(slot->name)) - return -EEXIST; + mutex_lock(&pci_hp_mutex); /* * No problems if we call this interface from both ACPI_PCI_SLOT * driver and call it here again. If we've already created the * pci_slot, the interface will simply bump the refcount. */ - pci_slot = pci_create_slot(bus, slot_nr, slot->name); - if (IS_ERR(pci_slot)) - return PTR_ERR(pci_slot); - - if (pci_slot->hotplug) { - dbg("%s: already claimed\n", __func__); - pci_destroy_slot(pci_slot); - return -EBUSY; + pci_slot = pci_create_slot(bus, slot_nr, name, slot); + if (IS_ERR(pci_slot)) { + result = PTR_ERR(pci_slot); + goto out; } slot->pci_slot = pci_slot; pci_slot->hotplug = slot; - /* - * Allow pcihp drivers to override the ACPI_PCI_SLOT name. - */ - if (strcmp(kobject_name(&pci_slot->kobj), slot->name)) { - result = kobject_rename(&pci_slot->kobj, slot->name); - if (result) { - pci_destroy_slot(pci_slot); - return result; - } - } - - spin_lock(&pci_hotplug_slot_list_lock); list_add(&slot->slot_list, &pci_hotplug_slot_list); - spin_unlock(&pci_hotplug_slot_list_lock); result = fs_add_slot(pci_slot); kobject_uevent(&pci_slot->kobj, KOBJ_ADD); - dbg("Added slot %s to the list\n", slot->name); - - + dbg("Added slot %s to the list\n", name); +out: + mutex_unlock(&pci_hp_mutex); return result; } @@ -630,21 +610,23 @@ int pci_hp_deregister(struct hotplug_slot *hotplug) if (!hotplug) return -ENODEV; - temp = get_slot_from_name(hotplug->name); - if (temp != hotplug) + mutex_lock(&pci_hp_mutex); + temp = get_slot_from_name(hotplug_slot_name(hotplug)); + if (temp != hotplug) { + mutex_unlock(&pci_hp_mutex); return -ENODEV; + } - spin_lock(&pci_hotplug_slot_list_lock); list_del(&hotplug->slot_list); - spin_unlock(&pci_hotplug_slot_list_lock); slot = hotplug->pci_slot; fs_remove_slot(slot); - dbg("Removed slot %s from the list\n", hotplug->name); + dbg("Removed slot %s from the list\n", hotplug_slot_name(hotplug)); hotplug->release(hotplug); slot->hotplug = NULL; pci_destroy_slot(slot); + mutex_unlock(&pci_hp_mutex); return 0; } diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index c367978..b2801a7 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -74,15 +74,13 @@ extern struct workqueue_struct *pciehp_wq; struct slot { u8 bus; u8 device; - u32 number; u8 state; - struct timer_list task_event; u8 hp_slot; + u32 number; struct controller *ctrl; struct hpc_ops *hpc_ops; struct hotplug_slot *hotplug_slot; struct list_head slot_list; - char name[SLOT_NAME_SIZE]; unsigned long last_emi_toggle; struct delayed_work work; /* work for button event */ struct mutex lock; @@ -112,6 +110,7 @@ struct controller { struct timer_list poll_timer; int cmd_busy; unsigned int no_cmd_complete:1; + unsigned int link_active_reporting:1; }; #define INT_BUTTON_IGNORE 0 @@ -175,6 +174,11 @@ int pciehp_enable_slot(struct slot *p_slot); int pciehp_disable_slot(struct slot *p_slot); int pcie_enable_notification(struct controller *ctrl); +static inline const char *slot_name(struct slot *slot) +{ + return hotplug_slot_name(slot->hotplug_slot); +} + static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) { struct slot *slot; @@ -184,7 +188,7 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) return slot; } - ctrl_err(ctrl, "%s: slot (device=0x%x) not found\n", __func__, device); + ctrl_err(ctrl, "Slot (device=0x%02x) not found\n", device); return NULL; } diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index c748a19..39cf248 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -184,8 +184,8 @@ static void release_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; - ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n", - __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, hotplug_slot_name(hotplug_slot)); kfree(hotplug_slot->info); kfree(hotplug_slot); @@ -196,7 +196,7 @@ static int init_slots(struct controller *ctrl) struct slot *slot; struct hotplug_slot *hotplug_slot; struct hotplug_slot_info *info; - int len, dup = 1; + char name[SLOT_NAME_SIZE]; int retval = -ENOMEM; list_for_each_entry(slot, &ctrl->slot_list, slot_list) { @@ -210,48 +210,37 @@ static int init_slots(struct controller *ctrl) /* register this slot with the hotplug pci core */ hotplug_slot->info = info; - hotplug_slot->name = slot->name; hotplug_slot->private = slot; hotplug_slot->release = &release_slot; hotplug_slot->ops = &pciehp_hotplug_slot_ops; - get_power_status(hotplug_slot, &info->power_status); - get_attention_status(hotplug_slot, &info->attention_status); - get_latch_status(hotplug_slot, &info->latch_status); - get_adapter_status(hotplug_slot, &info->adapter_status); slot->hotplug_slot = hotplug_slot; + snprintf(name, SLOT_NAME_SIZE, "%u", slot->number); - ctrl_dbg(ctrl, "Registering bus=%x dev=%x hp_slot=%x sun=%x " - "slot_device_offset=%x\n", slot->bus, slot->device, - slot->hp_slot, slot->number, ctrl->slot_device_offset); -duplicate_name: + ctrl_dbg(ctrl, "Registering domain:bus:dev=%04x:%02x:%02x " + "hp_slot=%x sun=%x slot_device_offset=%x\n", + pci_domain_nr(ctrl->pci_dev->subordinate), + slot->bus, slot->device, slot->hp_slot, slot->number, + ctrl->slot_device_offset); retval = pci_hp_register(hotplug_slot, ctrl->pci_dev->subordinate, - slot->device); + slot->device, + name); if (retval) { - /* - * If slot N already exists, we'll try to create - * slot N-1, N-2 ... N-M, until we overflow. - */ - if (retval == -EEXIST) { - len = snprintf(slot->name, SLOT_NAME_SIZE, - "%d-%d", slot->number, dup++); - if (len < SLOT_NAME_SIZE) - goto duplicate_name; - else - ctrl_err(ctrl, "duplicate slot name " - "overflow\n"); - } ctrl_err(ctrl, "pci_hp_register failed with error %d\n", retval); goto error_info; } + get_power_status(hotplug_slot, &info->power_status); + get_attention_status(hotplug_slot, &info->attention_status); + get_latch_status(hotplug_slot, &info->latch_status); + get_adapter_status(hotplug_slot, &info->adapter_status); /* create additional sysfs entries */ if (EMI(ctrl)) { retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj, &hotplug_slot_attr_lock.attr); if (retval) { pci_hp_deregister(hotplug_slot); - ctrl_err(ctrl, "cannot create additional sysfs " + ctrl_err(ctrl, "Cannot create additional sysfs " "entries\n"); goto error_info; } @@ -286,8 +275,8 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) { struct slot *slot = hotplug_slot->private; - ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n", - __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); hotplug_slot->info->attention_status = status; @@ -302,8 +291,8 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; - ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n", - __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); return pciehp_sysfs_enable_slot(slot); } @@ -313,8 +302,8 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; - ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n", - __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); return pciehp_sysfs_disable_slot(slot); } @@ -324,8 +313,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = hotplug_slot->private; int retval; - ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n", - __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); retval = slot->hpc_ops->get_power_status(slot, value); if (retval < 0) @@ -339,8 +328,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = hotplug_slot->private; int retval; - ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n", - __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); retval = slot->hpc_ops->get_attention_status(slot, value); if (retval < 0) @@ -354,8 +343,8 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = hotplug_slot->private; int retval; - ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n", - __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); retval = slot->hpc_ops->get_latch_status(slot, value); if (retval < 0) @@ -369,8 +358,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = hotplug_slot->private; int retval; - ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n", - __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); retval = slot->hpc_ops->get_adapter_status(slot, value); if (retval < 0) @@ -385,8 +374,8 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, struct slot *slot = hotplug_slot->private; int retval; - ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n", - __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); retval = slot->hpc_ops->get_max_bus_speed(slot, value); if (retval < 0) @@ -400,8 +389,8 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe struct slot *slot = hotplug_slot->private; int retval; - ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n", - __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); retval = slot->hpc_ops->get_cur_bus_speed(slot, value); if (retval < 0) @@ -427,7 +416,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ ctrl = pcie_init(dev); if (!ctrl) { - dev_err(&dev->device, "controller initialization failed\n"); + dev_err(&dev->device, "Controller initialization failed\n"); goto err_out_none; } set_service_data(dev, ctrl); @@ -436,25 +425,26 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ rc = init_slots(ctrl); if (rc) { if (rc == -EBUSY) - ctrl_warn(ctrl, "slot already registered by another " + ctrl_warn(ctrl, "Slot already registered by another " "hotplug driver\n"); else - ctrl_err(ctrl, "slot initialization failed\n"); + ctrl_err(ctrl, "Slot initialization failed\n"); goto err_out_release_ctlr; } + /* Check if slot is occupied */ t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); - - t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ - if (value && pciehp_force) { - rc = pciehp_enable_slot(t_slot); - if (rc) /* -ENODEV: shouldn't happen, but deal with it */ - value = 0; - } - if ((POWER_CTRL(ctrl)) && !value) { - rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ - if (rc) - goto err_out_free_ctrl_slot; + t_slot->hpc_ops->get_adapter_status(t_slot, &value); + if (value) { + if (pciehp_force) + pciehp_enable_slot(t_slot); + } else { + /* Power off slot if not occupied */ + if (POWER_CTRL(ctrl)) { + rc = t_slot->hpc_ops->power_off_slot(t_slot); + if (rc) + goto err_out_free_ctrl_slot; + } } return 0; @@ -536,7 +526,7 @@ static int __init pcied_init(void) dbg("pcie_port_service_register = %d\n", retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); if (retval) - dbg("%s: Failure to register service\n", __func__); + dbg("Failure to register service\n"); return retval; } diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index acb7f9e..fead63c 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -61,12 +61,12 @@ u8 pciehp_handle_attention_button(struct slot *p_slot) struct controller *ctrl = p_slot->ctrl; /* Attention Button Change */ - ctrl_dbg(ctrl, "Attention button interrupt received.\n"); + ctrl_dbg(ctrl, "Attention button interrupt received\n"); /* * Button pressed - See if need to TAKE ACTION!!! */ - ctrl_info(ctrl, "Button pressed on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot)); event_type = INT_BUTTON_PRESS; queue_interrupt_event(p_slot, event_type); @@ -81,20 +81,20 @@ u8 pciehp_handle_switch_change(struct slot *p_slot) struct controller *ctrl = p_slot->ctrl; /* Switch Change */ - ctrl_dbg(ctrl, "Switch interrupt received.\n"); + ctrl_dbg(ctrl, "Switch interrupt received\n"); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (getstatus) { /* * Switch opened */ - ctrl_info(ctrl, "Latch open on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot)); event_type = INT_SWITCH_OPEN; } else { /* * Switch closed */ - ctrl_info(ctrl, "Latch close on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot)); event_type = INT_SWITCH_CLOSE; } @@ -110,7 +110,7 @@ u8 pciehp_handle_presence_change(struct slot *p_slot) struct controller *ctrl = p_slot->ctrl; /* Presence Change */ - ctrl_dbg(ctrl, "Presence/Notify input change.\n"); + ctrl_dbg(ctrl, "Presence/Notify input change\n"); /* Switch is open, assume a presence change * Save the presence state @@ -120,13 +120,14 @@ u8 pciehp_handle_presence_change(struct slot *p_slot) /* * Card Present */ - ctrl_info(ctrl, "Card present on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Card present on Slot(%s)\n", slot_name(p_slot)); event_type = INT_PRESENCE_ON; } else { /* * Not Present */ - ctrl_info(ctrl, "Card not present on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Card not present on Slot(%s)\n", + slot_name(p_slot)); event_type = INT_PRESENCE_OFF; } @@ -141,22 +142,22 @@ u8 pciehp_handle_power_fault(struct slot *p_slot) struct controller *ctrl = p_slot->ctrl; /* power fault */ - ctrl_dbg(ctrl, "Power fault interrupt received.\n"); + ctrl_dbg(ctrl, "Power fault interrupt received\n"); if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { /* * power fault Cleared */ ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n", - p_slot->name); + slot_name(p_slot)); event_type = INT_POWER_FAULT_CLEAR; } else { /* * power fault */ - ctrl_info(ctrl, "Power fault on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot)); event_type = INT_POWER_FAULT; - ctrl_info(ctrl, "power fault bit %x set\n", 0); + ctrl_info(ctrl, "Power fault bit %x set\n", 0); } queue_interrupt_event(p_slot, event_type); @@ -174,8 +175,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) if (POWER_CTRL(ctrl)) { if (pslot->hpc_ops->power_off_slot(pslot)) { ctrl_err(ctrl, - "%s: Issue of Slot Power Off command failed\n", - __func__); + "Issue of Slot Power Off command failed\n"); return; } } @@ -192,8 +192,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) if (ATTN_LED(ctrl)) { if (pslot->hpc_ops->set_attention_status(pslot, 1)) { - ctrl_err(ctrl, "%s: Issue of Set Attention " - "Led command failed\n", __func__); + ctrl_err(ctrl, + "Issue of Set Attention Led command failed\n"); return; } } @@ -210,8 +210,9 @@ static int board_added(struct slot *p_slot) { int retval = 0; struct controller *ctrl = p_slot->ctrl; + struct pci_bus *parent = ctrl->pci_dev->subordinate; - ctrl_dbg(ctrl, "%s: slot device, slot offset, hp slot = %d, %d ,%d\n", + ctrl_dbg(ctrl, "%s: slot device, slot offset, hp slot = %d, %d, %d\n", __func__, p_slot->device, ctrl->slot_device_offset, p_slot->hp_slot); @@ -225,28 +226,25 @@ static int board_added(struct slot *p_slot) if (PWR_LED(ctrl)) p_slot->hpc_ops->green_led_blink(p_slot); - /* Wait for ~1 second */ - msleep(1000); - /* Check link training status */ retval = p_slot->hpc_ops->check_lnk_status(ctrl); if (retval) { - ctrl_err(ctrl, "%s: Failed to check link status\n", __func__); + ctrl_err(ctrl, "Failed to check link status\n"); set_slot_off(ctrl, p_slot); return retval; } /* Check for a power fault */ if (p_slot->hpc_ops->query_power_fault(p_slot)) { - ctrl_dbg(ctrl, "%s: power fault detected\n", __func__); + ctrl_dbg(ctrl, "Power fault detected\n"); retval = POWER_FAILURE; goto err_exit; } retval = pciehp_configure_device(p_slot); if (retval) { - ctrl_err(ctrl, "Cannot add device 0x%x:%x\n", - p_slot->bus, p_slot->device); + ctrl_err(ctrl, "Cannot add device at %04x:%02x:%02x\n", + pci_domain_nr(parent), p_slot->bus, p_slot->device); goto err_exit; } @@ -278,14 +276,14 @@ static int remove_board(struct slot *p_slot) if (retval) return retval; - ctrl_dbg(ctrl, "In %s, hp_slot = %d\n", __func__, p_slot->hp_slot); + ctrl_dbg(ctrl, "%s: hp_slot = %d\n", __func__, p_slot->hp_slot); if (POWER_CTRL(ctrl)) { /* power off slot */ retval = p_slot->hpc_ops->power_off_slot(p_slot); if (retval) { - ctrl_err(ctrl, "%s: Issue of Slot Disable command " - "failed\n", __func__); + ctrl_err(ctrl, + "Issue of Slot Disable command failed\n"); return retval; } } @@ -326,8 +324,10 @@ static void pciehp_power_thread(struct work_struct *work) switch (p_slot->state) { case POWEROFF_STATE: mutex_unlock(&p_slot->lock); - ctrl_dbg(p_slot->ctrl, "%s: disabling bus:device(%x:%x)\n", - __func__, p_slot->bus, p_slot->device); + ctrl_dbg(p_slot->ctrl, + "Disabling domain:bus:device=%04x:%02x:%02x\n", + pci_domain_nr(p_slot->ctrl->pci_dev->subordinate), + p_slot->bus, p_slot->device); pciehp_disable_slot(p_slot); mutex_lock(&p_slot->lock); p_slot->state = STATIC_STATE; @@ -412,12 +412,12 @@ static void handle_button_press_event(struct slot *p_slot) p_slot->state = BLINKINGOFF_STATE; ctrl_info(ctrl, "PCI slot #%s - powering off due to button " - "press.\n", p_slot->name); + "press.\n", slot_name(p_slot)); } else { p_slot->state = BLINKINGON_STATE; ctrl_info(ctrl, "PCI slot #%s - powering on due to button " - "press.\n", p_slot->name); + "press.\n", slot_name(p_slot)); } /* blink green LED and turn off amber */ if (PWR_LED(ctrl)) @@ -434,8 +434,7 @@ static void handle_button_press_event(struct slot *p_slot) * press the attention again before the 5 sec. limit * expires to cancel hot-add or hot-remove */ - ctrl_info(ctrl, "Button cancel on Slot(%s)\n", p_slot->name); - ctrl_dbg(ctrl, "%s: button cancel\n", __func__); + ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot)); cancel_delayed_work(&p_slot->work); if (p_slot->state == BLINKINGOFF_STATE) { if (PWR_LED(ctrl)) @@ -447,7 +446,7 @@ static void handle_button_press_event(struct slot *p_slot) if (ATTN_LED(ctrl)) p_slot->hpc_ops->set_attention_status(p_slot, 0); ctrl_info(ctrl, "PCI slot #%s - action canceled " - "due to button press\n", p_slot->name); + "due to button press\n", slot_name(p_slot)); p_slot->state = STATIC_STATE; break; case POWEROFF_STATE: @@ -457,7 +456,7 @@ static void handle_button_press_event(struct slot *p_slot) * this means that the previous attention button action * to hot-add or hot-remove is undergoing */ - ctrl_info(ctrl, "Button ignore on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot)); update_slot_info(p_slot); break; default: @@ -539,16 +538,15 @@ int pciehp_enable_slot(struct slot *p_slot) rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { - ctrl_info(ctrl, "%s: no adapter on slot(%s)\n", - __func__, p_slot->name); + ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } if (MRL_SENS(p_slot->ctrl)) { rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { - ctrl_info(ctrl, "%s: latch open on slot(%s)\n", - __func__, p_slot->name); + ctrl_info(ctrl, "Latch open on slot(%s)\n", + slot_name(p_slot)); mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } @@ -557,8 +555,8 @@ int pciehp_enable_slot(struct slot *p_slot) if (POWER_CTRL(p_slot->ctrl)) { rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { - ctrl_info(ctrl, "%s: already enabled on slot(%s)\n", - __func__, p_slot->name); + ctrl_info(ctrl, "Already enabled on slot(%s)\n", + slot_name(p_slot)); mutex_unlock(&p_slot->ctrl->crit_sect); return -EINVAL; } @@ -593,8 +591,8 @@ int pciehp_disable_slot(struct slot *p_slot) if (!HP_SUPR_RM(p_slot->ctrl)) { ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (ret || !getstatus) { - ctrl_info(ctrl, "%s: no adapter on slot(%s)\n", - __func__, p_slot->name); + ctrl_info(ctrl, "No adapter on slot(%s)\n", + slot_name(p_slot)); mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } @@ -603,8 +601,8 @@ int pciehp_disable_slot(struct slot *p_slot) if (MRL_SENS(p_slot->ctrl)) { ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { - ctrl_info(ctrl, "%s: latch open on slot(%s)\n", - __func__, p_slot->name); + ctrl_info(ctrl, "Latch open on slot(%s)\n", + slot_name(p_slot)); mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } @@ -613,8 +611,8 @@ int pciehp_disable_slot(struct slot *p_slot) if (POWER_CTRL(p_slot->ctrl)) { ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { - ctrl_info(ctrl, "%s: already disabled slot(%s)\n", - __func__, p_slot->name); + ctrl_info(ctrl, "Already disabled on slot(%s)\n", + slot_name(p_slot)); mutex_unlock(&p_slot->ctrl->crit_sect); return -EINVAL; } @@ -645,14 +643,16 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot) break; case POWERON_STATE: ctrl_info(ctrl, "Slot %s is already in powering on state\n", - p_slot->name); + slot_name(p_slot)); break; case BLINKINGOFF_STATE: case POWEROFF_STATE: - ctrl_info(ctrl, "Already enabled on slot %s\n", p_slot->name); + ctrl_info(ctrl, "Already enabled on slot %s\n", + slot_name(p_slot)); break; default: - ctrl_err(ctrl, "Not a valid state on slot %s\n", p_slot->name); + ctrl_err(ctrl, "Not a valid state on slot %s\n", + slot_name(p_slot)); break; } mutex_unlock(&p_slot->lock); @@ -678,14 +678,16 @@ int pciehp_sysfs_disable_slot(struct slot *p_slot) break; case POWEROFF_STATE: ctrl_info(ctrl, "Slot %s is already in powering off state\n", - p_slot->name); + slot_name(p_slot)); break; case BLINKINGON_STATE: case POWERON_STATE: - ctrl_info(ctrl, "Already disabled on slot %s\n", p_slot->name); + ctrl_info(ctrl, "Already disabled on slot %s\n", + slot_name(p_slot)); break; default: - ctrl_err(ctrl, "Not a valid state on slot %s\n", p_slot->name); + ctrl_err(ctrl, "Not a valid state on slot %s\n", + slot_name(p_slot)); break; } mutex_unlock(&p_slot->lock); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 8e9530c..b643ca1 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -125,6 +125,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) /* Field definitions in Link Capabilities Register */ #define MAX_LNK_SPEED 0x000F #define MAX_LNK_WIDTH 0x03F0 +#define LINK_ACTIVE_REPORTING 0x00100000 /* Link Width Encoding */ #define LNK_X1 0x01 @@ -141,6 +142,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) #define LNK_TRN_ERR 0x0400 #define LNK_TRN 0x0800 #define SLOT_CLK_CONF 0x1000 +#define LINK_ACTIVE 0x2000 /* Field definitions in Slot Capabilities Register */ #define ATTN_BUTTN_PRSN 0x00000001 @@ -314,22 +316,19 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) * proceed forward to issue the next command according * to spec. Just print out the error message. */ - ctrl_dbg(ctrl, - "%s: CMD_COMPLETED not clear after 1 sec.\n", - __func__); + ctrl_dbg(ctrl, "CMD_COMPLETED not clear after 1 sec\n"); } else if (!NO_CMD_CMPL(ctrl)) { /* * This controller semms to notify of command completed * event even though it supports none of power * controller, attention led, power led and EMI. */ - ctrl_dbg(ctrl, "%s: Unexpected CMD_COMPLETED. Need to " - "wait for command completed event.\n", - __func__); + ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Need to " + "wait for command completed event.\n"); ctrl->no_cmd_complete = 0; } else { - ctrl_dbg(ctrl, "%s: Unexpected CMD_COMPLETED. Maybe " - "the controller is broken.\n", __func__); + ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Maybe " + "the controller is broken.\n"); } } @@ -345,8 +344,7 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) smp_mb(); retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl); if (retval) - ctrl_err(ctrl, "%s: Cannot write to SLOTCTRL register\n", - __func__); + ctrl_err(ctrl, "Cannot write to SLOTCTRL register\n"); /* * Wait for command completion. @@ -368,22 +366,62 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) return retval; } +static inline int check_link_active(struct controller *ctrl) +{ + u16 link_status; + + if (pciehp_readw(ctrl, LNKSTATUS, &link_status)) + return 0; + return !!(link_status & LINK_ACTIVE); +} + +static void pcie_wait_link_active(struct controller *ctrl) +{ + int timeout = 1000; + + if (check_link_active(ctrl)) + return; + while (timeout > 0) { + msleep(10); + timeout -= 10; + if (check_link_active(ctrl)) + return; + } + ctrl_dbg(ctrl, "Data Link Layer Link Active not set in 1000 msec\n"); +} + static int hpc_check_lnk_status(struct controller *ctrl) { u16 lnk_status; int retval = 0; + /* + * Data Link Layer Link Active Reporting must be capable for + * hot-plug capable downstream port. But old controller might + * not implement it. In this case, we wait for 1000 ms. + */ + if (ctrl->link_active_reporting){ + /* Wait for Data Link Layer Link Active bit to be set */ + pcie_wait_link_active(ctrl); + /* + * We must wait for 100 ms after the Data Link Layer + * Link Active bit reads 1b before initiating a + * configuration access to the hot added device. + */ + msleep(100); + } else + msleep(1000); + retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status); if (retval) { - ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n", - __func__); + ctrl_err(ctrl, "Cannot read LNKSTATUS register\n"); return retval; } ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status); if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) || !(lnk_status & NEG_LINK_WD)) { - ctrl_err(ctrl, "%s : Link Training Error occurs \n", __func__); + ctrl_err(ctrl, "Link Training Error occurs \n"); retval = -1; return retval; } @@ -508,7 +546,7 @@ static int hpc_query_power_fault(struct slot *slot) retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); if (retval) { - ctrl_err(ctrl, "%s: Cannot check for power fault\n", __func__); + ctrl_err(ctrl, "Cannot check for power fault\n"); return retval; } pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); @@ -524,7 +562,7 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status) retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); if (retval) { - ctrl_err(ctrl, "%s : Cannot check EMI status\n", __func__); + ctrl_err(ctrl, "Cannot check EMI status\n"); return retval; } *status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT; @@ -654,8 +692,7 @@ static int hpc_power_on_slot(struct slot * slot) retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); if (retval) { - ctrl_err(ctrl, "%s: Write %x command failed!\n", - __func__, slot_cmd); + ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); return -1; } ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", @@ -733,7 +770,7 @@ static int hpc_power_off_slot(struct slot * slot) retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); if (retval) { - ctrl_err(ctrl, "%s: Write command failed!\n", __func__); + ctrl_err(ctrl, "Write command failed!\n"); retval = -1; goto out; } @@ -1013,8 +1050,7 @@ int pcie_enable_notification(struct controller *ctrl) PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE; if (pcie_write_cmd(ctrl, cmd, mask)) { - ctrl_err(ctrl, "%s: Cannot enable software notification\n", - __func__); + ctrl_err(ctrl, "Cannot enable software notification\n"); return -1; } return 0; @@ -1026,8 +1062,7 @@ static void pcie_disable_notification(struct controller *ctrl) mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | MRL_DETECT_ENABLE | PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE; if (pcie_write_cmd(ctrl, 0, mask)) - ctrl_warn(ctrl, "%s: Cannot disable software notification\n", - __func__); + ctrl_warn(ctrl, "Cannot disable software notification\n"); } static int pcie_init_notification(struct controller *ctrl) @@ -1061,7 +1096,6 @@ static int pcie_init_slot(struct controller *ctrl) slot->device = ctrl->slot_device_offset + slot->hp_slot; slot->hpc_ops = ctrl->hpc_ops; slot->number = ctrl->first_slot; - snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number); mutex_init(&slot->lock); INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); list_add(&slot->slot_list, &ctrl->slot_list); @@ -1132,12 +1166,12 @@ static inline void dbg_ctrl(struct controller *ctrl) struct controller *pcie_init(struct pcie_device *dev) { struct controller *ctrl; - u32 slot_cap; + u32 slot_cap, link_cap; struct pci_dev *pdev = dev->port; ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { - dev_err(&dev->device, "%s : out of memory\n", __func__); + dev_err(&dev->device, "%s: Out of memory\n", __func__); goto abort; } INIT_LIST_HEAD(&ctrl->slot_list); @@ -1146,13 +1180,12 @@ struct controller *pcie_init(struct pcie_device *dev) ctrl->pci_dev = pdev; ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (!ctrl->cap_base) { - ctrl_err(ctrl, "%s: Cannot find PCI Express capability\n", - __func__); - goto abort; + ctrl_err(ctrl, "Cannot find PCI Express capability\n"); + goto abort_ctrl; } if (pciehp_readl(ctrl, SLOTCAP, &slot_cap)) { - ctrl_err(ctrl, "%s: Cannot read SLOTCAP register\n", __func__); - goto abort; + ctrl_err(ctrl, "Cannot read SLOTCAP register\n"); + goto abort_ctrl; } ctrl->slot_cap = slot_cap; @@ -1174,6 +1207,16 @@ struct controller *pcie_init(struct pcie_device *dev) !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl))) ctrl->no_cmd_complete = 1; + /* Check if Data Link Layer Link Active Reporting is implemented */ + if (pciehp_readl(ctrl, LNKCAP, &link_cap)) { + ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); + goto abort_ctrl; + } + if (link_cap & LINK_ACTIVE_REPORTING) { + ctrl_dbg(ctrl, "Link Active Reporting supported\n"); + ctrl->link_active_reporting = 1; + } + /* Clear all remaining event bits in Slot Status register */ if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) goto abort_ctrl; diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index ffd1114..10f9566 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -39,8 +39,7 @@ static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) u16 pci_cmd, pci_bctl; if (hpp->revision > 1) { - printk(KERN_WARNING "%s: Rev.%d type0 record not supported\n", - __func__, hpp->revision); + warn("Rev.%d type0 record not supported\n", hpp->revision); return; } @@ -81,8 +80,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) u32 reg32; if (hpp->revision > 1) { - printk(KERN_WARNING "%s: Rev.%d type2 record not supported\n", - __func__, hpp->revision); + warn("Rev.%d type2 record not supported\n", hpp->revision); return; } @@ -149,8 +147,7 @@ static void program_fw_provided_values(struct pci_dev *dev) return; if (pciehp_get_hp_params_from_firmware(dev, &hpp)) { - printk(KERN_WARNING "%s: Could not get hotplug parameters\n", - __func__); + warn("Could not get hotplug parameters\n"); return; } @@ -202,9 +199,9 @@ int pciehp_configure_device(struct slot *p_slot) dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); if (dev) { - ctrl_err(ctrl, - "Device %s already exists at %x:%x, cannot hot-add\n", - pci_name(dev), p_slot->bus, p_slot->device); + ctrl_err(ctrl, "Device %s already exists " + "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev), + pci_domain_nr(parent), p_slot->bus, p_slot->device); pci_dev_put(dev); return -EINVAL; } @@ -248,8 +245,8 @@ int pciehp_unconfigure_device(struct slot *p_slot) u16 command; struct controller *ctrl = p_slot->ctrl; - ctrl_dbg(ctrl, "%s: bus/dev = %x/%x\n", __func__, - p_slot->bus, p_slot->device); + ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", + __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence); if (ret) presence = 0; diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 5088450..2ea9cf1 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -43,7 +43,7 @@ static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot) void dealloc_slot_struct(struct slot *slot) { kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); + kfree(slot->name); kfree(slot->hotplug_slot); kfree(slot); } @@ -63,11 +63,9 @@ struct slot *alloc_slot_struct(struct device_node *dn, GFP_KERNEL); if (!slot->hotplug_slot->info) goto error_hpslot; - slot->hotplug_slot->name = kmalloc(strlen(drc_name) + 1, GFP_KERNEL); - if (!slot->hotplug_slot->name) + slot->name = kstrdup(drc_name, GFP_KERNEL); + if (!slot->name) goto error_info; - slot->name = slot->hotplug_slot->name; - strcpy(slot->name, drc_name); slot->dn = dn; slot->index = drc_index; slot->power_domain = power_domain; @@ -137,7 +135,7 @@ int rpaphp_register_slot(struct slot *slot) slotno = PCI_SLOT(PCI_DN(slot->dn->child)->devfn); else slotno = -1; - retval = pci_hp_register(php_slot, slot->bus, slotno); + retval = pci_hp_register(php_slot, slot->bus, slotno, slot->name); if (retval) { err("pci_hp_register failed with error %d\n", retval); return retval; diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index 410fe03..3eee709 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -161,7 +161,8 @@ static int sn_pci_bus_valid(struct pci_bus *pci_bus) } static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot, - struct pci_bus *pci_bus, int device) + struct pci_bus *pci_bus, int device, + char *name) { struct pcibus_info *pcibus_info; struct slot *slot; @@ -173,15 +174,9 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot, return -ENOMEM; bss_hotplug_slot->private = slot; - bss_hotplug_slot->name = kmalloc(SN_SLOT_NAME_SIZE, GFP_KERNEL); - if (!bss_hotplug_slot->name) { - kfree(bss_hotplug_slot->private); - return -ENOMEM; - } - slot->device_num = device; slot->pci_bus = pci_bus; - sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x", + sprintf(name, "%04x:%02x:%02x", pci_domain_nr(pci_bus), ((u16)pcibus_info->pbi_buscommon.bs_persist_busnum), device + 1); @@ -418,7 +413,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) /* * Add the slot's devices to the ACPI infrastructure */ if (SN_ACPI_BASE_SUPPORT() && ssdt) { - unsigned long adr; + unsigned long long adr; struct acpi_device *pdevice; struct acpi_device *device; acpi_handle phandle; @@ -510,7 +505,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) /* free the ACPI resources for the slot */ if (SN_ACPI_BASE_SUPPORT() && PCI_CONTROLLER(slot->pci_bus)->acpi_handle) { - unsigned long adr; + unsigned long long adr; struct acpi_device *device; acpi_handle phandle; acpi_handle chandle = NULL; @@ -608,7 +603,6 @@ static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot, static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot) { kfree(bss_hotplug_slot->info); - kfree(bss_hotplug_slot->name); kfree(bss_hotplug_slot->private); kfree(bss_hotplug_slot); } @@ -618,6 +612,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) int device; struct pci_slot *pci_slot; struct hotplug_slot *bss_hotplug_slot; + char name[SN_SLOT_NAME_SIZE]; int rc = 0; /* @@ -645,15 +640,14 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) } if (sn_hp_slot_private_alloc(bss_hotplug_slot, - pci_bus, device)) { + pci_bus, device, name)) { rc = -ENOMEM; goto alloc_err; } - bss_hotplug_slot->ops = &sn_hotplug_slot_ops; bss_hotplug_slot->release = &sn_release_slot; - rc = pci_hp_register(bss_hotplug_slot, pci_bus, device); + rc = pci_hp_register(bss_hotplug_slot, pci_bus, device, name); if (rc) goto register_err; diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 8a026f7..6aba0b6 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -59,6 +59,20 @@ extern struct workqueue_struct *shpchp_wq; #define warn(format, arg...) \ printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) +#define ctrl_dbg(ctrl, format, arg...) \ + do { \ + if (shpchp_debug) \ + dev_printk(, &ctrl->pci_dev->dev, \ + format, ## arg); \ + } while (0) +#define ctrl_err(ctrl, format, arg...) \ + dev_err(&ctrl->pci_dev->dev, format, ## arg) +#define ctrl_info(ctrl, format, arg...) \ + dev_info(&ctrl->pci_dev->dev, format, ## arg) +#define ctrl_warn(ctrl, format, arg...) \ + dev_warn(&ctrl->pci_dev->dev, format, ## arg) + + #define SLOT_NAME_SIZE 10 struct slot { u8 bus; @@ -69,15 +83,13 @@ struct slot { u8 state; u8 presence_save; u8 pwr_save; - struct timer_list task_event; - u8 hp_slot; struct controller *ctrl; struct hpc_ops *hpc_ops; struct hotplug_slot *hotplug_slot; struct list_head slot_list; - char name[SLOT_NAME_SIZE]; struct delayed_work work; /* work for button event */ struct mutex lock; + u8 hp_slot; }; struct event_info { @@ -169,6 +181,11 @@ extern void cleanup_slots(struct controller *ctrl); extern void shpchp_queue_pushbutton_work(struct work_struct *work); extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); +static inline const char *slot_name(struct slot *slot) +{ + return hotplug_slot_name(slot->hotplug_slot); +} + #ifdef CONFIG_ACPI #include <linux/pci-acpi.h> static inline int get_hp_params_from_firmware(struct pci_dev *dev, @@ -236,7 +253,7 @@ static inline struct slot *shpchp_find_slot(struct controller *ctrl, u8 device) return slot; } - err("%s: slot (device=0x%x) not found\n", __func__, device); + ctrl_err(ctrl, "Slot (device=0x%02x) not found\n", device); return NULL; } @@ -270,7 +287,9 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot) pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, &pcix_bridge_errors_reg); perr_set = pcix_bridge_errors_reg & PERR_OBSERVED_MASK; if (perr_set) { - dbg ("%s W1C: Bridge_Errors[ PERR_OBSERVED = %08X]\n",__func__ , perr_set); + ctrl_dbg(p_slot->ctrl, + "Bridge_Errors[ PERR_OBSERVED = %08X] (W1C)\n", + perr_set); pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, perr_set); } @@ -279,7 +298,7 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot) pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, &pcix_mem_base_reg); rse_set = pcix_mem_base_reg & RSE_MASK; if (rse_set) { - dbg ("%s W1C: Memory_Base_Limit[ RSE ]\n",__func__ ); + ctrl_dbg(p_slot->ctrl, "Memory_Base_Limit[ RSE ] (W1C)\n"); pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, rse_set); } diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index cc38615..fe8d149 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -89,7 +89,8 @@ static void release_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); kfree(slot->hotplug_slot->info); kfree(slot->hotplug_slot); @@ -101,8 +102,9 @@ static int init_slots(struct controller *ctrl) struct slot *slot; struct hotplug_slot *hotplug_slot; struct hotplug_slot_info *info; + char name[SLOT_NAME_SIZE]; int retval = -ENOMEM; - int i, len, dup = 1; + int i; for (i = 0; i < ctrl->num_slots; i++) { slot = kzalloc(sizeof(*slot), GFP_KERNEL); @@ -119,8 +121,6 @@ static int init_slots(struct controller *ctrl) goto error_hpslot; hotplug_slot->info = info; - hotplug_slot->name = slot->name; - slot->hp_slot = i; slot->ctrl = ctrl; slot->bus = ctrl->pci_dev->subordinate->number; @@ -133,37 +133,27 @@ static int init_slots(struct controller *ctrl) /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; hotplug_slot->release = &release_slot; - snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number); + snprintf(name, SLOT_NAME_SIZE, "%d", slot->number); hotplug_slot->ops = &shpchp_hotplug_slot_ops; - get_power_status(hotplug_slot, &info->power_status); - get_attention_status(hotplug_slot, &info->attention_status); - get_latch_status(hotplug_slot, &info->latch_status); - get_adapter_status(hotplug_slot, &info->adapter_status); - - dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " - "slot_device_offset=%x\n", slot->bus, slot->device, - slot->hp_slot, slot->number, ctrl->slot_device_offset); -duplicate_name: + ctrl_dbg(ctrl, "Registering domain:bus:dev=%04x:%02x:%02x " + "hp_slot=%x sun=%x slot_device_offset=%x\n", + pci_domain_nr(ctrl->pci_dev->subordinate), + slot->bus, slot->device, slot->hp_slot, slot->number, + ctrl->slot_device_offset); retval = pci_hp_register(slot->hotplug_slot, - ctrl->pci_dev->subordinate, slot->device); + ctrl->pci_dev->subordinate, slot->device, name); if (retval) { - /* - * If slot N already exists, we'll try to create - * slot N-1, N-2 ... N-M, until we overflow. - */ - if (retval == -EEXIST) { - len = snprintf(slot->name, SLOT_NAME_SIZE, - "%d-%d", slot->number, dup++); - if (len < SLOT_NAME_SIZE) - goto duplicate_name; - else - err("duplicate slot name overflow\n"); - } - err("pci_hp_register failed with error %d\n", retval); + ctrl_err(ctrl, "pci_hp_register failed with error %d\n", + retval); goto error_info; } + get_power_status(hotplug_slot, &info->power_status); + get_attention_status(hotplug_slot, &info->attention_status); + get_latch_status(hotplug_slot, &info->latch_status); + get_adapter_status(hotplug_slot, &info->adapter_status); + list_add(&slot->slot_list, &ctrl->slot_list); } @@ -201,7 +191,8 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) { struct slot *slot = get_slot(hotplug_slot); - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); hotplug_slot->info->attention_status = status; slot->hpc_ops->set_attention_status(slot, status); @@ -213,7 +204,8 @@ static int enable_slot (struct hotplug_slot *hotplug_slot) { struct slot *slot = get_slot(hotplug_slot); - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); return shpchp_sysfs_enable_slot(slot); } @@ -222,7 +214,8 @@ static int disable_slot (struct hotplug_slot *hotplug_slot) { struct slot *slot = get_slot(hotplug_slot); - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); return shpchp_sysfs_disable_slot(slot); } @@ -232,7 +225,8 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = get_slot(hotplug_slot); int retval; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); retval = slot->hpc_ops->get_power_status(slot, value); if (retval < 0) @@ -246,7 +240,8 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = get_slot(hotplug_slot); int retval; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); retval = slot->hpc_ops->get_attention_status(slot, value); if (retval < 0) @@ -260,7 +255,8 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = get_slot(hotplug_slot); int retval; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); retval = slot->hpc_ops->get_latch_status(slot, value); if (retval < 0) @@ -274,7 +270,8 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = get_slot(hotplug_slot); int retval; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); retval = slot->hpc_ops->get_adapter_status(slot, value); if (retval < 0) @@ -289,7 +286,8 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, struct slot *slot = get_slot(hotplug_slot); int retval; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); retval = slot->hpc_ops->get_max_bus_speed(slot, value); if (retval < 0) @@ -303,7 +301,8 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp struct slot *slot = get_slot(hotplug_slot); int retval; - dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", + __func__, slot_name(slot)); retval = slot->hpc_ops->get_cur_bus_speed(slot, value); if (retval < 0) @@ -334,15 +333,14 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { - err("%s : out of memory\n", __func__); + dev_err(&pdev->dev, "%s: Out of memory\n", __func__); goto err_out_none; } INIT_LIST_HEAD(&ctrl->slot_list); rc = shpc_init(ctrl, pdev); if (rc) { - dbg("%s: controller initialization failed\n", - SHPC_MODULE_NAME); + ctrl_dbg(ctrl, "Controller initialization failed\n"); goto err_out_free_ctrl; } @@ -351,7 +349,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Setup the slot information structures */ rc = init_slots(ctrl); if (rc) { - err("%s: slot initialization failed\n", SHPC_MODULE_NAME); + ctrl_err(ctrl, "Slot initialization failed\n"); goto err_out_release_ctlr; } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index dfb5393..b8ab279 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -62,7 +62,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl) u32 event_type; /* Attention Button Change */ - dbg("shpchp: Attention button interrupt received.\n"); + ctrl_dbg(ctrl, "Attention button interrupt received\n"); p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); @@ -70,7 +70,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl) /* * Button pressed - See if need to TAKE ACTION!!! */ - info("Button pressed on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot)); event_type = INT_BUTTON_PRESS; queue_interrupt_event(p_slot, event_type); @@ -86,29 +86,29 @@ u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl) u32 event_type; /* Switch Change */ - dbg("shpchp: Switch interrupt received.\n"); + ctrl_dbg(ctrl, "Switch interrupt received\n"); p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - dbg("%s: Card present %x Power status %x\n", __func__, - p_slot->presence_save, p_slot->pwr_save); + ctrl_dbg(ctrl, "Card present %x Power status %x\n", + p_slot->presence_save, p_slot->pwr_save); if (getstatus) { /* * Switch opened */ - info("Latch open on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot)); event_type = INT_SWITCH_OPEN; if (p_slot->pwr_save && p_slot->presence_save) { event_type = INT_POWER_FAULT; - err("Surprise Removal of card\n"); + ctrl_err(ctrl, "Surprise Removal of card\n"); } } else { /* * Switch closed */ - info("Latch close on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot)); event_type = INT_SWITCH_CLOSE; } @@ -123,7 +123,7 @@ u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl) u32 event_type; /* Presence Change */ - dbg("shpchp: Presence/Notify input change.\n"); + ctrl_dbg(ctrl, "Presence/Notify input change\n"); p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); @@ -135,13 +135,15 @@ u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl) /* * Card Present */ - info("Card present on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Card present on Slot(%s)\n", + slot_name(p_slot)); event_type = INT_PRESENCE_ON; } else { /* * Not Present */ - info("Card not present on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Card not present on Slot(%s)\n", + slot_name(p_slot)); event_type = INT_PRESENCE_OFF; } @@ -156,7 +158,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl) u32 event_type; /* Power fault */ - dbg("shpchp: Power fault interrupt received.\n"); + ctrl_dbg(ctrl, "Power fault interrupt received\n"); p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); @@ -164,18 +166,19 @@ u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl) /* * Power fault Cleared */ - info("Power fault cleared on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n", + slot_name(p_slot)); p_slot->status = 0x00; event_type = INT_POWER_FAULT_CLEAR; } else { /* * Power fault */ - info("Power fault on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot)); event_type = INT_POWER_FAULT; /* set power fault status for this board */ p_slot->status = 0xFF; - info("power fault bit %x set\n", hp_slot); + ctrl_info(ctrl, "Power fault bit %x set\n", hp_slot); } queue_interrupt_event(p_slot, event_type); @@ -191,10 +194,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, { int rc = 0; - dbg("%s: change to speed %d\n", __func__, speed); + ctrl_dbg(ctrl, "Change speed to %d\n", speed); if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { - err("%s: Issue of set bus speed mode command failed\n", - __func__); + ctrl_err(ctrl, "%s: Issue of set bus speed mode command " + "failed\n", __func__); return WRONG_BUS_FREQUENCY; } return rc; @@ -212,8 +215,8 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, */ if (flag) { if (asp < bsp) { - err("%s: speed of bus %x and adapter %x mismatch\n", - __func__, bsp, asp); + ctrl_err(ctrl, "Speed of bus %x and adapter %x " + "mismatch\n", bsp, asp); rc = WRONG_BUS_FREQUENCY; } return rc; @@ -243,17 +246,18 @@ static int board_added(struct slot *p_slot) int rc = 0; enum pci_bus_speed asp, bsp, msp; struct controller *ctrl = p_slot->ctrl; + struct pci_bus *parent = ctrl->pci_dev->subordinate; hp_slot = p_slot->device - ctrl->slot_device_offset; - dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n", - __func__, p_slot->device, - ctrl->slot_device_offset, hp_slot); + ctrl_dbg(ctrl, + "%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n", + __func__, p_slot->device, ctrl->slot_device_offset, hp_slot); /* Power on slot without connecting to bus */ rc = p_slot->hpc_ops->power_on_slot(p_slot); if (rc) { - err("%s: Failed to power on slot\n", __func__); + ctrl_err(ctrl, "Failed to power on slot\n"); return -1; } @@ -262,33 +266,34 @@ static int board_added(struct slot *p_slot) return WRONG_BUS_FREQUENCY; if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { - err("%s: Issue of set bus speed mode command failed\n", __func__); + ctrl_err(ctrl, "%s: Issue of set bus speed mode command" + " failed\n", __func__); return WRONG_BUS_FREQUENCY; } /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { - err("%s: Issue of Slot Enable command failed\n", __func__); + ctrl_err(ctrl, "Issue of Slot Enable command failed\n"); return rc; } } rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); if (rc) { - err("%s: Can't get adapter speed or bus mode mismatch\n", - __func__); + ctrl_err(ctrl, "Can't get adapter speed or " + "bus mode mismatch\n"); return WRONG_BUS_FREQUENCY; } rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp); if (rc) { - err("%s: Can't get bus operation speed\n", __func__); + ctrl_err(ctrl, "Can't get bus operation speed\n"); return WRONG_BUS_FREQUENCY; } rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp); if (rc) { - err("%s: Can't get max bus operation speed\n", __func__); + ctrl_err(ctrl, "Can't get max bus operation speed\n"); msp = bsp; } @@ -296,9 +301,9 @@ static int board_added(struct slot *p_slot) if (!list_empty(&ctrl->pci_dev->subordinate->devices)) slots_not_empty = 1; - dbg("%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, " - "max_bus_speed %d\n", __func__, slots_not_empty, asp, - bsp, msp); + ctrl_dbg(ctrl, "%s: slots_not_empty %d, adapter_speed %d, bus_speed %d," + " max_bus_speed %d\n", __func__, slots_not_empty, asp, + bsp, msp); rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp); if (rc) @@ -306,26 +311,26 @@ static int board_added(struct slot *p_slot) /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { - err("%s: Issue of Slot Enable command failed\n", __func__); + ctrl_err(ctrl, "Issue of Slot Enable command failed\n"); return rc; } /* Wait for ~1 second */ msleep(1000); - dbg("%s: slot status = %x\n", __func__, p_slot->status); + ctrl_dbg(ctrl, "%s: slot status = %x\n", __func__, p_slot->status); /* Check for a power fault */ if (p_slot->status == 0xFF) { /* power fault occurred, but it was benign */ - dbg("%s: power fault\n", __func__); + ctrl_dbg(ctrl, "%s: Power fault\n", __func__); rc = POWER_FAILURE; p_slot->status = 0; goto err_exit; } if (shpchp_configure_device(p_slot)) { - err("Cannot add device at 0x%x:0x%x\n", p_slot->bus, - p_slot->device); + ctrl_err(ctrl, "Cannot add device at %04x:%02x:%02x\n", + pci_domain_nr(parent), p_slot->bus, p_slot->device); goto err_exit; } @@ -341,7 +346,8 @@ err_exit: /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { - err("%s: Issue of Slot Disable command failed\n", __func__); + ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n", + __func__); return rc; } @@ -365,7 +371,7 @@ static int remove_board(struct slot *p_slot) hp_slot = p_slot->device - ctrl->slot_device_offset; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - dbg("In %s, hp_slot = %d\n", __func__, hp_slot); + ctrl_dbg(ctrl, "%s: hp_slot = %d\n", __func__, hp_slot); /* Change status to shutdown */ if (p_slot->is_a_board) @@ -374,13 +380,14 @@ static int remove_board(struct slot *p_slot) /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { - err("%s: Issue of Slot Disable command failed\n", __func__); + ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n", + __func__); return rc; } rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); if (rc) { - err("%s: Issue of Set Attention command failed\n", __func__); + ctrl_err(ctrl, "Issue of Set Attention command failed\n"); return rc; } @@ -439,7 +446,8 @@ void shpchp_queue_pushbutton_work(struct work_struct *work) info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) { - err("%s: Cannot allocate memory\n", __func__); + ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n", + __func__); return; } info->p_slot = p_slot; @@ -486,18 +494,19 @@ static int update_slot_info (struct slot *slot) static void handle_button_press_event(struct slot *p_slot) { u8 getstatus; + struct controller *ctrl = p_slot->ctrl; switch (p_slot->state) { case STATIC_STATE: p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (getstatus) { p_slot->state = BLINKINGOFF_STATE; - info("PCI slot #%s - powering off due to button " - "press.\n", p_slot->name); + ctrl_info(ctrl, "PCI slot #%s - powering off due to " + "button press.\n", slot_name(p_slot)); } else { p_slot->state = BLINKINGON_STATE; - info("PCI slot #%s - powering on due to button " - "press.\n", p_slot->name); + ctrl_info(ctrl, "PCI slot #%s - powering on due to " + "button press.\n", slot_name(p_slot)); } /* blink green LED and turn off amber */ p_slot->hpc_ops->green_led_blink(p_slot); @@ -512,16 +521,16 @@ static void handle_button_press_event(struct slot *p_slot) * press the attention again before the 5 sec. limit * expires to cancel hot-add or hot-remove */ - info("Button cancel on Slot(%s)\n", p_slot->name); - dbg("%s: button cancel\n", __func__); + ctrl_info(ctrl, "Button cancel on Slot(%s)\n", + slot_name(p_slot)); cancel_delayed_work(&p_slot->work); if (p_slot->state == BLINKINGOFF_STATE) p_slot->hpc_ops->green_led_on(p_slot); else p_slot->hpc_ops->green_led_off(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); - info("PCI slot #%s - action canceled due to button press\n", - p_slot->name); + ctrl_info(ctrl, "PCI slot #%s - action canceled due to " + "button press\n", slot_name(p_slot)); p_slot->state = STATIC_STATE; break; case POWEROFF_STATE: @@ -531,11 +540,12 @@ static void handle_button_press_event(struct slot *p_slot) * this means that the previous attention button action * to hot-add or hot-remove is undergoing */ - info("Button ignore on Slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Button ignore on Slot(%s)\n", + slot_name(p_slot)); update_slot_info(p_slot); break; default: - warn("Not a valid state\n"); + ctrl_warn(ctrl, "Not a valid state\n"); break; } } @@ -551,7 +561,7 @@ static void interrupt_event_handler(struct work_struct *work) handle_button_press_event(p_slot); break; case INT_POWER_FAULT: - dbg("%s: power fault\n", __func__); + ctrl_dbg(p_slot->ctrl, "%s: Power fault\n", __func__); p_slot->hpc_ops->set_attention_status(p_slot, 1); p_slot->hpc_ops->green_led_off(p_slot); break; @@ -569,22 +579,24 @@ static int shpchp_enable_slot (struct slot *p_slot) { u8 getstatus = 0; int rc, retval = -ENODEV; + struct controller *ctrl = p_slot->ctrl; /* Check to see if (latch closed, card present, power off) */ mutex_lock(&p_slot->ctrl->crit_sect); rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { - info("No adapter on slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); goto out; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { - info("Latch open on slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot)); goto out; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { - info("Already enabled on slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Already enabled on slot(%s)\n", + slot_name(p_slot)); goto out; } @@ -593,7 +605,7 @@ static int shpchp_enable_slot (struct slot *p_slot) /* We have to save the presence info for these slots */ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save)); - dbg("%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save); + ctrl_dbg(ctrl, "%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if(((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD) || @@ -624,6 +636,7 @@ static int shpchp_disable_slot (struct slot *p_slot) { u8 getstatus = 0; int rc, retval = -ENODEV; + struct controller *ctrl = p_slot->ctrl; if (!p_slot->ctrl) return -ENODEV; @@ -633,17 +646,18 @@ static int shpchp_disable_slot (struct slot *p_slot) rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { - info("No adapter on slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); goto out; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { - info("Latch open on slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot)); goto out; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || !getstatus) { - info("Already disabled slot(%s)\n", p_slot->name); + ctrl_info(ctrl, "Already disabled on slot(%s)\n", + slot_name(p_slot)); goto out; } @@ -657,6 +671,7 @@ static int shpchp_disable_slot (struct slot *p_slot) int shpchp_sysfs_enable_slot(struct slot *p_slot) { int retval = -ENODEV; + struct controller *ctrl = p_slot->ctrl; mutex_lock(&p_slot->lock); switch (p_slot->state) { @@ -670,15 +685,17 @@ int shpchp_sysfs_enable_slot(struct slot *p_slot) p_slot->state = STATIC_STATE; break; case POWERON_STATE: - info("Slot %s is already in powering on state\n", - p_slot->name); + ctrl_info(ctrl, "Slot %s is already in powering on state\n", + slot_name(p_slot)); break; case BLINKINGOFF_STATE: case POWEROFF_STATE: - info("Already enabled on slot %s\n", p_slot->name); + ctrl_info(ctrl, "Already enabled on slot %s\n", + slot_name(p_slot)); break; default: - err("Not a valid state on slot %s\n", p_slot->name); + ctrl_err(ctrl, "Not a valid state on slot %s\n", + slot_name(p_slot)); break; } mutex_unlock(&p_slot->lock); @@ -689,6 +706,7 @@ int shpchp_sysfs_enable_slot(struct slot *p_slot) int shpchp_sysfs_disable_slot(struct slot *p_slot) { int retval = -ENODEV; + struct controller *ctrl = p_slot->ctrl; mutex_lock(&p_slot->lock); switch (p_slot->state) { @@ -702,15 +720,17 @@ int shpchp_sysfs_disable_slot(struct slot *p_slot) p_slot->state = STATIC_STATE; break; case POWEROFF_STATE: - info("Slot %s is already in powering off state\n", - p_slot->name); + ctrl_info(ctrl, "Slot %s is already in powering off state\n", + slot_name(p_slot)); break; case BLINKINGON_STATE: case POWERON_STATE: - info("Already disabled on slot %s\n", p_slot->name); + ctrl_info(ctrl, "Already disabled on slot %s\n", + slot_name(p_slot)); break; default: - err("Not a valid state on slot %s\n", p_slot->name); + ctrl_err(ctrl, "Not a valid state on slot %s\n", + slot_name(p_slot)); break; } mutex_unlock(&p_slot->lock); diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 7a0bff3..86dc398 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -300,10 +300,10 @@ static inline int shpc_wait_cmd(struct controller *ctrl) !is_ctrl_busy(ctrl), timeout); if (!rc && is_ctrl_busy(ctrl)) { retval = -EIO; - err("Command not completed in 1000 msec\n"); + ctrl_err(ctrl, "Command not completed in 1000 msec\n"); } else if (rc < 0) { retval = -EINTR; - info("Command was interrupted by a signal\n"); + ctrl_info(ctrl, "Command was interrupted by a signal\n"); } return retval; @@ -320,15 +320,14 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) if (!shpc_poll_ctrl_busy(ctrl)) { /* After 1 sec and and the controller is still busy */ - err("%s : Controller is still busy after 1 sec.\n", - __func__); + ctrl_err(ctrl, "Controller is still busy after 1 sec\n"); retval = -EBUSY; goto out; } ++t_slot; temp_word = (t_slot << 8) | (cmd & 0xFF); - dbg("%s: t_slot %x cmd %x\n", __func__, t_slot, cmd); + ctrl_dbg(ctrl, "%s: t_slot %x cmd %x\n", __func__, t_slot, cmd); /* To make sure the Controller Busy bit is 0 before we send out the * command. @@ -344,8 +343,9 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) cmd_status = hpc_check_cmd_status(slot->ctrl); if (cmd_status) { - err("%s: Failed to issued command 0x%x (error code = %d)\n", - __func__, cmd, cmd_status); + ctrl_err(ctrl, + "Failed to issued command 0x%x (error code = %d)\n", + cmd, cmd_status); retval = -EIO; } out: @@ -364,15 +364,15 @@ static int hpc_check_cmd_status(struct controller *ctrl) break; case 1: retval = SWITCH_OPEN; - err("%s: Switch opened!\n", __func__); + ctrl_err(ctrl, "Switch opened!\n"); break; case 2: retval = INVALID_CMD; - err("%s: Invalid HPC command!\n", __func__); + ctrl_err(ctrl, "Invalid HPC command!\n"); break; case 4: retval = INVALID_SPEED_MODE; - err("%s: Invalid bus speed/mode!\n", __func__); + ctrl_err(ctrl, "Invalid bus speed/mode!\n"); break; default: retval = cmd_status; @@ -483,8 +483,8 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) return -ENODEV; } - dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", - __func__, slot_reg, pcix_cap, m66_cap); + ctrl_dbg(ctrl, "%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", + __func__, slot_reg, pcix_cap, m66_cap); switch (pcix_cap) { case 0x0: @@ -509,7 +509,7 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) break; } - dbg("Adapter speed = %d\n", *value); + ctrl_dbg(ctrl, "Adapter speed = %d\n", *value); return retval; } @@ -526,7 +526,7 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) retval = -1; } - dbg("Mode 1 ECC cap = %d\n", *mode); + ctrl_dbg(ctrl, "Mode 1 ECC cap = %d\n", *mode); return retval; } @@ -629,7 +629,7 @@ static int hpc_power_on_slot(struct slot * slot) retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR); if (retval) - err("%s: Write command failed!\n", __func__); + ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__); return retval; } @@ -642,7 +642,7 @@ static int hpc_slot_enable(struct slot * slot) retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF); if (retval) - err("%s: Write command failed!\n", __func__); + ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__); return retval; } @@ -655,7 +655,7 @@ static int hpc_slot_disable(struct slot * slot) retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON); if (retval) - err("%s: Write command failed!\n", __func__); + ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__); return retval; } @@ -719,7 +719,7 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) retval = shpc_write_cmd(slot, 0, cmd); if (retval) - err("%s: Write command failed!\n", __func__); + ctrl_err(ctrl, "%s: Write command failed!\n", __func__); return retval; } @@ -735,7 +735,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) if (!intr_loc) return IRQ_NONE; - dbg("%s: intr_loc = %x\n",__func__, intr_loc); + ctrl_dbg(ctrl, "%s: intr_loc = %x\n", __func__, intr_loc); if(!shpchp_poll_mode) { /* @@ -748,7 +748,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); intr_loc2 = shpc_readl(ctrl, INTR_LOC); - dbg("%s: intr_loc2 = %x\n",__func__, intr_loc2); + ctrl_dbg(ctrl, "%s: intr_loc2 = %x\n", __func__, intr_loc2); } if (intr_loc & CMD_INTR_PENDING) { @@ -773,8 +773,8 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) continue; slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); - dbg("%s: Slot %x with intr, slot register = %x\n", - __func__, hp_slot, slot_reg); + ctrl_dbg(ctrl, "Slot %x with intr, slot register = %x\n", + hp_slot, slot_reg); if (slot_reg & MRL_CHANGE_DETECTED) shpchp_handle_switch_change(hp_slot, ctrl); @@ -843,7 +843,7 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) } *value = bus_speed; - dbg("Max bus speed = %d\n", bus_speed); + ctrl_dbg(ctrl, "Max bus speed = %d\n", bus_speed); return retval; } @@ -911,7 +911,7 @@ static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) break; } - dbg("Current bus speed = %d\n", bus_speed); + ctrl_dbg(ctrl, "Current bus speed = %d\n", bus_speed); return retval; } @@ -949,6 +949,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) u8 i; ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ + ctrl_dbg(ctrl, "Hotplug Controller:\n"); if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)) { @@ -958,34 +959,33 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) } else { ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC); if (!ctrl->cap_offset) { - err("%s : cap_offset == 0\n", __func__); + ctrl_err(ctrl, "Cannot find PCI capability\n"); goto abort; } - dbg("%s: cap_offset = %x\n", __func__, ctrl->cap_offset); + ctrl_dbg(ctrl, " cap_offset = %x\n", ctrl->cap_offset); rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset); if (rc) { - err("%s: cannot read base_offset\n", __func__); + ctrl_err(ctrl, "Cannot read base_offset\n"); goto abort; } rc = shpc_indirect_read(ctrl, 3, &tempdword); if (rc) { - err("%s: cannot read slot config\n", __func__); + ctrl_err(ctrl, "Cannot read slot config\n"); goto abort; } num_slots = tempdword & SLOT_NUM; - dbg("%s: num_slots (indirect) %x\n", __func__, num_slots); + ctrl_dbg(ctrl, " num_slots (indirect) %x\n", num_slots); for (i = 0; i < 9 + num_slots; i++) { rc = shpc_indirect_read(ctrl, i, &tempdword); if (rc) { - err("%s: cannot read creg (index = %d)\n", - __func__, i); + ctrl_err(ctrl, + "Cannot read creg (index = %d)\n", i); goto abort; } - dbg("%s: offset %d: value %x\n", __func__,i, - tempdword); + ctrl_dbg(ctrl, " offset %d: value %x\n", i, tempdword); } ctrl->mmio_base = @@ -993,30 +993,31 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) ctrl->mmio_size = 0x24 + 0x4 * num_slots; } - info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, - pdev->subsystem_device); + ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", + pdev->vendor, pdev->device, pdev->subsystem_vendor, + pdev->subsystem_device); rc = pci_enable_device(pdev); if (rc) { - err("%s: pci_enable_device failed\n", __func__); + ctrl_err(ctrl, "pci_enable_device failed\n"); goto abort; } if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { - err("%s: cannot reserve MMIO region\n", __func__); + ctrl_err(ctrl, "Cannot reserve MMIO region\n"); rc = -1; goto abort; } ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size); if (!ctrl->creg) { - err("%s: cannot remap MMIO region %lx @ %lx\n", __func__, - ctrl->mmio_size, ctrl->mmio_base); + ctrl_err(ctrl, "Cannot remap MMIO region %lx @ %lx\n", + ctrl->mmio_size, ctrl->mmio_base); release_mem_region(ctrl->mmio_base, ctrl->mmio_size); rc = -1; goto abort; } - dbg("%s: ctrl->creg %p\n", __func__, ctrl->creg); + ctrl_dbg(ctrl, "ctrl->creg %p\n", ctrl->creg); mutex_init(&ctrl->crit_sect); mutex_init(&ctrl->cmd_lock); @@ -1035,21 +1036,21 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); - dbg("%s: SERR_INTR_ENABLE = %x\n", __func__, tempdword); + ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword); tempdword |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK | COMMAND_INTR_MASK | ARBITER_SERR_MASK); tempdword &= ~SERR_INTR_RSVDZ_MASK; shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); - dbg("%s: SERR_INTR_ENABLE = %x\n", __func__, tempdword); + ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword); /* Mask the MRL sensor SERR Mask of individual slot in * Slot SERR-INT Mask & clear all the existing event if any */ for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); - dbg("%s: Default Logical Slot Register %d value %x\n", __func__, - hp_slot, slot_reg); + ctrl_dbg(ctrl, "Default Logical Slot Register %d value %x\n", + hp_slot, slot_reg); slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK | @@ -1066,24 +1067,24 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) /* Installs the interrupt handler */ 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"); + ctrl_info(ctrl, + "Can't get msi for the hotplug controller\n"); + ctrl_info(ctrl, + "Use INTx for the hotplug controller\n"); } rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, MY_NAME, (void *)ctrl); - dbg("%s: request_irq %d for hpc%d (returns %d)\n", - __func__, ctrl->pci_dev->irq, + ctrl_dbg(ctrl, "request_irq %d for hpc%d (returns %d)\n", + ctrl->pci_dev->irq, atomic_read(&shpchp_num_controllers), rc); if (rc) { - err("Can't get irq %d for the hotplug controller\n", - ctrl->pci_dev->irq); + ctrl_err(ctrl, "Can't get irq %d for the hotplug " + "controller\n", ctrl->pci_dev->irq); goto abort_iounmap; } } - dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __func__, - pdev->bus->number, PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn), pdev->irq); + ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq); /* * If this is the first controller to be initialized, @@ -1102,8 +1103,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) */ for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); - dbg("%s: Default Logical Slot Register %d value %x\n", __func__, - hp_slot, slot_reg); + ctrl_dbg(ctrl, "Default Logical Slot Register %d value %x\n", + hp_slot, slot_reg); slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | CON_PFAULT_INTR_MASK | SLOT_REG_RSVDZ_MASK); @@ -1116,7 +1117,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) SERR_INTR_RSVDZ_MASK); shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); - dbg("%s: SERR_INTR_ENABLE = %x\n", __func__, tempdword); + ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword); } return 0; diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 3fc4ec0..138f161 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -49,9 +49,7 @@ static void program_fw_provided_values(struct pci_dev *dev) /* use default values if we can't get them from firmware */ if (get_hp_params_from_firmware(dev, &hpp) || !hpp.t0 || (hpp.t0->revision > 1)) { - printk(KERN_WARNING - "%s: Could not get hotplug parameters. Use defaults\n", - __func__); + warn("Could not get hotplug parameters. Use defaults\n"); hpp.t0 = &hpp.type0_data; hpp.t0->revision = 0; hpp.t0->cache_line_size = 8; @@ -101,18 +99,20 @@ int __ref shpchp_configure_device(struct slot *p_slot) struct pci_dev *dev; struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; int num, fn; + struct controller *ctrl = p_slot->ctrl; dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); if (dev) { - err("Device %s already exists at %x:%x, cannot hot-add\n", - pci_name(dev), p_slot->bus, p_slot->device); + ctrl_err(ctrl, "Device %s already exists " + "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev), + pci_domain_nr(parent), p_slot->bus, p_slot->device); pci_dev_put(dev); return -EINVAL; } num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0)); if (num == 0) { - err("No new device found\n"); + ctrl_err(ctrl, "No new device found\n"); return -ENODEV; } @@ -121,8 +121,8 @@ int __ref shpchp_configure_device(struct slot *p_slot) if (!dev) continue; if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { - err("Cannot hot-add display device %s\n", - pci_name(dev)); + ctrl_err(ctrl, "Cannot hot-add display device %s\n", + pci_name(dev)); pci_dev_put(dev); continue; } @@ -138,14 +138,15 @@ int __ref shpchp_configure_device(struct slot *p_slot) break; } if (busnr >= end) { - err("No free bus for hot-added bridge\n"); + ctrl_err(ctrl, + "No free bus for hot-added bridge\n"); pci_dev_put(dev); continue; } child = pci_add_new_bus(parent, dev, busnr); if (!child) { - err("Cannot add new bus for %s\n", - pci_name(dev)); + ctrl_err(ctrl, "Cannot add new bus for %s\n", + pci_name(dev)); pci_dev_put(dev); continue; } @@ -168,8 +169,10 @@ int shpchp_unconfigure_device(struct slot *p_slot) int j; u8 bctl = 0; struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; + struct controller *ctrl = p_slot->ctrl; - dbg("%s: bus/dev = %x/%x\n", __func__, p_slot->bus, p_slot->device); + ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", + __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); for (j=0; j<8 ; j++) { struct pci_dev* temp = pci_get_slot(parent, @@ -177,16 +180,17 @@ int shpchp_unconfigure_device(struct slot *p_slot) if (!temp) continue; if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { - err("Cannot remove display device %s\n", - pci_name(temp)); + ctrl_err(ctrl, "Cannot remove display device %s\n", + pci_name(temp)); pci_dev_put(temp); continue; } if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); if (bctl & PCI_BRIDGE_CTL_VGA) { - err("Cannot remove display device %s\n", - pci_name(temp)); + ctrl_err(ctrl, + "Cannot remove display device %s\n", + pci_name(temp)); pci_dev_put(temp); continue; } diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 8b51e10..5c8baa4 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -18,6 +18,7 @@ * Author: Ashok Raj <ashok.raj@intel.com> * Author: Shaohua Li <shaohua.li@intel.com> * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> + * Author: Fenghua Yu <fenghua.yu@intel.com> */ #include <linux/init.h> @@ -35,11 +36,13 @@ #include <linux/timer.h> #include <linux/iova.h> #include <linux/intel-iommu.h> -#include <asm/proto.h> /* force_iommu in this header in x86-64*/ #include <asm/cacheflush.h> #include <asm/iommu.h> #include "pci.h" +#define ROOT_SIZE VTD_PAGE_SIZE +#define CONTEXT_SIZE VTD_PAGE_SIZE + #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) @@ -199,7 +202,7 @@ static struct context_entry * device_to_context_entry(struct intel_iommu *iommu, spin_unlock_irqrestore(&iommu->lock, flags); return NULL; } - __iommu_flush_cache(iommu, (void *)context, PAGE_SIZE_4K); + __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE); phy_addr = virt_to_phys((void *)context); set_root_value(root, phy_addr); set_root_present(root); @@ -345,7 +348,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr) return NULL; } __iommu_flush_cache(domain->iommu, tmp_page, - PAGE_SIZE_4K); + PAGE_SIZE); dma_set_pte_addr(*pte, virt_to_phys(tmp_page)); /* * high level table always sets r/w, last level page @@ -408,13 +411,13 @@ static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end) start &= (((u64)1) << addr_width) - 1; end &= (((u64)1) << addr_width) - 1; /* in case it's partial page */ - start = PAGE_ALIGN_4K(start); - end &= PAGE_MASK_4K; + start = PAGE_ALIGN(start); + end &= PAGE_MASK; /* we don't need lock here, nobody else touches the iova range */ while (start < end) { dma_pte_clear_one(domain, start); - start += PAGE_SIZE_4K; + start += VTD_PAGE_SIZE; } } @@ -468,7 +471,7 @@ static int iommu_alloc_root_entry(struct intel_iommu *iommu) if (!root) return -ENOMEM; - __iommu_flush_cache(iommu, root, PAGE_SIZE_4K); + __iommu_flush_cache(iommu, root, ROOT_SIZE); spin_lock_irqsave(&iommu->lock, flags); iommu->root_entry = root; @@ -567,27 +570,6 @@ static int __iommu_flush_context(struct intel_iommu *iommu, return 0; } -static int inline iommu_flush_context_global(struct intel_iommu *iommu, - int non_present_entry_flush) -{ - return __iommu_flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL, - non_present_entry_flush); -} - -static int inline iommu_flush_context_domain(struct intel_iommu *iommu, u16 did, - int non_present_entry_flush) -{ - return __iommu_flush_context(iommu, did, 0, 0, DMA_CCMD_DOMAIN_INVL, - non_present_entry_flush); -} - -static int inline iommu_flush_context_device(struct intel_iommu *iommu, - u16 did, u16 source_id, u8 function_mask, int non_present_entry_flush) -{ - return __iommu_flush_context(iommu, did, source_id, function_mask, - DMA_CCMD_DEVICE_INVL, non_present_entry_flush); -} - /* return value determine if we need a write buffer flush */ static int __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, unsigned int size_order, u64 type, @@ -655,37 +637,25 @@ static int __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did, printk(KERN_ERR"IOMMU: flush IOTLB failed\n"); if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type)) pr_debug("IOMMU: tlb flush request %Lx, actual %Lx\n", - DMA_TLB_IIRG(type), DMA_TLB_IAIG(val)); + (unsigned long long)DMA_TLB_IIRG(type), + (unsigned long long)DMA_TLB_IAIG(val)); /* flush iotlb entry will implicitly flush write buffer */ return 0; } -static int inline iommu_flush_iotlb_global(struct intel_iommu *iommu, - int non_present_entry_flush) -{ - return __iommu_flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH, - non_present_entry_flush); -} - -static int inline iommu_flush_iotlb_dsi(struct intel_iommu *iommu, u16 did, - int non_present_entry_flush) -{ - return __iommu_flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH, - non_present_entry_flush); -} - static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, u64 addr, unsigned int pages, int non_present_entry_flush) { unsigned int mask; - BUG_ON(addr & (~PAGE_MASK_4K)); + BUG_ON(addr & (~VTD_PAGE_MASK)); BUG_ON(pages == 0); /* Fallback to domain selective flush if no PSI support */ if (!cap_pgsel_inv(iommu->cap)) - return iommu_flush_iotlb_dsi(iommu, did, - non_present_entry_flush); + return iommu->flush.flush_iotlb(iommu, did, 0, 0, + DMA_TLB_DSI_FLUSH, + non_present_entry_flush); /* * PSI requires page size to be 2 ^ x, and the base address is naturally @@ -694,11 +664,12 @@ static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, mask = ilog2(__roundup_pow_of_two(pages)); /* Fallback to domain selective flush if size is too big */ if (mask > cap_max_amask_val(iommu->cap)) - return iommu_flush_iotlb_dsi(iommu, did, - non_present_entry_flush); + return iommu->flush.flush_iotlb(iommu, did, 0, 0, + DMA_TLB_DSI_FLUSH, non_present_entry_flush); - return __iommu_flush_iotlb(iommu, did, addr, mask, - DMA_TLB_PSI_FLUSH, non_present_entry_flush); + return iommu->flush.flush_iotlb(iommu, did, addr, mask, + DMA_TLB_PSI_FLUSH, + non_present_entry_flush); } static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu) @@ -831,7 +802,7 @@ void dmar_msi_read(int irq, struct msi_msg *msg) } static int iommu_page_fault_do_one(struct intel_iommu *iommu, int type, - u8 fault_reason, u16 source_id, u64 addr) + u8 fault_reason, u16 source_id, unsigned long long addr) { const char *reason; @@ -1084,9 +1055,9 @@ static void dmar_init_reserved_ranges(void) if (!r->flags || !(r->flags & IORESOURCE_MEM)) continue; addr = r->start; - addr &= PAGE_MASK_4K; + addr &= PAGE_MASK; size = r->end - addr; - size = PAGE_ALIGN_4K(size); + size = PAGE_ALIGN(size); iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr), IOVA_PFN(size + addr) - 1); if (!iova) @@ -1148,7 +1119,7 @@ static int domain_init(struct dmar_domain *domain, int guest_width) domain->pgd = (struct dma_pte *)alloc_pgtable_page(); if (!domain->pgd) return -ENOMEM; - __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE_4K); + __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE); return 0; } @@ -1164,7 +1135,7 @@ static void domain_exit(struct dmar_domain *domain) /* destroy iovas */ put_iova_domain(&domain->iovad); end = DOMAIN_MAX_ADDR(domain->gaw); - end = end & (~PAGE_MASK_4K); + end = end & (~PAGE_MASK); /* clear ptes */ dma_pte_clear_range(domain, 0, end); @@ -1204,11 +1175,13 @@ static int domain_context_mapping_one(struct dmar_domain *domain, __iommu_flush_cache(iommu, context, sizeof(*context)); /* it's a non-present to present mapping */ - if (iommu_flush_context_device(iommu, domain->id, - (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT, 1)) + if (iommu->flush.flush_context(iommu, domain->id, + (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT, + DMA_CCMD_DEVICE_INVL, 1)) iommu_flush_write_buffer(iommu); else - iommu_flush_iotlb_dsi(iommu, 0, 0); + iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_DSI_FLUSH, 0); + spin_unlock_irqrestore(&iommu->lock, flags); return 0; } @@ -1283,22 +1256,25 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, u64 start_pfn, end_pfn; struct dma_pte *pte; int index; + int addr_width = agaw_to_width(domain->agaw); + + hpa &= (((u64)1) << addr_width) - 1; if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) return -EINVAL; - iova &= PAGE_MASK_4K; - start_pfn = ((u64)hpa) >> PAGE_SHIFT_4K; - end_pfn = (PAGE_ALIGN_4K(((u64)hpa) + size)) >> PAGE_SHIFT_4K; + iova &= PAGE_MASK; + start_pfn = ((u64)hpa) >> VTD_PAGE_SHIFT; + end_pfn = (VTD_PAGE_ALIGN(((u64)hpa) + size)) >> VTD_PAGE_SHIFT; index = 0; while (start_pfn < end_pfn) { - pte = addr_to_dma_pte(domain, iova + PAGE_SIZE_4K * index); + pte = addr_to_dma_pte(domain, iova + VTD_PAGE_SIZE * index); if (!pte) return -ENOMEM; /* We don't need lock here, nobody else * touches the iova range */ BUG_ON(dma_pte_addr(*pte)); - dma_set_pte_addr(*pte, start_pfn << PAGE_SHIFT_4K); + dma_set_pte_addr(*pte, start_pfn << VTD_PAGE_SHIFT); dma_set_pte_prot(*pte, prot); __iommu_flush_cache(domain->iommu, pte, sizeof(*pte)); start_pfn++; @@ -1310,8 +1286,10 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, static void detach_domain_for_dev(struct dmar_domain *domain, u8 bus, u8 devfn) { clear_context_table(domain->iommu, bus, devfn); - iommu_flush_context_global(domain->iommu, 0); - iommu_flush_iotlb_global(domain->iommu, 0); + domain->iommu->flush.flush_context(domain->iommu, 0, 0, 0, + DMA_CCMD_GLOBAL_INVL, 0); + domain->iommu->flush.flush_iotlb(domain->iommu, 0, 0, 0, + DMA_TLB_GLOBAL_FLUSH, 0); } static void domain_remove_dev_info(struct dmar_domain *domain) @@ -1474,11 +1452,13 @@ error: return find_domain(pdev); } -static int iommu_prepare_identity_map(struct pci_dev *pdev, u64 start, u64 end) +static int iommu_prepare_identity_map(struct pci_dev *pdev, + unsigned long long start, + unsigned long long end) { struct dmar_domain *domain; unsigned long size; - u64 base; + unsigned long long base; int ret; printk(KERN_INFO @@ -1490,9 +1470,9 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, u64 start, u64 end) return -ENOMEM; /* The address might not be aligned */ - base = start & PAGE_MASK_4K; + base = start & PAGE_MASK; size = end - base; - size = PAGE_ALIGN_4K(size); + size = PAGE_ALIGN(size); if (!reserve_iova(&domain->iovad, IOVA_PFN(base), IOVA_PFN(base + size) - 1)) { printk(KERN_ERR "IOMMU: reserve iova failed\n"); @@ -1662,6 +1642,30 @@ int __init init_dmars(void) } } + for_each_drhd_unit(drhd) { + if (drhd->ignored) + continue; + + iommu = drhd->iommu; + if (dmar_enable_qi(iommu)) { + /* + * Queued Invalidate not enabled, use Register Based + * Invalidate + */ + iommu->flush.flush_context = __iommu_flush_context; + iommu->flush.flush_iotlb = __iommu_flush_iotlb; + printk(KERN_INFO "IOMMU 0x%Lx: using Register based " + "invalidation\n", + (unsigned long long)drhd->reg_base_addr); + } else { + iommu->flush.flush_context = qi_flush_context; + iommu->flush.flush_iotlb = qi_flush_iotlb; + printk(KERN_INFO "IOMMU 0x%Lx: using Queued " + "invalidation\n", + (unsigned long long)drhd->reg_base_addr); + } + } + /* * For each rmrr * for each dev attached to rmrr @@ -1714,9 +1718,10 @@ int __init init_dmars(void) iommu_set_root_entry(iommu); - iommu_flush_context_global(iommu, 0); - iommu_flush_iotlb_global(iommu, 0); - + iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL, + 0); + iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH, + 0); iommu_disable_protect_mem_regions(iommu); ret = iommu_enable_translation(iommu); @@ -1738,8 +1743,8 @@ error: static inline u64 aligned_size(u64 host_addr, size_t size) { u64 addr; - addr = (host_addr & (~PAGE_MASK_4K)) + size; - return PAGE_ALIGN_4K(addr); + addr = (host_addr & (~PAGE_MASK)) + size; + return PAGE_ALIGN(addr); } struct iova * @@ -1753,20 +1758,20 @@ iommu_alloc_iova(struct dmar_domain *domain, size_t size, u64 end) return NULL; piova = alloc_iova(&domain->iovad, - size >> PAGE_SHIFT_4K, IOVA_PFN(end), 1); + size >> PAGE_SHIFT, IOVA_PFN(end), 1); return piova; } static struct iova * __intel_alloc_iova(struct device *dev, struct dmar_domain *domain, - size_t size) + size_t size, u64 dma_mask) { struct pci_dev *pdev = to_pci_dev(dev); struct iova *iova = NULL; - if ((pdev->dma_mask <= DMA_32BIT_MASK) || (dmar_forcedac)) { - iova = iommu_alloc_iova(domain, size, pdev->dma_mask); - } else { + if (dma_mask <= DMA_32BIT_MASK || dmar_forcedac) + iova = iommu_alloc_iova(domain, size, dma_mask); + else { /* * First try to allocate an io virtual address in * DMA_32BIT_MASK and if that fails then try allocating @@ -1774,7 +1779,7 @@ __intel_alloc_iova(struct device *dev, struct dmar_domain *domain, */ iova = iommu_alloc_iova(domain, size, DMA_32BIT_MASK); if (!iova) - iova = iommu_alloc_iova(domain, size, pdev->dma_mask); + iova = iommu_alloc_iova(domain, size, dma_mask); } if (!iova) { @@ -1813,12 +1818,12 @@ get_valid_domain_for_dev(struct pci_dev *pdev) return domain; } -static dma_addr_t -intel_map_single(struct device *hwdev, phys_addr_t paddr, size_t size, int dir) +static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, + size_t size, int dir, u64 dma_mask) { struct pci_dev *pdev = to_pci_dev(hwdev); struct dmar_domain *domain; - unsigned long start_paddr; + phys_addr_t start_paddr; struct iova *iova; int prot = 0; int ret; @@ -1833,11 +1838,11 @@ intel_map_single(struct device *hwdev, phys_addr_t paddr, size_t size, int dir) size = aligned_size((u64)paddr, size); - iova = __intel_alloc_iova(hwdev, domain, size); + iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); if (!iova) goto error; - start_paddr = iova->pfn_lo << PAGE_SHIFT_4K; + start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; /* * Check if DMAR supports zero-length reads on write only @@ -1855,30 +1860,33 @@ intel_map_single(struct device *hwdev, phys_addr_t paddr, size_t size, int dir) * is not a big problem */ ret = domain_page_mapping(domain, start_paddr, - ((u64)paddr) & PAGE_MASK_4K, size, prot); + ((u64)paddr) & PAGE_MASK, size, prot); if (ret) goto error; - pr_debug("Device %s request: %lx@%llx mapping: %lx@%llx, dir %d\n", - pci_name(pdev), size, (u64)paddr, - size, (u64)start_paddr, dir); - /* it's a non-present to present mapping */ ret = iommu_flush_iotlb_psi(domain->iommu, domain->id, - start_paddr, size >> PAGE_SHIFT_4K, 1); + start_paddr, size >> VTD_PAGE_SHIFT, 1); if (ret) iommu_flush_write_buffer(domain->iommu); - return (start_paddr + ((u64)paddr & (~PAGE_MASK_4K))); + return start_paddr + ((u64)paddr & (~PAGE_MASK)); error: if (iova) __free_iova(&domain->iovad, iova); printk(KERN_ERR"Device %s request: %lx@%llx dir %d --- failed\n", - pci_name(pdev), size, (u64)paddr, dir); + pci_name(pdev), size, (unsigned long long)paddr, dir); return 0; } +dma_addr_t intel_map_single(struct device *hwdev, phys_addr_t paddr, + size_t size, int dir) +{ + return __intel_map_single(hwdev, paddr, size, dir, + to_pci_dev(hwdev)->dma_mask); +} + static void flush_unmaps(void) { int i, j; @@ -1891,7 +1899,8 @@ static void flush_unmaps(void) struct intel_iommu *iommu = deferred_flush[i].domain[0]->iommu; - iommu_flush_iotlb_global(iommu, 0); + iommu->flush.flush_iotlb(iommu, 0, 0, 0, + DMA_TLB_GLOBAL_FLUSH, 0); for (j = 0; j < deferred_flush[i].next; j++) { __free_iova(&deferred_flush[i].domain[j]->iovad, deferred_flush[i].iova[j]); @@ -1936,8 +1945,8 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova) spin_unlock_irqrestore(&async_umap_flush_lock, flags); } -static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, - size_t size, int dir) +void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size, + int dir) { struct pci_dev *pdev = to_pci_dev(dev); struct dmar_domain *domain; @@ -1953,11 +1962,11 @@ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, if (!iova) return; - start_addr = iova->pfn_lo << PAGE_SHIFT_4K; + start_addr = iova->pfn_lo << PAGE_SHIFT; size = aligned_size((u64)dev_addr, size); pr_debug("Device %s unmapping: %lx@%llx\n", - pci_name(pdev), size, (u64)start_addr); + pci_name(pdev), size, (unsigned long long)start_addr); /* clear the whole page */ dma_pte_clear_range(domain, start_addr, start_addr + size); @@ -1965,7 +1974,7 @@ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, dma_pte_free_pagetable(domain, start_addr, start_addr + size); if (intel_iommu_strict) { if (iommu_flush_iotlb_psi(domain->iommu, - domain->id, start_addr, size >> PAGE_SHIFT_4K, 0)) + domain->id, start_addr, size >> VTD_PAGE_SHIFT, 0)) iommu_flush_write_buffer(domain->iommu); /* free iova */ __free_iova(&domain->iovad, iova); @@ -1978,13 +1987,13 @@ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, } } -static void * intel_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, gfp_t flags) +void *intel_alloc_coherent(struct device *hwdev, size_t size, + dma_addr_t *dma_handle, gfp_t flags) { void *vaddr; int order; - size = PAGE_ALIGN_4K(size); + size = PAGE_ALIGN(size); order = get_order(size); flags &= ~(GFP_DMA | GFP_DMA32); @@ -1993,19 +2002,21 @@ static void * intel_alloc_coherent(struct device *hwdev, size_t size, return NULL; memset(vaddr, 0, size); - *dma_handle = intel_map_single(hwdev, virt_to_bus(vaddr), size, DMA_BIDIRECTIONAL); + *dma_handle = __intel_map_single(hwdev, virt_to_bus(vaddr), size, + DMA_BIDIRECTIONAL, + hwdev->coherent_dma_mask); if (*dma_handle) return vaddr; free_pages((unsigned long)vaddr, order); return NULL; } -static void intel_free_coherent(struct device *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) +void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr, + dma_addr_t dma_handle) { int order; - size = PAGE_ALIGN_4K(size); + size = PAGE_ALIGN(size); order = get_order(size); intel_unmap_single(hwdev, dma_handle, size, DMA_BIDIRECTIONAL); @@ -2013,8 +2024,9 @@ static void intel_free_coherent(struct device *hwdev, size_t size, } #define SG_ENT_VIRT_ADDRESS(sg) (sg_virt((sg))) -static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, - int nelems, int dir) + +void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, + int nelems, int dir) { int i; struct pci_dev *pdev = to_pci_dev(hwdev); @@ -2038,7 +2050,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, size += aligned_size((u64)addr, sg->length); } - start_addr = iova->pfn_lo << PAGE_SHIFT_4K; + start_addr = iova->pfn_lo << PAGE_SHIFT; /* clear the whole page */ dma_pte_clear_range(domain, start_addr, start_addr + size); @@ -2046,7 +2058,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, dma_pte_free_pagetable(domain, start_addr, start_addr + size); if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr, - size >> PAGE_SHIFT_4K, 0)) + size >> VTD_PAGE_SHIFT, 0)) iommu_flush_write_buffer(domain->iommu); /* free iova */ @@ -2067,8 +2079,8 @@ static int intel_nontranslate_map_sg(struct device *hddev, return nelems; } -static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, - int nelems, int dir) +int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems, + int dir) { void *addr; int i; @@ -2096,7 +2108,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, size += aligned_size((u64)addr, sg->length); } - iova = __intel_alloc_iova(hwdev, domain, size); + iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); if (!iova) { sglist->dma_length = 0; return 0; @@ -2112,14 +2124,14 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) prot |= DMA_PTE_WRITE; - start_addr = iova->pfn_lo << PAGE_SHIFT_4K; + start_addr = iova->pfn_lo << PAGE_SHIFT; offset = 0; for_each_sg(sglist, sg, nelems, i) { addr = SG_ENT_VIRT_ADDRESS(sg); addr = (void *)virt_to_phys(addr); size = aligned_size((u64)addr, sg->length); ret = domain_page_mapping(domain, start_addr + offset, - ((u64)addr) & PAGE_MASK_4K, + ((u64)addr) & PAGE_MASK, size, prot); if (ret) { /* clear the page */ @@ -2133,14 +2145,14 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, return 0; } sg->dma_address = start_addr + offset + - ((u64)addr & (~PAGE_MASK_4K)); + ((u64)addr & (~PAGE_MASK)); sg->dma_length = sg->length; offset += size; } /* it's a non-present to present mapping */ if (iommu_flush_iotlb_psi(domain->iommu, domain->id, - start_addr, offset >> PAGE_SHIFT_4K, 1)) + start_addr, offset >> VTD_PAGE_SHIFT, 1)) iommu_flush_write_buffer(domain->iommu); return nelems; } @@ -2180,7 +2192,6 @@ static inline int iommu_devinfo_cache_init(void) sizeof(struct device_domain_info), 0, SLAB_HWCACHE_ALIGN, - NULL); if (!iommu_devinfo_cache) { printk(KERN_ERR "Couldn't create devinfo cache\n"); @@ -2198,7 +2209,6 @@ static inline int iommu_iova_cache_init(void) sizeof(struct iova), 0, SLAB_HWCACHE_ALIGN, - NULL); if (!iommu_iova_cache) { printk(KERN_ERR "Couldn't create iova cache\n"); @@ -2327,7 +2337,7 @@ void intel_iommu_domain_exit(struct dmar_domain *domain) return; end = DOMAIN_MAX_ADDR(domain->gaw); - end = end & (~PAGE_MASK_4K); + end = end & (~VTD_PAGE_MASK); /* clear ptes */ dma_pte_clear_range(domain, 0, end); @@ -2423,6 +2433,6 @@ u64 intel_iommu_iova_to_pfn(struct dmar_domain *domain, u64 iova) if (pte) pfn = dma_pte_addr(*pte); - return pfn >> PAGE_SHIFT_4K; + return pfn >> VTD_PAGE_SHIFT; } EXPORT_SYMBOL_GPL(intel_iommu_iova_to_pfn); diff --git a/drivers/pci/irq.c b/drivers/pci/irq.c new file mode 100644 index 0000000..6441dfa --- /dev/null +++ b/drivers/pci/irq.c @@ -0,0 +1,60 @@ +/* + * PCI IRQ failure handing code + * + * Copyright (c) 2008 James Bottomley <James.Bottomley@HansenPartnership.com> + */ + +#include <linux/acpi.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/pci.h> + +static void pci_note_irq_problem(struct pci_dev *pdev, const char *reason) +{ + struct pci_dev *parent = to_pci_dev(pdev->dev.parent); + + dev_printk(KERN_ERR, &pdev->dev, + "Potentially misrouted IRQ (Bridge %s %04x:%04x)\n", + parent->dev.bus_id, parent->vendor, parent->device); + dev_printk(KERN_ERR, &pdev->dev, "%s\n", reason); + dev_printk(KERN_ERR, &pdev->dev, "Please report to linux-kernel@vger.kernel.org\n"); + WARN_ON(1); +} + +/** + * pci_lost_interrupt - reports a lost PCI interrupt + * @pdev: device whose interrupt is lost + * + * The primary function of this routine is to report a lost interrupt + * in a standard way which users can recognise (instead of blaming the + * driver). + * + * Returns: + * a suggestion for fixing it (although the driver is not required to + * act on this). + */ +enum pci_lost_interrupt_reason pci_lost_interrupt(struct pci_dev *pdev) +{ + if (pdev->msi_enabled || pdev->msix_enabled) { + enum pci_lost_interrupt_reason ret; + + if (pdev->msix_enabled) { + pci_note_irq_problem(pdev, "MSIX routing failure"); + ret = PCI_LOST_IRQ_DISABLE_MSIX; + } else { + pci_note_irq_problem(pdev, "MSI routing failure"); + ret = PCI_LOST_IRQ_DISABLE_MSI; + } + return ret; + } +#ifdef CONFIG_ACPI + if (!(acpi_disabled || acpi_noirq)) { + pci_note_irq_problem(pdev, "Potential ACPI misrouting please reboot with acpi=noirq"); + /* currently no way to fix acpi on the fly */ + return PCI_LOST_IRQ_DISABLE_ACPI; + } +#endif + pci_note_irq_problem(pdev, "unknown cause (not MSI or ACPI)"); + return PCI_LOST_IRQ_NO_INFORMATION; +} +EXPORT_SYMBOL(pci_lost_interrupt); diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d281201..74801f7 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -759,3 +759,24 @@ void pci_msi_init_pci_dev(struct pci_dev *dev) { INIT_LIST_HEAD(&dev->msi_list); } + +#ifdef CONFIG_ACPI +#include <linux/acpi.h> +#include <linux/pci-acpi.h> +static void __devinit msi_acpi_init(void) +{ + if (acpi_pci_disabled) + return; + pci_osc_support_set(OSC_MSI_SUPPORT); + pcie_osc_support_set(OSC_MSI_SUPPORT); +} +#else +static inline void msi_acpi_init(void) { } +#endif /* CONFIG_ACPI */ + +void __devinit msi_init(void) +{ + if (!pci_msi_enable) + return; + msi_acpi_init(); +} diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 89a2f0f..ae5ec76 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -24,17 +24,17 @@ struct acpi_osc_data { acpi_handle handle; u32 support_set; u32 control_set; - int is_queried; - u32 query_result; struct list_head sibiling; }; static LIST_HEAD(acpi_osc_data_list); struct acpi_osc_args { u32 capbuf[3]; - u32 query_result; + u32 ctrl_result; }; +static DEFINE_MUTEX(pci_acpi_lock); + static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) { struct acpi_osc_data *data; @@ -63,7 +63,7 @@ static acpi_status acpi_run_osc(acpi_handle handle, union acpi_object in_params[4]; struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *out_obj; - u32 osc_dw0, flags = osc_args->capbuf[OSC_QUERY_TYPE]; + u32 errors, flags = osc_args->capbuf[OSC_QUERY_TYPE]; /* Setting up input parameters */ input.count = 4; @@ -83,21 +83,25 @@ static acpi_status acpi_run_osc(acpi_handle handle, if (ACPI_FAILURE(status)) return status; + if (!output.length) + return AE_NULL_OBJECT; + out_obj = output.pointer; if (out_obj->type != ACPI_TYPE_BUFFER) { printk(KERN_DEBUG "Evaluate _OSC returns wrong type\n"); status = AE_TYPE; goto out_kfree; } - osc_dw0 = *((u32 *)out_obj->buffer.pointer); - if (osc_dw0) { - if (osc_dw0 & OSC_REQUEST_ERROR) + /* Need to ignore the bit0 in result code */ + errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); + if (errors) { + if (errors & OSC_REQUEST_ERROR) printk(KERN_DEBUG "_OSC request fails\n"); - if (osc_dw0 & OSC_INVALID_UUID_ERROR) + if (errors & OSC_INVALID_UUID_ERROR) printk(KERN_DEBUG "_OSC invalid UUID\n"); - if (osc_dw0 & OSC_INVALID_REVISION_ERROR) + if (errors & OSC_INVALID_REVISION_ERROR) printk(KERN_DEBUG "_OSC invalid revision\n"); - if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { + if (errors & OSC_CAPABILITIES_MASK_ERROR) { if (flags & OSC_QUERY_ENABLE) goto out_success; printk(KERN_DEBUG "_OSC FW not grant req. control\n"); @@ -108,9 +112,8 @@ static acpi_status acpi_run_osc(acpi_handle handle, goto out_kfree; } out_success: - if (flags & OSC_QUERY_ENABLE) - osc_args->query_result = - *((u32 *)(out_obj->buffer.pointer + 8)); + osc_args->ctrl_result = + *((u32 *)(out_obj->buffer.pointer + 8)); status = AE_OK; out_kfree: @@ -118,41 +121,53 @@ out_kfree: return status; } -static acpi_status acpi_query_osc(acpi_handle handle, - u32 level, void *context, void **retval) +static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data, + u32 *result) { acpi_status status; - struct acpi_osc_data *osc_data; - u32 flags = (unsigned long)context, support_set; - acpi_handle tmp; + u32 support_set; struct acpi_osc_args osc_args; - status = acpi_get_handle(handle, "_OSC", &tmp); - if (ACPI_FAILURE(status)) - return status; - - osc_data = acpi_get_osc_data(handle); - if (!osc_data) { - printk(KERN_ERR "acpi osc data array is full\n"); - return AE_ERROR; - } - /* do _OSC query for all possible controls */ support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS); osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set; osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; - status = acpi_run_osc(handle, &osc_args); + status = acpi_run_osc(osc_data->handle, &osc_args); if (ACPI_SUCCESS(status)) { osc_data->support_set = support_set; - osc_data->query_result = osc_args.query_result; - osc_data->is_queried = 1; + *result = osc_args.ctrl_result; } return status; } +static acpi_status acpi_query_osc(acpi_handle handle, + u32 level, void *context, void **retval) +{ + acpi_status status; + struct acpi_osc_data *osc_data; + u32 flags = (unsigned long)context, dummy; + acpi_handle tmp; + + status = acpi_get_handle(handle, "_OSC", &tmp); + if (ACPI_FAILURE(status)) + return AE_OK; + + mutex_lock(&pci_acpi_lock); + osc_data = acpi_get_osc_data(handle); + if (!osc_data) { + printk(KERN_ERR "acpi osc data array is full\n"); + goto out; + } + + __acpi_query_osc(flags, osc_data, &dummy); +out: + mutex_unlock(&pci_acpi_lock); + return AE_OK; +} + /** * __pci_osc_support_set - register OS support to Firmware * @flags: OS support bits @@ -181,7 +196,7 @@ acpi_status __pci_osc_support_set(u32 flags, const char *hid) acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) { acpi_status status; - u32 ctrlset, control_set; + u32 ctrlset, control_set, result; acpi_handle tmp; struct acpi_osc_data *osc_data; struct acpi_osc_args osc_args; @@ -190,19 +205,28 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) if (ACPI_FAILURE(status)) return status; + mutex_lock(&pci_acpi_lock); osc_data = acpi_get_osc_data(handle); if (!osc_data) { printk(KERN_ERR "acpi osc data array is full\n"); - return AE_ERROR; + status = AE_ERROR; + goto out; } ctrlset = (flags & OSC_CONTROL_MASKS); - if (!ctrlset) - return AE_TYPE; + if (!ctrlset) { + status = AE_TYPE; + goto out; + } - if (osc_data->is_queried && - ((osc_data->query_result & ctrlset) != ctrlset)) - return AE_SUPPORT; + status = __acpi_query_osc(osc_data->support_set, osc_data, &result); + if (ACPI_FAILURE(status)) + goto out; + + if ((result & ctrlset) != ctrlset) { + status = AE_SUPPORT; + goto out; + } control_set = osc_data->control_set | ctrlset; osc_args.capbuf[OSC_QUERY_TYPE] = 0; @@ -211,7 +235,8 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) status = acpi_run_osc(handle, &osc_args); if (ACPI_SUCCESS(status)) osc_data->control_set = control_set; - +out: + mutex_unlock(&pci_acpi_lock); return status; } EXPORT_SYMBOL(pci_osc_control_set); diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 110022d..5d72866 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -575,7 +575,7 @@ static int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; start = vma->vm_pgoff; - size = pci_resource_len(pdev, resno) >> PAGE_SHIFT; + size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; if (start < size && size - start >= nr) return 1; WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n", diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4db261e..061d1ee 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -18,6 +18,7 @@ #include <linux/log2.h> #include <linux/pci-aspm.h> #include <linux/pm_wakeup.h> +#include <linux/interrupt.h> #include <asm/dma.h> /* isa_dma_bridge_buggy */ #include "pci.h" @@ -1308,27 +1309,32 @@ void pci_enable_ari(struct pci_dev *dev) int pos; u32 cap; u16 ctrl; + struct pci_dev *bridge; - if (!dev->is_pcie) + if (!dev->is_pcie || dev->devfn) return; - if (dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && - dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); + if (!pos) return; - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + bridge = dev->bus->self; + if (!bridge || !bridge->is_pcie) + return; + + pos = pci_find_capability(bridge, PCI_CAP_ID_EXP); if (!pos) return; - pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap); + pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap); if (!(cap & PCI_EXP_DEVCAP2_ARI)) return; - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); + pci_read_config_word(bridge, pos + PCI_EXP_DEVCTL2, &ctrl); ctrl |= PCI_EXP_DEVCTL2_ARI; - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); + pci_write_config_word(bridge, pos + PCI_EXP_DEVCTL2, ctrl); - dev->ari_enabled = 1; + bridge->ari_enabled = 1; } int @@ -1746,6 +1752,103 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary); #endif /** + * pci_execute_reset_function() - Reset a PCI device function + * @dev: Device function to reset + * + * Some devices allow an individual function to be reset without affecting + * other functions in the same device. The PCI device must be responsive + * to PCI config space in order to use this function. + * + * The device function is presumed to be unused when this function is called. + * Resetting the device will make the contents of PCI configuration space + * random, so any caller of this must be prepared to reinitialise the + * device including MSI, bus mastering, BARs, decoding IO and memory spaces, + * etc. + * + * Returns 0 if the device function was successfully reset or -ENOTTY if the + * device doesn't support resetting a single function. + */ +int pci_execute_reset_function(struct pci_dev *dev) +{ + u16 status; + u32 cap; + int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP); + + if (!exppos) + return -ENOTTY; + pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap); + if (!(cap & PCI_EXP_DEVCAP_FLR)) + return -ENOTTY; + + pci_block_user_cfg_access(dev); + + /* Wait for Transaction Pending bit clean */ + msleep(100); + pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); + if (status & PCI_EXP_DEVSTA_TRPND) { + dev_info(&dev->dev, "Busy after 100ms while trying to reset; " + "sleeping for 1 second\n"); + ssleep(1); + pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); + if (status & PCI_EXP_DEVSTA_TRPND) + dev_info(&dev->dev, "Still busy after 1s; " + "proceeding with reset anyway\n"); + } + + pci_write_config_word(dev, exppos + PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_BCR_FLR); + mdelay(100); + + pci_unblock_user_cfg_access(dev); + return 0; +} +EXPORT_SYMBOL_GPL(pci_execute_reset_function); + +/** + * pci_reset_function() - quiesce and reset a PCI device function + * @dev: Device function to reset + * + * Some devices allow an individual function to be reset without affecting + * other functions in the same device. The PCI device must be responsive + * to PCI config space in order to use this function. + * + * This function does not just reset the PCI portion of a device, but + * clears all the state associated with the device. This function differs + * from pci_execute_reset_function in that it saves and restores device state + * over the reset. + * + * Returns 0 if the device function was successfully reset or -ENOTTY if the + * device doesn't support resetting a single function. + */ +int pci_reset_function(struct pci_dev *dev) +{ + u32 cap; + int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP); + int r; + + if (!exppos) + return -ENOTTY; + pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap); + if (!(cap & PCI_EXP_DEVCAP_FLR)) + return -ENOTTY; + + if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0) + disable_irq(dev->irq); + pci_save_state(dev); + + pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE); + + r = pci_execute_reset_function(dev); + + pci_restore_state(dev); + if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0) + enable_irq(dev->irq); + + return r; +} +EXPORT_SYMBOL_GPL(pci_reset_function); + +/** * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count * @dev: PCI device to query * @@ -1933,10 +2036,13 @@ static int __devinit pci_init(void) while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { pci_fixup_device(pci_fixup_final, dev); } + + msi_init(); + return 0; } -static int __devinit pci_setup(char *str) +static int __init pci_setup(char *str) { while (str) { char *k = strchr(str, ','); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index b205ab8..9de87e9 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -98,9 +98,11 @@ extern unsigned int pci_pm_d3_delay; #ifdef CONFIG_PCI_MSI void pci_no_msi(void); extern void pci_msi_init_pci_dev(struct pci_dev *dev); +extern void __devinit msi_init(void); #else static inline void pci_no_msi(void) { } static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } +static inline void msi_init(void) { } #endif #ifdef CONFIG_PCIEAER diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index dfc63d0..aac7006 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -252,7 +252,7 @@ static void report_resume(struct pci_dev *dev, void *data) if (!dev->driver || !dev->driver->err_handler || - !dev->driver->err_handler->slot_reset) + !dev->driver->err_handler->resume) return; err_handler = dev->driver->err_handler; diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 8f63f4c..9aad608 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -16,6 +16,7 @@ #include <linux/pm.h> #include <linux/init.h> #include <linux/slab.h> +#include <linux/jiffies.h> #include <linux/pci-aspm.h> #include "../pci.h" @@ -161,11 +162,12 @@ static void pcie_check_clock_pm(struct pci_dev *pdev) */ static void pcie_aspm_configure_common_clock(struct pci_dev *pdev) { - int pos, child_pos; + int pos, child_pos, i = 0; u16 reg16 = 0; struct pci_dev *child_dev; int same_clock = 1; - + unsigned long start_jiffies; + u16 child_regs[8], parent_reg; /* * all functions of a slot should have the same Slot Clock * Configuration, so just check one function @@ -191,16 +193,19 @@ static void pcie_aspm_configure_common_clock(struct pci_dev *pdev) child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP); pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL, ®16); + child_regs[i] = reg16; if (same_clock) reg16 |= PCI_EXP_LNKCTL_CCC; else reg16 &= ~PCI_EXP_LNKCTL_CCC; pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL, reg16); + i++; } /* Configure upstream component */ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); + parent_reg = reg16; if (same_clock) reg16 |= PCI_EXP_LNKCTL_CCC; else @@ -212,12 +217,30 @@ static void pcie_aspm_configure_common_clock(struct pci_dev *pdev) pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); /* Wait for link training end */ - while (1) { + /* break out after waiting for 1 second */ + start_jiffies = jiffies; + while ((jiffies - start_jiffies) < HZ) { pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, ®16); if (!(reg16 & PCI_EXP_LNKSTA_LT)) break; cpu_relax(); } + /* training failed -> recover */ + if ((jiffies - start_jiffies) >= HZ) { + dev_printk (KERN_ERR, &pdev->dev, "ASPM: Could not configure" + " common clock\n"); + i = 0; + list_for_each_entry(child_dev, &pdev->subordinate->devices, + bus_list) { + child_pos = pci_find_capability(child_dev, + PCI_CAP_ID_EXP); + pci_write_config_word(child_dev, + child_pos + PCI_EXP_LNKCTL, + child_regs[i]); + i++; + } + pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, parent_reg); + } } /* diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index aaaf0a1..003a9b3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -298,9 +298,6 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) child->resource[i] = child->parent->resource[i - 3]; } - for(i=0; i<3; i++) - child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; - res = child->resource[0]; pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); @@ -480,19 +477,27 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); u32 buses, i, j = 0; u16 bctl; + int broken = 0; pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); dev_dbg(&dev->dev, "scanning behind bridge, config %06x, pass %d\n", buses & 0xffffff, pass); + /* Check if setup is sensible at all */ + if (!pass && + ((buses & 0xff) != bus->number || ((buses >> 8) & 0xff) <= bus->number)) { + dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n"); + broken = 1; + } + /* Disable MasterAbortMode during probing to avoid reporting of bus errors (in some architectures) */ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bctl); pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); - if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) { + if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus && !broken) { unsigned int cmax, busnr; /* * Bus already configured by firmware, process it in the first @@ -530,7 +535,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, * do in the second pass. */ if (!pass) { - if (pcibios_assign_all_busses()) + if (pcibios_assign_all_busses() || broken) /* Temporarily disable forwarding of the configuration cycles on all bridges in this bus segment to avoid possible diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index bbf66ea..ce09856 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -22,6 +22,7 @@ #include <linux/delay.h> #include <linux/acpi.h> #include <linux/kallsyms.h> +#include <linux/dmi.h> #include "pci.h" int isa_dma_bridge_buggy; @@ -605,27 +606,6 @@ static void __init quirk_ioapic_rmw(struct pci_dev *dev) sis_apic_bug = 1; } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw); - -#define AMD8131_revA0 0x01 -#define AMD8131_revB0 0x11 -#define AMD8131_MISC 0x40 -#define AMD8131_NIOAMODE_BIT 0 -static void quirk_amd_8131_ioapic(struct pci_dev *dev) -{ - unsigned char tmp; - - if (nr_ioapics == 0) - return; - - if (dev->revision == AMD8131_revA0 || dev->revision == AMD8131_revB0) { - dev_info(&dev->dev, "Fixing up AMD8131 IOAPIC mode\n"); - pci_read_config_byte( dev, AMD8131_MISC, &tmp); - tmp &= ~(1 << AMD8131_NIOAMODE_BIT); - pci_write_config_byte( dev, AMD8131_MISC, tmp); - } -} -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); #endif /* CONFIG_X86_IO_APIC */ /* @@ -1422,6 +1402,155 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2609, quirk_intel_pcie_pm); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); +#ifdef CONFIG_X86_IO_APIC +/* + * Boot interrupts on some chipsets cannot be turned off. For these chipsets, + * remap the original interrupt in the linux kernel to the boot interrupt, so + * that a PCI device's interrupt handler is installed on the boot interrupt + * line instead. + */ +static void quirk_reroute_to_boot_interrupts_intel(struct pci_dev *dev) +{ + if (noioapicquirk || noioapicreroute) + return; + + dev->irq_reroute_variant = INTEL_IRQ_REROUTE_VARIANT; + + printk(KERN_INFO "PCI quirk: reroute interrupts for 0x%04x:0x%04x\n", + dev->vendor, dev->device); + return; +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80333_0, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80333_1, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80332_0, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80332_1, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80333_0, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80333_1, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80332_0, quirk_reroute_to_boot_interrupts_intel); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80332_1, quirk_reroute_to_boot_interrupts_intel); + +/* + * On some chipsets we can disable the generation of legacy INTx boot + * interrupts. + */ + +/* + * IO-APIC1 on 6300ESB generates boot interrupts, see intel order no + * 300641-004US, section 5.7.3. + */ +#define INTEL_6300_IOAPIC_ABAR 0x40 +#define INTEL_6300_DISABLE_BOOT_IRQ (1<<14) + +static void quirk_disable_intel_boot_interrupt(struct pci_dev *dev) +{ + u16 pci_config_word; + + if (noioapicquirk) + return; + + pci_read_config_word(dev, INTEL_6300_IOAPIC_ABAR, &pci_config_word); + pci_config_word |= INTEL_6300_DISABLE_BOOT_IRQ; + pci_write_config_word(dev, INTEL_6300_IOAPIC_ABAR, pci_config_word); + + printk(KERN_INFO "disabled boot interrupt on device 0x%04x:0x%04x\n", + dev->vendor, dev->device); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_10, quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_10, quirk_disable_intel_boot_interrupt); + +/* + * disable boot interrupts on HT-1000 + */ +#define BC_HT1000_FEATURE_REG 0x64 +#define BC_HT1000_PIC_REGS_ENABLE (1<<0) +#define BC_HT1000_MAP_IDX 0xC00 +#define BC_HT1000_MAP_DATA 0xC01 + +static void quirk_disable_broadcom_boot_interrupt(struct pci_dev *dev) +{ + u32 pci_config_dword; + u8 irq; + + if (noioapicquirk) + return; + + pci_read_config_dword(dev, BC_HT1000_FEATURE_REG, &pci_config_dword); + pci_write_config_dword(dev, BC_HT1000_FEATURE_REG, pci_config_dword | + BC_HT1000_PIC_REGS_ENABLE); + + for (irq = 0x10; irq < 0x10 + 32; irq++) { + outb(irq, BC_HT1000_MAP_IDX); + outb(0x00, BC_HT1000_MAP_DATA); + } + + pci_write_config_dword(dev, BC_HT1000_FEATURE_REG, pci_config_dword); + + printk(KERN_INFO "disabled boot interrupts on PCI device" + "0x%04x:0x%04x\n", dev->vendor, dev->device); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB, quirk_disable_broadcom_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB, quirk_disable_broadcom_boot_interrupt); + +/* + * disable boot interrupts on AMD and ATI chipsets + */ +/* + * NOIOAMODE needs to be disabled to disable "boot interrupts". For AMD 8131 + * rev. A0 and B0, NOIOAMODE needs to be disabled anyway to fix IO-APIC mode + * (due to an erratum). + */ +#define AMD_813X_MISC 0x40 +#define AMD_813X_NOIOAMODE (1<<0) + +static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) +{ + u32 pci_config_dword; + + if (noioapicquirk) + return; + + pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword); + pci_config_dword &= ~AMD_813X_NOIOAMODE; + pci_write_config_dword(dev, AMD_813X_MISC, pci_config_dword); + + printk(KERN_INFO "disabled boot interrupts on PCI device " + "0x%04x:0x%04x\n", dev->vendor, dev->device); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt); + +#define AMD_8111_PCI_IRQ_ROUTING 0x56 + +static void quirk_disable_amd_8111_boot_interrupt(struct pci_dev *dev) +{ + u16 pci_config_word; + + if (noioapicquirk) + return; + + pci_read_config_word(dev, AMD_8111_PCI_IRQ_ROUTING, &pci_config_word); + if (!pci_config_word) { + printk(KERN_INFO "boot interrupts on PCI device 0x%04x:0x%04x " + "already disabled\n", + dev->vendor, dev->device); + return; + } + pci_write_config_word(dev, AMD_8111_PCI_IRQ_ROUTING, 0); + printk(KERN_INFO "disabled boot interrupts on PCI device " + "0x%04x:0x%04x\n", dev->vendor, dev->device); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS, quirk_disable_amd_8111_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS, quirk_disable_amd_8111_boot_interrupt); +#endif /* CONFIG_X86_IO_APIC */ + /* * Toshiba TC86C001 IDE controller reports the standard 8-byte BAR0 size * but the PIO transfers won't work if BAR0 falls at the odd 8 bytes. @@ -1692,24 +1821,24 @@ static void __devinit quirk_brcm_570x_limit_vpd(struct pci_dev *dev) } } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, - PCI_DEVICE_ID_NX2_5706, - quirk_brcm_570x_limit_vpd); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, - PCI_DEVICE_ID_NX2_5706S, - quirk_brcm_570x_limit_vpd); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, - PCI_DEVICE_ID_NX2_5708, - quirk_brcm_570x_limit_vpd); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, - PCI_DEVICE_ID_NX2_5708S, - quirk_brcm_570x_limit_vpd); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, - PCI_DEVICE_ID_NX2_5709, - quirk_brcm_570x_limit_vpd); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, - PCI_DEVICE_ID_NX2_5709S, - quirk_brcm_570x_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_NX2_5706, + quirk_brcm_570x_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_NX2_5706S, + quirk_brcm_570x_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_NX2_5708, + quirk_brcm_570x_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_NX2_5708S, + quirk_brcm_570x_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_NX2_5709, + quirk_brcm_570x_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_NX2_5709S, + quirk_brcm_570x_limit_vpd); #ifdef CONFIG_PCI_MSI /* Some chipsets do not support MSI. We cannot easily rely on setting @@ -1828,6 +1957,22 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB, ht_enable_msi_mapping); +/* The P5N32-SLI Premium motherboard from Asus has a problem with msi + * for the MCP55 NIC. It is not yet determined whether the msi problem + * also affects other devices. As for now, turn off msi for this device. + */ +static void __devinit nvenet_msi_disable(struct pci_dev *dev) +{ + if (dmi_name_in_vendors("P5N32-SLI PREMIUM")) { + dev_info(&dev->dev, + "Disabling msi for MCP55 NIC on P5N32-SLI Premium\n"); + dev->no_msi = 1; + } +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, + PCI_DEVICE_ID_NVIDIA_NVENET_15, + nvenet_msi_disable); + static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) { struct pci_dev *host_bridge; diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index 1f5f614..132a781 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -100,7 +100,8 @@ size_t pci_get_rom_size(void __iomem *rom, size_t size) * pci_map_rom - map a PCI ROM to kernel space * @pdev: pointer to pci device struct * @size: pointer to receive size of pci window over ROM - * @return: kernel virtual pointer to image of ROM + * + * 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 @@ -167,7 +168,8 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy * @pdev: pointer to pci device struct * @size: pointer to receive size of pci window over ROM - * @return: kernel virtual pointer to image of ROM + * + * 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 diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 4edfc47..5af8bd5 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -166,6 +166,7 @@ struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, { struct pci_dev *pdev; + pci_dev_get(from); pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); pci_dev_put(pdev); return pdev; @@ -270,12 +271,8 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, struct pci_dev *pdev = NULL; WARN_ON(in_interrupt()); - if (from) { - /* FIXME - * take the cast off, when bus_find_device is made const. - */ - dev_start = (struct device *)&from->dev; - } + if (from) + dev_start = &from->dev; dev = bus_find_device(&pci_bus_type, dev_start, (void *)id, match_pci_dev_by_id); if (dev) diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 0c6db03..5a8ccb4 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -78,18 +78,100 @@ static struct kobj_type pci_slot_ktype = { .default_attrs = pci_slot_default_attrs, }; +static char *make_slot_name(const char *name) +{ + char *new_name; + int len, max, dup; + + new_name = kstrdup(name, GFP_KERNEL); + if (!new_name) + return NULL; + + /* + * Make sure we hit the realloc case the first time through the + * loop. 'len' will be strlen(name) + 3 at that point which is + * enough space for "name-X" and the trailing NUL. + */ + len = strlen(name) + 2; + max = 1; + dup = 1; + + for (;;) { + struct kobject *dup_slot; + dup_slot = kset_find_obj(pci_slots_kset, new_name); + if (!dup_slot) + break; + kobject_put(dup_slot); + if (dup == max) { + len++; + max *= 10; + kfree(new_name); + new_name = kmalloc(len, GFP_KERNEL); + if (!new_name) + break; + } + sprintf(new_name, "%s-%d", name, dup++); + } + + return new_name; +} + +static int rename_slot(struct pci_slot *slot, const char *name) +{ + int result = 0; + char *slot_name; + + if (strcmp(pci_slot_name(slot), name) == 0) + return result; + + slot_name = make_slot_name(name); + if (!slot_name) + return -ENOMEM; + + result = kobject_rename(&slot->kobj, slot_name); + kfree(slot_name); + + return result; +} + +static struct pci_slot *get_slot(struct pci_bus *parent, int slot_nr) +{ + struct pci_slot *slot; + /* + * We already hold pci_bus_sem so don't worry + */ + list_for_each_entry(slot, &parent->slots, list) + if (slot->number == slot_nr) { + kobject_get(&slot->kobj); + return slot; + } + + return NULL; +} + /** * pci_create_slot - create or increment refcount for physical PCI slot * @parent: struct pci_bus of parent bridge * @slot_nr: PCI_SLOT(pci_dev->devfn) or -1 for placeholder * @name: user visible string presented in /sys/bus/pci/slots/<name> + * @hotplug: set if caller is hotplug driver, NULL otherwise * * PCI slots have first class attributes such as address, speed, width, * and a &struct pci_slot is used to manage them. This interface will * either return a new &struct pci_slot to the caller, or if the pci_slot * already exists, its refcount will be incremented. * - * Slots are uniquely identified by a @pci_bus, @slot_nr, @name tuple. + * Slots are uniquely identified by a @pci_bus, @slot_nr tuple. + * + * There are known platforms with broken firmware that assign the same + * name to multiple slots. Workaround these broken platforms by renaming + * the slots on behalf of the caller. If firmware assigns name N to + * multiple slots: + * + * The first slot is assigned N + * The second slot is assigned N-1 + * The third slot is assigned N-2 + * etc. * * Placeholder slots: * In most cases, @pci_bus, @slot_nr will be sufficient to uniquely identify @@ -98,61 +180,67 @@ static struct kobj_type pci_slot_ktype = { * the slot. In this scenario, the caller may pass -1 for @slot_nr. * * The following semantics are imposed when the caller passes @slot_nr == - * -1. First, the check for existing %struct pci_slot is skipped, as the - * caller may know about several unpopulated slots on a given %struct - * pci_bus, and each slot would have a @slot_nr of -1. Uniqueness for - * these slots is then determined by the @name parameter. We expect - * kobject_init_and_add() to warn us if the caller attempts to create - * multiple slots with the same name. The other change in semantics is + * -1. First, we no longer check for an existing %struct pci_slot, as there + * may be many slots with @slot_nr of -1. The other change in semantics is * user-visible, which is the 'address' parameter presented in sysfs will * consist solely of a dddd:bb tuple, where dddd is the PCI domain of the * %struct pci_bus and bb is the bus number. In other words, the devfn of * the 'placeholder' slot will not be displayed. */ - struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, - const char *name) + const char *name, + struct hotplug_slot *hotplug) { struct pci_dev *dev; struct pci_slot *slot; - int err; + int err = 0; + char *slot_name = NULL; down_write(&pci_bus_sem); if (slot_nr == -1) goto placeholder; - /* If we've already created this slot, bump refcount and return. */ - list_for_each_entry(slot, &parent->slots, list) { - if (slot->number == slot_nr) { - kobject_get(&slot->kobj); - pr_debug("%s: inc refcount to %d on %04x:%02x:%02x\n", - __func__, - atomic_read(&slot->kobj.kref.refcount), - pci_domain_nr(parent), parent->number, - slot_nr); - goto out; + /* + * Hotplug drivers are allowed to rename an existing slot, + * but only if not already claimed. + */ + slot = get_slot(parent, slot_nr); + if (slot) { + if (hotplug) { + if ((err = slot->hotplug ? -EBUSY : 0) + || (err = rename_slot(slot, name))) { + kobject_put(&slot->kobj); + slot = NULL; + goto err; + } } + goto out; } placeholder: slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) { - slot = ERR_PTR(-ENOMEM); - goto out; + err = -ENOMEM; + goto err; } slot->bus = parent; slot->number = slot_nr; slot->kobj.kset = pci_slots_kset; - err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL, - "%s", name); - if (err) { - printk(KERN_ERR "Unable to register kobject %s\n", name); + + slot_name = make_slot_name(name); + if (!slot_name) { + err = -ENOMEM; goto err; } + err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL, + "%s", slot_name); + if (err) + goto err; + INIT_LIST_HEAD(&slot->list); list_add(&slot->list, &parent->slots); @@ -164,10 +252,11 @@ placeholder: pr_debug("%s: created pci_slot on %04x:%02x:%02x\n", __func__, pci_domain_nr(parent), parent->number, slot_nr); - out: +out: + kfree(slot_name); up_write(&pci_bus_sem); return slot; - err: +err: kfree(slot); slot = ERR_PTR(err); goto out; @@ -175,7 +264,7 @@ placeholder: EXPORT_SYMBOL_GPL(pci_create_slot); /** - * pci_update_slot_number - update %struct pci_slot -> number + * pci_renumber_slot - update %struct pci_slot -> number * @slot - %struct pci_slot to update * @slot_nr - new number for slot * @@ -183,27 +272,22 @@ EXPORT_SYMBOL_GPL(pci_create_slot); * created a placeholder slot in pci_create_slot() by passing a -1 as * slot_nr, to update their %struct pci_slot with the correct @slot_nr. */ - -void pci_update_slot_number(struct pci_slot *slot, int slot_nr) +void pci_renumber_slot(struct pci_slot *slot, int slot_nr) { - int name_count = 0; struct pci_slot *tmp; down_write(&pci_bus_sem); list_for_each_entry(tmp, &slot->bus->slots, list) { WARN_ON(tmp->number == slot_nr); - if (!strcmp(kobject_name(&tmp->kobj), kobject_name(&slot->kobj))) - name_count++; + goto out; } - if (name_count > 1) - printk(KERN_WARNING "pci_update_slot_number found %d slots with the same name: %s\n", name_count, kobject_name(&slot->kobj)); - slot->number = slot_nr; +out: up_write(&pci_bus_sem); } -EXPORT_SYMBOL_GPL(pci_update_slot_number); +EXPORT_SYMBOL_GPL(pci_renumber_slot); /** * pci_destroy_slot - decrement refcount for physical PCI slot @@ -213,7 +297,6 @@ EXPORT_SYMBOL_GPL(pci_update_slot_number); * just call kobject_put on its kobj and let our release methods do the * rest. */ - void pci_destroy_slot(struct pci_slot *slot) { pr_debug("%s: dec refcount to %d on %04x:%02x:%02x\n", __func__, |