Quoting r. Roland Dreier <[EMAIL PROTECTED]>:
> the MAD module actually has to invent a pointer to return.

OK, the solution I propose is to actually have two remove
callbacks: one per client, called on all devices if defined.
Another one per client data, called only if add returns non-NULL.

Code now is actually getting smaller, so we are getting some benefit
out of it.

 core/cache.c            |    5 +-
 core/cm.c               |   21 ++++-----
 core/device.c           |  112 ++++++++++++++++--------------------------------
 core/mad.c              |    5 +-
 core/ping.c             |    5 +-
 core/sa_query.c         |   38 ++++++++--------
 core/user_mad.c         |   31 ++++++-------
 core/uverbs.h           |    1
 core/uverbs_main.c      |   29 ++++++------
 include/rdma/ib_verbs.h |   15 ++++--
 ulp/ipoib/ipoib_main.c  |   34 +++++++++-----
 ulp/sdp/sdp_conn.c      |   33 ++++++--------
 ulp/sdp/sdp_dev.h       |    1
 ulp/srp/ib_srp.c        |   33 ++++++++------
 14 files changed, 175 insertions(+), 188 deletions(-)

---

Add a way to client to avoid getting notifications for some
devices. Make it possible to use container_of to get per device
data instead of a list walk.

Signed-off-by: Michael S. Tsirkin <[EMAIL PROTECTED]>

Index: linux-2.6.12.2/drivers/infiniband/core/device.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/core/device.c        2005-09-01 
00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/device.c     2005-09-01 
00:41:12.000000000 +0300
@@ -47,12 +47,6 @@ MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("core kernel InfiniBand API");
 MODULE_LICENSE("Dual BSD/GPL");
 
-struct ib_client_data {
-       struct list_head  list;
-       struct ib_client *client;
-       void *            data;
-};
-
 static LIST_HEAD(device_list);
 static LIST_HEAD(client_list);
 
@@ -194,28 +188,6 @@ void ib_dealloc_device(struct ib_device 
 }
 EXPORT_SYMBOL(ib_dealloc_device);
 
