diff options
| -rw-r--r-- | drivers/infiniband/hw/ocrdma/ocrdma.h | 1 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ocrdma/ocrdma_main.c | 38 |
2 files changed, 23 insertions, 16 deletions
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h index d7a44b812dfc..85a69c958559 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma.h | |||
| @@ -168,6 +168,7 @@ struct ocrdma_dev { | |||
| 168 | struct be_dev_info nic_info; | 168 | struct be_dev_info nic_info; |
| 169 | 169 | ||
| 170 | struct list_head entry; | 170 | struct list_head entry; |
| 171 | struct rcu_head rcu; | ||
| 171 | int id; | 172 | int id; |
| 172 | }; | 173 | }; |
| 173 | 174 | ||
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index cee201ed14ae..0bc1efb02ff5 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c | |||
| @@ -47,7 +47,7 @@ MODULE_AUTHOR("Emulex Corporation"); | |||
| 47 | MODULE_LICENSE("GPL"); | 47 | MODULE_LICENSE("GPL"); |
| 48 | 48 | ||
| 49 | static LIST_HEAD(ocrdma_dev_list); | 49 | static LIST_HEAD(ocrdma_dev_list); |
| 50 | static DEFINE_MUTEX(ocrdma_devlist_lock); | 50 | static DEFINE_SPINLOCK(ocrdma_devlist_lock); |
| 51 | static DEFINE_IDR(ocrdma_dev_id); | 51 | static DEFINE_IDR(ocrdma_dev_id); |
| 52 | 52 | ||
| 53 | static union ib_gid ocrdma_zero_sgid; | 53 | static union ib_gid ocrdma_zero_sgid; |
| @@ -221,14 +221,14 @@ static int ocrdma_inet6addr_event(struct notifier_block *notifier, | |||
| 221 | is_vlan = true; | 221 | is_vlan = true; |
| 222 | vid = vlan_dev_vlan_id(event_netdev); | 222 | vid = vlan_dev_vlan_id(event_netdev); |
| 223 | } | 223 | } |
| 224 | mutex_lock(&ocrdma_devlist_lock); | 224 | rcu_read_lock(); |
| 225 | list_for_each_entry(dev, &ocrdma_dev_list, entry) { | 225 | list_for_each_entry_rcu(dev, &ocrdma_dev_list, entry) { |
| 226 | if (dev->nic_info.netdev == netdev) { | 226 | if (dev->nic_info.netdev == netdev) { |
| 227 | found = true; | 227 | found = true; |
| 228 | break; | 228 | break; |
| 229 | } | 229 | } |
| 230 | } | 230 | } |
| 231 | mutex_unlock(&ocrdma_devlist_lock); | 231 | rcu_read_unlock(); |
| 232 | 232 | ||
| 233 | if (!found) | 233 | if (!found) |
| 234 | return NOTIFY_DONE; | 234 | return NOTIFY_DONE; |
| @@ -431,9 +431,9 @@ static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info) | |||
| 431 | if (status) | 431 | if (status) |
| 432 | goto alloc_err; | 432 | goto alloc_err; |
| 433 | 433 | ||
| 434 | mutex_lock(&ocrdma_devlist_lock); | 434 | spin_lock(&ocrdma_devlist_lock); |
| 435 | list_add_tail(&dev->entry, &ocrdma_dev_list); | 435 | list_add_tail_rcu(&dev->entry, &ocrdma_dev_list); |
| 436 | mutex_unlock(&ocrdma_devlist_lock); | 436 | spin_unlock(&ocrdma_devlist_lock); |
| 437 | return dev; | 437 | return dev; |
| 438 | 438 | ||
| 439 | alloc_err: | 439 | alloc_err: |
| @@ -448,16 +448,9 @@ idr_err: | |||
| 448 | return NULL; | 448 | return NULL; |
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | static void ocrdma_remove(struct ocrdma_dev *dev) | 451 | static void ocrdma_remove_free(struct rcu_head *rcu) |
| 452 | { | 452 | { |
| 453 | /* first unregister with stack to stop all the active traffic | 453 | struct ocrdma_dev *dev = container_of(rcu, struct ocrdma_dev, rcu); |
| 454 | * of the registered clients. | ||
| 455 | */ | ||
| 456 | ib_unregister_device(&dev->ibdev); | ||
| 457 | |||
| 458 | mutex_lock(&ocrdma_devlist_lock); | ||
| 459 | list_del(&dev->entry); | ||
| 460 | mutex_unlock(&ocrdma_devlist_lock); | ||
| 461 | 454 | ||
| 462 | ocrdma_free_resources(dev); | 455 | ocrdma_free_resources(dev); |
| 463 | ocrdma_cleanup_hw(dev); | 456 | ocrdma_cleanup_hw(dev); |
| @@ -467,6 +460,19 @@ static void ocrdma_remove(struct ocrdma_dev *dev) | |||
| 467 | ib_dealloc_device(&dev->ibdev); | 460 | ib_dealloc_device(&dev->ibdev); |
| 468 | } | 461 | } |
| 469 | 462 | ||
| 463 | static void ocrdma_remove(struct ocrdma_dev *dev) | ||
| 464 | { | ||
| 465 | /* first unregister with stack to stop all the active traffic | ||
| 466 | * of the registered clients. | ||
| 467 | */ | ||
| 468 | ib_unregister_device(&dev->ibdev); | ||
| 469 | |||
| 470 | spin_lock(&ocrdma_devlist_lock); | ||
| 471 | list_del_rcu(&dev->entry); | ||
| 472 | spin_unlock(&ocrdma_devlist_lock); | ||
| 473 | call_rcu(&dev->rcu, ocrdma_remove_free); | ||
| 474 | } | ||
| 475 | |||
| 470 | static int ocrdma_open(struct ocrdma_dev *dev) | 476 | static int ocrdma_open(struct ocrdma_dev *dev) |
| 471 | { | 477 | { |
| 472 | struct ib_event port_event; | 478 | struct ib_event port_event; |
