From: Matthias Urlichs <[email protected]>
Macintosh CS89x0 Ethernet: Netif updates
Addition of netif_stop_queue() before transmission by Michael Schmitz
skb_copy_{from,to}_linear_data() conversion by Geert Uytterhoeven
Signed-off-by: Geert Uytterhoeven <[email protected]>
---
drivers/net/Kconfig | 2 -
drivers/net/mac89x0.c | 92 ++++++++++++++++++--------------------------------
2 files changed, 35 insertions(+), 59 deletions(-)
--- linux-m68k-2.6.21.orig/drivers/net/Kconfig
+++ linux-m68k-2.6.21/drivers/net/Kconfig
@@ -311,7 +311,7 @@ config MAC8390
config MAC89x0
tristate "Macintosh CS89x0 based ethernet cards"
- depends on NET_ETHERNET && MAC && BROKEN
+ depends on NET_ETHERNET && MAC
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
Nubus or LC-PDS network (Ethernet) card of this type, say Y and
--- linux-m68k-2.6.21.orig/drivers/net/mac89x0.c
+++ linux-m68k-2.6.21/drivers/net/mac89x0.c
@@ -128,7 +128,7 @@ struct net_local {
extern void reset_chip(struct net_device *dev);
#endif
static int net_open(struct net_device *dev);
-static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
+static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t net_interrupt(int irq, void *dev_id);
static void set_multicast_list(struct net_device *dev);
static void net_rx(struct net_device *dev);
@@ -374,56 +374,39 @@ net_open(struct net_device *dev)
static int
net_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- if (dev->tbusy) {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5)
- return 1;
- if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
- tx_done(dev) ? "IRQ conflict" : "network cable problem");
- /* Try to restart the adaptor. */
- dev->tbusy=0;
- dev->trans_start = jiffies;
- }
-
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
- struct net_local *lp = netdev_priv(dev);
- unsigned long flags;
-
- if (net_debug > 3)
- printk("%s: sent %d byte packet of type %x\n",
- dev->name, skb->len,
- (skb->data[ETH_ALEN+ETH_ALEN] << 8)
- | skb->data[ETH_ALEN+ETH_ALEN+1]);
-
- /* keep the upload from being interrupted, since we
- ask the chip to start transmitting before the
- whole packet has been completely uploaded. */
- local_irq_save(flags);
-
- /* initiate a transmit sequence */
- writereg(dev, PP_TxCMD, lp->send_cmd);
- writereg(dev, PP_TxLength, skb->len);
-
- /* Test to see if the chip has allocated memory for the packet */
- if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
- /* Gasp! It hasn't. But that shouldn't happen since
- we're waiting for TxOk, so return 1 and requeue this packet. */
- local_irq_restore(flags);
- return 1;
- }
+ struct net_local *lp = netdev_priv(dev);
+ unsigned long flags;
- /* Write the contents of the packet */
- memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1);
+ if (net_debug > 3)
+ printk("%s: sent %d byte packet of type %x\n",
+ dev->name, skb->len,
+ (skb->data[ETH_ALEN+ETH_ALEN] << 8)
+ | skb->data[ETH_ALEN+ETH_ALEN+1]);
+
+ /* keep the upload from being interrupted, since we
+ ask the chip to start transmitting before the
+ whole packet has been completely uploaded. */
+ local_irq_save(flags);
+ netif_stop_queue(dev);
+ /* initiate a transmit sequence */
+ writereg(dev, PP_TxCMD, lp->send_cmd);
+ writereg(dev, PP_TxLength, skb->len);
+
+ /* Test to see if the chip has allocated memory for the packet */
+ if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
+ /* Gasp! It hasn't. But that shouldn't happen since
+ we're waiting for TxOk, so return 1 and requeue this packet. */
local_irq_restore(flags);
- dev->trans_start = jiffies;
+ return 1;
}
+
+ /* Write the contents of the packet */
+ skb_copy_from_linear_data(skb, (void *)(dev->mem_start + PP_TxFrame),
+ skb->len+1);
+
+ local_irq_restore(flags);
+ dev->trans_start = jiffies;
dev_kfree_skb (skb);
return 0;
@@ -441,9 +424,6 @@ static irqreturn_t net_interrupt(int irq
printk ("net_interrupt(): irq %d for unknown device.\n", irq);
return IRQ_NONE;
}
- if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
- dev->interrupt = 1;
ioaddr = dev->base_addr;
lp = netdev_priv(dev);
@@ -464,8 +444,7 @@ static irqreturn_t net_interrupt(int irq
break;
case ISQ_TRANSMITTER_EVENT:
lp->stats.tx_packets++;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue(dev);
if ((status & TX_OK) == 0) lp->stats.tx_errors++;
if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
@@ -479,8 +458,7 @@ static irqreturn_t net_interrupt(int irq
That shouldn't happen since we only ever
load one packet. Shrug. Do the right
thing anyway. */
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue(dev);
}
if (status & TX_UNDERRUN) {
if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
@@ -497,7 +475,6 @@ static irqreturn_t net_interrupt(int irq
break;
}
}
- dev->interrupt = 0;
return IRQ_HANDLED;
}
@@ -531,7 +508,8 @@ net_rx(struct net_device *dev)
}
skb_put(skb, length);
- memcpy_fromio(skb->data, dev->mem_start + PP_RxFrame, length);
+ skb_copy_to_linear_data(skb, (void *)(dev->mem_start + PP_RxFrame),
+ length);
if (net_debug > 3)printk("%s: received %d byte packet of type %x\n",
dev->name, length,
@@ -610,8 +588,6 @@ static void set_multicast_list(struct ne
static int set_mac_address(struct net_device *dev, void *addr)
{
int i;
- if (dev->start)
- return -EBUSY;
printk("%s: Setting MAC address to ", dev->name);
for (i = 0; i < 6; i++)
printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);
--
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]