This fixes sky2 driver on big endian machines. I choose not to use the hardware byteswap facility as it would have required to have a different definition of the various ring data structures and it looks ugly :) On powerpc, there is pretty much no overhead at doing byteswap.
The patch has a couple of places where I reversed 2 assignments, they are harmless, it was before I figured out that the chip will (apparently) not access a descriptor before it's been told to do so via MMIO, and thus the order of the writes to the descriptors is irrelevant (I was also adding wmb's though I removed them). There is a couple of places where we were doing a BE and not LE conversion of a descriptor field (typically in the VLAN code). I'm not sure what's up there but BE "felt" wrong. I have turned them into LE conversions but then I haven't tested VLAN, and I might just misudnerstand what's happening there so I'll let you decide what to do about those. Signed-off-by: Benjamin Herrenschmidt <[EMAIL PROTECTED]> Index: linux-work/drivers/net/sky2.c =================================================================== --- linux-work.orig/drivers/net/sky2.c 2006-09-04 17:35:20.000000000 +1000 +++ linux-work/drivers/net/sky2.c 2006-09-04 17:41:50.000000000 +1000 @@ -811,8 +811,9 @@ static void rx_set_checksum(struct sky2_ struct sky2_rx_le *le; le = sky2_next_rx(sky2); - le->addr = (ETH_HLEN << 16) | ETH_HLEN; + le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN); le->ctrl = 0; + le->length = 0; le->opcode = OP_TCPSTART | HW_OWNER; sky2_write32(sky2->hw, @@ -1001,7 +1002,6 @@ static int sky2_rx_start(struct sky2_por sky2_rx_add(sky2, re->mapaddr); } - /* * The receiver hangs if it receives frames larger than the * packet buffer. As a workaround, truncate oversize frames, but @@ -1250,8 +1250,8 @@ static int sky2_xmit_frame(struct sk_buf le = get_tx_le(sky2); le->tx.tso.size = cpu_to_le16(mss); le->tx.tso.rsvd = 0; - le->opcode = OP_LRGLEN | HW_OWNER; le->ctrl = 0; + le->opcode = OP_LRGLEN | HW_OWNER; sky2->tx_last_mss = mss; } @@ -1262,11 +1262,11 @@ static int sky2_xmit_frame(struct sk_buf if (!le) { le = get_tx_le(sky2); le->tx.addr = 0; - le->opcode = OP_VLAN|HW_OWNER; le->ctrl = 0; + le->opcode = OP_VLAN|HW_OWNER; } else le->opcode |= OP_VLAN; - le->length = cpu_to_be16(vlan_tx_tag_get(skb)); + le->length = cpu_to_le16(vlan_tx_tag_get(skb)); ctrl |= INS_VLAN; } #endif @@ -1955,8 +1955,8 @@ static int sky2_status_intr(struct sky2_ dev = hw->dev[le->link]; sky2 = netdev_priv(dev); - length = le->length; - status = le->status; + length = le16_to_cpu(le->length); + status = le32_to_cpu(le->status); switch (le->opcode & ~HW_OWNER) { case OP_RXSTAT: @@ -1972,7 +1972,7 @@ static int sky2_status_intr(struct sky2_ if (sky2->vlgrp && (status & GMR_FS_VLAN)) { vlan_hwaccel_receive_skb(skb, sky2->vlgrp, - be16_to_cpu(sky2->rx_tag)); + le16_to_cpu(sky2->rx_tag)); } else #endif netif_receive_skb(skb); @@ -2001,7 +2001,7 @@ static int sky2_status_intr(struct sky2_ case OP_RXCHKS: skb = sky2->rx_ring[sky2->rx_next].skb; skb->ip_summed = CHECKSUM_HW; - skb->csum = le16_to_cpu(status); + skb->csum = status & 0xffffu; break; case OP_TXINDEXLE: @@ -3240,6 +3240,7 @@ static int __devinit sky2_probe(struct p struct net_device *dev, *dev1 = NULL; struct sky2_hw *hw; int err, pm_cap, using_dac = 0; + u32 reg; err = pci_enable_device(pdev); if (err) { @@ -3303,16 +3304,12 @@ static int __devinit sky2_probe(struct p } hw->pm_cap = pm_cap; -#ifdef __BIG_ENDIAN - /* byte swap descriptors in hardware */ - { - u32 reg; - - reg = sky2_pci_read32(hw, PCI_DEV_REG2); - reg |= PCI_REV_DESC; - sky2_pci_write32(hw, PCI_DEV_REG2, reg); - } -#endif + /* Don't let it byte swap descriptors in hardware. Clear the bit + * in case a previous driver have set it + */ + reg = sky2_pci_read32(hw, PCI_DEV_REG2); + reg &= ~PCI_REV_DESC; + sky2_pci_write32(hw, PCI_DEV_REG2, reg); /* ring for status responses */ hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES, Index: linux-work/drivers/net/sky2.h =================================================================== --- linux-work.orig/drivers/net/sky2.h 2006-09-04 17:35:20.000000000 +1000 +++ linux-work/drivers/net/sky2.h 2006-09-04 17:36:44.000000000 +1000 @@ -1785,7 +1785,6 @@ enum { }; /* Yukon 2 hardware interface - * Not tested on big endian */ struct sky2_tx_le { union { -- VGER BF report: S 0.992386 - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html