diff options
author | Mike Marciniszyn <mike.marciniszyn@intel.com> | 2014-03-07 08:40:49 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-03-17 19:16:51 -0400 |
commit | 1ed88dd7d0b361e677b2690f573e5c274bb25c87 (patch) | |
tree | d78f5aa8f9983b92b7db9f876817199b136c3a2b | |
parent | f8b6c47a44c063062317646683a73371c24c69ee (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.h | 10 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/qib_fs.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/qib_iba6120.c | 7 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/qib_iba7220.c | 8 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/qib_iba7322.c | 31 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/qib_init.c | 36 |
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 *); | |||
1449 | void qib_nomsix(struct qib_devdata *); | 1451 | void qib_nomsix(struct qib_devdata *); |
1450 | void qib_pcie_getcmd(struct qib_devdata *, u16 *, u8 *, u8 *); | 1452 | void qib_pcie_getcmd(struct qib_devdata *, u16 *, u8 *, u8 *); |
1451 | void qib_pcie_reenable(struct qib_devdata *, u16, u8, u8); | 1453 | void qib_pcie_reenable(struct qib_devdata *, u16, u8, u8); |
1454 | /* interrupts for device */ | ||
1455 | u64 qib_int_counter(struct qib_devdata *); | ||
1456 | /* interrupt for all devices */ | ||
1457 | u64 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, | |||
105 | static ssize_t driver_stats_read(struct file *file, char __user *buf, | 105 | static 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) | |||
525 | static void verify_interrupt(unsigned long opaque) | 525 | static 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 | ||
1088 | u64 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 | |||
1098 | u64 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(); |