diff options
Diffstat (limited to 'drivers/connector/connector.c')
| -rw-r--r-- | drivers/connector/connector.c | 47 | 
1 files changed, 12 insertions, 35 deletions
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index f7554de3be5e..d77005849af8 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -122,51 +122,28 @@ 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); +	} +  	return err;  }  |