diff options
author | Rémi Denis-Courmont <remi.denis-courmont@nokia.com> | 2008-12-15 03:53:57 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-15 03:53:57 -0500 |
commit | 4798a2b84ea5a98e4f36a815a646cb48ff521684 (patch) | |
tree | 353906b8ef910b62ef3ba9c6bc2d71a5db3bc974 | |
parent | eb9b851b980e20ba5f6bdfd6ec24f4bc77623ce6 (diff) |
Phonet: keep TX queue disabled when the device is off
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/phonet/pep-gprs.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c index 9978afbd9f2a..803eeef0aa85 100644 --- a/net/phonet/pep-gprs.c +++ b/net/phonet/pep-gprs.c | |||
@@ -155,12 +155,13 @@ static void gprs_data_ready(struct sock *sk, int len) | |||
155 | static void gprs_write_space(struct sock *sk) | 155 | static void gprs_write_space(struct sock *sk) |
156 | { | 156 | { |
157 | struct gprs_dev *dev = sk->sk_user_data; | 157 | struct gprs_dev *dev = sk->sk_user_data; |
158 | struct net_device *net = dev->net; | ||
158 | unsigned credits = pep_writeable(sk); | 159 | unsigned credits = pep_writeable(sk); |
159 | 160 | ||
160 | spin_lock_bh(&dev->tx_lock); | 161 | spin_lock_bh(&dev->tx_lock); |
161 | dev->tx_max = credits; | 162 | dev->tx_max = credits; |
162 | if (credits > skb_queue_len(&dev->tx_queue)) | 163 | if (credits > skb_queue_len(&dev->tx_queue) && netif_running(net)) |
163 | netif_wake_queue(dev->net); | 164 | netif_wake_queue(net); |
164 | spin_unlock_bh(&dev->tx_lock); | 165 | spin_unlock_bh(&dev->tx_lock); |
165 | } | 166 | } |
166 | 167 | ||
@@ -168,6 +169,23 @@ static void gprs_write_space(struct sock *sk) | |||
168 | * Network device callbacks | 169 | * Network device callbacks |
169 | */ | 170 | */ |
170 | 171 | ||
172 | static int gprs_open(struct net_device *dev) | ||
173 | { | ||
174 | struct gprs_dev *gp = netdev_priv(dev); | ||
175 | |||
176 | gprs_write_space(gp->sk); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int gprs_close(struct net_device *dev) | ||
181 | { | ||
182 | struct gprs_dev *gp = netdev_priv(dev); | ||
183 | |||
184 | netif_stop_queue(dev); | ||
185 | flush_work(&gp->tx_work); | ||
186 | return 0; | ||
187 | } | ||
188 | |||
171 | static int gprs_xmit(struct sk_buff *skb, struct net_device *net) | 189 | static int gprs_xmit(struct sk_buff *skb, struct net_device *net) |
172 | { | 190 | { |
173 | struct gprs_dev *dev = netdev_priv(net); | 191 | struct gprs_dev *dev = netdev_priv(net); |
@@ -254,6 +272,8 @@ static void gprs_setup(struct net_device *net) | |||
254 | net->tx_queue_len = 10; | 272 | net->tx_queue_len = 10; |
255 | 273 | ||
256 | net->destructor = free_netdev; | 274 | net->destructor = free_netdev; |
275 | net->open = gprs_open; | ||
276 | net->stop = gprs_close; | ||
257 | net->hard_start_xmit = gprs_xmit; /* mandatory */ | 277 | net->hard_start_xmit = gprs_xmit; /* mandatory */ |
258 | net->change_mtu = gprs_set_mtu; | 278 | net->change_mtu = gprs_set_mtu; |
259 | net->get_stats = gprs_get_stats; | 279 | net->get_stats = gprs_get_stats; |
@@ -318,7 +338,6 @@ int gprs_attach(struct sock *sk) | |||
318 | dev->sk = sk; | 338 | dev->sk = sk; |
319 | 339 | ||
320 | printk(KERN_DEBUG"%s: attached\n", net->name); | 340 | printk(KERN_DEBUG"%s: attached\n", net->name); |
321 | gprs_write_space(sk); /* kick off TX */ | ||
322 | return net->ifindex; | 341 | return net->ifindex; |
323 | 342 | ||
324 | out_rel: | 343 | out_rel: |
@@ -341,7 +360,5 @@ void gprs_detach(struct sock *sk) | |||
341 | 360 | ||
342 | printk(KERN_DEBUG"%s: detached\n", net->name); | 361 | printk(KERN_DEBUG"%s: detached\n", net->name); |
343 | unregister_netdev(net); | 362 | unregister_netdev(net); |
344 | flush_scheduled_work(); | ||
345 | sock_put(sk); | 363 | sock_put(sk); |
346 | skb_queue_purge(&dev->tx_queue); | ||
347 | } | 364 | } |