Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/axgbe/if_axgbe.c
/*- | /*- | ||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD | |||||
* | |||||
* Copyright (c) 2016,2017 SoftIron Inc. | * Copyright (c) 2016,2017 SoftIron Inc. | ||||
* All rights reserved. | * Copyright (c) 2020 Advanced Micro Devices, Inc. | ||||
* | * | ||||
* This software was developed by Andrew Turner under | * This software was developed by Andrew Turner under | ||||
* the sponsorship of SoftIron Inc. | * the sponsorship of SoftIron Inc. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | static struct resource_spec mac_spec[] = { | ||||
{ SYS_RES_IRQ, 1, RF_ACTIVE }, | { SYS_RES_IRQ, 1, RF_ACTIVE }, | ||||
{ SYS_RES_IRQ, 2, RF_ACTIVE | RF_OPTIONAL }, | { SYS_RES_IRQ, 2, RF_ACTIVE | RF_OPTIONAL }, | ||||
{ SYS_RES_IRQ, 3, RF_ACTIVE | RF_OPTIONAL }, | { SYS_RES_IRQ, 3, RF_ACTIVE | RF_OPTIONAL }, | ||||
{ SYS_RES_IRQ, 4, RF_ACTIVE | RF_OPTIONAL }, | { SYS_RES_IRQ, 4, RF_ACTIVE | RF_OPTIONAL }, | ||||
{ SYS_RES_IRQ, 5, RF_ACTIVE | RF_OPTIONAL }, | { SYS_RES_IRQ, 5, RF_ACTIVE | RF_OPTIONAL }, | ||||
{ -1, 0 } | { -1, 0 } | ||||
}; | }; | ||||
static struct xgbe_version_data xgbe_v1 = { | |||||
.init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v1, | |||||
.xpcs_access = XGBE_XPCS_ACCESS_V1, | |||||
.tx_max_fifo_size = 81920, | |||||
.rx_max_fifo_size = 81920, | |||||
.tx_tstamp_workaround = 1, | |||||
}; | |||||
MALLOC_DEFINE(M_AXGBE, "axgbe", "axgbe data"); | MALLOC_DEFINE(M_AXGBE, "axgbe", "axgbe data"); | ||||
static void | static void | ||||
axgbe_init(void *p) | axgbe_init(void *p) | ||||
{ | { | ||||
struct axgbe_softc *sc; | struct axgbe_softc *sc; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
sc = p; | sc = p; | ||||
ifp = sc->prv.netdev; | ifp = sc->prv.netdev; | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (ifp->if_drv_flags & IFF_DRV_RUNNING) | ||||
return; | return; | ||||
ifp->if_drv_flags |= IFF_DRV_RUNNING; | ifp->if_drv_flags |= IFF_DRV_RUNNING; | ||||
} | } | ||||
static int | static int | ||||
axgbe_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data) | axgbe_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data) | ||||
{ | { | ||||
struct axgbe_softc *sc = ifp->if_softc; | struct axgbe_softc *sc = ifp->if_softc; | ||||
struct ifreq *ifr = (struct ifreq *)data; | struct ifreq *ifr = (struct ifreq *)data; | ||||
int error; | int error = 0; | ||||
switch(command) { | switch(command) { | ||||
case SIOCSIFMTU: | case SIOCSIFMTU: | ||||
if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU_JUMBO) | if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU_JUMBO) | ||||
error = EINVAL; | error = EINVAL; | ||||
else | /* TODO - change it to iflib way */ | ||||
error = xgbe_change_mtu(ifp, ifr->ifr_mtu); | |||||
break; | break; | ||||
emaste: What's the story here? | |||||
Done Inline ActionsThe newer version of the driver is based on PCI-E. Also, the new version is written compatible to the Iflib framework. We made changes related to that in the existing code moving few function between files. We haven't made the Iflib compatible changes to the old version since we don't have the target hardware to verify the same. So, If the old version of the driver is still in use by someone, we would be happy to work with to make necessary changes and verify the same. Please let me know if more details needed. rajesh1.kumar_amd.com: The newer version of the driver is based on PCI-E. Also, the new version is written compatible… | |||||
case SIOCSIFFLAGS: | case SIOCSIFFLAGS: | ||||
error = 0; | error = 0; | ||||
break; | break; | ||||
case SIOCSIFMEDIA: | case SIOCSIFMEDIA: | ||||
case SIOCGIFMEDIA: | case SIOCGIFMEDIA: | ||||
error = ifmedia_ioctl(ifp, ifr, &sc->media, command); | error = ifmedia_ioctl(ifp, ifr, &sc->media, command); | ||||
break; | break; | ||||
default: | default: | ||||
▲ Show 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | axgbe_attach(device_t dev) | ||||
phandle_t node, phy_node; | phandle_t node, phy_node; | ||||
struct resource *mac_res[11]; | struct resource *mac_res[11]; | ||||
struct resource *phy_res[4]; | struct resource *phy_res[4]; | ||||
ssize_t len; | ssize_t len; | ||||
int error, i, j; | int error, i, j; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->prv.vdata = &xgbe_v1; | |||||
node = ofw_bus_get_node(dev); | node = ofw_bus_get_node(dev); | ||||
if (OF_getencprop(node, "phy-handle", &phy_handle, | if (OF_getencprop(node, "phy-handle", &phy_handle, | ||||
sizeof(phy_handle)) <= 0) { | sizeof(phy_handle)) <= 0) { | ||||
phy_node = node; | phy_node = node; | ||||
if (bus_alloc_resources(dev, mac_spec, mac_res)) { | if (bus_alloc_resources(dev, mac_spec, mac_res)) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"could not allocate phy resources\n"); | "could not allocate phy resources\n"); | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | if (ifp == NULL) { | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
sc->prv.dev = dev; | sc->prv.dev = dev; | ||||
sc->prv.dmat = bus_get_dma_tag(dev); | sc->prv.dmat = bus_get_dma_tag(dev); | ||||
sc->prv.phy.advertising = ADVERTISED_10000baseKR_Full | | sc->prv.phy.advertising = ADVERTISED_10000baseKR_Full | | ||||
ADVERTISED_1000baseKX_Full; | ADVERTISED_1000baseKX_Full; | ||||
/* | /* | ||||
* Read the needed properties from the phy node. | * Read the needed properties from the phy node. | ||||
*/ | */ | ||||
/* This is documented as optional, but Linux requires it */ | /* This is documented as optional, but Linux requires it */ | ||||
if (OF_getencprop(phy_node, XGBE_SPEEDSET_PROPERTY, &sc->prv.speed_set, | if (OF_getencprop(phy_node, XGBE_SPEEDSET_PROPERTY, &sc->prv.speed_set, | ||||
sizeof(sc->prv.speed_set)) <= 0) { | sizeof(sc->prv.speed_set)) <= 0) { | ||||
device_printf(dev, "%s property is missing\n", | device_printf(dev, "%s property is missing\n", | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | if (error > 0) { | ||||
sc->prv.serdes_dfe_tap_ena[0] = XGBE_SPEED_1000_DFE_TAP_ENABLE; | sc->prv.serdes_dfe_tap_ena[0] = XGBE_SPEED_1000_DFE_TAP_ENABLE; | ||||
sc->prv.serdes_dfe_tap_ena[1] = XGBE_SPEED_2500_DFE_TAP_ENABLE; | sc->prv.serdes_dfe_tap_ena[1] = XGBE_SPEED_2500_DFE_TAP_ENABLE; | ||||
sc->prv.serdes_dfe_tap_ena[2] = XGBE_SPEED_10000_DFE_TAP_ENABLE; | sc->prv.serdes_dfe_tap_ena[2] = XGBE_SPEED_10000_DFE_TAP_ENABLE; | ||||
} | } | ||||
/* Check if the NIC is DMA coherent */ | /* Check if the NIC is DMA coherent */ | ||||
sc->prv.coherent = OF_hasprop(node, "dma-coherent"); | sc->prv.coherent = OF_hasprop(node, "dma-coherent"); | ||||
if (sc->prv.coherent) { | if (sc->prv.coherent) { | ||||
sc->prv.axdomain = XGBE_DMA_OS_AXDOMAIN; | sc->prv.arcr = XGBE_DMA_OS_ARCR; | ||||
sc->prv.arcache = XGBE_DMA_OS_ARCACHE; | sc->prv.awcr = XGBE_DMA_OS_AWCR; | ||||
sc->prv.awcache = XGBE_DMA_OS_AWCACHE; | |||||
} else { | } else { | ||||
sc->prv.axdomain = XGBE_DMA_SYS_AXDOMAIN; | sc->prv.arcr = XGBE_DMA_SYS_ARCR; | ||||
sc->prv.arcache = XGBE_DMA_SYS_ARCACHE; | sc->prv.awcr = XGBE_DMA_SYS_AWCR; | ||||
sc->prv.awcache = XGBE_DMA_SYS_AWCACHE; | |||||
} | } | ||||
/* Create the lock & workqueues */ | /* Create the lock & workqueues */ | ||||
spin_lock_init(&sc->prv.xpcs_lock); | spin_lock_init(&sc->prv.xpcs_lock); | ||||
sc->prv.dev_workqueue = taskqueue_create("axgbe", M_WAITOK, | sc->prv.dev_workqueue = taskqueue_create("axgbe", M_WAITOK, | ||||
taskqueue_thread_enqueue, &sc->prv.dev_workqueue); | taskqueue_thread_enqueue, &sc->prv.dev_workqueue); | ||||
taskqueue_start_threads(&sc->prv.dev_workqueue, 1, PI_NET, | taskqueue_start_threads(&sc->prv.dev_workqueue, 1, PI_NET, | ||||
"axgbe taskq"); | "axgbe taskq"); | ||||
/* Set the needed pointers */ | /* Set the needed pointers */ | ||||
xgbe_init_function_ptrs_phy(&sc->prv.phy_if); | xgbe_init_function_ptrs_phy(&sc->prv.phy_if); | ||||
xgbe_init_function_ptrs_dev(&sc->prv.hw_if); | xgbe_init_function_ptrs_dev(&sc->prv.hw_if); | ||||
xgbe_init_function_ptrs_desc(&sc->prv.desc_if); | xgbe_init_function_ptrs_desc(&sc->prv.desc_if); | ||||
sc->prv.vdata->init_function_ptrs_phy_impl(&sc->prv.phy_if); | |||||
/* Reset the hardware */ | /* Reset the hardware */ | ||||
sc->prv.hw_if.exit(&sc->prv); | sc->prv.hw_if.exit(&sc->prv); | ||||
/* Read the hardware features */ | /* Read the hardware features */ | ||||
xgbe_get_all_hw_features(&sc->prv); | xgbe_get_all_hw_features(&sc->prv); | ||||
/* Set default values */ | /* Set default values */ | ||||
sc->prv.pblx8 = DMA_PBL_X8_ENABLE; | |||||
sc->prv.tx_desc_count = XGBE_TX_DESC_CNT; | sc->prv.tx_desc_count = XGBE_TX_DESC_CNT; | ||||
sc->prv.tx_sf_mode = MTL_TSF_ENABLE; | sc->prv.tx_sf_mode = MTL_TSF_ENABLE; | ||||
sc->prv.tx_threshold = MTL_TX_THRESHOLD_64; | sc->prv.tx_threshold = MTL_TX_THRESHOLD_64; | ||||
sc->prv.tx_pbl = DMA_PBL_16; | |||||
sc->prv.tx_osp_mode = DMA_OSP_ENABLE; | sc->prv.tx_osp_mode = DMA_OSP_ENABLE; | ||||
sc->prv.rx_desc_count = XGBE_RX_DESC_CNT; | sc->prv.rx_desc_count = XGBE_RX_DESC_CNT; | ||||
sc->prv.rx_sf_mode = MTL_RSF_DISABLE; | sc->prv.rx_sf_mode = MTL_RSF_DISABLE; | ||||
sc->prv.rx_threshold = MTL_RX_THRESHOLD_64; | sc->prv.rx_threshold = MTL_RX_THRESHOLD_64; | ||||
sc->prv.rx_pbl = DMA_PBL_16; | sc->prv.pbl = DMA_PBL_128; | ||||
sc->prv.pause_autoneg = 1; | sc->prv.pause_autoneg = 1; | ||||
sc->prv.tx_pause = 1; | sc->prv.tx_pause = 1; | ||||
sc->prv.rx_pause = 1; | sc->prv.rx_pause = 1; | ||||
sc->prv.phy_speed = SPEED_UNKNOWN; | sc->prv.phy_speed = SPEED_UNKNOWN; | ||||
sc->prv.power_down = 0; | sc->prv.power_down = 0; | ||||
/* TODO: Limit to min(ncpus, hw rings) */ | /* TODO: Limit to min(ncpus, hw rings) */ | ||||
sc->prv.tx_ring_count = 1; | sc->prv.tx_ring_count = 1; | ||||
sc->prv.tx_q_count = 1; | sc->prv.tx_q_count = 1; | ||||
sc->prv.rx_ring_count = 1; | sc->prv.rx_ring_count = 1; | ||||
sc->prv.rx_q_count = sc->prv.hw_feat.rx_q_cnt; | sc->prv.rx_q_count = sc->prv.hw_feat.rx_q_cnt; | ||||
/* Init the PHY */ | /* Init the PHY */ | ||||
sc->prv.phy_if.phy_init(&sc->prv); | sc->prv.phy_if.phy_init(&sc->prv); | ||||
/* Set the coalescing */ | /* Set the coalescing */ | ||||
xgbe_init_rx_coalesce(&sc->prv); | xgbe_init_rx_coalesce(&sc->prv); | ||||
xgbe_init_tx_coalesce(&sc->prv); | xgbe_init_tx_coalesce(&sc->prv); | ||||
if_initname(ifp, device_get_name(dev), device_get_unit(dev)); | if_initname(ifp, device_get_name(dev), device_get_unit(dev)); | ||||
ifp->if_init = axgbe_init; | ifp->if_init = axgbe_init; | ||||
ifp->if_softc = sc; | ifp->if_softc = sc; | ||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | ||||
ifp->if_ioctl = axgbe_ioctl; | ifp->if_ioctl = axgbe_ioctl; | ||||
ifp->if_transmit = xgbe_xmit; | /* TODO - change it to iflib way */ | ||||
Done Inline ActionsC++ style comments should not be used, please convert to C style, or why not just delete the line? rgrimes: C++ style comments should not be used, please convert to C style, or why not just delete the… | |||||
ifp->if_qflush = axgbe_qflush; | ifp->if_qflush = axgbe_qflush; | ||||
ifp->if_get_counter = axgbe_get_counter; | ifp->if_get_counter = axgbe_get_counter; | ||||
/* TODO: Support HW offload */ | /* TODO: Support HW offload */ | ||||
ifp->if_capabilities = 0; | ifp->if_capabilities = 0; | ||||
ifp->if_capenable = 0; | ifp->if_capenable = 0; | ||||
ifp->if_hwassist = 0; | ifp->if_hwassist = 0; | ||||
ether_ifattach(ifp, sc->mac_addr); | ether_ifattach(ifp, sc->mac_addr); | ||||
ifmedia_init(&sc->media, IFM_IMASK, axgbe_media_change, | ifmedia_init(&sc->media, IFM_IMASK, axgbe_media_change, | ||||
axgbe_media_status); | axgbe_media_status); | ||||
#ifdef notyet | #ifdef notyet | ||||
ifmedia_add(&sc->media, IFM_ETHER | IFM_10G_KR, 0, NULL); | ifmedia_add(&sc->media, IFM_ETHER | IFM_10G_KR, 0, NULL); | ||||
#endif | #endif | ||||
ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_KX, 0, NULL); | ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_KX, 0, NULL); | ||||
ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); | ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); | ||||
ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO); | ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO); | ||||
set_bit(XGBE_DOWN, &sc->prv.dev_state); | set_bit(XGBE_DOWN, &sc->prv.dev_state); | ||||
if (xgbe_open(ifp) < 0) { | /* TODO - change it to iflib way */ | ||||
device_printf(dev, "ndo_open failed\n"); | |||||
return (ENXIO); | |||||
} | |||||
return (0); | return (0); | ||||
} | } | ||||
static device_method_t axgbe_methods[] = { | static device_method_t axgbe_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, axgbe_probe), | DEVMETHOD(device_probe, axgbe_probe), | ||||
DEVMETHOD(device_attach, axgbe_attach), | DEVMETHOD(device_attach, axgbe_attach), | ||||
{ 0, 0 } | { 0, 0 } | ||||
}; | }; | ||||
static devclass_t axgbe_devclass; | static devclass_t axgbe_devclass; | ||||
DEFINE_CLASS_0(axgbe, axgbe_driver, axgbe_methods, | DEFINE_CLASS_0(axgbe, axgbe_driver, axgbe_methods, | ||||
sizeof(struct axgbe_softc)); | sizeof(struct axgbe_softc)); | ||||
DRIVER_MODULE(axgbe, simplebus, axgbe_driver, axgbe_devclass, 0, 0); | DRIVER_MODULE(axa, simplebus, axgbe_driver, axgbe_devclass, 0, 0); | ||||
static struct ofw_compat_data phy_compat_data[] = { | static struct ofw_compat_data phy_compat_data[] = { | ||||
{ "amd,xgbe-phy-seattle-v1a", true }, | { "amd,xgbe-phy-seattle-v1a", true }, | ||||
{ NULL, false } | { NULL, false } | ||||
}; | }; | ||||
static int | static int | ||||
axgbephy_probe(device_t dev) | axgbephy_probe(device_t dev) | ||||
{ | { | ||||
Show All 18 Lines | axgbephy_attach(device_t dev) | ||||
return (0); | return (0); | ||||
} | } | ||||
static device_method_t axgbephy_methods[] = { | static device_method_t axgbephy_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, axgbephy_probe), | DEVMETHOD(device_probe, axgbephy_probe), | ||||
DEVMETHOD(device_attach, axgbephy_attach), | DEVMETHOD(device_attach, axgbephy_attach), | ||||
{ 0, 0 } | { 0, 0 } | ||||
}; | }; | ||||
static devclass_t axgbephy_devclass; | static devclass_t axgbephy_devclass; | ||||
DEFINE_CLASS_0(axgbephy, axgbephy_driver, axgbephy_methods, 0); | DEFINE_CLASS_0(axgbephy, axgbephy_driver, axgbephy_methods, 0); | ||||
EARLY_DRIVER_MODULE(axgbephy, simplebus, axgbephy_driver, axgbephy_devclass, | EARLY_DRIVER_MODULE(axgbephy, simplebus, axgbephy_driver, axgbephy_devclass, | ||||
0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE); | 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE); |
What's the story here?