summaryrefslogtreecommitdiffstats
path: root/sys/mips/cavium
diff options
context:
space:
mode:
authorgonzo <gonzo@FreeBSD.org>2012-02-22 01:30:25 +0000
committergonzo <gonzo@FreeBSD.org>2012-02-22 01:30:25 +0000
commit1ec5baaef2e3798db4f06efbac2ca27d4d5506a5 (patch)
treebed1cfb774053fc4c6fbf83537567d690af8669c /sys/mips/cavium
parentcf70964fbe0955aecb81afc9fa6cfe2b5a5b39f8 (diff)
downloadFreeBSD-src-1ec5baaef2e3798db4f06efbac2ca27d4d5506a5.zip
FreeBSD-src-1ec5baaef2e3798db4f06efbac2ca27d4d5506a5.tar.gz
Refctor address assignment for Octeon's ethernet ports:
- Centralize address assignment - Make sure managment ports get first MAC address in pool - Properly propagate fail if address allocation failed Submitted by: Andrew Duane <aduane@juniper.net>
Diffstat (limited to 'sys/mips/cavium')
-rw-r--r--sys/mips/cavium/files.octeon18
-rw-r--r--sys/mips/cavium/if_octm.c8
-rw-r--r--sys/mips/cavium/octe/ethernet-common.c44
-rw-r--r--sys/mips/cavium/octe/ethernet-common.h2
-rw-r--r--sys/mips/cavium/octe/ethernet-rgmii.c4
-rw-r--r--sys/mips/cavium/octe/ethernet-sgmii.c5
-rw-r--r--sys/mips/cavium/octe/ethernet-spi.c3
-rw-r--r--sys/mips/cavium/octe/ethernet-xaui.c5
-rw-r--r--sys/mips/cavium/octe/ethernet.c44
9 files changed, 71 insertions, 52 deletions
diff --git a/sys/mips/cavium/files.octeon1 b/sys/mips/cavium/files.octeon1
index 1e4fdb0..7776893 100644
--- a/sys/mips/cavium/files.octeon1
+++ b/sys/mips/cavium/files.octeon1
@@ -24,6 +24,10 @@ mips/cavium/cryptocteon/cryptocteon.c optional cryptocteon
mips/mips/octeon_cop2_swtch.S standard
mips/mips/octeon_cop2.c standard
+# octm must be first, so management ports get the first MAC addresses
+mips/cavium/if_octm.c optional octm
+contrib/octeon-sdk/cvmx-mgmt-port.c optional octm
+
mips/cavium/octe/ethernet.c optional octe
mips/cavium/octe/ethernet-mv88e61xx.c optional octe octeon_vendor_lanner
mips/cavium/octe/ethernet-common.c optional octe
@@ -39,10 +43,6 @@ mips/cavium/octe/mv88e61xxphy.c optional octe mv88e61xxphy
mips/cavium/octe/octe.c optional octe
mips/cavium/octe/octebus.c optional octe
-mips/cavium/if_octm.c optional octm
-
-contrib/octeon-sdk/cvmx-mgmt-port.c optional octm
-
mips/cavium/octopci.c optional pci
mips/cavium/octopci_bus_space.c optional pci
diff --git a/sys/mips/cavium/if_octm.c b/sys/mips/cavium/if_octm.c
index 847ad3c..9364f1d 100644
--- a/sys/mips/cavium/if_octm.c
+++ b/sys/mips/cavium/if_octm.c
@@ -63,6 +63,7 @@
#include <contrib/octeon-sdk/cvmx.h>
#include <contrib/octeon-sdk/cvmx-interrupt.h>
#include <contrib/octeon-sdk/cvmx-mgmt-port.h>
+#include "octe/ethernet-common.h"
struct octm_softc {
struct ifnet *sc_ifp;
@@ -176,9 +177,10 @@ octm_attach(device_t dev)
/*
* Set MAC address for this management port.
*/
- mac = 0;
- memcpy((u_int8_t *)&mac + 2, cvmx_sysinfo_get()->mac_addr_base, 6);
- mac += sc->sc_port;
+ if (cvm_assign_mac_address(&mac, NULL) != 0) {
+ device_printf(dev, "unable to allocate MAC address.\n");
+ return (ENXIO);
+ }
cvmx_mgmt_port_set_mac(sc->sc_port, mac);
/* No watermark for input ring. */
diff --git a/sys/mips/cavium/octe/ethernet-common.c b/sys/mips/cavium/octe/ethernet-common.c
index 839b6f8..3a39b55 100644
--- a/sys/mips/cavium/octe/ethernet-common.c
+++ b/sys/mips/cavium/octe/ethernet-common.c
@@ -46,6 +46,8 @@ __FBSDID("$FreeBSD$");
extern int octeon_is_simulation(void);
+static uint64_t mac_addr = 0;
+static uint32_t mac_offset = 0;
/**
* Set the multicast list. Currently unimplemented.
@@ -90,6 +92,37 @@ void cvm_oct_common_set_multicast_list(struct ifnet *ifp)
/**
+ * Assign a MAC addres from the pool of available MAC addresses
+ * Can return as either a 64-bit value and/or 6 octets.
+ *
+ * @param macp Filled in with the assigned address if non-NULL
+ * @param octets Filled in with the assigned address if non-NULL
+ * @return Zero on success
+ */
+int cvm_assign_mac_address(uint64_t *macp, uint8_t *octets)
+{
+ /* Initialize from global MAC address base; fail if not set */
+ if (mac_addr == 0) {
+ memcpy((uint8_t *)&mac_addr + 2, cvmx_sysinfo_get()->mac_addr_base, 6);
+ if (mac_addr == 0)
+ return ENXIO;
+ }
+
+ if (mac_offset >= cvmx_sysinfo_get()->mac_addr_count)
+ return ENXIO; /* Out of addresses to assign */
+
+ if (macp)
+ *macp = mac_addr;
+ if (octets)
+ memcpy(octets, (u_int8_t *)&mac_addr + 2, 6);
+
+ mac_addr++;
+ mac_offset++;
+
+ return 0;
+}
+
+/**
* Set the hardware MAC address for a device
*
* @param dev Device to change the MAC address for
@@ -268,16 +301,11 @@ void cvm_oct_common_poll(struct ifnet *ifp)
*/
int cvm_oct_common_init(struct ifnet *ifp)
{
- char mac[6] = {
- cvmx_sysinfo_get()->mac_addr_base[0],
- cvmx_sysinfo_get()->mac_addr_base[1],
- cvmx_sysinfo_get()->mac_addr_base[2],
- cvmx_sysinfo_get()->mac_addr_base[3],
- cvmx_sysinfo_get()->mac_addr_base[4],
- cvmx_sysinfo_get()->mac_addr_base[5] };
+ uint8_t mac[6];
cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
- mac[5] += cvm_oct_mac_addr_offset++;
+ if (cvm_assign_mac_address(NULL, mac) != 0)
+ return ENXIO;
ifp->if_mtu = ETHERMTU;
diff --git a/sys/mips/cavium/octe/ethernet-common.h b/sys/mips/cavium/octe/ethernet-common.h
index cf23f5b..cb5fc81 100644
--- a/sys/mips/cavium/octe/ethernet-common.h
+++ b/sys/mips/cavium/octe/ethernet-common.h
@@ -37,6 +37,7 @@ void cvm_oct_common_uninit(struct ifnet *ifp);
int cvm_oct_common_change_mtu(struct ifnet *ifp, int new_mtu);
void cvm_oct_common_set_multicast_list(struct ifnet *ifp);
void cvm_oct_common_set_mac_address(struct ifnet *ifp, const void *);
+int cvm_assign_mac_address(uint64_t *, uint8_t *);
int cvm_oct_init_module(device_t);
void cvm_oct_cleanup_module(device_t);
@@ -52,4 +53,3 @@ int cvm_oct_spi_init(struct ifnet *ifp);
void cvm_oct_spi_uninit(struct ifnet *ifp);
int cvm_oct_xaui_init(struct ifnet *ifp);
-extern unsigned int cvm_oct_mac_addr_offset;
diff --git a/sys/mips/cavium/octe/ethernet-rgmii.c b/sys/mips/cavium/octe/ethernet-rgmii.c
index 4273a6f..e9921cd 100644
--- a/sys/mips/cavium/octe/ethernet-rgmii.c
+++ b/sys/mips/cavium/octe/ethernet-rgmii.c
@@ -215,7 +215,9 @@ int cvm_oct_rgmii_init(struct ifnet *ifp)
int error;
int rid;
- cvm_oct_common_init(ifp);
+ if (cvm_oct_common_init(ifp) != 0)
+ return ENXIO;
+
priv->open = cvm_oct_common_open;
priv->stop = cvm_oct_common_stop;
priv->stop(ifp);
diff --git a/sys/mips/cavium/octe/ethernet-sgmii.c b/sys/mips/cavium/octe/ethernet-sgmii.c
index 834df45..3bb5cee 100644
--- a/sys/mips/cavium/octe/ethernet-sgmii.c
+++ b/sys/mips/cavium/octe/ethernet-sgmii.c
@@ -49,7 +49,10 @@ extern int octeon_is_simulation(void);
int cvm_oct_sgmii_init(struct ifnet *ifp)
{
cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
- cvm_oct_common_init(ifp);
+
+ if (cvm_oct_common_init(ifp) != 0)
+ return ENXIO;
+
priv->open = cvm_oct_common_open;
priv->stop = cvm_oct_common_stop;
priv->stop(ifp);
diff --git a/sys/mips/cavium/octe/ethernet-spi.c b/sys/mips/cavium/octe/ethernet-spi.c
index 100f642..b88afd9 100644
--- a/sys/mips/cavium/octe/ethernet-spi.c
+++ b/sys/mips/cavium/octe/ethernet-spi.c
@@ -289,7 +289,8 @@ int cvm_oct_spi_init(struct ifnet *ifp)
cvm_oct_spi_enable_error_reporting(INTERFACE(priv->port));
priv->poll = cvm_oct_spi_poll;
}
- cvm_oct_common_init(ifp);
+ if (cvm_oct_common_init(ifp) != 0)
+ return ENXIO;
return 0;
}
diff --git a/sys/mips/cavium/octe/ethernet-xaui.c b/sys/mips/cavium/octe/ethernet-xaui.c
index 212cd2e..1e3fc8c 100644
--- a/sys/mips/cavium/octe/ethernet-xaui.c
+++ b/sys/mips/cavium/octe/ethernet-xaui.c
@@ -49,7 +49,10 @@ extern int octeon_is_simulation(void);
int cvm_oct_xaui_init(struct ifnet *ifp)
{
cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
- cvm_oct_common_init(ifp);
+
+ if (cvm_oct_common_init(ifp) != 0)
+ return ENXIO;
+
priv->open = cvm_oct_common_open;
priv->stop = cvm_oct_common_stop;
priv->stop(ifp);
diff --git a/sys/mips/cavium/octe/ethernet.c b/sys/mips/cavium/octe/ethernet.c
index a3a5ae7..65bff67 100644
--- a/sys/mips/cavium/octe/ethernet.c
+++ b/sys/mips/cavium/octe/ethernet.c
@@ -97,15 +97,6 @@ static struct taskqueue *cvm_oct_link_taskq;
*/
static int cvm_oct_num_output_buffers;
-/*
- * The offset from mac_addr_base that should be used for the next port
- * that is configured. By convention, if any mgmt ports exist on the
- * chip, they get the first mac addresses. The ports controlled by
- * this driver are numbered sequencially following any mgmt addresses
- * that may exist.
- */
-unsigned int cvm_oct_mac_addr_offset;
-
/**
* Function to update link status.
*/
@@ -321,20 +312,6 @@ int cvm_oct_init_module(device_t bus)
printf("cavium-ethernet: %s\n", OCTEON_SDK_VERSION_STRING);
- /*
- * MAC addresses for this driver start after the management
- * ports.
- *
- * XXX Would be nice if __cvmx_mgmt_port_num_ports() were
- * not static to cvmx-mgmt-port.c.
- */
- if (OCTEON_IS_MODEL(OCTEON_CN56XX))
- cvm_oct_mac_addr_offset = 1;
- else if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
- cvm_oct_mac_addr_offset = 2;
- else
- cvm_oct_mac_addr_offset = 0;
-
cvm_oct_rx_initialize();
cvm_oct_configure_common_hw(bus);
@@ -375,15 +352,17 @@ int cvm_oct_init_module(device_t bus)
int num_ports = cvmx_helper_ports_on_interface(interface);
int port;
- for (port = cvmx_helper_get_ipd_port(interface, 0); port < cvmx_helper_get_ipd_port(interface, num_ports); port++) {
+ for (port = cvmx_helper_get_ipd_port(interface, 0);
+ port < cvmx_helper_get_ipd_port(interface, num_ports);
+ ifnum++, port++) {
cvm_oct_private_t *priv;
struct ifnet *ifp;
- dev = BUS_ADD_CHILD(bus, 0, "octe", ifnum++);
+ dev = BUS_ADD_CHILD(bus, 0, "octe", ifnum);
if (dev != NULL)
ifp = if_alloc(IFT_ETHER);
if (dev == NULL || ifp == NULL) {
- printf("\t\tFailed to allocate ethernet device for port %d\n", port);
+ printf("Failed to allocate ethernet device for interface %d port %d\n", interface, port);
continue;
}
@@ -454,12 +433,13 @@ int cvm_oct_init_module(device_t bus)
ifp->if_softc = priv;
if (!priv->init) {
- panic("%s: unsupported device type, need to free ifp.", __func__);
- } else
- if (priv->init(ifp) < 0) {
- printf("\t\tFailed to register ethernet device for interface %d, port %d\n",
- interface, priv->port);
- panic("%s: init failed, need to free ifp.", __func__);
+ printf("octe%d: unsupported device type interface %d, port %d\n",
+ ifnum, interface, priv->port);
+ if_free(ifp);
+ } else if (priv->init(ifp) != 0) {
+ printf("octe%d: failed to register device for interface %d, port %d\n",
+ ifnum, interface, priv->port);
+ if_free(ifp);
} else {
cvm_oct_device[priv->port] = ifp;
fau -= cvmx_pko_get_num_queues(priv->port) * sizeof(uint32_t);
OpenPOWER on IntegriCloud