From fe98aeab8494cf431ef62e080cbe1dc1b6f5bd49 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Thu, 3 Nov 2005 18:51:17 -0600 Subject: [PATCH] ppc64: bugfix: crash on PHB add 19-rpaphp-crashing.patch This patch fixes a bug related to dlpar PHB add, after a PHB removal. -- The crash was due to the PHB not having a pci_dn structure yet, when the phb is being added. This code survived testing, of adding and removeig the PHB and all slots underneath it, 17 times so far, as of this writing. Signed-off-by: Linas Vepstas Signed-off-by: Paul Mackerras --- drivers/pci/hotplug/rpadlpar_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index fcb66b9a0e2..e8593a60ee8 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -306,7 +306,7 @@ static int dlpar_add_phb(char *drc_name, struct device_node *dn) { struct pci_controller *phb; - if (PCI_DN(dn)->phb) { + if (PCI_DN(dn) && PCI_DN(dn)->phb) { /* PHB already exists */ return -EINVAL; } -- cgit v1.2.3 From 24a4e377068d15424cd6a921d41352f295548037 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 28 Oct 2005 17:35:34 -0700 Subject: [PATCH] PCI: add pci_find_next_capability() Some devices have more than one capability of the same type. For example, the PCI header for the PathScale InfiniPath looks like: 04:01.0 InfiniBand: Unknown device 1fc1:000d (rev 02) Subsystem: Unknown device 1fc1:000d Flags: bus master, fast devsel, latency 0, IRQ 193 Memory at fea00000 (64-bit, non-prefetchable) [size=2M] Capabilities: [c0] HyperTransport: Slave or Primary Interface Capabilities: [f8] HyperTransport: Interrupt Discovery and Configuration There are _two_ HyperTransport capabilities, and the PathScale driver wants to look at both of them. The current pci_find_capability() API doesn't work for this, since it only allows us to get to the first capability of a given type. The patch below introduces a new pci_find_next_capability(), which can be used in a loop like for (pos = pci_find_capability(pdev, ); pos; pos = pci_find_next_capability(pdev, pos, )) { /* ... */ } Signed-off-by: Roland Dreier Signed-off-by: Matthew Wilcox Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e74d7584304..8e287a828d5 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -63,11 +63,38 @@ pci_max_busnr(void) return max; } +static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap) +{ + u8 id; + int ttl = 48; + + while (ttl--) { + pci_bus_read_config_byte(bus, devfn, pos, &pos); + if (pos < 0x40) + break; + pos &= ~3; + pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, + &id); + if (id == 0xff) + break; + if (id == cap) + return pos; + pos += PCI_CAP_LIST_NEXT; + } + return 0; +} + +int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap) +{ + return __pci_find_next_cap(dev->bus, dev->devfn, + pos + PCI_CAP_LIST_NEXT, cap); +} +EXPORT_SYMBOL_GPL(pci_find_next_capability); + static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap) { u16 status; - u8 pos, id; - int ttl = 48; + u8 pos; pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); if (!(status & PCI_STATUS_CAP_LIST)) @@ -76,24 +103,15 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty switch (hdr_type) { case PCI_HEADER_TYPE_NORMAL: case PCI_HEADER_TYPE_BRIDGE: - pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos); + pos = PCI_CAPABILITY_LIST; break; case PCI_HEADER_TYPE_CARDBUS: - pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos); + pos = PCI_CB_CAPABILITY_LIST; break; default: return 0; } - while (ttl-- && pos >= 0x40) { - pos &= ~3; - pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id); - if (id == 0xff) - break; - if (id == cap) - return pos; - pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos); - } - return 0; + return __pci_find_next_cap(bus, devfn, pos, cap); } /** -- cgit v1.2.3 From 71b720c0f96145f5868c87591c286b290bc1a6af Mon Sep 17 00:00:00 2001 From: "rajesh.shah@intel.com" Date: Mon, 31 Oct 2005 16:20:06 -0800 Subject: [PATCH] patch 1/8] pciehp: use the PCI core for hotplug resource management This patch converts the pci express hotplug controller driver to use the PCI core for resource management. This eliminates a lot of duplicated code and integrates pciehp with the system's normal PCI handling code. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 50 +- drivers/pci/hotplug/pciehp_core.c | 35 +- drivers/pci/hotplug/pciehp_ctrl.c | 1563 +------------------------------- drivers/pci/hotplug/pciehp_pci.c | 487 ++-------- drivers/pci/hotplug/pciehprm_acpi.c | 840 ----------------- drivers/pci/hotplug/pciehprm_nonacpi.c | 347 ------- 6 files changed, 85 insertions(+), 3237 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 061ead21ef1..e9480ddd5ab 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -59,14 +59,8 @@ struct pci_func { u8 configured; u8 switch_save; u8 presence_save; - u32 base_length[0x06]; - u8 base_type[0x06]; u16 reserved2; u32 config_space[0x20]; - struct pci_resource *mem_head; - struct pci_resource *p_mem_head; - struct pci_resource *io_head; - struct pci_resource *bus_head; struct pci_dev* pci_dev; }; @@ -90,12 +84,6 @@ struct slot { struct list_head slot_list; }; -struct pci_resource { - struct pci_resource * next; - u32 base; - u32 length; -}; - struct event_info { u32 event_type; u8 hp_slot; @@ -107,10 +95,6 @@ struct controller { void *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ - struct pci_resource *mem_head; - struct pci_resource *p_mem_head; - struct pci_resource *io_head; - struct pci_resource *bus_head; struct pci_dev *pci_dev; struct pci_bus *pci_bus; struct event_info event_queue[10]; @@ -133,20 +117,6 @@ struct controller { u8 cap_base; }; -struct irq_mapping { - u8 barber_pole; - u8 valid_INT; - u8 interrupt[4]; -}; - -struct resource_lists { - struct pci_resource *mem_head; - struct pci_resource *p_mem_head; - struct pci_resource *io_head; - struct pci_resource *bus_head; - struct irq_mapping *irqs; -}; - #define INT_BUTTON_IGNORE 0 #define INT_PRESENCE_ON 1 #define INT_PRESENCE_OFF 2 @@ -203,14 +173,12 @@ struct resource_lists { #define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n" #define msg_HPC_non_pcie "The PCI hot plug controller is not supported by this driver.\n" #define msg_HPC_not_supported "This system is not supported by this version of pciephd module. Upgrade to a newer version of pciehpd\n" -#define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n" #define msg_button_on "PCI slot #%d - powering on due to button press.\n" #define msg_button_off "PCI slot #%d - powering off due to button press.\n" #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" /* controller functions */ -extern int pciehprm_find_available_resources (struct controller *ctrl); extern int pciehp_event_start_thread (void); extern void pciehp_event_stop_thread (void); extern struct pci_func *pciehp_slot_create (unsigned char busnumber); @@ -224,19 +192,12 @@ extern u8 pciehp_handle_presence_change (u8 hp_slot, void *inst_id); extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); /* extern void long_delay (int delay); */ -/* resource functions */ -extern int pciehp_resource_sort_and_combine (struct pci_resource **head); - /* pci functions */ extern int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); /*extern int pciehp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/ extern int pciehp_save_config (struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); -extern int pciehp_save_used_resources (struct controller *ctrl, struct pci_func * func, int flag); extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot); -extern void pciehp_destroy_board_resources (struct pci_func * func); -extern int pciehp_return_board_resources (struct pci_func * func, struct resource_lists * resources); -extern void pciehp_destroy_resource_list (struct resource_lists * resources); -extern int pciehp_configure_device (struct controller* ctrl, struct pci_func* func); +extern int pciehp_configure_device (struct slot *ctrl); extern int pciehp_unconfigure_device (struct pci_func* func); @@ -289,15 +250,6 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl) return retval; } -/* Puts node back in the resource list pointed to by head */ -static inline void return_resource(struct pci_resource **head, struct pci_resource *node) -{ - if (!node || !head) - return; - node->next = *head; - *head = node; -} - #define SLOT_NAME_SIZE 10 static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index cafc7eadcf8..190664e5adf 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -433,16 +433,8 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ goto err_out_free_ctrl_bus; } - /* Get IO, memory, and IRQ resources for new devices */ - rc = pciehprm_find_available_resources(ctrl); - ctrl->add_support = !rc; + ctrl->add_support = 1; - if (rc) { - dbg("pciehprm_find_available_resources = %#x\n", rc); - err("unable to locate PCI configuration resources for hot plug add.\n"); - goto err_out_free_ctrl_bus; - } - /* Setup the slot information structures */ rc = init_slots(ctrl); if (rc) { @@ -521,18 +513,6 @@ static int pcie_start_thread(void) return retval; } -static inline void __exit -free_pciehp_res(struct pci_resource *res) -{ - struct pci_resource *tres; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } -} - static void __exit unload_pciehpd(void) { struct pci_func *next; @@ -546,11 +526,6 @@ static void __exit unload_pciehpd(void) while (ctrl) { cleanup_slots(ctrl); - free_pciehp_res(ctrl->io_head); - free_pciehp_res(ctrl->mem_head); - free_pciehp_res(ctrl->p_mem_head); - free_pciehp_res(ctrl->bus_head); - kfree (ctrl->pci_bus); ctrl->hpc_ops->release_ctlr(ctrl); @@ -564,11 +539,6 @@ static void __exit unload_pciehpd(void) for (loop = 0; loop < 256; loop++) { next = pciehp_slot_list[loop]; while (next != NULL) { - free_pciehp_res(next->io_head); - free_pciehp_res(next->mem_head); - free_pciehp_res(next->p_mem_head); - free_pciehp_res(next->bus_head); - TempSlot = next; next = next->next; kfree(TempSlot); @@ -652,8 +622,7 @@ error_hpc_init: if (retval) { pciehprm_cleanup(); pciehp_event_stop_thread(); - } else - pciehprm_print_pirt(); + }; return retval; } diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 898f6da6f0d..412783e0ef4 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -42,10 +42,6 @@ #include "pciehp.h" #include "pciehprm.h" -static u32 configure_new_device(struct controller *ctrl, struct pci_func *func, - u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev); -static int configure_new_function( struct controller *ctrl, struct pci_func *func, - u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev); static void interrupt_event_handler(struct controller *ctrl); static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ @@ -252,627 +248,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) return rc; } - -/** - * sort_by_size: sort nodes by their length, smallest first. - * - * @head: list to sort - */ -static int sort_by_size(struct pci_resource **head) -{ - struct pci_resource *current_res; - struct pci_resource *next_res; - int out_of_order = 1; - - if (!(*head)) - return 1; - - if (!((*head)->next)) - return 0; - - while (out_of_order) { - out_of_order = 0; - - /* Special case for swapping list head */ - if (((*head)->next) && - ((*head)->length > (*head)->next->length)) { - out_of_order++; - current_res = *head; - *head = (*head)->next; - current_res->next = (*head)->next; - (*head)->next = current_res; - } - - current_res = *head; - - while (current_res->next && current_res->next->next) { - if (current_res->next->length > current_res->next->next->length) { - out_of_order++; - next_res = current_res->next; - current_res->next = current_res->next->next; - current_res = current_res->next; - next_res->next = current_res->next; - current_res->next = next_res; - } else - current_res = current_res->next; - } - } /* End of out_of_order loop */ - - return 0; -} - - -/* - * sort_by_max_size - * - * Sorts nodes on the list by their length. - * Largest first. - * - */ -static int sort_by_max_size(struct pci_resource **head) -{ - struct pci_resource *current_res; - struct pci_resource *next_res; - int out_of_order = 1; - - if (!(*head)) - return 1; - - if (!((*head)->next)) - return 0; - - while (out_of_order) { - out_of_order = 0; - - /* Special case for swapping list head */ - if (((*head)->next) && - ((*head)->length < (*head)->next->length)) { - out_of_order++; - current_res = *head; - *head = (*head)->next; - current_res->next = (*head)->next; - (*head)->next = current_res; - } - - current_res = *head; - - while (current_res->next && current_res->next->next) { - if (current_res->next->length < current_res->next->next->length) { - out_of_order++; - next_res = current_res->next; - current_res->next = current_res->next->next; - current_res = current_res->next; - next_res->next = current_res->next; - current_res->next = next_res; - } else - current_res = current_res->next; - } - } /* End of out_of_order loop */ - - return 0; -} - - -/** - * do_pre_bridge_resource_split: return one unused resource node - * @head: list to scan - * - */ -static struct pci_resource * -do_pre_bridge_resource_split(struct pci_resource **head, - struct pci_resource **orig_head, u32 alignment) -{ - struct pci_resource *prevnode = NULL; - struct pci_resource *node; - struct pci_resource *split_node; - u32 rc; - u32 temp_dword; - dbg("do_pre_bridge_resource_split\n"); - - if (!(*head) || !(*orig_head)) - return NULL; - - rc = pciehp_resource_sort_and_combine(head); - - if (rc) - return NULL; - - if ((*head)->base != (*orig_head)->base) - return NULL; - - if ((*head)->length == (*orig_head)->length) - return NULL; - - - /* If we got here, there the bridge requires some of the resource, but - * we may be able to split some off of the front - */ - node = *head; - - if (node->length & (alignment -1)) { - /* this one isn't an aligned length, so we'll make a new entry - * and split it up. - */ - split_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - - if (!split_node) - return NULL; - - temp_dword = (node->length | (alignment-1)) + 1 - alignment; - - split_node->base = node->base; - split_node->length = temp_dword; - - node->length -= temp_dword; - node->base += split_node->length; - - /* Put it in the list */ - *head = split_node; - split_node->next = node; - } - - if (node->length < alignment) - return NULL; - - /* Now unlink it */ - if (*head == node) { - *head = node->next; - } else { - prevnode = *head; - while (prevnode->next != node) - prevnode = prevnode->next; - - prevnode->next = node->next; - } - node->next = NULL; - - return node; -} - - -/** - * do_bridge_resource_split: return one unused resource node - * @head: list to scan - * - */ -static struct pci_resource * -do_bridge_resource_split(struct pci_resource **head, u32 alignment) -{ - struct pci_resource *prevnode = NULL; - struct pci_resource *node; - u32 rc; - u32 temp_dword; - - if (!(*head)) - return NULL; - - rc = pciehp_resource_sort_and_combine(head); - - if (rc) - return NULL; - - node = *head; - - while (node->next) { - prevnode = node; - node = node->next; - kfree(prevnode); - } - - if (node->length < alignment) { - kfree(node); - return NULL; - } - - if (node->base & (alignment - 1)) { - /* Short circuit if adjusted size is too small */ - temp_dword = (node->base | (alignment-1)) + 1; - if ((node->length - (temp_dword - node->base)) < alignment) { - kfree(node); - return NULL; - } - - node->length -= (temp_dword - node->base); - node->base = temp_dword; - } - - if (node->length & (alignment - 1)) { - /* There's stuff in use after this node */ - kfree(node); - return NULL; - } - - return node; -} - - -/* - * get_io_resource - * - * this function sorts the resource list by size and then - * returns the first node of "size" length that is not in the - * ISA aliasing window. If it finds a node larger than "size" - * it will split it up. - * - * size must be a power of two. - */ -static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size) -{ - struct pci_resource *prevnode; - struct pci_resource *node; - struct pci_resource *split_node = NULL; - u32 temp_dword; - - if (!(*head)) - return NULL; - - if ( pciehp_resource_sort_and_combine(head) ) - return NULL; - - if ( sort_by_size(head) ) - return NULL; - - for (node = *head; node; node = node->next) { - if (node->length < size) - continue; - - if (node->base & (size - 1)) { - /* this one isn't base aligned properly - so we'll make a new entry and split it up */ - temp_dword = (node->base | (size-1)) + 1; - - /*/ Short circuit if adjusted size is too small */ - if ((node->length - (temp_dword - node->base)) < size) - continue; - - split_node = kmalloc(sizeof(struct pci_resource), - GFP_KERNEL); - - if (!split_node) - return NULL; - - split_node->base = node->base; - split_node->length = temp_dword - node->base; - node->base = temp_dword; - node->length -= split_node->length; - - /* Put it in the list */ - split_node->next = node->next; - node->next = split_node; - } /* End of non-aligned base */ - - /* Don't need to check if too small since we already did */ - if (node->length > size) { - /* this one is longer than we need - so we'll make a new entry and split it up */ - split_node = kmalloc(sizeof(struct pci_resource), - GFP_KERNEL); - - if (!split_node) - return NULL; - - split_node->base = node->base + size; - split_node->length = node->length - size; - node->length = size; - - /* Put it in the list */ - split_node->next = node->next; - node->next = split_node; - } /* End of too big on top end */ - - /* For IO make sure it's not in the ISA aliasing space */ - if (node->base & 0x300L) - continue; - - /* If we got here, then it is the right size - Now take it out of the list */ - if (*head == node) { - *head = node->next; - } else { - prevnode = *head; - while (prevnode->next != node) - prevnode = prevnode->next; - - prevnode->next = node->next; - } - node->next = NULL; - /* Stop looping */ - break; - } - - return node; -} - - -/* - * get_max_resource - * - * Gets the largest node that is at least "size" big from the - * list pointed to by head. It aligns the node on top and bottom - * to "size" alignment before returning it. - * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M - * This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot. - */ -static struct pci_resource *get_max_resource(struct pci_resource **head, u32 size) -{ - struct pci_resource *max; - struct pci_resource *temp; - struct pci_resource *split_node; - u32 temp_dword; - u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 }; - int i; - - if (!(*head)) - return NULL; - - if (pciehp_resource_sort_and_combine(head)) - return NULL; - - if (sort_by_max_size(head)) - return NULL; - - for (max = *head;max; max = max->next) { - - /* If not big enough we could probably just bail, - instead we'll continue to the next. */ - if (max->length < size) - continue; - - if (max->base & (size - 1)) { - /* this one isn't base aligned properly - so we'll make a new entry and split it up */ - temp_dword = (max->base | (size-1)) + 1; - - /* Short circuit if adjusted size is too small */ - if ((max->length - (temp_dword - max->base)) < size) - continue; - - split_node = kmalloc(sizeof(struct pci_resource), - GFP_KERNEL); - - if (!split_node) - return NULL; - - split_node->base = max->base; - split_node->length = temp_dword - max->base; - max->base = temp_dword; - max->length -= split_node->length; - - /* Put it next in the list */ - split_node->next = max->next; - max->next = split_node; - } - - if ((max->base + max->length) & (size - 1)) { - /* this one isn't end aligned properly at the top - so we'll make a new entry and split it up */ - split_node = kmalloc(sizeof(struct pci_resource), - GFP_KERNEL); - - if (!split_node) - return NULL; - temp_dword = ((max->base + max->length) & ~(size - 1)); - split_node->base = temp_dword; - split_node->length = max->length + max->base - - split_node->base; - max->length -= split_node->length; - - /* Put it in the list */ - split_node->next = max->next; - max->next = split_node; - } - - /* Make sure it didn't shrink too much when we aligned it */ - if (max->length < size) - continue; - - for ( i = 0; max_size[i] > size; i++) { - if (max->length > max_size[i]) { - split_node = kmalloc(sizeof(struct pci_resource), - GFP_KERNEL); - if (!split_node) - break; /* return NULL; */ - split_node->base = max->base + max_size[i]; - split_node->length = max->length - max_size[i]; - max->length = max_size[i]; - /* Put it next in the list */ - split_node->next = max->next; - max->next = split_node; - break; - } - } - - /* Now take it out of the list */ - temp = (struct pci_resource*) *head; - if (temp == max) { - *head = max->next; - } else { - while (temp && temp->next != max) { - temp = temp->next; - } - - temp->next = max->next; - } - - max->next = NULL; - return max; - } - - /* If we get here, we couldn't find one */ - return NULL; -} - - -/* - * get_resource - * - * this function sorts the resource list by size and then - * returns the first node of "size" length. If it finds a node - * larger than "size" it will split it up. - * - * size must be a power of two. - */ -static struct pci_resource *get_resource(struct pci_resource **head, u32 size) -{ - struct pci_resource *prevnode; - struct pci_resource *node; - struct pci_resource *split_node; - u32 temp_dword; - - if (!(*head)) - return NULL; - - if ( pciehp_resource_sort_and_combine(head) ) - return NULL; - - if ( sort_by_size(head) ) - return NULL; - - for (node = *head; node; node = node->next) { - dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n", - __FUNCTION__, size, node, node->base, node->length); - if (node->length < size) - continue; - - if (node->base & (size - 1)) { - dbg("%s: not aligned\n", __FUNCTION__); - /* this one isn't base aligned properly - so we'll make a new entry and split it up */ - temp_dword = (node->base | (size-1)) + 1; - - /* Short circuit if adjusted size is too small */ - if ((node->length - (temp_dword - node->base)) < size) - continue; - - split_node = kmalloc(sizeof(struct pci_resource), - GFP_KERNEL); - - if (!split_node) - return NULL; - - split_node->base = node->base; - split_node->length = temp_dword - node->base; - node->base = temp_dword; - node->length -= split_node->length; - - /* Put it in the list */ - split_node->next = node->next; - node->next = split_node; - } /* End of non-aligned base */ - - /* Don't need to check if too small since we already did */ - if (node->length > size) { - dbg("%s: too big\n", __FUNCTION__); - /* this one is longer than we need - so we'll make a new entry and split it up */ - split_node = kmalloc(sizeof(struct pci_resource), - GFP_KERNEL); - - if (!split_node) - return NULL; - - split_node->base = node->base + size; - split_node->length = node->length - size; - node->length = size; - - /* Put it in the list */ - split_node->next = node->next; - node->next = split_node; - } /* End of too big on top end */ - - dbg("%s: got one!!!\n", __FUNCTION__); - /* If we got here, then it is the right size - Now take it out of the list */ - if (*head == node) { - *head = node->next; - } else { - prevnode = *head; - while (prevnode->next != node) - prevnode = prevnode->next; - - prevnode->next = node->next; - } - node->next = NULL; - /* Stop looping */ - break; - } - return node; -} - - -/* - * pciehp_resource_sort_and_combine - * - * Sorts all of the nodes in the list in ascending order by - * their base addresses. Also does garbage collection by - * combining adjacent nodes. - * - * returns 0 if success - */ -int pciehp_resource_sort_and_combine(struct pci_resource **head) -{ - struct pci_resource *node1; - struct pci_resource *node2; - int out_of_order = 1; - - dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head); - - if (!(*head)) - return 1; - - dbg("*head->next = %p\n",(*head)->next); - - if (!(*head)->next) - return 0; /* only one item on the list, already sorted! */ - - dbg("*head->base = 0x%x\n",(*head)->base); - dbg("*head->next->base = 0x%x\n",(*head)->next->base); - while (out_of_order) { - out_of_order = 0; - - /* Special case for swapping list head */ - if (((*head)->next) && - ((*head)->base > (*head)->next->base)) { - node1 = *head; - (*head) = (*head)->next; - node1->next = (*head)->next; - (*head)->next = node1; - out_of_order++; - } - - node1 = (*head); - - while (node1->next && node1->next->next) { - if (node1->next->base > node1->next->next->base) { - out_of_order++; - node2 = node1->next; - node1->next = node1->next->next; - node1 = node1->next; - node2->next = node1->next; - node1->next = node2; - } else - node1 = node1->next; - } - } /* End of out_of_order loop */ - - node1 = *head; - - while (node1 && node1->next) { - if ((node1->base + node1->length) == node1->next->base) { - /* Combine */ - dbg("8..\n"); - node1->length += node1->next->length; - node2 = node1->next; - node1->next = node1->next->next; - kfree(node2); - } else - node1 = node1->next; - } - - return 0; -} - - /** * pciehp_slot_create - Creates a node and adds it to the proper bus. * @busnumber - bus where new node is to be located @@ -926,7 +301,6 @@ static int slot_remove(struct pci_func * old_slot) if (next == old_slot) { pciehp_slot_list[old_slot->bus] = old_slot->next; - pciehp_destroy_board_resources(old_slot); kfree(old_slot); return 0; } @@ -937,7 +311,6 @@ static int slot_remove(struct pci_func * old_slot) if (next->next == old_slot) { next->next = old_slot->next; - pciehp_destroy_board_resources(old_slot); kfree(old_slot); return 0; } else @@ -1103,12 +476,9 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) static u32 board_added(struct pci_func * func, struct controller * ctrl) { u8 hp_slot; - int index; u32 temp_register = 0xFFFFFFFF; u32 rc = 0; - struct pci_func *new_func = NULL; struct slot *p_slot; - struct resource_lists res_lists; p_slot = pciehp_find_slot(ctrl, func->device); hp_slot = func->device - ctrl->slot_device_offset; @@ -1162,89 +532,43 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register); rc = POWER_FAILURE; func->status = 0; - } else { - /* Get vendor/device ID u32 */ - rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function), - PCI_VENDOR_ID, &temp_register); - dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc); - dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register); - - if (rc != 0) { - /* Something's wrong here */ - temp_register = 0xFFFFFFFF; - dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register); - } - /* Preset return code. It will be changed later if things go okay. */ - rc = NO_ADAPTER_PRESENT; + goto err_exit; } - /* All F's is an empty slot or an invalid board */ - if (temp_register != 0xFFFFFFFF) { /* Check for a board in the slot */ - res_lists.io_head = ctrl->io_head; - res_lists.mem_head = ctrl->mem_head; - res_lists.p_mem_head = ctrl->p_mem_head; - res_lists.bus_head = ctrl->bus_head; - res_lists.irqs = NULL; - - rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0); - dbg("%s: back from configure_new_device\n", __FUNCTION__); - - ctrl->io_head = res_lists.io_head; - ctrl->mem_head = res_lists.mem_head; - ctrl->p_mem_head = res_lists.p_mem_head; - ctrl->bus_head = res_lists.bus_head; - - pciehp_resource_sort_and_combine(&(ctrl->mem_head)); - pciehp_resource_sort_and_combine(&(ctrl->p_mem_head)); - pciehp_resource_sort_and_combine(&(ctrl->io_head)); - pciehp_resource_sort_and_combine(&(ctrl->bus_head)); + rc = pciehp_configure_device(p_slot); + if (rc) { + err("Cannot add device 0x%x:%x\n", p_slot->bus, + p_slot->device); + goto err_exit; + } - if (rc) { - set_slot_off(ctrl, p_slot); - return rc; - } - pciehp_save_slot_config(ctrl, func); + pciehp_save_slot_config(ctrl, func); + func->status = 0; + func->switch_save = 0x10; + func->is_a_board = 0x01; - func->status = 0; - func->switch_save = 0x10; - func->is_a_board = 0x01; + /* + * Some PCI Express root ports require fixup after hot-plug operation. + */ + if (pcie_mch_quirk) + pci_fixup_device(pci_fixup_final, ctrl->pci_dev); + if (PWR_LED(ctrl->ctrlcap)) { + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); - /* next, we will instantiate the linux pci_dev structures - * (with appropriate driver notification, if already present) - */ - index = 0; - do { - new_func = pciehp_slot_find(ctrl->slot_bus, func->device, index++); - if (new_func && !new_func->pci_dev) { - dbg("%s:call pci_hp_configure_dev, func %x\n", - __FUNCTION__, index); - pciehp_configure_device(ctrl, new_func); - } - } while (new_func); - - /* - * Some PCI Express root ports require fixup after hot-plug operation. - */ - if (pcie_mch_quirk) - pci_fixup_device(pci_fixup_final, ctrl->pci_dev); - - if (PWR_LED(ctrl->ctrlcap)) { - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - p_slot->hpc_ops->green_led_on(p_slot); + p_slot->hpc_ops->green_led_on(p_slot); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - } - } else { - set_slot_off(ctrl, p_slot); - return -1; - } + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } return 0; + +err_exit: + set_slot_off(ctrl, p_slot); + return -1; } @@ -1254,13 +578,9 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) */ static u32 remove_board(struct pci_func *func, struct controller *ctrl) { - int index; - u8 skip = 0; u8 device; u8 hp_slot; u32 rc; - struct resource_lists res_lists; - struct pci_func *temp_func; struct slot *p_slot; if (func == NULL) @@ -1276,27 +596,6 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl) dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); - if ((ctrl->add_support) && - !(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) { - /* Here we check to see if we've saved any of the board's - * resources already. If so, we'll skip the attempt to - * determine what's being used. - */ - index = 0; - - temp_func = func; - - while ((temp_func = pciehp_slot_find(temp_func->bus, temp_func->device, index++))) { - if (temp_func->bus_head || temp_func->mem_head - || temp_func->p_mem_head || temp_func->io_head) { - skip = 1; - break; - } - } - - if (!skip) - rc = pciehp_save_used_resources(ctrl, func, DISABLE_CARD); - } /* Change status to shutdown */ if (func->is_a_board) func->status = 0x01; @@ -1330,26 +629,6 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl) if (ctrl->add_support) { while (func) { - res_lists.io_head = ctrl->io_head; - res_lists.mem_head = ctrl->mem_head; - res_lists.p_mem_head = ctrl->p_mem_head; - res_lists.bus_head = ctrl->bus_head; - - dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n", - func->bus, func->device, func->function); - - pciehp_return_board_resources(func, &res_lists); - - ctrl->io_head = res_lists.io_head; - ctrl->mem_head = res_lists.mem_head; - ctrl->p_mem_head = res_lists.p_mem_head; - ctrl->bus_head = res_lists.bus_head; - - pciehp_resource_sort_and_combine(&(ctrl->mem_head)); - pciehp_resource_sort_and_combine(&(ctrl->p_mem_head)); - pciehp_resource_sort_and_combine(&(ctrl->io_head)); - pciehp_resource_sort_and_combine(&(ctrl->bus_head)); - if (is_bridge(func)) { dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); @@ -1918,787 +1197,3 @@ int pciehp_disable_slot(struct slot *p_slot) return rc; } - -/** - * configure_new_device - Configures the PCI header information of one board. - * - * @ctrl: pointer to controller structure - * @func: pointer to function structure - * @behind_bridge: 1 if this is a recursive call, 0 if not - * @resources: pointer to set of resource lists - * - * Returns 0 if success - * - */ -static u32 configure_new_device(struct controller * ctrl, struct pci_func * func, - u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev) -{ - u8 temp_byte, function, max_functions, stop_it; - int rc; - u32 ID; - struct pci_func *new_slot; - struct pci_bus lpci_bus, *pci_bus; - int index; - - new_slot = func; - - dbg("%s\n", __FUNCTION__); - memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); - pci_bus = &lpci_bus; - pci_bus->number = func->bus; - - /* Check for Multi-function device */ - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte); - if (rc) { - dbg("%s: rc = %d\n", __FUNCTION__, rc); - return rc; - } - - if (temp_byte & 0x80) /* Multi-function device */ - max_functions = 8; - else - max_functions = 1; - - function = 0; - - do { - rc = configure_new_function(ctrl, new_slot, behind_bridge, - resources, bridge_bus, bridge_dev); - - if (rc) { - dbg("configure_new_function failed: %d\n", rc); - index = 0; - - while (new_slot) { - new_slot = pciehp_slot_find(new_slot->bus, - new_slot->device, index++); - - if (new_slot) - pciehp_return_board_resources(new_slot, - resources); - } - - return rc; - } - - function++; - - stop_it = 0; - - /* The following loop skips to the next present function - * and creates a board structure - */ - - while ((function < max_functions) && (!stop_it)) { - pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID); - - if (ID == 0xFFFFFFFF) { /* There's nothing there. */ - function++; - } else { /* There's something there */ - /* Setup slot structure. */ - new_slot = pciehp_slot_create(func->bus); - - if (new_slot == NULL) { - /* Out of memory */ - return 1; - } - - new_slot->bus = func->bus; - new_slot->device = func->device; - new_slot->function = function; - new_slot->is_a_board = 1; - new_slot->status = 0; - - stop_it++; - } - } - - } while (function < max_functions); - dbg("returning from %s\n", __FUNCTION__); - - return 0; -} - -/* - * Configuration logic that involves the hotplug data structures and - * their bookkeeping - */ - -/** - * configure_bridge: fill bridge's registers, either configure or disable it. - */ -static int -configure_bridge(struct pci_bus *pci_bus, unsigned int devfn, - struct pci_resource *mem_node, - struct pci_resource **hold_mem_node, - int base_addr, int limit_addr) -{ - u16 temp_word; - u32 rc; - - if (mem_node) { - memcpy(*hold_mem_node, mem_node, sizeof(struct pci_resource)); - mem_node->next = NULL; - - /* set Mem base and Limit registers */ - RES_CHECK(mem_node->base, 16); - temp_word = (u16)(mem_node->base >> 16); - rc = pci_bus_write_config_word(pci_bus, devfn, base_addr, temp_word); - - RES_CHECK(mem_node->base + mem_node->length - 1, 16); - temp_word = (u16)((mem_node->base + mem_node->length - 1) >> 16); - rc = pci_bus_write_config_word(pci_bus, devfn, limit_addr, temp_word); - } else { - temp_word = 0xFFFF; - rc = pci_bus_write_config_word(pci_bus, devfn, base_addr, temp_word); - - temp_word = 0x0000; - rc = pci_bus_write_config_word(pci_bus, devfn, limit_addr, temp_word); - - kfree(*hold_mem_node); - *hold_mem_node = NULL; - } - return rc; -} - -static int -configure_new_bridge(struct controller *ctrl, struct pci_func *func, - u8 behind_bridge, struct resource_lists *resources, - struct pci_bus *pci_bus) -{ - int cloop; - u8 temp_byte; - u8 device; - u16 temp_word; - u32 rc; - u32 ID; - unsigned int devfn; - struct pci_resource *mem_node; - struct pci_resource *p_mem_node; - struct pci_resource *io_node; - struct pci_resource *bus_node; - struct pci_resource *hold_mem_node; - struct pci_resource *hold_p_mem_node; - struct pci_resource *hold_IO_node; - struct pci_resource *hold_bus_node; - struct irq_mapping irqs; - struct pci_func *new_slot; - struct resource_lists temp_resources; - - devfn = PCI_DEVFN(func->device, func->function); - - /* set Primary bus */ - dbg("set Primary bus = 0x%x\n", func->bus); - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus); - if (rc) - return rc; - - /* find range of busses to use */ - bus_node = get_max_resource(&resources->bus_head, 1L); - - /* If we don't have any busses to allocate, we can't continue */ - if (!bus_node) { - err("Got NO bus resource to use\n"); - return -ENOMEM; - } - dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length); - - /* set Secondary bus */ - temp_byte = (u8)bus_node->base; - dbg("set Secondary bus = 0x%x\n", temp_byte); - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte); - if (rc) - return rc; - - /* set subordinate bus */ - temp_byte = (u8)(bus_node->base + bus_node->length - 1); - dbg("set subordinate bus = 0x%x\n", temp_byte); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); - if (rc) - return rc; - - /* Set HP parameters (Cache Line Size, Latency Timer) */ - rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE); - if (rc) - return rc; - - /* Setup the IO, memory, and prefetchable windows */ - - io_node = get_max_resource(&(resources->io_head), 0x1000L); - if (io_node) { - dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, - io_node->length, io_node->next); - } - - mem_node = get_max_resource(&(resources->mem_head), 0x100000L); - if (mem_node) { - dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, - mem_node->length, mem_node->next); - } - - if (resources->p_mem_head) - p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L); - else { - /* - * In some platform implementation, MEM and PMEM are not - * distinguished, and hence ACPI _CRS has only MEM entries - * for both MEM and PMEM. - */ - dbg("using MEM for PMEM\n"); - p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L); - } - if (p_mem_node) { - dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, - p_mem_node->length, p_mem_node->next); - } - - /* set up the IRQ info */ - if (!resources->irqs) { - irqs.barber_pole = 0; - irqs.interrupt[0] = 0; - irqs.interrupt[1] = 0; - irqs.interrupt[2] = 0; - irqs.interrupt[3] = 0; - irqs.valid_INT = 0; - } else { - irqs.barber_pole = resources->irqs->barber_pole; - irqs.interrupt[0] = resources->irqs->interrupt[0]; - irqs.interrupt[1] = resources->irqs->interrupt[1]; - irqs.interrupt[2] = resources->irqs->interrupt[2]; - irqs.interrupt[3] = resources->irqs->interrupt[3]; - irqs.valid_INT = resources->irqs->valid_INT; - } - - /* set up resource lists that are now aligned on top and bottom - * for anything behind the bridge. - */ - temp_resources.bus_head = bus_node; - temp_resources.io_head = io_node; - temp_resources.mem_head = mem_node; - temp_resources.p_mem_head = p_mem_node; - temp_resources.irqs = &irqs; - - /* Make copies of the nodes we are going to pass down so that - * if there is a problem,we can just use these to free resources - */ - hold_bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - hold_IO_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - hold_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - hold_p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - - if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) { - kfree(hold_bus_node); - kfree(hold_IO_node); - kfree(hold_mem_node); - kfree(hold_p_mem_node); - - return 1; - } - - memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource)); - - bus_node->base += 1; - bus_node->length -= 1; - bus_node->next = NULL; - - /* If we have IO resources copy them and fill in the bridge's - * IO range registers - */ - if (io_node) { - memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); - io_node->next = NULL; - - /* set IO base and Limit registers */ - RES_CHECK(io_node->base, 8); - temp_byte = (u8)(io_node->base >> 8); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); - - RES_CHECK(io_node->base + io_node->length - 1, 8); - temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); - } else { - kfree(hold_IO_node); - hold_IO_node = NULL; - } - - /* If we have memory resources copy them and fill in the bridge's - * memory range registers. Otherwise, fill in the range - * registers with values that disable them. - */ - rc = configure_bridge(pci_bus, devfn, mem_node, &hold_mem_node, - PCI_MEMORY_BASE, PCI_MEMORY_LIMIT); - - /* If we have prefetchable memory resources copy them and - * fill in the bridge's memory range registers. Otherwise, - * fill in the range registers with values that disable them. - */ - rc = configure_bridge(pci_bus, devfn, p_mem_node, &hold_p_mem_node, - PCI_PREF_MEMORY_BASE, PCI_PREF_MEMORY_LIMIT); - - /* Adjust this to compensate for extra adjustment in first loop */ - irqs.barber_pole--; - - rc = 0; - - /* Here we actually find the devices and configure them */ - for (device = 0; (device <= 0x1F) && !rc; device++) { - irqs.barber_pole = (irqs.barber_pole + 1) & 0x03; - - ID = 0xFFFFFFFF; - pci_bus->number = hold_bus_node->base; - pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); - pci_bus->number = func->bus; - - if (ID != 0xFFFFFFFF) { /* device Present */ - /* Setup slot structure. */ - new_slot = pciehp_slot_create(hold_bus_node->base); - - if (new_slot == NULL) { - /* Out of memory */ - rc = -ENOMEM; - continue; - } - - new_slot->bus = hold_bus_node->base; - new_slot->device = device; - new_slot->function = 0; - new_slot->is_a_board = 1; - new_slot->status = 0; - - rc = configure_new_device(ctrl, new_slot, 1, - &temp_resources, func->bus, - func->device); - dbg("configure_new_device rc=0x%x\n",rc); - } /* End of IF (device in slot?) */ - } /* End of FOR loop */ - - if (rc) { - pciehp_destroy_resource_list(&temp_resources); - - return_resource(&(resources->bus_head), hold_bus_node); - return_resource(&(resources->io_head), hold_IO_node); - return_resource(&(resources->mem_head), hold_mem_node); - return_resource(&(resources->p_mem_head), hold_p_mem_node); - return(rc); - } - - /* save the interrupt routing information */ - if (resources->irqs) { - resources->irqs->interrupt[0] = irqs.interrupt[0]; - resources->irqs->interrupt[1] = irqs.interrupt[1]; - resources->irqs->interrupt[2] = irqs.interrupt[2]; - resources->irqs->interrupt[3] = irqs.interrupt[3]; - resources->irqs->valid_INT = irqs.valid_INT; - } else if (!behind_bridge) { - /* We need to hook up the interrupts here */ - for (cloop = 0; cloop < 4; cloop++) { - if (irqs.valid_INT & (0x01 << cloop)) { - rc = pciehp_set_irq(func->bus, func->device, - 0x0A + cloop, irqs.interrupt[cloop]); - if (rc) { - pciehp_destroy_resource_list (&temp_resources); - return_resource(&(resources->bus_head), hold_bus_node); - return_resource(&(resources->io_head), hold_IO_node); - return_resource(&(resources->mem_head), hold_mem_node); - return_resource(&(resources->p_mem_head), hold_p_mem_node); - return rc; - } - } - } /* end of for loop */ - } - - /* Return unused bus resources - * First use the temporary node to store information for the board - */ - if (hold_bus_node && bus_node && temp_resources.bus_head) { - hold_bus_node->length = bus_node->base - hold_bus_node->base; - - hold_bus_node->next = func->bus_head; - func->bus_head = hold_bus_node; - - temp_byte = (u8)(temp_resources.bus_head->base - 1); - - /* set subordinate bus */ - dbg("re-set subordinate bus = 0x%x\n", temp_byte); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); - - if (temp_resources.bus_head->length == 0) { - kfree(temp_resources.bus_head); - temp_resources.bus_head = NULL; - } else { - dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n", - func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length); - return_resource(&(resources->bus_head), temp_resources.bus_head); - } - } - - /* If we have IO space available and there is some left, - * return the unused portion - */ - if (hold_IO_node && temp_resources.io_head) { - io_node = do_pre_bridge_resource_split(&(temp_resources.io_head), - &hold_IO_node, 0x1000); - - /* Check if we were able to split something off */ - if (io_node) { - hold_IO_node->base = io_node->base + io_node->length; - - RES_CHECK(hold_IO_node->base, 8); - temp_byte = (u8)((hold_IO_node->base) >> 8); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); - - return_resource(&(resources->io_head), io_node); - } - - io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000); - - /* Check if we were able to split something off */ - if (io_node) { - /* First use the temporary node to store information for the board */ - hold_IO_node->length = io_node->base - hold_IO_node->base; - - /* If we used any, add it to the board's list */ - if (hold_IO_node->length) { - hold_IO_node->next = func->io_head; - func->io_head = hold_IO_node; - - RES_CHECK(io_node->base - 1, 8); - temp_byte = (u8)((io_node->base - 1) >> 8); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); - - return_resource(&(resources->io_head), io_node); - } else { - /* it doesn't need any IO */ - temp_byte = 0x00; - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); - - return_resource(&(resources->io_head), io_node); - kfree(hold_IO_node); - } - } else { - /* it used most of the range */ - hold_IO_node->next = func->io_head; - func->io_head = hold_IO_node; - } - } else if (hold_IO_node) { - /* it used the whole range */ - hold_IO_node->next = func->io_head; - func->io_head = hold_IO_node; - } - - /* If we have memory space available and there is some left, - * return the unused portion - */ - if (hold_mem_node && temp_resources.mem_head) { - mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L); - - /* Check if we were able to split something off */ - if (mem_node) { - hold_mem_node->base = mem_node->base + mem_node->length; - - RES_CHECK(hold_mem_node->base, 16); - temp_word = (u16)((hold_mem_node->base) >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); - - return_resource(&(resources->mem_head), mem_node); - } - - mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L); - - /* Check if we were able to split something off */ - if (mem_node) { - /* First use the temporary node to store information for the board */ - hold_mem_node->length = mem_node->base - hold_mem_node->base; - - if (hold_mem_node->length) { - hold_mem_node->next = func->mem_head; - func->mem_head = hold_mem_node; - - /* configure end address */ - RES_CHECK(mem_node->base - 1, 16); - temp_word = (u16)((mem_node->base - 1) >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); - - /* Return unused resources to the pool */ - return_resource(&(resources->mem_head), mem_node); - } else { - /* it doesn't need any Mem */ - temp_word = 0x0000; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); - - return_resource(&(resources->mem_head), mem_node); - kfree(hold_mem_node); - } - } else { - /* it used most of the range */ - hold_mem_node->next = func->mem_head; - func->mem_head = hold_mem_node; - } - } else if (hold_mem_node) { - /* it used the whole range */ - hold_mem_node->next = func->mem_head; - func->mem_head = hold_mem_node; - } - - /* If we have prefetchable memory space available and there is some - * left at the end, return the unused portion - */ - if (hold_p_mem_node && temp_resources.p_mem_head) { - p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head), - &hold_p_mem_node, 0x100000L); - - /* Check if we were able to split something off */ - if (p_mem_node) { - hold_p_mem_node->base = p_mem_node->base + p_mem_node->length; - - RES_CHECK(hold_p_mem_node->base, 16); - temp_word = (u16)((hold_p_mem_node->base) >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); - - return_resource(&(resources->p_mem_head), p_mem_node); - } - - p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L); - - /* Check if we were able to split something off */ - if (p_mem_node) { - /* First use the temporary node to store information for the board */ - hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base; - - /* If we used any, add it to the board's list */ - if (hold_p_mem_node->length) { - hold_p_mem_node->next = func->p_mem_head; - func->p_mem_head = hold_p_mem_node; - - RES_CHECK(p_mem_node->base - 1, 16); - temp_word = (u16)((p_mem_node->base - 1) >> 16); - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); - - return_resource(&(resources->p_mem_head), p_mem_node); - } else { - /* it doesn't need any PMem */ - temp_word = 0x0000; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); - - return_resource(&(resources->p_mem_head), p_mem_node); - kfree(hold_p_mem_node); - } - } else { - /* it used the most of the range */ - hold_p_mem_node->next = func->p_mem_head; - func->p_mem_head = hold_p_mem_node; - } - } else if (hold_p_mem_node) { - /* it used the whole range */ - hold_p_mem_node->next = func->p_mem_head; - func->p_mem_head = hold_p_mem_node; - } - - /* We should be configuring an IRQ and the bridge's base address - * registers if it needs them. Although we have never seen such - * a device - */ - - pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE); - - dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); - - return rc; -} - -/** - * configure_new_function - Configures the PCI header information of one device - * - * @ctrl: pointer to controller structure - * @func: pointer to function structure - * @behind_bridge: 1 if this is a recursive call, 0 if not - * @resources: pointer to set of resource lists - * - * Calls itself recursively for bridged devices. - * Returns 0 if success - * - */ -static int -configure_new_function(struct controller *ctrl, struct pci_func *func, - u8 behind_bridge, struct resource_lists *resources, - u8 bridge_bus, u8 bridge_dev) -{ - int cloop; - u8 temp_byte; - u8 class_code; - u32 rc; - u32 temp_register; - u32 base; - unsigned int devfn; - struct pci_resource *mem_node; - struct pci_resource *io_node; - struct pci_bus lpci_bus, *pci_bus; - - memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); - pci_bus = &lpci_bus; - pci_bus->number = func->bus; - devfn = PCI_DEVFN(func->device, func->function); - - /* Check for Bridge */ - rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte); - if (rc) - return rc; - dbg("%s: bus %x dev %x func %x temp_byte = %x\n", __FUNCTION__, - func->bus, func->device, func->function, temp_byte); - - if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ - rc = configure_new_bridge(ctrl, func, behind_bridge, resources, - pci_bus); - - if (rc) - return rc; - } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) { - /* Standard device */ - u64 base64; - rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code); - - if (class_code == PCI_BASE_CLASS_DISPLAY) - return DEVICE_TYPE_NOT_SUPPORTED; - - /* Figure out IO and memory needs */ - for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { - temp_register = 0xFFFFFFFF; - - rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); - rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register); - dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register, - func->bus, func->device, func->function); - - if (!temp_register) - continue; - - base64 = 0L; - if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) { - /* Map IO */ - - /* set base = amount of IO space */ - base = temp_register & 0xFFFFFFFC; - base = ~base + 1; - - dbg("NEED IO length(0x%x)\n", base); - io_node = get_io_resource(&(resources->io_head),(ulong)base); - - /* allocate the resource to the board */ - if (io_node) { - dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length); - base = (u32)io_node->base; - io_node->next = func->io_head; - func->io_head = io_node; - } else { - err("Got NO IO resource(length=0x%x)\n", base); - return -ENOMEM; - } - } else { /* map MEM */ - int prefetchable = 1; - struct pci_resource **res_node = &func->p_mem_head; - char *res_type_str = "PMEM"; - u32 temp_register2; - - if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) { - prefetchable = 0; - res_node = &func->mem_head; - res_type_str++; - } - - base = temp_register & 0xFFFFFFF0; - base = ~base + 1; - - switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { - case PCI_BASE_ADDRESS_MEM_TYPE_32: - dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base); - - if (prefetchable && resources->p_mem_head) - mem_node=get_resource(&(resources->p_mem_head), (ulong)base); - else { - if (prefetchable) - dbg("using MEM for PMEM\n"); - mem_node = get_resource(&(resources->mem_head), (ulong)base); - } - - /* allocate the resource to the board */ - if (mem_node) { - base = (u32)mem_node->base; - mem_node->next = *res_node; - *res_node = mem_node; - dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base, - mem_node->length); - } else { - err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base); - return -ENOMEM; - } - break; - case PCI_BASE_ADDRESS_MEM_TYPE_64: - rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2); - dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2, - temp_register, base); - - if (prefetchable && resources->p_mem_head) - mem_node = get_resource(&(resources->p_mem_head), (ulong)base); - else { - if (prefetchable) - dbg("using MEM for PMEM\n"); - mem_node = get_resource(&(resources->mem_head), (ulong)base); - } - - /* allocate the resource to the board */ - if (mem_node) { - base64 = mem_node->base; - mem_node->next = *res_node; - *res_node = mem_node; - dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32), - (u32)base64, mem_node->length); - } else { - err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base); - return -ENOMEM; - } - break; - default: - dbg("reserved BAR type=0x%x\n", temp_register); - break; - } - - } - - if (base64) { - rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64); - cloop += 4; - base64 >>= 32; - - if (base64) { - dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64); - base64 = 0x0L; - } - - rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64); - } else { - rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base); - } - } /* End of base register loop */ - - /* disable ROM base Address */ - rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00); - - /* Set HP parameters (Cache Line Size, Latency Timer) */ - rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); - if (rc) - return rc; - - pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL); - - dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, - func->function); - } /* End of Not-A-Bridge else */ - else { - /* It's some strange type of PCI adapter (Cardbus?) */ - return DEVICE_TYPE_NOT_SUPPORTED; - } - - func->configured = 1; - - return 0; -} diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index ff17d8e07e9..db59a06ab0b 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -37,47 +37,70 @@ #include #include "../pci.h" #include "pciehp.h" -#ifndef CONFIG_IA64 -#include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */ -#endif -int pciehp_configure_device (struct controller* ctrl, struct pci_func* func) +int pciehp_configure_device(struct slot *p_slot) { - unsigned char bus; - struct pci_bus *child; - int num; - - if (func->pci_dev == NULL) - func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); - - /* Still NULL ? Well then scan for it ! */ - if (func->pci_dev == NULL) { - dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__); - - num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function)); - - if (num) - pci_bus_add_devices(ctrl->pci_dev->subordinate); - - func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); - if (func->pci_dev == NULL) { - dbg("ERROR: pci_dev still null\n"); - return 0; - } + struct pci_dev *dev; + struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; + int num, fn; + + dev = pci_find_slot(p_slot->bus, 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); + return -EINVAL; } - if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); - child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); - pci_do_scan_bus(child); + num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0)); + if (num == 0) { + err("No new device found\n"); + return -ENODEV; + } + for (fn = 0; fn < 8; fn++) { + if (!(dev = pci_find_slot(p_slot->bus, + PCI_DEVFN(p_slot->device, fn)))) + continue; + if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { + err("Cannot hot-add display device %s\n", + pci_name(dev)); + continue; + } + if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || + (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { + /* Find an unused bus number for the new bridge */ + struct pci_bus *child; + unsigned char busnr, start = parent->secondary; + unsigned char end = parent->subordinate; + for (busnr = start; busnr <= end; busnr++) { + if (!pci_find_bus(pci_domain_nr(parent), + busnr)) + break; + } + if (busnr >= end) { + err("No free bus for hot-added bridge\n"); + continue; + } + child = pci_add_new_bus(parent, dev, busnr); + if (!child) { + err("Cannot add new bus for %s\n", + pci_name(dev)); + continue; + } + child->subordinate = pci_do_scan_bus(child); + pci_bus_size_bridges(child); + } + /* TBD: program firmware provided _HPP values */ + /* program_fw_provided_values(dev); */ } + pci_bus_assign_resources(parent); + pci_bus_add_devices(parent); + pci_enable_bridges(parent); return 0; } - int pciehp_unconfigure_device(struct pci_func* func) { int rc = 0; @@ -104,47 +127,6 @@ int pciehp_unconfigure_device(struct pci_func* func) return rc; } -/* - * pciehp_set_irq - * - * @bus_num: bus number of PCI device - * @dev_num: device number of PCI device - * @slot: pointer to u8 where slot number will be returned - */ -int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num) -{ -#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_IO_APIC) - int rc; - u16 temp_word; - struct pci_dev fakedev; - struct pci_bus fakebus; - - fakedev.devfn = dev_num << 3; - fakedev.bus = &fakebus; - fakebus.number = bus_num; - dbg("%s: dev %d, bus %d, pin %d, num %d\n", - __FUNCTION__, dev_num, bus_num, int_pin, irq_num); - rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num); - dbg("%s: rc %d\n", __FUNCTION__, rc); - if (!rc) - return !rc; - - /* set the Edge Level Control Register (ELCR) */ - temp_word = inb(0x4d0); - temp_word |= inb(0x4d1) << 8; - - temp_word |= 0x01 << irq_num; - - /* This should only be for x86 as it sets the Edge Level Control Register */ - outb((u8) (temp_word & 0xFF), 0x4d0); - outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1); -#endif - return 0; -} - -/* More PCI configuration routines; this time centered around hotplug controller */ - - /* * pciehp_save_config * @@ -462,366 +444,3 @@ int pciehp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot) return 0; } - -/* - * pciehp_save_used_resources - * - * Stores used resource information for existing boards. this is - * for boards that were in the system when this driver was loaded. - * this function is for hot plug ADD - * - * returns 0 if success - * if disable == 1(DISABLE_CARD), - * it loops for all functions of the slot and disables them. - * else, it just get resources of the function and return. - */ -int pciehp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable) -{ - u8 cloop; - u8 header_type; - u8 secondary_bus; - u8 temp_byte; - u16 command; - u16 save_command; - u16 w_base, w_length; - u32 temp_register; - u32 save_base; - u32 base, length; - u64 base64 = 0; - int index = 0; - unsigned int devfn; - struct pci_resource *mem_node = NULL; - struct pci_resource *p_mem_node = NULL; - struct pci_resource *t_mem_node; - struct pci_resource *io_node; - struct pci_resource *bus_node; - struct pci_bus lpci_bus, *pci_bus; - memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); - pci_bus = &lpci_bus; - - if (disable) - func = pciehp_slot_find(func->bus, func->device, index++); - - while ((func != NULL) && func->is_a_board) { - pci_bus->number = func->bus; - devfn = PCI_DEVFN(func->device, func->function); - - /* Save the command register */ - pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command); - - if (disable) { - /* disable card */ - command = 0x00; - pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); - } - - /* Check for Bridge */ - pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type); - - if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ - dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", - func->bus, func->device, save_command); - if (disable) { - /* Clear Bridge Control Register */ - command = 0x00; - pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command); - } - - pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); - pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte); - - bus_node = kmalloc(sizeof(struct pci_resource), - GFP_KERNEL); - if (!bus_node) - return -ENOMEM; - - bus_node->base = (ulong)secondary_bus; - bus_node->length = (ulong)(temp_byte - secondary_bus + 1); - - bus_node->next = func->bus_head; - func->bus_head = bus_node; - - /* Save IO base and Limit registers */ - pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte); - base = temp_byte; - pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte); - length = temp_byte; - - if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) { - io_node = kmalloc(sizeof(struct pci_resource), - GFP_KERNEL); - if (!io_node) - return -ENOMEM; - - io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8; - io_node->length = (ulong)(length - base + 0x10) << 8; - - io_node->next = func->io_head; - func->io_head = io_node; - } - - /* Save memory base and Limit registers */ - pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base); - pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length); - - if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { - mem_node = kmalloc(sizeof(struct pci_resource), - GFP_KERNEL); - if (!mem_node) - return -ENOMEM; - - mem_node->base = (ulong)w_base << 16; - mem_node->length = (ulong)(w_length - w_base + 0x10) << 16; - - mem_node->next = func->mem_head; - func->mem_head = mem_node; - } - /* Save prefetchable memory base and Limit registers */ - pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base); - pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length); - - if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { - p_mem_node = kmalloc(sizeof(struct pci_resource), - GFP_KERNEL); - if (!p_mem_node) - return -ENOMEM; - - p_mem_node->base = (ulong)w_base << 16; - p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16; - - p_mem_node->next = func->p_mem_head; - func->p_mem_head = p_mem_node; - } - } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) { - dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", - func->bus, func->device, save_command); - - /* Figure out IO and memory base lengths */ - for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { - pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base); - - temp_register = 0xFFFFFFFF; - pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register); - pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register); - - if (!disable) - pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base); - - if (!temp_register) - continue; - - base = temp_register; - - if ((base & PCI_BASE_ADDRESS_SPACE_IO) && - (!disable || (save_command & PCI_COMMAND_IO))) { - /* IO base */ - /* set temp_register = amount of IO space requested */ - base = base & 0xFFFFFFFCL; - base = (~base) + 1; - - io_node = kmalloc(sizeof (struct pci_resource), - GFP_KERNEL); - if (!io_node) - return -ENOMEM; - - io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK; - io_node->length = (ulong)base; - dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", - io_node->base, io_node->length); - - io_node->next = func->io_head; - func->io_head = io_node; - } else { /* map Memory */ - int prefetchable = 1; - /* struct pci_resources **res_node; */ - char *res_type_str = "PMEM"; - u32 temp_register2; - - t_mem_node = kmalloc(sizeof (struct pci_resource), - GFP_KERNEL); - if (!t_mem_node) - return -ENOMEM; - - if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && - (!disable || (save_command & PCI_COMMAND_MEMORY))) { - prefetchable = 0; - mem_node = t_mem_node; - res_type_str++; - } else - p_mem_node = t_mem_node; - - base = base & 0xFFFFFFF0L; - base = (~base) + 1; - - switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { - case PCI_BASE_ADDRESS_MEM_TYPE_32: - if (prefetchable) { - p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; - p_mem_node->length = (ulong)base; - dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", - res_type_str, - p_mem_node->base, - p_mem_node->length); - - p_mem_node->next = func->p_mem_head; - func->p_mem_head = p_mem_node; - } else { - mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; - mem_node->length = (ulong)base; - dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", - res_type_str, - mem_node->base, - mem_node->length); - - mem_node->next = func->mem_head; - func->mem_head = mem_node; - } - break; - case PCI_BASE_ADDRESS_MEM_TYPE_64: - pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2); - base64 = temp_register2; - base64 = (base64 << 32) | save_base; - - if (temp_register2) { - dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n", - res_type_str, temp_register2, (u32)base64); - base64 &= 0x00000000FFFFFFFFL; - } - - if (prefetchable) { - p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; - p_mem_node->length = base; - dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", - res_type_str, - p_mem_node->base, - p_mem_node->length); - - p_mem_node->next = func->p_mem_head; - func->p_mem_head = p_mem_node; - } else { - mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; - mem_node->length = base; - dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", - res_type_str, - mem_node->base, - mem_node->length); - - mem_node->next = func->mem_head; - func->mem_head = mem_node; - } - cloop += 4; - break; - default: - dbg("asur: reserved BAR type=0x%x\n", - temp_register); - break; - } - } - } /* End of base register loop */ - } else { /* Some other unknown header type */ - dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", - func->bus, func->device); - } - - /* find the next device in this slot */ - if (!disable) - break; - func = pciehp_slot_find(func->bus, func->device, index++); - } - - return 0; -} - - -/** - * kfree_resource_list: release memory of all list members - * @res: resource list to free - */ -static inline void -return_resource_list(struct pci_resource **func, struct pci_resource **res) -{ - struct pci_resource *node; - struct pci_resource *t_node; - - node = *func; - *func = NULL; - while (node) { - t_node = node->next; - return_resource(res, node); - node = t_node; - } -} - -/* - * pciehp_return_board_resources - * - * this routine returns all resources allocated to a board to - * the available pool. - * - * returns 0 if success - */ -int pciehp_return_board_resources(struct pci_func * func, - struct resource_lists * resources) -{ - int rc; - - dbg("%s\n", __FUNCTION__); - - if (!func) - return 1; - - return_resource_list(&(func->io_head),&(resources->io_head)); - return_resource_list(&(func->mem_head),&(resources->mem_head)); - return_resource_list(&(func->p_mem_head),&(resources->p_mem_head)); - return_resource_list(&(func->bus_head),&(resources->bus_head)); - - rc = pciehp_resource_sort_and_combine(&(resources->mem_head)); - rc |= pciehp_resource_sort_and_combine(&(resources->p_mem_head)); - rc |= pciehp_resource_sort_and_combine(&(resources->io_head)); - rc |= pciehp_resource_sort_and_combine(&(resources->bus_head)); - - return rc; -} - -/** - * kfree_resource_list: release memory of all list members - * @res: resource list to free - */ -static inline void -kfree_resource_list(struct pci_resource **r) -{ - struct pci_resource *res, *tres; - - res = *r; - *r = NULL; - - while (res) { - tres = res; - res = res->next; - kfree(tres); - } -} - -/** - * pciehp_destroy_resource_list: put node back in the resource list - * @resources: list to put nodes back - */ -void pciehp_destroy_resource_list(struct resource_lists * resources) -{ - kfree_resource_list(&(resources->io_head)); - kfree_resource_list(&(resources->mem_head)); - kfree_resource_list(&(resources->p_mem_head)); - kfree_resource_list(&(resources->bus_head)); -} - -/** - * pciehp_destroy_board_resources: put node back in the resource list - * @resources: list to put nodes back - */ -void pciehp_destroy_board_resources(struct pci_func * func) -{ - kfree_resource_list(&(func->io_head)); - kfree_resource_list(&(func->mem_head)); - kfree_resource_list(&(func->p_mem_head)); - kfree_resource_list(&(func->bus_head)); -} diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c index 1406db35b08..078550ba270 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/pciehprm_acpi.c @@ -35,9 +35,6 @@ #include #include #include -#ifdef CONFIG_IA64 -#include -#endif #include #include #include @@ -84,10 +81,6 @@ struct acpi_php_slot { int dev; int fun; u32 sun; - struct pci_resource *mem_head; - struct pci_resource *p_mem_head; - struct pci_resource *io_head; - struct pci_resource *bus_head; void *slot_ops; /* _STA, _EJx, etc */ struct slot *slot; }; /* per func */ @@ -104,14 +97,6 @@ struct acpi_bridge { int bus; /* pdev->subordinate->number */ struct acpi__hpp *_hpp; struct acpi_php_slot *slots; - struct pci_resource *tmem_head; /* total from crs */ - struct pci_resource *tp_mem_head; /* total from crs */ - struct pci_resource *tio_head; /* total from crs */ - struct pci_resource *tbus_head; /* total from crs */ - struct pci_resource *mem_head; /* available */ - struct pci_resource *p_mem_head; /* available */ - struct pci_resource *io_head; /* available */ - struct pci_resource *bus_head; /* available */ int scanned; int type; }; @@ -268,485 +253,6 @@ static int acpi_run_oshp ( struct acpi_bridge *ab) return oshp_run_status; } -static acpi_status acpi_evaluate_crs( - acpi_handle handle, - struct acpi_resource **retbuf - ) -{ - acpi_status status; - struct acpi_buffer crsbuf; - u8 *path_name = acpi_path_name(handle); - - crsbuf.length = 0; - crsbuf.pointer = NULL; - - status = acpi_get_current_resources (handle, &crsbuf); - - switch (status) { - case AE_BUFFER_OVERFLOW: - break; /* found */ - case AE_NOT_FOUND: - dbg("acpi_pciehprm:%s _CRS not found\n", path_name); - return status; - default: - err ("acpi_pciehprm:%s _CRS fail=0x%x\n", path_name, status); - return status; - } - - crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL); - if (!crsbuf.pointer) { - err ("acpi_pciehprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name); - return AE_NO_MEMORY; - } - - status = acpi_get_current_resources (handle, &crsbuf); - if (ACPI_FAILURE(status)) { - err("acpi_pciehprm: %s _CRS fail=0x%x.\n", path_name, status); - kfree(crsbuf.pointer); - return status; - } - - *retbuf = crsbuf.pointer; - - return status; -} - -static void free_pci_resource ( struct pci_resource *aprh) -{ - struct pci_resource *res, *next; - - for (res = aprh; res; res = next) { - next = res->next; - kfree(res); - } -} - -static void print_pci_resource ( struct pci_resource *aprh) -{ - struct pci_resource *res; - - for (res = aprh; res; res = res->next) - dbg(" base= 0x%x length= 0x%x\n", res->base, res->length); -} - -static void print_slot_resources( struct acpi_php_slot *aps) -{ - if (aps->bus_head) { - dbg(" BUS Resources:\n"); - print_pci_resource (aps->bus_head); - } - - if (aps->io_head) { - dbg(" IO Resources:\n"); - print_pci_resource (aps->io_head); - } - - if (aps->mem_head) { - dbg(" MEM Resources:\n"); - print_pci_resource (aps->mem_head); - } - - if (aps->p_mem_head) { - dbg(" PMEM Resources:\n"); - print_pci_resource (aps->p_mem_head); - } -} - -static void print_pci_resources( struct acpi_bridge *ab) -{ - if (ab->tbus_head) { - dbg(" Total BUS Resources:\n"); - print_pci_resource (ab->tbus_head); - } - if (ab->bus_head) { - dbg(" BUS Resources:\n"); - print_pci_resource (ab->bus_head); - } - - if (ab->tio_head) { - dbg(" Total IO Resources:\n"); - print_pci_resource (ab->tio_head); - } - if (ab->io_head) { - dbg(" IO Resources:\n"); - print_pci_resource (ab->io_head); - } - - if (ab->tmem_head) { - dbg(" Total MEM Resources:\n"); - print_pci_resource (ab->tmem_head); - } - if (ab->mem_head) { - dbg(" MEM Resources:\n"); - print_pci_resource (ab->mem_head); - } - - if (ab->tp_mem_head) { - dbg(" Total PMEM Resources:\n"); - print_pci_resource (ab->tp_mem_head); - } - if (ab->p_mem_head) { - dbg(" PMEM Resources:\n"); - print_pci_resource (ab->p_mem_head); - } - if (ab->_hpp) { - dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size); - dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer); - dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr); - dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr); - } -} - -static int pciehprm_delete_resource( - struct pci_resource **aprh, - ulong base, - ulong size) -{ - struct pci_resource *res; - struct pci_resource *prevnode; - struct pci_resource *split_node; - ulong tbase; - - pciehp_resource_sort_and_combine(aprh); - - for (res = *aprh; res; res = res->next) { - if (res->base > base) - continue; - - if ((res->base + res->length) < (base + size)) - continue; - - if (res->base < base) { - tbase = base; - - if ((res->length - (tbase - res->base)) < size) - continue; - - split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - if (!split_node) - return -ENOMEM; - - split_node->base = res->base; - split_node->length = tbase - res->base; - res->base = tbase; - res->length -= split_node->length; - - split_node->next = res->next; - res->next = split_node; - } - - if (res->length >= size) { - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - if (!split_node) - return -ENOMEM; - - split_node->base = res->base + size; - split_node->length = res->length - size; - res->length = size; - - split_node->next = res->next; - res->next = split_node; - } - - if (*aprh == res) { - *aprh = res->next; - } else { - prevnode = *aprh; - while (prevnode->next != res) - prevnode = prevnode->next; - - prevnode->next = res->next; - } - res->next = NULL; - kfree(res); - break; - } - - return 0; -} - -static int pciehprm_delete_resources( - struct pci_resource **aprh, - struct pci_resource *this - ) -{ - struct pci_resource *res; - - for (res = this; res; res = res->next) - pciehprm_delete_resource(aprh, res->base, res->length); - - return 0; -} - -static int pciehprm_add_resource( - struct pci_resource **aprh, - ulong base, - ulong size) -{ - struct pci_resource *res; - - for (res = *aprh; res; res = res->next) { - if ((res->base + res->length) == base) { - res->length += size; - size = 0L; - break; - } - if (res->next == *aprh) - break; - } - - if (size) { - res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - if (!res) { - err ("acpi_pciehprm: alloc for res fail\n"); - return -ENOMEM; - } - memset(res, 0, sizeof (struct pci_resource)); - - res->base = base; - res->length = size; - res->next = *aprh; - *aprh = res; - } - - return 0; -} - -static int pciehprm_add_resources( - struct pci_resource **aprh, - struct pci_resource *this - ) -{ - struct pci_resource *res; - int rc = 0; - - for (res = this; res && !rc; res = res->next) - rc = pciehprm_add_resource(aprh, res->base, res->length); - - return rc; -} - -static void acpi_parse_io ( - struct acpi_bridge *ab, - union acpi_resource_data *data - ) -{ - struct acpi_resource_io *dataio; - dataio = (struct acpi_resource_io *) data; - - dbg("Io Resource\n"); - dbg(" %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10); - dbg(" Range minimum base: %08X\n", dataio->min_base_address); - dbg(" Range maximum base: %08X\n", dataio->max_base_address); - dbg(" Alignment: %08X\n", dataio->alignment); - dbg(" Range Length: %08X\n", dataio->range_length); -} - -static void acpi_parse_fixed_io ( - struct acpi_bridge *ab, - union acpi_resource_data *data - ) -{ - struct acpi_resource_fixed_io *datafio; - datafio = (struct acpi_resource_fixed_io *) data; - - dbg("Fixed Io Resource\n"); - dbg(" Range base address: %08X", datafio->base_address); - dbg(" Range length: %08X", datafio->range_length); -} - -static void acpi_parse_address16_32 ( - struct acpi_bridge *ab, - union acpi_resource_data *data, - acpi_resource_type id - ) -{ - /* - * acpi_resource_address16 == acpi_resource_address32 - * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data; - */ - struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data; - struct pci_resource **aprh, **tprh; - - if (id == ACPI_RSTYPE_ADDRESS16) - dbg("acpi_pciehprm:16-Bit Address Space Resource\n"); - else - dbg("acpi_pciehprm:32-Bit Address Space Resource\n"); - - switch (data32->resource_type) { - case ACPI_MEMORY_RANGE: - dbg(" Resource Type: Memory Range\n"); - aprh = &ab->mem_head; - tprh = &ab->tmem_head; - - switch (data32->attribute.memory.cache_attribute) { - case ACPI_NON_CACHEABLE_MEMORY: - dbg(" Type Specific: Noncacheable memory\n"); - break; - case ACPI_CACHABLE_MEMORY: - dbg(" Type Specific: Cacheable memory\n"); - break; - case ACPI_WRITE_COMBINING_MEMORY: - dbg(" Type Specific: Write-combining memory\n"); - break; - case ACPI_PREFETCHABLE_MEMORY: - aprh = &ab->p_mem_head; - dbg(" Type Specific: Prefetchable memory\n"); - break; - default: - dbg(" Type Specific: Invalid cache attribute\n"); - break; - } - - dbg(" Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only"); - break; - - case ACPI_IO_RANGE: - dbg(" Resource Type: I/O Range\n"); - aprh = &ab->io_head; - tprh = &ab->tio_head; - - switch (data32->attribute.io.range_attribute) { - case ACPI_NON_ISA_ONLY_RANGES: - dbg(" Type Specific: Non-ISA Io Addresses\n"); - break; - case ACPI_ISA_ONLY_RANGES: - dbg(" Type Specific: ISA Io Addresses\n"); - break; - case ACPI_ENTIRE_RANGE: - dbg(" Type Specific: ISA and non-ISA Io Addresses\n"); - break; - default: - dbg(" Type Specific: Invalid range attribute\n"); - break; - } - break; - - case ACPI_BUS_NUMBER_RANGE: - dbg(" Resource Type: Bus Number Range(fixed)\n"); - /* fixup to be compatible with the rest of php driver */ - data32->min_address_range++; - data32->address_length--; - aprh = &ab->bus_head; - tprh = &ab->tbus_head; - break; - default: - dbg(" Resource Type: Invalid resource type. Exiting.\n"); - return; - } - - dbg(" Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer"); - dbg(" %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive"); - dbg(" Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not"); - dbg(" Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not"); - dbg(" Granularity: %08X\n", data32->granularity); - dbg(" Address range min: %08X\n", data32->min_address_range); - dbg(" Address range max: %08X\n", data32->max_address_range); - dbg(" Address translation offset: %08X\n", data32->address_translation_offset); - dbg(" Address Length: %08X\n", data32->address_length); - - if (0xFF != data32->resource_source.index) { - dbg(" Resource Source Index: %X\n", data32->resource_source.index); - /* dbg(" Resource Source: %s\n", data32->resource_source.string_ptr); */ - } - - pciehprm_add_resource(aprh, data32->min_address_range, data32->address_length); -} - -static acpi_status acpi_parse_crs( - struct acpi_bridge *ab, - struct acpi_resource *crsbuf - ) -{ - acpi_status status = AE_OK; - struct acpi_resource *resource = crsbuf; - u8 count = 0; - u8 done = 0; - - while (!done) { - dbg("acpi_pciehprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++); - switch (resource->id) { - case ACPI_RSTYPE_IRQ: - dbg("Irq -------- Resource\n"); - break; - case ACPI_RSTYPE_DMA: - dbg("DMA -------- Resource\n"); - break; - case ACPI_RSTYPE_START_DPF: - dbg("Start DPF -------- Resource\n"); - break; - case ACPI_RSTYPE_END_DPF: - dbg("End DPF -------- Resource\n"); - break; - case ACPI_RSTYPE_IO: - acpi_parse_io (ab, &resource->data); - break; - case ACPI_RSTYPE_FIXED_IO: - acpi_parse_fixed_io (ab, &resource->data); - break; - case ACPI_RSTYPE_VENDOR: - dbg("Vendor -------- Resource\n"); - break; - case ACPI_RSTYPE_END_TAG: - dbg("End_tag -------- Resource\n"); - done = 1; - break; - case ACPI_RSTYPE_MEM24: - dbg("Mem24 -------- Resource\n"); - break; - case ACPI_RSTYPE_MEM32: - dbg("Mem32 -------- Resource\n"); - break; - case ACPI_RSTYPE_FIXED_MEM32: - dbg("Fixed Mem32 -------- Resource\n"); - break; - case ACPI_RSTYPE_ADDRESS16: - acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16); - break; - case ACPI_RSTYPE_ADDRESS32: - acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32); - break; - case ACPI_RSTYPE_ADDRESS64: - info("Address64 -------- Resource unparsed\n"); - break; - case ACPI_RSTYPE_EXT_IRQ: - dbg("Ext Irq -------- Resource\n"); - break; - default: - dbg("Invalid -------- resource type 0x%x\n", resource->id); - break; - } - - resource = (struct acpi_resource *) ((char *)resource + resource->length); - } - - return status; -} - -static acpi_status acpi_get_crs( struct acpi_bridge *ab) -{ - acpi_status status; - struct acpi_resource *crsbuf; - - status = acpi_evaluate_crs(ab->handle, &crsbuf); - if (ACPI_SUCCESS(status)) { - status = acpi_parse_crs(ab, crsbuf); - kfree(crsbuf); - - pciehp_resource_sort_and_combine(&ab->bus_head); - pciehp_resource_sort_and_combine(&ab->io_head); - pciehp_resource_sort_and_combine(&ab->mem_head); - pciehp_resource_sort_and_combine(&ab->p_mem_head); - - pciehprm_add_resources (&ab->tbus_head, ab->bus_head); - pciehprm_add_resources (&ab->tio_head, ab->io_head); - pciehprm_add_resources (&ab->tmem_head, ab->mem_head); - pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head); - } - - return status; -} - /* find acpi_bridge downword from ab. */ static struct acpi_bridge * find_acpi_bridge_by_bus( @@ -1064,14 +570,6 @@ static struct acpi_bridge * add_host_bridge( ab->scanned = 0; ab->type = BRIDGE_TYPE_HOST; - /* get root pci bridge's current resources */ - status = acpi_get_crs(ab); - if (ACPI_FAILURE(status)) { - err("acpi_pciehprm:%s evaluate _CRS fail=0x%x\n", path_name, status); - kfree(ab); - return NULL; - } - status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); if (ACPI_FAILURE(status)) { err("%s: status %x\n", __FUNCTION__, status); @@ -1179,11 +677,6 @@ static void free_a_slot(struct acpi_php_slot *aps) { dbg(" free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun); - free_pci_resource (aps->io_head); - free_pci_resource (aps->bus_head); - free_pci_resource (aps->mem_head); - free_pci_resource (aps->p_mem_head); - kfree(aps); } @@ -1208,15 +701,6 @@ static void free_a_bridge( struct acpi_bridge *ab) free_a_slot(aps); } - free_pci_resource (ab->io_head); - free_pci_resource (ab->tio_head); - free_pci_resource (ab->bus_head); - free_pci_resource (ab->tbus_head); - free_pci_resource (ab->mem_head); - free_pci_resource (ab->tmem_head); - free_pci_resource (ab->p_mem_head); - free_pci_resource (ab->tp_mem_head); - kfree(ab); } @@ -1266,48 +750,6 @@ static int get_number_of_slots ( return slot_num; } -static int print_acpi_resources (struct acpi_bridge *ab) -{ - struct acpi_php_slot *aps; - int i; - - switch (ab->type) { - case BRIDGE_TYPE_HOST: - dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle)); - break; - case BRIDGE_TYPE_P2P: - dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle)); - break; - }; - - print_pci_resources (ab); - - for ( i = -1, aps = ab->slots; aps; aps = aps->next) { - if (aps->dev == i) - continue; - dbg(" Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun); - print_slot_resources(aps); - i = aps->dev; - } - - if (ab->child) - print_acpi_resources (ab->child); - - if (ab->next) - print_acpi_resources (ab->next); - - return 0; -} - -int pciehprm_print_pirt(void) -{ - dbg("PCIEHPRM ACPI Slots\n"); - if (acpi_bridges_head) - print_acpi_resources (acpi_bridges_head); - - return 0; -} - static struct acpi_php_slot * get_acpi_slot ( struct acpi_bridge *ab, u32 sun @@ -1349,288 +791,6 @@ void * pciehprm_get_slot(struct slot *slot) } #endif -static void pciehprm_dump_func_res( struct pci_func *fun) -{ - struct pci_func *func = fun; - - if (func->bus_head) { - dbg(": BUS Resources:\n"); - print_pci_resource (func->bus_head); - } - if (func->io_head) { - dbg(": IO Resources:\n"); - print_pci_resource (func->io_head); - } - if (func->mem_head) { - dbg(": MEM Resources:\n"); - print_pci_resource (func->mem_head); - } - if (func->p_mem_head) { - dbg(": PMEM Resources:\n"); - print_pci_resource (func->p_mem_head); - } -} - -static void pciehprm_dump_ctrl_res( struct controller *ctlr) -{ - struct controller *ctrl = ctlr; - - if (ctrl->bus_head) { - dbg(": BUS Resources:\n"); - print_pci_resource (ctrl->bus_head); - } - if (ctrl->io_head) { - dbg(": IO Resources:\n"); - print_pci_resource (ctrl->io_head); - } - if (ctrl->mem_head) { - dbg(": MEM Resources:\n"); - print_pci_resource (ctrl->mem_head); - } - if (ctrl->p_mem_head) { - dbg(": PMEM Resources:\n"); - print_pci_resource (ctrl->p_mem_head); - } -} - -static int pciehprm_get_used_resources ( - struct controller *ctrl, - struct pci_func *func - ) -{ - return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD); -} - -static int configure_existing_function( - struct controller *ctrl, - struct pci_func *func - ) -{ - int rc; - - /* see how much resources the func has used. */ - rc = pciehprm_get_used_resources (ctrl, func); - - if (!rc) { - /* subtract the resources used by the func from ctrl resources */ - rc = pciehprm_delete_resources (&ctrl->bus_head, func->bus_head); - rc |= pciehprm_delete_resources (&ctrl->io_head, func->io_head); - rc |= pciehprm_delete_resources (&ctrl->mem_head, func->mem_head); - rc |= pciehprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head); - if (rc) - warn("aCEF: cannot del used resources\n"); - } else - err("aCEF: cannot get used resources\n"); - - return rc; -} - -static int bind_pci_resources_to_slots ( struct controller *ctrl) -{ - struct pci_func *func, new_func; - int busn = ctrl->slot_bus; - int devn, funn; - u32 vid; - - for (devn = 0; devn < 32; devn++) { - for (funn = 0; funn < 8; funn++) { - /* - if (devn == ctrl->device && funn == ctrl->function) - continue; - */ - /* find out if this entry is for an occupied slot */ - vid = 0xFFFFFFFF; - pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); - - if (vid != 0xFFFFFFFF) { - dbg("%s: vid = %x\n", __FUNCTION__, vid); - func = pciehp_slot_find(busn, devn, funn); - 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); - } - } - } - - return 0; -} - -static int bind_pci_resources( - struct controller *ctrl, - struct acpi_bridge *ab - ) -{ - int status = 0; - - if (ab->bus_head) { - dbg("bapr: BUS Resources add on PCI 0x%x\n", ab->bus); - status = pciehprm_add_resources (&ctrl->bus_head, ab->bus_head); - if (pciehprm_delete_resources (&ab->bus_head, ctrl->bus_head)) - warn("bapr: cannot sub BUS Resource on PCI 0x%x\n", ab->bus); - if (status) { - err("bapr: BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); - return status; - } - } else - info("bapr: No BUS Resource on PCI 0x%x.\n", ab->bus); - - if (ab->io_head) { - dbg("bapr: IO Resources add on PCI 0x%x\n", ab->bus); - status = pciehprm_add_resources (&ctrl->io_head, ab->io_head); - if (pciehprm_delete_resources (&ab->io_head, ctrl->io_head)) - warn("bapr: cannot sub IO Resource on PCI 0x%x\n", ab->bus); - if (status) { - err("bapr: IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); - return status; - } - } else - info("bapr: No IO Resource on PCI 0x%x.\n", ab->bus); - - if (ab->mem_head) { - dbg("bapr: MEM Resources add on PCI 0x%x\n", ab->bus); - status = pciehprm_add_resources (&ctrl->mem_head, ab->mem_head); - if (pciehprm_delete_resources (&ab->mem_head, ctrl->mem_head)) - warn("bapr: cannot sub MEM Resource on PCI 0x%x\n", ab->bus); - if (status) { - err("bapr: MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); - return status; - } - } else - info("bapr: No MEM Resource on PCI 0x%x.\n", ab->bus); - - if (ab->p_mem_head) { - dbg("bapr: PMEM Resources add on PCI 0x%x\n", ab->bus); - status = pciehprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head); - if (pciehprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head)) - warn("bapr: cannot sub PMEM Resource on PCI 0x%x\n", ab->bus); - if (status) { - err("bapr: PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); - return status; - } - } else - info("bapr: No PMEM Resource on PCI 0x%x.\n", ab->bus); - - return status; -} - -static int no_pci_resources( struct acpi_bridge *ab) -{ - return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head); -} - -static int find_pci_bridge_resources ( - struct controller *ctrl, - struct acpi_bridge *ab - ) -{ - int rc = 0; - struct pci_func func; - - memset(&func, 0, sizeof(struct pci_func)); - - func.bus = ab->pbus; - func.device = ab->pdevice; - func.function = ab->pfunction; - func.is_a_board = 1; - - /* Get used resources for this PCI bridge */ - rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD); - - ab->io_head = func.io_head; - ab->mem_head = func.mem_head; - ab->p_mem_head = func.p_mem_head; - ab->bus_head = func.bus_head; - if (ab->bus_head) - pciehprm_delete_resource(&ab->bus_head, ctrl->pci_dev->subordinate->number, 1); - - return rc; -} - -static int get_pci_resources_from_bridge( - struct controller *ctrl, - struct acpi_bridge *ab - ) -{ - int rc = 0; - - dbg("grfb: Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus); - - rc = find_pci_bridge_resources (ctrl, ab); - - pciehp_resource_sort_and_combine(&ab->bus_head); - pciehp_resource_sort_and_combine(&ab->io_head); - pciehp_resource_sort_and_combine(&ab->mem_head); - pciehp_resource_sort_and_combine(&ab->p_mem_head); - - pciehprm_add_resources (&ab->tbus_head, ab->bus_head); - pciehprm_add_resources (&ab->tio_head, ab->io_head); - pciehprm_add_resources (&ab->tmem_head, ab->mem_head); - pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head); - - return rc; -} - -static int get_pci_resources( - struct controller *ctrl, - struct acpi_bridge *ab - ) -{ - int rc = 0; - - if (no_pci_resources(ab)) { - dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus); - rc = get_pci_resources_from_bridge(ctrl, ab); - } - - return rc; -} - -/* - * Get resources for this ctrl. - * 1. get total resources from ACPI _CRS or bridge (this ctrl) - * 2. find used resources of existing adapters - * 3. subtract used resources from total resources - */ -int pciehprm_find_available_resources( struct controller *ctrl) -{ - int rc = 0; - struct acpi_bridge *ab; - - ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number); - if (!ab) { - err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number); - return -1; - } - if (no_pci_resources(ab)) { - rc = get_pci_resources(ctrl, ab); - if (rc) { - err("pfar:cannot get pci resources of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number); - return -1; - } - } - - rc = bind_pci_resources(ctrl, ab); - dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number); - pciehprm_dump_ctrl_res(ctrl); - - bind_pci_resources_to_slots (ctrl); - - dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number); - pciehprm_dump_ctrl_res(ctrl); - - return rc; -} - int pciehprm_set_hpp( struct controller *ctrl, struct pci_func *func, diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c index 76c727c74cc..ed68c3dd0f0 100644 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c @@ -35,12 +35,7 @@ #include #include #include - #include -#ifdef CONFIG_IA64 -#include -#endif - #include "pciehp.h" #include "pciehprm.h" #include "pciehprm_nonacpi.h" @@ -51,11 +46,6 @@ void pciehprm_cleanup(void) return; } -int pciehprm_print_pirt(void) -{ - return 0; -} - int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) { @@ -63,343 +53,6 @@ int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn return 0; } - -static void print_pci_resource ( struct pci_resource *aprh) -{ - struct pci_resource *res; - - for (res = aprh; res; res = res->next) - dbg(" base= 0x%x length= 0x%x\n", res->base, res->length); -} - - -static void phprm_dump_func_res( struct pci_func *fun) -{ - struct pci_func *func = fun; - - if (func->bus_head) { - dbg(": BUS Resources:\n"); - print_pci_resource (func->bus_head); - } - if (func->io_head) { - dbg(": IO Resources:\n"); - print_pci_resource (func->io_head); - } - if (func->mem_head) { - dbg(": MEM Resources:\n"); - print_pci_resource (func->mem_head); - } - if (func->p_mem_head) { - dbg(": PMEM Resources:\n"); - print_pci_resource (func->p_mem_head); - } -} - -static int phprm_get_used_resources ( - struct controller *ctrl, - struct pci_func *func - ) -{ - return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD); -} - -static int phprm_delete_resource( - struct pci_resource **aprh, - ulong base, - ulong size) -{ - struct pci_resource *res; - struct pci_resource *prevnode; - struct pci_resource *split_node; - ulong tbase; - - pciehp_resource_sort_and_combine(aprh); - - for (res = *aprh; res; res = res->next) { - if (res->base > base) - continue; - - if ((res->base + res->length) < (base + size)) - continue; - - if (res->base < base) { - tbase = base; - - if ((res->length - (tbase - res->base)) < size) - continue; - - split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - if (!split_node) - return -ENOMEM; - - split_node->base = res->base; - split_node->length = tbase - res->base; - res->base = tbase; - res->length -= split_node->length; - - split_node->next = res->next; - res->next = split_node; - } - - if (res->length >= size) { - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - if (!split_node) - return -ENOMEM; - - split_node->base = res->base + size; - split_node->length = res->length - size; - res->length = size; - - split_node->next = res->next; - res->next = split_node; - } - - if (*aprh == res) { - *aprh = res->next; - } else { - prevnode = *aprh; - while (prevnode->next != res) - prevnode = prevnode->next; - - prevnode->next = res->next; - } - res->next = NULL; - kfree(res); - break; - } - - return 0; -} - - -static int phprm_delete_resources( - struct pci_resource **aprh, - struct pci_resource *this - ) -{ - struct pci_resource *res; - - for (res = this; res; res = res->next) - phprm_delete_resource(aprh, res->base, res->length); - - return 0; -} - - -static int configure_existing_function( - struct controller *ctrl, - struct pci_func *func - ) -{ - int rc; - - /* see how much resources the func has used. */ - rc = phprm_get_used_resources (ctrl, func); - - if (!rc) { - /* subtract the resources used by the func from ctrl resources */ - rc = phprm_delete_resources (&ctrl->bus_head, func->bus_head); - rc |= phprm_delete_resources (&ctrl->io_head, func->io_head); - rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head); - rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head); - if (rc) - warn("aCEF: cannot del used resources\n"); - } else - err("aCEF: cannot get used resources\n"); - - return rc; -} - -static int pciehprm_delete_resource( - struct pci_resource **aprh, - ulong base, - ulong size) -{ - struct pci_resource *res; - struct pci_resource *prevnode; - struct pci_resource *split_node; - ulong tbase; - - pciehp_resource_sort_and_combine(aprh); - - for (res = *aprh; res; res = res->next) { - if (res->base > base) - continue; - - if ((res->base + res->length) < (base + size)) - continue; - - if (res->base < base) { - tbase = base; - - if ((res->length - (tbase - res->base)) < size) - continue; - - split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - if (!split_node) - return -ENOMEM; - - split_node->base = res->base; - split_node->length = tbase - res->base; - res->base = tbase; - res->length -= split_node->length; - - split_node->next = res->next; - res->next = split_node; - } - - if (res->length >= size) { - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - if (!split_node) - return -ENOMEM; - - split_node->base = res->base + size; - split_node->length = res->length - size; - res->length = size; - - split_node->next = res->next; - res->next = split_node; - } - - if (*aprh == res) { - *aprh = res->next; - } else { - prevnode = *aprh; - while (prevnode->next != res) - prevnode = prevnode->next; - - prevnode->next = res->next; - } - res->next = NULL; - kfree(res); - break; - } - - return 0; -} - -static int bind_pci_resources_to_slots ( struct controller *ctrl) -{ - struct pci_func *func, new_func; - int busn = ctrl->slot_bus; - int devn, funn; - u32 vid; - - for (devn = 0; devn < 32; devn++) { - for (funn = 0; funn < 8; funn++) { - /* - if (devn == ctrl->device && funn == ctrl->function) - continue; - */ - /* find out if this entry is for an occupied slot */ - vid = 0xFFFFFFFF; - - pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); - - if (vid != 0xFFFFFFFF) { - dbg("%s: vid = %x bus %x dev %x fun %x\n", __FUNCTION__, - vid, busn, devn, funn); - func = pciehp_slot_find(busn, devn, funn); - dbg("%s: func = %p\n", __FUNCTION__,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); - } - } - } - - return 0; -} - -static void phprm_dump_ctrl_res( struct controller *ctlr) -{ - struct controller *ctrl = ctlr; - - if (ctrl->bus_head) { - dbg(": BUS Resources:\n"); - print_pci_resource (ctrl->bus_head); - } - if (ctrl->io_head) { - dbg(": IO Resources:\n"); - print_pci_resource (ctrl->io_head); - } - if (ctrl->mem_head) { - dbg(": MEM Resources:\n"); - print_pci_resource (ctrl->mem_head); - } - if (ctrl->p_mem_head) { - dbg(": PMEM Resources:\n"); - print_pci_resource (ctrl->p_mem_head); - } -} - -/* - * phprm_find_available_resources - * - * Finds available memory, IO, and IRQ resources for programming - * devices which may be added to the system - * this function is for hot plug ADD! - * - * returns 0 if success - */ -int pciehprm_find_available_resources(struct controller *ctrl) -{ - struct pci_func func; - u32 rc; - - memset(&func, 0, sizeof(struct pci_func)); - - func.bus = ctrl->bus; - func.device = ctrl->device; - func.function = ctrl->function; - func.is_a_board = 1; - - /* Get resources for this PCI bridge */ - rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD); - dbg("%s: pciehp_save_used_resources rc = %d\n", __FUNCTION__, rc); - - if (func.mem_head) - func.mem_head->next = ctrl->mem_head; - ctrl->mem_head = func.mem_head; - - if (func.p_mem_head) - func.p_mem_head->next = ctrl->p_mem_head; - ctrl->p_mem_head = func.p_mem_head; - - if (func.io_head) - func.io_head->next = ctrl->io_head; - ctrl->io_head = func.io_head; - - if(func.bus_head) - func.bus_head->next = ctrl->bus_head; - ctrl->bus_head = func.bus_head; - - if (ctrl->bus_head) - pciehprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1); - - dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus); - phprm_dump_ctrl_res(ctrl); - - dbg("%s: before bind_pci_resources_to slots\n", __FUNCTION__); - - bind_pci_resources_to_slots (ctrl); - - dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus); - phprm_dump_ctrl_res(ctrl); - - return (rc); -} - int pciehprm_set_hpp( struct controller *ctrl, struct pci_func *func, -- cgit v1.2.3 From a8a2be949267cb0d1d933a92d9fb43eda4f4fe88 Mon Sep 17 00:00:00 2001 From: "rajesh.shah@intel.com" Date: Mon, 31 Oct 2005 16:20:07 -0800 Subject: [PATCH] pciehp: reduce dependence on ACPI Reduce the PCI Express hotplug driver's dependence on ACPI. We don't walk the acpi namespace anymore to build a list of bridges and devices. We go to ACPI only to run the _OSC or _OSHP methods to transition control of hotplug hardware from system BIOS to the hotplug driver, and to run the _HPP method to get hotplug device parameters like cache line size, latency timer and SERR/PERR enable from BIOS. Note that one of the side effects of this patch is that pciehp does not automatically enable the hot-added device or its DMA bus mastering capability now. It expects the device driver to do that. This may break some drivers and we will have to fix them as they are reported. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 11 + drivers/pci/hotplug/pciehp_core.c | 20 +- drivers/pci/hotplug/pciehp_ctrl.c | 1 - drivers/pci/hotplug/pciehp_hpc.c | 4 + drivers/pci/hotplug/pciehprm.h | 52 -- drivers/pci/hotplug/pciehprm_acpi.c | 838 +++------------------------------ drivers/pci/hotplug/pciehprm_nonacpi.c | 107 +---- drivers/pci/hotplug/pciehprm_nonacpi.h | 56 --- 8 files changed, 96 insertions(+), 993 deletions(-) delete mode 100644 drivers/pci/hotplug/pciehprm.h delete mode 100644 drivers/pci/hotplug/pciehprm_nonacpi.h (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e9480ddd5ab..e9c09566f85 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -49,6 +49,13 @@ extern int pciehp_debug; #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) +struct hotplug_params { + u8 cache_line_size; + u8 latency_timer; + u8 enable_serr; + u8 enable_perr; +}; + struct pci_func { struct pci_func *next; u8 bus; @@ -199,6 +206,10 @@ extern int pciehp_save_config (struct controller *ctrl, int busnumber, int num extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot); extern int pciehp_configure_device (struct slot *ctrl); extern int pciehp_unconfigure_device (struct pci_func* func); +extern int get_hp_hw_control_from_firmware(struct pci_dev *dev); +extern void get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp); + /* Global variables */ diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 190664e5adf..e20cf8e42bd 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -39,7 +39,6 @@ #include #include #include "pciehp.h" -#include "pciehprm.h" #include /* Global variables */ @@ -381,6 +380,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid); pdev = dev->port; + ctrl->pci_dev = pdev; rc = pcie_init(ctrl, dev, (php_intr_callback_t) pciehp_handle_attention_button, @@ -392,8 +392,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ goto err_out_free_ctrl; } - ctrl->pci_dev = pdev; - pci_set_drvdata(pdev, ctrl); ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); @@ -609,18 +607,14 @@ static int __init pcied_init(void) if (retval) goto error_hpc_init; - retval = pciehprm_init(PCI); - if (!retval) { - retval = pcie_port_service_register(&hpdriver_portdrv); - dbg("pcie_port_service_register = %d\n", retval); - info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - if (retval) - dbg("%s: Failure to register service\n", __FUNCTION__); - } + retval = pcie_port_service_register(&hpdriver_portdrv); + dbg("pcie_port_service_register = %d\n", retval); + info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + if (retval) + dbg("%s: Failure to register service\n", __FUNCTION__); error_hpc_init: if (retval) { - pciehprm_cleanup(); pciehp_event_stop_thread(); }; @@ -632,8 +626,6 @@ static void __exit pcied_cleanup(void) dbg("unload_pciehpd()\n"); unload_pciehpd(); - pciehprm_cleanup(); - dbg("pcie_port_service_unregister\n"); pcie_port_service_unregister(&hpdriver_portdrv); diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 412783e0ef4..d07d4194bc2 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -40,7 +40,6 @@ #include #include "../pci.h" #include "pciehp.h" -#include "pciehprm.h" static void interrupt_event_handler(struct controller *ctrl); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 7a0e27f0e06..ef79ca1f38d 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1470,6 +1470,10 @@ int pcie_init(struct controller * ctrl, } dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word); + rc = get_hp_hw_control_from_firmware(ctrl->pci_dev); + if (rc) + goto abort_free_ctlr; + /* Add this HPC instance into the HPC list */ spin_lock(&list_lock); if (php_ctlr_list_head == 0) { diff --git a/drivers/pci/hotplug/pciehprm.h b/drivers/pci/hotplug/pciehprm.h deleted file mode 100644 index 05f20fbc5f5..00000000000 --- a/drivers/pci/hotplug/pciehprm.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * PCIEHPRM : PCIEHP Resource Manager for ACPI/non-ACPI platform - * - * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2001 IBM Corp. - * Copyright (C) 2003-2004 Intel Corporation - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Send feedback to , - * - */ - -#ifndef _PCIEHPRM_H_ -#define _PCIEHPRM_H_ - -#ifdef CONFIG_HOTPLUG_PCI_PCIE_PHPRM_NONACPI -#include "pciehprm_nonacpi.h" -#endif - -int pciehprm_init(enum php_ctlr_type ct); -void pciehprm_cleanup(void); -int pciehprm_print_pirt(void); -int pciehprm_find_available_resources(struct controller *ctrl); -int pciehprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type); -void pciehprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type); - -#ifdef DEBUG -#define RES_CHECK(this, bits) \ - { if (((this) & (bits - 1))) \ - printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); } -#else -#define RES_CHECK(this, bits) -#endif - -#endif /* _PCIEHPRM_H_ */ diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c index 078550ba270..c823cfa42ee 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/pciehprm_acpi.c @@ -39,70 +39,11 @@ #include #include #include "pciehp.h" -#include "pciehprm.h" - -#define PCI_MAX_BUS 0x100 -#define ACPI_STA_DEVICE_PRESENT 0x01 #define METHOD_NAME__SUN "_SUN" #define METHOD_NAME__HPP "_HPP" #define METHOD_NAME_OSHP "OSHP" -/* Status code for running acpi method to gain native control */ -#define NC_NOT_RUN 0 -#define OSC_NOT_EXIST 1 -#define OSC_RUN_FAILED 2 -#define OSHP_NOT_EXIST 3 -#define OSHP_RUN_FAILED 4 -#define NC_RUN_SUCCESS 5 - -#define PHP_RES_BUS 0xA0 -#define PHP_RES_IO 0xA1 -#define PHP_RES_MEM 0xA2 -#define PHP_RES_PMEM 0xA3 - -#define BRIDGE_TYPE_P2P 0x00 -#define BRIDGE_TYPE_HOST 0x01 - -/* this should go to drivers/acpi/include/ */ -struct acpi__hpp { - u8 cache_line_size; - u8 latency_timer; - u8 enable_serr; - u8 enable_perr; -}; - -struct acpi_php_slot { - struct acpi_php_slot *next; - struct acpi_bridge *bridge; - acpi_handle handle; - int seg; - int bus; - int dev; - int fun; - u32 sun; - void *slot_ops; /* _STA, _EJx, etc */ - struct slot *slot; -}; /* per func */ - -struct acpi_bridge { - struct acpi_bridge *parent; - struct acpi_bridge *next; - struct acpi_bridge *child; - acpi_handle handle; - int seg; - int pbus; /* pdev->bus->number */ - int pdevice; /* PCI_SLOT(pdev->devfn) */ - int pfunction; /* PCI_DEVFN(pdev->devfn) */ - int bus; /* pdev->subordinate->number */ - struct acpi__hpp *_hpp; - struct acpi_php_slot *slots; - int scanned; - int type; -}; - -static struct acpi_bridge *acpi_bridges_head; - static u8 * acpi_path_name( acpi_handle handle) { acpi_status status; @@ -118,85 +59,43 @@ static u8 * acpi_path_name( acpi_handle handle) return path_name; } -static void acpi_get__hpp ( struct acpi_bridge *ab); -static int acpi_run_oshp ( struct acpi_bridge *ab); -static int osc_run_status = NC_NOT_RUN; -static int oshp_run_status = NC_NOT_RUN; - -static int acpi_add_slot_to_php_slots( - struct acpi_bridge *ab, - int bus_num, - acpi_handle handle, - u32 adr, - u32 sun - ) -{ - struct acpi_php_slot *aps; - static long samesun = -1; - - aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL); - if (!aps) { - err ("acpi_pciehprm: alloc for aps fail\n"); - return -1; - } - memset(aps, 0, sizeof(struct acpi_php_slot)); - - aps->handle = handle; - aps->bus = bus_num; - aps->dev = (adr >> 16) & 0xffff; - aps->fun = adr & 0xffff; - aps->sun = sun; - - aps->next = ab->slots; /* cling to the bridge */ - aps->bridge = ab; - ab->slots = aps; - - ab->scanned += 1; - if (!ab->_hpp) - acpi_get__hpp(ab); - - if (osc_run_status == OSC_NOT_EXIST) - oshp_run_status = acpi_run_oshp(ab); - - if (sun != samesun) { - info("acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", - aps->sun, ab->seg, aps->bus, aps->dev, aps->fun); - samesun = sun; - } - return 0; -} - -static void acpi_get__hpp ( struct acpi_bridge *ab) +static acpi_status +acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) { acpi_status status; u8 nui[4]; struct acpi_buffer ret_buf = { 0, NULL}; union acpi_object *ext_obj, *package; - u8 *path_name = acpi_path_name(ab->handle); + u8 *path_name = acpi_path_name(handle); int i, len = 0; /* get _hpp */ - status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); + status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); switch (status) { case AE_BUFFER_OVERFLOW: ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); if (!ret_buf.pointer) { - err ("acpi_pciehprm:%s alloc for _HPP fail\n", path_name); - return; + err ("%s:%s alloc for _HPP fail\n", __FUNCTION__, + path_name); + return AE_NO_MEMORY; } - status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); + status = acpi_evaluate_object(handle, METHOD_NAME__HPP, + NULL, &ret_buf); if (ACPI_SUCCESS(status)) break; default: if (ACPI_FAILURE(status)) { - err("acpi_pciehprm:%s _HPP fail=0x%x\n", path_name, status); - return; + dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__, + path_name, status); + return status; } } ext_obj = (union acpi_object *) ret_buf.pointer; if (ext_obj->type != ACPI_TYPE_PACKAGE) { - err ("acpi_pciehprm:%s _HPP obj not a package\n", path_name); + err ("%s:%s _HPP obj not a package\n", __FUNCTION__, + path_name); + status = AE_ERROR; goto free_and_return; } @@ -209,689 +108,94 @@ static void acpi_get__hpp ( struct acpi_bridge *ab) nui[i] = (u8)ext_obj->integer.value; break; default: - err ("acpi_pciehprm:%s _HPP obj type incorrect\n", path_name); + err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__, + path_name); + status = AE_ERROR; goto free_and_return; } } - 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)); + hpp->cache_line_size = nui[0]; + hpp->latency_timer = nui[1]; + hpp->enable_serr = nui[2]; + hpp->enable_perr = nui[3]; - ab->_hpp->cache_line_size = nui[0]; - ab->_hpp->latency_timer = nui[1]; - ab->_hpp->enable_serr = nui[2]; - ab->_hpp->enable_perr = nui[3]; - - dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size); - dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer); - dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr); - dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr); + dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); + dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer); + dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); + dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); free_and_return: kfree(ret_buf.pointer); + return status; } -static int acpi_run_oshp ( struct acpi_bridge *ab) +static acpi_status acpi_run_oshp(acpi_handle handle) { acpi_status status; - u8 *path_name = acpi_path_name(ab->handle); + u8 *path_name = acpi_path_name(handle); /* run OSHP */ - status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL); + status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); if (ACPI_FAILURE(status)) { - err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status); - oshp_run_status = (status == AE_NOT_FOUND) ? OSHP_NOT_EXIST : OSHP_RUN_FAILED; + err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, + status); } else { - oshp_run_status = NC_RUN_SUCCESS; - dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status); - dbg("acpi_pciehprm:%s oshp_run_status =0x%x\n", path_name, oshp_run_status); - } - return oshp_run_status; -} - -/* find acpi_bridge downword from ab. */ -static struct acpi_bridge * -find_acpi_bridge_by_bus( - struct acpi_bridge *ab, - int seg, - int bus /* pdev->subordinate->number */ - ) -{ - struct acpi_bridge *lab = NULL; - - if (!ab) - return NULL; - - if ((ab->bus == bus) && (ab->seg == seg)) - return ab; - - if (ab->child) - lab = find_acpi_bridge_by_bus(ab->child, seg, bus); - - if (!lab) - if (ab->next) - lab = find_acpi_bridge_by_bus(ab->next, seg, bus); - - return lab; -} - -/* - * Build a device tree of ACPI PCI Bridges - */ -static void pciehprm_acpi_register_a_bridge ( - struct acpi_bridge **head, - struct acpi_bridge *pab, /* parent bridge to which child bridge is added */ - struct acpi_bridge *cab /* child bridge to add */ - ) -{ - struct acpi_bridge *lpab; - struct acpi_bridge *lcab; - - lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus); - if (!lpab) { - if (!(pab->type & BRIDGE_TYPE_HOST)) - warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus); - pab->next = *head; - *head = pab; - lpab = pab; + dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name); } - - if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab)) - return; - - lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus); - if (lcab) { - if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus)) - err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus); - return; - } else - lcab = cab; - - lcab->parent = lpab; - lcab->next = lpab->child; - lpab->child = lcab; + return status; } -static acpi_status pciehprm_acpi_build_php_slots_callback( - acpi_handle handle, - u32 Level, - void *context, - void **retval - ) +int get_hp_hw_control_from_firmware(struct pci_dev *dev) { - ulong bus_num; - ulong seg_num; - ulong sun, adr; - ulong padr = 0; - acpi_handle phandle = NULL; - struct acpi_bridge *pab = (struct acpi_bridge *)context; - struct acpi_bridge *lab; - acpi_status status; - u8 *path_name = acpi_path_name(handle); - - /* get _SUN */ - status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun); - switch(status) { - case AE_NOT_FOUND: - return AE_OK; - default: - if (ACPI_FAILURE(status)) { - err("acpi_pciehprm:%s _SUN fail=0x%x\n", path_name, status); - return status; - } - } - - /* get _ADR. _ADR must exist if _SUN exists */ - status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); - if (ACPI_FAILURE(status)) { - err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status); - return status; - } - - dbg("acpi_pciehprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr); - - status = acpi_get_parent(handle, &phandle); - if (ACPI_FAILURE(status)) { - err("acpi_pciehprm:%s get_parent fail=0x%x\n", path_name, status); - return (status); - } - - bus_num = pab->bus; - seg_num = pab->seg; - - if (pab->bus == bus_num) { - lab = pab; - } else { - dbg("WARN: pab is not parent\n"); - lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num); - if (!lab) { - dbg("acpi_pciehprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun); - lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL); - if (!lab) { - err("acpi_pciehprm: alloc for ab fail\n"); - return AE_NO_MEMORY; - } - memset(lab, 0, sizeof(struct acpi_bridge)); - - lab->handle = phandle; - lab->pbus = pab->bus; - lab->pdevice = (int)(padr >> 16) & 0xffff; - lab->pfunction = (int)(padr & 0xffff); - lab->bus = (int)bus_num; - lab->scanned = 0; - lab->type = BRIDGE_TYPE_P2P; - - pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab); - } else - dbg("acpi_pciehprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun); + acpi_status status; + /* + * Per PCI firmware specification, we should run the ACPI _OSC + * method to get control of hotplug hardware before using it + */ + /* Fixme: run _OSC for a specific host bridge, not all of them */ + status = pci_osc_control_set(OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); + + /* Fixme: fail native hotplug if _OSC does not exist for root ports */ + if (status == AE_NOT_FOUND) { + /* + * Some older BIOS's don't support _OSC but support + * OSHP to do the same thing + */ + acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev)); + if (handle) + status = acpi_run_oshp(handle); } - - acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun); - - return (status); -} - -static int pciehprm_acpi_build_php_slots( - struct acpi_bridge *ab, - u32 depth - ) -{ - acpi_status status; - u8 *path_name = acpi_path_name(ab->handle); - - /* Walk down this pci bridge to get _SUNs if any behind P2P */ - status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, - ab->handle, - depth, - pciehprm_acpi_build_php_slots_callback, - ab, - NULL ); if (ACPI_FAILURE(status)) { - dbg("acpi_pciehprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status); + err("Cannot get control of hotplug hardware\n"); return -1; } + dbg("Sucess getting control of hotplug hardware\n"); return 0; } -static void build_a_bridge( - struct acpi_bridge *pab, - struct acpi_bridge *ab - ) -{ - u8 *path_name = acpi_path_name(ab->handle); - - pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab); - - switch (ab->type) { - case BRIDGE_TYPE_HOST: - dbg("acpi_pciehprm: Registered PCI HOST Bridge(%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n", - ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name); - break; - case BRIDGE_TYPE_P2P: - dbg("acpi_pciehprm: Registered PCI P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n", - ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name); - break; - }; - - /* build any immediate PHP slots under this pci bridge */ - pciehprm_acpi_build_php_slots(ab, 1); -} - -static struct acpi_bridge * add_p2p_bridge( - acpi_handle handle, - struct acpi_bridge *pab, /* parent */ - ulong adr - ) -{ - struct acpi_bridge *ab; - struct pci_dev *pdev; - ulong devnum, funcnum; - u8 *path_name = acpi_path_name(handle); - - ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL); - if (!ab) { - err("acpi_pciehprm: alloc for ab fail\n"); - return NULL; - } - memset(ab, 0, sizeof(struct acpi_bridge)); - - devnum = (adr >> 16) & 0xffff; - funcnum = adr & 0xffff; - - pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum)); - if (!pdev || !pdev->subordinate) { - err("acpi_pciehprm:%s is not a P2P Bridge\n", path_name); - kfree(ab); - return NULL; - } - - ab->handle = handle; - ab->seg = pab->seg; - ab->pbus = pab->bus; /* or pdev->bus->number */ - ab->pdevice = devnum; /* or PCI_SLOT(pdev->devfn) */ - ab->pfunction = funcnum; /* or PCI_FUNC(pdev->devfn) */ - ab->bus = pdev->subordinate->number; - ab->scanned = 0; - ab->type = BRIDGE_TYPE_P2P; - - dbg("acpi_pciehprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n", - pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), - pab->bus, (u32)devnum, (u32)funcnum, path_name); - - build_a_bridge(pab, ab); - - return ab; -} - -static acpi_status scan_p2p_bridge( - acpi_handle handle, - u32 Level, - void *context, - void **retval - ) -{ - struct acpi_bridge *pab = (struct acpi_bridge *)context; - struct acpi_bridge *ab; - acpi_status status; - ulong adr = 0; - u8 *path_name = acpi_path_name(handle); - ulong devnum, funcnum; - struct pci_dev *pdev; - - /* get device, function */ - status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); - if (ACPI_FAILURE(status)) { - if (status != AE_NOT_FOUND) - err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status); - return AE_OK; - } - - devnum = (adr >> 16) & 0xffff; - funcnum = adr & 0xffff; - - pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum)); - if (!pdev) - return AE_OK; - if (!pdev->subordinate) - return AE_OK; - - ab = add_p2p_bridge(handle, pab, adr); - if (ab) { - status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, - handle, - (u32)1, - scan_p2p_bridge, - ab, - NULL); - if (ACPI_FAILURE(status)) - dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status); - } - - return AE_OK; -} - -static struct acpi_bridge * add_host_bridge( - acpi_handle handle, - ulong segnum, - ulong busnum - ) -{ - ulong adr = 0; - acpi_status status; - struct acpi_bridge *ab; - u8 *path_name = acpi_path_name(handle); - - /* get device, function: host br adr is always 0000 though. */ - status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); - if (ACPI_FAILURE(status)) { - err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status); - return NULL; - } - dbg("acpi_pciehprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, - (u32)busnum, (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name); - - ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL); - if (!ab) { - err("acpi_pciehprm: alloc for ab fail\n"); - return NULL; - } - memset(ab, 0, sizeof(struct acpi_bridge)); - - ab->handle = handle; - ab->seg = (int)segnum; - ab->bus = ab->pbus = (int)busnum; - ab->pdevice = (int)(adr >> 16) & 0xffff; - ab->pfunction = (int)(adr & 0xffff); - ab->scanned = 0; - ab->type = BRIDGE_TYPE_HOST; - - status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); - if (ACPI_FAILURE(status)) { - err("%s: status %x\n", __FUNCTION__, status); - osc_run_status = (status == AE_NOT_FOUND) ? OSC_NOT_EXIST : OSC_RUN_FAILED; - } else { - osc_run_status = NC_RUN_SUCCESS; - } - dbg("%s: osc_run_status %x\n", __FUNCTION__, osc_run_status); - - build_a_bridge(ab, ab); - - return ab; -} - -static acpi_status acpi_scan_from_root_pci_callback ( - acpi_handle handle, - u32 Level, - void *context, - void **retval - ) -{ - ulong segnum = 0; - ulong busnum = 0; - acpi_status status; - struct acpi_bridge *ab; - u8 *path_name = acpi_path_name(handle); - - /* get bus number of this pci root bridge */ - status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum); - if (ACPI_FAILURE(status)) { - if (status != AE_NOT_FOUND) { - err("acpi_pciehprm:%s evaluate _SEG fail=0x%x\n", path_name, status); - return status; - } - segnum = 0; - } - - /* get bus number of this pci root bridge */ - status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum); - if (ACPI_FAILURE(status)) { - err("acpi_pciehprm:%s evaluate _BBN fail=0x%x\n", path_name, status); - return (status); - } - - ab = add_host_bridge(handle, segnum, busnum); - if (ab) { - status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, - handle, - 1, - scan_p2p_bridge, - ab, - NULL); - if (ACPI_FAILURE(status)) - dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status); - } - - return AE_OK; -} - -static int pciehprm_acpi_scan_pci (void) +void get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp) { - acpi_status status; + acpi_status status = AE_NOT_FOUND; + struct pci_dev *pdev = dev; /* - * TBD: traverse LDM device tree with the help of - * unified ACPI augmented for php device population. + * _HPP settings apply to all child buses, until another _HPP is + * encountered. If we don't find an _HPP for the input pci dev, + * look for it in the parent device scope since that would apply to + * this pci dev. If we don't find any _HPP, use hardcoded defaults */ - status = acpi_get_devices ( PCI_ROOT_HID_STRING, - acpi_scan_from_root_pci_callback, - NULL, - NULL ); - if (ACPI_FAILURE(status)) { - err("acpi_pciehprm:get_device PCI ROOT HID fail=0x%x\n", status); - return -1; - } - - return 0; -} - -int pciehprm_init(enum php_ctlr_type ctlr_type) -{ - int rc; - - if (ctlr_type != PCI) - return -ENODEV; - - dbg("pciehprm ACPI init \n"); - acpi_bridges_head = NULL; - - /* construct PCI bus:device tree of acpi_handles */ - rc = pciehprm_acpi_scan_pci(); - if (rc) - return rc; - - if ((oshp_run_status != NC_RUN_SUCCESS) && (osc_run_status != NC_RUN_SUCCESS)) { - err("Fails to gain control of native hot-plug\n"); - rc = -ENODEV; - } - - dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success"); - return rc; -} - -static void free_a_slot(struct acpi_php_slot *aps) -{ - dbg(" free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun); - - kfree(aps); -} - -static void free_a_bridge( struct acpi_bridge *ab) -{ - struct acpi_php_slot *aps, *next; - - switch (ab->type) { - case BRIDGE_TYPE_HOST: - dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n", - ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction); - break; - case BRIDGE_TYPE_P2P: - dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n", - ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction); - break; - }; - - /* free slots first */ - for (aps = ab->slots; aps; aps = next) { - next = aps->next; - free_a_slot(aps); - } - - kfree(ab); -} - -static void pciehprm_free_bridges ( struct acpi_bridge *ab) -{ - if (!ab) - return; - - if (ab->child) - pciehprm_free_bridges (ab->child); - - if (ab->next) - pciehprm_free_bridges (ab->next); - - free_a_bridge(ab); -} - -void pciehprm_cleanup(void) -{ - pciehprm_free_bridges (acpi_bridges_head); -} - -static int get_number_of_slots ( - struct acpi_bridge *ab, - int selfonly - ) -{ - struct acpi_php_slot *aps; - int prev_slot = -1; - int slot_num = 0; - - for ( aps = ab->slots; aps; aps = aps->next) - if (aps->dev != prev_slot) { - prev_slot = aps->dev; - slot_num++; - } - - if (ab->child) - slot_num += get_number_of_slots (ab->child, 0); - - if (selfonly) - return slot_num; - - if (ab->next) - slot_num += get_number_of_slots (ab->next, 0); - - return slot_num; -} - -static struct acpi_php_slot * get_acpi_slot ( - struct acpi_bridge *ab, - u32 sun - ) -{ - struct acpi_php_slot *aps = NULL; - - for ( aps = ab->slots; aps; aps = aps->next) - if (aps->sun == sun) - return aps; - - if (!aps && ab->child) { - aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun); - if (aps) - return aps; - } - - if (!aps && ab->next) { - aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun); - if (aps) - return aps; - } - - return aps; - -} - -#if 0 -void * pciehprm_get_slot(struct slot *slot) -{ - struct acpi_bridge *ab = acpi_bridges_head; - struct acpi_php_slot *aps = get_acpi_slot (ab, slot->number); - - aps->slot = slot; - - dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun); - - return (void *)aps; -} -#endif - -int pciehprm_set_hpp( - struct controller *ctrl, - struct pci_func *func, - u8 card_type - ) -{ - struct acpi_bridge *ab; - struct pci_bus lpci_bus, *pci_bus; - int rc = 0; - unsigned int devfn; - u8 cls= 0x08; /* default cache line size */ - u8 lt = 0x40; /* default latency timer */ - u8 ep = 0; - u8 es = 0; - - memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); - pci_bus = &lpci_bus; - pci_bus->number = func->bus; - devfn = PCI_DEVFN(func->device, func->function); - - ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); - - if (ab) { - if (ab->_hpp) { - lt = (u8)ab->_hpp->latency_timer; - cls = (u8)ab->_hpp->cache_line_size; - ep = (u8)ab->_hpp->enable_perr; - es = (u8)ab->_hpp->enable_serr; - } else - dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function); - } else - dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function); - - - if (card_type == PCI_HEADER_TYPE_BRIDGE) { - /* set subordinate Latency Timer */ - rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt); + while (pdev && (ACPI_FAILURE(status))) { + acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); + if (!handle) + break; + status = acpi_run_hpp(handle, hpp); + if (!(pdev->bus->parent)) + break; + /* Check if a parent object supports _HPP */ + pdev = pdev->bus->parent->self; } - - /* set base Latency Timer */ - rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt); - dbg(" set latency timer =0x%02x: %x\n", lt, rc); - - rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls); - dbg(" set cache_line_size=0x%02x: %x\n", cls, rc); - - return rc; } -void pciehprm_enable_card( - struct controller *ctrl, - struct pci_func *func, - u8 card_type) -{ - u16 command, cmd, bcommand, bcmd; - struct pci_bus lpci_bus, *pci_bus; - struct acpi_bridge *ab; - unsigned int devfn; - int rc; - - memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); - pci_bus = &lpci_bus; - pci_bus->number = func->bus; - devfn = PCI_DEVFN(func->device, func->function); - - rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &cmd); - - if (card_type == PCI_HEADER_TYPE_BRIDGE) { - rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcmd); - } - - command = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE - | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; - bcommand = bcmd | PCI_BRIDGE_CTL_NO_ISA; - - ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); - if (ab) { - if (ab->_hpp) { - if (ab->_hpp->enable_perr) { - command |= PCI_COMMAND_PARITY; - bcommand |= PCI_BRIDGE_CTL_PARITY; - } else { - command &= ~PCI_COMMAND_PARITY; - bcommand &= ~PCI_BRIDGE_CTL_PARITY; - } - if (ab->_hpp->enable_serr) { - command |= PCI_COMMAND_SERR; - bcommand |= PCI_BRIDGE_CTL_SERR; - } else { - command &= ~PCI_COMMAND_SERR; - bcommand &= ~PCI_BRIDGE_CTL_SERR; - } - } else - dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function); - } else - dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function); - - if (command != cmd) { - rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); - } - if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) { - rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand); - } -} diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c index ed68c3dd0f0..32371cd19e3 100644 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c @@ -37,15 +37,9 @@ #include #include #include "pciehp.h" -#include "pciehprm.h" #include "pciehprm_nonacpi.h" -void pciehprm_cleanup(void) -{ - return; -} - int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) { @@ -53,106 +47,13 @@ int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn return 0; } -int pciehprm_set_hpp( - struct controller *ctrl, - struct pci_func *func, - u8 card_type) -{ - u32 rc; - u8 temp_byte; - struct pci_bus lpci_bus, *pci_bus; - unsigned int devfn; - memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); - pci_bus = &lpci_bus; - pci_bus->number = func->bus; - devfn = PCI_DEVFN(func->device, func->function); - - temp_byte = 0x40; /* hard coded value for LT */ - if (card_type == PCI_HEADER_TYPE_BRIDGE) { - /* set subordinate Latency Timer */ - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte); - - if (rc) { - dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, - func->bus, func->device, func->function); - return rc; - } - } - - /* set base Latency Timer */ - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); - - if (rc) { - dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function); - return rc; - } - - /* set Cache Line size */ - temp_byte = 0x08; /* hard coded value for CLS */ - - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); - - if (rc) { - dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function); - } - - /* set enable_perr */ - /* set enable_serr */ - - return rc; -} - -void pciehprm_enable_card( - struct controller *ctrl, - struct pci_func *func, - u8 card_type) +void get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp) { - u16 command, bcommand; - struct pci_bus lpci_bus, *pci_bus; - unsigned int devfn; - int rc; - - memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); - pci_bus = &lpci_bus; - pci_bus->number = func->bus; - devfn = PCI_DEVFN(func->device, func->function); - - rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command); - - command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR - | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE - | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; - - rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); - - if (card_type == PCI_HEADER_TYPE_BRIDGE) { - - rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand); - - bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR - | PCI_BRIDGE_CTL_NO_ISA; - - rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand); - } + return; } -static int legacy_pciehprm_init_pci(void) +int get_hp_hw_control_from_firmware(struct pci_dev *dev) { return 0; } - -int pciehprm_init(enum php_ctlr_type ctrl_type) -{ - int retval; - - switch (ctrl_type) { - case PCI: - retval = legacy_pciehprm_init_pci(); - break; - default: - retval = -ENODEV; - break; - } - - return retval; -} diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.h b/drivers/pci/hotplug/pciehprm_nonacpi.h deleted file mode 100644 index b10603b0e95..00000000000 --- a/drivers/pci/hotplug/pciehprm_nonacpi.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform - * - * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2001 IBM Corp. - * Copyright (C) 2003-2004 Intel Corporation - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Send feedback to , - * - */ - -#ifndef _PCIEHPRM_NONACPI_H_ -#define _PCIEHPRM_NONACPI_H_ - -struct irq_info { - u8 bus, devfn; /* bus, device and function */ - struct { - u8 link; /* IRQ line ID, chipset dependent, 0=not routed */ - u16 bitmap; /* Available IRQs */ - } __attribute__ ((packed)) irq[4]; - u8 slot; /* slot number, 0=onboard */ - u8 rfu; -} __attribute__ ((packed)); - -struct irq_routing_table { - u32 signature; /* PIRQ_SIGNATURE should be here */ - u16 version; /* PIRQ_VERSION */ - u16 size; /* Table size in bytes */ - u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */ - u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */ - u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */ - u32 miniport_data; /* Crap */ - u8 rfu[11]; - u8 checksum; /* Modulo 256 checksum must give zero */ - struct irq_info slots[0]; -} __attribute__ ((packed)); - -#endif /* _PCIEHPRM_NONACPI_H_ */ -- cgit v1.2.3 From ca22a5e4d70620b7f3d809e424daa5214b0aa00d Mon Sep 17 00:00:00 2001 From: "rajesh.shah@intel.com" Date: Mon, 31 Oct 2005 16:20:08 -0800 Subject: [PATCH] pciehp: remove redundant data structures State information is currently stored in per-slot as well as per-pci-function data structures in pciehp. There's a lot of overlap in the information kept, and some of it is never used. This patch consolidates the state information to per-slot and eliminates unused data structures. The biggest change is to eliminate the pci_func structure and the code around managing its lists. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 30 +-- drivers/pci/hotplug/pciehp_core.c | 29 --- drivers/pci/hotplug/pciehp_ctrl.c | 391 ++++---------------------------------- drivers/pci/hotplug/pciehp_pci.c | 349 +++------------------------------- 4 files changed, 65 insertions(+), 734 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e9c09566f85..3e17e3d4dd6 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -56,25 +56,11 @@ struct hotplug_params { u8 enable_perr; }; -struct pci_func { - struct pci_func *next; - u8 bus; - u8 device; - u8 function; - u8 is_a_board; - u16 status; - u8 configured; - u8 switch_save; - u8 presence_save; - u16 reserved2; - u32 config_space[0x20]; - struct pci_dev* pci_dev; -}; - struct slot { struct slot *next; u8 bus; u8 device; + u16 status; u32 number; u8 is_a_board; u8 configured; @@ -177,9 +163,6 @@ struct controller { * error Messages */ #define msg_initialization_err "Initialization failure, error=%d\n" -#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n" -#define msg_HPC_non_pcie "The PCI hot plug controller is not supported by this driver.\n" -#define msg_HPC_not_supported "This system is not supported by this version of pciephd module. Upgrade to a newer version of pciehpd\n" #define msg_button_on "PCI slot #%d - powering on due to button press.\n" #define msg_button_off "PCI slot #%d - powering off due to button press.\n" #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" @@ -188,8 +171,6 @@ struct controller { /* controller functions */ extern int pciehp_event_start_thread (void); extern void pciehp_event_stop_thread (void); -extern struct pci_func *pciehp_slot_create (unsigned char busnumber); -extern struct pci_func *pciehp_slot_find (unsigned char bus, unsigned char device, unsigned char index); extern int pciehp_enable_slot (struct slot *slot); extern int pciehp_disable_slot (struct slot *slot); @@ -200,12 +181,8 @@ extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); /* extern void long_delay (int delay); */ /* pci functions */ -extern int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); -/*extern int pciehp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/ -extern int pciehp_save_config (struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); -extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot); -extern int pciehp_configure_device (struct slot *ctrl); -extern int pciehp_unconfigure_device (struct pci_func* func); +extern int pciehp_configure_device (struct slot *p_slot); +extern int pciehp_unconfigure_device (struct slot *p_slot); extern int get_hp_hw_control_from_firmware(struct pci_dev *dev); extern void get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp); @@ -214,7 +191,6 @@ extern void get_hp_params_from_firmware(struct pci_dev *dev, /* Global variables */ extern struct controller *pciehp_ctrl_list; -extern struct pci_func *pciehp_slot_list[256]; /* Inline functions */ diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index e20cf8e42bd..be608563e8b 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -46,7 +46,6 @@ int pciehp_debug; int pciehp_poll_mode; int pciehp_poll_time; struct controller *pciehp_ctrl_list; -struct pci_func *pciehp_slot_list[256]; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " @@ -422,15 +421,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ first_device_num = ctrl->slot_device_offset; num_ctlr_slots = ctrl->num_slots; - /* Store PCI Config Space for all devices on this bus */ - dbg("%s: Before calling pciehp_save_config, ctrl->bus %x,ctrl->slot_bus %x\n", - __FUNCTION__,ctrl->bus, ctrl->slot_bus); - rc = pciehp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num); - if (rc) { - err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc); - goto err_out_free_ctrl_bus; - } - ctrl->add_support = 1; /* Setup the slot information structures */ @@ -491,7 +481,6 @@ err_out_none: static int pcie_start_thread(void) { - int loop; int retval = 0; dbg("Initialize + Start the notification/polling mechanism \n"); @@ -502,20 +491,11 @@ static int pcie_start_thread(void) return retval; } - dbg("Initialize slot lists\n"); - /* One slot list for each bus in the system */ - for (loop = 0; loop < 256; loop++) { - pciehp_slot_list[loop] = NULL; - } - return retval; } static void __exit unload_pciehpd(void) { - struct pci_func *next; - struct pci_func *TempSlot; - int loop; struct controller *ctrl; struct controller *tctrl; @@ -534,15 +514,6 @@ static void __exit unload_pciehpd(void) kfree(tctrl); } - for (loop = 0; loop < 256; loop++) { - next = pciehp_slot_list[loop]; - while (next != NULL) { - TempSlot = next; - next = next->next; - kfree(TempSlot); - } - } - /* Stop the notification mechanism */ pciehp_event_stop_thread(); diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index d07d4194bc2..b60e4973289 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -55,19 +55,16 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) struct slot *p_slot; u8 rc = 0; u8 getstatus; - struct pci_func *func; struct event_info *taskInfo; /* Attention Button Change */ dbg("pciehp: Attention button interrupt received.\n"); - func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); - /* This is the structure that tells the worker thread what to do */ taskInfo = &(ctrl->event_queue[ctrl->next_event]); p_slot = pciehp_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_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); ctrl->next_event = (ctrl->next_event + 1) % 10; @@ -112,14 +109,11 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) struct slot *p_slot; u8 rc = 0; u8 getstatus; - struct pci_func *func; struct event_info *taskInfo; /* Switch Change */ dbg("pciehp: Switch interrupt received.\n"); - func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); - /* This is the structure that tells the worker thread * what to do */ @@ -129,7 +123,7 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) rc++; p_slot = pciehp_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_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (getstatus) { @@ -137,14 +131,14 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) * Switch opened */ info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); - func->switch_save = 0; + p_slot->switch_save = 0; taskInfo->event_type = INT_SWITCH_OPEN; } else { /* * Switch closed */ info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); - func->switch_save = 0x10; + p_slot->switch_save = 0x10; taskInfo->event_type = INT_SWITCH_CLOSE; } @@ -159,14 +153,11 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; u8 rc = 0; - struct pci_func *func; struct event_info *taskInfo; /* Presence Change */ dbg("pciehp: Presence/Notify input change.\n"); - func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); - /* This is the structure that tells the worker thread * what to do */ @@ -180,8 +171,8 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) /* Switch is open, assume a presence change * Save the presence state */ - p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); - if (func->presence_save) { + p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); + if (p_slot->presence_save) { /* * Card Present */ @@ -206,14 +197,11 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; u8 rc = 0; - struct pci_func *func; struct event_info *taskInfo; /* power fault */ dbg("pciehp: Power fault interrupt received.\n"); - func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); - /* this is the structure that tells the worker thread * what to do */ @@ -229,7 +217,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) * power fault Cleared */ info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); - func->status = 0x00; + p_slot->status = 0x00; taskInfo->event_type = INT_POWER_FAULT_CLEAR; } else { /* @@ -238,7 +226,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); taskInfo->event_type = INT_POWER_FAULT; /* set power fault status for this board */ - func->status = 0xFF; + p_slot->status = 0xFF; info("power fault bit %x set\n", hp_slot); } if (rc) @@ -247,187 +235,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) return rc; } -/** - * pciehp_slot_create - Creates a node and adds it to the proper bus. - * @busnumber - bus where new node is to be located - * - * Returns pointer to the new node or NULL if unsuccessful - */ -struct pci_func *pciehp_slot_create(u8 busnumber) -{ - struct pci_func *new_slot; - struct pci_func *next; - dbg("%s: busnumber %x\n", __FUNCTION__, busnumber); - new_slot = kmalloc(sizeof(struct pci_func), GFP_KERNEL); - - if (new_slot == NULL) - return new_slot; - - memset(new_slot, 0, sizeof(struct pci_func)); - - new_slot->next = NULL; - new_slot->configured = 1; - - if (pciehp_slot_list[busnumber] == NULL) { - pciehp_slot_list[busnumber] = new_slot; - } else { - next = pciehp_slot_list[busnumber]; - while (next->next != NULL) - next = next->next; - next->next = new_slot; - } - return new_slot; -} - - -/** - * slot_remove - Removes a node from the linked list of slots. - * @old_slot: slot to remove - * - * Returns 0 if successful, !0 otherwise. - */ -static int slot_remove(struct pci_func * old_slot) -{ - struct pci_func *next; - - if (old_slot == NULL) - return 1; - - next = pciehp_slot_list[old_slot->bus]; - - if (next == NULL) - return 1; - - if (next == old_slot) { - pciehp_slot_list[old_slot->bus] = old_slot->next; - kfree(old_slot); - return 0; - } - - while ((next->next != old_slot) && (next->next != NULL)) { - next = next->next; - } - - if (next->next == old_slot) { - next->next = old_slot->next; - kfree(old_slot); - return 0; - } else - return 2; -} - - -/** - * bridge_slot_remove - Removes a node from the linked list of slots. - * @bridge: bridge to remove - * - * Returns 0 if successful, !0 otherwise. - */ -static int bridge_slot_remove(struct pci_func *bridge) -{ - u8 subordinateBus, secondaryBus; - u8 tempBus; - struct pci_func *next; - - if (bridge == NULL) - return 1; - - secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF; - subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF; - - for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) { - next = pciehp_slot_list[tempBus]; - - while (!slot_remove(next)) { - next = pciehp_slot_list[tempBus]; - } - } - - next = pciehp_slot_list[bridge->bus]; - - if (next == NULL) { - return 1; - } - - if (next == bridge) { - pciehp_slot_list[bridge->bus] = bridge->next; - kfree(bridge); - return 0; - } - - while ((next->next != bridge) && (next->next != NULL)) { - next = next->next; - } - - if (next->next == bridge) { - next->next = bridge->next; - kfree(bridge); - return 0; - } else - return 2; -} - - -/** - * pciehp_slot_find - Looks for a node by bus, and device, multiple functions accessed - * @bus: bus to find - * @device: device to find - * @index: is 0 for first function found, 1 for the second... - * - * Returns pointer to the node if successful, %NULL otherwise. - */ -struct pci_func *pciehp_slot_find(u8 bus, u8 device, u8 index) -{ - int found = -1; - struct pci_func *func; - - func = pciehp_slot_list[bus]; - dbg("%s: bus %x device %x index %x\n", - __FUNCTION__, bus, device, index); - if (func != NULL) { - dbg("%s: func-> bus %x device %x function %x pci_dev %p\n", - __FUNCTION__, func->bus, func->device, func->function, - func->pci_dev); - } else - dbg("%s: func == NULL\n", __FUNCTION__); - - if ((func == NULL) || ((func->device == device) && (index == 0))) - return func; - - if (func->device == device) - found++; - - while (func->next != NULL) { - func = func->next; - - dbg("%s: In while loop, func-> bus %x device %x function %x pci_dev %p\n", - __FUNCTION__, func->bus, func->device, func->function, - func->pci_dev); - if (func->device == device) - found++; - dbg("%s: while loop, found %d, index %d\n", __FUNCTION__, - found, index); - - if ((found == index) || (func->function == index)) { - dbg("%s: Found bus %x dev %x func %x\n", __FUNCTION__, - func->bus, func->device, func->function); - return func; - } - } - - return NULL; -} - -static int is_bridge(struct pci_func * func) -{ - /* Check the header type */ - if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01) - return 1; - else - return 0; -} - - /* The following routines constitute the bulk of the hotplug controller logic */ @@ -472,17 +279,16 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) * Configures board * */ -static u32 board_added(struct pci_func * func, struct controller * ctrl) +static u32 board_added(struct slot *p_slot) { u8 hp_slot; u32 temp_register = 0xFFFFFFFF; u32 rc = 0; - struct slot *p_slot; + struct controller *ctrl = p_slot->ctrl; - p_slot = pciehp_find_slot(ctrl, func->device); - hp_slot = func->device - ctrl->slot_device_offset; + hp_slot = p_slot->device - ctrl->slot_device_offset; - dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); + dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, p_slot->device, ctrl->slot_device_offset, hp_slot); /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); @@ -522,15 +328,15 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) return rc; } - dbg("%s: func status = %x\n", __FUNCTION__, func->status); + dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); /* Check for a power fault */ - if (func->status == 0xFF) { + if (p_slot->status == 0xFF) { /* power fault occurred, but it was benign */ temp_register = 0xFFFFFFFF; dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register); rc = POWER_FAILURE; - func->status = 0; + p_slot->status = 0; goto err_exit; } @@ -541,10 +347,9 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) goto err_exit; } - pciehp_save_slot_config(ctrl, func); - func->status = 0; - func->switch_save = 0x10; - func->is_a_board = 0x01; + p_slot->status = 0; + p_slot->switch_save = 0x10; + p_slot->is_a_board = 0x01; /* * Some PCI Express root ports require fixup after hot-plug operation. @@ -575,30 +380,27 @@ err_exit: * remove_board - Turns off slot and LED's * */ -static u32 remove_board(struct pci_func *func, struct controller *ctrl) +static u32 remove_board(struct slot *p_slot) { u8 device; u8 hp_slot; u32 rc; - struct slot *p_slot; - - if (func == NULL) - return 1; + struct controller *ctrl = p_slot->ctrl; - if (pciehp_unconfigure_device(func)) + if (pciehp_unconfigure_device(p_slot)) return 1; - device = func->device; + device = p_slot->device; - hp_slot = func->device - ctrl->slot_device_offset; + hp_slot = p_slot->device - ctrl->slot_device_offset; p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); /* Change status to shutdown */ - if (func->is_a_board) - func->status = 0x01; - func->configured = 0; + if (p_slot->is_a_board) + p_slot->status = 0x01; + p_slot->configured = 0; /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); @@ -626,35 +428,8 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl) /* Done with exclusive hardware access */ up(&ctrl->crit_sect); - if (ctrl->add_support) { - while (func) { - if (is_bridge(func)) { - dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", - ctrl->seg, func->bus, func->device, func->function); - bridge_slot_remove(func); - } else { - dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", - ctrl->seg, func->bus, func->device, func->function); - slot_remove(func); - } - - func = pciehp_slot_find(ctrl->slot_bus, device, 0); - } - - /* Setup slot structure with entry for empty slot */ - func = pciehp_slot_create(ctrl->slot_bus); - - if (func == NULL) { - return 1; - } - - func->bus = ctrl->slot_bus; - func->device = device; - func->function = 0; - func->configured = 0; - func->switch_save = 0x10; - func->is_a_board = 0; - } + p_slot->switch_save = 0x10; + p_slot->is_a_board = 0; return 0; } @@ -851,7 +626,6 @@ static void interrupt_event_handler(struct controller *ctrl) { int loop = 0; int change = 1; - struct pci_func *func; u8 hp_slot; u8 getstatus; struct slot *p_slot; @@ -863,11 +637,9 @@ static void interrupt_event_handler(struct controller *ctrl) if (ctrl->event_queue[loop].event_type != 0) { hp_slot = ctrl->event_queue[loop].hp_slot; - func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); - p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - dbg("hp_slot %d, func %p, p_slot %p\n", hp_slot, func, p_slot); + dbg("hp_slot %d, p_slot %p\n", hp_slot, p_slot); if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { dbg("button cancel\n"); @@ -1015,13 +787,6 @@ int pciehp_enable_slot(struct slot *p_slot) { u8 getstatus = 0; int rc; - struct pci_func *func; - - func = pciehp_slot_find(p_slot->bus, p_slot->device, 0); - if (!func) { - dbg("%s: Error! slot NULL\n", __FUNCTION__); - return 1; - } /* Check to see if (latch closed, card present, power off) */ down(&p_slot->ctrl->crit_sect); @@ -1051,45 +816,21 @@ int pciehp_enable_slot(struct slot *p_slot) } up(&p_slot->ctrl->crit_sect); - slot_remove(func); - - func = pciehp_slot_create(p_slot->bus); - if (func == NULL) - return 1; - - func->bus = p_slot->bus; - func->device = p_slot->device; - func->function = 0; - func->configured = 0; - func->is_a_board = 1; + p_slot->configured = 0; + p_slot->is_a_board = 1; /* 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_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - func->switch_save = !getstatus? 0x10:0; + p_slot->switch_save = !getstatus? 0x10:0; - rc = board_added(func, p_slot->ctrl); + rc = board_added(p_slot); if (rc) { - if (is_bridge(func)) - bridge_slot_remove(func); - else - slot_remove(func); - - /* Setup slot structure with entry for empty slot */ - func = pciehp_slot_create(p_slot->bus); - if (func == NULL) - return 1; /* Out of memory */ - - func->bus = p_slot->bus; - func->device = p_slot->device; - func->function = 0; - func->configured = 0; - func->is_a_board = 1; - /* 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_adapter_status(p_slot, + &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - func->switch_save = !getstatus? 0x10:0; + p_slot->switch_save = !getstatus? 0x10:0; } if (p_slot) @@ -1101,14 +842,8 @@ int pciehp_enable_slot(struct slot *p_slot) int pciehp_disable_slot(struct slot *p_slot) { - u8 class_code, header_type, BCR; - u8 index = 0; u8 getstatus = 0; - u32 rc = 0; int ret = 0; - unsigned int devfn; - struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate; - struct pci_func *func; if (!p_slot->ctrl) return 1; @@ -1145,54 +880,8 @@ int pciehp_disable_slot(struct slot *p_slot) up(&p_slot->ctrl->crit_sect); - func = pciehp_slot_find(p_slot->bus, p_slot->device, index++); - - /* Make sure there are no video controllers here - * for all func of p_slot - */ - while (func && !rc) { - pci_bus->number = func->bus; - devfn = PCI_DEVFN(func->device, func->function); - - /* Check the Class Code */ - rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); - if (rc) - return rc; - - if (class_code == PCI_BASE_CLASS_DISPLAY) { - /* Display/Video adapter (not supported) */ - rc = REMOVE_NOT_SUPPORTED; - } else { - /* See if it's a bridge */ - rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); - if (rc) - return rc; - - /* If it's a bridge, check the VGA Enable bit */ - if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { - rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR); - if (rc) - return rc; - - /* If the VGA Enable bit is set, remove isn't supported */ - if (BCR & PCI_BRIDGE_CTL_VGA) { - rc = REMOVE_NOT_SUPPORTED; - } - } - } - - func = pciehp_slot_find(p_slot->bus, p_slot->device, index++); - } - - func = pciehp_slot_find(p_slot->bus, p_slot->device, 0); - if ((func != NULL) && !rc) { - rc = remove_board(func, p_slot->ctrl); - } else if (!rc) - rc = 1; - - if (p_slot) - update_slot_info(p_slot); - - return rc; + ret = remove_board(p_slot); + update_slot_info(p_slot); + return ret; } diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index db59a06ab0b..1d185c1bc77 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -101,346 +101,41 @@ int pciehp_configure_device(struct slot *p_slot) return 0; } -int pciehp_unconfigure_device(struct pci_func* func) +int pciehp_unconfigure_device(struct slot *p_slot) { int rc = 0; int j; - struct pci_bus *pbus; + u8 bctl = 0; - dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, - func->device, func->function); - pbus = func->pci_dev->bus; + dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, + p_slot->device); for (j=0; j<8 ; j++) { - struct pci_dev* temp = pci_find_slot(func->bus, - (func->device << 3) | j); - if (temp) { - pci_remove_bus_device(temp); + struct pci_dev* temp = pci_find_slot(p_slot->bus, + (p_slot->device << 3) | j); + if (!temp) + continue; + if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { + err("Cannot remove display device %s\n", + pci_name(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)); + continue; + } } + pci_remove_bus_device(temp); } /* * Some PCI Express root ports require fixup after hot-plug operation. */ if (pcie_mch_quirk) - pci_fixup_device(pci_fixup_final, pbus->self); + pci_fixup_device(pci_fixup_final, p_slot->ctrl->pci_dev); return rc; } -/* - * pciehp_save_config - * - * Reads configuration for all slots in a PCI bus and saves info. - * - * Note: For non-hot plug busses, the slot # saved is the device # - * - * returns 0 if success - */ -int pciehp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num) -{ - int rc; - u8 class_code; - u8 header_type; - u32 ID; - u8 secondary_bus; - struct pci_func *new_slot; - int sub_bus; - int max_functions; - int function; - u8 DevError; - int device = 0; - int cloop = 0; - int stop_it; - int index; - int is_hot_plug = num_ctlr_slots || first_device_num; - struct pci_bus lpci_bus, *pci_bus; - int FirstSupported, LastSupported; - - dbg("%s: Enter\n", __FUNCTION__); - - memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); - pci_bus = &lpci_bus; - - dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, - num_ctlr_slots, first_device_num); - - /* Decide which slots are supported */ - if (is_hot_plug) { - /********************************* - * is_hot_plug is the slot mask - *********************************/ - FirstSupported = first_device_num; - LastSupported = FirstSupported + num_ctlr_slots - 1; - } else { - FirstSupported = 0; - LastSupported = 0x1F; - } - - dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, - LastSupported); - - /* Save PCI configuration space for all devices in supported slots */ - dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number); - pci_bus->number = busnumber; - dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device); - for (device = FirstSupported; device <= LastSupported; device++) { - ID = 0xFFFFFFFF; - rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), - PCI_VENDOR_ID, &ID); - - if (ID != 0xFFFFFFFF) { /* device in slot */ - dbg("%s: ID = %x\n", __FUNCTION__, ID); - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), - 0x0B, &class_code); - if (rc) - return rc; - - rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), - PCI_HEADER_TYPE, &header_type); - if (rc) - return rc; - - dbg("class_code = %x, header_type = %x\n", class_code, header_type); - - /* If multi-function device, set max_functions to 8 */ - if (header_type & 0x80) - max_functions = 8; - else - max_functions = 1; - - function = 0; - - do { - DevError = 0; - dbg("%s: In do loop\n", __FUNCTION__); - - if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */ - /* Recurse the subordinate bus - * get the subordinate bus number - */ - rc = pci_bus_read_config_byte(pci_bus, - PCI_DEVFN(device, function), - PCI_SECONDARY_BUS, &secondary_bus); - if (rc) { - return rc; - } else { - sub_bus = (int) secondary_bus; - - /* Save secondary bus cfg spc with this recursive call. */ - rc = pciehp_save_config(ctrl, sub_bus, 0, 0); - if (rc) - return rc; - } - } - - index = 0; - new_slot = pciehp_slot_find(busnumber, device, index++); - - dbg("%s: new_slot = %p bus %x dev %x fun %x\n", - __FUNCTION__, new_slot, busnumber, device, index-1); - - while (new_slot && (new_slot->function != (u8) function)) { - new_slot = pciehp_slot_find(busnumber, device, index++); - dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n", - __FUNCTION__, new_slot, busnumber, device, index-1); - } - if (!new_slot) { - /* Setup slot structure. */ - new_slot = pciehp_slot_create(busnumber); - dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n", - __FUNCTION__, new_slot, busnumber, device, function); - - if (new_slot == NULL) - return(1); - } - - new_slot->bus = (u8) busnumber; - new_slot->device = (u8) device; - new_slot->function = (u8) function; - new_slot->is_a_board = 1; - new_slot->switch_save = 0x10; - /* In case of unsupported board */ - new_slot->status = DevError; - new_slot->pci_dev = pci_find_slot(new_slot->bus, - (new_slot->device << 3) | new_slot->function); - dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev); - - for (cloop = 0; cloop < 0x20; cloop++) { - rc = pci_bus_read_config_dword(pci_bus, - PCI_DEVFN(device, function), - cloop << 2, - (u32 *) &(new_slot->config_space [cloop])); - /* dbg("new_slot->config_space[%x] = %x\n", - cloop, new_slot->config_space[cloop]); */ - if (rc) - return rc; - } - - function++; - - stop_it = 0; - - /* this loop skips to the next present function - * reading in Class Code and Header type. - */ - - while ((function < max_functions)&&(!stop_it)) { - dbg("%s: In while loop \n", __FUNCTION__); - rc = pci_bus_read_config_dword(pci_bus, - PCI_DEVFN(device, function), - PCI_VENDOR_ID, &ID); - - if (ID == 0xFFFFFFFF) { /* nothing there. */ - function++; - dbg("Nothing there\n"); - } else { /* Something there */ - rc = pci_bus_read_config_byte(pci_bus, - PCI_DEVFN(device, function), - 0x0B, &class_code); - if (rc) - return rc; - - rc = pci_bus_read_config_byte(pci_bus, - PCI_DEVFN(device, function), - PCI_HEADER_TYPE, &header_type); - if (rc) - return rc; - - dbg("class_code = %x, header_type = %x\n", class_code, header_type); - stop_it++; - } - } - - } while (function < max_functions); - /* End of IF (device in slot?) */ - } else if (is_hot_plug) { - /* Setup slot structure with entry for empty slot */ - new_slot = pciehp_slot_create(busnumber); - - if (new_slot == NULL) { - return(1); - } - dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot, - new_slot->bus, new_slot->device, new_slot->function); - - new_slot->bus = (u8) busnumber; - new_slot->device = (u8) device; - new_slot->function = 0; - new_slot->is_a_board = 0; - new_slot->presence_save = 0; - new_slot->switch_save = 0; - } - } /* End of FOR loop */ - - dbg("%s: Exit\n", __FUNCTION__); - return(0); -} - - -/* - * pciehp_save_slot_config - * - * Saves configuration info for all PCI devices in a given slot - * including subordinate busses. - * - * returns 0 if success - */ -int pciehp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot) -{ - int rc; - u8 class_code; - u8 header_type; - u32 ID; - u8 secondary_bus; - int sub_bus; - int max_functions; - int function; - int cloop = 0; - int stop_it; - struct pci_bus lpci_bus, *pci_bus; - memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); - pci_bus = &lpci_bus; - pci_bus->number = new_slot->bus; - - ID = 0xFFFFFFFF; - - pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), - PCI_VENDOR_ID, &ID); - - if (ID != 0xFFFFFFFF) { /* device in slot */ - pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), - 0x0B, &class_code); - - pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), - PCI_HEADER_TYPE, &header_type); - - if (header_type & 0x80) /* Multi-function device */ - max_functions = 8; - else - max_functions = 1; - - function = 0; - - do { - if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ - /* Recurse the subordinate bus */ - pci_bus_read_config_byte(pci_bus, - PCI_DEVFN(new_slot->device, function), - PCI_SECONDARY_BUS, &secondary_bus); - - sub_bus = (int) secondary_bus; - - /* Save the config headers for the secondary bus. */ - rc = pciehp_save_config(ctrl, sub_bus, 0, 0); - - if (rc) - return rc; - - } /* End of IF */ - - new_slot->status = 0; - - for (cloop = 0; cloop < 0x20; cloop++) { - pci_bus_read_config_dword(pci_bus, - PCI_DEVFN(new_slot->device, function), - cloop << 2, - (u32 *) &(new_slot->config_space [cloop])); - } - - function++; - - stop_it = 0; - - /* this loop skips to the next present function - * reading in the Class Code and the Header type. - */ - - while ((function < max_functions) && (!stop_it)) { - pci_bus_read_config_dword(pci_bus, - PCI_DEVFN(new_slot->device, function), - PCI_VENDOR_ID, &ID); - - if (ID == 0xFFFFFFFF) { /* nothing there. */ - function++; - } else { /* Something there */ - pci_bus_read_config_byte(pci_bus, - PCI_DEVFN(new_slot->device, function), - 0x0B, &class_code); - - pci_bus_read_config_byte(pci_bus, - PCI_DEVFN(new_slot->device, function), - PCI_HEADER_TYPE, &header_type); - - stop_it++; - } - } - - } while (function < max_functions); - } /* End of IF (device in slot?) */ - else { - return 2; - } - - return 0; -} - -- cgit v1.2.3 From ed6cbcf2ac706aa47194fd2f7a99865cc06833d7 Mon Sep 17 00:00:00 2001 From: "rajesh.shah@intel.com" Date: Mon, 31 Oct 2005 16:20:09 -0800 Subject: [PATCH] pciehp: miscellaneous cleanups Remove un-necessary header includes, remove dead code, remove some hardcoded constants... Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 44 +++++++++++++------------- drivers/pci/hotplug/pciehp_core.c | 14 +-------- drivers/pci/hotplug/pciehp_ctrl.c | 56 ++++++++-------------------------- drivers/pci/hotplug/pciehp_hpc.c | 38 +++-------------------- drivers/pci/hotplug/pciehp_pci.c | 4 --- drivers/pci/hotplug/pciehprm_acpi.c | 6 ---- drivers/pci/hotplug/pciehprm_nonacpi.c | 12 -------- 7 files changed, 41 insertions(+), 133 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 3e17e3d4dd6..314989a3a93 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -32,8 +32,6 @@ #include #include #include -#include -#include #include #include "pci_hotplug.h" @@ -62,13 +60,7 @@ struct slot { u8 device; u16 status; u32 number; - u8 is_a_board; - u8 configured; u8 state; - u8 switch_save; - u8 presence_save; - u32 capabilities; - u16 reserved2; struct timer_list task_event; u8 hp_slot; struct controller *ctrl; @@ -82,27 +74,42 @@ struct event_info { u8 hp_slot; }; +typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id); + +struct php_ctlr_state_s { + struct php_ctlr_state_s *pnext; + struct pci_dev *pci_dev; + unsigned int irq; + unsigned long flags; /* spinlock's */ + u32 slot_device_offset; + u32 num_slots; + struct timer_list int_poll_timer; /* Added for poll event */ + php_intr_callback_t attention_button_callback; + php_intr_callback_t switch_change_callback; + php_intr_callback_t presence_change_callback; + php_intr_callback_t power_fault_callback; + void *callback_instance_id; + struct ctrl_reg *creg; /* Ptr to controller register space */ +}; + +#define MAX_EVENTS 10 struct controller { struct controller *next; struct semaphore crit_sect; /* critical section semaphore */ - void *hpc_ctlr_handle; /* HPC controller handle */ + struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ struct pci_dev *pci_dev; struct pci_bus *pci_bus; - struct event_info event_queue[10]; + struct event_info event_queue[MAX_EVENTS]; struct slot *slot; struct hpc_ops *hpc_ops; wait_queue_head_t queue; /* sleep & wake process */ u8 next_event; - u8 seg; u8 bus; u8 device; u8 function; - u8 rev; u8 slot_device_offset; - u8 add_support; - enum pci_bus_speed speed; u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */ u8 slot_bus; /* Bus where the slots handled by this controller sit */ u8 ctrlcap; @@ -250,14 +257,7 @@ enum php_ctlr_type { ACPI }; -typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id); - -int pcie_init(struct controller *ctrl, struct pcie_device *dev, - php_intr_callback_t attention_button_callback, - php_intr_callback_t switch_change_callback, - php_intr_callback_t presence_change_callback, - php_intr_callback_t power_fault_callback); - +int pcie_init(struct controller *ctrl, struct pcie_device *dev); /* This has no meaning for PCI Express, as there is only 1 slot per port */ int pcie_get_ctlr_slot_config(struct controller *ctrl, diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index be608563e8b..701243ea589 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -27,17 +27,11 @@ * */ -#include #include #include #include #include -#include -#include -#include #include -#include -#include #include "pciehp.h" #include @@ -381,11 +375,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ pdev = dev->port; ctrl->pci_dev = pdev; - rc = pcie_init(ctrl, dev, - (php_intr_callback_t) pciehp_handle_attention_button, - (php_intr_callback_t) pciehp_handle_switch_change, - (php_intr_callback_t) pciehp_handle_presence_change, - (php_intr_callback_t) pciehp_handle_power_fault); + rc = pcie_init(ctrl, dev); if (rc) { dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); goto err_out_free_ctrl; @@ -421,8 +411,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ first_device_num = ctrl->slot_device_offset; num_ctlr_slots = ctrl->num_slots; - ctrl->add_support = 1; - /* Setup the slot information structures */ rc = init_slots(ctrl); if (rc) { diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index b60e4973289..dcfbfffa17c 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -27,15 +27,9 @@ * */ -#include #include #include #include -#include -#include -#include -#include -#include #include #include #include "../pci.h" @@ -64,10 +58,9 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) taskInfo = &(ctrl->event_queue[ctrl->next_event]); p_slot = pciehp_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); - ctrl->next_event = (ctrl->next_event + 1) % 10; + ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; taskInfo->hp_slot = hp_slot; rc++; @@ -118,12 +111,11 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) * what to do */ taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; + ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; taskInfo->hp_slot = hp_slot; rc++; p_slot = pciehp_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); if (getstatus) { @@ -131,14 +123,12 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) * Switch opened */ info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); - p_slot->switch_save = 0; taskInfo->event_type = INT_SWITCH_OPEN; } else { /* * Switch closed */ info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); - p_slot->switch_save = 0x10; taskInfo->event_type = INT_SWITCH_CLOSE; } @@ -152,7 +142,7 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; + u8 presence_save, rc = 0; struct event_info *taskInfo; /* Presence Change */ @@ -162,7 +152,7 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) * what to do */ taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; + ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; taskInfo->hp_slot = hp_slot; rc++; @@ -171,8 +161,8 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) /* Switch is open, assume a presence change * Save the presence state */ - p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); - if (p_slot->presence_save) { + p_slot->hpc_ops->get_adapter_status(p_slot, &presence_save); + if (presence_save) { /* * Card Present */ @@ -206,7 +196,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) * what to do */ taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; + ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; taskInfo->hp_slot = hp_slot; rc++; @@ -279,11 +269,10 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) * Configures board * */ -static u32 board_added(struct slot *p_slot) +static int board_added(struct slot *p_slot) { u8 hp_slot; - u32 temp_register = 0xFFFFFFFF; - u32 rc = 0; + int rc = 0; struct controller *ctrl = p_slot->ctrl; hp_slot = p_slot->device - ctrl->slot_device_offset; @@ -333,8 +322,6 @@ static u32 board_added(struct slot *p_slot) /* Check for a power fault */ if (p_slot->status == 0xFF) { /* power fault occurred, but it was benign */ - temp_register = 0xFFFFFFFF; - dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register); rc = POWER_FAILURE; p_slot->status = 0; goto err_exit; @@ -348,8 +335,6 @@ static u32 board_added(struct slot *p_slot) } p_slot->status = 0; - p_slot->switch_save = 0x10; - p_slot->is_a_board = 0x01; /* * Some PCI Express root ports require fixup after hot-plug operation. @@ -380,11 +365,11 @@ err_exit: * remove_board - Turns off slot and LED's * */ -static u32 remove_board(struct slot *p_slot) +static int remove_board(struct slot *p_slot) { u8 device; u8 hp_slot; - u32 rc; + int rc; struct controller *ctrl = p_slot->ctrl; if (pciehp_unconfigure_device(p_slot)) @@ -398,9 +383,7 @@ static u32 remove_board(struct slot *p_slot) dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); /* Change status to shutdown */ - if (p_slot->is_a_board) - p_slot->status = 0x01; - p_slot->configured = 0; + p_slot->status = 0x01; /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); @@ -428,9 +411,6 @@ static u32 remove_board(struct slot *p_slot) /* Done with exclusive hardware access */ up(&ctrl->crit_sect); - p_slot->switch_save = 0x10; - p_slot->is_a_board = 0; - return 0; } @@ -633,7 +613,7 @@ static void interrupt_event_handler(struct controller *ctrl) while (change) { change = 0; - for (loop = 0; loop < 10; loop++) { + for (loop = 0; loop < MAX_EVENTS; loop++) { if (ctrl->event_queue[loop].event_type != 0) { hp_slot = ctrl->event_queue[loop].hp_slot; @@ -816,21 +796,11 @@ int pciehp_enable_slot(struct slot *p_slot) } up(&p_slot->ctrl->crit_sect); - p_slot->configured = 0; - p_slot->is_a_board = 1; - - /* 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_latch_status(p_slot, &getstatus); - p_slot->switch_save = !getstatus? 0x10:0; rc = board_added(p_slot); if (rc) { - /* 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_latch_status(p_slot, &getstatus); - p_slot->switch_save = !getstatus? 0x10:0; } if (p_slot) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index ef79ca1f38d..5358547f9ee 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -27,16 +27,10 @@ * */ -#include #include #include #include -#include -#include -#include -#include #include -#include #include "../pci.h" #include "pciehp.h" @@ -217,23 +211,6 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct #define MRL_STATE 0x0020 #define PRSN_STATE 0x0040 -struct php_ctlr_state_s { - struct php_ctlr_state_s *pnext; - struct pci_dev *pci_dev; - unsigned int irq; - unsigned long flags; /* spinlock's */ - u32 slot_device_offset; - u32 num_slots; - struct timer_list int_poll_timer; /* Added for poll event */ - php_intr_callback_t attention_button_callback; - php_intr_callback_t switch_change_callback; - php_intr_callback_t presence_change_callback; - php_intr_callback_t power_fault_callback; - void *callback_instance_id; - struct ctrl_reg *creg; /* Ptr to controller register space */ -}; - - static spinlock_t hpc_event_lock; DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ @@ -1248,12 +1225,7 @@ static struct hpc_ops pciehp_hpc_ops = { .check_lnk_status = hpc_check_lnk_status, }; -int pcie_init(struct controller * ctrl, - struct pcie_device *dev, - php_intr_callback_t attention_button_callback, - php_intr_callback_t switch_change_callback, - php_intr_callback_t presence_change_callback, - php_intr_callback_t power_fault_callback) +int pcie_init(struct controller * ctrl, struct pcie_device *dev) { struct php_ctlr_state_s *php_ctlr, *p; void *instance_id = ctrl; @@ -1362,10 +1334,10 @@ int pcie_init(struct controller * ctrl, dbg("HPC interrupt = %d\n", php_ctlr->irq); /* Save interrupt callback info */ - php_ctlr->attention_button_callback = attention_button_callback; - php_ctlr->switch_change_callback = switch_change_callback; - php_ctlr->presence_change_callback = presence_change_callback; - php_ctlr->power_fault_callback = power_fault_callback; + php_ctlr->attention_button_callback = pciehp_handle_attention_button; + php_ctlr->switch_change_callback = pciehp_handle_switch_change; + php_ctlr->presence_change_callback = pciehp_handle_presence_change; + php_ctlr->power_fault_callback = pciehp_handle_power_fault; php_ctlr->callback_instance_id = instance_id; /* return PCI Controller Info */ diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 1d185c1bc77..647673a7d22 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -27,13 +27,9 @@ * */ -#include #include #include #include -#include -#include -#include #include #include "../pci.h" #include "pciehp.h" diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c index c823cfa42ee..5d184582331 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/pciehprm_acpi.c @@ -24,18 +24,12 @@ * */ -#include #include #include #include #include -#include #include -#include #include -#include -#include -#include #include #include #include "pciehp.h" diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c index 32371cd19e3..6447642f78c 100644 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c @@ -27,25 +27,13 @@ * */ -#include #include #include #include #include #include -#include #include -#include #include "pciehp.h" -#include "pciehprm_nonacpi.h" - - -int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) -{ - - *sun = (u8) (ctrl->first_slot); - return 0; -} void get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) -- cgit v1.2.3 From 1a9ed1bfe2fb17cc30227a12a3c1212128bb78b6 Mon Sep 17 00:00:00 2001 From: "rajesh.shah@intel.com" Date: Mon, 31 Oct 2005 16:20:10 -0800 Subject: [PATCH] pciehp: reduce debug message verbosity Reduce the number of debug messages generated if pciehp debug is enabled. I tried to restrict this to removing debug messages that are either early-driver-debug type messages, or print information that can be inferred through other debug prints. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 5 ---- drivers/pci/hotplug/pciehp_core.c | 9 ------ drivers/pci/hotplug/pciehp_ctrl.c | 24 ++++++++-------- drivers/pci/hotplug/pciehp_hpc.c | 59 +++++++++++---------------------------- 4 files changed, 28 insertions(+), 69 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 314989a3a93..e1c2cea305f 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -207,12 +207,9 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) p_slot = ctrl->slot; - dbg("p_slot = %p\n", p_slot); - while (p_slot && (p_slot->device != device)) { tmp_slot = p_slot; p_slot = p_slot->next; - dbg("In while loop, p_slot = %p\n", p_slot); } if (p_slot == NULL) { err("ERROR: pciehp_find_slot device=0x%x\n", device); @@ -228,7 +225,6 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl) DECLARE_WAITQUEUE(wait, current); - dbg("%s : start\n", __FUNCTION__); add_wait_queue(&ctrl->queue, &wait); if (!pciehp_poll_mode) /* Sleep for up to 1 second */ @@ -240,7 +236,6 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl) if (signal_pending(current)) retval = -EINTR; - dbg("%s : end\n", __FUNCTION__); return retval; } diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 701243ea589..0bfc3732592 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -106,8 +106,6 @@ static int init_slots(struct controller *ctrl) u32 slot_number; int result = -ENOMEM; - dbg("%s\n",__FUNCTION__); - number_of_slots = ctrl->num_slots; slot_device = ctrl->slot_device_offset; slot_number = ctrl->first_slot; @@ -362,7 +360,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ u8 value; struct pci_dev *pdev; - dbg("%s: Called by hp_drv\n", __FUNCTION__); ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); @@ -370,8 +367,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ } memset(ctrl, 0, sizeof(struct controller)); - dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid); - pdev = dev->port; ctrl->pci_dev = pdev; @@ -389,7 +384,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ rc = -ENOMEM; goto err_out_unmap_mmio_region; } - dbg("%s: ctrl->pci_bus %p\n", __FUNCTION__, ctrl->pci_bus); memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); ctrl->bus = pdev->bus->number; /* ctrl bus */ ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */ @@ -419,7 +413,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ } t_slot = pciehp_find_slot(ctrl, first_device_num); - dbg("%s: t_slot %p\n", __FUNCTION__, t_slot); /* Finish setting up the hot plug ctrl device */ ctrl->next_event = 0; @@ -436,7 +429,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ down(&ctrl->crit_sect); t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ - dbg("%s: adpater value %x\n", __FUNCTION__, value); if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ @@ -585,7 +577,6 @@ static void __exit pcied_cleanup(void) dbg("unload_pciehpd()\n"); unload_pciehpd(); - dbg("pcie_port_service_unregister\n"); pcie_port_service_unregister(&hpdriver_portdrv); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index dcfbfffa17c..5e582eca21d 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -277,7 +277,9 @@ static int board_added(struct slot *p_slot) hp_slot = p_slot->device - ctrl->slot_device_offset; - dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, p_slot->device, ctrl->slot_device_offset, hp_slot); + dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n", + __FUNCTION__, p_slot->device, + ctrl->slot_device_offset, hp_slot); /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); @@ -305,9 +307,7 @@ static int board_added(struct slot *p_slot) up(&ctrl->crit_sect); /* Wait for ~1 second */ - dbg("%s: before long_delay\n", __FUNCTION__); wait_for_ctrl_irq (ctrl); - dbg("%s: afterlong_delay\n", __FUNCTION__); /* Check link training status */ rc = p_slot->hpc_ops->check_lnk_status(ctrl); @@ -444,13 +444,15 @@ static void pciehp_pushbutton_thread(unsigned long slot) p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (getstatus) { p_slot->state = POWEROFF_STATE; - dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); + dbg("%s: disabling bus:device(%x:%x)\n", __FUNCTION__, + p_slot->bus, p_slot->device); pciehp_disable_slot(p_slot); p_slot->state = STATIC_STATE; } else { p_slot->state = POWERON_STATE; - dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); + dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, + p_slot->bus, p_slot->device); if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ @@ -492,13 +494,15 @@ static void pciehp_surprise_rm_thread(unsigned long slot) p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (!getstatus) { p_slot->state = POWEROFF_STATE; - dbg("In removing board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); + dbg("%s: removing bus:device(%x:%x)\n", + __FUNCTION__, p_slot->bus, p_slot->device); pciehp_disable_slot(p_slot); p_slot->state = STATIC_STATE; } else { p_slot->state = POWERON_STATE; - dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); + dbg("%s: adding bus:device(%x:%x)\n", + __FUNCTION__, p_slot->bus, p_slot->device); if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ @@ -564,7 +568,6 @@ int pciehp_event_start_thread(void) err ("Can't start up our event thread\n"); return -1; } - dbg("Our event thread pid = %d\n", pid); return 0; } @@ -572,9 +575,7 @@ int pciehp_event_start_thread(void) void pciehp_event_stop_thread(void) { event_finished = 1; - dbg("event_thread finish command given\n"); up(&event_semaphore); - dbg("wait for event_thread to exit\n"); down(&event_exit); } @@ -619,8 +620,6 @@ static void interrupt_event_handler(struct controller *ctrl) p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - dbg("hp_slot %d, p_slot %p\n", hp_slot, p_slot); - if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { dbg("button cancel\n"); del_timer(&p_slot->task_event); @@ -712,7 +711,6 @@ static void interrupt_event_handler(struct controller *ctrl) p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; p_slot->task_event.data = (unsigned long) p_slot; - dbg("add_timer p_slot = %p\n", (void *) p_slot); add_timer(&p_slot->task_event); } } diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 5358547f9ee..5c812b85884 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -274,7 +274,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) DBG_ENTER_ROUTINE - dbg("%s : Enter\n", __FUNCTION__); if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; @@ -285,7 +284,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return retval; } - dbg("%s : hp_register_read_word SLOT_STATUS %x\n", __FUNCTION__, slot_status); if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { /* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue @@ -293,14 +291,11 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__); } - dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd); retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE); if (retval) { err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); return retval; } - dbg("%s : hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd | CMD_CMPL_INTR_ENABLE); - dbg("%s : Exit\n", __FUNCTION__); DBG_LEAVE_ROUTINE return retval; @@ -516,7 +511,8 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) u16 slot_ctrl; int rc = 0; - dbg("%s: \n", __FUNCTION__); + DBG_ENTER_ROUTINE + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; @@ -532,7 +528,6 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return rc; } - dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); switch (value) { case 0 : /* turn off */ @@ -553,6 +548,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) pcie_write_cmd(slot, slot_cmd); dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); + DBG_LEAVE_ROUTINE return rc; } @@ -564,7 +560,8 @@ static void hpc_set_green_led_on(struct slot *slot) u16 slot_ctrl; int rc = 0; - dbg("%s: \n", __FUNCTION__); + DBG_ENTER_ROUTINE + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return ; @@ -581,7 +578,6 @@ static void hpc_set_green_led_on(struct slot *slot) err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return; } - dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100; if (!pciehp_poll_mode) slot_cmd = slot_cmd | HP_INTR_ENABLE; @@ -589,6 +585,7 @@ static void hpc_set_green_led_on(struct slot *slot) pcie_write_cmd(slot, slot_cmd); dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); + DBG_LEAVE_ROUTINE return; } @@ -599,7 +596,8 @@ static void hpc_set_green_led_off(struct slot *slot) u16 slot_ctrl; int rc = 0; - dbg("%s: \n", __FUNCTION__); + DBG_ENTER_ROUTINE + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return ; @@ -616,7 +614,6 @@ static void hpc_set_green_led_off(struct slot *slot) err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return; } - dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300; @@ -625,6 +622,7 @@ static void hpc_set_green_led_off(struct slot *slot) pcie_write_cmd(slot, slot_cmd); dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); + DBG_LEAVE_ROUTINE return; } @@ -635,7 +633,8 @@ static void hpc_set_green_led_blink(struct slot *slot) u16 slot_ctrl; int rc = 0; - dbg("%s: \n", __FUNCTION__); + DBG_ENTER_ROUTINE + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return ; @@ -652,7 +651,6 @@ static void hpc_set_green_led_blink(struct slot *slot) err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return; } - dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200; @@ -661,6 +659,7 @@ static void hpc_set_green_led_blink(struct slot *slot) pcie_write_cmd(slot, slot_cmd); dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); + DBG_LEAVE_ROUTINE return; } @@ -757,7 +756,6 @@ static int hpc_power_on_slot(struct slot * slot) int retval = 0; DBG_ENTER_ROUTINE - dbg("%s: \n", __FUNCTION__); if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); @@ -776,8 +774,6 @@ static int hpc_power_on_slot(struct slot * slot) err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return retval; } - dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), - slot_ctrl); slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; @@ -806,7 +802,6 @@ static int hpc_power_off_slot(struct slot * slot) int retval = 0; DBG_ENTER_ROUTINE - dbg("%s: \n", __FUNCTION__); if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); @@ -825,8 +820,6 @@ static int hpc_power_off_slot(struct slot * slot) err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return retval; } - dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), - slot_ctrl); slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; @@ -901,7 +894,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) return IRQ_NONE; } - dbg("%s: Set Mask Hot-plug Interrupt Enable\n", __FUNCTION__); dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; @@ -910,7 +902,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); return IRQ_NONE; } - dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { @@ -926,14 +917,12 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } - dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); } if (intr_loc & CMD_COMPLETED) { /* * Command Complete Interrupt Pending */ - dbg("%s: In Command Complete Interrupt Pending\n", __FUNCTION__); wake_up_interruptible(&ctrl->queue); } @@ -966,7 +955,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) } dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__); - dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); @@ -974,14 +962,12 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); return IRQ_NONE; } - dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } - dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); /* Clear command complete interrupt caused by this write */ temp_word = 0x1F; @@ -1254,8 +1240,8 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) pdev = dev->port; php_ctlr->pci_dev = pdev; /* save pci_dev in context */ - dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__, - pdev->vendor, pdev->device); + dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n", + __FUNCTION__, pdev->vendor, pdev->device); saved_cap_base = pcie_cap_base; @@ -1312,8 +1298,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) first = 0; } - dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) if (pci_resource_len(pdev, rc) > 0) dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc, @@ -1331,7 +1315,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) /* find the IRQ */ php_ctlr->irq = dev->irq; - dbg("HPC interrupt = %d\n", php_ctlr->irq); /* Save interrupt callback info */ php_ctlr->attention_button_callback = pciehp_handle_attention_button; @@ -1359,15 +1342,12 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); goto abort_free_ctlr; } - dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word); rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); goto abort_free_ctlr; } - dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base) - , slot_status); temp_word = 0x1F; /* Clear all events */ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); @@ -1375,7 +1355,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); goto abort_free_ctlr; } - dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word); if (pciehp_poll_mode) {/* Install interrupt polling code */ /* Install and start the interrupt polling timer */ @@ -1391,13 +1370,14 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) } } + dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); + rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); goto abort_free_ctlr; } - dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word); - dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap); intr_enable = intr_enable | PRSN_DETECT_ENABLE; @@ -1417,7 +1397,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) } else { temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; } - dbg("%s: temp_word %x\n", __FUNCTION__, temp_word); /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */ rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); @@ -1425,14 +1404,11 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); goto abort_free_ctlr; } - dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word); rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); goto abort_free_ctlr; } - dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, - SLOT_STATUS(ctrl->cap_base), slot_status); temp_word = 0x1F; /* Clear all events */ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); @@ -1440,7 +1416,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); goto abort_free_ctlr; } - dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word); rc = get_hp_hw_control_from_firmware(ctrl->pci_dev); if (rc) -- cgit v1.2.3 From 427bf532b5ad6db5addc2bce675d13f874397c0c Mon Sep 17 00:00:00 2001 From: "rajesh.shah@intel.com" Date: Mon, 31 Oct 2005 16:20:11 -0800 Subject: [PATCH] pciehp: request control of each hotplug controller individually This patch tweaks the way pciehp requests control of the hotplug hardware from BIOS. It now tries to invoke the ACPI _OSC method for a specific hotplug controller only, rather than walking the entire acpi namespace invoking all possible _OSC methods under all host bridges. This allows us to gain control of each hotplug controller individually, even if BIOS fails to give us control of some other hotplug controller in the system. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehprm_acpi.c | 9 ++++----- drivers/pci/pci-acpi.c | 11 +++-------- 2 files changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c index 5d184582331..5acdae3d52b 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/pciehprm_acpi.c @@ -143,12 +143,13 @@ static acpi_status acpi_run_oshp(acpi_handle handle) int get_hp_hw_control_from_firmware(struct pci_dev *dev) { acpi_status status; + acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev)); /* * Per PCI firmware specification, we should run the ACPI _OSC * method to get control of hotplug hardware before using it */ - /* Fixme: run _OSC for a specific host bridge, not all of them */ - status = pci_osc_control_set(OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); + status = pci_osc_control_set(handle, + OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); /* Fixme: fail native hotplug if _OSC does not exist for root ports */ if (status == AE_NOT_FOUND) { @@ -156,9 +157,7 @@ int get_hp_hw_control_from_firmware(struct pci_dev *dev) * Some older BIOS's don't support _OSC but support * OSHP to do the same thing */ - acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev)); - if (handle) - status = acpi_run_oshp(handle); + status = acpi_run_oshp(handle); } if (ACPI_FAILURE(status)) { err("Cannot get control of hotplug hardware\n"); diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index e9e37abe1f7..a9b00cc2d88 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -91,9 +91,7 @@ acpi_query_osc ( static acpi_status acpi_run_osc ( acpi_handle handle, - u32 level, - void *context, - void **retval ) + void *context) { acpi_status status; struct acpi_object_list input; @@ -184,7 +182,7 @@ EXPORT_SYMBOL(pci_osc_support_set); * * Attempt to take control from Firmware on requested control bits. **/ -acpi_status pci_osc_control_set(u32 flags) +acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) { acpi_status status; u32 ctrlset; @@ -198,10 +196,7 @@ acpi_status pci_osc_control_set(u32 flags) return AE_SUPPORT; } ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; - status = acpi_get_devices ( PCI_ROOT_HID_STRING, - acpi_run_osc, - ctrlset_buf, - NULL ); + status = acpi_run_osc(handle, ctrlset_buf); if (ACPI_FAILURE (status)) { ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; } -- cgit v1.2.3 From a3a45ec8f8edaf088449e37fe81c99cbf580b9bd Mon Sep 17 00:00:00 2001 From: "rajesh.shah@intel.com" Date: Mon, 31 Oct 2005 16:20:12 -0800 Subject: [PATCH] pciehp: clean-up how we request control of hotplug hardware This patch further tweaks how we request control of hotplug controller hardware from BIOS. We first search the ACPI namespace corresponding to a specific hotplug controller looking for an _OSC or OSHP method. On failure, we successively move to the ACPI parent object, till we hit the highest level host bridge in the hierarchy. This allows for different types of BIOS's which place the _OSC/OSHP methods at various places in the acpi namespace, while still not encroaching on the namespace of some other root level host bridge. This patch also introduces a new load time option (pciehp_force) that allows us to bypass all _OSC/OSHP checking. Not supporting these methods seems to be be the most common ACPI firmware problem we've run into. This will still _not_ allow the pciehp driver to work correctly if the BIOS really doesn't support pciehp (i.e. if it doesn't generate a hotplug interrupt). Use this option with caution. Some BIOS's may deliberately not build any _OSC/OSHP methods to make sure it retains control the hotplug hardware. Using the pciehp_force parameter for such systems can lead to two separate entities trying to control the same hardware. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 1 + drivers/pci/hotplug/pciehp_core.c | 3 ++ drivers/pci/hotplug/pciehp_hpc.c | 11 +++-- drivers/pci/hotplug/pciehprm_acpi.c | 92 ++++++++++++++++++++++++++++++------- 4 files changed, 88 insertions(+), 19 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e1c2cea305f..e71f78318d6 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -40,6 +40,7 @@ extern int pciehp_poll_mode; extern int pciehp_poll_time; extern int pciehp_debug; +extern int pciehp_force; /*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ #define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 0bfc3732592..8df70486034 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -39,6 +39,7 @@ int pciehp_debug; int pciehp_poll_mode; int pciehp_poll_time; +int pciehp_force; struct controller *pciehp_ctrl_list; #define DRIVER_VERSION "0.4" @@ -52,9 +53,11 @@ MODULE_LICENSE("GPL"); module_param(pciehp_debug, bool, 0644); module_param(pciehp_poll_mode, bool, 0644); module_param(pciehp_poll_time, int, 0644); +module_param(pciehp_force, bool, 0644); MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); +MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"); #define PCIE_MODULE_NAME "pciehp" diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 5c812b85884..2d2539ba730 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1417,9 +1417,14 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) goto abort_free_ctlr; } - rc = get_hp_hw_control_from_firmware(ctrl->pci_dev); - if (rc) - goto abort_free_ctlr; + if (pciehp_force) { + dbg("Bypassing BIOS check for pciehp use on %s\n", + pci_name(ctrl->pci_dev)); + } else { + rc = get_hp_hw_control_from_firmware(ctrl->pci_dev); + if (rc) + goto abort_free_ctlr; + } /* Add this HPC instance into the HPC list */ spin_lock(&list_lock); diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c index 5acdae3d52b..4d013f86b1a 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/pciehprm_acpi.c @@ -132,7 +132,7 @@ static acpi_status acpi_run_oshp(acpi_handle handle) /* run OSHP */ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); if (ACPI_FAILURE(status)) { - err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, + dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, status); } else { dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name); @@ -140,32 +140,92 @@ static acpi_status acpi_run_oshp(acpi_handle handle) return status; } +static int is_root_bridge(acpi_handle handle) +{ + acpi_status status; + struct acpi_device_info *info; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + int i; + + status = acpi_get_object_info(handle, &buffer); + if (ACPI_SUCCESS(status)) { + info = buffer.pointer; + if ((info->valid & ACPI_VALID_HID) && + !strcmp(PCI_ROOT_HID_STRING, + info->hardware_id.value)) { + acpi_os_free(buffer.pointer); + return 1; + } + if (info->valid & ACPI_VALID_CID) { + for (i=0; i < info->compatibility_id.count; i++) { + if (!strcmp(PCI_ROOT_HID_STRING, + info->compatibility_id.id[i].value)) { + acpi_os_free(buffer.pointer); + return 1; + } + } + } + } + return 0; +} + int get_hp_hw_control_from_firmware(struct pci_dev *dev) { acpi_status status; - acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev)); + acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); + struct pci_dev *pdev = dev; + u8 *path_name; /* * Per PCI firmware specification, we should run the ACPI _OSC - * method to get control of hotplug hardware before using it + * method to get control of hotplug hardware before using it. + * If an _OSC is missing, we look for an OSHP to do the same thing. + * To handle different BIOS behavior, we look for _OSC and OSHP + * within the scope of the hotplug controller and its parents, upto + * the host bridge under which this controller exists. */ - status = pci_osc_control_set(handle, - OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); - - /* Fixme: fail native hotplug if _OSC does not exist for root ports */ - if (status == AE_NOT_FOUND) { + while (!handle) { /* - * Some older BIOS's don't support _OSC but support - * OSHP to do the same thing + * This hotplug controller was not listed in the ACPI name + * space at all. Try to get acpi handle of parent pci bus. */ - status = acpi_run_oshp(handle); + if (!pdev || !pdev->bus->parent) + break; + dbg("Could not find %s in acpi namespace, trying parent\n", + pci_name(pdev)); + if (!pdev->bus->parent->self) + /* Parent must be a host bridge */ + handle = acpi_get_pci_rootbridge_handle( + pci_domain_nr(pdev->bus->parent), + pdev->bus->parent->number); + else + handle = DEVICE_ACPI_HANDLE( + &(pdev->bus->parent->self->dev)); + pdev = pdev->bus->parent->self; } - if (ACPI_FAILURE(status)) { - err("Cannot get control of hotplug hardware\n"); - return -1; + + while (handle) { + path_name = acpi_path_name(handle); + dbg("Trying to get hotplug control for %s \n", path_name); + status = pci_osc_control_set(handle, + OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); + if (status == AE_NOT_FOUND) + status = acpi_run_oshp(handle); + if (ACPI_SUCCESS(status)) { + dbg("Gained control for hotplug HW for pci %s (%s)\n", + pci_name(dev), path_name); + return 0; + } + if (is_root_bridge(handle)) + break; + chandle = handle; + status = acpi_get_parent(chandle, &handle); + if (ACPI_FAILURE(status)) + break; } - dbg("Sucess getting control of hotplug hardware\n"); - return 0; + err("Cannot get control of hotplug hardware for pci %s\n", + pci_name(dev)); + return -1; } void get_hp_params_from_firmware(struct pci_dev *dev, -- cgit v1.2.3 From 8239def1b56e0c0c8e0fd3754a12df3d60a64ed7 Mon Sep 17 00:00:00 2001 From: "rajesh.shah@intel.com" Date: Mon, 31 Oct 2005 16:20:13 -0800 Subject: [PATCH] pciehp: fix handling of power faults during hotplug The current pciehp implementation reports a power-fail error even if the condition has cleared by the time the corresponding interrupt handling code gets a chance to run. This patch fixes this problem. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp_hpc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 2d2539ba730..f2b9b7686f2 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -481,7 +481,6 @@ static int hpc_query_power_fault(struct slot * slot) u16 slot_status; u8 pwr_fault; int retval = 0; - u8 status; DBG_ENTER_ROUTINE @@ -493,15 +492,13 @@ static int hpc_query_power_fault(struct slot * slot) retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); if (retval) { - err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); + err("%s : Cannot check for power fault\n", __FUNCTION__); return retval; } pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); - status = (pwr_fault != 1) ? 1 : 0; DBG_LEAVE_ROUTINE - /* Note: Logic 0 => fault */ - return status; + return pwr_fault; } static int hpc_set_attention_status(struct slot *slot, u8 value) -- cgit v1.2.3 From 02f313b2cc5d8273e3f2ffa23fc72392b2174cef Mon Sep 17 00:00:00 2001 From: Meelis Roos Date: Sat, 29 Oct 2005 13:31:49 +0300 Subject: [PATCH] PCI: Fix VIA 686 PCI quirk names The quirk names for VIA 686 are mistyped in 2.6.14 (686 vs 868). S3 868 influence? :) Here is a patch to correct them. Signed-off-by: Meelis Roos Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5627ce1d2b3..afcbd50ffc0 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -462,11 +462,11 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev) pci_read_config_word(dev, 0x70, &hm); hm &= PCI_BASE_ADDRESS_IO_MASK; - quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c868 HW-mon"); + quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c686 HW-mon"); pci_read_config_dword(dev, 0x90, &smb); smb &= PCI_BASE_ADDRESS_IO_MASK; - quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c868 SMB"); + quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB"); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi ); -- cgit v1.2.3 From a5312e28c195f6118ba52fb8abe17cf2efc6a427 Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Tue, 1 Nov 2005 01:43:56 +0300 Subject: [PATCH] PCI: NCR 53c810 quirk Move the PPC fixup for old NCR 810 controllers to generic quirks - it's needed for Alpha, x86 and other architectures that use setup-bus.c. Thanks to Jay Estabrook for pointing out the issue. Signed-off-by: Ivan Kokshaysky Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/pci') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index afcbd50ffc0..3a4f49f4eff 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1243,6 +1243,21 @@ static void __devinit quirk_netmos(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos); + +static void __devinit fixup_rev1_53c810(struct pci_dev* dev) +{ + /* rev 1 ncr53c810 chips don't set the class at all which means + * they don't get their resources remapped. Fix that here. + */ + + if (dev->class == PCI_CLASS_NOT_DEFINED) { + printk(KERN_INFO "NCR 53c810 rev 1 detected, setting PCI class.\n"); + dev->class = PCI_CLASS_STORAGE_SCSI; + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); + + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { while (f < end) { -- cgit v1.2.3 From f8eb1005a5bdb019d2a4ff3ef8d8e8015b22afcb Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 28 Oct 2005 20:36:51 -0700 Subject: [PATCH] pci-driver: store_new_id() not inline store_new_id() should not be (and cannot be) inline; the function pointer is stored in a device_attribute table. Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 94e68c54d27..efb88c10ed1 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -37,7 +37,7 @@ struct pci_dynid { * Adds a new dynamic pci device ID to this driver, * and causes the driver to probe for all devices again. */ -static inline ssize_t +static ssize_t store_new_id(struct device_driver *driver, const char *buf, size_t count) { struct pci_dynid *dynid; -- cgit v1.2.3 From 863b18f4b5e7d9e6903b353328cf6fa084dbb619 Mon Sep 17 00:00:00 2001 From: Laurent riffard Date: Thu, 27 Oct 2005 23:12:54 +0200 Subject: [PATCH] PCI: automatically set device_driver.owner A nice feature of sysfs is that it can create the symlink from the driver to the module that is contained in it. It requires that the device_driver.owner is set, what is not the case for many PCI drivers. This patch allows pci_register_driver to set automatically the device_driver.owner for any PCI driver. Credits to Al Viro who suggested the method. Signed-off-by: Laurent Riffard Signed-off-by: Greg Kroah-Hartman -- drivers/ide/setup-pci.c | 12 +++++++----- drivers/pci/pci-driver.c | 9 +++++---- include/linux/ide.h | 3 ++- include/linux/pci.h | 10 ++++++++-- 4 files changed, 22 insertions(+), 12 deletions(-) --- drivers/pci/pci-driver.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index efb88c10ed1..a9046d4b8af 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -364,15 +364,16 @@ static struct kobj_type pci_driver_kobj_type = { }; /** - * pci_register_driver - register a new pci driver + * __pci_register_driver - register a new pci driver * @drv: the driver structure to register + * @owner: owner module of drv * * Adds the driver structure to the list of registered drivers. * Returns a negative value on error, otherwise 0. * If no error occurred, the driver remains registered even if * no device was claimed during registration. */ -int pci_register_driver(struct pci_driver *drv) +int __pci_register_driver(struct pci_driver *drv, struct module *owner) { int error; @@ -389,7 +390,7 @@ int pci_register_driver(struct pci_driver *drv) printk(KERN_WARNING "Warning: PCI driver %s has a struct " "device_driver shutdown method, please update!\n", drv->name); - drv->driver.owner = drv->owner; + drv->driver.owner = owner; drv->driver.kobj.ktype = &pci_driver_kobj_type; spin_lock_init(&drv->dynids.lock); @@ -526,7 +527,7 @@ postcore_initcall(pci_driver_init); EXPORT_SYMBOL(pci_match_id); EXPORT_SYMBOL(pci_match_device); -EXPORT_SYMBOL(pci_register_driver); +EXPORT_SYMBOL(__pci_register_driver); EXPORT_SYMBOL(pci_unregister_driver); EXPORT_SYMBOL(pci_dev_driver); EXPORT_SYMBOL(pci_bus_type); -- cgit v1.2.3 From 5fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6 Mon Sep 17 00:00:00 2001 From: John Rose Date: Fri, 4 Nov 2005 15:38:50 -0600 Subject: [PATCH] dlpar regression for ppc64 - probe change This patch contains the driver bits for enabling DLPAR and PCI Hotplug for the new OF-based PCI probe. This functionality was regressed when the new PCI approach was introduced. Please apply if appropriate. Signed-off-by: John Rose Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 79 +++++++++++-------------------------- drivers/pci/hotplug/rpaphp.h | 2 + drivers/pci/hotplug/rpaphp_pci.c | 76 +++++++++++++++++++++++++---------- 3 files changed, 81 insertions(+), 76 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index e8593a60ee8..cc03609f45d 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -134,43 +134,6 @@ static void rpadlpar_claim_one_bus(struct pci_bus *b) rpadlpar_claim_one_bus(child_bus); } -static int pci_add_secondary_bus(struct device_node *dn, - struct pci_dev *bridge_dev) -{ - struct pci_dn *pdn = dn->data; - struct pci_controller *hose = pdn->phb; - struct pci_bus *child; - u8 sec_busno; - - /* Get busno of downstream bus */ - pci_read_config_byte(bridge_dev, PCI_SECONDARY_BUS, &sec_busno); - - /* Allocate and add to children of bridge_dev->bus */ - child = pci_add_new_bus(bridge_dev->bus, bridge_dev, sec_busno); - if (!child) { - printk(KERN_ERR "%s: could not add secondary bus\n", __FUNCTION__); - return -ENOMEM; - } - - sprintf(child->name, "PCI Bus #%02x", child->number); - - /* Fixup subordinate bridge bases and resources */ - pcibios_fixup_bus(child); - - /* Claim new bus resources */ - rpadlpar_claim_one_bus(bridge_dev->bus); - - if (hose->last_busno < child->number) - hose->last_busno = child->number; - - pdn->bussubno = child->number; - - /* ioremap() for child bus, which may or may not succeed */ - remap_bus_range(child); - - return 0; -} - static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, struct device_node *dev_dn) { @@ -188,29 +151,41 @@ static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) { struct pci_dn *pdn = dn->data; - struct pci_controller *hose = pdn->phb; + struct pci_controller *phb = pdn->phb; struct pci_dev *dev = NULL; - /* Scan phb bus for EADS device, adding new one to bus->devices */ - if (!pci_scan_single_device(hose->bus, pdn->devfn)) { - printk(KERN_ERR "%s: found no device on bus\n", __FUNCTION__); + rpaphp_eeh_init_nodes(dn); + /* Add EADS device to PHB bus, adding new entry to bus->devices */ + dev = of_create_pci_dev(dn, phb->bus, pdn->devfn); + if (!dev) { + printk(KERN_ERR "%s: failed to create pci dev for %s\n", + __FUNCTION__, dn->full_name); return NULL; } + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || + dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) + of_scan_pci_bridge(dn, dev); + + rpaphp_init_new_devs(dev->subordinate); + + /* Claim new bus resources */ + rpadlpar_claim_one_bus(dev->bus); + + /* ioremap() for child bus, which may or may not succeed */ + (void) remap_bus_range(dev->bus); + /* Add new devices to global lists. Register in proc, sysfs. */ - pci_bus_add_devices(hose->bus); + pci_bus_add_devices(phb->bus); /* Confirm new bridge dev was created */ - dev = dlpar_find_new_dev(hose->bus, dn); + dev = dlpar_find_new_dev(phb->bus, dn); if (dev) { if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { printk(KERN_ERR "%s: unexpected header type %d\n", __FUNCTION__, dev->hdr_type); return NULL; } - - if (pci_add_secondary_bus(dn, dev)) - return NULL; } return dev; @@ -219,7 +194,6 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) { struct pci_dev *dev; - int rc; if (rpaphp_find_pci_bus(dn)) return -EINVAL; @@ -232,15 +206,6 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) return -EIO; } - if (dn->child) { - rc = rpaphp_config_pci_adapter(dev->subordinate); - if (rc < 0) { - printk(KERN_ERR "%s: unable to enable slot %s\n", - __FUNCTION__, drc_name); - return -EIO; - } - } - /* Add hotplug slot */ if (rpaphp_add_slot(dn)) { printk(KERN_ERR "%s: unable to add hotplug slot %s\n", @@ -435,6 +400,8 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) __FUNCTION__, drc_name); return -EIO; } + } else { + rpaphp_unconfig_pci_adapter(bus); } if (unmap_bus_range(bus)) { diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 71ea5f9bb28..57ea71a7bda 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -93,6 +93,8 @@ extern int rpaphp_claim_resource(struct pci_dev *dev, int resource); extern int rpaphp_enable_pci_slot(struct slot *slot); extern int register_pci_slot(struct slot *slot); extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); +extern void rpaphp_init_new_devs(struct pci_bus *bus); +extern void rpaphp_eeh_init_nodes(struct device_node *dn); extern int rpaphp_config_pci_adapter(struct pci_bus *bus); extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus); diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index f7c12d7dfcf..a7859a84d1a 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -154,8 +154,7 @@ exit: } /* Must be called before pci_bus_add_devices */ -static void -rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) +void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) { struct pci_dev *dev; @@ -184,6 +183,20 @@ rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) } } +static void rpaphp_eeh_add_bus_device(struct pci_bus *bus) +{ + struct pci_dev *dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + eeh_add_device_late(dev); + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + struct pci_bus *subbus = dev->subordinate; + if (subbus) + rpaphp_eeh_add_bus_device (subbus); + } + } +} + static int rpaphp_pci_config_bridge(struct pci_dev *dev) { u8 sec_busno; @@ -217,6 +230,13 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev) return 0; } +void rpaphp_init_new_devs(struct pci_bus *bus) +{ + rpaphp_fixup_new_pci_devices(bus, 0); + rpaphp_eeh_add_bus_device(bus); +} +EXPORT_SYMBOL_GPL(rpaphp_init_new_devs); + /***************************************************************************** rpaphp_pci_config_slot() will configure all devices under the given slot->dn and return the the first pci_dev. @@ -233,36 +253,51 @@ rpaphp_pci_config_slot(struct pci_bus *bus) if (!dn || !dn->child) return NULL; - slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { + of_scan_bus(dn, bus); + if (list_empty(&bus->devices)) { + err("%s: No new device found\n", __FUNCTION__); + return NULL; + } - /* pci_scan_slot should find all children */ - num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); - if (num) { - rpaphp_fixup_new_pci_devices(bus, 1); + rpaphp_init_new_devs(bus); pci_bus_add_devices(bus); - } - if (list_empty(&bus->devices)) { - err("%s: No new device found\n", __FUNCTION__); - return NULL; - } - list_for_each_entry(dev, &bus->devices, bus_list) { - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) - rpaphp_pci_config_bridge(dev); + dev = list_entry(&bus->devices, struct pci_dev, bus_list); + } else { + slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); + + /* pci_scan_slot should find all children */ + num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); + if (num) { + rpaphp_fixup_new_pci_devices(bus, 1); + pci_bus_add_devices(bus); + } + if (list_empty(&bus->devices)) { + err("%s: No new device found\n", __FUNCTION__); + return NULL; + } + list_for_each_entry(dev, &bus->devices, bus_list) { + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) + rpaphp_pci_config_bridge(dev); + + rpaphp_eeh_add_bus_device(bus); + } } return dev; } -static void enable_eeh(struct device_node *dn) +void rpaphp_eeh_init_nodes(struct device_node *dn) { struct device_node *sib; for (sib = dn->child; sib; sib = sib->sibling) - enable_eeh(sib); + rpaphp_eeh_init_nodes(sib); eeh_add_device_early(dn); return; } +EXPORT_SYMBOL_GPL(rpaphp_eeh_init_nodes); static void print_slot_pci_funcs(struct pci_bus *bus) { @@ -289,7 +324,7 @@ int rpaphp_config_pci_adapter(struct pci_bus *bus) if (!dn) goto exit; - enable_eeh(dn); + rpaphp_eeh_init_nodes(dn); dev = rpaphp_pci_config_slot(bus); if (!dev) { err("%s: can't find any devices.\n", __FUNCTION__); @@ -331,6 +366,7 @@ int rpaphp_unconfig_pci_adapter(struct pci_bus *bus) } return 0; } +EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter); static int setup_pci_hotplug_slot_info(struct slot *slot) { @@ -444,8 +480,8 @@ int rpaphp_enable_pci_slot(struct slot *slot) retval = rpaphp_config_pci_adapter(slot->bus); if (!retval) { slot->state = CONFIGURED; - dbg("%s: PCI devices in slot[%s] has been configured\n", - __FUNCTION__, slot->name); + info("%s: devices in slot[%s] configured\n", + __FUNCTION__, slot->name); } else { slot->state = NOT_CONFIGURED; dbg("%s: no pci_dev struct for adapter in slot[%s]\n", -- cgit v1.2.3 From 48b19148733b4826eeedfd8be9f19b61c8d010b1 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 6 Nov 2005 01:45:08 +0100 Subject: [PATCH] PCI: drivers/pci/: small cleanups This patch contains the following cleanups: - access.c should #include "pci.h" for getting the prototypes of it's global functions - hotplug/shpchp_pci.c: make the needlessly global function program_fw_provided_values() static Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/pci/access.c | 2 ++ drivers/pci/hotplug/shpchp_pci.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 2a42add7f56..ea16805a153 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -2,6 +2,8 @@ #include #include +#include "pci.h" + /* * This interrupt-safe spinlock protects all accesses to PCI * configuration space. diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index b8e95acea3b..38009bc0fd5 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -34,7 +34,7 @@ #include "../pci.h" #include "shpchp.h" -void program_fw_provided_values(struct pci_dev *dev) +static void program_fw_provided_values(struct pci_dev *dev) { u16 pci_cmd, pci_bctl; struct pci_dev *cdev; -- cgit v1.2.3 From b4033c1715cb5aa1dcb1a25bdaf71fea908bb3f1 Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Tue, 8 Nov 2005 21:42:33 -0800 Subject: [PATCH] PCI: Change MSI to use physical delivery mode always MSI hardcoded delivery mode to use logical delivery mode. Recently x86_64 moved to use physical mode addressing to support physflat mode. With this mode enabled noticed that my eth with MSI werent working. msi_address_init() was hardcoded to use logical mode for i386 and x86_64. So when we switch to use physical mode, things stopped working. Since anyway we dont use lowest priority delivery with MSI, its always directed to just a single CPU. Its safe and simpler to use physical mode always, even when we use logical delivery mode for IPI's or other ioapic RTE's. Signed-off-by: Ashok Raj Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a2033552423..202b7507a35 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -23,6 +23,8 @@ #include "pci.h" #include "msi.h" +#define MSI_TARGET_CPU first_cpu(cpu_online_map) + static DEFINE_SPINLOCK(msi_lock); static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; static kmem_cache_t* msi_cachep; @@ -92,6 +94,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) struct msi_desc *entry; struct msg_address address; unsigned int irq = vector; + unsigned int dest_cpu = first_cpu(cpu_mask); entry = (struct msi_desc *)msi_desc[vector]; if (!entry || !entry->dev) @@ -108,9 +111,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), &address.lo_address.value); address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; - address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) << - MSI_TARGET_CPU_SHIFT); - entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask); + address.lo_address.value |= (cpu_physical_id(dest_cpu) << + MSI_TARGET_CPU_SHIFT); + entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), address.lo_address.value); set_native_irq_info(irq, cpu_mask); @@ -123,9 +126,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) address.lo_address.value = readl(entry->mask_base + offset); address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; - address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) << - MSI_TARGET_CPU_SHIFT); - entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask); + address.lo_address.value |= (cpu_physical_id(dest_cpu) << + MSI_TARGET_CPU_SHIFT); + entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); writel(address.lo_address.value, entry->mask_base + offset); set_native_irq_info(irq, cpu_mask); break; @@ -259,14 +262,15 @@ static void msi_data_init(struct msg_data *msi_data, static void msi_address_init(struct msg_address *msi_address) { unsigned int dest_id; + unsigned long dest_phys_id = cpu_physical_id(MSI_TARGET_CPU); memset(msi_address, 0, sizeof(struct msg_address)); msi_address->hi_address = (u32)0; dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT); - msi_address->lo_address.u.dest_mode = MSI_DEST_MODE; + msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE; msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE; msi_address->lo_address.u.dest_id = dest_id; - msi_address->lo_address.value |= (MSI_TARGET_CPU << MSI_TARGET_CPU_SHIFT); + msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT); } static int msi_free_vector(struct pci_dev* dev, int vector, int reassign); -- cgit v1.2.3 From 6560aa5c430fd8a7002b6e7abc1ee6c42521b06b Mon Sep 17 00:00:00 2001 From: Rajesh Shah Date: Mon, 7 Nov 2005 13:37:36 -0800 Subject: [PATCH] PCI: fix namespace clashes Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 4 ++-- drivers/pci/hotplug/pciehp_hpc.c | 2 +- drivers/pci/hotplug/pciehprm_acpi.c | 4 ++-- drivers/pci/hotplug/pciehprm_nonacpi.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e71f78318d6..c42b68d3aa2 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -191,8 +191,8 @@ extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); /* pci functions */ extern int pciehp_configure_device (struct slot *p_slot); extern int pciehp_unconfigure_device (struct slot *p_slot); -extern int get_hp_hw_control_from_firmware(struct pci_dev *dev); -extern void get_hp_params_from_firmware(struct pci_dev *dev, +extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev); +extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index f2b9b7686f2..4a3cecca012 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1418,7 +1418,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) dbg("Bypassing BIOS check for pciehp use on %s\n", pci_name(ctrl->pci_dev)); } else { - rc = get_hp_hw_control_from_firmware(ctrl->pci_dev); + rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev); if (rc) goto abort_free_ctlr; } diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c index 4d013f86b1a..ae244e21862 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/pciehprm_acpi.c @@ -169,7 +169,7 @@ static int is_root_bridge(acpi_handle handle) return 0; } -int get_hp_hw_control_from_firmware(struct pci_dev *dev) +int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) { acpi_status status; acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); @@ -228,7 +228,7 @@ int get_hp_hw_control_from_firmware(struct pci_dev *dev) return -1; } -void get_hp_params_from_firmware(struct pci_dev *dev, +void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) { acpi_status status = AE_NOT_FOUND; diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c index 6447642f78c..29180dfe849 100644 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c @@ -35,13 +35,13 @@ #include #include "pciehp.h" -void get_hp_params_from_firmware(struct pci_dev *dev, +void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) { return; } -int get_hp_hw_control_from_firmware(struct pci_dev *dev) +int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) { return 0; } -- cgit v1.2.3