aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/connector/connector.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/connector/connector.c')
-rw-r--r--drivers/connector/connector.c74
1 files changed, 38 insertions, 36 deletions
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index aaf6d468a8b9..bb0b3a8de14b 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -84,7 +84,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask)
84 spin_lock_bh(&dev->cbdev->queue_lock); 84 spin_lock_bh(&dev->cbdev->queue_lock);
85 list_for_each_entry(__cbq, &dev->cbdev->queue_list, 85 list_for_each_entry(__cbq, &dev->cbdev->queue_list,
86 callback_entry) { 86 callback_entry) {
87 if (cn_cb_equal(&__cbq->cb->id, &msg->id)) { 87 if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
88 found = 1; 88 found = 1;
89 group = __cbq->group; 89 group = __cbq->group;
90 } 90 }
@@ -127,42 +127,56 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
127{ 127{
128 struct cn_callback_entry *__cbq; 128 struct cn_callback_entry *__cbq;
129 struct cn_dev *dev = &cdev; 129 struct cn_dev *dev = &cdev;
130 int found = 0; 130 int err = -ENODEV;
131 131
132 spin_lock_bh(&dev->cbdev->queue_lock); 132 spin_lock_bh(&dev->cbdev->queue_lock);
133 list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) { 133 list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
134 if (cn_cb_equal(&__cbq->cb->id, &msg->id)) { 134 if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
135 /*
136 * Let's scream if there is some magic and the
137 * data will arrive asynchronously here.
138 * [i.e. netlink messages will be queued].
139 * After the first warning I will fix it
140 * quickly, but now I think it is
141 * impossible. --zbr (2004_04_27).
142 */
143 if (likely(!test_bit(0, &__cbq->work.pending) && 135 if (likely(!test_bit(0, &__cbq->work.pending) &&
144 __cbq->ddata == NULL)) { 136 __cbq->data.ddata == NULL)) {
145 __cbq->cb->priv = msg; 137 __cbq->data.callback_priv = msg;
146 138
147 __cbq->ddata = data; 139 __cbq->data.ddata = data;
148 __cbq->destruct_data = destruct_data; 140 __cbq->data.destruct_data = destruct_data;
149 141
150 if (queue_work(dev->cbdev->cn_queue, 142 if (queue_work(dev->cbdev->cn_queue,
151 &__cbq->work)) 143 &__cbq->work))
152 found = 1; 144 err = 0;
153 } else { 145 } else {
154 printk("%s: cbq->data=%p, " 146 struct work_struct *w;
155 "work->pending=%08lx.\n", 147 struct cn_callback_data *d;
156 __func__, __cbq->ddata, 148
157 __cbq->work.pending); 149 w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC);
158 WARN_ON(1); 150 if (w) {
151 d = (struct cn_callback_data *)(w+1);
152
153 d->callback_priv = msg;
154 d->callback = __cbq->data.callback;
155 d->ddata = data;
156 d->destruct_data = destruct_data;
157 d->free = w;
158
159 INIT_LIST_HEAD(&w->entry);
160 w->pending = 0;
161 w->func = &cn_queue_wrapper;
162 w->data = d;
163 init_timer(&w->timer);
164
165 if (queue_work(dev->cbdev->cn_queue, w))
166 err = 0;
167 else {
168 kfree(w);
169 err = -EINVAL;
170 }
171 } else
172 err = -ENOMEM;
159 } 173 }
160 break; 174 break;
161 } 175 }
162 } 176 }
163 spin_unlock_bh(&dev->cbdev->queue_lock); 177 spin_unlock_bh(&dev->cbdev->queue_lock);
164 178
165 return found ? 0 : -ENODEV; 179 return err;
166} 180}
167 181
168/* 182/*
@@ -291,22 +305,10 @@ int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
291{ 305{
292 int err; 306 int err;
293 struct cn_dev *dev = &cdev; 307 struct cn_dev *dev = &cdev;
294 struct cn_callback *cb;
295
296 cb = kzalloc(sizeof(*cb), GFP_KERNEL);
297 if (!cb)
298 return -ENOMEM;
299
300 scnprintf(cb->name, sizeof(cb->name), "%s", name);
301 308
302 memcpy(&cb->id, id, sizeof(cb->id)); 309 err = cn_queue_add_callback(dev->cbdev, name, id, callback);
303 cb->callback = callback; 310 if (err)
304
305 err = cn_queue_add_callback(dev->cbdev, cb);
306 if (err) {
307 kfree(cb);
308 return err; 311 return err;
309 }
310 312
311 cn_notify(id, 0); 313 cn_notify(id, 0);
312 314