aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2005-11-03 15:01:18 -0500
committerRoland Dreier <rolandd@cisco.com>2005-11-03 15:01:18 -0500
commit0c99cb6d5fe77872c5a32cff837c05f70158ce15 (patch)
treeb974a31452cb645f063589262bde09b6c5b05701
parent87cfe32375e0b69b999b59bf8287f501df3e43f7 (diff)
[IB] umad: fix hot remove of IB devices
Fix hotplug of devices for ib_umad module: when a device goes away, kill off all MAD agents for open files associated with that device, and make sure that the device is not touched again after ib_umad returns from its remove_one function. Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/infiniband/core/user_mad.c80
1 files changed, 64 insertions, 16 deletions
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 97128e25f78b..aed5ca23fb22 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -94,6 +94,9 @@ struct ib_umad_port {
94 struct class_device *sm_class_dev; 94 struct class_device *sm_class_dev;
95 struct semaphore sm_sem; 95 struct semaphore sm_sem;
96 96
97 struct rw_semaphore mutex;
98 struct list_head file_list;
99
97 struct ib_device *ib_dev; 100 struct ib_device *ib_dev;
98 struct ib_umad_device *umad_dev; 101 struct ib_umad_device *umad_dev;
99 int dev_num; 102 int dev_num;
@@ -108,10 +111,10 @@ struct ib_umad_device {
108 111
109struct ib_umad_file { 112struct ib_umad_file {
110 struct ib_umad_port *port; 113 struct ib_umad_port *port;
111 spinlock_t recv_lock;
112 struct list_head recv_list; 114 struct list_head recv_list;
115 struct list_head port_list;
116 spinlock_t recv_lock;
113 wait_queue_head_t recv_wait; 117 wait_queue_head_t recv_wait;
114 struct rw_semaphore agent_mutex;
115 struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS]; 118 struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS];
116 struct ib_mr *mr[IB_UMAD_MAX_AGENTS]; 119 struct ib_mr *mr[IB_UMAD_MAX_AGENTS];
117}; 120};
@@ -148,7 +151,7 @@ static int queue_packet(struct ib_umad_file *file,
148{ 151{
149 int ret = 1; 152 int ret = 1;
150 153
151 down_read(&file->agent_mutex); 154 down_read(&file->port->mutex);
152 for (packet->mad.hdr.id = 0; 155 for (packet->mad.hdr.id = 0;
153 packet->mad.hdr.id < IB_UMAD_MAX_AGENTS; 156 packet->mad.hdr.id < IB_UMAD_MAX_AGENTS;
154 packet->mad.hdr.id++) 157 packet->mad.hdr.id++)
@@ -161,7 +164,7 @@ static int queue_packet(struct ib_umad_file *file,
161 break; 164 break;
162 } 165 }
163 166
164 up_read(&file->agent_mutex); 167 up_read(&file->port->mutex);
165 168
166 return ret; 169 return ret;
167} 170}
@@ -322,7 +325,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
322 goto err; 325 goto err;
323 } 326 }
324 327
325 down_read(&file->agent_mutex); 328 down_read(&file->port->mutex);
326 329
327 agent = file->agent[packet->mad.hdr.id]; 330 agent = file->agent[packet->mad.hdr.id];
328 if (!agent) { 331 if (!agent) {
@@ -419,7 +422,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
419 if (ret) 422 if (ret)
420 goto err_msg; 423 goto err_msg;
421 424
422 up_read(&file->agent_mutex); 425 up_read(&file->port->mutex);
423 426
424 return count; 427 return count;
425 428
@@ -430,7 +433,7 @@ err_ah:
430 ib_destroy_ah(ah); 433 ib_destroy_ah(ah);
431 434
432err_up: 435err_up:
433 up_read(&file->agent_mutex); 436 up_read(&file->port->mutex);
434 437
435err: 438err:
436 kfree(packet); 439 kfree(packet);
@@ -460,7 +463,12 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg)
460 int agent_id; 463 int agent_id;
461 int ret; 464 int ret;
462 465
463 down_write(&file->agent_mutex); 466 down_write(&file->port->mutex);
467
468 if (!file->port->ib_dev) {
469 ret = -EPIPE;
470 goto out;
471 }
464 472
465 if (copy_from_user(&ureq, (void __user *) arg, sizeof ureq)) { 473 if (copy_from_user(&ureq, (void __user *) arg, sizeof ureq)) {
466 ret = -EFAULT; 474 ret = -EFAULT;
@@ -522,7 +530,7 @@ err:
522 ib_unregister_mad_agent(agent); 530 ib_unregister_mad_agent(agent);
523 531
524out: 532out:
525 up_write(&file->agent_mutex); 533 up_write(&file->port->mutex);
526 return ret; 534 return ret;
527} 535}
528 536
@@ -531,7 +539,7 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, unsigned long arg)
531 u32 id; 539 u32 id;
532 int ret = 0; 540 int ret = 0;
533 541
534 down_write(&file->agent_mutex); 542 down_write(&file->port->mutex);
535 543
536 if (get_user(id, (u32 __user *) arg)) { 544 if (get_user(id, (u32 __user *) arg)) {
537 ret = -EFAULT; 545 ret = -EFAULT;
@@ -548,7 +556,7 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, unsigned long arg)
548 file->agent[id] = NULL; 556 file->agent[id] = NULL;
549 557
550out: 558out:
551 up_write(&file->agent_mutex); 559 up_write(&file->port->mutex);
552 return ret; 560 return ret;
553} 561}
554 562
@@ -569,6 +577,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
569{ 577{
570 struct ib_umad_port *port; 578 struct ib_umad_port *port;
571 struct ib_umad_file *file; 579 struct ib_umad_file *file;
580 int ret = 0;
572 581
573 spin_lock(&port_lock); 582 spin_lock(&port_lock);
574 port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE]; 583 port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE];
@@ -579,21 +588,32 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
579 if (!port) 588 if (!port)
580 return -ENXIO; 589 return -ENXIO;
581 590
591 down_write(&port->mutex);
592
593 if (!port->ib_dev) {
594 ret = -ENXIO;
595 goto out;
596 }
597
582 file = kzalloc(sizeof *file, GFP_KERNEL); 598 file = kzalloc(sizeof *file, GFP_KERNEL);
583 if (!file) { 599 if (!file) {
584 kref_put(&port->umad_dev->ref, ib_umad_release_dev); 600 kref_put(&port->umad_dev->ref, ib_umad_release_dev);
585 return -ENOMEM; 601 ret = -ENOMEM;
602 goto out;
586 } 603 }
587 604
588 spin_lock_init(&file->recv_lock); 605 spin_lock_init(&file->recv_lock);
589 init_rwsem(&file->agent_mutex);
590 INIT_LIST_HEAD(&file->recv_list); 606 INIT_LIST_HEAD(&file->recv_list);
591 init_waitqueue_head(&file->recv_wait); 607 init_waitqueue_head(&file->recv_wait);
592 608
593 file->port = port; 609 file->port = port;
594 filp->private_data = file; 610 filp->private_data = file;
595 611
596 return 0; 612 list_add_tail(&file->port_list, &port->file_list);
613
614out:
615 up_write(&port->mutex);
616 return ret;
597} 617}
598 618
599static int ib_umad_close(struct inode *inode, struct file *filp) 619static int ib_umad_close(struct inode *inode, struct file *filp)
@@ -603,6 +623,7 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
603 struct ib_umad_packet *packet, *tmp; 623 struct ib_umad_packet *packet, *tmp;
604 int i; 624 int i;
605 625
626 down_write(&file->port->mutex);
606 for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i) 627 for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i)
607 if (file->agent[i]) { 628 if (file->agent[i]) {
608 ib_dereg_mr(file->mr[i]); 629 ib_dereg_mr(file->mr[i]);
@@ -612,6 +633,9 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
612 list_for_each_entry_safe(packet, tmp, &file->recv_list, list) 633 list_for_each_entry_safe(packet, tmp, &file->recv_list, list)
613 kfree(packet); 634 kfree(packet);
614 635
636 list_del(&file->port_list);
637 up_write(&file->port->mutex);
638
615 kfree(file); 639 kfree(file);
616 640
617 kref_put(&dev->ref, ib_umad_release_dev); 641 kref_put(&dev->ref, ib_umad_release_dev);
@@ -680,9 +704,13 @@ static int ib_umad_sm_close(struct inode *inode, struct file *filp)
680 struct ib_port_modify props = { 704 struct ib_port_modify props = {
681 .clr_port_cap_mask = IB_PORT_SM 705 .clr_port_cap_mask = IB_PORT_SM
682 }; 706 };
683 int ret; 707 int ret = 0;
708
709 down_write(&port->mutex);
710 if (port->ib_dev)
711 ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
712 up_write(&port->mutex);
684 713
685 ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
686 up(&port->sm_sem); 714 up(&port->sm_sem);
687 715
688 kref_put(&port->umad_dev->ref, ib_umad_release_dev); 716 kref_put(&port->umad_dev->ref, ib_umad_release_dev);
@@ -745,6 +773,8 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
745 port->ib_dev = device; 773 port->ib_dev = device;
746 port->port_num = port_num; 774 port->port_num = port_num;
747 init_MUTEX(&port->sm_sem); 775 init_MUTEX(&port->sm_sem);
776 init_rwsem(&port->mutex);
777 INIT_LIST_HEAD(&port->file_list);
748 778
749 port->dev = cdev_alloc(); 779 port->dev = cdev_alloc();
750 if (!port->dev) 780 if (!port->dev)
@@ -813,6 +843,9 @@ err_cdev:
813 843
814static void ib_umad_kill_port(struct ib_umad_port *port) 844static void ib_umad_kill_port(struct ib_umad_port *port)
815{ 845{
846 struct ib_umad_file *file;
847 int id;
848
816 class_set_devdata(port->class_dev, NULL); 849 class_set_devdata(port->class_dev, NULL);
817 class_set_devdata(port->sm_class_dev, NULL); 850 class_set_devdata(port->sm_class_dev, NULL);
818 851
@@ -826,6 +859,21 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
826 umad_port[port->dev_num] = NULL; 859 umad_port[port->dev_num] = NULL;
827 spin_unlock(&port_lock); 860 spin_unlock(&port_lock);
828 861
862 down_write(&port->mutex);
863
864 port->ib_dev = NULL;
865
866 list_for_each_entry(file, &port->file_list, port_list)
867 for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id) {
868 if (!file->agent[id])
869 continue;
870 ib_dereg_mr(file->mr[id]);
871 ib_unregister_mad_agent(file->agent[id]);
872 file->agent[id] = NULL;
873 }
874
875 up_write(&port->mutex);
876
829 clear_bit(port->dev_num, dev_map); 877 clear_bit(port->dev_num, dev_map);
830} 878}
831 879