Merge branch 'pm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[linux-2.6.git] / net / rds / ib.c
index d2007b9..b4c8b00 100644 (file)
 #include <linux/if_arp.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include "rds.h"
 #include "ib.h"
 
-unsigned int fmr_pool_size = RDS_FMR_POOL_SIZE;
+static unsigned int fmr_pool_size = RDS_FMR_POOL_SIZE;
 unsigned int fmr_message_size = RDS_FMR_SIZE + 1; /* +1 allows for unaligned MRs */
 unsigned int rds_ib_retry_count = RDS_IB_DEFAULT_RETRY_COUNT;
 
@@ -53,13 +54,19 @@ MODULE_PARM_DESC(fmr_message_size, " Max size of a RDMA transfer");
 module_param(rds_ib_retry_count, int, 0444);
 MODULE_PARM_DESC(rds_ib_retry_count, " Number of hw retries before reporting an error");
 
+/*
+ * we have a clumsy combination of RCU and a rwsem protecting this list
+ * because it is used both in the get_mr fast path and while blocking in
+ * the FMR flushing path.
+ */
+DECLARE_RWSEM(rds_ib_devices_lock);
 struct list_head rds_ib_devices;
 
 /* NOTE: if also grabbing ibdev lock, grab this first */
 DEFINE_SPINLOCK(ib_nodev_conns_lock);
 LIST_HEAD(ib_nodev_conns);
 
-void rds_ib_nodev_connect(void)
+static void rds_ib_nodev_connect(void)
 {
        struct rds_ib_connection *ic;
 
@@ -69,7 +76,7 @@ void rds_ib_nodev_connect(void)
        spin_unlock(&ib_nodev_conns_lock);
 }
 
-void rds_ib_dev_shutdown(struct rds_ib_device *rds_ibdev)
+static void rds_ib_dev_shutdown(struct rds_ib_device *rds_ibdev)
 {
        struct rds_ib_connection *ic;
        unsigned long flags;
@@ -112,7 +119,7 @@ void rds_ib_dev_put(struct rds_ib_device *rds_ibdev)
                queue_work(rds_wq, &rds_ibdev->free_work);
 }
 
-void rds_ib_add_one(struct ib_device *device)
+static void rds_ib_add_one(struct ib_device *device)
 {
        struct rds_ib_device *rds_ibdev;
        struct ib_device_attr *dev_attr;
@@ -171,7 +178,10 @@ void rds_ib_add_one(struct ib_device *device)
 
        INIT_LIST_HEAD(&rds_ibdev->ipaddr_list);
        INIT_LIST_HEAD(&rds_ibdev->conn_list);
-       list_add_tail(&rds_ibdev->list, &rds_ib_devices);
+
+       down_write(&rds_ib_devices_lock);
+       list_add_tail_rcu(&rds_ibdev->list, &rds_ib_devices);
+       up_write(&rds_ib_devices_lock);
        atomic_inc(&rds_ibdev->refcount);
 
        ib_set_client_data(device, &rds_ib_client, rds_ibdev);
@@ -220,7 +230,7 @@ struct rds_ib_device *rds_ib_get_client_data(struct ib_device *device)
  *
  * This can be called at any time and can be racing with any other RDS path.
  */
-void rds_ib_remove_one(struct ib_device *device)
+static void rds_ib_remove_one(struct ib_device *device)
 {
        struct rds_ib_device *rds_ibdev;
 
@@ -230,16 +240,20 @@ void rds_ib_remove_one(struct ib_device *device)
 
        rds_ib_dev_shutdown(rds_ibdev);
 
+       /* stop connection attempts from getting a reference to this device. */
+       ib_set_client_data(device, &rds_ib_client, NULL);
+
+       down_write(&rds_ib_devices_lock);
+       list_del_rcu(&rds_ibdev->list);
+       up_write(&rds_ib_devices_lock);
+
        /*
-        * prevent future connection attempts from getting a reference to this
-        * device and wait for currently racing connection attempts to finish
-        * getting their reference
+        * This synchronize rcu is waiting for readers of both the ib
+        * client data and the devices list to finish before we drop
+        * both of those references.
         */
-       ib_set_client_data(device, &rds_ib_client, NULL);
        synchronize_rcu();
        rds_ib_dev_put(rds_ibdev);
-
-       list_del(&rds_ibdev->list);
        rds_ib_dev_put(rds_ibdev);
 }
 
@@ -312,7 +326,7 @@ static int rds_ib_laddr_check(__be32 addr)
        /* Create a CMA ID and try to bind it. This catches both
         * IB and iWARP capable NICs.
         */
-       cm_id = rdma_create_id(NULL, NULL, RDMA_PS_TCP);
+       cm_id = rdma_create_id(NULL, NULL, RDMA_PS_TCP, IB_QPT_RC);
        if (IS_ERR(cm_id))
                return PTR_ERR(cm_id);
 
@@ -351,7 +365,6 @@ void rds_ib_exit(void)
        rds_ib_sysctl_exit();
        rds_ib_recv_exit();
        rds_trans_unregister(&rds_ib_transport);
-       rds_ib_fmr_exit();
 }
 
 struct rds_transport rds_ib_transport = {
@@ -381,19 +394,15 @@ struct rds_transport rds_ib_transport = {
        .t_type                 = RDS_TRANS_IB
 };
 
-int __init rds_ib_init(void)
+int rds_ib_init(void)
 {
        int ret;
 
        INIT_LIST_HEAD(&rds_ib_devices);
 
-       ret = rds_ib_fmr_init();
-       if (ret)
-               goto out;
-
        ret = ib_register_client(&rds_ib_client);
        if (ret)
-               goto out_fmr_exit;
+               goto out;
 
        ret = rds_ib_sysctl_init();
        if (ret)
@@ -417,8 +426,6 @@ out_sysctl:
        rds_ib_sysctl_exit();
 out_ibreg:
        rds_ib_unregister_client();
-out_fmr_exit:
-       rds_ib_fmr_exit();
 out:
        return ret;
 }