[PATCH] IB/ipath - program intconfig register using new HT irq hook

Eric's changes to the htirq infrastructure require corresponding
modifications to the ipath HT driver code so that interrupts are still
delivered properly.

Signed-off-by: Bryan O'Sullivan <bryan.osullivan@qlogic.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Roland Dreier <rdreier@cisco.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Bryan O'Sullivan and committed by Linus Torvalds 51f65ebc 43539c38

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