Date: Fri, 18 Feb 2011 02:14:53 +0000 (UTC) From: Pyun YongHyeon <yongari@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r218787 - head/sys/dev/dc Message-ID: <201102180214.p1I2ErOJ038791@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: yongari Date: Fri Feb 18 02:14:53 2011 New Revision: 218787 URL: http://svn.freebsd.org/changeset/base/218787 Log: When driver have to use base softc due to lack of SROM on second port, copy SROM information from base softc as well and run SROM parser again. This change is necessary for some dual port controllers to make dc(4) correctly detect PHY media based on first port configuration table. While I'm here add a check for validity of the base softc before duplicating SROM contents from base softc. If driver failed to attach to the first port it can access invalid area. PR: kern/79262 Reviewed by: marius Modified: head/sys/dev/dc/if_dc.c Modified: head/sys/dev/dc/if_dc.c ============================================================================== --- head/sys/dev/dc/if_dc.c Fri Feb 18 01:56:25 2011 (r218786) +++ head/sys/dev/dc/if_dc.c Fri Feb 18 02:14:53 2011 (r218787) @@ -1815,6 +1815,7 @@ dc_attach(device_t dev) u_int32_t command; struct dc_softc *sc; struct ifnet *ifp; + struct dc_mediainfo *m; u_int32_t reg, revision; int error, i, mac_offset, phy, rid, tmp; u_int8_t *mac; @@ -2108,8 +2109,24 @@ dc_attach(device_t dev) if ((sc->dc_eaddr[0] == 0 && (sc->dc_eaddr[1] & ~0xffff) == 0) || (sc->dc_eaddr[0] == 0xffffffff && (sc->dc_eaddr[1] & 0xffff) == 0xffff)) { - if (dc_check_multiport(sc) == 0) + error = dc_check_multiport(sc); + if (error == 0) { bcopy(sc->dc_eaddr, eaddr, sizeof(eaddr)); + /* Extract media information. */ + if (DC_IS_INTEL(sc) && sc->dc_srom != NULL) { + while (sc->dc_mi != NULL) { + m = sc->dc_mi->dc_next; + free(sc->dc_mi, M_DEVBUF); + sc->dc_mi = m; + } + error = dc_parse_21143_srom(sc); + if (error != 0) + goto fail; + } + } else if (error == ENOMEM) + goto fail; + else + error = 0; } /* Allocate a busdma tag and DMA safe memory for TX/RX descriptors. */ @@ -3875,12 +3892,30 @@ dc_check_multiport(struct dc_softc *sc) continue; if (unit > device_get_unit(sc->dc_dev)) continue; + if (device_is_attached(child) == 0) + continue; dsc = device_get_softc(child); - device_printf(sc->dc_dev, "Using station address of %s as base", + device_printf(sc->dc_dev, + "Using station address of %s as base\n", device_get_nameunit(child)); bcopy(dsc->dc_eaddr, sc->dc_eaddr, ETHER_ADDR_LEN); eaddr = (uint8_t *)sc->dc_eaddr; eaddr[5]++; + /* Prepare SROM to parse again. */ + if (DC_IS_INTEL(sc) && dsc->dc_srom != NULL && + sc->dc_romwidth != 0) { + free(sc->dc_srom, M_DEVBUF); + sc->dc_romwidth = dsc->dc_romwidth; + sc->dc_srom = malloc(DC_ROM_SIZE(sc->dc_romwidth), + M_DEVBUF, M_NOWAIT); + if (sc->dc_srom == NULL) { + device_printf(sc->dc_dev, + "Could not allocate SROM buffer\n"); + return (ENOMEM); + } + bcopy(dsc->dc_srom, sc->dc_srom, + DC_ROM_SIZE(sc->dc_romwidth)); + } return (0); } return (ENOENT);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201102180214.p1I2ErOJ038791>