* [BK PATCH] PCI fixes for 2.6.7 @ 2004-06-24 21:30 Greg KH 2004-06-24 21:46 ` [PATCH] " Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2004-06-24 21:30 UTC (permalink / raw) To: torvalds, akpm; +Cc: linux-kernel Hi, Here are some small PCI patches for 2.6.7. They include some pci id fixes, quirk fixups, and pci hotplug driver updates. They have all been in the last few -mm releases. Please pull from: bk://kernel.bkbits.net/gregkh/linux/pci-2.6 thanks, greg k-h p.s. I'll send these as patches in response to this email to lkml for those who want to see them. Documentation/pci.txt | 5 Documentation/power/pci.txt | 8 arch/i386/kernel/dmi_scan.c | 59 +++++ arch/i386/pci/irq.c | 27 ++ drivers/pci/hotplug/pciehp_ctrl.c | 147 ++++---------- drivers/pci/hotplug/pciehp_hpc.c | 4 drivers/pci/hotplug/pciehprm_acpi.c | 22 +- drivers/pci/hotplug/pciehprm_nonacpi.c | 18 + drivers/pci/hotplug/rpadlpar_core.c | 28 -- drivers/pci/hotplug/rpaphp.h | 28 ++ drivers/pci/hotplug/rpaphp_core.c | 199 +++++++++++++------- drivers/pci/hotplug/rpaphp_pci.c | 328 ++++++++++++++++++++++----------- drivers/pci/hotplug/rpaphp_slot.c | 136 +++++++++++-- drivers/pci/hotplug/rpaphp_vio.c | 6 drivers/pci/hotplug/shpchp.h | 1 drivers/pci/hotplug/shpchp_ctrl.c | 60 ++---- drivers/pci/hotplug/shpchp_pci.c | 1 drivers/pci/hotplug/shpchprm_acpi.c | 22 +- drivers/pci/hotplug/shpchprm_nonacpi.c | 18 + drivers/pci/msi.c | 10 - drivers/pci/pci.c | 2 drivers/pci/quirks.c | 1 include/linux/pci_ids.h | 54 +++-- 23 files changed, 781 insertions(+), 403 deletions(-) ----- <ossi:kde.org>: o PCI: (one more) PCI quirk for SMBus bridge on Asus P4 boards Bjorn Helgaas: o PCI: clarify pci.txt wrt IRQ allocation Daniel Ritz: o PCI: fix irq routing on acer travelmate 360 laptop Dely Sy: o Fixes for hot-plug drivers (updated) Linda Xie: o PCI Hotplug: rpaphp.patch -- multi-function devices not handled correctly Roger Luethi: o PCI: Fix off-by-one in pci_enable_wake o PCI: Fix PME bits in pci.txt Roland Dreier: o PCI: Fix MSI-X setup Stephen Hemminger: o PCI: add id's for sk98 driver o PCI: fix out of order entry in pci_ids.h o PCI: remove duplicate in pci_ids.h ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] PCI fixes for 2.6.7 2004-06-24 21:30 [BK PATCH] PCI fixes for 2.6.7 Greg KH @ 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2004-06-24 21:46 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1722.103.1, 2004/06/04 15:01:07-07:00, dlsy@snoqualmie.dp.intel.com [PATCH] Fixes for hot-plug drivers (updated) Here is the updated patch (against 2.6.7-rc1) for the shpchp and pciehp drivers that fixes the following issues: - proper LED status when latch is open or card is not present while the user tries to power up the slot; (reported by D. Keck) - check if kmalloc() return NULL before proceeding in acpi_get__hpp(); (provided by L. Capitulino) - add up(&ctrl->crit_sect) before return in error cases in several places; - proper handling of resources when there are other onboard devices behind the p2p bridge that has the hot-plug capabaility; - need to check negotiated link width in check_lnk_status(); - cleanup board_added() in pciehp Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> drivers/pci/hotplug/pciehp_ctrl.c | 147 +++++++++++---------------------- drivers/pci/hotplug/pciehp_hpc.c | 4 drivers/pci/hotplug/pciehprm_acpi.c | 22 +++- drivers/pci/hotplug/pciehprm_nonacpi.c | 18 ++-- drivers/pci/hotplug/shpchp.h | 1 drivers/pci/hotplug/shpchp_ctrl.c | 60 +++++-------- drivers/pci/hotplug/shpchp_pci.c | 1 drivers/pci/hotplug/shpchprm_acpi.c | 22 +++- drivers/pci/hotplug/shpchprm_nonacpi.c | 18 ++-- 9 files changed, 137 insertions(+), 156 deletions(-) diff -Nru a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c --- a/drivers/pci/hotplug/pciehp_ctrl.c 2004-06-24 13:52:05 -07:00 +++ b/drivers/pci/hotplug/pciehp_ctrl.c 2004-06-24 13:52:05 -07:00 @@ -1058,6 +1058,34 @@ hotplug controller logic */ +static void set_slot_off(struct controller *ctrl, struct slot * pslot) +{ + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* turn off slot, turn on Amber LED, turn off Green LED */ + if (pslot->hpc_ops->power_off_slot(pslot)) { + err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return; + } + wait_for_ctrl_irq (ctrl); + + pslot->hpc_ops->green_led_off(pslot); + + wait_for_ctrl_irq (ctrl); + + /* turn on Amber LED */ + if (pslot->hpc_ops->set_attention_status(pslot, 1)) { + err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return; + } + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); +} /** * board_added - Called after a board has been added to the system. @@ -1071,7 +1099,7 @@ u8 hp_slot; int index; u32 temp_register = 0xFFFFFFFF; - u32 retval, rc = 0; + u32 rc = 0; struct pci_func *new_func = NULL; struct slot *p_slot; struct resource_lists res_lists; @@ -1086,8 +1114,10 @@ /* Power on slot */ rc = p_slot->hpc_ops->power_on_slot(p_slot); - if (rc) + if (rc) { + up(&ctrl->crit_sect); return -1; + } /* Wait for the command to complete */ wait_for_ctrl_irq (ctrl); @@ -1105,11 +1135,12 @@ wait_for_ctrl_irq (ctrl); dbg("%s: afterlong_delay\n", __FUNCTION__); - /* Make this to check for link training status */ + /* Check link training status */ rc = p_slot->hpc_ops->check_lnk_status(ctrl); if (rc) { err("%s: Failed to check link status\n", __FUNCTION__); - return -1; + set_slot_off(ctrl, p_slot); + return rc; } dbg("%s: func status = %x\n", __FUNCTION__, func->status); @@ -1159,36 +1190,7 @@ pciehp_resource_sort_and_combine(&(ctrl->bus_head)); if (rc) { - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - /* turn off slot, turn on Amber LED, turn off Green LED */ - retval = p_slot->hpc_ops->power_off_slot(p_slot); - /* In PCI Express, just power off slot */ - if (retval) { - err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); - return retval; - } - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - p_slot->hpc_ops->green_led_off(p_slot); - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - /* turn on Amber LED */ - retval = p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (retval) { - err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); - return retval; - } - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - + set_slot_off(ctrl, p_slot); return rc; } pciehp_save_slot_config(ctrl, func); @@ -1223,37 +1225,8 @@ up(&ctrl->crit_sect); } else { - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - /* turn off slot, turn on Amber LED, turn off Green LED */ - retval = p_slot->hpc_ops->power_off_slot(p_slot); - /* In PCI Express, just power off slot */ - if (retval) { - err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); - return retval; - } - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - p_slot->hpc_ops->green_led_off(p_slot); - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - /* turn on Amber LED */ - retval = p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (retval) { - err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); - return retval; - } - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - - return rc; + set_slot_off(ctrl, p_slot); + return -1; } return 0; } @@ -1320,6 +1293,7 @@ rc = p_slot->hpc_ops->power_off_slot(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); return rc; } /* Wait for the command to complete */ @@ -1406,7 +1380,6 @@ { struct slot *p_slot = (struct slot *) slot; u8 getstatus; - int rc; pushbutton_pending = 0; @@ -1420,23 +1393,7 @@ p_slot->state = POWEROFF_STATE; dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); - if (pciehp_disable_slot(p_slot)) { - /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); - - /* Turn on the Attention LED */ - rc = p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (rc) { - err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__); - return; - } - - /* Wait for the command to complete */ - wait_for_ctrl_irq (p_slot->ctrl); - - /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); - } + pciehp_disable_slot(p_slot); p_slot->state = STATIC_STATE; } else { p_slot->state = POWERON_STATE; @@ -1446,15 +1403,6 @@ /* Wait for exclusive access to hardware */ down(&p_slot->ctrl->crit_sect); - /* Turn off the green LED */ - rc = p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (rc) { - err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__); - return; - } - /* Wait for the command to complete */ - wait_for_ctrl_irq (p_slot->ctrl); - p_slot->hpc_ops->green_led_off(p_slot); /* Wait for the command to complete */ @@ -1664,7 +1612,10 @@ down(&ctrl->crit_sect); p_slot->hpc_ops->set_attention_status(p_slot, 1); + wait_for_ctrl_irq (ctrl); + p_slot->hpc_ops->green_led_off(p_slot); + wait_for_ctrl_irq (ctrl); /* Done with exclusive hardware access */ up(&ctrl->crit_sect); @@ -1701,21 +1652,21 @@ if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return 0; + return 1; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return 0; + return 1; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return 0; + return 1; } up(&p_slot->ctrl->crit_sect); @@ -1788,21 +1739,21 @@ if (ret || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return 0; + return 1; } ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return 0; + return 1; } ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return 0; + return 1; } up(&p_slot->ctrl->crit_sect); diff -Nru a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c --- a/drivers/pci/hotplug/pciehp_hpc.c 2004-06-24 13:52:05 -07:00 +++ b/drivers/pci/hotplug/pciehp_hpc.c 2004-06-24 13:52:05 -07:00 @@ -349,7 +349,9 @@ return retval; } - if ( (lnk_status & (LNK_TRN | LNK_TRN_ERR)) == 0x0C00) { + dbg("%s: lnk_status = %x\n", __FUNCTION__, lnk_status); + if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) || + !(lnk_status & NEG_LINK_WD)) { err("%s : Link Training Error occurs \n", __FUNCTION__); retval = -1; return retval; diff -Nru a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c --- a/drivers/pci/hotplug/pciehprm_acpi.c 2004-06-24 13:52:05 -07:00 +++ b/drivers/pci/hotplug/pciehprm_acpi.c 2004-06-24 13:52:05 -07:00 @@ -218,6 +218,10 @@ } ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL); + if (!ab->_hpp) { + err ("acpi_pciehprm:%s alloc for _HPP failed\n", path_name); + goto free_and_return; + } memset(ab->_hpp, 0, sizeof(struct acpi__hpp)); ab->_hpp->cache_line_size = nui[0]; @@ -1393,7 +1397,7 @@ static int bind_pci_resources_to_slots ( struct controller *ctrl) { - struct pci_func *func; + struct pci_func *func, new_func; int busn = ctrl->slot_bus; int devn, funn; u32 vid; @@ -1411,11 +1415,19 @@ if (vid != 0xFFFFFFFF) { dbg("%s: vid = %x\n", __FUNCTION__, vid); func = pciehp_slot_find(busn, devn, funn); - if (!func) - continue; - configure_existing_function(ctrl, func); + if (!func) { + memset(&new_func, 0, sizeof(struct pci_func)); + new_func.bus = busn; + new_func.device = devn; + new_func.function = funn; + new_func.is_a_board = 1; + configure_existing_function(ctrl, &new_func); + pciehprm_dump_func_res(&new_func); + } else { + configure_existing_function(ctrl, func); + pciehprm_dump_func_res(func); + } dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); - pciehprm_dump_func_res(func); } } } diff -Nru a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c --- a/drivers/pci/hotplug/pciehprm_nonacpi.c 2004-06-24 13:52:05 -07:00 +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c 2004-06-24 13:52:05 -07:00 @@ -276,7 +276,7 @@ static int bind_pci_resources_to_slots ( struct controller *ctrl) { - struct pci_func *func; + struct pci_func *func, new_func; int busn = ctrl->slot_bus; int devn, funn; u32 vid; @@ -297,11 +297,19 @@ vid, busn, devn, funn); func = pciehp_slot_find(busn, devn, funn); dbg("%s: func = %p\n", __FUNCTION__,func); - if (!func) - continue; - configure_existing_function(ctrl, func); + if (!func) { + memset(&new_func, 0, sizeof(struct pci_func)); + new_func.bus = busn; + new_func.device = devn; + new_func.function = funn; + new_func.is_a_board = 1; + configure_existing_function(ctrl, &new_func); + phprm_dump_func_res(&new_func); + } else { + configure_existing_function(ctrl, func); + phprm_dump_func_res(func); + } dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); - phprm_dump_func_res(func); } } } diff -Nru a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h --- a/drivers/pci/hotplug/shpchp.h 2004-06-24 13:52:05 -07:00 +++ b/drivers/pci/hotplug/shpchp.h 2004-06-24 13:52:05 -07:00 @@ -61,6 +61,7 @@ u8 configured; u8 switch_save; u8 presence_save; + u8 pwr_save; u32 base_length[0x06]; u8 base_type[0x06]; u16 reserved2; diff -Nru a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c --- a/drivers/pci/hotplug/shpchp_ctrl.c 2004-06-24 13:52:05 -07:00 +++ b/drivers/pci/hotplug/shpchp_ctrl.c 2004-06-24 13:52:05 -07:00 @@ -137,6 +137,8 @@ p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + dbg("%s: Card present %x Power status %x\n", __FUNCTION__, + func->presence_save, func->pwr_save); if (getstatus) { /* @@ -145,6 +147,10 @@ info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); func->switch_save = 0; taskInfo->event_type = INT_SWITCH_OPEN; + if (func->pwr_save && func->presence_save) { + taskInfo->event_type = INT_POWER_FAULT; + err("Surprise Removal of card\n"); + } } else { /* * Switch closed @@ -1427,6 +1433,7 @@ rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, adapter_speed); if (rc) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -1438,6 +1445,7 @@ err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", __FUNCTION__); err("%s: Error code (%d)\n", __FUNCTION__, rc); + up(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } /* Done with exclusive hardware access */ @@ -1589,8 +1597,9 @@ func->status = 0; func->switch_save = 0x10; func->is_a_board = 0x01; + func->pwr_save = 1; - /* next, we will instantiate the linux pci_dev structures + /* Next, we will instantiate the linux pci_dev structures * (with appropriate driver notification, if already present) */ index = 0; @@ -1781,6 +1790,7 @@ func->function = 0; func->configured = 0; func->switch_save = 0x10; + func->pwr_save = 0; func->is_a_board = 0; } @@ -1807,7 +1817,6 @@ { struct slot *p_slot = (struct slot *) slot; u8 getstatus; - int rc; pushbutton_pending = 0; @@ -1821,23 +1830,7 @@ p_slot->state = POWEROFF_STATE; dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); - if (shpchp_disable_slot(p_slot)) { - /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); - - /* Turn on the Attention LED */ - rc = p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (rc) { - err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__); - return; - } - - /* Wait for the command to complete */ - wait_for_ctrl_irq (p_slot->ctrl); - - /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); - } + shpchp_disable_slot(p_slot); p_slot->state = STATIC_STATE; } else { p_slot->state = POWERON_STATE; @@ -1847,15 +1840,6 @@ /* Wait for exclusive access to hardware */ down(&p_slot->ctrl->crit_sect); - /* Turn off the green LED */ - rc = p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (rc) { - err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__); - return; - } - /* Wait for the command to complete */ - wait_for_ctrl_irq (p_slot->ctrl); - p_slot->hpc_ops->green_led_off(p_slot); /* Wait for the command to complete */ @@ -2096,7 +2080,7 @@ func = shpchp_slot_find(p_slot->bus, p_slot->device, 0); if (!func) { dbg("%s: Error! slot NULL\n", __FUNCTION__); - return (1); + return 1; } /* Check to see if (latch closed, card present, power off) */ @@ -2105,19 +2089,19 @@ if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return 1; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return 1; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return 1; } up(&p_slot->ctrl->crit_sect); @@ -2125,7 +2109,7 @@ func = shpchp_slot_create(p_slot->bus); if (func == NULL) - return (1); + return 1; func->bus = p_slot->bus; func->device = p_slot->device; @@ -2135,6 +2119,8 @@ /* We have to save the presence info for these slots */ p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_power_status(p_slot, &(func->pwr_save)); + dbg("%s: func->pwr_save %x\n", __FUNCTION__, func->pwr_save); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); func->switch_save = !getstatus? 0x10:0; @@ -2181,7 +2167,7 @@ struct pci_func *func; if (!p_slot->ctrl) - return (1); + return 1; /* Check to see if (latch closed, card present, power on) */ down(&p_slot->ctrl->crit_sect); @@ -2190,19 +2176,19 @@ if (ret || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return 1; } ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return 1; } ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return 1; } up(&p_slot->ctrl->crit_sect); diff -Nru a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c --- a/drivers/pci/hotplug/shpchp_pci.c 2004-06-24 13:52:05 -07:00 +++ b/drivers/pci/hotplug/shpchp_pci.c 2004-06-24 13:52:05 -07:00 @@ -263,6 +263,7 @@ new_slot->function = (u8) function; new_slot->is_a_board = 1; new_slot->switch_save = 0x10; + new_slot->pwr_save = 1; /* In case of unsupported board */ new_slot->status = DevError; new_slot->pci_dev = pci_find_slot(new_slot->bus, diff -Nru a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c --- a/drivers/pci/hotplug/shpchprm_acpi.c 2004-06-24 13:52:05 -07:00 +++ b/drivers/pci/hotplug/shpchprm_acpi.c 2004-06-24 13:52:05 -07:00 @@ -218,6 +218,10 @@ } ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL); + if (!ab->_hpp) { + err ("acpi_shpchprm:%s alloc for _HPP failed\n", path_name); + goto free_and_return; + } memset(ab->_hpp, 0, sizeof(struct acpi__hpp)); ab->_hpp->cache_line_size = nui[0]; @@ -1391,7 +1395,7 @@ static int bind_pci_resources_to_slots ( struct controller *ctrl) { - struct pci_func *func; + struct pci_func *func, new_func; int busn = ctrl->bus; int devn, funn; u32 vid; @@ -1406,11 +1410,19 @@ if (vid != 0xFFFFFFFF) { func = shpchp_slot_find(busn, devn, funn); - if (!func) - continue; - configure_existing_function(ctrl, func); + if (!func) { + memset(&new_func, 0, sizeof(struct pci_func)); + new_func.bus = busn; + new_func.device = devn; + new_func.function = funn; + new_func.is_a_board = 1; + configure_existing_function(ctrl, &new_func); + shpchprm_dump_func_res(&new_func); + } else { + configure_existing_function(ctrl, func); + shpchprm_dump_func_res(func); + } dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); - shpchprm_dump_func_res(func); } } } diff -Nru a/drivers/pci/hotplug/shpchprm_nonacpi.c b/drivers/pci/hotplug/shpchprm_nonacpi.c --- a/drivers/pci/hotplug/shpchprm_nonacpi.c 2004-06-24 13:52:05 -07:00 +++ b/drivers/pci/hotplug/shpchprm_nonacpi.c 2004-06-24 13:52:05 -07:00 @@ -208,7 +208,7 @@ static int bind_pci_resources_to_slots ( struct controller *ctrl) { - struct pci_func *func; + struct pci_func *func, new_func; int busn = ctrl->slot_bus; int devn, funn; u32 vid; @@ -226,11 +226,19 @@ if (vid != 0xFFFFFFFF) { func = shpchp_slot_find(busn, devn, funn); - if (!func) - continue; - configure_existing_function(ctrl, func); + if (!func) { + memset(&new_func, 0, sizeof(struct pci_func)); + new_func.bus = busn; + new_func.device = devn; + new_func.function = funn; + new_func.is_a_board = 1; + configure_existing_function(ctrl, &new_func); + phprm_dump_func_res(&new_func); + } else { + configure_existing_function(ctrl, func); + phprm_dump_func_res(func); + } dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); - phprm_dump_func_res(func); } } } ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI fixes for 2.6.7 2004-06-24 21:46 ` [PATCH] " Greg KH @ 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2004-06-24 21:46 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1722.103.2, 2004/06/08 14:28:46-07:00, daniel.ritz@gmx.ch [PATCH] PCI: fix irq routing on acer travelmate 360 laptop Fixes interrupt routing on acer travelmate 360 notebooks. it looks like the bios assigned the wrong pirq value for the cardbus bridge. just assigning irq 10 to all devices with pirq 0x63 would break second usb port. pirq 0x68 seems to be right one for cardbus. Signed-off-by: Daniel Ritz <daniel.ritz@gmx.ch> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> arch/i386/kernel/dmi_scan.c | 29 +++++++++++++++++++++++++++++ arch/i386/pci/irq.c | 9 +++++++++ 2 files changed, 38 insertions(+) diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c --- a/arch/i386/kernel/dmi_scan.c 2004-06-24 13:51:49 -07:00 +++ b/arch/i386/kernel/dmi_scan.c 2004-06-24 13:51:49 -07:00 @@ -360,6 +360,21 @@ } /* + * Work around broken Acer TravelMate 360 Notebooks which assign Cardbus to + * IRQ 11 even though it is actually wired to IRQ 10 + */ +static __init int fix_acer_tm360_irqrouting(struct dmi_blacklist *d) +{ +#ifdef CONFIG_PCI + extern int acer_tm360_irqrouting; + if (acer_tm360_irqrouting == 0) { + acer_tm360_irqrouting = 1; + printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident); + } +#endif + return 0; +} +/* * Check for clue free BIOS implementations who use * the following QA technique * @@ -844,6 +859,13 @@ MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"), MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736") } }, + + { fix_acer_tm360_irqrouting, "Acer TravelMate 36x Laptop", { + MATCH(DMI_SYS_VENDOR, "Acer"), + MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), + NO_MATCH, NO_MATCH + } }, + /* @@ -1033,6 +1055,13 @@ MATCH(DMI_BOARD_NAME, "PR-DLS"), MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"), MATCH(DMI_BIOS_DATE, "03/21/2003") }}, + + { disable_acpi_pci, "Acer TravelMate 36x Laptop", { + MATCH(DMI_SYS_VENDOR, "Acer"), + MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), + NO_MATCH, NO_MATCH + } }, + #endif { NULL, } diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c --- a/arch/i386/pci/irq.c 2004-06-24 13:51:49 -07:00 +++ b/arch/i386/pci/irq.c 2004-06-24 13:51:49 -07:00 @@ -23,6 +23,7 @@ #define PIRQ_VERSION 0x0100 int broken_hp_bios_irq9; +int acer_tm360_irqrouting; static struct irq_routing_table *pirq_table; @@ -743,6 +744,14 @@ dev->irq = 11; pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); r->set(pirq_router_dev, dev, pirq, 11); + } + + /* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */ + if (acer_tm360_irqrouting && dev->irq == 11 && dev->vendor == PCI_VENDOR_ID_O2) { + pirq = 0x68; + mask = 0x400; + dev->irq = r->get(pirq_router_dev, dev, pirq); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } /* ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI fixes for 2.6.7 2004-06-24 21:46 ` Greg KH @ 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2004-06-24 21:46 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1722.103.3, 2004/06/11 17:15:00-07:00, bjorn.helgaas@hp.com [PATCH] PCI: clarify pci.txt wrt IRQ allocation I think we should make it explicit that PCI IRQs shouldn't be relied upon until after pci_enable_device(). This patch: ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.7-rc3/2.6.7-rc3-mm1/broken-out/bk-acpi.patch does PCI interrupt routing (based on ACPI _PRT) and IRQ allocation at pci_enable_device()-time. (To avoid breaking things in 2.6, the above patch still allocates all PCI IRQs in pci_acpi_init(), before any drivers are initialized. But that shouldn't be needed by correct drivers, and I'd like to remove it in 2.7.) Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> Documentation/pci.txt | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff -Nru a/Documentation/pci.txt b/Documentation/pci.txt --- a/Documentation/pci.txt 2004-06-24 13:51:35 -07:00 +++ b/Documentation/pci.txt 2004-06-24 13:51:35 -07:00 @@ -166,8 +166,9 @@ ~~~~~~~~~~~~~~~~~~~ Before you do anything with the device you've found, you need to enable it by calling pci_enable_device() which enables I/O and memory regions of -the device, assigns missing resources if needed and wakes up the device -if it was in suspended state. Please note that this function can fail. +the device, allocates an IRQ if necessary, assigns missing resources if +needed and wakes up the device if it was in suspended state. Please note +that this function can fail. If you want to use the device in bus mastering mode, call pci_set_master() which enables the bus master bit in PCI_COMMAND register and also fixes ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI fixes for 2.6.7 2004-06-24 21:46 ` Greg KH @ 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2004-06-24 21:46 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1722.103.4, 2004/06/11 17:15:38-07:00, lxiep@us.ibm.com [PATCH] PCI Hotplug: rpaphp.patch -- multi-function devices not handled correctly I made changes to rpaphp code, so it can handle multi-fuction devices correctly. The problem is that the pci_dev field of slot struct can only record one pci_dev of the devices of a multi-fuction card. I changed pci_dev (a single pci_dev type pointer) to pci_funcs( a list of pci_dev type pointers). I rewrote some of the config/unconfig code to support the slot struct change. Along with above changes, I added LDRSLOT(logical I/O slot) support. We need LDRSLOT support for DLPAR I/O. A card in a LDRSLOT can't be physically removed, but can be logically removed from one partiton and reassinged to another partition. I also merged rpaphp changes from ames tree. Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> drivers/pci/hotplug/rpadlpar_core.c | 28 --- drivers/pci/hotplug/rpaphp.h | 28 ++- drivers/pci/hotplug/rpaphp_core.c | 199 +++++++++++++++------ drivers/pci/hotplug/rpaphp_pci.c | 328 +++++++++++++++++++++++++----------- drivers/pci/hotplug/rpaphp_slot.c | 136 ++++++++++++-- drivers/pci/hotplug/rpaphp_vio.c | 6 6 files changed, 508 insertions(+), 217 deletions(-) diff -Nru a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c --- a/drivers/pci/hotplug/rpadlpar_core.c 2004-06-24 13:51:19 -07:00 +++ b/drivers/pci/hotplug/rpadlpar_core.c 2004-06-24 13:51:19 -07:00 @@ -24,25 +24,6 @@ static DECLARE_MUTEX(rpadlpar_sem); -static inline int is_hotplug_capable(struct device_node *dn) -{ - unsigned char *ptr = get_property(dn, "ibm,fw-pci-hot-plug-ctrl", NULL); - - return (int) (ptr != NULL); -} - -static char *get_node_drc_name(struct device_node *dn) -{ - char *ptr = NULL; - int *drc_names; - - drc_names = (int *) get_property(dn, "ibm,drc-names", NULL); - if (drc_names) - ptr = (char *) &drc_names[1]; - - return ptr; -} - static struct device_node *find_php_slot_vio_node(char *drc_name) { struct device_node *child; @@ -53,9 +34,9 @@ return NULL; for (child = of_get_next_child(parent, NULL); - child; child = of_get_next_child(parent, child)) { + child; child = of_get_next_child(parent, child)) { loc_code = get_property(child, "ibm,loc-code", NULL); - if (loc_code && !strcmp(loc_code, drc_name)) + if (loc_code && !strncmp(loc_code, drc_name, strlen(drc_name))) return child; } @@ -69,7 +50,7 @@ while ((np = of_find_node_by_type(np, "pci"))) if (is_hotplug_capable(np)) { - name = get_node_drc_name(np); + name = rpaphp_get_drc_name(np); if (name && (!strcmp(drc_name, name))) break; } @@ -324,6 +305,7 @@ } /* Remove pci bus */ + if (dlpar_pci_remove_bus(bridge_dev)) { printk(KERN_ERR "%s: unable to remove pci bus %s\n", __FUNCTION__, drc_name); @@ -364,7 +346,7 @@ rc = -EINVAL; goto exit; } - + switch (slot->dev_type) { case PCI_DEV: rc = dlpar_remove_pci_slot(slot, drc_name); diff -Nru a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h --- a/drivers/pci/hotplug/rpaphp.h 2004-06-24 13:51:19 -07:00 +++ b/drivers/pci/hotplug/rpaphp.h 2004-06-24 13:51:19 -07:00 @@ -30,6 +30,9 @@ #include <linux/pci.h> #include "pci_hotplug.h" +#define HOTPLUG 1 +#define EMBEDDED 0 + #define DR_INDICATOR 9002 #define DR_ENTITY_SENSE 9003 @@ -73,6 +76,11 @@ #define CONFIGURED 1 #define EMPTY 0 +struct rpaphp_pci_func { + struct pci_dev *pci_dev; + struct list_head sibling; +}; + /* * struct slot - slot information for each *physical* slot */ @@ -83,14 +91,13 @@ u32 power_domain; char *name; char *location; + u8 removable; struct device_node *dn; /* slot's device_node in OFDT */ - /* dn has phb info */ + /* dn has phb info */ struct pci_dev *bridge; /* slot's pci_dev in pci_devices */ union { - struct pci_dev *pci_dev; /* pci_dev of device in this slot */ - /* it will be used for unconfig */ - /* NULL if slot is empty */ - struct vio_dev *vio_dev; /* vio_dev of the device in this slot */ + struct list_head pci_funcs; /* pci_devs in PCI slot */ + struct vio_dev *vio_dev; /* vio_dev in VIO slot */ } dev; u8 dev_type; /* VIO or PCI */ struct hotplug_slot *hotplug_slot; @@ -101,6 +108,13 @@ extern struct list_head rpaphp_slot_head; extern int num_slots; +static inline int is_hotplug_capable(struct device_node *dn) +{ + unsigned char *ptr = get_property(dn, "ibm,fw-pci-hot-plug-ctrl", NULL); + + return (int) (ptr != NULL); +} + /* function prototypes */ /* rpaphp_pci.c */ @@ -110,10 +124,12 @@ extern int register_pci_slot(struct slot *slot); extern int rpaphp_unconfig_pci_adapter(struct slot *slot); extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); +extern struct hotplug_slot *rpaphp_find_hotplug_slot(struct pci_dev *dev); /* rpaphp_core.c */ extern int rpaphp_add_slot(struct device_node *dn); extern int rpaphp_remove_slot(struct slot *slot); +extern char *rpaphp_get_drc_name(struct device_node *dn); /* rpaphp_vio.c */ extern int rpaphp_get_vio_adapter_status(struct slot *slot, int is_init, u8 * value); @@ -125,8 +141,8 @@ extern void dealloc_slot_struct(struct slot *slot); extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain); extern int register_slot(struct slot *slot); +extern int deregister_slot(struct slot *slot); extern int rpaphp_get_power_status(struct slot *slot, u8 * value); extern int rpaphp_set_attention_status(struct slot *slot, u8 status); -extern void rpaphp_sysfs_remove_attr_location(struct hotplug_slot *slot); #endif /* _PPC64PHP_H */ diff -Nru a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c --- a/drivers/pci/hotplug/rpaphp_core.c 2004-06-24 13:51:19 -07:00 +++ b/drivers/pci/hotplug/rpaphp_core.c 2004-06-24 13:51:19 -07:00 @@ -54,6 +54,8 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); +void eeh_register_disable_func(int (*)(struct pci_dev *)); + module_param(debug, bool, 0644); static int enable_slot(struct hotplug_slot *slot); @@ -63,6 +65,7 @@ static int get_attention_status(struct hotplug_slot *slot, u8 * value); static int get_adapter_status(struct hotplug_slot *slot, u8 * value); static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); +static int rpaphp_disable_slot(struct pci_dev *dev); struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { .owner = THIS_MODULE, @@ -89,7 +92,7 @@ */ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) { - int retval; + int retval = 0; struct slot *slot = (struct slot *)hotplug_slot->private; down(&rpaphp_sem); @@ -208,47 +211,53 @@ int rpaphp_remove_slot(struct slot *slot) { - int retval = 0; - struct hotplug_slot *php_slot = slot->hotplug_slot; - - list_del(&slot->rpaphp_slot_list); - - /* remove "php_location" file */ - rpaphp_sysfs_remove_attr_location(php_slot); - - retval = pci_hp_deregister(php_slot); - if (retval) - err("Problem unregistering a slot %s\n", slot->name); - - num_slots--; - - dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); - return retval; + return deregister_slot(slot); } -static int is_php_dn(struct device_node *dn, int **indexes, int **names, int **types, - int **power_domains) +static int get_dn_properties(struct device_node *dn, int **indexes, int **names, + int **types, int **power_domains) { *indexes = (int *) get_property(dn, "ibm,drc-indexes", NULL); - if (!*indexes) - return 0; + /* &names[1] contains NULL terminated slot names */ *names = (int *) get_property(dn, "ibm,drc-names", NULL); - if (!*names) - return 0; + /* &types[1] contains NULL terminated slot types */ *types = (int *) get_property(dn, "ibm,drc-types", NULL); - if (!*types) - return 0; + /* power_domains[1...n] are the slot power domains */ - *power_domains = (int *) get_property(dn, - "ibm,drc-power-domains", NULL); - if (!*power_domains) - return 0; - if (strcmp(dn->name, "pci") == 0 && - !get_property(dn, "ibm,fw-pci-hot-plug-ctrl", NULL)) - return 0; - return 1; + *power_domains = (int *) get_property(dn, "ibm,drc-power-domains", NULL); + + if (*indexes && *names && *types && *power_domains) + return (1); + + return (0); +} + +static int is_php_dn(struct device_node *dn, int **indexes, int **names, int **types, + int **power_domains) +{ + if (!is_hotplug_capable(dn)) + return (0); + if (!get_dn_properties(dn, indexes, names, types, power_domains)) + return (0); + return (1); +} + +static int is_dr_dn(struct device_node *dn, int **indexes, int **names, int **types, + int **power_domains, int **my_drc_index) +{ + if (!is_hotplug_capable(dn)) + return (0); + + *my_drc_index = (int *) get_property(dn, "ibm,my-drc-index", NULL); + if(!*my_drc_index) + return (0); + + if (!dn->parent) + return (0); + + return get_dn_properties(dn->parent, indexes, names, types, power_domains); } static inline int is_vdevice_root(struct device_node *dn) @@ -256,15 +265,48 @@ return !strcmp(dn->name, "vdevice"); } -/** - * rpaphp_add_slot: Add Hot Plug slot(s) to sysfs - * - */ +char *rpaphp_get_drc_name(struct device_node *dn) +{ + char *name, *ptr = NULL; + int *drc_names, *drc_indexes, i; + struct device_node *parent = dn->parent; + u32 *my_drc_index; + + if (!parent) + return NULL; + + my_drc_index = (u32 *) get_property(dn, "ibm,my-drc-index", NULL); + if (!my_drc_index) + return NULL; + + drc_names = (int *) get_property(parent, "ibm,drc-names", NULL); + drc_indexes = (int *) get_property(parent, "ibm,drc-indexes", NULL); + if (!drc_names || !drc_indexes) + return NULL; + + name = (char *) &drc_names[1]; + for (i = 0; i < drc_indexes[0]; i++, name += (strlen(name) + 1)) { + if (drc_indexes[i + 1] == *my_drc_index) { + ptr = (char *) name; + break; + } + } + + return ptr; +} + +/**************************************************************** + * rpaphp not only registers PCI hotplug slots(HOTPLUG), + * but also logical DR slots(EMBEDDED). + * HOTPLUG slot: An adapter can be physically added/removed. + * EMBEDDED slot: An adapter can be logically removed/added + * from/to a partition with the slot. + ***************************************************************/ int rpaphp_add_slot(struct device_node *dn) { struct slot *slot; int retval = 0; - int i; + int i, *my_drc_index, slot_type; int *indexes, *names, *types, *power_domains; char *name, *type; @@ -277,42 +319,65 @@ } /* register PCI devices */ - if (dn->name != 0 && strcmp(dn->name, "pci") == 0 && - is_php_dn(dn, &indexes, &names, &types, &power_domains)) { + if (dn->name != 0 && strcmp(dn->name, "pci") == 0) { + if (is_php_dn(dn, &indexes, &names, &types, &power_domains)) + slot_type = HOTPLUG; + else if (is_dr_dn(dn, &indexes, &names, &types, &power_domains, &my_drc_index)) + slot_type = EMBEDDED; + else goto exit; name = (char *) &names[1]; type = (char *) &types[1]; - for (i = 0; i < indexes[0]; - i++, - name += (strlen(name) + 1), - type += (strlen(type) + 1)) { - if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name, - power_domains[i + 1]))) { - retval = -ENOMEM; - goto exit; - } - slot->type = simple_strtoul(type, NULL, 10); - if (slot->type < 1 || slot->type > 16) - slot->type = 0; - retval = register_pci_slot(slot); + for (i = 0; i < indexes[0]; i++, + name += (strlen(name) + 1), type += (strlen(type) + 1)) { - } /* for indexes */ - } /* end of PCI device_node */ + if ( slot_type == HOTPLUG || + (slot_type == EMBEDDED && indexes[i + 1] == my_drc_index[0])) { + + if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name, + power_domains[i + 1]))) { + retval = -ENOMEM; + goto exit; + } + if (slot_type == EMBEDDED) + slot->type = EMBEDDED; + else + slot->type = simple_strtoul(type, NULL, 10); + + dbg(" Found drc-index:0x%x drc-name:%s drc-type:%s\n", + indexes[i + 1], name, type); + + retval = register_pci_slot(slot); + if (slot_type == EMBEDDED) + goto exit; + } + } + } exit: dbg("%s - Exit: num_slots=%d rc[%d]\n", __FUNCTION__, num_slots, retval); return retval; } -static int __init init_rpa(void) +/* + * init_slots - initialize 'struct slot' structures for each slot + * + */ +static void init_slots(void) { struct device_node *dn; + for (dn = find_all_nodes(); dn; dn = dn->next) + rpaphp_add_slot(dn); +} + +static int __init init_rpa(void) +{ + init_MUTEX(&rpaphp_sem); /* initialize internal data structure etc. */ - for (dn = find_all_nodes(); dn; dn = dn->next) - rpaphp_add_slot(dn); + init_slots(); if (!num_slots) return -ENODEV; @@ -342,12 +407,18 @@ { info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + /* let EEH know they can use hotplug */ + eeh_register_disable_func(&rpaphp_disable_slot); + /* read all the PRA info from the system */ return init_rpa(); } static void __exit rpaphp_exit(void) { + /* let EEH know we are going away */ + eeh_register_disable_func(NULL); + cleanup_slots(); } @@ -374,11 +445,16 @@ retval = -EINVAL; } up(&rpaphp_sem); - exit: +exit: dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); return retval; } +static int rpaphp_disable_slot(struct pci_dev *dev) +{ + return disable_slot(rpaphp_find_hotplug_slot(dev)); +} + static int disable_slot(struct hotplug_slot *hotplug_slot) { int retval; @@ -395,9 +471,7 @@ down(&rpaphp_sem); switch (slot->dev_type) { case PCI_DEV: - rpaphp_set_attention_status(slot, LED_ID); retval = rpaphp_unconfig_pci_adapter(slot); - rpaphp_set_attention_status(slot, LED_OFF); break; case VIO_DEV: retval = rpaphp_unconfig_vio_adapter(slot); @@ -406,7 +480,7 @@ retval = -ENODEV; } up(&rpaphp_sem); - exit: +exit: dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); return retval; } @@ -417,3 +491,4 @@ EXPORT_SYMBOL_GPL(rpaphp_add_slot); EXPORT_SYMBOL_GPL(rpaphp_remove_slot); EXPORT_SYMBOL_GPL(rpaphp_slot_head); +EXPORT_SYMBOL_GPL(rpaphp_get_drc_name); diff -Nru a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c --- a/drivers/pci/hotplug/rpaphp_pci.c 2004-06-24 13:51:19 -07:00 +++ b/drivers/pci/hotplug/rpaphp_pci.c 2004-06-24 13:51:19 -07:00 @@ -30,24 +30,18 @@ struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn) { - struct pci_dev *retval_dev = NULL, *dev; + struct pci_dev *retval_dev = NULL, *dev = NULL; char bus_id[BUS_ID_SIZE]; sprintf(bus_id, "%04x:%02x:%02x.%d",dn->phb->global_number, dn->busno, PCI_SLOT(dn->devfn), PCI_FUNC(dn->devfn)); - - dbg("Enter rpaphp_find_pci_dev() full_name=%s bus_id=%s\n", - dn->full_name, bus_id); - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (!strcmp(pci_name(dev), bus_id)) { + if (!strcmp(pci_name(dev), bus_id)) { retval_dev = dev; - dbg("rpaphp_find_pci_dev(): found dev=%p\n\n", dev); break; } } return retval_dev; - } EXPORT_SYMBOL_GPL(rpaphp_find_pci_dev); @@ -79,11 +73,6 @@ return rpaphp_find_pci_dev(slot->dn); } -static struct pci_dev *rpaphp_find_adapter_pdev(struct slot *slot) -{ - return rpaphp_find_pci_dev(slot->dn->child); -} - static int rpaphp_get_sensor_state(struct slot *slot, int *state) { int rc; @@ -144,7 +133,8 @@ else if (rpaphp_find_pci_dev(slot->dn->child)) *value = CONFIGURED; else { - dbg("%s: can't find pdev of adapter in slot[%s]\n", __FUNCTION__, slot->name); + err("%s: can't find pdev of adapter in slot[%s]\n", + __FUNCTION__, slot->dn->full_name); *value = NOT_CONFIGURED; } } @@ -158,7 +148,8 @@ } /* Must be called before pci_bus_add_devices */ -static void rpaphp_fixup_new_pci_devices(struct pci_bus *bus) +static void +rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) { struct pci_dev *dev; @@ -169,8 +160,9 @@ */ if (list_empty(&dev->global_list)) { int i; - - pcibios_fixup_device_resources(dev, bus); + + if(fix_bus) + pcibios_fixup_device_resources(dev, bus); pci_read_irq_line(dev); for (i = 0; i < PCI_NUM_RESOURCES; i++) { struct resource *r = &dev->resource[i]; @@ -183,69 +175,139 @@ } } -static void -rpaphp_pci_config_device(struct pci_bus *pci_bus, struct device_node *dn) -{ - int num; - - num = pci_scan_slot(pci_bus, PCI_DEVFN(PCI_SLOT(dn->devfn), 0)); - if (num) { - rpaphp_fixup_new_pci_devices(pci_bus); - pci_bus_add_devices(pci_bus); - } -} - -static int rpaphp_pci_config_bridge(struct pci_dev *dev, struct device_node *dn); +static int rpaphp_pci_config_bridge(struct pci_dev *dev); /***************************************************************************** - rpaphp_pci_config_dn() will recursively configure all devices under the - given slot->dn and return the dn's pci_dev. + rpaphp_pci_config_slot() will configure all devices under the + given slot->dn and return the the first pci_dev. *****************************************************************************/ static struct pci_dev * -rpaphp_pci_config_dn(struct device_node *dn, struct pci_bus *bus) +rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus) { - struct device_node *local; + struct device_node *eads_first_child = dn->child; struct pci_dev *dev; + int num; + + dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name); - for (local = dn->child; local; local = local->sibling) { - rpaphp_pci_config_device(bus, local); - dev = rpaphp_find_pci_dev(local); - if (!rpaphp_pci_config_bridge(dev, local)) + if (eads_first_child) { + /* pci_scan_slot should find all children of EADs */ + num = pci_scan_slot(bus, PCI_DEVFN(PCI_SLOT(eads_first_child->devfn), 0)); + if (num) { + rpaphp_fixup_new_pci_devices(bus, 1); + pci_bus_add_devices(bus); + } + dev = rpaphp_find_pci_dev(eads_first_child); + if (!dev) { + err("No new device found\n"); return NULL; + } + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) + rpaphp_pci_config_bridge(dev); } - return dev; } -static int rpaphp_pci_config_bridge(struct pci_dev *dev, struct device_node *dn) +static int rpaphp_pci_config_bridge(struct pci_dev *dev) { - if (dev && dn->child) { /* dn is a PCI bridge node */ - struct pci_bus *child; - u8 sec_busno; - - /* get busno of downstream bus */ - pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno); - - /* add to children of PCI bridge dev->bus */ - child = pci_add_new_bus(dev->bus, dev, sec_busno); - if (!child) { - err("%s: could not add second bus\n", __FUNCTION__); - return 0; - } - sprintf(child->name, "PCI Bus #%02x", child->number); - /* Fixup subordinate bridge bases and resureces */ - pcibios_fixup_bus(child); + u8 sec_busno; + struct pci_bus *child_bus; + struct pci_dev *child_dev; + + dbg("Enter %s: BRIDGE dev=%s\n", __FUNCTION__, pci_name(dev)); - /* may need do more stuff here */ - rpaphp_pci_config_dn(dn, dev->subordinate); + /* get busno of downstream bus */ + pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno); + + /* add to children of PCI bridge dev->bus */ + child_bus = pci_add_new_bus(dev->bus, dev, sec_busno); + if (!child_bus) { + err("%s: could not add second bus\n", __FUNCTION__); + return -EIO; } - return 1; + sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number); + /* do pci_scan_child_bus */ + pci_scan_child_bus(child_bus); + + list_for_each_entry(child_dev, &child_bus->devices, bus_list) { + eeh_add_device_late(child_dev); + } + + /* fixup new pci devices without touching bus struct */ + rpaphp_fixup_new_pci_devices(child_bus, 0); + + /* Make the discovered devices available */ + pci_bus_add_devices(child_bus); + return 0; +} + +static void enable_eeh(struct device_node *dn) +{ + struct device_node *sib; + + for (sib = dn->child; sib; sib = sib->sibling) + enable_eeh(sib); + eeh_add_device_early(dn); + return; + +} + +#ifdef DEBUG +static void print_slot_pci_funcs(struct slot *slot) +{ + struct list_head *l; + + if (slot->dev_type == PCI_DEV) { + printk("pci_funcs of slot[%s]\n", slot->name); + if (list_empty(&slot->dev.pci_funcs)) + printk(" pci_funcs is EMPTY\n"); + + list_for_each (l, &slot->dev.pci_funcs) { + struct rpaphp_pci_func *func = + list_entry(l, struct rpaphp_pci_func, sibling); + printk(" FOUND dev=%s\n", pci_name(func->pci_dev)); + } + } + return; +} +#else +static void print_slot_pci_funcs(struct slot *slot) +{ + return; +} +#endif + +static int init_slot_pci_funcs(struct slot *slot) +{ + struct device_node *child; + + for (child = slot->dn->child; child != NULL; child = child->sibling) { + struct pci_dev *pdev = rpaphp_find_pci_dev(child); + + if (pdev) { + struct rpaphp_pci_func *func; + func = kmalloc(sizeof(struct rpaphp_pci_func), GFP_KERNEL); + if (!func) + return -ENOMEM; + memset(func, 0, sizeof(struct rpaphp_pci_func)); + INIT_LIST_HEAD(&func->sibling); + func->pci_dev = pdev; + list_add_tail(&func->sibling, &slot->dev.pci_funcs); + print_slot_pci_funcs(slot); + } else { + err("%s: dn=%s has no pci_dev\n", + __FUNCTION__, child->full_name); + return -EIO; + } + } + return 0; } -static struct pci_dev *rpaphp_config_pci_adapter(struct slot *slot) +static int rpaphp_config_pci_adapter(struct slot *slot) { struct pci_bus *pci_bus; - struct pci_dev *dev = NULL; + struct pci_dev *dev; + int rc = -ENODEV; dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name); @@ -256,38 +318,74 @@ err("%s: can't find bus structure\n", __FUNCTION__); goto exit; } - - eeh_add_device_early(slot->dn->child); - dev = rpaphp_pci_config_dn(slot->dn, pci_bus); - eeh_add_device_late(dev); + enable_eeh(slot->dn); + dev = rpaphp_pci_config_slot(slot->dn, pci_bus); + if (!dev) { + err("%s: can't find any devices.\n", __FUNCTION__); + goto exit; + } + /* associate corresponding pci_dev */ + rc = init_slot_pci_funcs(slot); + if (rc) + goto exit; + print_slot_pci_funcs(slot); + if (!list_empty(&slot->dev.pci_funcs)) + rc = 0; } else { /* slot is not enabled */ err("slot doesn't have pci_dev structure\n"); - dev = NULL; } - exit: - dbg("Exit %s: pci_dev %s\n", __FUNCTION__, dev ? "found" : "not found"); - return dev; + dbg("Exit %s: rc=%d\n", __FUNCTION__, rc); + return rc; +} + + +static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev) +{ + eeh_remove_device(dev); + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + struct pci_bus *bus = dev->subordinate; + struct list_head *ln; + if (!bus) + return; + for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { + struct pci_dev *pdev = pci_dev_b(ln); + if (pdev) + rpaphp_eeh_remove_bus_device(pdev); + } + + } + return; } int rpaphp_unconfig_pci_adapter(struct slot *slot) { int retval = 0; + struct list_head *ln; dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name); - if (!slot->dev.pci_dev) { - info("%s: no card in slot[%s]\n", __FUNCTION__, slot->name); + if (list_empty(&slot->dev.pci_funcs)) { + err("%s: slot[%s] doesn't have any devices.\n", __FUNCTION__, + slot->name); retval = -EINVAL; goto exit; } - /* remove the device from the pci core */ - eeh_remove_device(slot->dev.pci_dev); - pci_remove_bus_device(slot->dev.pci_dev); - + /* remove the devices from the pci core */ + list_for_each (ln, &slot->dev.pci_funcs) { + struct rpaphp_pci_func *func; + + func = list_entry(ln, struct rpaphp_pci_func, sibling); + if (func->pci_dev) { + rpaphp_eeh_remove_bus_device(func->pci_dev); + pci_remove_bus_device(func->pci_dev); + } + kfree(func); + } + INIT_LIST_HEAD(&slot->dev.pci_funcs); slot->state = NOT_CONFIGURED; - info("%s: adapter in slot[%s] unconfigured.\n", __FUNCTION__, + info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__, slot->name); exit: dbg("Exit %s, rc=0x%x\n", __FUNCTION__, retval); @@ -303,7 +401,7 @@ &slot->hotplug_slot->info-> adapter_status); if (slot->hotplug_slot->info->adapter_status == NOT_VALID) { - dbg("%s: NOT_VALID: skip dn->full_name=%s\n", + err("%s: NOT_VALID: skip dn->full_name=%s\n", __FUNCTION__, slot->dn->full_name); return -1; } @@ -314,35 +412,41 @@ { slot->bridge = rpaphp_find_bridge_pdev(slot); if (!slot->bridge) { /* slot being added doesn't have pci_dev yet */ - dbg("%s: no pci_dev for bridge dn %s\n", __FUNCTION__, slot->name); - dealloc_slot_struct(slot); - return 1; + err("%s: no pci_dev for bridge dn %s\n", __FUNCTION__, slot->name); + goto exit_rc; } - + dbg("%s set slot->name to %s\n", __FUNCTION__, pci_name(slot->bridge)); strcpy(slot->name, pci_name(slot->bridge)); + /* find slot's pci_dev if it's not empty */ if (slot->hotplug_slot->info->adapter_status == EMPTY) { slot->state = EMPTY; /* slot is empty */ - slot->dev.pci_dev = NULL; } else { /* slot is occupied */ if (!(slot->dn->child)) { /* non-empty slot has to have child */ - err("%s: slot[%s]'s device_node doesn't have child for adapter\n", __FUNCTION__, slot->name); - dealloc_slot_struct(slot); - return 1; + err("%s: slot[%s]'s device_node doesn't have child for adapter\n", + __FUNCTION__, slot->name); + goto exit_rc; + } + if (init_slot_pci_funcs(slot)) { + err("%s: init_slot_pci_funcs failed\n", __FUNCTION__); + goto exit_rc; } - slot->dev.pci_dev = rpaphp_find_adapter_pdev(slot); - if (slot->dev.pci_dev) { + print_slot_pci_funcs(slot); + if (!list_empty(&slot->dev.pci_funcs)) { slot->state = CONFIGURED; - + } else { /* DLPAR add as opposed to - * boot time */ + * boot time */ slot->state = NOT_CONFIGURED; } } return 0; +exit_rc: + dealloc_slot_struct(slot); + return 1; } int register_pci_slot(struct slot *slot) @@ -350,14 +454,17 @@ int rc = 1; slot->dev_type = PCI_DEV; + if (slot->type == EMBEDDED) + slot->removable = EMBEDDED; + else + slot->removable = HOTPLUG; + INIT_LIST_HEAD(&slot->dev.pci_funcs); if (setup_pci_hotplug_slot_info(slot)) goto exit_rc; if (setup_pci_slot(slot)) goto exit_rc; rc = register_slot(slot); exit_rc: - if (rc) - dealloc_slot_struct(slot); return rc; } @@ -371,12 +478,12 @@ dbg("%s: sensor state[%d]\n", __FUNCTION__, state); /* if slot is not empty, enable the adapter */ if (state == PRESENT) { - dbg("%s : slot[%s] is occupid.\n", __FUNCTION__, slot->name); - if ((slot->dev.pci_dev = - rpaphp_config_pci_adapter(slot)) != NULL) { + dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name); + retval = rpaphp_config_pci_adapter(slot); + if (!retval) { slot->state = CONFIGURED; - dbg("%s: PCI adapter %s in slot[%s] has been configured\n", - __FUNCTION__, pci_name(slot->dev.pci_dev), slot->name); + dbg("%s: PCI devices in slot[%s] has been configured\n", + __FUNCTION__, slot->name); } else { slot->state = NOT_CONFIGURED; dbg("%s: no pci_dev struct for adapter in slot[%s]\n", @@ -392,10 +499,31 @@ retval = -EINVAL; } exit: - if (slot->state != NOT_VALID) - rpaphp_set_attention_status(slot, LED_ON); - else - rpaphp_set_attention_status(slot, LED_ID); dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); return retval; } + +struct hotplug_slot *rpaphp_find_hotplug_slot(struct pci_dev *dev) +{ + struct list_head *tmp, *n; + struct slot *slot; + + list_for_each_safe(tmp, n, &rpaphp_slot_head) { + struct pci_bus *bus; + struct list_head *ln; + + slot = list_entry(tmp, struct slot, rpaphp_slot_list); + bus = slot->bridge->subordinate; + if (!bus) + return NULL; /* shouldn't be here */ + for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { + struct pci_dev *pdev = pci_dev_b(ln); + if (pdev == dev) + return slot->hotplug_slot; + } + } + + return NULL; +} + +EXPORT_SYMBOL_GPL(rpaphp_find_hotplug_slot); diff -Nru a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c --- a/drivers/pci/hotplug/rpaphp_slot.c 2004-06-24 13:51:19 -07:00 +++ b/drivers/pci/hotplug/rpaphp_slot.c 2004-06-24 13:51:19 -07:00 @@ -29,6 +29,35 @@ #include <linux/pci.h> #include "rpaphp.h" +static ssize_t removable_read_file (struct hotplug_slot *php_slot, char *buf) +{ + u8 value; + int retval = -ENOENT; + struct slot *slot = (struct slot *)php_slot->private; + + if (!slot) + return retval; + + value = slot->removable; + retval = sprintf (buf, "%d\n", value); + return retval; +} + +static struct hotplug_slot_attribute hotplug_slot_attr_removable = { + .attr = {.name = "phy_removable", .mode = S_IFREG | S_IRUGO}, + .show = removable_read_file, +}; + +static void rpaphp_sysfs_add_attr_removable (struct hotplug_slot *slot) +{ + sysfs_create_file(&slot->kobj, &hotplug_slot_attr_removable.attr); +} + +static void rpaphp_sysfs_remove_attr_removable (struct hotplug_slot *slot) +{ + sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_removable.attr); +} + static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf) { char *value; @@ -53,7 +82,7 @@ sysfs_create_file(&slot->kobj, &hotplug_slot_attr_location.attr); } -void rpaphp_sysfs_remove_attr_location (struct hotplug_slot *slot) +static void rpaphp_sysfs_remove_attr_location (struct hotplug_slot *slot) { sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_location.attr); } @@ -68,6 +97,17 @@ void dealloc_slot_struct(struct slot *slot) { + struct list_head *ln, *n; + + if (slot->dev_type == PCI_DEV) { + list_for_each_safe (ln, n, &slot->dev.pci_funcs) { + struct rpaphp_pci_func *func; + + func = list_entry(ln, struct rpaphp_pci_func, sibling); + kfree(func); + } + } + kfree(slot->hotplug_slot->info); kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); @@ -86,7 +126,7 @@ memset(slot, 0, sizeof (struct slot)); slot->hotplug_slot = kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL); if (!slot->hotplug_slot) - goto error_slot; + goto error_slot; memset(slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); slot->hotplug_slot->info = kmalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL); @@ -95,7 +135,7 @@ memset(slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL); if (!slot->hotplug_slot->name) - goto error_info; + goto error_info; slot->location = kmalloc(strlen(drc_name) + 1, GFP_KERNEL); if (!slot->location) goto error_name; @@ -107,9 +147,8 @@ slot->hotplug_slot->private = slot; slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops; slot->hotplug_slot->release = &rpaphp_release_slot; - slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; - - return slot; + + return (slot); error_name: kfree(slot->hotplug_slot->name); @@ -123,15 +162,56 @@ return NULL; } +static int is_registered(struct slot *slot) +{ + struct slot *tmp_slot; + + list_for_each_entry(tmp_slot, &rpaphp_slot_head, rpaphp_slot_list) { + if (!strcmp(tmp_slot->name, slot->name)) + return 1; + } + return 0; +} + +int deregister_slot(struct slot *slot) +{ + int retval = 0; + struct hotplug_slot *php_slot = slot->hotplug_slot; + + dbg("%s - Entry: deregistering slot=%s\n", + __FUNCTION__, slot->name); + + list_del(&slot->rpaphp_slot_list); + + /* remove "phy_location" file */ + rpaphp_sysfs_remove_attr_location(php_slot); + + /* remove "phy_removable" file */ + rpaphp_sysfs_remove_attr_removable(php_slot); + + retval = pci_hp_deregister(php_slot); + if (retval) + err("Problem unregistering a slot %s\n", slot->name); + else + num_slots--; + + dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); + return retval; +} + int register_slot(struct slot *slot) { int retval; - char *vio_uni_addr = NULL; - dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n", - __FUNCTION__, slot->dn->full_name, slot->index, slot->name, + dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n", + __FUNCTION__, slot->dn->full_name, slot->index, slot->name, slot->power_domain, slot->type); - + /* should not try to register the same slot twice */ + if (is_registered(slot)) { /* should't be here */ + err("register_slot: slot[%s] is already registered\n", slot->name); + rpaphp_release_slot(slot->hotplug_slot); + return 1; + } retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); @@ -142,30 +222,40 @@ /* create "phy_locatoin" file */ rpaphp_sysfs_add_attr_location(slot->hotplug_slot); + /* create "phy_removable" file */ + rpaphp_sysfs_add_attr_removable(slot->hotplug_slot); + /* add slot to our internal list */ dbg("%s adding slot[%s] to rpaphp_slot_list\n", __FUNCTION__, slot->name); list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head); - if (vio_uni_addr) - info("Slot [%s](vio_uni_addr=%s) registered\n", - slot->name, vio_uni_addr); + if (slot->dev_type == VIO_DEV) + info("Slot [%s](VIO location=%s) registered\n", + slot->name, slot->location); else - info("Slot [%s](bus_id=%s) registered\n", - slot->name, pci_name(slot->bridge)); + info("Slot [%s](PCI location=%s) registered\n", + slot->name, slot->location); num_slots++; return 0; } int rpaphp_get_power_status(struct slot *slot, u8 * value) { - int rc; - - rc = rtas_get_power_level(slot->power_domain, (int *) value); - if (rc) - err("failed to get power-level for slot(%s), rc=0x%x\n", - slot->name, rc); + int rc = 0; + + if (slot->type == EMBEDDED) { + dbg("%s set to POWER_ON for EMBEDDED slot %s\n", + __FUNCTION__, slot->location); + *value = POWER_ON; + } + else { + rc = rtas_get_power_level(slot->power_domain, (int *) value); + if (rc) + err("failed to get power-level for slot(%s), rc=0x%x\n", + slot->location, rc); + } return rc; } @@ -177,8 +267,8 @@ /* status: LED_OFF or LED_ON */ rc = rtas_set_indicator(DR_INDICATOR, slot->index, status); if (rc) - err("slot(%s) set attention-status(%d) failed! rc=0x%x\n", - slot->name, status, rc); + err("slot(name=%s location=%s index=0x%x) set attention-status(%d) failed! rc=0x%x\n", + slot->name, slot->location, slot->index, status, rc); return rc; } diff -Nru a/drivers/pci/hotplug/rpaphp_vio.c b/drivers/pci/hotplug/rpaphp_vio.c --- a/drivers/pci/hotplug/rpaphp_vio.c 2004-06-24 13:51:19 -07:00 +++ b/drivers/pci/hotplug/rpaphp_vio.c 2004-06-24 13:51:19 -07:00 @@ -74,11 +74,11 @@ int rc = 1; struct slot *slot = NULL; + name = rpaphp_get_drc_name(dn); + if (!name) + goto exit_rc; index = (u32 *) get_property(dn, "ibm,my-drc-index", NULL); if (!index) - goto exit_rc; - name = get_property(dn, "ibm,loc-code", NULL); - if (!name) goto exit_rc; if (!(slot = alloc_slot_struct(dn, *index, name, 0))) { rc = -ENOMEM; ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI fixes for 2.6.7 2004-06-24 21:46 ` Greg KH @ 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2004-06-24 21:46 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1722.103.5, 2004/06/14 11:08:54-07:00, rl@hellgate.ch [PATCH] PCI: Fix PME bits in pci.txt Signed-off-by: Roger Luethi <rl@hellgate.ch> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> Documentation/power/pci.txt | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff -Nru a/Documentation/power/pci.txt b/Documentation/power/pci.txt --- a/Documentation/power/pci.txt 2004-06-24 13:51:03 -07:00 +++ b/Documentation/power/pci.txt 2004-06-24 13:51:03 -07:00 @@ -286,11 +286,11 @@ +------------------+ | Bit | State | +------------------+ -| 15 | D0 | -| 14 | D1 | +| 11 | D0 | +| 12 | D1 | | 13 | D2 | -| 12 | D3hot | -| 11 | D3cold | +| 14 | D3hot | +| 15 | D3cold | +------------------+ A device can use this to enable wake events: ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI fixes for 2.6.7 2004-06-24 21:46 ` Greg KH @ 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2004-06-24 21:46 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1722.103.6, 2004/06/14 11:11:45-07:00, rl@hellgate.ch [PATCH] PCI: Fix off-by-one in pci_enable_wake Fix off-by-one in pci_enable_wake. Bit field location determined by mask, not value. Signed-off-by: Roger Luethi <rl@hellgate.ch> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> drivers/pci/pci.c | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c --- a/drivers/pci/pci.c 2004-06-24 13:50:47 -07:00 +++ b/drivers/pci/pci.c 2004-06-24 13:50:47 -07:00 @@ -442,7 +442,7 @@ pci_read_config_word(dev,pm+PCI_PM_PMC,&value); value &= PCI_PM_CAP_PME_MASK; - value >>= ffs(value); /* First bit of mask */ + value >>= ffs(PCI_PM_CAP_PME_MASK) - 1; /* First bit of mask */ /* Check if it can generate PME# from requested state. */ if (!value || !(value & (1 << state))) ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI fixes for 2.6.7 2004-06-24 21:46 ` Greg KH @ 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2004-06-24 21:46 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1823.1.7, 2004/06/22 16:57:06-07:00, roland@topspin.com [PATCH] PCI: Fix MSI-X setup msix_capability_init() puts the offset of the MSI-X capability into pos, then uses pos as a loop index to clear the MSI-X vector table, and then tries to use pos as the offset again, which results in writing the MSI-X enable bit off into space. This patch fixes that by adding a new loop index variable and using that to clear the vector table. Signed-off-by: Roland Dreier <roland@tospin.com> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> drivers/pci/msi.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff -Nru a/drivers/pci/msi.c b/drivers/pci/msi.c --- a/drivers/pci/msi.c 2004-06-24 13:50:17 -07:00 +++ b/drivers/pci/msi.c 2004-06-24 13:50:17 -07:00 @@ -569,7 +569,7 @@ struct msi_desc *entry; struct msg_address address; struct msg_data data; - int vector = 0, pos, dev_msi_cap; + int vector = 0, pos, dev_msi_cap, i; u32 phys_addr, table_offset; u32 control; u8 bir; @@ -629,12 +629,12 @@ writel(address.hi_address, base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); writel(*(u32*)&data, base + PCI_MSIX_ENTRY_DATA_OFFSET); /* Initialize all entries from 1 up to 0 */ - for (pos = 1; pos < dev_msi_cap; pos++) { - writel(0, base + pos * PCI_MSIX_ENTRY_SIZE + + for (i = 1; i < dev_msi_cap; i++) { + writel(0, base + i * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); - writel(0, base + pos * PCI_MSIX_ENTRY_SIZE + + writel(0, base + i * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); - writel(0, base + pos * PCI_MSIX_ENTRY_SIZE + + writel(0, base + i * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_DATA_OFFSET); } attach_msi_entry(entry, vector); ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI fixes for 2.6.7 2004-06-24 21:46 ` Greg KH @ 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2004-06-24 21:46 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1823.1.8, 2004/06/22 16:57:48-07:00, shemminger@osdl.org [PATCH] PCI: remove duplicate in pci_ids.h Get rid of duplicate entry, one is in the middle of the file with duplicate at the end Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> include/linux/pci_ids.h | 3 --- 1 files changed, 3 deletions(-) diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h --- a/include/linux/pci_ids.h 2004-06-24 13:50:01 -07:00 +++ b/include/linux/pci_ids.h 2004-06-24 13:50:01 -07:00 @@ -2272,6 +2272,3 @@ #define PCI_DEVICE_ID_MICROGATE_SCC 0x0020 #define PCI_DEVICE_ID_MICROGATE_SCA 0x0030 #define PCI_DEVICE_ID_MICROGATE_USC2 0x0210 - -#define PCI_VENDOR_ID_HINT 0x3388 -#define PCI_DEVICE_ID_HINT_VXPROII_IDE 0x8013 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI fixes for 2.6.7 2004-06-24 21:46 ` Greg KH @ 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2004-06-24 21:46 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1823.1.9, 2004/06/22 16:58:27-07:00, shemminger@osdl.org [PATCH] PCI: fix out of order entry in pci_ids.h The last entry in pci_ids.h is out of order, someone wasn't reading the comment to keep it sorted. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> include/linux/pci_ids.h | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h --- a/include/linux/pci_ids.h 2004-06-24 13:49:47 -07:00 +++ b/include/linux/pci_ids.h 2004-06-24 13:49:47 -07:00 @@ -1769,6 +1769,12 @@ #define PCI_DEVICE_ID_CCD_B00C 0xb00c #define PCI_DEVICE_ID_CCD_B100 0xb100 +#define PCI_VENDOR_ID_MICROGATE 0x13c0 +#define PCI_DEVICE_ID_MICROGATE_USC 0x0010 +#define PCI_DEVICE_ID_MICROGATE_SCC 0x0020 +#define PCI_DEVICE_ID_MICROGATE_SCA 0x0030 +#define PCI_DEVICE_ID_MICROGATE_USC2 0x0210 + #define PCI_VENDOR_ID_3WARE 0x13C1 #define PCI_DEVICE_ID_3WARE_1000 0x1000 #define PCI_DEVICE_ID_3WARE_7000 0x1001 @@ -2266,9 +2272,3 @@ #define PCI_DEVICE_ID_ARK_STING 0xa091 #define PCI_DEVICE_ID_ARK_STINGARK 0xa099 #define PCI_DEVICE_ID_ARK_2000MT 0xa0a1 - -#define PCI_VENDOR_ID_MICROGATE 0x13c0 -#define PCI_DEVICE_ID_MICROGATE_USC 0x0010 -#define PCI_DEVICE_ID_MICROGATE_SCC 0x0020 -#define PCI_DEVICE_ID_MICROGATE_SCA 0x0030 -#define PCI_DEVICE_ID_MICROGATE_USC2 0x0210 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI fixes for 2.6.7 2004-06-24 21:46 ` Greg KH @ 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2004-06-24 21:46 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1823.1.10, 2004/06/22 16:59:02-07:00, shemminger@osdl.org [PATCH] PCI: add id's for sk98 driver Redoing the sk98 driver to correct pci model. These are (most of) the entries it uses. Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> include/linux/pci_ids.h | 12 ++++++++++++ 1 files changed, 12 insertions(+) diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h --- a/include/linux/pci_ids.h 2004-06-24 13:49:32 -07:00 +++ b/include/linux/pci_ids.h 2004-06-24 13:49:32 -07:00 @@ -967,12 +967,14 @@ #define PCI_VENDOR_ID_3COM 0x10b7 #define PCI_DEVICE_ID_3COM_3C985 0x0001 +#define PCI_DEVICE_ID_3COM_3C940 0x1700 #define PCI_DEVICE_ID_3COM_3C339 0x3390 #define PCI_DEVICE_ID_3COM_3C359 0x3590 #define PCI_DEVICE_ID_3COM_3C590 0x5900 #define PCI_DEVICE_ID_3COM_3C595TX 0x5950 #define PCI_DEVICE_ID_3COM_3C595T4 0x5951 #define PCI_DEVICE_ID_3COM_3C595MII 0x5952 +#define PCI_DEVICE_ID_3COM_3C940B 0x80eb #define PCI_DEVICE_ID_3COM_3C900TPO 0x9000 #define PCI_DEVICE_ID_3COM_3C900COMBO 0x9001 #define PCI_DEVICE_ID_3COM_3C905TX 0x9050 @@ -1420,6 +1422,9 @@ #define PCI_DEVICE_ID_RICOH_RL5C476 0x0476 #define PCI_DEVICE_ID_RICOH_RL5C478 0x0478 +#define PCI_VENDOR_ID_DLINK 0x1186 +#define PCI_DEVICE_ID_DLINK_DGE510T 0x4c00 + #define PCI_VENDOR_ID_ARTOP 0x1191 #define PCI_DEVICE_ID_ARTOP_ATP8400 0x0004 #define PCI_DEVICE_ID_ARTOP_ATP850UF 0x0005 @@ -1735,6 +1740,9 @@ #define PCI_VENDOR_ID_KAWASAKI 0x136b #define PCI_DEVICE_ID_MCHIP_KL5A72002 0xff01 +#define PCI_VENDOR_ID_CNET 0x1371 +#define PCI_DEVICE_ID_CNET_GIGACARD 0x434e + #define PCI_VENDOR_ID_LMC 0x1376 #define PCI_DEVICE_ID_LMC_HSSI 0x0003 #define PCI_DEVICE_ID_LMC_DS3 0x0004 @@ -1918,6 +1926,10 @@ #define PCI_DEVICE_ID_FARSITE_T4U 0x0640 #define PCI_DEVICE_ID_FARSITE_TE1 0x1610 #define PCI_DEVICE_ID_FARSITE_TE1C 0x1612 + +#define PCI_VENDOR_ID_LINKSYS 0x1737 +#define PCI_DEVICE_ID_LINKSYS_EG1032 0x1032 +#define PCI_DEVICE_ID_LINKSYS_EG1064 0x1064 #define PCI_VENDOR_ID_ALTIMA 0x173b #define PCI_DEVICE_ID_ALTIMA_AC1000 0x03e8 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI fixes for 2.6.7 2004-06-24 21:46 ` Greg KH @ 2004-06-24 21:46 ` Greg KH 0 siblings, 0 replies; 12+ messages in thread From: Greg KH @ 2004-06-24 21:46 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1823.1.11, 2004/06/23 16:59:52-07:00, ossi@kde.org [PATCH] PCI: (one more) PCI quirk for SMBus bridge on Asus P4 boards my board has one of those "clever" bioses that hide the smbus. this tiny patch adds it to the Bad Guy List (TM). Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> drivers/pci/quirks.c | 1 + 1 files changed, 1 insertion(+) diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c --- a/drivers/pci/quirks.c 2004-06-24 13:49:17 -07:00 +++ b/drivers/pci/quirks.c 2004-06-24 13:49:17 -07:00 @@ -705,6 +705,7 @@ } if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) switch(dev->subsystem_device) { + case 0x80b1: /* P4GE-V */ case 0x80b2: /* P4PE */ case 0x8093: /* P4B533-V */ asus_hides_smbus = 1; ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2004-06-24 22:40 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2004-06-24 21:30 [BK PATCH] PCI fixes for 2.6.7 Greg KH 2004-06-24 21:46 ` [PATCH] " Greg KH 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH 2004-06-24 21:46 ` Greg KH
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox