aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wan/cosa.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2008-08-07 04:05:46 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-08-07 04:05:46 -0400
commit3859069bc3358772b08bd91efe9edec39a746ea8 (patch)
tree9ffe71711dd98cf511ad21d9990c597de0ac3b2b /drivers/net/wan/cosa.c
parente2c709b0ba2886b5438b666222b4b3faf82d65a9 (diff)
parent867240f7b2a37b1be4ba37d904a9064a96c82099 (diff)
Merge branch 'for-jeff' of git://git.kernel.org/pub/scm/linux/kernel/git/chris/linux-2.6 into tmp
Diffstat (limited to 'drivers/net/wan/cosa.c')
-rw-r--r--drivers/net/wan/cosa.c293
1 files changed, 128 insertions, 165 deletions
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index f7d3349dc3ec..f14051556c87 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -2,6 +2,7 @@
2 2
3/* 3/*
4 * Copyright (C) 1995-1997 Jan "Yenya" Kasprzak <kas@fi.muni.cz> 4 * Copyright (C) 1995-1997 Jan "Yenya" Kasprzak <kas@fi.muni.cz>
5 * Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl>
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -54,7 +55,7 @@
54 * 55 *
55 * The Linux driver (unlike the present *BSD drivers :-) can work even 56 * The Linux driver (unlike the present *BSD drivers :-) can work even
56 * for the COSA and SRP in one computer and allows each channel to work 57 * for the COSA and SRP in one computer and allows each channel to work
57 * in one of the three modes (character device, Cisco HDLC, Sync PPP). 58 * in one of the two modes (character or network device).
58 * 59 *
59 * AUTHOR 60 * AUTHOR
60 * 61 *
@@ -72,12 +73,6 @@
72 * The Comtrol Hostess SV11 driver by Alan Cox 73 * The Comtrol Hostess SV11 driver by Alan Cox
73 * The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox 74 * The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox
74 */ 75 */
75/*
76 * 5/25/1999 : Marcelo Tosatti <marcelo@conectiva.com.br>
77 * fixed a deadlock in cosa_sppp_open
78 */
79
80/* ---------- Headers, macros, data structures ---------- */
81 76
82#include <linux/module.h> 77#include <linux/module.h>
83#include <linux/kernel.h> 78#include <linux/kernel.h>
@@ -86,6 +81,7 @@
86#include <linux/fs.h> 81#include <linux/fs.h>
87#include <linux/interrupt.h> 82#include <linux/interrupt.h>
88#include <linux/delay.h> 83#include <linux/delay.h>
84#include <linux/hdlc.h>
89#include <linux/errno.h> 85#include <linux/errno.h>
90#include <linux/ioport.h> 86#include <linux/ioport.h>
91#include <linux/netdevice.h> 87#include <linux/netdevice.h>
@@ -93,14 +89,12 @@
93#include <linux/mutex.h> 89#include <linux/mutex.h>
94#include <linux/device.h> 90#include <linux/device.h>
95#include <linux/smp_lock.h> 91#include <linux/smp_lock.h>
96
97#undef COSA_SLOW_IO /* for testing purposes only */
98
99#include <asm/io.h> 92#include <asm/io.h>
100#include <asm/dma.h> 93#include <asm/dma.h>
101#include <asm/byteorder.h> 94#include <asm/byteorder.h>
102 95
103#include <net/syncppp.h> 96#undef COSA_SLOW_IO /* for testing purposes only */
97
104#include "cosa.h" 98#include "cosa.h"
105 99
106/* Maximum length of the identification string. */ 100/* Maximum length of the identification string. */
@@ -112,7 +106,6 @@
112/* Per-channel data structure */ 106/* Per-channel data structure */
113 107
114struct channel_data { 108struct channel_data {
115 void *if_ptr; /* General purpose pointer (used by SPPP) */
116 int usage; /* Usage count; >0 for chrdev, -1 for netdev */ 109 int usage; /* Usage count; >0 for chrdev, -1 for netdev */
117 int num; /* Number of the channel */ 110 int num; /* Number of the channel */
118 struct cosa_data *cosa; /* Pointer to the per-card structure */ 111 struct cosa_data *cosa; /* Pointer to the per-card structure */
@@ -136,10 +129,9 @@ struct channel_data {
136 wait_queue_head_t txwaitq, rxwaitq; 129 wait_queue_head_t txwaitq, rxwaitq;
137 int tx_status, rx_status; 130 int tx_status, rx_status;
138 131
139 /* SPPP/HDLC device parts */ 132 /* generic HDLC device parts */
140 struct ppp_device pppdev; 133 struct net_device *netdev;
141 struct sk_buff *rx_skb, *tx_skb; 134 struct sk_buff *rx_skb, *tx_skb;
142 struct net_device_stats stats;
143}; 135};
144 136
145/* cosa->firmware_status bits */ 137/* cosa->firmware_status bits */
@@ -281,21 +273,19 @@ static int cosa_start_tx(struct channel_data *channel, char *buf, int size);
281static void cosa_kick(struct cosa_data *cosa); 273static void cosa_kick(struct cosa_data *cosa);
282static int cosa_dma_able(struct channel_data *chan, char *buf, int data); 274static int cosa_dma_able(struct channel_data *chan, char *buf, int data);
283 275
284/* SPPP/HDLC stuff */ 276/* Network device stuff */
285static void sppp_channel_init(struct channel_data *chan); 277static int cosa_net_attach(struct net_device *dev, unsigned short encoding,
286static void sppp_channel_delete(struct channel_data *chan); 278 unsigned short parity);
287static int cosa_sppp_open(struct net_device *d); 279static int cosa_net_open(struct net_device *d);
288static int cosa_sppp_close(struct net_device *d); 280static int cosa_net_close(struct net_device *d);
289static void cosa_sppp_timeout(struct net_device *d); 281static void cosa_net_timeout(struct net_device *d);
290static int cosa_sppp_tx(struct sk_buff *skb, struct net_device *d); 282static int cosa_net_tx(struct sk_buff *skb, struct net_device *d);
291static char *sppp_setup_rx(struct channel_data *channel, int size); 283static char *cosa_net_setup_rx(struct channel_data *channel, int size);
292static int sppp_rx_done(struct channel_data *channel); 284static int cosa_net_rx_done(struct channel_data *channel);
293static int sppp_tx_done(struct channel_data *channel, int size); 285static int cosa_net_tx_done(struct channel_data *channel, int size);
294static int cosa_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); 286static int cosa_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
295static struct net_device_stats *cosa_net_stats(struct net_device *dev);
296 287
297/* Character device */ 288/* Character device */
298static void chardev_channel_init(struct channel_data *chan);
299static char *chrdev_setup_rx(struct channel_data *channel, int size); 289static char *chrdev_setup_rx(struct channel_data *channel, int size);
300static int chrdev_rx_done(struct channel_data *channel); 290static int chrdev_rx_done(struct channel_data *channel);
301static int chrdev_tx_done(struct channel_data *channel, int size); 291static int chrdev_tx_done(struct channel_data *channel, int size);
@@ -357,17 +347,17 @@ static void debug_status_in(struct cosa_data *cosa, int status);
357static void debug_status_out(struct cosa_data *cosa, int status); 347static void debug_status_out(struct cosa_data *cosa, int status);
358#endif 348#endif
359 349
360 350static inline struct channel_data* dev_to_chan(struct net_device *dev)
351{
352 return (struct channel_data *)dev_to_hdlc(dev)->priv;
353}
354
361/* ---------- Initialization stuff ---------- */ 355/* ---------- Initialization stuff ---------- */
362 356
363static int __init cosa_init(void) 357static int __init cosa_init(void)
364{ 358{
365 int i, err = 0; 359 int i, err = 0;
366 360
367 printk(KERN_INFO "cosa v1.08 (c) 1997-2000 Jan Kasprzak <kas@fi.muni.cz>\n");
368#ifdef CONFIG_SMP
369 printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n");
370#endif
371 if (cosa_major > 0) { 361 if (cosa_major > 0) {
372 if (register_chrdev(cosa_major, "cosa", &cosa_fops)) { 362 if (register_chrdev(cosa_major, "cosa", &cosa_fops)) {
373 printk(KERN_WARNING "cosa: unable to get major %d\n", 363 printk(KERN_WARNING "cosa: unable to get major %d\n",
@@ -402,7 +392,7 @@ static int __init cosa_init(void)
402 NULL, "cosa%d", i); 392 NULL, "cosa%d", i);
403 err = 0; 393 err = 0;
404 goto out; 394 goto out;
405 395
406out_chrdev: 396out_chrdev:
407 unregister_chrdev(cosa_major, "cosa"); 397 unregister_chrdev(cosa_major, "cosa");
408out: 398out:
@@ -414,43 +404,29 @@ static void __exit cosa_exit(void)
414{ 404{
415 struct cosa_data *cosa; 405 struct cosa_data *cosa;
416 int i; 406 int i;
417 printk(KERN_INFO "Unloading the cosa module\n");
418 407
419 for (i=0; i<nr_cards; i++) 408 for (i = 0; i < nr_cards; i++)
420 device_destroy(cosa_class, MKDEV(cosa_major, i)); 409 device_destroy(cosa_class, MKDEV(cosa_major, i));
421 class_destroy(cosa_class); 410 class_destroy(cosa_class);
422 for (cosa=cosa_cards; nr_cards--; cosa++) { 411
412 for (cosa = cosa_cards; nr_cards--; cosa++) {
423 /* Clean up the per-channel data */ 413 /* Clean up the per-channel data */
424 for (i=0; i<cosa->nchannels; i++) { 414 for (i = 0; i < cosa->nchannels; i++) {
425 /* Chardev driver has no alloc'd per-channel data */ 415 /* Chardev driver has no alloc'd per-channel data */
426 sppp_channel_delete(cosa->chan+i); 416 unregister_hdlc_device(cosa->chan[i].netdev);
417 free_netdev(cosa->chan[i].netdev);
427 } 418 }
428 /* Clean up the per-card data */ 419 /* Clean up the per-card data */
429 kfree(cosa->chan); 420 kfree(cosa->chan);
430 kfree(cosa->bouncebuf); 421 kfree(cosa->bouncebuf);
431 free_irq(cosa->irq, cosa); 422 free_irq(cosa->irq, cosa);
432 free_dma(cosa->dma); 423 free_dma(cosa->dma);
433 release_region(cosa->datareg,is_8bit(cosa)?2:4); 424 release_region(cosa->datareg, is_8bit(cosa) ? 2 : 4);
434 } 425 }
435 unregister_chrdev(cosa_major, "cosa"); 426 unregister_chrdev(cosa_major, "cosa");
436} 427}
437module_exit(cosa_exit); 428module_exit(cosa_exit);
438 429
439/*
440 * This function should register all the net devices needed for the
441 * single channel.
442 */
443static __inline__ void channel_init(struct channel_data *chan)
444{
445 sprintf(chan->name, "cosa%dc%d", chan->cosa->num, chan->num);
446
447 /* Initialize the chardev data structures */
448 chardev_channel_init(chan);
449
450 /* Register the sppp interface */
451 sppp_channel_init(chan);
452}
453
454static int cosa_probe(int base, int irq, int dma) 430static int cosa_probe(int base, int irq, int dma)
455{ 431{
456 struct cosa_data *cosa = cosa_cards+nr_cards; 432 struct cosa_data *cosa = cosa_cards+nr_cards;
@@ -576,13 +552,43 @@ static int cosa_probe(int base, int irq, int dma)
576 /* Initialize the per-channel data */ 552 /* Initialize the per-channel data */
577 cosa->chan = kcalloc(cosa->nchannels, sizeof(struct channel_data), GFP_KERNEL); 553 cosa->chan = kcalloc(cosa->nchannels, sizeof(struct channel_data), GFP_KERNEL);
578 if (!cosa->chan) { 554 if (!cosa->chan) {
579 err = -ENOMEM; 555 err = -ENOMEM;
580 goto err_out3; 556 goto err_out3;
581 } 557 }
582 for (i=0; i<cosa->nchannels; i++) { 558
583 cosa->chan[i].cosa = cosa; 559 for (i = 0; i < cosa->nchannels; i++) {
584 cosa->chan[i].num = i; 560 struct channel_data *chan = &cosa->chan[i];
585 channel_init(cosa->chan+i); 561
562 chan->cosa = cosa;
563 chan->num = i;
564 sprintf(chan->name, "cosa%dc%d", chan->cosa->num, i);
565
566 /* Initialize the chardev data structures */
567 mutex_init(&chan->rlock);
568 init_MUTEX(&chan->wsem);
569
570 /* Register the network interface */
571 if (!(chan->netdev = alloc_hdlcdev(chan))) {
572 printk(KERN_WARNING "%s: alloc_hdlcdev failed.\n",
573 chan->name);
574 goto err_hdlcdev;
575 }
576 dev_to_hdlc(chan->netdev)->attach = cosa_net_attach;
577 dev_to_hdlc(chan->netdev)->xmit = cosa_net_tx;
578 chan->netdev->open = cosa_net_open;
579 chan->netdev->stop = cosa_net_close;
580 chan->netdev->do_ioctl = cosa_net_ioctl;
581 chan->netdev->tx_timeout = cosa_net_timeout;
582 chan->netdev->watchdog_timeo = TX_TIMEOUT;
583 chan->netdev->base_addr = chan->cosa->datareg;
584 chan->netdev->irq = chan->cosa->irq;
585 chan->netdev->dma = chan->cosa->dma;
586 if (register_hdlc_device(chan->netdev)) {
587 printk(KERN_WARNING "%s: register_hdlc_device()"
588 " failed.\n", chan->netdev->name);
589 free_netdev(chan->netdev);
590 goto err_hdlcdev;
591 }
586 } 592 }
587 593
588 printk (KERN_INFO "cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n", 594 printk (KERN_INFO "cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",
@@ -590,13 +596,20 @@ static int cosa_probe(int base, int irq, int dma)
590 cosa->datareg, cosa->irq, cosa->dma, cosa->nchannels); 596 cosa->datareg, cosa->irq, cosa->dma, cosa->nchannels);
591 597
592 return nr_cards++; 598 return nr_cards++;
599
600err_hdlcdev:
601 while (i-- > 0) {
602 unregister_hdlc_device(cosa->chan[i].netdev);
603 free_netdev(cosa->chan[i].netdev);
604 }
605 kfree(cosa->chan);
593err_out3: 606err_out3:
594 kfree(cosa->bouncebuf); 607 kfree(cosa->bouncebuf);
595err_out2: 608err_out2:
596 free_dma(cosa->dma); 609 free_dma(cosa->dma);
597err_out1: 610err_out1:
598 free_irq(cosa->irq, cosa); 611 free_irq(cosa->irq, cosa);
599err_out: 612err_out:
600 release_region(cosa->datareg,is_8bit(cosa)?2:4); 613 release_region(cosa->datareg,is_8bit(cosa)?2:4);
601 printk(KERN_NOTICE "cosa%d: allocating resources failed\n", 614 printk(KERN_NOTICE "cosa%d: allocating resources failed\n",
602 cosa->num); 615 cosa->num);
@@ -604,54 +617,19 @@ err_out:
604} 617}
605 618
606 619
607/*---------- SPPP/HDLC netdevice ---------- */ 620/*---------- network device ---------- */
608 621
609static void cosa_setup(struct net_device *d) 622static int cosa_net_attach(struct net_device *dev, unsigned short encoding,
623 unsigned short parity)
610{ 624{
611 d->open = cosa_sppp_open; 625 if (encoding == ENCODING_NRZ && parity == PARITY_CRC16_PR1_CCITT)
612 d->stop = cosa_sppp_close; 626 return 0;
613 d->hard_start_xmit = cosa_sppp_tx; 627 return -EINVAL;
614 d->do_ioctl = cosa_sppp_ioctl;
615 d->get_stats = cosa_net_stats;
616 d->tx_timeout = cosa_sppp_timeout;
617 d->watchdog_timeo = TX_TIMEOUT;
618}
619
620static void sppp_channel_init(struct channel_data *chan)
621{
622 struct net_device *d;
623 chan->if_ptr = &chan->pppdev;
624 d = alloc_netdev(0, chan->name, cosa_setup);
625 if (!d) {
626 printk(KERN_WARNING "%s: alloc_netdev failed.\n", chan->name);
627 return;
628 }
629 chan->pppdev.dev = d;
630 d->base_addr = chan->cosa->datareg;
631 d->irq = chan->cosa->irq;
632 d->dma = chan->cosa->dma;
633 d->ml_priv = chan;
634 sppp_attach(&chan->pppdev);
635 if (register_netdev(d)) {
636 printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
637 sppp_detach(d);
638 free_netdev(d);
639 chan->pppdev.dev = NULL;
640 return;
641 }
642}
643
644static void sppp_channel_delete(struct channel_data *chan)
645{
646 unregister_netdev(chan->pppdev.dev);
647 sppp_detach(chan->pppdev.dev);
648 free_netdev(chan->pppdev.dev);
649 chan->pppdev.dev = NULL;
650} 628}
651 629
652static int cosa_sppp_open(struct net_device *d) 630static int cosa_net_open(struct net_device *dev)
653{ 631{
654 struct channel_data *chan = d->ml_priv; 632 struct channel_data *chan = dev_to_chan(dev);
655 int err; 633 int err;
656 unsigned long flags; 634 unsigned long flags;
657 635
@@ -662,36 +640,35 @@ static int cosa_sppp_open(struct net_device *d)
662 } 640 }
663 spin_lock_irqsave(&chan->cosa->lock, flags); 641 spin_lock_irqsave(&chan->cosa->lock, flags);
664 if (chan->usage != 0) { 642 if (chan->usage != 0) {
665 printk(KERN_WARNING "%s: sppp_open called with usage count %d\n", 643 printk(KERN_WARNING "%s: cosa_net_open called with usage count"
666 chan->name, chan->usage); 644 " %d\n", chan->name, chan->usage);
667 spin_unlock_irqrestore(&chan->cosa->lock, flags); 645 spin_unlock_irqrestore(&chan->cosa->lock, flags);
668 return -EBUSY; 646 return -EBUSY;
669 } 647 }
670 chan->setup_rx = sppp_setup_rx; 648 chan->setup_rx = cosa_net_setup_rx;
671 chan->tx_done = sppp_tx_done; 649 chan->tx_done = cosa_net_tx_done;
672 chan->rx_done = sppp_rx_done; 650 chan->rx_done = cosa_net_rx_done;
673 chan->usage=-1; 651 chan->usage = -1;
674 chan->cosa->usage++; 652 chan->cosa->usage++;
675 spin_unlock_irqrestore(&chan->cosa->lock, flags); 653 spin_unlock_irqrestore(&chan->cosa->lock, flags);
676 654
677 err = sppp_open(d); 655 err = hdlc_open(dev);
678 if (err) { 656 if (err) {
679 spin_lock_irqsave(&chan->cosa->lock, flags); 657 spin_lock_irqsave(&chan->cosa->lock, flags);
680 chan->usage=0; 658 chan->usage = 0;
681 chan->cosa->usage--; 659 chan->cosa->usage--;
682
683 spin_unlock_irqrestore(&chan->cosa->lock, flags); 660 spin_unlock_irqrestore(&chan->cosa->lock, flags);
684 return err; 661 return err;
685 } 662 }
686 663
687 netif_start_queue(d); 664 netif_start_queue(dev);
688 cosa_enable_rx(chan); 665 cosa_enable_rx(chan);
689 return 0; 666 return 0;
690} 667}
691 668
692static int cosa_sppp_tx(struct sk_buff *skb, struct net_device *dev) 669static int cosa_net_tx(struct sk_buff *skb, struct net_device *dev)
693{ 670{
694 struct channel_data *chan = dev->ml_priv; 671 struct channel_data *chan = dev_to_chan(dev);
695 672
696 netif_stop_queue(dev); 673 netif_stop_queue(dev);
697 674
@@ -700,16 +677,16 @@ static int cosa_sppp_tx(struct sk_buff *skb, struct net_device *dev)
700 return 0; 677 return 0;
701} 678}
702 679
703static void cosa_sppp_timeout(struct net_device *dev) 680static void cosa_net_timeout(struct net_device *dev)
704{ 681{
705 struct channel_data *chan = dev->ml_priv; 682 struct channel_data *chan = dev_to_chan(dev);
706 683
707 if (test_bit(RXBIT, &chan->cosa->rxtx)) { 684 if (test_bit(RXBIT, &chan->cosa->rxtx)) {
708 chan->stats.rx_errors++; 685 chan->netdev->stats.rx_errors++;
709 chan->stats.rx_missed_errors++; 686 chan->netdev->stats.rx_missed_errors++;
710 } else { 687 } else {
711 chan->stats.tx_errors++; 688 chan->netdev->stats.tx_errors++;
712 chan->stats.tx_aborted_errors++; 689 chan->netdev->stats.tx_aborted_errors++;
713 } 690 }
714 cosa_kick(chan->cosa); 691 cosa_kick(chan->cosa);
715 if (chan->tx_skb) { 692 if (chan->tx_skb) {
@@ -719,13 +696,13 @@ static void cosa_sppp_timeout(struct net_device *dev)
719 netif_wake_queue(dev); 696 netif_wake_queue(dev);
720} 697}
721 698
722static int cosa_sppp_close(struct net_device *d) 699static int cosa_net_close(struct net_device *dev)
723{ 700{
724 struct channel_data *chan = d->ml_priv; 701 struct channel_data *chan = dev_to_chan(dev);
725 unsigned long flags; 702 unsigned long flags;
726 703
727 netif_stop_queue(d); 704 netif_stop_queue(dev);
728 sppp_close(d); 705 hdlc_close(dev);
729 cosa_disable_rx(chan); 706 cosa_disable_rx(chan);
730 spin_lock_irqsave(&chan->cosa->lock, flags); 707 spin_lock_irqsave(&chan->cosa->lock, flags);
731 if (chan->rx_skb) { 708 if (chan->rx_skb) {
@@ -736,13 +713,13 @@ static int cosa_sppp_close(struct net_device *d)
736 kfree_skb(chan->tx_skb); 713 kfree_skb(chan->tx_skb);
737 chan->tx_skb = NULL; 714 chan->tx_skb = NULL;
738 } 715 }
739 chan->usage=0; 716 chan->usage = 0;
740 chan->cosa->usage--; 717 chan->cosa->usage--;
741 spin_unlock_irqrestore(&chan->cosa->lock, flags); 718 spin_unlock_irqrestore(&chan->cosa->lock, flags);
742 return 0; 719 return 0;
743} 720}
744 721
745static char *sppp_setup_rx(struct channel_data *chan, int size) 722static char *cosa_net_setup_rx(struct channel_data *chan, int size)
746{ 723{
747 /* 724 /*
748 * We can safely fall back to non-dma-able memory, because we have 725 * We can safely fall back to non-dma-able memory, because we have
@@ -754,66 +731,53 @@ static char *sppp_setup_rx(struct channel_data *chan, int size)
754 if (chan->rx_skb == NULL) { 731 if (chan->rx_skb == NULL) {
755 printk(KERN_NOTICE "%s: Memory squeeze, dropping packet\n", 732 printk(KERN_NOTICE "%s: Memory squeeze, dropping packet\n",
756 chan->name); 733 chan->name);
757 chan->stats.rx_dropped++; 734 chan->netdev->stats.rx_dropped++;
758 return NULL; 735 return NULL;
759 } 736 }
760 chan->pppdev.dev->trans_start = jiffies; 737 chan->netdev->trans_start = jiffies;
761 return skb_put(chan->rx_skb, size); 738 return skb_put(chan->rx_skb, size);
762} 739}
763 740
764static int sppp_rx_done(struct channel_data *chan) 741static int cosa_net_rx_done(struct channel_data *chan)
765{ 742{
766 if (!chan->rx_skb) { 743 if (!chan->rx_skb) {
767 printk(KERN_WARNING "%s: rx_done with empty skb!\n", 744 printk(KERN_WARNING "%s: rx_done with empty skb!\n",
768 chan->name); 745 chan->name);
769 chan->stats.rx_errors++; 746 chan->netdev->stats.rx_errors++;
770 chan->stats.rx_frame_errors++; 747 chan->netdev->stats.rx_frame_errors++;
771 return 0; 748 return 0;
772 } 749 }
773 chan->rx_skb->protocol = htons(ETH_P_WAN_PPP); 750 chan->rx_skb->protocol = hdlc_type_trans(chan->rx_skb, chan->netdev);
774 chan->rx_skb->dev = chan->pppdev.dev; 751 chan->rx_skb->dev = chan->netdev;
775 skb_reset_mac_header(chan->rx_skb); 752 skb_reset_mac_header(chan->rx_skb);
776 chan->stats.rx_packets++; 753 chan->netdev->stats.rx_packets++;
777 chan->stats.rx_bytes += chan->cosa->rxsize; 754 chan->netdev->stats.rx_bytes += chan->cosa->rxsize;
778 netif_rx(chan->rx_skb); 755 netif_rx(chan->rx_skb);
779 chan->rx_skb = NULL; 756 chan->rx_skb = NULL;
780 chan->pppdev.dev->last_rx = jiffies; 757 chan->netdev->last_rx = jiffies;
781 return 0; 758 return 0;
782} 759}
783 760
784/* ARGSUSED */ 761/* ARGSUSED */
785static int sppp_tx_done(struct channel_data *chan, int size) 762static int cosa_net_tx_done(struct channel_data *chan, int size)
786{ 763{
787 if (!chan->tx_skb) { 764 if (!chan->tx_skb) {
788 printk(KERN_WARNING "%s: tx_done with empty skb!\n", 765 printk(KERN_WARNING "%s: tx_done with empty skb!\n",
789 chan->name); 766 chan->name);
790 chan->stats.tx_errors++; 767 chan->netdev->stats.tx_errors++;
791 chan->stats.tx_aborted_errors++; 768 chan->netdev->stats.tx_aborted_errors++;
792 return 1; 769 return 1;
793 } 770 }
794 dev_kfree_skb_irq(chan->tx_skb); 771 dev_kfree_skb_irq(chan->tx_skb);
795 chan->tx_skb = NULL; 772 chan->tx_skb = NULL;
796 chan->stats.tx_packets++; 773 chan->netdev->stats.tx_packets++;
797 chan->stats.tx_bytes += size; 774 chan->netdev->stats.tx_bytes += size;
798 netif_wake_queue(chan->pppdev.dev); 775 netif_wake_queue(chan->netdev);
799 return 1; 776 return 1;
800} 777}
801 778
802static struct net_device_stats *cosa_net_stats(struct net_device *dev)
803{
804 struct channel_data *chan = dev->ml_priv;
805 return &chan->stats;
806}
807
808
809/*---------- Character device ---------- */ 779/*---------- Character device ---------- */
810 780
811static void chardev_channel_init(struct channel_data *chan)
812{
813 mutex_init(&chan->rlock);
814 init_MUTEX(&chan->wsem);
815}
816
817static ssize_t cosa_read(struct file *file, 781static ssize_t cosa_read(struct file *file,
818 char __user *buf, size_t count, loff_t *ppos) 782 char __user *buf, size_t count, loff_t *ppos)
819{ 783{
@@ -1223,16 +1187,15 @@ static int cosa_ioctl_common(struct cosa_data *cosa,
1223 return -ENOIOCTLCMD; 1187 return -ENOIOCTLCMD;
1224} 1188}
1225 1189
1226static int cosa_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, 1190static int cosa_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1227 int cmd)
1228{ 1191{
1229 int rv; 1192 int rv;
1230 struct channel_data *chan = dev->ml_priv; 1193 struct channel_data *chan = dev_to_chan(dev);
1231 rv = cosa_ioctl_common(chan->cosa, chan, cmd, (unsigned long)ifr->ifr_data); 1194 rv = cosa_ioctl_common(chan->cosa, chan, cmd,
1232 if (rv == -ENOIOCTLCMD) { 1195 (unsigned long)ifr->ifr_data);
1233 return sppp_do_ioctl(dev, ifr, cmd); 1196 if (rv != -ENOIOCTLCMD)
1234 } 1197 return rv;
1235 return rv; 1198 return hdlc_ioctl(dev, ifr, cmd);
1236} 1199}
1237 1200
1238static int cosa_chardev_ioctl(struct inode *inode, struct file *file, 1201static int cosa_chardev_ioctl(struct inode *inode, struct file *file,