msk(4) issues

Pyun YongHyeon pyunyh at gmail.com
Sat Sep 20 01:36:36 UTC 2008


On Wed, Sep 17, 2008 at 10:16:29AM +0200, Ian Freislich wrote:
 > Hi
 > 
 > I'm having an issue with the msk hardware in my laptop.  It stops
 > transmitting or recieving sometimes, always triggered by periods
 > of intense network load.
 > 
 > Sep 16 18:39:31 apple kernel: msk0: watchdog timeout (missed Tx interrupts) -- recovering
 > Sep 16 18:40:35 apple kernel: msk0: watchdog timeout (missed Tx interrupts) -- recovering
 > Sep 16 18:41:41 apple kernel: msk0: watchdog timeout (missed Tx interrupts) -- recovering
 > 
 > But it never recovers.
 > 
 > mskc0 at pci0:2:0:0:       class=0x020000 card=0x532111ab chip=0x436211ab rev=0x22 hdr=0x00
 >     vendor     = 'Marvell Semiconductor (Was: Galileo Technology Ltd)'
 >     device     = '88E8053 Marvell Yukon 88E8053 PCI-E Gigabit Ethernet Controller'
 >     class      = network
 >     subclass   = ethernet
 > 
 > Ian
 > 

Would you try attached patch?

-- 
Regards,
Pyun YongHyeon
-------------- next part --------------
Index: if_msk.c
===================================================================
--- if_msk.c	(revision 183165)
+++ if_msk.c	(working copy)
@@ -244,6 +244,9 @@
 static int msk_handle_events(struct msk_softc *);
 static void msk_handle_hwerr(struct msk_if_softc *, uint32_t);
 static void msk_intr_hwerr(struct msk_softc *);
+#ifndef __NO_STRICT_ALIGNMENT
+static __inline void msk_fixup_rx(struct mbuf *);
+#endif
 static void msk_rxeof(struct msk_if_softc *, uint32_t, int);
 static void msk_jumbo_rxeof(struct msk_if_softc *, uint32_t, int);
 static void msk_txeof(struct msk_if_softc *, int);
@@ -783,7 +786,12 @@
 		return (ENOBUFS);
 
 	m->m_len = m->m_pkthdr.len = MCLBYTES;
-	m_adj(m, ETHER_ALIGN);
+	if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0)
+		m_adj(m, ETHER_ALIGN);
+#ifndef __NO_STRICT_ALIGNMENT
+	else
+		m_adj(m, MSK_RX_BUF_ALIGN);
+#endif
 
 	if (bus_dmamap_load_mbuf_sg(sc_if->msk_cdata.msk_rx_tag,
 	    sc_if->msk_cdata.msk_rx_sparemap, m, segs, &nsegs,
@@ -840,7 +848,12 @@
 		return (ENOBUFS);
 	}
 	m->m_pkthdr.len = m->m_len = MSK_JLEN;
-	m_adj(m, ETHER_ALIGN);
+	if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0)
+		m_adj(m, ETHER_ALIGN);
+#ifndef __NO_STRICT_ALIGNMENT
+	else
+		m_adj(m, MSK_RX_BUF_ALIGN);
+#endif
 
 	if (bus_dmamap_load_mbuf_sg(sc_if->msk_cdata.msk_jumbo_rx_tag,
 	    sc_if->msk_cdata.msk_jumbo_rx_sparemap, m, segs, &nsegs,
@@ -1041,14 +1054,16 @@
 {
 	int next;
 	int i;
-	uint8_t val;
 
 	/* Get adapter SRAM size. */
-	val = CSR_READ_1(sc, B2_E_0);
-	sc->msk_ramsize = (val == 0) ? 128 : val * 4;
+	sc->msk_ramsize = CSR_READ_1(sc, B2_E_0) * 4;
 	if (bootverbose)
 		device_printf(sc->msk_dev,
 		    "RAM buffer size : %dKB\n", sc->msk_ramsize);
+	if (sc->msk_ramsize == 0)
+		return (0);
+
+	sc->msk_pflags |= MSK_FLAG_RAMBUF;
 	/*
 	 * Give receiver 2/3 of memory and round down to the multiple
 	 * of 1024. Tx/Rx RAM buffer size of Yukon II shoud be multiple
@@ -1412,6 +1427,7 @@
 	sc_if->msk_if_dev = dev;
 	sc_if->msk_port = port;
 	sc_if->msk_softc = sc;
+	sc_if->msk_flags = sc->msk_pflags;
 	sc->msk_if[port] = sc_if;
 	/* Setup Tx/Rx queue register offsets. */
 	if (port == MSK_PORT_A) {
@@ -1976,6 +1992,7 @@
 	struct msk_rxdesc *jrxd;
 	struct msk_jpool_entry *entry;
 	uint8_t *ptr;
+	bus_size_t rxalign;
 	int error, i;
 
 	mtx_init(&sc_if->msk_jlist_mtx, "msk_jlist_mtx", NULL, MTX_DEF);
@@ -2107,9 +2124,16 @@
 		goto fail;
 	}
 
+	rxalign = 1;
+	/*
+	 * Workaround hardware hang which seems to happen when Rx buffer
+	 * is not aligned on multiple of FIFO word(8 bytes).
+	 */
+	if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) != 0)
+		rxalign = MSK_RX_BUF_ALIGN;
 	/* Create tag for Rx buffers. */
 	error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */
-		    1, 0,			/* alignment, boundary */
+		    rxalign, 0,			/* alignment, boundary */
 		    BUS_SPACE_MAXADDR,		/* lowaddr */
 		    BUS_SPACE_MAXADDR,		/* highaddr */
 		    NULL, NULL,			/* filter, filterarg */
@@ -2918,6 +2942,23 @@
 	return (0);
 }
 
