Skip to contentSkip to conversation

Marvell SysKonnect related driver fixes

PATCH New Stephen Hemminger 1 participant 8 messages Jul 12, 2006

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Marvell SysKonnect related driver fixes

Minor fixes for sky2 and related drivers. Includes the collision threshold mask (and related drivers).

Known outstanding problems:
* sky2 hangs which are unreproducible on the machines in

    my environment :-(

* sky2 probably has problems on dual-port card on pci-express, fixed on pci-x
* wake on LAN still not supported
--

#1 lore raw

PATCH 1/7 sky2: fix truncated collision threshold mask

Patch to correct broken collision threshold mask in sky2 driver. Should be three bits wide, but the mask only allows for 1 bit to be set.

Thanks & Regards
Neil

 sky2.h |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)
drivers/net/sky2.h +1 -1
index 8a0bc55..2db8d19 100644
@@ -1480,7 +1480,7 @@ enum {
 	GM_TXCR_FORCE_JAM	= 1<<15, /* Bit 15:	Force Jam / Flow-Control */
 	GM_TXCR_CRC_DIS		= 1<<14, /* Bit 14:	Disable insertion of CRC */
 	GM_TXCR_PAD_DIS		= 1<<13, /* Bit 13:	Disable padding of packets */
-	GM_TXCR_COL_THR_MSK	= 1<<10, /* Bit 12..10:	Collision Threshold */
+	GM_TXCR_COL_THR_MSK	= 7<<10, /* Bit 12..10:	Collision Threshold */
 };
 
 #define TX_COL_THR(x)		(((x)<<10) & GM_TXCR_COL_THR_MSK)
Signature · 7 lines
/***************************************************
 *Neil Horman
 *Software Engineer
 *gpg keyid: 1024D / 0x92A74FA1 - http://pgp.mit.edu
 ***************************************************/

--
#2 lore raw

PATCH 2/7 skge: fix truncated collision threshold mask

In reply to Stephen Hemminger

Patch to correct broken collision threshold mask in (same problem as sky2 driver). Should be three bits wide, but the mask only allows for 1 bit to be set.

drivers/net/skge.h +2 -2
@@ -1734,11 +1734,11 @@
 	GM_TXCR_FORCE_JAM	= 1<<15, /* Bit 15:	Force Jam / Flow-Control */
 	GM_TXCR_CRC_DIS		= 1<<14, /* Bit 14:	Disable insertion of CRC */
 	GM_TXCR_PAD_DIS		= 1<<13, /* Bit 13:	Disable padding of packets */
-	GM_TXCR_COL_THR_MSK	= 1<<10, /* Bit 12..10:	Collision Threshold */
+	GM_TXCR_COL_THR_MSK	= 7<<10, /* Bit 12..10:	Collision Threshold */
 };
 
 #define TX_COL_THR(x)		(((x)<<10) & GM_TXCR_COL_THR_MSK)
