svn commit: r207157 - user/jmallett/octeon/sys/mips/cavium/octe

Juli Mallett jmallett at FreeBSD.org
Sat Apr 24 19:51:08 UTC 2010


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 <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/init.h>
-#include <linux/etherdevice.h>
-#include <linux/ip.h>
-#include <linux/string.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#include <linux/seq_file.h>
-#include <linux/proc_fs.h>
-#include <net/dst.h>
-#ifdef CONFIG_XFRM
-#include <linux/xfrm.h>
-#include <net/xfrm.h>
-#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 <net/ethernet.h>
 #include <net/if.h>
+#include <net/if_media.h>
 #include <net/if_types.h>
 
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
 #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);


More information about the svn-src-user mailing list