Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Fix a bug that the driver sometimes incorrectly ...



details:   https://anonhg.NetBSD.org/src/rev/1079cf3617de
branches:  trunk
changeset: 847525:1079cf3617de
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Dec 26 17:51:08 2019 +0000

description:
Fix a bug that the driver sometimes incorrectly attach gentbi(4) instead of
gphyter(4) on non-fiber device.

Tested with Sun Quad GigaSwift Ethernet UTP (QGE) (part no. 501-6522) on
amd64. On this environment, the problem frequently had occurred. I also
tested with other 4 cas(4) variants.

diffstat:

 sys/dev/pci/if_cas.c    |  173 +++++++++++++++++++++++++++++++++++++----------
 sys/dev/pci/if_casreg.h |   15 +++-
 sys/dev/pci/if_casvar.h |   13 +++-
 3 files changed, 160 insertions(+), 41 deletions(-)

diffs (truncated from 351 to 300 lines):

diff -r b12180cc4269 -r 1079cf3617de sys/dev/pci/if_cas.c
--- a/sys/dev/pci/if_cas.c      Thu Dec 26 15:32:37 2019 +0000
+++ b/sys/dev/pci/if_cas.c      Thu Dec 26 17:51:08 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_cas.c,v 1.36 2019/11/21 09:12:30 msaitoh Exp $      */
+/*     $NetBSD: if_cas.c,v 1.37 2019/12/26 17:51:08 msaitoh Exp $      */
 /*     $OpenBSD: if_cas.c,v 1.29 2009/11/29 16:19:38 kettenis Exp $    */
 
 /*
@@ -44,7 +44,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_cas.c,v 1.36 2019/11/21 09:12:30 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_cas.c,v 1.37 2019/12/26 17:51:08 msaitoh Exp $");
 
 #ifndef _MODULE
 #include "opt_inet.h"
@@ -114,7 +114,7 @@
     cas_match, cas_attach, cas_detach, NULL, NULL, NULL,
     DVF_DETACH_SHUTDOWN);
 
-int    cas_pci_enaddr(struct cas_softc *, struct pci_attach_args *, uint8_t *);
+int    cas_pci_readvpd(struct cas_softc *, struct pci_attach_args *, uint8_t *);
 
 void           cas_config(struct cas_softc *, const uint8_t *);
 void           cas_start(struct ifnet *);
@@ -163,18 +163,32 @@
 #define        DPRINTF(sc, x)  /* nothing */
 #endif
 
+static const struct cas_pci_dev {
+       uint16_t cpd_vendor;
+       uint16_t cpd_device;
+       int cpd_variant;
+} cas_pci_devlist[] = {
+       { PCI_VENDOR_SUN, PCI_PRODUCT_SUN_CASSINI, CAS_CAS },
+       { PCI_VENDOR_NS, PCI_PRODUCT_NS_SATURN, CAS_SATURN },
+       { 0, 0, 0 }
+};
+
+#define        CAS_LOCAL_MAC_ADDRESS   "local-mac-address"
+#define        CAS_PHY_INTERFACE       "phy-interface"
+#define        CAS_PHY_TYPE            "phy-type"
+#define        CAS_PHY_TYPE_PCS        "pcs"
+
 int
 cas_match(device_t parent, cfdata_t cf, void *aux)
 {
        struct pci_attach_args *pa = aux;
+       int i;
 
-       if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN &&
-           (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_CASSINI))
-               return 1;
-
-       if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NS &&
-           (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NS_SATURN))
-               return 1;
+       for (i = 0; cas_pci_devlist[i].cpd_vendor != 0; i++) {
+               if ((PCI_VENDOR(pa->pa_id) == cas_pci_devlist[i].cpd_vendor) &&
+                   (PCI_PRODUCT(pa->pa_id) == cas_pci_devlist[i].cpd_device))
+                       return 1;
+       }
 
        return 0;
 }
@@ -205,7 +219,7 @@
 
 #define CAS_LMA_MAXNUM 4
 int
