[openib-general] Re: [PATCH] hotplug support: selective removal notification
Michael S. Tsirkin
mst at mellanox.co.il
Wed Aug 31 12:59:12 PDT 2005
Quoting r. Roland Dreier <rolandd at cisco.com>:
> 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 <mst at mellanox.co.il>
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
More information about the general
mailing list