diff options
Diffstat (limited to 'drivers/infiniband/hw/qib/qib_tx.c')
-rw-r--r-- | drivers/infiniband/hw/qib/qib_tx.c | 25 |
1 files changed, 17 insertions, 8 deletions
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) { |
298 | update_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; |
307 | rescan: | ||
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); |