-#define TX_COL_DEF		0x04
+#define TX_COL_DEF		0x04	/* late collision after 64 byte */
 
 /*	GM_RX_CTRL			16 bit r/w	Receive Control Register */
 enum {

--

#3 lore raw

PATCH 3/7 sk98lin: fix truncated collision threshold mask

In reply to Stephen Hemminger

Patch to correct broken collision threshold mask in (same problem as sky2 driver). Should be three bits wide, but the mask only allows for 1 bit to be set.

drivers/net/sk98lin/h/xmac_ii.h +1 -1
@@ -1473,7 +1473,7 @@
 #define GM_TXCR_FORCE_JAM	(1<<15)	/* Bit 15:	Force Jam / Flow-Control */
 #define GM_TXCR_CRC_DIS		(1<<14)	/* Bit 14:	Disable insertion of CRC */
 #define GM_TXCR_PAD_DIS		(1<<13)	/* Bit 13:	Disable padding of packets */
-#define GM_TXCR_COL_THR_MSK	(1<<10)	/* Bit 12..10:	Collision Threshold */
+#define GM_TXCR_COL_THR_MSK	(7<<10)	/* Bit 12..10:	Collision Threshold */
 
 #define TX_COL_THR(x)		(SHIFT10(x) & GM_TXCR_COL_THR_MSK)
 

--

#5 lore raw

PATCH 5/7 sky2: NAPI suspend/resume of dual port cards

In reply to Stephen Hemminger

The changes to handle suspend/resume didn't handle the case where a dual port card has the first port down, but the second is running. In this driver, all NAPI polling is done on the primary port.

drivers/net/sky2.c +4 -7
@@ -3437,17 +3437,14 @@
 		return -EINVAL;
 
 	del_timer_sync(&hw->idle_timer);
+	netif_poll_disable(hw->dev[0]);
 
 	for (i = 0; i < hw->ports; i++) {
 		struct net_device *dev = hw->dev[i];
 
-		if (dev) {
-			if (!netif_running(dev))
-				continue;
-
+		if (netif_running(dev)) {
 			sky2_down(dev);
 			netif_device_detach(dev);
-			netif_poll_disable(dev);
 		}
 	}
 
@@ -3474,9 +3471,8 @@
 
 	for (i = 0; i < hw->ports; i++) {
 		struct net_device *dev = hw->dev[i];
-		if (dev && netif_running(dev)) {
+		if (netif_running(dev)) {
 			netif_device_attach(dev);
-			netif_poll_enable(dev);
 
 			err = sky2_up(dev);
 			if (err) {
@@ -3488,6 +3484,7 @@
 		}
 	}
 
+	netif_poll_enable(hw->dev[0]);
 	sky2_idle_start(hw);
 out:
 	return err;

--

#6 lore raw

PATCH 6/7 sky2: PHY power on delays

In reply to Stephen Hemminger

The documentation says we need to wait after turning on the PHY. Also, don't enable WOL by default.

drivers/net/sky2.c +2 -1
@@ -234,7 +234,6 @@
 		}
 
 		if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
-			sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON);
 			sky2_pci_write32(hw, PCI_DEV_REG3, 0);
 			reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
 			reg1 &= P_ASPM_CONTROL_MSK;
@@ -243,6 +242,7 @@
 		}
 
 		sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+		udelay(100);
 
 		break;
 
@@ -255,6 +255,7 @@
 		else
 			reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
 		sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+		udelay(100);
 
 		if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
 			sky2_write8(hw, B2_Y2_CLK_GATE, 0);

--

#7 lore raw

PATCH 7/7 sky2: optimize receive restart

In reply to Stephen Hemminger

When the driver handles multiple packets per NAPI poll, it is better to reload the receive ring, then tell the hardware. Otherwise, under packet storm with flow control, the driver/hardware will degrade down to one packet getting through per pause-exchange.

Likewise on transmit, don't wakeup until a little more than minimum ring space is available.

drivers/net/sky2.c +22 -5
@@ -65,6 +65,7 @@
 #define RX_MAX_PENDING		(RX_LE_SIZE/2 - 2)
 #define RX_DEF_PENDING		RX_MAX_PENDING
 #define RX_SKB_ALIGN		8
+#define RX_BUF_WRITE		16
 
 #define TX_RING_SIZE		512
 #define TX_DEF_PENDING		(TX_RING_SIZE - 1)
@@ -1390,7 +1391,7 @@
 	}
 
 	sky2->tx_cons = put;
-	if (tx_avail(sky2) > MAX_SKB_TX_LE)
+	if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
 		netif_wake_queue(dev);
 }
 
@@ -1889,9 +1890,6 @@
 	re->skb->ip_summed = CHECKSUM_NONE;
 	sky2_rx_add(sky2, re->mapaddr);
 
-	/* Tell receiver about new buffers. */
-	sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put);
-
 	return skb;
 
 oversize:
@@ -1938,7 +1936,9 @@
 /* Process status response ring */
 static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 {
+	struct sky2_port *sky2;
 	int work_done = 0;
+	unsigned buf_write[2] = { 0, 0 };
 	u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
 
 	rmb();
@@ -1946,7 +1946,6 @@
 	while (hw->st_idx != hwidx) {
 		struct sky2_status_le *le  = hw->st_le + hw->st_idx;
 		struct net_device *dev;
-		struct sky2_port *sky2;
 		struct sk_buff *skb;
 		u32 status;
 		u16 length;
@@ -1979,6 +1978,14 @@
 #endif
 				netif_receive_skb(skb);
 
+			/* Update receiver after 16 frames */
+			if (++buf_write[le->link] == RX_BUF_WRITE) {
+				sky2_put_idx(hw, rxqaddr[le->link],
+					     sky2->rx_put);
+				buf_write[le->link] = 0;
+			}
+
+			/* Stop after net poll weight */
 			if (++work_done >= to_do)
 				goto exit_loop;
 			break;
@@ -2017,6 +2024,16 @@
 	}
 
 exit_loop:
+	if (buf_write[0]) {
+		sky2 = netdev_priv(hw->dev[0]);
+		sky2_put_idx(hw, Q_R1, sky2->rx_put);
+	}
+
+	if (buf_write[1]) {
+		sky2 = netdev_priv(hw->dev[1]);
+		sky2_put_idx(hw, Q_R2, sky2->rx_put);
+	}
+
 	return work_done;
 }
 

--