Commit 19685246 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleed-2.5

into kroah.com:/home/greg/linux/BK/pci-hp-2.5
parents 7d5bea38 b8d261e0
...@@ -9,8 +9,7 @@ obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o ...@@ -9,8 +9,7 @@ obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o
pci_hotplug-objs := pci_hotplug_core.o \ pci_hotplug-objs := pci_hotplug_core.o
pci_hotplug_util.o
ifdef CONFIG_HOTPLUG_PCI_CPCI ifdef CONFIG_HOTPLUG_PCI_CPCI
pci_hotplug-objs += cpci_hotplug_core.o \ pci_hotplug-objs += cpci_hotplug_core.o \
......
...@@ -578,6 +578,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int ...@@ -578,6 +578,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1); bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
if (!bridge->io_head) { if (!bridge->io_head) {
err("out of memory\n"); err("out of memory\n");
kfree(bridge);
return; return;
} }
dbg("16bit I/O range: %04x-%04x\n", dbg("16bit I/O range: %04x-%04x\n",
...@@ -592,6 +593,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int ...@@ -592,6 +593,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1); bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
if (!bridge->io_head) { if (!bridge->io_head) {
err("out of memory\n"); err("out of memory\n");
kfree(bridge);
return; return;
} }
dbg("32bit I/O range: %08x-%08x\n", dbg("32bit I/O range: %08x-%08x\n",
...@@ -613,6 +615,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int ...@@ -613,6 +615,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1); bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
if (!bridge->mem_head) { if (!bridge->mem_head) {
err("out of memory\n"); err("out of memory\n");
kfree(bridge);
return; return;
} }
dbg("32bit Memory range: %08x-%08x\n", dbg("32bit Memory range: %08x-%08x\n",
...@@ -632,6 +635,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int ...@@ -632,6 +635,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1); bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
if (!bridge->p_mem_head) { if (!bridge->p_mem_head) {
err("out of memory\n"); err("out of memory\n");
kfree(bridge);
return; return;
} }
dbg("32bit Prefetchable memory range: %08x-%08x\n", dbg("32bit Prefetchable memory range: %08x-%08x\n",
...@@ -647,6 +651,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int ...@@ -647,6 +651,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1); bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1);
if (!bridge->p_mem_head) { if (!bridge->p_mem_head) {
err("out of memory\n"); err("out of memory\n");
kfree(bridge);
return; return;
} }
dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x\n", dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x\n",
......
...@@ -130,7 +130,7 @@ update_latch_status(struct hotplug_slot *hotplug_slot, u8 value) ...@@ -130,7 +130,7 @@ update_latch_status(struct hotplug_slot *hotplug_slot, u8 value)
return -EINVAL; return -EINVAL;
memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info)); memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info));
info.latch_status = value; info.latch_status = value;
return pci_hp_change_slot_info(hotplug_slot->name, &info); return pci_hp_change_slot_info(hotplug_slot, &info);
} }
static int static int
...@@ -142,7 +142,7 @@ update_adapter_status(struct hotplug_slot *hotplug_slot, u8 value) ...@@ -142,7 +142,7 @@ update_adapter_status(struct hotplug_slot *hotplug_slot, u8 value)
return -EINVAL; return -EINVAL;
memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info)); memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info));
info.adapter_status = value; info.adapter_status = value;
return pci_hp_change_slot_info(hotplug_slot->name, &info); return pci_hp_change_slot_info(hotplug_slot, &info);
} }
static int static int
......
...@@ -395,6 +395,8 @@ static int cpci_configure_bridge(struct pci_bus* bus, struct pci_dev* dev) ...@@ -395,6 +395,8 @@ static int cpci_configure_bridge(struct pci_bus* bus, struct pci_dev* dev)
/* Scan behind bridge */ /* Scan behind bridge */
n = pci_scan_bridge(bus, dev, max, 2); n = pci_scan_bridge(bus, dev, max, 2);
child = pci_find_bus(max + 1); child = pci_find_bus(max + 1);
if (!child)
return -ENODEV;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
pci_proc_attach_bus(child); pci_proc_attach_bus(child);
#endif #endif
......
...@@ -488,6 +488,8 @@ static int get_slot_mapping (struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *sl ...@@ -488,6 +488,8 @@ static int get_slot_mapping (struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *sl
bridgeSlot = 0xFF; bridgeSlot = 0xFF;
PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table(); PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
if (!PCIIRQRoutingInfoLength)
return -1;
len = (PCIIRQRoutingInfoLength->size - len = (PCIIRQRoutingInfoLength->size -
sizeof(struct irq_routing_table)) / sizeof(struct irq_info); sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
......
...@@ -188,6 +188,8 @@ static u8 handle_presence_change(u16 change, struct controller * ctrl) ...@@ -188,6 +188,8 @@ static u8 handle_presence_change(u16 change, struct controller * ctrl)
rc++; rc++;
p_slot = find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4)); p_slot = find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4));
if (!p_slot)
return 0;
// If the switch closed, must be a button // If the switch closed, must be a button
// If not in button mode, nevermind // If not in button mode, nevermind
...@@ -1765,19 +1767,17 @@ void cpqhp_event_stop_thread (void) ...@@ -1765,19 +1767,17 @@ void cpqhp_event_stop_thread (void)
static int update_slot_info (struct controller *ctrl, struct slot *slot) static int update_slot_info (struct controller *ctrl, struct slot *slot)
{ {
struct hotplug_slot_info *info; struct hotplug_slot_info *info;
char buffer[SLOT_NAME_SIZE];
int result; int result;
info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;
make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot);
info->power_status = get_slot_enabled(ctrl, slot); info->power_status = get_slot_enabled(ctrl, slot);
info->attention_status = cpq_get_attention_status(ctrl, slot); info->attention_status = cpq_get_attention_status(ctrl, slot);
info->latch_status = cpq_get_latch_status(ctrl, slot); info->latch_status = cpq_get_latch_status(ctrl, slot);
info->adapter_status = get_presence_status(ctrl, slot); info->adapter_status = get_presence_status(ctrl, slot);
result = pci_hp_change_slot_info(buffer, info); result = pci_hp_change_slot_info(slot->hotplug_slot, info);
kfree (info); kfree (info);
return result; return result;
} }
...@@ -1799,8 +1799,12 @@ static void interrupt_event_handler(struct controller *ctrl) ...@@ -1799,8 +1799,12 @@ static void interrupt_event_handler(struct controller *ctrl)
hp_slot = ctrl->event_queue[loop].hp_slot; hp_slot = ctrl->event_queue[loop].hp_slot;
func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0); func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
if (!func)
return;
p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
if (!p_slot)
return;
dbg("hp_slot %d, func %p, p_slot %p\n", dbg("hp_slot %d, func %p, p_slot %p\n",
hp_slot, func, p_slot); hp_slot, func, p_slot);
...@@ -2511,8 +2515,14 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f ...@@ -2511,8 +2515,14 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f
// Setup the IO, memory, and prefetchable windows // Setup the IO, memory, and prefetchable windows
io_node = get_max_resource(&(resources->io_head), 0x1000); io_node = get_max_resource(&(resources->io_head), 0x1000);
if (!io_node)
return -ENOMEM;
mem_node = get_max_resource(&(resources->mem_head), 0x100000); mem_node = get_max_resource(&(resources->mem_head), 0x100000);
if (!mem_node)
return -ENOMEM;
p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000); p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000);
if (!p_mem_node)
return -ENOMEM;
dbg("Setup the IO, memory, and prefetchable windows\n"); dbg("Setup the IO, memory, and prefetchable windows\n");
dbg("io_node\n"); dbg("io_node\n");
dbg("(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next); dbg("(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next);
......
...@@ -473,7 +473,7 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl) ...@@ -473,7 +473,7 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl)
p_byte += 3; p_byte += 3;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length))
return(2); return 2;
bus = p_ev_ctrl->bus; bus = p_ev_ctrl->bus;
device = p_ev_ctrl->device; device = p_ev_ctrl->device;
...@@ -490,20 +490,20 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl) ...@@ -490,20 +490,20 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl)
p_byte += 4; p_byte += 4;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length))
return(2); return 2;
// Skip forward to the next entry // Skip forward to the next entry
p_byte += (nummem + numpmem + numio + numbus) * 8; p_byte += (nummem + numpmem + numio + numbus) * 8;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length))
return(2); return 2;
p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte; p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte;
p_byte += 3; p_byte += 3;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length))
return(2); return 2;
bus = p_ev_ctrl->bus; bus = p_ev_ctrl->bus;
device = p_ev_ctrl->device; device = p_ev_ctrl->device;
...@@ -518,7 +518,7 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl) ...@@ -518,7 +518,7 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl)
p_byte += 4; p_byte += 4;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length))
return(2); return 2;
while (nummem--) { while (nummem--) {
mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
...@@ -530,15 +530,19 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl) ...@@ -530,15 +530,19 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl)
dbg("mem base = %8.8x\n",mem_node->base); dbg("mem base = %8.8x\n",mem_node->base);
p_byte += 4; p_byte += 4;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
return(2); kfree(mem_node);
return 2;
}
mem_node->length = *(u32*)p_byte; mem_node->length = *(u32*)p_byte;
dbg("mem length = %8.8x\n",mem_node->length); dbg("mem length = %8.8x\n",mem_node->length);
p_byte += 4; p_byte += 4;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
return(2); kfree(mem_node);
return 2;
}
mem_node->next = ctrl->mem_head; mem_node->next = ctrl->mem_head;
ctrl->mem_head = mem_node; ctrl->mem_head = mem_node;
...@@ -554,15 +558,19 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl) ...@@ -554,15 +558,19 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl)
dbg("pre-mem base = %8.8x\n",p_mem_node->base); dbg("pre-mem base = %8.8x\n",p_mem_node->base);
p_byte += 4; p_byte += 4;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
return(2); kfree(p_mem_node);
return 2;
}
p_mem_node->length = *(u32*)p_byte; p_mem_node->length = *(u32*)p_byte;
dbg("pre-mem length = %8.8x\n",p_mem_node->length); dbg("pre-mem length = %8.8x\n",p_mem_node->length);
p_byte += 4; p_byte += 4;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
return(2); kfree(p_mem_node);
return 2;
}
p_mem_node->next = ctrl->p_mem_head; p_mem_node->next = ctrl->p_mem_head;
ctrl->p_mem_head = p_mem_node; ctrl->p_mem_head = p_mem_node;
...@@ -578,15 +586,19 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl) ...@@ -578,15 +586,19 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl)
dbg("io base = %8.8x\n",io_node->base); dbg("io base = %8.8x\n",io_node->base);
p_byte += 4; p_byte += 4;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
return(2); kfree(io_node);
return 2;
}
io_node->length = *(u32*)p_byte; io_node->length = *(u32*)p_byte;
dbg("io length = %8.8x\n",io_node->length); dbg("io length = %8.8x\n",io_node->length);
p_byte += 4; p_byte += 4;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
return(2); kfree(io_node);
return 2;
}
io_node->next = ctrl->io_head; io_node->next = ctrl->io_head;
ctrl->io_head = io_node; ctrl->io_head = io_node;
...@@ -601,15 +613,18 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl) ...@@ -601,15 +613,18 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl)
bus_node->base = *(u32*)p_byte; bus_node->base = *(u32*)p_byte;
p_byte += 4; p_byte += 4;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
return(2); kfree(bus_node);
return 2;
}
bus_node->length = *(u32*)p_byte; bus_node->length = *(u32*)p_byte;
p_byte += 4; p_byte += 4;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) kfree(bus_node);
return(2); return 2;
}
bus_node->next = ctrl->bus_head; bus_node->next = ctrl->bus_head;
ctrl->bus_head = bus_node; ctrl->bus_head = bus_node;
...@@ -623,13 +638,11 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl) ...@@ -623,13 +638,11 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl)
rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head)); rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
if (rc) { if (rc)
return(rc); return(rc);
}
} else { } else {
if ((evbuffer[0] != 0) && (!ctrl->push_flag)) { if ((evbuffer[0] != 0) && (!ctrl->push_flag))
return(1); return 1;
}
} }
return 0; return 0;
......
...@@ -435,6 +435,8 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num ...@@ -435,6 +435,8 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num
u8 tbus, tdevice, tslot; u8 tbus, tdevice, tslot;
PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table(); PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
if (!PCIIRQRoutingInfoLength)
return -1;
len = (PCIIRQRoutingInfoLength->size - len = (PCIIRQRoutingInfoLength->size -
sizeof(struct irq_routing_table)) / sizeof(struct irq_info); sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
...@@ -1191,7 +1193,7 @@ int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func) ...@@ -1191,7 +1193,7 @@ int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func)
if (temp != func->config_space[cloop >> 2]) { if (temp != func->config_space[cloop >> 2]) {
dbg("Config space compare failure!!! offset = %x\n", cloop); dbg("Config space compare failure!!! offset = %x\n", cloop);
dbg("bus = %x, device = %x, function = %x\n", func->bus, func->device, func->function); dbg("bus = %x, device = %x, function = %x\n", func->bus, func->device, func->function);
dbg("temp = %x, config space = %x\n\n", temp, func->config_space[cloop]); dbg("temp = %x, config space = %x\n\n", temp, func->config_space[cloop >> 2]);
return 1; return 1;
} }
} }
......
...@@ -113,6 +113,8 @@ static int read_dev (char *buf, char **start, off_t offset, int len, int *eof, v ...@@ -113,6 +113,8 @@ static int read_dev (char *buf, char **start, off_t offset, int len, int *eof, v
while (slot) { while (slot) {
new_slot = cpqhp_slot_find(slot->bus, slot->device, 0); new_slot = cpqhp_slot_find(slot->bus, slot->device, 0);
if (!new_slot)
break;
out += sprintf(out, "assigned resources: memory\n"); out += sprintf(out, "assigned resources: memory\n");
index = 11; index = 11;
res = new_slot->mem_head; res = new_slot->mem_head;
......
...@@ -686,7 +686,6 @@ static int validate (struct slot *slot_cur, int opn) ...@@ -686,7 +686,6 @@ static int validate (struct slot *slot_cur, int opn)
int ibmphp_update_slot_info (struct slot *slot_cur) int ibmphp_update_slot_info (struct slot *slot_cur)
{ {
struct hotplug_slot_info *info; struct hotplug_slot_info *info;
char buffer[30];
int rc; int rc;
u8 bus_speed; u8 bus_speed;
u8 mode; u8 mode;
...@@ -697,7 +696,6 @@ int ibmphp_update_slot_info (struct slot *slot_cur) ...@@ -697,7 +696,6 @@ int ibmphp_update_slot_info (struct slot *slot_cur)
return -ENOMEM; return -ENOMEM;
} }
strncpy (buffer, slot_cur->hotplug_slot->name, 30);
info->power_status = SLOT_PWRGD (slot_cur->status); info->power_status = SLOT_PWRGD (slot_cur->status);
info->attention_status = SLOT_ATTN (slot_cur->status, slot_cur->ext_status); info->attention_status = SLOT_ATTN (slot_cur->status, slot_cur->ext_status);
info->latch_status = SLOT_LATCH (slot_cur->status); info->latch_status = SLOT_LATCH (slot_cur->status);
...@@ -735,7 +733,7 @@ int ibmphp_update_slot_info (struct slot *slot_cur) ...@@ -735,7 +733,7 @@ int ibmphp_update_slot_info (struct slot *slot_cur)
info->max_bus_speed = slot_cur->hotplug_slot->info->max_bus_speed; info->max_bus_speed = slot_cur->hotplug_slot->info->max_bus_speed;
// To do: bus_names // To do: bus_names
rc = pci_hp_change_slot_info (buffer, info); rc = pci_hp_change_slot_info (slot_cur->hotplug_slot, info);
kfree (info); kfree (info);
return rc; return rc;
} }
...@@ -1057,6 +1055,8 @@ static int ibm_configure_device (struct pci_func *func) ...@@ -1057,6 +1055,8 @@ static int ibm_configure_device (struct pci_func *func)
if (func->dev == NULL) { if (func->dev == NULL) {
dev0.bus = ibmphp_find_bus (func->busno); dev0.bus = ibmphp_find_bus (func->busno);
if (!dev0.bus)
return 0;
dev0.devfn = ((func->device << 3) + (func->function & 0x7)); dev0.devfn = ((func->device << 3) + (func->function & 0x7));
dev0.sysdata = dev0.bus->sysdata; dev0.sysdata = dev0.bus->sysdata;
...@@ -1097,6 +1097,8 @@ static int is_bus_empty (struct slot * slot_cur) ...@@ -1097,6 +1097,8 @@ static int is_bus_empty (struct slot * slot_cur)
continue; continue;
} }
tmp_slot = ibmphp_get_slot_from_physical_num (i); tmp_slot = ibmphp_get_slot_from_physical_num (i);
if (!tmp_slot)
return 0;
rc = slot_update (&tmp_slot); rc = slot_update (&tmp_slot);
if (rc) if (rc)
return 0; return 0;
...@@ -1219,6 +1221,8 @@ static int check_limitations (struct slot *slot_cur) ...@@ -1219,6 +1221,8 @@ static int check_limitations (struct slot *slot_cur)
for (i = slot_cur->bus_on->slot_min; i <= slot_cur->bus_on->slot_max; i++) { for (i = slot_cur->bus_on->slot_min; i <= slot_cur->bus_on->slot_max; i++) {
tmp_slot = ibmphp_get_slot_from_physical_num (i); tmp_slot = ibmphp_get_slot_from_physical_num (i);
if (!tmp_slot)
return -ENODEV;
if ((SLOT_PWRGD (tmp_slot->status)) && !(SLOT_CONNECT (tmp_slot->status))) if ((SLOT_PWRGD (tmp_slot->status)) && !(SLOT_CONNECT (tmp_slot->status)))
count++; count++;
} }
......
This diff is collapsed.
...@@ -951,6 +951,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) ...@@ -951,6 +951,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
if (rc) { if (rc) {
if (rc == -ENOMEM) { if (rc == -ENOMEM) {
ibmphp_remove_bus (bus, func->busno); ibmphp_remove_bus (bus, func->busno);
kfree (amount_needed);
return rc; return rc;
} }
retval = rc; retval = rc;
...@@ -1621,23 +1622,23 @@ int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end) ...@@ -1621,23 +1622,23 @@ int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end)
} }
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (cur_func->io[count]) { if (cur_func->io[i]) {
debug ("io[%d] exists \n", count); debug ("io[%d] exists \n", i);
if (the_end > 0) if (the_end > 0)
ibmphp_remove_resource (cur_func->io[count]); ibmphp_remove_resource (cur_func->io[i]);
cur_func->io[count] = NULL; cur_func->io[i] = NULL;
} }
if (cur_func->mem[count]) { if (cur_func->mem[i]) {
debug ("mem[%d] exists \n", count); debug ("mem[%d] exists \n", i);
if (the_end > 0) if (the_end > 0)
ibmphp_remove_resource (cur_func->mem[count]); ibmphp_remove_resource (cur_func->mem[i]);
cur_func->mem[count] = NULL; cur_func->mem[i] = NULL;
} }
if (cur_func->pfmem[count]) { if (cur_func->pfmem[i]) {
debug ("pfmem[%d] exists \n", count); debug ("pfmem[%d] exists \n", i);
if (the_end > 0) if (the_end > 0)
ibmphp_remove_resource (cur_func->pfmem[count]); ibmphp_remove_resource (cur_func->pfmem[i]);
cur_func->pfmem[count] = NULL; cur_func->pfmem[i] = NULL;
} }
} }
......
...@@ -46,8 +46,11 @@ enum pci_bus_speed { ...@@ -46,8 +46,11 @@ enum pci_bus_speed {
}; };
struct hotplug_slot; struct hotplug_slot;
struct hotplug_slot_core; struct hotplug_slot_attribute {
struct attribute attr;
ssize_t (*show)(struct hotplug_slot *, char *);
ssize_t (*store)(struct hotplug_slot *, const char *, size_t);
};
/** /**
* struct hotplug_slot_ops -the callbacks that the hotplug pci core can use * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use
* @owner: The module owner of this structure * @owner: The module owner of this structure
...@@ -131,45 +134,13 @@ struct hotplug_slot { ...@@ -131,45 +134,13 @@ struct hotplug_slot {
/* Variables below this are for use only by the hotplug pci core. */ /* Variables below this are for use only by the hotplug pci core. */
struct list_head slot_list; struct list_head slot_list;
struct hotplug_slot_core *core_priv; struct kobject kobj;
}; };
extern int pci_hp_register (struct hotplug_slot *slot); extern int pci_hp_register (struct hotplug_slot *slot);
extern int pci_hp_deregister (struct hotplug_slot *slot); extern int pci_hp_deregister (struct hotplug_slot *slot);
extern int pci_hp_change_slot_info (const char *name, extern int pci_hp_change_slot_info (struct hotplug_slot *slot,
struct hotplug_slot_info *info); struct hotplug_slot_info *info);
struct pci_dev_wrapped {
struct pci_dev *dev;
void *data;
};
struct pci_bus_wrapped {
struct pci_bus *bus;
void *data;
};
struct pci_visit {
int (* pre_visit_pci_bus) (struct pci_bus_wrapped *,
struct pci_dev_wrapped *);
int (* post_visit_pci_bus) (struct pci_bus_wrapped *,
struct pci_dev_wrapped *);
int (* pre_visit_pci_dev) (struct pci_dev_wrapped *,
struct pci_bus_wrapped *);
int (* visit_pci_dev) (struct pci_dev_wrapped *,
struct pci_bus_wrapped *);
int (* post_visit_pci_dev) (struct pci_dev_wrapped *,
struct pci_bus_wrapped *);
};
extern int pci_visit_dev (struct pci_visit *fn,
struct pci_dev_wrapped *wrapped_dev,
struct pci_bus_wrapped *wrapped_parent);
int pci_is_dev_in_use(struct pci_dev *dev);
int pci_remove_device_safe(struct pci_dev *dev);
#endif #endif
This diff is collapsed.
/*
* PCI HotPlug Utility functions
*
* Copyright (c) 1995,2001 Compaq Computer Corporation
* Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (c) 2001 IBM Corp.
*
* 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 <greg@kroah.com>
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include "pci_hotplug.h"
#if !defined(CONFIG_HOTPLUG_PCI_MODULE)
#define MY_NAME "pci_hotplug"
#else
#define MY_NAME THIS_MODULE->name
#endif
#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0)
#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
/* local variables */
static int debug;
/*
* This is code that scans the pci buses.
* Every bus and every function is presented to a custom
* function that can act upon it.
*/
static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_parent)
{
struct list_head *ln;
struct pci_dev *dev;
struct pci_dev_wrapped wrapped_dev;
int result = 0;
dbg("scanning bus %02x\n", wrapped_bus->bus->number);
if (fn->pre_visit_pci_bus) {
result = fn->pre_visit_pci_bus(wrapped_bus, wrapped_parent);
if (result)
return result;
}
ln = wrapped_bus->bus->devices.next;
while (ln != &wrapped_bus->bus->devices) {
dev = pci_dev_b(ln);
ln = ln->next;
memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
wrapped_dev.dev = dev;
result = pci_visit_dev(fn, &wrapped_dev, wrapped_bus);
if (result)
return result;
}
if (fn->post_visit_pci_bus)
result = fn->post_visit_pci_bus(wrapped_bus, wrapped_parent);
return result;
}
static int pci_visit_bridge (struct pci_visit * fn, struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_parent)
{
struct pci_bus *bus;
struct pci_bus_wrapped wrapped_bus;
int result = 0;
dbg("scanning bridge %02x, %02x\n", PCI_SLOT(wrapped_dev->dev->devfn),
PCI_FUNC(wrapped_dev->dev->devfn));
if (fn->visit_pci_dev) {
result = fn->visit_pci_dev(wrapped_dev, wrapped_parent);
if (result)
return result;
}
bus = wrapped_dev->dev->subordinate;
if(bus) {
memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
wrapped_bus.bus = bus;
result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev);
}
return result;
}
int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_parent)
{
struct pci_dev* dev = wrapped_dev ? wrapped_dev->dev : NULL;
int result = 0;
if (!dev)
return 0;
if (fn->pre_visit_pci_dev) {
result = fn->pre_visit_pci_dev(wrapped_dev, wrapped_parent);
if (result)
return result;
}
switch (dev->class >> 8) {
case PCI_CLASS_BRIDGE_PCI:
result = pci_visit_bridge(fn, wrapped_dev,
wrapped_parent);
if (result)
return result;
break;
default:
dbg("scanning device %02x, %02x\n",
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
if (fn->visit_pci_dev) {
result = fn->visit_pci_dev (wrapped_dev,
wrapped_parent);
if (result)
return result;
}
}
if (fn->post_visit_pci_dev)
result = fn->post_visit_pci_dev(wrapped_dev, wrapped_parent);
return result;
}
/**
* pci_is_dev_in_use - query devices' usage
* @dev: PCI device to query
*
* Queries whether a given PCI device is in use by a driver or not.
* Returns 1 if the device is in use, 0 if it is not.
*/
int pci_is_dev_in_use(struct pci_dev *dev)
{
/*
* dev->driver will be set if the device is in use by a new-style
* driver -- otherwise, check the device's regions to see if any
* driver has claimed them.
*/
int i;
int inuse = 0;
if (dev->driver) {
/* Assume driver feels responsible */
return 1;
}
for (i = 0; !dev->driver && !inuse && (i < 6); i++) {
if (!pci_resource_start(dev, i))
continue;
if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
inuse = check_region(pci_resource_start(dev, i),
pci_resource_len(dev, i));
} else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) {
inuse = check_mem_region(pci_resource_start(dev, i),
pci_resource_len(dev, i));
}
}
return inuse;
}
/**
* pci_remove_device_safe - remove an unused hotplug device
* @dev: the device to remove
*
* Delete the device structure from the device lists and
* notify userspace (/sbin/hotplug), but only if the device
* in question is not being used by a driver.
* Returns 0 on success.
*/
int pci_remove_device_safe(struct pci_dev *dev)
{
if (pci_is_dev_in_use(dev)) {
return -EBUSY;
}
pci_remove_device(dev);
return 0;
}
EXPORT_SYMBOL(pci_visit_dev);
EXPORT_SYMBOL(pci_is_dev_in_use);
EXPORT_SYMBOL(pci_remove_device_safe);
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
# #
obj-y += access.o probe.o pci.o pool.o quirks.o \ obj-y += access.o probe.o pci.o pool.o quirks.o \
names.o pci-driver.o search.o hotplug.o names.o pci-driver.o search.o hotplug.o \
pci-sysfs.o
obj-$(CONFIG_PM) += power.o obj-$(CONFIG_PM) += power.o
obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_PROC_FS) += proc.o
......
...@@ -2,6 +2,14 @@ ...@@ -2,6 +2,14 @@
#include <linux/module.h> #include <linux/module.h>
#include "pci.h" #include "pci.h"
#undef DEBUG
#ifdef DEBUG
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
int pci_hotplug (struct device *dev, char **envp, int num_envp, int pci_hotplug (struct device *dev, char **envp, int num_envp,
...@@ -57,13 +65,179 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp, ...@@ -57,13 +65,179 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
return 0; return 0;
} }
#else
static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_parent)
{
struct list_head *ln;
struct pci_dev *dev;
struct pci_dev_wrapped wrapped_dev;
int result = 0;
DBG("scanning bus %02x\n", wrapped_bus->bus->number);
if (fn->pre_visit_pci_bus) {
result = fn->pre_visit_pci_bus(wrapped_bus, wrapped_parent);
if (result)
return result;
}
ln = wrapped_bus->bus->devices.next;
while (ln != &wrapped_bus->bus->devices) {
dev = pci_dev_b(ln);
ln = ln->next;
memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
wrapped_dev.dev = dev;
result = pci_visit_dev(fn, &wrapped_dev, wrapped_bus);
if (result)
return result;
}
if (fn->post_visit_pci_bus)
result = fn->post_visit_pci_bus(wrapped_bus, wrapped_parent);
return result;
}
static int pci_visit_bridge (struct pci_visit * fn,
struct pci_dev_wrapped *wrapped_dev,
struct pci_bus_wrapped *wrapped_parent)
{
struct pci_bus *bus;
struct pci_bus_wrapped wrapped_bus;
int result = 0;
DBG("scanning bridge %02x, %02x\n", PCI_SLOT(wrapped_dev->dev->devfn),
PCI_FUNC(wrapped_dev->dev->devfn));
if (fn->visit_pci_dev) {
result = fn->visit_pci_dev(wrapped_dev, wrapped_parent);
if (result)
return result;
}
bus = wrapped_dev->dev->subordinate;
if(bus) {
memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
wrapped_bus.bus = bus;
result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev);
}
return result;
}
/**
* pci_visit_dev - scans the pci buses.
* Every bus and every function is presented to a custom
* function that can act upon it.
*/
int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev,
struct pci_bus_wrapped *wrapped_parent)
{
struct pci_dev* dev = wrapped_dev ? wrapped_dev->dev : NULL;
int result = 0;
if (!dev)
return 0;
if (fn->pre_visit_pci_dev) {
result = fn->pre_visit_pci_dev(wrapped_dev, wrapped_parent);
if (result)
return result;
}
switch (dev->class >> 8) {
case PCI_CLASS_BRIDGE_PCI:
result = pci_visit_bridge(fn, wrapped_dev,
wrapped_parent);
if (result)
return result;
break;
default:
DBG("scanning device %02x, %02x\n",
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
if (fn->visit_pci_dev) {
result = fn->visit_pci_dev (wrapped_dev,
wrapped_parent);
if (result)
return result;
}
}
if (fn->post_visit_pci_dev)
result = fn->post_visit_pci_dev(wrapped_dev, wrapped_parent);
return result;
}
EXPORT_SYMBOL(pci_visit_dev);
/**
* pci_is_dev_in_use - query devices' usage
* @dev: PCI device to query
*
* Queries whether a given PCI device is in use by a driver or not.
* Returns 1 if the device is in use, 0 if it is not.
*/
int pci_is_dev_in_use(struct pci_dev *dev)
{
/*
* dev->driver will be set if the device is in use by a new-style
* driver -- otherwise, check the device's regions to see if any
* driver has claimed them.
*/
int i;
int inuse = 0;
if (dev->driver) {
/* Assume driver feels responsible */
return 1;
}
for (i = 0; !dev->driver && !inuse && (i < 6); i++) {
if (!pci_resource_start(dev, i))
continue;
if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
inuse = check_region(pci_resource_start(dev, i),
pci_resource_len(dev, i));
} else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) {
inuse = check_mem_region(pci_resource_start(dev, i),
pci_resource_len(dev, i));
}
}
return inuse;
}
EXPORT_SYMBOL(pci_is_dev_in_use);
/**
* pci_remove_device_safe - remove an unused hotplug device
* @dev: the device to remove
*
* Delete the device structure from the device lists and
* notify userspace (/sbin/hotplug), but only if the device
* in question is not being used by a driver.
* Returns 0 on success.
*/
int pci_remove_device_safe(struct pci_dev *dev)
{
if (pci_is_dev_in_use(dev)) {
return -EBUSY;
}
pci_remove_device(dev);
return 0;
}
EXPORT_SYMBOL(pci_remove_device_safe);
#else /* CONFIG_HOTPLUG */
int pci_hotplug (struct device *dev, char **envp, int num_envp, int pci_hotplug (struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size) char *buffer, int buffer_size)
{ {
return -ENODEV; return -ENODEV;
} }
#endif
#endif /* CONFIG_HOTPLUG */
/** /**
* pci_insert_device - insert a pci device * pci_insert_device - insert a pci device
...@@ -81,6 +255,8 @@ pci_insert_device(struct pci_dev *dev, struct pci_bus *bus) ...@@ -81,6 +255,8 @@ pci_insert_device(struct pci_dev *dev, struct pci_bus *bus)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
pci_proc_attach_device(dev); pci_proc_attach_device(dev);
#endif #endif
/* add sysfs device files */
pci_create_sysfs_dev_files(dev);
} }
static void static void
......
/*
* drivers/pci/pci-sysfs.c
*
* (C) Copyright 2002 Greg Kroah-Hartman
* (C) Copyright 2002 IBM Corp.
*
* File attributes for PCI devices
*
* Modeled after usb's driverfs.c
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include "pci.h"
#if BITS_PER_LONG == 32
#define LONG_FORMAT "\t%08lx"
#else
#define LONG_FORMAT "\t%16lx"
#endif
/* show configuration fields */
#define pci_config_attr(field, format_string) \
static ssize_t \
show_##field (struct device *dev, char *buf) \
{ \
struct pci_dev *pdev; \
\
pdev = to_pci_dev (dev); \
return sprintf (buf, format_string, pdev->field); \
} \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
pci_config_attr(vendor, "%04x\n");
pci_config_attr(device, "%04x\n");
pci_config_attr(subsystem_vendor, "%04x\n");
pci_config_attr(subsystem_device, "%04x\n");
pci_config_attr(class, "%06x\n");
pci_config_attr(irq, "%u\n");
/* show resources */
static ssize_t
pci_show_resources(struct device * dev, char * buf)
{
struct pci_dev * pci_dev = to_pci_dev(dev);
char * str = buf;
int i;
for (i = 0; i < DEVICE_COUNT_RESOURCE && pci_resource_start(pci_dev,i); i++) {
str += sprintf(str,LONG_FORMAT LONG_FORMAT LONG_FORMAT "\n",
pci_resource_start(pci_dev,i),
pci_resource_end(pci_dev,i),
pci_resource_flags(pci_dev,i));
}
return (str - buf);
}
static DEVICE_ATTR(resource,S_IRUGO,pci_show_resources,NULL);
void pci_create_sysfs_dev_files (struct pci_dev *pdev)
{
struct device *dev = &pdev->dev;
/* current configuration's attributes */
device_create_file (dev, &dev_attr_vendor);
device_create_file (dev, &dev_attr_device);
device_create_file (dev, &dev_attr_subsystem_vendor);
device_create_file (dev, &dev_attr_subsystem_device);
device_create_file (dev, &dev_attr_class);
device_create_file (dev, &dev_attr_irq);
device_create_file (dev, &dev_attr_resource);
}
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
extern int pci_hotplug (struct device *dev, char **envp, int num_envp, extern int pci_hotplug (struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size); char *buffer, int buffer_size);
extern void pci_create_sysfs_dev_files(struct pci_dev *pdev);
...@@ -373,32 +373,6 @@ static struct seq_operations proc_bus_pci_devices_op = { ...@@ -373,32 +373,6 @@ static struct seq_operations proc_bus_pci_devices_op = {
struct proc_dir_entry *proc_bus_pci_dir; struct proc_dir_entry *proc_bus_pci_dir;
/* driverfs files */
static ssize_t pci_show_irq(struct device * dev, char * buf)
{
struct pci_dev * pci_dev = to_pci_dev(dev);
return sprintf(buf,"%u\n",pci_dev->irq);
}
static DEVICE_ATTR(irq,S_IRUGO,pci_show_irq,NULL);
static ssize_t pci_show_resources(struct device * dev, char * buf)
{
struct pci_dev * pci_dev = to_pci_dev(dev);
char * str = buf;
int i;
for (i = 0; i < DEVICE_COUNT_RESOURCE && pci_resource_start(pci_dev,i); i++) {
str += sprintf(str,LONG_FORMAT LONG_FORMAT LONG_FORMAT "\n",
pci_resource_start(pci_dev,i),
pci_resource_end(pci_dev,i),
pci_resource_flags(pci_dev,i));
}
return (str - buf);
}
static DEVICE_ATTR(resource,S_IRUGO,pci_show_resources,NULL);
int pci_proc_attach_device(struct pci_dev *dev) int pci_proc_attach_device(struct pci_dev *dev)
{ {
struct pci_bus *bus = dev->bus; struct pci_bus *bus = dev->bus;
...@@ -422,8 +396,6 @@ int pci_proc_attach_device(struct pci_dev *dev) ...@@ -422,8 +396,6 @@ int pci_proc_attach_device(struct pci_dev *dev)
e->data = dev; e->data = dev;
e->size = PCI_CFG_SPACE_SIZE; e->size = PCI_CFG_SPACE_SIZE;
device_create_file(&dev->dev,&dev_attr_irq);
device_create_file(&dev->dev,&dev_attr_resource);
return 0; return 0;
} }
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/dnotify.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
/* Random magic number */ /* Random magic number */
...@@ -716,6 +717,46 @@ static void hash_and_remove(struct dentry * dir, const char * name) ...@@ -716,6 +717,46 @@ static void hash_and_remove(struct dentry * dir, const char * name)
up(&dir->d_inode->i_sem); up(&dir->d_inode->i_sem);
} }
/**
* sysfs_update_file - update the modified timestamp on an object attribute.
* @kobj: object we're acting for.
* @attr: attribute descriptor.
*
* Also call dnotify for the dentry, which lots of userspace programs
* use.
*/
int sysfs_update_file(struct kobject * kobj, struct attribute * attr)
{
struct dentry * dir = kobj->dentry;
struct dentry * victim;
int res = -ENOENT;
down(&dir->d_inode->i_sem);
victim = get_dentry(dir, attr->name);
if (!IS_ERR(victim)) {
/* make sure dentry is really there */
if (victim->d_inode &&
(victim->d_parent->d_inode == dir->d_inode)) {
victim->d_inode->i_mtime = CURRENT_TIME;
dnotify_parent(victim, DN_MODIFY);
/**
* Drop reference from initial get_dentry().
*/
dput(victim);
res = 0;
}
/**
* Drop the reference acquired from get_dentry() above.
*/
dput(victim);
}
up(&dir->d_inode->i_sem);
return res;
}
/** /**
* sysfs_remove_file - remove an object attribute. * sysfs_remove_file - remove an object attribute.
......
...@@ -671,6 +671,37 @@ void pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t addr); ...@@ -671,6 +671,37 @@ void pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t addr);
extern struct pci_dev *isa_bridge; extern struct pci_dev *isa_bridge;
#endif #endif
/* Some worker functions that PCI Hotplug drivers find useful */
struct pci_dev_wrapped {
struct pci_dev *dev;
void *data;
};
struct pci_bus_wrapped {
struct pci_bus *bus;
void *data;
};
struct pci_visit {
int (* pre_visit_pci_bus) (struct pci_bus_wrapped *,
struct pci_dev_wrapped *);
int (* post_visit_pci_bus) (struct pci_bus_wrapped *,
struct pci_dev_wrapped *);
int (* pre_visit_pci_dev) (struct pci_dev_wrapped *,
struct pci_bus_wrapped *);
int (* visit_pci_dev) (struct pci_dev_wrapped *,
struct pci_bus_wrapped *);
int (* post_visit_pci_dev) (struct pci_dev_wrapped *,
struct pci_bus_wrapped *);
};
extern int pci_visit_dev(struct pci_visit *fn,
struct pci_dev_wrapped *wrapped_dev,
struct pci_bus_wrapped *wrapped_parent);
extern int pci_is_dev_in_use(struct pci_dev *dev);
extern int pci_remove_device_safe(struct pci_dev *dev);
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
/* Include architecture-dependent settings and functions */ /* Include architecture-dependent settings and functions */
......
...@@ -30,6 +30,9 @@ sysfs_remove_dir(struct kobject *); ...@@ -30,6 +30,9 @@ sysfs_remove_dir(struct kobject *);
extern int extern int
sysfs_create_file(struct kobject *, struct attribute *); sysfs_create_file(struct kobject *, struct attribute *);
extern int
sysfs_update_file(struct kobject *, struct attribute *);
extern void extern void
sysfs_remove_file(struct kobject *, struct attribute *); sysfs_remove_file(struct kobject *, struct attribute *);
......
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