From owner-svn-src-user@FreeBSD.ORG Sat Apr 24 19:51:08 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 43596106564A; Sat, 24 Apr 2010 19:51:08 +0000 (UTC) (envelope-from jmallett@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 314D68FC1A; Sat, 24 Apr 2010 19:51:08 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o3OJp8dj029712; Sat, 24 Apr 2010 19:51:08 GMT (envelope-from jmallett@svn.freebsd.org) Received: (from jmallett@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o3OJp81u029710; Sat, 24 Apr 2010 19:51:08 GMT (envelope-from jmallett@svn.freebsd.org) Message-Id: <201004241951.o3OJp81u029710@svn.freebsd.org> From: Juli Mallett Date: Sat, 24 Apr 2010 19:51:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r207157 - user/jmallett/octeon/sys/mips/cavium/octe X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 24 Apr 2010 19:51:08 -0000 Author: jmallett Date: Sat Apr 24 19:51:07 2010 New Revision: 207157 URL: http://svn.freebsd.org/changeset/base/207157 Log: o) Move more interface initialization into octe.c. o) Add MII support. o) Fix how octe_init() and octe_stop() are called within octe.c. This is enough to get link status reported correctly (XXX only on interfaces that are marked UP, though; an interface that's never marked UP is forced into 10M mode and is inoperable in the bootloader without a cold boot) and to receive packets, although the content of those packets is just garbage. Modified: user/jmallett/octeon/sys/mips/cavium/octe/cavium-ethernet.h user/jmallett/octeon/sys/mips/cavium/octe/ethernet-common.c user/jmallett/octeon/sys/mips/cavium/octe/ethernet-mdio.c user/jmallett/octeon/sys/mips/cavium/octe/ethernet-mdio.h user/jmallett/octeon/sys/mips/cavium/octe/octe.c Modified: user/jmallett/octeon/sys/mips/cavium/octe/cavium-ethernet.h ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/octe/cavium-ethernet.h Sat Apr 24 18:13:12 2010 (r207156) +++ user/jmallett/octeon/sys/mips/cavium/octe/cavium-ethernet.h Sat Apr 24 19:51:07 2010 (r207157) @@ -85,6 +85,9 @@ typedef cvm_oct_callback_result_t (*cvm_ * driver state stored in ifp->if_softc. */ typedef struct { + /* XXX FreeBSD device softcs must start with an ifnet pointer. */ + struct ifnet *ifp; + int port; /* PKO hardware output port */ int queue; /* PKO hardware queue for the port */ int fau; /* Hardware fetch and add to count outstanding tx buffers */ @@ -103,7 +106,7 @@ typedef struct { * FreeBSD additions. */ device_t dev; - struct ifnet *ifp; + device_t miibus; int (*open)(struct ifnet *ifp); int (*stop)(struct ifnet *ifp); @@ -111,6 +114,9 @@ typedef struct { int (*init)(struct ifnet *ifp); void (*uninit)(struct ifnet *ifp); + uint8_t mac[6]; + int phy_id; + struct ifmedia media; int if_flags; } cvm_oct_private_t; Modified: user/jmallett/octeon/sys/mips/cavium/octe/ethernet-common.c ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/octe/ethernet-common.c Sat Apr 24 18:13:12 2010 (r207156) +++ user/jmallett/octeon/sys/mips/cavium/octe/ethernet-common.c Sat Apr 24 19:51:07 2010 (r207157) @@ -151,6 +151,8 @@ static int cvm_oct_common_set_mac_addres int interface = INTERFACE(priv->port); int index = INDEX(priv->port); + memcpy(priv->mac, addr, 6); + if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) { int i; uint8_t *ptr = addr; @@ -242,8 +244,6 @@ int cvm_oct_common_init(struct ifnet *if octeon_bootinfo->mac_addr_base[5] + count}; cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc; - device_attach(priv->dev); - /* Force the interface to use the POW send if always_use_pow was specified or it is in the pow send list */ if ((pow_send_group != -1) && (always_use_pow || strstr(pow_send_list, if_name(ifp)))) @@ -265,9 +265,7 @@ int cvm_oct_common_init(struct ifnet *if ifp->get_stats = cvm_oct_common_get_stats; ifp->set_mac_address = cvm_oct_common_set_mac_address; ifp->set_multicast_list = cvm_oct_common_set_multicast_list; - ifp->do_ioctl = cvm_oct_ioctl; ifp->features |= NETIF_F_LLTX; /* We do our own locking, Linux doesn't need to */ - SET_ETHTOOL_OPS(ifp, &cvm_oct_ethtool_ops); #ifdef CONFIG_NET_POLL_CONTROLLER ifp->poll_controller = cvm_oct_poll_controller; #endif @@ -284,7 +282,7 @@ int cvm_oct_common_init(struct ifnet *if memset(ifp->get_stats(ifp), 0, sizeof(struct ifnet_stats)); #endif - ether_ifattach(ifp, mac); + device_attach(priv->dev); return 0; } Modified: user/jmallett/octeon/sys/mips/cavium/octe/ethernet-mdio.c ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/octe/ethernet-mdio.c Sat Apr 24 18:13:12 2010 (r207156) +++ user/jmallett/octeon/sys/mips/cavium/octe/ethernet-mdio.c Sat Apr 24 19:51:07 2010 (r207157) @@ -49,7 +49,6 @@ MTX_SYSINIT(cvm_oct_mdio, &mdio_mtx, "MD #define MDIO_LOCK() mtx_lock(&mdio_mtx) #define MDIO_UNLOCK() mtx_unlock(&mdio_mtx) -#if 0 /** * Perform an MII read. Called by the generic MII routines * @@ -58,11 +57,12 @@ MTX_SYSINIT(cvm_oct_mdio, &mdio_mtx, "MD * @param location Register location to read * @return Result from the read or zero on failure */ -static int cvm_oct_mdio_read(struct ifnet *ifp, int phy_id, int location) +int cvm_oct_mdio_read(struct ifnet *ifp, int phy_id, int location) { cvmx_smi_cmd_t smi_cmd; cvmx_smi_rd_dat_t smi_rd; + MDIO_LOCK(); smi_cmd.u64 = 0; smi_cmd.s.phy_op = 1; smi_cmd.s.phy_adr = phy_id; @@ -70,22 +70,21 @@ static int cvm_oct_mdio_read(struct ifne cvmx_write_csr(CVMX_SMI_CMD, smi_cmd.u64); do { +#if 0 if (!in_interrupt()) yield(); +#endif smi_rd.u64 = cvmx_read_csr(CVMX_SMI_RD_DAT); } while (smi_rd.s.pending); + MDIO_UNLOCK(); + if (smi_rd.s.val) return smi_rd.s.dat; else return 0; } -static int cvm_oct_mdio_dummy_read(struct ifnet *ifp, int phy_id, int location) -{ - return 0xffff; -} - /** * Perform an MII write. Called by the generic MII routines @@ -95,11 +94,12 @@ static int cvm_oct_mdio_dummy_read(struc * @param location Register location to write * @param val Value to write */ -static void cvm_oct_mdio_write(struct ifnet *ifp, int phy_id, int location, int val) +void cvm_oct_mdio_write(struct ifnet *ifp, int phy_id, int location, int val) { cvmx_smi_cmd_t smi_cmd; cvmx_smi_wr_dat_t smi_wr; + MDIO_LOCK(); smi_wr.u64 = 0; smi_wr.s.dat = val; cvmx_write_csr(CVMX_SMI_WR_DAT, smi_wr.u64); @@ -111,116 +111,15 @@ static void cvm_oct_mdio_write(struct if cvmx_write_csr(CVMX_SMI_CMD, smi_cmd.u64); do { +#if 0 if (!in_interrupt()) yield(); +#endif smi_wr.u64 = cvmx_read_csr(CVMX_SMI_WR_DAT); } while (smi_wr.s.pending); -} - -static void cvm_oct_mdio_dummy_write(struct ifnet *ifp, int phy_id, int location, int val) -{ -} - - -static void cvm_oct_get_drvinfo(struct ifnet *ifp, struct ethtool_drvinfo *info) -{ - strcpy(info->driver, "cavium-ethernet"); - strcpy(info->version, OCTEON_SDK_VERSION_STRING); - strcpy(info->bus_info, "Builtin"); -} - - -static int cvm_oct_get_settings(struct ifnet *ifp, struct ethtool_cmd *cmd) -{ - cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc; - int ret; - - MDIO_LOCK(); - ret = mii_ethtool_gset(&priv->mii_info, cmd); - MDIO_UNLOCK(); - - return ret; -} - - -static int cvm_oct_set_settings(struct ifnet *ifp, struct ethtool_cmd *cmd) -{ - cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc; - int ret; - - MDIO_LOCK(); - ret = mii_ethtool_sset(&priv->mii_info, cmd); - MDIO_UNLOCK(); - - return ret; -} - - -static int cvm_oct_nway_reset(struct ifnet *ifp) -{ - cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc; - int ret; - - MDIO_LOCK(); - ret = mii_nway_restart(&priv->mii_info); MDIO_UNLOCK(); - - return ret; } - -static u32 cvm_oct_get_link(struct ifnet *ifp) -{ - cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc; - u32 ret; - - MDIO_LOCK(); - ret = mii_link_ok(&priv->mii_info); - MDIO_UNLOCK(); - - return ret; -} - - -struct ethtool_ops cvm_oct_ethtool_ops = { - .get_drvinfo = cvm_oct_get_drvinfo, - .get_settings = cvm_oct_get_settings, - .set_settings = cvm_oct_set_settings, - .nway_reset = cvm_oct_nway_reset, - .get_link = cvm_oct_get_link, - .get_sg = ethtool_op_get_sg, - .get_tx_csum = ethtool_op_get_tx_csum, -}; -#endif - - -/** - * IOCTL support for PHY control - * - * @param dev Device to change - * @param rq the request - * @param cmd the command - * @return Zero on success - */ -int cvm_oct_ioctl(struct ifnet *ifp, struct ifreq *rq, int cmd) -{ -#if 0 - cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc; - struct mii_ioctl_data *data = if_mii(rq); - unsigned int duplex_chg; - int ret; - - MDIO_LOCK(); - ret = generic_mii_ioctl(&priv->mii_info, data, cmd, &duplex_chg); - MDIO_UNLOCK(); - - return ret; -#else - panic("%s: not yet implemented.", __func__); -#endif -} - - /** * Setup the MDIO device structures * @@ -230,23 +129,10 @@ int cvm_oct_ioctl(struct ifnet *ifp, str */ int cvm_oct_mdio_setup_device(struct ifnet *ifp) { - /* - * XXX/juli - * Once we have a device_t for this interface, attach the MII bus to it. - */ -#if 0 cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc; - int phy_id = cvmx_helper_board_get_mii_address(priv->port); - if (phy_id != -1) { - priv->mii_info.dev = dev; - priv->mii_info.phy_id = phy_id; - priv->mii_info.phy_id_mask = 0xff; - priv->mii_info.supports_gmii = 1; - priv->mii_info.reg_num_mask = 0x1f; - priv->mii_info.mdio_read = cvm_oct_mdio_read; - priv->mii_info.mdio_write = cvm_oct_mdio_write; - } -#endif + + priv->phy_id = cvmx_helper_board_get_mii_address(priv->port); + return 0; } Modified: user/jmallett/octeon/sys/mips/cavium/octe/ethernet-mdio.h ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/octe/ethernet-mdio.h Sat Apr 24 18:13:12 2010 (r207156) +++ user/jmallett/octeon/sys/mips/cavium/octe/ethernet-mdio.h Sat Apr 24 19:51:07 2010 (r207157) @@ -26,26 +26,8 @@ TO THE MAXIMUM EXTENT PERMITTED BY LAW, AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. *************************************************************************/ -#if 0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_XFRM -#include -#include -#endif /* CONFIG_XFRM */ -#endif -extern struct ethtool_ops cvm_oct_ethtool_ops; -int cvm_oct_ioctl(struct ifnet *ifp, struct ifreq *rq, int cmd); +int cvm_oct_mdio_read(struct ifnet *ifp, int phy_id, int location); +void cvm_oct_mdio_write(struct ifnet *ifp, int phy_id, int location, int val); int cvm_oct_mdio_setup_device(struct ifnet *ifp); Modified: user/jmallett/octeon/sys/mips/cavium/octe/octe.c ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/octe/octe.c Sat Apr 24 18:13:12 2010 (r207156) +++ user/jmallett/octeon/sys/mips/cavium/octe/octe.c Sat Apr 24 19:51:07 2010 (r207157) @@ -50,21 +50,34 @@ #include #include +#include #include +#include +#include + #include "wrapper-cvmx-includes.h" #include "cavium-ethernet.h" #include "ethernet-common.h" +#include "ethernet-mdio.h" + +#include "miibus_if.h" static int octe_probe(device_t); static int octe_attach(device_t); static int octe_detach(device_t); static int octe_shutdown(device_t); +static int octe_miibus_readreg(device_t, int, int); +static int octe_miibus_writereg(device_t, int, int, int); + static void octe_init(void *); static void octe_stop(void *); +static int octe_mii_medchange(struct ifnet *); +static void octe_mii_medstat(struct ifnet *, struct ifmediareq *); + static int octe_medchange(struct ifnet *); static void octe_medstat(struct ifnet *, struct ifmediareq *); @@ -77,6 +90,10 @@ static device_method_t octe_methods[] = DEVMETHOD(device_detach, octe_detach), DEVMETHOD(device_shutdown, octe_shutdown), + /* MII interface */ + DEVMETHOD(miibus_readreg, octe_miibus_readreg), + DEVMETHOD(miibus_writereg, octe_miibus_writereg), + { 0, 0 } }; @@ -89,6 +106,7 @@ static driver_t octe_driver = { static devclass_t octe_devclass; DRIVER_MODULE(octe, octebus, octe_driver, octe_devclass, 0, 0); +DRIVER_MODULE(miibus, octe, miibus_driver, miibus_devclass, 0, 0); static driver_t pow_driver = { "pow", @@ -111,6 +129,7 @@ octe_attach(device_t dev) { struct ifnet *ifp; cvm_oct_private_t *priv; + int error; priv = device_get_softc(dev); ifp = priv->ifp; @@ -118,8 +137,18 @@ octe_attach(device_t dev) if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifmedia_init(&priv->media, 0, octe_medchange, octe_medstat); - ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL); - ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO); + if (priv->phy_id == -1) { + ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO); + } else { + error = mii_phy_probe(dev, &priv->miibus, octe_mii_medchange, + octe_mii_medstat); + if (error != 0) { + device_printf(dev, "could not find PHY!\n"); + /* XXX Cleanup. */ + return (error); + } + } ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = octe_init; @@ -127,6 +156,8 @@ octe_attach(device_t dev) priv->if_flags = ifp->if_flags; + ether_ifattach(ifp, priv->mac); + return (0); } @@ -142,6 +173,28 @@ octe_shutdown(device_t dev) return (octe_detach(dev)); } +static int +octe_miibus_readreg(device_t dev, int phy, int reg) +{ + cvm_oct_private_t *priv; + + priv = device_get_softc(dev); + + return (cvm_oct_mdio_read(priv->ifp, phy, reg)); +} + +static int +octe_miibus_writereg(device_t dev, int phy, int reg, int val) +{ + cvm_oct_private_t *priv; + + priv = device_get_softc(dev); + + cvm_oct_mdio_write(priv->ifp, phy, reg, val); + + return (0); +} + static void octe_init(void *arg) { @@ -151,8 +204,13 @@ octe_init(void *arg) priv = arg; ifp = priv->ifp; + octe_stop(priv); + if (priv->open != NULL) priv->open(ifp); + + if (priv->miibus != NULL) + mii_mediachg(device_get_softc(priv->miibus)); } static void @@ -169,6 +227,40 @@ octe_stop(void *arg) } static int +octe_mii_medchange(struct ifnet *ifp) +{ + cvm_oct_private_t *priv; + struct mii_data *mii; + + priv = ifp->if_softc; + mii = device_get_softc(priv->miibus); + + if (mii->mii_instance) { + struct mii_softc *miisc; + + LIST_FOREACH(miisc, &mii->mii_phys, mii_list) + mii_phy_reset(miisc); + } + mii_mediachg(mii); + + return (0); +} + +static void +octe_mii_medstat(struct ifnet *ifp, struct ifmediareq *ifm) +{ + cvm_oct_private_t *priv; + struct mii_data *mii; + + priv = ifp->if_softc; + mii = device_get_softc(priv->miibus); + + mii_pollstat(mii); + ifm->ifm_active = mii->mii_media_active; + ifm->ifm_status = mii->mii_media_status; +} + +static int octe_medchange(struct ifnet *ifp) { return (ENOTSUP); @@ -221,6 +313,7 @@ static int octe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { cvm_oct_private_t *priv; + struct mii_data *mii; struct ifreq *ifr; int error; @@ -231,10 +324,10 @@ octe_ioctl(struct ifnet *ifp, u_long cmd case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) != 0) { if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - octe_init(ifp); + octe_init(priv); } else { if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) - octe_stop(ifp); + octe_stop(priv); } priv->if_flags = ifp->if_flags; return (0); @@ -247,6 +340,13 @@ octe_ioctl(struct ifnet *ifp, u_long cmd case SIOCSIFMEDIA: case SIOCGIFMEDIA: + if (priv->miibus != NULL) { + mii = device_get_softc(priv->miibus); + error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); + if (error != 0) + return (error); + return (0); + } error = ifmedia_ioctl(ifp, ifr, &priv->media, cmd); if (error != 0) return (error);