Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 195105
b: refs/heads/master
c: f22cf68
h: refs/heads/master
i:
  195103: 4b225d7
v: v3
  • Loading branch information
Cindy H Kao authored and Inaky Perez-Gonzalez committed May 11, 2010
1 parent 3fa6ed3 commit ac70ab7
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 9 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: 570eb0ea65db625e0b11ca97f4ae857bc1193250
refs/heads/master: f22cf689a6353f072bca15d0a26f870e62dfacf8
5 changes: 4 additions & 1 deletion trunk/drivers/net/wimax/i2400m/i2400m-sdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ enum {
*
* @tx_workqueue: workqeueue used for data TX; we don't use the
* system's workqueue as that might cause deadlocks with code in
* the bus-generic driver.
* the bus-generic driver. The read/write operation to the queue
* is protected with spinlock (tx_lock in struct i2400m) to avoid
* the queue being destroyed in the middle of a the queue read/write
* operation.
*
* @debugfs_dentry: dentry for the SDIO specific debugfs files
*
Expand Down
31 changes: 24 additions & 7 deletions trunk/drivers/net/wimax/i2400m/sdio-tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,17 @@ void i2400ms_bus_tx_kick(struct i2400m *i2400m)
{
struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
struct device *dev = &i2400ms->func->dev;
unsigned long flags;

d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m);

/* schedule tx work, this is because tx may block, therefore
* it has to run in a thread context.
*/
queue_work(i2400ms->tx_workqueue, &i2400ms->tx_worker);
spin_lock_irqsave(&i2400m->tx_lock, flags);
if (i2400ms->tx_workqueue != NULL)
queue_work(i2400ms->tx_workqueue, &i2400ms->tx_worker);
spin_unlock_irqrestore(&i2400m->tx_lock, flags);

d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
}
Expand All @@ -130,27 +134,40 @@ int i2400ms_tx_setup(struct i2400ms *i2400ms)
int result;
struct device *dev = &i2400ms->func->dev;
struct i2400m *i2400m = &i2400ms->i2400m;
struct workqueue_struct *tx_workqueue;
unsigned long flags;

d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);

INIT_WORK(&i2400ms->tx_worker, i2400ms_tx_submit);
snprintf(i2400ms->tx_wq_name, sizeof(i2400ms->tx_wq_name),
"%s-tx", i2400m->wimax_dev.name);
i2400ms->tx_workqueue =
tx_workqueue =
create_singlethread_workqueue(i2400ms->tx_wq_name);
if (NULL == i2400ms->tx_workqueue) {
if (tx_workqueue == NULL) {
dev_err(dev, "TX: failed to create workqueue\n");
result = -ENOMEM;
} else
result = 0;
spin_lock_irqsave(&i2400m->tx_lock, flags);
i2400ms->tx_workqueue = tx_workqueue;
spin_unlock_irqrestore(&i2400m->tx_lock, flags);
d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
return result;
}

void i2400ms_tx_release(struct i2400ms *i2400ms)
{
if (i2400ms->tx_workqueue) {
destroy_workqueue(i2400ms->tx_workqueue);
i2400ms->tx_workqueue = NULL;
}
struct i2400m *i2400m = &i2400ms->i2400m;
struct workqueue_struct *tx_workqueue;
unsigned long flags;

tx_workqueue = i2400ms->tx_workqueue;

spin_lock_irqsave(&i2400m->tx_lock, flags);
i2400ms->tx_workqueue = NULL;
spin_unlock_irqrestore(&i2400m->tx_lock, flags);

if (tx_workqueue)
destroy_workqueue(tx_workqueue);
}

0 comments on commit ac70ab7

Please sign in to comment.