Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 171220
b: refs/heads/master
c: ac53aed
h: refs/heads/master
v: v3
  • Loading branch information
Inaky Perez-Gonzalez committed Oct 19, 2009
1 parent 69da321 commit aa3e0e2
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 21 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: cb5b756f746b77c5323ae413a41e9a40ea33c453
refs/heads/master: ac53aed9349242095a780f57ac0c995fb170c950
1 change: 1 addition & 0 deletions trunk/drivers/net/wimax/i2400m/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ void __i2400m_dev_stop(struct i2400m *i2400m)

d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING);
i2400m_net_wake_stop(i2400m);
i2400m_dev_shutdown(i2400m);
i2400m->ready = 0;
i2400m->bus_dev_stop(i2400m);
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/net/wimax/i2400m/i2400m.h
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,7 @@ extern void i2400m_net_rx(struct i2400m *, struct sk_buff *, unsigned,
const void *, int);
extern void i2400m_net_erx(struct i2400m *, struct sk_buff *,
enum i2400m_cs);
extern void i2400m_net_wake_stop(struct i2400m *);
enum i2400m_pt;
extern int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt);

Expand Down
53 changes: 33 additions & 20 deletions trunk/drivers/net/wimax/i2400m/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,33 +113,14 @@ int i2400m_open(struct net_device *net_dev)
}


/*
*
* On kernel versions where cancel_work_sync() didn't return anything,
* we rely on wake_tx_skb() being non-NULL.
*/
static
int i2400m_stop(struct net_device *net_dev)
{
struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
struct device *dev = i2400m_dev(i2400m);

d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m);
/* See i2400m_hard_start_xmit(), references are taken there
* and here we release them if the work was still
* pending. Note we can't differentiate work not pending vs
* never scheduled, so the NULL check does that. */
if (cancel_work_sync(&i2400m->wake_tx_ws) == 0
&& i2400m->wake_tx_skb != NULL) {
unsigned long flags;
struct sk_buff *wake_tx_skb;
spin_lock_irqsave(&i2400m->tx_lock, flags);
wake_tx_skb = i2400m->wake_tx_skb; /* compat help */
i2400m->wake_tx_skb = NULL; /* compat help */
spin_unlock_irqrestore(&i2400m->tx_lock, flags);
i2400m_put(i2400m);
kfree_skb(wake_tx_skb);
}
i2400m_net_wake_stop(i2400m);
d_fnend(3, dev, "(net_dev %p [i2400m %p]) = 0\n", net_dev, i2400m);
return 0;
}
Expand Down Expand Up @@ -230,6 +211,38 @@ void i2400m_tx_prep_header(struct sk_buff *skb)
}



/*
* Cleanup resources acquired during i2400m_net_wake_tx()
*
* This is called by __i2400m_dev_stop and means we have to make sure
* the workqueue is flushed from any pending work.
*/
void i2400m_net_wake_stop(struct i2400m *i2400m)
{
struct device *dev = i2400m_dev(i2400m);

d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
/* See i2400m_hard_start_xmit(), references are taken there
* and here we release them if the work was still
* pending. Note we can't differentiate work not pending vs
* never scheduled, so the NULL check does that. */
if (cancel_work_sync(&i2400m->wake_tx_ws) == 0
&& i2400m->wake_tx_skb != NULL) {
unsigned long flags;
struct sk_buff *wake_tx_skb;
spin_lock_irqsave(&i2400m->tx_lock, flags);
wake_tx_skb = i2400m->wake_tx_skb; /* compat help */
i2400m->wake_tx_skb = NULL; /* compat help */
spin_unlock_irqrestore(&i2400m->tx_lock, flags);
i2400m_put(i2400m);
kfree_skb(wake_tx_skb);
}
d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
return;
}


/*
* TX an skb to an idle device
*
Expand Down

0 comments on commit aa3e0e2

Please sign in to comment.