From f03b865491c2f30f2a4d77cdafc69c978ceb38a0 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 28 Nov 2007 14:27:03 -0800 Subject: sky2: align IP header on Rx if possible The sky2 driver was not aligning the IP header on receive buffers. This workaround is only needed on hardware with broken FIFO, newer chips without FIFO can just DMA to unaligned address. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'drivers/net/sky2.c') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index bc15940ce1bc..30e567a2d5a1 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -64,7 +64,6 @@ #define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le)) #define RX_MAX_PENDING (RX_LE_SIZE/6 - 2) #define RX_DEF_PENDING RX_MAX_PENDING -#define RX_SKB_ALIGN 8 #define TX_RING_SIZE 512 #define TX_DEF_PENDING (TX_RING_SIZE - 1) @@ -1174,24 +1173,32 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp /* * Allocate an skb for receiving. If the MTU is large enough * make the skb non-linear with a fragment list of pages. - * - * It appears the hardware has a bug in the FIFO logic that - * cause it to hang if the FIFO gets overrun and the receive buffer - * is not 64 byte aligned. The buffer returned from netdev_alloc_skb is - * aligned except if slab debugging is enabled. */ static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2) { struct sk_buff *skb; - unsigned long p; int i; - skb = netdev_alloc_skb(sky2->netdev, sky2->rx_data_size + RX_SKB_ALIGN); - if (!skb) - goto nomem; - - p = (unsigned long) skb->data; - skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p); + if (sky2->hw->flags & SKY2_HW_FIFO_HANG_CHECK) { + unsigned char *start; + /* + * Workaround for a bug in FIFO that cause hang + * if the FIFO if the receive buffer is not 64 byte aligned. + * The buffer returned from netdev_alloc_skb is + * aligned except if slab debugging is enabled. + */ + skb = netdev_alloc_skb(sky2->netdev, sky2->rx_data_size + 8); + if (!skb) + goto nomem; + start = PTR_ALIGN(skb->data, 8); + skb_reserve(skb, start - skb->data); + } else { + skb = netdev_alloc_skb(sky2->netdev, + sky2->rx_data_size + NET_IP_ALIGN); + if (!skb) + goto nomem; + skb_reserve(skb, NET_IP_ALIGN); + } for (i = 0; i < sky2->rx_nfrags; i++) { struct page *page = alloc_page(GFP_ATOMIC); -- cgit v1.2.3 From 5f06eba4dce361bfc077868d044768476b41d698 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 28 Nov 2007 14:50:16 -0800 Subject: sky2: rx allocation threshold change When using larger MTU's sky2 driver changes from allocating one data area, to using multiple pages. The threshold for this was based on a heuristic where the cost of a single allocation is bigger than one page. Since the allocator has changed, this heuristic is now incorrect; instead just make the threshold be when the total size of the allocation is greater than one page. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'drivers/net/sky2.c') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 30e567a2d5a1..c177e87182f4 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1234,7 +1234,7 @@ static int sky2_rx_start(struct sky2_port *sky2) struct sky2_hw *hw = sky2->hw; struct rx_ring_info *re; unsigned rxq = rxqaddr[sky2->port]; - unsigned i, size, space, thresh; + unsigned i, size, thresh; sky2->rx_put = sky2->rx_next = 0; sky2_qset(hw, rxq); @@ -1261,28 +1261,18 @@ static int sky2_rx_start(struct sky2_port *sky2) /* Stopping point for hardware truncation */ thresh = (size - 8) / sizeof(u32); - /* Account for overhead of skb - to avoid order > 0 allocation */ - space = SKB_DATA_ALIGN(size) + NET_SKB_PAD - + sizeof(struct skb_shared_info); - - sky2->rx_nfrags = space >> PAGE_SHIFT; + sky2->rx_nfrags = size >> PAGE_SHIFT; BUG_ON(sky2->rx_nfrags > ARRAY_SIZE(re->frag_addr)); - if (sky2->rx_nfrags != 0) { - /* Compute residue after pages */ - space = sky2->rx_nfrags << PAGE_SHIFT; + /* Compute residue after pages */ + size -= sky2->rx_nfrags << PAGE_SHIFT; - if (space < size) - size -= space; - else - size = 0; + /* Optimize to handle small packets and headers */ + if (size < copybreak) + size = copybreak; + if (size < ETH_HLEN) + size = ETH_HLEN; - /* Optimize to handle small packets and headers */ - if (size < copybreak) - size = copybreak; - if (size < ETH_HLEN) - size = ETH_HLEN; - } sky2->rx_data_size = size; /* Fill Rx ring */ -- cgit v1.2.3 From ed4d41616baa404cf29576ff452ea1db12b9e03b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 10 Jan 2008 16:14:14 -0800 Subject: sky2: support for Yukon Supreme Add support from sk98lin vendor driver 10.50.1.3 for 88E8055 and 88E8075 chips. I don't have this hardware to test, so this changes are untested. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 54 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'drivers/net/sky2.c') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c177e87182f4..1e7418f6645a 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -134,6 +134,8 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436C) }, /* 88E8072 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436D) }, /* 88E8055 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4370) }, /* 88E8075 */ { 0 } }; @@ -547,6 +549,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) case CHIP_ID_YUKON_EC_U: case CHIP_ID_YUKON_EX: + case CHIP_ID_YUKON_SUPR: pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); /* select page 3 to access LED control register */ @@ -713,23 +716,33 @@ static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port) { struct net_device *dev = hw->dev[port]; - if (dev->mtu <= ETH_DATA_LEN) - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_DIS | TX_STFW_ENA); + if ( (hw->chip_id == CHIP_ID_YUKON_EX && + hw->chip_rev != CHIP_REV_YU_EX_A0) || + hw->chip_id == CHIP_ID_YUKON_FE_P || + hw->chip_id == CHIP_ID_YUKON_SUPR) { + /* Yukon-Extreme B0 and further Extreme devices */ + /* enable Store & Forward mode for TX */ - else if (hw->chip_id != CHIP_ID_YUKON_EC_U) - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_STFW_ENA | TX_JUMBO_ENA); - else { - /* set Tx GMAC FIFO Almost Empty Threshold */ - sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), - (ECU_JUMBO_WM << 16) | ECU_AE_THR); + if (dev->mtu <= ETH_DATA_LEN) + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_DIS | TX_STFW_ENA); - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_ENA | TX_STFW_DIS); + else + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_ENA| TX_STFW_ENA); + } else { + if (dev->mtu <= ETH_DATA_LEN) + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_ENA); + else { + /* set Tx GMAC FIFO Almost Empty Threshold */ + sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), + (ECU_JUMBO_WM << 16) | ECU_AE_THR); - /* Can't do offload because of lack of store/forward */ - dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM); + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS); + + /* Can't do offload because of lack of store/forward */ + dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM); + } } } @@ -2660,6 +2673,7 @@ static u32 sky2_mhz(const struct sky2_hw *hw) case CHIP_ID_YUKON_EC: case CHIP_ID_YUKON_EC_U: case CHIP_ID_YUKON_EX: + case CHIP_ID_YUKON_SUPR: return 125; case CHIP_ID_YUKON_FE: @@ -2743,6 +2757,15 @@ static int __devinit sky2_init(struct sky2_hw *hw) | SKY2_HW_AUTO_TX_SUM | SKY2_HW_ADV_POWER_CTL; break; + + case CHIP_ID_YUKON_SUPR: + hw->flags = SKY2_HW_GIGABIT + | SKY2_HW_NEWER_PHY + | SKY2_HW_NEW_LE + | SKY2_HW_AUTO_TX_SUM + | SKY2_HW_ADV_POWER_CTL; + break; + default: dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", hw->chip_id); @@ -2813,7 +2836,8 @@ static void sky2_reset(struct sky2_hw *hw) sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR); - if (hw->chip_id == CHIP_ID_YUKON_EX) + if (hw->chip_id == CHIP_ID_YUKON_EX || + hw->chip_id == CHIP_ID_YUKON_SUPR) sky2_write16(hw, SK_REG(i, GMAC_CTRL), GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON | GMC_BYP_RETR_ON); -- cgit v1.2.3 From bcc52894988ac8471667d84eb7d118af37763338 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 10 Jan 2008 16:14:15 -0800 Subject: sky2: version 1.21 Update driver version reflects new hardware support. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/sky2.c') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 1e7418f6645a..626190eb91e7 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -51,7 +51,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.20" +#define DRV_VERSION "1.21" #define PFX DRV_NAME " " /* -- cgit v1.2.3