Skip to content

Commit fa619a7

Browse files
Hal RosenstockLinus Torvalds
authored andcommitted
[PATCH] IB: Add RMPP implementation
Add RMPP implementation. Signed-off-by: Sean Hefty <[email protected]> Signed-off-by: Hal Rosenstock <[email protected]> Cc: Roland Dreier <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent d2082ee commit fa619a7

File tree

5 files changed

+966
-50
lines changed

5 files changed

+966
-50
lines changed

drivers/infiniband/core/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ obj-$(CONFIG_INFINIBAND_USER_VERBS) += ib_uverbs.o
66
ib_core-y := packer.o ud_header.o verbs.o sysfs.o \
77
device.o fmr_pool.o cache.o
88

9-
ib_mad-y := mad.o smi.o agent.o
9+
ib_mad-y := mad.o smi.o agent.o mad_rmpp.o
1010

1111
ib_sa-y := sa_query.o
1212

drivers/infiniband/core/mad.c

Lines changed: 117 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/*
22
* Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
3+
* Copyright (c) 2005 Intel Corporation. All rights reserved.
4+
* Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved.
35
*
46
* This software is available to you under a choice of one of two
57
* licenses. You may choose to be licensed under the terms of the GNU
@@ -29,12 +31,12 @@
2931
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3032
* SOFTWARE.
3133
*
32-
* $Id: mad.c 1389 2004-12-27 22:56:47Z roland $
34+
* $Id: mad.c 2817 2005-07-07 11:29:26Z halr $
3335
*/
34-
3536
#include <linux/dma-mapping.h>
3637

3738
#include "mad_priv.h"
39+
#include "mad_rmpp.h"
3840
#include "smi.h"
3941
#include "agent.h"
4042

@@ -45,6 +47,7 @@ MODULE_AUTHOR("Sean Hefty");
4547

4648

4749
kmem_cache_t *ib_mad_cache;
50+
4851
static struct list_head ib_mad_port_list;
4952
static u32 ib_mad_client_id = 0;
5053

@@ -62,8 +65,6 @@ static struct ib_mad_agent_private *find_mad_agent(
6265
static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
6366
struct ib_mad_private *mad);
6467
static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv);
65-
static void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
66-
struct ib_mad_send_wc *mad_send_wc);
6768
static void timeout_sends(void *data);
6869
static void local_completions(void *data);
6970
static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req,
@@ -195,8 +196,8 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
195196
if (qpn == -1)
196197
goto error1;
197198

198-
if (rmpp_version)
199-
goto error1; /* XXX: until RMPP implemented */
199+
if (rmpp_version && rmpp_version != IB_MGMT_RMPP_VERSION)
200+
goto error1;
200201

