summaryrefslogtreecommitdiffstats
path: root/drivers/net/wan/z85230.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wan/z85230.c')
-rw-r--r--drivers/net/wan/z85230.c119
1 files changed, 47 insertions, 72 deletions
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index a802170ce..f6b385de5 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -5,18 +5,18 @@
* 2 of the License, or (at your option) any later version.
*
* (c) Copyright 1998 Building Number Three Ltd
+ * (c) Copyright 2000 Red Hat Software
*
* Development of this driver was funded by Equiinet Ltd
* http://www.equiinet.com
*
* ChangeLog:
*
- * Asynchronous mode dropped for 2.2. For 2.3 we will attempt the
+ * Asynchronous mode dropped for 2.2. For 2.5 we will attempt the
* unification of all the Z85x30 asynchronous drivers for real.
*
- * To Do:
- *
- * Finish DMA mode support.
+ * DMA now uses get_free_page as kmalloc buffers may span a 64K
+ * boundary.
*
* Performance
*
@@ -170,7 +170,7 @@ EXPORT_SYMBOL(z8530_hdlc_kilostream);
/*
* As above but for enhanced chips.
*/
-
+
u8 z8530_hdlc_kilostream_85230[]=
{
4, SYNC_ENAB|SDLC|X1CLK,
@@ -355,13 +355,15 @@ static void z8530_status(struct z8530_channel *chan)
z8530_tx_done(chan);
}
- if(altered&DCD)
+ if(altered&chan->dcdcheck)
{
- if(status&DCD)
+ if(status&chan->dcdcheck)
{
printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3]|RxENABLE);
- if(chan->netdevice)
+ if(chan->netdevice &&
+ ((chan->netdevice->type == ARPHRD_HDLC) ||
+ (chan->netdevice->type == ARPHRD_PPP)))
sppp_reopen(chan->netdevice);
}
else
@@ -441,7 +443,6 @@ static void z8530_dma_status(struct z8530_channel *chan)
if(status&TxEOM)
{
flags=claim_dma_lock();
- /* Transmit underrun */
disable_dma(chan->txdma);
clear_dma_ff(chan->txdma);
chan->txdma_on=0;
@@ -449,13 +450,15 @@ static void z8530_dma_status(struct z8530_channel *chan)
z8530_tx_done(chan);
}
}
- if(altered&DCD)
+ if(altered&chan->dcdcheck)
{
- if(status&DCD)
+ if(status&chan->dcdcheck)
{
printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3]|RxENABLE);
- if(chan->netdevice)
+ if(chan->netdevice &&
+ ((chan->netdevice->type == ARPHRD_HDLC) ||
+ (chan->netdevice->type == ARPHRD_PPP)))
sppp_reopen(chan->netdevice);
}
else
@@ -662,39 +665,28 @@ int z8530_sync_dma_open(struct net_device *dev, struct z8530_channel *c)
c->txdma_on = 0;
/*
- * Allocate the DMA flip buffers
+ * Allocate the DMA flip buffers. Limit by page size.
+ * Everyone runs 1500 mtu or less on wan links so this
+ * should be fine.
*/
- c->rx_buf[0]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
+ if(c->mtu > PAGE_SIZE/2)
+ return -EMSGSIZE;
+
+ c->rx_buf[0]=(void *)get_free_page(GFP_KERNEL|GFP_DMA);
if(c->rx_buf[0]==NULL)
return -ENOBUFS;
- c->rx_buf[1]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
- if(c->rx_buf[1]==NULL)
- {
- kfree(c->rx_buf[0]);
- c->rx_buf[0]=NULL;
- return -ENOBUFS;
- }
+ c->rx_buf[1]=c->rx_buf[0]+PAGE_SIZE/2;
- c->tx_dma_buf[0]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
+ c->tx_dma_buf[0]=(void *)get_free_page(GFP_KERNEL|GFP_DMA);
if(c->tx_dma_buf[0]==NULL)
{
- kfree(c->rx_buf[0]);
- kfree(c->rx_buf[1]);
- c->rx_buf[0]=NULL;
- return -ENOBUFS;
- }
- c->tx_dma_buf[1]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
- if(c->tx_dma_buf[1]==NULL)
- {
- kfree(c->tx_dma_buf[0]);
- kfree(c->rx_buf[0]);
- kfree(c->rx_buf[1]);
+ free_page((unsigned long)c->rx_buf[0]);
c->rx_buf[0]=NULL;
- c->rx_buf[1]=NULL;
- c->tx_dma_buf[0]=NULL;
return -ENOBUFS;
}
+ c->tx_dma_buf[1]=c->tx_dma_buf[0]+PAGE_SIZE/2;
+
c->tx_dma_used=0;
c->dma_tx = 1;
c->dma_num=0;
@@ -806,24 +798,14 @@ int z8530_sync_dma_close(struct net_device *dev, struct z8530_channel *c)
if(c->rx_buf[0])
{
- kfree(c->rx_buf[0]);
+ free_page((unsigned long)c->rx_buf[0]);
c->rx_buf[0]=NULL;
}
- if(c->rx_buf[1])
- {
- kfree(c->rx_buf[1]);
- c->rx_buf[1]=NULL;
- }
if(c->tx_dma_buf[0])
{
- kfree(c->tx_dma_buf[0]);
+ free_page((unsigned long)c->tx_dma_buf[0]);
c->tx_dma_buf[0]=NULL;
}
- if(c->tx_dma_buf[1])
- {
- kfree(c->tx_dma_buf[1]);
- c->tx_dma_buf[1]=NULL;
- }
chk=read_zsreg(c,R0);
write_zsreg(c, R3, c->regs[R3]);
z8530_rtsdtr(c,0);
@@ -857,25 +839,21 @@ int z8530_sync_txdma_open(struct net_device *dev, struct z8530_channel *c)
c->rxdma_on = 0;
c->txdma_on = 0;
- c->tx_dma_buf[0]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
+ /*
+ * Allocate the DMA flip buffers. Limit by page size.
+ * Everyone runs 1500 mtu or less on wan links so this
+ * should be fine.
+ */
+
+ if(c->mtu > PAGE_SIZE/2)
+ return -EMSGSIZE;
+
+ c->tx_dma_buf[0]=(void *)get_free_page(GFP_KERNEL|GFP_DMA);
if(c->tx_dma_buf[0]==NULL)
- {
- kfree(c->rx_buf[0]);
- kfree(c->rx_buf[1]);
- c->rx_buf[0]=NULL;
return -ENOBUFS;
- }
- c->tx_dma_buf[1]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
- if(c->tx_dma_buf[1]==NULL)
- {
- kfree(c->tx_dma_buf[0]);
- kfree(c->rx_buf[0]);
- kfree(c->rx_buf[1]);
- c->rx_buf[0]=NULL;
- c->rx_buf[1]=NULL;
- c->tx_dma_buf[0]=NULL;
- return -ENOBUFS;
- }
+
+ c->tx_dma_buf[1] = c->tx_dma_buf[0] + PAGE_SIZE/2;
+
c->tx_dma_used=0;
c->dma_num=0;
c->dma_ready=1;
@@ -960,14 +938,9 @@ int z8530_sync_txdma_close(struct net_device *dev, struct z8530_channel *c)
if(c->tx_dma_buf[0])
{
- kfree(c->tx_dma_buf[0]);
+ free_page((unsigned long)c->tx_dma_buf[0]);
c->tx_dma_buf[0]=NULL;
}
- if(c->tx_dma_buf[1])
- {
- kfree(c->tx_dma_buf[1]);
- c->tx_dma_buf[1]=NULL;
- }
chk=read_zsreg(c,R0);
write_zsreg(c, R3, c->regs[R3]);
z8530_rtsdtr(c,0);
@@ -1012,6 +985,8 @@ int z8530_init(struct z8530_dev *dev)
floating IRQ transition when we reset the chip */
dev->chanA.irqs=&z8530_nop;
dev->chanB.irqs=&z8530_nop;
+ dev->chanA.dcdcheck=DCD;
+ dev->chanB.dcdcheck=DCD;
/* Reset the chip */
write_zsreg(&dev->chanA, R9, 0xC0);
udelay(200);
@@ -1104,7 +1079,7 @@ int z8530_channel_load(struct z8530_channel *c, u8 *rtable)
c->mtu=1500;
c->max=0;
c->count=0;
- c->status=0; /* Fixme - check DCD now */
+ c->status=read_zsreg(c, R0);
c->sync=1;
write_zsreg(c, R3, c->regs[R3]|RxENABLE);
return 0;
@@ -1251,7 +1226,7 @@ static void z8530_rx_done(struct z8530_channel *c)
* Save the ready state and the buffer currently
* being used as the DMA target
*/
-
+
int ready=c->dma_ready;
unsigned char *rxb=c->rx_buf[c->dma_num];
unsigned long flags;