Commit 2bd5662d authored by David S. Miller's avatar David S. Miller

Merge branch 'sonic-next'

Finn Thain says:

====================
Improvements for SONIC ethernet drivers

Now that the necessary sonic driver fixes have been merged, and the merge
window has closed again, I'm sending the remainder of my sonic driver
patch queue.

A couple of these patches will have to be applied in sequence to avoid
'git am' rejects. The others are independent and could have been submitted
individually. Please let me know if I should do that.

The complete sonic driver patch queue was tested on National Semiconductor
hardware (macsonic), qemu-system-m68k (macsonic) and qemu-system-mips64el
(jazzsonic).
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8fb9df97 d5f3889a
...@@ -147,39 +147,12 @@ static int sonic_probe1(struct net_device *dev) ...@@ -147,39 +147,12 @@ static int sonic_probe1(struct net_device *dev)
dev->dev_addr[i*2+1] = val >> 8; dev->dev_addr[i*2+1] = val >> 8;
} }
err = -ENOMEM;
/* Initialize the device structure. */
lp->dma_bitmode = SONIC_BITMODE32; lp->dma_bitmode = SONIC_BITMODE32;
/* Allocate the entire chunk of memory for the descriptors. err = sonic_alloc_descriptors(dev);
Note that this cannot cross a 64K boundary. */ if (err)
lp->descriptors = dma_alloc_coherent(lp->device,
SIZEOF_SONIC_DESC *
SONIC_BUS_SCALE(lp->dma_bitmode),
&lp->descriptors_laddr,
GFP_KERNEL);
if (lp->descriptors == NULL)
goto out; goto out;
/* Now set up the pointers to point to the appropriate places */
lp->cda = lp->descriptors;
lp->tda = lp->cda + (SIZEOF_SONIC_CDA
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->cda_laddr = lp->descriptors_laddr;
lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
dev->netdev_ops = &sonic_netdev_ops; dev->netdev_ops = &sonic_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
......
...@@ -114,17 +114,6 @@ static inline void bit_reverse_addr(unsigned char addr[6]) ...@@ -114,17 +114,6 @@ static inline void bit_reverse_addr(unsigned char addr[6])
addr[i] = bitrev8(addr[i]); addr[i] = bitrev8(addr[i]);
} }
static irqreturn_t macsonic_interrupt(int irq, void *dev_id)
{
irqreturn_t result;
unsigned long flags;
local_irq_save(flags);
result = sonic_interrupt(irq, dev_id);
local_irq_restore(flags);
return result;
}
static int macsonic_open(struct net_device* dev) static int macsonic_open(struct net_device* dev)
{ {
int retval; int retval;
...@@ -135,12 +124,12 @@ static int macsonic_open(struct net_device* dev) ...@@ -135,12 +124,12 @@ static int macsonic_open(struct net_device* dev)
dev->name, dev->irq); dev->name, dev->irq);
goto err; goto err;
} }
/* Under the A/UX interrupt scheme, the onboard SONIC interrupt comes /* Under the A/UX interrupt scheme, the onboard SONIC interrupt gets
* in at priority level 3. However, we sometimes get the level 2 inter- * moved from level 2 to level 3. Unfortunately we still get some
* rupt as well, which must prevent re-entrance of the sonic handler. * level 2 interrupts so register the handler for both.
*/ */
if (dev->irq == IRQ_AUTO_3) { if (dev->irq == IRQ_AUTO_3) {
retval = request_irq(IRQ_NUBUS_9, macsonic_interrupt, 0, retval = request_irq(IRQ_NUBUS_9, sonic_interrupt, 0,
"sonic", dev); "sonic", dev);
if (retval) { if (retval) {
printk(KERN_ERR "%s: unable to get IRQ %d.\n", printk(KERN_ERR "%s: unable to get IRQ %d.\n",
...@@ -186,33 +175,10 @@ static const struct net_device_ops macsonic_netdev_ops = { ...@@ -186,33 +175,10 @@ static const struct net_device_ops macsonic_netdev_ops = {
static int macsonic_init(struct net_device *dev) static int macsonic_init(struct net_device *dev)
{ {
struct sonic_local* lp = netdev_priv(dev); struct sonic_local* lp = netdev_priv(dev);
int err = sonic_alloc_descriptors(dev);
/* Allocate the entire chunk of memory for the descriptors. if (err)
Note that this cannot cross a 64K boundary. */ return err;
lp->descriptors = dma_alloc_coherent(lp->device,
SIZEOF_SONIC_DESC *
SONIC_BUS_SCALE(lp->dma_bitmode),
&lp->descriptors_laddr,
GFP_KERNEL);
if (lp->descriptors == NULL)
return -ENOMEM;
/* Now set up the pointers to point to the appropriate places */
lp->cda = lp->descriptors;
lp->tda = lp->cda + (SIZEOF_SONIC_CDA
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->cda_laddr = lp->descriptors_laddr;
lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
dev->netdev_ops = &macsonic_netdev_ops; dev->netdev_ops = &macsonic_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
......
...@@ -50,6 +50,42 @@ static void sonic_msg_init(struct net_device *dev) ...@@ -50,6 +50,42 @@ static void sonic_msg_init(struct net_device *dev)
netif_dbg(lp, drv, dev, "%s", version); netif_dbg(lp, drv, dev, "%s", version);
} }
static int sonic_alloc_descriptors(struct net_device *dev)
{
struct sonic_local *lp = netdev_priv(dev);
/* Allocate a chunk of memory for the descriptors. Note that this
* must not cross a 64K boundary. It is smaller than one page which
* means that page alignment is a sufficient condition.
*/
lp->descriptors =
dma_alloc_coherent(lp->device,
SIZEOF_SONIC_DESC *
SONIC_BUS_SCALE(lp->dma_bitmode),
&lp->descriptors_laddr, GFP_KERNEL);
if (!lp->descriptors)
return -ENOMEM;
lp->cda = lp->descriptors;
lp->tda = lp->cda + SIZEOF_SONIC_CDA *
SONIC_BUS_SCALE(lp->dma_bitmode);
lp->rda = lp->tda + SIZEOF_SONIC_TD * SONIC_NUM_TDS *
SONIC_BUS_SCALE(lp->dma_bitmode);
lp->rra = lp->rda + SIZEOF_SONIC_RD * SONIC_NUM_RDS *
SONIC_BUS_SCALE(lp->dma_bitmode);
lp->cda_laddr = lp->descriptors_laddr;
lp->tda_laddr = lp->cda_laddr + SIZEOF_SONIC_CDA *
SONIC_BUS_SCALE(lp->dma_bitmode);
lp->rda_laddr = lp->tda_laddr + SIZEOF_SONIC_TD * SONIC_NUM_TDS *
SONIC_BUS_SCALE(lp->dma_bitmode);
lp->rra_laddr = lp->rda_laddr + SIZEOF_SONIC_RD * SONIC_NUM_RDS *
SONIC_BUS_SCALE(lp->dma_bitmode);
return 0;
}
/* /*
* Open/initialize the SONIC controller. * Open/initialize the SONIC controller.
* *
...@@ -264,7 +300,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) ...@@ -264,7 +300,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
entry = lp->next_tx; entry = (lp->eol_tx + 1) & SONIC_TDS_MASK;
sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */ sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */
sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1); /* single fragment */ sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1); /* single fragment */
...@@ -275,27 +311,26 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) ...@@ -275,27 +311,26 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
sonic_tda_put(dev, entry, SONIC_TD_LINK, sonic_tda_put(dev, entry, SONIC_TD_LINK,
sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL); sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL);
wmb(); sonic_tda_put(dev, lp->eol_tx, SONIC_TD_LINK, ~SONIC_EOL &
sonic_tda_get(dev, lp->eol_tx, SONIC_TD_LINK));
netif_dbg(lp, tx_queued, dev, "%s: issuing Tx command\n", __func__);
SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
lp->tx_len[entry] = length; lp->tx_len[entry] = length;
lp->tx_laddr[entry] = laddr; lp->tx_laddr[entry] = laddr;
lp->tx_skb[entry] = skb; lp->tx_skb[entry] = skb;
wmb();
sonic_tda_put(dev, lp->eol_tx, SONIC_TD_LINK,
sonic_tda_get(dev, lp->eol_tx, SONIC_TD_LINK) & ~SONIC_EOL);
lp->eol_tx = entry; lp->eol_tx = entry;
lp->next_tx = (entry + 1) & SONIC_TDS_MASK; entry = (entry + 1) & SONIC_TDS_MASK;
if (lp->tx_skb[lp->next_tx] != NULL) { if (lp->tx_skb[entry]) {
/* The ring is full, the ISR has yet to process the next TD. */ /* The ring is full, the ISR has yet to process the next TD. */
netif_dbg(lp, tx_queued, dev, "%s: stopping queue\n", __func__); netif_dbg(lp, tx_queued, dev, "%s: stopping queue\n", __func__);
netif_stop_queue(dev); netif_stop_queue(dev);
/* after this packet, wait for ISR to free up some TDAs */ /* after this packet, wait for ISR to free up some TDAs */
} else netif_start_queue(dev); }
netif_dbg(lp, tx_queued, dev, "%s: issuing Tx command\n", __func__);
SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&lp->lock, flags);
...@@ -594,11 +629,6 @@ static void sonic_rx(struct net_device *dev) ...@@ -594,11 +629,6 @@ static void sonic_rx(struct net_device *dev)
if (rbe) if (rbe)
SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE); SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE);
/*
* If any worth-while packets have been received, netif_rx()
* has done a mark_bh(NET_BH) for us and will work on them
* when we get to the bottom-half routine.
*/
} }
...@@ -780,7 +810,7 @@ static int sonic_init(struct net_device *dev) ...@@ -780,7 +810,7 @@ static int sonic_init(struct net_device *dev)
SONIC_WRITE(SONIC_UTDA, lp->tda_laddr >> 16); SONIC_WRITE(SONIC_UTDA, lp->tda_laddr >> 16);
SONIC_WRITE(SONIC_CTDA, lp->tda_laddr & 0xffff); SONIC_WRITE(SONIC_CTDA, lp->tda_laddr & 0xffff);
lp->cur_tx = lp->next_tx = 0; lp->cur_tx = 0;
lp->eol_tx = SONIC_NUM_TDS - 1; lp->eol_tx = SONIC_NUM_TDS - 1;
/* /*
......
...@@ -321,7 +321,6 @@ struct sonic_local { ...@@ -321,7 +321,6 @@ struct sonic_local {
unsigned int cur_tx; /* first unacked transmit packet */ unsigned int cur_tx; /* first unacked transmit packet */
unsigned int eol_rx; unsigned int eol_rx;
unsigned int eol_tx; /* last unacked transmit packet */ unsigned int eol_tx; /* last unacked transmit packet */
unsigned int next_tx; /* next free TD */
int msg_enable; int msg_enable;
struct device *device; /* generic device */ struct device *device; /* generic device */
struct net_device_stats stats; struct net_device_stats stats;
...@@ -342,6 +341,7 @@ static void sonic_multicast_list(struct net_device *dev); ...@@ -342,6 +341,7 @@ static void sonic_multicast_list(struct net_device *dev);
static int sonic_init(struct net_device *dev); static int sonic_init(struct net_device *dev);
static void sonic_tx_timeout(struct net_device *dev, unsigned int txqueue); static void sonic_tx_timeout(struct net_device *dev, unsigned int txqueue);
static void sonic_msg_init(struct net_device *dev); static void sonic_msg_init(struct net_device *dev);
static int sonic_alloc_descriptors(struct net_device *dev);
/* Internal inlines for reading/writing DMA buffers. Note that bus /* Internal inlines for reading/writing DMA buffers. Note that bus
size and endianness matter here, whereas they don't for registers, size and endianness matter here, whereas they don't for registers,
......
...@@ -167,47 +167,11 @@ static int __init sonic_probe1(struct net_device *dev) ...@@ -167,47 +167,11 @@ static int __init sonic_probe1(struct net_device *dev)
dev->dev_addr[i*2+1] = val >> 8; dev->dev_addr[i*2+1] = val >> 8;
} }
/* Initialize the device structure. */
lp->dma_bitmode = SONIC_BITMODE32; lp->dma_bitmode = SONIC_BITMODE32;
/* err = sonic_alloc_descriptors(dev);
* Allocate local private descriptor areas in uncached space. if (err)
* The entire structure must be located within the same 64kb segment.
* A simple way to ensure this is to allocate twice the
* size of the structure -- given that the structure is
* much less than 64 kB, at least one of the halves of
* the allocated area will be contained entirely in 64 kB.
* We also allocate extra space for a pointer to allow freeing
* this structure later on (in xtsonic_cleanup_module()).
*/
lp->descriptors = dma_alloc_coherent(lp->device,
SIZEOF_SONIC_DESC *
SONIC_BUS_SCALE(lp->dma_bitmode),
&lp->descriptors_laddr,
GFP_KERNEL);
if (lp->descriptors == NULL) {
err = -ENOMEM;
goto out; goto out;
}
lp->cda = lp->descriptors;
lp->tda = lp->cda + (SIZEOF_SONIC_CDA
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
/* get the virtual dma address */
lp->cda_laddr = lp->descriptors_laddr;
lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
dev->netdev_ops = &xtsonic_netdev_ops; dev->netdev_ops = &xtsonic_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment