user_mad.c revision ec914c52d6208d8752dfd85b48a9aff304911434
1/* 2 * Copyright (c) 2004 Topspin Communications. All rights reserved. 3 * Copyright (c) 2005 Voltaire, Inc. All rights reserved. 4 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 * 34 * $Id: user_mad.c 2814 2005-07-06 19:14:09Z halr $ 35 */ 36 37#include <linux/module.h> 38#include <linux/init.h> 39#include <linux/device.h> 40#include <linux/err.h> 41#include <linux/fs.h> 42#include <linux/cdev.h> 43#include <linux/pci.h> 44#include <linux/dma-mapping.h> 45#include <linux/poll.h> 46#include <linux/rwsem.h> 47#include <linux/kref.h> 48 49#include <asm/uaccess.h> 50#include <asm/semaphore.h> 51 52#include <rdma/ib_mad.h> 53#include <rdma/ib_user_mad.h> 54 55MODULE_AUTHOR("Roland Dreier"); 56MODULE_DESCRIPTION("InfiniBand userspace MAD packet access"); 57MODULE_LICENSE("Dual BSD/GPL"); 58 59enum { 60 IB_UMAD_MAX_PORTS = 64, 61 IB_UMAD_MAX_AGENTS = 32, 62 63 IB_UMAD_MAJOR = 231, 64 IB_UMAD_MINOR_BASE = 0 65}; 66 67/* 68 * Our lifetime rules for these structs are the following: each time a 69 * device special file is opened, we look up the corresponding struct 70 * ib_umad_port by minor in the umad_port[] table while holding the 71 * port_lock. If this lookup succeeds, we take a reference on the 72 * ib_umad_port's struct ib_umad_device while still holding the 73 * port_lock; if the lookup fails, we fail the open(). We drop these 74 * references in the corresponding close(). 75 * 76 * In addition to references coming from open character devices, there 77 * is one more reference to each ib_umad_device representing the 78 * module's reference taken when allocating the ib_umad_device in 79 * ib_umad_add_one(). 80 * 81 * When destroying an ib_umad_device, we clear all of its 82 * ib_umad_ports from umad_port[] while holding port_lock before 83 * dropping the module's reference to the ib_umad_device. This is 84 * always safe because any open() calls will either succeed and obtain 85 * a reference before we clear the umad_port[] entries, or fail after 86 * we clear the umad_port[] entries. 87 */ 88 89struct ib_umad_port { 90 struct cdev *dev; 91 struct class_device *class_dev; 92 93 struct cdev *sm_dev; 94 struct class_device *sm_class_dev; 95 struct semaphore sm_sem; 96 97 struct rw_semaphore mutex; 98 struct list_head file_list; 99 100 struct ib_device *ib_dev; 101 struct ib_umad_device *umad_dev; 102 int dev_num; 103 u8 port_num; 104}; 105 106struct ib_umad_device { 107 int start_port, end_port; 108 struct kref ref; 109 struct ib_umad_port port[0]; 110}; 111 112struct ib_umad_file { 113 struct ib_umad_port *port; 114 struct list_head recv_list; 115 struct list_head port_list; 116 spinlock_t recv_lock; 117 wait_queue_head_t recv_wait; 118 struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS]; 119}; 120 121struct ib_umad_packet { 122 struct ib_mad_send_buf *msg; 123 struct list_head list; 124 int length; 125 struct ib_user_mad mad; 126}; 127 128static struct class *umad_class; 129 130static const dev_t base_dev = MKDEV(IB_UMAD_MAJOR, IB_UMAD_MINOR_BASE); 131 132static DEFINE_SPINLOCK(port_lock); 133static struct ib_umad_port *umad_port[IB_UMAD_MAX_PORTS]; 134static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS * 2); 135 136static void ib_umad_add_one(struct ib_device *device); 137static void ib_umad_remove_one(struct ib_device *device); 138 139static void ib_umad_release_dev(struct kref *ref) 140{ 141 struct ib_umad_device *dev = 142 container_of(ref, struct ib_umad_device, ref); 143 144 kfree(dev); 145} 146 147static int queue_packet(struct ib_umad_file *file, 148 struct ib_mad_agent *agent, 149 struct ib_umad_packet *packet) 150{ 151 int ret = 1; 152 153 down_read(&file->port->mutex); 154 for (packet->mad.hdr.id = 0; 155 packet->mad.hdr.id < IB_UMAD_MAX_AGENTS; 156 packet->mad.hdr.id++) 157 if (agent == file->agent[packet->mad.hdr.id]) { 158 spin_lock_irq(&file->recv_lock); 159 list_add_tail(&packet->list, &file->recv_list); 160 spin_unlock_irq(&file->recv_lock); 161 wake_up_interruptible(&file->recv_wait); 162 ret = 0; 163 break; 164 } 165 166 up_read(&file->port->mutex); 167 168 return ret; 169} 170 171static void send_handler(struct ib_mad_agent *agent, 172 struct ib_mad_send_wc *send_wc) 173{ 174 struct ib_umad_file *file = agent->context; 175 struct ib_umad_packet *timeout; 176 struct ib_umad_packet *packet = send_wc->send_buf->context[0]; 177 178 ib_destroy_ah(packet->msg->ah); 179 ib_free_send_mad(packet->msg); 180 181 if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) { 182 timeout = kzalloc(sizeof *timeout + IB_MGMT_MAD_HDR, GFP_KERNEL); 183 if (!timeout) 184 goto out; 185 186 timeout->length = IB_MGMT_MAD_HDR; 187 timeout->mad.hdr.id = packet->mad.hdr.id; 188 timeout->mad.hdr.status = ETIMEDOUT; 189 memcpy(timeout->mad.data, packet->mad.data, 190 sizeof (struct ib_mad_hdr)); 191 192 if (!queue_packet(file, agent, timeout)) 193 return; 194 } 195out: 196 kfree(packet); 197} 198 199static void recv_handler(struct ib_mad_agent *agent, 200 struct ib_mad_recv_wc *mad_recv_wc) 201{ 202 struct ib_umad_file *file = agent->context; 203 struct ib_umad_packet *packet; 204 int length; 205 206 if (mad_recv_wc->wc->status != IB_WC_SUCCESS) 207 goto out; 208 209 length = mad_recv_wc->mad_len; 210 packet = kzalloc(sizeof *packet + length, GFP_KERNEL); 211 if (!packet) 212 goto out; 213 214 packet->length = length; 215 216 ib_coalesce_recv_mad(mad_recv_wc, packet->mad.data); 217 218 packet->mad.hdr.status = 0; 219 packet->mad.hdr.length = length + sizeof (struct ib_user_mad); 220 packet->mad.hdr.qpn = cpu_to_be32(mad_recv_wc->wc->src_qp); 221 packet->mad.hdr.lid = cpu_to_be16(mad_recv_wc->wc->slid); 222 packet->mad.hdr.sl = mad_recv_wc->wc->sl; 223 packet->mad.hdr.path_bits = mad_recv_wc->wc->dlid_path_bits; 224 packet->mad.hdr.grh_present = !!(mad_recv_wc->wc->wc_flags & IB_WC_GRH); 225 if (packet->mad.hdr.grh_present) { 226 /* XXX parse GRH */ 227 packet->mad.hdr.gid_index = 0; 228 packet->mad.hdr.hop_limit = 0; 229 packet->mad.hdr.traffic_class = 0; 230 memset(packet->mad.hdr.gid, 0, 16); 231 packet->mad.hdr.flow_label = 0; 232 } 233 234 if (queue_packet(file, agent, packet)) 235 kfree(packet); 236 237out: 238 ib_free_recv_mad(mad_recv_wc); 239} 240 241static ssize_t ib_umad_read(struct file *filp, char __user *buf, 242 size_t count, loff_t *pos) 243{ 244 struct ib_umad_file *file = filp->private_data; 245 struct ib_umad_packet *packet; 246 ssize_t ret; 247 248 if (count < sizeof (struct ib_user_mad) + sizeof (struct ib_mad)) 249 return -EINVAL; 250 251 spin_lock_irq(&file->recv_lock); 252 253 while (list_empty(&file->recv_list)) { 254 spin_unlock_irq(&file->recv_lock); 255 256 if (filp->f_flags & O_NONBLOCK) 257 return -EAGAIN; 258 259 if (wait_event_interruptible(file->recv_wait, 260 !list_empty(&file->recv_list))) 261 return -ERESTARTSYS; 262 263 spin_lock_irq(&file->recv_lock); 264 } 265 266 packet = list_entry(file->recv_list.next, struct ib_umad_packet, list); 267 list_del(&packet->list); 268 269 spin_unlock_irq(&file->recv_lock); 270 271 if (count < packet->length + sizeof (struct ib_user_mad)) { 272 /* Return length needed (and first RMPP segment) if too small */ 273 if (copy_to_user(buf, &packet->mad, 274 sizeof (struct ib_user_mad) + sizeof (struct ib_mad))) 275 ret = -EFAULT; 276 else 277 ret = -ENOSPC; 278 } else if (copy_to_user(buf, &packet->mad, 279 packet->length + sizeof (struct ib_user_mad))) 280 ret = -EFAULT; 281 else 282 ret = packet->length + sizeof (struct ib_user_mad); 283 if (ret < 0) { 284 /* Requeue packet */ 285 spin_lock_irq(&file->recv_lock); 286 list_add(&packet->list, &file->recv_list); 287 spin_unlock_irq(&file->recv_lock); 288 } else 289 kfree(packet); 290 return ret; 291} 292 293static ssize_t ib_umad_write(struct file *filp, const char __user *buf, 294 size_t count, loff_t *pos) 295{ 296 struct ib_umad_file *file = filp->private_data; 297 struct ib_umad_packet *packet; 298 struct ib_mad_agent *agent; 299 struct ib_ah_attr ah_attr; 300 struct ib_ah *ah; 301 struct ib_rmpp_mad *rmpp_mad; 302 u8 method; 303 __be64 *tid; 304 int ret, length, hdr_len, copy_offset; 305 int rmpp_active = 0; 306 307 if (count < sizeof (struct ib_user_mad)) 308 return -EINVAL; 309 310 length = count - sizeof (struct ib_user_mad); 311 packet = kmalloc(sizeof *packet + IB_MGMT_RMPP_HDR, GFP_KERNEL); 312 if (!packet) 313 return -ENOMEM; 314 315 if (copy_from_user(&packet->mad, buf, 316 sizeof (struct ib_user_mad) + IB_MGMT_RMPP_HDR)) { 317 ret = -EFAULT; 318 goto err; 319 } 320 321 if (packet->mad.hdr.id < 0 || 322 packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) { 323 ret = -EINVAL; 324 goto err; 325 } 326 327 down_read(&file->port->mutex); 328 329 agent = file->agent[packet->mad.hdr.id]; 330 if (!agent) { 331 ret = -EINVAL; 332 goto err_up; 333 } 334 335 memset(&ah_attr, 0, sizeof ah_attr); 336 ah_attr.dlid = be16_to_cpu(packet->mad.hdr.lid); 337 ah_attr.sl = packet->mad.hdr.sl; 338 ah_attr.src_path_bits = packet->mad.hdr.path_bits; 339 ah_attr.port_num = file->port->port_num; 340 if (packet->mad.hdr.grh_present) { 341 ah_attr.ah_flags = IB_AH_GRH; 342 memcpy(ah_attr.grh.dgid.raw, packet->mad.hdr.gid, 16); 343 ah_attr.grh.flow_label = be32_to_cpu(packet->mad.hdr.flow_label); 344 ah_attr.grh.hop_limit = packet->mad.hdr.hop_limit; 345 ah_attr.grh.traffic_class = packet->mad.hdr.traffic_class; 346 } 347 348 ah = ib_create_ah(agent->qp->pd, &ah_attr); 349 if (IS_ERR(ah)) { 350 ret = PTR_ERR(ah); 351 goto err_up; 352 } 353 354 rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data; 355 if (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE) { 356 /* RMPP active */ 357 if (!agent->rmpp_version) { 358 ret = -EINVAL; 359 goto err_ah; 360 } 361 362 /* Validate that the management class can support RMPP */ 363 if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { 364 hdr_len = IB_MGMT_SA_HDR; 365 } else if ((rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && 366 (rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) { 367 hdr_len = IB_MGMT_VENDOR_HDR; 368 } else { 369 ret = -EINVAL; 370 goto err_ah; 371 } 372 rmpp_active = 1; 373 copy_offset = IB_MGMT_RMPP_HDR; 374 } else { 375 hdr_len = IB_MGMT_MAD_HDR; 376 copy_offset = IB_MGMT_MAD_HDR; 377 } 378 379 packet->msg = ib_create_send_mad(agent, 380 be32_to_cpu(packet->mad.hdr.qpn), 381 0, rmpp_active, 382 hdr_len, length - hdr_len, 383 GFP_KERNEL); 384 if (IS_ERR(packet->msg)) { 385 ret = PTR_ERR(packet->msg); 386 goto err_ah; 387 } 388 389 packet->msg->ah = ah; 390 packet->msg->timeout_ms = packet->mad.hdr.timeout_ms; 391 packet->msg->retries = packet->mad.hdr.retries; 392 packet->msg->context[0] = packet; 393 394 /* Copy MAD headers (RMPP header in place) */ 395 memcpy(packet->msg->mad, packet->mad.data, IB_MGMT_MAD_HDR); 396 /* Now, copy rest of message from user into send buffer */ 397 if (copy_from_user(packet->msg->mad + copy_offset, 398 buf + sizeof (struct ib_user_mad) + copy_offset, 399 length - copy_offset)) { 400 ret = -EFAULT; 401 goto err_msg; 402 } 403 404 /* 405 * If userspace is generating a request that will generate a 406 * response, we need to make sure the high-order part of the 407 * transaction ID matches the agent being used to send the 408 * MAD. 409 */ 410 method = ((struct ib_mad_hdr *) packet->msg->mad)->method; 411 412 if (!(method & IB_MGMT_METHOD_RESP) && 413 method != IB_MGMT_METHOD_TRAP_REPRESS && 414 method != IB_MGMT_METHOD_SEND) { 415 tid = &((struct ib_mad_hdr *) packet->msg->mad)->tid; 416 *tid = cpu_to_be64(((u64) agent->hi_tid) << 32 | 417 (be64_to_cpup(tid) & 0xffffffff)); 418 } 419 420 ret = ib_post_send_mad(packet->msg, NULL); 421 if (ret) 422 goto err_msg; 423 424 up_read(&file->port->mutex); 425 426 return count; 427 428err_msg: 429 ib_free_send_mad(packet->msg); 430 431err_ah: 432 ib_destroy_ah(ah); 433 434err_up: 435 up_read(&file->port->mutex); 436 437err: 438 kfree(packet); 439 return ret; 440} 441 442static unsigned int ib_umad_poll(struct file *filp, struct poll_table_struct *wait) 443{ 444 struct ib_umad_file *file = filp->private_data; 445 446 /* we will always be able to post a MAD send */ 447 unsigned int mask = POLLOUT | POLLWRNORM; 448 449 poll_wait(filp, &file->recv_wait, wait); 450 451 if (!list_empty(&file->recv_list)) 452 mask |= POLLIN | POLLRDNORM; 453 454 return mask; 455} 456 457static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg) 458{ 459 struct ib_user_mad_reg_req ureq; 460 struct ib_mad_reg_req req; 461 struct ib_mad_agent *agent; 462 int agent_id; 463 int ret; 464 465 down_write(&file->port->mutex); 466 467 if (!file->port->ib_dev) { 468 ret = -EPIPE; 469 goto out; 470 } 471 472 if (copy_from_user(&ureq, (void __user *) arg, sizeof ureq)) { 473 ret = -EFAULT; 474 goto out; 475 } 476 477 if (ureq.qpn != 0 && ureq.qpn != 1) { 478 ret = -EINVAL; 479 goto out; 480 } 481 482 for (agent_id = 0; agent_id < IB_UMAD_MAX_AGENTS; ++agent_id) 483 if (!file->agent[agent_id]) 484 goto found; 485 486 ret = -ENOMEM; 487 goto out; 488 489found: 490 if (ureq.mgmt_class) { 491 req.mgmt_class = ureq.mgmt_class; 492 req.mgmt_class_version = ureq.mgmt_class_version; 493 memcpy(req.method_mask, ureq.method_mask, sizeof req.method_mask); 494 memcpy(req.oui, ureq.oui, sizeof req.oui); 495 } 496 497 agent = ib_register_mad_agent(file->port->ib_dev, file->port->port_num, 498 ureq.qpn ? IB_QPT_GSI : IB_QPT_SMI, 499 ureq.mgmt_class ? &req : NULL, 500 ureq.rmpp_version, 501 send_handler, recv_handler, file); 502 if (IS_ERR(agent)) { 503 ret = PTR_ERR(agent); 504 goto out; 505 } 506 507 if (put_user(agent_id, 508 (u32 __user *) (arg + offsetof(struct ib_user_mad_reg_req, id)))) { 509 ret = -EFAULT; 510 ib_unregister_mad_agent(agent); 511 goto out; 512 } 513 514 file->agent[agent_id] = agent; 515 ret = 0; 516 517out: 518 up_write(&file->port->mutex); 519 return ret; 520} 521 522static int ib_umad_unreg_agent(struct ib_umad_file *file, unsigned long arg) 523{ 524 struct ib_mad_agent *agent = NULL; 525 u32 id; 526 int ret = 0; 527 528 if (get_user(id, (u32 __user *) arg)) 529 return -EFAULT; 530 531 down_write(&file->port->mutex); 532 533 if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !file->agent[id]) { 534 ret = -EINVAL; 535 goto out; 536 } 537 538 agent = file->agent[id]; 539 file->agent[id] = NULL; 540 541out: 542 up_write(&file->port->mutex); 543 544 if (agent) 545 ib_unregister_mad_agent(agent); 546 547 return ret; 548} 549 550static long ib_umad_ioctl(struct file *filp, unsigned int cmd, 551 unsigned long arg) 552{ 553 switch (cmd) { 554 case IB_USER_MAD_REGISTER_AGENT: 555 return ib_umad_reg_agent(filp->private_data, arg); 556 case IB_USER_MAD_UNREGISTER_AGENT: 557 return ib_umad_unreg_agent(filp->private_data, arg); 558 default: 559 return -ENOIOCTLCMD; 560 } 561} 562 563static int ib_umad_open(struct inode *inode, struct file *filp) 564{ 565 struct ib_umad_port *port; 566 struct ib_umad_file *file; 567 int ret = 0; 568 569 spin_lock(&port_lock); 570 port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE]; 571 if (port) 572 kref_get(&port->umad_dev->ref); 573 spin_unlock(&port_lock); 574 575 if (!port) 576 return -ENXIO; 577 578 down_write(&port->mutex); 579 580 if (!port->ib_dev) { 581 ret = -ENXIO; 582 goto out; 583 } 584 585 file = kzalloc(sizeof *file, GFP_KERNEL); 586 if (!file) { 587 kref_put(&port->umad_dev->ref, ib_umad_release_dev); 588 ret = -ENOMEM; 589 goto out; 590 } 591 592 spin_lock_init(&file->recv_lock); 593 INIT_LIST_HEAD(&file->recv_list); 594 init_waitqueue_head(&file->recv_wait); 595 596 file->port = port; 597 filp->private_data = file; 598 599 list_add_tail(&file->port_list, &port->file_list); 600 601out: 602 up_write(&port->mutex); 603 return ret; 604} 605 606static int ib_umad_close(struct inode *inode, struct file *filp) 607{ 608 struct ib_umad_file *file = filp->private_data; 609 struct ib_umad_device *dev = file->port->umad_dev; 610 struct ib_umad_packet *packet, *tmp; 611 int i; 612 613 for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i) 614 if (file->agent[i]) 615 ib_unregister_mad_agent(file->agent[i]); 616 617 list_for_each_entry_safe(packet, tmp, &file->recv_list, list) 618 kfree(packet); 619 620 down_write(&file->port->mutex); 621 list_del(&file->port_list); 622 up_write(&file->port->mutex); 623 624 kfree(file); 625 626 kref_put(&dev->ref, ib_umad_release_dev); 627 628 return 0; 629} 630 631static struct file_operations umad_fops = { 632 .owner = THIS_MODULE, 633 .read = ib_umad_read, 634 .write = ib_umad_write, 635 .poll = ib_umad_poll, 636 .unlocked_ioctl = ib_umad_ioctl, 637 .compat_ioctl = ib_umad_ioctl, 638 .open = ib_umad_open, 639 .release = ib_umad_close 640}; 641 642static int ib_umad_sm_open(struct inode *inode, struct file *filp) 643{ 644 struct ib_umad_port *port; 645 struct ib_port_modify props = { 646 .set_port_cap_mask = IB_PORT_SM 647 }; 648 int ret; 649 650 spin_lock(&port_lock); 651 port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE - IB_UMAD_MAX_PORTS]; 652 if (port) 653 kref_get(&port->umad_dev->ref); 654 spin_unlock(&port_lock); 655 656 if (!port) 657 return -ENXIO; 658 659 if (filp->f_flags & O_NONBLOCK) { 660 if (down_trylock(&port->sm_sem)) { 661 ret = -EAGAIN; 662 goto fail; 663 } 664 } else { 665 if (down_interruptible(&port->sm_sem)) { 666 ret = -ERESTARTSYS; 667 goto fail; 668 } 669 } 670 671 ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props); 672 if (ret) { 673 up(&port->sm_sem); 674 goto fail; 675 } 676 677 filp->private_data = port; 678 679 return 0; 680 681fail: 682 kref_put(&port->umad_dev->ref, ib_umad_release_dev); 683 return ret; 684} 685 686static int ib_umad_sm_close(struct inode *inode, struct file *filp) 687{ 688 struct ib_umad_port *port = filp->private_data; 689 struct ib_port_modify props = { 690 .clr_port_cap_mask = IB_PORT_SM 691 }; 692 int ret = 0; 693 694 down_write(&port->mutex); 695 if (port->ib_dev) 696 ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props); 697 up_write(&port->mutex); 698 699 up(&port->sm_sem); 700 701 kref_put(&port->umad_dev->ref, ib_umad_release_dev); 702 703 return ret; 704} 705 706static struct file_operations umad_sm_fops = { 707 .owner = THIS_MODULE, 708 .open = ib_umad_sm_open, 709 .release = ib_umad_sm_close 710}; 711 712static struct ib_client umad_client = { 713 .name = "umad", 714 .add = ib_umad_add_one, 715 .remove = ib_umad_remove_one 716}; 717 718static ssize_t show_ibdev(struct class_device *class_dev, char *buf) 719{ 720 struct ib_umad_port *port = class_get_devdata(class_dev); 721 722 if (!port) 723 return -ENODEV; 724 725 return sprintf(buf, "%s\n", port->ib_dev->name); 726} 727static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); 728 729static ssize_t show_port(struct class_device *class_dev, char *buf) 730{ 731 struct ib_umad_port *port = class_get_devdata(class_dev); 732 733 if (!port) 734 return -ENODEV; 735 736 return sprintf(buf, "%d\n", port->port_num); 737} 738static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); 739 740static ssize_t show_abi_version(struct class *class, char *buf) 741{ 742 return sprintf(buf, "%d\n", IB_USER_MAD_ABI_VERSION); 743} 744static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); 745 746static int ib_umad_init_port(struct ib_device *device, int port_num, 747 struct ib_umad_port *port) 748{ 749 spin_lock(&port_lock); 750 port->dev_num = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS); 751 if (port->dev_num >= IB_UMAD_MAX_PORTS) { 752 spin_unlock(&port_lock); 753 return -1; 754 } 755 set_bit(port->dev_num, dev_map); 756 spin_unlock(&port_lock); 757 758 port->ib_dev = device; 759 port->port_num = port_num; 760 init_MUTEX(&port->sm_sem); 761 init_rwsem(&port->mutex); 762 INIT_LIST_HEAD(&port->file_list); 763 764 port->dev = cdev_alloc(); 765 if (!port->dev) 766 return -1; 767 port->dev->owner = THIS_MODULE; 768 port->dev->ops = &umad_fops; 769 kobject_set_name(&port->dev->kobj, "umad%d", port->dev_num); 770 if (cdev_add(port->dev, base_dev + port->dev_num, 1)) 771 goto err_cdev; 772 773 port->class_dev = class_device_create(umad_class, NULL, port->dev->dev, 774 device->dma_device, 775 "umad%d", port->dev_num); 776 if (IS_ERR(port->class_dev)) 777 goto err_cdev; 778 779 if (class_device_create_file(port->class_dev, &class_device_attr_ibdev)) 780 goto err_class; 781 if (class_device_create_file(port->class_dev, &class_device_attr_port)) 782 goto err_class; 783 784 port->sm_dev = cdev_alloc(); 785 if (!port->sm_dev) 786 goto err_class; 787 port->sm_dev->owner = THIS_MODULE; 788 port->sm_dev->ops = &umad_sm_fops; 789 kobject_set_name(&port->sm_dev->kobj, "issm%d", port->dev_num); 790 if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1)) 791 goto err_sm_cdev; 792 793 port->sm_class_dev = class_device_create(umad_class, NULL, port->sm_dev->dev, 794 device->dma_device, 795 "issm%d", port->dev_num); 796 if (IS_ERR(port->sm_class_dev)) 797 goto err_sm_cdev; 798 799 class_set_devdata(port->class_dev, port); 800 class_set_devdata(port->sm_class_dev, port); 801 802 if (class_device_create_file(port->sm_class_dev, &class_device_attr_ibdev)) 803 goto err_sm_class; 804 if (class_device_create_file(port->sm_class_dev, &class_device_attr_port)) 805 goto err_sm_class; 806 807 spin_lock(&port_lock); 808 umad_port[port->dev_num] = port; 809 spin_unlock(&port_lock); 810 811 return 0; 812 813err_sm_class: 814 class_device_destroy(umad_class, port->sm_dev->dev); 815 816err_sm_cdev: 817 cdev_del(port->sm_dev); 818 819err_class: 820 class_device_destroy(umad_class, port->dev->dev); 821 822err_cdev: 823 cdev_del(port->dev); 824 clear_bit(port->dev_num, dev_map); 825 826 return -1; 827} 828 829static void ib_umad_kill_port(struct ib_umad_port *port) 830{ 831 struct ib_umad_file *file; 832 int id; 833 834 class_set_devdata(port->class_dev, NULL); 835 class_set_devdata(port->sm_class_dev, NULL); 836 837 class_device_destroy(umad_class, port->dev->dev); 838 class_device_destroy(umad_class, port->sm_dev->dev); 839 840 cdev_del(port->dev); 841 cdev_del(port->sm_dev); 842 843 spin_lock(&port_lock); 844 umad_port[port->dev_num] = NULL; 845 spin_unlock(&port_lock); 846 847 down_write(&port->mutex); 848 849 port->ib_dev = NULL; 850 851 list_for_each_entry(file, &port->file_list, port_list) 852 for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id) { 853 if (!file->agent[id]) 854 continue; 855 ib_unregister_mad_agent(file->agent[id]); 856 file->agent[id] = NULL; 857 } 858 859 up_write(&port->mutex); 860 861 clear_bit(port->dev_num, dev_map); 862} 863 864static void ib_umad_add_one(struct ib_device *device) 865{ 866 struct ib_umad_device *umad_dev; 867 int s, e, i; 868 869 if (device->node_type == IB_NODE_SWITCH) 870 s = e = 0; 871 else { 872 s = 1; 873 e = device->phys_port_cnt; 874 } 875 876 umad_dev = kzalloc(sizeof *umad_dev + 877 (e - s + 1) * sizeof (struct ib_umad_port), 878 GFP_KERNEL); 879 if (!umad_dev) 880 return; 881 882 kref_init(&umad_dev->ref); 883 884 umad_dev->start_port = s; 885 umad_dev->end_port = e; 886 887 for (i = s; i <= e; ++i) { 888 umad_dev->port[i - s].umad_dev = umad_dev; 889 890 if (ib_umad_init_port(device, i, &umad_dev->port[i - s])) 891 goto err; 892 } 893 894 ib_set_client_data(device, &umad_client, umad_dev); 895 896 return; 897 898err: 899 while (--i >= s) 900 ib_umad_kill_port(&umad_dev->port[i - s]); 901 902 kref_put(&umad_dev->ref, ib_umad_release_dev); 903} 904 905static void ib_umad_remove_one(struct ib_device *device) 906{ 907 struct ib_umad_device *umad_dev = ib_get_client_data(device, &umad_client); 908 int i; 909 910 if (!umad_dev) 911 return; 912 913 for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i) 914 ib_umad_kill_port(&umad_dev->port[i]); 915 916 kref_put(&umad_dev->ref, ib_umad_release_dev); 917} 918 919static int __init ib_umad_init(void) 920{ 921 int ret; 922 923 ret = register_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2, 924 "infiniband_mad"); 925 if (ret) { 926 printk(KERN_ERR "user_mad: couldn't register device number\n"); 927 goto out; 928 } 929 930 umad_class = class_create(THIS_MODULE, "infiniband_mad"); 931 if (IS_ERR(umad_class)) { 932 ret = PTR_ERR(umad_class); 933 printk(KERN_ERR "user_mad: couldn't create class infiniband_mad\n"); 934 goto out_chrdev; 935 } 936 937 ret = class_create_file(umad_class, &class_attr_abi_version); 938 if (ret) { 939 printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n"); 940 goto out_class; 941 } 942 943 ret = ib_register_client(&umad_client); 944 if (ret) { 945 printk(KERN_ERR "user_mad: couldn't register ib_umad client\n"); 946 goto out_class; 947 } 948 949 return 0; 950 951out_class: 952 class_destroy(umad_class); 953 954out_chrdev: 955 unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2); 956 957out: 958 return ret; 959} 960 961static void __exit ib_umad_cleanup(void) 962{ 963 ib_unregister_client(&umad_client); 964 class_destroy(umad_class); 965 unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2); 966} 967 968module_init(ib_umad_init); 969module_exit(ib_umad_cleanup); 970