summaryrefslogtreecommitdiffstats
path: root/drivers/net/wan
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wan')
-rw-r--r--drivers/net/wan/cosa.c19
-rw-r--r--drivers/net/wan/cycx_x25.c62
-rw-r--r--drivers/net/wan/dlci.c67
-rw-r--r--drivers/net/wan/hostess_sv11.c7
-rw-r--r--drivers/net/wan/lapbether.c15
-rw-r--r--drivers/net/wan/sbni.c73
-rw-r--r--drivers/net/wan/sbni.h2
-rw-r--r--drivers/net/wan/sdla.c163
-rw-r--r--drivers/net/wan/sdla_chdlc.c3
-rw-r--r--drivers/net/wan/sdla_fr.c137
-rw-r--r--drivers/net/wan/sdla_ppp.c3
-rw-r--r--drivers/net/wan/sdla_x25.c62
-rw-r--r--drivers/net/wan/sealevel.c7
-rw-r--r--drivers/net/wan/x25_asy.c63
-rw-r--r--drivers/net/wan/z85230.c389
-rw-r--r--drivers/net/wan/z85230.h6
16 files changed, 681 insertions, 397 deletions
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 6883aa69f..873a561ef 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -84,6 +84,7 @@
#include <linux/malloc.h>
#include <linux/poll.h>
#include <linux/fs.h>
+#include <linux/devfs_fs_kernel.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -359,6 +360,8 @@ static void debug_status_out(struct cosa_data *cosa, int status);
/* ---------- Initialization stuff ---------- */
+static devfs_handle_t devfs_handle = NULL;
+
#ifdef MODULE
int init_module(void)
#else
@@ -366,18 +369,19 @@ static int __init cosa_init(void)
#endif
{
int i;
+
printk(KERN_INFO "cosa v1.06 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
#ifdef __SMP__
printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n");
#endif
if (cosa_major > 0) {
- if (register_chrdev(cosa_major, "cosa", &cosa_fops)) {
+ if (devfs_register_chrdev(cosa_major, "cosa", &cosa_fops)) {
printk(KERN_WARNING "cosa: unable to get major %d\n",
cosa_major);
return -EIO;
}
} else {
- if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) {
+ if (!(cosa_major=devfs_register_chrdev(0, "cosa", &cosa_fops))) {
printk(KERN_WARNING "cosa: unable to register chardev\n");
return -EIO;
}
@@ -386,9 +390,14 @@ static int __init cosa_init(void)
cosa_cards[i].num = -1;
for (i=0; io[i] != 0 && i < MAX_CARDS; i++)
cosa_probe(io[i], irq[i], dma[i]);
+ devfs_handle = devfs_mk_dir (NULL, "cosa", 4, NULL);
+ devfs_register_series (devfs_handle, "%u", nr_cards, DEVFS_FL_DEFAULT,
+ cosa_major, 0,
+ S_IFCHR | S_IRUSR | S_IWUSR, 0, 0,
+ &cosa_fops, NULL);
if (!nr_cards) {
printk(KERN_WARNING "cosa: no devices found.\n");
- unregister_chrdev(cosa_major, "cosa");
+ devfs_unregister_chrdev(cosa_major, "cosa");
return -ENODEV;
}
return 0;
@@ -397,9 +406,11 @@ static int __init cosa_init(void)
#ifdef MODULE
void cleanup_module (void)
{
+ int i;
struct cosa_data *cosa;
printk(KERN_INFO "Unloading the cosa module\n");
+ devfs_unregister (devfs_handle);
for (cosa=cosa_cards; nr_cards--; cosa++) {
int i;
/* Clean up the per-channel data */
@@ -414,7 +425,7 @@ void cleanup_module (void)
free_dma(cosa->dma);
release_region(cosa->datareg,is_8bit(cosa)?2:4);
}
- unregister_chrdev(cosa_major, "cosa");
+ devfs_unregister_chrdev(cosa_major, "cosa");
}
#endif
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index e11c9bcfe..e56125734 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -93,6 +93,9 @@
/* This is an extension of the 'struct net_device' we create for each network
interface to keep the rest of X.25 channel-specific data. */
typedef struct x25_channel {
+ /* This member must be first. */
+ struct net_device *slave; /* WAN slave */
+
char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */
char *local_addr; /* local media address, ASCIIZ -
@@ -502,12 +505,10 @@ static int if_open (struct net_device *dev)
x25_channel_t *chan = dev->priv;
cycx_t *card = chan->card;
- if (dev->start)
+ if (netif_running(dev))
return -EBUSY; /* only one open is allowed */
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 1;
+ netif_start_queue(dev);
cyclomx_mod_inc_use_count(card);
return 0;
@@ -521,8 +522,8 @@ static int if_close (struct net_device *dev)
x25_channel_t *chan = dev->priv;
cycx_t *card = chan->card;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
if (chan->state == WAN_CONNECTED || chan->state == WAN_CONNECTING)
chan_disconnect(dev);
@@ -556,7 +557,7 @@ static int if_rebuild_hdr (struct sk_buff *skb)
}
/* Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission).
+ * o set busy flag (marks start of the transmission).
* o check link state. If link is not up, then drop the packet.
* o check channel status. If it's down then initiate a call.
* o pass a packet to corresponding WAN device.
@@ -575,11 +576,6 @@ static int if_send (struct sk_buff *skb, struct net_device *dev)
x25_channel_t *chan = dev->priv;
cycx_t *card = chan->card;
- if (dev->tbusy) {
- ++chan->ifstats.rx_dropped;
- return -EBUSY;
- }
-
if (!chan->svc)
chan->protocol = skb->protocol;
@@ -595,14 +591,14 @@ static int if_send (struct sk_buff *skb, struct net_device *dev)
switch (chan->state) {
case WAN_DISCONNECTED:
if (chan_connect(dev)) {
- dev->tbusy = 1;
+ netif_stop_queue(dev);
return -EBUSY;
}
/* fall thru */
case WAN_CONNECTED:
reset_timer(dev);
dev->trans_start = jiffies;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
if (chan_send(dev, skb))
return -EBUSY;
@@ -632,8 +628,8 @@ static int if_send (struct sk_buff *skb, struct net_device *dev)
skb_pull(skb, 1); /* Remove control byte */
reset_timer(dev);
dev->trans_start = jiffies;
- dev->tbusy = 1;
-
+ netif_stop_queue(dev);
+
if (chan_send(dev, skb)) {
/* prepare for future retransmissions */
skb_push(skb, 1);
@@ -705,9 +701,6 @@ static void cyx_isr (cycx_t *card)
cycx_poke(&card->hw, 0, &z, sizeof(z));
cycx_poke(&card->hw, X25_RXMBOX_OFFS, &z, sizeof(z));
card->in_isr = 0;
-
- if (card->buff_int_mode_unbusy)
- mark_bh(NET_BH);
}
/* Transmit interrupt handler.
@@ -724,7 +717,7 @@ static void tx_intr (cycx_t *card, TX25Cmd *cmd)
/* unbusy device and then dev_tint(); */
if ((dev = get_dev_by_lcn(wandev, lcn)) != NULL) {
card->buff_int_mode_unbusy = 1;
- dev->tbusy = 0;
+ netif_wake_queue(dev);
} else
printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n",
card->devname, lcn);
@@ -1263,11 +1256,13 @@ static int x25_send (cycx_t *card, u8 link, u8 lcn, u8 bitm, int len, void *buf)
static struct net_device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn)
{
struct net_device *dev = wandev->dev;
+ x25_channel_t *chan;
- for (; dev; dev = dev->slave)
- if (((x25_channel_t*)dev->priv)->lcn == lcn)
+ while (dev) {
+ if (chan->lcn == lcn)
break;
-
+ dev = chan->slave;
+ }
return dev;
}
@@ -1275,11 +1270,13 @@ static struct net_device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn)
static struct net_device *get_dev_by_dte_addr (wan_device_t *wandev, char *dte)
{
struct net_device *dev = wandev->dev;
+ x25_channel_t *chan;
- for (; dev; dev = dev->slave)
- if (!strcmp(((x25_channel_t*)dev->priv)->addr, dte))
+ while (dev) {
+ if (!strcmp(chan->addr, dte))
break;
-
+ dev = chan->slave;
+ }
return dev;
}
@@ -1357,7 +1354,7 @@ static void set_chan_state (struct net_device *dev, u8 state)
case WAN_CONNECTED:
string_state = "connected!";
*(u16*)dev->dev_addr = htons(chan->lcn);
- dev->tbusy = 0;
+ netif_wake_queue(dev);
reset_timer(dev);
if (chan->protocol == ETH_P_X25)
@@ -1384,7 +1381,7 @@ static void set_chan_state (struct net_device *dev, u8 state)
if (chan->protocol == ETH_P_X25)
chan_x25_send_event(dev, 2);
- dev->tbusy = 0;
+ netif_wake_queue(dev);
break;
}
@@ -1560,15 +1557,16 @@ static void x25_dump_devs(wan_device_t *wandev)
struct net_device *dev = wandev->dev;
printk(KERN_INFO "X.25 dev states\n");
- printk(KERN_INFO "name: addr: tbusy: protocol:\n");
+ printk(KERN_INFO "name: addr: txoff: protocol:\n");
printk(KERN_INFO "---------------------------------------\n");
- for (; dev; dev = dev->slave) {
+ while(dev) {
x25_channel_t *chan = dev->priv;
- printk(KERN_INFO "%-5.5s %-15.15s %ld ETH_P_%s\n",
- chan->name, chan->addr, dev->tbusy,
+ printk(KERN_INFO "%-5.5s %-15.15s %d ETH_P_%s\n",
+ chan->name, chan->addr, netif_queue_stopped(dev),
chan->protocol == ETH_P_IP ? "IP" : "X25");
+ dev = chan->slave;
}
}
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index a8c52f0d6..362e7a36e 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -244,43 +244,34 @@ static int dlci_transmit(struct sk_buff *skb, struct net_device *dev)
if (!skb || !dev)
return(0);
- if (dev->tbusy)
- return(1);
-
dlp = dev->priv;
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk(KERN_WARNING "%s: transmitter access conflict.\n", dev->name);
- else
+ netif_stop_queue(dev);
+
+ ret = dlp->slave->hard_start_xmit(skb, dlp->slave);
+ switch (ret)
{
- ret = dlp->slave->hard_start_xmit(skb, dlp->slave);
- switch (ret)
- {
- case DLCI_RET_OK:
- dlp->stats.tx_packets++;
- ret = 0;
- break;
-
+ case DLCI_RET_OK:
+ dlp->stats.tx_packets++;
+ ret = 0;
+ break;
case DLCI_RET_ERR:
- dlp->stats.tx_errors++;
- ret = 0;
- break;
-
+ dlp->stats.tx_errors++;
+ ret = 0;
+ break;
case DLCI_RET_DROP:
- dlp->stats.tx_dropped++;
- ret = 1;
- break;
- }
-
- /* Alan Cox recommends always returning 0, and always freeing the packet */
- /* experience suggest a slightly more conservative approach */
-
- if (!ret)
- dev_kfree_skb(skb);
-
- dev->tbusy = 0;
+ dlp->stats.tx_dropped++;
+ ret = 1;
+ break;
}
+ /* Alan Cox recommends always returning 0, and always freeing the packet */
+ /* experience suggest a slightly more conservative approach */
+ if (!ret)
+ {
+ dev_kfree_skb(skb);
+ netif_wake_queue(dev);
+ }
return(ret);
}
@@ -370,19 +361,16 @@ static int dlci_open(struct net_device *dev)
if (!*(short *)(dev->dev_addr))
return(-EINVAL);
- if (!dlp->slave->start)
+ if (!netif_running(dlp->slave))
return(-ENOTCONN);
- dev->flags = 0;
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
flp = dlp->slave->priv;
err = (*flp->activate)(dlp->slave, dev);
if (err)
return(err);
+ netif_start_queue(dev);
+
return 0;
}
@@ -392,14 +380,13 @@ static int dlci_close(struct net_device *dev)
struct frad_local *flp;
int err;
+ netif_stop_queue(dev);
+
dlp = dev->priv;
flp = dlp->slave->priv;
err = (*flp->deactivate)(dlp->slave, dev);
- dev->start = 0;
- dev->tbusy = 1;
-
return 0;
}
@@ -508,7 +495,7 @@ int dlci_del(struct dlci_add *dlci)
if (!master)
return(-ENODEV);
- if (master->start)
+ if (netif_running(master))
return(-EBUSY);
dlp = master->priv;
diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
index d5c7ebd5e..6220d7fdd 100644
--- a/drivers/net/wan/hostess_sv11.c
+++ b/drivers/net/wan/hostess_sv11.c
@@ -122,7 +122,8 @@ static int hostess_open(struct net_device *d)
/*
* Go go go
*/
- d->tbusy=0;
+
+ netif_start_queue(d);
MOD_INC_USE_COUNT;
return 0;
}
@@ -141,8 +142,8 @@ static int hostess_close(struct net_device *d)
/*
* Link layer down
*/
- d->tbusy=1;
-
+ netif_stop_queue(d);
+
switch(dma)
{
case 0:
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index a4564afcb..1fa07475b 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -163,7 +163,7 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
dev = lapbeth_get_x25_dev(dev);
- if (dev == NULL || dev->start == 0) {
+ if (dev == NULL || !netif_running(dev)) {
kfree_skb(skb);
return 0;
}
@@ -215,7 +215,7 @@ static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev)
* Just to be *really* sure not to send anything if the interface
* is down, the ethernet device may have gone.
*/
- if (!dev->start) {
+ if (!netif_running(dev)) {
lapbeth_check_devices(dev);
kfree_skb(skb);
return -ENODEV;
@@ -360,9 +360,6 @@ static int lapbeth_open(struct net_device *dev)
if (lapbeth_check_devices(dev))
return -ENODEV; /* oops, it's gone */
- dev->tbusy = 0;
- dev->start = 1;
-
lapbeth = (struct lapbethdev *)dev->priv;
lapbeth_callbacks.connect_confirmation = lapbeth_connected;
@@ -374,12 +371,11 @@ static int lapbeth_open(struct net_device *dev)
if ((err = lapb_register(lapbeth, &lapbeth_callbacks)) != LAPB_OK) {
printk(KERN_ERR "lapbeth: lapb_register error - %d\n", err);
- dev->tbusy = 1;
- dev->start = 0;
return -ENODEV;
}
MOD_INC_USE_COUNT;
+ netif_start_queue(dev);
return 0;
}
@@ -389,9 +385,8 @@ static int lapbeth_close(struct net_device *dev)
struct lapbethdev *lapbeth;
int err;
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
lapbeth = (struct lapbethdev *)dev->priv;
if ((err = lapb_unregister(lapbeth)) != LAPB_OK)
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 4cf0c05a1..b161fbabc 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -59,11 +59,6 @@
#include <linux/version.h>
-#if LINUX_VERSION_CODE >=0x020200
-#define v22
-#endif
-
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -74,6 +69,7 @@
#include <linux/malloc.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/types.h>
@@ -88,12 +84,8 @@
#include <net/arp.h>
-
-
-#ifdef v22
#include <asm/uaccess.h>
#include <linux/init.h>
-#endif
#include "sbni.h"
@@ -523,6 +515,7 @@ static int __init sbni_probe1(struct net_device *dev, int ioaddr)
dev->hard_header_cache = sbni_header_cache;
dev->header_cache_update = sbni_header_cache_update;
+ spin_lock_init(&lp->lock);
lp->m=dev;
lp->me=dev;
lp->next_lp=NULL;
@@ -538,15 +531,15 @@ static int sbni_open(struct net_device *dev)
{
struct net_local* lp = (struct net_local*)dev->priv;
struct timer_list* watchdog = &lp->watchdog;
-
+ unsigned long flags;
DP( printk("%s: sbni_open\n", dev->name); )
+ save_flags(flags);
cli();
lp->currframe = NULL;
card_start(dev);
- dev->start = 1;
/* set timer watchdog */
init_timer(watchdog);
watchdog->expires = jiffies + SBNI_TIMEOUT;
@@ -555,8 +548,9 @@ static int sbni_open(struct net_device *dev)
add_timer(watchdog);
DP( printk("%s: sbni timer watchdog initialized\n", dev->name); );
- sti();
-
+ restore_flags(flags);
+
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0;
}
@@ -566,21 +560,18 @@ static int sbni_close(struct net_device *dev)
int ioaddr = dev->base_addr;
struct net_local* lp = (struct net_local*) dev->priv;
struct timer_list* watchdog = &lp->watchdog;
-
-
+ unsigned long flags;
+
DP( printk("%s: sbni_close\n", dev->name); )
+ netif_stop_queue(dev);
+
+ save_flags(flags);
cli();
-
sbni_drop_tx_queue(dev);
-
- dev->tbusy = 1;
- dev->start = 0;
-
del_timer(watchdog);
-
outb(0, ioaddr + CSR0);
- sti();
+ restore_flags(flags);
MOD_DEC_USE_COUNT;
return 0;
@@ -590,6 +581,7 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct net_local *lp = (struct net_local*)dev->priv;
struct sbni_hard_header *hh=(struct sbni_hard_header *)skb->data;
+ unsigned long flags;
#ifdef KATYUSHA
struct net_local *nl;
@@ -602,13 +594,6 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev)
if(lp->me != dev)
panic("sbni: lp->me != dev !!!\nMail to developer (xenon@granch.ru) if you noticed this error\n");
- if(dev->interrupt)
- {
- DP( printk("sbni_xmit_start: interrupt\n"); )
- /* May be unloading, don't stamp on */
- return 1; /* the packet buffer this time */
- }
-
hh->number = 1;
hh->reserv = 0;
@@ -623,6 +608,7 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb->len - sizeof(struct sbni_hard_header),
hh->crc);
+ spin_lock_irqsave(&lp->lock, flags);
#ifdef KATYUSHA
/* looking for first idle device */
for (stop=0,nl=lp; nl && !stop; nl=nl->next_lp)
@@ -657,6 +643,7 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* set request for transmit */
outb(inb(dev->base_addr + CSR0) | TR_REQ, dev->base_addr + CSR0);
#endif
+ spin_unlock_irqrestore(&lp->lock, flags);
return 0;
}
@@ -677,9 +664,6 @@ void card_start(struct net_device *dev)
lp->waitack=0;
skb_queue_head_init(&lp->queue);
sbni_drop_tx_queue(dev);
- dev->tbusy = 0;
-
- dev->interrupt = 0;
/* Reset the card and set start parameters */
outb(PR_RES | *(char*)&lp->csr1, dev->base_addr + CSR1);
outb(EN_INT, dev->base_addr + CSR0);
@@ -776,8 +760,7 @@ static inline unsigned short sbni_recv(struct net_device *dev)
/*
* reset output active flags
*/
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
/*} if */
}
case PACKET_RESEND:
@@ -920,17 +903,12 @@ static void sbni_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return;
}
- if(dev->interrupt)
- {
- printk("%s: Reentering the interrupt driver!\n", dev->name);
- return;
- }
- dev->interrupt = 1;
-
csr0 = inb(dev->base_addr + CSR0);
DP( printk("%s: entering interrupt handler, CSR0 = %02x\n", dev->name, csr0); )
lp=dev->priv;
+
+ spin_lock(&lp->lock);
if(!lp->carrier)
lp->carrier=1;
@@ -971,7 +949,7 @@ static void sbni_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
outb(csr0 | EN_INT, dev->base_addr + CSR0);
- dev->interrupt = 0;
+ spin_unlock(&lp->lock);
}
static struct enet_statistics *sbni_get_stats(struct net_device *dev)
@@ -1103,7 +1081,7 @@ static void sbni_watchdog(unsigned long arg)
}
sti();
outb(csr0 | RC_CHK, dev->base_addr + CSR0);
- if(dev->start)
+ if(netif_running(dev))
{
struct timer_list* watchdog = &lp->watchdog;
init_timer(watchdog);
@@ -1167,9 +1145,8 @@ static void sbni_drop_tx_queue(struct net_device *dev)
}
}
lp->waitack=0;
- dev->tbusy = 0;
-
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
+
DP( printk("%s: queue dropping stoped\n",dev->name); );
}
@@ -1194,7 +1171,7 @@ static int sbni_set_mac_address(struct net_device *dev, void *addr)
/* struct net_local *lp = (struct net_local *)dev->priv; */
struct sockaddr *saddr = addr;
- if(dev->start)
+ if(netif_running(dev))
{
/* Only possible while card isn't started */
return -EBUSY;
@@ -1400,13 +1377,11 @@ static int rxl[SBNI_MAX_NUM_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
static int baud[SBNI_MAX_NUM_CARDS] = { 0 };
static long mac[SBNI_MAX_NUM_CARDS] = { 0 };
-#ifdef v22
MODULE_PARM(io, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
MODULE_PARM(rxl, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
MODULE_PARM(baud, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
MODULE_PARM(mac, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
-#endif
static int sbniautodetect = -1;
diff --git a/drivers/net/wan/sbni.h b/drivers/net/wan/sbni.h
index 2e34d8d34..56550d8f2 100644
--- a/drivers/net/wan/sbni.h
+++ b/drivers/net/wan/sbni.h
@@ -146,7 +146,7 @@ struct net_local {
int carrier;
-
+ spinlock_t lock;
};
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 29bedf8f9..64165cd0e 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -510,7 +510,7 @@ int sdla_activate(struct net_device *slave, struct net_device *master)
flp->dlci[i] = abs(flp->dlci[i]);
- if (slave->start && (flp->config.station == FRAD_STATION_NODE))
+ if (netif_running(slave) && (flp->config.station == FRAD_STATION_NODE))
sdla_cmd(slave, SDLA_ACTIVATE_DLCI, 0, 0, &flp->dlci[i], sizeof(short), NULL, NULL);
return(0);
@@ -532,7 +532,7 @@ int sdla_deactivate(struct net_device *slave, struct net_device *master)
flp->dlci[i] = -abs(flp->dlci[i]);
- if (slave->start && (flp->config.station == FRAD_STATION_NODE))
+ if (netif_running(slave) && (flp->config.station == FRAD_STATION_NODE))
sdla_cmd(slave, SDLA_DEACTIVATE_DLCI, 0, 0, &flp->dlci[i], sizeof(short), NULL, NULL);
return(0);
@@ -565,7 +565,7 @@ int sdla_assoc(struct net_device *slave, struct net_device *master)
flp->dlci[i] = -*(short *)(master->dev_addr);
master->mtu = slave->mtu;
- if (slave->start) {
+ if (netif_running(dev)) {
if (flp->config.station == FRAD_STATION_CPE)
sdla_reconfig(slave);
else
@@ -594,7 +594,7 @@ int sdla_deassoc(struct net_device *slave, struct net_device *master)
MOD_DEC_USE_COUNT;
- if (slave->start) {
+ if (netif_running(slave)) {
if (flp->config.station == FRAD_STATION_CPE)
sdla_reconfig(slave);
else
@@ -624,7 +624,7 @@ int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
ret = SDLA_RET_OK;
len = sizeof(struct dlci_conf);
- if (slave->start) {
+ if (netif_running(slave)) {
if (get)
ret = sdla_cmd(slave, SDLA_READ_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0,
NULL, 0, &dlp->config, &len);
@@ -646,7 +646,7 @@ int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
static int sdla_transmit(struct sk_buff *skb, struct net_device *dev)
{
struct frad_local *flp;
- int ret, addr, accept;
+ int ret, addr, accept, i;
short size;
unsigned long flags;
struct buf_entry *pbuf;
@@ -655,90 +655,80 @@ static int sdla_transmit(struct sk_buff *skb, struct net_device *dev)
ret = 0;
accept = 1;
- if (dev->tbusy)
- return(1);
+ netif_stop_queue(dev);
- if (skb == NULL)
- return(0);
+ /*
+ * stupid GateD insists on setting up the multicast router thru us
+ * and we're ill equipped to handle a non Frame Relay packet at this
+ * time!
+ */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk(KERN_WARNING "%s: transmitter access conflict.\n", dev->name);
- else
+ accept = 1;
+ switch (dev->type)
{
- /*
- * stupid GateD insists on setting up the multicast router thru us
- * and we're ill equipped to handle a non Frame Relay packet at this
- * time!
- */
-
- accept = 1;
- switch (dev->type)
+ case ARPHRD_FRAD:
+ if (skb->dev->type != ARPHRD_DLCI)
+ {
+ printk(KERN_WARNING "%s: Non DLCI device, type %i, tried to send on FRAD module.\n", dev->name, skb->dev->type);
+ accept = 0;
+ }
+ break;
+ default:
+ printk(KERN_WARNING "%s: unknown firmware type 0x%4.4X\n", dev->name, dev->type);
+ accept = 0;
+ break;
+ }
+ if (accept)
+ {
+ /* this is frame specific, but till there's a PPP module, it's the default */
+ switch (flp->type)
{
- case ARPHRD_FRAD:
- if (skb->dev->type != ARPHRD_DLCI)
+ case SDLA_S502A:
+ case SDLA_S502E:
+ ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, skb->data, skb->len, NULL, NULL);
+ break;
+ case SDLA_S508:
+ size = sizeof(addr);
+ ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, NULL, skb->len, &addr, &size);
+ if (ret == SDLA_RET_OK)
{
- printk(KERN_WARNING "%s: Non DLCI device, type %i, tried to send on FRAD module.\n", dev->name, skb->dev->type);
- accept = 0;
+ save_flags(flags);
+ cli();
+ SDLA_WINDOW(dev, addr);
+ pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK));
+ sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);
+ SDLA_WINDOW(dev, addr);
+ pbuf->opp_flag = 1;
+ restore_flags(flags);
}
break;
-
- default:
- printk(KERN_WARNING "%s: unknown firmware type 0x%4.4X\n", dev->name, dev->type);
- accept = 0;
- break;
}
-
- if (accept)
+ switch (ret)
{
- /* this is frame specific, but till there's a PPP module, it's the default */
- switch (flp->type)
- {
- case SDLA_S502A:
- case SDLA_S502E:
- ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, skb->data, skb->len, NULL, NULL);
- break;
-
- case SDLA_S508:
- size = sizeof(addr);
- ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, NULL, skb->len, &addr, &size);
- if (ret == SDLA_RET_OK)
- {
- save_flags(flags);
- cli();
- SDLA_WINDOW(dev, addr);
- pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK));
-
- sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);
-
- SDLA_WINDOW(dev, addr);
- pbuf->opp_flag = 1;
- restore_flags(flags);
- }
- break;
- }
-
- switch (ret)
- {
- case SDLA_RET_OK:
- flp->stats.tx_packets++;
- ret = DLCI_RET_OK;
- break;
+ case SDLA_RET_OK:
+ flp->stats.tx_packets++;
+ ret = DLCI_RET_OK;
+ break;
- case SDLA_RET_CIR_OVERFLOW:
- case SDLA_RET_BUF_OVERSIZE:
- case SDLA_RET_NO_BUFS:
- flp->stats.tx_dropped++;
- ret = DLCI_RET_DROP;
- break;
+ case SDLA_RET_CIR_OVERFLOW:
+ case SDLA_RET_BUF_OVERSIZE:
+ case SDLA_RET_NO_BUFS:
+ flp->stats.tx_dropped++;
+ ret = DLCI_RET_DROP;
+ break;
- default:
- flp->stats.tx_errors++;
- ret = DLCI_RET_ERR;
- break;
- }
+ default:
+ flp->stats.tx_errors++;
+ ret = DLCI_RET_ERR;
+ break;
}
- dev->tbusy = 0;
}
+ netif_wake_queue(dev);
+ for(i=0;i<CONFIG_DLCI_MAX;i++)
+ {
+ if(flp->master[i]!=NULL)
+ netif_wake_queue(flp->master[i]);
+ }
return(ret);
}
@@ -892,7 +882,6 @@ static void sdla_isr(int irq, void *dev_id, struct pt_regs * regs)
return;
}
- dev->interrupt = 1;
byte = sdla_byte(dev, flp->type == SDLA_S508 ? SDLA_508_IRQ_INTERFACE : SDLA_502_IRQ_INTERFACE);
switch (byte)
{
@@ -925,7 +914,6 @@ static void sdla_isr(int irq, void *dev_id, struct pt_regs * regs)
/* this clears the byte, informing the Z80 we're done */
byte = 0;
sdla_write(dev, flp->type == SDLA_S508 ? SDLA_508_IRQ_INTERFACE : SDLA_502_IRQ_INTERFACE, &byte, sizeof(byte));
- dev->interrupt = 0;
}
static void sdla_poll(unsigned long device)
@@ -992,9 +980,8 @@ static int sdla_close(struct net_device *dev)
sdla_cmd(dev, SDLA_DISABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
MOD_DEC_USE_COUNT;
return(0);
@@ -1096,10 +1083,8 @@ static int sdla_open(struct net_device *dev)
sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0, &dlp->config, sizeof(struct dlci_conf), NULL, NULL);
}
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
+ netif_start_queue(dev);
+
MOD_INC_USE_COUNT;
return(0);
@@ -1119,7 +1104,7 @@ static int sdla_config(struct net_device *dev, struct frad_conf *conf, int get)
if (!get)
{
- if (dev->start)
+ if (netif_running(dev))
return(-EBUSY);
if(copy_from_user(&data.config, conf, sizeof(struct frad_conf)))
@@ -1182,7 +1167,7 @@ static int sdla_config(struct net_device *dev, struct frad_conf *conf, int get)
else
{
/* no sense reading if the CPU isn't started */
- if (dev->start)
+ if (netif_running(dev))
{
size = sizeof(data);
if (sdla_cmd(dev, SDLA_READ_DLCI_CONFIGURATION, 0, 0, NULL, 0, &data, &size) != SDLA_RET_OK)
@@ -1331,7 +1316,7 @@ int sdla_change_mtu(struct net_device *dev, int new_mtu)
flp = dev->priv;
- if (dev->start)
+ if (netif_running(dev))
return(-EBUSY);
/* for now, you can't change the MTU! */
diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
index 3df910ea1..c0b419afa 100644
--- a/drivers/net/wan/sdla_chdlc.c
+++ b/drivers/net/wan/sdla_chdlc.c
@@ -74,6 +74,9 @@
typedef struct chdlc_private_area
{
+ /* This member must be first. */
+ struct net_device *slave; /* WAN slave */
+
sdla_t *card;
int TracingEnabled; /* For enabling Tracing */
unsigned long curr_trace_addr; /* Used for Tracing */
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
index 0c7f7e8f0..f4431c9dc 100644
--- a/drivers/net/wan/sdla_fr.c
+++ b/drivers/net/wan/sdla_fr.c
@@ -167,6 +167,9 @@
*/
typedef struct fr_channel
{
+ /* This member must be first. */
+ struct net_device *slave; /* WAN slave */
+
char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
unsigned dlci_configured ; /* check whether configured or not */
unsigned cir_status; /* check whether CIR enabled or not */
@@ -1960,7 +1963,9 @@ goto L4;
// Used to send inarp request at given interval
if (card->wandev.state == WAN_CONNECTED) {
int num_remaining = 0;
- for (dev=card->wandev.dev;dev;dev=dev->slave) {
+
+ dev = card->wandev.dev;
+ while (dev) {
fr_channel_t *chan = dev->priv;
if (chan->inarp == INARP_REQUEST &&
@@ -1972,6 +1977,7 @@ goto L4;
chan->inarp_tick = jiffies;
}
}
+ dev = chan->slave;
}
if (!num_remaining) { // no more to process
flags->imask &= ~FR_INTR_TIMER;
@@ -2135,65 +2141,68 @@ static void process_route (sdla_t* card)
/* Dynamic Route adding/removing */
- for (dev = card->wandev.dev; dev ; dev = dev->slave) {
- if ( ((fr_channel_t*)dev->priv)->route_flag == ADD_ROUTE ||
- ((fr_channel_t*)dev->priv)->route_flag == REMOVE_ROUTE ) {
- fs = get_fs();
+ dev = card->wandev.dev;
+ while (dev) {
+ fr_channel_t *chan = dev->priv;
+
+ if (chan->route_flag == ADD_ROUTE ||
+ chan->route_flag == REMOVE_ROUTE ) {
+ fs = get_fs();
- in_dev = dev->ip_ptr;
-
- if( in_dev != NULL && in_dev->ifa_list != NULL) {
- memset(&route, 0, sizeof(route));
- route.rt_dev = dev->name;
- route.rt_flags = 0;
-
- ((struct sockaddr_in *) &(route.rt_dst)) ->
- sin_addr.s_addr=in_dev->ifa_list->ifa_address;
- ((struct sockaddr_in *) &(route.rt_dst)) ->
- sin_family = AF_INET;
- ((struct sockaddr_in *) &(route.rt_genmask)) ->
- sin_addr.s_addr = 0xFFFFFFFF;
- ((struct sockaddr_in *) &(route.rt_genmask)) ->
- sin_family = AF_INET;
-
- switch(((fr_channel_t*)dev->priv)->route_flag) {
-
- case ADD_ROUTE:
- set_fs(get_ds()); /* get user space block */
- err = ip_rt_ioctl( SIOCADDRT, &route);
- set_fs(fs); /* restore old block */
-
- if (err) {
- printk(KERN_INFO "%s: Adding of route failed. Error: %d\n", card->devname,err);
- printk(KERN_INFO "%s: Address: %s\n",
- ((fr_channel_t*)dev->priv)->name,
- in_ntoa(in_dev->ifa_list->ifa_address) );
- }
- else {
- ((fr_channel_t*)dev->priv)->
- route_flag = ROUTE_ADDED;
- }
- break;
+ in_dev = dev->ip_ptr;
+
+ if( in_dev != NULL && in_dev->ifa_list != NULL) {
+ memset(&route, 0, sizeof(route));
+ route.rt_dev = dev->name;
+ route.rt_flags = 0;
+
+ ((struct sockaddr_in *) &(route.rt_dst)) ->
+ sin_addr.s_addr=in_dev->ifa_list->ifa_address;
+ ((struct sockaddr_in *) &(route.rt_dst)) ->
+ sin_family = AF_INET;
+ ((struct sockaddr_in *) &(route.rt_genmask)) ->
+ sin_addr.s_addr = 0xFFFFFFFF;
+ ((struct sockaddr_in *) &(route.rt_genmask)) ->
+ sin_family = AF_INET;
+
+ switch(chan->route_flag) {
+
+ case ADD_ROUTE:
+ set_fs(get_ds()); /* get user space block */
+ err = ip_rt_ioctl( SIOCADDRT, &route);
+ set_fs(fs); /* restore old block */
+
+ if (err) {
+ printk(KERN_INFO "%s: Adding of route failed. Error: %d\n", card->devname,err);
+ printk(KERN_INFO "%s: Address: %s\n",
+ chan->name,
+ in_ntoa(in_dev->ifa_list->ifa_address) );
+ } else {
+ chan->route_flag = ROUTE_ADDED;
+ }
+ break;
- case REMOVE_ROUTE:
- set_fs(get_ds()); /* get user space block */
- err = ip_rt_ioctl( SIOCDELRT, &route);
- set_fs(fs); /* restore old block */
+ case REMOVE_ROUTE:
+ set_fs(get_ds()); /* get user space block */
+ err = ip_rt_ioctl( SIOCDELRT, &route);
+ set_fs(fs); /* restore old block */
+
+ if (err) {
+ printk(KERN_INFO "%s: Deleting of route failed. Error: %d\n", card->devname,err);
+ printk(KERN_INFO "%s: Address: %s\n",
+ dev->name,in_ntoa(in_dev->ifa_list->ifa_address) );
+ } else {
+ printk(KERN_INFO "%s: Removed route.\n",
+ chan->name);
+ chan->route_flag = NO_ROUTE;
+ }
+ break;
+ } /* Case Statement */
+ }
+ } /* If ADD/DELETE ROUTE */
- if (err) {
- printk(KERN_INFO "%s: Deleting of route failed. Error: %d\n", card->devname,err);
- printk(KERN_INFO "%s: Address: %s\n",
- dev->name,in_ntoa(in_dev->ifa_list->ifa_address) );
- } else {
- printk(KERN_INFO "%s: Removed route.\n",
- ((fr_channel_t*)dev->priv)->name);
- ((fr_channel_t*)dev->priv)->route_flag = NO_ROUTE;
- }
- break;
- } /* Case Statement */
- }
- } /* If ADD/DELETE ROUTE */
- } /* Device 'For' Loop */
+ dev = chan->slave;
+ } /* Device 'While' Loop */
card->poll = NULL;
}
@@ -2568,7 +2577,8 @@ static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox)
struct net_device *dev;
/* Remove all routes from associated DLCI's */
- for (dev = card->wandev.dev; dev; dev = dev->slave) {
+ dev = card->wandev.dev;
+ while (dev) {
fr_channel_t *chan = dev->priv;
if (chan->route_flag == ROUTE_ADDED) {
chan->route_flag = REMOVE_ROUTE;
@@ -2578,6 +2588,8 @@ static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox)
if (chan->inarp == INARP_CONFIGURED) {
chan->inarp = INARP_REQUEST;
}
+
+ dev = chan->slave;
}
wanpipe_set_state(card, WAN_DISCONNECTED);
@@ -2590,12 +2602,14 @@ static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox)
int num_requests = 0;
/* Remove all routes from associated DLCI's */
- for (dev = card->wandev.dev; dev; dev = dev->slave) {
+ dev = card->wandev.dev;
+ while (dev) {
fr_channel_t *chan = dev->priv;
if( chan->inarp == INARP_REQUEST ){
num_requests++;
chan->inarp_tick = jiffies;
}
+ dev = chan->slave;
}
/* Allow timer interrupts */
@@ -2731,8 +2745,8 @@ static int fr_dlci_change (sdla_t *card, fr_mbox_t* mbox)
}
}
- for (dev2 =card->wandev.dev; dev2; dev2 = dev2->slave){
-
+ dev2 = card->wandev.dev;
+ while (dev2) {
chan = dev2->priv;
if (chan->dlci_configured == DLCI_CONFIG_PENDING) {
@@ -2741,6 +2755,7 @@ static int fr_dlci_change (sdla_t *card, fr_mbox_t* mbox)
}
}
+ dev2 = chan->slave;
}
return 1;
}
diff --git a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c
index 1b900fc62..f3dcc129b 100644
--- a/drivers/net/wan/sdla_ppp.c
+++ b/drivers/net/wan/sdla_ppp.c
@@ -155,6 +155,9 @@
typedef struct ppp_private_area
{
+ /* This member must be first. */
+ struct net_device *slave; /* WAN slave */
+
sdla_t* card;
unsigned long router_start_time; /*router start time in sec */
unsigned long tick_counter; /*used for 5 second counter*/
diff --git a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c
index 270c5a59f..dfb5d36a5 100644
--- a/drivers/net/wan/sdla_x25.c
+++ b/drivers/net/wan/sdla_x25.c
@@ -75,6 +75,9 @@
*/
typedef struct x25_channel
{
+ /* This member must be first. */
+ struct net_device *slave; /* WAN slave */
+
char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */
unsigned lcn; /* logical channel number */
@@ -708,11 +711,13 @@ static int if_send (struct sk_buff* skb, struct net_device* dev)
return dev->tbusy;
}
printk(KERN_INFO "%s: Transmit time out %s!\n",
- card->devname, dev->name)
- ;
- for( dev2 = card->wandev.dev; dev2; dev2 = dev2->slave)
- {
+ card->devname, dev->name);
+
+ dev2 = card->wandev.dev;
+ while (dev2) {
+ x25_channel_t *chan2 = dev2->priv;
dev2->tbusy = 0;
+ dev2 = chan2->slave;
}
}
chan->tick_counter = jiffies;
@@ -898,13 +903,17 @@ static void wpx_isr (sdla_t* card)
if(card->buff_int_mode_unbusy)
{
- for(dev = card->wandev.dev; dev; dev = dev->slave)
- {
- if(((x25_channel_t*)dev->priv)->devtint)
- {
+ x25_channel_t *chan;
+
+ dev = card->wandev.dev;
+ while (dev) {
+ chan = dev->priv;
+ if(chan->devtint) {
mark_bh(NET_BH);
return;
}
+
+ dev = chan->slave;
}
}
}
@@ -1042,12 +1051,15 @@ static void rx_intr (sdla_t* card)
static void tx_intr (sdla_t* card)
{
struct net_device *dev;
+ x25_channel_t *chan;
/* unbusy all devices and then dev_tint(); */
- for(dev = card->wandev.dev; dev; dev = dev->slave)
- {
- ((x25_channel_t*)dev->priv)->devtint = dev->tbusy;
+ dev = card->wandev.dev;
+ while (dev) {
+ chan->devtint = dev->tbusy;
dev->tbusy = 0;
+
+ dev = chan->slave;
}
}
@@ -1170,8 +1182,8 @@ static void poll_active (sdla_t* card)
/* Fetch X.25 asynchronous events */
x25_fetch_events(card);
- for (dev = card->wandev.dev; dev; dev = dev->slave)
- {
+ dev = card->wandev.dev;
+ while (dev) {
x25_channel_t* chan = dev->priv;
struct sk_buff* skb = chan->tx_skb;
@@ -1199,6 +1211,8 @@ static void poll_active (sdla_t* card)
chan_disc(dev);
}
}
+
+ dev = chan->slave;
}
}
@@ -1785,8 +1799,8 @@ static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
card->devname, new_lcn, mb->data);
/* Find available channel */
- for (dev = wandev->dev; dev; dev = dev->slave)
- {
+ dev = wandev->dev;
+ while (dev) {
chan = dev->priv;
if (!chan->svc || (chan->state != WAN_DISCONNECTED))
@@ -1796,6 +1810,8 @@ static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
/* If just an '@' is specified, accept all incoming calls */
if (strcmp(chan->addr, "") == 0)
break;
+
+ dev = chan->slave;
}
if (dev == NULL)
@@ -1912,8 +1928,14 @@ static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
card->devname, mb->cmd.cause, mb->cmd.diagn);
/* down all logical channels */
- for (dev = wandev->dev; dev; dev = dev->slave)
+ dev = wandev->dev;
+ while (dev) {
+ x25_channel_t *chan = dev->priv;
+
set_chan_state(dev, WAN_DISCONNECTED);
+ dev = chan->slave;
+ }
+
return (cmd == X25_WRITE) ? 0 : 1;
}
@@ -1979,10 +2001,14 @@ static int disconnect (sdla_t* card)
static struct net_device* get_dev_by_lcn (wan_device_t* wandev, unsigned lcn)
{
struct net_device* dev;
+ x25_channel_t *chan;
- for (dev = wandev->dev; dev; dev = dev->slave)
- if (((x25_channel_t*)dev->priv)->lcn == lcn)
+ dev = wandev->dev;
+ while (dev) {
+ if (chan->lcn == lcn)
break;
+ dev = chan->slave;
+ }
return dev;
}
diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c
index 90cccf81d..8fd2ff105 100644
--- a/drivers/net/wan/sealevel.c
+++ b/drivers/net/wan/sealevel.c
@@ -119,7 +119,7 @@ static int sealevel_open(struct net_device *d)
/*
* Go go go
*/
- d->tbusy=0;
+ netif_start_queue(d);
MOD_INC_USE_COUNT;
return 0;
}
@@ -142,8 +142,9 @@ static int sealevel_close(struct net_device *d)
/*
* Link layer down
*/
- d->tbusy=1;
-
+
+ netif_stop_queue(d);
+
switch(unit)
{
case 0:
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index e50865d97..7b647d663 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -205,8 +205,7 @@ static void x25_asy_changed_mtu(struct x25_asy *sl)
static inline void x25_asy_lock(struct x25_asy *sl)
{
- if (test_and_set_bit(0, (void *) &sl->dev->tbusy))
- printk("%s: trying to lock already locked device!\n", sl->dev->name);
+ netif_stop_queue(sl->dev);
}
@@ -214,8 +213,7 @@ static inline void x25_asy_lock(struct x25_asy *sl)
static inline void x25_asy_unlock(struct x25_asy *sl)
{
- if (!test_and_clear_bit(0, (void *)&sl->dev->tbusy))
- printk("%s: trying to unlock already unlocked device!\n", sl->dev->name);
+ netif_wake_queue(sl->dev);
}
/* Send one completely decapsulated IP datagram to the IP layer. */
@@ -303,7 +301,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
/* First make sure we're connected. */
- if (!sl || sl->magic != X25_ASY_MAGIC || !sl->dev->start)
+ if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
return;
if (sl->xleft <= 0)
@@ -313,7 +311,6 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
sl->tx_packets++;
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
x25_asy_unlock(sl);
- mark_bh(NET_BH);
return;
}
@@ -322,6 +319,20 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
sl->xhead += actual;
}
+static void x25_asy_timeout(struct net_device *dev)
+{
+ struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+ /* May be we must check transmitter timeout here ?
+ * 14 Oct 1994 Dmitry Gorodchanin.
+ */
+ printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+ (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ?
+ "bad line quality" : "driver error");
+ sl->xleft = 0;
+ sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ x25_asy_unlock(sl);
+}
+
/* Encapsulate an IP datagram and kick it into a TTY queue. */
static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -329,7 +340,7 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
struct x25_asy *sl = (struct x25_asy*)(dev->priv);
int err;
- if (!dev->start)
+ if (!netif_running(sl->dev))
{
printk("%s: xmit call when iface is down\n", dev->name);
return 1;
@@ -361,25 +372,6 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
* So, no queues !
* 14 Oct 1994 Dmitry Gorodchanin.
*/
- if (dev->tbusy) {
- /* May be we must check transmitter timeout here ?
- * 14 Oct 1994 Dmitry Gorodchanin.
- */
-#ifdef SL_CHECK_TRANSMIT
- if (jiffies - dev->trans_start < 20 * HZ) {
- /* 20 sec timeout not reached */
- return 1;
- }
- printk("%s: transmit timed out, %s?\n", dev->name,
- (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ?
- "bad line quality" : "driver error");
- sl->xleft = 0;
- sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- x25_asy_unlock(sl);
-#else
- return 1;
-#endif
- }
if((err=lapb_data_request(sl,skb))!=LAPB_OK)
{
@@ -414,7 +406,7 @@ static void x25_asy_data_indication(void *token, struct sk_buff *skb)
static void x25_asy_data_transmit(void *token, struct sk_buff *skb)
{
struct x25_asy *sl=token;
- if(sl->dev->tbusy)
+ if (netif_queue_stopped(sl->dev))
{
printk(KERN_ERR "x25_asy: tbusy drop\n");
kfree_skb(skb);
@@ -514,10 +506,8 @@ static int x25_asy_open(struct net_device *dev)
sl->xleft = 0;
sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */
- dev->tbusy = 0;
-/* dev->flags |= IFF_UP; */
- dev->start = 1;
-
+ netif_start_queue(dev);
+
/*
* Now attach LAPB
*/
@@ -551,12 +541,9 @@ static int x25_asy_close(struct net_device *dev)
return -EBUSY;
sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
if((err=lapb_unregister(sl))!=LAPB_OK)
printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err);
-
-/* dev->flags &= ~IFF_UP; */
return 0;
}
@@ -576,7 +563,7 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp,
{
struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
- if (!sl || sl->magic != X25_ASY_MAGIC || !sl->dev->start)
+ if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
return;
/*
@@ -876,6 +863,8 @@ int x25_asy_init(struct net_device *dev)
dev->mtu = SL_MTU;
dev->hard_start_xmit = x25_asy_xmit;
+ dev->tx_timeout = x25_asy_timeout;
+ dev->watchdog_timeo = HZ*20;
dev->open = x25_asy_open_dev;
dev->stop = x25_asy_close;
dev->get_stats = x25_asy_get_stats;
@@ -914,7 +903,7 @@ cleanup_module(void)
* VSV = if dev->start==0, then device
* unregistered while close proc.
*/
- if (x25_asy_ctrls[i]->dev.start)
+ if (netif_running(&(x25_asy_ctrls[i]->dev)))
unregister_netdev(&(x25_asy_ctrls[i]->dev));
kfree(x25_asy_ctrls[i]);
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index f6b385de5..2ff818b04 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -54,12 +54,23 @@
static spinlock_t z8530_buffer_lock = SPIN_LOCK_UNLOCKED;
-/*
+/**
+ * z8530_read_port:
+ * @p: port to read
+ *
* Provided port access methods. The Comtrol SV11 requires no delays
* between accesses and uses PC I/O. Some drivers may need a 5uS delay
+ *
+ * In the longer term this should become an architecture specific
+ * section so that this can become a generic driver interface for all
+ * platforms. For now we only handle PC I/O ports with or without the
+ * dread 5uS sanity delay.
+ *
+ * The caller must hold sufficient locks to avoid violating the horrible
+ * 5uS delay rule.
*/
-extern __inline__ int z8530_read_port(int p)
+extern __inline__ int z8530_read_port(unsigned long p)
{
u8 r=inb(Z8530_PORT_OF(p));
if(p&Z8530_PORT_SLEEP) /* gcc should figure this out efficiently ! */
@@ -67,7 +78,23 @@ extern __inline__ int z8530_read_port(int p)
return r;
}
-extern __inline__ void z8530_write_port(int p, u8 d)
+/**
+ * z8530_write_port:
+ * @p: port to write
+ * @d: value to write
+ *
+ * Write a value to a port with delays if need be. Note that the
+ * caller must hold locks to avoid read/writes from other contexts
+ * violating the 5uS rule
+ *
+ * In the longer term this should become an architecture specific
+ * section so that this can become a generic driver interface for all
+ * platforms. For now we only handle PC I/O ports with or without the
+ * dread 5uS sanity delay.
+ */
+
+
+extern __inline__ void z8530_write_port(unsigned long p, u8 d)
{
outb(d,Z8530_PORT_OF(p));
if(p&Z8530_PORT_SLEEP)
@@ -80,8 +107,16 @@ static void z8530_rx_done(struct z8530_channel *c);
static void z8530_tx_done(struct z8530_channel *c);
-/*
- * Port accesses
+/**
+ * read_zsreg:
+ * @c: Z8530 channel to read from (2 per chip)
+ * @reg: Register to read
+ * FIXME: Use a spinlock.
+ *
+ * Most of the Z8530 registers are indexed off the control registers.
+ * A read is done by writing to the control register and reading the
+ * register back. We do the locking needed to protect this
+ * operation.
*/
extern inline u8 read_zsreg(struct z8530_channel *c, u8 reg)
@@ -97,6 +132,14 @@ extern inline u8 read_zsreg(struct z8530_channel *c, u8 reg)
return r;
}
+/**
+ * read_zsdata:
+ * @c: The Z8530 channel to read the data port from
+ *
+ * The data port provides fast access to some things. We still
+ * have all the 5uS delays to worry about.
+ */
+
extern inline u8 read_zsdata(struct z8530_channel *c)
{
u8 r;
@@ -104,6 +147,17 @@ extern inline u8 read_zsdata(struct z8530_channel *c)
return r;
}
+/**
+ * write_zsreg:
+ * @c: The Z8530 channel
+ * @reg: Register number
+ * @val: Value to write
+ *
+ * Write a value to an indexed register. Perform the locking needed
+ * to honour the irritating delay rules. We know about register 0
+ * being fast to access.
+ */
+
extern inline void write_zsreg(struct z8530_channel *c, u8 reg, u8 val)
{
unsigned long flags;
@@ -194,8 +248,16 @@ u8 z8530_hdlc_kilostream_85230[]=
EXPORT_SYMBOL(z8530_hdlc_kilostream_85230);
-/*
- * Flush the FIFO
+/**
+ * z8530_flush_fifo:
+ * @c: Channel to flush
+ *
+ * Flush the receive FIFO. There is no specific option for this, we
+ * blindly read bytes and discard them. Reading when there is no data
+ * is harmless. The 8530 has a 4 byte FIFO, the 85230 has 8 bytes.
+ *
+ * All locking is handled for the caller. On return data may still be
+ * present if it arrived during the flush.
*/
static void z8530_flush_fifo(struct z8530_channel *c)
@@ -213,7 +275,16 @@ static void z8530_flush_fifo(struct z8530_channel *c)
}
}
-/* Sets or clears DTR/RTS on the requested line */
+/**
+ * z8530_rtsdtr:
+ * @c: The Z8530 channel to contro;
+ * @set: 1 to set, 0 to clear
+ *
+ * Sets or clears DTR/RTS on the requested line. All locking is handled
+ * for the caller. For now we assume all boards use the actual RTS/DTR
+ * on the chip. Apparently one or two don't. We'll scream about them
+ * later.
+ */
static void z8530_rtsdtr(struct z8530_channel *c, int set)
{
@@ -224,9 +295,12 @@ static void z8530_rtsdtr(struct z8530_channel *c, int set)
write_zsreg(c, R5, c->regs[5]);
}
-/*
- * Receive handler. This is much like the async one but not quite the
- * same or as complex
+/**
+ * z8530_rx:
+ * @c: Z8530 channel to process
+ *
+ * Receive handler for receiving in PIO mode. This is much like the
+ * async one but not quite the same or as complex
*
* Note: Its intended that this handler can easily be separated from
* the main code to run realtime. That'll be needed for some machines
@@ -238,9 +312,9 @@ static void z8530_rtsdtr(struct z8530_channel *c, int set)
* other code - this is true in the RT case too.
*
* We only cover the sync cases for this. If you want 2Mbit async
- * do it yourself but consider medical assistance first.
- *
- * This non DMA synchronous mode is portable code.
+ * do it yourself but consider medical assistance first. This non DMA
+ * synchronous mode is portable code. The DMA mode assumes PCI like
+ * ISA DMA
*/
static void z8530_rx(struct z8530_channel *c)
@@ -303,8 +377,14 @@ static void z8530_rx(struct z8530_channel *c)
}
-/*
- * Z8530 transmit interrupt handler
+/**
+ * z8530_tx:
+ * @c: Z8530 channel to process
+ *
+ * Z8530 transmit interrupt handler for the PIO mode. The basic
+ * idea is to attempt to keep the FIFO fed. We fill as many bytes
+ * in as possible, its quite possible that we won't keep up with the
+ * data rate otherwise.
*/
static void z8530_tx(struct z8530_channel *c)
@@ -340,6 +420,17 @@ static void z8530_tx(struct z8530_channel *c)
write_zsctrl(c, RES_H_IUS);
}
+/**
+ * z8530_status:
+ * @chan: Z8530 channel to process
+ *
+ * A status event occured in PIO synchronous mode. There are several
+ * reasons the chip will bother us here. A transmit underrun means we
+ * failed to feed the chip fast enough and just broke a packet. A DCD
+ * change is a line up or down. We communicate that back to the protocol
+ * layer for synchronous PPP to renegotiate.
+ */
+
static void z8530_status(struct z8530_channel *chan)
{
u8 status=read_zsreg(chan, R0);
@@ -387,9 +478,14 @@ struct z8530_irqhandler z8530_sync=
EXPORT_SYMBOL(z8530_sync);
-/*
+/**
+ * z8530_dma_rx:
+ * @chan: Channel to handle
+ *
* Non bus mastering DMA interfaces for the Z8x30 devices. This
- * is really pretty PC specific.
+ * is really pretty PC specific. The DMA mode means that most receive
+ * events are handled by the DMA hardware. We get a kick here only if
+ * a frame ended.
*/
static void z8530_dma_rx(struct z8530_channel *chan)
@@ -417,6 +513,14 @@ static void z8530_dma_rx(struct z8530_channel *chan)
}
}
+/**
+ * z8530_dma_tx:
+ * @chan: The Z8530 channel to handle
+ *
+ * We have received an interrupt while doing DMA transmissions. It
+ * shouldn't happen. Scream loudly if it does.
+ */
+
static void z8530_dma_tx(struct z8530_channel *chan)
{
if(!chan->dma_tx)
@@ -430,6 +534,17 @@ static void z8530_dma_tx(struct z8530_channel *chan)
z8530_tx(chan);
}
+/**
+ * z8530_dma_status:
+ * @chan: Z8530 channel to process
+ *
+ * A status event occured on the Z8530. We receive these for two reasons
+ * when in DMA mode. Firstly if we finished a packet transfer we get one
+ * and kick the next packet out. Secondly we may see a DCD change and
+ * have to poke the protocol layer.
+ *
+ */
+
static void z8530_dma_status(struct z8530_channel *chan)
{
unsigned long flags;
@@ -490,8 +605,11 @@ struct z8530_irqhandler z8530_txdma_sync=
EXPORT_SYMBOL(z8530_txdma_sync);
-/*
- * Interrupt vectors for a Z8530 that is in 'parked' mode.
+/**
+ * z8530_rx_clear:
+ * @c: Z8530 channel to shut up
+ *
+ * Receive interrupt vectors for a Z8530 that is in 'parked' mode.
* For machines with PCI Z85x30 cards, or level triggered interrupts
* (eg the MacII) we must clear the interrupt cause or die.
*/
@@ -516,12 +634,30 @@ static void z8530_rx_clear(struct z8530_channel *c)
write_zsctrl(c, RES_H_IUS);
}
+/**
+ * z8530_tx_clear:
+ * @c: Z8530 channel to shut up
+ *
+ * Transmit interrupt vectors for a Z8530 that is in 'parked' mode.
+ * For machines with PCI Z85x30 cards, or level triggered interrupts
+ * (eg the MacII) we must clear the interrupt cause or die.
+ */
+
static void z8530_tx_clear(struct z8530_channel *c)
{
write_zsctrl(c, RES_Tx_P);
write_zsctrl(c, RES_H_IUS);
}
+/**
+ * z8530_status_clear:
+ * @chan: Z8530 channel to shut up
+ *
+ * Status interrupt vectors for a Z8530 that is in 'parked' mode.
+ * For machines with PCI Z85x30 cards, or level triggered interrupts
+ * (eg the MacII) we must clear the interrupt cause or die.
+ */
+
static void z8530_status_clear(struct z8530_channel *chan)
{
u8 status=read_zsreg(chan, R0);
@@ -541,8 +677,17 @@ struct z8530_irqhandler z8530_nop=
EXPORT_SYMBOL(z8530_nop);
-/*
- * A Z85[2]30 device has stuck its hand in the air for attention
+/**
+ * z8530_interrupt:
+ * @irq: Interrupt number
+ * @dev_id: The Z8530 device that is interrupting.
+ * @regs: unused
+ *
+ * A Z85[2]30 device has stuck its hand in the air for attention.
+ * We scan both the channels on the chip for events and then call
+ * the channel specific call backs for each channel that has events.
+ * We have to use callback functions because the two channels can be
+ * in different modes.
*/
void z8530_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -612,6 +757,15 @@ static char reg_init[16]=
};
+/**
+ * z8530_sync_open:
+ * @dev: The network interface we are using
+ * @c: The Z8530 channel to open in synchronous PIO mode
+ *
+ * Switch a Z8530 into synchronous mode without DMA assist. We
+ * raise the RTS/DTR and commence network operation.
+ */
+
int z8530_sync_open(struct net_device *dev, struct z8530_channel *c)
{
c->sync = 1;
@@ -634,9 +788,19 @@ int z8530_sync_open(struct net_device *dev, struct z8530_channel *c)
EXPORT_SYMBOL(z8530_sync_open);
+/**
+ * z8530_sync_close:
+ * @dev: Network device to close
+ * @c: Z8530 channel to disassociate and move to idle
+ *
+ * Close down a Z8530 interface and switch its interrupt handlers
+ * to discard future events.
+ */
+
int z8530_sync_close(struct net_device *dev, struct z8530_channel *c)
{
u8 chk;
+
c->irqs = &z8530_nop;
c->max = 0;
c->sync = 0;
@@ -649,6 +813,16 @@ int z8530_sync_close(struct net_device *dev, struct z8530_channel *c)
EXPORT_SYMBOL(z8530_sync_close);
+/**
+ * z8530_sync_dma_open:
+ * @dev: The network device to attach
+ * @c: The Z8530 channel to configure in sync DMA mode.
+ *
+ * Set up a Z85x30 device for synchronous DMA in both directions. Two
+ * ISA DMA channels must be available for this to work. We assume ISA
+ * DMA driven I/O and PC limits on access.
+ */
+
int z8530_sync_dma_open(struct net_device *dev, struct z8530_channel *c)
{
unsigned long flags;
@@ -753,11 +927,21 @@ int z8530_sync_dma_open(struct net_device *dev, struct z8530_channel *c)
c->irqs = &z8530_dma_sync;
z8530_rtsdtr(c,1);
write_zsreg(c, R3, c->regs[R3]|RxENABLE);
+
return 0;
}
EXPORT_SYMBOL(z8530_sync_dma_open);
+/**
+ * z8530_sync_dma_close:
+ * @dev: Network device to detach
+ * @c: Z8530 channel to move into discard mode
+ *
+ * Shut down a DMA mode synchronous interface. Halt the DMA, and
+ * free the buffers.
+ */
+
int z8530_sync_dma_close(struct net_device *dev, struct z8530_channel *c)
{
u8 chk;
@@ -814,6 +998,16 @@ int z8530_sync_dma_close(struct net_device *dev, struct z8530_channel *c)
EXPORT_SYMBOL(z8530_sync_dma_close);
+/**
+ * z8530_sync_txdma_open:
+ * @dev: The network device to attach
+ * @c: The Z8530 channel to configure in sync DMA mode.
+ *
+ * Set up a Z85x30 device for synchronous DMA tranmission. One
+ * ISA DMA channel must be available for this to work. The receive
+ * side is run in PIO mode, but then it has the bigger FIFO.
+ */
+
int z8530_sync_txdma_open(struct net_device *dev, struct z8530_channel *c)
{
unsigned long flags;
@@ -898,15 +1092,26 @@ int z8530_sync_txdma_open(struct net_device *dev, struct z8530_channel *c)
z8530_rtsdtr(c,1);
printk("Rx interrupts ON\n");
write_zsreg(c, R3, c->regs[R3]|RxENABLE);
+
return 0;
}
EXPORT_SYMBOL(z8530_sync_txdma_open);
-
+
+/**
+ * z8530_sync_txdma_close:
+ * @dev: Network device to detach
+ * @c: Z8530 channel to move into discard mode
+ *
+ * Shut down a DMA/PIO split mode synchronous interface. Halt the DMA,
+ * and free the buffers.
+ */
+
int z8530_sync_txdma_close(struct net_device *dev, struct z8530_channel *c)
{
unsigned long flags;
u8 chk;
+
c->irqs = &z8530_nop;
c->max = 0;
c->sync = 0;
@@ -950,21 +1155,32 @@ int z8530_sync_txdma_close(struct net_device *dev, struct z8530_channel *c)
EXPORT_SYMBOL(z8530_sync_txdma_close);
+
/*
- * Describe a Z8530 in a standard format. We must pass the I/O as
- * the port offset isnt predictable. The main reason for this function
- * is to try and get a common format of report.
+ * Name strings for Z8530 chips. SGI claim to have a 130, Zilog deny
+ * it exists...
*/
-
+
static char *z8530_type_name[]={
"Z8530",
"Z85C30",
"Z85230"
};
-void z8530_describe(struct z8530_dev *dev, char *mapping, int io)
+/**
+ * z8530_describe:
+ * @dev: Z8530 device to describe
+ * @mapping: string holding mapping type (eg "I/O" or "Mem")
+ * @io: the port value in question
+ *
+ * Describe a Z8530 in a standard format. We must pass the I/O as
+ * the port offset isnt predictable. The main reason for this function
+ * is to try and get a common format of report.
+ */
+
+void z8530_describe(struct z8530_dev *dev, char *mapping, unsigned long io)
{
- printk(KERN_INFO "%s: %s found at %s 0x%X, IRQ %d.\n",
+ printk(KERN_INFO "%s: %s found at %s 0x%lX, IRQ %d.\n",
dev->name,
z8530_type_name[dev->type],
mapping,
@@ -974,8 +1190,21 @@ void z8530_describe(struct z8530_dev *dev, char *mapping, int io)
EXPORT_SYMBOL(z8530_describe);
-/*
- * Configure up a Z8530
+/**
+ * z8530_init:
+ * @dev: Z8530 device to initialise.
+ *
+ * Configure up a Z8530/Z85C30 or Z85230 chip. We check the device
+ * is present, identify the type and then program it to hopefully
+ * keep quite and behave. This matters a lot, a Z8530 in the wrong
+ * state will sometimes get into stupid modes generating 10Khz
+ * interrupt streams and the like.
+ *
+ * We set the interrupt handler up to discard any events, in case
+ * we get them during reset or setp.
+ *
+ * Return 0 for success, or a negative value indicating the problem
+ * in errno form.
*/
@@ -1043,6 +1272,15 @@ int z8530_init(struct z8530_dev *dev)
EXPORT_SYMBOL(z8530_init);
+/**
+ * z8530_shutdown:
+ * @dev: The Z8530 chip to shutdown
+ *
+ * We set the interrupt handlers to silence any interrupts. We then
+ * reset the chip and wait 100uS to be sure the reset completed. Just
+ * in case the caller then tries to do stuff.
+ */
+
int z8530_shutdown(struct z8530_dev *dev)
{
/* Reset the chip */
@@ -1055,9 +1293,15 @@ int z8530_shutdown(struct z8530_dev *dev)
EXPORT_SYMBOL(z8530_shutdown);
-/*
- * Load a Z8530 channel up from the system data
- * We use +16 to indicate the 'prime' registers
+/**
+ * z8530_channel_load:
+ * @c: Z8530 channel to configure
+ * @rtable: Table of register, value pairs
+ * FIXME: ioctl to allow user uploaded tables
+ *
+ * Load a Z8530 channel up from the system data> We use +16 to
+ * indicate the 'prime' registers. The value 255 terminates the
+ * table
*/
int z8530_channel_load(struct z8530_channel *c, u8 *rtable)
@@ -1088,8 +1332,16 @@ int z8530_channel_load(struct z8530_channel *c, u8 *rtable)
EXPORT_SYMBOL(z8530_channel_load);
-/*
- * Higher level shovelling - transmit chains
+/**
+ * z8530_tx_begin:
+ * @c: The Z8530 channel to kick
+ *
+ * This is the speed sensitive side of transmission. If we are called
+ * and no buffer is being transmitted we commence the next buffer. If
+ * nothing is queued we idle the sync.
+ *
+ * Note: We are handling this code path in the interrupt path, keep it
+ * fast or bad things will happen.
*/
static void z8530_tx_begin(struct z8530_channel *c)
@@ -1102,7 +1354,7 @@ static void z8530_tx_begin(struct z8530_channel *c)
c->tx_next_skb=NULL;
c->tx_ptr=c->tx_next_ptr;
- mark_bh(NET_BH);
+ netif_wake_queue(c->netdevice);
if(c->tx_skb==NULL)
{
/* Idle on */
@@ -1176,7 +1428,15 @@ static void z8530_tx_begin(struct z8530_channel *c)
}
}
}
-
+
+/**
+ * z8530_tx_done:
+ * @c: The channel that completed a transmit.
+ *
+ * This is called when we complete a packet send. We wake the queue,
+ * start the next packet going and then free the buffer of the existing
+ * packet. This code is fairly timing sensitive.
+ */
static void z8530_tx_done(struct z8530_channel *c)
{
@@ -1184,7 +1444,7 @@ static void z8530_tx_done(struct z8530_channel *c)
struct sk_buff *skb;
spin_lock_irqsave(&z8530_buffer_lock, flags);
- c->netdevice->tbusy=0;
+ netif_wake_queue(c->netdevice);
/* Actually this can happen.*/
if(c->tx_skb==NULL)
{
@@ -1197,11 +1457,16 @@ static void z8530_tx_done(struct z8530_channel *c)
spin_unlock_irqrestore(&z8530_buffer_lock, flags);
c->stats.tx_packets++;
c->stats.tx_bytes+=skb->len;
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
}
-/*
- * Higher level shovelling - receive chains
+/**
+ * z8530_null_rx:
+ * @c: The channel the packet arrived on
+ * @skb: The buffer
+ *
+ * We point the receive handler at this function when idle. Instead
+ * of syncppp processing the frames we get to throw them away.
*/
void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb)
@@ -1211,6 +1476,17 @@ void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb)
EXPORT_SYMBOL(z8530_null_rx);
+/**
+ * z8530_rx_done:
+ * @c: The channel that completed a receive
+ *
+ * A new packet is complete. Our goal here is to get back into receive
+ * mode as fast as possible. On the Z85230 we could change to using
+ * ESCC mode, but on the older chips we have no choice. We flip to the
+ * new buffer immediately in DMA mode so that the DMA of the next
+ * frame can occur while we are copying the previous buffer to an sk_buff
+ */
+
static void z8530_rx_done(struct z8530_channel *c)
{
struct sk_buff *skb;
@@ -1265,7 +1541,7 @@ static void z8530_rx_done(struct z8530_channel *c)
else
/* Can't occur as we dont reenable the DMA irq until
after the flip is done */
- printk("DMA flip overrun!\n");
+ printk(KERN_WARNING "%s: DMA flip overrun!\n", c->netdevice->name);
release_dma_lock(flags);
@@ -1353,8 +1629,12 @@ static void z8530_rx_done(struct z8530_channel *c)
}
}
-/*
- * Cannot DMA over a 64K boundary on a PC
+/**
+ * spans_boundary:
+ * @skb: The buffer to check
+ *
+ * Returns true if the buffer cross a DMA boundary on a PC. The poor
+ * thing can only DMA within a 64K block not across the edges of it.
*/
extern inline int spans_boundary(struct sk_buff *skb)
@@ -1369,7 +1649,11 @@ extern inline int spans_boundary(struct sk_buff *skb)
return 0;
}
-/*
+/**
+ * z8530_queue_xmit:
+ * @c: The channel to use
+ * @skb: The packet to kick down the channel
+ *
* Queue a packet for transmission. Because we have rather
* hard to hit interrupt latencies for the Z85230 per packet
* even in DMA mode we do the flip to DMA buffer if needed here
@@ -1379,9 +1663,10 @@ extern inline int spans_boundary(struct sk_buff *skb)
int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb)
{
unsigned long flags;
+
+ netif_stop_queue(c->netdevice);
if(c->tx_next_skb)
{
- skb->dev->tbusy=1;
return 1;
}
@@ -1414,11 +1699,21 @@ int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb)
spin_lock_irqsave(&z8530_buffer_lock, flags);
z8530_tx_begin(c);
spin_unlock_irqrestore(&z8530_buffer_lock, flags);
+
+ netif_wake_queue(c->netdevice);
return 0;
}
EXPORT_SYMBOL(z8530_queue_xmit);
+/**
+ * z8530_get_stats:
+ * @c: The channel to use
+ *
+ * Get the statistics block. We keep the statistics in software as
+ * the chip doesn't do it for us.
+ */
+
struct net_device_stats *z8530_get_stats(struct z8530_channel *c)
{
return &c->stats;
diff --git a/drivers/net/wan/z85230.h b/drivers/net/wan/z85230.h
index dcad711b0..8dc92a535 100644
--- a/drivers/net/wan/z85230.h
+++ b/drivers/net/wan/z85230.h
@@ -304,8 +304,8 @@ struct z8530_channel
*/
struct z8530_dev *dev; /* Z85230 chip instance we are from */
- int ctrlio; /* I/O ports */
- int dataio;
+ unsigned long ctrlio; /* I/O ports */
+ unsigned long dataio;
/*
* For PC we encode this way.
@@ -395,7 +395,7 @@ extern u8 z8530_dead_port[];
extern u8 z8530_hdlc_kilostream_85230[];
extern u8 z8530_hdlc_kilostream[];
extern void z8530_interrupt(int, void *, struct pt_regs *);
-extern void z8530_describe(struct z8530_dev *, char *mapping,int io);
+extern void z8530_describe(struct z8530_dev *, char *mapping, unsigned long io);
extern int z8530_init(struct z8530_dev *);
extern int z8530_shutdown(struct z8530_dev *);
extern int z8530_sync_open(struct net_device *, struct z8530_channel *);