diff options
Diffstat (limited to 'drivers/infiniband/hw/qib/qib_tx.c')
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_tx.c | 26 | 
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/infiniband/hw/qib/qib_tx.c b/drivers/infiniband/hw/qib/qib_tx.c index 7f36454c225..31d3561400a 100644 --- a/drivers/infiniband/hw/qib/qib_tx.c +++ b/drivers/infiniband/hw/qib/qib_tx.c @@ -36,6 +36,7 @@  #include <linux/delay.h>  #include <linux/netdevice.h>  #include <linux/vmalloc.h> +#include <linux/moduleparam.h>  #include "qib.h" @@ -294,6 +295,7 @@ u32 __iomem *qib_getsendbuf_range(struct qib_devdata *dd, u32 *pbufnum,  	nbufs = last - first + 1; /* number in range to check */  	if (dd->upd_pio_shadow) { +update_shadow:  		/*  		 * Minor optimization.  If we had no buffers on last call,  		 * start out by doing the update; continue and do scan even @@ -303,37 +305,39 @@ u32 __iomem *qib_getsendbuf_range(struct qib_devdata *dd, u32 *pbufnum,  		updated++;  	}  	i = first; -rescan:  	/*  	 * While test_and_set_bit() is atomic, we do that and then the  	 * change_bit(), and the pair is not.  See if this is the cause  	 * of the remaining armlaunch errors.  	 */  	spin_lock_irqsave(&dd->pioavail_lock, flags); +	if (dd->last_pio >= first && dd->last_pio <= last) +		i = dd->last_pio + 1; +	if (!first) +		/* adjust to min possible  */ +		nbufs = last - dd->min_kernel_pio + 1;  	for (j = 0; j < nbufs; j++, i++) {  		if (i > last) -			i = first; +			i = !first ? dd->min_kernel_pio : first;  		if (__test_and_set_bit((2 * i) + 1, shadow))  			continue;  		/* flip generation bit */  		__change_bit(2 * i, shadow);  		/* remember that the buffer can be written to now */  		__set_bit(i, dd->pio_writing); +		if (!first && first != last) /* first == last on VL15, avoid */ +			dd->last_pio = i;  		break;  	}  	spin_unlock_irqrestore(&dd->pioavail_lock, flags);  	if (j == nbufs) { -		if (!updated) { +		if (!updated)  			/*  			 * First time through; shadow exhausted, but may be  			 * buffers available, try an update and then rescan.  			 */ -			update_send_bufs(dd); -			updated++; -			i = first; -			goto rescan; -		} +			goto update_shadow;  		no_send_bufs(dd);  		buf = NULL;  	} else { @@ -421,14 +425,20 @@ void qib_chg_pioavailkernel(struct qib_devdata *dd, unsigned start,  				__clear_bit(QLOGIC_IB_SENDPIOAVAIL_CHECK_SHIFT  					    + start, dd->pioavailshadow);  			__set_bit(start, dd->pioavailkernel); +			if ((start >> 1) < dd->min_kernel_pio) +				dd->min_kernel_pio = start >> 1;  		} else {  			__set_bit(start + QLOGIC_IB_SENDPIOAVAIL_BUSY_SHIFT,  				  dd->pioavailshadow);  			__clear_bit(start, dd->pioavailkernel); +			if ((start >> 1) > dd->min_kernel_pio) +				dd->min_kernel_pio = start >> 1;  		}  		start += 2;  	} +	if (dd->min_kernel_pio > 0 && dd->last_pio < dd->min_kernel_pio - 1) +		dd->last_pio = dd->min_kernel_pio - 1;  	spin_unlock_irqrestore(&dd->pioavail_lock, flags);  	dd->f_txchk_change(dd, ostart, len, avail, rcd);  | 
