diff options
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 17 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_iba6110.c | 117 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_iba6120.c | 8 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_intr.c | 10 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 4 |
5 files changed, 74 insertions, 82 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index b4ffaa7bcbb7..09a13c1fc46a 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
| @@ -304,7 +304,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, | |||
| 304 | } | 304 | } |
| 305 | addr = pci_resource_start(pdev, 0); | 305 | addr = pci_resource_start(pdev, 0); |
| 306 | len = pci_resource_len(pdev, 0); | 306 | len = pci_resource_len(pdev, 0); |
| 307 | ipath_cdbg(VERBOSE, "regbase (0) %llx len %d irq %x, vend %x/%x " | 307 | ipath_cdbg(VERBOSE, "regbase (0) %llx len %d pdev->irq %d, vend %x/%x " |
| 308 | "driver_data %lx\n", addr, len, pdev->irq, ent->vendor, | 308 | "driver_data %lx\n", addr, len, pdev->irq, ent->vendor, |
| 309 | ent->device, ent->driver_data); | 309 | ent->device, ent->driver_data); |
| 310 | 310 | ||
| @@ -467,15 +467,15 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, | |||
| 467 | * check 0 irq after we return from chip-specific bus setup, since | 467 | * check 0 irq after we return from chip-specific bus setup, since |
| 468 | * that can affect this due to setup | 468 | * that can affect this due to setup |
| 469 | */ | 469 | */ |
| 470 | if (!pdev->irq) | 470 | if (!dd->ipath_irq) |
| 471 | ipath_dev_err(dd, "irq is 0, BIOS error? Interrupts won't " | 471 | ipath_dev_err(dd, "irq is 0, BIOS error? Interrupts won't " |
| 472 | "work\n"); | 472 | "work\n"); |
| 473 | else { | 473 | else { |
| 474 | ret = request_irq(pdev->irq, ipath_intr, IRQF_SHARED, | 474 | ret = request_irq(dd->ipath_irq, ipath_intr, IRQF_SHARED, |
| 475 | IPATH_DRV_NAME, dd); | 475 | IPATH_DRV_NAME, dd); |
| 476 | if (ret) { | 476 | if (ret) { |
| 477 | ipath_dev_err(dd, "Couldn't setup irq handler, " | 477 | ipath_dev_err(dd, "Couldn't setup irq handler, " |
| 478 | "irq=%u: %d\n", pdev->irq, ret); | 478 | "irq=%d: %d\n", dd->ipath_irq, ret); |
| 479 | goto bail_iounmap; | 479 | goto bail_iounmap; |
| 480 | } | 480 | } |
| 481 | } | 481 | } |
| @@ -637,11 +637,10 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev) | |||
| 637 | * free up port 0 (kernel) rcvhdr, egr bufs, and eventually tid bufs | 637 | * free up port 0 (kernel) rcvhdr, egr bufs, and eventually tid bufs |
| 638 | * for all versions of the driver, if they were allocated | 638 | * for all versions of the driver, if they were allocated |
| 639 | */ | 639 | */ |
| 640 | if (pdev->irq) { | 640 | if (dd->ipath_irq) { |
| 641 | ipath_cdbg(VERBOSE, | 641 | ipath_cdbg(VERBOSE, "unit %u free irq %d\n", |
| 642 | "unit %u free_irq of irq %x\n", | 642 | dd->ipath_unit, dd->ipath_irq); |
| 643 | dd->ipath_unit, pdev->irq); | 643 | dd->ipath_f_free_irq(dd); |
| 644 | free_irq(pdev->irq, dd); | ||
| 645 | } else | 644 | } else |
| 646 | ipath_dbg("irq is 0, not doing free_irq " | 645 | ipath_dbg("irq is 0, not doing free_irq " |
| 647 | "for unit %u\n", dd->ipath_unit); | 646 | "for unit %u\n", dd->ipath_unit); |
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c index 9e4e8d4c6e20..e57c7a351cb5 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6110.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | 38 | ||
| 39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
| 40 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
| 41 | #include <linux/htirq.h> | ||
| 41 | 42 | ||
| 42 | #include "ipath_kernel.h" | 43 | #include "ipath_kernel.h" |
| 43 | #include "ipath_registers.h" | 44 | #include "ipath_registers.h" |
| @@ -913,49 +914,40 @@ static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev, | |||
| 913 | } | 914 | } |
| 914 | } | 915 | } |
| 915 | 916 | ||
| 916 | static int set_int_handler(struct ipath_devdata *dd, struct pci_dev *pdev, | 917 | static int ipath_ht_intconfig(struct ipath_devdata *dd) |
| 917 | int pos) | ||
| 918 | { | 918 | { |
| 919 | u32 int_handler_addr_lower; | 919 | int ret; |
| 920 | u32 int_handler_addr_upper; | ||
| 921 | u64 ihandler; | ||
| 922 | u32 intvec; | ||
| 923 | 920 | ||
| 924 | /* use indirection register to get the intr handler */ | 921 | if (dd->ipath_intconfig) { |
| 925 | pci_write_config_byte(pdev, pos + HT_INTR_REG_INDEX, 0x10); | 922 | ipath_write_kreg(dd, dd->ipath_kregs->kr_interruptconfig, |
| 926 | pci_read_config_dword(pdev, pos + 4, &int_handler_addr_lower); | 923 | dd->ipath_intconfig); /* interrupt address */ |
| 927 | pci_write_config_byte(pdev, pos + HT_INTR_REG_INDEX, 0x11); | 924 | ret = 0; |
| 928 | pci_read_config_dword(pdev, pos + 4, &int_handler_addr_upper); | 925 | } else { |
| 926 | ipath_dev_err(dd, "No interrupts enabled, couldn't setup " | ||
| 927 | "interrupt address\n"); | ||
| 928 | ret = -EINVAL; | ||
| 929 | } | ||
| 929 | 930 | ||
| 930 | ihandler = (u64) int_handler_addr_lower | | 931 | return ret; |
| 931 | ((u64) int_handler_addr_upper << 32); | 932 | } |
| 933 | |||
| 934 | static void ipath_ht_irq_update(struct pci_dev *dev, int irq, | ||
| 935 | struct ht_irq_msg *msg) | ||
| 936 | { | ||
| 937 | struct ipath_devdata *dd = pci_get_drvdata(dev); | ||
| 938 | u64 prev_intconfig = dd->ipath_intconfig; | ||
| 939 | |||
| 940 | dd->ipath_intconfig = msg->address_lo; | ||
| 941 | dd->ipath_intconfig |= ((u64) msg->address_hi) << 32; | ||
| 932 | 942 | ||
| 933 | /* | 943 | /* |
| 934 | * kernels with CONFIG_PCI_MSI set the vector in the irq field of | 944 | * If the previous value of dd->ipath_intconfig is zero, we're |
| 935 | * struct pci_device, so we use that to program the internal | 945 | * getting configured for the first time, and must not program the |
| 936 | * interrupt register (not config space) with that value. The BIOS | 946 | * intconfig register here (it will be programmed later, when the |
| 937 | * must still have done the basic MSI setup. | 947 | * hardware is ready). Otherwise, we should. |
| 938 | */ | ||
| 939 | intvec = pdev->irq; | ||
| 940 | /* | ||
| 941 | * clear any vector bits there; normally not set but we'll overload | ||
| 942 | * this for some debug purposes (setting the HTC debug register | ||
| 943 | * value from software, rather than GPIOs), so it might be set on a | ||
| 944 | * driver reload. | ||
| 945 | */ | 948 | */ |
| 946 | ihandler &= ~0xff0000; | 949 | if (prev_intconfig) |
| 947 | /* x86 vector goes in intrinfo[23:16] */ | 950 | ipath_ht_intconfig(dd); |
| 948 | ihandler |= intvec << 16; | ||
| 949 | ipath_cdbg(VERBOSE, "ihandler lower %x, upper %x, intvec %x, " | ||
| 950 | "interruptconfig %llx\n", int_handler_addr_lower, | ||
| 951 | int_handler_addr_upper, intvec, | ||
| 952 | (unsigned long long) ihandler); | ||
| 953 | |||
| 954 | /* can't program yet, so save for interrupt setup */ | ||
| 955 | dd->ipath_intconfig = ihandler; | ||
| 956 | /* keep going, so we find link control stuff also */ | ||
| 957 | |||
| 958 | return ihandler != 0; | ||
| 959 | } | 951 | } |
| 960 | 952 | ||
| 961 | /** | 953 | /** |
| @@ -971,12 +963,19 @@ static int set_int_handler(struct ipath_devdata *dd, struct pci_dev *pdev, | |||
| 971 | static int ipath_setup_ht_config(struct ipath_devdata *dd, | 963 | static int ipath_setup_ht_config(struct ipath_devdata *dd, |
| 972 | struct pci_dev *pdev) | 964 | struct pci_dev *pdev) |
| 973 | { | 965 | { |
| 974 | int pos, ret = 0; | 966 | int pos, ret; |
| 975 | int ihandler = 0; | 967 | |
| 968 | ret = __ht_create_irq(pdev, 0, ipath_ht_irq_update); | ||
| 969 | if (ret < 0) { | ||
| 970 | ipath_dev_err(dd, "Couldn't create interrupt handler: " | ||
| 971 | "err %d\n", ret); | ||
| 972 | goto bail; | ||
| 973 | } | ||
| 974 | dd->ipath_irq = ret; | ||
| 975 | ret = 0; | ||
| 976 | 976 | ||
| 977 | /* | 977 | /* |
| 978 | * Read the capability info to find the interrupt info, and also | 978 | * Handle clearing CRC errors in linkctrl register if necessary. We |
| 979 | * handle clearing CRC errors in linkctrl register if necessary. We | ||
| 980 | * do this early, before we ever enable errors or hardware errors, | 979 | * do this early, before we ever enable errors or hardware errors, |
| 981 | * mostly to avoid causing the chip to enter freeze mode. | 980 | * mostly to avoid causing the chip to enter freeze mode. |
| 982 | */ | 981 | */ |
| @@ -1000,17 +999,9 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd, | |||
| 1000 | } | 999 | } |
| 1001 | if (!(cap_type & 0xE0)) | 1000 | if (!(cap_type & 0xE0)) |
| 1002 | slave_or_pri_blk(dd, pdev, pos, cap_type); | 1001 | slave_or_pri_blk(dd, pdev, pos, cap_type); |
| 1003 | else if (cap_type == HT_INTR_DISC_CONFIG) | ||
| 1004 | ihandler = set_int_handler(dd, pdev, pos); | ||
| 1005 | } while ((pos = pci_find_next_capability(pdev, pos, | 1002 | } while ((pos = pci_find_next_capability(pdev, pos, |
| 1006 | PCI_CAP_ID_HT))); | 1003 | PCI_CAP_ID_HT))); |
| 1007 | 1004 | ||
| 1008 | if (!ihandler) { | ||
| 1009 | ipath_dev_err(dd, "Couldn't find interrupt handler in " | ||
| 1010 | "config space\n"); | ||
| 1011 | ret = -ENODEV; | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | bail: | 1005 | bail: |
| 1015 | return ret; | 1006 | return ret; |
| 1016 | } | 1007 | } |
| @@ -1360,25 +1351,6 @@ static void ipath_ht_quiet_serdes(struct ipath_devdata *dd) | |||
| 1360 | ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val); | 1351 | ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val); |
| 1361 | } | 1352 | } |
| 1362 | 1353 | ||
| 1363 | static int ipath_ht_intconfig(struct ipath_devdata *dd) | ||
| 1364 | { | ||
| 1365 | int ret; | ||
| 1366 | |||
| 1367 | if (!dd->ipath_intconfig) { | ||
| 1368 | ipath_dev_err(dd, "No interrupts enabled, couldn't setup " | ||
| 1369 | "interrupt address\n"); | ||
| 1370 | ret = 1; | ||
| 1371 | goto bail; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | ipath_write_kreg(dd, dd->ipath_kregs->kr_interruptconfig, | ||
| 1375 | dd->ipath_intconfig); /* interrupt address */ | ||
| 1376 | ret = 0; | ||
| 1377 | |||
| 1378 | bail: | ||
| 1379 | return ret; | ||
| 1380 | } | ||
| 1381 | |||
| 1382 | /** | 1354 | /** |
| 1383 | * ipath_pe_put_tid - write a TID in chip | 1355 | * ipath_pe_put_tid - write a TID in chip |
| 1384 | * @dd: the infinipath device | 1356 | * @dd: the infinipath device |
| @@ -1575,6 +1547,14 @@ static int ipath_ht_get_base_info(struct ipath_portdata *pd, void *kbase) | |||
| 1575 | return 0; | 1547 | return 0; |
| 1576 | } | 1548 | } |
| 1577 | 1549 | ||
| 1550 | static void ipath_ht_free_irq(struct ipath_devdata *dd) | ||
| 1551 | { | ||
| 1552 | free_irq(dd->ipath_irq, dd); | ||
| 1553 | ht_destroy_irq(dd->ipath_irq); | ||
| 1554 | dd->ipath_irq = 0; | ||
| 1555 | dd->ipath_intconfig = 0; | ||
| 1556 | } | ||
| 1557 | |||
| 1578 | /** | 1558 | /** |
| 1579 | * ipath_init_iba6110_funcs - set up the chip-specific function pointers | 1559 | * ipath_init_iba6110_funcs - set up the chip-specific function pointers |
| 1580 | * @dd: the infinipath device | 1560 | * @dd: the infinipath device |
| @@ -1598,6 +1578,7 @@ void ipath_init_iba6110_funcs(struct ipath_devdata *dd) | |||
| 1598 | dd->ipath_f_cleanup = ipath_setup_ht_cleanup; | 1578 | dd->ipath_f_cleanup = ipath_setup_ht_cleanup; |
| 1599 | dd->ipath_f_setextled = ipath_setup_ht_setextled; | 1579 | dd->ipath_f_setextled = ipath_setup_ht_setextled; |
| 1600 | dd->ipath_f_get_base_info = ipath_ht_get_base_info; | 1580 | dd->ipath_f_get_base_info = ipath_ht_get_base_info; |
| 1581 | dd->ipath_f_free_irq = ipath_ht_free_irq; | ||
| 1601 | 1582 | ||
| 1602 | /* | 1583 | /* |
| 1603 | * initialize chip-specific variables | 1584 | * initialize chip-specific variables |
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c index a72ab9de386a..6af89683f710 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6120.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c | |||
| @@ -851,6 +851,7 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd, | |||
| 851 | int pos, ret; | 851 | int pos, ret; |
| 852 | 852 | ||
| 853 | dd->ipath_msi_lo = 0; /* used as a flag during reset processing */ | 853 | dd->ipath_msi_lo = 0; /* used as a flag during reset processing */ |
| 854 | dd->ipath_irq = pdev->irq; | ||
| 854 | ret = pci_enable_msi(dd->pcidev); | 855 | ret = pci_enable_msi(dd->pcidev); |
| 855 | if (ret) | 856 | if (ret) |
| 856 | ipath_dev_err(dd, "pci_enable_msi failed: %d, " | 857 | ipath_dev_err(dd, "pci_enable_msi failed: %d, " |
| @@ -1323,6 +1324,12 @@ done: | |||
| 1323 | return 0; | 1324 | return 0; |
| 1324 | } | 1325 | } |
| 1325 | 1326 | ||
| 1327 | static void ipath_pe_free_irq(struct ipath_devdata *dd) | ||
| 1328 | { | ||
| 1329 | free_irq(dd->ipath_irq, dd); | ||
| 1330 | dd->ipath_irq = 0; | ||
| 1331 | } | ||
| 1332 | |||
| 1326 | /** | 1333 | /** |
| 1327 | * ipath_init_iba6120_funcs - set up the chip-specific function pointers | 1334 | * ipath_init_iba6120_funcs - set up the chip-specific function pointers |
| 1328 | * @dd: the infinipath device | 1335 | * @dd: the infinipath device |
| @@ -1349,6 +1356,7 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd) | |||
| 1349 | dd->ipath_f_cleanup = ipath_setup_pe_cleanup; | 1356 | dd->ipath_f_cleanup = ipath_setup_pe_cleanup; |
| 1350 | dd->ipath_f_setextled = ipath_setup_pe_setextled; | 1357 | dd->ipath_f_setextled = ipath_setup_pe_setextled; |
| 1351 | dd->ipath_f_get_base_info = ipath_pe_get_base_info; | 1358 | dd->ipath_f_get_base_info = ipath_pe_get_base_info; |
| 1359 | dd->ipath_f_free_irq = ipath_pe_free_irq; | ||
| 1352 | 1360 | ||
| 1353 | /* initialize chip-specific variables */ | 1361 | /* initialize chip-specific variables */ |
| 1354 | dd->ipath_f_tidtemplate = ipath_pe_tidtemplate; | 1362 | dd->ipath_f_tidtemplate = ipath_pe_tidtemplate; |
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index d9079ee12030..5652a550d442 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c | |||
| @@ -710,14 +710,14 @@ static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp) | |||
| 710 | * linuxbios development work, and it may happen in | 710 | * linuxbios development work, and it may happen in |
| 711 | * the future again. | 711 | * the future again. |
| 712 | */ | 712 | */ |
| 713 | if (dd->pcidev && dd->pcidev->irq) { | 713 | if (dd->pcidev && dd->ipath_irq) { |
| 714 | ipath_dev_err(dd, "Now %u unexpected " | 714 | ipath_dev_err(dd, "Now %u unexpected " |
| 715 | "interrupts, unregistering " | 715 | "interrupts, unregistering " |
| 716 | "interrupt handler\n", | 716 | "interrupt handler\n", |
| 717 | *unexpectp); | 717 | *unexpectp); |
| 718 | ipath_dbg("free_irq of irq %x\n", | 718 | ipath_dbg("free_irq of irq %d\n", |
| 719 | dd->pcidev->irq); | 719 | dd->ipath_irq); |
| 720 | free_irq(dd->pcidev->irq, dd); | 720 | dd->ipath_f_free_irq(dd); |
| 721 | } | 721 | } |
| 722 | } | 722 | } |
| 723 | if (ipath_read_kreg32(dd, dd->ipath_kregs->kr_intmask)) { | 723 | if (ipath_read_kreg32(dd, dd->ipath_kregs->kr_intmask)) { |
| @@ -753,7 +753,7 @@ static void ipath_bad_regread(struct ipath_devdata *dd) | |||
| 753 | if (allbits == 2) { | 753 | if (allbits == 2) { |
| 754 | ipath_dev_err(dd, "Still bad interrupt status, " | 754 | ipath_dev_err(dd, "Still bad interrupt status, " |
| 755 | "unregistering interrupt\n"); | 755 | "unregistering interrupt\n"); |
| 756 | free_irq(dd->pcidev->irq, dd); | 756 | dd->ipath_f_free_irq(dd); |
| 757 | } else if (allbits > 2) { | 757 | } else if (allbits > 2) { |
| 758 | if ((allbits % 10000) == 0) | 758 | if ((allbits % 10000) == 0) |
| 759 | printk("."); | 759 | printk("."); |
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 06d5020a2f60..986b2125b8f5 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
| @@ -213,6 +213,8 @@ struct ipath_devdata { | |||
| 213 | void (*ipath_f_setextled)(struct ipath_devdata *, u64, u64); | 213 | void (*ipath_f_setextled)(struct ipath_devdata *, u64, u64); |
| 214 | /* fill out chip-specific fields */ | 214 | /* fill out chip-specific fields */ |
| 215 | int (*ipath_f_get_base_info)(struct ipath_portdata *, void *); | 215 | int (*ipath_f_get_base_info)(struct ipath_portdata *, void *); |
| 216 | /* free irq */ | ||
| 217 | void (*ipath_f_free_irq)(struct ipath_devdata *); | ||
| 216 | struct ipath_ibdev *verbs_dev; | 218 | struct ipath_ibdev *verbs_dev; |
| 217 | struct timer_list verbs_timer; | 219 | struct timer_list verbs_timer; |
| 218 | /* total dwords sent (summed from counter) */ | 220 | /* total dwords sent (summed from counter) */ |
| @@ -328,6 +330,8 @@ struct ipath_devdata { | |||
| 328 | /* so we can rewrite it after a chip reset */ | 330 | /* so we can rewrite it after a chip reset */ |
| 329 | u32 ipath_pcibar1; | 331 | u32 ipath_pcibar1; |
| 330 | 332 | ||
| 333 | /* interrupt number */ | ||
| 334 | int ipath_irq; | ||
| 331 | /* HT/PCI Vendor ID (here for NodeInfo) */ | 335 | /* HT/PCI Vendor ID (here for NodeInfo) */ |
| 332 | u16 ipath_vendorid; | 336 | u16 ipath_vendorid; |
| 333 | /* HT/PCI Device ID (here for NodeInfo) */ | 337 | /* HT/PCI Device ID (here for NodeInfo) */ |
