PageRenderTime 53ms CodeModel.GetById 13ms app.highlight 34ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/infiniband/ulp/ipoib/ipoib_verbs.c

https://bitbucket.org/evzijst/gittest
C | 260 lines | 178 code | 41 blank | 41 comment | 23 complexity | 5fbdfbdaa25a64282a55bdad2d5d6226 MD5 | raw file
  1/*
  2 * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  3 *
  4 * This software is available to you under a choice of one of two
  5 * licenses.  You may choose to be licensed under the terms of the GNU
  6 * General Public License (GPL) Version 2, available from the file
  7 * COPYING in the main directory of this source tree, or the
  8 * OpenIB.org BSD license below:
  9 *
 10 *     Redistribution and use in source and binary forms, with or
 11 *     without modification, are permitted provided that the following
 12 *     conditions are met:
 13 *
 14 *      - Redistributions of source code must retain the above
 15 *        copyright notice, this list of conditions and the following
 16 *        disclaimer.
 17 *
 18 *      - Redistributions in binary form must reproduce the above
 19 *        copyright notice, this list of conditions and the following
 20 *        disclaimer in the documentation and/or other materials
 21 *        provided with the distribution.
 22 *
 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 30 * SOFTWARE.
 31 *
 32 * $Id: ipoib_verbs.c 1349 2004-12-16 21:09:43Z roland $
 33 */
 34
 35#include <ib_cache.h>
 36
 37#include "ipoib.h"
 38
 39int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
 40{
 41	struct ipoib_dev_priv *priv = netdev_priv(dev);
 42	struct ib_qp_attr *qp_attr;
 43	int attr_mask;
 44	int ret;
 45	u16 pkey_index;
 46
 47	ret = -ENOMEM;
 48	qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL);
 49	if (!qp_attr)
 50		goto out;
 51
 52	if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) {
 53		clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
 54		ret = -ENXIO;
 55		goto out;
 56	}
 57	set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
 58
 59	/* set correct QKey for QP */
 60	qp_attr->qkey = priv->qkey;
 61	attr_mask = IB_QP_QKEY;
 62	ret = ib_modify_qp(priv->qp, qp_attr, attr_mask);
 63	if (ret) {
 64		ipoib_warn(priv, "failed to modify QP, ret = %d\n", ret);
 65		goto out;
 66	}
 67
 68	/* attach QP to multicast group */
 69	down(&priv->mcast_mutex);
 70	ret = ib_attach_mcast(priv->qp, mgid, mlid);
 71	up(&priv->mcast_mutex);
 72	if (ret)
 73		ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret);
 74
 75out:
 76	kfree(qp_attr);
 77	return ret;
 78}
 79
 80int ipoib_mcast_detach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
 81{
 82	struct ipoib_dev_priv *priv = netdev_priv(dev);
 83	int ret;
 84
 85	down(&priv->mcast_mutex);
 86	ret = ib_detach_mcast(priv->qp, mgid, mlid);
 87	up(&priv->mcast_mutex);
 88	if (ret)
 89		ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret);
 90
 91	return ret;
 92}
 93
 94int ipoib_qp_create(struct net_device *dev)
 95{
 96	struct ipoib_dev_priv *priv = netdev_priv(dev);
 97	int ret;
 98	u16 pkey_index;
 99	struct ib_qp_attr qp_attr;
100	int attr_mask;
101
102	/*
103	 * Search through the port P_Key table for the requested pkey value.
104	 * The port has to be assigned to the respective IB partition in
105	 * advance.
106	 */
107	ret = ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index);
108	if (ret) {
109		clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
110		return ret;
111	}
112	set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
113
114	qp_attr.qp_state = IB_QPS_INIT;
115	qp_attr.qkey = 0;
116	qp_attr.port_num = priv->port;
117	qp_attr.pkey_index = pkey_index;
118	attr_mask =
119	    IB_QP_QKEY |
120	    IB_QP_PORT |
121	    IB_QP_PKEY_INDEX |
122	    IB_QP_STATE;
123	ret = ib_modify_qp(priv->qp, &qp_attr, attr_mask);
124	if (ret) {
125		ipoib_warn(priv, "failed to modify QP to init, ret = %d\n", ret);
126		goto out_fail;
127	}
128
129	qp_attr.qp_state = IB_QPS_RTR;
130	/* Can't set this in a INIT->RTR transition */
131	attr_mask &= ~IB_QP_PORT;
132	ret = ib_modify_qp(priv->qp, &qp_attr, attr_mask);
133	if (ret) {
134		ipoib_warn(priv, "failed to modify QP to RTR, ret = %d\n", ret);
135		goto out_fail;
136	}
137
138	qp_attr.qp_state = IB_QPS_RTS;
139	qp_attr.sq_psn = 0;
140	attr_mask |= IB_QP_SQ_PSN;
141	attr_mask &= ~IB_QP_PKEY_INDEX;
142	ret = ib_modify_qp(priv->qp, &qp_attr, attr_mask);
143	if (ret) {
144		ipoib_warn(priv, "failed to modify QP to RTS, ret = %d\n", ret);
145		goto out_fail;
146	}
147
148	return 0;
149
150out_fail:
151	ib_destroy_qp(priv->qp);
152	priv->qp = NULL;
153
154	return -EINVAL;
155}
156
157int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
158{
159	struct ipoib_dev_priv *priv = netdev_priv(dev);
160	struct ib_qp_init_attr init_attr = {
161		.cap = {
162			.max_send_wr  = IPOIB_TX_RING_SIZE,
163			.max_recv_wr  = IPOIB_RX_RING_SIZE,
164			.max_send_sge = 1,
165			.max_recv_sge = 1
166		},
167		.sq_sig_type = IB_SIGNAL_ALL_WR,
168		.qp_type     = IB_QPT_UD
169	};
170
171	priv->pd = ib_alloc_pd(priv->ca);
172	if (IS_ERR(priv->pd)) {
173		printk(KERN_WARNING "%s: failed to allocate PD\n", ca->name);
174		return -ENODEV;
175	}
176
177	priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev,
178				IPOIB_TX_RING_SIZE + IPOIB_RX_RING_SIZE + 1);
179	if (IS_ERR(priv->cq)) {
180		printk(KERN_WARNING "%s: failed to create CQ\n", ca->name);
181		goto out_free_pd;
182	}
183
184	if (ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP))
185		goto out_free_cq;
186
187	priv->mr = ib_get_dma_mr(priv->pd, IB_ACCESS_LOCAL_WRITE);
188	if (IS_ERR(priv->mr)) {
189		printk(KERN_WARNING "%s: ib_get_dma_mr failed\n", ca->name);
190		goto out_free_cq;
191	}
192
193	init_attr.send_cq = priv->cq;
194	init_attr.recv_cq = priv->cq,
195
196	priv->qp = ib_create_qp(priv->pd, &init_attr);
197	if (IS_ERR(priv->qp)) {
198		printk(KERN_WARNING "%s: failed to create QP\n", ca->name);
199		goto out_free_mr;
200	}
201
202	priv->dev->dev_addr[1] = (priv->qp->qp_num >> 16) & 0xff;
203	priv->dev->dev_addr[2] = (priv->qp->qp_num >>  8) & 0xff;
204	priv->dev->dev_addr[3] = (priv->qp->qp_num      ) & 0xff;
205
206	priv->tx_sge.lkey 	= priv->mr->lkey;
207
208	priv->tx_wr.opcode 	= IB_WR_SEND;
209	priv->tx_wr.sg_list 	= &priv->tx_sge;
210	priv->tx_wr.num_sge 	= 1;
211	priv->tx_wr.send_flags 	= IB_SEND_SIGNALED;
212
213	return 0;
214
215out_free_mr:
216	ib_dereg_mr(priv->mr);
217
218out_free_cq:
219	ib_destroy_cq(priv->cq);
220
221out_free_pd:
222	ib_dealloc_pd(priv->pd);
223	return -ENODEV;
224}
225
226void ipoib_transport_dev_cleanup(struct net_device *dev)
227{
228	struct ipoib_dev_priv *priv = netdev_priv(dev);
229
230	if (priv->qp) {
231		if (ib_destroy_qp(priv->qp))
232			ipoib_warn(priv, "ib_qp_destroy failed\n");
233
234		priv->qp = NULL;
235		clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
236	}
237
238	if (ib_dereg_mr(priv->mr))
239		ipoib_warn(priv, "ib_dereg_mr failed\n");
240
241	if (ib_destroy_cq(priv->cq))
242		ipoib_warn(priv, "ib_cq_destroy failed\n");
243
244	if (ib_dealloc_pd(priv->pd))
245		ipoib_warn(priv, "ib_dealloc_pd failed\n");
246}
247
248void ipoib_event(struct ib_event_handler *handler,
249		 struct ib_event *record)
250{
251	struct ipoib_dev_priv *priv =
252		container_of(handler, struct ipoib_dev_priv, event_handler);
253
254	if (record->event == IB_EVENT_PORT_ACTIVE ||
255	    record->event == IB_EVENT_LID_CHANGE  ||
256	    record->event == IB_EVENT_SM_CHANGE) {
257		ipoib_dbg(priv, "Port active event\n");
258		schedule_work(&priv->flush_task);
259	}
260}