Commit c61b1d93 authored by Rolf Eike Beer's avatar Rolf Eike Beer Committed by Deepak Saxena

[PATCH] PCI Express Hotplug: splut pciehp_ctrl.c::configure_new_function

configure_new_function is way too big (>600 lines). Split it in 2 functions,
one for the new functions and one for bridges. And split out a small piece
from the bridge function which is used twice to it's own function.

Patch is huge because of the identation changes but does nothing than the
split and some minor coding style changes.
parent 30c6a0e8
......@@ -1958,36 +1958,58 @@ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func
return 0;
}
/*
* Configuration logic that involves the hotplug data structures and
* their bookkeeping
*/
/**
* 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
*
* configure_bridge: fill bridge's registers, either configure or disable it.
*/
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 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;
u8 class_code;
u16 temp_word;
u32 rc;
u32 temp_register;
u32 base;
u32 ID;
unsigned int devfn;
struct pci_resource *mem_node;
......@@ -2000,22 +2022,10 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
struct pci_resource *hold_bus_node;
struct irq_mapping irqs;
struct pci_func *new_slot;
struct pci_bus lpci_bus, *pci_bus;
struct resource_lists temp_resources;
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 */
/* 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);
......@@ -2033,9 +2043,6 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length);
/* set Secondary bus */
dbg("set Secondary bus = 0x%x\n", temp_byte);
dbg("func->bus %x\n", func->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);
......@@ -2058,12 +2065,14 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
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);
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);
dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base,
mem_node->length, mem_node->next);
}
if (resources->p_mem_head)
......@@ -2078,7 +2087,8 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
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);
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 */
......@@ -2110,19 +2120,15 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
/* 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 = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
hold_p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
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) {
if (hold_bus_node)
kfree(hold_bus_node);
if (hold_IO_node)
kfree(hold_IO_node);
if (hold_mem_node)
kfree(hold_mem_node);
if (hold_p_mem_node)
kfree(hold_p_mem_node);
return 1;
......@@ -2158,55 +2164,15 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
* memory range registers. Otherwise, fill in the range
* registers with values that disable them.
*/
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 = (u32)(mem_node->base >> 16);
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
RES_CHECK(mem_node->base + mem_node->length - 1, 16);
temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16);
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
} else {
temp_word = 0xFFFF;
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
temp_word = 0x0000;
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
kfree(hold_mem_node);
hold_mem_node = NULL;
}
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.
*/
if (p_mem_node) {
memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
p_mem_node->next = NULL;
/* set Pre Mem base and Limit registers */
RES_CHECK(p_mem_node->base, 16);
temp_word = (u32)(p_mem_node->base >> 16);
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16);
temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16);
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
} else {
temp_word = 0xFFFF;
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
temp_word = 0x0000;
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
kfree(hold_p_mem_node);
hold_p_mem_node = NULL;
}
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--;
......@@ -2238,7 +2204,9 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
new_slot->is_a_board = 1;
new_slot->status = 0;
rc = configure_new_device(ctrl, new_slot, 1, &temp_resources, func->bus, func->device);
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 */
......@@ -2250,7 +2218,7 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
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;
return(rc);
}
/* save the interrupt routing information */
......@@ -2368,7 +2336,7 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
hold_mem_node->base = mem_node->base + mem_node->length;
RES_CHECK(hold_mem_node->base, 16);
temp_word = (u32)((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);
......@@ -2387,7 +2355,7 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
/* configure end address */
RES_CHECK(mem_node->base - 1, 16);
temp_word = (u32)((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 */
......@@ -2423,7 +2391,7 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;
RES_CHECK(hold_p_mem_node->base, 16);
temp_word = (u32)((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);
......@@ -2442,7 +2410,7 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
func->p_mem_head = hold_p_mem_node;
RES_CHECK(p_mem_node->base - 1, 16);
temp_word = (u32)((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);
......@@ -2473,10 +2441,61 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
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;
u16 temp_word;
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);
rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code);
if (class_code == PCI_BASE_CLASS_DISPLAY)
return DEVICE_TYPE_NOT_SUPPORTED;
......@@ -2538,7 +2557,7 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
else {
if (prefetchable)
dbg("using MEM for PMEM\n");
mem_node=get_resource(&(resources->mem_head), (ulong)base);
mem_node = get_resource(&(resources->mem_head), (ulong)base);
}
/* allocate the resource to the board */
......@@ -2624,4 +2643,3 @@ static int configure_new_function(struct controller * ctrl, struct pci_func * fu
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment