Commit 1ed88dd7 authored by Mike Marciniszyn's avatar Mike Marciniszyn Committed by Roland Dreier

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: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarMike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent f8b6c47a
...@@ -868,8 +868,10 @@ struct qib_devdata { ...@@ -868,8 +868,10 @@ struct qib_devdata {
/* last buffer for user use */ /* last buffer for user use */
u32 lastctxt_piobuf; u32 lastctxt_piobuf;
/* saturating counter of (non-port-specific) device interrupts */ /* reset value */
u32 int_counter; u64 z_int_counter;
/* percpu intcounter */
u64 __percpu *int_counter;
/* pio bufs allocated per ctxt */ /* pio bufs allocated per ctxt */
u32 pbufsctxt; u32 pbufsctxt;
...@@ -1449,6 +1451,10 @@ void qib_nomsi(struct qib_devdata *); ...@@ -1449,6 +1451,10 @@ void qib_nomsi(struct qib_devdata *);
void qib_nomsix(struct qib_devdata *); void qib_nomsix(struct qib_devdata *);
void qib_pcie_getcmd(struct qib_devdata *, u16 *, u8 *, u8 *); void qib_pcie_getcmd(struct qib_devdata *, u16 *, u8 *, u8 *);
void qib_pcie_reenable(struct qib_devdata *, u16, u8, u8); void qib_pcie_reenable(struct qib_devdata *, u16, u8, u8);
/* interrupts for device */
u64 qib_int_counter(struct qib_devdata *);
/* interrupt for all devices */
u64 qib_sps_ints(void);
/* /*
* dma_addr wrappers - all 0's invalid for hw * dma_addr wrappers - all 0's invalid for hw
......
...@@ -105,6 +105,7 @@ static int create_file(const char *name, umode_t mode, ...@@ -105,6 +105,7 @@ static int create_file(const char *name, umode_t mode,
static ssize_t driver_stats_read(struct file *file, char __user *buf, static ssize_t driver_stats_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
qib_stats.sps_ints = qib_sps_ints();
return simple_read_from_buffer(buf, count, ppos, &qib_stats, return simple_read_from_buffer(buf, count, ppos, &qib_stats,
sizeof qib_stats); sizeof qib_stats);
} }
......
...@@ -1634,9 +1634,7 @@ static irqreturn_t qib_6120intr(int irq, void *data) ...@@ -1634,9 +1634,7 @@ static irqreturn_t qib_6120intr(int irq, void *data)
goto bail; goto bail;
} }
qib_stats.sps_ints++; this_cpu_inc(*dd->int_counter);
if (dd->int_counter != (u32) -1)
dd->int_counter++;
if (unlikely(istat & (~QLOGIC_IB_I_BITSEXTANT | if (unlikely(istat & (~QLOGIC_IB_I_BITSEXTANT |
QLOGIC_IB_I_GPIO | QLOGIC_IB_I_ERROR))) QLOGIC_IB_I_GPIO | QLOGIC_IB_I_ERROR)))
...@@ -1808,7 +1806,8 @@ static int qib_6120_setup_reset(struct qib_devdata *dd) ...@@ -1808,7 +1806,8 @@ static int qib_6120_setup_reset(struct qib_devdata *dd)
* isn't set. * isn't set.
*/ */
dd->flags &= ~(QIB_INITTED | QIB_PRESENT); dd->flags &= ~(QIB_INITTED | QIB_PRESENT);
dd->int_counter = 0; /* so we check interrupts work again */ /* so we check interrupts work again */
dd->z_int_counter = qib_int_counter(dd);
val = dd->control | QLOGIC_IB_C_RESET; val = dd->control | QLOGIC_IB_C_RESET;
writeq(val, &dd->kregbase[kr_control]); writeq(val, &dd->kregbase[kr_control]);
mb(); /* prevent compiler re-ordering around actual reset */ mb(); /* prevent compiler re-ordering around actual reset */
......
...@@ -1962,10 +1962,7 @@ static irqreturn_t qib_7220intr(int irq, void *data) ...@@ -1962,10 +1962,7 @@ static irqreturn_t qib_7220intr(int irq, void *data)
goto bail; goto bail;
} }
qib_stats.sps_ints++; this_cpu_inc(*dd->int_counter);
if (dd->int_counter != (u32) -1)
dd->int_counter++;
if (unlikely(istat & (~QLOGIC_IB_I_BITSEXTANT | if (unlikely(istat & (~QLOGIC_IB_I_BITSEXTANT |
QLOGIC_IB_I_GPIO | QLOGIC_IB_I_ERROR))) QLOGIC_IB_I_GPIO | QLOGIC_IB_I_ERROR)))
unlikely_7220_intr(dd, istat); unlikely_7220_intr(dd, istat);
...@@ -2120,7 +2117,8 @@ static int qib_setup_7220_reset(struct qib_devdata *dd) ...@@ -2120,7 +2117,8 @@ static int qib_setup_7220_reset(struct qib_devdata *dd)
* isn't set. * isn't set.
*/ */
dd->flags &= ~(QIB_INITTED | QIB_PRESENT); dd->flags &= ~(QIB_INITTED | QIB_PRESENT);
dd->int_counter = 0; /* so we check interrupts work again */ /* so we check interrupts work again */
dd->z_int_counter = qib_int_counter(dd);
val = dd->control | QLOGIC_IB_C_RESET; val = dd->control | QLOGIC_IB_C_RESET;
writeq(val, &dd->kregbase[kr_control]); writeq(val, &dd->kregbase[kr_control]);
mb(); /* prevent compiler reordering around actual reset */ mb(); /* prevent compiler reordering around actual reset */
......
...@@ -3115,9 +3115,7 @@ static irqreturn_t qib_7322intr(int irq, void *data) ...@@ -3115,9 +3115,7 @@ static irqreturn_t qib_7322intr(int irq, void *data)
goto bail; goto bail;
} }
qib_stats.sps_ints++; this_cpu_inc(*dd->int_counter);
if (dd->int_counter != (u32) -1)
dd->int_counter++;
/* handle "errors" of various kinds first, device ahead of port */ /* handle "errors" of various kinds first, device ahead of port */
if (unlikely(istat & (~QIB_I_BITSEXTANT | QIB_I_GPIO | if (unlikely(istat & (~QIB_I_BITSEXTANT | QIB_I_GPIO |
...@@ -3186,9 +3184,7 @@ static irqreturn_t qib_7322pintr(int irq, void *data) ...@@ -3186,9 +3184,7 @@ static irqreturn_t qib_7322pintr(int irq, void *data)
*/ */
return IRQ_HANDLED; return IRQ_HANDLED;
qib_stats.sps_ints++; this_cpu_inc(*dd->int_counter);
if (dd->int_counter != (u32) -1)
dd->int_counter++;
/* Clear the interrupt bit we expect to be set. */ /* Clear the interrupt bit we expect to be set. */
qib_write_kreg(dd, kr_intclear, ((1ULL << QIB_I_RCVAVAIL_LSB) | 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,9 +3211,7 @@ static irqreturn_t qib_7322bufavail(int irq, void *data)
*/ */
return IRQ_HANDLED; return IRQ_HANDLED;
qib_stats.sps_ints++; this_cpu_inc(*dd->int_counter);
if (dd->int_counter != (u32) -1)
dd->int_counter++;
/* Clear the interrupt bit we expect to be set. */ /* Clear the interrupt bit we expect to be set. */
qib_write_kreg(dd, kr_intclear, QIB_I_SPIOBUFAVAIL); qib_write_kreg(dd, kr_intclear, QIB_I_SPIOBUFAVAIL);
...@@ -3248,9 +3242,7 @@ static irqreturn_t sdma_intr(int irq, void *data) ...@@ -3248,9 +3242,7 @@ static irqreturn_t sdma_intr(int irq, void *data)
*/ */
return IRQ_HANDLED; return IRQ_HANDLED;
qib_stats.sps_ints++; this_cpu_inc(*dd->int_counter);
if (dd->int_counter != (u32) -1)
dd->int_counter++;
/* Clear the interrupt bit we expect to be set. */ /* Clear the interrupt bit we expect to be set. */
qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
...@@ -3277,9 +3269,7 @@ static irqreturn_t sdma_idle_intr(int irq, void *data) ...@@ -3277,9 +3269,7 @@ static irqreturn_t sdma_idle_intr(int irq, void *data)
*/ */
return IRQ_HANDLED; return IRQ_HANDLED;
qib_stats.sps_ints++; this_cpu_inc(*dd->int_counter);
if (dd->int_counter != (u32) -1)
dd->int_counter++;
/* Clear the interrupt bit we expect to be set. */ /* Clear the interrupt bit we expect to be set. */
qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
...@@ -3306,9 +3296,7 @@ static irqreturn_t sdma_progress_intr(int irq, void *data) ...@@ -3306,9 +3296,7 @@ static irqreturn_t sdma_progress_intr(int irq, void *data)
*/ */
return IRQ_HANDLED; return IRQ_HANDLED;
qib_stats.sps_ints++; this_cpu_inc(*dd->int_counter);
if (dd->int_counter != (u32) -1)
dd->int_counter++;
/* Clear the interrupt bit we expect to be set. */ /* Clear the interrupt bit we expect to be set. */
qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
...@@ -3336,9 +3324,7 @@ static irqreturn_t sdma_cleanup_intr(int irq, void *data) ...@@ -3336,9 +3324,7 @@ static irqreturn_t sdma_cleanup_intr(int irq, void *data)
*/ */
return IRQ_HANDLED; return IRQ_HANDLED;
qib_stats.sps_ints++; this_cpu_inc(*dd->int_counter);
if (dd->int_counter != (u32) -1)
dd->int_counter++;
/* Clear the interrupt bit we expect to be set. */ /* Clear the interrupt bit we expect to be set. */
qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
...@@ -3723,7 +3709,8 @@ static int qib_do_7322_reset(struct qib_devdata *dd) ...@@ -3723,7 +3709,8 @@ static int qib_do_7322_reset(struct qib_devdata *dd)
dd->pport->cpspec->ibsymdelta = 0; dd->pport->cpspec->ibsymdelta = 0;
dd->pport->cpspec->iblnkerrdelta = 0; dd->pport->cpspec->iblnkerrdelta = 0;
dd->pport->cpspec->ibmalfdelta = 0; dd->pport->cpspec->ibmalfdelta = 0;
dd->int_counter = 0; /* so we check interrupts work again */ /* so we check interrupts work again */
dd->z_int_counter = qib_int_counter(dd);
/* /*
* Keep chip from being accessed until we are ready. Use * Keep chip from being accessed until we are ready. Use
......
...@@ -525,6 +525,7 @@ static void enable_chip(struct qib_devdata *dd) ...@@ -525,6 +525,7 @@ static void enable_chip(struct qib_devdata *dd)
static void verify_interrupt(unsigned long opaque) static void verify_interrupt(unsigned long opaque)
{ {
struct qib_devdata *dd = (struct qib_devdata *) opaque; struct qib_devdata *dd = (struct qib_devdata *) opaque;
u64 int_counter;
if (!dd) if (!dd)
return; /* being torn down */ return; /* being torn down */
...@@ -533,7 +534,8 @@ static void verify_interrupt(unsigned long opaque) ...@@ -533,7 +534,8 @@ static void verify_interrupt(unsigned long opaque)
* If we don't have a lid or any interrupts, let the user know and * If we don't have a lid or any interrupts, let the user know and
* don't bother checking again. * don't bother checking again.
*/ */
if (dd->int_counter == 0) { int_counter = qib_int_counter(dd) - dd->z_int_counter;
if (int_counter == 0) {
if (!dd->f_intr_fallback(dd)) if (!dd->f_intr_fallback(dd))
dev_err(&dd->pcidev->dev, dev_err(&dd->pcidev->dev,
"No interrupts detected, not usable.\n"); "No interrupts detected, not usable.\n");
...@@ -1079,9 +1081,34 @@ void qib_free_devdata(struct qib_devdata *dd) ...@@ -1079,9 +1081,34 @@ void qib_free_devdata(struct qib_devdata *dd)
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
qib_dbg_ibdev_exit(&dd->verbs_dev); qib_dbg_ibdev_exit(&dd->verbs_dev);
#endif #endif
free_percpu(dd->int_counter);
ib_dealloc_device(&dd->verbs_dev.ibdev); ib_dealloc_device(&dd->verbs_dev.ibdev);
} }
u64 qib_int_counter(struct qib_devdata *dd)
{
int cpu;
u64 int_counter = 0;
for_each_possible_cpu(cpu)
int_counter += *per_cpu_ptr(dd->int_counter, cpu);
return int_counter;
}
u64 qib_sps_ints(void)
{
unsigned long flags;
struct qib_devdata *dd;
u64 sps_ints = 0;
spin_lock_irqsave(&qib_devs_lock, flags);
list_for_each_entry(dd, &qib_dev_list, list) {
sps_ints += qib_int_counter(dd);
}
spin_unlock_irqrestore(&qib_devs_lock, flags);
return sps_ints;
}
/* /*
* Allocate our primary per-unit data structure. Must be done via verbs * Allocate our primary per-unit data structure. Must be done via verbs
* allocator, because the verbs cleanup process both does cleanup and * 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,6 +1146,13 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra)
"Could not allocate unit ID: error %d\n", -ret); "Could not allocate unit ID: error %d\n", -ret);
goto bail; goto bail;
} }
dd->int_counter = alloc_percpu(u64);
if (!dd->int_counter) {
ret = -ENOMEM;
qib_early_err(&pdev->dev,
"Could not allocate per-cpu int_counter\n");
goto bail;
}
if (!qib_cpulist_count) { if (!qib_cpulist_count) {
u32 count = num_online_cpus(); u32 count = num_online_cpus();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment