diff options
Diffstat (limited to 'drivers/infiniband/hw/cxgb4/cm.c')
| -rw-r--r-- | drivers/infiniband/hw/cxgb4/cm.c | 88 | 
1 files changed, 58 insertions, 30 deletions
| diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index f660cd04ec2f..77f769d9227d 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -1325,6 +1325,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)  	unsigned int stid = GET_POPEN_TID(ntohl(req->tos_stid));  	struct tid_info *t = dev->rdev.lldi.tids;  	unsigned int hwtid = GET_TID(req); +	struct neighbour *neigh;  	struct dst_entry *dst;  	struct l2t_entry *l2t;  	struct rtable *rt; @@ -1357,11 +1358,11 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)  		goto reject;  	}  	dst = &rt->dst; -	if (dst->neighbour->dev->flags & IFF_LOOPBACK) { +	neigh = dst_get_neighbour(dst); +	if (neigh->dev->flags & IFF_LOOPBACK) {  		pdev = ip_dev_find(&init_net, peer_ip);  		BUG_ON(!pdev); -		l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour, -				    pdev, 0); +		l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, pdev, 0);  		mtu = pdev->mtu;  		tx_chan = cxgb4_port_chan(pdev);  		smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1; @@ -1372,17 +1373,16 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)  		rss_qid = dev->rdev.lldi.rxq_ids[cxgb4_port_idx(pdev) * step];  		dev_put(pdev);  	} else { -		l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour, -					dst->neighbour->dev, 0); +		l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, neigh->dev, 0);  		mtu = dst_mtu(dst); -		tx_chan = cxgb4_port_chan(dst->neighbour->dev); -		smac_idx = (cxgb4_port_viid(dst->neighbour->dev) & 0x7F) << 1; +		tx_chan = cxgb4_port_chan(neigh->dev); +		smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;  		step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan; -		txq_idx = cxgb4_port_idx(dst->neighbour->dev) * step; -		ctrlq_idx = cxgb4_port_idx(dst->neighbour->dev); +		txq_idx = cxgb4_port_idx(neigh->dev) * step; +		ctrlq_idx = cxgb4_port_idx(neigh->dev);  		step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;  		rss_qid = dev->rdev.lldi.rxq_ids[ -			  cxgb4_port_idx(dst->neighbour->dev) * step]; +			  cxgb4_port_idx(neigh->dev) * step];  	}  	if (!l2t) {  		printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", @@ -1463,9 +1463,9 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)  	struct c4iw_qp_attributes attrs;  	int disconnect = 1;  	int release = 0; -	int abort = 0;  	struct tid_info *t = dev->rdev.lldi.tids;  	unsigned int tid = GET_TID(hdr); +	int ret;  	ep = lookup_tid(t, tid);  	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); @@ -1501,10 +1501,12 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)  		start_ep_timer(ep);  		__state_set(&ep->com, CLOSING);  		attrs.next_state = C4IW_QP_STATE_CLOSING; -		abort = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, +		ret = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,  				       C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); -		peer_close_upcall(ep); -		disconnect = 1; +		if (ret != -ECONNRESET) { +			peer_close_upcall(ep); +			disconnect = 1; +		}  		break;  	case ABORTING:  		disconnect = 0; @@ -1845,6 +1847,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	struct c4iw_ep *ep;  	struct rtable *rt;  	struct net_device *pdev; +	struct neighbour *neigh;  	int step;  	if ((conn_param->ord > c4iw_max_read_depth) || @@ -1906,14 +1909,15 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	}  	ep->dst = &rt->dst; +	neigh = dst_get_neighbour(ep->dst); +  	/* get a l2t entry */ -	if (ep->dst->neighbour->dev->flags & IFF_LOOPBACK) { +	if (neigh->dev->flags & IFF_LOOPBACK) {  		PDBG("%s LOOPBACK\n", __func__);  		pdev = ip_dev_find(&init_net,  				   cm_id->remote_addr.sin_addr.s_addr);  		ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t, -					ep->dst->neighbour, -					pdev, 0); +					neigh, pdev, 0);  		ep->mtu = pdev->mtu;  		ep->tx_chan = cxgb4_port_chan(pdev);  		ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1; @@ -1928,20 +1932,18 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  		dev_put(pdev);  	} else {  		ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t, -					ep->dst->neighbour, -					ep->dst->neighbour->dev, 0); +					neigh, neigh->dev, 0);  		ep->mtu = dst_mtu(ep->dst); -		ep->tx_chan = cxgb4_port_chan(ep->dst->neighbour->dev); -		ep->smac_idx = (cxgb4_port_viid(ep->dst->neighbour->dev) & -				0x7F) << 1; +		ep->tx_chan = cxgb4_port_chan(neigh->dev); +		ep->smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;  		step = ep->com.dev->rdev.lldi.ntxq /  		       ep->com.dev->rdev.lldi.nchan; -		ep->txq_idx = cxgb4_port_idx(ep->dst->neighbour->dev) * step; -		ep->ctrlq_idx = cxgb4_port_idx(ep->dst->neighbour->dev); +		ep->txq_idx = cxgb4_port_idx(neigh->dev) * step; +		ep->ctrlq_idx = cxgb4_port_idx(neigh->dev);  		step = ep->com.dev->rdev.lldi.nrxq /  		       ep->com.dev->rdev.lldi.nchan;  		ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[ -			      cxgb4_port_idx(ep->dst->neighbour->dev) * step]; +			      cxgb4_port_idx(neigh->dev) * step];  	}  	if (!ep->l2t) {  		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); @@ -2109,15 +2111,16 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)  		break;  	} -	mutex_unlock(&ep->com.mutex);  	if (close) { -		if (abrupt) -			ret = abort_connection(ep, NULL, gfp); -		else +		if (abrupt) { +			close_complete_upcall(ep); +			ret = send_abort(ep, NULL, gfp); +		} else  			ret = send_halfclose(ep, gfp);  		if (ret)  			fatal = 1;  	} +	mutex_unlock(&ep->com.mutex);  	if (fatal)  		release_ep_resources(ep);  	return ret; @@ -2301,6 +2304,31 @@ static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)  	return 0;  } +static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb) +{ +	struct cpl_abort_req_rss *req = cplhdr(skb); +	struct c4iw_ep *ep; +	struct tid_info *t = dev->rdev.lldi.tids; +	unsigned int tid = GET_TID(req); + +	ep = lookup_tid(t, tid); +	if (is_neg_adv_abort(req->status)) { +		PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep, +		     ep->hwtid); +		kfree_skb(skb); +		return 0; +	} +	PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid, +	     ep->com.state); + +	/* +	 * Wake up any threads in rdma_init() or rdma_fini(). +	 */ +	c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); +	sched(dev, skb); +	return 0; +} +  /*   * Most upcalls from the T4 Core go to sched() to   * schedule the processing on a work queue. @@ -2317,7 +2345,7 @@ c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS] = {  	[CPL_PASS_ESTABLISH] = sched,  	[CPL_PEER_CLOSE] = sched,  	[CPL_CLOSE_CON_RPL] = sched, -	[CPL_ABORT_REQ_RSS] = sched, +	[CPL_ABORT_REQ_RSS] = peer_abort_intr,  	[CPL_RDMA_TERMINATE] = sched,  	[CPL_FW4_ACK] = sched,  	[CPL_SET_TCB_RPL] = set_tcb_rpl, | 
