[openib-general] [PATCH] hotplug support: selective removal notification
Michael S. Tsirkin
mst at mellanox.co.il
Wed Aug 31 09:20:20 PDT 2005
Hi!
As Sean pointed out, in the existing client registration
the client gets removal events even from devices which it
may not be interested in.
As a way of solving this, I propose the following patch.
The idea is that instead of setting client context separately
with ib_set_client_data, client's add method will return
ib_client_data object which is then kept in a per-device list.
Returning NULL signals that the client will not be interested
in this device.
Removing the device walks this list and only calls the clients
that returned non-NULL object on add.
In this way most ulps can now use container_of to get their
context in the remove method, instead of scanning the client list
each time, which in my opinion is very nice.
I updated sdp,srp,ipoib for this API change.
I can split ULPs to separate patches if needed.
Let me know,
MST
---
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>
core/cache.c | 18 +++++--
core/cm.c | 19 +++----
core/device.c | 122 ++++++++++++++++--------------------------------
core/mad.c | 18 +++++--
core/ping.c | 15 ++++-
core/sa_query.c | 36 +++++++-------
core/user_mad.c | 29 +++++------
core/uverbs.h | 1
core/uverbs_main.c | 26 ++++------
include/rdma/ib_verbs.h | 16 ++++--
ulp/ipoib/ipoib_main.c | 32 +++++++-----
ulp/sdp/sdp_conn.c | 31 +++++-------
ulp/sdp/sdp_dev.h | 1
ulp/srp/ib_srp.c | 31 +++++++-----
14 files changed, 203 insertions(+), 192 deletions(-)
Index: linux-2.6.12.2/drivers/infiniband/core/device.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/core/device.c 2005-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/device.c 2005-08-31 21:07:15.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:
@@ -280,26 +258,29 @@ 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.next,
+ typeof(*context), list);
+ list_del(&context->list);
+ spin_unlock_irqrestore(&device->client_data_lock, flags);
+ if (context->client->remove)
+ context->client->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 +299,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,23 +330,25 @@ 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;
down(&device_sem);
list_for_each_entry(device, &device_list, core_list) {
- if (client->remove)
- 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);
+ if (client->remove)
+ client->remove(device, context);
+ spin_lock_irqsave(&device->client_data_lock, flags);
+ break;
}
spin_unlock_irqrestore(&device->client_data_lock, flags);
+
}
list_del(&client->list);
@@ -375,16 +364,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 +384,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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/include/rdma/ib_verbs.h 2005-08-31 21:07:15.000000000 +0300
@@ -956,14 +956,21 @@ struct ib_device {
u8 phys_port_cnt;
};
+struct ib_client_data;
+
struct ib_client {
char *name;
- void (*add) (struct ib_device *);
- void (*remove)(struct ib_device *);
+ struct ib_client_data *(*add) (struct ib_device *);
+ void (*remove)(struct ib_device *, struct ib_client_data *);
struct list_head list;
};
+struct ib_client_data {
+ struct list_head list;
+ struct ib_client *client;
+};
+
struct ib_device *ib_alloc_device(size_t size);
void ib_dealloc_device(struct ib_device *device);
@@ -973,9 +980,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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/user_mad.c 2005-08-31 21:07:15.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,
@@ -819,7 +821,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,7 +837,7 @@ 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));
@@ -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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/cm.c 2005-08-31 21:07:15.000000000 +0300
@@ -51,8 +51,8 @@ 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",
@@ -81,6 +81,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 +3195,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,7 +3213,7 @@ 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->device = device;
cm_dev->ca_guid = cm_get_ca_guid(device);
@@ -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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/sa_query.c 2005-08-31 21:07:15.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,8 +99,8 @@ 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",
@@ -426,13 +427,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 +610,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 +713,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 +797,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 +905,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,7 +921,7 @@ 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->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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_conn.c 2005-08-31 21:07:15.000000000 +0300
@@ -37,8 +37,9 @@
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",
@@ -959,6 +960,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 +971,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 +1710,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,7 +1723,7 @@ 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.
@@ -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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/ulp/srp/ib_srp.c 2005-08-31 21:09:37.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,8 +72,8 @@ 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",
@@ -1335,16 +1340,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",
@@ -1356,7 +1361,7 @@ static void srp_add_one(struct ib_device
if (!dev_list)
goto out;
- INIT_LIST_HEAD(dev_list);
+ INIT_LIST_HEAD(&dev_list->list);
if (device->node_type == IB_NODE_SWITCH) {
s = 0;
@@ -1369,24 +1374,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);
@@ -1405,6 +1409,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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/uverbs.h 2005-08-31 21:07:15.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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/mad.c 2005-08-31 21:07:15.000000000 +0300
@@ -2681,10 +2681,18 @@ 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)
{
+ struct ib_client_data *data;
int num_ports, cur_port, i;
+ data = kmalloc(sizeof *data, GFP_KERNEL);
+ if (!data) {
+ printk(KERN_ERR PFX "Couldn't allocate memory for device %s\n",
+ device->name);
+ return NULL;
+ }
+
if (device->node_type == IB_NODE_SWITCH) {
num_ports = 1;
cur_port = 0;
@@ -2705,7 +2713,7 @@ static void ib_mad_init_device(struct ib
goto error_device_open;
}
}
- return;
+ return data;
error_device_open:
while (i > 0) {
@@ -2719,11 +2727,15 @@ error_device_open:
device->name, cur_port);
i--;
}
+ kfree(data);
+ return NULL;
}
-static void ib_mad_remove_device(struct ib_device *device)
+static void ib_mad_remove_device(struct ib_device *device,
+ struct ib_client_data *data)
{
int i, num_ports, cur_port;
+ kfree(data);
if (device->node_type == IB_NODE_SWITCH) {
num_ports = 1;
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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_dev.h 2005-08-31 21:07:15.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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/ulp/ipoib/ipoib_main.c 2005-08-31 21:07:15.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,8 +72,9 @@ 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",
@@ -1018,18 +1024,18 @@ 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);
+ 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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/cache.c 2005-08-31 21:07:15.000000000 +0300
@@ -291,10 +291,18 @@ 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)
{
+ struct ib_client_data *data;
int p;
+ data = kmalloc(sizeof *data, GFP_KERNEL);
+ if (!data) {
+ printk(KERN_WARNING "Couldn't allocate client data "
+ "for %s\n", device->name);
+ return NULL;
+ }
+
rwlock_init(&device->cache.lock);
device->cache.pkey_cache =
@@ -321,7 +329,7 @@ static void ib_cache_setup_one(struct ib
if (ib_register_event_handler(&device->cache.event_handler))
goto err_cache;
- return;
+ return data;
err_cache:
for (p = 0; p <= end_port(device) - start_port(device); ++p) {
@@ -332,9 +340,12 @@ err_cache:
err:
kfree(device->cache.pkey_cache);
kfree(device->cache.gid_cache);
+ kfree(data);
+ return NULL;
}
-static void ib_cache_cleanup_one(struct ib_device *device)
+static void ib_cache_cleanup_one(struct ib_device *device,
+ struct ib_client_data *data)
{
int p;
@@ -348,6 +359,7 @@ static void ib_cache_cleanup_one(struct
kfree(device->cache.pkey_cache);
kfree(device->cache.gid_cache);
+ kfree(data);
}
static struct ib_client cache_client = {
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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/uverbs_main.c 2005-08-31 21:07:15.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)
{
@@ -581,16 +582,16 @@ 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);
@@ -626,9 +627,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 +638,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-08-31 21:06:55.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/core/ping.c 2005-08-31 21:07:15.000000000 +0300
@@ -245,9 +245,10 @@ 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;
+ struct ib_client_data *data;
if (device->node_type == IB_NODE_SWITCH) {
num_ports = 1;
@@ -263,7 +264,11 @@ static void ib_ping_init_device(struct i
device->name, cur_port);
goto error_device_open;
}
- return;
+
+ data = kmalloc(sizeof *data, GFP_KERNEL);
+ if (!data)
+ goto error_device_open;
+ return data;
error_device_open:
while (i > 0) {
@@ -274,12 +279,16 @@ error_device_open:
device->name, cur_port);
i--;
}
+ return NULL;
}
-static void ib_ping_remove_device(struct ib_device *device)
+static void ib_ping_remove_device(struct ib_device *device,
+ struct ib_client_data *data)
{
int i, num_ports, cur_port;
+ kfree(data);
+
if (device->node_type == IB_NODE_SWITCH) {
num_ports = 1;
cur_port = 0;
--
MST
More information about the general
mailing list