Marvell Yukon 88E8062 - media selection problem

Pyun YongHyeon pyunyh at gmail.com
Mon Jul 7 10:26:45 UTC 2008


On Sun, Jul 06, 2008 at 10:45:28PM +0200, Krzysztof J??druczyk wrote:
 > Pyun YongHyeon pisze:
 > >
 > >Would you try the patch at the following URL?
 > >http://people.freebsd.org/~yongari/msk/msk.88E8040.patch5
 > >
 > >The diff generated against HEAD and it could be cleanly applied to
 > >7-stable. 7-stable also has a couple of important bug fixes.
 > >So it would be better to use 7-stable.
 > 
 > After applying both patches (the one from previous email and the one 
 > from http link) both interfaces work. I'm impressed :)
 > 

Thanks a lot for testing!

Since the patch had lots of code not related with 88E8062 dual
port controller, would you try attached patch again? I think
the attached patch is minimal one that makes 88E8062 work.

The patch also try to enable MSI for dual port controllers. At the
time of writing support for MSI I had no testers to experiment MSI
so MSI on dual port controllers were ignored. Please see if msk(4)
take advantage of MSI. irq256 or higher number would be showed in
"vmstat -i" output if MSI is active.

 > I understand the media selection fix I am using at the moment is just a 
 > hack - but will the other patch get in the -stable anytime soon?
 > 

I'll MFC attached patch if it work well on your hardware.
-- 
Regards,
Pyun YongHyeon
-------------- next part --------------
--- sys/dev/mii/e1000phy.c.orig	2007-11-16 19:39:18.000000000 +0900
+++ sys/dev/mii/e1000phy.c	2008-07-07 16:58:31.000000000 +0900
@@ -59,6 +59,9 @@
 #include "miidevs.h"
 
 #include <dev/mii/e1000phyreg.h>
+/* XXX */
+#include <machine/bus.h>
+#include <dev/msk/if_mskreg.h>
 
 #include "miibus_if.h"
 
@@ -128,6 +131,8 @@
 	struct mii_softc *sc;
 	struct mii_attach_args *ma;
 	struct mii_data *mii;
+	struct ifnet *ifp;
+	struct msk_mii_data *mmd;
 	int fast_ether;
 
 	esc = device_get_softc(dev);
@@ -148,10 +153,20 @@
 	esc->mii_model = MII_MODEL(ma->mii_id2);
 	switch (esc->mii_model) {
 	case MII_MODEL_MARVELL_E1011:
-	case MII_MODEL_MARVELL_E1112:
 		if (PHY_READ(sc, E1000_ESSR) & E1000_ESSR_FIBER_LINK)
 			sc->mii_flags |= MIIF_HAVEFIBER;
 		break;
+	case MII_MODEL_MARVELL_E1112:
+		/* XXX */
+		ifp = sc->mii_pdata->mii_ifp;
+		if (strcmp(ifp->if_dname, "msk") == 0) {
+			mmd = device_get_ivars(
+			    device_get_parent(device_get_parent(dev)));
+			if (mmd != NULL &&
+			    (mmd->mii_flags & MIIF_HAVEFIBER) != 0);
+				sc->mii_flags |= MIIF_HAVEFIBER;
+		}
+		break;
 	case MII_MODEL_MARVELL_E3082:
 		/* 88E3082 10/100 Fast Ethernet PHY. */
 		sc->mii_anegticks = MII_ANEGTICKS;
@@ -209,7 +224,7 @@
 e1000phy_reset(struct mii_softc *sc)
 {
 	struct e1000phy_softc *esc;
-	uint16_t reg;
+	uint16_t page, reg;
 
 	esc = (struct e1000phy_softc *)sc;
 	reg = PHY_READ(sc, E1000_SCR);
@@ -217,13 +232,14 @@
 		reg &= ~E1000_SCR_AUTO_X_MODE;
 		PHY_WRITE(sc, E1000_SCR, reg);
 		if (esc->mii_model == MII_MODEL_MARVELL_E1112) {
+			page = PHY_READ(sc, E1000_EADR);
 			/* Select 1000BASE-X only mode. */
 			PHY_WRITE(sc, E1000_EADR, 2);
 			reg = PHY_READ(sc, E1000_SCR);
 			reg &= ~E1000_SCR_MODE_MASK;
 			reg |= E1000_SCR_MODE_1000BX;
 			PHY_WRITE(sc, E1000_SCR, reg);
-			PHY_WRITE(sc, E1000_EADR, 1);
+			PHY_WRITE(sc, E1000_EADR, page);
 		}
 	} else {
 		switch (esc->mii_model) {
@@ -472,8 +488,8 @@
 		else
 			mii->mii_media_active |= IFM_10_T;
 	} else {
-		if (ssr & E1000_SSR_1000MBS)
-			mii->mii_media_active |= IFM_1000_SX;
+		/* XXX Should have a way to tell IFM_1000_SX/IFM_1000_LX. */
+		mii->mii_media_active |= IFM_1000_SX;
 	}
 
 	if (ssr & E1000_SSR_DUPLEX)
--- sys/dev/msk/if_msk.c.orig	2008-03-27 13:43:51.000000000 +0900
+++ sys/dev/msk/if_msk.c	2008-07-07 17:32:48.000000000 +0900
@@ -1398,6 +1398,7 @@
 	struct msk_softc *sc;
 	struct msk_if_softc *sc_if;
 	struct ifnet *ifp;
+	struct msk_mii_data *mmd;
 	int i, port, error;
 	uint8_t eaddr[6];
 
@@ -1407,7 +1408,8 @@
 	error = 0;
 	sc_if = device_get_softc(dev);
 	sc = device_get_softc(device_get_parent(dev));
-	port = *(int *)device_get_ivars(dev);
+	mmd = device_get_ivars(dev);
+	port = mmd->port;
 
 	sc_if->msk_if_dev = dev;
 	sc_if->msk_port = port;
@@ -1537,7 +1539,8 @@
 mskc_attach(device_t dev)
 {
 	struct msk_softc *sc;
-	int error, msic, msir, *port, reg;
+	struct msk_mii_data *mmd;
+	int error, i, msic, msir, reg;
 
 	sc = device_get_softc(dev);
 	sc->msk_dev = dev;
@@ -1646,15 +1649,7 @@
 	msic = pci_msi_count(dev);
 	if (bootverbose)
 		device_printf(dev, "MSI count : %d\n", msic);
-	/*
-	 * The Yukon II reports it can handle two messages, one for each
-	 * possible port.  We go ahead and allocate two messages and only
-	 * setup a handler for both if we have a dual port card.
-	 *
-	 * XXX: I haven't untangled the interrupt handler to handle dual
-	 * port cards with separate MSI messages, so for now I disable MSI
-	 * on dual port cards.
-	 */
+
 	if (legacy_intr != 0)
 		msi_disable = 1;
 	if (msi_disable == 0) {
@@ -1662,10 +1657,9 @@
 		case 2:
 		case 1: /* 88E8058 reports 1 MSI message */
 			msir = msic;
-			if (sc->msk_num_port == 1 &&
-			    pci_alloc_msi(dev, &msir) == 0) {
+			if (pci_alloc_msi(dev, &msir) == 0) {
 				if (msic == msir) {
-					sc->msk_msi = 1;
+					sc->msk_msi = msic;
 					sc->msk_irq_spec = msic == 2 ?
 					    msk_irq_spec_msi2 :
 					    msk_irq_spec_msi;
@@ -1706,15 +1700,17 @@
 		error = ENXIO;
 		goto fail;
 	}
-	port = malloc(sizeof(int), M_DEVBUF, M_WAITOK);
-	if (port == NULL) {
+	mmd = malloc(sizeof(struct msk_mii_data), M_DEVBUF, M_WAITOK | M_ZERO);
+	if (mmd == NULL) {
 		device_printf(dev, "failed to allocate memory for "
 		    "ivars of PORT_A\n");
 		error = ENXIO;
 		goto fail;
 	}
-	*port = MSK_PORT_A;
-	device_set_ivars(sc->msk_devs[MSK_PORT_A], port);
+	mmd->port = MSK_PORT_A;
+	if (sc->msk_coppertype == 0)
+		mmd->mii_flags |= MIIF_HAVEFIBER;
+	device_set_ivars(sc->msk_devs[MSK_PORT_A], mmd);
 
 	if (sc->msk_num_port > 1) {
 		sc->msk_devs[MSK_PORT_B] = device_add_child(dev, "msk", -1);
@@ -1723,15 +1719,18 @@
 			error = ENXIO;
 			goto fail;
 		}
-		port = malloc(sizeof(int), M_DEVBUF, M_WAITOK);
-		if (port == NULL) {
+		mmd = malloc(sizeof(struct msk_mii_data), M_DEVBUF,
+		    M_WAITOK | M_ZERO);
+		if (mmd == NULL) {
 			device_printf(dev, "failed to allocate memory for "
 			    "ivars of PORT_B\n");
 			error = ENXIO;
 			goto fail;
 		}
-		*port = MSK_PORT_B;
-		device_set_ivars(sc->msk_devs[MSK_PORT_B], port);
+		mmd->port = MSK_PORT_A;
+		if (sc->msk_coppertype == 0)
+			mmd->mii_flags |= MIIF_HAVEFIBER;
+		device_set_ivars(sc->msk_devs[MSK_PORT_B], mmd);
 	}
 
 	error = bus_generic_attach(dev);
@@ -1751,8 +1750,13 @@
 		    taskqueue_thread_enqueue, &sc->msk_tq);
 		taskqueue_start_threads(&sc->msk_tq, 1, PI_NET, "%s taskq",
 		    device_get_nameunit(sc->msk_dev));
-		error = bus_setup_intr(dev, sc->msk_irq[0], INTR_TYPE_NET |
-		    INTR_MPSAFE, msk_intr, NULL, sc, &sc->msk_intrhand[0]);
+		for (i = 0; i < sc->msk_msi; i++) {
+			error = bus_setup_intr(dev, sc->msk_irq[i],
+			    INTR_TYPE_NET | INTR_MPSAFE, msk_intr, NULL, sc,
+			    &sc->msk_intrhand[i]);
+			if (error != 0)
+				break;
+		}
 	}
 
 	if (error != 0) {
@@ -1829,6 +1833,7 @@
 mskc_detach(device_t dev)
 {
 	struct msk_softc *sc;
+	int i;
 
 	sc = device_get_softc(dev);
 	KASSERT(mtx_initialized(&sc->msk_mtx), ("msk mutex not initialized"));
@@ -1866,14 +1871,20 @@
 		taskqueue_free(sc->msk_tq);
 		sc->msk_tq = NULL;
 	}
-	if (sc->msk_intrhand[0]) {
+
+	if (sc->msk_msi == 0) {
 		bus_teardown_intr(dev, sc->msk_irq[0], sc->msk_intrhand[0]);
 		sc->msk_intrhand[0] = NULL;
+	} else {
+		for (i = 0; i < sc->msk_msi; i++) {
+			if (sc->msk_intrhand[i] != NULL) {
+				bus_teardown_intr(dev, sc->msk_irq[i],
+				    sc->msk_intrhand[i]);
+				sc->msk_intrhand[i] = NULL;
+			}
+		}
 	}
-	if (sc->msk_intrhand[1]) {
-		bus_teardown_intr(dev, sc->msk_irq[0], sc->msk_intrhand[0]);
-		sc->msk_intrhand[1] = NULL;
-	}
+
 	bus_release_resources(dev, sc->msk_irq_spec, sc->msk_irq);
 	if (sc->msk_msi)
 		pci_release_msi(dev);
@@ -3585,6 +3596,14 @@
 		ifp->if_capenable &= ~(IFCAP_TSO4 | IFCAP_TXCSUM);
 	}
 
+	/* GPHY Control reset. */
+	CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GPHY_CTRL), GPC_RST_SET);
+	CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GPHY_CTRL), GPC_RST_CLR);
+	/* GMAC Control reset. */
+	CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_RST_SET);
+	CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_RST_CLR);
+	CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_F_LOOPB_OFF);
+
 	/*
 	 * Initialize GMAC first.
 	 * Without this initialization, Rx MAC did not work as expected
--- sys/dev/msk/if_mskreg.h.orig	2008-02-29 12:38:12.000000000 +0900
+++ sys/dev/msk/if_mskreg.h	2008-07-07 16:18:39.000000000 +0900
@@ -2287,6 +2287,11 @@
 #define	MSK_TX_TIMEOUT		5
 #define	MSK_PUT_WM	10
 
+struct msk_mii_data {
+	int			port;
+	int			mii_flags;
+};
+
 /* Forward decl. */
 struct msk_if_softc;
 


More information about the freebsd-stable mailing list