aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/infiniband/user_mad.txt14
-rw-r--r--drivers/infiniband/core/user_mad.c102
-rw-r--r--include/rdma/ib_user_mad.h48
3 files changed, 135 insertions, 29 deletions
diff --git a/Documentation/infiniband/user_mad.txt b/Documentation/infiniband/user_mad.txt
index 8ec54b974b67..744687dd195b 100644
--- a/Documentation/infiniband/user_mad.txt
+++ b/Documentation/infiniband/user_mad.txt
@@ -99,6 +99,20 @@ Transaction IDs
99 request/response pairs. The upper 32 bits are reserved for use by 99 request/response pairs. The upper 32 bits are reserved for use by
100 the kernel and will be overwritten before a MAD is sent. 100 the kernel and will be overwritten before a MAD is sent.
101 101
102P_Key Index Handling
103
104 The old ib_umad interface did not allow setting the P_Key index for
105 MADs that are sent and did not provide a way for obtaining the P_Key
106 index of received MADs. A new layout for struct ib_user_mad_hdr
107 with a pkey_index member has been defined; however, to preserve
108 binary compatibility with older applications, this new layout will
109 not be used unless the IB_USER_MAD_ENABLE_PKEY ioctl is called
110 before a file descriptor is used for anything else.
111
112 In September 2008, the IB_USER_MAD_ABI_VERSION will be incremented
113 to 6, the new layout of struct ib_user_mad_hdr will be used by
114 default, and the IB_USER_MAD_ENABLE_PKEY ioctl will be removed.
115
102Setting IsSM Capability Bit 116Setting IsSM Capability Bit
103 117
104 To set the IsSM capability bit for a port, simply open the 118 To set the IsSM capability bit for a port, simply open the
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index d97ded25c4ff..aee29139368c 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -118,6 +118,8 @@ struct ib_umad_file {
118 wait_queue_head_t recv_wait; 118 wait_queue_head_t recv_wait;
119 struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS]; 119 struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS];
120 int agents_dead; 120 int agents_dead;
121 u8 use_pkey_index;
122 u8 already_used;
121}; 123};
122 124
123struct ib_umad_packet { 125struct ib_umad_packet {
@@ -147,6 +149,12 @@ static void ib_umad_release_dev(struct kref *ref)
147 kfree(dev); 149 kfree(dev);
148} 150}
149 151
152static int hdr_size(struct ib_umad_file *file)
153{
154 return file->use_pkey_index ? sizeof (struct ib_user_mad_hdr) :
155 sizeof (struct ib_user_mad_hdr_old);
156}
157
150/* caller must hold port->mutex at least for reading */ 158/* caller must hold port->mutex at least for reading */
151static struct ib_mad_agent *__get_agent(struct ib_umad_file *file, int id) 159static struct ib_mad_agent *__get_agent(struct ib_umad_file *file, int id)
152{ 160{
@@ -221,13 +229,13 @@ static void recv_handler(struct ib_mad_agent *agent,
221 packet->length = mad_recv_wc->mad_len; 229 packet->length = mad_recv_wc->mad_len;
222 packet->recv_wc = mad_recv_wc; 230 packet->recv_wc = mad_recv_wc;
223 231
224 packet->mad.hdr.status = 0; 232 packet->mad.hdr.status = 0;
225 packet->mad.hdr.length = sizeof (struct ib_user_mad) + 233 packet->mad.hdr.length = hdr_size(file) + mad_recv_wc->mad_len;
226 mad_recv_wc->mad_len; 234 packet->mad.hdr.qpn = cpu_to_be32(mad_recv_wc->wc->src_qp);
227 packet->mad.hdr.qpn = cpu_to_be32(mad_recv_wc->wc->src_qp); 235 packet->mad.hdr.lid = cpu_to_be16(mad_recv_wc->wc->slid);
228 packet->mad.hdr.lid = cpu_to_be16(mad_recv_wc->wc->slid); 236 packet->mad.hdr.sl = mad_recv_wc->wc->sl;
229 packet->mad.hdr.sl = mad_recv_wc->wc->sl; 237 packet->mad.hdr.path_bits = mad_recv_wc->wc->dlid_path_bits;
230 packet->mad.hdr.path_bits = mad_recv_wc->wc->dlid_path_bits; 238 packet->mad.hdr.pkey_index = mad_recv_wc->wc->pkey_index;
231 packet->mad.hdr.grh_present = !!(mad_recv_wc->wc->wc_flags & IB_WC_GRH); 239 packet->mad.hdr.grh_present = !!(mad_recv_wc->wc->wc_flags & IB_WC_GRH);
232 if (packet->mad.hdr.grh_present) { 240 if (packet->mad.hdr.grh_present) {
233 struct ib_ah_attr ah_attr; 241 struct ib_ah_attr ah_attr;
@@ -253,8 +261,8 @@ err1:
253 ib_free_recv_mad(mad_recv_wc); 261 ib_free_recv_mad(mad_recv_wc);
254} 262}
255 263
256static ssize_t copy_recv_mad(char __user *buf, struct ib_umad_packet *packet, 264static ssize_t copy_recv_mad(struct ib_umad_file *file, char __user *buf,
257 size_t count) 265 struct ib_umad_packet *packet, size_t count)
258{ 266{
259 struct ib_mad_recv_buf *recv_buf; 267 struct ib_mad_recv_buf *recv_buf;
260 int left, seg_payload, offset, max_seg_payload; 268 int left, seg_payload, offset, max_seg_payload;
@@ -262,15 +270,15 @@ static ssize_t copy_recv_mad(char __user *buf, struct ib_umad_packet *packet,
262 /* We need enough room to copy the first (or only) MAD segment. */ 270 /* We need enough room to copy the first (or only) MAD segment. */
263 recv_buf = &packet->recv_wc->recv_buf; 271 recv_buf = &packet->recv_wc->recv_buf;
264 if ((packet->length <= sizeof (*recv_buf->mad) && 272 if ((packet->length <= sizeof (*recv_buf->mad) &&
265 count < sizeof (packet->mad) + packet->length) || 273 count < hdr_size(file) + packet->length) ||
266 (packet->length > sizeof (*recv_buf->mad) && 274 (packet->length > sizeof (*recv_buf->mad) &&
267 count < sizeof (packet->mad) + sizeof (*recv_buf->mad))) 275 count < hdr_size(file) + sizeof (*recv_buf->mad)))
268 return -EINVAL; 276 return -EINVAL;
269 277
270 if (copy_to_user(buf, &packet->mad, sizeof (packet->mad))) 278 if (copy_to_user(buf, &packet->mad, hdr_size(file)))
271 return -EFAULT; 279 return -EFAULT;
272 280
273 buf += sizeof (packet->mad); 281 buf += hdr_size(file);
274 seg_payload = min_t(int, packet->length, sizeof (*recv_buf->mad)); 282 seg_payload = min_t(int, packet->length, sizeof (*recv_buf->mad));
275 if (copy_to_user(buf, recv_buf->mad, seg_payload)) 283 if (copy_to_user(buf, recv_buf->mad, seg_payload))
276 return -EFAULT; 284 return -EFAULT;
@@ -280,7 +288,7 @@ static ssize_t copy_recv_mad(char __user *buf, struct ib_umad_packet *packet,
280 * Multipacket RMPP MAD message. Copy remainder of message. 288 * Multipacket RMPP MAD message. Copy remainder of message.
281 * Note that last segment may have a shorter payload. 289 * Note that last segment may have a shorter payload.
282 */ 290 */
283 if (count < sizeof (packet->mad) + packet->length) { 291 if (count < hdr_size(file) + packet->length) {
284 /* 292 /*
285 * The buffer is too small, return the first RMPP segment, 293 * The buffer is too small, return the first RMPP segment,
286 * which includes the RMPP message length. 294 * which includes the RMPP message length.
@@ -300,18 +308,23 @@ static ssize_t copy_recv_mad(char __user *buf, struct ib_umad_packet *packet,
300 return -EFAULT; 308 return -EFAULT;
301 } 309 }
302 } 310 }
303 return sizeof (packet->mad) + packet->length; 311 return hdr_size(file) + packet->length;
304} 312}
305 313
306static ssize_t copy_send_mad(char __user *buf, struct ib_umad_packet *packet, 314static ssize_t copy_send_mad(struct ib_umad_file *file, char __user *buf,
307 size_t count) 315 struct ib_umad_packet *packet, size_t count)
308{ 316{
309 ssize_t size = sizeof (packet->mad) + packet->length; 317 ssize_t size = hdr_size(file) + packet->length;
310 318
311 if (count < size) 319 if (count < size)
312 return -EINVAL; 320 return -EINVAL;
313 321
314 if (copy_to_user(buf, &packet->mad, size)) 322 if (copy_to_user(buf, &packet->mad, hdr_size(file)))
323 return -EFAULT;
324
325 buf += hdr_size(file);
326
327 if (copy_to_user(buf, packet->mad.data, packet->length))
315 return -EFAULT; 328 return -EFAULT;
316 329
317 return size; 330 return size;
@@ -324,7 +337,7 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
324 struct ib_umad_packet *packet; 337 struct ib_umad_packet *packet;
325 ssize_t ret; 338 ssize_t ret;
326 339
327 if (count < sizeof (struct ib_user_mad)) 340 if (count < hdr_size(file))
328 return -EINVAL; 341 return -EINVAL;
329 342
330 spin_lock_irq(&file->recv_lock); 343 spin_lock_irq(&file->recv_lock);
@@ -348,9 +361,9 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
348 spin_unlock_irq(&file->recv_lock); 361 spin_unlock_irq(&file->recv_lock);
349 362
350 if (packet->recv_wc) 363 if (packet->recv_wc)
351 ret = copy_recv_mad(buf, packet, count); 364 ret = copy_recv_mad(file, buf, packet, count);
352 else 365 else
353 ret = copy_send_mad(buf, packet, count); 366 ret = copy_send_mad(file, buf, packet, count);
354 367
355 if (ret < 0) { 368 if (ret < 0) {
356 /* Requeue packet */ 369 /* Requeue packet */
@@ -442,15 +455,14 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
442 __be64 *tid; 455 __be64 *tid;
443 int ret, data_len, hdr_len, copy_offset, rmpp_active; 456 int ret, data_len, hdr_len, copy_offset, rmpp_active;
444 457
445 if (count < sizeof (struct ib_user_mad) + IB_MGMT_RMPP_HDR) 458 if (count < hdr_size(file) + IB_MGMT_RMPP_HDR)
446 return -EINVAL; 459 return -EINVAL;
447 460
448 packet = kzalloc(sizeof *packet + IB_MGMT_RMPP_HDR, GFP_KERNEL); 461 packet = kzalloc(sizeof *packet + IB_MGMT_RMPP_HDR, GFP_KERNEL);
449 if (!packet) 462 if (!packet)
450 return -ENOMEM; 463 return -ENOMEM;
451 464
452 if (copy_from_user(&packet->mad, buf, 465 if (copy_from_user(&packet->mad, buf, hdr_size(file))) {
453 sizeof (struct ib_user_mad) + IB_MGMT_RMPP_HDR)) {
454 ret = -EFAULT; 466 ret = -EFAULT;
455 goto err; 467 goto err;
456 } 468 }
@@ -461,6 +473,13 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
461 goto err; 473 goto err;
462 } 474 }
463 475
476 buf += hdr_size(file);
477
478 if (copy_from_user(packet->mad.data, buf, IB_MGMT_RMPP_HDR)) {
479 ret = -EFAULT;
480 goto err;
481 }
482
464 down_read(&file->port->mutex); 483 down_read(&file->port->mutex);
465 484
466 agent = __get_agent(file, packet->mad.hdr.id); 485 agent = __get_agent(file, packet->mad.hdr.id);
@@ -500,11 +519,11 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
500 IB_MGMT_RMPP_FLAG_ACTIVE; 519 IB_MGMT_RMPP_FLAG_ACTIVE;
501 } 520 }
502 521
503 data_len = count - sizeof (struct ib_user_mad) - hdr_len; 522 data_len = count - hdr_size(file) - hdr_len;
504 packet->msg = ib_create_send_mad(agent, 523 packet->msg = ib_create_send_mad(agent,
505 be32_to_cpu(packet->mad.hdr.qpn), 524 be32_to_cpu(packet->mad.hdr.qpn),
506 0, rmpp_active, hdr_len, 525 packet->mad.hdr.pkey_index, rmpp_active,
507 data_len, GFP_KERNEL); 526 hdr_len, data_len, GFP_KERNEL);
508 if (IS_ERR(packet->msg)) { 527 if (IS_ERR(packet->msg)) {
509 ret = PTR_ERR(packet->msg); 528 ret = PTR_ERR(packet->msg);
510 goto err_ah; 529 goto err_ah;
@@ -517,7 +536,6 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
517 536
518 /* Copy MAD header. Any RMPP header is already in place. */ 537 /* Copy MAD header. Any RMPP header is already in place. */
519 memcpy(packet->msg->mad, packet->mad.data, IB_MGMT_MAD_HDR); 538 memcpy(packet->msg->mad, packet->mad.data, IB_MGMT_MAD_HDR);
520 buf += sizeof (struct ib_user_mad);
521 539
522 if (!rmpp_active) { 540 if (!rmpp_active) {
523 if (copy_from_user(packet->msg->mad + copy_offset, 541 if (copy_from_user(packet->msg->mad + copy_offset,
@@ -646,6 +664,16 @@ found:
646 goto out; 664 goto out;
647 } 665 }
648 666
667 if (!file->already_used) {
668 file->already_used = 1;
669 if (!file->use_pkey_index) {
670 printk(KERN_WARNING "user_mad: process %s did not enable "
671 "P_Key index support.\n", current->comm);
672 printk(KERN_WARNING "user_mad: Documentation/infiniband/user_mad.txt "
673 "has info on the new ABI.\n");
674 }
675 }
676
649 file->agent[agent_id] = agent; 677 file->agent[agent_id] = agent;
650 ret = 0; 678 ret = 0;
651 679
@@ -682,6 +710,20 @@ out:
682 return ret; 710 return ret;
683} 711}
684 712
713static long ib_umad_enable_pkey(struct ib_umad_file *file)
714{
715 int ret = 0;
716
717 down_write(&file->port->mutex);
718 if (file->already_used)
719 ret = -EINVAL;
720 else
721 file->use_pkey_index = 1;
722 up_write(&file->port->mutex);
723
724 return ret;
725}
726
685static long ib_umad_ioctl(struct file *filp, unsigned int cmd, 727static long ib_umad_ioctl(struct file *filp, unsigned int cmd,
686 unsigned long arg) 728 unsigned long arg)
687{ 729{
@@ -690,6 +732,8 @@ static long ib_umad_ioctl(struct file *filp, unsigned int cmd,
690 return ib_umad_reg_agent(filp->private_data, arg); 732 return ib_umad_reg_agent(filp->private_data, arg);
691 case IB_USER_MAD_UNREGISTER_AGENT: 733 case IB_USER_MAD_UNREGISTER_AGENT:
692 return ib_umad_unreg_agent(filp->private_data, arg); 734 return ib_umad_unreg_agent(filp->private_data, arg);
735 case IB_USER_MAD_ENABLE_PKEY:
736 return ib_umad_enable_pkey(filp->private_data);
693 default: 737 default:
694 return -ENOIOCTLCMD; 738 return -ENOIOCTLCMD;
695 } 739 }
diff --git a/include/rdma/ib_user_mad.h b/include/rdma/ib_user_mad.h
index d66b15ea82c4..2a32043d1abd 100644
--- a/include/rdma/ib_user_mad.h
+++ b/include/rdma/ib_user_mad.h
@@ -52,7 +52,50 @@
52 */ 52 */
53 53
54/** 54/**
55 * ib_user_mad_hdr_old - Old version of MAD packet header without pkey_index
56 * @id - ID of agent MAD received with/to be sent with
57 * @status - 0 on successful receive, ETIMEDOUT if no response
58 * received (transaction ID in data[] will be set to TID of original
59 * request) (ignored on send)
60 * @timeout_ms - Milliseconds to wait for response (unset on receive)
61 * @retries - Number of automatic retries to attempt
62 * @qpn - Remote QP number received from/to be sent to
63 * @qkey - Remote Q_Key to be sent with (unset on receive)
64 * @lid - Remote lid received from/to be sent to
65 * @sl - Service level received with/to be sent with
66 * @path_bits - Local path bits received with/to be sent with
67 * @grh_present - If set, GRH was received/should be sent
68 * @gid_index - Local GID index to send with (unset on receive)
69 * @hop_limit - Hop limit in GRH
70 * @traffic_class - Traffic class in GRH
71 * @gid - Remote GID in GRH
72 * @flow_label - Flow label in GRH
73 */
74struct ib_user_mad_hdr_old {
75 __u32 id;
76 __u32 status;
77 __u32 timeout_ms;
78 __u32 retries;
79 __u32 length;
80 __be32 qpn;
81 __be32 qkey;
82 __be16 lid;
83 __u8 sl;
84 __u8 path_bits;
85 __u8 grh_present;
86 __u8 gid_index;
87 __u8 hop_limit;
88 __u8 traffic_class;
89 __u8 gid[16];
90 __be32 flow_label;
91};
92
93/**
55 * ib_user_mad_hdr - MAD packet header 94 * ib_user_mad_hdr - MAD packet header
95 * This layout allows specifying/receiving the P_Key index. To use
96 * this capability, an application must call the
97 * IB_USER_MAD_ENABLE_PKEY ioctl on the user MAD file handle before
98 * any other actions with the file handle.
56 * @id - ID of agent MAD received with/to be sent with 99 * @id - ID of agent MAD received with/to be sent with
57 * @status - 0 on successful receive, ETIMEDOUT if no response 100 * @status - 0 on successful receive, ETIMEDOUT if no response
58 * received (transaction ID in data[] will be set to TID of original 101 * received (transaction ID in data[] will be set to TID of original
@@ -70,6 +113,7 @@
70 * @traffic_class - Traffic class in GRH 113 * @traffic_class - Traffic class in GRH
71 * @gid - Remote GID in GRH 114 * @gid - Remote GID in GRH
72 * @flow_label - Flow label in GRH 115 * @flow_label - Flow label in GRH
116 * @pkey_index - P_Key index
73 */ 117 */
74struct ib_user_mad_hdr { 118struct ib_user_mad_hdr {
75 __u32 id; 119 __u32 id;
@@ -88,6 +132,8 @@ struct ib_user_mad_hdr {
88 __u8 traffic_class; 132 __u8 traffic_class;
89 __u8 gid[16]; 133 __u8 gid[16];
90 __be32 flow_label; 134 __be32 flow_label;
135 __u16 pkey_index;
136 __u8 reserved[6];
91}; 137};
92 138
93/** 139/**
@@ -134,4 +180,6 @@ struct ib_user_mad_reg_req {
134 180
135#define IB_USER_MAD_UNREGISTER_AGENT _IOW(IB_IOCTL_MAGIC, 2, __u32) 181#define IB_USER_MAD_UNREGISTER_AGENT _IOW(IB_IOCTL_MAGIC, 2, __u32)
136 182
183#define IB_USER_MAD_ENABLE_PKEY _IO(IB_IOCTL_MAGIC, 3)
184
137#endif /* IB_USER_MAD_H */ 185#endif /* IB_USER_MAD_H */