+#ifndef __NO_STRICT_ALIGNMENT
+static __inline void
+msk_fixup_rx(struct mbuf *m)
+{
+        int i;
+        uint16_t *src, *dst;
+
+	src = mtod(m, uint16_t *);
+	dst = src - 3;
+
+	for (i = 0; i < (m->m_len / sizeof(uint16_t) + 1); i++)
+		*dst++ = *src++;
+
+	m->m_data -= (MSK_RX_BUF_ALIGN - ETHER_ALIGN);
+}
+#endif
+
 static void
 msk_rxeof(struct msk_if_softc *sc_if, uint32_t status, int len)
 {
@@ -2955,6 +2996,10 @@
 		}
 		m->m_pkthdr.rcvif = ifp;
 		m->m_pkthdr.len = m->m_len = len;
+#ifndef __NO_STRICT_ALIGNMENT
+		if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) != 0)
+			msk_fixup_rx(m);
+#endif
 		ifp->if_ipackets++;
 		/* Check for VLAN tagged packets. */
 		if ((status & GMR_FS_VLAN) != 0 &&
@@ -3008,6 +3053,10 @@
 		}
 		m->m_pkthdr.rcvif = ifp;
 		m->m_pkthdr.len = m->m_len = len;
+#ifndef __NO_STRICT_ALIGNMENT
+		if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) != 0)
+			msk_fixup_rx(m);
+#endif
 		ifp->if_ipackets++;
 		/* Check for VLAN tagged packets. */
 		if ((status & GMR_FS_VLAN) != 0 &&
@@ -3677,7 +3726,7 @@
 	/* Configure hardware VLAN tag insertion/stripping. */
 	msk_setvlan(sc_if, ifp);
 
-	if (sc->msk_hw_id == CHIP_ID_YUKON_EC_U) {
+	if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0) {
 		/* Set Rx Pause threshould. */
 		CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, RX_GMF_LP_THR),
 		    MSK_ECU_LLPP);
@@ -3790,6 +3839,8 @@
 	int ltpp, utpp;
 
 	sc = sc_if->msk_softc;
+	if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0)
+		return;
 
 	/* Setup Rx Queue. */
 	CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_rxq, RB_CTRL), RB_RST_CLR);
Index: if_mskreg.h
===================================================================
--- if_mskreg.h	(revision 183165)
+++ if_mskreg.h	(working copy)
@@ -2158,6 +2158,7 @@
 
 #define MSK_TX_RING_CNT		256
 #define MSK_RX_RING_CNT		256
+#define	MSK_RX_BUF_ALIGN	8
 #define MSK_JUMBO_RX_RING_CNT	MSK_RX_RING_CNT
 #define	MSK_STAT_RING_CNT	((1 + 3) * (MSK_TX_RING_CNT + MSK_RX_RING_CNT))
 #define MSK_MAXTXSEGS		32
@@ -2307,6 +2308,7 @@
 	uint32_t		msk_coppertype;
 	uint32_t		msk_intrmask;
 	uint32_t		msk_intrhwemask;
+	uint32_t		msk_pflags;
 	int			msk_suspended;
 	int			msk_clock;
 	int			msk_msi;
@@ -2348,6 +2350,8 @@
 	int			msk_phytype;
 	int			msk_phyaddr;
 	int			msk_link;
+	uint32_t		msk_flags;
+#define	MSK_FLAG_RAMBUF		0x0010
 	struct callout		msk_tick_ch;
 	int			msk_watchdog_timer;
 	uint32_t		msk_txq;	/* Tx. Async Queue offset */


More information about the freebsd-current mailing list