diff options
Diffstat (limited to 'drivers/connector/connector.c')
-rw-r--r-- | drivers/connector/connector.c | 74 |
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 | ||