aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Marciniszyn <mike.marciniszyn@intel.com>2014-03-07 08:40:49 -0500
committerRoland Dreier <roland@purestorage.com>2014-03-17 19:16:51 -0400
commit1ed88dd7d0b361e677b2690f573e5c274bb25c87 (patch)
treed78f5aa8f9983b92b7db9f876817199b136c3a2b
parentf8b6c47a44c063062317646683a73371c24c69ee (diff)
IB/qib: Add percpu counter replacing qib_devdata int_counter
This patch replaces the dd->int_counter with a percpu counter. The maintanance of qib_stats.sps_ints and int_counter are combined into the new counter. There are two new functions added to read the counter: - qib_int_counter (for a particular qib_devdata) - qib_sps_ints (for all HCAs) A z_int_counter is added to allow the interrupt detection logic to determine if interrupts have occured since z_int_counter was "reset". Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/infiniband/hw/qib/qib.h10
-rw-r--r--drivers/infiniband/hw/qib/qib_fs.c1
-rw-r--r--drivers/infiniband/hw/qib/qib_iba6120.c7
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7220.c8
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c31
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c36
6 files changed, 59 insertions, 34 deletions
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index 1946101419a3..f044430ed98e 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -868,8 +868,10 @@ struct qib_devdata {
868 /* last buffer for user use */ 868 /* last buffer for user use */
869 u32 lastctxt_piobuf; 869 u32 lastctxt_piobuf;
870 870
871 /* saturating counter of (non-port-specific) device interrupts */ 871 /* reset value */
872 u32 int_counter; 872 u64 z_int_counter;
873 /* percpu intcounter */
874 u64 __percpu *int_counter;
873 875
874 /* pio bufs allocated per ctxt */ 876 /* pio bufs allocated per ctxt */
875 u32 pbufsctxt; 877 u32 pbufsctxt;
@@ -1449,6 +1451,10 @@ void qib_nomsi(struct qib_devdata *);
1449void qib_nomsix(struct qib_devdata *); 1451void qib_nomsix(struct qib_devdata *);
1450void qib_pcie_getcmd(struct qib_devdata *, u16 *, u8 *, u8 *); 1452void qib_pcie_getcmd(struct qib_devdata *, u16 *, u8 *, u8 *);
1451void qib_pcie_reenable(struct qib_devdata *, u16, u8, u8); 1453void qib_pcie_reenable(struct qib_devdata *, u16, u8, u8);
1454/* interrupts for device */
1455u64 qib_int_counter(struct qib_devdata *);
1456/* interrupt for all devices */
1457u64 qib_sps_ints(void);
1452 1458
1453/* 1459/*
1454 * dma_addr wrappers - all 0's invalid for hw 1460 * dma_addr wrappers - all 0's invalid for hw
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
index c61e2a92b3c1..cab610ccd50e 100644
--- a/drivers/infiniband/hw/qib/qib_fs.c
+++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -105,6 +105,7 @@ static int create_file(const char *name, umode_t mode,
105static ssize_t driver_stats_read(struct file *file, char __user *buf, 105static ssize_t driver_stats_read(struct file *file, char __user *buf,
106 size_t count, loff_t *ppos) 106 size_t count, loff_t *ppos)
107{ 107{
108 qib_stats.sps_ints = qib_sps_ints();
108 return simple_read_from_buffer(buf, count, ppos, &qib_stats, 109 return simple_read_from_buffer(buf, count, ppos, &qib_stats,
109 sizeof qib_stats); 110 sizeof qib_stats);
110} 111}
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index 84e593d6007b..b9bea2ebfd4a 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -1634,9 +1634,7 @@ static irqreturn_t qib_6120intr(int irq, void *data)
1634 goto bail; 1634 goto bail;
1635 } 1635 }
1636 1636
1637 qib_stats.sps_ints++; 1637 this_cpu_inc(*dd->int_counter);
1638 if (dd->int_counter != (u32) -1)
1639 dd->int_counter++;
1640 1638
1641 if (unlikely(istat & (~QLOGIC_IB_I_BITSEXTANT | 1639 if (unlikely(istat & (~QLOGIC_IB_I_BITSEXTANT |
1642 QLOGIC_IB_I_GPIO | QLOGIC_IB_I_ERROR))) 1640 QLOGIC_IB_I_GPIO | QLOGIC_IB_I_ERROR)))
@@ -1808,7 +1806,8 @@ static int qib_6120_setup_reset(struct qib_devdata *dd)
1808 * isn't set. 1806 * isn't set.
1809 */ 1807 */
1810 dd->flags &= ~(QIB_INITTED | QIB_PRESENT); 1808 dd->flags &= ~(QIB_INITTED | QIB_PRESENT);
1811 dd->int_counter = 0; /* so we check interrupts work again */ 1809 /* so we check interrupts work again */
1810 dd->z_int_counter = qib_int_counter(dd);
1812 val = dd->control | QLOGIC_IB_C_RESET; 1811 val = dd->control | QLOGIC_IB_C_RESET;
1813 writeq(val, &dd->kregbase[kr_control]); 1812 writeq(val, &dd->kregbase[kr_control]);
1814 mb(); /* prevent compiler re-ordering around actual reset */ 1813 mb(); /* prevent compiler re-ordering around actual reset */
diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c
index 454c2e7668fe..28063d4c225b 100644
--- a/drivers/infiniband/hw/qib/qib_iba7220.c
+++ b/drivers/infiniband/hw/qib/qib_iba7220.c
@@ -1962,10 +1962,7 @@ static irqreturn_t qib_7220intr(int irq, void *data)
1962 goto bail; 1962 goto bail;
1963 } 1963 }
1964 1964
1965 qib_stats.sps_ints++; 1965 this_cpu_inc(*dd->int_counter);
1966 if (dd->int_counter != (u32) -1)
1967 dd->int_counter++;
1968
1969 if (unlikely(istat & (~QLOGIC_IB_I_BITSEXTANT | 1966 if (unlikely(istat & (~QLOGIC_IB_I_BITSEXTANT |
1970 QLOGIC_IB_I_GPIO | QLOGIC_IB_I_ERROR))) 1967 QLOGIC_IB_I_GPIO | QLOGIC_IB_I_ERROR)))
1971 unlikely_7220_intr(dd, istat); 1968 unlikely_7220_intr(dd, istat);
@@ -2120,7 +2117,8 @@ static int qib_setup_7220_reset(struct qib_devdata *dd)
2120 * isn't set. 2117 * isn't set.
2121 */ 2118 */
2122 dd->flags &= ~(QIB_INITTED | QIB_PRESENT); 2119 dd->flags &= ~(QIB_INITTED | QIB_PRESENT);
2123 dd->int_counter = 0; /* so we check interrupts work again */ 2120 /* so we check interrupts work again */
2121 dd->z_int_counter = qib_int_counter(dd);
2124 val = dd->control | QLOGIC_IB_C_RESET; 2122 val = dd->control | QLOGIC_IB_C_RESET;
2125 writeq(val, &dd->kregbase[kr_control]); 2123 writeq(val, &dd->kregbase[kr_control]);
2126 mb(); /* prevent compiler reordering around actual reset */ 2124 mb(); /* prevent compiler reordering around actual reset */
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index d1bd21319d7d..8441579decd9 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -3115,9 +3115,7 @@ static irqreturn_t qib_7322intr(int irq, void *data)
3115 goto bail; 3115 goto bail;
3116 } 3116 }
3117 3117
3118 qib_stats.sps_ints++; 3118 this_cpu_inc(*dd->int_counter);
3119 if (dd->int_counter != (u32) -1)
3120 dd->int_counter++;
3121 3119
3122 /* handle "errors" of various kinds first, device ahead of port */ 3120 /* handle "errors" of various kinds first, device ahead of port */
3123 if (unlikely(istat & (~QIB_I_BITSEXTANT | QIB_I_GPIO | 3121 if (unlikely(istat & (~QIB_I_BITSEXTANT | QIB_I_GPIO |
@@ -3186,9 +3184,7 @@ static irqreturn_t qib_7322pintr(int irq, void *data)
3186 */ 3184 */
3187 return IRQ_HANDLED; 3185 return IRQ_HANDLED;
3188 3186
3189 qib_stats.sps_ints++; 3187 this_cpu_inc(*dd->int_counter);
3190 if (dd->int_counter != (u32) -1)
3191 dd->int_counter++;
3192 3188
3193 /* Clear the interrupt bit we expect to be set. */ 3189 /* Clear the interrupt bit we expect to be set. */
3194 qib_write_kreg(dd, kr_intclear, ((1ULL << QIB_I_RCVAVAIL_LSB) | 3190 qib_write_kreg(dd, kr_intclear, ((1ULL << QIB_I_RCVAVAIL_LSB) |
@@ -3215,9 +3211,7 @@ static irqreturn_t qib_7322bufavail(int irq, void *data)
3215 */ 3211 */
3216 return IRQ_HANDLED; 3212 return IRQ_HANDLED;
3217 3213
3218 qib_stats.sps_ints++; 3214 this_cpu_inc(*dd->int_counter);
3219 if (dd->int_counter != (u32) -1)
3220 dd->int_counter++;
3221 3215
3222 /* Clear the interrupt bit we expect to be set. */ 3216 /* Clear the interrupt bit we expect to be set. */
3223 qib_write_kreg(dd, kr_intclear, QIB_I_SPIOBUFAVAIL); 3217 qib_write_kreg(dd, kr_intclear, QIB_I_SPIOBUFAVAIL);
@@ -3248,9 +3242,7 @@ static irqreturn_t sdma_intr(int irq, void *data)
3248 */ 3242 */
3249 return IRQ_HANDLED; 3243 return IRQ_HANDLED;
3250 3244
3251 qib_stats.sps_ints++; 3245 this_cpu_inc(*dd->int_counter);
3252 if (dd->int_counter != (u32) -1)
3253 dd->int_counter++;
3254 3246
3255 /* Clear the interrupt bit we expect to be set. */ 3247 /* Clear the interrupt bit we expect to be set. */
3256 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? 3248 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
@@ -3277,9 +3269,7 @@ static irqreturn_t sdma_idle_intr(int irq, void *data)
3277 */ 3269 */
3278 return IRQ_HANDLED; 3270 return IRQ_HANDLED;
3279 3271
3280 qib_stats.sps_ints++; 3272 this_cpu_inc(*dd->int_counter);
3281 if (dd->int_counter != (u32) -1)
3282 dd->int_counter++;
3283 3273
3284 /* Clear the interrupt bit we expect to be set. */ 3274 /* Clear the interrupt bit we expect to be set. */
3285 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? 3275 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
@@ -3306,9 +3296,7 @@ static irqreturn_t sdma_progress_intr(int irq, void *data)
3306 */ 3296 */
3307 return IRQ_HANDLED; 3297 return IRQ_HANDLED;
3308 3298
3309 qib_stats.sps_ints++; 3299 this_cpu_inc(*dd->int_counter);
3310 if (dd->int_counter != (u32) -1)
3311 dd->int_counter++;
3312 3300
3313 /* Clear the interrupt bit we expect to be set. */ 3301 /* Clear the interrupt bit we expect to be set. */
3314 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? 3302 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
@@ -3336,9 +3324,7 @@ static irqreturn_t sdma_cleanup_intr(int irq, void *data)
3336 */ 3324 */
3337 return IRQ_HANDLED; 3325 return IRQ_HANDLED;
3338 3326
3339 qib_stats.sps_ints++; 3327 this_cpu_inc(*dd->int_counter);
3340 if (dd->int_counter != (u32) -1)
3341 dd->int_counter++;
3342 3328
3343 /* Clear the interrupt bit we expect to be set. */ 3329 /* Clear the interrupt bit we expect to be set. */
3344 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? 3330 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
@@ -3723,7 +3709,8 @@ static int qib_do_7322_reset(struct qib_devdata *dd)
3723 dd->pport->cpspec->ibsymdelta = 0; 3709 dd->pport->cpspec->ibsymdelta = 0;
3724 dd->pport->cpspec->iblnkerrdelta = 0; 3710 dd->pport->cpspec->iblnkerrdelta = 0;
3725 dd->pport->cpspec->ibmalfdelta = 0; 3711 dd->pport->cpspec->ibmalfdelta = 0;
3726 dd->int_counter = 0; /* so we check interrupts work again */ 3712 /* so we check interrupts work again */
3713 dd->z_int_counter = qib_int_counter(dd);
3727 3714
3728 /* 3715 /*
3729 * Keep chip from being accessed until we are ready. Use 3716 * Keep chip from being accessed until we are ready. Use
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index 76c3e177164d..6d2629990cb3 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -525,6 +525,7 @@ static void enable_chip(struct qib_devdata *dd)
525static void verify_interrupt(unsigned long opaque) 525static void verify_interrupt(unsigned long opaque)
526{ 526{
527 struct qib_devdata *dd = (struct qib_devdata *) opaque; 527 struct qib_devdata *dd = (struct qib_devdata *) opaque;
528 u64 int_counter;
528 529
529 if (!dd) 530 if (!dd)
530 return; /* being torn down */ 531 return; /* being torn down */
@@ -533,7 +534,8 @@ static void verify_interrupt(unsigned long opaque)
533 * If we don't have a lid or any interrupts, let the user know and 534 * If we don't have a lid or any interrupts, let the user know and
534 * don't bother checking again. 535 * don't bother checking again.
535 */ 536 */
536 if (dd->int_counter == 0) { 537 int_counter = qib_int_counter(dd) - dd->z_int_counter;
538 if (int_counter == 0) {
537 if (!dd->f_intr_fallback(dd)) 539 if (!dd->f_intr_fallback(dd))
538 dev_err(&dd->pcidev->dev, 540 dev_err(&dd->pcidev->dev,
539 "No interrupts detected, not usable.\n"); 541 "No interrupts detected, not usable.\n");
@@ -1079,9 +1081,34 @@ void qib_free_devdata(struct qib_devdata *dd)
1079#ifdef CONFIG_DEBUG_FS 1081#ifdef CONFIG_DEBUG_FS
1080 qib_dbg_ibdev_exit(&dd->verbs_dev); 1082 qib_dbg_ibdev_exit(&dd->verbs_dev);
1081#endif 1083#endif
1084 free_percpu(dd->int_counter);
1082 ib_dealloc_device(&dd->verbs_dev.ibdev); 1085 ib_dealloc_device(&dd->verbs_dev.ibdev);
1083} 1086}
1084 1087
1088u64 qib_int_counter(struct qib_devdata *dd)
1089{
1090 int cpu;
1091 u64 int_counter = 0;
1092
1093 for_each_possible_cpu(cpu)
1094 int_counter += *per_cpu_ptr(dd->int_counter, cpu);
1095 return int_counter;
1096}
1097
1098u64 qib_sps_ints(void)
1099{
1100 unsigned long flags;
1101 struct qib_devdata *dd;
1102 u64 sps_ints = 0;
1103
1104 spin_lock_irqsave(&qib_devs_lock, flags);
1105 list_for_each_entry(dd, &qib_dev_list, list) {
1106 sps_ints += qib_int_counter(dd);
1107 }
1108 spin_unlock_irqrestore(&qib_devs_lock, flags);
1109 return sps_ints;
1110}
1111
1085/* 1112/*
1086 * Allocate our primary per-unit data structure. Must be done via verbs 1113 * Allocate our primary per-unit data structure. Must be done via verbs
1087 * allocator, because the verbs cleanup process both does cleanup and 1114 * allocator, because the verbs cleanup process both does cleanup and
@@ -1119,6 +1146,13 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra)
1119 "Could not allocate unit ID: error %d\n", -ret); 1146 "Could not allocate unit ID: error %d\n", -ret);
1120 goto bail; 1147 goto bail;
1121 } 1148 }
1149 dd->int_counter = alloc_percpu(u64);
1150 if (!dd->int_counter) {
1151 ret = -ENOMEM;
1152 qib_early_err(&pdev->dev,
1153 "Could not allocate per-cpu int_counter\n");
1154 goto bail;
1155 }
1122 1156
1123 if (!qib_cpulist_count) { 1157 if (!qib_cpulist_count) {
1124 u32 count = num_online_cpus(); 1158 u32 count = num_online_cpus();