-static int add_client_context(struct ib_device *device, struct ib_client 
*client)
-{
-       struct ib_client_data *context;
-       unsigned long flags;
-
-       context = kmalloc(sizeof *context, GFP_KERNEL);
-       if (!context) {
-               printk(KERN_WARNING "Couldn't allocate client context for 
%s/%s\n",
-                      device->name, client->name);
-               return -ENOMEM;
-       }
-
-       context->client = client;
-       context->data   = NULL;
-
-       spin_lock_irqsave(&device->client_data_lock, flags);
-       list_add(&context->list, &device->client_data_list);
-       spin_unlock_irqrestore(&device->client_data_lock, flags);
-
-       return 0;
-}
-
 /**
  * ib_register_device - Register an IB device with IB core
  * @device:Device to register
@@ -259,11 +231,17 @@ int ib_register_device(struct ib_device 
        device->reg_state = IB_DEV_REGISTERED;
 
        {
+               struct ib_client_data *context;
                struct ib_client *client;
+               unsigned long flags;
 
                list_for_each_entry(client, &client_list, list)
-                       if (client->add && !add_client_context(device, client))
-                               client->add(device);
+                       if (client->add && (context = client->add(device))) {
+                               context->client = client;
+                               spin_lock_irqsave(&device->client_data_lock, 
flags);
+                               list_add(&context->list, 
&device->client_data_list);
+                               
spin_unlock_irqrestore(&device->client_data_lock, flags);
+                       }
        }
 
  out:
@@ -281,25 +259,31 @@ EXPORT_SYMBOL(ib_register_device);
 void ib_unregister_device(struct ib_device *device)
 {
        struct ib_client *client;
-       struct ib_client_data *context, *tmp;
+       struct ib_client_data *context;
        unsigned long flags;
 
        down(&device_sem);
-
        list_for_each_entry_reverse(client, &client_list, list)
                if (client->remove)
                        client->remove(device);
 
        list_del(&device->core_list);
 
-       up(&device_sem);
-
        spin_lock_irqsave(&device->client_data_lock, flags);
-       list_for_each_entry_safe(context, tmp, &device->client_data_list, list)
-               kfree(context);
+       for (;;) {
+               if (list_empty(&device->client_data_list))
+                       break;
+               context = list_entry(device->client_data_list.prev,
+                                       typeof(*context), list);
+               list_del(&context->list);
+               spin_unlock_irqrestore(&device->client_data_lock, flags);
+               context->remove(device, context);
+               spin_lock_irqsave(&device->client_data_lock, flags);
+       }
        spin_unlock_irqrestore(&device->client_data_lock, flags);
 
        device->reg_state = IB_DEV_UNREGISTERED;
+       up(&device_sem);
 }
 EXPORT_SYMBOL(ib_unregister_device);
 
@@ -318,14 +302,20 @@ EXPORT_SYMBOL(ib_unregister_device);
  */
 int ib_register_client(struct ib_client *client)
 {
+       struct ib_client_data *context;
        struct ib_device *device;
+       unsigned long flags;
 
        down(&device_sem);
 
        list_add_tail(&client->list, &client_list);
        list_for_each_entry(device, &device_list, core_list)
-               if (client->add && !add_client_context(device, client))
-                       client->add(device);
+               if (client->add && (context = client->add(device))) {
+                       context->client = client;
+                       spin_lock_irqsave(&device->client_data_lock, flags);
+                       list_add(&context->list, &device->client_data_list);
+                       spin_unlock_irqrestore(&device->client_data_lock, 
flags);
+               }
 
        up(&device_sem);
 
@@ -343,7 +333,7 @@ EXPORT_SYMBOL(ib_register_client);
  */
 void ib_unregister_client(struct ib_client *client)
 {
-       struct ib_client_data *context, *tmp;
+       struct ib_client_data *context;
        struct ib_device *device;
        unsigned long flags;
 
@@ -354,10 +344,13 @@ void ib_unregister_client(struct ib_clie
                        client->remove(device);
 
                spin_lock_irqsave(&device->client_data_lock, flags);
-               list_for_each_entry_safe(context, tmp, 
&device->client_data_list, list)
+               list_for_each_entry(context, &device->client_data_list, list)
                        if (context->client == client) {
                                list_del(&context->list);
-                               kfree(context);
+                               
spin_unlock_irqrestore(&device->client_data_lock, flags);
+                               context->remove(device, context);
+                               spin_lock_irqsave(&device->client_data_lock, 
flags);
+                               break;
                        }
                spin_unlock_irqrestore(&device->client_data_lock, flags);
        }
@@ -375,16 +368,17 @@ EXPORT_SYMBOL(ib_unregister_client);
  * ib_get_client_data() returns client context set with
  * ib_set_client_data().
  */
-void *ib_get_client_data(struct ib_device *device, struct ib_client *client)
+struct ib_client_data *ib_get_client_data(struct ib_device *device,
+                                         struct ib_client *client)
 {
        struct ib_client_data *context;
-       void *ret = NULL;
+       struct ib_client_data *ret = NULL;
        unsigned long flags;
 
        spin_lock_irqsave(&device->client_data_lock, flags);
        list_for_each_entry(context, &device->client_data_list, list)
                if (context->client == client) {
-                       ret = context->data;
+                       ret = context;
                        break;
                }
        spin_unlock_irqrestore(&device->client_data_lock, flags);
@@ -394,36 +388,6 @@ void *ib_get_client_data(struct ib_devic
 EXPORT_SYMBOL(ib_get_client_data);
 
 /**
- * ib_set_client_data - Get IB client context
- * @device:Device to set context for
- * @client:Client to set context for
- * @data:Context to set
- *
- * ib_set_client_data() sets client context that can be retrieved with
- * ib_get_client_data().
- */
-void ib_set_client_data(struct ib_device *device, struct ib_client *client,
-                       void *data)
-{
-       struct ib_client_data *context;
-       unsigned long flags;
-
-       spin_lock_irqsave(&device->client_data_lock, flags);
-       list_for_each_entry(context, &device->client_data_list, list)
-               if (context->client == client) {
-                       context->data = data;
-                       goto out;
-               }
-
-       printk(KERN_WARNING "No client context found for %s/%s\n",
-              device->name, client->name);
-
-out:
-       spin_unlock_irqrestore(&device->client_data_lock, flags);
-}
-EXPORT_SYMBOL(ib_set_client_data);
-
-/**
  * ib_register_event_handler - Register an IB event handler
  * @event_handler:Handler to register
  *
Index: linux-2.6.12.2/drivers/infiniband/include/rdma/ib_verbs.h
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/include/rdma/ib_verbs.h      
2005-09-01 00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/include/rdma/ib_verbs.h   2005-09-01 
00:41:12.000000000 +0300
@@ -956,14 +956,22 @@ struct ib_device {
        u8                           phys_port_cnt;
 };
 
+struct ib_client_data;
+
 struct ib_client {
        char  *name;
-       void (*add)   (struct ib_device *);
+       struct ib_client_data *(*add) (struct ib_device *);
        void (*remove)(struct ib_device *);
 
        struct list_head list;
 };
 
+struct ib_client_data {
+       struct list_head  list;
+       struct ib_client *client;
+       void (*remove)(struct ib_device *, struct ib_client_data *);
+};
+
 struct ib_device *ib_alloc_device(size_t size);
 void ib_dealloc_device(struct ib_device *device);
 
@@ -973,9 +981,8 @@ void ib_unregister_device(struct ib_devi
 int ib_register_client   (struct ib_client *client);
 void ib_unregister_client(struct ib_client *client);
 
-void *ib_get_client_data(struct ib_device *device, struct ib_client *client);
-void  ib_set_client_data(struct ib_device *device, struct ib_client *client,
-                        void *data);
+struct ib_client_data *ib_get_client_data(struct ib_device *device,
+                                         struct ib_client *client);
 
 static inline int ib_copy_from_udata(void *dest, struct ib_udata *udata, 
size_t len)
 {
Index: linux-2.6.12.2/drivers/infiniband/core/user_mad.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/core/user_mad.c      2005-09-01 
00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/user_mad.c   2005-09-01 
00:41:12.000000000 +0300
@@ -80,9 +80,10 @@ struct ib_umad_port {
 };
 
 struct ib_umad_device {
-       int                  start_port, end_port;
-       struct kref          ref;
-       struct ib_umad_port  port[0];
+       struct ib_client_data data;
+       int                   start_port, end_port;
+       struct kref           ref;
+       struct ib_umad_port   port[0];
 };
 
 struct ib_umad_file {
@@ -108,8 +109,9 @@ static const dev_t base_dev = MKDEV(IB_U
 static spinlock_t map_lock;
 static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS * 2);
 
-static void ib_umad_add_one(struct ib_device *device);
-static void ib_umad_remove_one(struct ib_device *device);
+static struct ib_client_data *ib_umad_add_one(struct ib_device *device);
+static void ib_umad_remove_one(struct ib_device *device,
+                              struct ib_client_data *);
 
 static int queue_packet(struct ib_umad_file *file,
                        struct ib_mad_agent *agent,
@@ -667,7 +669,6 @@ static struct file_operations umad_sm_fo
 static struct ib_client umad_client = {
        .name   = "umad",
        .add    = ib_umad_add_one,
-       .remove = ib_umad_remove_one
 };
 
 static ssize_t show_dev(struct class_device *class_dev, char *buf)
@@ -819,7 +820,7 @@ err_cdev:
        return -1;
 }
 
-static void ib_umad_add_one(struct ib_device *device)
+static struct ib_client_data *ib_umad_add_one(struct ib_device *device)
 {
        struct ib_umad_device *umad_dev;
        int s, e, i;
@@ -835,13 +836,14 @@ static void ib_umad_add_one(struct ib_de
                           (e - s + 1) * sizeof (struct ib_umad_port),
                           GFP_KERNEL);
        if (!umad_dev)
-               return;
+               return NULL;
 
        memset(umad_dev, 0, sizeof *umad_dev +
               (e - s + 1) * sizeof (struct ib_umad_port));
 
        kref_init(&umad_dev->ref);
 
+       umad_dev->data.remove = ib_umad_remove_one;
        umad_dev->start_port = s;
        umad_dev->end_port   = e;
 
@@ -852,9 +854,7 @@ static void ib_umad_add_one(struct ib_de
                        goto err;
        }
 
-       ib_set_client_data(device, &umad_client, umad_dev);
-
-       return;
+       return &umad_dev->data;
 
 err:
        while (--i >= s) {
@@ -863,15 +863,16 @@ err:
        }
 
        kref_put(&umad_dev->ref, ib_umad_release_dev);
+       return NULL;
 }
 
-static void ib_umad_remove_one(struct ib_device *device)
+static void ib_umad_remove_one(struct ib_device *device,
+                              struct ib_client_data *data)
 {
-       struct ib_umad_device *umad_dev = ib_get_client_data(device, 
&umad_client);
+       struct ib_umad_device *umad_dev;
        int i;
 
-       if (!umad_dev)
-               return;
+       umad_dev = container_of(data, struct ib_umad_device, data);
 
        for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i) {
                class_device_unregister(&umad_dev->port[i].class_dev);
Index: linux-2.6.12.2/drivers/infiniband/core/cm.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/core/cm.c    2005-09-01 
00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/cm.c 2005-09-01 00:41:12.000000000 
+0300
@@ -51,13 +51,12 @@ MODULE_AUTHOR("Sean Hefty");
 MODULE_DESCRIPTION("InfiniBand CM");
 MODULE_LICENSE("Dual BSD/GPL");
 
-static void cm_add_one(struct ib_device *device);
-static void cm_remove_one(struct ib_device *device);
+static struct ib_client_data *cm_add_one(struct ib_device *device);
+static void cm_remove_one(struct ib_device *device, struct ib_client_data *);
 
 static struct ib_client cm_client = {
        .name   = "cm",
        .add    = cm_add_one,
-       .remove = cm_remove_one
 };
 
 static struct ib_cm {
@@ -81,6 +80,7 @@ struct cm_port {
 };
 
 struct cm_device {
+       struct ib_client_data data;
        struct list_head list;
        struct ib_device *device;
        __be64 ca_guid;
@@ -3194,7 +3194,7 @@ static __be64 cm_get_ca_guid(struct ib_d
        return guid;
 }
 
-static void cm_add_one(struct ib_device *device)
+static struct ib_client_data *cm_add_one(struct ib_device *device)
 {
        struct cm_device *cm_dev;
        struct cm_port *port;
@@ -3212,8 +3212,9 @@ static void cm_add_one(struct ib_device 
        cm_dev = kmalloc(sizeof(*cm_dev) + sizeof(*port) *
                         device->phys_port_cnt, GFP_KERNEL);
        if (!cm_dev)
-               return;
+               return NULL;
 
+       cm_dev->data.remove = cm_remove_one;
        cm_dev->device = device;
        cm_dev->ca_guid = cm_get_ca_guid(device);
        if (!cm_dev->ca_guid)
@@ -3238,12 +3239,11 @@ static void cm_add_one(struct ib_device 
                if (ret)
                        goto error3;
        }
-       ib_set_client_data(device, &cm_client, cm_dev);
 
        write_lock_irqsave(&cm.device_lock, flags);
        list_add_tail(&cm_dev->list, &cm.device_list);
        write_unlock_irqrestore(&cm.device_lock, flags);
-       return;
+       return &cm_dev->data;
 
 error3:
        ib_unregister_mad_agent(port->mad_agent);
@@ -3257,9 +3257,10 @@ error2:
        }
 error1:
        kfree(cm_dev);
+       return NULL;
 }
 
-static void cm_remove_one(struct ib_device *device)
+static void cm_remove_one(struct ib_device *device, struct ib_client_data 
*data)
 {
        struct cm_device *cm_dev;
        struct cm_port *port;
@@ -3269,9 +3270,7 @@ static void cm_remove_one(struct ib_devi
        unsigned long flags;
        int i;
 
-       cm_dev = ib_get_client_data(device, &cm_client);
-       if (!cm_dev)
-               return;
+       cm_dev = container_of(data, struct cm_device, data);
 
        write_lock_irqsave(&cm.device_lock, flags);
        list_del(&cm_dev->list);
Index: linux-2.6.12.2/drivers/infiniband/core/sa_query.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/core/sa_query.c      2005-09-01 
00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/sa_query.c   2005-09-01 
00:41:12.000000000 +0300
@@ -65,6 +65,7 @@ struct ib_sa_port {
 };
 
 struct ib_sa_device {
+       struct ib_client_data   data;
        int                     start_port, end_port;
        struct ib_event_handler event_handler;
        struct ib_sa_port port[0];
@@ -98,13 +99,12 @@ struct ib_sa_mcmember_query {
        struct ib_sa_query sa_query;
 };
 
-static void ib_sa_add_one(struct ib_device *device);
-static void ib_sa_remove_one(struct ib_device *device);
+static struct ib_client_data *ib_sa_add_one(struct ib_device *device);
+static void ib_sa_remove_one(struct ib_device *device, struct ib_client_data 
*data);
 
 static struct ib_client sa_client = {
        .name   = "sa",
        .add    = ib_sa_add_one,
-       .remove = ib_sa_remove_one
 };
 
 static spinlock_t idr_lock;
@@ -426,13 +426,14 @@ static void update_sm_ah(void *port_ptr)
 
 static void ib_sa_event(struct ib_event_handler *handler, struct ib_event 
*event)
 {
+       struct ib_sa_device *sa_dev;
+
        if (event->event == IB_EVENT_PORT_ERR    ||
            event->event == IB_EVENT_PORT_ACTIVE ||
            event->event == IB_EVENT_LID_CHANGE  ||
            event->event == IB_EVENT_PKEY_CHANGE ||
            event->event == IB_EVENT_SM_CHANGE) {
-               struct ib_sa_device *sa_dev =
-                       ib_get_client_data(event->device, &sa_client);
+               sa_dev = container_of(handler, struct ib_sa_device, 
event_handler);
 
                schedule_work(&sa_dev->port[event->element.port_num -
                                            sa_dev->start_port].update_task);
@@ -608,7 +609,8 @@ int ib_sa_path_rec_get(struct ib_device 
                       struct ib_sa_query **sa_query)
 {
        struct ib_sa_path_query *query;
-       struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
+       struct ib_client_data *data = ib_get_client_data(device, &sa_client);
+       struct ib_sa_device *sa_dev = container_of(data, struct ib_sa_device, 
data);
        struct ib_sa_port   *port   = &sa_dev->port[port_num - 
sa_dev->start_port];
        struct ib_mad_agent *agent  = port->agent;
        int ret;
@@ -710,7 +712,8 @@ int ib_sa_service_rec_query(struct ib_de
                            struct ib_sa_query **sa_query)
 {
        struct ib_sa_service_query *query;
-       struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
+       struct ib_client_data *data = ib_get_client_data(device, &sa_client);
+       struct ib_sa_device *sa_dev = container_of(data, struct ib_sa_device, 
data);
        struct ib_sa_port   *port   = &sa_dev->port[port_num - 
sa_dev->start_port];
        struct ib_mad_agent *agent  = port->agent;
        int ret;
@@ -793,7 +796,8 @@ int ib_sa_mcmember_rec_query(struct ib_d
                             struct ib_sa_query **sa_query)
 {
        struct ib_sa_mcmember_query *query;
-       struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
+       struct ib_client_data *data = ib_get_client_data(device, &sa_client);
+       struct ib_sa_device *sa_dev = container_of(data, struct ib_sa_device, 
data);
        struct ib_sa_port   *port   = &sa_dev->port[port_num - 
sa_dev->start_port];
        struct ib_mad_agent *agent  = port->agent;
        int ret;
@@ -900,7 +904,7 @@ static void recv_handler(struct ib_mad_a
        ib_free_recv_mad(mad_recv_wc);
 }
 
-static void ib_sa_add_one(struct ib_device *device)
+static struct ib_client_data *ib_sa_add_one(struct ib_device *device)
 {
        struct ib_sa_device *sa_dev;
        int s, e, i;
@@ -916,8 +920,9 @@ static void ib_sa_add_one(struct ib_devi
                         (e - s + 1) * sizeof (struct ib_sa_port),
                         GFP_KERNEL);
        if (!sa_dev)
-               return;
+               return NULL;
 
+       sa_dev->data.remove = ib_sa_remove_one;
        sa_dev->start_port = s;
        sa_dev->end_port   = e;
 
@@ -937,8 +942,6 @@ static void ib_sa_add_one(struct ib_devi
                          update_sm_ah, &sa_dev->port[i]);
        }
 
-       ib_set_client_data(device, &sa_client, sa_dev);
-
        /*
         * We register our event handler after everything is set up,
         * and then update our cached info after the event handler is
@@ -953,7 +956,7 @@ static void ib_sa_add_one(struct ib_devi
        for (i = 0; i <= e - s; ++i)
                update_sm_ah(&sa_dev->port[i]);
 
-       return;
+       return &sa_dev->data;
 
 err:
        while (--i >= 0)
@@ -961,17 +964,14 @@ err:
 
        kfree(sa_dev);
 
-       return;
+       return NULL;
 }
 
-static void ib_sa_remove_one(struct ib_device *device)
+static void ib_sa_remove_one(struct ib_device *device, struct ib_client_data 
*data)
 {
-       struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
+       struct ib_sa_device *sa_dev = container_of(data, struct ib_sa_device, 
data);
        int i;
 
-       if (!sa_dev)
-               return;
-
        ib_unregister_event_handler(&sa_dev->event_handler);
 
        for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
Index: linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_conn.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/ulp/sdp/sdp_conn.c   2005-09-01 
00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_conn.c        2005-09-01 
00:41:12.000000000 +0300
@@ -37,13 +37,13 @@
 
 static struct sdev_root dev_root_s;
 
-static void sdp_device_init_one(struct ib_device *device);
-static void sdp_device_remove_one(struct ib_device *device);
+static struct ib_client_data *sdp_device_init_one(struct ib_device *device);
+static void sdp_device_remove_one(struct ib_device *device,
+                                 struct ib_client_data *data);
 
 static struct ib_client sdp_client = {
        .name   = "sdp",
        .add    = sdp_device_init_one,
-       .remove = sdp_device_remove_one
 };
 
 static DEFINE_SPINLOCK(psn_lock);
@@ -959,6 +959,7 @@ static void sdp_conn_lock_init(struct sd
 int sdp_conn_alloc_ib(struct sdp_sock *conn, struct ib_device *device,
                      u8 hw_port, u16 pkey)
 {
+       struct ib_client_data *data;
        struct ib_qp_init_attr *init_attr;
        struct ib_qp_attr     *qp_attr;
        struct sdev_hca_port  *port;
@@ -969,10 +970,12 @@ int sdp_conn_alloc_ib(struct sdp_sock *c
        /*
         * look up correct HCA and port
         */
-       hca = ib_get_client_data(device, &sdp_client);
-       if (!hca)
+       data = ib_get_client_data(device, &sdp_client);
+       if (!data)
                return -ERANGE;
 
+       hca = container_of(data, struct sdev_hca, data);
+
        list_for_each_entry(port, &hca->port_list, list)
                if (hw_port == port->index) {
                        result = 1;
@@ -1706,7 +1709,7 @@ int sdp_proc_dump_device(char *buffer, i
 /*
  * sdp_device_init_one - add a device to the list
  */
-static void sdp_device_init_one(struct ib_device *device)
+static struct ib_client_data *sdp_device_init_one(struct ib_device *device)
 {
        struct ib_fmr_pool_param fmr_param_s;
        struct sdev_hca_port *port, *tmp;
@@ -1719,13 +1722,14 @@ static void sdp_device_init_one(struct i
        hca = kmalloc(sizeof *hca, GFP_KERNEL);
        if (!hca) {
                sdp_warn("Error allocating HCA <%s> memory.", device->name);
-               return;
+               return NULL;
        }
        /*
         * init and insert into list.
         */
        memset(hca, 0, sizeof *hca);
 
+       hca->data.remove = sdp_device_remove_one;
        hca->ca = device;
        INIT_LIST_HEAD(&hca->port_list);
        /*
@@ -1801,9 +1805,7 @@ static void sdp_device_init_one(struct i
                }
        }
 
-       ib_set_client_data(device, &sdp_client, hca);
-
-       return;
+       return &hca->data;
 
 error:
        list_for_each_entry_safe(port, tmp, &hca->port_list, list) {
@@ -1821,22 +1823,19 @@ error:
                (void)ib_dealloc_pd(hca->pd);
 
        kfree(hca);
+       return NULL;
 }
 
 /*
  * sdp_device_remove_one - remove a device from the hca list
  */
-static void sdp_device_remove_one(struct ib_device *device)
+static void sdp_device_remove_one(struct ib_device *device,
+                                 struct ib_client_data *data)
 {
        struct sdev_hca_port *port, *tmp;
        struct sdev_hca *hca;
 
-       hca = ib_get_client_data(device, &sdp_client);
-
-       if (!hca) {
-               sdp_warn("Device <%s> has no HCA info.", device->name);
-               return;
-       }
+       hca = container_of(data, struct sdev_hca, data);
 
        list_for_each_entry_safe(port, tmp, &hca->port_list, list) {
                list_del(&port->list);
Index: linux-2.6.12.2/drivers/infiniband/ulp/srp/ib_srp.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/ulp/srp/ib_srp.c     2005-09-01 
00:41:10.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/ulp/srp/ib_srp.c  2005-09-01 
00:42:51.000000000 +0300
@@ -59,6 +59,11 @@ MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol driver");
 MODULE_LICENSE("Dual BSD/GPL");
 
+struct ib_srp_client_data {
+       struct ib_client_data data;
+       struct list_head list;
+};
+
 static int topspin_workarounds = 1;
 
 module_param(topspin_workarounds, int, 0444);
@@ -67,13 +72,12 @@ MODULE_PARM_DESC(topspin_workarounds,
 
 static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad };
 
-static void srp_add_one(struct ib_device *device);
-static void srp_remove_one(struct ib_device *device);
+static struct ib_client_data *srp_add_one(struct ib_device *device);
+static void srp_remove_one(struct ib_device *device, struct ib_client_data 
*data);
 
 static struct ib_client srp_client = {
        .name   = "srp",
        .add    = srp_add_one,
-       .remove = srp_remove_one
 };
 
 static inline struct srp_target_port *host_to_target(struct Scsi_Host *host)
@@ -1346,16 +1350,16 @@ err_free:
        return NULL;
 }
 
-static void srp_add_one(struct ib_device *device)
+static struct ib_client_data *srp_add_one(struct ib_device *device)
 {
-       struct list_head *dev_list;
+       struct ib_srp_client_data *dev_list = NULL;
        struct srp_host *host;
        struct ib_device_attr *dev_attr;
        int s, e, p;
 
        dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL);
        if (!dev_attr)
-               return;
+               return NULL;
 
        if (ib_query_device(device, dev_attr)) {
                printk(KERN_WARNING PFX "Couldn't query node GUID for %s.\n",
@@ -1367,7 +1371,8 @@ static void srp_add_one(struct ib_device
        if (!dev_list)
                goto out;
 
-       INIT_LIST_HEAD(dev_list);
+       dev_list->data.remove = srp_remove_one;
+       INIT_LIST_HEAD(&dev_list->list);
 
        if (device->node_type == IB_NODE_SWITCH) {
                s = 0;
@@ -1380,24 +1385,23 @@ static void srp_add_one(struct ib_device
        for (p = s; p <= e; ++p) {
                host = srp_add_port(device, dev_attr->node_guid, p);
                if (host)
-                       list_add_tail(&host->list, dev_list);
+                       list_add_tail(&host->list, &dev_list->list);
        }
 
-       ib_set_client_data(device, &srp_client, dev_list);
-
 out:
        kfree(dev_attr);
+       return dev_list ? &dev_list->data : NULL;
 }
 
-static void srp_remove_one(struct ib_device *device)
+static void srp_remove_one(struct ib_device *device, struct ib_client_data 
*data)
 {
-       struct list_head *dev_list;
+       struct ib_srp_client_data *dev_list;
        struct srp_host *host, *tmp_host;
        struct srp_target_port *target, *tmp_target;
 
-       dev_list = ib_get_client_data(device, &srp_client);
+       dev_list = container_of(data, struct ib_srp_client_data, data);
 
-       list_for_each_entry_safe(host, tmp_host, dev_list, list) {
+       list_for_each_entry_safe(host, tmp_host, &dev_list->list, list) {
                class_device_unregister(&host->class_dev);
                wait_for_completion(&host->released);
 
@@ -1416,6 +1420,7 @@ static void srp_remove_one(struct ib_dev
                ib_dealloc_pd(host->pd);
                kfree(host);
        }
+       kfree(dev_list);
 }
 
 static int __init srp_init_module(void)
Index: linux-2.6.12.2/drivers/infiniband/core/uverbs.h
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/core/uverbs.h        2005-09-01 
00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/uverbs.h     2005-09-01 
00:41:12.000000000 +0300
@@ -49,6 +49,7 @@
 #include <rdma/ib_user_verbs.h>
 
 struct ib_uverbs_device {
+       struct ib_client_data                   data;
        int                                     devnum;
        struct cdev                             dev;
        struct class_device                     class_dev;
Index: linux-2.6.12.2/drivers/infiniband/core/mad.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/core/mad.c   2005-09-01 
00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/mad.c        2005-09-01 
00:41:12.000000000 +0300
@@ -2681,7 +2681,7 @@ static int ib_mad_port_close(struct ib_d
        return 0;
 }
 
-static void ib_mad_init_device(struct ib_device *device)
+static struct ib_client_data *ib_mad_init_device(struct ib_device *device)
 {
        int num_ports, cur_port, i;
 
@@ -2705,7 +2705,7 @@ static void ib_mad_init_device(struct ib
                        goto error_device_open;
                }
        }
-       return;
+       return NULL;
 
 error_device_open:
        while (i > 0) {
@@ -2719,6 +2719,7 @@ error_device_open:
                               device->name, cur_port);
                i--;
        }
+       return NULL;
 }
 
 static void ib_mad_remove_device(struct ib_device *device)
Index: linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_dev.h
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/ulp/sdp/sdp_dev.h    2005-09-01 
00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_dev.h 2005-09-01 
00:41:12.000000000 +0300
@@ -154,6 +154,7 @@ struct sdev_hca_port {
 };
 
 struct sdev_hca {
+       struct ib_client_data data;
        struct ib_device     *ca;        /* HCA */
        struct ib_pd         *pd;        /* protection domain for this HCA */
        struct ib_mr         *mem_h;     /* registered memory region */
Index: linux-2.6.12.2/drivers/infiniband/ulp/ipoib/ipoib_main.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/ulp/ipoib/ipoib_main.c       
2005-09-01 00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/ulp/ipoib/ipoib_main.c    2005-09-01 
00:41:12.000000000 +0300
@@ -51,6 +51,11 @@ MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("IP-over-InfiniBand net driver");
 MODULE_LICENSE("Dual BSD/GPL");
 
+struct ipoib_client_data {
+       struct ib_client_data data;
+       struct list_head list;
+};
+
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
 int ipoib_debug_level;
 
@@ -67,13 +72,13 @@ static const u8 ipv4_bcast_addr[] = {
 struct workqueue_struct *ipoib_workqueue;
 struct workqueue_struct *ipoib_event_workqueue;
 
-static void ipoib_add_one(struct ib_device *device);
-static void ipoib_remove_one(struct ib_device *device);
+static struct ib_client_data *ipoib_add_one(struct ib_device *device);
+static void ipoib_remove_one(struct ib_device *device,
+                            struct ib_client_data *data);
 
 static struct ib_client ipoib_client = {
        .name   = "ipoib",
        .add    = ipoib_add_one,
-       .remove = ipoib_remove_one
 };
 
 int ipoib_open(struct net_device *dev)
@@ -1018,18 +1023,19 @@ alloc_mem_failed:
        return ERR_PTR(result);
 }
 
-static void ipoib_add_one(struct ib_device *device)
+static struct ib_client_data *ipoib_add_one(struct ib_device *device)
 {
-       struct list_head *dev_list;
+       struct ipoib_client_data *dev_list;
        struct net_device *dev;
        struct ipoib_dev_priv *priv;
        int s, e, p;
 
        dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
        if (!dev_list)
-               return;
+               return NULL;
 
-       INIT_LIST_HEAD(dev_list);
+       dev_list->data.remove = ipoib_remove_one;
+       INIT_LIST_HEAD(&dev_list->list);
 
        if (device->node_type == IB_NODE_SWITCH) {
                s = 0;
@@ -1043,21 +1049,22 @@ static void ipoib_add_one(struct ib_devi
                dev = ipoib_add_port("ib%d", device, p);
                if (!IS_ERR(dev)) {
                        priv = netdev_priv(dev);
-                       list_add_tail(&priv->list, dev_list);
+                       list_add_tail(&priv->list, &dev_list->list);
                }
        }
 
-       ib_set_client_data(device, &ipoib_client, dev_list);
+       return &dev_list->data;
 }
 
-static void ipoib_remove_one(struct ib_device *device)
+static void ipoib_remove_one(struct ib_device *device,
+                            struct ib_client_data *data)
 {
        struct ipoib_dev_priv *priv, *tmp;
-       struct list_head *dev_list;
+       struct ipoib_client_data *dev_list;
 
-       dev_list = ib_get_client_data(device, &ipoib_client);
+       dev_list = container_of(data, struct ipoib_client_data, data);
 
-       list_for_each_entry_safe(priv, tmp, dev_list, list) {
+       list_for_each_entry_safe(priv, tmp, &dev_list->list, list) {
                ib_unregister_event_handler(&priv->event_handler);
                flush_workqueue(ipoib_event_workqueue);
 
@@ -1065,6 +1072,7 @@ static void ipoib_remove_one(struct ib_d
                ipoib_dev_cleanup(priv->dev);
                free_netdev(priv->dev);
        }
+       kfree(dev_list);
 }
 
 static int __init ipoib_init_module(void)
Index: linux-2.6.12.2/drivers/infiniband/core/cache.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/core/cache.c 2005-09-01 
00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/cache.c      2005-09-01 
00:41:26.000000000 +0300
@@ -291,7 +291,7 @@ static void ib_cache_event(struct ib_eve
        }
 }
 
-static void ib_cache_setup_one(struct ib_device *device)
+static struct ib_client_data *ib_cache_setup_one(struct ib_device *device)
 {
        int p;
 
@@ -321,7 +321,7 @@ static void ib_cache_setup_one(struct ib
        if (ib_register_event_handler(&device->cache.event_handler))
                goto err_cache;
 
-       return;
+       return NULL;
 
 err_cache:
        for (p = 0; p <= end_port(device) - start_port(device); ++p) {
@@ -332,6 +332,7 @@ err_cache:
 err:
        kfree(device->cache.pkey_cache);
        kfree(device->cache.gid_cache);
+       return NULL;
 }
 
 static void ib_cache_cleanup_one(struct ib_device *device)
Index: linux-2.6.12.2/drivers/infiniband/core/uverbs_main.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/core/uverbs_main.c   2005-09-01 
00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/uverbs_main.c        2005-09-01 
00:42:20.000000000 +0300
@@ -101,8 +101,9 @@ static ssize_t (*uverbs_cmd_table[])(str
 
 static struct vfsmount *uverbs_event_mnt;
 
-static void ib_uverbs_add_one(struct ib_device *device);
-static void ib_uverbs_remove_one(struct ib_device *device);
+static struct ib_client_data *ib_uverbs_add_one(struct ib_device *device);
+static void ib_uverbs_remove_one(struct ib_device *device,
+                                struct ib_client_data *data);
 
 static int ib_dealloc_ucontext(struct ib_ucontext *context)
 {
@@ -539,7 +540,6 @@ static struct file_operations uverbs_mma
 static struct ib_client uverbs_client = {
        .name   = "uverbs",
        .add    = ib_uverbs_add_one,
-       .remove = ib_uverbs_remove_one
 };
 
 static ssize_t show_dev(struct class_device *class_dev, char *buf)
@@ -581,19 +581,21 @@ static ssize_t show_abi_version(struct c
 }
 static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
 
-static void ib_uverbs_add_one(struct ib_device *device)
+static struct ib_client_data *ib_uverbs_add_one(struct ib_device *device)
 {
        struct ib_uverbs_device *uverbs_dev;
 
        if (!device->alloc_ucontext)
-               return;
+               return NULL;
 
        uverbs_dev = kmalloc(sizeof *uverbs_dev, GFP_KERNEL);
        if (!uverbs_dev)
-               return;
+               return NULL;
 
        memset(uverbs_dev, 0, sizeof *uverbs_dev);
 
+       uverbs_dev->data.remove = ib_uverbs_remove_one;
+
        spin_lock(&map_lock);
        uverbs_dev->devnum = find_first_zero_bit(dev_map, 
IB_UVERBS_MAX_DEVICES);
        if (uverbs_dev->devnum >= IB_UVERBS_MAX_DEVICES) {
@@ -626,9 +628,7 @@ static void ib_uverbs_add_one(struct ib_
        if (class_device_create_file(&uverbs_dev->class_dev, 
&class_device_attr_ibdev))
                goto err_class;
 
-       ib_set_client_data(device, &uverbs_client, uverbs_dev);
-
-       return;
+       return &uverbs_dev->data;
 
 err_class:
        class_device_unregister(&uverbs_dev->class_dev);
@@ -639,15 +639,14 @@ err_cdev:
 
 err:
        kfree(uverbs_dev);
-       return;
+       return NULL;
 }
 
-static void ib_uverbs_remove_one(struct ib_device *device)
+static void ib_uverbs_remove_one(struct ib_device *device,
+                                struct ib_client_data *data)
 {
-       struct ib_uverbs_device *uverbs_dev = ib_get_client_data(device, 
&uverbs_client);
-
-       if (!uverbs_dev)
-               return;
+       struct ib_uverbs_device *uverbs_dev;
+       uverbs_dev = container_of(data, struct ib_uverbs_device, data);
 
        class_device_unregister(&uverbs_dev->class_dev);
 }
Index: linux-2.6.12.2/drivers/infiniband/core/ping.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/core/ping.c  2005-09-01 
00:40:39.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/ping.c       2005-09-01 
00:41:12.000000000 +0300
@@ -245,7 +245,7 @@ static int ib_ping_port_close(struct ib_
        return 0;
 }
 
-static void ib_ping_init_device(struct ib_device *device)
+static struct ib_client_data *ib_ping_init_device(struct ib_device *device)
 {
        int num_ports, cur_port, i;
 
@@ -263,7 +263,7 @@ static void ib_ping_init_device(struct i
                               device->name, cur_port);
                        goto error_device_open;
        }
-       return;
+       return NULL;
 
 error_device_open:
        while (i > 0) {
@@ -274,6 +274,7 @@ error_device_open:
                               device->name, cur_port);
                i--;
        }
+       return NULL;
 }
 
 static void ib_ping_remove_device(struct ib_device *device)

-- 
MST
_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to