From 57fa7d31012dd13f1d89d67a9cfebe06715196dc Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Wed, 22 Feb 2012 01:30:25 +0000 Subject: [PATCH] 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 --- sys/mips/cavium/files.octeon1 | 8 ++--- sys/mips/cavium/if_octm.c | 8 +++-- sys/mips/cavium/octe/ethernet-common.c | 44 +++++++++++++++++++++----- sys/mips/cavium/octe/ethernet-common.h | 2 +- sys/mips/cavium/octe/ethernet-rgmii.c | 4 ++- sys/mips/cavium/octe/ethernet-sgmii.c | 5 ++- sys/mips/cavium/octe/ethernet-spi.c | 3 +- sys/mips/cavium/octe/ethernet-xaui.c | 5 ++- sys/mips/cavium/octe/ethernet.c | 44 +++++++------------------- 9 files changed, 71 insertions(+), 52 deletions(-) diff --git a/sys/mips/cavium/files.octeon1 b/sys/mips/cavium/files.octeon1 index 1e4fdb050ed2..777689346bd9 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 847ad3c0fd88..9364f1dd1252 100644 --- a/sys/mips/cavium/if_octm.c +++ b/sys/mips/cavium/if_octm.c @@ -63,6 +63,7 @@ #include #include #include +#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 839b6f82ecee..3a39b55b139b 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. @@ -89,6 +91,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 * @@ -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 cf23f5bd6d75..cb5fc81b1349 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 4273a6fca3f8..e9921cd92838 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 834df4563056..3bb5cee14743 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 100f642ef195..b88afd9ceaeb 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 212cd2ed0ecf..1e3fc8cb290f 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 a3a5ae79d3fb..65bff67ae88b 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);