Commit c827ba4cb49a30ce581201fd0ba2be77cde412c7
Exists in
master
and in
7 other branches
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: [SPARC64]: Update defconfig. [SPARC64]: Add PCI MSI support on Niagara. [SPARC64] IRQ: Use irq_desc->chip_data instead of irq_desc->handler_data [SPARC64]: Add obppath sysfs attribute for SBUS and PCI devices. [PARTITION]: Add whole_disk attribute.
Showing 17 changed files Side-by-side Diff
- arch/sparc64/defconfig
- arch/sparc64/kernel/irq.c
- arch/sparc64/kernel/pci.c
- arch/sparc64/kernel/pci_common.c
- arch/sparc64/kernel/pci_sun4v.c
- arch/sparc64/kernel/pci_sun4v.h
- arch/sparc64/kernel/pci_sun4v_asm.S
- block/ioctl.c
- drivers/pci/Kconfig
- drivers/sbus/sbus.c
- fs/partitions/check.c
- fs/partitions/msdos.c
- fs/partitions/sgi.c
- fs/partitions/sun.c
- include/asm-sparc64/irq.h
- include/asm-sparc64/pbm.h
- include/linux/genhd.h
arch/sparc64/defconfig
1 | 1 | # |
2 | 2 | # Automatically generated make config: don't edit |
3 | -# Linux kernel version: 2.6.20-rc2 | |
4 | -# Thu Dec 28 15:09:49 2006 | |
3 | +# Linux kernel version: 2.6.20 | |
4 | +# Sat Feb 10 23:08:12 2007 | |
5 | 5 | # |
6 | 6 | CONFIG_SPARC=y |
7 | 7 | CONFIG_SPARC64=y |
... | ... | @@ -151,7 +151,7 @@ |
151 | 151 | CONFIG_SUN_IO=y |
152 | 152 | CONFIG_PCI=y |
153 | 153 | CONFIG_PCI_DOMAINS=y |
154 | -# CONFIG_PCI_MULTITHREAD_PROBE is not set | |
154 | +CONFIG_PCI_MSI=y | |
155 | 155 | # CONFIG_PCI_DEBUG is not set |
156 | 156 | CONFIG_SUN_OPENPROMFS=m |
157 | 157 | CONFIG_SPARC32_COMPAT=y |
158 | 158 | |
... | ... | @@ -182,7 +182,9 @@ |
182 | 182 | CONFIG_XFRM=y |
183 | 183 | CONFIG_XFRM_USER=m |
184 | 184 | # CONFIG_XFRM_SUB_POLICY is not set |
185 | +CONFIG_XFRM_MIGRATE=y | |
185 | 186 | CONFIG_NET_KEY=m |
187 | +CONFIG_NET_KEY_MIGRATE=y | |
186 | 188 | CONFIG_INET=y |
187 | 189 | CONFIG_IP_MULTICAST=y |
188 | 190 | # CONFIG_IP_ADVANCED_ROUTER is not set |
... | ... | @@ -300,6 +302,7 @@ |
300 | 302 | # CONFIG_PREVENT_FIRMWARE_BUILD is not set |
301 | 303 | CONFIG_FW_LOADER=y |
302 | 304 | # CONFIG_DEBUG_DRIVER is not set |
305 | +# CONFIG_DEBUG_DEVRES is not set | |
303 | 306 | # CONFIG_SYS_HYPERVISOR is not set |
304 | 307 | |
305 | 308 | # |
... | ... | @@ -393,6 +396,7 @@ |
393 | 396 | # CONFIG_BLK_DEV_JMICRON is not set |
394 | 397 | # CONFIG_BLK_DEV_SC1200 is not set |
395 | 398 | # CONFIG_BLK_DEV_PIIX is not set |
399 | +# CONFIG_BLK_DEV_IT8213 is not set | |
396 | 400 | # CONFIG_BLK_DEV_IT821X is not set |
397 | 401 | # CONFIG_BLK_DEV_NS87415 is not set |
398 | 402 | # CONFIG_BLK_DEV_PDC202XX_OLD is not set |
... | ... | @@ -402,6 +406,7 @@ |
402 | 406 | # CONFIG_BLK_DEV_SLC90E66 is not set |
403 | 407 | # CONFIG_BLK_DEV_TRM290 is not set |
404 | 408 | # CONFIG_BLK_DEV_VIA82CXXX is not set |
409 | +# CONFIG_BLK_DEV_TC86C001 is not set | |
405 | 410 | # CONFIG_IDE_ARM is not set |
406 | 411 | CONFIG_BLK_DEV_IDEDMA=y |
407 | 412 | # CONFIG_IDEDMA_IVB is not set |
... | ... | @@ -579,6 +584,7 @@ |
579 | 584 | # CONFIG_EPIC100 is not set |
580 | 585 | # CONFIG_SUNDANCE is not set |
581 | 586 | # CONFIG_VIA_RHINE is not set |
587 | +# CONFIG_SC92031 is not set | |
582 | 588 | |
583 | 589 | # |
584 | 590 | # Ethernet (1000 Mbit) |
585 | 591 | |
... | ... | @@ -601,11 +607,13 @@ |
601 | 607 | CONFIG_TIGON3=m |
602 | 608 | CONFIG_BNX2=m |
603 | 609 | # CONFIG_QLA3XXX is not set |
610 | +# CONFIG_ATL1 is not set | |
604 | 611 | |
605 | 612 | # |
606 | 613 | # Ethernet (10000 Mbit) |
607 | 614 | # |
608 | 615 | # CONFIG_CHELSIO_T1 is not set |
616 | +# CONFIG_CHELSIO_T3 is not set | |
609 | 617 | # CONFIG_IXGB is not set |
610 | 618 | # CONFIG_S2IO is not set |
611 | 619 | # CONFIG_MYRI10GE is not set |
612 | 620 | |
... | ... | @@ -627,8 +635,17 @@ |
627 | 635 | # CONFIG_WAN is not set |
628 | 636 | # CONFIG_FDDI is not set |
629 | 637 | # CONFIG_HIPPI is not set |
630 | -# CONFIG_PPP is not set | |
638 | +CONFIG_PPP=m | |
639 | +CONFIG_PPP_MULTILINK=y | |
640 | +CONFIG_PPP_FILTER=y | |
641 | +CONFIG_PPP_ASYNC=m | |
642 | +CONFIG_PPP_SYNC_TTY=m | |
643 | +CONFIG_PPP_DEFLATE=m | |
644 | +CONFIG_PPP_BSDCOMP=m | |
645 | +CONFIG_PPP_MPPE=m | |
646 | +CONFIG_PPPOE=m | |
631 | 647 | # CONFIG_SLIP is not set |
648 | +CONFIG_SLHC=m | |
632 | 649 | # CONFIG_NET_FC is not set |
633 | 650 | # CONFIG_SHAPER is not set |
634 | 651 | # CONFIG_NETCONSOLE is not set |
... | ... | @@ -1043,6 +1060,11 @@ |
1043 | 1060 | # CONFIG_SND_SUN_DBRI is not set |
1044 | 1061 | |
1045 | 1062 | # |
1063 | +# SoC audio support | |
1064 | +# | |
1065 | +# CONFIG_SND_SOC is not set | |
1066 | + | |
1067 | +# | |
1046 | 1068 | # Open Sound System |
1047 | 1069 | # |
1048 | 1070 | # CONFIG_SOUND_PRIME is not set |
... | ... | @@ -1052,6 +1074,7 @@ |
1052 | 1074 | # HID Devices |
1053 | 1075 | # |
1054 | 1076 | CONFIG_HID=y |
1077 | +# CONFIG_HID_DEBUG is not set | |
1055 | 1078 | |
1056 | 1079 | # |
1057 | 1080 | # USB support |
1058 | 1081 | |
... | ... | @@ -1066,9 +1089,7 @@ |
1066 | 1089 | # Miscellaneous USB options |
1067 | 1090 | # |
1068 | 1091 | CONFIG_USB_DEVICEFS=y |
1069 | -# CONFIG_USB_BANDWIDTH is not set | |
1070 | 1092 | # CONFIG_USB_DYNAMIC_MINORS is not set |
1071 | -# CONFIG_USB_MULTITHREAD_PROBE is not set | |
1072 | 1093 | # CONFIG_USB_OTG is not set |
1073 | 1094 | |
1074 | 1095 | # |
1075 | 1096 | |
... | ... | @@ -1078,9 +1099,11 @@ |
1078 | 1099 | # CONFIG_USB_EHCI_SPLIT_ISO is not set |
1079 | 1100 | # CONFIG_USB_EHCI_ROOT_HUB_TT is not set |
1080 | 1101 | # CONFIG_USB_EHCI_TT_NEWSCHED is not set |
1102 | +# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set | |
1081 | 1103 | # CONFIG_USB_ISP116X_HCD is not set |
1082 | 1104 | CONFIG_USB_OHCI_HCD=y |
1083 | -# CONFIG_USB_OHCI_BIG_ENDIAN is not set | |
1105 | +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set | |
1106 | +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set | |
1084 | 1107 | CONFIG_USB_OHCI_LITTLE_ENDIAN=y |
1085 | 1108 | CONFIG_USB_UHCI_HCD=m |
1086 | 1109 | # CONFIG_USB_SL811_HCD is not set |
... | ... | @@ -1132,6 +1155,7 @@ |
1132 | 1155 | # CONFIG_USB_ATI_REMOTE2 is not set |
1133 | 1156 | # CONFIG_USB_KEYSPAN_REMOTE is not set |
1134 | 1157 | # CONFIG_USB_APPLETOUCH is not set |
1158 | +# CONFIG_USB_GTCO is not set | |
1135 | 1159 | |
1136 | 1160 | # |
1137 | 1161 | # USB Imaging devices |
1138 | 1162 | |
... | ... | @@ -1473,8 +1497,10 @@ |
1473 | 1497 | CONFIG_CRYPTO_GF128MUL=m |
1474 | 1498 | CONFIG_CRYPTO_ECB=m |
1475 | 1499 | CONFIG_CRYPTO_CBC=y |
1500 | +CONFIG_CRYPTO_PCBC=m | |
1476 | 1501 | CONFIG_CRYPTO_LRW=m |
1477 | 1502 | CONFIG_CRYPTO_DES=y |
1503 | +CONFIG_CRYPTO_FCRYPT=m | |
1478 | 1504 | CONFIG_CRYPTO_BLOWFISH=m |
1479 | 1505 | CONFIG_CRYPTO_TWOFISH=m |
1480 | 1506 | CONFIG_CRYPTO_TWOFISH_COMMON=m |
... | ... | @@ -1489,6 +1515,7 @@ |
1489 | 1515 | CONFIG_CRYPTO_DEFLATE=y |
1490 | 1516 | CONFIG_CRYPTO_MICHAEL_MIC=m |
1491 | 1517 | CONFIG_CRYPTO_CRC32C=m |
1518 | +CONFIG_CRYPTO_CAMELLIA=m | |
1492 | 1519 | CONFIG_CRYPTO_TEST=m |
1493 | 1520 | |
1494 | 1521 | # |
arch/sparc64/kernel/irq.c
... | ... | @@ -22,6 +22,7 @@ |
22 | 22 | #include <linux/seq_file.h> |
23 | 23 | #include <linux/bootmem.h> |
24 | 24 | #include <linux/irq.h> |
25 | +#include <linux/msi.h> | |
25 | 26 | |
26 | 27 | #include <asm/ptrace.h> |
27 | 28 | #include <asm/processor.h> |
... | ... | @@ -87,7 +88,6 @@ |
87 | 88 | #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) |
88 | 89 | |
89 | 90 | static unsigned int virt_to_real_irq_table[NR_IRQS]; |
90 | -static unsigned char virt_irq_cur = 1; | |
91 | 91 | |
92 | 92 | static unsigned char virt_irq_alloc(unsigned int real_irq) |
93 | 93 | { |
94 | 94 | |
95 | 95 | |
96 | 96 | |
97 | 97 | |
98 | 98 | |
... | ... | @@ -95,26 +95,32 @@ |
95 | 95 | |
96 | 96 | BUILD_BUG_ON(NR_IRQS >= 256); |
97 | 97 | |
98 | - ent = virt_irq_cur; | |
98 | + for (ent = 1; ent < NR_IRQS; ent++) { | |
99 | + if (!virt_to_real_irq_table[ent]) | |
100 | + break; | |
101 | + } | |
99 | 102 | if (ent >= NR_IRQS) { |
100 | 103 | printk(KERN_ERR "IRQ: Out of virtual IRQs.\n"); |
101 | 104 | return 0; |
102 | 105 | } |
103 | 106 | |
104 | - virt_irq_cur = ent + 1; | |
105 | 107 | virt_to_real_irq_table[ent] = real_irq; |
106 | 108 | |
107 | 109 | return ent; |
108 | 110 | } |
109 | 111 | |
110 | -#if 0 /* Currently unused. */ | |
111 | -static unsigned char real_to_virt_irq(unsigned int real_irq) | |
112 | +static void virt_irq_free(unsigned int virt_irq) | |
112 | 113 | { |
113 | - struct ino_bucket *bucket = __bucket(real_irq); | |
114 | + unsigned int real_irq; | |
114 | 115 | |
115 | - return bucket->virt_irq; | |
116 | + if (virt_irq >= NR_IRQS) | |
117 | + return; | |
118 | + | |
119 | + real_irq = virt_to_real_irq_table[virt_irq]; | |
120 | + virt_to_real_irq_table[virt_irq] = 0; | |
121 | + | |
122 | + __bucket(real_irq)->virt_irq = 0; | |
116 | 123 | } |
117 | -#endif | |
118 | 124 | |
119 | 125 | static unsigned int virt_to_real_irq(unsigned char virt_irq) |
120 | 126 | { |
... | ... | @@ -268,8 +274,7 @@ |
268 | 274 | |
269 | 275 | static void sun4u_irq_enable(unsigned int virt_irq) |
270 | 276 | { |
271 | - irq_desc_t *desc = irq_desc + virt_irq; | |
272 | - struct irq_handler_data *data = desc->handler_data; | |
277 | + struct irq_handler_data *data = get_irq_chip_data(virt_irq); | |
273 | 278 | |
274 | 279 | if (likely(data)) { |
275 | 280 | unsigned long cpuid, imap; |
... | ... | @@ -286,8 +291,7 @@ |
286 | 291 | |
287 | 292 | static void sun4u_irq_disable(unsigned int virt_irq) |
288 | 293 | { |
289 | - irq_desc_t *desc = irq_desc + virt_irq; | |
290 | - struct irq_handler_data *data = desc->handler_data; | |
294 | + struct irq_handler_data *data = get_irq_chip_data(virt_irq); | |
291 | 295 | |
292 | 296 | if (likely(data)) { |
293 | 297 | unsigned long imap = data->imap; |
... | ... | @@ -300,8 +304,7 @@ |
300 | 304 | |
301 | 305 | static void sun4u_irq_end(unsigned int virt_irq) |
302 | 306 | { |
303 | - irq_desc_t *desc = irq_desc + virt_irq; | |
304 | - struct irq_handler_data *data = desc->handler_data; | |
307 | + struct irq_handler_data *data = get_irq_chip_data(virt_irq); | |
305 | 308 | |
306 | 309 | if (likely(data)) |
307 | 310 | upa_writel(ICLR_IDLE, data->iclr); |
... | ... | @@ -344,6 +347,20 @@ |
344 | 347 | } |
345 | 348 | } |
346 | 349 | |
350 | +#ifdef CONFIG_PCI_MSI | |
351 | +static void sun4v_msi_enable(unsigned int virt_irq) | |
352 | +{ | |
353 | + sun4v_irq_enable(virt_irq); | |
354 | + unmask_msi_irq(virt_irq); | |
355 | +} | |
356 | + | |
357 | +static void sun4v_msi_disable(unsigned int virt_irq) | |
358 | +{ | |
359 | + mask_msi_irq(virt_irq); | |
360 | + sun4v_irq_disable(virt_irq); | |
361 | +} | |
362 | +#endif | |
363 | + | |
347 | 364 | static void sun4v_irq_end(unsigned int virt_irq) |
348 | 365 | { |
349 | 366 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
... | ... | @@ -362,8 +379,7 @@ |
362 | 379 | static void run_pre_handler(unsigned int virt_irq) |
363 | 380 | { |
364 | 381 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
365 | - irq_desc_t *desc = irq_desc + virt_irq; | |
366 | - struct irq_handler_data *data = desc->handler_data; | |
382 | + struct irq_handler_data *data = get_irq_chip_data(virt_irq); | |
367 | 383 | |
368 | 384 | if (likely(data->pre_handler)) { |
369 | 385 | data->pre_handler(__irq_ino(__irq(bucket)), |
370 | 386 | |
371 | 387 | |
372 | 388 | |
373 | 389 | |
... | ... | @@ -402,30 +418,47 @@ |
402 | 418 | .end = sun4v_irq_end, |
403 | 419 | }; |
404 | 420 | |
421 | +#ifdef CONFIG_PCI_MSI | |
422 | +static struct irq_chip sun4v_msi = { | |
423 | + .typename = "sun4v+msi", | |
424 | + .mask = mask_msi_irq, | |
425 | + .unmask = unmask_msi_irq, | |
426 | + .enable = sun4v_msi_enable, | |
427 | + .disable = sun4v_msi_disable, | |
428 | + .ack = run_pre_handler, | |
429 | + .end = sun4v_irq_end, | |
430 | +}; | |
431 | +#endif | |
432 | + | |
405 | 433 | void irq_install_pre_handler(int virt_irq, |
406 | 434 | void (*func)(unsigned int, void *, void *), |
407 | 435 | void *arg1, void *arg2) |
408 | 436 | { |
409 | - irq_desc_t *desc = irq_desc + virt_irq; | |
410 | - struct irq_handler_data *data = desc->handler_data; | |
437 | + struct irq_handler_data *data = get_irq_chip_data(virt_irq); | |
438 | + struct irq_chip *chip; | |
411 | 439 | |
412 | 440 | data->pre_handler = func; |
413 | 441 | data->pre_handler_arg1 = arg1; |
414 | 442 | data->pre_handler_arg2 = arg2; |
415 | 443 | |
416 | - if (desc->chip == &sun4u_irq_ack || | |
417 | - desc->chip == &sun4v_irq_ack) | |
444 | + chip = get_irq_chip(virt_irq); | |
445 | + if (chip == &sun4u_irq_ack || | |
446 | + chip == &sun4v_irq_ack | |
447 | +#ifdef CONFIG_PCI_MSI | |
448 | + || chip == &sun4v_msi | |
449 | +#endif | |
450 | + ) | |
418 | 451 | return; |
419 | 452 | |
420 | - desc->chip = (desc->chip == &sun4u_irq ? | |
421 | - &sun4u_irq_ack : &sun4v_irq_ack); | |
453 | + chip = (chip == &sun4u_irq ? | |
454 | + &sun4u_irq_ack : &sun4v_irq_ack); | |
455 | + set_irq_chip(virt_irq, chip); | |
422 | 456 | } |
423 | 457 | |
424 | 458 | unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) |
425 | 459 | { |
426 | 460 | struct ino_bucket *bucket; |
427 | 461 | struct irq_handler_data *data; |
428 | - irq_desc_t *desc; | |
429 | 462 | int ino; |
430 | 463 | |
431 | 464 | BUG_ON(tlb_type == hypervisor); |
432 | 465 | |
... | ... | @@ -434,11 +467,11 @@ |
434 | 467 | bucket = &ivector_table[ino]; |
435 | 468 | if (!bucket->virt_irq) { |
436 | 469 | bucket->virt_irq = virt_irq_alloc(__irq(bucket)); |
437 | - irq_desc[bucket->virt_irq].chip = &sun4u_irq; | |
470 | + set_irq_chip(bucket->virt_irq, &sun4u_irq); | |
438 | 471 | } |
439 | 472 | |
440 | - desc = irq_desc + bucket->virt_irq; | |
441 | - if (unlikely(desc->handler_data)) | |
473 | + data = get_irq_chip_data(bucket->virt_irq); | |
474 | + if (unlikely(data)) | |
442 | 475 | goto out; |
443 | 476 | |
444 | 477 | data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); |
... | ... | @@ -446,7 +479,7 @@ |
446 | 479 | prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); |
447 | 480 | prom_halt(); |
448 | 481 | } |
449 | - desc->handler_data = data; | |
482 | + set_irq_chip_data(bucket->virt_irq, data); | |
450 | 483 | |
451 | 484 | data->imap = imap; |
452 | 485 | data->iclr = iclr; |
... | ... | @@ -460,7 +493,6 @@ |
460 | 493 | struct ino_bucket *bucket; |
461 | 494 | struct irq_handler_data *data; |
462 | 495 | unsigned long sysino; |
463 | - irq_desc_t *desc; | |
464 | 496 | |
465 | 497 | BUG_ON(tlb_type != hypervisor); |
466 | 498 | |
467 | 499 | |
... | ... | @@ -468,11 +500,11 @@ |
468 | 500 | bucket = &ivector_table[sysino]; |
469 | 501 | if (!bucket->virt_irq) { |
470 | 502 | bucket->virt_irq = virt_irq_alloc(__irq(bucket)); |
471 | - irq_desc[bucket->virt_irq].chip = &sun4v_irq; | |
503 | + set_irq_chip(bucket->virt_irq, &sun4v_irq); | |
472 | 504 | } |
473 | 505 | |
474 | - desc = irq_desc + bucket->virt_irq; | |
475 | - if (unlikely(desc->handler_data)) | |
506 | + data = get_irq_chip_data(bucket->virt_irq); | |
507 | + if (unlikely(data)) | |
476 | 508 | goto out; |
477 | 509 | |
478 | 510 | data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); |
... | ... | @@ -480,7 +512,7 @@ |
480 | 512 | prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); |
481 | 513 | prom_halt(); |
482 | 514 | } |
483 | - desc->handler_data = data; | |
515 | + set_irq_chip_data(bucket->virt_irq, data); | |
484 | 516 | |
485 | 517 | /* Catch accidental accesses to these things. IMAP/ICLR handling |
486 | 518 | * is done by hypervisor calls on sun4v platforms, not by direct |
... | ... | @@ -492,6 +524,56 @@ |
492 | 524 | out: |
493 | 525 | return bucket->virt_irq; |
494 | 526 | } |
527 | + | |
528 | +#ifdef CONFIG_PCI_MSI | |
529 | +unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p, | |
530 | + unsigned int msi_start, unsigned int msi_end) | |
531 | +{ | |
532 | + struct ino_bucket *bucket; | |
533 | + struct irq_handler_data *data; | |
534 | + unsigned long sysino; | |
535 | + unsigned int devino; | |
536 | + | |
537 | + BUG_ON(tlb_type != hypervisor); | |
538 | + | |
539 | + /* Find a free devino in the given range. */ | |
540 | + for (devino = msi_start; devino < msi_end; devino++) { | |
541 | + sysino = sun4v_devino_to_sysino(devhandle, devino); | |
542 | + bucket = &ivector_table[sysino]; | |
543 | + if (!bucket->virt_irq) | |
544 | + break; | |
545 | + } | |
546 | + if (devino >= msi_end) | |
547 | + return 0; | |
548 | + | |
549 | + sysino = sun4v_devino_to_sysino(devhandle, devino); | |
550 | + bucket = &ivector_table[sysino]; | |
551 | + bucket->virt_irq = virt_irq_alloc(__irq(bucket)); | |
552 | + *virt_irq_p = bucket->virt_irq; | |
553 | + set_irq_chip(bucket->virt_irq, &sun4v_msi); | |
554 | + | |
555 | + data = get_irq_chip_data(bucket->virt_irq); | |
556 | + if (unlikely(data)) | |
557 | + return devino; | |
558 | + | |
559 | + data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); | |
560 | + if (unlikely(!data)) { | |
561 | + prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); | |
562 | + prom_halt(); | |
563 | + } | |
564 | + set_irq_chip_data(bucket->virt_irq, data); | |
565 | + | |
566 | + data->imap = ~0UL; | |
567 | + data->iclr = ~0UL; | |
568 | + | |
569 | + return devino; | |
570 | +} | |
571 | + | |
572 | +void sun4v_destroy_msi(unsigned int virt_irq) | |
573 | +{ | |
574 | + virt_irq_free(virt_irq); | |
575 | +} | |
576 | +#endif | |
495 | 577 | |
496 | 578 | void ack_bad_irq(unsigned int virt_irq) |
497 | 579 | { |
arch/sparc64/kernel/pci.c
... | ... | @@ -13,6 +13,8 @@ |
13 | 13 | #include <linux/capability.h> |
14 | 14 | #include <linux/errno.h> |
15 | 15 | #include <linux/smp_lock.h> |
16 | +#include <linux/msi.h> | |
17 | +#include <linux/irq.h> | |
16 | 18 | #include <linux/init.h> |
17 | 19 | |
18 | 20 | #include <asm/uaccess.h> |
... | ... | @@ -645,6 +647,39 @@ |
645 | 647 | return ret; |
646 | 648 | } |
647 | 649 | EXPORT_SYMBOL(pci_domain_nr); |
650 | + | |
651 | +#ifdef CONFIG_PCI_MSI | |
652 | +int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) | |
653 | +{ | |
654 | + struct pcidev_cookie *pcp = pdev->sysdata; | |
655 | + struct pci_pbm_info *pbm = pcp->pbm; | |
656 | + struct pci_controller_info *p = pbm->parent; | |
657 | + int virt_irq, err; | |
658 | + | |
659 | + if (!pbm->msi_num || !p->setup_msi_irq) | |
660 | + return -EINVAL; | |
661 | + | |
662 | + err = p->setup_msi_irq(&virt_irq, pdev, desc); | |
663 | + if (err < 0) | |
664 | + return err; | |
665 | + | |
666 | + return virt_irq; | |
667 | +} | |
668 | + | |
669 | +void arch_teardown_msi_irq(unsigned int virt_irq) | |
670 | +{ | |
671 | + struct msi_desc *entry = get_irq_data(virt_irq); | |
672 | + struct pci_dev *pdev = entry->dev; | |
673 | + struct pcidev_cookie *pcp = pdev->sysdata; | |
674 | + struct pci_pbm_info *pbm = pcp->pbm; | |
675 | + struct pci_controller_info *p = pbm->parent; | |
676 | + | |
677 | + if (!pbm->msi_num || !p->setup_msi_irq) | |
678 | + return; | |
679 | + | |
680 | + return p->teardown_msi_irq(virt_irq, pdev); | |
681 | +} | |
682 | +#endif /* !(CONFIG_PCI_MSI) */ | |
648 | 683 | |
649 | 684 | #endif /* !(CONFIG_PCI) */ |
arch/sparc64/kernel/pci_common.c
... | ... | @@ -7,6 +7,8 @@ |
7 | 7 | #include <linux/string.h> |
8 | 8 | #include <linux/slab.h> |
9 | 9 | #include <linux/init.h> |
10 | +#include <linux/pci.h> | |
11 | +#include <linux/device.h> | |
10 | 12 | |
11 | 13 | #include <asm/pbm.h> |
12 | 14 | #include <asm/prom.h> |
... | ... | @@ -129,6 +131,20 @@ |
129 | 131 | } |
130 | 132 | } |
131 | 133 | |
134 | +static ssize_t | |
135 | +show_pciobppath_attr(struct device * dev, struct device_attribute * attr, char * buf) | |
136 | +{ | |
137 | + struct pci_dev *pdev; | |
138 | + struct pcidev_cookie *sysdata; | |
139 | + | |
140 | + pdev = to_pci_dev(dev); | |
141 | + sysdata = pdev->sysdata; | |
142 | + | |
143 | + return snprintf (buf, PAGE_SIZE, "%s\n", sysdata->prom_node->full_name); | |
144 | +} | |
145 | + | |
146 | +static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL); | |
147 | + | |
132 | 148 | /* Fill in the PCI device cookie sysdata for the given |
133 | 149 | * PCI device. This cookie is the means by which one |
134 | 150 | * can get to OBP and PCI controller specific information |
... | ... | @@ -142,7 +158,7 @@ |
142 | 158 | struct pcidev_cookie *pcp; |
143 | 159 | struct device_node *dp; |
144 | 160 | struct property *prop; |
145 | - int nregs, len; | |
161 | + int nregs, len, err; | |
146 | 162 | |
147 | 163 | dp = find_device_prom_node(pbm, pdev, bus_node, |
148 | 164 | &pregs, &nregs); |
... | ... | @@ -215,6 +231,13 @@ |
215 | 231 | fixup_obp_assignments(pdev, pcp); |
216 | 232 | |
217 | 233 | pdev->sysdata = pcp; |
234 | + | |
235 | + /* we don't really care if we can create this file or not, | |
236 | + * but we need to assign the result of the call or the world will fall | |
237 | + * under alien invasion and everybody will be frozen on a spaceship | |
238 | + * ready to be eaten on alpha centauri by some green and jelly humanoid. | |
239 | + */ | |
240 | + err = sysfs_create_file(&pdev->dev.kobj, &dev_attr_obppath.attr); | |
218 | 241 | } |
219 | 242 | |
220 | 243 | void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus, |
arch/sparc64/kernel/pci_sun4v.c
... | ... | @@ -10,6 +10,8 @@ |
10 | 10 | #include <linux/slab.h> |
11 | 11 | #include <linux/interrupt.h> |
12 | 12 | #include <linux/percpu.h> |
13 | +#include <linux/irq.h> | |
14 | +#include <linux/msi.h> | |
13 | 15 | |
14 | 16 | #include <asm/pbm.h> |
15 | 17 | #include <asm/iommu.h> |
... | ... | @@ -1074,6 +1076,443 @@ |
1074 | 1076 | |
1075 | 1077 | } |
1076 | 1078 | |
1079 | +#ifdef CONFIG_PCI_MSI | |
1080 | +struct pci_sun4v_msiq_entry { | |
1081 | + u64 version_type; | |
1082 | +#define MSIQ_VERSION_MASK 0xffffffff00000000UL | |
1083 | +#define MSIQ_VERSION_SHIFT 32 | |
1084 | +#define MSIQ_TYPE_MASK 0x00000000000000ffUL | |
1085 | +#define MSIQ_TYPE_SHIFT 0 | |
1086 | +#define MSIQ_TYPE_NONE 0x00 | |
1087 | +#define MSIQ_TYPE_MSG 0x01 | |
1088 | +#define MSIQ_TYPE_MSI32 0x02 | |
1089 | +#define MSIQ_TYPE_MSI64 0x03 | |
1090 | +#define MSIQ_TYPE_INTX 0x08 | |
1091 | +#define MSIQ_TYPE_NONE2 0xff | |
1092 | + | |
1093 | + u64 intx_sysino; | |
1094 | + u64 reserved1; | |
1095 | + u64 stick; | |
1096 | + u64 req_id; /* bus/device/func */ | |
1097 | +#define MSIQ_REQID_BUS_MASK 0xff00UL | |
1098 | +#define MSIQ_REQID_BUS_SHIFT 8 | |
1099 | +#define MSIQ_REQID_DEVICE_MASK 0x00f8UL | |
1100 | +#define MSIQ_REQID_DEVICE_SHIFT 3 | |
1101 | +#define MSIQ_REQID_FUNC_MASK 0x0007UL | |
1102 | +#define MSIQ_REQID_FUNC_SHIFT 0 | |
1103 | + | |
1104 | + u64 msi_address; | |
1105 | + | |
1106 | + /* The format of this value is message type dependant. | |
1107 | + * For MSI bits 15:0 are the data from the MSI packet. | |
1108 | + * For MSI-X bits 31:0 are the data from the MSI packet. | |
1109 | + * For MSG, the message code and message routing code where: | |
1110 | + * bits 39:32 is the bus/device/fn of the msg target-id | |
1111 | + * bits 18:16 is the message routing code | |
1112 | + * bits 7:0 is the message code | |
1113 | + * For INTx the low order 2-bits are: | |
1114 | + * 00 - INTA | |
1115 | + * 01 - INTB | |
1116 | + * 10 - INTC | |
1117 | + * 11 - INTD | |
1118 | + */ | |
1119 | + u64 msi_data; | |
1120 | + | |
1121 | + u64 reserved2; | |
1122 | +}; | |
1123 | + | |
1124 | +/* For now this just runs as a pre-handler for the real interrupt handler. | |
1125 | + * So we just walk through the queue and ACK all the entries, update the | |
1126 | + * head pointer, and return. | |
1127 | + * | |
1128 | + * In the longer term it would be nice to do something more integrated | |
1129 | + * wherein we can pass in some of this MSI info to the drivers. This | |
1130 | + * would be most useful for PCIe fabric error messages, although we could | |
1131 | + * invoke those directly from the loop here in order to pass the info around. | |
1132 | + */ | |
1133 | +static void pci_sun4v_msi_prehandler(unsigned int ino, void *data1, void *data2) | |
1134 | +{ | |
1135 | + struct pci_pbm_info *pbm = data1; | |
1136 | + struct pci_sun4v_msiq_entry *base, *ep; | |
1137 | + unsigned long msiqid, orig_head, head, type, err; | |
1138 | + | |
1139 | + msiqid = (unsigned long) data2; | |
1140 | + | |
1141 | + head = 0xdeadbeef; | |
1142 | + err = pci_sun4v_msiq_gethead(pbm->devhandle, msiqid, &head); | |
1143 | + if (unlikely(err)) | |
1144 | + goto hv_error_get; | |
1145 | + | |
1146 | + if (unlikely(head >= (pbm->msiq_ent_count * sizeof(struct pci_sun4v_msiq_entry)))) | |
1147 | + goto bad_offset; | |
1148 | + | |
1149 | + head /= sizeof(struct pci_sun4v_msiq_entry); | |
1150 | + orig_head = head; | |
1151 | + base = (pbm->msi_queues + ((msiqid - pbm->msiq_first) * | |
1152 | + (pbm->msiq_ent_count * | |
1153 | + sizeof(struct pci_sun4v_msiq_entry)))); | |
1154 | + ep = &base[head]; | |
1155 | + while ((ep->version_type & MSIQ_TYPE_MASK) != 0) { | |
1156 | + type = (ep->version_type & MSIQ_TYPE_MASK) >> MSIQ_TYPE_SHIFT; | |
1157 | + if (unlikely(type != MSIQ_TYPE_MSI32 && | |
1158 | + type != MSIQ_TYPE_MSI64)) | |
1159 | + goto bad_type; | |
1160 | + | |
1161 | + pci_sun4v_msi_setstate(pbm->devhandle, | |
1162 | + ep->msi_data /* msi_num */, | |
1163 | + HV_MSISTATE_IDLE); | |
1164 | + | |
1165 | + /* Clear the entry. */ | |
1166 | + ep->version_type &= ~MSIQ_TYPE_MASK; | |
1167 | + | |
1168 | + /* Go to next entry in ring. */ | |
1169 | + head++; | |
1170 | + if (head >= pbm->msiq_ent_count) | |
1171 | + head = 0; | |
1172 | + ep = &base[head]; | |
1173 | + } | |
1174 | + | |
1175 | + if (likely(head != orig_head)) { | |
1176 | + /* ACK entries by updating head pointer. */ | |
1177 | + head *= sizeof(struct pci_sun4v_msiq_entry); | |
1178 | + err = pci_sun4v_msiq_sethead(pbm->devhandle, msiqid, head); | |
1179 | + if (unlikely(err)) | |
1180 | + goto hv_error_set; | |
1181 | + } | |
1182 | + return; | |
1183 | + | |
1184 | +hv_error_set: | |
1185 | + printk(KERN_EMERG "MSI: Hypervisor set head gives error %lu\n", err); | |
1186 | + goto hv_error_cont; | |
1187 | + | |
1188 | +hv_error_get: | |
1189 | + printk(KERN_EMERG "MSI: Hypervisor get head gives error %lu\n", err); | |
1190 | + | |
1191 | +hv_error_cont: | |
1192 | + printk(KERN_EMERG "MSI: devhandle[%x] msiqid[%lx] head[%lu]\n", | |
1193 | + pbm->devhandle, msiqid, head); | |
1194 | + return; | |
1195 | + | |
1196 | +bad_offset: | |
1197 | + printk(KERN_EMERG "MSI: Hypervisor gives bad offset %lx max(%lx)\n", | |
1198 | + head, pbm->msiq_ent_count * sizeof(struct pci_sun4v_msiq_entry)); | |
1199 | + return; | |
1200 | + | |
1201 | +bad_type: | |
1202 | + printk(KERN_EMERG "MSI: Entry has bad type %lx\n", type); | |
1203 | + return; | |
1204 | +} | |
1205 | + | |
1206 | +static int msi_bitmap_alloc(struct pci_pbm_info *pbm) | |
1207 | +{ | |
1208 | + unsigned long size, bits_per_ulong; | |
1209 | + | |
1210 | + bits_per_ulong = sizeof(unsigned long) * 8; | |
1211 | + size = (pbm->msi_num + (bits_per_ulong - 1)) & ~(bits_per_ulong - 1); | |
1212 | + size /= 8; | |
1213 | + BUG_ON(size % sizeof(unsigned long)); | |
1214 | + | |
1215 | + pbm->msi_bitmap = kzalloc(size, GFP_KERNEL); | |
1216 | + if (!pbm->msi_bitmap) | |
1217 | + return -ENOMEM; | |
1218 | + | |
1219 | + return 0; | |
1220 | +} | |
1221 | + | |
1222 | +static void msi_bitmap_free(struct pci_pbm_info *pbm) | |
1223 | +{ | |
1224 | + kfree(pbm->msi_bitmap); | |
1225 | + pbm->msi_bitmap = NULL; | |
1226 | +} | |
1227 | + | |
1228 | +static int msi_queue_alloc(struct pci_pbm_info *pbm) | |
1229 | +{ | |
1230 | + unsigned long q_size, alloc_size, pages, order; | |
1231 | + int i; | |
1232 | + | |
1233 | + q_size = pbm->msiq_ent_count * sizeof(struct pci_sun4v_msiq_entry); | |
1234 | + alloc_size = (pbm->msiq_num * q_size); | |
1235 | + order = get_order(alloc_size); | |
1236 | + pages = __get_free_pages(GFP_KERNEL | __GFP_COMP, order); | |
1237 | + if (pages == 0UL) { | |
1238 | + printk(KERN_ERR "MSI: Cannot allocate MSI queues (o=%lu).\n", | |
1239 | + order); | |
1240 | + return -ENOMEM; | |
1241 | + } | |
1242 | + memset((char *)pages, 0, PAGE_SIZE << order); | |
1243 | + pbm->msi_queues = (void *) pages; | |
1244 | + | |
1245 | + for (i = 0; i < pbm->msiq_num; i++) { | |
1246 | + unsigned long err, base = __pa(pages + (i * q_size)); | |
1247 | + unsigned long ret1, ret2; | |
1248 | + | |
1249 | + err = pci_sun4v_msiq_conf(pbm->devhandle, | |
1250 | + pbm->msiq_first + i, | |
1251 | + base, pbm->msiq_ent_count); | |
1252 | + if (err) { | |
1253 | + printk(KERN_ERR "MSI: msiq register fails (err=%lu)\n", | |
1254 | + err); | |
1255 | + goto h_error; | |
1256 | + } | |
1257 | + | |
1258 | + err = pci_sun4v_msiq_info(pbm->devhandle, | |
1259 | + pbm->msiq_first + i, | |
1260 | + &ret1, &ret2); | |
1261 | + if (err) { | |
1262 | + printk(KERN_ERR "MSI: Cannot read msiq (err=%lu)\n", | |
1263 | + err); | |
1264 | + goto h_error; | |
1265 | + } | |
1266 | + if (ret1 != base || ret2 != pbm->msiq_ent_count) { | |
1267 | + printk(KERN_ERR "MSI: Bogus qconf " | |
1268 | + "expected[%lx:%x] got[%lx:%lx]\n", | |
1269 | + base, pbm->msiq_ent_count, | |
1270 | + ret1, ret2); | |
1271 | + goto h_error; | |
1272 | + } | |
1273 | + } | |
1274 | + | |
1275 | + return 0; | |
1276 | + | |
1277 | +h_error: | |
1278 | + free_pages(pages, order); | |
1279 | + return -EINVAL; | |
1280 | +} | |
1281 | + | |
1282 | +static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) | |
1283 | +{ | |
1284 | + u32 *val; | |
1285 | + int len; | |
1286 | + | |
1287 | + val = of_get_property(pbm->prom_node, "#msi-eqs", &len); | |
1288 | + if (!val || len != 4) | |
1289 | + goto no_msi; | |
1290 | + pbm->msiq_num = *val; | |
1291 | + if (pbm->msiq_num) { | |
1292 | + struct msiq_prop { | |
1293 | + u32 first_msiq; | |
1294 | + u32 num_msiq; | |
1295 | + u32 first_devino; | |
1296 | + } *mqp; | |
1297 | + struct msi_range_prop { | |
1298 | + u32 first_msi; | |
1299 | + u32 num_msi; | |
1300 | + } *mrng; | |
1301 | + struct addr_range_prop { | |
1302 | + u32 msi32_high; | |
1303 | + u32 msi32_low; | |
1304 | + u32 msi32_len; | |
1305 | + u32 msi64_high; | |
1306 | + u32 msi64_low; | |
1307 | + u32 msi64_len; | |
1308 | + } *arng; | |
1309 | + | |
1310 | + val = of_get_property(pbm->prom_node, "msi-eq-size", &len); | |
1311 | + if (!val || len != 4) | |
1312 | + goto no_msi; | |
1313 | + | |
1314 | + pbm->msiq_ent_count = *val; | |
1315 | + | |
1316 | + mqp = of_get_property(pbm->prom_node, | |
1317 | + "msi-eq-to-devino", &len); | |
1318 | + if (!mqp || len != sizeof(struct msiq_prop)) | |
1319 | + goto no_msi; | |
1320 | + | |
1321 | + pbm->msiq_first = mqp->first_msiq; | |
1322 | + pbm->msiq_first_devino = mqp->first_devino; | |
1323 | + | |
1324 | + val = of_get_property(pbm->prom_node, "#msi", &len); | |
1325 | + if (!val || len != 4) | |
1326 | + goto no_msi; | |
1327 | + pbm->msi_num = *val; | |
1328 | + | |
1329 | + mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); | |
1330 | + if (!mrng || len != sizeof(struct msi_range_prop)) | |
1331 | + goto no_msi; | |
1332 | + pbm->msi_first = mrng->first_msi; | |
1333 | + | |
1334 | + val = of_get_property(pbm->prom_node, "msi-data-mask", &len); | |
1335 | + if (!val || len != 4) | |
1336 | + goto no_msi; | |
1337 | + pbm->msi_data_mask = *val; | |
1338 | + | |
1339 | + val = of_get_property(pbm->prom_node, "msix-data-width", &len); | |
1340 | + if (!val || len != 4) | |
1341 | + goto no_msi; | |
1342 | + pbm->msix_data_width = *val; | |
1343 | + | |
1344 | + arng = of_get_property(pbm->prom_node, "msi-address-ranges", | |
1345 | + &len); | |
1346 | + if (!arng || len != sizeof(struct addr_range_prop)) | |
1347 | + goto no_msi; | |
1348 | + pbm->msi32_start = ((u64)arng->msi32_high << 32) | | |
1349 | + (u64) arng->msi32_low; | |
1350 | + pbm->msi64_start = ((u64)arng->msi64_high << 32) | | |
1351 | + (u64) arng->msi64_low; | |
1352 | + pbm->msi32_len = arng->msi32_len; | |
1353 | + pbm->msi64_len = arng->msi64_len; | |
1354 | + | |
1355 | + if (msi_bitmap_alloc(pbm)) | |
1356 | + goto no_msi; | |
1357 | + | |
1358 | + if (msi_queue_alloc(pbm)) { | |
1359 | + msi_bitmap_free(pbm); | |
1360 | + goto no_msi; | |
1361 | + } | |
1362 | + | |
1363 | + printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] " | |
1364 | + "devino[0x%x]\n", | |
1365 | + pbm->name, | |
1366 | + pbm->msiq_first, pbm->msiq_num, | |
1367 | + pbm->msiq_ent_count, | |
1368 | + pbm->msiq_first_devino); | |
1369 | + printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] " | |
1370 | + "width[%u]\n", | |
1371 | + pbm->name, | |
1372 | + pbm->msi_first, pbm->msi_num, pbm->msi_data_mask, | |
1373 | + pbm->msix_data_width); | |
1374 | + printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] " | |
1375 | + "addr64[0x%lx:0x%x]\n", | |
1376 | + pbm->name, | |
1377 | + pbm->msi32_start, pbm->msi32_len, | |
1378 | + pbm->msi64_start, pbm->msi64_len); | |
1379 | + printk(KERN_INFO "%s: MSI queues at RA [%p]\n", | |
1380 | + pbm->name, | |
1381 | + pbm->msi_queues); | |
1382 | + } | |
1383 | + | |
1384 | + return; | |
1385 | + | |
1386 | +no_msi: | |
1387 | + pbm->msiq_num = 0; | |
1388 | + printk(KERN_INFO "%s: No MSI support.\n", pbm->name); | |
1389 | +} | |
1390 | + | |
1391 | +static int alloc_msi(struct pci_pbm_info *pbm) | |
1392 | +{ | |
1393 | + int i; | |
1394 | + | |
1395 | + for (i = 0; i < pbm->msi_num; i++) { | |
1396 | + if (!test_and_set_bit(i, pbm->msi_bitmap)) | |
1397 | + return i + pbm->msi_first; | |
1398 | + } | |
1399 | + | |
1400 | + return -ENOENT; | |
1401 | +} | |
1402 | + | |
1403 | +static void free_msi(struct pci_pbm_info *pbm, int msi_num) | |
1404 | +{ | |
1405 | + msi_num -= pbm->msi_first; | |
1406 | + clear_bit(msi_num, pbm->msi_bitmap); | |
1407 | +} | |
1408 | + | |
1409 | +static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p, | |
1410 | + struct pci_dev *pdev, | |
1411 | + struct msi_desc *entry) | |
1412 | +{ | |
1413 | + struct pcidev_cookie *pcp = pdev->sysdata; | |
1414 | + struct pci_pbm_info *pbm = pcp->pbm; | |
1415 | + unsigned long devino, msiqid; | |
1416 | + struct msi_msg msg; | |
1417 | + int msi_num, err; | |
1418 | + | |
1419 | + *virt_irq_p = 0; | |
1420 | + | |
1421 | + msi_num = alloc_msi(pbm); | |
1422 | + if (msi_num < 0) | |
1423 | + return msi_num; | |
1424 | + | |
1425 | + devino = sun4v_build_msi(pbm->devhandle, virt_irq_p, | |
1426 | + pbm->msiq_first_devino, | |
1427 | + (pbm->msiq_first_devino + | |
1428 | + pbm->msiq_num)); | |
1429 | + err = -ENOMEM; | |
1430 | + if (!devino) | |
1431 | + goto out_err; | |
1432 | + | |
1433 | + set_irq_msi(*virt_irq_p, entry); | |
1434 | + | |
1435 | + msiqid = ((devino - pbm->msiq_first_devino) + | |
1436 | + pbm->msiq_first); | |
1437 | + | |
1438 | + err = -EINVAL; | |
1439 | + if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE)) | |
1440 | + if (err) | |
1441 | + goto out_err; | |
1442 | + | |
1443 | + if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID)) | |
1444 | + goto out_err; | |
1445 | + | |
1446 | + if (pci_sun4v_msi_setmsiq(pbm->devhandle, | |
1447 | + msi_num, msiqid, | |
1448 | + (entry->msi_attrib.is_64 ? | |
1449 | + HV_MSITYPE_MSI64 : HV_MSITYPE_MSI32))) | |
1450 | + goto out_err; | |
1451 | + | |
1452 | + if (pci_sun4v_msi_setstate(pbm->devhandle, msi_num, HV_MSISTATE_IDLE)) | |
1453 | + goto out_err; | |
1454 | + | |
1455 | + if (pci_sun4v_msi_setvalid(pbm->devhandle, msi_num, HV_MSIVALID_VALID)) | |
1456 | + goto out_err; | |
1457 | + | |
1458 | + pcp->msi_num = msi_num; | |
1459 | + | |
1460 | + if (entry->msi_attrib.is_64) { | |
1461 | + msg.address_hi = pbm->msi64_start >> 32; | |
1462 | + msg.address_lo = pbm->msi64_start & 0xffffffff; | |
1463 | + } else { | |
1464 | + msg.address_hi = 0; | |
1465 | + msg.address_lo = pbm->msi32_start; | |
1466 | + } | |
1467 | + msg.data = msi_num; | |
1468 | + write_msi_msg(*virt_irq_p, &msg); | |
1469 | + | |
1470 | + irq_install_pre_handler(*virt_irq_p, | |
1471 | + pci_sun4v_msi_prehandler, | |
1472 | + pbm, (void *) msiqid); | |
1473 | + | |
1474 | + return 0; | |
1475 | + | |
1476 | +out_err: | |
1477 | + free_msi(pbm, msi_num); | |
1478 | + sun4v_destroy_msi(*virt_irq_p); | |
1479 | + *virt_irq_p = 0; | |
1480 | + return err; | |
1481 | + | |
1482 | +} | |
1483 | + | |
1484 | +static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq, | |
1485 | + struct pci_dev *pdev) | |
1486 | +{ | |
1487 | + struct pcidev_cookie *pcp = pdev->sysdata; | |
1488 | + struct pci_pbm_info *pbm = pcp->pbm; | |
1489 | + unsigned long msiqid, err; | |
1490 | + unsigned int msi_num; | |
1491 | + | |
1492 | + msi_num = pcp->msi_num; | |
1493 | + err = pci_sun4v_msi_getmsiq(pbm->devhandle, msi_num, &msiqid); | |
1494 | + if (err) { | |
1495 | + printk(KERN_ERR "%s: getmsiq gives error %lu\n", | |
1496 | + pbm->name, err); | |
1497 | + return; | |
1498 | + } | |
1499 | + | |
1500 | + pci_sun4v_msi_setvalid(pbm->devhandle, msi_num, HV_MSIVALID_INVALID); | |
1501 | + pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_INVALID); | |
1502 | + | |
1503 | + free_msi(pbm, msi_num); | |
1504 | + | |
1505 | + /* The sun4v_destroy_msi() will liberate the devino and thus the MSIQ | |
1506 | + * allocation. | |
1507 | + */ | |
1508 | + sun4v_destroy_msi(virt_irq); | |
1509 | +} | |
1510 | +#else /* CONFIG_PCI_MSI */ | |
1511 | +static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) | |
1512 | +{ | |
1513 | +} | |
1514 | +#endif /* !(CONFIG_PCI_MSI) */ | |
1515 | + | |
1077 | 1516 | static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle) |
1078 | 1517 | { |
1079 | 1518 | struct pci_pbm_info *pbm; |
... | ... | @@ -1119,6 +1558,7 @@ |
1119 | 1558 | |
1120 | 1559 | pci_sun4v_get_bus_range(pbm); |
1121 | 1560 | pci_sun4v_iommu_init(pbm); |
1561 | + pci_sun4v_msi_init(pbm); | |
1122 | 1562 | |
1123 | 1563 | pdev_htab_populate(pbm); |
1124 | 1564 | } |
... | ... | @@ -1187,6 +1627,10 @@ |
1187 | 1627 | p->scan_bus = pci_sun4v_scan_bus; |
1188 | 1628 | p->base_address_update = pci_sun4v_base_address_update; |
1189 | 1629 | p->resource_adjust = pci_sun4v_resource_adjust; |
1630 | +#ifdef CONFIG_PCI_MSI | |
1631 | + p->setup_msi_irq = pci_sun4v_setup_msi_irq; | |
1632 | + p->teardown_msi_irq = pci_sun4v_teardown_msi_irq; | |
1633 | +#endif | |
1190 | 1634 | p->pci_ops = &pci_sun4v_ops; |
1191 | 1635 | |
1192 | 1636 | /* Like PSYCHO and SCHIZO we have a 2GB aligned area |
arch/sparc64/kernel/pci_sun4v.h
... | ... | @@ -28,5 +28,66 @@ |
28 | 28 | unsigned long size, |
29 | 29 | unsigned long data); |
30 | 30 | |
31 | +extern unsigned long pci_sun4v_msiq_conf(unsigned long devhandle, | |
32 | + unsigned long msiqid, | |
33 | + unsigned long msiq_paddr, | |
34 | + unsigned long num_entries); | |
35 | +extern unsigned long pci_sun4v_msiq_info(unsigned long devhandle, | |
36 | + unsigned long msiqid, | |
37 | + unsigned long *msiq_paddr, | |
38 | + unsigned long *num_entries); | |
39 | +extern unsigned long pci_sun4v_msiq_getvalid(unsigned long devhandle, | |
40 | + unsigned long msiqid, | |
41 | + unsigned long *valid); | |
42 | +extern unsigned long pci_sun4v_msiq_setvalid(unsigned long devhandle, | |
43 | + unsigned long msiqid, | |
44 | + unsigned long valid); | |
45 | +extern unsigned long pci_sun4v_msiq_getstate(unsigned long devhandle, | |
46 | + unsigned long msiqid, | |
47 | + unsigned long *state); | |
48 | +extern unsigned long pci_sun4v_msiq_setstate(unsigned long devhandle, | |
49 | + unsigned long msiqid, | |
50 | + unsigned long state); | |
51 | +extern unsigned long pci_sun4v_msiq_gethead(unsigned long devhandle, | |
52 | + unsigned long msiqid, | |
53 | + unsigned long *head); | |
54 | +extern unsigned long pci_sun4v_msiq_sethead(unsigned long devhandle, | |
55 | + unsigned long msiqid, | |
56 | + unsigned long head); | |
57 | +extern unsigned long pci_sun4v_msiq_gettail(unsigned long devhandle, | |
58 | + unsigned long msiqid, | |
59 | + unsigned long *head); | |
60 | +extern unsigned long pci_sun4v_msi_getvalid(unsigned long devhandle, | |
61 | + unsigned long msinum, | |
62 | + unsigned long *valid); | |
63 | +extern unsigned long pci_sun4v_msi_setvalid(unsigned long devhandle, | |
64 | + unsigned long msinum, | |
65 | + unsigned long valid); | |
66 | +extern unsigned long pci_sun4v_msi_getmsiq(unsigned long devhandle, | |
67 | + unsigned long msinum, | |
68 | + unsigned long *msiq); | |
69 | +extern unsigned long pci_sun4v_msi_setmsiq(unsigned long devhandle, | |
70 | + unsigned long msinum, | |
71 | + unsigned long msiq, | |
72 | + unsigned long msitype); | |
73 | +extern unsigned long pci_sun4v_msi_getstate(unsigned long devhandle, | |
74 | + unsigned long msinum, | |
75 | + unsigned long *state); | |
76 | +extern unsigned long pci_sun4v_msi_setstate(unsigned long devhandle, | |
77 | + unsigned long msinum, | |
78 | + unsigned long state); | |
79 | +extern unsigned long pci_sun4v_msg_getmsiq(unsigned long devhandle, | |
80 | + unsigned long msinum, | |
81 | + unsigned long *msiq); | |
82 | +extern unsigned long pci_sun4v_msg_setmsiq(unsigned long devhandle, | |
83 | + unsigned long msinum, | |
84 | + unsigned long msiq); | |
85 | +extern unsigned long pci_sun4v_msg_getvalid(unsigned long devhandle, | |
86 | + unsigned long msinum, | |
87 | + unsigned long *valid); | |
88 | +extern unsigned long pci_sun4v_msg_setvalid(unsigned long devhandle, | |
89 | + unsigned long msinum, | |
90 | + unsigned long valid); | |
91 | + | |
31 | 92 | #endif /* !(_PCI_SUN4V_H) */ |
arch/sparc64/kernel/pci_sun4v_asm.S
... | ... | @@ -93,4 +93,269 @@ |
93 | 93 | mov -1, %o1 |
94 | 94 | 1: retl |
95 | 95 | mov %o1, %o0 |
96 | + | |
97 | + /* %o0: devhandle | |
98 | + * %o1: msiqid | |
99 | + * %o2: msiq phys address | |
100 | + * %o3: num entries | |
101 | + * | |
102 | + * returns %o0: status | |
103 | + * | |
104 | + * status will be zero if the operation completed | |
105 | + * successfully, else -1 if not | |
106 | + */ | |
107 | + .globl pci_sun4v_msiq_conf | |
108 | +pci_sun4v_msiq_conf: | |
109 | + mov HV_FAST_PCI_MSIQ_CONF, %o5 | |
110 | + ta HV_FAST_TRAP | |
111 | + retl | |
112 | + mov %o0, %o0 | |
113 | + | |
114 | + /* %o0: devhandle | |
115 | + * %o1: msiqid | |
116 | + * %o2: &msiq_phys_addr | |
117 | + * %o3: &msiq_num_entries | |
118 | + * | |
119 | + * returns %o0: status | |
120 | + */ | |
121 | + .globl pci_sun4v_msiq_info | |
122 | +pci_sun4v_msiq_info: | |
123 | + mov %o2, %o4 | |
124 | + mov HV_FAST_PCI_MSIQ_INFO, %o5 | |
125 | + ta HV_FAST_TRAP | |
126 | + stx %o1, [%o4] | |
127 | + stx %o2, [%o3] | |
128 | + retl | |
129 | + mov %o0, %o0 | |
130 | + | |
131 | + /* %o0: devhandle | |
132 | + * %o1: msiqid | |
133 | + * %o2: &valid | |
134 | + * | |
135 | + * returns %o0: status | |
136 | + */ | |
137 | + .globl pci_sun4v_msiq_getvalid | |
138 | +pci_sun4v_msiq_getvalid: | |
139 | + mov HV_FAST_PCI_MSIQ_GETVALID, %o5 | |
140 | + ta HV_FAST_TRAP | |
141 | + stx %o1, [%o2] | |
142 | + retl | |
143 | + mov %o0, %o0 | |
144 | + | |
145 | + /* %o0: devhandle | |
146 | + * %o1: msiqid | |
147 | + * %o2: valid | |
148 | + * | |
149 | + * returns %o0: status | |
150 | + */ | |
151 | + .globl pci_sun4v_msiq_setvalid | |
152 | +pci_sun4v_msiq_setvalid: | |
153 | + mov HV_FAST_PCI_MSIQ_SETVALID, %o5 | |
154 | + ta HV_FAST_TRAP | |
155 | + retl | |
156 | + mov %o0, %o0 | |
157 | + | |
158 | + /* %o0: devhandle | |
159 | + * %o1: msiqid | |
160 | + * %o2: &state | |
161 | + * | |
162 | + * returns %o0: status | |
163 | + */ | |
164 | + .globl pci_sun4v_msiq_getstate | |
165 | +pci_sun4v_msiq_getstate: | |
166 | + mov HV_FAST_PCI_MSIQ_GETSTATE, %o5 | |
167 | + ta HV_FAST_TRAP | |
168 | + stx %o1, [%o2] | |
169 | + retl | |
170 | + mov %o0, %o0 | |
171 | + | |
172 | + /* %o0: devhandle | |
173 | + * %o1: msiqid | |
174 | + * %o2: state | |
175 | + * | |
176 | + * returns %o0: status | |
177 | + */ | |
178 | + .globl pci_sun4v_msiq_setstate | |
179 | +pci_sun4v_msiq_setstate: | |
180 | + mov HV_FAST_PCI_MSIQ_SETSTATE, %o5 | |
181 | + ta HV_FAST_TRAP | |
182 | + retl | |
183 | + mov %o0, %o0 | |
184 | + | |
185 | + /* %o0: devhandle | |
186 | + * %o1: msiqid | |
187 | + * %o2: &head | |
188 | + * | |
189 | + * returns %o0: status | |
190 | + */ | |
191 | + .globl pci_sun4v_msiq_gethead | |
192 | +pci_sun4v_msiq_gethead: | |
193 | + mov HV_FAST_PCI_MSIQ_GETHEAD, %o5 | |
194 | + ta HV_FAST_TRAP | |
195 | + stx %o1, [%o2] | |
196 | + retl | |
197 | + mov %o0, %o0 | |
198 | + | |
199 | + /* %o0: devhandle | |
200 | + * %o1: msiqid | |
201 | + * %o2: head | |
202 | + * | |
203 | + * returns %o0: status | |
204 | + */ | |
205 | + .globl pci_sun4v_msiq_sethead | |
206 | +pci_sun4v_msiq_sethead: | |
207 | + mov HV_FAST_PCI_MSIQ_SETHEAD, %o5 | |
208 | + ta HV_FAST_TRAP | |
209 | + retl | |
210 | + mov %o0, %o0 | |
211 | + | |
212 | + /* %o0: devhandle | |
213 | + * %o1: msiqid | |
214 | + * %o2: &tail | |
215 | + * | |
216 | + * returns %o0: status | |
217 | + */ | |
218 | + .globl pci_sun4v_msiq_gettail | |
219 | +pci_sun4v_msiq_gettail: | |
220 | + mov HV_FAST_PCI_MSIQ_GETTAIL, %o5 | |
221 | + ta HV_FAST_TRAP | |
222 | + stx %o1, [%o2] | |
223 | + retl | |
224 | + mov %o0, %o0 | |
225 | + | |
226 | + /* %o0: devhandle | |
227 | + * %o1: msinum | |
228 | + * %o2: &valid | |
229 | + * | |
230 | + * returns %o0: status | |
231 | + */ | |
232 | + .globl pci_sun4v_msi_getvalid | |
233 | +pci_sun4v_msi_getvalid: | |
234 | + mov HV_FAST_PCI_MSI_GETVALID, %o5 | |
235 | + ta HV_FAST_TRAP | |
236 | + stx %o1, [%o2] | |
237 | + retl | |
238 | + mov %o0, %o0 | |
239 | + | |
240 | + /* %o0: devhandle | |
241 | + * %o1: msinum | |
242 | + * %o2: valid | |
243 | + * | |
244 | + * returns %o0: status | |
245 | + */ | |
246 | + .globl pci_sun4v_msi_setvalid | |
247 | +pci_sun4v_msi_setvalid: | |
248 | + mov HV_FAST_PCI_MSI_SETVALID, %o5 | |
249 | + ta HV_FAST_TRAP | |
250 | + retl | |
251 | + mov %o0, %o0 | |
252 | + | |
253 | + /* %o0: devhandle | |
254 | + * %o1: msinum | |
255 | + * %o2: &msiq | |
256 | + * | |
257 | + * returns %o0: status | |
258 | + */ | |
259 | + .globl pci_sun4v_msi_getmsiq | |
260 | +pci_sun4v_msi_getmsiq: | |
261 | + mov HV_FAST_PCI_MSI_GETMSIQ, %o5 | |
262 | + ta HV_FAST_TRAP | |
263 | + stx %o1, [%o2] | |
264 | + retl | |
265 | + mov %o0, %o0 | |
266 | + | |
267 | + /* %o0: devhandle | |
268 | + * %o1: msinum | |
269 | + * %o2: msitype | |
270 | + * %o3: msiq | |
271 | + * | |
272 | + * returns %o0: status | |
273 | + */ | |
274 | + .globl pci_sun4v_msi_setmsiq | |
275 | +pci_sun4v_msi_setmsiq: | |
276 | + mov HV_FAST_PCI_MSI_SETMSIQ, %o5 | |
277 | + ta HV_FAST_TRAP | |
278 | + retl | |
279 | + mov %o0, %o0 | |
280 | + | |
281 | + /* %o0: devhandle | |
282 | + * %o1: msinum | |
283 | + * %o2: &state | |
284 | + * | |
285 | + * returns %o0: status | |
286 | + */ | |
287 | + .globl pci_sun4v_msi_getstate | |
288 | +pci_sun4v_msi_getstate: | |
289 | + mov HV_FAST_PCI_MSI_GETSTATE, %o5 | |
290 | + ta HV_FAST_TRAP | |
291 | + stx %o1, [%o2] | |
292 | + retl | |
293 | + mov %o0, %o0 | |
294 | + | |
295 | + /* %o0: devhandle | |
296 | + * %o1: msinum | |
297 | + * %o2: state | |
298 | + * | |
299 | + * returns %o0: status | |
300 | + */ | |
301 | + .globl pci_sun4v_msi_setstate | |
302 | +pci_sun4v_msi_setstate: | |
303 | + mov HV_FAST_PCI_MSI_SETSTATE, %o5 | |
304 | + ta HV_FAST_TRAP | |
305 | + retl | |
306 | + mov %o0, %o0 | |
307 | + | |
308 | + /* %o0: devhandle | |
309 | + * %o1: msinum | |
310 | + * %o2: &msiq | |
311 | + * | |
312 | + * returns %o0: status | |
313 | + */ | |
314 | + .globl pci_sun4v_msg_getmsiq | |
315 | +pci_sun4v_msg_getmsiq: | |
316 | + mov HV_FAST_PCI_MSG_GETMSIQ, %o5 | |
317 | + ta HV_FAST_TRAP | |
318 | + stx %o1, [%o2] | |
319 | + retl | |
320 | + mov %o0, %o0 | |
321 | + | |
322 | + /* %o0: devhandle | |
323 | + * %o1: msinum | |
324 | + * %o2: msiq | |
325 | + * | |
326 | + * returns %o0: status | |
327 | + */ | |
328 | + .globl pci_sun4v_msg_setmsiq | |
329 | +pci_sun4v_msg_setmsiq: | |
330 | + mov HV_FAST_PCI_MSG_SETMSIQ, %o5 | |
331 | + ta HV_FAST_TRAP | |
332 | + retl | |
333 | + mov %o0, %o0 | |
334 | + | |
335 | + /* %o0: devhandle | |
336 | + * %o1: msinum | |
337 | + * %o2: &valid | |
338 | + * | |
339 | + * returns %o0: status | |
340 | + */ | |
341 | + .globl pci_sun4v_msg_getvalid | |
342 | +pci_sun4v_msg_getvalid: | |
343 | + mov HV_FAST_PCI_MSG_GETVALID, %o5 | |
344 | + ta HV_FAST_TRAP | |
345 | + stx %o1, [%o2] | |
346 | + retl | |
347 | + mov %o0, %o0 | |
348 | + | |
349 | + /* %o0: devhandle | |
350 | + * %o1: msinum | |
351 | + * %o2: valid | |
352 | + * | |
353 | + * returns %o0: status | |
354 | + */ | |
355 | + .globl pci_sun4v_msg_setvalid | |
356 | +pci_sun4v_msg_setvalid: | |
357 | + mov HV_FAST_PCI_MSG_SETVALID, %o5 | |
358 | + ta HV_FAST_TRAP | |
359 | + retl | |
360 | + mov %o0, %o0 |
block/ioctl.c
drivers/pci/Kconfig
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | config PCI_MSI |
5 | 5 | bool "Message Signaled Interrupts (MSI and MSI-X)" |
6 | 6 | depends on PCI |
7 | - depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64 | |
7 | + depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64 || SPARC64 | |
8 | 8 | help |
9 | 9 | This allows device drivers to enable MSI (Message Signaled |
10 | 10 | Interrupts). Message Signaled Interrupts enable a device to |
drivers/sbus/sbus.c
... | ... | @@ -7,6 +7,7 @@ |
7 | 7 | #include <linux/slab.h> |
8 | 8 | #include <linux/init.h> |
9 | 9 | #include <linux/pci.h> |
10 | +#include <linux/device.h> | |
10 | 11 | |
11 | 12 | #include <asm/system.h> |
12 | 13 | #include <asm/sbus.h> |
13 | 14 | |
... | ... | @@ -17,13 +18,25 @@ |
17 | 18 | #include <asm/bpp.h> |
18 | 19 | #include <asm/irq.h> |
19 | 20 | |
21 | +static ssize_t | |
22 | +show_sbusobppath_attr(struct device * dev, struct device_attribute * attr, char * buf) | |
23 | +{ | |
24 | + struct sbus_dev *sbus; | |
25 | + | |
26 | + sbus = to_sbus_device(dev); | |
27 | + | |
28 | + return snprintf (buf, PAGE_SIZE, "%s\n", sbus->ofdev.node->full_name); | |
29 | +} | |
30 | + | |
31 | +static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_sbusobppath_attr, NULL); | |
32 | + | |
20 | 33 | struct sbus_bus *sbus_root; |
21 | 34 | |
22 | 35 | static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev) |
23 | 36 | { |
24 | 37 | unsigned long base; |
25 | 38 | void *pval; |
26 | - int len; | |
39 | + int len, err; | |
27 | 40 | |
28 | 41 | sdev->prom_node = dp->node; |
29 | 42 | strcpy(sdev->prom_name, dp->name); |
... | ... | @@ -66,6 +79,9 @@ |
66 | 79 | if (of_device_register(&sdev->ofdev) != 0) |
67 | 80 | printk(KERN_DEBUG "sbus: device registration error for %s!\n", |
68 | 81 | dp->path_component_name); |
82 | + | |
83 | + /* WE HAVE BEEN INVADED BY ALIENS! */ | |
84 | + err = sysfs_create_file(&sdev->ofdev.dev.kobj, &dev_attr_obppath.attr); | |
69 | 85 | } |
70 | 86 | |
71 | 87 | static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus) |
fs/partitions/check.c
... | ... | @@ -365,7 +365,7 @@ |
365 | 365 | kobject_put(&p->kobj); |
366 | 366 | } |
367 | 367 | |
368 | -void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) | |
368 | +void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags) | |
369 | 369 | { |
370 | 370 | struct hd_struct *p; |
371 | 371 | |
... | ... | @@ -390,6 +390,15 @@ |
390 | 390 | if (!disk->part_uevent_suppress) |
391 | 391 | kobject_uevent(&p->kobj, KOBJ_ADD); |
392 | 392 | sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem"); |
393 | + if (flags & ADDPART_FLAG_WHOLEDISK) { | |
394 | + static struct attribute addpartattr = { | |
395 | + .name = "whole_disk", | |
396 | + .mode = S_IRUSR | S_IRGRP | S_IROTH, | |
397 | + .owner = THIS_MODULE, | |
398 | + }; | |
399 | + | |
400 | + sysfs_create_file(&p->kobj, &addpartattr); | |
401 | + } | |
393 | 402 | partition_sysfs_add_subdir(p); |
394 | 403 | disk->part[part-1] = p; |
395 | 404 | } |
396 | 405 | |
... | ... | @@ -543,9 +552,9 @@ |
543 | 552 | printk(" %s: p%d exceeds device capacity\n", |
544 | 553 | disk->disk_name, p); |
545 | 554 | } |
546 | - add_partition(disk, p, from, size); | |
555 | + add_partition(disk, p, from, size, state->parts[p].flags); | |
547 | 556 | #ifdef CONFIG_BLK_DEV_MD |
548 | - if (state->parts[p].flags) | |
557 | + if (state->parts[p].flags & ADDPART_FLAG_RAID) | |
549 | 558 | md_autodetect_dev(bdev->bd_dev+p); |
550 | 559 | #endif |
551 | 560 | } |
fs/partitions/msdos.c
... | ... | @@ -165,7 +165,7 @@ |
165 | 165 | |
166 | 166 | put_partition(state, state->next, next, size); |
167 | 167 | if (SYS_IND(p) == LINUX_RAID_PARTITION) |
168 | - state->parts[state->next].flags = 1; | |
168 | + state->parts[state->next].flags = ADDPART_FLAG_RAID; | |
169 | 169 | loopct = 0; |
170 | 170 | if (++state->next == state->limit) |
171 | 171 | goto done; |
fs/partitions/sgi.c
fs/partitions/sun.c
... | ... | @@ -80,8 +80,11 @@ |
80 | 80 | num_sectors = be32_to_cpu(p->num_sectors); |
81 | 81 | if (num_sectors) { |
82 | 82 | put_partition(state, slot, st_sector, num_sectors); |
83 | + state->parts[slot].flags = 0; | |
83 | 84 | if (label->infos[i].id == LINUX_RAID_PARTITION) |
84 | - state->parts[slot].flags = 1; | |
85 | + state->parts[slot].flags |= ADDPART_FLAG_RAID; | |
86 | + if (label->infos[i].id == SUN_WHOLE_DISK) | |
87 | + state->parts[slot].flags |= ADDPART_FLAG_WHOLEDISK; | |
85 | 88 | } |
86 | 89 | slot++; |
87 | 90 | } |
include/asm-sparc64/irq.h
... | ... | @@ -46,6 +46,10 @@ |
46 | 46 | #define irq_canonicalize(irq) (irq) |
47 | 47 | extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap); |
48 | 48 | extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino); |
49 | +extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p, | |
50 | + unsigned int msi_devino_start, | |
51 | + unsigned int msi_devino_end); | |
52 | +extern void sun4v_destroy_msi(unsigned int virt_irq); | |
49 | 53 | extern unsigned int sbus_build_irq(void *sbus, unsigned int ino); |
50 | 54 | |
51 | 55 | static __inline__ void set_softint(unsigned long bits) |
include/asm-sparc64/pbm.h
... | ... | @@ -11,6 +11,7 @@ |
11 | 11 | #include <linux/pci.h> |
12 | 12 | #include <linux/ioport.h> |
13 | 13 | #include <linux/spinlock.h> |
14 | +#include <linux/msi.h> | |
14 | 15 | |
15 | 16 | #include <asm/io.h> |
16 | 17 | #include <asm/page.h> |
... | ... | @@ -177,6 +178,24 @@ |
177 | 178 | int is_66mhz_capable; |
178 | 179 | int all_devs_66mhz; |
179 | 180 | |
181 | +#ifdef CONFIG_PCI_MSI | |
182 | + /* MSI info. */ | |
183 | + u32 msiq_num; | |
184 | + u32 msiq_ent_count; | |
185 | + u32 msiq_first; | |
186 | + u32 msiq_first_devino; | |
187 | + u32 msi_num; | |
188 | + u32 msi_first; | |
189 | + u32 msi_data_mask; | |
190 | + u32 msix_data_width; | |
191 | + u64 msi32_start; | |
192 | + u64 msi64_start; | |
193 | + u32 msi32_len; | |
194 | + u32 msi64_len; | |
195 | + void *msi_queues; | |
196 | + unsigned long *msi_bitmap; | |
197 | +#endif /* !(CONFIG_PCI_MSI) */ | |
198 | + | |
180 | 199 | /* This PBM's streaming buffer. */ |
181 | 200 | struct pci_strbuf stc; |
182 | 201 | |
... | ... | @@ -213,6 +232,12 @@ |
213 | 232 | void (*base_address_update)(struct pci_dev *, int); |
214 | 233 | void (*resource_adjust)(struct pci_dev *, struct resource *, struct resource *); |
215 | 234 | |
235 | +#ifdef CONFIG_PCI_MSI | |
236 | + int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev, | |
237 | + struct msi_desc *entry); | |
238 | + void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev); | |
239 | +#endif | |
240 | + | |
216 | 241 | /* Now things for the actual PCI bus probes. */ |
217 | 242 | struct pci_ops *pci_ops; |
218 | 243 | unsigned int pci_first_busno; |
... | ... | @@ -231,6 +256,9 @@ |
231 | 256 | int num_prom_regs; |
232 | 257 | struct linux_prom_pci_registers prom_assignments[PROMREG_MAX]; |
233 | 258 | int num_prom_assignments; |
259 | +#ifdef CONFIG_PCI_MSI | |
260 | + unsigned int msi_num; | |
261 | +#endif | |
234 | 262 | }; |
235 | 263 | |
236 | 264 | /* Currently these are the same across all PCI controllers |
include/linux/genhd.h
... | ... | @@ -20,6 +20,8 @@ |
20 | 20 | LINUX_EXTENDED_PARTITION = 0x85, |
21 | 21 | WIN98_EXTENDED_PARTITION = 0x0f, |
22 | 22 | |
23 | + SUN_WHOLE_DISK = DOS_EXTENDED_PARTITION, | |
24 | + | |
23 | 25 | LINUX_SWAP_PARTITION = 0x82, |
24 | 26 | LINUX_DATA_PARTITION = 0x83, |
25 | 27 | LINUX_LVM_PARTITION = 0x8e, |
26 | 28 | |
... | ... | @@ -402,10 +404,14 @@ |
402 | 404 | |
403 | 405 | #ifdef __KERNEL__ |
404 | 406 | |
407 | +#define ADDPART_FLAG_NONE 0 | |
408 | +#define ADDPART_FLAG_RAID 1 | |
409 | +#define ADDPART_FLAG_WHOLEDISK 2 | |
410 | + | |
405 | 411 | char *disk_name (struct gendisk *hd, int part, char *buf); |
406 | 412 | |
407 | 413 | extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); |
408 | -extern void add_partition(struct gendisk *, int, sector_t, sector_t); | |
414 | +extern void add_partition(struct gendisk *, int, sector_t, sector_t, int); | |
409 | 415 | extern void delete_partition(struct gendisk *, int); |
410 | 416 | |
411 | 417 | extern struct gendisk *alloc_disk_node(int minors, int node_id); |