diff options
author | Rémi Denis-Courmont <remi.denis-courmont@nokia.com> | 2008-12-17 18:48:50 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-17 18:48:50 -0500 |
commit | 893873f3965ae0173a9315534bec7628162d2243 (patch) | |
tree | a68217bad43abcebd4bb19af4dd8d50c10940f8a | |
parent | be677730a0ccb6bedced6f65f2ba8f57a3c607ba (diff) |
Phonet: get rid of deferred work on the transmission path
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 | 91 |
1 files changed, 28 insertions, 63 deletions
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c index a2873203dff2..b0ceac2d6cd1 100644 --- a/net/phonet/pep-gprs.c +++ b/net/phonet/pep-gprs.c | |||
@@ -41,11 +41,6 @@ struct gprs_dev { | |||
41 | void (*old_write_space)(struct sock *); | 41 | void (*old_write_space)(struct sock *); |
42 | 42 | ||
43 | struct net_device *dev; | 43 | struct net_device *dev; |
44 | |||
45 | struct sk_buff_head tx_queue; | ||
46 | struct work_struct tx_work; | ||
47 | spinlock_t tx_lock; | ||
48 | unsigned tx_max; | ||
49 | }; | 44 | }; |
50 | 45 | ||
51 | static __be16 gprs_type_trans(struct sk_buff *skb) | 46 | static __be16 gprs_type_trans(struct sk_buff *skb) |
@@ -66,6 +61,14 @@ static __be16 gprs_type_trans(struct sk_buff *skb) | |||
66 | return htons(0); | 61 | return htons(0); |
67 | } | 62 | } |
68 | 63 | ||
64 | static void gprs_writeable(struct gprs_dev *gp) | ||
65 | { | ||
66 | struct net_device *dev = gp->dev; | ||
67 | |||
68 | if (pep_writeable(gp->sk)) | ||
69 | netif_wake_queue(dev); | ||
70 | } | ||
71 | |||
69 | /* | 72 | /* |
70 | * Socket callbacks | 73 | * Socket callbacks |
71 | */ | 74 | */ |
@@ -157,14 +160,9 @@ static void gprs_data_ready(struct sock *sk, int len) | |||
157 | static void gprs_write_space(struct sock *sk) | 160 | static void gprs_write_space(struct sock *sk) |
158 | { | 161 | { |
159 | struct gprs_dev *gp = sk->sk_user_data; | 162 | struct gprs_dev *gp = sk->sk_user_data; |
160 | struct net_device *dev = gp->dev; | ||
161 | unsigned credits = pep_writeable(sk); | ||
162 | 163 | ||
163 | spin_lock_bh(&gp->tx_lock); | 164 | if (netif_running(gp->dev)) |
164 | gp->tx_max = credits; | 165 | gprs_writeable(gp); |
165 | if (credits > skb_queue_len(&gp->tx_queue) && netif_running(dev)) | ||
166 | netif_wake_queue(dev); | ||
167 | spin_unlock_bh(&gp->tx_lock); | ||
168 | } | 166 | } |
169 | 167 | ||
170 | /* | 168 | /* |
@@ -175,22 +173,21 @@ static int gprs_open(struct net_device *dev) | |||
175 | { | 173 | { |
176 | struct gprs_dev *gp = netdev_priv(dev); | 174 | struct gprs_dev *gp = netdev_priv(dev); |
177 | 175 | ||
178 | gprs_write_space(gp->sk); | 176 | gprs_writeable(gp); |
179 | return 0; | 177 | return 0; |
180 | } | 178 | } |
181 | 179 | ||
182 | static int gprs_close(struct net_device *dev) | 180 | static int gprs_close(struct net_device *dev) |
183 | { | 181 | { |
184 | struct gprs_dev *gp = netdev_priv(dev); | ||
185 | |||
186 | netif_stop_queue(dev); | 182 | netif_stop_queue(dev); |
187 | flush_work(&gp->tx_work); | ||
188 | return 0; | 183 | return 0; |
189 | } | 184 | } |
190 | 185 | ||
191 | static int gprs_xmit(struct sk_buff *skb, struct net_device *dev) | 186 | static int gprs_xmit(struct sk_buff *skb, struct net_device *dev) |
192 | { | 187 | { |
193 | struct gprs_dev *gp = netdev_priv(dev); | 188 | struct gprs_dev *gp = netdev_priv(dev); |
189 | struct sock *sk = gp->sk; | ||
190 | int len, err; | ||
194 | 191 | ||
195 | switch (skb->protocol) { | 192 | switch (skb->protocol) { |
196 | case htons(ETH_P_IP): | 193 | case htons(ETH_P_IP): |
@@ -201,51 +198,24 @@ static int gprs_xmit(struct sk_buff *skb, struct net_device *dev) | |||
201 | return 0; | 198 | return 0; |
202 | } | 199 | } |
203 | 200 | ||
204 | spin_lock(&gp->tx_lock); | 201 | skb_orphan(skb); |
205 | if (likely(skb_queue_len(&gp->tx_queue) < gp->tx_max)) { | 202 | skb_set_owner_w(skb, sk); |
206 | skb_queue_tail(&gp->tx_queue, skb); | 203 | len = skb->len; |
207 | skb = NULL; | 204 | err = pep_write(sk, skb); |
208 | } | 205 | if (err) { |
209 | if (skb_queue_len(&gp->tx_queue) >= gp->tx_max) | 206 | LIMIT_NETDEBUG(KERN_WARNING"%s: TX error (%d)\n", |
210 | netif_stop_queue(dev); | 207 | dev->name, err); |
211 | spin_unlock(&gp->tx_lock); | 208 | dev->stats.tx_aborted_errors++; |
212 | 209 | dev->stats.tx_errors++; | |
213 | schedule_work(&gp->tx_work); | ||
214 | if (unlikely(skb)) | ||
215 | dev_kfree_skb(skb); | 210 | dev_kfree_skb(skb); |
216 | return 0; | 211 | } else { |
217 | } | ||
218 | |||
219 | static void gprs_tx(struct work_struct *work) | ||
220 | { | ||
221 | struct gprs_dev *gp = container_of(work, struct gprs_dev, tx_work); | ||
222 | struct net_device *dev = gp->dev; | ||
223 | struct sock *sk = gp->sk; | ||
224 | struct sk_buff *skb; | ||
225 | |||
226 | while ((skb = skb_dequeue(&gp->tx_queue)) != NULL) { | ||
227 | int err; | ||
228 | |||
229 | dev->stats.tx_bytes += skb->len; | ||
230 | dev->stats.tx_packets++; | 212 | dev->stats.tx_packets++; |
231 | 213 | dev->stats.tx_bytes += len; | |
232 | skb_orphan(skb); | ||
233 | skb_set_owner_w(skb, sk); | ||
234 | |||
235 | lock_sock(sk); | ||
236 | err = pep_write(sk, skb); | ||
237 | if (err) { | ||
238 | LIMIT_NETDEBUG(KERN_WARNING"%s: TX error (%d)\n", | ||
239 | dev->name, err); | ||
240 | dev->stats.tx_aborted_errors++; | ||
241 | dev->stats.tx_errors++; | ||
242 | } | ||
243 | release_sock(sk); | ||
244 | } | 214 | } |
245 | 215 | ||
246 | lock_sock(sk); | 216 | if (!pep_writeable(sk)) |
247 | gprs_write_space(sk); | 217 | netif_stop_queue(dev); |
248 | release_sock(sk); | 218 | return 0; |
249 | } | 219 | } |
250 | 220 | ||
251 | static int gprs_set_mtu(struct net_device *dev, int new_mtu) | 221 | static int gprs_set_mtu(struct net_device *dev, int new_mtu) |
@@ -297,11 +267,8 @@ int gprs_attach(struct sock *sk) | |||
297 | if (!dev) | 267 | if (!dev) |
298 | return -ENOMEM; | 268 | return -ENOMEM; |
299 | gp = netdev_priv(dev); | 269 | gp = netdev_priv(dev); |
270 | gp->sk = sk; | ||
300 | gp->dev = dev; | 271 | gp->dev = dev; |
301 | gp->tx_max = 0; | ||
302 | spin_lock_init(&gp->tx_lock); | ||
303 | skb_queue_head_init(&gp->tx_queue); | ||
304 | INIT_WORK(&gp->tx_work, gprs_tx); | ||
305 | 272 | ||
306 | netif_stop_queue(dev); | 273 | netif_stop_queue(dev); |
307 | err = register_netdev(dev); | 274 | err = register_netdev(dev); |
@@ -328,9 +295,7 @@ int gprs_attach(struct sock *sk) | |||
328 | sk->sk_data_ready = gprs_data_ready; | 295 | sk->sk_data_ready = gprs_data_ready; |
329 | sk->sk_write_space = gprs_write_space; | 296 | sk->sk_write_space = gprs_write_space; |
330 | release_sock(sk); | 297 | release_sock(sk); |
331 | |||
332 | sock_hold(sk); | 298 | sock_hold(sk); |
333 | gp->sk = sk; | ||
334 | 299 | ||
335 | printk(KERN_DEBUG"%s: attached\n", dev->name); | 300 | printk(KERN_DEBUG"%s: attached\n", dev->name); |
336 | return dev->ifindex; | 301 | return dev->ifindex; |