-cas_pci_enaddr(struct cas_softc *sc, struct pci_attach_args *pa,
+cas_pci_readvpd(struct cas_softc *sc, struct pci_attach_args *pa,
     uint8_t *enaddr)
 {
        struct pci_vpd_largeres *res;
@@ -214,9 +228,10 @@
        bus_space_tag_t romt;
        bus_size_t romsize = 0;
        uint8_t enaddrs[CAS_LMA_MAXNUM][ETHER_ADDR_LEN];
+       bool pcs[4] = {false, false, false, false};
        uint8_t buf[32], *desc;
        pcireg_t address;
-       int dataoff, vpdoff, len, lma = 0;
+       int dataoff, vpdoff, len, lma = 0, phy = 0;
        int i, rv = -1;
 
        if (pci_mapreg_map(pa, PCI_MAPREG_ROM, PCI_MAPREG_TYPE_MEM, 0,
@@ -261,6 +276,20 @@
                goto next;
 
        case PCI_VPDRES_TYPE_VPD:
+#ifdef CAS_DEBUG
+       printf("\n");
+       for (i = 0; i < len; i++) {
+               uint8_t byte;
+               if (i % 16 == 0)
+                       printf("%04x :", i);
+               byte = bus_space_read_1(romt, romh, vpdoff + i);
+               printf(" %02x", byte);
+               if (i % 16 == 15)
+                       printf("\n");
+       }
+       printf("\n");
+#endif
+
                while (len > 0) {
                        bus_space_read_region_1(romt, romh, vpdoff,
                             buf, sizeof(buf));
@@ -284,26 +313,57 @@
                                continue;
                        desc += 3;
 
-                       /*
-                        * ...that's a byte array with the proper
-                        * length for a MAC address...
-                        */
-                       if (desc[0] != 'B' || desc[1] != ETHER_ADDR_LEN)
+                       if (desc[0] == 'B' || desc[1] == ETHER_ADDR_LEN) {
+                               /*
+                                * ...that's a byte array with the proper
+                                * length for a MAC address...
+                                */
+                               desc += 2;
+
+                               /*
+                                * ...named "local-mac-address".
+                                */
+                               if (strcmp(desc, CAS_LOCAL_MAC_ADDRESS) != 0)
+                                       continue;
+                               desc += sizeof(CAS_LOCAL_MAC_ADDRESS);
+
+                               if (lma == CAS_LMA_MAXNUM)
+                                       continue;
+
+                               memcpy(enaddrs[lma], desc, ETHER_ADDR_LEN);
+                               lma++;
+                               rv = 0;
                                continue;
-                       desc += 2;
+                       } else if (desc[0] == 'S') {
+                               size_t k;
 
-                       /*
-                        * ...named "local-mac-address".
-                        */
-                       if (strcmp(desc, "local-mac-address") != 0)
+                               /* String */
+                               desc += 2;
+#ifdef CAS_DEBUG
+                               /* ...named "pcs". */
+                               printf("STR: \"%s\"\n", desc);
+                               if (strcmp(desc, CAS_PHY_TYPE_PCS) != 0)
+                                       continue;
+                               desc += sizeof(CAS_PHY_TYPE_PCS);
+                               printf("STR: \"%s\"\n", desc);
+#endif
+                               /* ...named "phy-interface" or "phy-type". */
+                               if (strcmp(desc, CAS_PHY_INTERFACE) == 0)
+                                       k = sizeof(CAS_PHY_INTERFACE);
+                               else if (strcmp(desc, CAS_PHY_TYPE) == 0)
+                                       k = sizeof(CAS_PHY_TYPE);
+                               else
+                                       continue;
+
+                               desc += k;
+#ifdef CAS_DEBUG
+                               printf("STR: \"%s\"\n", desc);
+#endif
+                               if (strcmp(desc, CAS_PHY_TYPE_PCS) == 0)
+                                       pcs[phy] = true;
+                               phy++;
                                continue;
-                       desc += strlen("local-mac-address") + 1;
-
-                       memcpy(enaddrs[lma], desc, ETHER_ADDR_LEN);
-                       lma++;
-                       rv = 0;
-                       if (lma == CAS_LMA_MAXNUM)
-                               break;
+                       }
                }
                break;
 
@@ -311,7 +371,6 @@
                goto fail;
        }
 
-       i = 0;
        /*
         * Multi port card has bridge chip. The device number is fixed:
         * e.g.
@@ -320,10 +379,15 @@
         * p2: 006:02:0
         * p3: 006:03:0
         */
-       if ((lma > 1) && (pa->pa_device < CAS_LMA_MAXNUM)
-           && (pa->pa_device < lma))
-               i = pa->pa_device;
-       memcpy(enaddr, enaddrs[i], ETHER_ADDR_LEN);
+       if (enaddr != 0) {
+               i = 0;
+               if ((lma > 1) && (pa->pa_device < CAS_LMA_MAXNUM)
+                   && (pa->pa_device < lma))
+                       i = pa->pa_device;
+               memcpy(enaddr, enaddrs[i], ETHER_ADDR_LEN);
+       }
+       if (pcs[pa->pa_device])
+               sc->sc_flags |= CAS_SERDES;
  fail:
        if (romsize != 0)
                bus_space_unmap(romt, romh, romsize);
@@ -340,6 +404,7 @@
 {
        struct pci_attach_args *pa = aux;
        struct cas_softc *sc = device_private(self);
+       int i;
        prop_data_t data;
        uint8_t enaddr[ETHER_ADDR_LEN];
 
@@ -348,6 +413,20 @@
        sc->sc_rev = PCI_REVISION(pa->pa_class);
        sc->sc_dmatag = pa->pa_dmat;
 
+       sc->sc_variant = CAS_UNKNOWN;
+       for (i = 0; cas_pci_devlist[i].cpd_vendor != 0; i++) {
+               if ((PCI_VENDOR(pa->pa_id) == cas_pci_devlist[i].cpd_vendor) &&
+                   (PCI_PRODUCT(pa->pa_id) == cas_pci_devlist[i].cpd_device)) {
+                       sc->sc_variant = cas_pci_devlist[i].cpd_variant;
+                       break;
+               }
+       }
+       aprint_debug_dev(sc->sc_dev, "variant = %d\n", sc->sc_variant);
+       if (sc->sc_variant == CAS_UNKNOWN) {
+               aprint_error_dev(sc->sc_dev, "unknown adaptor\n");
+               return;
+       }
+
 #define PCI_CAS_BASEADDR       0x10
        if (pci_mapreg_map(pa, PCI_CAS_BASEADDR, PCI_MAPREG_TYPE_MEM, 0,
            &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_size) != 0) {
@@ -359,7 +438,7 @@
        if ((data = prop_dictionary_get(device_properties(sc->sc_dev),
            "mac-address")) != NULL)
                memcpy(enaddr, prop_data_data_nocopy(data), ETHER_ADDR_LEN);
-       else if (cas_pci_enaddr(sc, pa, enaddr) != 0) {
+       if (cas_pci_readvpd(sc, pa, (data == NULL) ? enaddr : 0) != 0) {
                aprint_error_dev(sc->sc_dev, "no Ethernet address found\n");
                memset(enaddr, 0, sizeof(enaddr));
        }
@@ -409,6 +488,7 @@
        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
        struct mii_data *mii = &sc->sc_mii;
        struct mii_softc *child;
+       uint32_t reg;
        int i, error;
 
        /* Make sure the chip is stopped. */
@@ -555,10 +635,25 @@
 
        cas_mifinit(sc);
 
-       if (sc->sc_mif_config & CAS_MIF_CONFIG_MDI1) {
-               sc->sc_mif_config |= CAS_MIF_CONFIG_PHY_SEL;
-               bus_space_write_4(sc->sc_memt, sc->sc_memh,
-                   CAS_MIF_CONFIG, sc->sc_mif_config);
+       if (sc->sc_mif_config & (CAS_MIF_CONFIG_MDI1 | CAS_MIF_CONFIG_MDI0)) {
+               if (sc->sc_mif_config & CAS_MIF_CONFIG_MDI1) {
+                       sc->sc_mif_config |= CAS_MIF_CONFIG_PHY_SEL;
+                       bus_space_write_4(sc->sc_memt, sc->sc_memh,
+                           CAS_MIF_CONFIG, sc->sc_mif_config);
+               }
+               /* Enable/unfreeze the GMII pins of Saturn. */
+               if (sc->sc_variant == CAS_SATURN) {
+                       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh,
+                           CAS_SATURN_PCFG) & ~CAS_SATURN_PCFG_FSI;
+                       if ((sc->sc_mif_config & CAS_MIF_CONFIG_MDI0) != 0)
+                               reg |= CAS_SATURN_PCFG_FSI;
+                       bus_space_write_4(sc->sc_memt, sc->sc_memh,
+                           CAS_SATURN_PCFG, reg);
+                       /* Read to flush */
+                       bus_space_read_4(sc->sc_memt, sc->sc_memh,
+                           CAS_SATURN_PCFG);
+                       DELAY(10000);
+               }
        }
 
        mii_attach(sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY,
diff -r b12180cc4269 -r 1079cf3617de sys/dev/pci/if_casreg.h
--- a/sys/dev/pci/if_casreg.h   Thu Dec 26 15:32:37 2019 +0000
+++ b/sys/dev/pci/if_casreg.h   Thu Dec 26 17:51:08 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_casreg.h,v 1.1 2010/01/07 09:19:55 jdc Exp $ */
+/*     $NetBSD: if_casreg.h,v 1.2 2019/12/26 17:51:08 msaitoh Exp $ */
 /*     $OpenBSD: if_casreg.h,v 1.10 2008/05/31 22:49:03 kettenis Exp $ */
 
 /*
@@ -55,6 +55,7 @@
 #define        CAS_BIF_CONFIG          0x0008  /* BIF config reg */
 #define        CAS_BIF_DIAG            0x000c



Home | Main Index | Thread Index | Old Index