diff options
Diffstat (limited to 'drivers/infiniband/hw/ipath')
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_diag.c | 68 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_dma.c | 43 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_intr.c | 4 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_mr.c | 39 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_qp.c | 2 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_sdma.c | 4 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_user_sdma.c | 7 | 
7 files changed, 66 insertions, 101 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c index 714293b7851..45802e97332 100644 --- a/drivers/infiniband/hw/ipath/ipath_diag.c +++ b/drivers/infiniband/hw/ipath/ipath_diag.c @@ -326,7 +326,7 @@ static ssize_t ipath_diagpkt_write(struct file *fp,  				   size_t count, loff_t *off)  {  	u32 __iomem *piobuf; -	u32 plen, clen, pbufn; +	u32 plen, pbufn, maxlen_reserve;  	struct ipath_diag_pkt odp;  	struct ipath_diag_xpkt dp;  	u32 *tmpbuf = NULL; @@ -335,42 +335,24 @@ static ssize_t ipath_diagpkt_write(struct file *fp,  	u64 val;  	u32 l_state, lt_state; /* LinkState, LinkTrainingState */ -	if (count < sizeof(odp)) { -		ret = -EINVAL; -		goto bail; -	}  	if (count == sizeof(dp)) {  		if (copy_from_user(&dp, data, sizeof(dp))) {  			ret = -EFAULT;  			goto bail;  		} -	} else if (copy_from_user(&odp, data, sizeof(odp))) { -		ret = -EFAULT; -		goto bail; -	} - -	/* -	 * Due to padding/alignment issues (lessened with new struct) -	 * the old and new structs are the same length. We need to -	 * disambiguate them, which we can do because odp.len has never -	 * been less than the total of LRH+BTH+DETH so far, while -	 * dp.unit (same offset) unit is unlikely to get that high. -	 * Similarly, dp.data, the pointer to user at the same offset -	 * as odp.unit, is almost certainly at least one (512byte)page -	 * "above" NULL. The if-block below can be omitted if compatibility -	 * between a new driver and older diagnostic code is unimportant. -	 * compatibility the other direction (new diags, old driver) is -	 * handled in the diagnostic code, with a warning. -	 */ -	if (dp.unit >= 20 && dp.data < 512) { -		/* very probable version mismatch. Fix it up */ -		memcpy(&odp, &dp, sizeof(odp)); -		/* We got a legacy dp, copy elements to dp */ +	} else if (count == sizeof(odp)) { +		if (copy_from_user(&odp, data, sizeof(odp))) { +			ret = -EFAULT; +			goto bail; +		} +		dp.len = odp.len;  		dp.unit = odp.unit;  		dp.data = odp.data; -		dp.len = odp.len; -		dp.pbc_wd = 0; /* Indicate we need to compute PBC wd */ +		dp.pbc_wd = 0; +	} else { +		ret = -EINVAL; +		goto bail;  	}  	/* send count must be an exact number of dwords */ @@ -379,7 +361,7 @@ static ssize_t ipath_diagpkt_write(struct file *fp,  		goto bail;  	} -	clen = dp.len >> 2; +	plen = dp.len >> 2;  	dd = ipath_lookup(dp.unit);  	if (!dd || !(dd->ipath_flags & IPATH_PRESENT) || @@ -422,16 +404,22 @@ static ssize_t ipath_diagpkt_write(struct file *fp,  		goto bail;  	} -	/* need total length before first word written */ -	/* +1 word is for the qword padding */ -	plen = sizeof(u32) + dp.len; - -	if ((plen + 4) > dd->ipath_ibmaxlen) { +	/* +	 * need total length before first word written, plus 2 Dwords. One Dword +	 * is for padding so we get the full user data when not aligned on +	 * a word boundary. The other Dword is to make sure we have room for the +	 * ICRC which gets tacked on later. +	 */ +	maxlen_reserve = 2 * sizeof(u32); +	if (dp.len > dd->ipath_ibmaxlen - maxlen_reserve) {  		ipath_dbg("Pkt len 0x%x > ibmaxlen %x\n", -			  plen - 4, dd->ipath_ibmaxlen); +			  dp.len, dd->ipath_ibmaxlen);  		ret = -EINVAL; -		goto bail;	/* before writing pbc */ +		goto bail;  	} + +	plen = sizeof(u32) + dp.len; +  	tmpbuf = vmalloc(plen);  	if (!tmpbuf) {  		dev_info(&dd->pcidev->dev, "Unable to allocate tmp buffer, " @@ -473,11 +461,11 @@ static ssize_t ipath_diagpkt_write(struct file *fp,  	 */  	if (dd->ipath_flags & IPATH_PIO_FLUSH_WC) {  		ipath_flush_wc(); -		__iowrite32_copy(piobuf + 2, tmpbuf, clen - 1); +		__iowrite32_copy(piobuf + 2, tmpbuf, plen - 1);  		ipath_flush_wc(); -		__raw_writel(tmpbuf[clen - 1], piobuf + clen + 1); +		__raw_writel(tmpbuf[plen - 1], piobuf + plen + 1);  	} else -		__iowrite32_copy(piobuf + 2, tmpbuf, clen); +		__iowrite32_copy(piobuf + 2, tmpbuf, plen);  	ipath_flush_wc(); diff --git a/drivers/infiniband/hw/ipath/ipath_dma.c b/drivers/infiniband/hw/ipath/ipath_dma.c index 644c2c74e05..123a8c05353 100644 --- a/drivers/infiniband/hw/ipath/ipath_dma.c +++ b/drivers/infiniband/hw/ipath/ipath_dma.c @@ -115,6 +115,10 @@ static int ipath_map_sg(struct ib_device *dev, struct scatterlist *sgl,  			ret = 0;  			break;  		} +		sg->dma_address = addr + sg->offset; +#ifdef CONFIG_NEED_SG_DMA_LENGTH +		sg->dma_length = sg->length; +#endif  	}  	return ret;  } @@ -126,21 +130,6 @@ static void ipath_unmap_sg(struct ib_device *dev,  	BUG_ON(!valid_dma_direction(direction));  } -static u64 ipath_sg_dma_address(struct ib_device *dev, struct scatterlist *sg) -{ -	u64 addr = (u64) page_address(sg_page(sg)); - -	if (addr) -		addr += sg->offset; -	return addr; -} - -static unsigned int ipath_sg_dma_len(struct ib_device *dev, -				     struct scatterlist *sg) -{ -	return sg->length; -} -  static void ipath_sync_single_for_cpu(struct ib_device *dev,  				      u64 addr,  				      size_t size, @@ -176,17 +165,15 @@ static void ipath_dma_free_coherent(struct ib_device *dev, size_t size,  }  struct ib_dma_mapping_ops ipath_dma_mapping_ops = { -	ipath_mapping_error, -	ipath_dma_map_single, -	ipath_dma_unmap_single, -	ipath_dma_map_page, -	ipath_dma_unmap_page, -	ipath_map_sg, -	ipath_unmap_sg, -	ipath_sg_dma_address, -	ipath_sg_dma_len, -	ipath_sync_single_for_cpu, -	ipath_sync_single_for_device, -	ipath_dma_alloc_coherent, -	ipath_dma_free_coherent +	.mapping_error = ipath_mapping_error, +	.map_single = ipath_dma_map_single, +	.unmap_single = ipath_dma_unmap_single, +	.map_page = ipath_dma_map_page, +	.unmap_page = ipath_dma_unmap_page, +	.map_sg = ipath_map_sg, +	.unmap_sg = ipath_unmap_sg, +	.sync_single_for_cpu = ipath_sync_single_for_cpu, +	.sync_single_for_device = ipath_sync_single_for_device, +	.alloc_coherent = ipath_dma_alloc_coherent, +	.free_coherent = ipath_dma_free_coherent  }; diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index 26dfbc8ee0f..01ba792791a 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c @@ -70,7 +70,7 @@ void ipath_disarm_senderrbufs(struct ipath_devdata *dd)  	if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) {  		int i;  		if (ipath_debug & (__IPATH_PKTDBG|__IPATH_DBG) && -			dd->ipath_lastcancel > jiffies) { +			time_after(dd->ipath_lastcancel, jiffies)) {  			__IPATH_DBG_WHICH(__IPATH_PKTDBG|__IPATH_DBG,  					  "SendbufErrs %lx %lx", sbuf[0],  					  sbuf[1]); @@ -755,7 +755,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)  	/* likely due to cancel; so suppress message unless verbose */  	if ((errs & (INFINIPATH_E_SPKTLEN | INFINIPATH_E_SPIOARMLAUNCH)) && -		dd->ipath_lastcancel > jiffies) { +		time_after(dd->ipath_lastcancel, jiffies)) {  		/* armlaunch takes precedence; it often causes both. */  		ipath_cdbg(VERBOSE,  			"Suppressed %s error (%llx) after sendbuf cancel\n", diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c b/drivers/infiniband/hw/ipath/ipath_mr.c index e346d3890a0..5e61e9bff69 100644 --- a/drivers/infiniband/hw/ipath/ipath_mr.c +++ b/drivers/infiniband/hw/ipath/ipath_mr.c @@ -188,8 +188,8 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,  {  	struct ipath_mr *mr;  	struct ib_umem *umem; -	struct ib_umem_chunk *chunk; -	int n, m, i; +	int n, m, entry; +	struct scatterlist *sg;  	struct ib_mr *ret;  	if (length == 0) { @@ -202,10 +202,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,  	if (IS_ERR(umem))  		return (void *) umem; -	n = 0; -	list_for_each_entry(chunk, &umem->chunk_list, list) -		n += chunk->nents; - +	n = umem->nmap;  	mr = alloc_mr(n, &to_idev(pd->device)->lk_table);  	if (!mr) {  		ret = ERR_PTR(-ENOMEM); @@ -224,22 +221,20 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,  	m = 0;  	n = 0; -	list_for_each_entry(chunk, &umem->chunk_list, list) { -		for (i = 0; i < chunk->nents; i++) { -			void *vaddr; - -			vaddr = page_address(sg_page(&chunk->page_list[i])); -			if (!vaddr) { -				ret = ERR_PTR(-EINVAL); -				goto bail; -			} -			mr->mr.map[m]->segs[n].vaddr = vaddr; -			mr->mr.map[m]->segs[n].length = umem->page_size; -			n++; -			if (n == IPATH_SEGSZ) { -				m++; -				n = 0; -			} +	for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) { +		void *vaddr; + +		vaddr = page_address(sg_page(sg)); +		if (!vaddr) { +			ret = ERR_PTR(-EINVAL); +			goto bail; +		} +		mr->mr.map[m]->segs[n].vaddr = vaddr; +		mr->mr.map[m]->segs[n].length = umem->page_size; +		n++; +		if (n == IPATH_SEGSZ) { +			m++; +			n = 0;  		}  	}  	ret = &mr->ibmr; diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index 0857a9c3cd3..face87602dc 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c @@ -463,7 +463,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,  	new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;  	if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, -				attr_mask)) +				attr_mask, IB_LINK_LAYER_UNSPECIFIED))  		goto inval;  	if (attr_mask & IB_QP_AV) { diff --git a/drivers/infiniband/hw/ipath/ipath_sdma.c b/drivers/infiniband/hw/ipath/ipath_sdma.c index 98ac18ec977..17a517766ad 100644 --- a/drivers/infiniband/hw/ipath/ipath_sdma.c +++ b/drivers/infiniband/hw/ipath/ipath_sdma.c @@ -247,7 +247,7 @@ static void sdma_abort_task(unsigned long opaque)  	/* ipath_sdma_abort() is done, waiting for interrupt */  	if (status == IPATH_SDMA_ABORT_DISARMED) { -		if (jiffies < dd->ipath_sdma_abort_intr_timeout) +		if (time_before(jiffies, dd->ipath_sdma_abort_intr_timeout))  			goto resched_noprint;  		/* give up, intr got lost somewhere */  		ipath_dbg("give up waiting for SDMADISABLED intr\n"); @@ -341,7 +341,7 @@ resched:  	 * JAG - this is bad to just have default be a loop without  	 * state change  	 */ -	if (jiffies > dd->ipath_sdma_abort_jiffies) { +	if (time_after(jiffies, dd->ipath_sdma_abort_jiffies)) {  		ipath_dbg("looping with status 0x%08lx\n",  			  dd->ipath_sdma_status);  		dd->ipath_sdma_abort_jiffies = jiffies + 5 * HZ; diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.c b/drivers/infiniband/hw/ipath/ipath_user_sdma.c index f5cb13b2144..cc04b7ba348 100644 --- a/drivers/infiniband/hw/ipath/ipath_user_sdma.c +++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.c @@ -280,9 +280,7 @@ static int ipath_user_sdma_pin_pages(const struct ipath_devdata *dd,  	int j;  	int ret; -	ret = get_user_pages(current, current->mm, addr, -			     npages, 0, 1, pages, NULL); - +	ret = get_user_pages_fast(addr, npages, 0, pages);  	if (ret != npages) {  		int i; @@ -811,10 +809,7 @@ int ipath_user_sdma_writev(struct ipath_devdata *dd,  	while (dim) {  		const int mxp = 8; -		down_write(¤t->mm->mmap_sem);  		ret = ipath_user_sdma_queue_pkts(dd, pq, &list, iov, dim, mxp); -		up_write(¤t->mm->mmap_sem); -  		if (ret <= 0)  			goto done_unlock;  		else {  | 