201202
/* Validate MAD registration request if supplied */
202203
if (mad_reg_req) {
@@ -281,7 +282,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
281282
/* Now, fill in the various structures */
282283
mad_agent_priv->qp_info = &port_priv->qp_info[qpn];
283284
mad_agent_priv->reg_req = reg_req;
284-
mad_agent_priv->rmpp_version = rmpp_version;
285+
mad_agent_priv->agent.rmpp_version = rmpp_version;
285286
mad_agent_priv->agent.device = device;
286287
mad_agent_priv->agent.recv_handler = recv_handler;
287288
mad_agent_priv->agent.send_handler = send_handler;
@@ -341,6 +342,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
341342
INIT_LIST_HEAD(&mad_agent_priv->send_list);
342343
INIT_LIST_HEAD(&mad_agent_priv->wait_list);
343344
INIT_LIST_HEAD(&mad_agent_priv->done_list);
345+
INIT_LIST_HEAD(&mad_agent_priv->rmpp_list);
344346
INIT_WORK(&mad_agent_priv->timed_work, timeout_sends, mad_agent_priv);
345347
INIT_LIST_HEAD(&mad_agent_priv->local_list);
346348
INIT_WORK(&mad_agent_priv->local_work, local_completions,
@@ -502,6 +504,7 @@ static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
502504
spin_unlock_irqrestore(&port_priv->reg_lock, flags);
503505

504506
flush_workqueue(port_priv->wq);
507+
ib_cancel_rmpp_recvs(mad_agent_priv);
505508

506509
atomic_dec(&mad_agent_priv->refcount);
507510
wait_event(mad_agent_priv->wait,
@@ -786,12 +789,15 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
786789
int buf_size;
787790
void *buf;
788791

789-
if (rmpp_active)
790-
return ERR_PTR(-EINVAL); /* until RMPP implemented */
791792
mad_agent_priv = container_of(mad_agent,
792793
struct ib_mad_agent_private, agent);
793794
buf_size = get_buf_length(hdr_len, data_len);
794795

796+
if ((!mad_agent->rmpp_version &&
797+
(rmpp_active || buf_size > sizeof(struct ib_mad))) ||
798+
(!rmpp_active && buf_size > sizeof(struct ib_mad)))
799+
return ERR_PTR(-EINVAL);
800+
795801
buf = kmalloc(sizeof *send_buf + buf_size, gfp_mask);
796802
if (!buf)
797803
return ERR_PTR(-ENOMEM);
@@ -816,6 +822,18 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
816822
send_buf->send_wr.wr.ud.remote_qpn = remote_qpn;
817823
send_buf->send_wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
818824
send_buf->send_wr.wr.ud.pkey_index = pkey_index;
825+
826+
if (rmpp_active) {
827+
struct ib_rmpp_mad *rmpp_mad;
828+
rmpp_mad = (struct ib_rmpp_mad *)send_buf->mad;
829+
rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(hdr_len -
830+
offsetof(struct ib_rmpp_mad, data) + data_len);
831+
rmpp_mad->rmpp_hdr.rmpp_version = mad_agent->rmpp_version;
832+
rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_DATA;
833+
ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr,
834+
IB_MGMT_RMPP_FLAG_ACTIVE);
835+
}
836+
819837
send_buf->mad_agent = mad_agent;
820838
atomic_inc(&mad_agent_priv->refcount);
821839
return send_buf;
@@ -839,7 +857,7 @@ void ib_free_send_mad(struct ib_mad_send_buf *send_buf)
839857
}
840858
EXPORT_SYMBOL(ib_free_send_mad);
841859

842-
static int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
860+
int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
843861
{
844862
struct ib_mad_qp_info *qp_info;
845863
struct ib_send_wr *bad_send_wr;
@@ -940,13 +958,13 @@ int ib_post_send_mad(struct ib_mad_agent *mad_agent,
940958
ret = -ENOMEM;
941959
goto error2;
942960
}
961+
memset(mad_send_wr, 0, sizeof *mad_send_wr);
943962

944963
mad_send_wr->send_wr = *send_wr;
945964
mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list;
946965
memcpy(mad_send_wr->sg_list, send_wr->sg_list,
947966
sizeof *send_wr->sg_list * send_wr->num_sge);
948-
mad_send_wr->wr_id = mad_send_wr->send_wr.wr_id;
949-
mad_send_wr->send_wr.next = NULL;
967+
mad_send_wr->wr_id = send_wr->wr_id;
950968
mad_send_wr->tid = send_wr->wr.ud.mad_hdr->tid;
951969
mad_send_wr->mad_agent_priv = mad_agent_priv;
952970
/* Timeout will be updated after send completes */
@@ -964,8 +982,13 @@ int ib_post_send_mad(struct ib_mad_agent *mad_agent,
964982
&mad_agent_priv->send_list);
965983
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
966984

967-
ret = ib_send_mad(mad_send_wr);
968-
if (ret) {
985+
if (mad_agent_priv->agent.rmpp_version) {
986+
ret = ib_send_rmpp_mad(mad_send_wr);
987+
if (ret >= 0 && ret != IB_RMPP_RESULT_CONSUMED)
988+
ret = ib_send_mad(mad_send_wr);
989+
} else
990+
ret = ib_send_mad(mad_send_wr);
991+
if (ret < 0) {
969992
/* Fail send request */
970993
spin_lock_irqsave(&mad_agent_priv->lock, flags);
971994
list_del(&mad_send_wr->agent_list);
@@ -991,31 +1014,25 @@ EXPORT_SYMBOL(ib_post_send_mad);
9911014
*/
9921015
void ib_free_recv_mad(struct ib_mad_recv_wc *mad_recv_wc)
9931016
{
994-
struct ib_mad_recv_buf *entry;
1017+
struct ib_mad_recv_buf *mad_recv_buf, *temp_recv_buf;
9951018
struct ib_mad_private_header *mad_priv_hdr;
9961019
struct ib_mad_private *priv;
1020+
struct list_head free_list;
9971021

998-
mad_priv_hdr = container_of(mad_recv_wc,
999-
struct ib_mad_private_header,
1000-
recv_wc);
1001-
priv = container_of(mad_priv_hdr, struct ib_mad_private, header);
1022+
INIT_LIST_HEAD(&free_list);
1023+
list_splice_init(&mad_recv_wc->rmpp_list, &free_list);
10021024

1003-
/*
1004-
* Walk receive buffer list associated with this WC
1005-
* No need to remove them from list of receive buffers
1006-
*/
1007-
list_for_each_entry(entry, &mad_recv_wc->recv_buf.list, list) {
1008-
/* Free previous receive buffer */
1009-
kmem_cache_free(ib_mad_cache, priv);
1025+
list_for_each_entry_safe(mad_recv_buf, temp_recv_buf,
1026+
&free_list, list) {
1027+
mad_recv_wc = container_of(mad_recv_buf, struct ib_mad_recv_wc,
1028+
recv_buf);
10101029
mad_priv_hdr = container_of(mad_recv_wc,
10111030
struct ib_mad_private_header,
10121031
recv_wc);
10131032
priv = container_of(mad_priv_hdr, struct ib_mad_private,
10141033
header);
1034+
kmem_cache_free(ib_mad_cache, priv);
10151035
}
1016-
1017-
/* Free last buffer */
1018-
kmem_cache_free(ib_mad_cache, priv);
10191036
}
10201037
EXPORT_SYMBOL(ib_free_recv_mad);
10211038

@@ -1524,9 +1541,20 @@ static int validate_mad(struct ib_mad *mad, u32 qp_num)
15241541
return valid;
15251542
}
15261543

1527-
static struct ib_mad_send_wr_private*
1528-
find_send_req(struct ib_mad_agent_private *mad_agent_priv,
1529-
u64 tid)
1544+
static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv,
1545+
struct ib_mad_hdr *mad_hdr)
1546+
{
1547+
struct ib_rmpp_mad *rmpp_mad;
1548+
1549+
rmpp_mad = (struct ib_rmpp_mad *)mad_hdr;
1550+
return !mad_agent_priv->agent.rmpp_version ||
1551+
!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
1552+
IB_MGMT_RMPP_FLAG_ACTIVE) ||
1553+
(rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA);
1554+
}
1555+
1556+
struct ib_mad_send_wr_private*
1557+
ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, u64 tid)
15301558
{
15311559
struct ib_mad_send_wr_private *mad_send_wr;
15321560

@@ -1542,7 +1570,9 @@ find_send_req(struct ib_mad_agent_private *mad_agent_priv,
15421570
*/
15431571
list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
15441572
agent_list) {
1545-
if (mad_send_wr->tid == tid && mad_send_wr->timeout) {
1573+
if (is_data_mad(mad_agent_priv,
1574+
mad_send_wr->send_wr.wr.ud.mad_hdr) &&
1575+
mad_send_wr->tid == tid && mad_send_wr->timeout) {
15461576
/* Verify request has not been canceled */
15471577
return (mad_send_wr->status == IB_WC_SUCCESS) ?
15481578
mad_send_wr : NULL;
@@ -1551,7 +1581,7 @@ find_send_req(struct ib_mad_agent_private *mad_agent_priv,
15511581
return NULL;
15521582
}
15531583

1554-
static void ib_mark_req_done(struct ib_mad_send_wr_private *mad_send_wr)
1584+
void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr)
15551585
{
15561586
mad_send_wr->timeout = 0;
15571587
if (mad_send_wr->refcount == 1) {
@@ -1569,20 +1599,31 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
15691599
unsigned long flags;
15701600
u64 tid;
15711601

1572-
INIT_LIST_HEAD(&mad_recv_wc->recv_buf.list);
1602+
INIT_LIST_HEAD(&mad_recv_wc->rmpp_list);
1603+
list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
1604+
if (mad_agent_priv->agent.rmpp_version) {
1605+
mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv,
1606+
mad_recv_wc);
1607+
if (!mad_recv_wc) {
1608+
if (atomic_dec_and_test(&mad_agent_priv->refcount))
1609+
wake_up(&mad_agent_priv->wait);
1610+
return;
1611+
}
1612+
}
1613+
15731614
/* Complete corresponding request */
15741615
if (response_mad(mad_recv_wc->recv_buf.mad)) {
15751616
tid = mad_recv_wc->recv_buf.mad->mad_hdr.tid;
15761617
spin_lock_irqsave(&mad_agent_priv->lock, flags);
1577-
mad_send_wr = find_send_req(mad_agent_priv, tid);
1618+
mad_send_wr = ib_find_send_mad(mad_agent_priv, tid);
15781619
if (!mad_send_wr) {
15791620
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
15801621
ib_free_recv_mad(mad_recv_wc);
15811622
if (atomic_dec_and_test(&mad_agent_priv->refcount))
15821623
wake_up(&mad_agent_priv->wait);
15831624
return;
15841625
}
1585-
ib_mark_req_done(mad_send_wr);
1626+
ib_mark_mad_done(mad_send_wr);
15861627
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
15871628

15881629
/* Defined behavior is to complete response before request */
@@ -1787,14 +1828,22 @@ void ib_reset_mad_timeout(struct ib_mad_send_wr_private *mad_send_wr,
17871828
/*
17881829
* Process a send work completion
17891830
*/
1790-
static void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
1791-
struct ib_mad_send_wc *mad_send_wc)
1831+
void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
1832+
struct ib_mad_send_wc *mad_send_wc)
17921833
{
17931834
struct ib_mad_agent_private *mad_agent_priv;
17941835
unsigned long flags;
1836+
int ret;
17951837

17961838
mad_agent_priv = mad_send_wr->mad_agent_priv;
17971839
spin_lock_irqsave(&mad_agent_priv->lock, flags);
1840+
if (mad_agent_priv->agent.rmpp_version) {
1841+
ret = ib_process_rmpp_send_wc(mad_send_wr, mad_send_wc);
1842+
if (ret == IB_RMPP_RESULT_CONSUMED)
1843+
goto done;
1844+
} else
1845+
ret = IB_RMPP_RESULT_UNHANDLED;
1846+
17981847
if (mad_send_wc->status != IB_WC_SUCCESS &&
17991848
mad_send_wr->status == IB_WC_SUCCESS) {
18001849
mad_send_wr->status = mad_send_wc->status;
@@ -1806,8 +1855,7 @@ static void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
18061855
mad_send_wr->status == IB_WC_SUCCESS) {
18071856
wait_for_response(mad_send_wr);
18081857
}
1809-
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
1810-
return;
1858+
goto done;
18111859
}
18121860

18131861
/* Remove send from MAD agent and notify client of completion */
@@ -1817,14 +1865,18 @@ static void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
18171865

18181866
if (mad_send_wr->status != IB_WC_SUCCESS )
18191867
mad_send_wc->status = mad_send_wr->status;
1820-
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
1821-
mad_send_wc);
1868+
if (ret != IB_RMPP_RESULT_INTERNAL)
1869+
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
1870+
mad_send_wc);
18221871

18231872
/* Release reference on agent taken when sending */
18241873
if (atomic_dec_and_test(&mad_agent_priv->refcount))
18251874
wake_up(&mad_agent_priv->wait);
18261875

18271876
kfree(mad_send_wr);
1877+
return;
1878+
done:
1879+
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
18281880
}
18291881

18301882
static void ib_mad_send_done_handler(struct ib_mad_port_private *port_priv,
@@ -2036,7 +2088,9 @@ find_send_by_wr_id(struct ib_mad_agent_private *mad_agent_priv, u64 wr_id)
20362088

20372089
list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
20382090
agent_list) {
2039-
if (mad_send_wr->wr_id == wr_id)
2091+
if (is_data_mad(mad_agent_priv,
2092+
mad_send_wr->send_wr.wr.ud.mad_hdr) &&
2093+
mad_send_wr->wr_id == wr_id)
20402094
return mad_send_wr;
20412095
}
20422096
return NULL;
@@ -2118,7 +2172,9 @@ static void local_completions(void *data)
21182172
local->mad_priv->header.recv_wc.wc = &wc;
21192173
local->mad_priv->header.recv_wc.mad_len =
21202174
sizeof(struct ib_mad);
2121-
INIT_LIST_HEAD(&local->mad_priv->header.recv_wc.recv_buf.list);
2175+
INIT_LIST_HEAD(&local->mad_priv->header.recv_wc.rmpp_list);
2176+
list_add(&local->mad_priv->header.recv_wc.recv_buf.list,
2177+
&local->mad_priv->header.recv_wc.rmpp_list);
21222178
local->mad_priv->header.recv_wc.recv_buf.grh = NULL;
21232179
local->mad_priv->header.recv_wc.recv_buf.mad =
21242180
&local->mad_priv->mad.mad;
@@ -2166,7 +2222,21 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr)
21662222
mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_wr.
21672223
wr.ud.timeout_ms);
21682224

2169-
ret = ib_send_mad(mad_send_wr);
2225+
if (mad_send_wr->mad_agent_priv->agent.rmpp_version) {
2226+
ret = ib_retry_rmpp(mad_send_wr);
2227+
switch (ret) {
2228+
case IB_RMPP_RESULT_UNHANDLED:
2229+
ret = ib_send_mad(mad_send_wr);
2230+
break;
2231+
case IB_RMPP_RESULT_CONSUMED:
2232+
ret = 0;
2233+
break;
2234+
default:
2235+
ret = -ECOMM;
2236+
break;
2237+
}
2238+
} else
2239+
ret = ib_send_mad(mad_send_wr);
21702240

21712241
if (!ret) {
21722242
mad_send_wr->refcount++;
@@ -2724,3 +2794,4 @@ static void __exit ib_mad_cleanup_module(void)
27242794

27252795
module_init(ib_mad_init_module);
27262796
module_exit(ib_mad_cleanup_module);
2797+

0 commit comments

Comments
 (0)