diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2008-04-30 03:54:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:47 -0400 |
commit | f34d7a5b7010b82fe97da95496b9971435530062 (patch) | |
tree | 87e2abec1e33ed4fe5e63ee2fd000bc2ad745e57 /drivers/net/wan/x25_asy.c | |
parent | 251b8dd7eee30fda089a1dc088abf4fc9a0dee9c (diff) |
tty: The big operations rework
- Operations are now a shared const function block as with most other Linux
objects
- Introduce wrappers for some optional functions to get consistent behaviour
- Wrap put_char which used to be patched by the tty layer
- Document which functions are needed/optional
- Make put_char report success/fail
- Cache the driver->ops pointer in the tty as tty->ops
- Remove various surplus lock calls we no longer need
- Remove proc_write method as noted by Alexey Dobriyan
- Introduce some missing sanity checks where certain driver/ldisc
combinations would oops as they didn't check needed methods were present
[akpm@linux-foundation.org: fix fs/compat_ioctl.c build]
[akpm@linux-foundation.org: fix isicom]
[akpm@linux-foundation.org: fix arch/ia64/hp/sim/simserial.c build]
[akpm@linux-foundation.org: fix kgdb]
Signed-off-by: Alan Cox <alan@redhat.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/net/wan/x25_asy.c')
-rw-r--r-- | drivers/net/wan/x25_asy.c | 279 |
1 files changed, 135 insertions, 144 deletions
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 0f8aca8a4d43..249e18053d5f 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | 18 | ||
19 | #include <asm/system.h> | 19 | #include <asm/system.h> |
20 | #include <asm/uaccess.h> | 20 | #include <linux/uaccess.h> |
21 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
22 | #include <linux/string.h> | 22 | #include <linux/string.h> |
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
@@ -95,7 +95,7 @@ static struct x25_asy *x25_asy_alloc(void) | |||
95 | x25_asy_devs[i] = dev; | 95 | x25_asy_devs[i] = dev; |
96 | return sl; | 96 | return sl; |
97 | } else { | 97 | } else { |
98 | printk("x25_asy_alloc() - register_netdev() failure.\n"); | 98 | printk(KERN_WARNING "x25_asy_alloc() - register_netdev() failure.\n"); |
99 | free_netdev(dev); | 99 | free_netdev(dev); |
100 | } | 100 | } |
101 | } | 101 | } |
@@ -112,23 +112,22 @@ static void x25_asy_free(struct x25_asy *sl) | |||
112 | kfree(sl->xbuff); | 112 | kfree(sl->xbuff); |
113 | sl->xbuff = NULL; | 113 | sl->xbuff = NULL; |
114 | 114 | ||
115 | if (!test_and_clear_bit(SLF_INUSE, &sl->flags)) { | 115 | if (!test_and_clear_bit(SLF_INUSE, &sl->flags)) |
116 | printk("%s: x25_asy_free for already free unit.\n", sl->dev->name); | 116 | printk(KERN_ERR "%s: x25_asy_free for already free unit.\n", |
117 | } | 117 | sl->dev->name); |
118 | } | 118 | } |
119 | 119 | ||
120 | static int x25_asy_change_mtu(struct net_device *dev, int newmtu) | 120 | static int x25_asy_change_mtu(struct net_device *dev, int newmtu) |
121 | { | 121 | { |
122 | struct x25_asy *sl = dev->priv; | 122 | struct x25_asy *sl = dev->priv; |
123 | unsigned char *xbuff, *rbuff; | 123 | unsigned char *xbuff, *rbuff; |
124 | int len = 2* newmtu; | 124 | int len = 2 * newmtu; |
125 | 125 | ||
126 | xbuff = kmalloc(len + 4, GFP_ATOMIC); | 126 | xbuff = kmalloc(len + 4, GFP_ATOMIC); |
127 | rbuff = kmalloc(len + 4, GFP_ATOMIC); | 127 | rbuff = kmalloc(len + 4, GFP_ATOMIC); |
128 | 128 | ||
129 | if (xbuff == NULL || rbuff == NULL) | 129 | if (xbuff == NULL || rbuff == NULL) { |
130 | { | 130 | printk(KERN_WARNING "%s: unable to grow X.25 buffers, MTU change cancelled.\n", |
131 | printk("%s: unable to grow X.25 buffers, MTU change cancelled.\n", | ||
132 | dev->name); | 131 | dev->name); |
133 | kfree(xbuff); | 132 | kfree(xbuff); |
134 | kfree(rbuff); | 133 | kfree(rbuff); |
@@ -193,25 +192,23 @@ static void x25_asy_bump(struct x25_asy *sl) | |||
193 | int err; | 192 | int err; |
194 | 193 | ||
195 | count = sl->rcount; | 194 | count = sl->rcount; |
196 | sl->stats.rx_bytes+=count; | 195 | sl->stats.rx_bytes += count; |
197 | 196 | ||
198 | skb = dev_alloc_skb(count+1); | 197 | skb = dev_alloc_skb(count+1); |
199 | if (skb == NULL) | 198 | if (skb == NULL) { |
200 | { | 199 | printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", |
201 | printk("%s: memory squeeze, dropping packet.\n", sl->dev->name); | 200 | sl->dev->name); |
202 | sl->stats.rx_dropped++; | 201 | sl->stats.rx_dropped++; |
203 | return; | 202 | return; |
204 | } | 203 | } |
205 | skb_push(skb,1); /* LAPB internal control */ | 204 | skb_push(skb, 1); /* LAPB internal control */ |
206 | memcpy(skb_put(skb,count), sl->rbuff, count); | 205 | memcpy(skb_put(skb, count), sl->rbuff, count); |
207 | skb->protocol = x25_type_trans(skb, sl->dev); | 206 | skb->protocol = x25_type_trans(skb, sl->dev); |
208 | if((err=lapb_data_received(skb->dev, skb))!=LAPB_OK) | 207 | err = lapb_data_received(skb->dev, skb); |
209 | { | 208 | if (err != LAPB_OK) { |
210 | kfree_skb(skb); | 209 | kfree_skb(skb); |
211 | printk(KERN_DEBUG "x25_asy: data received err - %d\n",err); | 210 | printk(KERN_DEBUG "x25_asy: data received err - %d\n", err); |
212 | } | 211 | } else { |
213 | else | ||
214 | { | ||
215 | netif_rx(skb); | 212 | netif_rx(skb); |
216 | sl->dev->last_rx = jiffies; | 213 | sl->dev->last_rx = jiffies; |
217 | sl->stats.rx_packets++; | 214 | sl->stats.rx_packets++; |
@@ -224,10 +221,11 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len) | |||
224 | unsigned char *p; | 221 | unsigned char *p; |
225 | int actual, count, mtu = sl->dev->mtu; | 222 | int actual, count, mtu = sl->dev->mtu; |
226 | 223 | ||
227 | if (len > mtu) | 224 | if (len > mtu) { |
228 | { /* Sigh, shouldn't occur BUT ... */ | 225 | /* Sigh, shouldn't occur BUT ... */ |
229 | len = mtu; | 226 | len = mtu; |
230 | printk ("%s: truncating oversized transmit packet!\n", sl->dev->name); | 227 | printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n", |
228 | sl->dev->name); | ||
231 | sl->stats.tx_dropped++; | 229 | sl->stats.tx_dropped++; |
232 | x25_asy_unlock(sl); | 230 | x25_asy_unlock(sl); |
233 | return; | 231 | return; |
@@ -245,7 +243,7 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len) | |||
245 | * 14 Oct 1994 Dmitry Gorodchanin. | 243 | * 14 Oct 1994 Dmitry Gorodchanin. |
246 | */ | 244 | */ |
247 | sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); | 245 | sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); |
248 | actual = sl->tty->driver->write(sl->tty, sl->xbuff, count); | 246 | actual = sl->tty->ops->write(sl->tty, sl->xbuff, count); |
249 | sl->xleft = count - actual; | 247 | sl->xleft = count - actual; |
250 | sl->xhead = sl->xbuff + actual; | 248 | sl->xhead = sl->xbuff + actual; |
251 | /* VSV */ | 249 | /* VSV */ |
@@ -265,8 +263,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty) | |||
265 | if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev)) | 263 | if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev)) |
266 | return; | 264 | return; |
267 | 265 | ||
268 | if (sl->xleft <= 0) | 266 | if (sl->xleft <= 0) { |
269 | { | ||
270 | /* Now serial buffer is almost free & we can start | 267 | /* Now serial buffer is almost free & we can start |
271 | * transmission of another packet */ | 268 | * transmission of another packet */ |
272 | sl->stats.tx_packets++; | 269 | sl->stats.tx_packets++; |
@@ -275,14 +272,14 @@ static void x25_asy_write_wakeup(struct tty_struct *tty) | |||
275 | return; | 272 | return; |
276 | } | 273 | } |
277 | 274 | ||
278 | actual = tty->driver->write(tty, sl->xhead, sl->xleft); | 275 | actual = tty->ops->write(tty, sl->xhead, sl->xleft); |
279 | sl->xleft -= actual; | 276 | sl->xleft -= actual; |
280 | sl->xhead += actual; | 277 | sl->xhead += actual; |
281 | } | 278 | } |
282 | 279 | ||
283 | static void x25_asy_timeout(struct net_device *dev) | 280 | static void x25_asy_timeout(struct net_device *dev) |
284 | { | 281 | { |
285 | struct x25_asy *sl = (struct x25_asy*)(dev->priv); | 282 | struct x25_asy *sl = dev->priv; |
286 | 283 | ||
287 | spin_lock(&sl->lock); | 284 | spin_lock(&sl->lock); |
288 | if (netif_queue_stopped(dev)) { | 285 | if (netif_queue_stopped(dev)) { |
@@ -290,7 +287,7 @@ static void x25_asy_timeout(struct net_device *dev) | |||
290 | * 14 Oct 1994 Dmitry Gorodchanin. | 287 | * 14 Oct 1994 Dmitry Gorodchanin. |
291 | */ | 288 | */ |
292 | printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, | 289 | printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, |
293 | (sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ? | 290 | (tty_chars_in_buffer(sl->tty) || sl->xleft) ? |
294 | "bad line quality" : "driver error"); | 291 | "bad line quality" : "driver error"); |
295 | sl->xleft = 0; | 292 | sl->xleft = 0; |
296 | sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); | 293 | sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); |
@@ -303,31 +300,34 @@ static void x25_asy_timeout(struct net_device *dev) | |||
303 | 300 | ||
304 | static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev) | 301 | static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev) |
305 | { | 302 | { |
306 | struct x25_asy *sl = (struct x25_asy*)(dev->priv); | 303 | struct x25_asy *sl = dev->priv; |
307 | int err; | 304 | int err; |
308 | 305 | ||
309 | if (!netif_running(sl->dev)) { | 306 | if (!netif_running(sl->dev)) { |
310 | printk("%s: xmit call when iface is down\n", dev->name); | 307 | printk(KERN_ERR "%s: xmit call when iface is down\n", |
308 | dev->name); | ||
311 | kfree_skb(skb); | 309 | kfree_skb(skb); |
312 | return 0; | 310 | return 0; |
313 | } | 311 | } |
314 | 312 | ||
315 | switch(skb->data[0]) | 313 | switch (skb->data[0]) { |
316 | { | 314 | case 0x00: |
317 | case 0x00:break; | 315 | break; |
318 | case 0x01: /* Connection request .. do nothing */ | 316 | case 0x01: /* Connection request .. do nothing */ |
319 | if((err=lapb_connect_request(dev))!=LAPB_OK) | 317 | err = lapb_connect_request(dev); |
320 | printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err); | 318 | if (err != LAPB_OK) |
321 | kfree_skb(skb); | 319 | printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err); |
322 | return 0; | 320 | kfree_skb(skb); |
323 | case 0x02: /* Disconnect request .. do nothing - hang up ?? */ | 321 | return 0; |
324 | if((err=lapb_disconnect_request(dev))!=LAPB_OK) | 322 | case 0x02: /* Disconnect request .. do nothing - hang up ?? */ |
325 | printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err); | 323 | err = lapb_disconnect_request(dev); |
326 | default: | 324 | if (err != LAPB_OK) |
327 | kfree_skb(skb); | 325 | printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err); |
328 | return 0; | 326 | default: |
327 | kfree_skb(skb); | ||
328 | return 0; | ||
329 | } | 329 | } |
330 | skb_pull(skb,1); /* Remove control byte */ | 330 | skb_pull(skb, 1); /* Remove control byte */ |
331 | /* | 331 | /* |
332 | * If we are busy already- too bad. We ought to be able | 332 | * If we are busy already- too bad. We ought to be able |
333 | * to queue things at this point, to allow for a little | 333 | * to queue things at this point, to allow for a little |
@@ -338,10 +338,10 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev) | |||
338 | * So, no queues ! | 338 | * So, no queues ! |
339 | * 14 Oct 1994 Dmitry Gorodchanin. | 339 | * 14 Oct 1994 Dmitry Gorodchanin. |
340 | */ | 340 | */ |
341 | 341 | ||
342 | if((err=lapb_data_request(dev,skb))!=LAPB_OK) | 342 | err = lapb_data_request(dev, skb); |
343 | { | 343 | if (err != LAPB_OK) { |
344 | printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err); | 344 | printk(KERN_ERR "x25_asy: lapb_data_request error - %d\n", err); |
345 | kfree_skb(skb); | 345 | kfree_skb(skb); |
346 | return 0; | 346 | return 0; |
347 | } | 347 | } |
@@ -357,7 +357,7 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev) | |||
357 | * Called when I frame data arrives. We did the work above - throw it | 357 | * Called when I frame data arrives. We did the work above - throw it |
358 | * at the net layer. | 358 | * at the net layer. |
359 | */ | 359 | */ |
360 | 360 | ||
361 | static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb) | 361 | static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb) |
362 | { | 362 | { |
363 | skb->dev->last_rx = jiffies; | 363 | skb->dev->last_rx = jiffies; |
@@ -369,24 +369,22 @@ static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb) | |||
369 | * busy cases too well. Its tricky to see how to do this nicely - | 369 | * busy cases too well. Its tricky to see how to do this nicely - |
370 | * perhaps lapb should allow us to bounce this ? | 370 | * perhaps lapb should allow us to bounce this ? |
371 | */ | 371 | */ |
372 | 372 | ||
373 | static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb) | 373 | static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb) |
374 | { | 374 | { |
375 | struct x25_asy *sl=dev->priv; | 375 | struct x25_asy *sl = dev->priv; |
376 | 376 | ||
377 | spin_lock(&sl->lock); | 377 | spin_lock(&sl->lock); |
378 | if (netif_queue_stopped(sl->dev) || sl->tty == NULL) | 378 | if (netif_queue_stopped(sl->dev) || sl->tty == NULL) { |
379 | { | ||
380 | spin_unlock(&sl->lock); | 379 | spin_unlock(&sl->lock); |
381 | printk(KERN_ERR "x25_asy: tbusy drop\n"); | 380 | printk(KERN_ERR "x25_asy: tbusy drop\n"); |
382 | kfree_skb(skb); | 381 | kfree_skb(skb); |
383 | return; | 382 | return; |
384 | } | 383 | } |
385 | /* We were not busy, so we are now... :-) */ | 384 | /* We were not busy, so we are now... :-) */ |
386 | if (skb != NULL) | 385 | if (skb != NULL) { |
387 | { | ||
388 | x25_asy_lock(sl); | 386 | x25_asy_lock(sl); |
389 | sl->stats.tx_bytes+=skb->len; | 387 | sl->stats.tx_bytes += skb->len; |
390 | x25_asy_encaps(sl, skb->data, skb->len); | 388 | x25_asy_encaps(sl, skb->data, skb->len); |
391 | dev_kfree_skb(skb); | 389 | dev_kfree_skb(skb); |
392 | } | 390 | } |
@@ -396,15 +394,16 @@ static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb) | |||
396 | /* | 394 | /* |
397 | * LAPB connection establish/down information. | 395 | * LAPB connection establish/down information. |
398 | */ | 396 | */ |
399 | 397 | ||
400 | static void x25_asy_connected(struct net_device *dev, int reason) | 398 | static void x25_asy_connected(struct net_device *dev, int reason) |
401 | { | 399 | { |
402 | struct x25_asy *sl = dev->priv; | 400 | struct x25_asy *sl = dev->priv; |
403 | struct sk_buff *skb; | 401 | struct sk_buff *skb; |
404 | unsigned char *ptr; | 402 | unsigned char *ptr; |
405 | 403 | ||
406 | if ((skb = dev_alloc_skb(1)) == NULL) { | 404 | skb = dev_alloc_skb(1); |
407 | printk(KERN_ERR "lapbeth: out of memory\n"); | 405 | if (skb == NULL) { |
406 | printk(KERN_ERR "x25_asy: out of memory\n"); | ||
408 | return; | 407 | return; |
409 | } | 408 | } |
410 | 409 | ||
@@ -422,7 +421,8 @@ static void x25_asy_disconnected(struct net_device *dev, int reason) | |||
422 | struct sk_buff *skb; | 421 | struct sk_buff *skb; |
423 | unsigned char *ptr; | 422 | unsigned char *ptr; |
424 | 423 | ||
425 | if ((skb = dev_alloc_skb(1)) == NULL) { | 424 | skb = dev_alloc_skb(1); |
425 | if (skb == NULL) { | ||
426 | printk(KERN_ERR "x25_asy: out of memory\n"); | 426 | printk(KERN_ERR "x25_asy: out of memory\n"); |
427 | return; | 427 | return; |
428 | } | 428 | } |
@@ -449,7 +449,7 @@ static struct lapb_register_struct x25_asy_callbacks = { | |||
449 | /* Open the low-level part of the X.25 channel. Easy! */ | 449 | /* Open the low-level part of the X.25 channel. Easy! */ |
450 | static int x25_asy_open(struct net_device *dev) | 450 | static int x25_asy_open(struct net_device *dev) |
451 | { | 451 | { |
452 | struct x25_asy *sl = (struct x25_asy*)(dev->priv); | 452 | struct x25_asy *sl = dev->priv; |
453 | unsigned long len; | 453 | unsigned long len; |
454 | int err; | 454 | int err; |
455 | 455 | ||
@@ -466,13 +466,11 @@ static int x25_asy_open(struct net_device *dev) | |||
466 | len = dev->mtu * 2; | 466 | len = dev->mtu * 2; |
467 | 467 | ||
468 | sl->rbuff = kmalloc(len + 4, GFP_KERNEL); | 468 | sl->rbuff = kmalloc(len + 4, GFP_KERNEL); |
469 | if (sl->rbuff == NULL) { | 469 | if (sl->rbuff == NULL) |
470 | goto norbuff; | 470 | goto norbuff; |
471 | } | ||
472 | sl->xbuff = kmalloc(len + 4, GFP_KERNEL); | 471 | sl->xbuff = kmalloc(len + 4, GFP_KERNEL); |
473 | if (sl->xbuff == NULL) { | 472 | if (sl->xbuff == NULL) |
474 | goto noxbuff; | 473 | goto noxbuff; |
475 | } | ||
476 | 474 | ||
477 | sl->buffsize = len; | 475 | sl->buffsize = len; |
478 | sl->rcount = 0; | 476 | sl->rcount = 0; |
@@ -480,11 +478,12 @@ static int x25_asy_open(struct net_device *dev) | |||
480 | sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */ | 478 | sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */ |
481 | 479 | ||
482 | netif_start_queue(dev); | 480 | netif_start_queue(dev); |
483 | 481 | ||
484 | /* | 482 | /* |
485 | * Now attach LAPB | 483 | * Now attach LAPB |
486 | */ | 484 | */ |
487 | if((err=lapb_register(dev, &x25_asy_callbacks))==LAPB_OK) | 485 | err = lapb_register(dev, &x25_asy_callbacks); |
486 | if (err == LAPB_OK) | ||
488 | return 0; | 487 | return 0; |
489 | 488 | ||
490 | /* Cleanup */ | 489 | /* Cleanup */ |
@@ -499,18 +498,20 @@ norbuff: | |||
499 | /* Close the low-level part of the X.25 channel. Easy! */ | 498 | /* Close the low-level part of the X.25 channel. Easy! */ |
500 | static int x25_asy_close(struct net_device *dev) | 499 | static int x25_asy_close(struct net_device *dev) |
501 | { | 500 | { |
502 | struct x25_asy *sl = (struct x25_asy*)(dev->priv); | 501 | struct x25_asy *sl = dev->priv; |
503 | int err; | 502 | int err; |
504 | 503 | ||
505 | spin_lock(&sl->lock); | 504 | spin_lock(&sl->lock); |
506 | if (sl->tty) | 505 | if (sl->tty) |
507 | sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); | 506 | sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); |
508 | 507 | ||
509 | netif_stop_queue(dev); | 508 | netif_stop_queue(dev); |
510 | sl->rcount = 0; | 509 | sl->rcount = 0; |
511 | sl->xleft = 0; | 510 | sl->xleft = 0; |
512 | if((err=lapb_unregister(dev))!=LAPB_OK) | 511 | err = lapb_unregister(dev); |
513 | printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err); | 512 | if (err != LAPB_OK) |
513 | printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n", | ||
514 | err); | ||
514 | spin_unlock(&sl->lock); | 515 | spin_unlock(&sl->lock); |
515 | return 0; | 516 | return 0; |
516 | } | 517 | } |
@@ -521,8 +522,9 @@ static int x25_asy_close(struct net_device *dev) | |||
521 | * a block of X.25 data has been received, which can now be decapsulated | 522 | * a block of X.25 data has been received, which can now be decapsulated |
522 | * and sent on to some IP layer for further processing. | 523 | * and sent on to some IP layer for further processing. |
523 | */ | 524 | */ |
524 | 525 | ||
525 | static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) | 526 | static void x25_asy_receive_buf(struct tty_struct *tty, |
527 | const unsigned char *cp, char *fp, int count) | ||
526 | { | 528 | { |
527 | struct x25_asy *sl = (struct x25_asy *) tty->disc_data; | 529 | struct x25_asy *sl = (struct x25_asy *) tty->disc_data; |
528 | 530 | ||
@@ -533,9 +535,8 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
533 | /* Read the characters out of the buffer */ | 535 | /* Read the characters out of the buffer */ |
534 | while (count--) { | 536 | while (count--) { |
535 | if (fp && *fp++) { | 537 | if (fp && *fp++) { |
536 | if (!test_and_set_bit(SLF_ERROR, &sl->flags)) { | 538 | if (!test_and_set_bit(SLF_ERROR, &sl->flags)) |
537 | sl->stats.rx_errors++; | 539 | sl->stats.rx_errors++; |
538 | } | ||
539 | cp++; | 540 | cp++; |
540 | continue; | 541 | continue; |
541 | } | 542 | } |
@@ -556,31 +557,31 @@ static int x25_asy_open_tty(struct tty_struct *tty) | |||
556 | struct x25_asy *sl = (struct x25_asy *) tty->disc_data; | 557 | struct x25_asy *sl = (struct x25_asy *) tty->disc_data; |
557 | int err; | 558 | int err; |
558 | 559 | ||
560 | if (tty->ops->write == NULL) | ||
561 | return -EOPNOTSUPP; | ||
562 | |||
559 | /* First make sure we're not already connected. */ | 563 | /* First make sure we're not already connected. */ |
560 | if (sl && sl->magic == X25_ASY_MAGIC) { | 564 | if (sl && sl->magic == X25_ASY_MAGIC) |
561 | return -EEXIST; | 565 | return -EEXIST; |
562 | } | ||
563 | 566 | ||
564 | /* OK. Find a free X.25 channel to use. */ | 567 | /* OK. Find a free X.25 channel to use. */ |
565 | if ((sl = x25_asy_alloc()) == NULL) { | 568 | sl = x25_asy_alloc(); |
569 | if (sl == NULL) | ||
566 | return -ENFILE; | 570 | return -ENFILE; |
567 | } | ||
568 | 571 | ||
569 | sl->tty = tty; | 572 | sl->tty = tty; |
570 | tty->disc_data = sl; | 573 | tty->disc_data = sl; |
571 | tty->receive_room = 65536; | 574 | tty->receive_room = 65536; |
572 | if (tty->driver->flush_buffer) { | 575 | tty_driver_flush_buffer(tty); |
573 | tty->driver->flush_buffer(tty); | ||
574 | } | ||
575 | tty_ldisc_flush(tty); | 576 | tty_ldisc_flush(tty); |
576 | 577 | ||
577 | /* Restore default settings */ | 578 | /* Restore default settings */ |
578 | sl->dev->type = ARPHRD_X25; | 579 | sl->dev->type = ARPHRD_X25; |
579 | 580 | ||
580 | /* Perform the low-level X.25 async init */ | 581 | /* Perform the low-level X.25 async init */ |
581 | if ((err = x25_asy_open(sl->dev))) | 582 | err = x25_asy_open(sl->dev); |
583 | if (err) | ||
582 | return err; | 584 | return err; |
583 | |||
584 | /* Done. We have linked the TTY line to a channel. */ | 585 | /* Done. We have linked the TTY line to a channel. */ |
585 | return sl->dev->base_addr; | 586 | return sl->dev->base_addr; |
586 | } | 587 | } |
@@ -601,9 +602,7 @@ static void x25_asy_close_tty(struct tty_struct *tty) | |||
601 | return; | 602 | return; |
602 | 603 | ||
603 | if (sl->dev->flags & IFF_UP) | 604 | if (sl->dev->flags & IFF_UP) |
604 | { | 605 | dev_close(sl->dev); |
605 | (void) dev_close(sl->dev); | ||
606 | } | ||
607 | 606 | ||
608 | tty->disc_data = NULL; | 607 | tty->disc_data = NULL; |
609 | sl->tty = NULL; | 608 | sl->tty = NULL; |
@@ -613,8 +612,7 @@ static void x25_asy_close_tty(struct tty_struct *tty) | |||
613 | 612 | ||
614 | static struct net_device_stats *x25_asy_get_stats(struct net_device *dev) | 613 | static struct net_device_stats *x25_asy_get_stats(struct net_device *dev) |
615 | { | 614 | { |
616 | struct x25_asy *sl = (struct x25_asy*)(dev->priv); | 615 | struct x25_asy *sl = dev->priv; |
617 | |||
618 | return &sl->stats; | 616 | return &sl->stats; |
619 | } | 617 | } |
620 | 618 | ||
@@ -641,21 +639,19 @@ int x25_asy_esc(unsigned char *s, unsigned char *d, int len) | |||
641 | * character sequence, according to the X.25 protocol. | 639 | * character sequence, according to the X.25 protocol. |
642 | */ | 640 | */ |
643 | 641 | ||
644 | while (len-- > 0) | 642 | while (len-- > 0) { |
645 | { | 643 | switch (c = *s++) { |
646 | switch(c = *s++) | 644 | case X25_END: |
647 | { | 645 | *ptr++ = X25_ESC; |
648 | case X25_END: | 646 | *ptr++ = X25_ESCAPE(X25_END); |
649 | *ptr++ = X25_ESC; | 647 | break; |
650 | *ptr++ = X25_ESCAPE(X25_END); | 648 | case X25_ESC: |
651 | break; | 649 | *ptr++ = X25_ESC; |
652 | case X25_ESC: | 650 | *ptr++ = X25_ESCAPE(X25_ESC); |
653 | *ptr++ = X25_ESC; | 651 | break; |
654 | *ptr++ = X25_ESCAPE(X25_ESC); | 652 | default: |
655 | break; | 653 | *ptr++ = c; |
656 | default: | 654 | break; |
657 | *ptr++ = c; | ||
658 | break; | ||
659 | } | 655 | } |
660 | } | 656 | } |
661 | *ptr++ = X25_END; | 657 | *ptr++ = X25_END; |
@@ -665,31 +661,25 @@ int x25_asy_esc(unsigned char *s, unsigned char *d, int len) | |||
665 | static void x25_asy_unesc(struct x25_asy *sl, unsigned char s) | 661 | static void x25_asy_unesc(struct x25_asy *sl, unsigned char s) |
666 | { | 662 | { |
667 | 663 | ||
668 | switch(s) | 664 | switch (s) { |
669 | { | 665 | case X25_END: |
670 | case X25_END: | 666 | if (!test_and_clear_bit(SLF_ERROR, &sl->flags) |
671 | if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2)) | 667 | && sl->rcount > 2) |
672 | { | 668 | x25_asy_bump(sl); |
673 | x25_asy_bump(sl); | 669 | clear_bit(SLF_ESCAPE, &sl->flags); |
674 | } | 670 | sl->rcount = 0; |
675 | clear_bit(SLF_ESCAPE, &sl->flags); | 671 | return; |
676 | sl->rcount = 0; | 672 | case X25_ESC: |
677 | return; | 673 | set_bit(SLF_ESCAPE, &sl->flags); |
678 | 674 | return; | |
679 | case X25_ESC: | 675 | case X25_ESCAPE(X25_ESC): |
680 | set_bit(SLF_ESCAPE, &sl->flags); | 676 | case X25_ESCAPE(X25_END): |
681 | return; | 677 | if (test_and_clear_bit(SLF_ESCAPE, &sl->flags)) |
682 | 678 | s = X25_UNESCAPE(s); | |
683 | case X25_ESCAPE(X25_ESC): | 679 | break; |
684 | case X25_ESCAPE(X25_END): | 680 | } |
685 | if (test_and_clear_bit(SLF_ESCAPE, &sl->flags)) | 681 | if (!test_bit(SLF_ERROR, &sl->flags)) { |
686 | s = X25_UNESCAPE(s); | 682 | if (sl->rcount < sl->buffsize) { |
687 | break; | ||
688 | } | ||
689 | if (!test_bit(SLF_ERROR, &sl->flags)) | ||
690 | { | ||
691 | if (sl->rcount < sl->buffsize) | ||
692 | { | ||
693 | sl->rbuff[sl->rcount++] = s; | 683 | sl->rbuff[sl->rcount++] = s; |
694 | return; | 684 | return; |
695 | } | 685 | } |
@@ -709,7 +699,7 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file, | |||
709 | if (!sl || sl->magic != X25_ASY_MAGIC) | 699 | if (!sl || sl->magic != X25_ASY_MAGIC) |
710 | return -EINVAL; | 700 | return -EINVAL; |
711 | 701 | ||
712 | switch(cmd) { | 702 | switch (cmd) { |
713 | case SIOCGIFNAME: | 703 | case SIOCGIFNAME: |
714 | if (copy_to_user((void __user *)arg, sl->dev->name, | 704 | if (copy_to_user((void __user *)arg, sl->dev->name, |
715 | strlen(sl->dev->name) + 1)) | 705 | strlen(sl->dev->name) + 1)) |
@@ -724,8 +714,8 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file, | |||
724 | 714 | ||
725 | static int x25_asy_open_dev(struct net_device *dev) | 715 | static int x25_asy_open_dev(struct net_device *dev) |
726 | { | 716 | { |
727 | struct x25_asy *sl = (struct x25_asy*)(dev->priv); | 717 | struct x25_asy *sl = dev->priv; |
728 | if(sl->tty==NULL) | 718 | if (sl->tty == NULL) |
729 | return -ENODEV; | 719 | return -ENODEV; |
730 | return 0; | 720 | return 0; |
731 | } | 721 | } |
@@ -741,9 +731,9 @@ static void x25_asy_setup(struct net_device *dev) | |||
741 | set_bit(SLF_INUSE, &sl->flags); | 731 | set_bit(SLF_INUSE, &sl->flags); |
742 | 732 | ||
743 | /* | 733 | /* |
744 | * Finish setting up the DEVICE info. | 734 | * Finish setting up the DEVICE info. |
745 | */ | 735 | */ |
746 | 736 | ||
747 | dev->mtu = SL_MTU; | 737 | dev->mtu = SL_MTU; |
748 | dev->hard_start_xmit = x25_asy_xmit; | 738 | dev->hard_start_xmit = x25_asy_xmit; |
749 | dev->tx_timeout = x25_asy_timeout; | 739 | dev->tx_timeout = x25_asy_timeout; |
@@ -778,9 +768,10 @@ static int __init init_x25_asy(void) | |||
778 | x25_asy_maxdev = 4; /* Sanity */ | 768 | x25_asy_maxdev = 4; /* Sanity */ |
779 | 769 | ||
780 | printk(KERN_INFO "X.25 async: version 0.00 ALPHA " | 770 | printk(KERN_INFO "X.25 async: version 0.00 ALPHA " |
781 | "(dynamic channels, max=%d).\n", x25_asy_maxdev ); | 771 | "(dynamic channels, max=%d).\n", x25_asy_maxdev); |
782 | 772 | ||
783 | x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device*), GFP_KERNEL); | 773 | x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device *), |
774 | GFP_KERNEL); | ||
784 | if (!x25_asy_devs) { | 775 | if (!x25_asy_devs) { |
785 | printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] " | 776 | printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] " |
786 | "array! Uaargh! (-> No X.25 available)\n"); | 777 | "array! Uaargh! (-> No X.25 available)\n"); |
@@ -802,7 +793,7 @@ static void __exit exit_x25_asy(void) | |||
802 | struct x25_asy *sl = dev->priv; | 793 | struct x25_asy *sl = dev->priv; |
803 | 794 | ||
804 | spin_lock_bh(&sl->lock); | 795 | spin_lock_bh(&sl->lock); |
805 | if (sl->tty) | 796 | if (sl->tty) |
806 | tty_hangup(sl->tty); | 797 | tty_hangup(sl->tty); |
807 | 798 | ||
808 | spin_unlock_bh(&sl->lock); | 799 | spin_unlock_bh(&sl->lock); |