diff options
130 files changed, 1013 insertions, 5557 deletions
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index 3984226a8b98..eeb1b1f2d548 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c | |||
| @@ -433,9 +433,8 @@ static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev) | |||
| 433 | return; /* only applies to certain Toshibas (so far) */ | 433 | return; /* only applies to certain Toshibas (so far) */ |
| 434 | 434 | ||
| 435 | /* Restore config space on Toshiba laptops */ | 435 | /* Restore config space on Toshiba laptops */ |
| 436 | mdelay(10); | ||
| 437 | pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size); | 436 | pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size); |
| 438 | pci_write_config_word(dev, PCI_INTERRUPT_LINE, dev->irq); | 437 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, (u8 *)&dev->irq); |
| 439 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, | 438 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, |
| 440 | pci_resource_start(dev, 0)); | 439 | pci_resource_start(dev, 0)); |
| 441 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, | 440 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, |
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index f72ea6aebcb1..a3aa45cbcfa0 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c | |||
| @@ -987,7 +987,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, | |||
| 987 | break; | 987 | break; |
| 988 | } | 988 | } |
| 989 | 989 | ||
| 990 | if ((res = kcalloc(1, sizeof(struct resource), GFP_KERNEL)) == NULL) { | 990 | if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { |
| 991 | printk(KERN_ERR "failed to alocate resource for iomem\n"); | 991 | printk(KERN_ERR "failed to alocate resource for iomem\n"); |
| 992 | return; | 992 | return; |
| 993 | } | 993 | } |
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 96736a119c91..801eeaeaf3de 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
| @@ -347,7 +347,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 347 | ((struct fnptr *)kretprobe_trampoline)->ip; | 347 | ((struct fnptr *)kretprobe_trampoline)->ip; |
| 348 | 348 | ||
| 349 | spin_lock_irqsave(&kretprobe_lock, flags); | 349 | spin_lock_irqsave(&kretprobe_lock, flags); |
| 350 | head = kretprobe_inst_table_head(current); | 350 | head = kretprobe_inst_table_head(current); |
| 351 | 351 | ||
| 352 | /* | 352 | /* |
| 353 | * It is possible to have multiple instances associated with a given | 353 | * It is possible to have multiple instances associated with a given |
| @@ -363,9 +363,9 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 363 | * kretprobe_trampoline | 363 | * kretprobe_trampoline |
| 364 | */ | 364 | */ |
| 365 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | 365 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { |
| 366 | if (ri->task != current) | 366 | if (ri->task != current) |
| 367 | /* another task is sharing our hash bucket */ | 367 | /* another task is sharing our hash bucket */ |
| 368 | continue; | 368 | continue; |
| 369 | 369 | ||
| 370 | if (ri->rp && ri->rp->handler) | 370 | if (ri->rp && ri->rp->handler) |
| 371 | ri->rp->handler(ri, regs); | 371 | ri->rp->handler(ri, regs); |
| @@ -394,7 +394,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 394 | * kprobe_handler() that we don't want the post_handler | 394 | * kprobe_handler() that we don't want the post_handler |
| 395 | * to run (and have re-enabled preemption) | 395 | * to run (and have re-enabled preemption) |
| 396 | */ | 396 | */ |
| 397 | return 1; | 397 | return 1; |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | /* Called with kretprobe_lock held */ | 400 | /* Called with kretprobe_lock held */ |
| @@ -739,12 +739,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
| 739 | 739 | ||
| 740 | switch(val) { | 740 | switch(val) { |
| 741 | case DIE_BREAK: | 741 | case DIE_BREAK: |
| 742 | if (pre_kprobes_handler(args)) | 742 | /* err is break number from ia64_bad_break() */ |
| 743 | ret = NOTIFY_STOP; | 743 | if (args->err == 0x80200 || args->err == 0x80300) |
| 744 | if (pre_kprobes_handler(args)) | ||
| 745 | ret = NOTIFY_STOP; | ||
| 744 | break; | 746 | break; |
| 745 | case DIE_SS: | 747 | case DIE_FAULT: |
| 746 | if (post_kprobes_handler(args->regs)) | 748 | /* err is vector number from ia64_fault() */ |
| 747 | ret = NOTIFY_STOP; | 749 | if (args->err == 36) |
| 750 | if (post_kprobes_handler(args->regs)) | ||
| 751 | ret = NOTIFY_STOP; | ||
| 748 | break; | 752 | break; |
| 749 | case DIE_PAGE_FAULT: | 753 | case DIE_PAGE_FAULT: |
| 750 | /* kprobe_running() needs smp_processor_id() */ | 754 | /* kprobe_running() needs smp_processor_id() */ |
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 52c47da17246..355af15287c7 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c | |||
| @@ -51,6 +51,9 @@ | |||
| 51 | * | 51 | * |
| 52 | * 2005-08-12 Keith Owens <kaos@sgi.com> | 52 | * 2005-08-12 Keith Owens <kaos@sgi.com> |
| 53 | * Convert MCA/INIT handlers to use per event stacks and SAL/OS state. | 53 | * Convert MCA/INIT handlers to use per event stacks and SAL/OS state. |
| 54 | * | ||
| 55 | * 2005-10-07 Keith Owens <kaos@sgi.com> | ||
| 56 | * Add notify_die() hooks. | ||
| 54 | */ | 57 | */ |
| 55 | #include <linux/config.h> | 58 | #include <linux/config.h> |
| 56 | #include <linux/types.h> | 59 | #include <linux/types.h> |
| @@ -58,7 +61,6 @@ | |||
| 58 | #include <linux/sched.h> | 61 | #include <linux/sched.h> |
| 59 | #include <linux/interrupt.h> | 62 | #include <linux/interrupt.h> |
| 60 | #include <linux/irq.h> | 63 | #include <linux/irq.h> |
| 61 | #include <linux/kallsyms.h> | ||
| 62 | #include <linux/smp_lock.h> | 64 | #include <linux/smp_lock.h> |
| 63 | #include <linux/bootmem.h> | 65 | #include <linux/bootmem.h> |
| 64 | #include <linux/acpi.h> | 66 | #include <linux/acpi.h> |
| @@ -69,6 +71,7 @@ | |||
| 69 | #include <linux/workqueue.h> | 71 | #include <linux/workqueue.h> |
| 70 | 72 | ||
| 71 | #include <asm/delay.h> | 73 | #include <asm/delay.h> |
| 74 | #include <asm/kdebug.h> | ||
| 72 | #include <asm/machvec.h> | 75 | #include <asm/machvec.h> |
| 73 | #include <asm/meminit.h> | 76 | #include <asm/meminit.h> |
| 74 | #include <asm/page.h> | 77 | #include <asm/page.h> |
| @@ -132,6 +135,14 @@ extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe); | |||
| 132 | 135 | ||
| 133 | static int mca_init; | 136 | static int mca_init; |
| 134 | 137 | ||
| 138 | |||
| 139 | static void inline | ||
| 140 | ia64_mca_spin(const char *func) | ||
| 141 | { | ||
| 142 | printk(KERN_EMERG "%s: spinning here, not returning to SAL\n", func); | ||
| 143 | while (1) | ||
| 144 | cpu_relax(); | ||
| 145 | } | ||
| 135 | /* | 146 | /* |
| 136 | * IA64_MCA log support | 147 | * IA64_MCA log support |
| 137 | */ | 148 | */ |
| @@ -526,13 +537,16 @@ ia64_mca_wakeup_all(void) | |||
| 526 | * Outputs : None | 537 | * Outputs : None |
| 527 | */ | 538 | */ |
| 528 | static irqreturn_t | 539 | static irqreturn_t |
| 529 | ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs) | 540 | ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs) |
| 530 | { | 541 | { |
| 531 | unsigned long flags; | 542 | unsigned long flags; |
| 532 | int cpu = smp_processor_id(); | 543 | int cpu = smp_processor_id(); |
| 533 | 544 | ||
| 534 | /* Mask all interrupts */ | 545 | /* Mask all interrupts */ |
| 535 | local_irq_save(flags); | 546 | local_irq_save(flags); |
| 547 | if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", regs, 0, 0, 0) | ||
| 548 | == NOTIFY_STOP) | ||
| 549 | ia64_mca_spin(__FUNCTION__); | ||
| 536 | 550 | ||
| 537 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE; | 551 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE; |
| 538 | /* Register with the SAL monarch that the slave has | 552 | /* Register with the SAL monarch that the slave has |
| @@ -540,10 +554,18 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs) | |||
| 540 | */ | 554 | */ |
| 541 | ia64_sal_mc_rendez(); | 555 | ia64_sal_mc_rendez(); |
| 542 | 556 | ||
| 557 | if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", regs, 0, 0, 0) | ||
| 558 | == NOTIFY_STOP) | ||
| 559 | ia64_mca_spin(__FUNCTION__); | ||
| 560 | |||
| 543 | /* Wait for the monarch cpu to exit. */ | 561 | /* Wait for the monarch cpu to exit. */ |
| 544 | while (monarch_cpu != -1) | 562 | while (monarch_cpu != -1) |
| 545 | cpu_relax(); /* spin until monarch leaves */ | 563 | cpu_relax(); /* spin until monarch leaves */ |
| 546 | 564 | ||
| 565 | if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", regs, 0, 0, 0) | ||
| 566 | == NOTIFY_STOP) | ||
| 567 | ia64_mca_spin(__FUNCTION__); | ||
| 568 | |||
| 547 | /* Enable all interrupts */ | 569 | /* Enable all interrupts */ |
| 548 | local_irq_restore(flags); | 570 | local_irq_restore(flags); |
| 549 | return IRQ_HANDLED; | 571 | return IRQ_HANDLED; |
| @@ -933,6 +955,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
| 933 | oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ | 955 | oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ |
| 934 | previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA"); | 956 | previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA"); |
| 935 | monarch_cpu = cpu; | 957 | monarch_cpu = cpu; |
| 958 | if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0) | ||
| 959 | == NOTIFY_STOP) | ||
| 960 | ia64_mca_spin(__FUNCTION__); | ||
| 936 | ia64_wait_for_slaves(cpu); | 961 | ia64_wait_for_slaves(cpu); |
| 937 | 962 | ||
| 938 | /* Wakeup all the processors which are spinning in the rendezvous loop. | 963 | /* Wakeup all the processors which are spinning in the rendezvous loop. |
| @@ -942,6 +967,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
| 942 | * spinning in SAL does not work. | 967 | * spinning in SAL does not work. |
| 943 | */ | 968 | */ |
| 944 | ia64_mca_wakeup_all(); | 969 | ia64_mca_wakeup_all(); |
| 970 | if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, 0, 0, 0) | ||
| 971 | == NOTIFY_STOP) | ||
| 972 | ia64_mca_spin(__FUNCTION__); | ||
| 945 | 973 | ||
| 946 | /* Get the MCA error record and log it */ | 974 | /* Get the MCA error record and log it */ |
| 947 | ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); | 975 | ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); |
| @@ -960,6 +988,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
| 960 | ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA); | 988 | ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA); |
| 961 | sos->os_status = IA64_MCA_CORRECTED; | 989 | sos->os_status = IA64_MCA_CORRECTED; |
| 962 | } | 990 | } |
| 991 | if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, 0, 0, recover) | ||
| 992 | == NOTIFY_STOP) | ||
| 993 | ia64_mca_spin(__FUNCTION__); | ||
| 963 | 994 | ||
| 964 | set_curr_task(cpu, previous_current); | 995 | set_curr_task(cpu, previous_current); |
| 965 | monarch_cpu = -1; | 996 | monarch_cpu = -1; |
| @@ -1188,6 +1219,37 @@ ia64_mca_cpe_poll (unsigned long dummy) | |||
| 1188 | 1219 | ||
| 1189 | #endif /* CONFIG_ACPI */ | 1220 | #endif /* CONFIG_ACPI */ |
| 1190 | 1221 | ||
| 1222 | static int | ||
| 1223 | default_monarch_init_process(struct notifier_block *self, unsigned long val, void *data) | ||
| 1224 | { | ||
| 1225 | int c; | ||
| 1226 | struct task_struct *g, *t; | ||
| 1227 | if (val != DIE_INIT_MONARCH_PROCESS) | ||
| 1228 | return NOTIFY_DONE; | ||
| 1229 | printk(KERN_ERR "Processes interrupted by INIT -"); | ||
| 1230 | for_each_online_cpu(c) { | ||
| 1231 | struct ia64_sal_os_state *s; | ||
| 1232 | t = __va(__per_cpu_mca[c] + IA64_MCA_CPU_INIT_STACK_OFFSET); | ||
| 1233 | s = (struct ia64_sal_os_state *)((char *)t + MCA_SOS_OFFSET); | ||
| 1234 | g = s->prev_task; | ||
| 1235 | if (g) { | ||
| 1236 | if (g->pid) | ||
| 1237 | printk(" %d", g->pid); | ||
| 1238 | else | ||
| 1239 | printk(" %d (cpu %d task 0x%p)", g->pid, task_cpu(g), g); | ||
| 1240 | } | ||
| 1241 | } | ||
| 1242 | printk("\n\n"); | ||
| 1243 | if (read_trylock(&tasklist_lock)) { | ||
| 1244 | do_each_thread (g, t) { | ||
| 1245 | printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm); | ||
| 1246 | show_stack(t, NULL); | ||
| 1247 | } while_each_thread (g, t); | ||
| 1248 | read_unlock(&tasklist_lock); | ||
| 1249 | } | ||
| 1250 | return NOTIFY_DONE; | ||
| 1251 | } | ||
| 1252 | |||
| 1191 | /* | 1253 | /* |
| 1192 | * C portion of the OS INIT handler | 1254 | * C portion of the OS INIT handler |
| 1193 | * | 1255 | * |
| @@ -1212,8 +1274,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
| 1212 | static atomic_t slaves; | 1274 | static atomic_t slaves; |
| 1213 | static atomic_t monarchs; | 1275 | static atomic_t monarchs; |
| 1214 | task_t *previous_current; | 1276 | task_t *previous_current; |
| 1215 | int cpu = smp_processor_id(), c; | 1277 | int cpu = smp_processor_id(); |
| 1216 | struct task_struct *g, *t; | ||
| 1217 | 1278 | ||
| 1218 | oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ | 1279 | oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ |
| 1219 | console_loglevel = 15; /* make sure printks make it to console */ | 1280 | console_loglevel = 15; /* make sure printks make it to console */ |
| @@ -1253,8 +1314,17 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
| 1253 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT; | 1314 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT; |
| 1254 | while (monarch_cpu == -1) | 1315 | while (monarch_cpu == -1) |
| 1255 | cpu_relax(); /* spin until monarch enters */ | 1316 | cpu_relax(); /* spin until monarch enters */ |
| 1317 | if (notify_die(DIE_INIT_SLAVE_ENTER, "INIT", regs, 0, 0, 0) | ||
| 1318 | == NOTIFY_STOP) | ||
| 1319 | ia64_mca_spin(__FUNCTION__); | ||
| 1320 | if (notify_die(DIE_INIT_SLAVE_PROCESS, "INIT", regs, 0, 0, 0) | ||
| 1321 | == NOTIFY_STOP) | ||
| 1322 | ia64_mca_spin(__FUNCTION__); | ||
| 1256 | while (monarch_cpu != -1) | 1323 | while (monarch_cpu != -1) |
| 1257 | cpu_relax(); /* spin until monarch leaves */ | 1324 | cpu_relax(); /* spin until monarch leaves */ |
| 1325 | if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, 0, 0, 0) | ||
| 1326 | == NOTIFY_STOP) | ||
| 1327 | ia64_mca_spin(__FUNCTION__); | ||
| 1258 | printk("Slave on cpu %d returning to normal service.\n", cpu); | 1328 | printk("Slave on cpu %d returning to normal service.\n", cpu); |
| 1259 | set_curr_task(cpu, previous_current); | 1329 | set_curr_task(cpu, previous_current); |
| 1260 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; | 1330 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; |
| @@ -1263,6 +1333,9 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
| 1263 | } | 1333 | } |
| 1264 | 1334 | ||
| 1265 | monarch_cpu = cpu; | 1335 | monarch_cpu = cpu; |
| 1336 | if (notify_die(DIE_INIT_MONARCH_ENTER, "INIT", regs, 0, 0, 0) | ||
| 1337 | == NOTIFY_STOP) | ||
| 1338 | ia64_mca_spin(__FUNCTION__); | ||
| 1266 | 1339 | ||
| 1267 | /* | 1340 | /* |
| 1268 | * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be | 1341 | * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be |
| @@ -1273,27 +1346,16 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
| 1273 | printk("Delaying for 5 seconds...\n"); | 1346 | printk("Delaying for 5 seconds...\n"); |
| 1274 | udelay(5*1000000); | 1347 | udelay(5*1000000); |
| 1275 | ia64_wait_for_slaves(cpu); | 1348 | ia64_wait_for_slaves(cpu); |
| 1276 | printk(KERN_ERR "Processes interrupted by INIT -"); | 1349 | /* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through |
| 1277 | for_each_online_cpu(c) { | 1350 | * to default_monarch_init_process() above and just print all the |
| 1278 | struct ia64_sal_os_state *s; | 1351 | * tasks. |
| 1279 | t = __va(__per_cpu_mca[c] + IA64_MCA_CPU_INIT_STACK_OFFSET); | 1352 | */ |
| 1280 | s = (struct ia64_sal_os_state *)((char *)t + MCA_SOS_OFFSET); | 1353 | if (notify_die(DIE_INIT_MONARCH_PROCESS, "INIT", regs, 0, 0, 0) |
| 1281 | g = s->prev_task; | 1354 | == NOTIFY_STOP) |
| 1282 | if (g) { | 1355 | ia64_mca_spin(__FUNCTION__); |
| 1283 | if (g->pid) | 1356 | if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, 0, 0, 0) |
| 1284 | printk(" %d", g->pid); | 1357 | == NOTIFY_STOP) |
| 1285 | else | 1358 | ia64_mca_spin(__FUNCTION__); |
| 1286 | printk(" %d (cpu %d task 0x%p)", g->pid, task_cpu(g), g); | ||
| 1287 | } | ||
| 1288 | } | ||
| 1289 | printk("\n\n"); | ||
| 1290 | if (read_trylock(&tasklist_lock)) { | ||
| 1291 | do_each_thread (g, t) { | ||
| 1292 | printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm); | ||
| 1293 | show_stack(t, NULL); | ||
| 1294 | } while_each_thread (g, t); | ||
| 1295 | read_unlock(&tasklist_lock); | ||
| 1296 | } | ||
| 1297 | printk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu); | 1359 | printk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu); |
| 1298 | atomic_dec(&monarchs); | 1360 | atomic_dec(&monarchs); |
| 1299 | set_curr_task(cpu, previous_current); | 1361 | set_curr_task(cpu, previous_current); |
| @@ -1462,6 +1524,10 @@ ia64_mca_init(void) | |||
| 1462 | s64 rc; | 1524 | s64 rc; |
| 1463 | struct ia64_sal_retval isrv; | 1525 | struct ia64_sal_retval isrv; |
| 1464 | u64 timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */ | 1526 | u64 timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */ |
| 1527 | static struct notifier_block default_init_monarch_nb = { | ||
| 1528 | .notifier_call = default_monarch_init_process, | ||
| 1529 | .priority = 0/* we need to notified last */ | ||
| 1530 | }; | ||
| 1465 | 1531 | ||
| 1466 | IA64_MCA_DEBUG("%s: begin\n", __FUNCTION__); | 1532 | IA64_MCA_DEBUG("%s: begin\n", __FUNCTION__); |
| 1467 | 1533 | ||
| @@ -1555,6 +1621,10 @@ ia64_mca_init(void) | |||
| 1555 | "(status %ld)\n", rc); | 1621 | "(status %ld)\n", rc); |
| 1556 | return; | 1622 | return; |
| 1557 | } | 1623 | } |
| 1624 | if (register_die_notifier(&default_init_monarch_nb)) { | ||
| 1625 | printk(KERN_ERR "Failed to register default monarch INIT process\n"); | ||
| 1626 | return; | ||
| 1627 | } | ||
| 1558 | 1628 | ||
| 1559 | IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __FUNCTION__); | 1629 | IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __FUNCTION__); |
| 1560 | 1630 | ||
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index eb39bc9c133b..3492e3211a44 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c | |||
| @@ -547,9 +547,20 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, | |||
| 547 | (pal_processor_state_info_t*)peidx_psp(peidx); | 547 | (pal_processor_state_info_t*)peidx_psp(peidx); |
| 548 | 548 | ||
| 549 | /* | 549 | /* |
| 550 | * We cannot recover errors with other than bus_check. | 550 | * Processor recovery status must key off of the PAL recovery |
| 551 | * status in the Processor State Parameter. | ||
| 551 | */ | 552 | */ |
| 552 | if (psp->cc || psp->rc || psp->uc) | 553 | |
| 554 | /* | ||
| 555 | * The machine check is corrected. | ||
| 556 | */ | ||
| 557 | if (psp->cm == 1) | ||
| 558 | return 1; | ||
| 559 | |||
| 560 | /* | ||
| 561 | * The error was not contained. Software must be reset. | ||
| 562 | */ | ||
| 563 | if (psp->us || psp->ci == 0) | ||
| 553 | return 0; | 564 | return 0; |
| 554 | 565 | ||
| 555 | /* | 566 | /* |
| @@ -570,8 +581,6 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, | |||
| 570 | return 0; | 581 | return 0; |
| 571 | if (pbci->eb && pbci->bsi > 0) | 582 | if (pbci->eb && pbci->bsi > 0) |
| 572 | return 0; | 583 | return 0; |
| 573 | if (psp->ci == 0) | ||
| 574 | return 0; | ||
| 575 | 584 | ||
| 576 | /* | 585 | /* |
| 577 | * This is a local MCA and estimated as recoverble external bus error. | 586 | * This is a local MCA and estimated as recoverble external bus error. |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 640d6908f8ec..e92ea64d8040 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
| @@ -4,6 +4,9 @@ | |||
| 4 | * Copyright (C) 1998-2003 Hewlett-Packard Co | 4 | * Copyright (C) 1998-2003 Hewlett-Packard Co |
| 5 | * David Mosberger-Tang <davidm@hpl.hp.com> | 5 | * David Mosberger-Tang <davidm@hpl.hp.com> |
| 6 | * 04/11/17 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support | 6 | * 04/11/17 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support |
| 7 | * | ||
| 8 | * 2005-10-07 Keith Owens <kaos@sgi.com> | ||
| 9 | * Add notify_die() hooks. | ||
| 7 | */ | 10 | */ |
| 8 | #define __KERNEL_SYSCALLS__ /* see <asm/unistd.h> */ | 11 | #define __KERNEL_SYSCALLS__ /* see <asm/unistd.h> */ |
| 9 | #include <linux/config.h> | 12 | #include <linux/config.h> |
| @@ -34,6 +37,7 @@ | |||
| 34 | #include <asm/elf.h> | 37 | #include <asm/elf.h> |
| 35 | #include <asm/ia32.h> | 38 | #include <asm/ia32.h> |
| 36 | #include <asm/irq.h> | 39 | #include <asm/irq.h> |
| 40 | #include <asm/kdebug.h> | ||
| 37 | #include <asm/pgalloc.h> | 41 | #include <asm/pgalloc.h> |
| 38 | #include <asm/processor.h> | 42 | #include <asm/processor.h> |
| 39 | #include <asm/sal.h> | 43 | #include <asm/sal.h> |
| @@ -808,12 +812,14 @@ cpu_halt (void) | |||
| 808 | void | 812 | void |
| 809 | machine_restart (char *restart_cmd) | 813 | machine_restart (char *restart_cmd) |
| 810 | { | 814 | { |
| 815 | (void) notify_die(DIE_MACHINE_RESTART, restart_cmd, NULL, 0, 0, 0); | ||
| 811 | (*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL); | 816 | (*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL); |
| 812 | } | 817 | } |
| 813 | 818 | ||
| 814 | void | 819 | void |
| 815 | machine_halt (void) | 820 | machine_halt (void) |
| 816 | { | 821 | { |
| 822 | (void) notify_die(DIE_MACHINE_HALT, "", NULL, 0, 0, 0); | ||
| 817 | cpu_halt(); | 823 | cpu_halt(); |
| 818 | } | 824 | } |
| 819 | 825 | ||
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 3af6de36a482..5add0bcf87a7 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c | |||
| @@ -461,6 +461,7 @@ setup_arch (char **cmdline_p) | |||
| 461 | #endif | 461 | #endif |
| 462 | 462 | ||
| 463 | cpu_init(); /* initialize the bootstrap CPU */ | 463 | cpu_init(); /* initialize the bootstrap CPU */ |
| 464 | mmu_context_init(); /* initialize context_id bitmap */ | ||
| 464 | 465 | ||
| 465 | #ifdef CONFIG_ACPI | 466 | #ifdef CONFIG_ACPI |
| 466 | acpi_boot_init(); | 467 | acpi_boot_init(); |
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 774f34b675cf..58ce07efc56e 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c | |||
| @@ -387,15 +387,14 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, | |||
| 387 | struct sigscratch *scr) | 387 | struct sigscratch *scr) |
| 388 | { | 388 | { |
| 389 | extern char __kernel_sigtramp[]; | 389 | extern char __kernel_sigtramp[]; |
| 390 | unsigned long tramp_addr, new_rbs = 0; | 390 | unsigned long tramp_addr, new_rbs = 0, new_sp; |
| 391 | struct sigframe __user *frame; | 391 | struct sigframe __user *frame; |
| 392 | long err; | 392 | long err; |
| 393 | 393 | ||
| 394 | frame = (void __user *) scr->pt.r12; | 394 | new_sp = scr->pt.r12; |
| 395 | tramp_addr = (unsigned long) __kernel_sigtramp; | 395 | tramp_addr = (unsigned long) __kernel_sigtramp; |
| 396 | if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags((unsigned long) frame) == 0) { | 396 | if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(new_sp) == 0) { |
| 397 | frame = (void __user *) ((current->sas_ss_sp + current->sas_ss_size) | 397 | new_sp = current->sas_ss_sp + current->sas_ss_size; |
| 398 | & ~(STACK_ALIGN - 1)); | ||
| 399 | /* | 398 | /* |
| 400 | * We need to check for the register stack being on the signal stack | 399 | * We need to check for the register stack being on the signal stack |
| 401 | * separately, because it's switched separately (memory stack is switched | 400 | * separately, because it's switched separately (memory stack is switched |
| @@ -404,7 +403,7 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, | |||
| 404 | if (!rbs_on_sig_stack(scr->pt.ar_bspstore)) | 403 | if (!rbs_on_sig_stack(scr->pt.ar_bspstore)) |
| 405 | new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1); | 404 | new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1); |
| 406 | } | 405 | } |
| 407 | frame = (void __user *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1)); | 406 | frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN); |
| 408 | 407 | ||
| 409 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 408 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
| 410 | return force_sigsegv_info(sig, frame); | 409 | return force_sigsegv_info(sig, frame); |
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index f970359e7edf..fba5fdd1f968 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c | |||
| @@ -30,17 +30,20 @@ fpswa_interface_t *fpswa_interface; | |||
| 30 | EXPORT_SYMBOL(fpswa_interface); | 30 | EXPORT_SYMBOL(fpswa_interface); |
| 31 | 31 | ||
| 32 | struct notifier_block *ia64die_chain; | 32 | struct notifier_block *ia64die_chain; |
| 33 | static DEFINE_SPINLOCK(die_notifier_lock); | ||
| 34 | 33 | ||
| 35 | int register_die_notifier(struct notifier_block *nb) | 34 | int |
| 35 | register_die_notifier(struct notifier_block *nb) | ||
| 36 | { | 36 | { |
| 37 | int err = 0; | 37 | return notifier_chain_register(&ia64die_chain, nb); |
| 38 | unsigned long flags; | ||
| 39 | spin_lock_irqsave(&die_notifier_lock, flags); | ||
| 40 | err = notifier_chain_register(&ia64die_chain, nb); | ||
| 41 | spin_unlock_irqrestore(&die_notifier_lock, flags); | ||
| 42 | return err; | ||
| 43 | } | 38 | } |
| 39 | EXPORT_SYMBOL_GPL(register_die_notifier); | ||
| 40 | |||
| 41 | int | ||
| 42 | unregister_die_notifier(struct notifier_block *nb) | ||
| 43 | { | ||
| 44 | return notifier_chain_unregister(&ia64die_chain, nb); | ||
| 45 | } | ||
| 46 | EXPORT_SYMBOL_GPL(unregister_die_notifier); | ||
| 44 | 47 | ||
| 45 | void __init | 48 | void __init |
| 46 | trap_init (void) | 49 | trap_init (void) |
| @@ -105,6 +108,7 @@ die (const char *str, struct pt_regs *regs, long err) | |||
| 105 | if (++die.lock_owner_depth < 3) { | 108 | if (++die.lock_owner_depth < 3) { |
| 106 | printk("%s[%d]: %s %ld [%d]\n", | 109 | printk("%s[%d]: %s %ld [%d]\n", |
| 107 | current->comm, current->pid, str, err, ++die_counter); | 110 | current->comm, current->pid, str, err, ++die_counter); |
| 111 | (void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); | ||
| 108 | show_regs(regs); | 112 | show_regs(regs); |
| 109 | } else | 113 | } else |
| 110 | printk(KERN_ERR "Recursive die() failure, output suppressed\n"); | 114 | printk(KERN_ERR "Recursive die() failure, output suppressed\n"); |
| @@ -155,9 +159,8 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) | |||
| 155 | switch (break_num) { | 159 | switch (break_num) { |
| 156 | case 0: /* unknown error (used by GCC for __builtin_abort()) */ | 160 | case 0: /* unknown error (used by GCC for __builtin_abort()) */ |
| 157 | if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP) | 161 | if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP) |
| 158 | == NOTIFY_STOP) { | 162 | == NOTIFY_STOP) |
| 159 | return; | 163 | return; |
| 160 | } | ||
| 161 | die_if_kernel("bugcheck!", regs, break_num); | 164 | die_if_kernel("bugcheck!", regs, break_num); |
| 162 | sig = SIGILL; code = ILL_ILLOPC; | 165 | sig = SIGILL; code = ILL_ILLOPC; |
| 163 | break; | 166 | break; |
| @@ -210,15 +213,6 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) | |||
| 210 | sig = SIGILL; code = __ILL_BNDMOD; | 213 | sig = SIGILL; code = __ILL_BNDMOD; |
| 211 | break; | 214 | break; |
| 212 | 215 | ||
| 213 | case 0x80200: | ||
| 214 | case 0x80300: | ||
| 215 | if (notify_die(DIE_BREAK, "kprobe", regs, break_num, TRAP_BRKPT, SIGTRAP) | ||
| 216 | == NOTIFY_STOP) { | ||
| 217 | return; | ||
| 218 | } | ||
| 219 | sig = SIGTRAP; code = TRAP_BRKPT; | ||
| 220 | break; | ||
| 221 | |||
| 222 | default: | 216 | default: |
| 223 | if (break_num < 0x40000 || break_num > 0x100000) | 217 | if (break_num < 0x40000 || break_num > 0x100000) |
| 224 | die_if_kernel("Bad break", regs, break_num); | 218 | die_if_kernel("Bad break", regs, break_num); |
| @@ -226,6 +220,9 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) | |||
| 226 | if (break_num < 0x80000) { | 220 | if (break_num < 0x80000) { |
| 227 | sig = SIGILL; code = __ILL_BREAK; | 221 | sig = SIGILL; code = __ILL_BREAK; |
| 228 | } else { | 222 | } else { |
| 223 | if (notify_die(DIE_BREAK, "bad break", regs, break_num, TRAP_BRKPT, SIGTRAP) | ||
| 224 | == NOTIFY_STOP) | ||
| 225 | return; | ||
| 229 | sig = SIGTRAP; code = TRAP_BRKPT; | 226 | sig = SIGTRAP; code = TRAP_BRKPT; |
| 230 | } | 227 | } |
| 231 | } | 228 | } |
| @@ -578,12 +575,11 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, | |||
| 578 | #endif | 575 | #endif |
| 579 | break; | 576 | break; |
| 580 | case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break; | 577 | case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break; |
| 581 | case 36: | 578 | case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break; |
| 582 | if (notify_die(DIE_SS, "ss", ®s, vector, | ||
| 583 | vector, SIGTRAP) == NOTIFY_STOP) | ||
| 584 | return; | ||
| 585 | siginfo.si_code = TRAP_TRACE; ifa = 0; break; | ||
| 586 | } | 579 | } |
| 580 | if (notify_die(DIE_FAULT, "ia64_fault", ®s, vector, siginfo.si_code, SIGTRAP) | ||
| 581 | == NOTIFY_STOP) | ||
| 582 | return; | ||
| 587 | siginfo.si_signo = SIGTRAP; | 583 | siginfo.si_signo = SIGTRAP; |
| 588 | siginfo.si_errno = 0; | 584 | siginfo.si_errno = 0; |
| 589 | siginfo.si_addr = (void __user *) ifa; | 585 | siginfo.si_addr = (void __user *) ifa; |
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index a88cdb7232f8..0f776b032d31 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c | |||
| @@ -350,14 +350,12 @@ static void __init initialize_pernode_data(void) | |||
| 350 | * for best. | 350 | * for best. |
| 351 | * @nid: node id | 351 | * @nid: node id |
| 352 | * @pernodesize: size of this node's pernode data | 352 | * @pernodesize: size of this node's pernode data |
| 353 | * @align: alignment to use for this node's pernode data | ||
| 354 | */ | 353 | */ |
| 355 | static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize, | 354 | static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize) |
| 356 | unsigned long align) | ||
| 357 | { | 355 | { |
| 358 | void *ptr = NULL; | 356 | void *ptr = NULL; |
| 359 | u8 best = 0xff; | 357 | u8 best = 0xff; |
| 360 | int bestnode = -1, node; | 358 | int bestnode = -1, node, anynode = 0; |
| 361 | 359 | ||
| 362 | for_each_online_node(node) { | 360 | for_each_online_node(node) { |
| 363 | if (node_isset(node, memory_less_mask)) | 361 | if (node_isset(node, memory_less_mask)) |
| @@ -366,13 +364,15 @@ static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize, | |||
| 366 | best = node_distance(nid, node); | 364 | best = node_distance(nid, node); |
| 367 | bestnode = node; | 365 | bestnode = node; |
| 368 | } | 366 | } |
| 367 | anynode = node; | ||
| 369 | } | 368 | } |
| 370 | 369 | ||
| 371 | ptr = __alloc_bootmem_node(mem_data[bestnode].pgdat, | 370 | if (bestnode == -1) |
| 372 | pernodesize, align, __pa(MAX_DMA_ADDRESS)); | 371 | bestnode = anynode; |
| 372 | |||
| 373 | ptr = __alloc_bootmem_node(mem_data[bestnode].pgdat, pernodesize, | ||
| 374 | PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); | ||
| 373 | 375 | ||
| 374 | if (!ptr) | ||
| 375 | panic("NO memory for memory less node\n"); | ||
| 376 | return ptr; | 376 | return ptr; |
| 377 | } | 377 | } |
| 378 | 378 | ||
| @@ -413,8 +413,7 @@ static void __init memory_less_nodes(void) | |||
| 413 | 413 | ||
| 414 | for_each_node_mask(node, memory_less_mask) { | 414 | for_each_node_mask(node, memory_less_mask) { |
| 415 | pernodesize = compute_pernodesize(node); | 415 | pernodesize = compute_pernodesize(node); |
| 416 | pernode = memory_less_node_alloc(node, pernodesize, | 416 | pernode = memory_less_node_alloc(node, pernodesize); |
| 417 | (node) ? (node * PERCPU_PAGE_SIZE) : (1024*1024)); | ||
| 418 | fill_pernode(node, __pa(pernode), pernodesize); | 417 | fill_pernode(node, __pa(pernode), pernodesize); |
| 419 | } | 418 | } |
| 420 | 419 | ||
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index c79a9b96d02b..41105d454423 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c | |||
| @@ -8,6 +8,8 @@ | |||
| 8 | * Modified RID allocation for SMP | 8 | * Modified RID allocation for SMP |
| 9 | * Goutham Rao <goutham.rao@intel.com> | 9 | * Goutham Rao <goutham.rao@intel.com> |
| 10 | * IPI based ptc implementation and A-step IPI implementation. | 10 | * IPI based ptc implementation and A-step IPI implementation. |
| 11 | * Rohit Seth <rohit.seth@intel.com> | ||
| 12 | * Ken Chen <kenneth.w.chen@intel.com> | ||
| 11 | */ | 13 | */ |
| 12 | #include <linux/config.h> | 14 | #include <linux/config.h> |
| 13 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| @@ -16,78 +18,75 @@ | |||
| 16 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
| 17 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
| 18 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
| 21 | #include <linux/bootmem.h> | ||
| 19 | 22 | ||
| 20 | #include <asm/delay.h> | 23 | #include <asm/delay.h> |
| 21 | #include <asm/mmu_context.h> | 24 | #include <asm/mmu_context.h> |
| 22 | #include <asm/pgalloc.h> | 25 | #include <asm/pgalloc.h> |
| 23 | #include <asm/pal.h> | 26 | #include <asm/pal.h> |
| 24 | #include <asm/tlbflush.h> | 27 | #include <asm/tlbflush.h> |
| 28 | #include <asm/dma.h> | ||
| 25 | 29 | ||
| 26 | static struct { | 30 | static struct { |
| 27 | unsigned long mask; /* mask of supported purge page-sizes */ | 31 | unsigned long mask; /* mask of supported purge page-sizes */ |
| 28 | unsigned long max_bits; /* log2() of largest supported purge page-size */ | 32 | unsigned long max_bits; /* log2 of largest supported purge page-size */ |
| 29 | } purge; | 33 | } purge; |
| 30 | 34 | ||
| 31 | struct ia64_ctx ia64_ctx = { | 35 | struct ia64_ctx ia64_ctx = { |
| 32 | .lock = SPIN_LOCK_UNLOCKED, | 36 | .lock = SPIN_LOCK_UNLOCKED, |
| 33 | .next = 1, | 37 | .next = 1, |
| 34 | .limit = (1 << 15) - 1, /* start out with the safe (architected) limit */ | ||
| 35 | .max_ctx = ~0U | 38 | .max_ctx = ~0U |
| 36 | }; | 39 | }; |
| 37 | 40 | ||
| 38 | DEFINE_PER_CPU(u8, ia64_need_tlb_flush); | 41 | DEFINE_PER_CPU(u8, ia64_need_tlb_flush); |
| 39 | 42 | ||
| 40 | /* | 43 | /* |
| 44 | * Initializes the ia64_ctx.bitmap array based on max_ctx+1. | ||
| 45 | * Called after cpu_init() has setup ia64_ctx.max_ctx based on | ||
| 46 | * maximum RID that is supported by boot CPU. | ||
| 47 | */ | ||
| 48 | void __init | ||
| 49 | mmu_context_init (void) | ||
| 50 | { | ||
| 51 | ia64_ctx.bitmap = alloc_bootmem((ia64_ctx.max_ctx+1)>>3); | ||
| 52 | ia64_ctx.flushmap = alloc_bootmem((ia64_ctx.max_ctx+1)>>3); | ||
| 53 | } | ||
| 54 | |||
| 55 | /* | ||
| 41 | * Acquire the ia64_ctx.lock before calling this function! | 56 | * Acquire the ia64_ctx.lock before calling this function! |
| 42 | */ | 57 | */ |
| 43 | void | 58 | void |
| 44 | wrap_mmu_context (struct mm_struct *mm) | 59 | wrap_mmu_context (struct mm_struct *mm) |
| 45 | { | 60 | { |
| 46 | unsigned long tsk_context, max_ctx = ia64_ctx.max_ctx; | 61 | int i, cpu; |
| 47 | struct task_struct *tsk; | 62 | unsigned long flush_bit; |
| 48 | int i; | ||
| 49 | 63 | ||
| 50 | if (ia64_ctx.next > max_ctx) | 64 | for (i=0; i <= ia64_ctx.max_ctx / BITS_PER_LONG; i++) { |
| 51 | ia64_ctx.next = 300; /* skip daemons */ | 65 | flush_bit = xchg(&ia64_ctx.flushmap[i], 0); |
| 52 | ia64_ctx.limit = max_ctx + 1; | 66 | ia64_ctx.bitmap[i] ^= flush_bit; |
| 67 | } | ||
| 68 | |||
| 69 | /* use offset at 300 to skip daemons */ | ||
| 70 | ia64_ctx.next = find_next_zero_bit(ia64_ctx.bitmap, | ||
| 71 | ia64_ctx.max_ctx, 300); | ||
| 72 | ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap, | ||
| 73 | ia64_ctx.max_ctx, ia64_ctx.next); | ||
| 53 | 74 | ||
| 54 | /* | 75 | /* |
| 55 | * Scan all the task's mm->context and set proper safe range | 76 | * can't call flush_tlb_all() here because of race condition |
| 77 | * with O(1) scheduler [EF] | ||
| 56 | */ | 78 | */ |
| 57 | 79 | cpu = get_cpu(); /* prevent preemption/migration */ | |
| 58 | read_lock(&tasklist_lock); | 80 | for_each_online_cpu(i) |
| 59 | repeat: | 81 | if (i != cpu) |
| 60 | for_each_process(tsk) { | 82 | per_cpu(ia64_need_tlb_flush, i) = 1; |
| 61 | if (!tsk->mm) | 83 | put_cpu(); |
| 62 | continue; | ||
| 63 | tsk_context = tsk->mm->context; | ||
| 64 | if (tsk_context == ia64_ctx.next) { | ||
| 65 | if (++ia64_ctx.next >= ia64_ctx.limit) { | ||
| 66 | /* empty range: reset the range limit and start over */ | ||
| 67 | if (ia64_ctx.next > max_ctx) | ||
| 68 | ia64_ctx.next = 300; | ||
| 69 | ia64_ctx.limit = max_ctx + 1; | ||
| 70 | goto repeat; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | if ((tsk_context > ia64_ctx.next) && (tsk_context < ia64_ctx.limit)) | ||
| 74 | ia64_ctx.limit = tsk_context; | ||
| 75 | } | ||
| 76 | read_unlock(&tasklist_lock); | ||
| 77 | /* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */ | ||
| 78 | { | ||
| 79 | int cpu = get_cpu(); /* prevent preemption/migration */ | ||
| 80 | for_each_online_cpu(i) { | ||
| 81 | if (i != cpu) | ||
| 82 | per_cpu(ia64_need_tlb_flush, i) = 1; | ||
| 83 | } | ||
| 84 | put_cpu(); | ||
| 85 | } | ||
| 86 | local_flush_tlb_all(); | 84 | local_flush_tlb_all(); |
| 87 | } | 85 | } |
| 88 | 86 | ||
| 89 | void | 87 | void |
| 90 | ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long nbits) | 88 | ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, |
| 89 | unsigned long end, unsigned long nbits) | ||
| 91 | { | 90 | { |
| 92 | static DEFINE_SPINLOCK(ptcg_lock); | 91 | static DEFINE_SPINLOCK(ptcg_lock); |
| 93 | 92 | ||
| @@ -135,7 +134,8 @@ local_flush_tlb_all (void) | |||
| 135 | } | 134 | } |
| 136 | 135 | ||
| 137 | void | 136 | void |
| 138 | flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long end) | 137 | flush_tlb_range (struct vm_area_struct *vma, unsigned long start, |
| 138 | unsigned long end) | ||
| 139 | { | 139 | { |
| 140 | struct mm_struct *mm = vma->vm_mm; | 140 | struct mm_struct *mm = vma->vm_mm; |
| 141 | unsigned long size = end - start; | 141 | unsigned long size = end - start; |
| @@ -149,7 +149,8 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long | |||
| 149 | #endif | 149 | #endif |
| 150 | 150 | ||
| 151 | nbits = ia64_fls(size + 0xfff); | 151 | nbits = ia64_fls(size + 0xfff); |
| 152 | while (unlikely (((1UL << nbits) & purge.mask) == 0) && (nbits < purge.max_bits)) | 152 | while (unlikely (((1UL << nbits) & purge.mask) == 0) && |
| 153 | (nbits < purge.max_bits)) | ||
| 153 | ++nbits; | 154 | ++nbits; |
| 154 | if (nbits > purge.max_bits) | 155 | if (nbits > purge.max_bits) |
| 155 | nbits = purge.max_bits; | 156 | nbits = purge.max_bits; |
| @@ -191,5 +192,5 @@ ia64_tlb_init (void) | |||
| 191 | local_cpu_data->ptce_stride[0] = ptce_info.stride[0]; | 192 | local_cpu_data->ptce_stride[0] = ptce_info.stride[0]; |
| 192 | local_cpu_data->ptce_stride[1] = ptce_info.stride[1]; | 193 | local_cpu_data->ptce_stride[1] = ptce_info.stride[1]; |
| 193 | 194 | ||
| 194 | local_flush_tlb_all(); /* nuke left overs from bootstrapping... */ | 195 | local_flush_tlb_all(); /* nuke left overs from bootstrapping... */ |
| 195 | } | 196 | } |
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 017cfc3f4789..20d76fae24e8 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
| @@ -95,7 +95,7 @@ pci_sal_write (unsigned int seg, unsigned int bus, unsigned int devfn, | |||
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | static struct pci_raw_ops pci_sal_ops = { | 97 | static struct pci_raw_ops pci_sal_ops = { |
| 98 | .read = pci_sal_read, | 98 | .read = pci_sal_read, |
| 99 | .write = pci_sal_write | 99 | .write = pci_sal_write |
| 100 | }; | 100 | }; |
| 101 | 101 | ||
| @@ -137,35 +137,98 @@ alloc_pci_controller (int seg) | |||
| 137 | return controller; | 137 | return controller; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | static u64 __devinit | 140 | struct pci_root_info { |
| 141 | add_io_space (struct acpi_resource_address64 *addr) | 141 | struct pci_controller *controller; |
| 142 | char *name; | ||
| 143 | }; | ||
| 144 | |||
| 145 | static unsigned int | ||
| 146 | new_space (u64 phys_base, int sparse) | ||
| 142 | { | 147 | { |
| 143 | u64 offset; | 148 | u64 mmio_base; |
| 144 | int sparse = 0; | ||
| 145 | int i; | 149 | int i; |
| 146 | 150 | ||
| 147 | if (addr->address_translation_offset == 0) | 151 | if (phys_base == 0) |
| 148 | return IO_SPACE_BASE(0); /* part of legacy IO space */ | 152 | return 0; /* legacy I/O port space */ |
| 149 | |||
| 150 | if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) | ||
| 151 | sparse = 1; | ||
| 152 | 153 | ||
| 153 | offset = (u64) ioremap(addr->address_translation_offset, 0); | 154 | mmio_base = (u64) ioremap(phys_base, 0); |
| 154 | for (i = 0; i < num_io_spaces; i++) | 155 | for (i = 0; i < num_io_spaces; i++) |
| 155 | if (io_space[i].mmio_base == offset && | 156 | if (io_space[i].mmio_base == mmio_base && |
| 156 | io_space[i].sparse == sparse) | 157 | io_space[i].sparse == sparse) |
| 157 | return IO_SPACE_BASE(i); | 158 | return i; |
| 158 | 159 | ||
| 159 | if (num_io_spaces == MAX_IO_SPACES) { | 160 | if (num_io_spaces == MAX_IO_SPACES) { |
| 160 | printk("Too many IO port spaces\n"); | 161 | printk(KERN_ERR "PCI: Too many IO port spaces " |
| 162 | "(MAX_IO_SPACES=%lu)\n", MAX_IO_SPACES); | ||
| 161 | return ~0; | 163 | return ~0; |
| 162 | } | 164 | } |
| 163 | 165 | ||
| 164 | i = num_io_spaces++; | 166 | i = num_io_spaces++; |
| 165 | io_space[i].mmio_base = offset; | 167 | io_space[i].mmio_base = mmio_base; |
| 166 | io_space[i].sparse = sparse; | 168 | io_space[i].sparse = sparse; |
| 167 | 169 | ||
| 168 | return IO_SPACE_BASE(i); | 170 | return i; |
| 171 | } | ||
| 172 | |||
| 173 | static u64 __devinit | ||
| 174 | add_io_space (struct pci_root_info *info, struct acpi_resource_address64 *addr) | ||
| 175 | { | ||
| 176 | struct resource *resource; | ||
| 177 | char *name; | ||
| 178 | u64 base, min, max, base_port; | ||
| 179 | unsigned int sparse = 0, space_nr, len; | ||
| 180 | |||
| 181 | resource = kzalloc(sizeof(*resource), GFP_KERNEL); | ||
| 182 | if (!resource) { | ||
| 183 | printk(KERN_ERR "PCI: No memory for %s I/O port space\n", | ||
| 184 | info->name); | ||
| 185 | goto out; | ||
| 186 | } | ||
| 187 | |||
| 188 | len = strlen(info->name) + 32; | ||
| 189 | name = kzalloc(len, GFP_KERNEL); | ||
| 190 | if (!name) { | ||
| 191 | printk(KERN_ERR "PCI: No memory for %s I/O port space name\n", | ||
| 192 | info->name); | ||
| 193 | goto free_resource; | ||
| 194 | } | ||
| 195 | |||
| 196 | min = addr->min_address_range; | ||
| 197 | max = min + addr->address_length - 1; | ||
| 198 | if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) | ||
| 199 | sparse = 1; | ||
| 200 | |||
| 201 | space_nr = new_space(addr->address_translation_offset, sparse); | ||
| 202 | if (space_nr == ~0) | ||
| 203 | goto free_name; | ||
| 204 | |||
| 205 | base = __pa(io_space[space_nr].mmio_base); | ||
| 206 | base_port = IO_SPACE_BASE(space_nr); | ||
| 207 | snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->name, | ||
| 208 | base_port + min, base_port + max); | ||
| 209 | |||
| 210 | /* | ||
| 211 | * The SDM guarantees the legacy 0-64K space is sparse, but if the | ||
| 212 | * mapping is done by the processor (not the bridge), ACPI may not | ||
| 213 | * mark it as sparse. | ||
| 214 | */ | ||
| 215 | if (space_nr == 0) | ||
| 216 | sparse = 1; | ||
| 217 | |||
| 218 | resource->name = name; | ||
| 219 | resource->flags = IORESOURCE_MEM; | ||
| 220 | resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min); | ||
| 221 | resource->end = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max); | ||
| 222 | insert_resource(&iomem_resource, resource); | ||
| 223 | |||
| 224 | return base_port; | ||
| 225 | |||
| 226 | free_name: | ||
| 227 | kfree(name); | ||
| 228 | free_resource: | ||
| 229 | kfree(resource); | ||
| 230 | out: | ||
| 231 | return ~0; | ||
| 169 | } | 232 | } |
| 170 | 233 | ||
| 171 | static acpi_status __devinit resource_to_window(struct acpi_resource *resource, | 234 | static acpi_status __devinit resource_to_window(struct acpi_resource *resource, |
| @@ -205,11 +268,6 @@ count_window (struct acpi_resource *resource, void *data) | |||
| 205 | return AE_OK; | 268 | return AE_OK; |
| 206 | } | 269 | } |
| 207 | 270 | ||
| 208 | struct pci_root_info { | ||
| 209 | struct pci_controller *controller; | ||
| 210 | char *name; | ||
| 211 | }; | ||
| 212 | |||
| 213 | static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | 271 | static __devinit acpi_status add_window(struct acpi_resource *res, void *data) |
| 214 | { | 272 | { |
| 215 | struct pci_root_info *info = data; | 273 | struct pci_root_info *info = data; |
| @@ -231,7 +289,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | |||
| 231 | } else if (addr.resource_type == ACPI_IO_RANGE) { | 289 | } else if (addr.resource_type == ACPI_IO_RANGE) { |
| 232 | flags = IORESOURCE_IO; | 290 | flags = IORESOURCE_IO; |
| 233 | root = &ioport_resource; | 291 | root = &ioport_resource; |
| 234 | offset = add_io_space(&addr); | 292 | offset = add_io_space(info, &addr); |
| 235 | if (offset == ~0) | 293 | if (offset == ~0) |
| 236 | return AE_OK; | 294 | return AE_OK; |
| 237 | } else | 295 | } else |
| @@ -241,7 +299,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | |||
| 241 | window->resource.name = info->name; | 299 | window->resource.name = info->name; |
| 242 | window->resource.flags = flags; | 300 | window->resource.flags = flags; |
| 243 | window->resource.start = addr.min_address_range + offset; | 301 | window->resource.start = addr.min_address_range + offset; |
| 244 | window->resource.end = addr.max_address_range + offset; | 302 | window->resource.end = window->resource.start + addr.address_length - 1; |
| 245 | window->resource.child = NULL; | 303 | window->resource.child = NULL; |
| 246 | window->offset = offset; | 304 | window->offset = offset; |
| 247 | 305 | ||
| @@ -739,7 +797,7 @@ int pci_vector_resources(int last, int nr_released) | |||
| 739 | { | 797 | { |
| 740 | int count = nr_released; | 798 | int count = nr_released; |
| 741 | 799 | ||
| 742 | count += (IA64_LAST_DEVICE_VECTOR - last); | 800 | count += (IA64_LAST_DEVICE_VECTOR - last); |
| 743 | 801 | ||
| 744 | return count; | 802 | return count; |
| 745 | } | 803 | } |
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index b4f5053f5e1b..05e4ea889981 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c | |||
| @@ -349,7 +349,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) | |||
| 349 | return; /*bus # does not exist */ | 349 | return; /*bus # does not exist */ |
| 350 | prom_bussoft_ptr = __va(prom_bussoft_ptr); | 350 | prom_bussoft_ptr = __va(prom_bussoft_ptr); |
| 351 | 351 | ||
| 352 | controller = kcalloc(1,sizeof(struct pci_controller), GFP_KERNEL); | 352 | controller = kzalloc(sizeof(struct pci_controller), GFP_KERNEL); |
| 353 | controller->segment = segment; | 353 | controller->segment = segment; |
| 354 | if (!controller) | 354 | if (!controller) |
| 355 | BUG(); | 355 | BUG(); |
diff --git a/arch/ia64/sn/kernel/xpc.h b/arch/ia64/sn/kernel/xpc.h index fbcedc7c27fa..5483a9f227d4 100644 --- a/arch/ia64/sn/kernel/xpc.h +++ b/arch/ia64/sn/kernel/xpc.h | |||
| @@ -163,7 +163,7 @@ struct xpc_vars { | |||
| 163 | u8 version; | 163 | u8 version; |
| 164 | u64 heartbeat; | 164 | u64 heartbeat; |
| 165 | u64 heartbeating_to_mask; | 165 | u64 heartbeating_to_mask; |
| 166 | u64 kdb_status; /* 0 = machine running */ | 166 | u64 heartbeat_offline; /* if 0, heartbeat should be changing */ |
| 167 | int act_nasid; | 167 | int act_nasid; |
| 168 | int act_phys_cpuid; | 168 | int act_phys_cpuid; |
| 169 | u64 vars_part_pa; | 169 | u64 vars_part_pa; |
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index cece3c7c69be..b617236524c6 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c | |||
| @@ -57,6 +57,7 @@ | |||
| 57 | #include <linux/reboot.h> | 57 | #include <linux/reboot.h> |
| 58 | #include <asm/sn/intr.h> | 58 | #include <asm/sn/intr.h> |
| 59 | #include <asm/sn/sn_sal.h> | 59 | #include <asm/sn/sn_sal.h> |
| 60 | #include <asm/kdebug.h> | ||
| 60 | #include <asm/uaccess.h> | 61 | #include <asm/uaccess.h> |
| 61 | #include "xpc.h" | 62 | #include "xpc.h" |
| 62 | 63 | ||
| @@ -188,6 +189,11 @@ static struct notifier_block xpc_reboot_notifier = { | |||
| 188 | .notifier_call = xpc_system_reboot, | 189 | .notifier_call = xpc_system_reboot, |
| 189 | }; | 190 | }; |
| 190 | 191 | ||
| 192 | static int xpc_system_die(struct notifier_block *, unsigned long, void *); | ||
| 193 | static struct notifier_block xpc_die_notifier = { | ||
| 194 | .notifier_call = xpc_system_die, | ||
| 195 | }; | ||
| 196 | |||
| 191 | 197 | ||
| 192 | /* | 198 | /* |
| 193 | * Timer function to enforce the timelimit on the partition disengage request. | 199 | * Timer function to enforce the timelimit on the partition disengage request. |
| @@ -997,6 +1003,9 @@ xpc_do_exit(enum xpc_retval reason) | |||
| 997 | /* take ourselves off of the reboot_notifier_list */ | 1003 | /* take ourselves off of the reboot_notifier_list */ |
| 998 | (void) unregister_reboot_notifier(&xpc_reboot_notifier); | 1004 | (void) unregister_reboot_notifier(&xpc_reboot_notifier); |
| 999 | 1005 | ||
| 1006 | /* take ourselves off of the die_notifier list */ | ||
| 1007 | (void) unregister_die_notifier(&xpc_die_notifier); | ||
| 1008 | |||
| 1000 | /* close down protections for IPI operations */ | 1009 | /* close down protections for IPI operations */ |
| 1001 | xpc_restrict_IPI_ops(); | 1010 | xpc_restrict_IPI_ops(); |
| 1002 | 1011 | ||
| @@ -1011,6 +1020,63 @@ xpc_do_exit(enum xpc_retval reason) | |||
| 1011 | 1020 | ||
| 1012 | 1021 | ||
| 1013 | /* | 1022 | /* |
| 1023 | * Called when the system is about to be either restarted or halted. | ||
| 1024 | */ | ||
| 1025 | static void | ||
| 1026 | xpc_die_disengage(void) | ||
| 1027 | { | ||
| 1028 | struct xpc_partition *part; | ||
| 1029 | partid_t partid; | ||
| 1030 | unsigned long engaged; | ||
| 1031 | long time, print_time, disengage_request_timeout; | ||
| 1032 | |||
| 1033 | |||
| 1034 | /* keep xpc_hb_checker thread from doing anything (just in case) */ | ||
| 1035 | xpc_exiting = 1; | ||
| 1036 | |||
| 1037 | xpc_vars->heartbeating_to_mask = 0; /* indicate we're deactivated */ | ||
| 1038 | |||
| 1039 | for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) { | ||
| 1040 | part = &xpc_partitions[partid]; | ||
| 1041 | |||
| 1042 | if (!XPC_SUPPORTS_DISENGAGE_REQUEST(part-> | ||
| 1043 | remote_vars_version)) { | ||
| 1044 | |||
| 1045 | /* just in case it was left set by an earlier XPC */ | ||
| 1046 | xpc_clear_partition_engaged(1UL << partid); | ||
| 1047 | continue; | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | if (xpc_partition_engaged(1UL << partid) || | ||
| 1051 | part->act_state != XPC_P_INACTIVE) { | ||
| 1052 | xpc_request_partition_disengage(part); | ||
| 1053 | xpc_mark_partition_disengaged(part); | ||
| 1054 | xpc_IPI_send_disengage(part); | ||
| 1055 | } | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | print_time = rtc_time(); | ||
| 1059 | disengage_request_timeout = print_time + | ||
| 1060 | (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second); | ||
| 1061 | |||
| 1062 | /* wait for all other partitions to disengage from us */ | ||
| 1063 | |||
| 1064 | while ((engaged = xpc_partition_engaged(-1UL)) && | ||
| 1065 | (time = rtc_time()) < disengage_request_timeout) { | ||
| 1066 | |||
| 1067 | if (time >= print_time) { | ||
| 1068 | dev_info(xpc_part, "waiting for remote partitions to " | ||
| 1069 | "disengage, engaged=0x%lx\n", engaged); | ||
| 1070 | print_time = time + (XPC_DISENGAGE_PRINTMSG_INTERVAL * | ||
| 1071 | sn_rtc_cycles_per_second); | ||
| 1072 | } | ||
| 1073 | } | ||
| 1074 | dev_info(xpc_part, "finished waiting for remote partitions to " | ||
| 1075 | "disengage, engaged=0x%lx\n", engaged); | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | |||
| 1079 | /* | ||
| 1014 | * This function is called when the system is being rebooted. | 1080 | * This function is called when the system is being rebooted. |
| 1015 | */ | 1081 | */ |
| 1016 | static int | 1082 | static int |
| @@ -1038,6 +1104,33 @@ xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) | |||
| 1038 | } | 1104 | } |
| 1039 | 1105 | ||
| 1040 | 1106 | ||
| 1107 | /* | ||
| 1108 | * This function is called when the system is being rebooted. | ||
| 1109 | */ | ||
| 1110 | static int | ||
| 1111 | xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | ||
| 1112 | { | ||
| 1113 | switch (event) { | ||
| 1114 | case DIE_MACHINE_RESTART: | ||
| 1115 | case DIE_MACHINE_HALT: | ||
| 1116 | xpc_die_disengage(); | ||
| 1117 | break; | ||
| 1118 | case DIE_MCA_MONARCH_ENTER: | ||
| 1119 | case DIE_INIT_MONARCH_ENTER: | ||
| 1120 | xpc_vars->heartbeat++; | ||
| 1121 | xpc_vars->heartbeat_offline = 1; | ||
| 1122 | break; | ||
| 1123 | case DIE_MCA_MONARCH_LEAVE: | ||
| 1124 | case DIE_INIT_MONARCH_LEAVE: | ||
| 1125 | xpc_vars->heartbeat++; | ||
| 1126 | xpc_vars->heartbeat_offline = 0; | ||
| 1127 | break; | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | return NOTIFY_DONE; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | |||
| 1041 | int __init | 1134 | int __init |
| 1042 | xpc_init(void) | 1135 | xpc_init(void) |
| 1043 | { | 1136 | { |
| @@ -1154,6 +1247,12 @@ xpc_init(void) | |||
| 1154 | dev_warn(xpc_part, "can't register reboot notifier\n"); | 1247 | dev_warn(xpc_part, "can't register reboot notifier\n"); |
| 1155 | } | 1248 | } |
| 1156 | 1249 | ||
| 1250 | /* add ourselves to the die_notifier list (i.e., ia64die_chain) */ | ||
| 1251 | ret = register_die_notifier(&xpc_die_notifier); | ||
| 1252 | if (ret != 0) { | ||
| 1253 | dev_warn(xpc_part, "can't register die notifier\n"); | ||
| 1254 | } | ||
| 1255 | |||
| 1157 | 1256 | ||
| 1158 | /* | 1257 | /* |
| 1159 | * Set the beating to other partitions into motion. This is | 1258 | * Set the beating to other partitions into motion. This is |
| @@ -1179,6 +1278,9 @@ xpc_init(void) | |||
| 1179 | /* take ourselves off of the reboot_notifier_list */ | 1278 | /* take ourselves off of the reboot_notifier_list */ |
| 1180 | (void) unregister_reboot_notifier(&xpc_reboot_notifier); | 1279 | (void) unregister_reboot_notifier(&xpc_reboot_notifier); |
| 1181 | 1280 | ||
| 1281 | /* take ourselves off of the die_notifier list */ | ||
| 1282 | (void) unregister_die_notifier(&xpc_die_notifier); | ||
| 1283 | |||
| 1182 | del_timer_sync(&xpc_hb_timer); | 1284 | del_timer_sync(&xpc_hb_timer); |
| 1183 | free_irq(SGI_XPC_ACTIVATE, NULL); | 1285 | free_irq(SGI_XPC_ACTIVATE, NULL); |
| 1184 | xpc_restrict_IPI_ops(); | 1286 | xpc_restrict_IPI_ops(); |
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c index 581e113d2d37..cdd6431853a1 100644 --- a/arch/ia64/sn/kernel/xpc_partition.c +++ b/arch/ia64/sn/kernel/xpc_partition.c | |||
| @@ -436,13 +436,13 @@ xpc_check_remote_hb(void) | |||
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat" | 438 | dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat" |
| 439 | " = %ld, kdb_status = %ld, HB_mask = 0x%lx\n", partid, | 439 | " = %ld, heartbeat_offline = %ld, HB_mask = 0x%lx\n", |
| 440 | remote_vars->heartbeat, part->last_heartbeat, | 440 | partid, remote_vars->heartbeat, part->last_heartbeat, |
| 441 | remote_vars->kdb_status, | 441 | remote_vars->heartbeat_offline, |
| 442 | remote_vars->heartbeating_to_mask); | 442 | remote_vars->heartbeating_to_mask); |
| 443 | 443 | ||
| 444 | if (((remote_vars->heartbeat == part->last_heartbeat) && | 444 | if (((remote_vars->heartbeat == part->last_heartbeat) && |
| 445 | (remote_vars->kdb_status == 0)) || | 445 | (remote_vars->heartbeat_offline == 0)) || |
| 446 | !xpc_hb_allowed(sn_partition_id, remote_vars)) { | 446 | !xpc_hb_allowed(sn_partition_id, remote_vars)) { |
| 447 | 447 | ||
| 448 | XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat); | 448 | XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat); |
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index 9f03d4e5121c..dda196c9e324 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c | |||
| @@ -218,7 +218,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
| 218 | if (i > last) | 218 | if (i > last) |
| 219 | return 0; | 219 | return 0; |
| 220 | 220 | ||
| 221 | map = kcalloc(1, sizeof(struct tioce_dmamap), GFP_ATOMIC); | 221 | map = kzalloc(sizeof(struct tioce_dmamap), GFP_ATOMIC); |
| 222 | if (!map) | 222 | if (!map) |
| 223 | return 0; | 223 | return 0; |
| 224 | 224 | ||
| @@ -555,7 +555,7 @@ tioce_kern_init(struct tioce_common *tioce_common) | |||
| 555 | struct tioce *tioce_mmr; | 555 | struct tioce *tioce_mmr; |
| 556 | struct tioce_kernel *tioce_kern; | 556 | struct tioce_kernel *tioce_kern; |
| 557 | 557 | ||
| 558 | tioce_kern = kcalloc(1, sizeof(struct tioce_kernel), GFP_KERNEL); | 558 | tioce_kern = kzalloc(sizeof(struct tioce_kernel), GFP_KERNEL); |
| 559 | if (!tioce_kern) { | 559 | if (!tioce_kern) { |
| 560 | return NULL; | 560 | return NULL; |
| 561 | } | 561 | } |
| @@ -727,7 +727,7 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont | |||
| 727 | * Allocate kernel bus soft and copy from prom. | 727 | * Allocate kernel bus soft and copy from prom. |
| 728 | */ | 728 | */ |
| 729 | 729 | ||
| 730 | tioce_common = kcalloc(1, sizeof(struct tioce_common), GFP_KERNEL); | 730 | tioce_common = kzalloc(sizeof(struct tioce_common), GFP_KERNEL); |
| 731 | if (!tioce_common) | 731 | if (!tioce_common) |
| 732 | return NULL; | 732 | return NULL; |
| 733 | 733 | ||
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index e8f4e576750a..48ed58f995c0 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c | |||
| @@ -62,20 +62,6 @@ struct pci_controller** hose_tail = &hose_head; | |||
| 62 | static int pci_bus_count; | 62 | static int pci_bus_count; |
| 63 | 63 | ||
| 64 | static void | 64 | static void |
| 65 | fixup_rev1_53c810(struct pci_dev* dev) | ||
| 66 | { | ||
| 67 | /* rev 1 ncr53c810 chips don't set the class at all which means | ||
| 68 | * they don't get their resources remapped. Fix that here. | ||
| 69 | */ | ||
| 70 | |||
| 71 | if ((dev->class == PCI_CLASS_NOT_DEFINED)) { | ||
| 72 | printk("NCR 53c810 rev 1 detected, setting PCI class.\n"); | ||
| 73 | dev->class = PCI_CLASS_STORAGE_SCSI; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); | ||
| 77 | |||
| 78 | static void | ||
| 79 | fixup_broken_pcnet32(struct pci_dev* dev) | 65 | fixup_broken_pcnet32(struct pci_dev* dev) |
| 80 | { | 66 | { |
| 81 | if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { | 67 | if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 3937adf4e5e5..aa993715d644 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -203,6 +203,7 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) | |||
| 203 | acpi_get_devices(PCI_ROOT_HID_STRING, find_pci_rootbridge, &find, NULL); | 203 | acpi_get_devices(PCI_ROOT_HID_STRING, find_pci_rootbridge, &find, NULL); |
| 204 | return find.handle; | 204 | return find.handle; |
| 205 | } | 205 | } |
| 206 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); | ||
| 206 | 207 | ||
| 207 | /* Get device's handler per its address under its parent */ | 208 | /* Get device's handler per its address under its parent */ |
| 208 | struct acpi_find_child { | 209 | struct acpi_find_child { |
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index ba54b5872578..b02fc2267159 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c | |||
| @@ -389,7 +389,6 @@ static struct pci_device_id agp_ali_pci_table[] = { | |||
| 389 | MODULE_DEVICE_TABLE(pci, agp_ali_pci_table); | 389 | MODULE_DEVICE_TABLE(pci, agp_ali_pci_table); |
| 390 | 390 | ||
| 391 | static struct pci_driver agp_ali_pci_driver = { | 391 | static struct pci_driver agp_ali_pci_driver = { |
| 392 | .owner = THIS_MODULE, | ||
| 393 | .name = "agpgart-ali", | 392 | .name = "agpgart-ali", |
| 394 | .id_table = agp_ali_pci_table, | 393 | .id_table = agp_ali_pci_table, |
| 395 | .probe = agp_ali_probe, | 394 | .probe = agp_ali_probe, |
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 40fcd88b2cea..1f776651ac64 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c | |||
| @@ -515,7 +515,6 @@ static struct pci_device_id agp_amdk7_pci_table[] = { | |||
| 515 | MODULE_DEVICE_TABLE(pci, agp_amdk7_pci_table); | 515 | MODULE_DEVICE_TABLE(pci, agp_amdk7_pci_table); |
| 516 | 516 | ||
| 517 | static struct pci_driver agp_amdk7_pci_driver = { | 517 | static struct pci_driver agp_amdk7_pci_driver = { |
| 518 | .owner = THIS_MODULE, | ||
| 519 | .name = "agpgart-amdk7", | 518 | .name = "agpgart-amdk7", |
| 520 | .id_table = agp_amdk7_pci_table, | 519 | .id_table = agp_amdk7_pci_table, |
| 521 | .probe = agp_amdk7_probe, | 520 | .probe = agp_amdk7_probe, |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 8f748fddca94..78ce98a69f37 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
| @@ -703,7 +703,6 @@ static struct pci_device_id agp_amd64_pci_table[] = { | |||
| 703 | MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table); | 703 | MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table); |
| 704 | 704 | ||
| 705 | static struct pci_driver agp_amd64_pci_driver = { | 705 | static struct pci_driver agp_amd64_pci_driver = { |
| 706 | .owner = THIS_MODULE, | ||
| 707 | .name = "agpgart-amd64", | 706 | .name = "agpgart-amd64", |
| 708 | .id_table = agp_amd64_pci_table, | 707 | .id_table = agp_amd64_pci_table, |
| 709 | .probe = agp_amd64_probe, | 708 | .probe = agp_amd64_probe, |
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index fbd415565463..53372a83b675 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c | |||
| @@ -521,7 +521,6 @@ static struct pci_device_id agp_ati_pci_table[] = { | |||
| 521 | MODULE_DEVICE_TABLE(pci, agp_ati_pci_table); | 521 | MODULE_DEVICE_TABLE(pci, agp_ati_pci_table); |
| 522 | 522 | ||
| 523 | static struct pci_driver agp_ati_pci_driver = { | 523 | static struct pci_driver agp_ati_pci_driver = { |
| 524 | .owner = THIS_MODULE, | ||
| 525 | .name = "agpgart-ati", | 524 | .name = "agpgart-ati", |
| 526 | .id_table = agp_ati_pci_table, | 525 | .id_table = agp_ati_pci_table, |
| 527 | .probe = agp_ati_probe, | 526 | .probe = agp_ati_probe, |
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index d41e0a62e32e..e7aea77a60f9 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c | |||
| @@ -429,7 +429,6 @@ static struct pci_device_id agp_efficeon_pci_table[] = { | |||
| 429 | MODULE_DEVICE_TABLE(pci, agp_efficeon_pci_table); | 429 | MODULE_DEVICE_TABLE(pci, agp_efficeon_pci_table); |
| 430 | 430 | ||
| 431 | static struct pci_driver agp_efficeon_pci_driver = { | 431 | static struct pci_driver agp_efficeon_pci_driver = { |
| 432 | .owner = THIS_MODULE, | ||
| 433 | .name = "agpgart-efficeon", | 432 | .name = "agpgart-efficeon", |
| 434 | .id_table = agp_efficeon_pci_table, | 433 | .id_table = agp_efficeon_pci_table, |
| 435 | .probe = agp_efficeon_probe, | 434 | .probe = agp_efficeon_probe, |
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 34a444658ffe..8ee19a4a6bce 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c | |||
| @@ -622,7 +622,6 @@ static struct pci_device_id agp_intel_i460_pci_table[] = { | |||
| 622 | MODULE_DEVICE_TABLE(pci, agp_intel_i460_pci_table); | 622 | MODULE_DEVICE_TABLE(pci, agp_intel_i460_pci_table); |
| 623 | 623 | ||
| 624 | static struct pci_driver agp_intel_i460_pci_driver = { | 624 | static struct pci_driver agp_intel_i460_pci_driver = { |
| 625 | .owner = THIS_MODULE, | ||
| 626 | .name = "agpgart-intel-i460", | 625 | .name = "agpgart-intel-i460", |
| 627 | .id_table = agp_intel_i460_pci_table, | 626 | .id_table = agp_intel_i460_pci_table, |
| 628 | .probe = agp_intel_i460_probe, | 627 | .probe = agp_intel_i460_probe, |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 027161ab88e9..e7bed5047dcc 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
| @@ -1827,7 +1827,6 @@ static struct pci_device_id agp_intel_pci_table[] = { | |||
| 1827 | MODULE_DEVICE_TABLE(pci, agp_intel_pci_table); | 1827 | MODULE_DEVICE_TABLE(pci, agp_intel_pci_table); |
| 1828 | 1828 | ||
| 1829 | static struct pci_driver agp_intel_pci_driver = { | 1829 | static struct pci_driver agp_intel_pci_driver = { |
| 1830 | .owner = THIS_MODULE, | ||
| 1831 | .name = "agpgart-intel", | 1830 | .name = "agpgart-intel", |
| 1832 | .id_table = agp_intel_pci_table, | 1831 | .id_table = agp_intel_pci_table, |
| 1833 | .probe = agp_intel_probe, | 1832 | .probe = agp_intel_probe, |
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 3aed0c5e2f92..80dafa3030bd 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c | |||
| @@ -398,7 +398,6 @@ static struct pci_device_id agp_nvidia_pci_table[] = { | |||
| 398 | MODULE_DEVICE_TABLE(pci, agp_nvidia_pci_table); | 398 | MODULE_DEVICE_TABLE(pci, agp_nvidia_pci_table); |
| 399 | 399 | ||
| 400 | static struct pci_driver agp_nvidia_pci_driver = { | 400 | static struct pci_driver agp_nvidia_pci_driver = { |
| 401 | .owner = THIS_MODULE, | ||
| 402 | .name = "agpgart-nvidia", | 401 | .name = "agpgart-nvidia", |
| 403 | .id_table = agp_nvidia_pci_table, | 402 | .id_table = agp_nvidia_pci_table, |
| 404 | .probe = agp_nvidia_probe, | 403 | .probe = agp_nvidia_probe, |
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index a701361a8890..ebc05554045c 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c | |||
| @@ -332,7 +332,6 @@ static struct pci_device_id agp_sis_pci_table[] = { | |||
| 332 | MODULE_DEVICE_TABLE(pci, agp_sis_pci_table); | 332 | MODULE_DEVICE_TABLE(pci, agp_sis_pci_table); |
| 333 | 333 | ||
| 334 | static struct pci_driver agp_sis_pci_driver = { | 334 | static struct pci_driver agp_sis_pci_driver = { |
| 335 | .owner = THIS_MODULE, | ||
| 336 | .name = "agpgart-sis", | 335 | .name = "agpgart-sis", |
| 337 | .id_table = agp_sis_pci_table, | 336 | .id_table = agp_sis_pci_table, |
| 338 | .probe = agp_sis_probe, | 337 | .probe = agp_sis_probe, |
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 5a5392dd1254..3f8f7fa6b0ff 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c | |||
| @@ -545,7 +545,6 @@ static struct pci_device_id agp_serverworks_pci_table[] = { | |||
| 545 | MODULE_DEVICE_TABLE(pci, agp_serverworks_pci_table); | 545 | MODULE_DEVICE_TABLE(pci, agp_serverworks_pci_table); |
| 546 | 546 | ||
| 547 | static struct pci_driver agp_serverworks_pci_driver = { | 547 | static struct pci_driver agp_serverworks_pci_driver = { |
| 548 | .owner = THIS_MODULE, | ||
| 549 | .name = "agpgart-serverworks", | 548 | .name = "agpgart-serverworks", |
| 550 | .id_table = agp_serverworks_pci_table, | 549 | .id_table = agp_serverworks_pci_table, |
| 551 | .probe = agp_serverworks_probe, | 550 | .probe = agp_serverworks_probe, |
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 183c50acab27..c8255312b8c1 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c | |||
| @@ -658,7 +658,6 @@ static struct pci_device_id agp_uninorth_pci_table[] = { | |||
| 658 | MODULE_DEVICE_TABLE(pci, agp_uninorth_pci_table); | 658 | MODULE_DEVICE_TABLE(pci, agp_uninorth_pci_table); |
| 659 | 659 | ||
| 660 | static struct pci_driver agp_uninorth_pci_driver = { | 660 | static struct pci_driver agp_uninorth_pci_driver = { |
| 661 | .owner = THIS_MODULE, | ||
| 662 | .name = "agpgart-uninorth", | 661 | .name = "agpgart-uninorth", |
| 663 | .id_table = agp_uninorth_pci_table, | 662 | .id_table = agp_uninorth_pci_table, |
| 664 | .probe = agp_uninorth_probe, | 663 | .probe = agp_uninorth_probe, |
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index 5d9a13700074..c847df575cf5 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c | |||
| @@ -518,7 +518,6 @@ MODULE_DEVICE_TABLE(pci, agp_via_pci_table); | |||
| 518 | 518 | ||
| 519 | 519 | ||
| 520 | static struct pci_driver agp_via_pci_driver = { | 520 | static struct pci_driver agp_via_pci_driver = { |
| 521 | .owner = THIS_MODULE, | ||
| 522 | .name = "agpgart-via", | 521 | .name = "agpgart-via", |
| 523 | .id_table = agp_via_pci_table, | 522 | .id_table = agp_via_pci_table, |
| 524 | .probe = agp_via_probe, | 523 | .probe = agp_via_probe, |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index b7a0e4d6b934..407708a001e4 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
| @@ -3113,7 +3113,6 @@ MODULE_DEVICE_TABLE(pci, epca_pci_tbl); | |||
| 3113 | int __init init_PCI (void) | 3113 | int __init init_PCI (void) |
| 3114 | { /* Begin init_PCI */ | 3114 | { /* Begin init_PCI */ |
| 3115 | memset (&epca_driver, 0, sizeof (epca_driver)); | 3115 | memset (&epca_driver, 0, sizeof (epca_driver)); |
| 3116 | epca_driver.owner = THIS_MODULE; | ||
| 3117 | epca_driver.name = "epca"; | 3116 | epca_driver.name = "epca"; |
| 3118 | epca_driver.id_table = epca_pci_tbl; | 3117 | epca_driver.id_table = epca_pci_tbl; |
| 3119 | epca_driver.probe = epca_init_one; | 3118 | epca_driver.probe = epca_init_one; |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 5d1ffa3bd4c3..82c6abde68df 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
| @@ -912,7 +912,6 @@ MODULE_DEVICE_TABLE(pci, synclink_pci_tbl); | |||
| 912 | MODULE_LICENSE("GPL"); | 912 | MODULE_LICENSE("GPL"); |
| 913 | 913 | ||
| 914 | static struct pci_driver synclink_pci_driver = { | 914 | static struct pci_driver synclink_pci_driver = { |
| 915 | .owner = THIS_MODULE, | ||
| 916 | .name = "synclink", | 915 | .name = "synclink", |
| 917 | .id_table = synclink_pci_tbl, | 916 | .id_table = synclink_pci_tbl, |
| 918 | .probe = synclink_init_one, | 917 | .probe = synclink_init_one, |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 7c063c5abc55..ee5a40be9f99 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
| @@ -500,7 +500,6 @@ MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl); | |||
| 500 | MODULE_LICENSE("GPL"); | 500 | MODULE_LICENSE("GPL"); |
| 501 | 501 | ||
| 502 | static struct pci_driver synclinkmp_pci_driver = { | 502 | static struct pci_driver synclinkmp_pci_driver = { |
| 503 | .owner = THIS_MODULE, | ||
| 504 | .name = "synclinkmp", | 503 | .name = "synclinkmp", |
| 505 | .id_table = synclinkmp_pci_tbl, | 504 | .id_table = synclinkmp_pci_tbl, |
| 506 | .probe = synclinkmp_init_one, | 505 | .probe = synclinkmp_init_one, |
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c index d9ef55bdf88a..2451edbefece 100644 --- a/drivers/char/watchdog/pcwd_pci.c +++ b/drivers/char/watchdog/pcwd_pci.c | |||
| @@ -755,7 +755,6 @@ static struct pci_device_id pcipcwd_pci_tbl[] = { | |||
| 755 | MODULE_DEVICE_TABLE(pci, pcipcwd_pci_tbl); | 755 | MODULE_DEVICE_TABLE(pci, pcipcwd_pci_tbl); |
| 756 | 756 | ||
| 757 | static struct pci_driver pcipcwd_driver = { | 757 | static struct pci_driver pcipcwd_driver = { |
| 758 | .owner = THIS_MODULE, | ||
| 759 | .name = WATCHDOG_NAME, | 758 | .name = WATCHDOG_NAME, |
| 760 | .id_table = pcipcwd_pci_tbl, | 759 | .id_table = pcipcwd_pci_tbl, |
| 761 | .probe = pcipcwd_card_init, | 760 | .probe = pcipcwd_card_init, |
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c index dc9370f6c348..4b3311993d48 100644 --- a/drivers/char/watchdog/wdt_pci.c +++ b/drivers/char/watchdog/wdt_pci.c | |||
| @@ -711,7 +711,6 @@ MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl); | |||
| 711 | 711 | ||
| 712 | 712 | ||
| 713 | static struct pci_driver wdtpci_driver = { | 713 | static struct pci_driver wdtpci_driver = { |
| 714 | .owner = THIS_MODULE, | ||
| 715 | .name = "wdt_pci", | 714 | .name = "wdt_pci", |
| 716 | .id_table = wdtpci_pci_tbl, | 715 | .id_table = wdtpci_pci_tbl, |
| 717 | .probe = wdtpci_init_one, | 716 | .probe = wdtpci_init_one, |
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index ba90f5140af6..3eb47890db40 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c | |||
| @@ -513,7 +513,6 @@ static void __devexit ali1535_remove(struct pci_dev *dev) | |||
| 513 | } | 513 | } |
| 514 | 514 | ||
| 515 | static struct pci_driver ali1535_driver = { | 515 | static struct pci_driver ali1535_driver = { |
| 516 | .owner = THIS_MODULE, | ||
| 517 | .name = "ali1535_smbus", | 516 | .name = "ali1535_smbus", |
| 518 | .id_table = ali1535_ids, | 517 | .id_table = ali1535_ids, |
| 519 | .probe = ali1535_probe, | 518 | .probe = ali1535_probe, |
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index f1a62d892425..e6f63208fc4a 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c | |||
| @@ -408,7 +408,6 @@ static struct pci_device_id __devinitdata ali1563_id_table[] = { | |||
| 408 | MODULE_DEVICE_TABLE (pci, ali1563_id_table); | 408 | MODULE_DEVICE_TABLE (pci, ali1563_id_table); |
| 409 | 409 | ||
| 410 | static struct pci_driver ali1563_pci_driver = { | 410 | static struct pci_driver ali1563_pci_driver = { |
| 411 | .owner = THIS_MODULE, | ||
| 412 | .name = "ali1563_smbus", | 411 | .name = "ali1563_smbus", |
| 413 | .id_table = ali1563_id_table, | 412 | .id_table = ali1563_id_table, |
| 414 | .probe = ali1563_probe, | 413 | .probe = ali1563_probe, |
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 400b08ed4299..7a5c0941dbc1 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c | |||
| @@ -504,7 +504,6 @@ static void __devexit ali15x3_remove(struct pci_dev *dev) | |||
| 504 | } | 504 | } |
| 505 | 505 | ||
| 506 | static struct pci_driver ali15x3_driver = { | 506 | static struct pci_driver ali15x3_driver = { |
| 507 | .owner = THIS_MODULE, | ||
| 508 | .name = "ali15x3_smbus", | 507 | .name = "ali15x3_smbus", |
| 509 | .id_table = ali15x3_ids, | 508 | .id_table = ali15x3_ids, |
| 510 | .probe = ali15x3_probe, | 509 | .probe = ali15x3_probe, |
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index de035d137c3f..1750dedaf4b5 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c | |||
| @@ -401,7 +401,6 @@ static void __devexit amd756_remove(struct pci_dev *dev) | |||
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | static struct pci_driver amd756_driver = { | 403 | static struct pci_driver amd756_driver = { |
| 404 | .owner = THIS_MODULE, | ||
| 405 | .name = "amd756_smbus", | 404 | .name = "amd756_smbus", |
| 406 | .id_table = amd756_ids, | 405 | .id_table = amd756_ids, |
| 407 | .probe = amd756_probe, | 406 | .probe = amd756_probe, |
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index f3b79a68dbec..e5ef560e686a 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c | |||
| @@ -384,7 +384,6 @@ static void __devexit amd8111_remove(struct pci_dev *dev) | |||
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | static struct pci_driver amd8111_driver = { | 386 | static struct pci_driver amd8111_driver = { |
| 387 | .owner = THIS_MODULE, | ||
| 388 | .name = "amd8111_smbus2", | 387 | .name = "amd8111_smbus2", |
| 389 | .id_table = amd8111_ids, | 388 | .id_table = amd8111_ids, |
| 390 | .probe = amd8111_probe, | 389 | .probe = amd8111_probe, |
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c index 1b5354e24bf5..e0cb3b0f92fa 100644 --- a/drivers/i2c/busses/i2c-hydra.c +++ b/drivers/i2c/busses/i2c-hydra.c | |||
| @@ -155,7 +155,6 @@ static void __devexit hydra_remove(struct pci_dev *dev) | |||
| 155 | 155 | ||
| 156 | 156 | ||
| 157 | static struct pci_driver hydra_driver = { | 157 | static struct pci_driver hydra_driver = { |
| 158 | .owner = THIS_MODULE, | ||
| 159 | .name = "hydra_smbus", | 158 | .name = "hydra_smbus", |
| 160 | .id_table = hydra_ids, | 159 | .id_table = hydra_ids, |
| 161 | .probe = hydra_probe, | 160 | .probe = hydra_probe, |
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 4f63195069da..ac3eafa8aac0 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
| @@ -560,7 +560,6 @@ static void __devexit i801_remove(struct pci_dev *dev) | |||
| 560 | } | 560 | } |
| 561 | 561 | ||
| 562 | static struct pci_driver i801_driver = { | 562 | static struct pci_driver i801_driver = { |
| 563 | .owner = THIS_MODULE, | ||
| 564 | .name = "i801_smbus", | 563 | .name = "i801_smbus", |
| 565 | .id_table = i801_ids, | 564 | .id_table = i801_ids, |
| 566 | .probe = i801_probe, | 565 | .probe = i801_probe, |
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c index 52bc30593bd7..748be30f2bae 100644 --- a/drivers/i2c/busses/i2c-i810.c +++ b/drivers/i2c/busses/i2c-i810.c | |||
| @@ -233,7 +233,6 @@ static void __devexit i810_remove(struct pci_dev *dev) | |||
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | static struct pci_driver i810_driver = { | 235 | static struct pci_driver i810_driver = { |
| 236 | .owner = THIS_MODULE, | ||
| 237 | .name = "i810_smbus", | 236 | .name = "i810_smbus", |
| 238 | .id_table = i810_ids, | 237 | .id_table = i810_ids, |
| 239 | .probe = i810_probe, | 238 | .probe = i810_probe, |
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index fd26036e68a3..4d18e6e5f159 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c | |||
| @@ -347,7 +347,6 @@ static void __devexit nforce2_remove(struct pci_dev *dev) | |||
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | static struct pci_driver nforce2_driver = { | 349 | static struct pci_driver nforce2_driver = { |
| 350 | .owner = THIS_MODULE, | ||
| 351 | .name = "nForce2_smbus", | 350 | .name = "nForce2_smbus", |
| 352 | .id_table = nforce2_ids, | 351 | .id_table = nforce2_ids, |
| 353 | .probe = nforce2_probe, | 352 | .probe = nforce2_probe, |
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 7d63eec423fe..692f47345481 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c | |||
| @@ -462,7 +462,6 @@ static void __devexit piix4_remove(struct pci_dev *dev) | |||
| 462 | } | 462 | } |
| 463 | 463 | ||
| 464 | static struct pci_driver piix4_driver = { | 464 | static struct pci_driver piix4_driver = { |
| 465 | .owner = THIS_MODULE, | ||
| 466 | .name = "piix4_smbus", | 465 | .name = "piix4_smbus", |
| 467 | .id_table = piix4_ids, | 466 | .id_table = piix4_ids, |
| 468 | .probe = piix4_probe, | 467 | .probe = piix4_probe, |
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c index 42cb1d8ca659..9479525892e3 100644 --- a/drivers/i2c/busses/i2c-prosavage.c +++ b/drivers/i2c/busses/i2c-prosavage.c | |||
| @@ -301,7 +301,6 @@ static struct pci_device_id prosavage_pci_tbl[] = { | |||
| 301 | MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl); | 301 | MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl); |
| 302 | 302 | ||
| 303 | static struct pci_driver prosavage_driver = { | 303 | static struct pci_driver prosavage_driver = { |
| 304 | .owner = THIS_MODULE, | ||
| 305 | .name = "prosavage_smbus", | 304 | .name = "prosavage_smbus", |
| 306 | .id_table = prosavage_pci_tbl, | 305 | .id_table = prosavage_pci_tbl, |
| 307 | .probe = prosavage_probe, | 306 | .probe = prosavage_probe, |
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c index aebe87ba4033..0c8518298e4d 100644 --- a/drivers/i2c/busses/i2c-savage4.c +++ b/drivers/i2c/busses/i2c-savage4.c | |||
| @@ -179,7 +179,6 @@ static void __devexit savage4_remove(struct pci_dev *dev) | |||
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | static struct pci_driver savage4_driver = { | 181 | static struct pci_driver savage4_driver = { |
| 182 | .owner = THIS_MODULE, | ||
| 183 | .name = "savage4_smbus", | 182 | .name = "savage4_smbus", |
| 184 | .id_table = savage4_ids, | 183 | .id_table = savage4_ids, |
| 185 | .probe = savage4_probe, | 184 | .probe = savage4_probe, |
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index 3ad27c3ba15b..b57ab74d23ec 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c | |||
| @@ -398,7 +398,6 @@ static void __devexit sis5595_remove(struct pci_dev *dev) | |||
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | static struct pci_driver sis5595_driver = { | 400 | static struct pci_driver sis5595_driver = { |
| 401 | .owner = THIS_MODULE, | ||
| 402 | .name = "sis5595_smbus", | 401 | .name = "sis5595_smbus", |
| 403 | .id_table = sis5595_ids, | 402 | .id_table = sis5595_ids, |
| 404 | .probe = sis5595_probe, | 403 | .probe = sis5595_probe, |
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 7f49e5fd3ff0..acb75e282414 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c | |||
| @@ -496,7 +496,6 @@ static void __devexit sis630_remove(struct pci_dev *dev) | |||
| 496 | 496 | ||
| 497 | 497 | ||
| 498 | static struct pci_driver sis630_driver = { | 498 | static struct pci_driver sis630_driver = { |
| 499 | .owner = THIS_MODULE, | ||
| 500 | .name = "sis630_smbus", | 499 | .name = "sis630_smbus", |
| 501 | .id_table = sis630_ids, | 500 | .id_table = sis630_ids, |
| 502 | .probe = sis630_probe, | 501 | .probe = sis630_probe, |
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c index 6a134c091324..3024907cdafe 100644 --- a/drivers/i2c/busses/i2c-sis96x.c +++ b/drivers/i2c/busses/i2c-sis96x.c | |||
| @@ -329,7 +329,6 @@ static void __devexit sis96x_remove(struct pci_dev *dev) | |||
| 329 | } | 329 | } |
| 330 | 330 | ||
| 331 | static struct pci_driver sis96x_driver = { | 331 | static struct pci_driver sis96x_driver = { |
| 332 | .owner = THIS_MODULE, | ||
| 333 | .name = "sis96x_smbus", | 332 | .name = "sis96x_smbus", |
| 334 | .id_table = sis96x_ids, | 333 | .id_table = sis96x_ids, |
| 335 | .probe = sis96x_probe, | 334 | .probe = sis96x_probe, |
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c index 544a38e64394..484bbacfce6b 100644 --- a/drivers/i2c/busses/i2c-via.c +++ b/drivers/i2c/busses/i2c-via.c | |||
| @@ -159,7 +159,6 @@ static void __devexit vt586b_remove(struct pci_dev *dev) | |||
| 159 | 159 | ||
| 160 | 160 | ||
| 161 | static struct pci_driver vt586b_driver = { | 161 | static struct pci_driver vt586b_driver = { |
| 162 | .owner = THIS_MODULE, | ||
| 163 | .name = "vt586b_smbus", | 162 | .name = "vt586b_smbus", |
| 164 | .id_table = vt586b_ids, | 163 | .id_table = vt586b_ids, |
| 165 | .probe = vt586b_probe, | 164 | .probe = vt586b_probe, |
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index a2237d4b2cf2..47e52bf2c5ec 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c | |||
| @@ -440,7 +440,6 @@ static struct pci_device_id vt596_ids[] = { | |||
| 440 | MODULE_DEVICE_TABLE(pci, vt596_ids); | 440 | MODULE_DEVICE_TABLE(pci, vt596_ids); |
| 441 | 441 | ||
| 442 | static struct pci_driver vt596_driver = { | 442 | static struct pci_driver vt596_driver = { |
| 443 | .owner = THIS_MODULE, | ||
| 444 | .name = "vt596_smbus", | 443 | .name = "vt596_smbus", |
| 445 | .id_table = vt596_ids, | 444 | .id_table = vt596_ids, |
| 446 | .probe = vt596_probe, | 445 | .probe = vt596_probe, |
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c index 650c3ebde84c..b675773b0cc1 100644 --- a/drivers/i2c/busses/i2c-voodoo3.c +++ b/drivers/i2c/busses/i2c-voodoo3.c | |||
| @@ -225,7 +225,6 @@ static void __devexit voodoo3_remove(struct pci_dev *dev) | |||
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | static struct pci_driver voodoo3_driver = { | 227 | static struct pci_driver voodoo3_driver = { |
| 228 | .owner = THIS_MODULE, | ||
| 229 | .name = "voodoo3_smbus", | 228 | .name = "voodoo3_smbus", |
| 230 | .id_table = voodoo3_ids, | 229 | .id_table = voodoo3_ids, |
| 231 | .probe = voodoo3_probe, | 230 | .probe = voodoo3_probe, |
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 18ed7765417c..d4f2111d4364 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c | |||
| @@ -787,8 +787,9 @@ static int pre_init = 1; /* Before first ordered IDE scan */ | |||
| 787 | static LIST_HEAD(ide_pci_drivers); | 787 | static LIST_HEAD(ide_pci_drivers); |
| 788 | 788 | ||
| 789 | /* | 789 | /* |
| 790 | * ide_register_pci_driver - attach IDE driver | 790 | * __ide_register_pci_driver - attach IDE driver |
| 791 | * @driver: pci driver | 791 | * @driver: pci driver |
| 792 | * @module: owner module of the driver | ||
| 792 | * | 793 | * |
| 793 | * Registers a driver with the IDE layer. The IDE layer arranges that | 794 | * Registers a driver with the IDE layer. The IDE layer arranges that |
| 794 | * boot time setup is done in the expected device order and then | 795 | * boot time setup is done in the expected device order and then |
| @@ -801,15 +802,16 @@ static LIST_HEAD(ide_pci_drivers); | |||
| 801 | * Returns are the same as for pci_register_driver | 802 | * Returns are the same as for pci_register_driver |
| 802 | */ | 803 | */ |
| 803 | 804 | ||
| 804 | int ide_pci_register_driver(struct pci_driver *driver) | 805 | int __ide_pci_register_driver(struct pci_driver *driver, struct module *module) |
| 805 | { | 806 | { |
| 806 | if(!pre_init) | 807 | if(!pre_init) |
| 807 | return pci_module_init(driver); | 808 | return __pci_register_driver(driver, module); |
| 809 | driver->driver.owner = module; | ||
| 808 | list_add_tail(&driver->node, &ide_pci_drivers); | 810 | list_add_tail(&driver->node, &ide_pci_drivers); |
| 809 | return 0; | 811 | return 0; |
| 810 | } | 812 | } |
| 811 | 813 | ||
| 812 | EXPORT_SYMBOL_GPL(ide_pci_register_driver); | 814 | EXPORT_SYMBOL_GPL(__ide_pci_register_driver); |
| 813 | 815 | ||
| 814 | /** | 816 | /** |
| 815 | * ide_unregister_pci_driver - unregister an IDE driver | 817 | * ide_unregister_pci_driver - unregister an IDE driver |
| @@ -897,6 +899,6 @@ void __init ide_scan_pcibus (int scan_direction) | |||
| 897 | { | 899 | { |
| 898 | list_del(l); | 900 | list_del(l); |
| 899 | d = list_entry(l, struct pci_driver, node); | 901 | d = list_entry(l, struct pci_driver, node); |
| 900 | pci_register_driver(d); | 902 | __pci_register_driver(d, d->driver.owner); |
| 901 | } | 903 | } |
| 902 | } | 904 | } |
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 147f248a8073..6f94b25f3acd 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c | |||
| @@ -1198,7 +1198,6 @@ MODULE_DEVICE_TABLE(pci, mthca_pci_table); | |||
| 1198 | 1198 | ||
| 1199 | static struct pci_driver mthca_driver = { | 1199 | static struct pci_driver mthca_driver = { |
| 1200 | .name = DRV_NAME, | 1200 | .name = DRV_NAME, |
| 1201 | .owner = THIS_MODULE, | ||
| 1202 | .id_table = mthca_pci_table, | 1201 | .id_table = mthca_pci_table, |
| 1203 | .probe = mthca_init_one, | 1202 | .probe = mthca_init_one, |
| 1204 | .remove = __devexit_p(mthca_remove_one) | 1203 | .remove = __devexit_p(mthca_remove_one) |
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index c796f41b4a52..0d765f1733b5 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c | |||
| @@ -2290,7 +2290,6 @@ spider_net_remove(struct pci_dev *pdev) | |||
| 2290 | } | 2290 | } |
| 2291 | 2291 | ||
| 2292 | static struct pci_driver spider_net_driver = { | 2292 | static struct pci_driver spider_net_driver = { |
| 2293 | .owner = THIS_MODULE, | ||
| 2294 | .name = spider_net_driver_name, | 2293 | .name = spider_net_driver_name, |
| 2295 | .id_table = spider_net_pci_tbl, | 2294 | .id_table = spider_net_pci_tbl, |
| 2296 | .probe = spider_net_probe, | 2295 | .probe = spider_net_probe, |
diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 2a42add7f563..ea16805a153c 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
| 3 | #include <linux/ioport.h> | 3 | #include <linux/ioport.h> |
| 4 | 4 | ||
| 5 | #include "pci.h" | ||
| 6 | |||
| 5 | /* | 7 | /* |
| 6 | * This interrupt-safe spinlock protects all accesses to PCI | 8 | * This interrupt-safe spinlock protects all accesses to PCI |
| 7 | * configuration space. | 9 | * configuration space. |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 061ead21ef14..c42b68d3aa24 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
| @@ -32,8 +32,6 @@ | |||
| 32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
| 33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
| 34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
| 35 | #include <asm/semaphore.h> | ||
| 36 | #include <asm/io.h> | ||
| 37 | #include <linux/pcieport_if.h> | 35 | #include <linux/pcieport_if.h> |
| 38 | #include "pci_hotplug.h" | 36 | #include "pci_hotplug.h" |
| 39 | 37 | ||
| @@ -42,6 +40,7 @@ | |||
| 42 | extern int pciehp_poll_mode; | 40 | extern int pciehp_poll_mode; |
| 43 | extern int pciehp_poll_time; | 41 | extern int pciehp_poll_time; |
| 44 | extern int pciehp_debug; | 42 | extern int pciehp_debug; |
| 43 | extern int pciehp_force; | ||
| 45 | 44 | ||
| 46 | /*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ | 45 | /*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ |
| 47 | #define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) | 46 | #define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) |
| @@ -49,39 +48,20 @@ extern int pciehp_debug; | |||
| 49 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) | 48 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) |
| 50 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) | 49 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) |
| 51 | 50 | ||
| 52 | struct pci_func { | 51 | struct hotplug_params { |
| 53 | struct pci_func *next; | 52 | u8 cache_line_size; |
| 54 | u8 bus; | 53 | u8 latency_timer; |
| 55 | u8 device; | 54 | u8 enable_serr; |
| 56 | u8 function; | 55 | u8 enable_perr; |
| 57 | u8 is_a_board; | ||
| 58 | u16 status; | ||
| 59 | u8 configured; | ||
| 60 | u8 switch_save; | ||
| 61 | u8 presence_save; | ||
| 62 | u32 base_length[0x06]; | ||
| 63 | u8 base_type[0x06]; | ||
| 64 | u16 reserved2; | ||
| 65 | u32 config_space[0x20]; | ||
| 66 | struct pci_resource *mem_head; | ||
| 67 | struct pci_resource *p_mem_head; | ||
| 68 | struct pci_resource *io_head; | ||
| 69 | struct pci_resource *bus_head; | ||
| 70 | struct pci_dev* pci_dev; | ||
| 71 | }; | 56 | }; |
| 72 | 57 | ||
| 73 | struct slot { | 58 | struct slot { |
| 74 | struct slot *next; | 59 | struct slot *next; |
| 75 | u8 bus; | 60 | u8 bus; |
| 76 | u8 device; | 61 | u8 device; |
| 62 | u16 status; | ||
| 77 | u32 number; | 63 | u32 number; |
| 78 | u8 is_a_board; | ||
| 79 | u8 configured; | ||
| 80 | u8 state; | 64 | u8 state; |
| 81 | u8 switch_save; | ||
| 82 | u8 presence_save; | ||
| 83 | u32 capabilities; | ||
| 84 | u16 reserved2; | ||
| 85 | struct timer_list task_event; | 65 | struct timer_list task_event; |
| 86 | u8 hp_slot; | 66 | u8 hp_slot; |
| 87 | struct controller *ctrl; | 67 | struct controller *ctrl; |
| @@ -90,42 +70,47 @@ struct slot { | |||
| 90 | struct list_head slot_list; | 70 | struct list_head slot_list; |
| 91 | }; | 71 | }; |
| 92 | 72 | ||
| 93 | struct pci_resource { | ||
| 94 | struct pci_resource * next; | ||
| 95 | u32 base; | ||
| 96 | u32 length; | ||
| 97 | }; | ||
| 98 | |||
| 99 | struct event_info { | 73 | struct event_info { |
| 100 | u32 event_type; | 74 | u32 event_type; |
| 101 | u8 hp_slot; | 75 | u8 hp_slot; |
| 102 | }; | 76 | }; |
| 103 | 77 | ||
| 78 | typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id); | ||
| 79 | |||
| 80 | struct php_ctlr_state_s { | ||
| 81 | struct php_ctlr_state_s *pnext; | ||
| 82 | struct pci_dev *pci_dev; | ||
| 83 | unsigned int irq; | ||
| 84 | unsigned long flags; /* spinlock's */ | ||
| 85 | u32 slot_device_offset; | ||
| 86 | u32 num_slots; | ||
| 87 | struct timer_list int_poll_timer; /* Added for poll event */ | ||
| 88 | php_intr_callback_t attention_button_callback; | ||
| 89 | php_intr_callback_t switch_change_callback; | ||
| 90 | php_intr_callback_t presence_change_callback; | ||
| 91 | php_intr_callback_t power_fault_callback; | ||
| 92 | void *callback_instance_id; | ||
| 93 | struct ctrl_reg *creg; /* Ptr to controller register space */ | ||
| 94 | }; | ||
| 95 | |||
| 96 | #define MAX_EVENTS 10 | ||
| 104 | struct controller { | 97 | struct controller { |
| 105 | struct controller *next; | 98 | struct controller *next; |
| 106 | struct semaphore crit_sect; /* critical section semaphore */ | 99 | struct semaphore crit_sect; /* critical section semaphore */ |
| 107 | void *hpc_ctlr_handle; /* HPC controller handle */ | 100 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ |
| 108 | int num_slots; /* Number of slots on ctlr */ | 101 | int num_slots; /* Number of slots on ctlr */ |
| 109 | int slot_num_inc; /* 1 or -1 */ | 102 | int slot_num_inc; /* 1 or -1 */ |
| 110 | struct pci_resource *mem_head; | ||
| 111 | struct pci_resource *p_mem_head; | ||
| 112 | struct pci_resource *io_head; | ||
| 113 | struct pci_resource *bus_head; | ||
| 114 | struct pci_dev *pci_dev; | 103 | struct pci_dev *pci_dev; |
| 115 | struct pci_bus *pci_bus; | 104 | struct pci_bus *pci_bus; |
| 116 | struct event_info event_queue[10]; | 105 | struct event_info event_queue[MAX_EVENTS]; |
| 117 | struct slot *slot; | 106 | struct slot *slot; |
| 118 | struct hpc_ops *hpc_ops; | 107 | struct hpc_ops *hpc_ops; |
| 119 | wait_queue_head_t queue; /* sleep & wake process */ | 108 | wait_queue_head_t queue; /* sleep & wake process */ |
| 120 | u8 next_event; | 109 | u8 next_event; |
| 121 | u8 seg; | ||
| 122 | u8 bus; | 110 | u8 bus; |
| 123 | u8 device; | 111 | u8 device; |
| 124 | u8 function; | 112 | u8 function; |
| 125 | u8 rev; | ||
| 126 | u8 slot_device_offset; | 113 | u8 slot_device_offset; |
| 127 | u8 add_support; | ||
| 128 | enum pci_bus_speed speed; | ||
| 129 | u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */ | 114 | u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */ |
| 130 | u8 slot_bus; /* Bus where the slots handled by this controller sit */ | 115 | u8 slot_bus; /* Bus where the slots handled by this controller sit */ |
| 131 | u8 ctrlcap; | 116 | u8 ctrlcap; |
| @@ -133,20 +118,6 @@ struct controller { | |||
| 133 | u8 cap_base; | 118 | u8 cap_base; |
| 134 | }; | 119 | }; |
| 135 | 120 | ||
| 136 | struct irq_mapping { | ||
| 137 | u8 barber_pole; | ||
| 138 | u8 valid_INT; | ||
| 139 | u8 interrupt[4]; | ||
| 140 | }; | ||
| 141 | |||
| 142 | struct resource_lists { | ||
| 143 | struct pci_resource *mem_head; | ||
| 144 | struct pci_resource *p_mem_head; | ||
| 145 | struct pci_resource *io_head; | ||
| 146 | struct pci_resource *bus_head; | ||
| 147 | struct irq_mapping *irqs; | ||
| 148 | }; | ||
| 149 | |||
| 150 | #define INT_BUTTON_IGNORE 0 | 121 | #define INT_BUTTON_IGNORE 0 |
| 151 | #define INT_PRESENCE_ON 1 | 122 | #define INT_PRESENCE_ON 1 |
| 152 | #define INT_PRESENCE_OFF 2 | 123 | #define INT_PRESENCE_OFF 2 |
| @@ -200,21 +171,14 @@ struct resource_lists { | |||
| 200 | * error Messages | 171 | * error Messages |
| 201 | */ | 172 | */ |
| 202 | #define msg_initialization_err "Initialization failure, error=%d\n" | 173 | #define msg_initialization_err "Initialization failure, error=%d\n" |
| 203 | #define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n" | ||
| 204 | #define msg_HPC_non_pcie "The PCI hot plug controller is not supported by this driver.\n" | ||
| 205 | #define msg_HPC_not_supported "This system is not supported by this version of pciephd module. Upgrade to a newer version of pciehpd\n" | ||
| 206 | #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" | ||
| 207 | #define msg_button_on "PCI slot #%d - powering on due to button press.\n" | 174 | #define msg_button_on "PCI slot #%d - powering on due to button press.\n" |
| 208 | #define msg_button_off "PCI slot #%d - powering off due to button press.\n" | 175 | #define msg_button_off "PCI slot #%d - powering off due to button press.\n" |
| 209 | #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" | 176 | #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" |
| 210 | #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" | 177 | #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" |
| 211 | 178 | ||
| 212 | /* controller functions */ | 179 | /* controller functions */ |
| 213 | extern int pciehprm_find_available_resources (struct controller *ctrl); | ||
| 214 | extern int pciehp_event_start_thread (void); | 180 | extern int pciehp_event_start_thread (void); |
| 215 | extern void pciehp_event_stop_thread (void); | 181 | extern void pciehp_event_stop_thread (void); |
| 216 | extern struct pci_func *pciehp_slot_create (unsigned char busnumber); | ||
| 217 | extern struct pci_func *pciehp_slot_find (unsigned char bus, unsigned char device, unsigned char index); | ||
| 218 | extern int pciehp_enable_slot (struct slot *slot); | 182 | extern int pciehp_enable_slot (struct slot *slot); |
| 219 | extern int pciehp_disable_slot (struct slot *slot); | 183 | extern int pciehp_disable_slot (struct slot *slot); |
| 220 | 184 | ||
| @@ -224,25 +188,17 @@ extern u8 pciehp_handle_presence_change (u8 hp_slot, void *inst_id); | |||
| 224 | extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); | 188 | extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); |
| 225 | /* extern void long_delay (int delay); */ | 189 | /* extern void long_delay (int delay); */ |
| 226 | 190 | ||
| 227 | /* resource functions */ | ||
| 228 | extern int pciehp_resource_sort_and_combine (struct pci_resource **head); | ||
| 229 | |||
| 230 | /* pci functions */ | 191 | /* pci functions */ |
| 231 | extern int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); | 192 | extern int pciehp_configure_device (struct slot *p_slot); |
| 232 | /*extern int pciehp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/ | 193 | extern int pciehp_unconfigure_device (struct slot *p_slot); |
| 233 | extern int pciehp_save_config (struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); | 194 | extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev); |
| 234 | extern int pciehp_save_used_resources (struct controller *ctrl, struct pci_func * func, int flag); | 195 | extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, |
| 235 | extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot); | 196 | struct hotplug_params *hpp); |
| 236 | extern void pciehp_destroy_board_resources (struct pci_func * func); | 197 | |
| 237 | extern int pciehp_return_board_resources (struct pci_func * func, struct resource_lists * resources); | ||
| 238 | extern void pciehp_destroy_resource_list (struct resource_lists * resources); | ||
| 239 | extern int pciehp_configure_device (struct controller* ctrl, struct pci_func* func); | ||
| 240 | extern int pciehp_unconfigure_device (struct pci_func* func); | ||
| 241 | 198 | ||
| 242 | 199 | ||
| 243 | /* Global variables */ | 200 | /* Global variables */ |
| 244 | extern struct controller *pciehp_ctrl_list; | 201 | extern struct controller *pciehp_ctrl_list; |
| 245 | extern struct pci_func *pciehp_slot_list[256]; | ||
| 246 | 202 | ||
| 247 | /* Inline functions */ | 203 | /* Inline functions */ |
| 248 | 204 | ||
| @@ -252,12 +208,9 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) | |||
| 252 | 208 | ||
| 253 | p_slot = ctrl->slot; | 209 | p_slot = ctrl->slot; |
| 254 | 210 | ||
| 255 | dbg("p_slot = %p\n", p_slot); | ||
| 256 | |||
| 257 | while (p_slot && (p_slot->device != device)) { | 211 | while (p_slot && (p_slot->device != device)) { |
| 258 | tmp_slot = p_slot; | 212 | tmp_slot = p_slot; |
| 259 | p_slot = p_slot->next; | 213 | p_slot = p_slot->next; |
| 260 | dbg("In while loop, p_slot = %p\n", p_slot); | ||
| 261 | } | 214 | } |
| 262 | if (p_slot == NULL) { | 215 | if (p_slot == NULL) { |
| 263 | err("ERROR: pciehp_find_slot device=0x%x\n", device); | 216 | err("ERROR: pciehp_find_slot device=0x%x\n", device); |
| @@ -273,7 +226,6 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl) | |||
| 273 | 226 | ||
| 274 | DECLARE_WAITQUEUE(wait, current); | 227 | DECLARE_WAITQUEUE(wait, current); |
| 275 | 228 | ||
| 276 | dbg("%s : start\n", __FUNCTION__); | ||
| 277 | add_wait_queue(&ctrl->queue, &wait); | 229 | add_wait_queue(&ctrl->queue, &wait); |
| 278 | if (!pciehp_poll_mode) | 230 | if (!pciehp_poll_mode) |
| 279 | /* Sleep for up to 1 second */ | 231 | /* Sleep for up to 1 second */ |
| @@ -285,19 +237,9 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl) | |||
| 285 | if (signal_pending(current)) | 237 | if (signal_pending(current)) |
| 286 | retval = -EINTR; | 238 | retval = -EINTR; |
| 287 | 239 | ||
| 288 | dbg("%s : end\n", __FUNCTION__); | ||
| 289 | return retval; | 240 | return retval; |
| 290 | } | 241 | } |
| 291 | 242 | ||
| 292 | /* Puts node back in the resource list pointed to by head */ | ||
| 293 | static inline void return_resource(struct pci_resource **head, struct pci_resource *node) | ||
| 294 | { | ||
| 295 | if (!node || !head) | ||
| 296 | return; | ||
| 297 | node->next = *head; | ||
| 298 | *head = node; | ||
| 299 | } | ||
| 300 | |||
| 301 | #define SLOT_NAME_SIZE 10 | 243 | #define SLOT_NAME_SIZE 10 |
| 302 | 244 | ||
| 303 | static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) | 245 | static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) |
| @@ -311,14 +253,7 @@ enum php_ctlr_type { | |||
| 311 | ACPI | 253 | ACPI |
| 312 | }; | 254 | }; |
| 313 | 255 | ||
| 314 | typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id); | 256 | int pcie_init(struct controller *ctrl, struct pcie_device *dev); |
| 315 | |||
| 316 | int pcie_init(struct controller *ctrl, struct pcie_device *dev, | ||
| 317 | php_intr_callback_t attention_button_callback, | ||
| 318 | php_intr_callback_t switch_change_callback, | ||
| 319 | php_intr_callback_t presence_change_callback, | ||
| 320 | php_intr_callback_t power_fault_callback); | ||
| 321 | |||
| 322 | 257 | ||
| 323 | /* This has no meaning for PCI Express, as there is only 1 slot per port */ | 258 | /* This has no meaning for PCI Express, as there is only 1 slot per port */ |
| 324 | int pcie_get_ctlr_slot_config(struct controller *ctrl, | 259 | 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 cafc7eadcf80..8df704860348 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
| @@ -27,27 +27,20 @@ | |||
| 27 | * | 27 | * |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #include <linux/config.h> | ||
| 31 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 32 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
| 33 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
| 34 | #include <linux/types.h> | 33 | #include <linux/types.h> |
| 35 | #include <linux/proc_fs.h> | ||
| 36 | #include <linux/slab.h> | ||
| 37 | #include <linux/workqueue.h> | ||
| 38 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
| 39 | #include <linux/init.h> | ||
| 40 | #include <asm/uaccess.h> | ||
| 41 | #include "pciehp.h" | 35 | #include "pciehp.h" |
| 42 | #include "pciehprm.h" | ||
| 43 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
| 44 | 37 | ||
| 45 | /* Global variables */ | 38 | /* Global variables */ |
| 46 | int pciehp_debug; | 39 | int pciehp_debug; |
| 47 | int pciehp_poll_mode; | 40 | int pciehp_poll_mode; |
| 48 | int pciehp_poll_time; | 41 | int pciehp_poll_time; |
| 42 | int pciehp_force; | ||
| 49 | struct controller *pciehp_ctrl_list; | 43 | struct controller *pciehp_ctrl_list; |
| 50 | struct pci_func *pciehp_slot_list[256]; | ||
| 51 | 44 | ||
| 52 | #define DRIVER_VERSION "0.4" | 45 | #define DRIVER_VERSION "0.4" |
| 53 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 46 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
| @@ -60,9 +53,11 @@ MODULE_LICENSE("GPL"); | |||
| 60 | module_param(pciehp_debug, bool, 0644); | 53 | module_param(pciehp_debug, bool, 0644); |
| 61 | module_param(pciehp_poll_mode, bool, 0644); | 54 | module_param(pciehp_poll_mode, bool, 0644); |
| 62 | module_param(pciehp_poll_time, int, 0644); | 55 | module_param(pciehp_poll_time, int, 0644); |
| 56 | module_param(pciehp_force, bool, 0644); | ||
| 63 | MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); | 57 | MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); |
| 64 | MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); | 58 | MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); |
| 65 | MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); | 59 | MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); |
| 60 | MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"); | ||
| 66 | 61 | ||
| 67 | #define PCIE_MODULE_NAME "pciehp" | 62 | #define PCIE_MODULE_NAME "pciehp" |
| 68 | 63 | ||
| @@ -114,8 +109,6 @@ static int init_slots(struct controller *ctrl) | |||
| 114 | u32 slot_number; | 109 | u32 slot_number; |
| 115 | int result = -ENOMEM; | 110 | int result = -ENOMEM; |
| 116 | 111 | ||
| 117 | dbg("%s\n",__FUNCTION__); | ||
| 118 | |||
| 119 | number_of_slots = ctrl->num_slots; | 112 | number_of_slots = ctrl->num_slots; |
| 120 | slot_device = ctrl->slot_device_offset; | 113 | slot_device = ctrl->slot_device_offset; |
| 121 | slot_number = ctrl->first_slot; | 114 | slot_number = ctrl->first_slot; |
| @@ -370,7 +363,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 370 | u8 value; | 363 | u8 value; |
| 371 | struct pci_dev *pdev; | 364 | struct pci_dev *pdev; |
| 372 | 365 | ||
| 373 | dbg("%s: Called by hp_drv\n", __FUNCTION__); | ||
| 374 | ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL); | 366 | ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL); |
| 375 | if (!ctrl) { | 367 | if (!ctrl) { |
| 376 | err("%s : out of memory\n", __FUNCTION__); | 368 | err("%s : out of memory\n", __FUNCTION__); |
| @@ -378,22 +370,15 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 378 | } | 370 | } |
| 379 | memset(ctrl, 0, sizeof(struct controller)); | 371 | memset(ctrl, 0, sizeof(struct controller)); |
| 380 | 372 | ||
| 381 | dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid); | ||
| 382 | |||
| 383 | pdev = dev->port; | 373 | pdev = dev->port; |
| 374 | ctrl->pci_dev = pdev; | ||
| 384 | 375 | ||
| 385 | rc = pcie_init(ctrl, dev, | 376 | rc = pcie_init(ctrl, dev); |
| 386 | (php_intr_callback_t) pciehp_handle_attention_button, | ||
| 387 | (php_intr_callback_t) pciehp_handle_switch_change, | ||
| 388 | (php_intr_callback_t) pciehp_handle_presence_change, | ||
| 389 | (php_intr_callback_t) pciehp_handle_power_fault); | ||
| 390 | if (rc) { | 377 | if (rc) { |
| 391 | dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); | 378 | dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); |
| 392 | goto err_out_free_ctrl; | 379 | goto err_out_free_ctrl; |
| 393 | } | 380 | } |
| 394 | 381 | ||
| 395 | ctrl->pci_dev = pdev; | ||
| 396 | |||
| 397 | pci_set_drvdata(pdev, ctrl); | 382 | pci_set_drvdata(pdev, ctrl); |
| 398 | 383 | ||
| 399 | ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); | 384 | ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); |
| @@ -402,7 +387,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 402 | rc = -ENOMEM; | 387 | rc = -ENOMEM; |
| 403 | goto err_out_unmap_mmio_region; | 388 | goto err_out_unmap_mmio_region; |
| 404 | } | 389 | } |
| 405 | dbg("%s: ctrl->pci_bus %p\n", __FUNCTION__, ctrl->pci_bus); | ||
| 406 | memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); | 390 | memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); |
| 407 | ctrl->bus = pdev->bus->number; /* ctrl bus */ | 391 | ctrl->bus = pdev->bus->number; /* ctrl bus */ |
| 408 | ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */ | 392 | ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */ |
| @@ -424,25 +408,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 424 | first_device_num = ctrl->slot_device_offset; | 408 | first_device_num = ctrl->slot_device_offset; |
| 425 | num_ctlr_slots = ctrl->num_slots; | 409 | num_ctlr_slots = ctrl->num_slots; |
| 426 | 410 | ||
| 427 | /* Store PCI Config Space for all devices on this bus */ | ||
| 428 | dbg("%s: Before calling pciehp_save_config, ctrl->bus %x,ctrl->slot_bus %x\n", | ||
| 429 | __FUNCTION__,ctrl->bus, ctrl->slot_bus); | ||
| 430 | rc = pciehp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num); | ||
| 431 | if (rc) { | ||
| 432 | err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc); | ||
| 433 | goto err_out_free_ctrl_bus; | ||
| 434 | } | ||
| 435 | |||
| 436 | /* Get IO, memory, and IRQ resources for new devices */ | ||
| 437 | rc = pciehprm_find_available_resources(ctrl); | ||
| 438 | ctrl->add_support = !rc; | ||
| 439 | |||
| 440 | if (rc) { | ||
| 441 | dbg("pciehprm_find_available_resources = %#x\n", rc); | ||
| 442 | err("unable to locate PCI configuration resources for hot plug add.\n"); | ||
| 443 | goto err_out_free_ctrl_bus; | ||
| 444 | } | ||
| 445 | |||
| 446 | /* Setup the slot information structures */ | 411 | /* Setup the slot information structures */ |
| 447 | rc = init_slots(ctrl); | 412 | rc = init_slots(ctrl); |
| 448 | if (rc) { | 413 | if (rc) { |
| @@ -451,7 +416,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 451 | } | 416 | } |
| 452 | 417 | ||
| 453 | t_slot = pciehp_find_slot(ctrl, first_device_num); | 418 | t_slot = pciehp_find_slot(ctrl, first_device_num); |
| 454 | dbg("%s: t_slot %p\n", __FUNCTION__, t_slot); | ||
| 455 | 419 | ||
| 456 | /* Finish setting up the hot plug ctrl device */ | 420 | /* Finish setting up the hot plug ctrl device */ |
| 457 | ctrl->next_event = 0; | 421 | ctrl->next_event = 0; |
| @@ -468,7 +432,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 468 | down(&ctrl->crit_sect); | 432 | down(&ctrl->crit_sect); |
| 469 | 433 | ||
| 470 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ | 434 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ |
| 471 | dbg("%s: adpater value %x\n", __FUNCTION__, value); | ||
| 472 | 435 | ||
| 473 | if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { | 436 | if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { |
| 474 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ | 437 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ |
| @@ -501,7 +464,6 @@ err_out_none: | |||
| 501 | 464 | ||
| 502 | static int pcie_start_thread(void) | 465 | static int pcie_start_thread(void) |
| 503 | { | 466 | { |
| 504 | int loop; | ||
| 505 | int retval = 0; | 467 | int retval = 0; |
| 506 | 468 | ||
| 507 | dbg("Initialize + Start the notification/polling mechanism \n"); | 469 | dbg("Initialize + Start the notification/polling mechanism \n"); |
| @@ -512,32 +474,11 @@ static int pcie_start_thread(void) | |||
| 512 | return retval; | 474 | return retval; |
| 513 | } | 475 | } |
| 514 | 476 | ||
| 515 | dbg("Initialize slot lists\n"); | ||
| 516 | /* One slot list for each bus in the system */ | ||
| 517 | for (loop = 0; loop < 256; loop++) { | ||
| 518 | pciehp_slot_list[loop] = NULL; | ||
| 519 | } | ||
| 520 | |||
| 521 | return retval; | 477 | return retval; |
| 522 | } | 478 | } |
| 523 | 479 | ||
| 524 | static inline void __exit | ||
| 525 | free_pciehp_res(struct pci_resource *res) | ||
| 526 | { | ||
| 527 | struct pci_resource *tres; | ||
| 528 | |||
| 529 | while (res) { | ||
| 530 | tres = res; | ||
| 531 | res = res->next; | ||
| 532 | kfree(tres); | ||
| 533 | } | ||
| 534 | } | ||
| 535 | |||
| 536 | static void __exit unload_pciehpd(void) | 480 | static void __exit unload_pciehpd(void) |
| 537 | { | 481 | { |
| 538 | struct pci_func *next; | ||
| 539 | struct pci_func *TempSlot; | ||
| 540 | int loop; | ||
| 541 | struct controller *ctrl; | 482 | struct controller *ctrl; |
| 542 | struct controller *tctrl; | 483 | struct controller *tctrl; |
| 543 | 484 | ||
| @@ -546,11 +487,6 @@ static void __exit unload_pciehpd(void) | |||
| 546 | while (ctrl) { | 487 | while (ctrl) { |
| 547 | cleanup_slots(ctrl); | 488 | cleanup_slots(ctrl); |
| 548 | 489 | ||
| 549 | free_pciehp_res(ctrl->io_head); | ||
| 550 | free_pciehp_res(ctrl->mem_head); | ||
| 551 | free_pciehp_res(ctrl->p_mem_head); | ||
| 552 | free_pciehp_res(ctrl->bus_head); | ||
| 553 | |||
| 554 | kfree (ctrl->pci_bus); | 490 | kfree (ctrl->pci_bus); |
| 555 | 491 | ||
| 556 | ctrl->hpc_ops->release_ctlr(ctrl); | 492 | ctrl->hpc_ops->release_ctlr(ctrl); |
| @@ -561,20 +497,6 @@ static void __exit unload_pciehpd(void) | |||
| 561 | kfree(tctrl); | 497 | kfree(tctrl); |
| 562 | } | 498 | } |
| 563 | 499 | ||
| 564 | for (loop = 0; loop < 256; loop++) { | ||
| 565 | next = pciehp_slot_list[loop]; | ||
| 566 | while (next != NULL) { | ||
| 567 | free_pciehp_res(next->io_head); | ||
| 568 | free_pciehp_res(next->mem_head); | ||
| 569 | free_pciehp_res(next->p_mem_head); | ||
| 570 | free_pciehp_res(next->bus_head); | ||
| 571 | |||
| 572 | TempSlot = next; | ||
| 573 | next = next->next; | ||
| 574 | kfree(TempSlot); | ||
| 575 | } | ||
| 576 | } | ||
| 577 | |||
| 578 | /* Stop the notification mechanism */ | 500 | /* Stop the notification mechanism */ |
| 579 | pciehp_event_stop_thread(); | 501 | pciehp_event_stop_thread(); |
| 580 | 502 | ||
| @@ -639,21 +561,16 @@ static int __init pcied_init(void) | |||
| 639 | if (retval) | 561 | if (retval) |
| 640 | goto error_hpc_init; | 562 | goto error_hpc_init; |
| 641 | 563 | ||
| 642 | retval = pciehprm_init(PCI); | 564 | retval = pcie_port_service_register(&hpdriver_portdrv); |
| 643 | if (!retval) { | 565 | dbg("pcie_port_service_register = %d\n", retval); |
| 644 | retval = pcie_port_service_register(&hpdriver_portdrv); | 566 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
| 645 | dbg("pcie_port_service_register = %d\n", retval); | 567 | if (retval) |
| 646 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 568 | dbg("%s: Failure to register service\n", __FUNCTION__); |
| 647 | if (retval) | ||
| 648 | dbg("%s: Failure to register service\n", __FUNCTION__); | ||
| 649 | } | ||
| 650 | 569 | ||
| 651 | error_hpc_init: | 570 | error_hpc_init: |
| 652 | if (retval) { | 571 | if (retval) { |
| 653 | pciehprm_cleanup(); | ||
| 654 | pciehp_event_stop_thread(); | 572 | pciehp_event_stop_thread(); |
| 655 | } else | 573 | }; |
| 656 | pciehprm_print_pirt(); | ||
| 657 | 574 | ||
| 658 | return retval; | 575 | return retval; |
| 659 | } | 576 | } |
| @@ -663,9 +580,6 @@ static void __exit pcied_cleanup(void) | |||
| 663 | dbg("unload_pciehpd()\n"); | 580 | dbg("unload_pciehpd()\n"); |
| 664 | unload_pciehpd(); | 581 | unload_pciehpd(); |
| 665 | 582 | ||
| 666 | pciehprm_cleanup(); | ||
| 667 | |||
| 668 | dbg("pcie_port_service_unregister\n"); | ||
| 669 | pcie_port_service_unregister(&hpdriver_portdrv); | 583 | pcie_port_service_unregister(&hpdriver_portdrv); |
| 670 | 584 | ||
| 671 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); | 585 | 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 898f6da6f0de..5e582eca21d8 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
| @@ -27,25 +27,14 @@ | |||
| 27 | * | 27 | * |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #include <linux/config.h> | ||
| 31 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
| 33 | #include <linux/types.h> | 32 | #include <linux/types.h> |
| 34 | #include <linux/slab.h> | ||
| 35 | #include <linux/workqueue.h> | ||
| 36 | #include <linux/interrupt.h> | ||
| 37 | #include <linux/delay.h> | ||
| 38 | #include <linux/wait.h> | ||
| 39 | #include <linux/smp_lock.h> | 33 | #include <linux/smp_lock.h> |
| 40 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
| 41 | #include "../pci.h" | 35 | #include "../pci.h" |
| 42 | #include "pciehp.h" | 36 | #include "pciehp.h" |
| 43 | #include "pciehprm.h" | ||
| 44 | 37 | ||
| 45 | static u32 configure_new_device(struct controller *ctrl, struct pci_func *func, | ||
| 46 | u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev); | ||
| 47 | static int configure_new_function( struct controller *ctrl, struct pci_func *func, | ||
| 48 | u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev); | ||
| 49 | static void interrupt_event_handler(struct controller *ctrl); | 38 | static void interrupt_event_handler(struct controller *ctrl); |
| 50 | 39 | ||
| 51 | static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ | 40 | static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ |
| @@ -60,22 +49,18 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
| 60 | struct slot *p_slot; | 49 | struct slot *p_slot; |
| 61 | u8 rc = 0; | 50 | u8 rc = 0; |
| 62 | u8 getstatus; | 51 | u8 getstatus; |
| 63 | struct pci_func *func; | ||
| 64 | struct event_info *taskInfo; | 52 | struct event_info *taskInfo; |
| 65 | 53 | ||
| 66 | /* Attention Button Change */ | 54 | /* Attention Button Change */ |
| 67 | dbg("pciehp: Attention button interrupt received.\n"); | 55 | dbg("pciehp: Attention button interrupt received.\n"); |
| 68 | 56 | ||
| 69 | func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
| 70 | |||
| 71 | /* This is the structure that tells the worker thread what to do */ | 57 | /* This is the structure that tells the worker thread what to do */ |
| 72 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | 58 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); |
| 73 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 59 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
| 74 | 60 | ||
| 75 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | ||
| 76 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 61 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 77 | 62 | ||
| 78 | ctrl->next_event = (ctrl->next_event + 1) % 10; | 63 | ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; |
| 79 | taskInfo->hp_slot = hp_slot; | 64 | taskInfo->hp_slot = hp_slot; |
| 80 | 65 | ||
| 81 | rc++; | 66 | rc++; |
| @@ -117,24 +102,20 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
| 117 | struct slot *p_slot; | 102 | struct slot *p_slot; |
| 118 | u8 rc = 0; | 103 | u8 rc = 0; |
| 119 | u8 getstatus; | 104 | u8 getstatus; |
| 120 | struct pci_func *func; | ||
| 121 | struct event_info *taskInfo; | 105 | struct event_info *taskInfo; |
| 122 | 106 | ||
| 123 | /* Switch Change */ | 107 | /* Switch Change */ |
| 124 | dbg("pciehp: Switch interrupt received.\n"); | 108 | dbg("pciehp: Switch interrupt received.\n"); |
| 125 | 109 | ||
| 126 | func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
| 127 | |||
| 128 | /* This is the structure that tells the worker thread | 110 | /* This is the structure that tells the worker thread |
| 129 | * what to do | 111 | * what to do |
| 130 | */ | 112 | */ |
| 131 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | 113 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); |
| 132 | ctrl->next_event = (ctrl->next_event + 1) % 10; | 114 | ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; |
| 133 | taskInfo->hp_slot = hp_slot; | 115 | taskInfo->hp_slot = hp_slot; |
| 134 | 116 | ||
| 135 | rc++; | 117 | rc++; |
| 136 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 118 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
| 137 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | ||
| 138 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 119 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 139 | 120 | ||
| 140 | if (getstatus) { | 121 | if (getstatus) { |
| @@ -142,14 +123,12 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
| 142 | * Switch opened | 123 | * Switch opened |
| 143 | */ | 124 | */ |
| 144 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); | 125 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); |
| 145 | func->switch_save = 0; | ||
| 146 | taskInfo->event_type = INT_SWITCH_OPEN; | 126 | taskInfo->event_type = INT_SWITCH_OPEN; |
| 147 | } else { | 127 | } else { |
| 148 | /* | 128 | /* |
| 149 | * Switch closed | 129 | * Switch closed |
| 150 | */ | 130 | */ |
| 151 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); | 131 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); |
| 152 | func->switch_save = 0x10; | ||
| 153 | taskInfo->event_type = INT_SWITCH_CLOSE; | 132 | taskInfo->event_type = INT_SWITCH_CLOSE; |
| 154 | } | 133 | } |
| 155 | 134 | ||
| @@ -163,20 +142,17 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
| 163 | { | 142 | { |
| 164 | struct controller *ctrl = (struct controller *) inst_id; | 143 | struct controller *ctrl = (struct controller *) inst_id; |
| 165 | struct slot *p_slot; | 144 | struct slot *p_slot; |
| 166 | u8 rc = 0; | 145 | u8 presence_save, rc = 0; |
| 167 | struct pci_func *func; | ||
| 168 | struct event_info *taskInfo; | 146 | struct event_info *taskInfo; |
| 169 | 147 | ||
| 170 | /* Presence Change */ | 148 | /* Presence Change */ |
| 171 | dbg("pciehp: Presence/Notify input change.\n"); | 149 | dbg("pciehp: Presence/Notify input change.\n"); |
| 172 | 150 | ||
| 173 | func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
| 174 | |||
| 175 | /* This is the structure that tells the worker thread | 151 | /* This is the structure that tells the worker thread |
| 176 | * what to do | 152 | * what to do |
| 177 | */ | 153 | */ |
| 178 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | 154 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); |
| 179 | ctrl->next_event = (ctrl->next_event + 1) % 10; | 155 | ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; |
| 180 | taskInfo->hp_slot = hp_slot; | 156 | taskInfo->hp_slot = hp_slot; |
| 181 | 157 | ||
| 182 | rc++; | 158 | rc++; |
| @@ -185,8 +161,8 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
| 185 | /* Switch is open, assume a presence change | 161 | /* Switch is open, assume a presence change |
| 186 | * Save the presence state | 162 | * Save the presence state |
| 187 | */ | 163 | */ |
| 188 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | 164 | p_slot->hpc_ops->get_adapter_status(p_slot, &presence_save); |
| 189 | if (func->presence_save) { | 165 | if (presence_save) { |
| 190 | /* | 166 | /* |
| 191 | * Card Present | 167 | * Card Present |
| 192 | */ | 168 | */ |
| @@ -211,19 +187,16 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
| 211 | struct controller *ctrl = (struct controller *) inst_id; | 187 | struct controller *ctrl = (struct controller *) inst_id; |
| 212 | struct slot *p_slot; | 188 | struct slot *p_slot; |
| 213 | u8 rc = 0; | 189 | u8 rc = 0; |
| 214 | struct pci_func *func; | ||
| 215 | struct event_info *taskInfo; | 190 | struct event_info *taskInfo; |
| 216 | 191 | ||
| 217 | /* power fault */ | 192 | /* power fault */ |
| 218 | dbg("pciehp: Power fault interrupt received.\n"); | 193 | dbg("pciehp: Power fault interrupt received.\n"); |
| 219 | 194 | ||
| 220 | func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
| 221 | |||
| 222 | /* this is the structure that tells the worker thread | 195 | /* this is the structure that tells the worker thread |
| 223 | * what to do | 196 | * what to do |
| 224 | */ | 197 | */ |
| 225 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | 198 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); |
| 226 | ctrl->next_event = (ctrl->next_event + 1) % 10; | 199 | ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; |
| 227 | taskInfo->hp_slot = hp_slot; | 200 | taskInfo->hp_slot = hp_slot; |
| 228 | 201 | ||
| 229 | rc++; | 202 | rc++; |
| @@ -234,7 +207,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
| 234 | * power fault Cleared | 207 | * power fault Cleared |
| 235 | */ | 208 | */ |
| 236 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); | 209 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); |
| 237 | func->status = 0x00; | 210 | p_slot->status = 0x00; |
| 238 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; | 211 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; |
| 239 | } else { | 212 | } else { |
| 240 | /* | 213 | /* |
| @@ -243,7 +216,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
| 243 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); | 216 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); |
| 244 | taskInfo->event_type = INT_POWER_FAULT; | 217 | taskInfo->event_type = INT_POWER_FAULT; |
| 245 | /* set power fault status for this board */ | 218 | /* set power fault status for this board */ |
| 246 | func->status = 0xFF; | 219 | p_slot->status = 0xFF; |
| 247 | info("power fault bit %x set\n", hp_slot); | 220 | info("power fault bit %x set\n", hp_slot); |
| 248 | } | 221 | } |
| 249 | if (rc) | 222 | if (rc) |
| @@ -252,810 +225,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
| 252 | return rc; | 225 | return rc; |
| 253 | } | 226 | } |
| 254 | 227 | ||
| 255 | |||
| 256 | /** | ||
| 257 | * sort_by_size: sort nodes by their length, smallest first. | ||
| 258 | * | ||
| 259 | * @head: list to sort | ||
| 260 | */ | ||
| 261 | static int sort_by_size(struct pci_resource **head) | ||
| 262 | { | ||
| 263 | struct pci_resource *current_res; | ||
| 264 | struct pci_resource *next_res; | ||
| 265 | int out_of_order = 1; | ||
| 266 | |||
| 267 | if (!(*head)) | ||
| 268 | return 1; | ||
| 269 | |||
| 270 | if (!((*head)->next)) | ||
| 271 | return 0; | ||
| 272 | |||
| 273 | while (out_of_order) { | ||
| 274 | out_of_order = 0; | ||
| 275 | |||
| 276 | /* Special case for swapping list head */ | ||
| 277 | if (((*head)->next) && | ||
| 278 | ((*head)->length > (*head)->next->length)) { | ||
| 279 | out_of_order++; | ||
| 280 | current_res = *head; | ||
| 281 | *head = (*head)->next; | ||
| 282 | current_res->next = (*head)->next; | ||
| 283 | (*head)->next = current_res; | ||
| 284 | } | ||
| 285 | |||
| 286 | current_res = *head; | ||
| 287 | |||
| 288 | while (current_res->next && current_res->next->next) { | ||
| 289 | if (current_res->next->length > current_res->next->next->length) { | ||
| 290 | out_of_order++; | ||
| 291 | next_res = current_res->next; | ||
| 292 | current_res->next = current_res->next->next; | ||
| 293 | current_res = current_res->next; | ||
| 294 | next_res->next = current_res->next; | ||
| 295 | current_res->next = next_res; | ||
| 296 | } else | ||
| 297 | current_res = current_res->next; | ||
| 298 | } | ||
| 299 | } /* End of out_of_order loop */ | ||
| 300 | |||
| 301 | return 0; | ||
| 302 | } | ||
| 303 | |||
| 304 | |||
| 305 | /* | ||
| 306 | * sort_by_max_size | ||
| 307 | * | ||
| 308 | * Sorts nodes on the list by their length. | ||
| 309 | * Largest first. | ||
| 310 | * | ||
| 311 | */ | ||
| 312 | static int sort_by_max_size(struct pci_resource **head) | ||
| 313 | { | ||
| 314 | struct pci_resource *current_res; | ||
| 315 | struct pci_resource *next_res; | ||
| 316 | int out_of_order = 1; | ||
| 317 | |||
| 318 | if (!(*head)) | ||
| 319 | return 1; | ||
| 320 | |||
| 321 | if (!((*head)->next)) | ||
| 322 | return 0; | ||
| 323 | |||
| 324 | while (out_of_order) { | ||
| 325 | out_of_order = 0; | ||
| 326 | |||
| 327 | /* Special case for swapping list head */ | ||
| 328 | if (((*head)->next) && | ||
| 329 | ((*head)->length < (*head)->next->length)) { | ||
| 330 | out_of_order++; | ||
| 331 | current_res = *head; | ||
| 332 | *head = (*head)->next; | ||
| 333 | current_res->next = (*head)->next; | ||
| 334 | (*head)->next = current_res; | ||
| 335 | } | ||
| 336 | |||
| 337 | current_res = *head; | ||
| 338 | |||
| 339 | while (current_res->next && current_res->next->next) { | ||
| 340 | if (current_res->next->length < current_res->next->next->length) { | ||
| 341 | out_of_order++; | ||
| 342 | next_res = current_res->next; | ||
| 343 | current_res->next = current_res->next->next; | ||
| 344 | current_res = current_res->next; | ||
| 345 | next_res->next = current_res->next; | ||
| 346 | current_res->next = next_res; | ||
| 347 | } else | ||
| 348 | current_res = current_res->next; | ||
| 349 | } | ||
| 350 | } /* End of out_of_order loop */ | ||
| 351 | |||
| 352 | return 0; | ||
| 353 | } | ||
| 354 | |||
| 355 | |||
| 356 | /** | ||
| 357 | * do_pre_bridge_resource_split: return one unused resource node | ||
| 358 | * @head: list to scan | ||
| 359 | * | ||
| 360 | */ | ||
| 361 | static struct pci_resource * | ||
| 362 | do_pre_bridge_resource_split(struct pci_resource **head, | ||
| 363 | struct pci_resource **orig_head, u32 alignment) | ||
| 364 | { | ||
| 365 | struct pci_resource *prevnode = NULL; | ||
| 366 | struct pci_resource *node; | ||
| 367 | struct pci_resource *split_node; | ||
| 368 | u32 rc; | ||
| 369 | u32 temp_dword; | ||
| 370 | dbg("do_pre_bridge_resource_split\n"); | ||
| 371 | |||
| 372 | if (!(*head) || !(*orig_head)) | ||
| 373 | return NULL; | ||
| 374 | |||
| 375 | rc = pciehp_resource_sort_and_combine(head); | ||
| 376 | |||
| 377 | if (rc) | ||
| 378 | return NULL; | ||
| 379 | |||
| 380 | if ((*head)->base != (*orig_head)->base) | ||
| 381 | return NULL; | ||
| 382 | |||
| 383 | if ((*head)->length == (*orig_head)->length) | ||
| 384 | return NULL; | ||
| 385 | |||
| 386 | |||
| 387 | /* If we got here, there the bridge requires some of the resource, but | ||
| 388 | * we may be able to split some off of the front | ||
| 389 | */ | ||
| 390 | node = *head; | ||
| 391 | |||
| 392 | if (node->length & (alignment -1)) { | ||
| 393 | /* this one isn't an aligned length, so we'll make a new entry | ||
| 394 | * and split it up. | ||
| 395 | */ | ||
| 396 | split_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
| 397 | |||
| 398 | if (!split_node) | ||
| 399 | return NULL; | ||
| 400 | |||
| 401 | temp_dword = (node->length | (alignment-1)) + 1 - alignment; | ||
| 402 | |||
| 403 | split_node->base = node->base; | ||
| 404 | split_node->length = temp_dword; | ||
| 405 | |||
| 406 | node->length -= temp_dword; | ||
| 407 | node->base += split_node->length; | ||
| 408 | |||
| 409 | /* Put it in the list */ | ||
| 410 | *head = split_node; | ||
| 411 | split_node->next = node; | ||
| 412 | } | ||
| 413 | |||
| 414 | if (node->length < alignment) | ||
| 415 | return NULL; | ||
| 416 | |||
| 417 | /* Now unlink it */ | ||
| 418 | if (*head == node) { | ||
| 419 | *head = node->next; | ||
| 420 | } else { | ||
| 421 | prevnode = *head; | ||
| 422 | while (prevnode->next != node) | ||
| 423 | prevnode = prevnode->next; | ||
| 424 | |||
| 425 | prevnode->next = node->next; | ||
| 426 | } | ||
| 427 | node->next = NULL; | ||
| 428 | |||
| 429 | return node; | ||
| 430 | } | ||
| 431 | |||
| 432 | |||
| 433 | /** | ||
| 434 | * do_bridge_resource_split: return one unused resource node | ||
| 435 | * @head: list to scan | ||
| 436 | * | ||
| 437 | */ | ||
| 438 | static struct pci_resource * | ||
| 439 | do_bridge_resource_split(struct pci_resource **head, u32 alignment) | ||
| 440 | { | ||
| 441 | struct pci_resource *prevnode = NULL; | ||
| 442 | struct pci_resource *node; | ||
| 443 | u32 rc; | ||
| 444 | u32 temp_dword; | ||
| 445 | |||
| 446 | if (!(*head)) | ||
| 447 | return NULL; | ||
| 448 | |||
| 449 | rc = pciehp_resource_sort_and_combine(head); | ||
| 450 | |||
| 451 | if (rc) | ||
| 452 | return NULL; | ||
| 453 | |||
| 454 | node = *head; | ||
| 455 | |||
| 456 | while (node->next) { | ||
| 457 | prevnode = node; | ||
| 458 | node = node->next; | ||
| 459 | kfree(prevnode); | ||
| 460 | } | ||
| 461 | |||
| 462 | if (node->length < alignment) { | ||
| 463 | kfree(node); | ||
| 464 | return NULL; | ||
| 465 | } | ||
| 466 | |||
| 467 | if (node->base & (alignment - 1)) { | ||
| 468 | /* Short circuit if adjusted size is too small */ | ||
| 469 | temp_dword = (node->base | (alignment-1)) + 1; | ||
| 470 | if ((node->length - (temp_dword - node->base)) < alignment) { | ||
| 471 | kfree(node); | ||
| 472 | return NULL; | ||
| 473 | } | ||
| 474 | |||
| 475 | node->length -= (temp_dword - node->base); | ||
| 476 | node->base = temp_dword; | ||
| 477 | } | ||
| 478 | |||
| 479 | if (node->length & (alignment - 1)) { | ||
| 480 | /* There's stuff in use after this node */ | ||
| 481 | kfree(node); | ||
| 482 | return NULL; | ||
| 483 | } | ||
| 484 | |||
| 485 | return node; | ||
| 486 | } | ||
| 487 | |||
| 488 | |||
| 489 | /* | ||
| 490 | * get_io_resource | ||
| 491 | * | ||
| 492 | * this function sorts the resource list by size and then | ||
| 493 | * returns the first node of "size" length that is not in the | ||
| 494 | * ISA aliasing window. If it finds a node larger than "size" | ||
| 495 | * it will split it up. | ||
| 496 | * | ||
| 497 | * size must be a power of two. | ||
| 498 | */ | ||
| 499 | static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size) | ||
| 500 | { | ||
| 501 | struct pci_resource *prevnode; | ||
| 502 | struct pci_resource *node; | ||
| 503 | struct pci_resource *split_node = NULL; | ||
| 504 | u32 temp_dword; | ||
| 505 | |||
| 506 | if (!(*head)) | ||
| 507 | return NULL; | ||
| 508 | |||
| 509 | if ( pciehp_resource_sort_and_combine(head) ) | ||
| 510 | return NULL; | ||
| 511 | |||
| 512 | if ( sort_by_size(head) ) | ||
| 513 | return NULL; | ||
| 514 | |||
| 515 | for (node = *head; node; node = node->next) { | ||
| 516 | if (node->length < size) | ||
| 517 | continue; | ||
| 518 | |||
| 519 | if (node->base & (size - 1)) { | ||
| 520 | /* this one isn't base aligned properly | ||
| 521 | so we'll make a new entry and split it up */ | ||
| 522 | temp_dword = (node->base | (size-1)) + 1; | ||
| 523 | |||
| 524 | /*/ Short circuit if adjusted size is too small */ | ||
| 525 | if ((node->length - (temp_dword - node->base)) < size) | ||
| 526 | continue; | ||
| 527 | |||
| 528 | split_node = kmalloc(sizeof(struct pci_resource), | ||
| 529 | GFP_KERNEL); | ||
| 530 | |||
| 531 | if (!split_node) | ||
| 532 | return NULL; | ||
| 533 | |||
| 534 | split_node->base = node->base; | ||
| 535 | split_node->length = temp_dword - node->base; | ||
| 536 | node->base = temp_dword; | ||
| 537 | node->length -= split_node->length; | ||
| 538 | |||
| 539 | /* Put it in the list */ | ||
| 540 | split_node->next = node->next; | ||
| 541 | node->next = split_node; | ||
| 542 | } /* End of non-aligned base */ | ||
| 543 | |||
| 544 | /* Don't need to check if too small since we already did */ | ||
| 545 | if (node->length > size) { | ||
| 546 | /* this one is longer than we need | ||
| 547 | so we'll make a new entry and split it up */ | ||
| 548 | split_node = kmalloc(sizeof(struct pci_resource), | ||
| 549 | GFP_KERNEL); | ||
| 550 | |||
| 551 | if (!split_node) | ||
| 552 | return NULL; | ||
| 553 | |||
| 554 | split_node->base = node->base + size; | ||
| 555 | split_node->length = node->length - size; | ||
| 556 | node->length = size; | ||
| 557 | |||
| 558 | /* Put it in the list */ | ||
| 559 | split_node->next = node->next; | ||
| 560 | node->next = split_node; | ||
| 561 | } /* End of too big on top end */ | ||
| 562 | |||
| 563 | /* For IO make sure it's not in the ISA aliasing space */ | ||
| 564 | if (node->base & 0x300L) | ||
| 565 | continue; | ||
| 566 | |||
| 567 | /* If we got here, then it is the right size | ||
| 568 | Now take it out of the list */ | ||
| 569 | if (*head == node) { | ||
| 570 | *head = node->next; | ||
| 571 | } else { | ||
| 572 | prevnode = *head; | ||
| 573 | while (prevnode->next != node) | ||
| 574 | prevnode = prevnode->next; | ||
| 575 | |||
| 576 | prevnode->next = node->next; | ||
| 577 | } | ||
| 578 | node->next = NULL; | ||
| 579 | /* Stop looping */ | ||
| 580 | break; | ||
| 581 | } | ||
| 582 | |||
| 583 | return node; | ||
| 584 | } | ||
| 585 | |||
| 586 | |||
| 587 | /* | ||
| 588 | * get_max_resource | ||
| 589 | * | ||
| 590 | * Gets the largest node that is at least "size" big from the | ||
| 591 | * list pointed to by head. It aligns the node on top and bottom | ||
| 592 | * to "size" alignment before returning it. | ||
| 593 | * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M | ||
| 594 | * This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot. | ||
| 595 | */ | ||
| 596 | static struct pci_resource *get_max_resource(struct pci_resource **head, u32 size) | ||
| 597 | { | ||
| 598 | struct pci_resource *max; | ||
| 599 | struct pci_resource *temp; | ||
| 600 | struct pci_resource *split_node; | ||
| 601 | u32 temp_dword; | ||
| 602 | u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 }; | ||
| 603 | int i; | ||
| 604 | |||
| 605 | if (!(*head)) | ||
| 606 | return NULL; | ||
| 607 | |||
| 608 | if (pciehp_resource_sort_and_combine(head)) | ||
| 609 | return NULL; | ||
| 610 | |||
| 611 | if (sort_by_max_size(head)) | ||
| 612 | return NULL; | ||
| 613 | |||
| 614 | for (max = *head;max; max = max->next) { | ||
| 615 | |||
| 616 | /* If not big enough we could probably just bail, | ||
| 617 | instead we'll continue to the next. */ | ||
| 618 | if (max->length < size) | ||
| 619 | continue; | ||
| 620 | |||
| 621 | if (max->base & (size - 1)) { | ||
| 622 | /* this one isn't base aligned properly | ||
| 623 | so we'll make a new entry and split it up */ | ||
| 624 | temp_dword = (max->base | (size-1)) + 1; | ||
| 625 | |||
| 626 | /* Short circuit if adjusted size is too small */ | ||
| 627 | if ((max->length - (temp_dword - max->base)) < size) | ||
| 628 | continue; | ||
| 629 | |||
| 630 | split_node = kmalloc(sizeof(struct pci_resource), | ||
| 631 | GFP_KERNEL); | ||
| 632 | |||
| 633 | if (!split_node) | ||
| 634 | return NULL; | ||
| 635 | |||
| 636 | split_node->base = max->base; | ||
| 637 | split_node->length = temp_dword - max->base; | ||
| 638 | max->base = temp_dword; | ||
| 639 | max->length -= split_node->length; | ||
| 640 | |||
| 641 | /* Put it next in the list */ | ||
| 642 | split_node->next = max->next; | ||
| 643 | max->next = split_node; | ||
| 644 | } | ||
| 645 | |||
| 646 | if ((max->base + max->length) & (size - 1)) { | ||
| 647 | /* this one isn't end aligned properly at the top | ||
| 648 | so we'll make a new entry and split it up */ | ||
| 649 | split_node = kmalloc(sizeof(struct pci_resource), | ||
| 650 | GFP_KERNEL); | ||
| 651 | |||
| 652 | if (!split_node) | ||
| 653 | return NULL; | ||
| 654 | temp_dword = ((max->base + max->length) & ~(size - 1)); | ||
| 655 | split_node->base = temp_dword; | ||
| 656 | split_node->length = max->length + max->base | ||
| 657 | - split_node->base; | ||
| 658 | max->length -= split_node->length; | ||
| 659 | |||
| 660 | /* Put it in the list */ | ||
| 661 | split_node->next = max->next; | ||
| 662 | max->next = split_node; | ||
| 663 | } | ||
| 664 | |||
| 665 | /* Make sure it didn't shrink too much when we aligned it */ | ||
| 666 | if (max->length < size) | ||
| 667 | continue; | ||
| 668 | |||
| 669 | for ( i = 0; max_size[i] > size; i++) { | ||
| 670 | if (max->length > max_size[i]) { | ||
| 671 | split_node = kmalloc(sizeof(struct pci_resource), | ||
| 672 | GFP_KERNEL); | ||
| 673 | if (!split_node) | ||
| 674 | break; /* return NULL; */ | ||
| 675 | split_node->base = max->base + max_size[i]; | ||
| 676 | split_node->length = max->length - max_size[i]; | ||
| 677 | max->length = max_size[i]; | ||
| 678 | /* Put it next in the list */ | ||
| 679 | split_node->next = max->next; | ||
| 680 | max->next = split_node; | ||
| 681 | break; | ||
| 682 | } | ||
| 683 | } | ||
| 684 | |||
| 685 | /* Now take it out of the list */ | ||
| 686 | temp = (struct pci_resource*) *head; | ||
| 687 | if (temp == max) { | ||
| 688 | *head = max->next; | ||
| 689 | } else { | ||
| 690 | while (temp && temp->next != max) { | ||
| 691 | temp = temp->next; | ||
| 692 | } | ||
| 693 | |||
| 694 | temp->next = max->next; | ||
| 695 | } | ||
| 696 | |||
| 697 | max->next = NULL; | ||
| 698 | return max; | ||
| 699 | } | ||
| 700 | |||
| 701 | /* If we get here, we couldn't find one */ | ||
| 702 | return NULL; | ||
| 703 | } | ||
| 704 | |||
| 705 | |||
| 706 | /* | ||
| 707 | * get_resource | ||
| 708 | * | ||
| 709 | * this function sorts the resource list by size and then | ||
| 710 | * returns the first node of "size" length. If it finds a node | ||
| 711 | * larger than "size" it will split it up. | ||
| 712 | * | ||
| 713 | * size must be a power of two. | ||
| 714 | */ | ||
| 715 | static struct pci_resource *get_resource(struct pci_resource **head, u32 size) | ||
| 716 | { | ||
| 717 | struct pci_resource *prevnode; | ||
| 718 | struct pci_resource *node; | ||
| 719 | struct pci_resource *split_node; | ||
| 720 | u32 temp_dword; | ||
| 721 | |||
| 722 | if (!(*head)) | ||
| 723 | return NULL; | ||
| 724 | |||
| 725 | if ( pciehp_resource_sort_and_combine(head) ) | ||
| 726 | return NULL; | ||
| 727 | |||
| 728 | if ( sort_by_size(head) ) | ||
| 729 | return NULL; | ||
| 730 | |||
| 731 | for (node = *head; node; node = node->next) { | ||
| 732 | dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n", | ||
| 733 | __FUNCTION__, size, node, node->base, node->length); | ||
| 734 | if (node->length < size) | ||
| 735 | continue; | ||
| 736 | |||
| 737 | if (node->base & (size - 1)) { | ||
| 738 | dbg("%s: not aligned\n", __FUNCTION__); | ||
| 739 | /* this one isn't base aligned properly | ||
| 740 | so we'll make a new entry and split it up */ | ||
| 741 | temp_dword = (node->base | (size-1)) + 1; | ||
| 742 | |||
| 743 | /* Short circuit if adjusted size is too small */ | ||
| 744 | if ((node->length - (temp_dword - node->base)) < size) | ||
| 745 | continue; | ||
| 746 | |||
| 747 | split_node = kmalloc(sizeof(struct pci_resource), | ||
| 748 | GFP_KERNEL); | ||
| 749 | |||
| 750 | if (!split_node) | ||
| 751 | return NULL; | ||
| 752 | |||
| 753 | split_node->base = node->base; | ||
| 754 | split_node->length = temp_dword - node->base; | ||
| 755 | node->base = temp_dword; | ||
| 756 | node->length -= split_node->length; | ||
| 757 | |||
| 758 | /* Put it in the list */ | ||
| 759 | split_node->next = node->next; | ||
| 760 | node->next = split_node; | ||
| 761 | } /* End of non-aligned base */ | ||
| 762 | |||
| 763 | /* Don't need to check if too small since we already did */ | ||
| 764 | if (node->length > size) { | ||
| 765 | dbg("%s: too big\n", __FUNCTION__); | ||
| 766 | /* this one is longer than we need | ||
| 767 | so we'll make a new entry and split it up */ | ||
| 768 | split_node = kmalloc(sizeof(struct pci_resource), | ||
| 769 | GFP_KERNEL); | ||
| 770 | |||
| 771 | if (!split_node) | ||
| 772 | return NULL; | ||
| 773 | |||
| 774 | split_node->base = node->base + size; | ||
| 775 | split_node->length = node->length - size; | ||
| 776 | node->length = size; | ||
| 777 | |||
| 778 | /* Put it in the list */ | ||
| 779 | split_node->next = node->next; | ||
| 780 | node->next = split_node; | ||
| 781 | } /* End of too big on top end */ | ||
| 782 | |||
| 783 | dbg("%s: got one!!!\n", __FUNCTION__); | ||
| 784 | /* If we got here, then it is the right size | ||
| 785 | Now take it out of the list */ | ||
| 786 | if (*head == node) { | ||
| 787 | *head = node->next; | ||
| 788 | } else { | ||
| 789 | prevnode = *head; | ||
| 790 | while (prevnode->next != node) | ||
| 791 | prevnode = prevnode->next; | ||
| 792 | |||
| 793 | prevnode->next = node->next; | ||
| 794 | } | ||
| 795 | node->next = NULL; | ||
| 796 | /* Stop looping */ | ||
| 797 | break; | ||
| 798 | } | ||
| 799 | return node; | ||
| 800 | } | ||
| 801 | |||
| 802 | |||
| 803 | /* | ||
| 804 | * pciehp_resource_sort_and_combine | ||
| 805 | * | ||
| 806 | * Sorts all of the nodes in the list in ascending order by | ||
| 807 | * their base addresses. Also does garbage collection by | ||
| 808 | * combining adjacent nodes. | ||
| 809 | * | ||
| 810 | * returns 0 if success | ||
| 811 | */ | ||
| 812 | int pciehp_resource_sort_and_combine(struct pci_resource **head) | ||
| 813 | { | ||
| 814 | struct pci_resource *node1; | ||
| 815 | struct pci_resource *node2; | ||
| 816 | int out_of_order = 1; | ||
| 817 | |||
| 818 | dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head); | ||
| 819 | |||
| 820 | if (!(*head)) | ||
| 821 | return 1; | ||
| 822 | |||
| 823 | dbg("*head->next = %p\n",(*head)->next); | ||
| 824 | |||
| 825 | if (!(*head)->next) | ||
| 826 | return 0; /* only one item on the list, already sorted! */ | ||
| 827 | |||
| 828 | dbg("*head->base = 0x%x\n",(*head)->base); | ||
| 829 | dbg("*head->next->base = 0x%x\n",(*head)->next->base); | ||
| 830 | while (out_of_order) { | ||
| 831 | out_of_order = 0; | ||
| 832 | |||
| 833 | /* Special case for swapping list head */ | ||
| 834 | if (((*head)->next) && | ||
| 835 | ((*head)->base > (*head)->next->base)) { | ||
| 836 | node1 = *head; | ||
| 837 | (*head) = (*head)->next; | ||
| 838 | node1->next = (*head)->next; | ||
| 839 | (*head)->next = node1; | ||
| 840 | out_of_order++; | ||
| 841 | } | ||
| 842 | |||
| 843 | node1 = (*head); | ||
| 844 | |||
| 845 | while (node1->next && node1->next->next) { | ||
| 846 | if (node1->next->base > node1->next->next->base) { | ||
| 847 | out_of_order++; | ||
| 848 | node2 = node1->next; | ||
| 849 | node1->next = node1->next->next; | ||
| 850 | node1 = node1->next; | ||
| 851 | node2->next = node1->next; | ||
| 852 | node1->next = node2; | ||
| 853 | } else | ||
| 854 | node1 = node1->next; | ||
| 855 | } | ||
| 856 | } /* End of out_of_order loop */ | ||
| 857 | |||
| 858 | node1 = *head; | ||
| 859 | |||
| 860 | while (node1 && node1->next) { | ||
| 861 | if ((node1->base + node1->length) == node1->next->base) { | ||
| 862 | /* Combine */ | ||
| 863 | dbg("8..\n"); | ||
| 864 | node1->length += node1->next->length; | ||
| 865 | node2 = node1->next; | ||
| 866 | node1->next = node1->next->next; | ||
| 867 | kfree(node2); | ||
| 868 | } else | ||
| 869 | node1 = node1->next; | ||
| 870 | } | ||
| 871 | |||
| 872 | return 0; | ||
| 873 | } | ||
| 874 | |||
| 875 | |||
| 876 | /** | ||
| 877 | * pciehp_slot_create - Creates a node and adds it to the proper bus. | ||
| 878 | * @busnumber - bus where new node is to be located | ||
| 879 | * | ||
| 880 | * Returns pointer to the new node or NULL if unsuccessful | ||
| 881 | */ | ||
| 882 | struct pci_func *pciehp_slot_create(u8 busnumber) | ||
| 883 | { | ||
| 884 | struct pci_func *new_slot; | ||
| 885 | struct pci_func *next; | ||
| 886 | dbg("%s: busnumber %x\n", __FUNCTION__, busnumber); | ||
| 887 | new_slot = kmalloc(sizeof(struct pci_func), GFP_KERNEL); | ||
| 888 | |||
| 889 | if (new_slot == NULL) | ||
| 890 | return new_slot; | ||
| 891 | |||
| 892 | memset(new_slot, 0, sizeof(struct pci_func)); | ||
| 893 | |||
| 894 | new_slot->next = NULL; | ||
| 895 | new_slot->configured = 1; | ||
| 896 | |||
| 897 | if (pciehp_slot_list[busnumber] == NULL) { | ||
| 898 | pciehp_slot_list[busnumber] = new_slot; | ||
| 899 | } else { | ||
| 900 | next = pciehp_slot_list[busnumber]; | ||
| 901 | while (next->next != NULL) | ||
| 902 | next = next->next; | ||
| 903 | next->next = new_slot; | ||
| 904 | } | ||
| 905 | return new_slot; | ||
| 906 | } | ||
| 907 | |||
| 908 | |||
| 909 | /** | ||
| 910 | * slot_remove - Removes a node from the linked list of slots. | ||
| 911 | * @old_slot: slot to remove | ||
| 912 | * | ||
| 913 | * Returns 0 if successful, !0 otherwise. | ||
| 914 | */ | ||
| 915 | static int slot_remove(struct pci_func * old_slot) | ||
| 916 | { | ||
| 917 | struct pci_func *next; | ||
| 918 | |||
| 919 | if (old_slot == NULL) | ||
| 920 | return 1; | ||
| 921 | |||
| 922 | next = pciehp_slot_list[old_slot->bus]; | ||
| 923 | |||
| 924 | if (next == NULL) | ||
| 925 | return 1; | ||
| 926 | |||
| 927 | if (next == old_slot) { | ||
| 928 | pciehp_slot_list[old_slot->bus] = old_slot->next; | ||
| 929 | pciehp_destroy_board_resources(old_slot); | ||
| 930 | kfree(old_slot); | ||
| 931 | return 0; | ||
| 932 | } | ||
| 933 | |||
| 934 | while ((next->next != old_slot) && (next->next != NULL)) { | ||
| 935 | next = next->next; | ||
| 936 | } | ||
| 937 | |||
| 938 | if (next->next == old_slot) { | ||
| 939 | next->next = old_slot->next; | ||
| 940 | pciehp_destroy_board_resources(old_slot); | ||
| 941 | kfree(old_slot); | ||
| 942 | return 0; | ||
| 943 | } else | ||
| 944 | return 2; | ||
| 945 | } | ||
| 946 | |||
| 947 | |||
| 948 | /** | ||
| 949 | * bridge_slot_remove - Removes a node from the linked list of slots. | ||
| 950 | * @bridge: bridge to remove | ||
| 951 | * | ||
| 952 | * Returns 0 if successful, !0 otherwise. | ||
| 953 | */ | ||
| 954 | static int bridge_slot_remove(struct pci_func *bridge) | ||
| 955 | { | ||
| 956 | u8 subordinateBus, secondaryBus; | ||
| 957 | u8 tempBus; | ||
| 958 | struct pci_func *next; | ||
| 959 | |||
| 960 | if (bridge == NULL) | ||
| 961 | return 1; | ||
| 962 | |||
| 963 | secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF; | ||
| 964 | subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF; | ||
| 965 | |||
| 966 | for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) { | ||
| 967 | next = pciehp_slot_list[tempBus]; | ||
| 968 | |||
| 969 | while (!slot_remove(next)) { | ||
| 970 | next = pciehp_slot_list[tempBus]; | ||
| 971 | } | ||
| 972 | } | ||
| 973 | |||
| 974 | next = pciehp_slot_list[bridge->bus]; | ||
| 975 | |||
| 976 | if (next == NULL) { | ||
| 977 | return 1; | ||
| 978 | } | ||
| 979 | |||
| 980 | if (next == bridge) { | ||
| 981 | pciehp_slot_list[bridge->bus] = bridge->next; | ||
| 982 | kfree(bridge); | ||
| 983 | return 0; | ||
| 984 | } | ||
| 985 | |||
| 986 | while ((next->next != bridge) && (next->next != NULL)) { | ||
| 987 | next = next->next; | ||
| 988 | } | ||
| 989 | |||
| 990 | if (next->next == bridge) { | ||
| 991 | next->next = bridge->next; | ||
| 992 | kfree(bridge); | ||
| 993 | return 0; | ||
| 994 | } else | ||
| 995 | return 2; | ||
| 996 | } | ||
| 997 | |||
| 998 | |||
| 999 | /** | ||
| 1000 | * pciehp_slot_find - Looks for a node by bus, and device, multiple functions accessed | ||
| 1001 | * @bus: bus to find | ||
| 1002 | * @device: device to find | ||
| 1003 | * @index: is 0 for first function found, 1 for the second... | ||
| 1004 | * | ||
| 1005 | * Returns pointer to the node if successful, %NULL otherwise. | ||
| 1006 | */ | ||
| 1007 | struct pci_func *pciehp_slot_find(u8 bus, u8 device, u8 index) | ||
| 1008 | { | ||
| 1009 | int found = -1; | ||
| 1010 | struct pci_func *func; | ||
| 1011 | |||
| 1012 | func = pciehp_slot_list[bus]; | ||
| 1013 | dbg("%s: bus %x device %x index %x\n", | ||
| 1014 | __FUNCTION__, bus, device, index); | ||
| 1015 | if (func != NULL) { | ||
| 1016 | dbg("%s: func-> bus %x device %x function %x pci_dev %p\n", | ||
| 1017 | __FUNCTION__, func->bus, func->device, func->function, | ||
| 1018 | func->pci_dev); | ||
| 1019 | } else | ||
| 1020 | dbg("%s: func == NULL\n", __FUNCTION__); | ||
| 1021 | |||
| 1022 | if ((func == NULL) || ((func->device == device) && (index == 0))) | ||
| 1023 | return func; | ||
| 1024 | |||
| 1025 | if (func->device == device) | ||
| 1026 | found++; | ||
| 1027 | |||
| 1028 | while (func->next != NULL) { | ||
| 1029 | func = func->next; | ||
| 1030 | |||
| 1031 | dbg("%s: In while loop, func-> bus %x device %x function %x pci_dev %p\n", | ||
| 1032 | __FUNCTION__, func->bus, func->device, func->function, | ||
| 1033 | func->pci_dev); | ||
| 1034 | if (func->device == device) | ||
| 1035 | found++; | ||
| 1036 | dbg("%s: while loop, found %d, index %d\n", __FUNCTION__, | ||
| 1037 | found, index); | ||
| 1038 | |||
| 1039 | if ((found == index) || (func->function == index)) { | ||
| 1040 | dbg("%s: Found bus %x dev %x func %x\n", __FUNCTION__, | ||
| 1041 | func->bus, func->device, func->function); | ||
| 1042 | return func; | ||
| 1043 | } | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | return NULL; | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | static int is_bridge(struct pci_func * func) | ||
| 1050 | { | ||
| 1051 | /* Check the header type */ | ||
| 1052 | if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01) | ||
| 1053 | return 1; | ||
| 1054 | else | ||
| 1055 | return 0; | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | |||
| 1059 | /* The following routines constitute the bulk of the | 228 | /* The following routines constitute the bulk of the |
| 1060 | hotplug controller logic | 229 | hotplug controller logic |
| 1061 | */ | 230 | */ |
| @@ -1100,20 +269,17 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) | |||
| 1100 | * Configures board | 269 | * Configures board |
| 1101 | * | 270 | * |
| 1102 | */ | 271 | */ |
| 1103 | static u32 board_added(struct pci_func * func, struct controller * ctrl) | 272 | static int board_added(struct slot *p_slot) |
| 1104 | { | 273 | { |
| 1105 | u8 hp_slot; | 274 | u8 hp_slot; |
| 1106 | int index; | 275 | int rc = 0; |
| 1107 | u32 temp_register = 0xFFFFFFFF; | 276 | struct controller *ctrl = p_slot->ctrl; |
| 1108 | u32 rc = 0; | ||
| 1109 | struct pci_func *new_func = NULL; | ||
| 1110 | struct slot *p_slot; | ||
| 1111 | struct resource_lists res_lists; | ||
| 1112 | 277 | ||
| 1113 | p_slot = pciehp_find_slot(ctrl, func->device); | 278 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
| 1114 | hp_slot = func->device - ctrl->slot_device_offset; | ||
| 1115 | 279 | ||
| 1116 | dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); | 280 | dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n", |
| 281 | __FUNCTION__, p_slot->device, | ||
| 282 | ctrl->slot_device_offset, hp_slot); | ||
| 1117 | 283 | ||
| 1118 | /* Wait for exclusive access to hardware */ | 284 | /* Wait for exclusive access to hardware */ |
| 1119 | down(&ctrl->crit_sect); | 285 | down(&ctrl->crit_sect); |
| @@ -1141,9 +307,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) | |||
| 1141 | up(&ctrl->crit_sect); | 307 | up(&ctrl->crit_sect); |
| 1142 | 308 | ||
| 1143 | /* Wait for ~1 second */ | 309 | /* Wait for ~1 second */ |
| 1144 | dbg("%s: before long_delay\n", __FUNCTION__); | ||
| 1145 | wait_for_ctrl_irq (ctrl); | 310 | wait_for_ctrl_irq (ctrl); |
| 1146 | dbg("%s: afterlong_delay\n", __FUNCTION__); | ||
| 1147 | 311 | ||
| 1148 | /* Check link training status */ | 312 | /* Check link training status */ |
| 1149 | rc = p_slot->hpc_ops->check_lnk_status(ctrl); | 313 | rc = p_slot->hpc_ops->check_lnk_status(ctrl); |
| @@ -1153,98 +317,47 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) | |||
| 1153 | return rc; | 317 | return rc; |
| 1154 | } | 318 | } |
| 1155 | 319 | ||
| 1156 | dbg("%s: func status = %x\n", __FUNCTION__, func->status); | 320 | dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); |
| 1157 | 321 | ||
| 1158 | /* Check for a power fault */ | 322 | /* Check for a power fault */ |
| 1159 | if (func->status == 0xFF) { | 323 | if (p_slot->status == 0xFF) { |
| 1160 | /* power fault occurred, but it was benign */ | 324 | /* power fault occurred, but it was benign */ |
| 1161 | temp_register = 0xFFFFFFFF; | ||
| 1162 | dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register); | ||
| 1163 | rc = POWER_FAILURE; | 325 | rc = POWER_FAILURE; |
| 1164 | func->status = 0; | 326 | p_slot->status = 0; |
| 1165 | } else { | 327 | goto err_exit; |
| 1166 | /* Get vendor/device ID u32 */ | ||
| 1167 | rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function), | ||
| 1168 | PCI_VENDOR_ID, &temp_register); | ||
| 1169 | dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc); | ||
| 1170 | dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register); | ||
| 1171 | |||
| 1172 | if (rc != 0) { | ||
| 1173 | /* Something's wrong here */ | ||
| 1174 | temp_register = 0xFFFFFFFF; | ||
| 1175 | dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register); | ||
| 1176 | } | ||
| 1177 | /* Preset return code. It will be changed later if things go okay. */ | ||
| 1178 | rc = NO_ADAPTER_PRESENT; | ||
| 1179 | } | 328 | } |
| 1180 | 329 | ||
| 1181 | /* All F's is an empty slot or an invalid board */ | 330 | rc = pciehp_configure_device(p_slot); |
| 1182 | if (temp_register != 0xFFFFFFFF) { /* Check for a board in the slot */ | 331 | if (rc) { |
| 1183 | res_lists.io_head = ctrl->io_head; | 332 | err("Cannot add device 0x%x:%x\n", p_slot->bus, |
| 1184 | res_lists.mem_head = ctrl->mem_head; | 333 | p_slot->device); |
| 1185 | res_lists.p_mem_head = ctrl->p_mem_head; | 334 | goto err_exit; |
| 1186 | res_lists.bus_head = ctrl->bus_head; | 335 | } |
| 1187 | res_lists.irqs = NULL; | ||
| 1188 | |||
| 1189 | rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0); | ||
| 1190 | dbg("%s: back from configure_new_device\n", __FUNCTION__); | ||
| 1191 | |||
| 1192 | ctrl->io_head = res_lists.io_head; | ||
| 1193 | ctrl->mem_head = res_lists.mem_head; | ||
| 1194 | ctrl->p_mem_head = res_lists.p_mem_head; | ||
| 1195 | ctrl->bus_head = res_lists.bus_head; | ||
| 1196 | 336 | ||
| 1197 | pciehp_resource_sort_and_combine(&(ctrl->mem_head)); | 337 | p_slot->status = 0; |
| 1198 | pciehp_resource_sort_and_combine(&(ctrl->p_mem_head)); | ||
| 1199 | pciehp_resource_sort_and_combine(&(ctrl->io_head)); | ||
| 1200 | pciehp_resource_sort_and_combine(&(ctrl->bus_head)); | ||
| 1201 | 338 | ||
| 1202 | if (rc) { | 339 | /* |
| 1203 | set_slot_off(ctrl, p_slot); | 340 | * Some PCI Express root ports require fixup after hot-plug operation. |
| 1204 | return rc; | 341 | */ |
| 1205 | } | 342 | if (pcie_mch_quirk) |
| 1206 | pciehp_save_slot_config(ctrl, func); | 343 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); |
| 1207 | 344 | if (PWR_LED(ctrl->ctrlcap)) { | |
| 1208 | func->status = 0; | 345 | /* Wait for exclusive access to hardware */ |
| 1209 | func->switch_save = 0x10; | 346 | down(&ctrl->crit_sect); |
| 1210 | func->is_a_board = 0x01; | ||
| 1211 | 347 | ||
| 1212 | /* next, we will instantiate the linux pci_dev structures | 348 | p_slot->hpc_ops->green_led_on(p_slot); |
| 1213 | * (with appropriate driver notification, if already present) | ||
| 1214 | */ | ||
| 1215 | index = 0; | ||
| 1216 | do { | ||
| 1217 | new_func = pciehp_slot_find(ctrl->slot_bus, func->device, index++); | ||
| 1218 | if (new_func && !new_func->pci_dev) { | ||
| 1219 | dbg("%s:call pci_hp_configure_dev, func %x\n", | ||
| 1220 | __FUNCTION__, index); | ||
| 1221 | pciehp_configure_device(ctrl, new_func); | ||
| 1222 | } | ||
| 1223 | } while (new_func); | ||
| 1224 | |||
| 1225 | /* | ||
| 1226 | * Some PCI Express root ports require fixup after hot-plug operation. | ||
| 1227 | */ | ||
| 1228 | if (pcie_mch_quirk) | ||
| 1229 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); | ||
| 1230 | |||
| 1231 | if (PWR_LED(ctrl->ctrlcap)) { | ||
| 1232 | /* Wait for exclusive access to hardware */ | ||
| 1233 | down(&ctrl->crit_sect); | ||
| 1234 | |||
| 1235 | p_slot->hpc_ops->green_led_on(p_slot); | ||
| 1236 | 349 | ||
| 1237 | /* Wait for the command to complete */ | 350 | /* Wait for the command to complete */ |
| 1238 | wait_for_ctrl_irq (ctrl); | 351 | wait_for_ctrl_irq (ctrl); |
| 1239 | 352 | ||
| 1240 | /* Done with exclusive hardware access */ | 353 | /* Done with exclusive hardware access */ |
| 1241 | up(&ctrl->crit_sect); | 354 | up(&ctrl->crit_sect); |
| 1242 | } | 355 | } |
| 1243 | } else { | ||
| 1244 | set_slot_off(ctrl, p_slot); | ||
| 1245 | return -1; | ||
| 1246 | } | ||
| 1247 | return 0; | 356 | return 0; |
| 357 | |||
| 358 | err_exit: | ||
| 359 | set_slot_off(ctrl, p_slot); | ||
| 360 | return -1; | ||
| 1248 | } | 361 | } |
| 1249 | 362 | ||
| 1250 | 363 | ||
| @@ -1252,55 +365,25 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) | |||
| 1252 | * remove_board - Turns off slot and LED's | 365 | * remove_board - Turns off slot and LED's |
| 1253 | * | 366 | * |
| 1254 | */ | 367 | */ |
| 1255 | static u32 remove_board(struct pci_func *func, struct controller *ctrl) | 368 | static int remove_board(struct slot *p_slot) |
| 1256 | { | 369 | { |
| 1257 | int index; | ||
| 1258 | u8 skip = 0; | ||
| 1259 | u8 device; | 370 | u8 device; |
| 1260 | u8 hp_slot; | 371 | u8 hp_slot; |
| 1261 | u32 rc; | 372 | int rc; |
| 1262 | struct resource_lists res_lists; | 373 | struct controller *ctrl = p_slot->ctrl; |
| 1263 | struct pci_func *temp_func; | ||
| 1264 | struct slot *p_slot; | ||
| 1265 | |||
| 1266 | if (func == NULL) | ||
| 1267 | return 1; | ||
| 1268 | 374 | ||
| 1269 | if (pciehp_unconfigure_device(func)) | 375 | if (pciehp_unconfigure_device(p_slot)) |
| 1270 | return 1; | 376 | return 1; |
| 1271 | 377 | ||
| 1272 | device = func->device; | 378 | device = p_slot->device; |
| 1273 | 379 | ||
| 1274 | hp_slot = func->device - ctrl->slot_device_offset; | 380 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
| 1275 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 381 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
| 1276 | 382 | ||
| 1277 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); | 383 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); |
| 1278 | 384 | ||
| 1279 | if ((ctrl->add_support) && | ||
| 1280 | !(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) { | ||
| 1281 | /* Here we check to see if we've saved any of the board's | ||
| 1282 | * resources already. If so, we'll skip the attempt to | ||
| 1283 | * determine what's being used. | ||
| 1284 | */ | ||
| 1285 | index = 0; | ||
| 1286 | |||
| 1287 | temp_func = func; | ||
| 1288 | |||
| 1289 | while ((temp_func = pciehp_slot_find(temp_func->bus, temp_func->device, index++))) { | ||
| 1290 | if (temp_func->bus_head || temp_func->mem_head | ||
| 1291 | || temp_func->p_mem_head || temp_func->io_head) { | ||
| 1292 | skip = 1; | ||
| 1293 | break; | ||
| 1294 | } | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | if (!skip) | ||
| 1298 | rc = pciehp_save_used_resources(ctrl, func, DISABLE_CARD); | ||
| 1299 | } | ||
| 1300 | /* Change status to shutdown */ | 385 | /* Change status to shutdown */ |
| 1301 | if (func->is_a_board) | 386 | p_slot->status = 0x01; |
| 1302 | func->status = 0x01; | ||
| 1303 | func->configured = 0; | ||
| 1304 | 387 | ||
| 1305 | /* Wait for exclusive access to hardware */ | 388 | /* Wait for exclusive access to hardware */ |
| 1306 | down(&ctrl->crit_sect); | 389 | down(&ctrl->crit_sect); |
| @@ -1328,56 +411,6 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl) | |||
| 1328 | /* Done with exclusive hardware access */ | 411 | /* Done with exclusive hardware access */ |
| 1329 | up(&ctrl->crit_sect); | 412 | up(&ctrl->crit_sect); |
| 1330 | 413 | ||
| 1331 | if (ctrl->add_support) { | ||
| 1332 | while (func) { | ||
| 1333 | res_lists.io_head = ctrl->io_head; | ||
| 1334 | res_lists.mem_head = ctrl->mem_head; | ||
| 1335 | res_lists.p_mem_head = ctrl->p_mem_head; | ||
| 1336 | res_lists.bus_head = ctrl->bus_head; | ||
| 1337 | |||
| 1338 | dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n", | ||
| 1339 | func->bus, func->device, func->function); | ||
| 1340 | |||
| 1341 | pciehp_return_board_resources(func, &res_lists); | ||
| 1342 | |||
| 1343 | ctrl->io_head = res_lists.io_head; | ||
| 1344 | ctrl->mem_head = res_lists.mem_head; | ||
| 1345 | ctrl->p_mem_head = res_lists.p_mem_head; | ||
| 1346 | ctrl->bus_head = res_lists.bus_head; | ||
| 1347 | |||
| 1348 | pciehp_resource_sort_and_combine(&(ctrl->mem_head)); | ||
| 1349 | pciehp_resource_sort_and_combine(&(ctrl->p_mem_head)); | ||
| 1350 | pciehp_resource_sort_and_combine(&(ctrl->io_head)); | ||
| 1351 | pciehp_resource_sort_and_combine(&(ctrl->bus_head)); | ||
| 1352 | |||
| 1353 | if (is_bridge(func)) { | ||
| 1354 | dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", | ||
| 1355 | ctrl->seg, func->bus, func->device, func->function); | ||
| 1356 | bridge_slot_remove(func); | ||
| 1357 | } else { | ||
| 1358 | dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", | ||
| 1359 | ctrl->seg, func->bus, func->device, func->function); | ||
| 1360 | slot_remove(func); | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | func = pciehp_slot_find(ctrl->slot_bus, device, 0); | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | /* Setup slot structure with entry for empty slot */ | ||
| 1367 | func = pciehp_slot_create(ctrl->slot_bus); | ||
| 1368 | |||
| 1369 | if (func == NULL) { | ||
| 1370 | return 1; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | func->bus = ctrl->slot_bus; | ||
| 1374 | func->device = device; | ||
| 1375 | func->function = 0; | ||
| 1376 | func->configured = 0; | ||
| 1377 | func->switch_save = 0x10; | ||
| 1378 | func->is_a_board = 0; | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | return 0; | 414 | return 0; |
| 1382 | } | 415 | } |
| 1383 | 416 | ||
| @@ -1411,13 +444,15 @@ static void pciehp_pushbutton_thread(unsigned long slot) | |||
| 1411 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 444 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
| 1412 | if (getstatus) { | 445 | if (getstatus) { |
| 1413 | p_slot->state = POWEROFF_STATE; | 446 | p_slot->state = POWEROFF_STATE; |
| 1414 | dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); | 447 | dbg("%s: disabling bus:device(%x:%x)\n", __FUNCTION__, |
| 448 | p_slot->bus, p_slot->device); | ||
| 1415 | 449 | ||
| 1416 | pciehp_disable_slot(p_slot); | 450 | pciehp_disable_slot(p_slot); |
| 1417 | p_slot->state = STATIC_STATE; | 451 | p_slot->state = STATIC_STATE; |
| 1418 | } else { | 452 | } else { |
| 1419 | p_slot->state = POWERON_STATE; | 453 | p_slot->state = POWERON_STATE; |
| 1420 | dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); | 454 | dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, |
| 455 | p_slot->bus, p_slot->device); | ||
| 1421 | 456 | ||
| 1422 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 457 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { |
| 1423 | /* Wait for exclusive access to hardware */ | 458 | /* Wait for exclusive access to hardware */ |
| @@ -1459,13 +494,15 @@ static void pciehp_surprise_rm_thread(unsigned long slot) | |||
| 1459 | p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 494 | p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); |
| 1460 | if (!getstatus) { | 495 | if (!getstatus) { |
| 1461 | p_slot->state = POWEROFF_STATE; | 496 | p_slot->state = POWEROFF_STATE; |
| 1462 | dbg("In removing board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); | 497 | dbg("%s: removing bus:device(%x:%x)\n", |
| 498 | __FUNCTION__, p_slot->bus, p_slot->device); | ||
| 1463 | 499 | ||
| 1464 | pciehp_disable_slot(p_slot); | 500 | pciehp_disable_slot(p_slot); |
| 1465 | p_slot->state = STATIC_STATE; | 501 | p_slot->state = STATIC_STATE; |
| 1466 | } else { | 502 | } else { |
| 1467 | p_slot->state = POWERON_STATE; | 503 | p_slot->state = POWERON_STATE; |
| 1468 | dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); | 504 | dbg("%s: adding bus:device(%x:%x)\n", |
| 505 | __FUNCTION__, p_slot->bus, p_slot->device); | ||
| 1469 | 506 | ||
| 1470 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 507 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { |
| 1471 | /* Wait for exclusive access to hardware */ | 508 | /* Wait for exclusive access to hardware */ |
| @@ -1531,7 +568,6 @@ int pciehp_event_start_thread(void) | |||
| 1531 | err ("Can't start up our event thread\n"); | 568 | err ("Can't start up our event thread\n"); |
| 1532 | return -1; | 569 | return -1; |
| 1533 | } | 570 | } |
| 1534 | dbg("Our event thread pid = %d\n", pid); | ||
| 1535 | return 0; | 571 | return 0; |
| 1536 | } | 572 | } |
| 1537 | 573 | ||
| @@ -1539,9 +575,7 @@ int pciehp_event_start_thread(void) | |||
| 1539 | void pciehp_event_stop_thread(void) | 575 | void pciehp_event_stop_thread(void) |
| 1540 | { | 576 | { |
| 1541 | event_finished = 1; | 577 | event_finished = 1; |
| 1542 | dbg("event_thread finish command given\n"); | ||
| 1543 | up(&event_semaphore); | 578 | up(&event_semaphore); |
| 1544 | dbg("wait for event_thread to exit\n"); | ||
| 1545 | down(&event_exit); | 579 | down(&event_exit); |
| 1546 | } | 580 | } |
| 1547 | 581 | ||
| @@ -1573,7 +607,6 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 1573 | { | 607 | { |
| 1574 | int loop = 0; | 608 | int loop = 0; |
| 1575 | int change = 1; | 609 | int change = 1; |
| 1576 | struct pci_func *func; | ||
| 1577 | u8 hp_slot; | 610 | u8 hp_slot; |
| 1578 | u8 getstatus; | 611 | u8 getstatus; |
| 1579 | struct slot *p_slot; | 612 | struct slot *p_slot; |
| @@ -1581,16 +614,12 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 1581 | while (change) { | 614 | while (change) { |
| 1582 | change = 0; | 615 | change = 0; |
| 1583 | 616 | ||
| 1584 | for (loop = 0; loop < 10; loop++) { | 617 | for (loop = 0; loop < MAX_EVENTS; loop++) { |
| 1585 | if (ctrl->event_queue[loop].event_type != 0) { | 618 | if (ctrl->event_queue[loop].event_type != 0) { |
| 1586 | hp_slot = ctrl->event_queue[loop].hp_slot; | 619 | hp_slot = ctrl->event_queue[loop].hp_slot; |
| 1587 | 620 | ||
| 1588 | func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); | ||
| 1589 | |||
| 1590 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 621 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
| 1591 | 622 | ||
| 1592 | dbg("hp_slot %d, func %p, p_slot %p\n", hp_slot, func, p_slot); | ||
| 1593 | |||
| 1594 | if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { | 623 | if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { |
| 1595 | dbg("button cancel\n"); | 624 | dbg("button cancel\n"); |
| 1596 | del_timer(&p_slot->task_event); | 625 | del_timer(&p_slot->task_event); |
| @@ -1682,7 +711,6 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 1682 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; | 711 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; |
| 1683 | p_slot->task_event.data = (unsigned long) p_slot; | 712 | p_slot->task_event.data = (unsigned long) p_slot; |
| 1684 | 713 | ||
| 1685 | dbg("add_timer p_slot = %p\n", (void *) p_slot); | ||
| 1686 | add_timer(&p_slot->task_event); | 714 | add_timer(&p_slot->task_event); |
| 1687 | } | 715 | } |
| 1688 | } | 716 | } |
| @@ -1737,13 +765,6 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
| 1737 | { | 765 | { |
| 1738 | u8 getstatus = 0; | 766 | u8 getstatus = 0; |
| 1739 | int rc; | 767 | int rc; |
| 1740 | struct pci_func *func; | ||
| 1741 | |||
| 1742 | func = pciehp_slot_find(p_slot->bus, p_slot->device, 0); | ||
| 1743 | if (!func) { | ||
| 1744 | dbg("%s: Error! slot NULL\n", __FUNCTION__); | ||
| 1745 | return 1; | ||
| 1746 | } | ||
| 1747 | 768 | ||
| 1748 | /* Check to see if (latch closed, card present, power off) */ | 769 | /* Check to see if (latch closed, card present, power off) */ |
| 1749 | down(&p_slot->ctrl->crit_sect); | 770 | down(&p_slot->ctrl->crit_sect); |
| @@ -1773,45 +794,11 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
| 1773 | } | 794 | } |
| 1774 | up(&p_slot->ctrl->crit_sect); | 795 | up(&p_slot->ctrl->crit_sect); |
| 1775 | 796 | ||
| 1776 | slot_remove(func); | ||
| 1777 | |||
| 1778 | func = pciehp_slot_create(p_slot->bus); | ||
| 1779 | if (func == NULL) | ||
| 1780 | return 1; | ||
| 1781 | |||
| 1782 | func->bus = p_slot->bus; | ||
| 1783 | func->device = p_slot->device; | ||
| 1784 | func->function = 0; | ||
| 1785 | func->configured = 0; | ||
| 1786 | func->is_a_board = 1; | ||
| 1787 | |||
| 1788 | /* We have to save the presence info for these slots */ | ||
| 1789 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | ||
| 1790 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 797 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 1791 | func->switch_save = !getstatus? 0x10:0; | ||
| 1792 | 798 | ||
| 1793 | rc = board_added(func, p_slot->ctrl); | 799 | rc = board_added(p_slot); |
| 1794 | if (rc) { | 800 | if (rc) { |
| 1795 | if (is_bridge(func)) | ||
| 1796 | bridge_slot_remove(func); | ||
| 1797 | else | ||
| 1798 | slot_remove(func); | ||
| 1799 | |||
| 1800 | /* Setup slot structure with entry for empty slot */ | ||
| 1801 | func = pciehp_slot_create(p_slot->bus); | ||
| 1802 | if (func == NULL) | ||
| 1803 | return 1; /* Out of memory */ | ||
| 1804 | |||
| 1805 | func->bus = p_slot->bus; | ||
| 1806 | func->device = p_slot->device; | ||
| 1807 | func->function = 0; | ||
| 1808 | func->configured = 0; | ||
| 1809 | func->is_a_board = 1; | ||
| 1810 | |||
| 1811 | /* We have to save the presence info for these slots */ | ||
| 1812 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | ||
| 1813 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 801 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 1814 | func->switch_save = !getstatus? 0x10:0; | ||
| 1815 | } | 802 | } |
| 1816 | 803 | ||
| 1817 | if (p_slot) | 804 | if (p_slot) |
| @@ -1823,14 +810,8 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
| 1823 | 810 | ||
| 1824 | int pciehp_disable_slot(struct slot *p_slot) | 811 | int pciehp_disable_slot(struct slot *p_slot) |
| 1825 | { | 812 | { |
| 1826 | u8 class_code, header_type, BCR; | ||
| 1827 | u8 index = 0; | ||
| 1828 | u8 getstatus = 0; | 813 | u8 getstatus = 0; |
| 1829 | u32 rc = 0; | ||
| 1830 | int ret = 0; | 814 | int ret = 0; |
| 1831 | unsigned int devfn; | ||
| 1832 | struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate; | ||
| 1833 | struct pci_func *func; | ||
| 1834 | 815 | ||
| 1835 | if (!p_slot->ctrl) | 816 | if (!p_slot->ctrl) |
| 1836 | return 1; | 817 | return 1; |
| @@ -1867,838 +848,8 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
| 1867 | 848 | ||
| 1868 | up(&p_slot->ctrl->crit_sect); | 849 | up(&p_slot->ctrl->crit_sect); |
| 1869 | 850 | ||
| 1870 | func = pciehp_slot_find(p_slot->bus, p_slot->device, index++); | 851 | ret = remove_board(p_slot); |
| 1871 | 852 | update_slot_info(p_slot); | |
| 1872 | /* Make sure there are no video controllers here | 853 | return ret; |
| 1873 | * for all func of p_slot | ||
| 1874 | */ | ||
| 1875 | while (func && !rc) { | ||
| 1876 | pci_bus->number = func->bus; | ||
| 1877 | devfn = PCI_DEVFN(func->device, func->function); | ||
| 1878 | |||
| 1879 | /* Check the Class Code */ | ||
| 1880 | rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); | ||
| 1881 | if (rc) | ||
| 1882 | return rc; | ||
| 1883 | |||
| 1884 | if (class_code == PCI_BASE_CLASS_DISPLAY) { | ||
| 1885 | /* Display/Video adapter (not supported) */ | ||
| 1886 | rc = REMOVE_NOT_SUPPORTED; | ||
| 1887 | } else { | ||
| 1888 | /* See if it's a bridge */ | ||
| 1889 | rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); | ||
| 1890 | if (rc) | ||
| 1891 | return rc; | ||
| 1892 | |||
| 1893 | /* If it's a bridge, check the VGA Enable bit */ | ||
| 1894 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { | ||
| 1895 | rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR); | ||
| 1896 | if (rc) | ||
| 1897 | return rc; | ||
| 1898 | |||
| 1899 | /* If the VGA Enable bit is set, remove isn't supported */ | ||
| 1900 | if (BCR & PCI_BRIDGE_CTL_VGA) { | ||
| 1901 | rc = REMOVE_NOT_SUPPORTED; | ||
| 1902 | } | ||
| 1903 | } | ||
| 1904 | } | ||
| 1905 | |||
| 1906 | func = pciehp_slot_find(p_slot->bus, p_slot->device, index++); | ||
| 1907 | } | ||
| 1908 | |||
| 1909 | func = pciehp_slot_find(p_slot->bus, p_slot->device, 0); | ||
| 1910 | if ((func != NULL) && !rc) { | ||
| 1911 | rc = remove_board(func, p_slot->ctrl); | ||
| 1912 | } else if (!rc) | ||
| 1913 | rc = 1; | ||
| 1914 | |||
| 1915 | if (p_slot) | ||
| 1916 | update_slot_info(p_slot); | ||
| 1917 | |||
| 1918 | return rc; | ||
| 1919 | } | ||
| 1920 | |||
| 1921 | |||
| 1922 | /** | ||
| 1923 | * configure_new_device - Configures the PCI header information of one board. | ||
| 1924 | * | ||
| 1925 | * @ctrl: pointer to controller structure | ||
| 1926 | * @func: pointer to function structure | ||
| 1927 | * @behind_bridge: 1 if this is a recursive call, 0 if not | ||
| 1928 | * @resources: pointer to set of resource lists | ||
| 1929 | * | ||
| 1930 | * Returns 0 if success | ||
| 1931 | * | ||
| 1932 | */ | ||
| 1933 | static u32 configure_new_device(struct controller * ctrl, struct pci_func * func, | ||
| 1934 | u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev) | ||
| 1935 | { | ||
| 1936 | u8 temp_byte, function, max_functions, stop_it; | ||
| 1937 | int rc; | ||
| 1938 | u32 ID; | ||
| 1939 | struct pci_func *new_slot; | ||
| 1940 | struct pci_bus lpci_bus, *pci_bus; | ||
| 1941 | int index; | ||
| 1942 | |||
| 1943 | new_slot = func; | ||
| 1944 | |||
| 1945 | dbg("%s\n", __FUNCTION__); | ||
| 1946 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
| 1947 | pci_bus = &lpci_bus; | ||
| 1948 | pci_bus->number = func->bus; | ||
| 1949 | |||
| 1950 | /* Check for Multi-function device */ | ||
| 1951 | rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte); | ||
| 1952 | if (rc) { | ||
| 1953 | dbg("%s: rc = %d\n", __FUNCTION__, rc); | ||
| 1954 | return rc; | ||
| 1955 | } | ||
| 1956 | |||
| 1957 | if (temp_byte & 0x80) /* Multi-function device */ | ||
| 1958 | max_functions = 8; | ||
| 1959 | else | ||
| 1960 | max_functions = 1; | ||
| 1961 | |||
| 1962 | function = 0; | ||
| 1963 | |||
| 1964 | do { | ||
| 1965 | rc = configure_new_function(ctrl, new_slot, behind_bridge, | ||
| 1966 | resources, bridge_bus, bridge_dev); | ||
| 1967 | |||
| 1968 | if (rc) { | ||
| 1969 | dbg("configure_new_function failed: %d\n", rc); | ||
| 1970 | index = 0; | ||
| 1971 | |||
| 1972 | while (new_slot) { | ||
| 1973 | new_slot = pciehp_slot_find(new_slot->bus, | ||
| 1974 | new_slot->device, index++); | ||
| 1975 | |||
| 1976 | if (new_slot) | ||
| 1977 | pciehp_return_board_resources(new_slot, | ||
| 1978 | resources); | ||
| 1979 | } | ||
| 1980 | |||
| 1981 | return rc; | ||
| 1982 | } | ||
| 1983 | |||
| 1984 | function++; | ||
| 1985 | |||
| 1986 | stop_it = 0; | ||
| 1987 | |||
| 1988 | /* The following loop skips to the next present function | ||
| 1989 | * and creates a board structure | ||
| 1990 | */ | ||
| 1991 | |||
| 1992 | while ((function < max_functions) && (!stop_it)) { | ||
| 1993 | pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID); | ||
| 1994 | |||
| 1995 | if (ID == 0xFFFFFFFF) { /* There's nothing there. */ | ||
| 1996 | function++; | ||
| 1997 | } else { /* There's something there */ | ||
| 1998 | /* Setup slot structure. */ | ||
| 1999 | new_slot = pciehp_slot_create(func->bus); | ||
| 2000 | |||
| 2001 | if (new_slot == NULL) { | ||
| 2002 | /* Out of memory */ | ||
| 2003 | return 1; | ||
| 2004 | } | ||
| 2005 | |||
| 2006 | new_slot->bus = func->bus; | ||
| 2007 | new_slot->device = func->device; | ||
| 2008 | new_slot->function = function; | ||
| 2009 | new_slot->is_a_board = 1; | ||
| 2010 | new_slot->status = 0; | ||
| 2011 | |||
| 2012 | stop_it++; | ||
| 2013 | } | ||
| 2014 | } | ||
| 2015 | |||
| 2016 | } while (function < max_functions); | ||
| 2017 | dbg("returning from %s\n", __FUNCTION__); | ||
| 2018 | |||
| 2019 | return 0; | ||
| 2020 | } | ||
| 2021 | |||
| 2022 | /* | ||
| 2023 | * Configuration logic that involves the hotplug data structures and | ||
| 2024 | * their bookkeeping | ||
| 2025 | */ | ||
| 2026 | |||
| 2027 | /** | ||
| 2028 | * configure_bridge: fill bridge's registers, either configure or disable it. | ||
| 2029 | */ | ||
| 2030 | static int | ||
| 2031 | configure_bridge(struct pci_bus *pci_bus, unsigned int devfn, | ||
| 2032 | struct pci_resource *mem_node, | ||
| 2033 | struct pci_resource **hold_mem_node, | ||
| 2034 | int base_addr, int limit_addr) | ||
| 2035 | { | ||
| 2036 | u16 temp_word; | ||
| 2037 | u32 rc; | ||
| 2038 | |||
| 2039 | if (mem_node) { | ||
| 2040 | memcpy(*hold_mem_node, mem_node, sizeof(struct pci_resource)); | ||
| 2041 | mem_node->next = NULL; | ||
| 2042 | |||
| 2043 | /* set Mem base and Limit registers */ | ||
| 2044 | RES_CHECK(mem_node->base, 16); | ||
| 2045 | temp_word = (u16)(mem_node->base >> 16); | ||
| 2046 | rc = pci_bus_write_config_word(pci_bus, devfn, base_addr, temp_word); | ||
| 2047 | |||
| 2048 | RES_CHECK(mem_node->base + mem_node->length - 1, 16); | ||
| 2049 | temp_word = (u16)((mem_node->base + mem_node->length - 1) >> 16); | ||
| 2050 | rc = pci_bus_write_config_word(pci_bus, devfn, limit_addr, temp_word); | ||
| 2051 | } else { | ||
| 2052 | temp_word = 0xFFFF; | ||
| 2053 | rc = pci_bus_write_config_word(pci_bus, devfn, base_addr, temp_word); | ||
| 2054 | |||
| 2055 | temp_word = 0x0000; | ||
| 2056 | rc = pci_bus_write_config_word(pci_bus, devfn, limit_addr, temp_word); | ||
| 2057 | |||
| 2058 | kfree(*hold_mem_node); | ||
| 2059 | *hold_mem_node = NULL; | ||
| 2060 | } | ||
| 2061 | return rc; | ||
| 2062 | } | ||
| 2063 | |||
| 2064 | static int | ||
| 2065 | configure_new_bridge(struct controller *ctrl, struct pci_func *func, | ||
| 2066 | u8 behind_bridge, struct resource_lists *resources, | ||
| 2067 | struct pci_bus *pci_bus) | ||
| 2068 | { | ||
| 2069 | int cloop; | ||
| 2070 | u8 temp_byte; | ||
| 2071 | u8 device; | ||
| 2072 | u16 temp_word; | ||
| 2073 | u32 rc; | ||
| 2074 | u32 ID; | ||
| 2075 | unsigned int devfn; | ||
| 2076 | struct pci_resource *mem_node; | ||
| 2077 | struct pci_resource *p_mem_node; | ||
| 2078 | struct pci_resource *io_node; | ||
| 2079 | struct pci_resource *bus_node; | ||
| 2080 | struct pci_resource *hold_mem_node; | ||
| 2081 | struct pci_resource *hold_p_mem_node; | ||
| 2082 | struct pci_resource *hold_IO_node; | ||
| 2083 | struct pci_resource *hold_bus_node; | ||
| 2084 | struct irq_mapping irqs; | ||
| 2085 | struct pci_func *new_slot; | ||
| 2086 | struct resource_lists temp_resources; | ||
| 2087 | |||
| 2088 | devfn = PCI_DEVFN(func->device, func->function); | ||
| 2089 | |||
| 2090 | /* set Primary bus */ | ||
| 2091 | dbg("set Primary bus = 0x%x\n", func->bus); | ||
| 2092 | rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus); | ||
| 2093 | if (rc) | ||
| 2094 | return rc; | ||
| 2095 | |||
| 2096 | /* find range of busses to use */ | ||
| 2097 | bus_node = get_max_resource(&resources->bus_head, 1L); | ||
| 2098 | |||
| 2099 | /* If we don't have any busses to allocate, we can't continue */ | ||
| 2100 | if (!bus_node) { | ||
| 2101 | err("Got NO bus resource to use\n"); | ||
| 2102 | return -ENOMEM; | ||
| 2103 | } | ||
| 2104 | dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length); | ||
| 2105 | |||
| 2106 | /* set Secondary bus */ | ||
| 2107 | temp_byte = (u8)bus_node->base; | ||
| 2108 | dbg("set Secondary bus = 0x%x\n", temp_byte); | ||
| 2109 | rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte); | ||
| 2110 | if (rc) | ||
| 2111 | return rc; | ||
| 2112 | |||
| 2113 | /* set subordinate bus */ | ||
| 2114 | temp_byte = (u8)(bus_node->base + bus_node->length - 1); | ||
| 2115 | dbg("set subordinate bus = 0x%x\n", temp_byte); | ||
| 2116 | rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); | ||
| 2117 | if (rc) | ||
| 2118 | return rc; | ||
| 2119 | |||
| 2120 | /* Set HP parameters (Cache Line Size, Latency Timer) */ | ||
| 2121 | rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE); | ||
| 2122 | if (rc) | ||
| 2123 | return rc; | ||
| 2124 | |||
| 2125 | /* Setup the IO, memory, and prefetchable windows */ | ||
| 2126 | |||
| 2127 | io_node = get_max_resource(&(resources->io_head), 0x1000L); | ||
| 2128 | if (io_node) { | ||
| 2129 | dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, | ||
| 2130 | io_node->length, io_node->next); | ||
| 2131 | } | ||
| 2132 | |||
| 2133 | mem_node = get_max_resource(&(resources->mem_head), 0x100000L); | ||
| 2134 | if (mem_node) { | ||
| 2135 | dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, | ||
| 2136 | mem_node->length, mem_node->next); | ||
| 2137 | } | ||
| 2138 | |||
| 2139 | if (resources->p_mem_head) | ||
| 2140 | p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L); | ||
| 2141 | else { | ||
| 2142 | /* | ||
| 2143 | * In some platform implementation, MEM and PMEM are not | ||
| 2144 | * distinguished, and hence ACPI _CRS has only MEM entries | ||
| 2145 | * for both MEM and PMEM. | ||
| 2146 | */ | ||
| 2147 | dbg("using MEM for PMEM\n"); | ||
| 2148 | p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L); | ||
| 2149 | } | ||
| 2150 | if (p_mem_node) { | ||
| 2151 | dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, | ||
| 2152 | p_mem_node->length, p_mem_node->next); | ||
| 2153 | } | ||
| 2154 | |||
| 2155 | /* set up the IRQ info */ | ||
| 2156 | if (!resources->irqs) { | ||
| 2157 | irqs.barber_pole = 0; | ||
| 2158 | irqs.interrupt[0] = 0; | ||
| 2159 | irqs.interrupt[1] = 0; | ||
| 2160 | irqs.interrupt[2] = 0; | ||
| 2161 | irqs.interrupt[3] = 0; | ||
| 2162 | irqs.valid_INT = 0; | ||
| 2163 | } else { | ||
| 2164 | irqs.barber_pole = resources->irqs->barber_pole; | ||
| 2165 | irqs.interrupt[0] = resources->irqs->interrupt[0]; | ||
| 2166 | irqs.interrupt[1] = resources->irqs->interrupt[1]; | ||
| 2167 | irqs.interrupt[2] = resources->irqs->interrupt[2]; | ||
| 2168 | irqs.interrupt[3] = resources->irqs->interrupt[3]; | ||
| 2169 | irqs.valid_INT = resources->irqs->valid_INT; | ||
| 2170 | } | ||
| 2171 | |||
| 2172 | /* set up resource lists that are now aligned on top and bottom | ||
| 2173 | * for anything behind the bridge. | ||
| 2174 | */ | ||
| 2175 | temp_resources.bus_head = bus_node; | ||
| 2176 | temp_resources.io_head = io_node; | ||
| 2177 | temp_resources.mem_head = mem_node; | ||
| 2178 | temp_resources.p_mem_head = p_mem_node; | ||
| 2179 | temp_resources.irqs = &irqs; | ||
| 2180 | |||
| 2181 | /* Make copies of the nodes we are going to pass down so that | ||
| 2182 | * if there is a problem,we can just use these to free resources | ||
| 2183 | */ | ||
| 2184 | hold_bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
| 2185 | hold_IO_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
| 2186 | hold_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
| 2187 | hold_p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
| 2188 | |||
| 2189 | if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) { | ||
| 2190 | kfree(hold_bus_node); | ||
| 2191 | kfree(hold_IO_node); | ||
| 2192 | kfree(hold_mem_node); | ||
| 2193 | kfree(hold_p_mem_node); | ||
| 2194 | |||
| 2195 | return 1; | ||
| 2196 | } | ||
| 2197 | |||
| 2198 | memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource)); | ||
| 2199 | |||
| 2200 | bus_node->base += 1; | ||
| 2201 | bus_node->length -= 1; | ||
| 2202 | bus_node->next = NULL; | ||
| 2203 | |||
| 2204 | /* If we have IO resources copy them and fill in the bridge's | ||
| 2205 | * IO range registers | ||
| 2206 | */ | ||
| 2207 | if (io_node) { | ||
| 2208 | memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); | ||
| 2209 | io_node->next = NULL; | ||
| 2210 | |||
| 2211 | /* set IO base and Limit registers */ | ||
| 2212 | RES_CHECK(io_node->base, 8); | ||
| 2213 | temp_byte = (u8)(io_node->base >> 8); | ||
| 2214 | rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); | ||
| 2215 | |||
| 2216 | RES_CHECK(io_node->base + io_node->length - 1, 8); | ||
| 2217 | temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8); | ||
| 2218 | rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); | ||
| 2219 | } else { | ||
| 2220 | kfree(hold_IO_node); | ||
| 2221 | hold_IO_node = NULL; | ||
| 2222 | } | ||
| 2223 | |||
| 2224 | /* If we have memory resources copy them and fill in the bridge's | ||
| 2225 | * memory range registers. Otherwise, fill in the range | ||
| 2226 | * registers with values that disable them. | ||
| 2227 | */ | ||
| 2228 | rc = configure_bridge(pci_bus, devfn, mem_node, &hold_mem_node, | ||
| 2229 | PCI_MEMORY_BASE, PCI_MEMORY_LIMIT); | ||
| 2230 | |||
| 2231 | /* If we have prefetchable memory resources copy them and | ||
| 2232 | * fill in the bridge's memory range registers. Otherwise, | ||
| 2233 | * fill in the range registers with values that disable them. | ||
| 2234 | */ | ||
| 2235 | rc = configure_bridge(pci_bus, devfn, p_mem_node, &hold_p_mem_node, | ||
| 2236 | PCI_PREF_MEMORY_BASE, PCI_PREF_MEMORY_LIMIT); | ||
| 2237 | |||
| 2238 | /* Adjust this to compensate for extra adjustment in first loop */ | ||
| 2239 | irqs.barber_pole--; | ||
| 2240 | |||
| 2241 | rc = 0; | ||
| 2242 | |||
| 2243 | /* Here we actually find the devices and configure them */ | ||
| 2244 | for (device = 0; (device <= 0x1F) && !rc; device++) { | ||
| 2245 | irqs.barber_pole = (irqs.barber_pole + 1) & 0x03; | ||
| 2246 | |||
| 2247 | ID = 0xFFFFFFFF; | ||
| 2248 | pci_bus->number = hold_bus_node->base; | ||
| 2249 | pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); | ||
| 2250 | pci_bus->number = func->bus; | ||
| 2251 | |||
| 2252 | if (ID != 0xFFFFFFFF) { /* device Present */ | ||
| 2253 | /* Setup slot structure. */ | ||
| 2254 | new_slot = pciehp_slot_create(hold_bus_node->base); | ||
| 2255 | |||
| 2256 | if (new_slot == NULL) { | ||
| 2257 | /* Out of memory */ | ||
| 2258 | rc = -ENOMEM; | ||
| 2259 | continue; | ||
| 2260 | } | ||
| 2261 | |||
| 2262 | new_slot->bus = hold_bus_node->base; | ||
| 2263 | new_slot->device = device; | ||
| 2264 | new_slot->function = 0; | ||
| 2265 | new_slot->is_a_board = 1; | ||
| 2266 | new_slot->status = 0; | ||
| 2267 | |||
| 2268 | rc = configure_new_device(ctrl, new_slot, 1, | ||
| 2269 | &temp_resources, func->bus, | ||
| 2270 | func->device); | ||
| 2271 | dbg("configure_new_device rc=0x%x\n",rc); | ||
| 2272 | } /* End of IF (device in slot?) */ | ||
| 2273 | } /* End of FOR loop */ | ||
| 2274 | |||
| 2275 | if (rc) { | ||
| 2276 | pciehp_destroy_resource_list(&temp_resources); | ||
| 2277 | |||
| 2278 | return_resource(&(resources->bus_head), hold_bus_node); | ||
| 2279 | return_resource(&(resources->io_head), hold_IO_node); | ||
| 2280 | return_resource(&(resources->mem_head), hold_mem_node); | ||
| 2281 | return_resource(&(resources->p_mem_head), hold_p_mem_node); | ||
| 2282 | return(rc); | ||
| 2283 | } | ||
| 2284 | |||
| 2285 | /* save the interrupt routing information */ | ||
| 2286 | if (resources->irqs) { | ||
| 2287 | resources->irqs->interrupt[0] = irqs.interrupt[0]; | ||
| 2288 | resources->irqs->interrupt[1] = irqs.interrupt[1]; | ||
| 2289 | resources->irqs->interrupt[2] = irqs.interrupt[2]; | ||
| 2290 | resources->irqs->interrupt[3] = irqs.interrupt[3]; | ||
| 2291 | resources->irqs->valid_INT = irqs.valid_INT; | ||
| 2292 | } else if (!behind_bridge) { | ||
| 2293 | /* We need to hook up the interrupts here */ | ||
| 2294 | for (cloop = 0; cloop < 4; cloop++) { | ||
| 2295 | if (irqs.valid_INT & (0x01 << cloop)) { | ||
| 2296 | rc = pciehp_set_irq(func->bus, func->device, | ||
| 2297 | 0x0A + cloop, irqs.interrupt[cloop]); | ||
| 2298 | if (rc) { | ||
| 2299 | pciehp_destroy_resource_list (&temp_resources); | ||
| 2300 | return_resource(&(resources->bus_head), hold_bus_node); | ||
| 2301 | return_resource(&(resources->io_head), hold_IO_node); | ||
| 2302 | return_resource(&(resources->mem_head), hold_mem_node); | ||
| 2303 | return_resource(&(resources->p_mem_head), hold_p_mem_node); | ||
| 2304 | return rc; | ||
| 2305 | } | ||
| 2306 | } | ||
| 2307 | } /* end of for loop */ | ||
| 2308 | } | ||
| 2309 | |||
| 2310 | /* Return unused bus resources | ||
| 2311 | * First use the temporary node to store information for the board | ||
| 2312 | */ | ||
| 2313 | if (hold_bus_node && bus_node && temp_resources.bus_head) { | ||
| 2314 | hold_bus_node->length = bus_node->base - hold_bus_node->base; | ||
| 2315 | |||
| 2316 | hold_bus_node->next = func->bus_head; | ||
| 2317 | func->bus_head = hold_bus_node; | ||
| 2318 | |||
| 2319 | temp_byte = (u8)(temp_resources.bus_head->base - 1); | ||
| 2320 | |||
| 2321 | /* set subordinate bus */ | ||
| 2322 | dbg("re-set subordinate bus = 0x%x\n", temp_byte); | ||
| 2323 | rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); | ||
| 2324 | |||
| 2325 | if (temp_resources.bus_head->length == 0) { | ||
| 2326 | kfree(temp_resources.bus_head); | ||
| 2327 | temp_resources.bus_head = NULL; | ||
| 2328 | } else { | ||
| 2329 | dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n", | ||
| 2330 | func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length); | ||
| 2331 | return_resource(&(resources->bus_head), temp_resources.bus_head); | ||
| 2332 | } | ||
| 2333 | } | ||
| 2334 | |||
| 2335 | /* If we have IO space available and there is some left, | ||
| 2336 | * return the unused portion | ||
| 2337 | */ | ||
| 2338 | if (hold_IO_node && temp_resources.io_head) { | ||
| 2339 | io_node = do_pre_bridge_resource_split(&(temp_resources.io_head), | ||
| 2340 | &hold_IO_node, 0x1000); | ||
| 2341 | |||
| 2342 | /* Check if we were able to split something off */ | ||
| 2343 | if (io_node) { | ||
| 2344 | hold_IO_node->base = io_node->base + io_node->length; | ||
| 2345 | |||
| 2346 | RES_CHECK(hold_IO_node->base, 8); | ||
| 2347 | temp_byte = (u8)((hold_IO_node->base) >> 8); | ||
| 2348 | rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); | ||
| 2349 | |||
| 2350 | return_resource(&(resources->io_head), io_node); | ||
| 2351 | } | ||
| 2352 | |||
| 2353 | io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000); | ||
| 2354 | |||
| 2355 | /* Check if we were able to split something off */ | ||
| 2356 | if (io_node) { | ||
| 2357 | /* First use the temporary node to store information for the board */ | ||
| 2358 | hold_IO_node->length = io_node->base - hold_IO_node->base; | ||
| 2359 | |||
| 2360 | /* If we used any, add it to the board's list */ | ||
| 2361 | if (hold_IO_node->length) { | ||
| 2362 | hold_IO_node->next = func->io_head; | ||
| 2363 | func->io_head = hold_IO_node; | ||
| 2364 | |||
| 2365 | RES_CHECK(io_node->base - 1, 8); | ||
| 2366 | temp_byte = (u8)((io_node->base - 1) >> 8); | ||
| 2367 | rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); | ||
| 2368 | |||
| 2369 | return_resource(&(resources->io_head), io_node); | ||
| 2370 | } else { | ||
| 2371 | /* it doesn't need any IO */ | ||
| 2372 | temp_byte = 0x00; | ||
| 2373 | rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); | ||
| 2374 | |||
| 2375 | return_resource(&(resources->io_head), io_node); | ||
| 2376 | kfree(hold_IO_node); | ||
| 2377 | } | ||
| 2378 | } else { | ||
| 2379 | /* it used most of the range */ | ||
| 2380 | hold_IO_node->next = func->io_head; | ||
| 2381 | func->io_head = hold_IO_node; | ||
| 2382 | } | ||
| 2383 | } else if (hold_IO_node) { | ||
| 2384 | /* it used the whole range */ | ||
| 2385 | hold_IO_node->next = func->io_head; | ||
| 2386 | func->io_head = hold_IO_node; | ||
| 2387 | } | ||
| 2388 | |||
| 2389 | /* If we have memory space available and there is some left, | ||
| 2390 | * return the unused portion | ||
| 2391 | */ | ||
| 2392 | if (hold_mem_node && temp_resources.mem_head) { | ||
| 2393 | mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L); | ||
| 2394 | |||
| 2395 | /* Check if we were able to split something off */ | ||
| 2396 | if (mem_node) { | ||
| 2397 | hold_mem_node->base = mem_node->base + mem_node->length; | ||
| 2398 | |||
| 2399 | RES_CHECK(hold_mem_node->base, 16); | ||
| 2400 | temp_word = (u16)((hold_mem_node->base) >> 16); | ||
| 2401 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); | ||
| 2402 | |||
| 2403 | return_resource(&(resources->mem_head), mem_node); | ||
| 2404 | } | ||
| 2405 | |||
| 2406 | mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L); | ||
| 2407 | |||
| 2408 | /* Check if we were able to split something off */ | ||
| 2409 | if (mem_node) { | ||
| 2410 | /* First use the temporary node to store information for the board */ | ||
| 2411 | hold_mem_node->length = mem_node->base - hold_mem_node->base; | ||
| 2412 | |||
| 2413 | if (hold_mem_node->length) { | ||
| 2414 | hold_mem_node->next = func->mem_head; | ||
| 2415 | func->mem_head = hold_mem_node; | ||
| 2416 | |||
| 2417 | /* configure end address */ | ||
| 2418 | RES_CHECK(mem_node->base - 1, 16); | ||
| 2419 | temp_word = (u16)((mem_node->base - 1) >> 16); | ||
| 2420 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); | ||
| 2421 | |||
| 2422 | /* Return unused resources to the pool */ | ||
| 2423 | return_resource(&(resources->mem_head), mem_node); | ||
| 2424 | } else { | ||
| 2425 | /* it doesn't need any Mem */ | ||
| 2426 | temp_word = 0x0000; | ||
| 2427 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); | ||
| 2428 | |||
| 2429 | return_resource(&(resources->mem_head), mem_node); | ||
| 2430 | kfree(hold_mem_node); | ||
| 2431 | } | ||
| 2432 | } else { | ||
| 2433 | /* it used most of the range */ | ||
| 2434 | hold_mem_node->next = func->mem_head; | ||
| 2435 | func->mem_head = hold_mem_node; | ||
| 2436 | } | ||
| 2437 | } else if (hold_mem_node) { | ||
| 2438 | /* it used the whole range */ | ||
| 2439 | hold_mem_node->next = func->mem_head; | ||
| 2440 | func->mem_head = hold_mem_node; | ||
| 2441 | } | ||
| 2442 | |||
| 2443 | /* If we have prefetchable memory space available and there is some | ||
| 2444 | * left at the end, return the unused portion | ||
| 2445 | */ | ||
| 2446 | if (hold_p_mem_node && temp_resources.p_mem_head) { | ||
| 2447 | p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head), | ||
| 2448 | &hold_p_mem_node, 0x100000L); | ||
| 2449 | |||
| 2450 | /* Check if we were able to split something off */ | ||
| 2451 | if (p_mem_node) { | ||
| 2452 | hold_p_mem_node->base = p_mem_node->base + p_mem_node->length; | ||
| 2453 | |||
| 2454 | RES_CHECK(hold_p_mem_node->base, 16); | ||
| 2455 | temp_word = (u16)((hold_p_mem_node->base) >> 16); | ||
| 2456 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); | ||
| 2457 | |||
| 2458 | return_resource(&(resources->p_mem_head), p_mem_node); | ||
| 2459 | } | ||
| 2460 | |||
| 2461 | p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L); | ||
| 2462 | |||
| 2463 | /* Check if we were able to split something off */ | ||
| 2464 | if (p_mem_node) { | ||
| 2465 | /* First use the temporary node to store information for the board */ | ||
| 2466 | hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base; | ||
| 2467 | |||
| 2468 | /* If we used any, add it to the board's list */ | ||
| 2469 | if (hold_p_mem_node->length) { | ||
| 2470 | hold_p_mem_node->next = func->p_mem_head; | ||
| 2471 | func->p_mem_head = hold_p_mem_node; | ||
| 2472 | |||
| 2473 | RES_CHECK(p_mem_node->base - 1, 16); | ||
| 2474 | temp_word = (u16)((p_mem_node->base - 1) >> 16); | ||
| 2475 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); | ||
| 2476 | |||
| 2477 | return_resource(&(resources->p_mem_head), p_mem_node); | ||
| 2478 | } else { | ||
| 2479 | /* it doesn't need any PMem */ | ||
| 2480 | temp_word = 0x0000; | ||
| 2481 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); | ||
| 2482 | |||
| 2483 | return_resource(&(resources->p_mem_head), p_mem_node); | ||
| 2484 | kfree(hold_p_mem_node); | ||
| 2485 | } | ||
| 2486 | } else { | ||
| 2487 | /* it used the most of the range */ | ||
| 2488 | hold_p_mem_node->next = func->p_mem_head; | ||
| 2489 | func->p_mem_head = hold_p_mem_node; | ||
| 2490 | } | ||
| 2491 | } else if (hold_p_mem_node) { | ||
| 2492 | /* it used the whole range */ | ||
| 2493 | hold_p_mem_node->next = func->p_mem_head; | ||
| 2494 | func->p_mem_head = hold_p_mem_node; | ||
| 2495 | } | ||
| 2496 | |||
| 2497 | /* We should be configuring an IRQ and the bridge's base address | ||
| 2498 | * registers if it needs them. Although we have never seen such | ||
| 2499 | * a device | ||
| 2500 | */ | ||
| 2501 | |||
| 2502 | pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE); | ||
| 2503 | |||
| 2504 | dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); | ||
| 2505 | |||
| 2506 | return rc; | ||
| 2507 | } | 854 | } |
| 2508 | 855 | ||
| 2509 | /** | ||
| 2510 | * configure_new_function - Configures the PCI header information of one device | ||
| 2511 | * | ||
| 2512 | * @ctrl: pointer to controller structure | ||
| 2513 | * @func: pointer to function structure | ||
| 2514 | * @behind_bridge: 1 if this is a recursive call, 0 if not | ||
| 2515 | * @resources: pointer to set of resource lists | ||
| 2516 | * | ||
| 2517 | * Calls itself recursively for bridged devices. | ||
| 2518 | * Returns 0 if success | ||
| 2519 | * | ||
| 2520 | */ | ||
| 2521 | static int | ||
| 2522 | configure_new_function(struct controller *ctrl, struct pci_func *func, | ||
| 2523 | u8 behind_bridge, struct resource_lists *resources, | ||
| 2524 | u8 bridge_bus, u8 bridge_dev) | ||
| 2525 | { | ||
| 2526 | int cloop; | ||
| 2527 | u8 temp_byte; | ||
| 2528 | u8 class_code; | ||
| 2529 | u32 rc; | ||
| 2530 | u32 temp_register; | ||
| 2531 | u32 base; | ||
| 2532 | unsigned int devfn; | ||
| 2533 | struct pci_resource *mem_node; | ||
| 2534 | struct pci_resource *io_node; | ||
| 2535 | struct pci_bus lpci_bus, *pci_bus; | ||
| 2536 | |||
| 2537 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
| 2538 | pci_bus = &lpci_bus; | ||
| 2539 | pci_bus->number = func->bus; | ||
| 2540 | devfn = PCI_DEVFN(func->device, func->function); | ||
| 2541 | |||
| 2542 | /* Check for Bridge */ | ||
| 2543 | rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte); | ||
| 2544 | if (rc) | ||
| 2545 | return rc; | ||
| 2546 | dbg("%s: bus %x dev %x func %x temp_byte = %x\n", __FUNCTION__, | ||
| 2547 | func->bus, func->device, func->function, temp_byte); | ||
| 2548 | |||
| 2549 | if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ | ||
| 2550 | rc = configure_new_bridge(ctrl, func, behind_bridge, resources, | ||
| 2551 | pci_bus); | ||
| 2552 | |||
| 2553 | if (rc) | ||
| 2554 | return rc; | ||
| 2555 | } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) { | ||
| 2556 | /* Standard device */ | ||
| 2557 | u64 base64; | ||
| 2558 | rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code); | ||
| 2559 | |||
| 2560 | if (class_code == PCI_BASE_CLASS_DISPLAY) | ||
| 2561 | return DEVICE_TYPE_NOT_SUPPORTED; | ||
| 2562 | |||
| 2563 | /* Figure out IO and memory needs */ | ||
| 2564 | for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { | ||
| 2565 | temp_register = 0xFFFFFFFF; | ||
| 2566 | |||
| 2567 | rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); | ||
| 2568 | rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register); | ||
| 2569 | dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register, | ||
| 2570 | func->bus, func->device, func->function); | ||
| 2571 | |||
| 2572 | if (!temp_register) | ||
| 2573 | continue; | ||
| 2574 | |||
| 2575 | base64 = 0L; | ||
| 2576 | if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) { | ||
| 2577 | /* Map IO */ | ||
| 2578 | |||
| 2579 | /* set base = amount of IO space */ | ||
| 2580 | base = temp_register & 0xFFFFFFFC; | ||
| 2581 | base = ~base + 1; | ||
| 2582 | |||
| 2583 | dbg("NEED IO length(0x%x)\n", base); | ||
| 2584 | io_node = get_io_resource(&(resources->io_head),(ulong)base); | ||
| 2585 | |||
| 2586 | /* allocate the resource to the board */ | ||
| 2587 | if (io_node) { | ||
| 2588 | dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length); | ||
| 2589 | base = (u32)io_node->base; | ||
| 2590 | io_node->next = func->io_head; | ||
| 2591 | func->io_head = io_node; | ||
| 2592 | } else { | ||
| 2593 | err("Got NO IO resource(length=0x%x)\n", base); | ||
| 2594 | return -ENOMEM; | ||
| 2595 | } | ||
| 2596 | } else { /* map MEM */ | ||
| 2597 | int prefetchable = 1; | ||
| 2598 | struct pci_resource **res_node = &func->p_mem_head; | ||
| 2599 | char *res_type_str = "PMEM"; | ||
| 2600 | u32 temp_register2; | ||
| 2601 | |||
| 2602 | if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) { | ||
| 2603 | prefetchable = 0; | ||
| 2604 | res_node = &func->mem_head; | ||
| 2605 | res_type_str++; | ||
| 2606 | } | ||
| 2607 | |||
| 2608 | base = temp_register & 0xFFFFFFF0; | ||
| 2609 | base = ~base + 1; | ||
| 2610 | |||
| 2611 | switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { | ||
| 2612 | case PCI_BASE_ADDRESS_MEM_TYPE_32: | ||
| 2613 | dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base); | ||
| 2614 | |||
| 2615 | if (prefetchable && resources->p_mem_head) | ||
| 2616 | mem_node=get_resource(&(resources->p_mem_head), (ulong)base); | ||
| 2617 | else { | ||
| 2618 | if (prefetchable) | ||
| 2619 | dbg("using MEM for PMEM\n"); | ||
| 2620 | mem_node = get_resource(&(resources->mem_head), (ulong)base); | ||
| 2621 | } | ||
| 2622 | |||
| 2623 | /* allocate the resource to the board */ | ||
| 2624 | if (mem_node) { | ||
| 2625 | base = (u32)mem_node->base; | ||
| 2626 | mem_node->next = *res_node; | ||
| 2627 | *res_node = mem_node; | ||
| 2628 | dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base, | ||
| 2629 | mem_node->length); | ||
| 2630 | } else { | ||
| 2631 | err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base); | ||
| 2632 | return -ENOMEM; | ||
| 2633 | } | ||
| 2634 | break; | ||
| 2635 | case PCI_BASE_ADDRESS_MEM_TYPE_64: | ||
| 2636 | rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2); | ||
| 2637 | dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2, | ||
| 2638 | temp_register, base); | ||
| 2639 | |||
| 2640 | if (prefetchable && resources->p_mem_head) | ||
| 2641 | mem_node = get_resource(&(resources->p_mem_head), (ulong)base); | ||
| 2642 | else { | ||
| 2643 | if (prefetchable) | ||
| 2644 | dbg("using MEM for PMEM\n"); | ||
| 2645 | mem_node = get_resource(&(resources->mem_head), (ulong)base); | ||
| 2646 | } | ||
| 2647 | |||
| 2648 | /* allocate the resource to the board */ | ||
| 2649 | if (mem_node) { | ||
| 2650 | base64 = mem_node->base; | ||
| 2651 | mem_node->next = *res_node; | ||
| 2652 | *res_node = mem_node; | ||
| 2653 | dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32), | ||
| 2654 | (u32)base64, mem_node->length); | ||
| 2655 | } else { | ||
| 2656 | err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base); | ||
| 2657 | return -ENOMEM; | ||
| 2658 | } | ||
| 2659 | break; | ||
| 2660 | default: | ||
| 2661 | dbg("reserved BAR type=0x%x\n", temp_register); | ||
| 2662 | break; | ||
| 2663 | } | ||
| 2664 | |||
| 2665 | } | ||
| 2666 | |||
| 2667 | if (base64) { | ||
| 2668 | rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64); | ||
| 2669 | cloop += 4; | ||
| 2670 | base64 >>= 32; | ||
| 2671 | |||
| 2672 | if (base64) { | ||
| 2673 | dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64); | ||
| 2674 | base64 = 0x0L; | ||
| 2675 | } | ||
| 2676 | |||
| 2677 | rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64); | ||
| 2678 | } else { | ||
| 2679 | rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base); | ||
| 2680 | } | ||
| 2681 | } /* End of base register loop */ | ||
| 2682 | |||
| 2683 | /* disable ROM base Address */ | ||
| 2684 | rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00); | ||
| 2685 | |||
| 2686 | /* Set HP parameters (Cache Line Size, Latency Timer) */ | ||
| 2687 | rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); | ||
| 2688 | if (rc) | ||
| 2689 | return rc; | ||
| 2690 | |||
| 2691 | pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL); | ||
| 2692 | |||
| 2693 | dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, | ||
| 2694 | func->function); | ||
| 2695 | } /* End of Not-A-Bridge else */ | ||
| 2696 | else { | ||
| 2697 | /* It's some strange type of PCI adapter (Cardbus?) */ | ||
| 2698 | return DEVICE_TYPE_NOT_SUPPORTED; | ||
| 2699 | } | ||
| 2700 | |||
| 2701 | func->configured = 1; | ||
| 2702 | |||
| 2703 | return 0; | ||
| 2704 | } | ||
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 7a0e27f0e063..4a3cecca012c 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
| @@ -27,16 +27,10 @@ | |||
| 27 | * | 27 | * |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #include <linux/config.h> | ||
| 31 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
| 32 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 33 | #include <linux/types.h> | 32 | #include <linux/types.h> |
| 34 | #include <linux/slab.h> | ||
| 35 | #include <linux/vmalloc.h> | ||
| 36 | #include <linux/interrupt.h> | ||
| 37 | #include <linux/spinlock.h> | ||
| 38 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
| 39 | #include <asm/system.h> | ||
| 40 | #include "../pci.h" | 34 | #include "../pci.h" |
| 41 | #include "pciehp.h" | 35 | #include "pciehp.h" |
| 42 | 36 | ||
| @@ -217,23 +211,6 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct | |||
| 217 | #define MRL_STATE 0x0020 | 211 | #define MRL_STATE 0x0020 |
| 218 | #define PRSN_STATE 0x0040 | 212 | #define PRSN_STATE 0x0040 |
| 219 | 213 | ||
| 220 | struct php_ctlr_state_s { | ||
| 221 | struct php_ctlr_state_s *pnext; | ||
| 222 | struct pci_dev *pci_dev; | ||
| 223 | unsigned int irq; | ||
| 224 | unsigned long flags; /* spinlock's */ | ||
| 225 | u32 slot_device_offset; | ||
| 226 | u32 num_slots; | ||
| 227 | struct timer_list int_poll_timer; /* Added for poll event */ | ||
| 228 | php_intr_callback_t attention_button_callback; | ||
| 229 | php_intr_callback_t switch_change_callback; | ||
| 230 | php_intr_callback_t presence_change_callback; | ||
| 231 | php_intr_callback_t power_fault_callback; | ||
| 232 | void *callback_instance_id; | ||
| 233 | struct ctrl_reg *creg; /* Ptr to controller register space */ | ||
| 234 | }; | ||
| 235 | |||
| 236 | |||
| 237 | static spinlock_t hpc_event_lock; | 214 | static spinlock_t hpc_event_lock; |
| 238 | 215 | ||
| 239 | DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ | 216 | DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ |
| @@ -297,7 +274,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) | |||
| 297 | 274 | ||
| 298 | DBG_ENTER_ROUTINE | 275 | DBG_ENTER_ROUTINE |
| 299 | 276 | ||
| 300 | dbg("%s : Enter\n", __FUNCTION__); | ||
| 301 | if (!php_ctlr) { | 277 | if (!php_ctlr) { |
| 302 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 278 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
| 303 | return -1; | 279 | return -1; |
| @@ -308,7 +284,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) | |||
| 308 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 284 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
| 309 | return retval; | 285 | return retval; |
| 310 | } | 286 | } |
| 311 | dbg("%s : hp_register_read_word SLOT_STATUS %x\n", __FUNCTION__, slot_status); | ||
| 312 | 287 | ||
| 313 | if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { | 288 | if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { |
| 314 | /* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue | 289 | /* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue |
| @@ -316,14 +291,11 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) | |||
| 316 | dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__); | 291 | dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__); |
| 317 | } | 292 | } |
| 318 | 293 | ||
| 319 | dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd); | ||
| 320 | retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE); | 294 | retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE); |
| 321 | if (retval) { | 295 | if (retval) { |
| 322 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 296 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
| 323 | return retval; | 297 | return retval; |
| 324 | } | 298 | } |
| 325 | dbg("%s : hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd | CMD_CMPL_INTR_ENABLE); | ||
| 326 | dbg("%s : Exit\n", __FUNCTION__); | ||
| 327 | 299 | ||
| 328 | DBG_LEAVE_ROUTINE | 300 | DBG_LEAVE_ROUTINE |
| 329 | return retval; | 301 | return retval; |
| @@ -509,7 +481,6 @@ static int hpc_query_power_fault(struct slot * slot) | |||
| 509 | u16 slot_status; | 481 | u16 slot_status; |
| 510 | u8 pwr_fault; | 482 | u8 pwr_fault; |
| 511 | int retval = 0; | 483 | int retval = 0; |
| 512 | u8 status; | ||
| 513 | 484 | ||
| 514 | DBG_ENTER_ROUTINE | 485 | DBG_ENTER_ROUTINE |
| 515 | 486 | ||
| @@ -521,15 +492,13 @@ static int hpc_query_power_fault(struct slot * slot) | |||
| 521 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); | 492 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); |
| 522 | 493 | ||
| 523 | if (retval) { | 494 | if (retval) { |
| 524 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 495 | err("%s : Cannot check for power fault\n", __FUNCTION__); |
| 525 | return retval; | 496 | return retval; |
| 526 | } | 497 | } |
| 527 | pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); | 498 | pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); |
| 528 | status = (pwr_fault != 1) ? 1 : 0; | ||
| 529 | 499 | ||
| 530 | DBG_LEAVE_ROUTINE | 500 | DBG_LEAVE_ROUTINE |
| 531 | /* Note: Logic 0 => fault */ | 501 | return pwr_fault; |
| 532 | return status; | ||
| 533 | } | 502 | } |
| 534 | 503 | ||
| 535 | static int hpc_set_attention_status(struct slot *slot, u8 value) | 504 | static int hpc_set_attention_status(struct slot *slot, u8 value) |
| @@ -539,7 +508,8 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) | |||
| 539 | u16 slot_ctrl; | 508 | u16 slot_ctrl; |
| 540 | int rc = 0; | 509 | int rc = 0; |
| 541 | 510 | ||
| 542 | dbg("%s: \n", __FUNCTION__); | 511 | DBG_ENTER_ROUTINE |
| 512 | |||
| 543 | if (!php_ctlr) { | 513 | if (!php_ctlr) { |
| 544 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 514 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
| 545 | return -1; | 515 | return -1; |
| @@ -555,7 +525,6 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) | |||
| 555 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 525 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 556 | return rc; | 526 | return rc; |
| 557 | } | 527 | } |
| 558 | dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); | ||
| 559 | 528 | ||
| 560 | switch (value) { | 529 | switch (value) { |
| 561 | case 0 : /* turn off */ | 530 | case 0 : /* turn off */ |
| @@ -576,6 +545,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) | |||
| 576 | pcie_write_cmd(slot, slot_cmd); | 545 | pcie_write_cmd(slot, slot_cmd); |
| 577 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 546 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
| 578 | 547 | ||
| 548 | DBG_LEAVE_ROUTINE | ||
| 579 | return rc; | 549 | return rc; |
| 580 | } | 550 | } |
| 581 | 551 | ||
| @@ -587,7 +557,8 @@ static void hpc_set_green_led_on(struct slot *slot) | |||
| 587 | u16 slot_ctrl; | 557 | u16 slot_ctrl; |
| 588 | int rc = 0; | 558 | int rc = 0; |
| 589 | 559 | ||
| 590 | dbg("%s: \n", __FUNCTION__); | 560 | DBG_ENTER_ROUTINE |
| 561 | |||
| 591 | if (!php_ctlr) { | 562 | if (!php_ctlr) { |
| 592 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 563 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
| 593 | return ; | 564 | return ; |
| @@ -604,7 +575,6 @@ static void hpc_set_green_led_on(struct slot *slot) | |||
| 604 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 575 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 605 | return; | 576 | return; |
| 606 | } | 577 | } |
| 607 | dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); | ||
| 608 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100; | 578 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100; |
| 609 | if (!pciehp_poll_mode) | 579 | if (!pciehp_poll_mode) |
| 610 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | 580 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
| @@ -612,6 +582,7 @@ static void hpc_set_green_led_on(struct slot *slot) | |||
| 612 | pcie_write_cmd(slot, slot_cmd); | 582 | pcie_write_cmd(slot, slot_cmd); |
| 613 | 583 | ||
| 614 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 584 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
| 585 | DBG_LEAVE_ROUTINE | ||
| 615 | return; | 586 | return; |
| 616 | } | 587 | } |
| 617 | 588 | ||
| @@ -622,7 +593,8 @@ static void hpc_set_green_led_off(struct slot *slot) | |||
| 622 | u16 slot_ctrl; | 593 | u16 slot_ctrl; |
| 623 | int rc = 0; | 594 | int rc = 0; |
| 624 | 595 | ||
| 625 | dbg("%s: \n", __FUNCTION__); | 596 | DBG_ENTER_ROUTINE |
| 597 | |||
| 626 | if (!php_ctlr) { | 598 | if (!php_ctlr) { |
| 627 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 599 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
| 628 | return ; | 600 | return ; |
| @@ -639,7 +611,6 @@ static void hpc_set_green_led_off(struct slot *slot) | |||
| 639 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 611 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 640 | return; | 612 | return; |
| 641 | } | 613 | } |
| 642 | dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); | ||
| 643 | 614 | ||
| 644 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300; | 615 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300; |
| 645 | 616 | ||
| @@ -648,6 +619,7 @@ static void hpc_set_green_led_off(struct slot *slot) | |||
| 648 | pcie_write_cmd(slot, slot_cmd); | 619 | pcie_write_cmd(slot, slot_cmd); |
| 649 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 620 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
| 650 | 621 | ||
| 622 | DBG_LEAVE_ROUTINE | ||
| 651 | return; | 623 | return; |
| 652 | } | 624 | } |
| 653 | 625 | ||
| @@ -658,7 +630,8 @@ static void hpc_set_green_led_blink(struct slot *slot) | |||
| 658 | u16 slot_ctrl; | 630 | u16 slot_ctrl; |
| 659 | int rc = 0; | 631 | int rc = 0; |
| 660 | 632 | ||
| 661 | dbg("%s: \n", __FUNCTION__); | 633 | DBG_ENTER_ROUTINE |
| 634 | |||
| 662 | if (!php_ctlr) { | 635 | if (!php_ctlr) { |
| 663 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 636 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
| 664 | return ; | 637 | return ; |
| @@ -675,7 +648,6 @@ static void hpc_set_green_led_blink(struct slot *slot) | |||
| 675 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 648 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 676 | return; | 649 | return; |
| 677 | } | 650 | } |
| 678 | dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); | ||
| 679 | 651 | ||
| 680 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200; | 652 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200; |
| 681 | 653 | ||
| @@ -684,6 +656,7 @@ static void hpc_set_green_led_blink(struct slot *slot) | |||
| 684 | pcie_write_cmd(slot, slot_cmd); | 656 | pcie_write_cmd(slot, slot_cmd); |
| 685 | 657 | ||
| 686 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 658 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
| 659 | DBG_LEAVE_ROUTINE | ||
| 687 | return; | 660 | return; |
| 688 | } | 661 | } |
| 689 | 662 | ||
| @@ -780,7 +753,6 @@ static int hpc_power_on_slot(struct slot * slot) | |||
| 780 | int retval = 0; | 753 | int retval = 0; |
| 781 | 754 | ||
| 782 | DBG_ENTER_ROUTINE | 755 | DBG_ENTER_ROUTINE |
| 783 | dbg("%s: \n", __FUNCTION__); | ||
| 784 | 756 | ||
| 785 | if (!php_ctlr) { | 757 | if (!php_ctlr) { |
| 786 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 758 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
| @@ -799,8 +771,6 @@ static int hpc_power_on_slot(struct slot * slot) | |||
| 799 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 771 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 800 | return retval; | 772 | return retval; |
| 801 | } | 773 | } |
| 802 | dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), | ||
| 803 | slot_ctrl); | ||
| 804 | 774 | ||
| 805 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; | 775 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; |
| 806 | 776 | ||
| @@ -829,7 +799,6 @@ static int hpc_power_off_slot(struct slot * slot) | |||
| 829 | int retval = 0; | 799 | int retval = 0; |
| 830 | 800 | ||
| 831 | DBG_ENTER_ROUTINE | 801 | DBG_ENTER_ROUTINE |
| 832 | dbg("%s: \n", __FUNCTION__); | ||
| 833 | 802 | ||
| 834 | if (!php_ctlr) { | 803 | if (!php_ctlr) { |
| 835 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 804 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); |
| @@ -848,8 +817,6 @@ static int hpc_power_off_slot(struct slot * slot) | |||
| 848 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 817 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 849 | return retval; | 818 | return retval; |
| 850 | } | 819 | } |
| 851 | dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), | ||
| 852 | slot_ctrl); | ||
| 853 | 820 | ||
| 854 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; | 821 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; |
| 855 | 822 | ||
| @@ -924,7 +891,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
| 924 | return IRQ_NONE; | 891 | return IRQ_NONE; |
| 925 | } | 892 | } |
| 926 | 893 | ||
| 927 | dbg("%s: Set Mask Hot-plug Interrupt Enable\n", __FUNCTION__); | ||
| 928 | dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | 894 | dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); |
| 929 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; | 895 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; |
| 930 | 896 | ||
| @@ -933,7 +899,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
| 933 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 899 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
| 934 | return IRQ_NONE; | 900 | return IRQ_NONE; |
| 935 | } | 901 | } |
| 936 | dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | ||
| 937 | 902 | ||
| 938 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 903 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
| 939 | if (rc) { | 904 | if (rc) { |
| @@ -949,14 +914,12 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
| 949 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 914 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); |
| 950 | return IRQ_NONE; | 915 | return IRQ_NONE; |
| 951 | } | 916 | } |
| 952 | dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); | ||
| 953 | } | 917 | } |
| 954 | 918 | ||
| 955 | if (intr_loc & CMD_COMPLETED) { | 919 | if (intr_loc & CMD_COMPLETED) { |
| 956 | /* | 920 | /* |
| 957 | * Command Complete Interrupt Pending | 921 | * Command Complete Interrupt Pending |
| 958 | */ | 922 | */ |
| 959 | dbg("%s: In Command Complete Interrupt Pending\n", __FUNCTION__); | ||
| 960 | wake_up_interruptible(&ctrl->queue); | 923 | wake_up_interruptible(&ctrl->queue); |
| 961 | } | 924 | } |
| 962 | 925 | ||
| @@ -989,7 +952,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
| 989 | } | 952 | } |
| 990 | 953 | ||
| 991 | dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__); | 954 | dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__); |
| 992 | dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | ||
| 993 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; | 955 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; |
| 994 | 956 | ||
| 995 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); | 957 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); |
| @@ -997,14 +959,12 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
| 997 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 959 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
| 998 | return IRQ_NONE; | 960 | return IRQ_NONE; |
| 999 | } | 961 | } |
| 1000 | dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | ||
| 1001 | 962 | ||
| 1002 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 963 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
| 1003 | if (rc) { | 964 | if (rc) { |
| 1004 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 965 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
| 1005 | return IRQ_NONE; | 966 | return IRQ_NONE; |
| 1006 | } | 967 | } |
| 1007 | dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); | ||
| 1008 | 968 | ||
| 1009 | /* Clear command complete interrupt caused by this write */ | 969 | /* Clear command complete interrupt caused by this write */ |
| 1010 | temp_word = 0x1F; | 970 | temp_word = 0x1F; |
| @@ -1248,12 +1208,7 @@ static struct hpc_ops pciehp_hpc_ops = { | |||
| 1248 | .check_lnk_status = hpc_check_lnk_status, | 1208 | .check_lnk_status = hpc_check_lnk_status, |
| 1249 | }; | 1209 | }; |
| 1250 | 1210 | ||
| 1251 | int pcie_init(struct controller * ctrl, | 1211 | int pcie_init(struct controller * ctrl, struct pcie_device *dev) |
| 1252 | struct pcie_device *dev, | ||
| 1253 | php_intr_callback_t attention_button_callback, | ||
| 1254 | php_intr_callback_t switch_change_callback, | ||
| 1255 | php_intr_callback_t presence_change_callback, | ||
| 1256 | php_intr_callback_t power_fault_callback) | ||
| 1257 | { | 1212 | { |
| 1258 | struct php_ctlr_state_s *php_ctlr, *p; | 1213 | struct php_ctlr_state_s *php_ctlr, *p; |
| 1259 | void *instance_id = ctrl; | 1214 | void *instance_id = ctrl; |
| @@ -1282,8 +1237,8 @@ int pcie_init(struct controller * ctrl, | |||
| 1282 | pdev = dev->port; | 1237 | pdev = dev->port; |
| 1283 | php_ctlr->pci_dev = pdev; /* save pci_dev in context */ | 1238 | php_ctlr->pci_dev = pdev; /* save pci_dev in context */ |
| 1284 | 1239 | ||
| 1285 | dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__, | 1240 | dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n", |
| 1286 | pdev->vendor, pdev->device); | 1241 | __FUNCTION__, pdev->vendor, pdev->device); |
| 1287 | 1242 | ||
| 1288 | saved_cap_base = pcie_cap_base; | 1243 | saved_cap_base = pcie_cap_base; |
| 1289 | 1244 | ||
| @@ -1340,8 +1295,6 @@ int pcie_init(struct controller * ctrl, | |||
| 1340 | first = 0; | 1295 | first = 0; |
| 1341 | } | 1296 | } |
| 1342 | 1297 | ||
| 1343 | dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, | ||
| 1344 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); | ||
| 1345 | for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) | 1298 | for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) |
| 1346 | if (pci_resource_len(pdev, rc) > 0) | 1299 | if (pci_resource_len(pdev, rc) > 0) |
| 1347 | dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc, | 1300 | dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc, |
| @@ -1359,13 +1312,12 @@ int pcie_init(struct controller * ctrl, | |||
| 1359 | 1312 | ||
| 1360 | /* find the IRQ */ | 1313 | /* find the IRQ */ |
| 1361 | php_ctlr->irq = dev->irq; | 1314 | php_ctlr->irq = dev->irq; |
| 1362 | dbg("HPC interrupt = %d\n", php_ctlr->irq); | ||
| 1363 | 1315 | ||
| 1364 | /* Save interrupt callback info */ | 1316 | /* Save interrupt callback info */ |
| 1365 | php_ctlr->attention_button_callback = attention_button_callback; | 1317 | php_ctlr->attention_button_callback = pciehp_handle_attention_button; |
| 1366 | php_ctlr->switch_change_callback = switch_change_callback; | 1318 | php_ctlr->switch_change_callback = pciehp_handle_switch_change; |
| 1367 | php_ctlr->presence_change_callback = presence_change_callback; | 1319 | php_ctlr->presence_change_callback = pciehp_handle_presence_change; |
| 1368 | php_ctlr->power_fault_callback = power_fault_callback; | 1320 | php_ctlr->power_fault_callback = pciehp_handle_power_fault; |
| 1369 | php_ctlr->callback_instance_id = instance_id; | 1321 | php_ctlr->callback_instance_id = instance_id; |
| 1370 | 1322 | ||
| 1371 | /* return PCI Controller Info */ | 1323 | /* return PCI Controller Info */ |
| @@ -1387,15 +1339,12 @@ int pcie_init(struct controller * ctrl, | |||
| 1387 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 1339 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
| 1388 | goto abort_free_ctlr; | 1340 | goto abort_free_ctlr; |
| 1389 | } | 1341 | } |
| 1390 | dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word); | ||
| 1391 | 1342 | ||
| 1392 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 1343 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
| 1393 | if (rc) { | 1344 | if (rc) { |
| 1394 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 1345 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
| 1395 | goto abort_free_ctlr; | 1346 | goto abort_free_ctlr; |
| 1396 | } | 1347 | } |
| 1397 | dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base) | ||
| 1398 | , slot_status); | ||
| 1399 | 1348 | ||
| 1400 | temp_word = 0x1F; /* Clear all events */ | 1349 | temp_word = 0x1F; /* Clear all events */ |
| 1401 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); | 1350 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); |
| @@ -1403,7 +1352,6 @@ int pcie_init(struct controller * ctrl, | |||
| 1403 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 1352 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); |
| 1404 | goto abort_free_ctlr; | 1353 | goto abort_free_ctlr; |
| 1405 | } | 1354 | } |
| 1406 | dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word); | ||
| 1407 | 1355 | ||
| 1408 | if (pciehp_poll_mode) {/* Install interrupt polling code */ | 1356 | if (pciehp_poll_mode) {/* Install interrupt polling code */ |
| 1409 | /* Install and start the interrupt polling timer */ | 1357 | /* Install and start the interrupt polling timer */ |
| @@ -1419,13 +1367,14 @@ int pcie_init(struct controller * ctrl, | |||
| 1419 | } | 1367 | } |
| 1420 | } | 1368 | } |
| 1421 | 1369 | ||
| 1370 | dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, | ||
| 1371 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); | ||
| 1372 | |||
| 1422 | rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); | 1373 | rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); |
| 1423 | if (rc) { | 1374 | if (rc) { |
| 1424 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 1375 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 1425 | goto abort_free_ctlr; | 1376 | goto abort_free_ctlr; |
| 1426 | } | 1377 | } |
| 1427 | dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word); | ||
| 1428 | dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap); | ||
| 1429 | 1378 | ||
| 1430 | intr_enable = intr_enable | PRSN_DETECT_ENABLE; | 1379 | intr_enable = intr_enable | PRSN_DETECT_ENABLE; |
| 1431 | 1380 | ||
| @@ -1445,7 +1394,6 @@ int pcie_init(struct controller * ctrl, | |||
| 1445 | } else { | 1394 | } else { |
| 1446 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; | 1395 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; |
| 1447 | } | 1396 | } |
| 1448 | dbg("%s: temp_word %x\n", __FUNCTION__, temp_word); | ||
| 1449 | 1397 | ||
| 1450 | /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */ | 1398 | /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */ |
| 1451 | rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); | 1399 | rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); |
| @@ -1453,14 +1401,11 @@ int pcie_init(struct controller * ctrl, | |||
| 1453 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 1401 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
| 1454 | goto abort_free_ctlr; | 1402 | goto abort_free_ctlr; |
| 1455 | } | 1403 | } |
| 1456 | dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word); | ||
| 1457 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 1404 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
| 1458 | if (rc) { | 1405 | if (rc) { |
| 1459 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 1406 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
| 1460 | goto abort_free_ctlr; | 1407 | goto abort_free_ctlr; |
| 1461 | } | 1408 | } |
| 1462 | dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, | ||
| 1463 | SLOT_STATUS(ctrl->cap_base), slot_status); | ||
| 1464 | 1409 | ||
| 1465 | temp_word = 0x1F; /* Clear all events */ | 1410 | temp_word = 0x1F; /* Clear all events */ |
| 1466 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); | 1411 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); |
| @@ -1468,8 +1413,16 @@ int pcie_init(struct controller * ctrl, | |||
| 1468 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 1413 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); |
| 1469 | goto abort_free_ctlr; | 1414 | goto abort_free_ctlr; |
| 1470 | } | 1415 | } |
| 1471 | dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word); | ||
| 1472 | 1416 | ||
| 1417 | if (pciehp_force) { | ||
| 1418 | dbg("Bypassing BIOS check for pciehp use on %s\n", | ||
| 1419 | pci_name(ctrl->pci_dev)); | ||
| 1420 | } else { | ||
| 1421 | rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev); | ||
| 1422 | if (rc) | ||
| 1423 | goto abort_free_ctlr; | ||
| 1424 | } | ||
| 1425 | |||
| 1473 | /* Add this HPC instance into the HPC list */ | 1426 | /* Add this HPC instance into the HPC list */ |
| 1474 | spin_lock(&list_lock); | 1427 | spin_lock(&list_lock); |
| 1475 | if (php_ctlr_list_head == 0) { | 1428 | if (php_ctlr_list_head == 0) { |
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index ff17d8e07e94..647673a7d224 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
| @@ -27,801 +27,111 @@ | |||
| 27 | * | 27 | * |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #include <linux/config.h> | ||
| 31 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
| 33 | #include <linux/types.h> | 32 | #include <linux/types.h> |
| 34 | #include <linux/slab.h> | ||
| 35 | #include <linux/workqueue.h> | ||
| 36 | #include <linux/proc_fs.h> | ||
| 37 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
| 38 | #include "../pci.h" | 34 | #include "../pci.h" |
| 39 | #include "pciehp.h" | 35 | #include "pciehp.h" |
| 40 | #ifndef CONFIG_IA64 | ||
| 41 | #include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */ | ||
| 42 | #endif | ||
| 43 | 36 | ||
| 44 | 37 | ||
| 45 | int pciehp_configure_device (struct controller* ctrl, struct pci_func* func) | 38 | int pciehp_configure_device(struct slot *p_slot) |
| 46 | { | 39 | { |
| 47 | unsigned char bus; | 40 | struct pci_dev *dev; |
| 48 | struct pci_bus *child; | 41 | struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; |
| 49 | int num; | 42 | int num, fn; |
| 50 | 43 | ||
| 51 | if (func->pci_dev == NULL) | 44 | dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0)); |
| 52 | func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); | 45 | if (dev) { |
| 53 | 46 | err("Device %s already exists at %x:%x, cannot hot-add\n", | |
| 54 | /* Still NULL ? Well then scan for it ! */ | 47 | pci_name(dev), p_slot->bus, p_slot->device); |
| 55 | if (func->pci_dev == NULL) { | 48 | return -EINVAL; |
| 56 | dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__); | ||
| 57 | |||
| 58 | num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function)); | ||
| 59 | |||
| 60 | if (num) | ||
| 61 | pci_bus_add_devices(ctrl->pci_dev->subordinate); | ||
| 62 | |||
| 63 | func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); | ||
| 64 | if (func->pci_dev == NULL) { | ||
| 65 | dbg("ERROR: pci_dev still null\n"); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | } | 49 | } |
| 69 | 50 | ||
| 70 | if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | 51 | num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0)); |
| 71 | pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); | 52 | if (num == 0) { |
| 72 | child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); | 53 | err("No new device found\n"); |
| 73 | pci_do_scan_bus(child); | 54 | return -ENODEV; |
| 55 | } | ||
| 74 | 56 | ||
| 57 | for (fn = 0; fn < 8; fn++) { | ||
| 58 | if (!(dev = pci_find_slot(p_slot->bus, | ||
| 59 | PCI_DEVFN(p_slot->device, fn)))) | ||
| 60 | continue; | ||
| 61 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
| 62 | err("Cannot hot-add display device %s\n", | ||
| 63 | pci_name(dev)); | ||
| 64 | continue; | ||
| 65 | } | ||
| 66 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || | ||
| 67 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { | ||
| 68 | /* Find an unused bus number for the new bridge */ | ||
| 69 | struct pci_bus *child; | ||
| 70 | unsigned char busnr, start = parent->secondary; | ||
| 71 | unsigned char end = parent->subordinate; | ||
| 72 | for (busnr = start; busnr <= end; busnr++) { | ||
| 73 | if (!pci_find_bus(pci_domain_nr(parent), | ||
| 74 | busnr)) | ||
| 75 | break; | ||
| 76 | } | ||
| 77 | if (busnr >= end) { | ||
| 78 | err("No free bus for hot-added bridge\n"); | ||
| 79 | continue; | ||
| 80 | } | ||
| 81 | child = pci_add_new_bus(parent, dev, busnr); | ||
| 82 | if (!child) { | ||
| 83 | err("Cannot add new bus for %s\n", | ||
| 84 | pci_name(dev)); | ||
| 85 | continue; | ||
| 86 | } | ||
| 87 | child->subordinate = pci_do_scan_bus(child); | ||
| 88 | pci_bus_size_bridges(child); | ||
| 89 | } | ||
| 90 | /* TBD: program firmware provided _HPP values */ | ||
| 91 | /* program_fw_provided_values(dev); */ | ||
| 75 | } | 92 | } |
| 76 | 93 | ||
| 94 | pci_bus_assign_resources(parent); | ||
| 95 | pci_bus_add_devices(parent); | ||
| 96 | pci_enable_bridges(parent); | ||
| 77 | return 0; | 97 | return 0; |
| 78 | } | 98 | } |
| 79 | 99 | ||
| 80 | 100 | int pciehp_unconfigure_device(struct slot *p_slot) | |
| 81 | int pciehp_unconfigure_device(struct pci_func* func) | ||
| 82 | { | 101 | { |
| 83 | int rc = 0; | 102 | int rc = 0; |
| 84 | int j; | 103 | int j; |
| 85 | struct pci_bus *pbus; | 104 | u8 bctl = 0; |
| 86 | 105 | ||
| 87 | dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, | 106 | dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, |
| 88 | func->device, func->function); | 107 | p_slot->device); |
| 89 | pbus = func->pci_dev->bus; | ||
| 90 | 108 | ||
| 91 | for (j=0; j<8 ; j++) { | 109 | for (j=0; j<8 ; j++) { |
| 92 | struct pci_dev* temp = pci_find_slot(func->bus, | 110 | struct pci_dev* temp = pci_find_slot(p_slot->bus, |
| 93 | (func->device << 3) | j); | 111 | (p_slot->device << 3) | j); |
| 94 | if (temp) { | 112 | if (!temp) |
| 95 | pci_remove_bus_device(temp); | 113 | continue; |
| 114 | if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
| 115 | err("Cannot remove display device %s\n", | ||
| 116 | pci_name(temp)); | ||
| 117 | continue; | ||
| 96 | } | 118 | } |
| 119 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | ||
| 120 | pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); | ||
| 121 | if (bctl & PCI_BRIDGE_CTL_VGA) { | ||
| 122 | err("Cannot remove display device %s\n", | ||
| 123 | pci_name(temp)); | ||
| 124 | continue; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | pci_remove_bus_device(temp); | ||
| 97 | } | 128 | } |
| 98 | /* | 129 | /* |
| 99 | * Some PCI Express root ports require fixup after hot-plug operation. | 130 | * Some PCI Express root ports require fixup after hot-plug operation. |
| 100 | */ | 131 | */ |
| 101 | if (pcie_mch_quirk) | 132 | if (pcie_mch_quirk) |
| 102 | pci_fixup_device(pci_fixup_final, pbus->self); | 133 | pci_fixup_device(pci_fixup_final, p_slot->ctrl->pci_dev); |
| 103 | 134 | ||
| 104 | return rc; | 135 | return rc; |
| 105 | } | 136 | } |
| 106 | 137 | ||
| 107 | /* | ||
| 108 | * pciehp_set_irq | ||
| 109 | * | ||
| 110 | * @bus_num: bus number of PCI device | ||
| 111 | * @dev_num: device number of PCI device | ||
| 112 | * @slot: pointer to u8 where slot number will be returned | ||
| 113 | */ | ||
| 114 | int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num) | ||
| 115 | { | ||
| 116 | #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_IO_APIC) | ||
| 117 | int rc; | ||
| 118 | u16 temp_word; | ||
| 119 | struct pci_dev fakedev; | ||
| 120 | struct pci_bus fakebus; | ||
| 121 | |||
| 122 | fakedev.devfn = dev_num << 3; | ||
| 123 | fakedev.bus = &fakebus; | ||
| 124 | fakebus.number = bus_num; | ||
| 125 | dbg("%s: dev %d, bus %d, pin %d, num %d\n", | ||
| 126 | __FUNCTION__, dev_num, bus_num, int_pin, irq_num); | ||
| 127 | rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num); | ||
| 128 | dbg("%s: rc %d\n", __FUNCTION__, rc); | ||
| 129 | if (!rc) | ||
| 130 | return !rc; | ||
| 131 | |||
| 132 | /* set the Edge Level Control Register (ELCR) */ | ||
| 133 | temp_word = inb(0x4d0); | ||
| 134 | temp_word |= inb(0x4d1) << 8; | ||
| 135 | |||
| 136 | temp_word |= 0x01 << irq_num; | ||
| 137 | |||
| 138 | /* This should only be for x86 as it sets the Edge Level Control Register */ | ||
| 139 | outb((u8) (temp_word & 0xFF), 0x4d0); | ||
| 140 | outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1); | ||
| 141 | #endif | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* More PCI configuration routines; this time centered around hotplug controller */ | ||
| 146 | |||
| 147 | |||
| 148 | /* | ||
| 149 | * pciehp_save_config | ||
| 150 | * | ||
| 151 | * Reads configuration for all slots in a PCI bus and saves info. | ||
| 152 | * | ||
| 153 | * Note: For non-hot plug busses, the slot # saved is the device # | ||
| 154 | * | ||
| 155 | * returns 0 if success | ||
| 156 | */ | ||
| 157 | int pciehp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num) | ||
| 158 | { | ||
| 159 | int rc; | ||
| 160 | u8 class_code; | ||
| 161 | u8 header_type; | ||
| 162 | u32 ID; | ||
| 163 | u8 secondary_bus; | ||
| 164 | struct pci_func *new_slot; | ||
| 165 | int sub_bus; | ||
| 166 | int max_functions; | ||
| 167 | int function; | ||
| 168 | u8 DevError; | ||
| 169 | int device = 0; | ||
| 170 | int cloop = 0; | ||
| 171 | int stop_it; | ||
| 172 | int index; | ||
| 173 | int is_hot_plug = num_ctlr_slots || first_device_num; | ||
| 174 | struct pci_bus lpci_bus, *pci_bus; | ||
| 175 | int FirstSupported, LastSupported; | ||
| 176 | |||
| 177 | dbg("%s: Enter\n", __FUNCTION__); | ||
| 178 | |||
| 179 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
| 180 | pci_bus = &lpci_bus; | ||
| 181 | |||
| 182 | dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, | ||
| 183 | num_ctlr_slots, first_device_num); | ||
| 184 | |||
| 185 | /* Decide which slots are supported */ | ||
| 186 | if (is_hot_plug) { | ||
| 187 | /********************************* | ||
| 188 | * is_hot_plug is the slot mask | ||
| 189 | *********************************/ | ||
| 190 | FirstSupported = first_device_num; | ||
| 191 | LastSupported = FirstSupported + num_ctlr_slots - 1; | ||
| 192 | } else { | ||
| 193 | FirstSupported = 0; | ||
| 194 | LastSupported = 0x1F; | ||
| 195 | } | ||
| 196 | |||
| 197 | dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, | ||
| 198 | LastSupported); | ||
| 199 | |||
| 200 | /* Save PCI configuration space for all devices in supported slots */ | ||
| 201 | dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number); | ||
| 202 | pci_bus->number = busnumber; | ||
| 203 | dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device); | ||
| 204 | for (device = FirstSupported; device <= LastSupported; device++) { | ||
| 205 | ID = 0xFFFFFFFF; | ||
| 206 | rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), | ||
| 207 | PCI_VENDOR_ID, &ID); | ||
| 208 | |||
| 209 | if (ID != 0xFFFFFFFF) { /* device in slot */ | ||
| 210 | dbg("%s: ID = %x\n", __FUNCTION__, ID); | ||
| 211 | rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), | ||
| 212 | 0x0B, &class_code); | ||
| 213 | if (rc) | ||
| 214 | return rc; | ||
| 215 | |||
| 216 | rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), | ||
| 217 | PCI_HEADER_TYPE, &header_type); | ||
| 218 | if (rc) | ||
| 219 | return rc; | ||
| 220 | |||
| 221 | dbg("class_code = %x, header_type = %x\n", class_code, header_type); | ||
| 222 | |||
| 223 | /* If multi-function device, set max_functions to 8 */ | ||
| 224 | if (header_type & 0x80) | ||
| 225 | max_functions = 8; | ||
| 226 | else | ||
| 227 | max_functions = 1; | ||
| 228 | |||
| 229 | function = 0; | ||
| 230 | |||
| 231 | do { | ||
| 232 | DevError = 0; | ||
| 233 | dbg("%s: In do loop\n", __FUNCTION__); | ||
| 234 | |||
| 235 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */ | ||
| 236 | /* Recurse the subordinate bus | ||
| 237 | * get the subordinate bus number | ||
| 238 | */ | ||
| 239 | rc = pci_bus_read_config_byte(pci_bus, | ||
| 240 | PCI_DEVFN(device, function), | ||
| 241 | PCI_SECONDARY_BUS, &secondary_bus); | ||
| 242 | if (rc) { | ||
| 243 | return rc; | ||
| 244 | } else { | ||
| 245 | sub_bus = (int) secondary_bus; | ||
| 246 | |||
| 247 | /* Save secondary bus cfg spc with this recursive call. */ | ||
| 248 | rc = pciehp_save_config(ctrl, sub_bus, 0, 0); | ||
| 249 | if (rc) | ||
| 250 | return rc; | ||
| 251 | } | ||
| 252 | } | ||
| 253 | |||
| 254 | index = 0; | ||
| 255 | new_slot = pciehp_slot_find(busnumber, device, index++); | ||
| 256 | |||
| 257 | dbg("%s: new_slot = %p bus %x dev %x fun %x\n", | ||
| 258 | __FUNCTION__, new_slot, busnumber, device, index-1); | ||
| 259 | |||
| 260 | while (new_slot && (new_slot->function != (u8) function)) { | ||
| 261 | new_slot = pciehp_slot_find(busnumber, device, index++); | ||
| 262 | dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n", | ||
| 263 | __FUNCTION__, new_slot, busnumber, device, index-1); | ||
| 264 | } | ||
| 265 | if (!new_slot) { | ||
| 266 | /* Setup slot structure. */ | ||
| 267 | new_slot = pciehp_slot_create(busnumber); | ||
| 268 | dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n", | ||
| 269 | __FUNCTION__, new_slot, busnumber, device, function); | ||
| 270 | |||
| 271 | if (new_slot == NULL) | ||
| 272 | return(1); | ||
| 273 | } | ||
| 274 | |||
| 275 | new_slot->bus = (u8) busnumber; | ||
| 276 | new_slot->device = (u8) device; | ||
| 277 | new_slot->function = (u8) function; | ||
| 278 | new_slot->is_a_board = 1; | ||
| 279 | new_slot->switch_save = 0x10; | ||
| 280 | /* In case of unsupported board */ | ||
| 281 | new_slot->status = DevError; | ||
| 282 | new_slot->pci_dev = pci_find_slot(new_slot->bus, | ||
| 283 | (new_slot->device << 3) | new_slot->function); | ||
| 284 | dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev); | ||
| 285 | |||
| 286 | for (cloop = 0; cloop < 0x20; cloop++) { | ||
| 287 | rc = pci_bus_read_config_dword(pci_bus, | ||
| 288 | PCI_DEVFN(device, function), | ||
| 289 | cloop << 2, | ||
| 290 | (u32 *) &(new_slot->config_space [cloop])); | ||
| 291 | /* dbg("new_slot->config_space[%x] = %x\n", | ||
| 292 | cloop, new_slot->config_space[cloop]); */ | ||
| 293 | if (rc) | ||
| 294 | return rc; | ||
| 295 | } | ||
| 296 | |||
| 297 | function++; | ||
| 298 | |||
| 299 | stop_it = 0; | ||
| 300 | |||
| 301 | /* this loop skips to the next present function | ||
| 302 | * reading in Class Code and Header type. | ||
| 303 | */ | ||
| 304 | |||
| 305 | while ((function < max_functions)&&(!stop_it)) { | ||
| 306 | dbg("%s: In while loop \n", __FUNCTION__); | ||
| 307 | rc = pci_bus_read_config_dword(pci_bus, | ||
| 308 | PCI_DEVFN(device, function), | ||
| 309 | PCI_VENDOR_ID, &ID); | ||
| 310 | |||
| 311 | if (ID == 0xFFFFFFFF) { /* nothing there. */ | ||
| 312 | function++; | ||
| 313 | dbg("Nothing there\n"); | ||
| 314 | } else { /* Something there */ | ||
| 315 | rc = pci_bus_read_config_byte(pci_bus, | ||
| 316 | PCI_DEVFN(device, function), | ||
| 317 | 0x0B, &class_code); | ||
| 318 | if (rc) | ||
| 319 | return rc; | ||
| 320 | |||
| 321 | rc = pci_bus_read_config_byte(pci_bus, | ||
| 322 | PCI_DEVFN(device, function), | ||
| 323 | PCI_HEADER_TYPE, &header_type); | ||
| 324 | if (rc) | ||
| 325 | return rc; | ||
| 326 | |||
| 327 | dbg("class_code = %x, header_type = %x\n", class_code, header_type); | ||
| 328 | stop_it++; | ||
| 329 | } | ||
| 330 | } | ||
| 331 | |||
| 332 | } while (function < max_functions); | ||
| 333 | /* End of IF (device in slot?) */ | ||
| 334 | } else if (is_hot_plug) { | ||
| 335 | /* Setup slot structure with entry for empty slot */ | ||
| 336 | new_slot = pciehp_slot_create(busnumber); | ||
| 337 | |||
| 338 | if (new_slot == NULL) { | ||
| 339 | return(1); | ||
| 340 | } | ||
| 341 | dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot, | ||
| 342 | new_slot->bus, new_slot->device, new_slot->function); | ||
| 343 | |||
| 344 | new_slot->bus = (u8) busnumber; | ||
| 345 | new_slot->device = (u8) device; | ||
| 346 | new_slot->function = 0; | ||
| 347 | new_slot->is_a_board = 0; | ||
| 348 | new_slot->presence_save = 0; | ||
| 349 | new_slot->switch_save = 0; | ||
| 350 | } | ||
| 351 | } /* End of FOR loop */ | ||
| 352 | |||
| 353 | dbg("%s: Exit\n", __FUNCTION__); | ||
| 354 | return(0); | ||
| 355 | } | ||
| 356 | |||
| 357 | |||
| 358 | /* | ||
| 359 | * pciehp_save_slot_config | ||
| 360 | * | ||
| 361 | * Saves configuration info for all PCI devices in a given slot | ||
| 362 | * including subordinate busses. | ||
| 363 | * | ||
| 364 | * returns 0 if success | ||
| 365 | */ | ||
| 366 | int pciehp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot) | ||
| 367 | { | ||
| 368 | int rc; | ||
| 369 | u8 class_code; | ||
| 370 | u8 header_type; | ||
| 371 | u32 ID; | ||
| 372 | u8 secondary_bus; | ||
| 373 | int sub_bus; | ||
| 374 | int max_functions; | ||
| 375 | int function; | ||
| 376 | int cloop = 0; | ||
| 377 | int stop_it; | ||
| 378 | struct pci_bus lpci_bus, *pci_bus; | ||
| 379 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
| 380 | pci_bus = &lpci_bus; | ||
| 381 | pci_bus->number = new_slot->bus; | ||
| 382 | |||
| 383 | ID = 0xFFFFFFFF; | ||
| 384 | |||
| 385 | pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), | ||
| 386 | PCI_VENDOR_ID, &ID); | ||
| 387 | |||
| 388 | if (ID != 0xFFFFFFFF) { /* device in slot */ | ||
| 389 | pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), | ||
| 390 | 0x0B, &class_code); | ||
| 391 | |||
| 392 | pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), | ||
| 393 | PCI_HEADER_TYPE, &header_type); | ||
| 394 | |||
| 395 | if (header_type & 0x80) /* Multi-function device */ | ||
| 396 | max_functions = 8; | ||
| 397 | else | ||
| 398 | max_functions = 1; | ||
| 399 | |||
| 400 | function = 0; | ||
| 401 | |||
| 402 | do { | ||
| 403 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ | ||
| 404 | /* Recurse the subordinate bus */ | ||
| 405 | pci_bus_read_config_byte(pci_bus, | ||
| 406 | PCI_DEVFN(new_slot->device, function), | ||
| 407 | PCI_SECONDARY_BUS, &secondary_bus); | ||
| 408 | |||
| 409 | sub_bus = (int) secondary_bus; | ||
| 410 | |||
| 411 | /* Save the config headers for the secondary bus. */ | ||
| 412 | rc = pciehp_save_config(ctrl, sub_bus, 0, 0); | ||
| 413 | |||
| 414 | if (rc) | ||
| 415 | return rc; | ||
| 416 | |||
| 417 | } /* End of IF */ | ||
| 418 | |||
| 419 | new_slot->status = 0; | ||
| 420 | |||
| 421 | for (cloop = 0; cloop < 0x20; cloop++) { | ||
| 422 | pci_bus_read_config_dword(pci_bus, | ||
| 423 | PCI_DEVFN(new_slot->device, function), | ||
| 424 | cloop << 2, | ||
| 425 | (u32 *) &(new_slot->config_space [cloop])); | ||
| 426 | } | ||
| 427 | |||
| 428 | function++; | ||
| 429 | |||
| 430 | stop_it = 0; | ||
| 431 | |||
| 432 | /* this loop skips to the next present function | ||
| 433 | * reading in the Class Code and the Header type. | ||
| 434 | */ | ||
| 435 | |||
| 436 | while ((function < max_functions) && (!stop_it)) { | ||
| 437 | pci_bus_read_config_dword(pci_bus, | ||
| 438 | PCI_DEVFN(new_slot->device, function), | ||
| 439 | PCI_VENDOR_ID, &ID); | ||
| 440 | |||
| 441 | if (ID == 0xFFFFFFFF) { /* nothing there. */ | ||
| 442 | function++; | ||
| 443 | } else { /* Something there */ | ||
| 444 | pci_bus_read_config_byte(pci_bus, | ||
| 445 | PCI_DEVFN(new_slot->device, function), | ||
| 446 | 0x0B, &class_code); | ||
| 447 | |||
| 448 | pci_bus_read_config_byte(pci_bus, | ||
| 449 | PCI_DEVFN(new_slot->device, function), | ||
| 450 | PCI_HEADER_TYPE, &header_type); | ||
| 451 | |||
| 452 | stop_it++; | ||
| 453 | } | ||
| 454 | } | ||
| 455 | |||
| 456 | } while (function < max_functions); | ||
| 457 | } /* End of IF (device in slot?) */ | ||
| 458 | else { | ||
| 459 | return 2; | ||
| 460 | } | ||
| 461 | |||
| 462 | return 0; | ||
| 463 | } | ||
| 464 | |||
| 465 | |||
| 466 | /* | ||
| 467 | * pciehp_save_used_resources | ||
| 468 | * | ||
| 469 | * Stores used resource information for existing boards. this is | ||
| 470 | * for boards that were in the system when this driver was loaded. | ||
| 471 | * this function is for hot plug ADD | ||
| 472 | * | ||
| 473 | * returns 0 if success | ||
| 474 | * if disable == 1(DISABLE_CARD), | ||
| 475 | * it loops for all functions of the slot and disables them. | ||
| 476 | * else, it just get resources of the function and return. | ||
| 477 | */ | ||
| 478 | int pciehp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable) | ||
| 479 | { | ||
| 480 | u8 cloop; | ||
| 481 | u8 header_type; | ||
| 482 | u8 secondary_bus; | ||
| 483 | u8 temp_byte; | ||
| 484 | u16 command; | ||
| 485 | u16 save_command; | ||
| 486 | u16 w_base, w_length; | ||
| 487 | u32 temp_register; | ||
| 488 | u32 save_base; | ||
| 489 | u32 base, length; | ||
| 490 | u64 base64 = 0; | ||
| 491 | int index = 0; | ||
| 492 | unsigned int devfn; | ||
| 493 | struct pci_resource *mem_node = NULL; | ||
| 494 | struct pci_resource *p_mem_node = NULL; | ||
| 495 | struct pci_resource *t_mem_node; | ||
| 496 | struct pci_resource *io_node; | ||
| 497 | struct pci_resource *bus_node; | ||
| 498 | struct pci_bus lpci_bus, *pci_bus; | ||
| 499 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
| 500 | pci_bus = &lpci_bus; | ||
| 501 | |||
| 502 | if (disable) | ||
| 503 | func = pciehp_slot_find(func->bus, func->device, index++); | ||
| 504 | |||
| 505 | while ((func != NULL) && func->is_a_board) { | ||
| 506 | pci_bus->number = func->bus; | ||
| 507 | devfn = PCI_DEVFN(func->device, func->function); | ||
| 508 | |||
| 509 | /* Save the command register */ | ||
| 510 | pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command); | ||
| 511 | |||
| 512 | if (disable) { | ||
| 513 | /* disable card */ | ||
| 514 | command = 0x00; | ||
| 515 | pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); | ||
| 516 | } | ||
| 517 | |||
| 518 | /* Check for Bridge */ | ||
| 519 | pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type); | ||
| 520 | |||
| 521 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ | ||
| 522 | dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", | ||
| 523 | func->bus, func->device, save_command); | ||
| 524 | if (disable) { | ||
| 525 | /* Clear Bridge Control Register */ | ||
| 526 | command = 0x00; | ||
| 527 | pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command); | ||
| 528 | } | ||
| 529 | |||
| 530 | pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); | ||
| 531 | pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte); | ||
| 532 | |||
| 533 | bus_node = kmalloc(sizeof(struct pci_resource), | ||
| 534 | GFP_KERNEL); | ||
| 535 | if (!bus_node) | ||
| 536 | return -ENOMEM; | ||
| 537 | |||
| 538 | bus_node->base = (ulong)secondary_bus; | ||
| 539 | bus_node->length = (ulong)(temp_byte - secondary_bus + 1); | ||
| 540 | |||
| 541 | bus_node->next = func->bus_head; | ||
| 542 | func->bus_head = bus_node; | ||
| 543 | |||
| 544 | /* Save IO base and Limit registers */ | ||
| 545 | pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte); | ||
| 546 | base = temp_byte; | ||
| 547 | pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte); | ||
| 548 | length = temp_byte; | ||
| 549 | |||
| 550 | if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) { | ||
| 551 | io_node = kmalloc(sizeof(struct pci_resource), | ||
| 552 | GFP_KERNEL); | ||
| 553 | if (!io_node) | ||
| 554 | return -ENOMEM; | ||
| 555 | |||
| 556 | io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8; | ||
| 557 | io_node->length = (ulong)(length - base + 0x10) << 8; | ||
| 558 | |||
| 559 | io_node->next = func->io_head; | ||
| 560 | func->io_head = io_node; | ||
| 561 | } | ||
| 562 | |||
| 563 | /* Save memory base and Limit registers */ | ||
| 564 | pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base); | ||
| 565 | pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length); | ||
| 566 | |||
| 567 | if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { | ||
| 568 | mem_node = kmalloc(sizeof(struct pci_resource), | ||
| 569 | GFP_KERNEL); | ||
| 570 | if (!mem_node) | ||
| 571 | return -ENOMEM; | ||
| 572 | |||
| 573 | mem_node->base = (ulong)w_base << 16; | ||
| 574 | mem_node->length = (ulong)(w_length - w_base + 0x10) << 16; | ||
| 575 | |||
| 576 | mem_node->next = func->mem_head; | ||
| 577 | func->mem_head = mem_node; | ||
| 578 | } | ||
| 579 | /* Save prefetchable memory base and Limit registers */ | ||
| 580 | pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base); | ||
| 581 | pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length); | ||
| 582 | |||
| 583 | if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { | ||
| 584 | p_mem_node = kmalloc(sizeof(struct pci_resource), | ||
| 585 | GFP_KERNEL); | ||
| 586 | if (!p_mem_node) | ||
| 587 | return -ENOMEM; | ||
| 588 | |||
| 589 | p_mem_node->base = (ulong)w_base << 16; | ||
| 590 | p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16; | ||
| 591 | |||
| 592 | p_mem_node->next = func->p_mem_head; | ||
| 593 | func->p_mem_head = p_mem_node; | ||
| 594 | } | ||
| 595 | } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) { | ||
| 596 | dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", | ||
| 597 | func->bus, func->device, save_command); | ||
| 598 | |||
| 599 | /* Figure out IO and memory base lengths */ | ||
| 600 | for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { | ||
| 601 | pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base); | ||
| 602 | |||
| 603 | temp_register = 0xFFFFFFFF; | ||
| 604 | pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register); | ||
| 605 | pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register); | ||
| 606 | |||
| 607 | if (!disable) | ||
| 608 | pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base); | ||
| 609 | |||
| 610 | if (!temp_register) | ||
| 611 | continue; | ||
| 612 | |||
| 613 | base = temp_register; | ||
| 614 | |||
| 615 | if ((base & PCI_BASE_ADDRESS_SPACE_IO) && | ||
| 616 | (!disable || (save_command & PCI_COMMAND_IO))) { | ||
| 617 | /* IO base */ | ||
| 618 | /* set temp_register = amount of IO space requested */ | ||
| 619 | base = base & 0xFFFFFFFCL; | ||
| 620 | base = (~base) + 1; | ||
| 621 | |||
| 622 | io_node = kmalloc(sizeof (struct pci_resource), | ||
| 623 | GFP_KERNEL); | ||
| 624 | if (!io_node) | ||
| 625 | return -ENOMEM; | ||
| 626 | |||
| 627 | io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK; | ||
| 628 | io_node->length = (ulong)base; | ||
| 629 | dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", | ||
| 630 | io_node->base, io_node->length); | ||
| 631 | |||
| 632 | io_node->next = func->io_head; | ||
| 633 | func->io_head = io_node; | ||
| 634 | } else { /* map Memory */ | ||
| 635 | int prefetchable = 1; | ||
| 636 | /* struct pci_resources **res_node; */ | ||
| 637 | char *res_type_str = "PMEM"; | ||
| 638 | u32 temp_register2; | ||
| 639 | |||
| 640 | t_mem_node = kmalloc(sizeof (struct pci_resource), | ||
| 641 | GFP_KERNEL); | ||
| 642 | if (!t_mem_node) | ||
| 643 | return -ENOMEM; | ||
| 644 | |||
| 645 | if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && | ||
| 646 | (!disable || (save_command & PCI_COMMAND_MEMORY))) { | ||
| 647 | prefetchable = 0; | ||
| 648 | mem_node = t_mem_node; | ||
| 649 | res_type_str++; | ||
| 650 | } else | ||
| 651 | p_mem_node = t_mem_node; | ||
| 652 | |||
| 653 | base = base & 0xFFFFFFF0L; | ||
| 654 | base = (~base) + 1; | ||
| 655 | |||
| 656 | switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { | ||
| 657 | case PCI_BASE_ADDRESS_MEM_TYPE_32: | ||
| 658 | if (prefetchable) { | ||
| 659 | p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; | ||
| 660 | p_mem_node->length = (ulong)base; | ||
| 661 | dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", | ||
| 662 | res_type_str, | ||
| 663 | p_mem_node->base, | ||
| 664 | p_mem_node->length); | ||
| 665 | |||
| 666 | p_mem_node->next = func->p_mem_head; | ||
| 667 | func->p_mem_head = p_mem_node; | ||
| 668 | } else { | ||
| 669 | mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; | ||
| 670 | mem_node->length = (ulong)base; | ||
| 671 | dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", | ||
| 672 | res_type_str, | ||
| 673 | mem_node->base, | ||
| 674 | mem_node->length); | ||
| 675 | |||
| 676 | mem_node->next = func->mem_head; | ||
| 677 | func->mem_head = mem_node; | ||
| 678 | } | ||
| 679 | break; | ||
| 680 | case PCI_BASE_ADDRESS_MEM_TYPE_64: | ||
| 681 | pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2); | ||
| 682 | base64 = temp_register2; | ||
| 683 | base64 = (base64 << 32) | save_base; | ||
| 684 | |||
| 685 | if (temp_register2) { | ||
| 686 | dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n", | ||
| 687 | res_type_str, temp_register2, (u32)base64); | ||
| 688 | base64 &= 0x00000000FFFFFFFFL; | ||
| 689 | } | ||
| 690 | |||
| 691 | if (prefetchable) { | ||
| 692 | p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; | ||
| 693 | p_mem_node->length = base; | ||
| 694 | dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", | ||
| 695 | res_type_str, | ||
| 696 | p_mem_node->base, | ||
| 697 | p_mem_node->length); | ||
| 698 | |||
| 699 | p_mem_node->next = func->p_mem_head; | ||
| 700 | func->p_mem_head = p_mem_node; | ||
| 701 | } else { | ||
| 702 | mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; | ||
| 703 | mem_node->length = base; | ||
| 704 | dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", | ||
| 705 | res_type_str, | ||
| 706 | mem_node->base, | ||
| 707 | mem_node->length); | ||
| 708 | |||
| 709 | mem_node->next = func->mem_head; | ||
| 710 | func->mem_head = mem_node; | ||
| 711 | } | ||
| 712 | cloop += 4; | ||
| 713 | break; | ||
| 714 | default: | ||
| 715 | dbg("asur: reserved BAR type=0x%x\n", | ||
| 716 | temp_register); | ||
| 717 | break; | ||
| 718 | } | ||
| 719 | } | ||
| 720 | } /* End of base register loop */ | ||
| 721 | } else { /* Some other unknown header type */ | ||
| 722 | dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", | ||
| 723 | func->bus, func->device); | ||
| 724 | } | ||
| 725 | |||
| 726 | /* find the next device in this slot */ | ||
| 727 | if (!disable) | ||
| 728 | break; | ||
| 729 | func = pciehp_slot_find(func->bus, func->device, index++); | ||
| 730 | } | ||
| 731 | |||
| 732 | return 0; | ||
| 733 | } | ||
| 734 | |||
| 735 | |||
| 736 | /** | ||
| 737 | * kfree_resource_list: release memory of all list members | ||
| 738 | * @res: resource list to free | ||
| 739 | */ | ||
| 740 | static inline void | ||
| 741 | return_resource_list(struct pci_resource **func, struct pci_resource **res) | ||
| 742 | { | ||
| 743 | struct pci_resource *node; | ||
| 744 | struct pci_resource *t_node; | ||
| 745 | |||
| 746 | node = *func; | ||
| 747 | *func = NULL; | ||
| 748 | while (node) { | ||
| 749 | t_node = node->next; | ||
| 750 | return_resource(res, node); | ||
| 751 | node = t_node; | ||
| 752 | } | ||
| 753 | } | ||
| 754 | |||
| 755 | /* | ||
| 756 | * pciehp_return_board_resources | ||
| 757 | * | ||
| 758 | * this routine returns all resources allocated to a board to | ||
| 759 | * the available pool. | ||
| 760 | * | ||
| 761 | * returns 0 if success | ||
| 762 | */ | ||
| 763 | int pciehp_return_board_resources(struct pci_func * func, | ||
| 764 | struct resource_lists * resources) | ||
| 765 | { | ||
| 766 | int rc; | ||
| 767 | |||
| 768 | dbg("%s\n", __FUNCTION__); | ||
| 769 | |||
| 770 | if (!func) | ||
| 771 | return 1; | ||
| 772 | |||
| 773 | return_resource_list(&(func->io_head),&(resources->io_head)); | ||
| 774 | return_resource_list(&(func->mem_head),&(resources->mem_head)); | ||
| 775 | return_resource_list(&(func->p_mem_head),&(resources->p_mem_head)); | ||
| 776 | return_resource_list(&(func->bus_head),&(resources->bus_head)); | ||
| 777 | |||
| 778 | rc = pciehp_resource_sort_and_combine(&(resources->mem_head)); | ||
| 779 | rc |= pciehp_resource_sort_and_combine(&(resources->p_mem_head)); | ||
| 780 | rc |= pciehp_resource_sort_and_combine(&(resources->io_head)); | ||
| 781 | rc |= pciehp_resource_sort_and_combine(&(resources->bus_head)); | ||
| 782 | |||
| 783 | return rc; | ||
| 784 | } | ||
| 785 | |||
| 786 | /** | ||
| 787 | * kfree_resource_list: release memory of all list members | ||
| 788 | * @res: resource list to free | ||
| 789 | */ | ||
| 790 | static inline void | ||
| 791 | kfree_resource_list(struct pci_resource **r) | ||
| 792 | { | ||
| 793 | struct pci_resource *res, *tres; | ||
| 794 | |||
| 795 | res = *r; | ||
| 796 | *r = NULL; | ||
| 797 | |||
| 798 | while (res) { | ||
| 799 | tres = res; | ||
| 800 | res = res->next; | ||
| 801 | kfree(tres); | ||
| 802 | } | ||
| 803 | } | ||
| 804 | |||
| 805 | /** | ||
| 806 | * pciehp_destroy_resource_list: put node back in the resource list | ||
| 807 | * @resources: list to put nodes back | ||
| 808 | */ | ||
| 809 | void pciehp_destroy_resource_list(struct resource_lists * resources) | ||
| 810 | { | ||
| 811 | kfree_resource_list(&(resources->io_head)); | ||
| 812 | kfree_resource_list(&(resources->mem_head)); | ||
| 813 | kfree_resource_list(&(resources->p_mem_head)); | ||
| 814 | kfree_resource_list(&(resources->bus_head)); | ||
| 815 | } | ||
| 816 | |||
| 817 | /** | ||
| 818 | * pciehp_destroy_board_resources: put node back in the resource list | ||
| 819 | * @resources: list to put nodes back | ||
| 820 | */ | ||
| 821 | void pciehp_destroy_board_resources(struct pci_func * func) | ||
| 822 | { | ||
| 823 | kfree_resource_list(&(func->io_head)); | ||
| 824 | kfree_resource_list(&(func->mem_head)); | ||
| 825 | kfree_resource_list(&(func->p_mem_head)); | ||
| 826 | kfree_resource_list(&(func->bus_head)); | ||
| 827 | } | ||
diff --git a/drivers/pci/hotplug/pciehprm.h b/drivers/pci/hotplug/pciehprm.h deleted file mode 100644 index 05f20fbc5f50..000000000000 --- a/drivers/pci/hotplug/pciehprm.h +++ /dev/null | |||
| @@ -1,52 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * PCIEHPRM : PCIEHP Resource Manager for ACPI/non-ACPI platform | ||
| 3 | * | ||
| 4 | * Copyright (C) 1995,2001 Compaq Computer Corporation | ||
| 5 | * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) | ||
| 6 | * Copyright (C) 2001 IBM Corp. | ||
| 7 | * Copyright (C) 2003-2004 Intel Corporation | ||
| 8 | * | ||
| 9 | * All rights reserved. | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or (at | ||
| 14 | * your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, but | ||
| 17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
| 19 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
| 20 | * details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License | ||
| 23 | * along with this program; if not, write to the Free Software | ||
| 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 25 | * | ||
| 26 | * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> | ||
| 27 | * | ||
| 28 | */ | ||
| 29 | |||
| 30 | #ifndef _PCIEHPRM_H_ | ||
| 31 | #define _PCIEHPRM_H_ | ||
| 32 | |||
| 33 | #ifdef CONFIG_HOTPLUG_PCI_PCIE_PHPRM_NONACPI | ||
| 34 | #include "pciehprm_nonacpi.h" | ||
| 35 | #endif | ||
| 36 | |||
| 37 | int pciehprm_init(enum php_ctlr_type ct); | ||
| 38 | void pciehprm_cleanup(void); | ||
| 39 | int pciehprm_print_pirt(void); | ||
| 40 | int pciehprm_find_available_resources(struct controller *ctrl); | ||
| 41 | int pciehprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type); | ||
| 42 | void pciehprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type); | ||
| 43 | |||
| 44 | #ifdef DEBUG | ||
| 45 | #define RES_CHECK(this, bits) \ | ||
| 46 | { if (((this) & (bits - 1))) \ | ||
| 47 | printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); } | ||
| 48 | #else | ||
| 49 | #define RES_CHECK(this, bits) | ||
| 50 | #endif | ||
| 51 | |||
| 52 | #endif /* _PCIEHPRM_H_ */ | ||
diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c index 1406db35b089..ae244e218620 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/pciehprm_acpi.c | |||
| @@ -24,100 +24,20 @@ | |||
| 24 | * | 24 | * |
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| 27 | #include <linux/config.h> | ||
| 28 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| 29 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
| 30 | #include <linux/types.h> | 29 | #include <linux/types.h> |
| 31 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/acpi.h> | 31 | #include <linux/acpi.h> |
| 34 | #include <linux/efi.h> | ||
| 35 | #include <linux/pci-acpi.h> | 32 | #include <linux/pci-acpi.h> |
| 36 | #include <asm/uaccess.h> | ||
| 37 | #include <asm/system.h> | ||
| 38 | #ifdef CONFIG_IA64 | ||
| 39 | #include <asm/iosapic.h> | ||
| 40 | #endif | ||
| 41 | #include <acpi/acpi.h> | ||
| 42 | #include <acpi/acpi_bus.h> | 33 | #include <acpi/acpi_bus.h> |
| 43 | #include <acpi/actypes.h> | 34 | #include <acpi/actypes.h> |
| 44 | #include "pciehp.h" | 35 | #include "pciehp.h" |
| 45 | #include "pciehprm.h" | ||
| 46 | |||
| 47 | #define PCI_MAX_BUS 0x100 | ||
| 48 | #define ACPI_STA_DEVICE_PRESENT 0x01 | ||
| 49 | 36 | ||
| 50 | #define METHOD_NAME__SUN "_SUN" | 37 | #define METHOD_NAME__SUN "_SUN" |
| 51 | #define METHOD_NAME__HPP "_HPP" | 38 | #define METHOD_NAME__HPP "_HPP" |
| 52 | #define METHOD_NAME_OSHP "OSHP" | 39 | #define METHOD_NAME_OSHP "OSHP" |
| 53 | 40 | ||
| 54 | /* Status code for running acpi method to gain native control */ | ||
| 55 | #define NC_NOT_RUN 0 | ||
| 56 | #define OSC_NOT_EXIST 1 | ||
| 57 | #define OSC_RUN_FAILED 2 | ||
| 58 | #define OSHP_NOT_EXIST 3 | ||
| 59 | #define OSHP_RUN_FAILED 4 | ||
| 60 | #define NC_RUN_SUCCESS 5 | ||
| 61 | |||
| 62 | #define PHP_RES_BUS 0xA0 | ||
| 63 | #define PHP_RES_IO 0xA1 | ||
| 64 | #define PHP_RES_MEM 0xA2 | ||
| 65 | #define PHP_RES_PMEM 0xA3 | ||
| 66 | |||
| 67 | #define BRIDGE_TYPE_P2P 0x00 | ||
| 68 | #define BRIDGE_TYPE_HOST 0x01 | ||
| 69 | |||
| 70 | /* this should go to drivers/acpi/include/ */ | ||
| 71 | struct acpi__hpp { | ||
| 72 | u8 cache_line_size; | ||
| 73 | u8 latency_timer; | ||
| 74 | u8 enable_serr; | ||
| 75 | u8 enable_perr; | ||
| 76 | }; | ||
| 77 | |||
| 78 | struct acpi_php_slot { | ||
| 79 | struct acpi_php_slot *next; | ||
| 80 | struct acpi_bridge *bridge; | ||
| 81 | acpi_handle handle; | ||
| 82 | int seg; | ||
| 83 | int bus; | ||
| 84 | int dev; | ||
| 85 | int fun; | ||
| 86 | u32 sun; | ||
| 87 | struct pci_resource *mem_head; | ||
| 88 | struct pci_resource *p_mem_head; | ||
| 89 | struct pci_resource *io_head; | ||
| 90 | struct pci_resource *bus_head; | ||
| 91 | void *slot_ops; /* _STA, _EJx, etc */ | ||
| 92 | struct slot *slot; | ||
| 93 | }; /* per func */ | ||
| 94 | |||
| 95 | struct acpi_bridge { | ||
| 96 | struct acpi_bridge *parent; | ||
| 97 | struct acpi_bridge *next; | ||
| 98 | struct acpi_bridge *child; | ||
| 99 | acpi_handle handle; | ||
| 100 | int seg; | ||
| 101 | int pbus; /* pdev->bus->number */ | ||
| 102 | int pdevice; /* PCI_SLOT(pdev->devfn) */ | ||
| 103 | int pfunction; /* PCI_DEVFN(pdev->devfn) */ | ||
| 104 | int bus; /* pdev->subordinate->number */ | ||
| 105 | struct acpi__hpp *_hpp; | ||
| 106 | struct acpi_php_slot *slots; | ||
| 107 | struct pci_resource *tmem_head; /* total from crs */ | ||
| 108 | struct pci_resource *tp_mem_head; /* total from crs */ | ||
| 109 | struct pci_resource *tio_head; /* total from crs */ | ||
| 110 | struct pci_resource *tbus_head; /* total from crs */ | ||
| 111 | struct pci_resource *mem_head; /* available */ | ||
| 112 | struct pci_resource *p_mem_head; /* available */ | ||
| 113 | struct pci_resource *io_head; /* available */ | ||
| 114 | struct pci_resource *bus_head; /* available */ | ||
| 115 | int scanned; | ||
| 116 | int type; | ||
| 117 | }; | ||
| 118 | |||
| 119 | static struct acpi_bridge *acpi_bridges_head; | ||
| 120 | |||
| 121 | static u8 * acpi_path_name( acpi_handle handle) | 41 | static u8 * acpi_path_name( acpi_handle handle) |
| 122 | { | 42 | { |
| 123 | acpi_status status; | 43 | acpi_status status; |
| @@ -133,85 +53,43 @@ static u8 * acpi_path_name( acpi_handle handle) | |||
| 133 | return path_name; | 53 | return path_name; |
| 134 | } | 54 | } |
| 135 | 55 | ||
| 136 | static void acpi_get__hpp ( struct acpi_bridge *ab); | 56 | static acpi_status |
| 137 | static int acpi_run_oshp ( struct acpi_bridge *ab); | 57 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) |
| 138 | static int osc_run_status = NC_NOT_RUN; | ||
| 139 | static int oshp_run_status = NC_NOT_RUN; | ||
| 140 | |||
| 141 | static int acpi_add_slot_to_php_slots( | ||
| 142 | struct acpi_bridge *ab, | ||
| 143 | int bus_num, | ||
| 144 | acpi_handle handle, | ||
| 145 | u32 adr, | ||
| 146 | u32 sun | ||
| 147 | ) | ||
| 148 | { | ||
| 149 | struct acpi_php_slot *aps; | ||
| 150 | static long samesun = -1; | ||
| 151 | |||
| 152 | aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL); | ||
| 153 | if (!aps) { | ||
| 154 | err ("acpi_pciehprm: alloc for aps fail\n"); | ||
| 155 | return -1; | ||
| 156 | } | ||
| 157 | memset(aps, 0, sizeof(struct acpi_php_slot)); | ||
| 158 | |||
| 159 | aps->handle = handle; | ||
| 160 | aps->bus = bus_num; | ||
| 161 | aps->dev = (adr >> 16) & 0xffff; | ||
| 162 | aps->fun = adr & 0xffff; | ||
| 163 | aps->sun = sun; | ||
| 164 | |||
| 165 | aps->next = ab->slots; /* cling to the bridge */ | ||
| 166 | aps->bridge = ab; | ||
| 167 | ab->slots = aps; | ||
| 168 | |||
| 169 | ab->scanned += 1; | ||
| 170 | if (!ab->_hpp) | ||
| 171 | acpi_get__hpp(ab); | ||
| 172 | |||
| 173 | if (osc_run_status == OSC_NOT_EXIST) | ||
| 174 | oshp_run_status = acpi_run_oshp(ab); | ||
| 175 | |||
| 176 | if (sun != samesun) { | ||
| 177 | info("acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", | ||
| 178 | aps->sun, ab->seg, aps->bus, aps->dev, aps->fun); | ||
| 179 | samesun = sun; | ||
| 180 | } | ||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | static void acpi_get__hpp ( struct acpi_bridge *ab) | ||
| 185 | { | 58 | { |
| 186 | acpi_status status; | 59 | acpi_status status; |
| 187 | u8 nui[4]; | 60 | u8 nui[4]; |
| 188 | struct acpi_buffer ret_buf = { 0, NULL}; | 61 | struct acpi_buffer ret_buf = { 0, NULL}; |
| 189 | union acpi_object *ext_obj, *package; | 62 | union acpi_object *ext_obj, *package; |
| 190 | u8 *path_name = acpi_path_name(ab->handle); | 63 | u8 *path_name = acpi_path_name(handle); |
| 191 | int i, len = 0; | 64 | int i, len = 0; |
| 192 | 65 | ||
| 193 | /* get _hpp */ | 66 | /* get _hpp */ |
| 194 | status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); | 67 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); |
| 195 | switch (status) { | 68 | switch (status) { |
| 196 | case AE_BUFFER_OVERFLOW: | 69 | case AE_BUFFER_OVERFLOW: |
| 197 | ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); | 70 | ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); |
| 198 | if (!ret_buf.pointer) { | 71 | if (!ret_buf.pointer) { |
| 199 | err ("acpi_pciehprm:%s alloc for _HPP fail\n", path_name); | 72 | err ("%s:%s alloc for _HPP fail\n", __FUNCTION__, |
| 200 | return; | 73 | path_name); |
| 74 | return AE_NO_MEMORY; | ||
| 201 | } | 75 | } |
| 202 | status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); | 76 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, |
| 77 | NULL, &ret_buf); | ||
| 203 | if (ACPI_SUCCESS(status)) | 78 | if (ACPI_SUCCESS(status)) |
| 204 | break; | 79 | break; |
| 205 | default: | 80 | default: |
| 206 | if (ACPI_FAILURE(status)) { | 81 | if (ACPI_FAILURE(status)) { |
| 207 | err("acpi_pciehprm:%s _HPP fail=0x%x\n", path_name, status); | 82 | dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__, |
| 208 | return; | 83 | path_name, status); |
| 84 | return status; | ||
| 209 | } | 85 | } |
| 210 | } | 86 | } |
| 211 | 87 | ||
| 212 | ext_obj = (union acpi_object *) ret_buf.pointer; | 88 | ext_obj = (union acpi_object *) ret_buf.pointer; |
| 213 | if (ext_obj->type != ACPI_TYPE_PACKAGE) { | 89 | if (ext_obj->type != ACPI_TYPE_PACKAGE) { |
| 214 | err ("acpi_pciehprm:%s _HPP obj not a package\n", path_name); | 90 | err ("%s:%s _HPP obj not a package\n", __FUNCTION__, |
| 91 | path_name); | ||
| 92 | status = AE_ERROR; | ||
| 215 | goto free_and_return; | 93 | goto free_and_return; |
| 216 | } | 94 | } |
| 217 | 95 | ||
| @@ -224,1514 +102,153 @@ static void acpi_get__hpp ( struct acpi_bridge *ab) | |||
| 224 | nui[i] = (u8)ext_obj->integer.value; | 102 | nui[i] = (u8)ext_obj->integer.value; |
| 225 | break; | 103 | break; |
| 226 | default: | 104 | default: |
| 227 | err ("acpi_pciehprm:%s _HPP obj type incorrect\n", path_name); | 105 | err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__, |
| 106 | path_name); | ||
| 107 | status = AE_ERROR; | ||
| 228 | goto free_and_return; | 108 | goto free_and_return; |
| 229 | } | 109 | } |
| 230 | } | 110 | } |
| 231 | 111 | ||
| 232 | ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL); | 112 | hpp->cache_line_size = nui[0]; |
| 233 | if (!ab->_hpp) { | 113 | hpp->latency_timer = nui[1]; |
| 234 | err ("acpi_pciehprm:%s alloc for _HPP failed\n", path_name); | 114 | hpp->enable_serr = nui[2]; |
| 235 | goto free_and_return; | 115 | hpp->enable_perr = nui[3]; |
| 236 | } | ||
| 237 | memset(ab->_hpp, 0, sizeof(struct acpi__hpp)); | ||
| 238 | 116 | ||
| 239 | ab->_hpp->cache_line_size = nui[0]; | 117 | dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); |
| 240 | ab->_hpp->latency_timer = nui[1]; | 118 | dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer); |
| 241 | ab->_hpp->enable_serr = nui[2]; | 119 | dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); |
| 242 | ab->_hpp->enable_perr = nui[3]; | 120 | dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); |
| 243 | |||
| 244 | dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size); | ||
| 245 | dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer); | ||
| 246 | dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr); | ||
| 247 | dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr); | ||
| 248 | 121 | ||
| 249 | free_and_return: | 122 | free_and_return: |
| 250 | kfree(ret_buf.pointer); | 123 | kfree(ret_buf.pointer); |
| 124 | return status; | ||
| 251 | } | 125 | } |
| 252 | 126 | ||
| 253 | static int acpi_run_oshp ( struct acpi_bridge *ab) | 127 | static acpi_status acpi_run_oshp(acpi_handle handle) |
| 254 | { | 128 | { |
| 255 | acpi_status status; | 129 | acpi_status status; |
| 256 | u8 *path_name = acpi_path_name(ab->handle); | 130 | u8 *path_name = acpi_path_name(handle); |
| 257 | 131 | ||
| 258 | /* run OSHP */ | 132 | /* run OSHP */ |
| 259 | status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL); | 133 | status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); |
| 260 | if (ACPI_FAILURE(status)) { | 134 | if (ACPI_FAILURE(status)) { |
| 261 | err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status); | 135 | dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, |
| 262 | oshp_run_status = (status == AE_NOT_FOUND) ? OSHP_NOT_EXIST : OSHP_RUN_FAILED; | 136 | status); |
| 263 | } else { | 137 | } else { |
| 264 | oshp_run_status = NC_RUN_SUCCESS; | 138 | dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name); |
| 265 | dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status); | ||
| 266 | dbg("acpi_pciehprm:%s oshp_run_status =0x%x\n", path_name, oshp_run_status); | ||
| 267 | } | ||
| 268 | return oshp_run_status; | ||
| 269 | } | ||
| 270 | |||
| 271 | static acpi_status acpi_evaluate_crs( | ||
| 272 | acpi_handle handle, | ||
| 273 | struct acpi_resource **retbuf | ||
| 274 | ) | ||
| 275 | { | ||
| 276 | acpi_status status; | ||
| 277 | struct acpi_buffer crsbuf; | ||
| 278 | u8 *path_name = acpi_path_name(handle); | ||
| 279 | |||
| 280 | crsbuf.length = 0; | ||
| 281 | crsbuf.pointer = NULL; | ||
| 282 | |||
| 283 | status = acpi_get_current_resources (handle, &crsbuf); | ||
| 284 | |||
| 285 | switch (status) { | ||
| 286 | case AE_BUFFER_OVERFLOW: | ||
| 287 | break; /* found */ | ||
| 288 | case AE_NOT_FOUND: | ||
| 289 | dbg("acpi_pciehprm:%s _CRS not found\n", path_name); | ||
| 290 | return status; | ||
| 291 | default: | ||
| 292 | err ("acpi_pciehprm:%s _CRS fail=0x%x\n", path_name, status); | ||
| 293 | return status; | ||
| 294 | } | 139 | } |
| 295 | |||
| 296 | crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL); | ||
| 297 | if (!crsbuf.pointer) { | ||
| 298 | err ("acpi_pciehprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name); | ||
| 299 | return AE_NO_MEMORY; | ||
| 300 | } | ||
| 301 | |||
| 302 | status = acpi_get_current_resources (handle, &crsbuf); | ||
| 303 | if (ACPI_FAILURE(status)) { | ||
| 304 | err("acpi_pciehprm: %s _CRS fail=0x%x.\n", path_name, status); | ||
| 305 | kfree(crsbuf.pointer); | ||
| 306 | return status; | ||
| 307 | } | ||
| 308 | |||
| 309 | *retbuf = crsbuf.pointer; | ||
| 310 | |||
| 311 | return status; | 140 | return status; |
| 312 | } | 141 | } |
| 313 | 142 | ||
| 314 | static void free_pci_resource ( struct pci_resource *aprh) | 143 | static int is_root_bridge(acpi_handle handle) |
| 315 | { | 144 | { |
| 316 | struct pci_resource *res, *next; | 145 | acpi_status status; |
| 146 | struct acpi_device_info *info; | ||
| 147 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
| 148 | int i; | ||
| 317 | 149 | ||
| 318 | for (res = aprh; res; res = next) { | 150 | status = acpi_get_object_info(handle, &buffer); |
| 319 | next = res->next; | 151 | if (ACPI_SUCCESS(status)) { |
| 320 | kfree(res); | 152 | info = buffer.pointer; |
| 321 | } | 153 | if ((info->valid & ACPI_VALID_HID) && |
| 322 | } | 154 | !strcmp(PCI_ROOT_HID_STRING, |
| 323 | 155 | info->hardware_id.value)) { | |
| 324 | static void print_pci_resource ( struct pci_resource *aprh) | 156 | acpi_os_free(buffer.pointer); |
| 325 | { | 157 | return 1; |
| 326 | struct pci_resource *res; | 158 | } |
| 327 | 159 | if (info->valid & ACPI_VALID_CID) { | |
| 328 | for (res = aprh; res; res = res->next) | 160 | for (i=0; i < info->compatibility_id.count; i++) { |
| 329 | dbg(" base= 0x%x length= 0x%x\n", res->base, res->length); | 161 | if (!strcmp(PCI_ROOT_HID_STRING, |
| 330 | } | 162 | info->compatibility_id.id[i].value)) { |
| 331 | 163 | acpi_os_free(buffer.pointer); | |
| 332 | static void print_slot_resources( struct acpi_php_slot *aps) | 164 | return 1; |
| 333 | { | 165 | } |
| 334 | if (aps->bus_head) { | 166 | } |
| 335 | dbg(" BUS Resources:\n"); | ||
| 336 | print_pci_resource (aps->bus_head); | ||
| 337 | } | ||
| 338 | |||
| 339 | if (aps->io_head) { | ||
| 340 | dbg(" IO Resources:\n"); | ||
| 341 | print_pci_resource (aps->io_head); | ||
| 342 | } | ||
| 343 | |||
| 344 | if (aps->mem_head) { | ||
| 345 | dbg(" MEM Resources:\n"); | ||
| 346 | print_pci_resource (aps->mem_head); | ||
| 347 | } | ||
| 348 | |||
| 349 | if (aps->p_mem_head) { | ||
| 350 | dbg(" PMEM Resources:\n"); | ||
| 351 | print_pci_resource (aps->p_mem_head); | ||
| 352 | } | ||
| 353 | } | ||
| 354 | |||
| 355 | static void print_pci_resources( struct acpi_bridge *ab) | ||
| 356 | { | ||
| 357 | if (ab->tbus_head) { | ||
| 358 | dbg(" Total BUS Resources:\n"); | ||
| 359 | print_pci_resource (ab->tbus_head); | ||
| 360 | } | ||
| 361 | if (ab->bus_head) { | ||
| 362 | dbg(" BUS Resources:\n"); | ||
| 363 | print_pci_resource (ab->bus_head); | ||
| 364 | } | ||
| 365 | |||
| 366 | if (ab->tio_head) { | ||
| 367 | dbg(" Total IO Resources:\n"); | ||
| 368 | print_pci_resource (ab->tio_head); | ||
| 369 | } | ||
| 370 | if (ab->io_head) { | ||
| 371 | dbg(" IO Resources:\n"); | ||
| 372 | print_pci_resource (ab->io_head); | ||
| 373 | } | ||
| 374 | |||
| 375 | if (ab->tmem_head) { | ||
| 376 | dbg(" Total MEM Resources:\n"); | ||
| 377 | print_pci_resource (ab->tmem_head); | ||
| 378 | } | ||
| 379 | if (ab->mem_head) { | ||
| 380 | dbg(" MEM Resources:\n"); | ||
| 381 | print_pci_resource (ab->mem_head); | ||
| 382 | } | ||
| 383 | |||
| 384 | if (ab->tp_mem_head) { | ||
| 385 | dbg(" Total PMEM Resources:\n"); | ||
| 386 | print_pci_resource (ab->tp_mem_head); | ||
| 387 | } | ||
| 388 | if (ab->p_mem_head) { | ||
| 389 | dbg(" PMEM Resources:\n"); | ||
| 390 | print_pci_resource (ab->p_mem_head); | ||
| 391 | } | ||
| 392 | if (ab->_hpp) { | ||
| 393 | dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size); | ||
| 394 | dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer); | ||
| 395 | dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr); | ||
| 396 | dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr); | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 400 | static int pciehprm_delete_resource( | ||
| 401 | struct pci_resource **aprh, | ||
| 402 | ulong base, | ||
| 403 | ulong size) | ||
| 404 | { | ||
| 405 | struct pci_resource *res; | ||
| 406 | struct pci_resource *prevnode; | ||
| 407 | struct pci_resource *split_node; | ||
| 408 | ulong tbase; | ||
| 409 | |||
| 410 | pciehp_resource_sort_and_combine(aprh); | ||
| 411 | |||
| 412 | for (res = *aprh; res; res = res->next) { | ||
| 413 | if (res->base > base) | ||
| 414 | continue; | ||
| 415 | |||
| 416 | if ((res->base + res->length) < (base + size)) | ||
| 417 | continue; | ||
| 418 | |||
| 419 | if (res->base < base) { | ||
| 420 | tbase = base; | ||
| 421 | |||
| 422 | if ((res->length - (tbase - res->base)) < size) | ||
| 423 | continue; | ||
| 424 | |||
| 425 | split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
| 426 | if (!split_node) | ||
| 427 | return -ENOMEM; | ||
| 428 | |||
| 429 | split_node->base = res->base; | ||
| 430 | split_node->length = tbase - res->base; | ||
| 431 | res->base = tbase; | ||
| 432 | res->length -= split_node->length; | ||
| 433 | |||
| 434 | split_node->next = res->next; | ||
| 435 | res->next = split_node; | ||
| 436 | } | ||
| 437 | |||
| 438 | if (res->length >= size) { | ||
| 439 | split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
| 440 | if (!split_node) | ||
| 441 | return -ENOMEM; | ||
| 442 | |||
| 443 | split_node->base = res->base + size; | ||
| 444 | split_node->length = res->length - size; | ||
| 445 | res->length = size; | ||
| 446 | |||
| 447 | split_node->next = res->next; | ||
| 448 | res->next = split_node; | ||
| 449 | } | ||
| 450 | |||
| 451 | if (*aprh == res) { | ||
| 452 | *aprh = res->next; | ||
| 453 | } else { | ||
| 454 | prevnode = *aprh; | ||
| 455 | while (prevnode->next != res) | ||
| 456 | prevnode = prevnode->next; | ||
| 457 | |||
| 458 | prevnode->next = res->next; | ||
| 459 | } | ||
| 460 | res->next = NULL; | ||
| 461 | kfree(res); | ||
| 462 | break; | ||
| 463 | } | ||
| 464 | |||
| 465 | return 0; | ||
| 466 | } | ||
| 467 | |||
| 468 | static int pciehprm_delete_resources( | ||
| 469 | struct pci_resource **aprh, | ||
| 470 | struct pci_resource *this | ||
| 471 | ) | ||
| 472 | { | ||
| 473 | struct pci_resource *res; | ||
| 474 | |||
| 475 | for (res = this; res; res = res->next) | ||
| 476 | pciehprm_delete_resource(aprh, res->base, res->length); | ||
| 477 | |||
| 478 | return 0; | ||
| 479 | } | ||
| 480 | |||
| 481 | static int pciehprm_add_resource( | ||
| 482 | struct pci_resource **aprh, | ||
| 483 | ulong base, | ||
| 484 | ulong size) | ||
| 485 | { | ||
| 486 | struct pci_resource *res; | ||
| 487 | |||
| 488 | for (res = *aprh; res; res = res->next) { | ||
| 489 | if ((res->base + res->length) == base) { | ||
| 490 | res->length += size; | ||
| 491 | size = 0L; | ||
| 492 | break; | ||
| 493 | } | 167 | } |
| 494 | if (res->next == *aprh) | ||
| 495 | break; | ||
| 496 | } | 168 | } |
| 497 | |||
| 498 | if (size) { | ||
| 499 | res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
| 500 | if (!res) { | ||
| 501 | err ("acpi_pciehprm: alloc for res fail\n"); | ||
| 502 | return -ENOMEM; | ||
| 503 | } | ||
| 504 | memset(res, 0, sizeof (struct pci_resource)); | ||
| 505 | |||
| 506 | res->base = base; | ||
| 507 | res->length = size; | ||
| 508 | res->next = *aprh; | ||
| 509 | *aprh = res; | ||
| 510 | } | ||
| 511 | |||
| 512 | return 0; | 169 | return 0; |
| 513 | } | 170 | } |
| 514 | 171 | ||
| 515 | static int pciehprm_add_resources( | 172 | int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) |
| 516 | struct pci_resource **aprh, | ||
| 517 | struct pci_resource *this | ||
| 518 | ) | ||
| 519 | { | ||
| 520 | struct pci_resource *res; | ||
| 521 | int rc = 0; | ||
| 522 | |||
| 523 | for (res = this; res && !rc; res = res->next) | ||
| 524 | rc = pciehprm_add_resource(aprh, res->base, res->length); | ||
| 525 | |||
| 526 | return rc; | ||
| 527 | } | ||
| 528 | |||
| 529 | static void acpi_parse_io ( | ||
| 530 | struct acpi_bridge *ab, | ||
| 531 | union acpi_resource_data *data | ||
| 532 | ) | ||
| 533 | { | 173 | { |
| 534 | struct acpi_resource_io *dataio; | 174 | acpi_status status; |
| 535 | dataio = (struct acpi_resource_io *) data; | 175 | acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); |
| 536 | 176 | struct pci_dev *pdev = dev; | |
| 537 | dbg("Io Resource\n"); | 177 | u8 *path_name; |
| 538 | dbg(" %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10); | 178 | /* |
| 539 | dbg(" Range minimum base: %08X\n", dataio->min_base_address); | 179 | * Per PCI firmware specification, we should run the ACPI _OSC |
| 540 | dbg(" Range maximum base: %08X\n", dataio->max_base_address); | 180 | * method to get control of hotplug hardware before using it. |
| 541 | dbg(" Alignment: %08X\n", dataio->alignment); | 181 | * If an _OSC is missing, we look for an OSHP to do the same thing. |
| 542 | dbg(" Range Length: %08X\n", dataio->range_length); | 182 | * To handle different BIOS behavior, we look for _OSC and OSHP |
| 543 | } | 183 | * within the scope of the hotplug controller and its parents, upto |
| 544 | 184 | * the host bridge under which this controller exists. | |
| 545 | static void acpi_parse_fixed_io ( | ||
| 546 | struct acpi_bridge *ab, | ||
| 547 | union acpi_resource_data *data | ||
| 548 | ) | ||
| 549 | { | ||
| 550 | struct acpi_resource_fixed_io *datafio; | ||
| 551 | datafio = (struct acpi_resource_fixed_io *) data; | ||
| 552 | |||
| 553 | dbg("Fixed Io Resource\n"); | ||
| 554 | dbg(" Range base address: %08X", datafio->base_address); | ||
| 555 | dbg(" Range length: %08X", datafio->range_length); | ||
| 556 | } | ||
| 557 | |||
| 558 | static void acpi_parse_address16_32 ( | ||
| 559 | struct acpi_bridge *ab, | ||
| 560 | union acpi_resource_data *data, | ||
| 561 | acpi_resource_type id | ||
| 562 | ) | ||
| 563 | { | ||
| 564 | /* | ||
| 565 | * acpi_resource_address16 == acpi_resource_address32 | ||
| 566 | * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data; | ||
| 567 | */ | 185 | */ |
| 568 | struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data; | 186 | while (!handle) { |
| 569 | struct pci_resource **aprh, **tprh; | 187 | /* |
| 570 | 188 | * This hotplug controller was not listed in the ACPI name | |
| 571 | if (id == ACPI_RSTYPE_ADDRESS16) | 189 | * space at all. Try to get acpi handle of parent pci bus. |
| 572 | dbg("acpi_pciehprm:16-Bit Address Space Resource\n"); | 190 | */ |
| 573 | else | 191 | if (!pdev || !pdev->bus->parent) |
| 574 | dbg("acpi_pciehprm:32-Bit Address Space Resource\n"); | ||
| 575 | |||
| 576 | switch (data32->resource_type) { | ||
| 577 | case ACPI_MEMORY_RANGE: | ||
| 578 | dbg(" Resource Type: Memory Range\n"); | ||
| 579 | aprh = &ab->mem_head; | ||
| 580 | tprh = &ab->tmem_head; | ||
| 581 | |||
| 582 | switch (data32->attribute.memory.cache_attribute) { | ||
| 583 | case ACPI_NON_CACHEABLE_MEMORY: | ||
| 584 | dbg(" Type Specific: Noncacheable memory\n"); | ||
| 585 | break; | ||
| 586 | case ACPI_CACHABLE_MEMORY: | ||
| 587 | dbg(" Type Specific: Cacheable memory\n"); | ||
| 588 | break; | ||
| 589 | case ACPI_WRITE_COMBINING_MEMORY: | ||
| 590 | dbg(" Type Specific: Write-combining memory\n"); | ||
| 591 | break; | ||
| 592 | case ACPI_PREFETCHABLE_MEMORY: | ||
| 593 | aprh = &ab->p_mem_head; | ||
| 594 | dbg(" Type Specific: Prefetchable memory\n"); | ||
| 595 | break; | ||
| 596 | default: | ||
| 597 | dbg(" Type Specific: Invalid cache attribute\n"); | ||
| 598 | break; | 192 | break; |
| 599 | } | 193 | dbg("Could not find %s in acpi namespace, trying parent\n", |
| 600 | 194 | pci_name(pdev)); | |
| 601 | dbg(" Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only"); | 195 | if (!pdev->bus->parent->self) |
| 602 | break; | 196 | /* Parent must be a host bridge */ |
| 603 | 197 | handle = acpi_get_pci_rootbridge_handle( | |
| 604 | case ACPI_IO_RANGE: | 198 | pci_domain_nr(pdev->bus->parent), |
| 605 | dbg(" Resource Type: I/O Range\n"); | 199 | pdev->bus->parent->number); |
| 606 | aprh = &ab->io_head; | 200 | else |
| 607 | tprh = &ab->tio_head; | 201 | handle = DEVICE_ACPI_HANDLE( |
| 608 | 202 | &(pdev->bus->parent->self->dev)); | |
| 609 | switch (data32->attribute.io.range_attribute) { | 203 | pdev = pdev->bus->parent->self; |
| 610 | case ACPI_NON_ISA_ONLY_RANGES: | 204 | } |
| 611 | dbg(" Type Specific: Non-ISA Io Addresses\n"); | 205 | |
| 612 | break; | 206 | while (handle) { |
| 613 | case ACPI_ISA_ONLY_RANGES: | 207 | path_name = acpi_path_name(handle); |
| 614 | dbg(" Type Specific: ISA Io Addresses\n"); | 208 | dbg("Trying to get hotplug control for %s \n", path_name); |
| 615 | break; | 209 | status = pci_osc_control_set(handle, |
| 616 | case ACPI_ENTIRE_RANGE: | 210 | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); |
| 617 | dbg(" Type Specific: ISA and non-ISA Io Addresses\n"); | 211 | if (status == AE_NOT_FOUND) |
| 618 | break; | 212 | status = acpi_run_oshp(handle); |
| 619 | default: | 213 | if (ACPI_SUCCESS(status)) { |
| 620 | dbg(" Type Specific: Invalid range attribute\n"); | 214 | dbg("Gained control for hotplug HW for pci %s (%s)\n", |
| 215 | pci_name(dev), path_name); | ||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | if (is_root_bridge(handle)) | ||
| 621 | break; | 219 | break; |
| 622 | } | 220 | chandle = handle; |
| 623 | break; | 221 | status = acpi_get_parent(chandle, &handle); |
| 624 | |||
| 625 | case ACPI_BUS_NUMBER_RANGE: | ||
| 626 | dbg(" Resource Type: Bus Number Range(fixed)\n"); | ||
| 627 | /* fixup to be compatible with the rest of php driver */ | ||
| 628 | data32->min_address_range++; | ||
| 629 | data32->address_length--; | ||
| 630 | aprh = &ab->bus_head; | ||
| 631 | tprh = &ab->tbus_head; | ||
| 632 | break; | ||
| 633 | default: | ||
| 634 | dbg(" Resource Type: Invalid resource type. Exiting.\n"); | ||
| 635 | return; | ||
| 636 | } | ||
| 637 | |||
| 638 | dbg(" Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer"); | ||
| 639 | dbg(" %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive"); | ||
| 640 | dbg(" Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not"); | ||
| 641 | dbg(" Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not"); | ||
| 642 | dbg(" Granularity: %08X\n", data32->granularity); | ||
| 643 | dbg(" Address range min: %08X\n", data32->min_address_range); | ||
| 644 | dbg(" Address range max: %08X\n", data32->max_address_range); | ||
| 645 | dbg(" Address translation offset: %08X\n", data32->address_translation_offset); | ||
| 646 | dbg(" Address Length: %08X\n", data32->address_length); | ||
| 647 | |||
| 648 | if (0xFF != data32->resource_source.index) { | ||
| 649 | dbg(" Resource Source Index: %X\n", data32->resource_source.index); | ||
| 650 | /* dbg(" Resource Source: %s\n", data32->resource_source.string_ptr); */ | ||
| 651 | } | ||
| 652 | |||
| 653 | pciehprm_add_resource(aprh, data32->min_address_range, data32->address_length); | ||
| 654 | } | ||
| 655 | |||
| 656 | static acpi_status acpi_parse_crs( | ||
| 657 | struct acpi_bridge *ab, | ||
| 658 | struct acpi_resource *crsbuf | ||
| 659 | ) | ||
| 660 | { | ||
| 661 | acpi_status status = AE_OK; | ||
| 662 | struct acpi_resource *resource = crsbuf; | ||
| 663 | u8 count = 0; | ||
| 664 | u8 done = 0; | ||
| 665 | |||
| 666 | while (!done) { | ||
| 667 | dbg("acpi_pciehprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++); | ||
| 668 | switch (resource->id) { | ||
| 669 | case ACPI_RSTYPE_IRQ: | ||
| 670 | dbg("Irq -------- Resource\n"); | ||
| 671 | break; | ||
| 672 | case ACPI_RSTYPE_DMA: | ||
| 673 | dbg("DMA -------- Resource\n"); | ||
| 674 | break; | ||
| 675 | case ACPI_RSTYPE_START_DPF: | ||
| 676 | dbg("Start DPF -------- Resource\n"); | ||
| 677 | break; | ||
| 678 | case ACPI_RSTYPE_END_DPF: | ||
| 679 | dbg("End DPF -------- Resource\n"); | ||
| 680 | break; | ||
| 681 | case ACPI_RSTYPE_IO: | ||
| 682 | acpi_parse_io (ab, &resource->data); | ||
| 683 | break; | ||
| 684 | case ACPI_RSTYPE_FIXED_IO: | ||
| 685 | acpi_parse_fixed_io (ab, &resource->data); | ||
| 686 | break; | ||
| 687 | case ACPI_RSTYPE_VENDOR: | ||
| 688 | dbg("Vendor -------- Resource\n"); | ||
| 689 | break; | ||
| 690 | case ACPI_RSTYPE_END_TAG: | ||
| 691 | dbg("End_tag -------- Resource\n"); | ||
| 692 | done = 1; | ||
| 693 | break; | ||
| 694 | case ACPI_RSTYPE_MEM24: | ||
| 695 | dbg("Mem24 -------- Resource\n"); | ||
| 696 | break; | ||
| 697 | case ACPI_RSTYPE_MEM32: | ||
| 698 | dbg("Mem32 -------- Resource\n"); | ||
| 699 | break; | ||
| 700 | case ACPI_RSTYPE_FIXED_MEM32: | ||
| 701 | dbg("Fixed Mem32 -------- Resource\n"); | ||
| 702 | break; | ||
| 703 | case ACPI_RSTYPE_ADDRESS16: | ||
| 704 | acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16); | ||
| 705 | break; | ||
| 706 | case ACPI_RSTYPE_ADDRESS32: | ||
| 707 | acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32); | ||
| 708 | break; | ||
| 709 | case ACPI_RSTYPE_ADDRESS64: | ||
| 710 | info("Address64 -------- Resource unparsed\n"); | ||
| 711 | break; | ||
| 712 | case ACPI_RSTYPE_EXT_IRQ: | ||
| 713 | dbg("Ext Irq -------- Resource\n"); | ||
| 714 | break; | ||
| 715 | default: | ||
| 716 | dbg("Invalid -------- resource type 0x%x\n", resource->id); | ||
| 717 | break; | ||
| 718 | } | ||
| 719 | |||
| 720 | resource = (struct acpi_resource *) ((char *)resource + resource->length); | ||
| 721 | } | ||
| 722 | |||
| 723 | return status; | ||
| 724 | } | ||
| 725 | |||
| 726 | static acpi_status acpi_get_crs( struct acpi_bridge *ab) | ||
| 727 | { | ||
| 728 | acpi_status status; | ||
| 729 | struct acpi_resource *crsbuf; | ||
| 730 | |||
| 731 | status = acpi_evaluate_crs(ab->handle, &crsbuf); | ||
| 732 | if (ACPI_SUCCESS(status)) { | ||
| 733 | status = acpi_parse_crs(ab, crsbuf); | ||
| 734 | kfree(crsbuf); | ||
| 735 | |||
| 736 | pciehp_resource_sort_and_combine(&ab->bus_head); | ||
| 737 | pciehp_resource_sort_and_combine(&ab->io_head); | ||
| 738 | pciehp_resource_sort_and_combine(&ab->mem_head); | ||
| 739 | pciehp_resource_sort_and_combine(&ab->p_mem_head); | ||
| 740 | |||
| 741 | pciehprm_add_resources (&ab->tbus_head, ab->bus_head); | ||
| 742 | pciehprm_add_resources (&ab->tio_head, ab->io_head); | ||
| 743 | pciehprm_add_resources (&ab->tmem_head, ab->mem_head); | ||
| 744 | pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head); | ||
| 745 | } | ||
| 746 | |||
| 747 | return status; | ||
| 748 | } | ||
| 749 | |||
| 750 | /* find acpi_bridge downword from ab. */ | ||
| 751 | static struct acpi_bridge * | ||
| 752 | find_acpi_bridge_by_bus( | ||
| 753 | struct acpi_bridge *ab, | ||
| 754 | int seg, | ||
| 755 | int bus /* pdev->subordinate->number */ | ||
| 756 | ) | ||
| 757 | { | ||
| 758 | struct acpi_bridge *lab = NULL; | ||
| 759 | |||
| 760 | if (!ab) | ||
| 761 | return NULL; | ||
| 762 | |||
| 763 | if ((ab->bus == bus) && (ab->seg == seg)) | ||
| 764 | return ab; | ||
| 765 | |||
| 766 | if (ab->child) | ||
| 767 | lab = find_acpi_bridge_by_bus(ab->child, seg, bus); | ||
| 768 | |||
| 769 | if (!lab) | ||
| 770 | if (ab->next) | ||
| 771 | lab = find_acpi_bridge_by_bus(ab->next, seg, bus); | ||
| 772 | |||
| 773 | return lab; | ||
| 774 | } | ||
| 775 | |||
| 776 | /* | ||
| 777 | * Build a device tree of ACPI PCI Bridges | ||
| 778 | */ | ||
| 779 | static void pciehprm_acpi_register_a_bridge ( | ||
| 780 | struct acpi_bridge **head, | ||
| 781 | struct acpi_bridge *pab, /* parent bridge to which child bridge is added */ | ||
| 782 | struct acpi_bridge *cab /* child bridge to add */ | ||
| 783 | ) | ||
| 784 | { | ||
| 785 | struct acpi_bridge *lpab; | ||
| 786 | struct acpi_bridge *lcab; | ||
| 787 | |||
| 788 | lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus); | ||
| 789 | if (!lpab) { | ||
| 790 | if (!(pab->type & BRIDGE_TYPE_HOST)) | ||
| 791 | warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus); | ||
| 792 | pab->next = *head; | ||
| 793 | *head = pab; | ||
| 794 | lpab = pab; | ||
| 795 | } | ||
| 796 | |||
| 797 | if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab)) | ||
| 798 | return; | ||
| 799 | |||
| 800 | lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus); | ||
| 801 | if (lcab) { | ||
| 802 | if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus)) | ||
| 803 | err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus); | ||
| 804 | return; | ||
| 805 | } else | ||
| 806 | lcab = cab; | ||
| 807 | |||
| 808 | lcab->parent = lpab; | ||
| 809 | lcab->next = lpab->child; | ||
| 810 | lpab->child = lcab; | ||
| 811 | } | ||
| 812 | |||
| 813 | static acpi_status pciehprm_acpi_build_php_slots_callback( | ||
| 814 | acpi_handle handle, | ||
| 815 | u32 Level, | ||
| 816 | void *context, | ||
| 817 | void **retval | ||
| 818 | ) | ||
| 819 | { | ||
| 820 | ulong bus_num; | ||
| 821 | ulong seg_num; | ||
| 822 | ulong sun, adr; | ||
| 823 | ulong padr = 0; | ||
| 824 | acpi_handle phandle = NULL; | ||
| 825 | struct acpi_bridge *pab = (struct acpi_bridge *)context; | ||
| 826 | struct acpi_bridge *lab; | ||
| 827 | acpi_status status; | ||
| 828 | u8 *path_name = acpi_path_name(handle); | ||
| 829 | |||
| 830 | /* get _SUN */ | ||
| 831 | status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun); | ||
| 832 | switch(status) { | ||
| 833 | case AE_NOT_FOUND: | ||
| 834 | return AE_OK; | ||
| 835 | default: | ||
| 836 | if (ACPI_FAILURE(status)) { | ||
| 837 | err("acpi_pciehprm:%s _SUN fail=0x%x\n", path_name, status); | ||
| 838 | return status; | ||
| 839 | } | ||
| 840 | } | ||
| 841 | |||
| 842 | /* get _ADR. _ADR must exist if _SUN exists */ | ||
| 843 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); | ||
| 844 | if (ACPI_FAILURE(status)) { | ||
| 845 | err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status); | ||
| 846 | return status; | ||
| 847 | } | ||
| 848 | |||
| 849 | dbg("acpi_pciehprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr); | ||
| 850 | |||
| 851 | status = acpi_get_parent(handle, &phandle); | ||
| 852 | if (ACPI_FAILURE(status)) { | ||
| 853 | err("acpi_pciehprm:%s get_parent fail=0x%x\n", path_name, status); | ||
| 854 | return (status); | ||
| 855 | } | ||
| 856 | |||
| 857 | bus_num = pab->bus; | ||
| 858 | seg_num = pab->seg; | ||
| 859 | |||
| 860 | if (pab->bus == bus_num) { | ||
| 861 | lab = pab; | ||
| 862 | } else { | ||
| 863 | dbg("WARN: pab is not parent\n"); | ||
| 864 | lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num); | ||
| 865 | if (!lab) { | ||
| 866 | dbg("acpi_pciehprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun); | ||
| 867 | lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL); | ||
| 868 | if (!lab) { | ||
| 869 | err("acpi_pciehprm: alloc for ab fail\n"); | ||
| 870 | return AE_NO_MEMORY; | ||
| 871 | } | ||
| 872 | memset(lab, 0, sizeof(struct acpi_bridge)); | ||
| 873 | |||
| 874 | lab->handle = phandle; | ||
| 875 | lab->pbus = pab->bus; | ||
| 876 | lab->pdevice = (int)(padr >> 16) & 0xffff; | ||
| 877 | lab->pfunction = (int)(padr & 0xffff); | ||
| 878 | lab->bus = (int)bus_num; | ||
| 879 | lab->scanned = 0; | ||
| 880 | lab->type = BRIDGE_TYPE_P2P; | ||
| 881 | |||
| 882 | pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab); | ||
| 883 | } else | ||
| 884 | dbg("acpi_pciehprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun); | ||
| 885 | } | ||
| 886 | |||
| 887 | acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun); | ||
| 888 | |||
| 889 | return (status); | ||
| 890 | } | ||
| 891 | |||
| 892 | static int pciehprm_acpi_build_php_slots( | ||
| 893 | struct acpi_bridge *ab, | ||
| 894 | u32 depth | ||
| 895 | ) | ||
| 896 | { | ||
| 897 | acpi_status status; | ||
| 898 | u8 *path_name = acpi_path_name(ab->handle); | ||
| 899 | |||
| 900 | /* Walk down this pci bridge to get _SUNs if any behind P2P */ | ||
| 901 | status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, | ||
| 902 | ab->handle, | ||
| 903 | depth, | ||
| 904 | pciehprm_acpi_build_php_slots_callback, | ||
| 905 | ab, | ||
| 906 | NULL ); | ||
| 907 | if (ACPI_FAILURE(status)) { | ||
| 908 | 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); | ||
| 909 | return -1; | ||
| 910 | } | ||
| 911 | |||
| 912 | return 0; | ||
| 913 | } | ||
| 914 | |||
| 915 | static void build_a_bridge( | ||
| 916 | struct acpi_bridge *pab, | ||
| 917 | struct acpi_bridge *ab | ||
| 918 | ) | ||
| 919 | { | ||
| 920 | u8 *path_name = acpi_path_name(ab->handle); | ||
| 921 | |||
| 922 | pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab); | ||
| 923 | |||
| 924 | switch (ab->type) { | ||
| 925 | case BRIDGE_TYPE_HOST: | ||
| 926 | dbg("acpi_pciehprm: Registered PCI HOST Bridge(%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n", | ||
| 927 | ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name); | ||
| 928 | break; | ||
| 929 | case BRIDGE_TYPE_P2P: | ||
| 930 | dbg("acpi_pciehprm: Registered PCI P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n", | ||
| 931 | ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name); | ||
| 932 | break; | ||
| 933 | }; | ||
| 934 | |||
| 935 | /* build any immediate PHP slots under this pci bridge */ | ||
| 936 | pciehprm_acpi_build_php_slots(ab, 1); | ||
| 937 | } | ||
| 938 | |||
| 939 | static struct acpi_bridge * add_p2p_bridge( | ||
| 940 | acpi_handle handle, | ||
| 941 | struct acpi_bridge *pab, /* parent */ | ||
| 942 | ulong adr | ||
| 943 | ) | ||
| 944 | { | ||
| 945 | struct acpi_bridge *ab; | ||
| 946 | struct pci_dev *pdev; | ||
| 947 | ulong devnum, funcnum; | ||
| 948 | u8 *path_name = acpi_path_name(handle); | ||
| 949 | |||
| 950 | ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL); | ||
| 951 | if (!ab) { | ||
| 952 | err("acpi_pciehprm: alloc for ab fail\n"); | ||
| 953 | return NULL; | ||
| 954 | } | ||
| 955 | memset(ab, 0, sizeof(struct acpi_bridge)); | ||
| 956 | |||
| 957 | devnum = (adr >> 16) & 0xffff; | ||
| 958 | funcnum = adr & 0xffff; | ||
| 959 | |||
| 960 | pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum)); | ||
| 961 | if (!pdev || !pdev->subordinate) { | ||
| 962 | err("acpi_pciehprm:%s is not a P2P Bridge\n", path_name); | ||
| 963 | kfree(ab); | ||
| 964 | return NULL; | ||
| 965 | } | ||
| 966 | |||
| 967 | ab->handle = handle; | ||
| 968 | ab->seg = pab->seg; | ||
| 969 | ab->pbus = pab->bus; /* or pdev->bus->number */ | ||
| 970 | ab->pdevice = devnum; /* or PCI_SLOT(pdev->devfn) */ | ||
| 971 | ab->pfunction = funcnum; /* or PCI_FUNC(pdev->devfn) */ | ||
| 972 | ab->bus = pdev->subordinate->number; | ||
| 973 | ab->scanned = 0; | ||
| 974 | ab->type = BRIDGE_TYPE_P2P; | ||
| 975 | |||
| 976 | dbg("acpi_pciehprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n", | ||
| 977 | pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), | ||
| 978 | pab->bus, (u32)devnum, (u32)funcnum, path_name); | ||
| 979 | |||
| 980 | build_a_bridge(pab, ab); | ||
| 981 | |||
| 982 | return ab; | ||
| 983 | } | ||
| 984 | |||
| 985 | static acpi_status scan_p2p_bridge( | ||
| 986 | acpi_handle handle, | ||
| 987 | u32 Level, | ||
| 988 | void *context, | ||
| 989 | void **retval | ||
| 990 | ) | ||
| 991 | { | ||
| 992 | struct acpi_bridge *pab = (struct acpi_bridge *)context; | ||
| 993 | struct acpi_bridge *ab; | ||
| 994 | acpi_status status; | ||
| 995 | ulong adr = 0; | ||
| 996 | u8 *path_name = acpi_path_name(handle); | ||
| 997 | ulong devnum, funcnum; | ||
| 998 | struct pci_dev *pdev; | ||
| 999 | |||
| 1000 | /* get device, function */ | ||
| 1001 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); | ||
| 1002 | if (ACPI_FAILURE(status)) { | ||
| 1003 | if (status != AE_NOT_FOUND) | ||
| 1004 | err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status); | ||
| 1005 | return AE_OK; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | devnum = (adr >> 16) & 0xffff; | ||
| 1009 | funcnum = adr & 0xffff; | ||
| 1010 | |||
| 1011 | pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum)); | ||
| 1012 | if (!pdev) | ||
| 1013 | return AE_OK; | ||
| 1014 | if (!pdev->subordinate) | ||
| 1015 | return AE_OK; | ||
| 1016 | |||
| 1017 | ab = add_p2p_bridge(handle, pab, adr); | ||
| 1018 | if (ab) { | ||
| 1019 | status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, | ||
| 1020 | handle, | ||
| 1021 | (u32)1, | ||
| 1022 | scan_p2p_bridge, | ||
| 1023 | ab, | ||
| 1024 | NULL); | ||
| 1025 | if (ACPI_FAILURE(status)) | 222 | if (ACPI_FAILURE(status)) |
| 1026 | dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status); | 223 | break; |
| 1027 | } | ||
| 1028 | |||
| 1029 | return AE_OK; | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | static struct acpi_bridge * add_host_bridge( | ||
| 1033 | acpi_handle handle, | ||
| 1034 | ulong segnum, | ||
| 1035 | ulong busnum | ||
| 1036 | ) | ||
| 1037 | { | ||
| 1038 | ulong adr = 0; | ||
| 1039 | acpi_status status; | ||
| 1040 | struct acpi_bridge *ab; | ||
| 1041 | u8 *path_name = acpi_path_name(handle); | ||
| 1042 | |||
| 1043 | /* get device, function: host br adr is always 0000 though. */ | ||
| 1044 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); | ||
| 1045 | if (ACPI_FAILURE(status)) { | ||
| 1046 | err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status); | ||
| 1047 | return NULL; | ||
| 1048 | } | ||
| 1049 | dbg("acpi_pciehprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, | ||
| 1050 | (u32)busnum, (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name); | ||
| 1051 | |||
| 1052 | ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL); | ||
| 1053 | if (!ab) { | ||
| 1054 | err("acpi_pciehprm: alloc for ab fail\n"); | ||
| 1055 | return NULL; | ||
| 1056 | } | ||
| 1057 | memset(ab, 0, sizeof(struct acpi_bridge)); | ||
| 1058 | |||
| 1059 | ab->handle = handle; | ||
| 1060 | ab->seg = (int)segnum; | ||
| 1061 | ab->bus = ab->pbus = (int)busnum; | ||
| 1062 | ab->pdevice = (int)(adr >> 16) & 0xffff; | ||
| 1063 | ab->pfunction = (int)(adr & 0xffff); | ||
| 1064 | ab->scanned = 0; | ||
| 1065 | ab->type = BRIDGE_TYPE_HOST; | ||
| 1066 | |||
| 1067 | /* get root pci bridge's current resources */ | ||
| 1068 | status = acpi_get_crs(ab); | ||
| 1069 | if (ACPI_FAILURE(status)) { | ||
| 1070 | err("acpi_pciehprm:%s evaluate _CRS fail=0x%x\n", path_name, status); | ||
| 1071 | kfree(ab); | ||
| 1072 | return NULL; | ||
| 1073 | } | ||
| 1074 | |||
| 1075 | status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); | ||
| 1076 | if (ACPI_FAILURE(status)) { | ||
| 1077 | err("%s: status %x\n", __FUNCTION__, status); | ||
| 1078 | osc_run_status = (status == AE_NOT_FOUND) ? OSC_NOT_EXIST : OSC_RUN_FAILED; | ||
| 1079 | } else { | ||
| 1080 | osc_run_status = NC_RUN_SUCCESS; | ||
| 1081 | } | ||
| 1082 | dbg("%s: osc_run_status %x\n", __FUNCTION__, osc_run_status); | ||
| 1083 | |||
| 1084 | build_a_bridge(ab, ab); | ||
| 1085 | |||
| 1086 | return ab; | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | static acpi_status acpi_scan_from_root_pci_callback ( | ||
| 1090 | acpi_handle handle, | ||
| 1091 | u32 Level, | ||
| 1092 | void *context, | ||
| 1093 | void **retval | ||
| 1094 | ) | ||
| 1095 | { | ||
| 1096 | ulong segnum = 0; | ||
| 1097 | ulong busnum = 0; | ||
| 1098 | acpi_status status; | ||
| 1099 | struct acpi_bridge *ab; | ||
| 1100 | u8 *path_name = acpi_path_name(handle); | ||
| 1101 | |||
| 1102 | /* get bus number of this pci root bridge */ | ||
| 1103 | status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum); | ||
| 1104 | if (ACPI_FAILURE(status)) { | ||
| 1105 | if (status != AE_NOT_FOUND) { | ||
| 1106 | err("acpi_pciehprm:%s evaluate _SEG fail=0x%x\n", path_name, status); | ||
| 1107 | return status; | ||
| 1108 | } | ||
| 1109 | segnum = 0; | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | /* get bus number of this pci root bridge */ | ||
| 1113 | status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum); | ||
| 1114 | if (ACPI_FAILURE(status)) { | ||
| 1115 | err("acpi_pciehprm:%s evaluate _BBN fail=0x%x\n", path_name, status); | ||
| 1116 | return (status); | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | ab = add_host_bridge(handle, segnum, busnum); | ||
| 1120 | if (ab) { | ||
| 1121 | status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, | ||
| 1122 | handle, | ||
| 1123 | 1, | ||
| 1124 | scan_p2p_bridge, | ||
| 1125 | ab, | ||
| 1126 | NULL); | ||
| 1127 | if (ACPI_FAILURE(status)) | ||
| 1128 | dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status); | ||
| 1129 | } | 224 | } |
| 1130 | 225 | ||
| 1131 | return AE_OK; | 226 | err("Cannot get control of hotplug hardware for pci %s\n", |
| 227 | pci_name(dev)); | ||
| 228 | return -1; | ||
| 1132 | } | 229 | } |
| 1133 | 230 | ||
| 1134 | static int pciehprm_acpi_scan_pci (void) | 231 | void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, |
| 232 | struct hotplug_params *hpp) | ||
| 1135 | { | 233 | { |
| 1136 | acpi_status status; | 234 | acpi_status status = AE_NOT_FOUND; |
| 235 | struct pci_dev *pdev = dev; | ||
| 1137 | 236 | ||
| 1138 | /* | 237 | /* |
| 1139 | * TBD: traverse LDM device tree with the help of | 238 | * _HPP settings apply to all child buses, until another _HPP is |
| 1140 | * unified ACPI augmented for php device population. | 239 | * encountered. If we don't find an _HPP for the input pci dev, |
| 240 | * look for it in the parent device scope since that would apply to | ||
| 241 | * this pci dev. If we don't find any _HPP, use hardcoded defaults | ||
| 1141 | */ | 242 | */ |
| 1142 | status = acpi_get_devices ( PCI_ROOT_HID_STRING, | 243 | while (pdev && (ACPI_FAILURE(status))) { |
| 1143 | acpi_scan_from_root_pci_callback, | 244 | acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); |
| 1144 | NULL, | 245 | if (!handle) |
| 1145 | NULL ); | 246 | break; |
| 1146 | if (ACPI_FAILURE(status)) { | 247 | status = acpi_run_hpp(handle, hpp); |
| 1147 | err("acpi_pciehprm:get_device PCI ROOT HID fail=0x%x\n", status); | 248 | if (!(pdev->bus->parent)) |
| 1148 | return -1; | 249 | break; |
| 1149 | } | 250 | /* Check if a parent object supports _HPP */ |
| 1150 | 251 | pdev = pdev->bus->parent->self; | |
| 1151 | return 0; | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | int pciehprm_init(enum php_ctlr_type ctlr_type) | ||
| 1155 | { | ||
| 1156 | int rc; | ||
| 1157 | |||
| 1158 | if (ctlr_type != PCI) | ||
| 1159 | return -ENODEV; | ||
| 1160 | |||
| 1161 | dbg("pciehprm ACPI init <enter>\n"); | ||
| 1162 | acpi_bridges_head = NULL; | ||
| 1163 | |||
| 1164 | /* construct PCI bus:device tree of acpi_handles */ | ||
| 1165 | rc = pciehprm_acpi_scan_pci(); | ||
| 1166 | if (rc) | ||
| 1167 | return rc; | ||
| 1168 | |||
| 1169 | if ((oshp_run_status != NC_RUN_SUCCESS) && (osc_run_status != NC_RUN_SUCCESS)) { | ||
| 1170 | err("Fails to gain control of native hot-plug\n"); | ||
| 1171 | rc = -ENODEV; | ||
| 1172 | } | ||
| 1173 | |||
| 1174 | dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success"); | ||
| 1175 | return rc; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | static void free_a_slot(struct acpi_php_slot *aps) | ||
| 1179 | { | ||
| 1180 | 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); | ||
| 1181 | |||
| 1182 | free_pci_resource (aps->io_head); | ||
| 1183 | free_pci_resource (aps->bus_head); | ||
| 1184 | free_pci_resource (aps->mem_head); | ||
| 1185 | free_pci_resource (aps->p_mem_head); | ||
| 1186 | |||
| 1187 | kfree(aps); | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | static void free_a_bridge( struct acpi_bridge *ab) | ||
| 1191 | { | ||
| 1192 | struct acpi_php_slot *aps, *next; | ||
| 1193 | |||
| 1194 | switch (ab->type) { | ||
| 1195 | case BRIDGE_TYPE_HOST: | ||
| 1196 | dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n", | ||
| 1197 | ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction); | ||
| 1198 | break; | ||
| 1199 | case BRIDGE_TYPE_P2P: | ||
| 1200 | dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n", | ||
| 1201 | ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction); | ||
| 1202 | break; | ||
| 1203 | }; | ||
| 1204 | |||
| 1205 | /* free slots first */ | ||
| 1206 | for (aps = ab->slots; aps; aps = next) { | ||
| 1207 | next = aps->next; | ||
| 1208 | free_a_slot(aps); | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | free_pci_resource (ab->io_head); | ||
| 1212 | free_pci_resource (ab->tio_head); | ||
| 1213 | free_pci_resource (ab->bus_head); | ||
| 1214 | free_pci_resource (ab->tbus_head); | ||
| 1215 | free_pci_resource (ab->mem_head); | ||
| 1216 | free_pci_resource (ab->tmem_head); | ||
| 1217 | free_pci_resource (ab->p_mem_head); | ||
| 1218 | free_pci_resource (ab->tp_mem_head); | ||
| 1219 | |||
| 1220 | kfree(ab); | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | static void pciehprm_free_bridges ( struct acpi_bridge *ab) | ||
| 1224 | { | ||
| 1225 | if (!ab) | ||
| 1226 | return; | ||
| 1227 | |||
| 1228 | if (ab->child) | ||
| 1229 | pciehprm_free_bridges (ab->child); | ||
| 1230 | |||
| 1231 | if (ab->next) | ||
| 1232 | pciehprm_free_bridges (ab->next); | ||
| 1233 | |||
| 1234 | free_a_bridge(ab); | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | void pciehprm_cleanup(void) | ||
| 1238 | { | ||
| 1239 | pciehprm_free_bridges (acpi_bridges_head); | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | static int get_number_of_slots ( | ||
| 1243 | struct acpi_bridge *ab, | ||
| 1244 | int selfonly | ||
| 1245 | ) | ||
| 1246 | { | ||
| 1247 | struct acpi_php_slot *aps; | ||
| 1248 | int prev_slot = -1; | ||
| 1249 | int slot_num = 0; | ||
| 1250 | |||
| 1251 | for ( aps = ab->slots; aps; aps = aps->next) | ||
| 1252 | if (aps->dev != prev_slot) { | ||
| 1253 | prev_slot = aps->dev; | ||
| 1254 | slot_num++; | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | if (ab->child) | ||
| 1258 | slot_num += get_number_of_slots (ab->child, 0); | ||
| 1259 | |||
| 1260 | if (selfonly) | ||
| 1261 | return slot_num; | ||
| 1262 | |||
| 1263 | if (ab->next) | ||
| 1264 | slot_num += get_number_of_slots (ab->next, 0); | ||
| 1265 | |||
| 1266 | return slot_num; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | static int print_acpi_resources (struct acpi_bridge *ab) | ||
| 1270 | { | ||
| 1271 | struct acpi_php_slot *aps; | ||
| 1272 | int i; | ||
| 1273 | |||
| 1274 | switch (ab->type) { | ||
| 1275 | case BRIDGE_TYPE_HOST: | ||
| 1276 | dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle)); | ||
| 1277 | break; | ||
| 1278 | case BRIDGE_TYPE_P2P: | ||
| 1279 | dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle)); | ||
| 1280 | break; | ||
| 1281 | }; | ||
| 1282 | |||
| 1283 | print_pci_resources (ab); | ||
| 1284 | |||
| 1285 | for ( i = -1, aps = ab->slots; aps; aps = aps->next) { | ||
| 1286 | if (aps->dev == i) | ||
| 1287 | continue; | ||
| 1288 | dbg(" Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun); | ||
| 1289 | print_slot_resources(aps); | ||
| 1290 | i = aps->dev; | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | if (ab->child) | ||
| 1294 | print_acpi_resources (ab->child); | ||
| 1295 | |||
| 1296 | if (ab->next) | ||
| 1297 | print_acpi_resources (ab->next); | ||
| 1298 | |||
| 1299 | return 0; | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | int pciehprm_print_pirt(void) | ||
| 1303 | { | ||
| 1304 | dbg("PCIEHPRM ACPI Slots\n"); | ||
| 1305 | if (acpi_bridges_head) | ||
| 1306 | print_acpi_resources (acpi_bridges_head); | ||
| 1307 | |||
| 1308 | return 0; | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | static struct acpi_php_slot * get_acpi_slot ( | ||
| 1312 | struct acpi_bridge *ab, | ||
| 1313 | u32 sun | ||
| 1314 | ) | ||
| 1315 | { | ||
| 1316 | struct acpi_php_slot *aps = NULL; | ||
| 1317 | |||
| 1318 | for ( aps = ab->slots; aps; aps = aps->next) | ||
| 1319 | if (aps->sun == sun) | ||
| 1320 | return aps; | ||
| 1321 | |||
| 1322 | if (!aps && ab->child) { | ||
| 1323 | aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun); | ||
| 1324 | if (aps) | ||
| 1325 | return aps; | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | if (!aps && ab->next) { | ||
| 1329 | aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun); | ||
| 1330 | if (aps) | ||
| 1331 | return aps; | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | return aps; | ||
| 1335 | |||
| 1336 | } | ||
| 1337 | |||
| 1338 | #if 0 | ||
| 1339 | void * pciehprm_get_slot(struct slot *slot) | ||
| 1340 | { | ||
| 1341 | struct acpi_bridge *ab = acpi_bridges_head; | ||
| 1342 | struct acpi_php_slot *aps = get_acpi_slot (ab, slot->number); | ||
| 1343 | |||
| 1344 | aps->slot = slot; | ||
| 1345 | |||
| 1346 | 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); | ||
| 1347 | |||
| 1348 | return (void *)aps; | ||
| 1349 | } | ||
| 1350 | #endif | ||
| 1351 | |||
| 1352 | static void pciehprm_dump_func_res( struct pci_func *fun) | ||
| 1353 | { | ||
| 1354 | struct pci_func *func = fun; | ||
| 1355 | |||
| 1356 | if (func->bus_head) { | ||
| 1357 | dbg(": BUS Resources:\n"); | ||
| 1358 | print_pci_resource (func->bus_head); | ||
| 1359 | } | ||
| 1360 | if (func->io_head) { | ||
| 1361 | dbg(": IO Resources:\n"); | ||
| 1362 | print_pci_resource (func->io_head); | ||
| 1363 | } | ||
| 1364 | if (func->mem_head) { | ||
| 1365 | dbg(": MEM Resources:\n"); | ||
| 1366 | print_pci_resource (func->mem_head); | ||
| 1367 | } | ||
| 1368 | if (func->p_mem_head) { | ||
| 1369 | dbg(": PMEM Resources:\n"); | ||
| 1370 | print_pci_resource (func->p_mem_head); | ||
| 1371 | } | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | static void pciehprm_dump_ctrl_res( struct controller *ctlr) | ||
| 1375 | { | ||
| 1376 | struct controller *ctrl = ctlr; | ||
| 1377 | |||
| 1378 | if (ctrl->bus_head) { | ||
| 1379 | dbg(": BUS Resources:\n"); | ||
| 1380 | print_pci_resource (ctrl->bus_head); | ||
| 1381 | } | ||
| 1382 | if (ctrl->io_head) { | ||
| 1383 | dbg(": IO Resources:\n"); | ||
| 1384 | print_pci_resource (ctrl->io_head); | ||
| 1385 | } | ||
| 1386 | if (ctrl->mem_head) { | ||
| 1387 | dbg(": MEM Resources:\n"); | ||
| 1388 | print_pci_resource (ctrl->mem_head); | ||
| 1389 | } | ||
| 1390 | if (ctrl->p_mem_head) { | ||
| 1391 | dbg(": PMEM Resources:\n"); | ||
| 1392 | print_pci_resource (ctrl->p_mem_head); | ||
| 1393 | } | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | static int pciehprm_get_used_resources ( | ||
| 1397 | struct controller *ctrl, | ||
| 1398 | struct pci_func *func | ||
| 1399 | ) | ||
| 1400 | { | ||
| 1401 | return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD); | ||
| 1402 | } | ||
| 1403 | |||
| 1404 | static int configure_existing_function( | ||
| 1405 | struct controller *ctrl, | ||
| 1406 | struct pci_func *func | ||
| 1407 | ) | ||
| 1408 | { | ||
| 1409 | int rc; | ||
| 1410 | |||
| 1411 | /* see how much resources the func has used. */ | ||
| 1412 | rc = pciehprm_get_used_resources (ctrl, func); | ||
| 1413 | |||
| 1414 | if (!rc) { | ||
| 1415 | /* subtract the resources used by the func from ctrl resources */ | ||
| 1416 | rc = pciehprm_delete_resources (&ctrl->bus_head, func->bus_head); | ||
| 1417 | rc |= pciehprm_delete_resources (&ctrl->io_head, func->io_head); | ||
| 1418 | rc |= pciehprm_delete_resources (&ctrl->mem_head, func->mem_head); | ||
| 1419 | rc |= pciehprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head); | ||
| 1420 | if (rc) | ||
| 1421 | warn("aCEF: cannot del used resources\n"); | ||
| 1422 | } else | ||
| 1423 | err("aCEF: cannot get used resources\n"); | ||
| 1424 | |||
| 1425 | return rc; | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | static int bind_pci_resources_to_slots ( struct controller *ctrl) | ||
| 1429 | { | ||
| 1430 | struct pci_func *func, new_func; | ||
| 1431 | int busn = ctrl->slot_bus; | ||
| 1432 | int devn, funn; | ||
| 1433 | u32 vid; | ||
| 1434 | |||
| 1435 | for (devn = 0; devn < 32; devn++) { | ||
| 1436 | for (funn = 0; funn < 8; funn++) { | ||
| 1437 | /* | ||
| 1438 | if (devn == ctrl->device && funn == ctrl->function) | ||
| 1439 | continue; | ||
| 1440 | */ | ||
| 1441 | /* find out if this entry is for an occupied slot */ | ||
| 1442 | vid = 0xFFFFFFFF; | ||
| 1443 | pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); | ||
| 1444 | |||
| 1445 | if (vid != 0xFFFFFFFF) { | ||
| 1446 | dbg("%s: vid = %x\n", __FUNCTION__, vid); | ||
| 1447 | func = pciehp_slot_find(busn, devn, funn); | ||
| 1448 | if (!func) { | ||
| 1449 | memset(&new_func, 0, sizeof(struct pci_func)); | ||
| 1450 | new_func.bus = busn; | ||
| 1451 | new_func.device = devn; | ||
| 1452 | new_func.function = funn; | ||
| 1453 | new_func.is_a_board = 1; | ||
| 1454 | configure_existing_function(ctrl, &new_func); | ||
| 1455 | pciehprm_dump_func_res(&new_func); | ||
| 1456 | } else { | ||
| 1457 | configure_existing_function(ctrl, func); | ||
| 1458 | pciehprm_dump_func_res(func); | ||
| 1459 | } | ||
| 1460 | dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); | ||
| 1461 | } | ||
| 1462 | } | ||
| 1463 | } | ||
| 1464 | |||
| 1465 | return 0; | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | static int bind_pci_resources( | ||
| 1469 | struct controller *ctrl, | ||
| 1470 | struct acpi_bridge *ab | ||
| 1471 | ) | ||
| 1472 | { | ||
| 1473 | int status = 0; | ||
| 1474 | |||
| 1475 | if (ab->bus_head) { | ||
| 1476 | dbg("bapr: BUS Resources add on PCI 0x%x\n", ab->bus); | ||
| 1477 | status = pciehprm_add_resources (&ctrl->bus_head, ab->bus_head); | ||
| 1478 | if (pciehprm_delete_resources (&ab->bus_head, ctrl->bus_head)) | ||
| 1479 | warn("bapr: cannot sub BUS Resource on PCI 0x%x\n", ab->bus); | ||
| 1480 | if (status) { | ||
| 1481 | err("bapr: BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); | ||
| 1482 | return status; | ||
| 1483 | } | ||
| 1484 | } else | ||
| 1485 | info("bapr: No BUS Resource on PCI 0x%x.\n", ab->bus); | ||
| 1486 | |||
| 1487 | if (ab->io_head) { | ||
| 1488 | dbg("bapr: IO Resources add on PCI 0x%x\n", ab->bus); | ||
| 1489 | status = pciehprm_add_resources (&ctrl->io_head, ab->io_head); | ||
| 1490 | if (pciehprm_delete_resources (&ab->io_head, ctrl->io_head)) | ||
| 1491 | warn("bapr: cannot sub IO Resource on PCI 0x%x\n", ab->bus); | ||
| 1492 | if (status) { | ||
| 1493 | err("bapr: IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); | ||
| 1494 | return status; | ||
| 1495 | } | ||
| 1496 | } else | ||
| 1497 | info("bapr: No IO Resource on PCI 0x%x.\n", ab->bus); | ||
| 1498 | |||
| 1499 | if (ab->mem_head) { | ||
| 1500 | dbg("bapr: MEM Resources add on PCI 0x%x\n", ab->bus); | ||
| 1501 | status = pciehprm_add_resources (&ctrl->mem_head, ab->mem_head); | ||
| 1502 | if (pciehprm_delete_resources (&ab->mem_head, ctrl->mem_head)) | ||
| 1503 | warn("bapr: cannot sub MEM Resource on PCI 0x%x\n", ab->bus); | ||
| 1504 | if (status) { | ||
| 1505 | err("bapr: MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); | ||
| 1506 | return status; | ||
| 1507 | } | ||
| 1508 | } else | ||
| 1509 | info("bapr: No MEM Resource on PCI 0x%x.\n", ab->bus); | ||
| 1510 | |||
| 1511 | if (ab->p_mem_head) { | ||
| 1512 | dbg("bapr: PMEM Resources add on PCI 0x%x\n", ab->bus); | ||
| 1513 | status = pciehprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head); | ||
| 1514 | if (pciehprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head)) | ||
| 1515 | warn("bapr: cannot sub PMEM Resource on PCI 0x%x\n", ab->bus); | ||
| 1516 | if (status) { | ||
| 1517 | err("bapr: PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); | ||
| 1518 | return status; | ||
| 1519 | } | ||
| 1520 | } else | ||
| 1521 | info("bapr: No PMEM Resource on PCI 0x%x.\n", ab->bus); | ||
| 1522 | |||
| 1523 | return status; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | static int no_pci_resources( struct acpi_bridge *ab) | ||
| 1527 | { | ||
| 1528 | return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head); | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | static int find_pci_bridge_resources ( | ||
| 1532 | struct controller *ctrl, | ||
| 1533 | struct acpi_bridge *ab | ||
| 1534 | ) | ||
| 1535 | { | ||
| 1536 | int rc = 0; | ||
| 1537 | struct pci_func func; | ||
| 1538 | |||
| 1539 | memset(&func, 0, sizeof(struct pci_func)); | ||
| 1540 | |||
| 1541 | func.bus = ab->pbus; | ||
| 1542 | func.device = ab->pdevice; | ||
| 1543 | func.function = ab->pfunction; | ||
| 1544 | func.is_a_board = 1; | ||
| 1545 | |||
| 1546 | /* Get used resources for this PCI bridge */ | ||
| 1547 | rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD); | ||
| 1548 | |||
| 1549 | ab->io_head = func.io_head; | ||
| 1550 | ab->mem_head = func.mem_head; | ||
| 1551 | ab->p_mem_head = func.p_mem_head; | ||
| 1552 | ab->bus_head = func.bus_head; | ||
| 1553 | if (ab->bus_head) | ||
| 1554 | pciehprm_delete_resource(&ab->bus_head, ctrl->pci_dev->subordinate->number, 1); | ||
| 1555 | |||
| 1556 | return rc; | ||
| 1557 | } | ||
| 1558 | |||
| 1559 | static int get_pci_resources_from_bridge( | ||
| 1560 | struct controller *ctrl, | ||
| 1561 | struct acpi_bridge *ab | ||
| 1562 | ) | ||
| 1563 | { | ||
| 1564 | int rc = 0; | ||
| 1565 | |||
| 1566 | dbg("grfb: Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus); | ||
| 1567 | |||
| 1568 | rc = find_pci_bridge_resources (ctrl, ab); | ||
| 1569 | |||
| 1570 | pciehp_resource_sort_and_combine(&ab->bus_head); | ||
| 1571 | pciehp_resource_sort_and_combine(&ab->io_head); | ||
| 1572 | pciehp_resource_sort_and_combine(&ab->mem_head); | ||
| 1573 | pciehp_resource_sort_and_combine(&ab->p_mem_head); | ||
| 1574 | |||
| 1575 | pciehprm_add_resources (&ab->tbus_head, ab->bus_head); | ||
| 1576 | pciehprm_add_resources (&ab->tio_head, ab->io_head); | ||
| 1577 | pciehprm_add_resources (&ab->tmem_head, ab->mem_head); | ||
| 1578 | pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head); | ||
| 1579 | |||
| 1580 | return rc; | ||
| 1581 | } | ||
| 1582 | |||
| 1583 | static int get_pci_resources( | ||
| 1584 | struct controller *ctrl, | ||
| 1585 | struct acpi_bridge *ab | ||
| 1586 | ) | ||
| 1587 | { | ||
| 1588 | int rc = 0; | ||
| 1589 | |||
| 1590 | if (no_pci_resources(ab)) { | ||
| 1591 | dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus); | ||
| 1592 | rc = get_pci_resources_from_bridge(ctrl, ab); | ||
| 1593 | } | ||
| 1594 | |||
| 1595 | return rc; | ||
| 1596 | } | ||
| 1597 | |||
| 1598 | /* | ||
| 1599 | * Get resources for this ctrl. | ||
| 1600 | * 1. get total resources from ACPI _CRS or bridge (this ctrl) | ||
| 1601 | * 2. find used resources of existing adapters | ||
| 1602 | * 3. subtract used resources from total resources | ||
| 1603 | */ | ||
| 1604 | int pciehprm_find_available_resources( struct controller *ctrl) | ||
| 1605 | { | ||
| 1606 | int rc = 0; | ||
| 1607 | struct acpi_bridge *ab; | ||
| 1608 | |||
| 1609 | ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number); | ||
| 1610 | if (!ab) { | ||
| 1611 | err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number); | ||
| 1612 | return -1; | ||
| 1613 | } | ||
| 1614 | if (no_pci_resources(ab)) { | ||
| 1615 | rc = get_pci_resources(ctrl, ab); | ||
| 1616 | if (rc) { | ||
| 1617 | err("pfar:cannot get pci resources of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number); | ||
| 1618 | return -1; | ||
| 1619 | } | ||
| 1620 | } | ||
| 1621 | |||
| 1622 | rc = bind_pci_resources(ctrl, ab); | ||
| 1623 | dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number); | ||
| 1624 | pciehprm_dump_ctrl_res(ctrl); | ||
| 1625 | |||
| 1626 | bind_pci_resources_to_slots (ctrl); | ||
| 1627 | |||
| 1628 | dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number); | ||
| 1629 | pciehprm_dump_ctrl_res(ctrl); | ||
| 1630 | |||
| 1631 | return rc; | ||
| 1632 | } | ||
| 1633 | |||
| 1634 | int pciehprm_set_hpp( | ||
| 1635 | struct controller *ctrl, | ||
| 1636 | struct pci_func *func, | ||
| 1637 | u8 card_type | ||
| 1638 | ) | ||
| 1639 | { | ||
| 1640 | struct acpi_bridge *ab; | ||
| 1641 | struct pci_bus lpci_bus, *pci_bus; | ||
| 1642 | int rc = 0; | ||
| 1643 | unsigned int devfn; | ||
| 1644 | u8 cls= 0x08; /* default cache line size */ | ||
| 1645 | u8 lt = 0x40; /* default latency timer */ | ||
| 1646 | u8 ep = 0; | ||
| 1647 | u8 es = 0; | ||
| 1648 | |||
| 1649 | memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); | ||
| 1650 | pci_bus = &lpci_bus; | ||
| 1651 | pci_bus->number = func->bus; | ||
| 1652 | devfn = PCI_DEVFN(func->device, func->function); | ||
| 1653 | |||
| 1654 | ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); | ||
| 1655 | |||
| 1656 | if (ab) { | ||
| 1657 | if (ab->_hpp) { | ||
| 1658 | lt = (u8)ab->_hpp->latency_timer; | ||
| 1659 | cls = (u8)ab->_hpp->cache_line_size; | ||
| 1660 | ep = (u8)ab->_hpp->enable_perr; | ||
| 1661 | es = (u8)ab->_hpp->enable_serr; | ||
| 1662 | } else | ||
| 1663 | dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function); | ||
| 1664 | } else | ||
| 1665 | dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function); | ||
| 1666 | |||
| 1667 | |||
| 1668 | if (card_type == PCI_HEADER_TYPE_BRIDGE) { | ||
| 1669 | /* set subordinate Latency Timer */ | ||
| 1670 | rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt); | ||
| 1671 | } | 252 | } |
| 1672 | |||
| 1673 | /* set base Latency Timer */ | ||
| 1674 | rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt); | ||
| 1675 | dbg(" set latency timer =0x%02x: %x\n", lt, rc); | ||
| 1676 | |||
| 1677 | rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls); | ||
| 1678 | dbg(" set cache_line_size=0x%02x: %x\n", cls, rc); | ||
| 1679 | |||
| 1680 | return rc; | ||
| 1681 | } | 253 | } |
| 1682 | 254 | ||
| 1683 | void pciehprm_enable_card( | ||
| 1684 | struct controller *ctrl, | ||
| 1685 | struct pci_func *func, | ||
| 1686 | u8 card_type) | ||
| 1687 | { | ||
| 1688 | u16 command, cmd, bcommand, bcmd; | ||
| 1689 | struct pci_bus lpci_bus, *pci_bus; | ||
| 1690 | struct acpi_bridge *ab; | ||
| 1691 | unsigned int devfn; | ||
| 1692 | int rc; | ||
| 1693 | |||
| 1694 | memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); | ||
| 1695 | pci_bus = &lpci_bus; | ||
| 1696 | pci_bus->number = func->bus; | ||
| 1697 | devfn = PCI_DEVFN(func->device, func->function); | ||
| 1698 | |||
| 1699 | rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &cmd); | ||
| 1700 | |||
| 1701 | if (card_type == PCI_HEADER_TYPE_BRIDGE) { | ||
| 1702 | rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcmd); | ||
| 1703 | } | ||
| 1704 | |||
| 1705 | command = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | ||
| 1706 | | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; | ||
| 1707 | bcommand = bcmd | PCI_BRIDGE_CTL_NO_ISA; | ||
| 1708 | |||
| 1709 | ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); | ||
| 1710 | if (ab) { | ||
| 1711 | if (ab->_hpp) { | ||
| 1712 | if (ab->_hpp->enable_perr) { | ||
| 1713 | command |= PCI_COMMAND_PARITY; | ||
| 1714 | bcommand |= PCI_BRIDGE_CTL_PARITY; | ||
| 1715 | } else { | ||
| 1716 | command &= ~PCI_COMMAND_PARITY; | ||
| 1717 | bcommand &= ~PCI_BRIDGE_CTL_PARITY; | ||
| 1718 | } | ||
| 1719 | if (ab->_hpp->enable_serr) { | ||
| 1720 | command |= PCI_COMMAND_SERR; | ||
| 1721 | bcommand |= PCI_BRIDGE_CTL_SERR; | ||
| 1722 | } else { | ||
| 1723 | command &= ~PCI_COMMAND_SERR; | ||
| 1724 | bcommand &= ~PCI_BRIDGE_CTL_SERR; | ||
| 1725 | } | ||
| 1726 | } else | ||
| 1727 | dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function); | ||
| 1728 | } else | ||
| 1729 | dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function); | ||
| 1730 | |||
| 1731 | if (command != cmd) { | ||
| 1732 | rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); | ||
| 1733 | } | ||
| 1734 | if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) { | ||
| 1735 | rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand); | ||
| 1736 | } | ||
| 1737 | } | ||
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c index 76c727c74cc0..29180dfe8493 100644 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c | |||
| @@ -27,479 +27,21 @@ | |||
| 27 | * | 27 | * |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #include <linux/config.h> | ||
| 31 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
| 33 | #include <linux/types.h> | 32 | #include <linux/types.h> |
| 34 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
| 35 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
| 36 | #include <linux/init.h> | ||
| 37 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 38 | |||
| 39 | #include <asm/uaccess.h> | ||
| 40 | #ifdef CONFIG_IA64 | ||
| 41 | #include <asm/iosapic.h> | ||
| 42 | #endif | ||
| 43 | |||
| 44 | #include "pciehp.h" | 36 | #include "pciehp.h" |
| 45 | #include "pciehprm.h" | ||
| 46 | #include "pciehprm_nonacpi.h" | ||
| 47 | |||
| 48 | 37 | ||
| 49 | void pciehprm_cleanup(void) | 38 | void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, |
| 39 | struct hotplug_params *hpp) | ||
| 50 | { | 40 | { |
| 51 | return; | 41 | return; |
| 52 | } | 42 | } |
| 53 | 43 | ||
| 54 | int pciehprm_print_pirt(void) | 44 | int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) |
| 55 | { | ||
| 56 | return 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) | ||
| 60 | { | ||
| 61 | |||
| 62 | *sun = (u8) (ctrl->first_slot); | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | |||
| 67 | static void print_pci_resource ( struct pci_resource *aprh) | ||
| 68 | { | ||
| 69 | struct pci_resource *res; | ||
| 70 | |||
| 71 | for (res = aprh; res; res = res->next) | ||
| 72 | dbg(" base= 0x%x length= 0x%x\n", res->base, res->length); | ||
| 73 | } | ||
| 74 | |||
| 75 | |||
| 76 | static void phprm_dump_func_res( struct pci_func *fun) | ||
| 77 | { | ||
| 78 | struct pci_func *func = fun; | ||
| 79 | |||
| 80 | if (func->bus_head) { | ||
| 81 | dbg(": BUS Resources:\n"); | ||
| 82 | print_pci_resource (func->bus_head); | ||
| 83 | } | ||
| 84 | if (func->io_head) { | ||
| 85 | dbg(": IO Resources:\n"); | ||
| 86 | print_pci_resource (func->io_head); | ||
| 87 | } | ||
| 88 | if (func->mem_head) { | ||
| 89 | dbg(": MEM Resources:\n"); | ||
| 90 | print_pci_resource (func->mem_head); | ||
| 91 | } | ||
| 92 | if (func->p_mem_head) { | ||
| 93 | dbg(": PMEM Resources:\n"); | ||
| 94 | print_pci_resource (func->p_mem_head); | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | static int phprm_get_used_resources ( | ||
| 99 | struct controller *ctrl, | ||
| 100 | struct pci_func *func | ||
| 101 | ) | ||
| 102 | { | ||
| 103 | return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD); | ||
| 104 | } | ||
| 105 | |||
| 106 | static int phprm_delete_resource( | ||
| 107 | struct pci_resource **aprh, | ||
| 108 | ulong base, | ||
| 109 | ulong size) | ||
| 110 | { | ||
| 111 | struct pci_resource *res; | ||
| 112 | struct pci_resource *prevnode; | ||
| 113 | struct pci_resource *split_node; | ||
| 114 | ulong tbase; | ||
| 115 | |||
| 116 | pciehp_resource_sort_and_combine(aprh); | ||
| 117 | |||
| 118 | for (res = *aprh; res; res = res->next) { | ||
| 119 | if (res->base > base) | ||
| 120 | continue; | ||
| 121 | |||
| 122 | if ((res->base + res->length) < (base + size)) | ||
| 123 | continue; | ||
| 124 | |||
| 125 | if (res->base < base) { | ||
| 126 | tbase = base; | ||
| 127 | |||
| 128 | if ((res->length - (tbase - res->base)) < size) | ||
| 129 | continue; | ||
| 130 | |||
| 131 | split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
| 132 | if (!split_node) | ||
| 133 | return -ENOMEM; | ||
| 134 | |||
| 135 | split_node->base = res->base; | ||
| 136 | split_node->length = tbase - res->base; | ||
| 137 | res->base = tbase; | ||
| 138 | res->length -= split_node->length; | ||
| 139 | |||
| 140 | split_node->next = res->next; | ||
| 141 | res->next = split_node; | ||
| 142 | } | ||
| 143 | |||
| 144 | if (res->length >= size) { | ||
| 145 | split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
| 146 | if (!split_node) | ||
| 147 | return -ENOMEM; | ||
| 148 | |||
| 149 | split_node->base = res->base + size; | ||
| 150 | split_node->length = res->length - size; | ||
| 151 | res->length = size; | ||
| 152 | |||
| 153 | split_node->next = res->next; | ||
| 154 | res->next = split_node; | ||
| 155 | } | ||
| 156 | |||
| 157 | if (*aprh == res) { | ||
| 158 | *aprh = res->next; | ||
| 159 | } else { | ||
| 160 | prevnode = *aprh; | ||
| 161 | while (prevnode->next != res) | ||
| 162 | prevnode = prevnode->next; | ||
| 163 | |||
| 164 | prevnode->next = res->next; | ||
| 165 | } | ||
| 166 | res->next = NULL; | ||
| 167 | kfree(res); | ||
| 168 | break; | ||
| 169 | } | ||
| 170 | |||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | |||
| 175 | static int phprm_delete_resources( | ||
| 176 | struct pci_resource **aprh, | ||
| 177 | struct pci_resource *this | ||
| 178 | ) | ||
| 179 | { | ||
| 180 | struct pci_resource *res; | ||
| 181 | |||
| 182 | for (res = this; res; res = res->next) | ||
| 183 | phprm_delete_resource(aprh, res->base, res->length); | ||
| 184 | |||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | |||
| 189 | static int configure_existing_function( | ||
| 190 | struct controller *ctrl, | ||
| 191 | struct pci_func *func | ||
| 192 | ) | ||
| 193 | { | ||
| 194 | int rc; | ||
| 195 | |||
| 196 | /* see how much resources the func has used. */ | ||
| 197 | rc = phprm_get_used_resources (ctrl, func); | ||
| 198 | |||
| 199 | if (!rc) { | ||
| 200 | /* subtract the resources used by the func from ctrl resources */ | ||
| 201 | rc = phprm_delete_resources (&ctrl->bus_head, func->bus_head); | ||
| 202 | rc |= phprm_delete_resources (&ctrl->io_head, func->io_head); | ||
| 203 | rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head); | ||
| 204 | rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head); | ||
| 205 | if (rc) | ||
| 206 | warn("aCEF: cannot del used resources\n"); | ||
| 207 | } else | ||
| 208 | err("aCEF: cannot get used resources\n"); | ||
| 209 | |||
| 210 | return rc; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int pciehprm_delete_resource( | ||
| 214 | struct pci_resource **aprh, | ||
| 215 | ulong base, | ||
| 216 | ulong size) | ||
| 217 | { | ||
| 218 | struct pci_resource *res; | ||
| 219 | struct pci_resource *prevnode; | ||
| 220 | struct pci_resource *split_node; | ||
| 221 | ulong tbase; | ||
| 222 | |||
| 223 | pciehp_resource_sort_and_combine(aprh); | ||
| 224 | |||
| 225 | for (res = *aprh; res; res = res->next) { | ||
| 226 | if (res->base > base) | ||
| 227 | continue; | ||
| 228 | |||
| 229 | if ((res->base + res->length) < (base + size)) | ||
| 230 | continue; | ||
| 231 | |||
| 232 | if (res->base < base) { | ||
| 233 | tbase = base; | ||
| 234 | |||
| 235 | if ((res->length - (tbase - res->base)) < size) | ||
| 236 | continue; | ||
| 237 | |||
| 238 | split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
| 239 | if (!split_node) | ||
| 240 | return -ENOMEM; | ||
| 241 | |||
| 242 | split_node->base = res->base; | ||
| 243 | split_node->length = tbase - res->base; | ||
| 244 | res->base = tbase; | ||
| 245 | res->length -= split_node->length; | ||
| 246 | |||
| 247 | split_node->next = res->next; | ||
| 248 | res->next = split_node; | ||
| 249 | } | ||
| 250 | |||
| 251 | if (res->length >= size) { | ||
| 252 | split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); | ||
| 253 | if (!split_node) | ||
| 254 | return -ENOMEM; | ||
| 255 | |||
| 256 | split_node->base = res->base + size; | ||
| 257 | split_node->length = res->length - size; | ||
| 258 | res->length = size; | ||
| 259 | |||
| 260 | split_node->next = res->next; | ||
| 261 | res->next = split_node; | ||
| 262 | } | ||
| 263 | |||
| 264 | if (*aprh == res) { | ||
| 265 | *aprh = res->next; | ||
| 266 | } else { | ||
| 267 | prevnode = *aprh; | ||
| 268 | while (prevnode->next != res) | ||
| 269 | prevnode = prevnode->next; | ||
| 270 | |||
| 271 | prevnode->next = res->next; | ||
| 272 | } | ||
| 273 | res->next = NULL; | ||
| 274 | kfree(res); | ||
| 275 | break; | ||
| 276 | } | ||
| 277 | |||
| 278 | return 0; | ||
| 279 | } | ||
| 280 | |||
| 281 | static int bind_pci_resources_to_slots ( struct controller *ctrl) | ||
| 282 | { | 45 | { |
| 283 | struct pci_func *func, new_func; | ||
| 284 | int busn = ctrl->slot_bus; | ||
| 285 | int devn, funn; | ||
| 286 | u32 vid; | ||
| 287 | |||
| 288 | for (devn = 0; devn < 32; devn++) { | ||
| 289 | for (funn = 0; funn < 8; funn++) { | ||
| 290 | /* | ||
| 291 | if (devn == ctrl->device && funn == ctrl->function) | ||
| 292 | continue; | ||
| 293 | */ | ||
| 294 | /* find out if this entry is for an occupied slot */ | ||
| 295 | vid = 0xFFFFFFFF; | ||
| 296 | |||
| 297 | pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); | ||
| 298 | |||
| 299 | if (vid != 0xFFFFFFFF) { | ||
| 300 | dbg("%s: vid = %x bus %x dev %x fun %x\n", __FUNCTION__, | ||
| 301 | vid, busn, devn, funn); | ||
| 302 | func = pciehp_slot_find(busn, devn, funn); | ||
| 303 | dbg("%s: func = %p\n", __FUNCTION__,func); | ||
| 304 | if (!func) { | ||
| 305 | memset(&new_func, 0, sizeof(struct pci_func)); | ||
| 306 | new_func.bus = busn; | ||
| 307 | new_func.device = devn; | ||
| 308 | new_func.function = funn; | ||
| 309 | new_func.is_a_board = 1; | ||
| 310 | configure_existing_function(ctrl, &new_func); | ||
| 311 | phprm_dump_func_res(&new_func); | ||
| 312 | } else { | ||
| 313 | configure_existing_function(ctrl, func); | ||
| 314 | phprm_dump_func_res(func); | ||
| 315 | } | ||
| 316 | dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); | ||
| 317 | } | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | return 0; | 46 | return 0; |
| 322 | } | 47 | } |
| 323 | |||
| 324 | static void phprm_dump_ctrl_res( struct controller *ctlr) | ||
| 325 | { | ||
| 326 | struct controller *ctrl = ctlr; | ||
| 327 | |||
| 328 | if (ctrl->bus_head) { | ||
| 329 | dbg(": BUS Resources:\n"); | ||
| 330 | print_pci_resource (ctrl->bus_head); | ||
| 331 | } | ||
| 332 | if (ctrl->io_head) { | ||
| 333 | dbg(": IO Resources:\n"); | ||
| 334 | print_pci_resource (ctrl->io_head); | ||
| 335 | } | ||
| 336 | if (ctrl->mem_head) { | ||
| 337 | dbg(": MEM Resources:\n"); | ||
| 338 | print_pci_resource (ctrl->mem_head); | ||
| 339 | } | ||
| 340 | if (ctrl->p_mem_head) { | ||
| 341 | dbg(": PMEM Resources:\n"); | ||
| 342 | print_pci_resource (ctrl->p_mem_head); | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | /* | ||
| 347 | * phprm_find_available_resources | ||
| 348 | * | ||
| 349 | * Finds available memory, IO, and IRQ resources for programming | ||
| 350 | * devices which may be added to the system | ||
| 351 | * this function is for hot plug ADD! | ||
| 352 | * | ||
| 353 | * returns 0 if success | ||
| 354 | */ | ||
| 355 | int pciehprm_find_available_resources(struct controller *ctrl) | ||
| 356 | { | ||
| 357 | struct pci_func func; | ||
| 358 | u32 rc; | ||
| 359 | |||
| 360 | memset(&func, 0, sizeof(struct pci_func)); | ||
| 361 | |||
| 362 | func.bus = ctrl->bus; | ||
| 363 | func.device = ctrl->device; | ||
| 364 | func.function = ctrl->function; | ||
| 365 | func.is_a_board = 1; | ||
| 366 | |||
| 367 | /* Get resources for this PCI bridge */ | ||
| 368 | rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD); | ||
| 369 | dbg("%s: pciehp_save_used_resources rc = %d\n", __FUNCTION__, rc); | ||
| 370 | |||
| 371 | if (func.mem_head) | ||
| 372 | func.mem_head->next = ctrl->mem_head; | ||
| 373 | ctrl->mem_head = func.mem_head; | ||
| 374 | |||
| 375 | if (func.p_mem_head) | ||
| 376 | func.p_mem_head->next = ctrl->p_mem_head; | ||
| 377 | ctrl->p_mem_head = func.p_mem_head; | ||
| 378 | |||
| 379 | if (func.io_head) | ||
| 380 | func.io_head->next = ctrl->io_head; | ||
| 381 | ctrl->io_head = func.io_head; | ||
| 382 | |||
| 383 | if(func.bus_head) | ||
| 384 | func.bus_head->next = ctrl->bus_head; | ||
| 385 | ctrl->bus_head = func.bus_head; | ||
| 386 | |||
| 387 | if (ctrl->bus_head) | ||
| 388 | pciehprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1); | ||
| 389 | |||
| 390 | dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus); | ||
| 391 | phprm_dump_ctrl_res(ctrl); | ||
| 392 | |||
| 393 | dbg("%s: before bind_pci_resources_to slots\n", __FUNCTION__); | ||
| 394 | |||
| 395 | bind_pci_resources_to_slots (ctrl); | ||
| 396 | |||
| 397 | dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus); | ||
| 398 | phprm_dump_ctrl_res(ctrl); | ||
| 399 | |||
| 400 | return (rc); | ||
| 401 | } | ||
| 402 | |||
| 403 | int pciehprm_set_hpp( | ||
| 404 | struct controller *ctrl, | ||
| 405 | struct pci_func *func, | ||
| 406 | u8 card_type) | ||
| 407 | { | ||
| 408 | u32 rc; | ||
| 409 | u8 temp_byte; | ||
| 410 | struct pci_bus lpci_bus, *pci_bus; | ||
| 411 | unsigned int devfn; | ||
| 412 | memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); | ||
| 413 | pci_bus = &lpci_bus; | ||
| 414 | pci_bus->number = func->bus; | ||
| 415 | devfn = PCI_DEVFN(func->device, func->function); | ||
| 416 | |||
| 417 | temp_byte = 0x40; /* hard coded value for LT */ | ||
| 418 | if (card_type == PCI_HEADER_TYPE_BRIDGE) { | ||
| 419 | /* set subordinate Latency Timer */ | ||
| 420 | rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte); | ||
| 421 | |||
| 422 | if (rc) { | ||
| 423 | dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, | ||
| 424 | func->bus, func->device, func->function); | ||
| 425 | return rc; | ||
| 426 | } | ||
| 427 | } | ||
| 428 | |||
| 429 | /* set base Latency Timer */ | ||
| 430 | rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); | ||
| 431 | |||
| 432 | if (rc) { | ||
| 433 | dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function); | ||
| 434 | return rc; | ||
| 435 | } | ||
| 436 | |||
| 437 | /* set Cache Line size */ | ||
| 438 | temp_byte = 0x08; /* hard coded value for CLS */ | ||
| 439 | |||
| 440 | rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); | ||
| 441 | |||
| 442 | if (rc) { | ||
| 443 | dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function); | ||
| 444 | } | ||
| 445 | |||
| 446 | /* set enable_perr */ | ||
| 447 | /* set enable_serr */ | ||
| 448 | |||
| 449 | return rc; | ||
| 450 | } | ||
| 451 | |||
| 452 | void pciehprm_enable_card( | ||
| 453 | struct controller *ctrl, | ||
| 454 | struct pci_func *func, | ||
| 455 | u8 card_type) | ||
| 456 | { | ||
| 457 | u16 command, bcommand; | ||
| 458 | struct pci_bus lpci_bus, *pci_bus; | ||
| 459 | unsigned int devfn; | ||
| 460 | int rc; | ||
| 461 | |||
| 462 | memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); | ||
| 463 | pci_bus = &lpci_bus; | ||
| 464 | pci_bus->number = func->bus; | ||
| 465 | devfn = PCI_DEVFN(func->device, func->function); | ||
| 466 | |||
| 467 | rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command); | ||
| 468 | |||
| 469 | command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR | ||
| 470 | | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | ||
| 471 | | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; | ||
| 472 | |||
| 473 | rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); | ||
| 474 | |||
| 475 | if (card_type == PCI_HEADER_TYPE_BRIDGE) { | ||
| 476 | |||
| 477 | rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand); | ||
| 478 | |||
| 479 | bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | ||
| 480 | | PCI_BRIDGE_CTL_NO_ISA; | ||
| 481 | |||
| 482 | rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand); | ||
| 483 | } | ||
| 484 | } | ||
| 485 | |||
| 486 | static int legacy_pciehprm_init_pci(void) | ||
| 487 | { | ||
| 488 | return 0; | ||
| 489 | } | ||
| 490 | |||
| 491 | int pciehprm_init(enum php_ctlr_type ctrl_type) | ||
| 492 | { | ||
| 493 | int retval; | ||
| 494 | |||
| 495 | switch (ctrl_type) { | ||
| 496 | case PCI: | ||
| 497 | retval = legacy_pciehprm_init_pci(); | ||
| 498 | break; | ||
| 499 | default: | ||
| 500 | retval = -ENODEV; | ||
| 501 | break; | ||
| 502 | } | ||
| 503 | |||
| 504 | return retval; | ||
| 505 | } | ||
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.h b/drivers/pci/hotplug/pciehprm_nonacpi.h deleted file mode 100644 index b10603b0e958..000000000000 --- a/drivers/pci/hotplug/pciehprm_nonacpi.h +++ /dev/null | |||
| @@ -1,56 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform | ||
| 3 | * | ||
| 4 | * Copyright (C) 1995,2001 Compaq Computer Corporation | ||
| 5 | * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) | ||
| 6 | * Copyright (C) 2001 IBM Corp. | ||
| 7 | * Copyright (C) 2003-2004 Intel Corporation | ||
| 8 | * | ||
| 9 | * All rights reserved. | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or (at | ||
| 14 | * your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, but | ||
| 17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
| 19 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
| 20 | * details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License | ||
| 23 | * along with this program; if not, write to the Free Software | ||
| 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 25 | * | ||
| 26 | * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> | ||
| 27 | * | ||
| 28 | */ | ||
| 29 | |||
| 30 | #ifndef _PCIEHPRM_NONACPI_H_ | ||
| 31 | #define _PCIEHPRM_NONACPI_H_ | ||
| 32 | |||
| 33 | struct irq_info { | ||
| 34 | u8 bus, devfn; /* bus, device and function */ | ||
| 35 | struct { | ||
| 36 | u8 link; /* IRQ line ID, chipset dependent, 0=not routed */ | ||
| 37 | u16 bitmap; /* Available IRQs */ | ||
| 38 | } __attribute__ ((packed)) irq[4]; | ||
| 39 | u8 slot; /* slot number, 0=onboard */ | ||
| 40 | u8 rfu; | ||
| 41 | } __attribute__ ((packed)); | ||
| 42 | |||
| 43 | struct irq_routing_table { | ||
| 44 | u32 signature; /* PIRQ_SIGNATURE should be here */ | ||
| 45 | u16 version; /* PIRQ_VERSION */ | ||
| 46 | u16 size; /* Table size in bytes */ | ||
| 47 | u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */ | ||
| 48 | u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */ | ||
| 49 | u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */ | ||
| 50 | u32 miniport_data; /* Crap */ | ||
| 51 | u8 rfu[11]; | ||
| 52 | u8 checksum; /* Modulo 256 checksum must give zero */ | ||
| 53 | struct irq_info slots[0]; | ||
| 54 | } __attribute__ ((packed)); | ||
| 55 | |||
| 56 | #endif /* _PCIEHPRM_NONACPI_H_ */ | ||
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index e8593a60ee89..cc03609f45d0 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) | |||
| 134 | rpadlpar_claim_one_bus(child_bus); | 134 | rpadlpar_claim_one_bus(child_bus); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static int pci_add_secondary_bus(struct device_node *dn, | ||
| 138 | struct pci_dev *bridge_dev) | ||
| 139 | { | ||
| 140 | struct pci_dn *pdn = dn->data; | ||
| 141 | struct pci_controller *hose = pdn->phb; | ||
| 142 | struct pci_bus *child; | ||
| 143 | u8 sec_busno; | ||
| 144 | |||
| 145 | /* Get busno of downstream bus */ | ||
| 146 | pci_read_config_byte(bridge_dev, PCI_SECONDARY_BUS, &sec_busno); | ||
| 147 | |||
| 148 | /* Allocate and add to children of bridge_dev->bus */ | ||
| 149 | child = pci_add_new_bus(bridge_dev->bus, bridge_dev, sec_busno); | ||
| 150 | if (!child) { | ||
| 151 | printk(KERN_ERR "%s: could not add secondary bus\n", __FUNCTION__); | ||
| 152 | return -ENOMEM; | ||
| 153 | } | ||
| 154 | |||
| 155 | sprintf(child->name, "PCI Bus #%02x", child->number); | ||
| 156 | |||
| 157 | /* Fixup subordinate bridge bases and resources */ | ||
| 158 | pcibios_fixup_bus(child); | ||
| 159 | |||
| 160 | /* Claim new bus resources */ | ||
| 161 | rpadlpar_claim_one_bus(bridge_dev->bus); | ||
| 162 | |||
| 163 | if (hose->last_busno < child->number) | ||
| 164 | hose->last_busno = child->number; | ||
| 165 | |||
| 166 | pdn->bussubno = child->number; | ||
| 167 | |||
| 168 | /* ioremap() for child bus, which may or may not succeed */ | ||
| 169 | remap_bus_range(child); | ||
| 170 | |||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, | 137 | static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, |
| 175 | struct device_node *dev_dn) | 138 | struct device_node *dev_dn) |
| 176 | { | 139 | { |
| @@ -188,29 +151,41 @@ static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, | |||
| 188 | static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) | 151 | static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) |
| 189 | { | 152 | { |
| 190 | struct pci_dn *pdn = dn->data; | 153 | struct pci_dn *pdn = dn->data; |
| 191 | struct pci_controller *hose = pdn->phb; | 154 | struct pci_controller *phb = pdn->phb; |
| 192 | struct pci_dev *dev = NULL; | 155 | struct pci_dev *dev = NULL; |
| 193 | 156 | ||
| 194 | /* Scan phb bus for EADS device, adding new one to bus->devices */ | 157 | rpaphp_eeh_init_nodes(dn); |
| 195 | if (!pci_scan_single_device(hose->bus, pdn->devfn)) { | 158 | /* Add EADS device to PHB bus, adding new entry to bus->devices */ |
| 196 | printk(KERN_ERR "%s: found no device on bus\n", __FUNCTION__); | 159 | dev = of_create_pci_dev(dn, phb->bus, pdn->devfn); |
| 160 | if (!dev) { | ||
| 161 | printk(KERN_ERR "%s: failed to create pci dev for %s\n", | ||
| 162 | __FUNCTION__, dn->full_name); | ||
| 197 | return NULL; | 163 | return NULL; |
| 198 | } | 164 | } |
| 199 | 165 | ||
| 166 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | ||
| 167 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) | ||
| 168 | of_scan_pci_bridge(dn, dev); | ||
| 169 | |||
| 170 | rpaphp_init_new_devs(dev->subordinate); | ||
| 171 | |||
| 172 | /* Claim new bus resources */ | ||
| 173 | rpadlpar_claim_one_bus(dev->bus); | ||
| 174 | |||
| 175 | /* ioremap() for child bus, which may or may not succeed */ | ||
| 176 | (void) remap_bus_range(dev->bus); | ||
| 177 | |||
| 200 | /* Add new devices to global lists. Register in proc, sysfs. */ | 178 | /* Add new devices to global lists. Register in proc, sysfs. */ |
| 201 | pci_bus_add_devices(hose->bus); | 179 | pci_bus_add_devices(phb->bus); |
| 202 | 180 | ||
| 203 | /* Confirm new bridge dev was created */ | 181 | /* Confirm new bridge dev was created */ |
| 204 | dev = dlpar_find_new_dev(hose->bus, dn); | 182 | dev = dlpar_find_new_dev(phb->bus, dn); |
| 205 | if (dev) { | 183 | if (dev) { |
| 206 | if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { | 184 | if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { |
| 207 | printk(KERN_ERR "%s: unexpected header type %d\n", | 185 | printk(KERN_ERR "%s: unexpected header type %d\n", |
| 208 | __FUNCTION__, dev->hdr_type); | 186 | __FUNCTION__, dev->hdr_type); |
| 209 | return NULL; | 187 | return NULL; |
| 210 | } | 188 | } |
| 211 | |||
| 212 | if (pci_add_secondary_bus(dn, dev)) | ||
| 213 | return NULL; | ||
| 214 | } | 189 | } |
| 215 | 190 | ||
| 216 | return dev; | 191 | return dev; |
| @@ -219,7 +194,6 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) | |||
| 219 | static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) | 194 | static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) |
| 220 | { | 195 | { |
| 221 | struct pci_dev *dev; | 196 | struct pci_dev *dev; |
| 222 | int rc; | ||
| 223 | 197 | ||
| 224 | if (rpaphp_find_pci_bus(dn)) | 198 | if (rpaphp_find_pci_bus(dn)) |
| 225 | return -EINVAL; | 199 | return -EINVAL; |
| @@ -232,15 +206,6 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) | |||
| 232 | return -EIO; | 206 | return -EIO; |
| 233 | } | 207 | } |
| 234 | 208 | ||
| 235 | if (dn->child) { | ||
| 236 | rc = rpaphp_config_pci_adapter(dev->subordinate); | ||
| 237 | if (rc < 0) { | ||
| 238 | printk(KERN_ERR "%s: unable to enable slot %s\n", | ||
| 239 | __FUNCTION__, drc_name); | ||
| 240 | return -EIO; | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | /* Add hotplug slot */ | 209 | /* Add hotplug slot */ |
| 245 | if (rpaphp_add_slot(dn)) { | 210 | if (rpaphp_add_slot(dn)) { |
| 246 | printk(KERN_ERR "%s: unable to add hotplug slot %s\n", | 211 | 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) | |||
| 435 | __FUNCTION__, drc_name); | 400 | __FUNCTION__, drc_name); |
| 436 | return -EIO; | 401 | return -EIO; |
| 437 | } | 402 | } |
| 403 | } else { | ||
| 404 | rpaphp_unconfig_pci_adapter(bus); | ||
| 438 | } | 405 | } |
| 439 | 406 | ||
| 440 | if (unmap_bus_range(bus)) { | 407 | if (unmap_bus_range(bus)) { |
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 71ea5f9bb284..57ea71a7bda5 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); | |||
| 93 | extern int rpaphp_enable_pci_slot(struct slot *slot); | 93 | extern int rpaphp_enable_pci_slot(struct slot *slot); |
| 94 | extern int register_pci_slot(struct slot *slot); | 94 | extern int register_pci_slot(struct slot *slot); |
| 95 | extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); | 95 | extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); |
| 96 | extern void rpaphp_init_new_devs(struct pci_bus *bus); | ||
| 97 | extern void rpaphp_eeh_init_nodes(struct device_node *dn); | ||
| 96 | 98 | ||
| 97 | extern int rpaphp_config_pci_adapter(struct pci_bus *bus); | 99 | extern int rpaphp_config_pci_adapter(struct pci_bus *bus); |
| 98 | extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus); | 100 | 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 f7c12d7dfcfc..a7859a84d1ae 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c | |||
| @@ -154,8 +154,7 @@ exit: | |||
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | /* Must be called before pci_bus_add_devices */ | 156 | /* Must be called before pci_bus_add_devices */ |
| 157 | static void | 157 | void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) |
| 158 | rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | ||
| 159 | { | 158 | { |
| 160 | struct pci_dev *dev; | 159 | struct pci_dev *dev; |
| 161 | 160 | ||
| @@ -184,6 +183,20 @@ rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | |||
| 184 | } | 183 | } |
| 185 | } | 184 | } |
| 186 | 185 | ||
| 186 | static void rpaphp_eeh_add_bus_device(struct pci_bus *bus) | ||
| 187 | { | ||
| 188 | struct pci_dev *dev; | ||
| 189 | |||
| 190 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 191 | eeh_add_device_late(dev); | ||
| 192 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | ||
| 193 | struct pci_bus *subbus = dev->subordinate; | ||
| 194 | if (subbus) | ||
| 195 | rpaphp_eeh_add_bus_device (subbus); | ||
| 196 | } | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 187 | static int rpaphp_pci_config_bridge(struct pci_dev *dev) | 200 | static int rpaphp_pci_config_bridge(struct pci_dev *dev) |
| 188 | { | 201 | { |
| 189 | u8 sec_busno; | 202 | u8 sec_busno; |
| @@ -217,6 +230,13 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev) | |||
| 217 | return 0; | 230 | return 0; |
| 218 | } | 231 | } |
| 219 | 232 | ||
| 233 | void rpaphp_init_new_devs(struct pci_bus *bus) | ||
| 234 | { | ||
| 235 | rpaphp_fixup_new_pci_devices(bus, 0); | ||
| 236 | rpaphp_eeh_add_bus_device(bus); | ||
| 237 | } | ||
| 238 | EXPORT_SYMBOL_GPL(rpaphp_init_new_devs); | ||
| 239 | |||
| 220 | /***************************************************************************** | 240 | /***************************************************************************** |
| 221 | rpaphp_pci_config_slot() will configure all devices under the | 241 | rpaphp_pci_config_slot() will configure all devices under the |
| 222 | given slot->dn and return the the first pci_dev. | 242 | given slot->dn and return the the first pci_dev. |
| @@ -233,36 +253,51 @@ rpaphp_pci_config_slot(struct pci_bus *bus) | |||
| 233 | if (!dn || !dn->child) | 253 | if (!dn || !dn->child) |
| 234 | return NULL; | 254 | return NULL; |
| 235 | 255 | ||
| 236 | slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); | 256 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { |
| 257 | of_scan_bus(dn, bus); | ||
| 258 | if (list_empty(&bus->devices)) { | ||
| 259 | err("%s: No new device found\n", __FUNCTION__); | ||
| 260 | return NULL; | ||
| 261 | } | ||
| 237 | 262 | ||
| 238 | /* pci_scan_slot should find all children */ | 263 | rpaphp_init_new_devs(bus); |
| 239 | num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); | ||
| 240 | if (num) { | ||
| 241 | rpaphp_fixup_new_pci_devices(bus, 1); | ||
| 242 | pci_bus_add_devices(bus); | 264 | pci_bus_add_devices(bus); |
| 243 | } | 265 | dev = list_entry(&bus->devices, struct pci_dev, bus_list); |
| 244 | if (list_empty(&bus->devices)) { | 266 | } else { |
| 245 | err("%s: No new device found\n", __FUNCTION__); | 267 | slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); |
| 246 | return NULL; | 268 | |
| 247 | } | 269 | /* pci_scan_slot should find all children */ |
| 248 | list_for_each_entry(dev, &bus->devices, bus_list) { | 270 | num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); |
| 249 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | 271 | if (num) { |
| 250 | rpaphp_pci_config_bridge(dev); | 272 | rpaphp_fixup_new_pci_devices(bus, 1); |
| 273 | pci_bus_add_devices(bus); | ||
| 274 | } | ||
| 275 | if (list_empty(&bus->devices)) { | ||
| 276 | err("%s: No new device found\n", __FUNCTION__); | ||
| 277 | return NULL; | ||
| 278 | } | ||
| 279 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 280 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | ||
| 281 | rpaphp_pci_config_bridge(dev); | ||
| 282 | |||
| 283 | rpaphp_eeh_add_bus_device(bus); | ||
| 284 | } | ||
| 251 | } | 285 | } |
| 252 | 286 | ||
| 253 | return dev; | 287 | return dev; |
| 254 | } | 288 | } |
| 255 | 289 | ||
| 256 | static void enable_eeh(struct device_node *dn) | 290 | void rpaphp_eeh_init_nodes(struct device_node *dn) |
| 257 | { | 291 | { |
| 258 | struct device_node *sib; | 292 | struct device_node *sib; |
| 259 | 293 | ||
| 260 | for (sib = dn->child; sib; sib = sib->sibling) | 294 | for (sib = dn->child; sib; sib = sib->sibling) |
| 261 | enable_eeh(sib); | 295 | rpaphp_eeh_init_nodes(sib); |
| 262 | eeh_add_device_early(dn); | 296 | eeh_add_device_early(dn); |
| 263 | return; | 297 | return; |
| 264 | 298 | ||
| 265 | } | 299 | } |
| 300 | EXPORT_SYMBOL_GPL(rpaphp_eeh_init_nodes); | ||
| 266 | 301 | ||
| 267 | static void print_slot_pci_funcs(struct pci_bus *bus) | 302 | static void print_slot_pci_funcs(struct pci_bus *bus) |
| 268 | { | 303 | { |
| @@ -289,7 +324,7 @@ int rpaphp_config_pci_adapter(struct pci_bus *bus) | |||
| 289 | if (!dn) | 324 | if (!dn) |
| 290 | goto exit; | 325 | goto exit; |
| 291 | 326 | ||
| 292 | enable_eeh(dn); | 327 | rpaphp_eeh_init_nodes(dn); |
| 293 | dev = rpaphp_pci_config_slot(bus); | 328 | dev = rpaphp_pci_config_slot(bus); |
| 294 | if (!dev) { | 329 | if (!dev) { |
| 295 | err("%s: can't find any devices.\n", __FUNCTION__); | 330 | err("%s: can't find any devices.\n", __FUNCTION__); |
| @@ -331,6 +366,7 @@ int rpaphp_unconfig_pci_adapter(struct pci_bus *bus) | |||
| 331 | } | 366 | } |
| 332 | return 0; | 367 | return 0; |
| 333 | } | 368 | } |
| 369 | EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter); | ||
| 334 | 370 | ||
| 335 | static int setup_pci_hotplug_slot_info(struct slot *slot) | 371 | static int setup_pci_hotplug_slot_info(struct slot *slot) |
| 336 | { | 372 | { |
| @@ -444,8 +480,8 @@ int rpaphp_enable_pci_slot(struct slot *slot) | |||
| 444 | retval = rpaphp_config_pci_adapter(slot->bus); | 480 | retval = rpaphp_config_pci_adapter(slot->bus); |
| 445 | if (!retval) { | 481 | if (!retval) { |
| 446 | slot->state = CONFIGURED; | 482 | slot->state = CONFIGURED; |
| 447 | dbg("%s: PCI devices in slot[%s] has been configured\n", | 483 | info("%s: devices in slot[%s] configured\n", |
| 448 | __FUNCTION__, slot->name); | 484 | __FUNCTION__, slot->name); |
| 449 | } else { | 485 | } else { |
| 450 | slot->state = NOT_CONFIGURED; | 486 | slot->state = NOT_CONFIGURED; |
| 451 | dbg("%s: no pci_dev struct for adapter in slot[%s]\n", | 487 | dbg("%s: no pci_dev struct for adapter in slot[%s]\n", |
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index b8e95acea3b6..38009bc0fd5d 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
| @@ -34,7 +34,7 @@ | |||
| 34 | #include "../pci.h" | 34 | #include "../pci.h" |
| 35 | #include "shpchp.h" | 35 | #include "shpchp.h" |
| 36 | 36 | ||
| 37 | void program_fw_provided_values(struct pci_dev *dev) | 37 | static void program_fw_provided_values(struct pci_dev *dev) |
| 38 | { | 38 | { |
| 39 | u16 pci_cmd, pci_bctl; | 39 | u16 pci_cmd, pci_bctl; |
| 40 | struct pci_dev *cdev; | 40 | struct pci_dev *cdev; |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a2033552423c..202b7507a357 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
| @@ -23,6 +23,8 @@ | |||
| 23 | #include "pci.h" | 23 | #include "pci.h" |
| 24 | #include "msi.h" | 24 | #include "msi.h" |
| 25 | 25 | ||
| 26 | #define MSI_TARGET_CPU first_cpu(cpu_online_map) | ||
| 27 | |||
| 26 | static DEFINE_SPINLOCK(msi_lock); | 28 | static DEFINE_SPINLOCK(msi_lock); |
| 27 | static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; | 29 | static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; |
| 28 | static kmem_cache_t* msi_cachep; | 30 | static kmem_cache_t* msi_cachep; |
| @@ -92,6 +94,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | |||
| 92 | struct msi_desc *entry; | 94 | struct msi_desc *entry; |
| 93 | struct msg_address address; | 95 | struct msg_address address; |
| 94 | unsigned int irq = vector; | 96 | unsigned int irq = vector; |
| 97 | unsigned int dest_cpu = first_cpu(cpu_mask); | ||
| 95 | 98 | ||
| 96 | entry = (struct msi_desc *)msi_desc[vector]; | 99 | entry = (struct msi_desc *)msi_desc[vector]; |
| 97 | if (!entry || !entry->dev) | 100 | if (!entry || !entry->dev) |
| @@ -108,9 +111,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | |||
| 108 | pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), | 111 | pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), |
| 109 | &address.lo_address.value); | 112 | &address.lo_address.value); |
| 110 | address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; | 113 | address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; |
| 111 | address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) << | 114 | address.lo_address.value |= (cpu_physical_id(dest_cpu) << |
| 112 | MSI_TARGET_CPU_SHIFT); | 115 | MSI_TARGET_CPU_SHIFT); |
| 113 | entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask); | 116 | entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); |
| 114 | pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), | 117 | pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), |
| 115 | address.lo_address.value); | 118 | address.lo_address.value); |
| 116 | set_native_irq_info(irq, cpu_mask); | 119 | set_native_irq_info(irq, cpu_mask); |
| @@ -123,9 +126,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | |||
| 123 | 126 | ||
| 124 | address.lo_address.value = readl(entry->mask_base + offset); | 127 | address.lo_address.value = readl(entry->mask_base + offset); |
| 125 | address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; | 128 | address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; |
| 126 | address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) << | 129 | address.lo_address.value |= (cpu_physical_id(dest_cpu) << |
| 127 | MSI_TARGET_CPU_SHIFT); | 130 | MSI_TARGET_CPU_SHIFT); |
| 128 | entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask); | 131 | entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); |
| 129 | writel(address.lo_address.value, entry->mask_base + offset); | 132 | writel(address.lo_address.value, entry->mask_base + offset); |
| 130 | set_native_irq_info(irq, cpu_mask); | 133 | set_native_irq_info(irq, cpu_mask); |
| 131 | break; | 134 | break; |
| @@ -259,14 +262,15 @@ static void msi_data_init(struct msg_data *msi_data, | |||
| 259 | static void msi_address_init(struct msg_address *msi_address) | 262 | static void msi_address_init(struct msg_address *msi_address) |
| 260 | { | 263 | { |
| 261 | unsigned int dest_id; | 264 | unsigned int dest_id; |
| 265 | unsigned long dest_phys_id = cpu_physical_id(MSI_TARGET_CPU); | ||
| 262 | 266 | ||
| 263 | memset(msi_address, 0, sizeof(struct msg_address)); | 267 | memset(msi_address, 0, sizeof(struct msg_address)); |
| 264 | msi_address->hi_address = (u32)0; | 268 | msi_address->hi_address = (u32)0; |
| 265 | dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT); | 269 | dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT); |
| 266 | msi_address->lo_address.u.dest_mode = MSI_DEST_MODE; | 270 | msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE; |
| 267 | msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE; | 271 | msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE; |
| 268 | msi_address->lo_address.u.dest_id = dest_id; | 272 | msi_address->lo_address.u.dest_id = dest_id; |
| 269 | msi_address->lo_address.value |= (MSI_TARGET_CPU << MSI_TARGET_CPU_SHIFT); | 273 | msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT); |
| 270 | } | 274 | } |
| 271 | 275 | ||
| 272 | static int msi_free_vector(struct pci_dev* dev, int vector, int reassign); | 276 | static int msi_free_vector(struct pci_dev* dev, int vector, int reassign); |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index e9e37abe1f76..a9b00cc2d885 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
| @@ -91,9 +91,7 @@ acpi_query_osc ( | |||
| 91 | static acpi_status | 91 | static acpi_status |
| 92 | acpi_run_osc ( | 92 | acpi_run_osc ( |
| 93 | acpi_handle handle, | 93 | acpi_handle handle, |
| 94 | u32 level, | 94 | void *context) |
| 95 | void *context, | ||
| 96 | void **retval ) | ||
| 97 | { | 95 | { |
| 98 | acpi_status status; | 96 | acpi_status status; |
| 99 | struct acpi_object_list input; | 97 | struct acpi_object_list input; |
| @@ -184,7 +182,7 @@ EXPORT_SYMBOL(pci_osc_support_set); | |||
| 184 | * | 182 | * |
| 185 | * Attempt to take control from Firmware on requested control bits. | 183 | * Attempt to take control from Firmware on requested control bits. |
| 186 | **/ | 184 | **/ |
| 187 | acpi_status pci_osc_control_set(u32 flags) | 185 | acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) |
| 188 | { | 186 | { |
| 189 | acpi_status status; | 187 | acpi_status status; |
| 190 | u32 ctrlset; | 188 | u32 ctrlset; |
| @@ -198,10 +196,7 @@ acpi_status pci_osc_control_set(u32 flags) | |||
| 198 | return AE_SUPPORT; | 196 | return AE_SUPPORT; |
| 199 | } | 197 | } |
| 200 | ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; | 198 | ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; |
| 201 | status = acpi_get_devices ( PCI_ROOT_HID_STRING, | 199 | status = acpi_run_osc(handle, ctrlset_buf); |
| 202 | acpi_run_osc, | ||
| 203 | ctrlset_buf, | ||
| 204 | NULL ); | ||
| 205 | if (ACPI_FAILURE (status)) { | 200 | if (ACPI_FAILURE (status)) { |
| 206 | ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; | 201 | ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; |
| 207 | } | 202 | } |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 94e68c54d273..a9046d4b8af3 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
| @@ -37,7 +37,7 @@ struct pci_dynid { | |||
| 37 | * Adds a new dynamic pci device ID to this driver, | 37 | * Adds a new dynamic pci device ID to this driver, |
| 38 | * and causes the driver to probe for all devices again. | 38 | * and causes the driver to probe for all devices again. |
| 39 | */ | 39 | */ |
| 40 | static inline ssize_t | 40 | static ssize_t |
| 41 | store_new_id(struct device_driver *driver, const char *buf, size_t count) | 41 | store_new_id(struct device_driver *driver, const char *buf, size_t count) |
| 42 | { | 42 | { |
| 43 | struct pci_dynid *dynid; | 43 | struct pci_dynid *dynid; |
| @@ -364,15 +364,16 @@ static struct kobj_type pci_driver_kobj_type = { | |||
| 364 | }; | 364 | }; |
| 365 | 365 | ||
| 366 | /** | 366 | /** |
| 367 | * pci_register_driver - register a new pci driver | 367 | * __pci_register_driver - register a new pci driver |
| 368 | * @drv: the driver structure to register | 368 | * @drv: the driver structure to register |
| 369 | * @owner: owner module of drv | ||
| 369 | * | 370 | * |
| 370 | * Adds the driver structure to the list of registered drivers. | 371 | * Adds the driver structure to the list of registered drivers. |
| 371 | * Returns a negative value on error, otherwise 0. | 372 | * Returns a negative value on error, otherwise 0. |
| 372 | * If no error occurred, the driver remains registered even if | 373 | * If no error occurred, the driver remains registered even if |
| 373 | * no device was claimed during registration. | 374 | * no device was claimed during registration. |
| 374 | */ | 375 | */ |
| 375 | int pci_register_driver(struct pci_driver *drv) | 376 | int __pci_register_driver(struct pci_driver *drv, struct module *owner) |
| 376 | { | 377 | { |
| 377 | int error; | 378 | int error; |
| 378 | 379 | ||
| @@ -389,7 +390,7 @@ int pci_register_driver(struct pci_driver *drv) | |||
| 389 | printk(KERN_WARNING "Warning: PCI driver %s has a struct " | 390 | printk(KERN_WARNING "Warning: PCI driver %s has a struct " |
| 390 | "device_driver shutdown method, please update!\n", | 391 | "device_driver shutdown method, please update!\n", |
| 391 | drv->name); | 392 | drv->name); |
| 392 | drv->driver.owner = drv->owner; | 393 | drv->driver.owner = owner; |
| 393 | drv->driver.kobj.ktype = &pci_driver_kobj_type; | 394 | drv->driver.kobj.ktype = &pci_driver_kobj_type; |
| 394 | 395 | ||
| 395 | spin_lock_init(&drv->dynids.lock); | 396 | spin_lock_init(&drv->dynids.lock); |
| @@ -526,7 +527,7 @@ postcore_initcall(pci_driver_init); | |||
| 526 | 527 | ||
| 527 | EXPORT_SYMBOL(pci_match_id); | 528 | EXPORT_SYMBOL(pci_match_id); |
| 528 | EXPORT_SYMBOL(pci_match_device); | 529 | EXPORT_SYMBOL(pci_match_device); |
| 529 | EXPORT_SYMBOL(pci_register_driver); | 530 | EXPORT_SYMBOL(__pci_register_driver); |
| 530 | EXPORT_SYMBOL(pci_unregister_driver); | 531 | EXPORT_SYMBOL(pci_unregister_driver); |
| 531 | EXPORT_SYMBOL(pci_dev_driver); | 532 | EXPORT_SYMBOL(pci_dev_driver); |
| 532 | EXPORT_SYMBOL(pci_bus_type); | 533 | EXPORT_SYMBOL(pci_bus_type); |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e74d75843047..8e287a828d5d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -63,11 +63,38 @@ pci_max_busnr(void) | |||
| 63 | return max; | 63 | return max; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap) | ||
| 67 | { | ||
| 68 | u8 id; | ||
| 69 | int ttl = 48; | ||
| 70 | |||
| 71 | while (ttl--) { | ||
| 72 | pci_bus_read_config_byte(bus, devfn, pos, &pos); | ||
| 73 | if (pos < 0x40) | ||
| 74 | break; | ||
| 75 | pos &= ~3; | ||
| 76 | pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, | ||
| 77 | &id); | ||
| 78 | if (id == 0xff) | ||
| 79 | break; | ||
| 80 | if (id == cap) | ||
| 81 | return pos; | ||
| 82 | pos += PCI_CAP_LIST_NEXT; | ||
| 83 | } | ||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap) | ||
| 88 | { | ||
| 89 | return __pci_find_next_cap(dev->bus, dev->devfn, | ||
| 90 | pos + PCI_CAP_LIST_NEXT, cap); | ||
| 91 | } | ||
| 92 | EXPORT_SYMBOL_GPL(pci_find_next_capability); | ||
| 93 | |||
| 66 | static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap) | 94 | static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap) |
| 67 | { | 95 | { |
| 68 | u16 status; | 96 | u16 status; |
| 69 | u8 pos, id; | 97 | u8 pos; |
| 70 | int ttl = 48; | ||
| 71 | 98 | ||
| 72 | pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); | 99 | pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); |
| 73 | if (!(status & PCI_STATUS_CAP_LIST)) | 100 | 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 | |||
| 76 | switch (hdr_type) { | 103 | switch (hdr_type) { |
| 77 | case PCI_HEADER_TYPE_NORMAL: | 104 | case PCI_HEADER_TYPE_NORMAL: |
| 78 | case PCI_HEADER_TYPE_BRIDGE: | 105 | case PCI_HEADER_TYPE_BRIDGE: |
| 79 | pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos); | 106 | pos = PCI_CAPABILITY_LIST; |
| 80 | break; | 107 | break; |
| 81 | case PCI_HEADER_TYPE_CARDBUS: | 108 | case PCI_HEADER_TYPE_CARDBUS: |
| 82 | pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos); | 109 | pos = PCI_CB_CAPABILITY_LIST; |
| 83 | break; | 110 | break; |
| 84 | default: | 111 | default: |
| 85 | return 0; | 112 | return 0; |
| 86 | } | 113 | } |
| 87 | while (ttl-- && pos >= 0x40) { | 114 | return __pci_find_next_cap(bus, devfn, pos, cap); |
| 88 | pos &= ~3; | ||
| 89 | pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id); | ||
| 90 | if (id == 0xff) | ||
| 91 | break; | ||
| 92 | if (id == cap) | ||
| 93 | return pos; | ||
| 94 | pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos); | ||
| 95 | } | ||
| 96 | return 0; | ||
| 97 | } | 115 | } |
| 98 | 116 | ||
| 99 | /** | 117 | /** |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5627ce1d2b32..3a4f49f4effb 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) | |||
| 462 | 462 | ||
| 463 | pci_read_config_word(dev, 0x70, &hm); | 463 | pci_read_config_word(dev, 0x70, &hm); |
| 464 | hm &= PCI_BASE_ADDRESS_IO_MASK; | 464 | hm &= PCI_BASE_ADDRESS_IO_MASK; |
| 465 | quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c868 HW-mon"); | 465 | quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c686 HW-mon"); |
| 466 | 466 | ||
| 467 | pci_read_config_dword(dev, 0x90, &smb); | 467 | pci_read_config_dword(dev, 0x90, &smb); |
| 468 | smb &= PCI_BASE_ADDRESS_IO_MASK; | 468 | smb &= PCI_BASE_ADDRESS_IO_MASK; |
| 469 | quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c868 SMB"); | 469 | quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB"); |
| 470 | } | 470 | } |
| 471 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi ); | 471 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi ); |
| 472 | 472 | ||
| @@ -1243,6 +1243,21 @@ static void __devinit quirk_netmos(struct pci_dev *dev) | |||
| 1243 | } | 1243 | } |
| 1244 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos); | 1244 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos); |
| 1245 | 1245 | ||
| 1246 | |||
| 1247 | static void __devinit fixup_rev1_53c810(struct pci_dev* dev) | ||
| 1248 | { | ||
| 1249 | /* rev 1 ncr53c810 chips don't set the class at all which means | ||
| 1250 | * they don't get their resources remapped. Fix that here. | ||
| 1251 | */ | ||
| 1252 | |||
| 1253 | if (dev->class == PCI_CLASS_NOT_DEFINED) { | ||
| 1254 | printk(KERN_INFO "NCR 53c810 rev 1 detected, setting PCI class.\n"); | ||
| 1255 | dev->class = PCI_CLASS_STORAGE_SCSI; | ||
| 1256 | } | ||
| 1257 | } | ||
| 1258 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); | ||
| 1259 | |||
| 1260 | |||
| 1246 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) | 1261 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) |
| 1247 | { | 1262 | { |
| 1248 | while (f < end) { | 1263 | while (f < end) { |
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 654469778ab5..b0f3cd63e3b9 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c | |||
| @@ -1970,7 +1970,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids); | |||
| 1970 | static struct pci_driver goku_pci_driver = { | 1970 | static struct pci_driver goku_pci_driver = { |
| 1971 | .name = (char *) driver_name, | 1971 | .name = (char *) driver_name, |
| 1972 | .id_table = pci_ids, | 1972 | .id_table = pci_ids, |
| 1973 | .owner = THIS_MODULE, | ||
| 1974 | 1973 | ||
| 1975 | .probe = goku_probe, | 1974 | .probe = goku_probe, |
| 1976 | .remove = goku_remove, | 1975 | .remove = goku_remove, |
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 0dc6bb00bf72..c32e1f7476da 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
| @@ -2948,7 +2948,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids); | |||
| 2948 | static struct pci_driver net2280_pci_driver = { | 2948 | static struct pci_driver net2280_pci_driver = { |
| 2949 | .name = (char *) driver_name, | 2949 | .name = (char *) driver_name, |
| 2950 | .id_table = pci_ids, | 2950 | .id_table = pci_ids, |
| 2951 | .owner = THIS_MODULE, | ||
| 2952 | 2951 | ||
| 2953 | .probe = net2280_probe, | 2952 | .probe = net2280_probe, |
| 2954 | .remove = net2280_remove, | 2953 | .remove = net2280_remove, |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 145008853966..dfd9bd0b1828 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
| @@ -383,7 +383,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids); | |||
| 383 | static struct pci_driver ehci_pci_driver = { | 383 | static struct pci_driver ehci_pci_driver = { |
| 384 | .name = (char *) hcd_name, | 384 | .name = (char *) hcd_name, |
| 385 | .id_table = pci_ids, | 385 | .id_table = pci_ids, |
| 386 | .owner = THIS_MODULE, | ||
| 387 | 386 | ||
| 388 | .probe = usb_hcd_pci_probe, | 387 | .probe = usb_hcd_pci_probe, |
| 389 | .remove = usb_hcd_pci_remove, | 388 | .remove = usb_hcd_pci_remove, |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 7ce1d9ef0289..a59e536441e1 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
| @@ -218,7 +218,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids); | |||
| 218 | static struct pci_driver ohci_pci_driver = { | 218 | static struct pci_driver ohci_pci_driver = { |
| 219 | .name = (char *) hcd_name, | 219 | .name = (char *) hcd_name, |
| 220 | .id_table = pci_ids, | 220 | .id_table = pci_ids, |
| 221 | .owner = THIS_MODULE, | ||
| 222 | 221 | ||
| 223 | .probe = usb_hcd_pci_probe, | 222 | .probe = usb_hcd_pci_probe, |
| 224 | .remove = usb_hcd_pci_remove, | 223 | .remove = usb_hcd_pci_remove, |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 15e0a511069b..d33ce3982a5f 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
| @@ -831,7 +831,6 @@ MODULE_DEVICE_TABLE(pci, uhci_pci_ids); | |||
| 831 | static struct pci_driver uhci_pci_driver = { | 831 | static struct pci_driver uhci_pci_driver = { |
| 832 | .name = (char *)hcd_name, | 832 | .name = (char *)hcd_name, |
| 833 | .id_table = uhci_pci_ids, | 833 | .id_table = uhci_pci_ids, |
| 834 | .owner = THIS_MODULE, | ||
| 835 | 834 | ||
| 836 | .probe = usb_hcd_pci_probe, | 835 | .probe = usb_hcd_pci_probe, |
| 837 | .remove = usb_hcd_pci_remove, | 836 | .remove = usb_hcd_pci_remove, |
diff --git a/include/asm-i386/msi.h b/include/asm-i386/msi.h index b85393094c83..f041d4495faf 100644 --- a/include/asm-i386/msi.h +++ b/include/asm-i386/msi.h | |||
| @@ -10,13 +10,6 @@ | |||
| 10 | #include <mach_apic.h> | 10 | #include <mach_apic.h> |
| 11 | 11 | ||
| 12 | #define LAST_DEVICE_VECTOR 232 | 12 | #define LAST_DEVICE_VECTOR 232 |
| 13 | #define MSI_DEST_MODE MSI_LOGICAL_MODE | 13 | #define MSI_TARGET_CPU_SHIFT 12 |
| 14 | #define MSI_TARGET_CPU_SHIFT 12 | ||
| 15 | |||
| 16 | #ifdef CONFIG_SMP | ||
| 17 | #define MSI_TARGET_CPU logical_smp_processor_id() | ||
| 18 | #else | ||
| 19 | #define MSI_TARGET_CPU cpu_to_logical_apicid(first_cpu(cpu_online_map)) | ||
| 20 | #endif | ||
| 21 | 14 | ||
| 22 | #endif /* ASM_MSI_H */ | 15 | #endif /* ASM_MSI_H */ |
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h index 13250199976d..61d3ab9db70c 100644 --- a/include/asm-i386/smp.h +++ b/include/asm-i386/smp.h | |||
| @@ -45,6 +45,8 @@ extern void unlock_ipi_call_lock(void); | |||
| 45 | #define MAX_APICID 256 | 45 | #define MAX_APICID 256 |
| 46 | extern u8 x86_cpu_to_apicid[]; | 46 | extern u8 x86_cpu_to_apicid[]; |
| 47 | 47 | ||
| 48 | #define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu] | ||
| 49 | |||
| 48 | #ifdef CONFIG_HOTPLUG_CPU | 50 | #ifdef CONFIG_HOTPLUG_CPU |
| 49 | extern void cpu_exit_clear(void); | 51 | extern void cpu_exit_clear(void); |
| 50 | extern void cpu_uninit(void); | 52 | extern void cpu_uninit(void); |
| @@ -92,6 +94,10 @@ extern int __cpu_disable(void); | |||
| 92 | extern void __cpu_die(unsigned int cpu); | 94 | extern void __cpu_die(unsigned int cpu); |
| 93 | #endif /* !__ASSEMBLY__ */ | 95 | #endif /* !__ASSEMBLY__ */ |
| 94 | 96 | ||
| 97 | #else /* CONFIG_SMP */ | ||
| 98 | |||
| 99 | #define cpu_physical_id(cpu) boot_cpu_physical_apicid | ||
| 100 | |||
| 95 | #define NO_PROC_ID 0xFF /* No processor magic marker */ | 101 | #define NO_PROC_ID 0xFF /* No processor magic marker */ |
| 96 | 102 | ||
| 97 | #endif | 103 | #endif |
diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h index 4d376e1663f7..8b01a083dde6 100644 --- a/include/asm-ia64/kdebug.h +++ b/include/asm-ia64/kdebug.h | |||
| @@ -22,6 +22,9 @@ | |||
| 22 | * 2005-Apr Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy | 22 | * 2005-Apr Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy |
| 23 | * <anil.s.keshavamurthy@intel.com> adopted from | 23 | * <anil.s.keshavamurthy@intel.com> adopted from |
| 24 | * include/asm-x86_64/kdebug.h | 24 | * include/asm-x86_64/kdebug.h |
| 25 | * | ||
| 26 | * 2005-Oct Keith Owens <kaos@sgi.com>. Expand notify_die to cover more | ||
| 27 | * events. | ||
| 25 | */ | 28 | */ |
| 26 | #include <linux/notifier.h> | 29 | #include <linux/notifier.h> |
| 27 | 30 | ||
| @@ -35,13 +38,36 @@ struct die_args { | |||
| 35 | int signr; | 38 | int signr; |
| 36 | }; | 39 | }; |
| 37 | 40 | ||
| 38 | int register_die_notifier(struct notifier_block *nb); | 41 | extern int register_die_notifier(struct notifier_block *); |
| 42 | extern int unregister_die_notifier(struct notifier_block *); | ||
| 39 | extern struct notifier_block *ia64die_chain; | 43 | extern struct notifier_block *ia64die_chain; |
| 40 | 44 | ||
| 41 | enum die_val { | 45 | enum die_val { |
| 42 | DIE_BREAK = 1, | 46 | DIE_BREAK = 1, |
| 43 | DIE_SS, | 47 | DIE_FAULT, |
| 48 | DIE_OOPS, | ||
| 44 | DIE_PAGE_FAULT, | 49 | DIE_PAGE_FAULT, |
| 50 | DIE_MACHINE_HALT, | ||
| 51 | DIE_MACHINE_RESTART, | ||
| 52 | DIE_MCA_MONARCH_ENTER, | ||
| 53 | DIE_MCA_MONARCH_PROCESS, | ||
| 54 | DIE_MCA_MONARCH_LEAVE, | ||
| 55 | DIE_MCA_SLAVE_ENTER, | ||
| 56 | DIE_MCA_SLAVE_PROCESS, | ||
| 57 | DIE_MCA_SLAVE_LEAVE, | ||
| 58 | DIE_MCA_RENDZVOUS_ENTER, | ||
| 59 | DIE_MCA_RENDZVOUS_PROCESS, | ||
| 60 | DIE_MCA_RENDZVOUS_LEAVE, | ||
| 61 | DIE_INIT_MONARCH_ENTER, | ||
| 62 | DIE_INIT_MONARCH_PROCESS, | ||
| 63 | DIE_INIT_MONARCH_LEAVE, | ||
| 64 | DIE_INIT_SLAVE_ENTER, | ||
| 65 | DIE_INIT_SLAVE_PROCESS, | ||
| 66 | DIE_INIT_SLAVE_LEAVE, | ||
| 67 | DIE_KDEBUG_ENTER, | ||
| 68 | DIE_KDEBUG_LEAVE, | ||
| 69 | DIE_KDUMP_ENTER, | ||
| 70 | DIE_KDUMP_LEAVE, | ||
| 45 | }; | 71 | }; |
| 46 | 72 | ||
| 47 | static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs, | 73 | static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs, |
diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h index 8d6e72f7b08e..b5c65081a3aa 100644 --- a/include/asm-ia64/mmu_context.h +++ b/include/asm-ia64/mmu_context.h | |||
| @@ -7,12 +7,13 @@ | |||
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | /* | 9 | /* |
| 10 | * Routines to manage the allocation of task context numbers. Task context numbers are | 10 | * Routines to manage the allocation of task context numbers. Task context |
| 11 | * used to reduce or eliminate the need to perform TLB flushes due to context switches. | 11 | * numbers are used to reduce or eliminate the need to perform TLB flushes |
| 12 | * Context numbers are implemented using ia-64 region ids. Since the IA-64 TLB does not | 12 | * due to context switches. Context numbers are implemented using ia-64 |
| 13 | * consider the region number when performing a TLB lookup, we need to assign a unique | 13 | * region ids. Since the IA-64 TLB does not consider the region number when |
| 14 | * region id to each region in a process. We use the least significant three bits in a | 14 | * performing a TLB lookup, we need to assign a unique region id to each |
| 15 | * region id for this purpose. | 15 | * region in a process. We use the least significant three bits in aregion |
| 16 | * id for this purpose. | ||
| 16 | */ | 17 | */ |
| 17 | 18 | ||
| 18 | #define IA64_REGION_ID_KERNEL 0 /* the kernel's region id (tlb.c depends on this being 0) */ | 19 | #define IA64_REGION_ID_KERNEL 0 /* the kernel's region id (tlb.c depends on this being 0) */ |
| @@ -32,13 +33,17 @@ | |||
| 32 | struct ia64_ctx { | 33 | struct ia64_ctx { |
| 33 | spinlock_t lock; | 34 | spinlock_t lock; |
| 34 | unsigned int next; /* next context number to use */ | 35 | unsigned int next; /* next context number to use */ |
| 35 | unsigned int limit; /* next >= limit => must call wrap_mmu_context() */ | 36 | unsigned int limit; /* available free range */ |
| 36 | unsigned int max_ctx; /* max. context value supported by all CPUs */ | 37 | unsigned int max_ctx; /* max. context value supported by all CPUs */ |
| 38 | /* call wrap_mmu_context when next >= max */ | ||
| 39 | unsigned long *bitmap; /* bitmap size is max_ctx+1 */ | ||
| 40 | unsigned long *flushmap;/* pending rid to be flushed */ | ||
| 37 | }; | 41 | }; |
| 38 | 42 | ||
| 39 | extern struct ia64_ctx ia64_ctx; | 43 | extern struct ia64_ctx ia64_ctx; |
| 40 | DECLARE_PER_CPU(u8, ia64_need_tlb_flush); | 44 | DECLARE_PER_CPU(u8, ia64_need_tlb_flush); |
| 41 | 45 | ||
| 46 | extern void mmu_context_init (void); | ||
| 42 | extern void wrap_mmu_context (struct mm_struct *mm); | 47 | extern void wrap_mmu_context (struct mm_struct *mm); |
| 43 | 48 | ||
| 44 | static inline void | 49 | static inline void |
| @@ -47,10 +52,10 @@ enter_lazy_tlb (struct mm_struct *mm, struct task_struct *tsk) | |||
| 47 | } | 52 | } |
| 48 | 53 | ||
| 49 | /* | 54 | /* |
| 50 | * When the context counter wraps around all TLBs need to be flushed because an old | 55 | * When the context counter wraps around all TLBs need to be flushed because |
| 51 | * context number might have been reused. This is signalled by the ia64_need_tlb_flush | 56 | * an old context number might have been reused. This is signalled by the |
| 52 | * per-CPU variable, which is checked in the routine below. Called by activate_mm(). | 57 | * ia64_need_tlb_flush per-CPU variable, which is checked in the routine |
| 53 | * <efocht@ess.nec.de> | 58 | * below. Called by activate_mm(). <efocht@ess.nec.de> |
| 54 | */ | 59 | */ |
| 55 | static inline void | 60 | static inline void |
| 56 | delayed_tlb_flush (void) | 61 | delayed_tlb_flush (void) |
| @@ -60,11 +65,9 @@ delayed_tlb_flush (void) | |||
| 60 | 65 | ||
| 61 | if (unlikely(__ia64_per_cpu_var(ia64_need_tlb_flush))) { | 66 | if (unlikely(__ia64_per_cpu_var(ia64_need_tlb_flush))) { |
| 62 | spin_lock_irqsave(&ia64_ctx.lock, flags); | 67 | spin_lock_irqsave(&ia64_ctx.lock, flags); |
| 63 | { | 68 | if (__ia64_per_cpu_var(ia64_need_tlb_flush)) { |
| 64 | if (__ia64_per_cpu_var(ia64_need_tlb_flush)) { | 69 | local_flush_tlb_all(); |
| 65 | local_flush_tlb_all(); | 70 | __ia64_per_cpu_var(ia64_need_tlb_flush) = 0; |
| 66 | __ia64_per_cpu_var(ia64_need_tlb_flush) = 0; | ||
| 67 | } | ||
| 68 | } | 71 | } |
| 69 | spin_unlock_irqrestore(&ia64_ctx.lock, flags); | 72 | spin_unlock_irqrestore(&ia64_ctx.lock, flags); |
| 70 | } | 73 | } |
| @@ -76,20 +79,27 @@ get_mmu_context (struct mm_struct *mm) | |||
| 76 | unsigned long flags; | 79 | unsigned long flags; |
| 77 | nv_mm_context_t context = mm->context; | 80 | nv_mm_context_t context = mm->context; |
| 78 | 81 | ||
| 79 | if (unlikely(!context)) { | 82 | if (likely(context)) |
| 80 | spin_lock_irqsave(&ia64_ctx.lock, flags); | 83 | goto out; |
| 81 | { | 84 | |
| 82 | /* re-check, now that we've got the lock: */ | 85 | spin_lock_irqsave(&ia64_ctx.lock, flags); |
| 83 | context = mm->context; | 86 | /* re-check, now that we've got the lock: */ |
| 84 | if (context == 0) { | 87 | context = mm->context; |
| 85 | cpus_clear(mm->cpu_vm_mask); | 88 | if (context == 0) { |
| 86 | if (ia64_ctx.next >= ia64_ctx.limit) | 89 | cpus_clear(mm->cpu_vm_mask); |
| 87 | wrap_mmu_context(mm); | 90 | if (ia64_ctx.next >= ia64_ctx.limit) { |
| 88 | mm->context = context = ia64_ctx.next++; | 91 | ia64_ctx.next = find_next_zero_bit(ia64_ctx.bitmap, |
| 89 | } | 92 | ia64_ctx.max_ctx, ia64_ctx.next); |
| 93 | ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap, | ||
| 94 | ia64_ctx.max_ctx, ia64_ctx.next); | ||
| 95 | if (ia64_ctx.next >= ia64_ctx.max_ctx) | ||
| 96 | wrap_mmu_context(mm); | ||
| 90 | } | 97 | } |
| 91 | spin_unlock_irqrestore(&ia64_ctx.lock, flags); | 98 | mm->context = context = ia64_ctx.next++; |
| 99 | __set_bit(context, ia64_ctx.bitmap); | ||
| 92 | } | 100 | } |
| 101 | spin_unlock_irqrestore(&ia64_ctx.lock, flags); | ||
| 102 | out: | ||
| 93 | /* | 103 | /* |
| 94 | * Ensure we're not starting to use "context" before any old | 104 | * Ensure we're not starting to use "context" before any old |
| 95 | * uses of it are gone from our TLB. | 105 | * uses of it are gone from our TLB. |
| @@ -100,8 +110,8 @@ get_mmu_context (struct mm_struct *mm) | |||
| 100 | } | 110 | } |
| 101 | 111 | ||
| 102 | /* | 112 | /* |
| 103 | * Initialize context number to some sane value. MM is guaranteed to be a brand-new | 113 | * Initialize context number to some sane value. MM is guaranteed to be a |
| 104 | * address-space, so no TLB flushing is needed, ever. | 114 | * brand-new address-space, so no TLB flushing is needed, ever. |
| 105 | */ | 115 | */ |
| 106 | static inline int | 116 | static inline int |
| 107 | init_new_context (struct task_struct *p, struct mm_struct *mm) | 117 | init_new_context (struct task_struct *p, struct mm_struct *mm) |
| @@ -162,7 +172,10 @@ activate_context (struct mm_struct *mm) | |||
| 162 | if (!cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) | 172 | if (!cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) |
| 163 | cpu_set(smp_processor_id(), mm->cpu_vm_mask); | 173 | cpu_set(smp_processor_id(), mm->cpu_vm_mask); |
| 164 | reload_context(context); | 174 | reload_context(context); |
| 165 | /* in the unlikely event of a TLB-flush by another thread, redo the load: */ | 175 | /* |
| 176 | * in the unlikely event of a TLB-flush by another thread, | ||
| 177 | * redo the load. | ||
| 178 | */ | ||
| 166 | } while (unlikely(context != mm->context)); | 179 | } while (unlikely(context != mm->context)); |
| 167 | } | 180 | } |
| 168 | 181 | ||
| @@ -175,8 +188,8 @@ static inline void | |||
| 175 | activate_mm (struct mm_struct *prev, struct mm_struct *next) | 188 | activate_mm (struct mm_struct *prev, struct mm_struct *next) |
| 176 | { | 189 | { |
| 177 | /* | 190 | /* |
| 178 | * We may get interrupts here, but that's OK because interrupt handlers cannot | 191 | * We may get interrupts here, but that's OK because interrupt |
| 179 | * touch user-space. | 192 | * handlers cannot touch user-space. |
| 180 | */ | 193 | */ |
| 181 | ia64_set_kr(IA64_KR_PT_BASE, __pa(next->pgd)); | 194 | ia64_set_kr(IA64_KR_PT_BASE, __pa(next->pgd)); |
| 182 | activate_context(next); | 195 | activate_context(next); |
diff --git a/include/asm-ia64/msi.h b/include/asm-ia64/msi.h index 60f2137f9278..97890f7762b3 100644 --- a/include/asm-ia64/msi.h +++ b/include/asm-ia64/msi.h | |||
| @@ -12,9 +12,6 @@ | |||
| 12 | static inline void set_intr_gate (int nr, void *func) {} | 12 | static inline void set_intr_gate (int nr, void *func) {} |
| 13 | #define IO_APIC_VECTOR(irq) (irq) | 13 | #define IO_APIC_VECTOR(irq) (irq) |
| 14 | #define ack_APIC_irq ia64_eoi | 14 | #define ack_APIC_irq ia64_eoi |
| 15 | #define cpu_mask_to_apicid(mask) cpu_physical_id(first_cpu(mask)) | ||
| 16 | #define MSI_DEST_MODE MSI_PHYSICAL_MODE | ||
| 17 | #define MSI_TARGET_CPU ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff) | ||
| 18 | #define MSI_TARGET_CPU_SHIFT 4 | 15 | #define MSI_TARGET_CPU_SHIFT 4 |
| 19 | 16 | ||
| 20 | #endif /* ASM_MSI_H */ | 17 | #endif /* ASM_MSI_H */ |
diff --git a/include/asm-ia64/tlbflush.h b/include/asm-ia64/tlbflush.h index b65c62702724..a35b323bae4c 100644 --- a/include/asm-ia64/tlbflush.h +++ b/include/asm-ia64/tlbflush.h | |||
| @@ -51,6 +51,7 @@ flush_tlb_mm (struct mm_struct *mm) | |||
| 51 | if (!mm) | 51 | if (!mm) |
| 52 | return; | 52 | return; |
| 53 | 53 | ||
| 54 | set_bit(mm->context, ia64_ctx.flushmap); | ||
| 54 | mm->context = 0; | 55 | mm->context = 0; |
| 55 | 56 | ||
| 56 | if (atomic_read(&mm->mm_users) == 0) | 57 | if (atomic_read(&mm->mm_users) == 0) |
diff --git a/include/asm-x86_64/msi.h b/include/asm-x86_64/msi.h index 85c427e472bf..356e0e82f50b 100644 --- a/include/asm-x86_64/msi.h +++ b/include/asm-x86_64/msi.h | |||
| @@ -11,8 +11,6 @@ | |||
| 11 | #include <asm/smp.h> | 11 | #include <asm/smp.h> |
| 12 | 12 | ||
| 13 | #define LAST_DEVICE_VECTOR 232 | 13 | #define LAST_DEVICE_VECTOR 232 |
| 14 | #define MSI_DEST_MODE MSI_LOGICAL_MODE | 14 | #define MSI_TARGET_CPU_SHIFT 12 |
| 15 | #define MSI_TARGET_CPU_SHIFT 12 | ||
| 16 | #define MSI_TARGET_CPU logical_smp_processor_id() | ||
| 17 | 15 | ||
| 18 | #endif /* ASM_MSI_H */ | 16 | #endif /* ASM_MSI_H */ |
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h index c57ce4071342..b9fb2173ef99 100644 --- a/include/asm-x86_64/smp.h +++ b/include/asm-x86_64/smp.h | |||
| @@ -135,5 +135,11 @@ static __inline int logical_smp_processor_id(void) | |||
| 135 | } | 135 | } |
| 136 | #endif | 136 | #endif |
| 137 | 137 | ||
| 138 | #ifdef CONFIG_SMP | ||
| 139 | #define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu] | ||
| 140 | #else | ||
| 141 | #define cpu_physical_id(cpu) boot_cpu_id | ||
| 142 | #endif | ||
| 143 | |||
| 138 | #endif | 144 | #endif |
| 139 | 145 | ||
diff --git a/include/linux/ide.h b/include/linux/ide.h index 77ae55d4c13c..ac8b25fa6506 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
| @@ -1329,7 +1329,8 @@ void ide_init_disk(struct gendisk *, ide_drive_t *); | |||
| 1329 | extern int ideprobe_init(void); | 1329 | extern int ideprobe_init(void); |
| 1330 | 1330 | ||
| 1331 | extern void ide_scan_pcibus(int scan_direction) __init; | 1331 | extern void ide_scan_pcibus(int scan_direction) __init; |
| 1332 | extern int ide_pci_register_driver(struct pci_driver *driver); | 1332 | extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner); |
| 1333 | #define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE) | ||
| 1333 | extern void ide_pci_unregister_driver(struct pci_driver *driver); | 1334 | extern void ide_pci_unregister_driver(struct pci_driver *driver); |
| 1334 | void ide_pci_setup_ports(struct pci_dev *, struct ide_pci_device_s *, int, ata_index_t *); | 1335 | void ide_pci_setup_ports(struct pci_dev *, struct ide_pci_device_s *, int, ata_index_t *); |
| 1335 | extern void ide_setup_pci_noise (struct pci_dev *dev, struct ide_pci_device_s *d); | 1336 | extern void ide_setup_pci_noise (struct pci_dev *dev, struct ide_pci_device_s *d); |
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 857126a36ecc..4877e35ae202 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h | |||
| @@ -47,14 +47,15 @@ | |||
| 47 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) | 47 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) |
| 48 | 48 | ||
| 49 | #ifdef CONFIG_ACPI | 49 | #ifdef CONFIG_ACPI |
| 50 | extern acpi_status pci_osc_control_set(u32 flags); | 50 | extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags); |
| 51 | extern acpi_status pci_osc_support_set(u32 flags); | 51 | extern acpi_status pci_osc_support_set(u32 flags); |
| 52 | #else | 52 | #else |
| 53 | #if !defined(acpi_status) | 53 | #if !defined(acpi_status) |
| 54 | typedef u32 acpi_status; | 54 | typedef u32 acpi_status; |
| 55 | #define AE_ERROR (acpi_status) (0x0001) | 55 | #define AE_ERROR (acpi_status) (0x0001) |
| 56 | #endif | 56 | #endif |
| 57 | static inline acpi_status pci_osc_control_set(u32 flags) {return AE_ERROR;} | 57 | static inline acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) |
| 58 | {return AE_ERROR;} | ||
| 58 | static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;} | 59 | static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;} |
| 59 | #endif | 60 | #endif |
| 60 | 61 | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index 3596ac94ecff..de690ca73d58 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
| @@ -236,7 +236,6 @@ struct module; | |||
| 236 | struct pci_driver { | 236 | struct pci_driver { |
| 237 | struct list_head node; | 237 | struct list_head node; |
| 238 | char *name; | 238 | char *name; |
| 239 | struct module *owner; | ||
| 240 | const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */ | 239 | const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */ |
| 241 | int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ | 240 | int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ |
| 242 | void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ | 241 | void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ |
| @@ -338,6 +337,7 @@ struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, const | |||
| 338 | struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int device, const struct pci_dev *from); | 337 | struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int device, const struct pci_dev *from); |
| 339 | struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); | 338 | struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); |
| 340 | int pci_find_capability (struct pci_dev *dev, int cap); | 339 | int pci_find_capability (struct pci_dev *dev, int cap); |
| 340 | int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap); | ||
| 341 | int pci_find_ext_capability (struct pci_dev *dev, int cap); | 341 | int pci_find_ext_capability (struct pci_dev *dev, int cap); |
| 342 | struct pci_bus * pci_find_next_bus(const struct pci_bus *from); | 342 | struct pci_bus * pci_find_next_bus(const struct pci_bus *from); |
| 343 | 343 | ||
| @@ -432,8 +432,13 @@ int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | |||
| 432 | void *alignf_data); | 432 | void *alignf_data); |
| 433 | void pci_enable_bridges(struct pci_bus *bus); | 433 | void pci_enable_bridges(struct pci_bus *bus); |
| 434 | 434 | ||
| 435 | /* New-style probing supporting hot-pluggable devices */ | 435 | /* Proper probing supporting hot-pluggable devices */ |
| 436 | int pci_register_driver(struct pci_driver *); | 436 | int __pci_register_driver(struct pci_driver *, struct module *); |
| 437 | static inline int pci_register_driver(struct pci_driver *driver) | ||
| 438 | { | ||
| 439 | return __pci_register_driver(driver, THIS_MODULE); | ||
| 440 | } | ||
| 441 | |||
| 437 | void pci_unregister_driver(struct pci_driver *); | 442 | void pci_unregister_driver(struct pci_driver *); |
| 438 | void pci_remove_behind_bridge(struct pci_dev *); | 443 | void pci_remove_behind_bridge(struct pci_dev *); |
| 439 | struct pci_driver *pci_dev_driver(const struct pci_dev *); | 444 | struct pci_driver *pci_dev_driver(const struct pci_dev *); |
| @@ -547,9 +552,11 @@ static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } | |||
| 547 | static inline void pci_disable_device(struct pci_dev *dev) { } | 552 | static inline void pci_disable_device(struct pci_dev *dev) { } |
| 548 | static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; } | 553 | static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; } |
| 549 | static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;} | 554 | static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;} |
| 555 | static inline int __pci_register_driver(struct pci_driver *drv, struct module *owner) { return 0;} | ||
| 550 | static inline int pci_register_driver(struct pci_driver *drv) { return 0;} | 556 | static inline int pci_register_driver(struct pci_driver *drv) { return 0;} |
| 551 | static inline void pci_unregister_driver(struct pci_driver *drv) { } | 557 | static inline void pci_unregister_driver(struct pci_driver *drv) { } |
| 552 | static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; } | 558 | static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; } |
| 559 | static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; } | ||
| 553 | static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; } | 560 | static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; } |
| 554 | static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; } | 561 | static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; } |
| 555 | 562 | ||
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index e72ccd1a004f..1fdae678a345 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c | |||
| @@ -1067,7 +1067,6 @@ MODULE_DEVICE_TABLE(pci, snd_ad1889_ids); | |||
| 1067 | 1067 | ||
| 1068 | static struct pci_driver ad1889_pci = { | 1068 | static struct pci_driver ad1889_pci = { |
| 1069 | .name = "AD1889 Audio", | 1069 | .name = "AD1889 Audio", |
| 1070 | .owner = THIS_MODULE, | ||
| 1071 | .id_table = snd_ad1889_ids, | 1070 | .id_table = snd_ad1889_ids, |
| 1072 | .probe = snd_ad1889_probe, | 1071 | .probe = snd_ad1889_probe, |
| 1073 | .remove = __devexit_p(snd_ad1889_remove), | 1072 | .remove = __devexit_p(snd_ad1889_remove), |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 4e76c4a636d9..feffbe73387e 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
| @@ -2403,7 +2403,6 @@ static void __devexit snd_ali_remove(struct pci_dev *pci) | |||
| 2403 | 2403 | ||
| 2404 | static struct pci_driver driver = { | 2404 | static struct pci_driver driver = { |
| 2405 | .name = "ALI 5451", | 2405 | .name = "ALI 5451", |
| 2406 | .owner = THIS_MODULE, | ||
| 2407 | .id_table = snd_ali_ids, | 2406 | .id_table = snd_ali_ids, |
| 2408 | .probe = snd_ali_probe, | 2407 | .probe = snd_ali_probe, |
| 2409 | .remove = __devexit_p(snd_ali_remove), | 2408 | .remove = __devexit_p(snd_ali_remove), |
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 7c61561f297f..1904df650265 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
| @@ -768,7 +768,6 @@ static void __devexit snd_card_als4000_remove(struct pci_dev *pci) | |||
| 768 | 768 | ||
| 769 | static struct pci_driver driver = { | 769 | static struct pci_driver driver = { |
| 770 | .name = "ALS4000", | 770 | .name = "ALS4000", |
| 771 | .owner = THIS_MODULE, | ||
| 772 | .id_table = snd_als4000_ids, | 771 | .id_table = snd_als4000_ids, |
| 773 | .probe = snd_card_als4000_probe, | 772 | .probe = snd_card_als4000_probe, |
| 774 | .remove = __devexit_p(snd_card_als4000_remove), | 773 | .remove = __devexit_p(snd_card_als4000_remove), |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index f5dad9248e39..8bae10d93529 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
| @@ -1635,7 +1635,6 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci) | |||
| 1635 | 1635 | ||
| 1636 | static struct pci_driver driver = { | 1636 | static struct pci_driver driver = { |
| 1637 | .name = "ATI IXP AC97 controller", | 1637 | .name = "ATI IXP AC97 controller", |
| 1638 | .owner = THIS_MODULE, | ||
| 1639 | .id_table = snd_atiixp_ids, | 1638 | .id_table = snd_atiixp_ids, |
| 1640 | .probe = snd_atiixp_probe, | 1639 | .probe = snd_atiixp_probe, |
| 1641 | .remove = __devexit_p(snd_atiixp_remove), | 1640 | .remove = __devexit_p(snd_atiixp_remove), |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 0cf202079571..3174b6625419 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
| @@ -1309,7 +1309,6 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci) | |||
| 1309 | 1309 | ||
| 1310 | static struct pci_driver driver = { | 1310 | static struct pci_driver driver = { |
| 1311 | .name = "ATI IXP MC97 controller", | 1311 | .name = "ATI IXP MC97 controller", |
| 1312 | .owner = THIS_MODULE, | ||
| 1313 | .id_table = snd_atiixp_ids, | 1312 | .id_table = snd_atiixp_ids, |
| 1314 | .probe = snd_atiixp_probe, | 1313 | .probe = snd_atiixp_probe, |
| 1315 | .remove = __devexit_p(snd_atiixp_remove), | 1314 | .remove = __devexit_p(snd_atiixp_remove), |
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 6af3b13f2fd1..d965609d8b38 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c | |||
| @@ -373,7 +373,6 @@ static void __devexit snd_vortex_remove(struct pci_dev *pci) | |||
| 373 | // pci_driver definition | 373 | // pci_driver definition |
| 374 | static struct pci_driver driver = { | 374 | static struct pci_driver driver = { |
| 375 | .name = CARD_NAME_SHORT, | 375 | .name = CARD_NAME_SHORT, |
| 376 | .owner = THIS_MODULE, | ||
| 377 | .id_table = snd_vortex_ids, | 376 | .id_table = snd_vortex_ids, |
| 378 | .probe = snd_vortex_probe, | 377 | .probe = snd_vortex_probe, |
| 379 | .remove = __devexit_p(snd_vortex_remove), | 378 | .remove = __devexit_p(snd_vortex_remove), |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index da99b1be2e8f..ab737d6df41d 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
| @@ -1838,7 +1838,6 @@ snd_azf3328_remove(struct pci_dev *pci) | |||
| 1838 | 1838 | ||
| 1839 | static struct pci_driver driver = { | 1839 | static struct pci_driver driver = { |
| 1840 | .name = "AZF3328", | 1840 | .name = "AZF3328", |
| 1841 | .owner = THIS_MODULE, | ||
| 1842 | .id_table = snd_azf3328_ids, | 1841 | .id_table = snd_azf3328_ids, |
| 1843 | .probe = snd_azf3328_probe, | 1842 | .probe = snd_azf3328_probe, |
| 1844 | .remove = __devexit_p(snd_azf3328_remove), | 1843 | .remove = __devexit_p(snd_azf3328_remove), |
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 01d98eeb242e..8feca228c6d4 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
| @@ -897,14 +897,13 @@ static void __devexit snd_bt87x_remove(struct pci_dev *pci) | |||
| 897 | /* default entries for all Bt87x cards - it's not exported */ | 897 | /* default entries for all Bt87x cards - it's not exported */ |
| 898 | /* driver_data is set to 0 to call detection */ | 898 | /* driver_data is set to 0 to call detection */ |
| 899 | static struct pci_device_id snd_bt87x_default_ids[] = { | 899 | static struct pci_device_id snd_bt87x_default_ids[] = { |
| 900 | BT_DEVICE(878, PCI_ANY_ID, PCI_ANY_ID, 0), | 900 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, 0), |
| 901 | BT_DEVICE(879, PCI_ANY_ID, PCI_ANY_ID, 0), | 901 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, 0), |
| 902 | { } | 902 | { } |
| 903 | }; | 903 | }; |
| 904 | 904 | ||
| 905 | static struct pci_driver driver = { | 905 | static struct pci_driver driver = { |
| 906 | .name = "Bt87x", | 906 | .name = "Bt87x", |
| 907 | .owner = THIS_MODULE, | ||
| 908 | .id_table = snd_bt87x_ids, | 907 | .id_table = snd_bt87x_ids, |
| 909 | .probe = snd_bt87x_probe, | 908 | .probe = snd_bt87x_probe, |
| 910 | .remove = __devexit_p(snd_bt87x_remove), | 909 | .remove = __devexit_p(snd_bt87x_remove), |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index ee58d16002e5..389d967c97f4 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
| @@ -1499,7 +1499,6 @@ MODULE_DEVICE_TABLE(pci, snd_ca0106_ids); | |||
| 1499 | // pci_driver definition | 1499 | // pci_driver definition |
| 1500 | static struct pci_driver driver = { | 1500 | static struct pci_driver driver = { |
| 1501 | .name = "CA0106", | 1501 | .name = "CA0106", |
| 1502 | .owner = THIS_MODULE, | ||
| 1503 | .id_table = snd_ca0106_ids, | 1502 | .id_table = snd_ca0106_ids, |
| 1504 | .probe = snd_ca0106_probe, | 1503 | .probe = snd_ca0106_probe, |
| 1505 | .remove = __devexit_p(snd_ca0106_remove), | 1504 | .remove = __devexit_p(snd_ca0106_remove), |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 57e8e433d56f..db605373b3bc 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
| @@ -3053,7 +3053,6 @@ static void __devexit snd_cmipci_remove(struct pci_dev *pci) | |||
| 3053 | 3053 | ||
| 3054 | static struct pci_driver driver = { | 3054 | static struct pci_driver driver = { |
| 3055 | .name = "C-Media PCI", | 3055 | .name = "C-Media PCI", |
| 3056 | .owner = THIS_MODULE, | ||
| 3057 | .id_table = snd_cmipci_ids, | 3056 | .id_table = snd_cmipci_ids, |
| 3058 | .probe = snd_cmipci_probe, | 3057 | .probe = snd_cmipci_probe, |
| 3059 | .remove = __devexit_p(snd_cmipci_remove), | 3058 | .remove = __devexit_p(snd_cmipci_remove), |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index aea2c47712f9..034ff3755a3b 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
| @@ -2106,7 +2106,6 @@ static int cs4281_resume(snd_card_t *card) | |||
| 2106 | 2106 | ||
| 2107 | static struct pci_driver driver = { | 2107 | static struct pci_driver driver = { |
| 2108 | .name = "CS4281", | 2108 | .name = "CS4281", |
| 2109 | .owner = THIS_MODULE, | ||
| 2110 | .id_table = snd_cs4281_ids, | 2109 | .id_table = snd_cs4281_ids, |
| 2111 | .probe = snd_cs4281_probe, | 2110 | .probe = snd_cs4281_probe, |
| 2112 | .remove = __devexit_p(snd_cs4281_remove), | 2111 | .remove = __devexit_p(snd_cs4281_remove), |
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 32b4f8465cef..b9fff4ee6f9d 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c | |||
| @@ -163,7 +163,6 @@ static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci) | |||
| 163 | 163 | ||
| 164 | static struct pci_driver driver = { | 164 | static struct pci_driver driver = { |
| 165 | .name = "Sound Fusion CS46xx", | 165 | .name = "Sound Fusion CS46xx", |
| 166 | .owner = THIS_MODULE, | ||
| 167 | .id_table = snd_cs46xx_ids, | 166 | .id_table = snd_cs46xx_ids, |
| 168 | .probe = snd_card_cs46xx_probe, | 167 | .probe = snd_card_cs46xx_probe, |
| 169 | .remove = __devexit_p(snd_card_cs46xx_remove), | 168 | .remove = __devexit_p(snd_card_cs46xx_remove), |
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index dd1ea9d3b81a..78270f8710ff 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
| @@ -223,7 +223,6 @@ static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci) | |||
| 223 | 223 | ||
| 224 | static struct pci_driver driver = { | 224 | static struct pci_driver driver = { |
| 225 | .name = "EMU10K1_Audigy", | 225 | .name = "EMU10K1_Audigy", |
| 226 | .owner = THIS_MODULE, | ||
| 227 | .id_table = snd_emu10k1_ids, | 226 | .id_table = snd_emu10k1_ids, |
| 228 | .probe = snd_card_emu10k1_probe, | 227 | .probe = snd_card_emu10k1_probe, |
| 229 | .remove = __devexit_p(snd_card_emu10k1_remove), | 228 | .remove = __devexit_p(snd_card_emu10k1_remove), |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index cbb689474e7d..795577716a5d 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
| @@ -1613,7 +1613,6 @@ MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids); | |||
| 1613 | // pci_driver definition | 1613 | // pci_driver definition |
| 1614 | static struct pci_driver driver = { | 1614 | static struct pci_driver driver = { |
| 1615 | .name = "EMU10K1X", | 1615 | .name = "EMU10K1X", |
| 1616 | .owner = THIS_MODULE, | ||
| 1617 | .id_table = snd_emu10k1x_ids, | 1616 | .id_table = snd_emu10k1x_ids, |
| 1618 | .probe = snd_emu10k1x_probe, | 1617 | .probe = snd_emu10k1x_probe, |
| 1619 | .remove = __devexit_p(snd_emu10k1x_remove), | 1618 | .remove = __devexit_p(snd_emu10k1x_remove), |
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 92ff7c510f2b..2daa575f43ff 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
| @@ -2386,7 +2386,6 @@ static void __devexit snd_audiopci_remove(struct pci_dev *pci) | |||
| 2386 | 2386 | ||
| 2387 | static struct pci_driver driver = { | 2387 | static struct pci_driver driver = { |
| 2388 | .name = DRIVER_NAME, | 2388 | .name = DRIVER_NAME, |
| 2389 | .owner = THIS_MODULE, | ||
| 2390 | .id_table = snd_audiopci_ids, | 2389 | .id_table = snd_audiopci_ids, |
| 2391 | .probe = snd_audiopci_probe, | 2390 | .probe = snd_audiopci_probe, |
| 2392 | .remove = __devexit_p(snd_audiopci_remove), | 2391 | .remove = __devexit_p(snd_audiopci_remove), |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 78f90defcab1..c134f48152b0 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
| @@ -1758,7 +1758,6 @@ static void __devexit snd_es1938_remove(struct pci_dev *pci) | |||
| 1758 | 1758 | ||
| 1759 | static struct pci_driver driver = { | 1759 | static struct pci_driver driver = { |
| 1760 | .name = "ESS ES1938 (Solo-1)", | 1760 | .name = "ESS ES1938 (Solo-1)", |
| 1761 | .owner = THIS_MODULE, | ||
| 1762 | .id_table = snd_es1938_ids, | 1761 | .id_table = snd_es1938_ids, |
| 1763 | .probe = snd_es1938_probe, | 1762 | .probe = snd_es1938_probe, |
| 1764 | .remove = __devexit_p(snd_es1938_remove), | 1763 | .remove = __devexit_p(snd_es1938_remove), |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index ac8294e21cc1..50079dc90743 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
| @@ -2761,7 +2761,6 @@ static void __devexit snd_es1968_remove(struct pci_dev *pci) | |||
| 2761 | 2761 | ||
| 2762 | static struct pci_driver driver = { | 2762 | static struct pci_driver driver = { |
| 2763 | .name = "ES1968 (ESS Maestro)", | 2763 | .name = "ES1968 (ESS Maestro)", |
| 2764 | .owner = THIS_MODULE, | ||
| 2765 | .id_table = snd_es1968_ids, | 2764 | .id_table = snd_es1968_ids, |
| 2766 | .probe = snd_es1968_probe, | 2765 | .probe = snd_es1968_probe, |
| 2767 | .remove = __devexit_p(snd_es1968_remove), | 2766 | .remove = __devexit_p(snd_es1968_remove), |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 4c7c8d225c7f..4e1d3434888d 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
| @@ -1459,7 +1459,6 @@ static void __devexit snd_card_fm801_remove(struct pci_dev *pci) | |||
| 1459 | 1459 | ||
| 1460 | static struct pci_driver driver = { | 1460 | static struct pci_driver driver = { |
| 1461 | .name = "FM801", | 1461 | .name = "FM801", |
| 1462 | .owner = THIS_MODULE, | ||
| 1463 | .id_table = snd_fm801_ids, | 1462 | .id_table = snd_fm801_ids, |
| 1464 | .probe = snd_card_fm801_probe, | 1463 | .probe = snd_card_fm801_probe, |
| 1465 | .remove = __devexit_p(snd_card_fm801_remove), | 1464 | .remove = __devexit_p(snd_card_fm801_remove), |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 9d1412a9f2f8..ed525c03c996 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -1616,7 +1616,6 @@ MODULE_DEVICE_TABLE(pci, azx_ids); | |||
| 1616 | /* pci_driver definition */ | 1616 | /* pci_driver definition */ |
| 1617 | static struct pci_driver driver = { | 1617 | static struct pci_driver driver = { |
| 1618 | .name = "HDA Intel", | 1618 | .name = "HDA Intel", |
| 1619 | .owner = THIS_MODULE, | ||
| 1620 | .id_table = azx_ids, | 1619 | .id_table = azx_ids, |
| 1621 | .probe = azx_probe, | 1620 | .probe = azx_probe, |
| 1622 | .remove = __devexit_p(azx_remove), | 1621 | .remove = __devexit_p(azx_remove), |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 5aca37798c32..bd71bf424549 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
| @@ -2735,7 +2735,6 @@ static void __devexit snd_ice1712_remove(struct pci_dev *pci) | |||
| 2735 | 2735 | ||
| 2736 | static struct pci_driver driver = { | 2736 | static struct pci_driver driver = { |
| 2737 | .name = "ICE1712", | 2737 | .name = "ICE1712", |
| 2738 | .owner = THIS_MODULE, | ||
| 2739 | .id_table = snd_ice1712_ids, | 2738 | .id_table = snd_ice1712_ids, |
| 2740 | .probe = snd_ice1712_probe, | 2739 | .probe = snd_ice1712_probe, |
| 2741 | .remove = __devexit_p(snd_ice1712_remove), | 2740 | .remove = __devexit_p(snd_ice1712_remove), |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 5b4293f5a652..0b5389ee26d5 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
| @@ -2332,7 +2332,6 @@ static void __devexit snd_vt1724_remove(struct pci_dev *pci) | |||
| 2332 | 2332 | ||
| 2333 | static struct pci_driver driver = { | 2333 | static struct pci_driver driver = { |
| 2334 | .name = "ICE1724", | 2334 | .name = "ICE1724", |
| 2335 | .owner = THIS_MODULE, | ||
| 2336 | .id_table = snd_vt1724_ids, | 2335 | .id_table = snd_vt1724_ids, |
| 2337 | .probe = snd_vt1724_probe, | 2336 | .probe = snd_vt1724_probe, |
| 2338 | .remove = __devexit_p(snd_vt1724_remove), | 2337 | .remove = __devexit_p(snd_vt1724_remove), |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 0801083f32dd..cf7801d2dd10 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
| @@ -2876,7 +2876,6 @@ static void __devexit snd_intel8x0_remove(struct pci_dev *pci) | |||
| 2876 | 2876 | ||
| 2877 | static struct pci_driver driver = { | 2877 | static struct pci_driver driver = { |
| 2878 | .name = "Intel ICH", | 2878 | .name = "Intel ICH", |
| 2879 | .owner = THIS_MODULE, | ||
| 2880 | .id_table = snd_intel8x0_ids, | 2879 | .id_table = snd_intel8x0_ids, |
| 2881 | .probe = snd_intel8x0_probe, | 2880 | .probe = snd_intel8x0_probe, |
| 2882 | .remove = __devexit_p(snd_intel8x0_remove), | 2881 | .remove = __devexit_p(snd_intel8x0_remove), |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index acfb197a833c..a42091860da7 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
| @@ -1317,7 +1317,6 @@ static void __devexit snd_intel8x0m_remove(struct pci_dev *pci) | |||
| 1317 | 1317 | ||
| 1318 | static struct pci_driver driver = { | 1318 | static struct pci_driver driver = { |
| 1319 | .name = "Intel ICH Modem", | 1319 | .name = "Intel ICH Modem", |
| 1320 | .owner = THIS_MODULE, | ||
| 1321 | .id_table = snd_intel8x0m_ids, | 1320 | .id_table = snd_intel8x0m_ids, |
| 1322 | .probe = snd_intel8x0m_probe, | 1321 | .probe = snd_intel8x0m_probe, |
| 1323 | .remove = __devexit_p(snd_intel8x0m_remove), | 1322 | .remove = __devexit_p(snd_intel8x0m_remove), |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 5561fd4091e8..a110d664f626 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
| @@ -2534,7 +2534,6 @@ static void __devexit snd_korg1212_remove(struct pci_dev *pci) | |||
| 2534 | 2534 | ||
| 2535 | static struct pci_driver driver = { | 2535 | static struct pci_driver driver = { |
| 2536 | .name = "korg1212", | 2536 | .name = "korg1212", |
| 2537 | .owner = THIS_MODULE, | ||
| 2538 | .id_table = snd_korg1212_ids, | 2537 | .id_table = snd_korg1212_ids, |
| 2539 | .probe = snd_korg1212_probe, | 2538 | .probe = snd_korg1212_probe, |
| 2540 | .remove = __devexit_p(snd_korg1212_remove), | 2539 | .remove = __devexit_p(snd_korg1212_remove), |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 99eb76c56f81..ede7a75bfe08 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
| @@ -2858,7 +2858,6 @@ static void __devexit snd_m3_remove(struct pci_dev *pci) | |||
| 2858 | 2858 | ||
| 2859 | static struct pci_driver driver = { | 2859 | static struct pci_driver driver = { |
| 2860 | .name = "Maestro3", | 2860 | .name = "Maestro3", |
| 2861 | .owner = THIS_MODULE, | ||
| 2862 | .id_table = snd_m3_ids, | 2861 | .id_table = snd_m3_ids, |
| 2863 | .probe = snd_m3_probe, | 2862 | .probe = snd_m3_probe, |
| 2864 | .remove = __devexit_p(snd_m3_remove), | 2863 | .remove = __devexit_p(snd_m3_remove), |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index c341c99ec783..b3090a13edab 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
| @@ -1423,7 +1423,6 @@ static void __devexit snd_mixart_remove(struct pci_dev *pci) | |||
| 1423 | 1423 | ||
| 1424 | static struct pci_driver driver = { | 1424 | static struct pci_driver driver = { |
| 1425 | .name = "Digigram miXart", | 1425 | .name = "Digigram miXart", |
| 1426 | .owner = THIS_MODULE, | ||
| 1427 | .id_table = snd_mixart_ids, | 1426 | .id_table = snd_mixart_ids, |
| 1428 | .probe = snd_mixart_probe, | 1427 | .probe = snd_mixart_probe, |
| 1429 | .remove = __devexit_p(snd_mixart_remove), | 1428 | .remove = __devexit_p(snd_mixart_remove), |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index e7aa15178453..089d23b4a002 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
| @@ -1673,7 +1673,6 @@ static void __devexit snd_nm256_remove(struct pci_dev *pci) | |||
| 1673 | 1673 | ||
| 1674 | static struct pci_driver driver = { | 1674 | static struct pci_driver driver = { |
| 1675 | .name = "NeoMagic 256", | 1675 | .name = "NeoMagic 256", |
| 1676 | .owner = THIS_MODULE, | ||
| 1677 | .id_table = snd_nm256_ids, | 1676 | .id_table = snd_nm256_ids, |
| 1678 | .probe = snd_nm256_probe, | 1677 | .probe = snd_nm256_probe, |
| 1679 | .remove = __devexit_p(snd_nm256_remove), | 1678 | .remove = __devexit_p(snd_nm256_remove), |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index e6627b0e38e4..783df7625c1c 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
| @@ -2012,7 +2012,6 @@ static void __devexit snd_rme32_remove(struct pci_dev *pci) | |||
| 2012 | 2012 | ||
| 2013 | static struct pci_driver driver = { | 2013 | static struct pci_driver driver = { |
| 2014 | .name = "RME Digi32", | 2014 | .name = "RME Digi32", |
| 2015 | .owner = THIS_MODULE, | ||
| 2016 | .id_table = snd_rme32_ids, | 2015 | .id_table = snd_rme32_ids, |
| 2017 | .probe = snd_rme32_probe, | 2016 | .probe = snd_rme32_probe, |
| 2018 | .remove = __devexit_p(snd_rme32_remove), | 2017 | .remove = __devexit_p(snd_rme32_remove), |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 0eddeb16a10f..6d422ef64999 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
| @@ -2413,7 +2413,6 @@ static void __devexit snd_rme96_remove(struct pci_dev *pci) | |||
| 2413 | 2413 | ||
| 2414 | static struct pci_driver driver = { | 2414 | static struct pci_driver driver = { |
| 2415 | .name = "RME Digi96", | 2415 | .name = "RME Digi96", |
| 2416 | .owner = THIS_MODULE, | ||
| 2417 | .id_table = snd_rme96_ids, | 2416 | .id_table = snd_rme96_ids, |
| 2418 | .probe = snd_rme96_probe, | 2417 | .probe = snd_rme96_probe, |
| 2419 | .remove = __devexit_p(snd_rme96_remove), | 2418 | .remove = __devexit_p(snd_rme96_remove), |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 845158b01b02..d15ffb3e9b0a 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
| @@ -5062,7 +5062,6 @@ static void __devexit snd_hdsp_remove(struct pci_dev *pci) | |||
| 5062 | 5062 | ||
| 5063 | static struct pci_driver driver = { | 5063 | static struct pci_driver driver = { |
| 5064 | .name = "RME Hammerfall DSP", | 5064 | .name = "RME Hammerfall DSP", |
| 5065 | .owner = THIS_MODULE, | ||
| 5066 | .id_table = snd_hdsp_ids, | 5065 | .id_table = snd_hdsp_ids, |
| 5067 | .probe = snd_hdsp_probe, | 5066 | .probe = snd_hdsp_probe, |
| 5068 | .remove = __devexit_p(snd_hdsp_remove), | 5067 | .remove = __devexit_p(snd_hdsp_remove), |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 60a1141f1327..a1aef6f6767e 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
| @@ -3639,7 +3639,6 @@ static void __devexit snd_hdspm_remove(struct pci_dev *pci) | |||
| 3639 | 3639 | ||
| 3640 | static struct pci_driver driver = { | 3640 | static struct pci_driver driver = { |
| 3641 | .name = "RME Hammerfall DSP MADI", | 3641 | .name = "RME Hammerfall DSP MADI", |
| 3642 | .owner = THIS_MODULE, | ||
| 3643 | .id_table = snd_hdspm_ids, | 3642 | .id_table = snd_hdspm_ids, |
| 3644 | .probe = snd_hdspm_probe, | 3643 | .probe = snd_hdspm_probe, |
| 3645 | .remove = __devexit_p(snd_hdspm_remove), | 3644 | .remove = __devexit_p(snd_hdspm_remove), |
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 59fcef9b6b81..f9d0c126c213 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
| @@ -2654,7 +2654,6 @@ static void __devexit snd_rme9652_remove(struct pci_dev *pci) | |||
| 2654 | 2654 | ||
| 2655 | static struct pci_driver driver = { | 2655 | static struct pci_driver driver = { |
| 2656 | .name = "RME Digi9652 (Hammerfall)", | 2656 | .name = "RME Digi9652 (Hammerfall)", |
| 2657 | .owner = THIS_MODULE, | ||
| 2658 | .id_table = snd_rme9652_ids, | 2657 | .id_table = snd_rme9652_ids, |
| 2659 | .probe = snd_rme9652_probe, | 2658 | .probe = snd_rme9652_probe, |
| 2660 | .remove = __devexit_p(snd_rme9652_remove), | 2659 | .remove = __devexit_p(snd_rme9652_remove), |
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 9a35474aad05..e92ef3ae2ca1 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
| @@ -1502,7 +1502,6 @@ static void __devexit snd_sonic_remove(struct pci_dev *pci) | |||
| 1502 | 1502 | ||
| 1503 | static struct pci_driver driver = { | 1503 | static struct pci_driver driver = { |
| 1504 | .name = "S3 SonicVibes", | 1504 | .name = "S3 SonicVibes", |
| 1505 | .owner = THIS_MODULE, | ||
| 1506 | .id_table = snd_sonic_ids, | 1505 | .id_table = snd_sonic_ids, |
| 1507 | .probe = snd_sonic_probe, | 1506 | .probe = snd_sonic_probe, |
| 1508 | .remove = __devexit_p(snd_sonic_remove), | 1507 | .remove = __devexit_p(snd_sonic_remove), |
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index a8ca8e17853f..940d531575c0 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
| @@ -177,7 +177,6 @@ static void __devexit snd_trident_remove(struct pci_dev *pci) | |||
| 177 | 177 | ||
| 178 | static struct pci_driver driver = { | 178 | static struct pci_driver driver = { |
| 179 | .name = "Trident4DWaveAudio", | 179 | .name = "Trident4DWaveAudio", |
| 180 | .owner = THIS_MODULE, | ||
| 181 | .id_table = snd_trident_ids, | 180 | .id_table = snd_trident_ids, |
| 182 | .probe = snd_trident_probe, | 181 | .probe = snd_trident_probe, |
| 183 | .remove = __devexit_p(snd_trident_remove), | 182 | .remove = __devexit_p(snd_trident_remove), |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 523eace250f7..fad2a2413bf6 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
| @@ -2478,7 +2478,6 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci) | |||
| 2478 | 2478 | ||
| 2479 | static struct pci_driver driver = { | 2479 | static struct pci_driver driver = { |
| 2480 | .name = "VIA 82xx Audio", | 2480 | .name = "VIA 82xx Audio", |
| 2481 | .owner = THIS_MODULE, | ||
| 2482 | .id_table = snd_via82xx_ids, | 2481 | .id_table = snd_via82xx_ids, |
| 2483 | .probe = snd_via82xx_probe, | 2482 | .probe = snd_via82xx_probe, |
| 2484 | .remove = __devexit_p(snd_via82xx_remove), | 2483 | .remove = __devexit_p(snd_via82xx_remove), |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 011f0fb63bf9..b83660bd05b0 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
| @@ -1198,7 +1198,6 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci) | |||
| 1198 | 1198 | ||
| 1199 | static struct pci_driver driver = { | 1199 | static struct pci_driver driver = { |
| 1200 | .name = "VIA 82xx Modem", | 1200 | .name = "VIA 82xx Modem", |
| 1201 | .owner = THIS_MODULE, | ||
| 1202 | .id_table = snd_via82xx_modem_ids, | 1201 | .id_table = snd_via82xx_modem_ids, |
| 1203 | .probe = snd_via82xx_probe, | 1202 | .probe = snd_via82xx_probe, |
| 1204 | .remove = __devexit_p(snd_via82xx_remove), | 1203 | .remove = __devexit_p(snd_via82xx_remove), |
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index 2a7ad9dec021..dca6bd2c7580 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c | |||
| @@ -252,7 +252,6 @@ static void __devexit snd_vx222_remove(struct pci_dev *pci) | |||
| 252 | 252 | ||
| 253 | static struct pci_driver driver = { | 253 | static struct pci_driver driver = { |
| 254 | .name = "Digigram VX222", | 254 | .name = "Digigram VX222", |
| 255 | .owner = THIS_MODULE, | ||
| 256 | .id_table = snd_vx222_ids, | 255 | .id_table = snd_vx222_ids, |
| 257 | .probe = snd_vx222_probe, | 256 | .probe = snd_vx222_probe, |
| 258 | .remove = __devexit_p(snd_vx222_remove), | 257 | .remove = __devexit_p(snd_vx222_remove), |
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 1bbba32517ff..d013237205d8 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
| @@ -344,7 +344,6 @@ static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci) | |||
| 344 | 344 | ||
| 345 | static struct pci_driver driver = { | 345 | static struct pci_driver driver = { |
| 346 | .name = "Yamaha DS-XG PCI", | 346 | .name = "Yamaha DS-XG PCI", |
| 347 | .owner = THIS_MODULE, | ||
| 348 | .id_table = snd_ymfpci_ids, | 347 | .id_table = snd_ymfpci_ids, |
| 349 | .probe = snd_card_ymfpci_probe, | 348 | .probe = snd_card_ymfpci_probe, |
| 350 | .remove = __devexit_p(snd_card_ymfpci_remove), | 349 | .remove = __devexit_p(snd_card_ymfpci_remove), |
