Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 9323
b: refs/heads/master
c: acd042b
h: refs/heads/master
i:
  9321: 54a1cdc
  9319: f713a74
v: v3
  • Loading branch information
Evgeniy Polyakov authored and David S. Miller committed Sep 26, 2005
1 parent e9c125e commit 8ab4c16
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 56 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b9d717a7b413f227ebb2d61d9c118335f7292137
refs/heads/master: acd042bb2de50d4e6fb969281a00cc8b8b71e46d
32 changes: 19 additions & 13 deletions trunk/drivers/connector/cn_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,19 @@
#include <linux/connector.h>
#include <linux/delay.h>

static void cn_queue_wrapper(void *data)
void cn_queue_wrapper(void *data)
{
struct cn_callback_entry *cbq = data;
struct cn_callback_data *d = data;

cbq->cb->callback(cbq->cb->priv);
cbq->destruct_data(cbq->ddata);
cbq->ddata = NULL;
d->callback(d->callback_priv);

d->destruct_data(d->ddata);
d->ddata = NULL;

kfree(d->free);
}

static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callback *cb)
static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struct cb_id *id, void (*callback)(void *))
{
struct cn_callback_entry *cbq;

Expand All @@ -50,8 +53,11 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callbac
return NULL;
}

cbq->cb = cb;
INIT_WORK(&cbq->work, &cn_queue_wrapper, cbq);
snprintf(cbq->id.name, sizeof(cbq->id.name), "%s", name);
memcpy(&cbq->id.id, id, sizeof(struct cb_id));
cbq->data.callback = callback;

INIT_WORK(&cbq->work, &cn_queue_wrapper, &cbq->data);
return cbq;
}

Expand All @@ -68,12 +74,12 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
return ((i1->idx == i2->idx) && (i1->val == i2->val));
}

int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)
int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *))
{
struct cn_callback_entry *cbq, *__cbq;
int found = 0;

cbq = cn_queue_alloc_callback_entry(cb);
cbq = cn_queue_alloc_callback_entry(name, id, callback);
if (!cbq)
return -ENOMEM;

Expand All @@ -82,7 +88,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)

spin_lock_bh(&dev->queue_lock);
list_for_each_entry(__cbq, &dev->queue_list, callback_entry) {
if (cn_cb_equal(&__cbq->cb->id, &cb->id)) {
if (cn_cb_equal(&__cbq->id.id, id)) {
found = 1;
break;
}
Expand All @@ -99,7 +105,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)

cbq->nls = dev->nls;
cbq->seq = 0;
cbq->group = cbq->cb->id.idx;
cbq->group = cbq->id.id.idx;

return 0;
}
Expand All @@ -111,7 +117,7 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id)

spin_lock_bh(&dev->queue_lock);
list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) {
if (cn_cb_equal(&cbq->cb->id, id)) {
if (cn_cb_equal(&cbq->id.id, id)) {
list_del(&cbq->callback_entry);
found = 1;
break;
Expand Down
74 changes: 38 additions & 36 deletions trunk/drivers/connector/connector.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask)
spin_lock_bh(&dev->cbdev->queue_lock);
list_for_each_entry(__cbq, &dev->cbdev->queue_list,
callback_entry) {
if (cn_cb_equal(&__cbq->cb->id, &msg->id)) {
if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
found = 1;
group = __cbq->group;
}
Expand Down Expand Up @@ -127,42 +127,56 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
{
struct cn_callback_entry *__cbq;
struct cn_dev *dev = &cdev;
int found = 0;
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->cb->id, &msg->id)) {
/*
* Let's scream if there is some magic and the
* data will arrive asynchronously here.
* [i.e. netlink messages will be queued].
* After the first warning I will fix it
* quickly, but now I think it is
* impossible. --zbr (2004_04_27).
*/
if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
if (likely(!test_bit(0, &__cbq->work.pending) &&
__cbq->ddata == NULL)) {
__cbq->cb->priv = msg;
__cbq->data.ddata == NULL)) {
__cbq->data.callback_priv = msg;

__cbq->ddata = data;
__cbq->destruct_data = destruct_data;
__cbq->data.ddata = data;
__cbq->data.destruct_data = destruct_data;

if (queue_work(dev->cbdev->cn_queue,
&__cbq->work))
found = 1;
err = 0;
} else {
printk("%s: cbq->data=%p, "
"work->pending=%08lx.\n",
__func__, __cbq->ddata,
__cbq->work.pending);
WARN_ON(1);
struct work_struct *w;
struct cn_callback_data *d;

w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC);
if (w) {
d = (struct cn_callback_data *)(w+1);

d->callback_priv = msg;
d->callback = __cbq->data.callback;
d->ddata = data;
d->destruct_data = destruct_data;
d->free = w;

INIT_LIST_HEAD(&w->entry);
w->pending = 0;
w->func = &cn_queue_wrapper;
w->data = d;
init_timer(&w->timer);

if (queue_work(dev->cbdev->cn_queue, w))
err = 0;
else {
kfree(w);
err = -EINVAL;
}
} else
err = -ENOMEM;
}
break;
}
}
spin_unlock_bh(&dev->cbdev->queue_lock);

return found ? 0 : -ENODEV;
return err;
}

/*
Expand Down Expand Up @@ -291,22 +305,10 @@ int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
{
int err;
struct cn_dev *dev = &cdev;
struct cn_callback *cb;

cb = kzalloc(sizeof(*cb), GFP_KERNEL);
if (!cb)
return -ENOMEM;

scnprintf(cb->name, sizeof(cb->name), "%s", name);

memcpy(&cb->id, id, sizeof(cb->id));
cb->callback = callback;

err = cn_queue_add_callback(dev->cbdev, cb);
if (err) {
kfree(cb);
err = cn_queue_add_callback(dev->cbdev, name, id, callback);
if (err)
return err;
}

cn_notify(id, 0);

Expand Down
21 changes: 15 additions & 6 deletions trunk/include/linux/connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,19 @@ struct cn_queue_dev {
struct sock *nls;
};

struct cn_callback {
struct cn_callback_id {
unsigned char name[CN_CBQ_NAMELEN];

struct cb_id id;
};

struct cn_callback_data {
void (*destruct_data) (void *);
void *ddata;

void *callback_priv;
void (*callback) (void *);
void *priv;

void *free;
};

struct cn_callback_entry {
Expand All @@ -118,8 +125,8 @@ struct cn_callback_entry {
struct work_struct work;
struct cn_queue_dev *pdev;

void (*destruct_data) (void *);
void *ddata;
struct cn_callback_id id;
struct cn_callback_data data;

int seq, group;
struct sock *nls;
Expand All @@ -144,14 +151,16 @@ int cn_add_callback(struct cb_id *, char *, void (*callback) (void *));
void cn_del_callback(struct cb_id *);
int cn_netlink_send(struct cn_msg *, u32, int);

int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb);
int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *));
void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id);

struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *);
void cn_queue_free_dev(struct cn_queue_dev *dev);

int cn_cb_equal(struct cb_id *, struct cb_id *);

void cn_queue_wrapper(void *data);

extern int cn_already_initialized;

#endif /* __KERNEL__ */
Expand Down

0 comments on commit 8ab4c16

Please sign in to comment.