aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorMike Marciniszyn <mike.marciniszyn@intel.com>2012-05-07 14:02:42 -0400
committerRoland Dreier <roland@purestorage.com>2012-05-14 15:37:03 -0400
commitbb77a077232e78476d7bc39c080f9e6685cbfd3c (patch)
treed6b07dec8a7a7aa8fbbd752c2fd4b3b0c36088f9 /drivers/infiniband
parentcca195a168ac062967fd1fa75c75546167b1e213 (diff)
IB/qib: Optimize pio ack buffer allocation
This patch optimizes pio buffer allocation in the kernel. For qib, kernel pio buffers are used for sending acks. The code to allocate the buffer would always start at 0 until it found a buffer. This means that an average of 64 comparisions were done on each allocate, since the busy bit won't be cleared until the bits are refreshed when buffers are exhausted. This patch adds two new fields in the devdata struct, last_pio and min_kernel_pio. last_pio is the last buffer that was allocated. min_kernel_pio is the lowest potential available buffer. min_kernel_pio is modifed as contexts are allocated and deallocted. Reviewed-by: Ramkrishna Vepa <ramkrishna.vepa@intel.com> Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/qib/qib.h9
-rw-r--r--drivers/infiniband/hw/qib/qib_iba6120.c1
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7220.c1
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c1
-rw-r--r--drivers/infiniband/hw/qib/qib_tx.c25
5 files changed, 28 insertions, 9 deletions
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index 6b811e3e8bd1..2d638877c4af 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -873,7 +873,14 @@ struct qib_devdata {
873 * pio_writing. 873 * pio_writing.
874 */ 874 */
875 spinlock_t pioavail_lock; 875 spinlock_t pioavail_lock;
876 876 /*
877 * index of last buffer to optimize search for next
878 */
879 u32 last_pio;
880 /*
881 * min kernel pio buffer to optimize search
882 */
883 u32 min_kernel_pio;
877 /* 884 /*
878 * Shadow copies of registers; size indicates read access size. 885 * Shadow copies of registers; size indicates read access size.
879 * Most of them are readonly, but some are write-only register, 886 * Most of them are readonly, but some are write-only register,
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index d0c64d514813..4d352b90750a 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -3132,6 +3132,7 @@ static void get_6120_chip_params(struct qib_devdata *dd)
3132 val = qib_read_kreg64(dd, kr_sendpiobufcnt); 3132 val = qib_read_kreg64(dd, kr_sendpiobufcnt);
3133 dd->piobcnt2k = val & ~0U; 3133 dd->piobcnt2k = val & ~0U;
3134 dd->piobcnt4k = val >> 32; 3134 dd->piobcnt4k = val >> 32;
3135 dd->last_pio = dd->piobcnt4k + dd->piobcnt2k - 1;
3135 /* these may be adjusted in init_chip_wc_pat() */ 3136 /* these may be adjusted in init_chip_wc_pat() */
3136 dd->pio2kbase = (u32 __iomem *) 3137 dd->pio2kbase = (u32 __iomem *)
3137 (((char __iomem *)dd->kregbase) + dd->pio2k_bufbase); 3138 (((char __iomem *)dd->kregbase) + dd->pio2k_bufbase);
diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c
index 3c722f79d6f6..86a0ba7ca0c2 100644
--- a/drivers/infiniband/hw/qib/qib_iba7220.c
+++ b/drivers/infiniband/hw/qib/qib_iba7220.c
@@ -4157,6 +4157,7 @@ static int qib_init_7220_variables(struct qib_devdata *dd)
4157 dd->cspec->sdmabufcnt; 4157 dd->cspec->sdmabufcnt;
4158 dd->lastctxt_piobuf = dd->cspec->lastbuf_for_pio - sbufs; 4158 dd->lastctxt_piobuf = dd->cspec->lastbuf_for_pio - sbufs;
4159 dd->cspec->lastbuf_for_pio--; /* range is <= , not < */ 4159 dd->cspec->lastbuf_for_pio--; /* range is <= , not < */
4160 dd->last_pio = dd->cspec->lastbuf_for_pio;
4160 dd->pbufsctxt = dd->lastctxt_piobuf / 4161 dd->pbufsctxt = dd->lastctxt_piobuf /
4161 (dd->cfgctxts - dd->first_user_ctxt); 4162 (dd->cfgctxts - dd->first_user_ctxt);
4162 4163
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 060b96064469..e7b9ad34fe2e 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -6379,6 +6379,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
6379 dd->cspec->sdmabufcnt; 6379 dd->cspec->sdmabufcnt;
6380 dd->lastctxt_piobuf = dd->cspec->lastbuf_for_pio - sbufs; 6380 dd->lastctxt_piobuf = dd->cspec->lastbuf_for_pio - sbufs;
6381 dd->cspec->lastbuf_for_pio--; /* range is <= , not < */ 6381 dd->cspec->lastbuf_for_pio--; /* range is <= , not < */
6382 dd->last_pio = dd->cspec->lastbuf_for_pio;
6382 dd->pbufsctxt = (dd->cfgctxts > dd->first_user_ctxt) ? 6383 dd->pbufsctxt = (dd->cfgctxts > dd->first_user_ctxt) ?
6383 dd->lastctxt_piobuf / (dd->cfgctxts - dd->first_user_ctxt) : 0; 6384 dd->lastctxt_piobuf / (dd->cfgctxts - dd->first_user_ctxt) : 0;
6384 6385
diff --git a/drivers/infiniband/hw/qib/qib_tx.c b/drivers/infiniband/hw/qib/qib_tx.c
index 1bf626c40172..31d3561400a4 100644
--- a/drivers/infiniband/hw/qib/qib_tx.c
+++ b/drivers/infiniband/hw/qib/qib_tx.c
@@ -295,6 +295,7 @@ u32 __iomem *qib_getsendbuf_range(struct qib_devdata *dd, u32 *pbufnum,
295 295
296 nbufs = last - first + 1; /* number in range to check */ 296 nbufs = last - first + 1; /* number in range to check */
297 if (dd->upd_pio_shadow) { 297 if (dd->upd_pio_shadow) {
298update_shadow:
298 /* 299 /*
299 * Minor optimization. If we had no buffers on last call, 300 * Minor optimization. If we had no buffers on last call,
300 * start out by doing the update; continue and do scan even 301 * start out by doing the update; continue and do scan even
@@ -304,37 +305,39 @@ u32 __iomem *qib_getsendbuf_range(struct qib_devdata *dd, u32 *pbufnum,
304 updated++; 305 updated++;
305 } 306 }
306 i = first; 307 i = first;
307rescan:
308 /* 308 /*
309 * While test_and_set_bit() is atomic, we do that and then the 309 * While test_and_set_bit() is atomic, we do that and then the
310 * change_bit(), and the pair is not. See if this is the cause 310 * change_bit(), and the pair is not. See if this is the cause
311 * of the remaining armlaunch errors. 311 * of the remaining armlaunch errors.
312 */ 312 */
313 spin_lock_irqsave(&dd->pioavail_lock, flags); 313 spin_lock_irqsave(&dd->pioavail_lock, flags);
314 if (dd->last_pio >= first && dd->last_pio <= last)
315 i = dd->last_pio + 1;
316 if (!first)
317 /* adjust to min possible */
318 nbufs = last - dd->min_kernel_pio + 1;
314 for (j = 0; j < nbufs; j++, i++) { 319 for (j = 0; j < nbufs; j++, i++) {
315 if (i > last) 320 if (i > last)
316 i = first; 321 i = !first ? dd->min_kernel_pio : first;
317 if (__test_and_set_bit((2 * i) + 1, shadow)) 322 if (__test_and_set_bit((2 * i) + 1, shadow))
318 continue; 323 continue;
319 /* flip generation bit */ 324 /* flip generation bit */
320 __change_bit(2 * i, shadow); 325 __change_bit(2 * i, shadow);
321 /* remember that the buffer can be written to now */ 326 /* remember that the buffer can be written to now */
322 __set_bit(i, dd->pio_writing); 327 __set_bit(i, dd->pio_writing);
328 if (!first && first != last) /* first == last on VL15, avoid */
329 dd->last_pio = i;
323 break; 330 break;
324 } 331 }
325 spin_unlock_irqrestore(&dd->pioavail_lock, flags); 332 spin_unlock_irqrestore(&dd->pioavail_lock, flags);
326 333
327 if (j == nbufs) { 334 if (j == nbufs) {
328 if (!updated) { 335 if (!updated)
329 /* 336 /*
330 * First time through; shadow exhausted, but may be 337 * First time through; shadow exhausted, but may be
331 * buffers available, try an update and then rescan. 338 * buffers available, try an update and then rescan.
332 */ 339 */
333 update_send_bufs(dd); 340 goto update_shadow;
334 updated++;
335 i = first;
336 goto rescan;
337 }
338 no_send_bufs(dd); 341 no_send_bufs(dd);
339 buf = NULL; 342 buf = NULL;
340 } else { 343 } else {
@@ -422,14 +425,20 @@ void qib_chg_pioavailkernel(struct qib_devdata *dd, unsigned start,
422 __clear_bit(QLOGIC_IB_SENDPIOAVAIL_CHECK_SHIFT 425 __clear_bit(QLOGIC_IB_SENDPIOAVAIL_CHECK_SHIFT
423 + start, dd->pioavailshadow); 426 + start, dd->pioavailshadow);
424 __set_bit(start, dd->pioavailkernel); 427 __set_bit(start, dd->pioavailkernel);
428 if ((start >> 1) < dd->min_kernel_pio)
429 dd->min_kernel_pio = start >> 1;
425 } else { 430 } else {
426 __set_bit(start + QLOGIC_IB_SENDPIOAVAIL_BUSY_SHIFT, 431 __set_bit(start + QLOGIC_IB_SENDPIOAVAIL_BUSY_SHIFT,
427 dd->pioavailshadow); 432 dd->pioavailshadow);
428 __clear_bit(start, dd->pioavailkernel); 433 __clear_bit(start, dd->pioavailkernel);
434 if ((start >> 1) > dd->min_kernel_pio)
435 dd->min_kernel_pio = start >> 1;
429 } 436 }
430 start += 2; 437 start += 2;
431 } 438 }
432 439
440 if (dd->min_kernel_pio > 0 && dd->last_pio < dd->min_kernel_pio - 1)
441 dd->last_pio = dd->min_kernel_pio - 1;
433 spin_unlock_irqrestore(&dd->pioavail_lock, flags); 442 spin_unlock_irqrestore(&dd->pioavail_lock, flags);
434 443
435 dd->f_txchk_change(dd, ostart, len, avail, rcd); 444 dd->f_txchk_change(dd, ostart, len, avail, rcd);