Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[pandora-kernel.git] / drivers / connector / connector.c
index f7554de..219d88a 100644 (file)
@@ -122,51 +122,29 @@ EXPORT_SYMBOL_GPL(cn_netlink_send);
  */
 static int cn_call_callback(struct sk_buff *skb)
 {
-       struct cn_callback_entry *__cbq, *__new_cbq;
+       struct cn_callback_entry *i, *cbq = NULL;
        struct cn_dev *dev = &cdev;
        struct cn_msg *msg = NLMSG_DATA(nlmsg_hdr(skb));
+       struct netlink_skb_parms *nsp = &NETLINK_CB(skb);
        int err = -ENODEV;
 
        spin_lock_bh(&dev->cbdev->queue_lock);
-       list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
-               if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
-                       if (likely(!work_pending(&__cbq->work) &&
-                                       __cbq->data.skb == NULL)) {
-                               __cbq->data.skb = skb;
-
-                               if (queue_work(dev->cbdev->cn_queue,
-                                              &__cbq->work))
-                                       err = 0;
-                               else
-                                       err = -EINVAL;
-                       } else {
-                               struct cn_callback_data *d;
-
-                               err = -ENOMEM;
-                               __new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC);
-                               if (__new_cbq) {
-                                       d = &__new_cbq->data;
-                                       d->skb = skb;
-                                       d->callback = __cbq->data.callback;
-                                       d->free = __new_cbq;
-
-                                       INIT_WORK(&__new_cbq->work,
-                                                       &cn_queue_wrapper);
-
-                                       if (queue_work(dev->cbdev->cn_queue,
-                                                      &__new_cbq->work))
-                                               err = 0;
-                                       else {
-                                               kfree(__new_cbq);
-                                               err = -EINVAL;
-                                       }
-                               }
-                       }
+       list_for_each_entry(i, &dev->cbdev->queue_list, callback_entry) {
+               if (cn_cb_equal(&i->id.id, &msg->id)) {
+                       atomic_inc(&i->refcnt);
+                       cbq = i;
                        break;
                }
        }
        spin_unlock_bh(&dev->cbdev->queue_lock);
 
+       if (cbq != NULL) {
+               cbq->callback(msg, nsp);
+               kfree_skb(skb);
+               cn_queue_release_callback(cbq);
+               err = 0;
+       }
+
        return err;
 }