// SPDX-License-Identifier: GPL-2.0-only /**************************************************************************** * Driver for Solarflare network controllers and boards * Copyright 2018 Solarflare Communications Inc. * Copyright 2019-2020 Xilinx Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, incorporated herein by reference.
*/ #include"net_driver.h" #include"mcdi_port_common.h" #include"mcdi_functions.h" #include"efx_common.h" #include"efx_channels.h" #include"tx_common.h" #include"ef100_netdev.h" #include"ef100_ethtool.h" #include"nic_common.h" #include"ef100_nic.h" #include"ef100_tx.h" #include"ef100_regs.h" #include"mcdi_filters.h" #include"rx_common.h" #include"ef100_sriov.h" #include"tc_bindings.h" #include"tc_encap_actions.h" #include"efx_devlink.h"
staticint ef100_alloc_vis(struct efx_nic *efx, unsignedint *allocated_vis)
{ /* EF100 uses a single TXQ per channel, as all checksum offloading * is configured in the TX descriptor, and there is no TX Pacer for * HIGHPRI queues.
*/ unsignedint tx_vis = efx->n_tx_channels + efx->n_extra_tx_channels; unsignedint rx_vis = efx->n_rx_channels; unsignedint min_vis, max_vis; int rc;
/* We retry allocating VIs by reallocating channels when we have not * been able to allocate the maximum VIs.
*/ if (!rc && *allocated_vis < max_vis)
rc = -EAGAIN;
/* Extend the original UC mapping of the memory BAR */
membase = ioremap(efx->membase_phys, uc_mem_map_size); if (!membase) {
netif_err(efx, probe, efx->net_dev, "could not extend memory BAR to %x\n",
uc_mem_map_size); return -ENOMEM;
}
iounmap(efx->membase);
efx->membase = membase; return 0;
}
/* Context: process, rtnl_lock() held. * Note that the kernel will ignore our return code; this method * should really be a void.
*/ staticint ef100_net_stop(struct net_device *net_dev)
{ struct efx_nic *efx = efx_netdev_priv(net_dev);
netif_dbg(efx, ifdown, efx->net_dev, "closing on CPU %d\n",
raw_smp_processor_id());
/* Try one more time but with the maximum number of channels * equal to the allocated VIs, which would more likely succeed.
*/ if (rc == -EAGAIN) {
rc = efx_mcdi_free_vis(efx); if (rc) goto fail;
/* It should be very unlikely that we failed here again, but in * such a case we return ENOSPC.
*/ if (rc == -EAGAIN) {
rc = -ENOSPC; goto fail;
}
}
rc = efx_probe_channels(efx); if (rc) return rc;
rc = ef100_remap_bar(efx, allocated_vis); if (rc) goto fail;
efx_init_napi(efx);
rc = efx_probe_filters(efx); if (rc) goto fail;
rc = efx_nic_init_interrupt(efx); if (rc) goto fail;
efx_set_interrupt_affinity(efx);
rc = efx_enable_interrupts(efx); if (rc) goto fail;
/* in case the MC rebooted while we were stopped, consume the change * to the warm reboot count
*/
(void) efx_mcdi_poll_reboot(efx);
rc = efx_mcdi_mac_init_stats(efx); if (rc) goto fail;
efx_start_all(efx);
/* Link state detection is normally event-driven; we have * to poll now because we could have missed a change
*/
mutex_lock(&efx->mac_lock); if (efx_mcdi_phy_poll(efx))
efx_link_status_changed(efx);
mutex_unlock(&efx->mac_lock);
efx->state = STATE_NET_UP; if (netif_running(efx->net_dev))
efx_attach_reps(efx);
return 0;
fail:
ef100_net_stop(net_dev); return rc;
}
/* Initiate a packet transmission. We use one channel per CPU * (sharing when we have more CPUs than channels). * * Context: non-blocking. * Note that returning anything other than NETDEV_TX_OK will cause the * OS to free the skb.
*/ static netdev_tx_t ef100_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
{ struct efx_nic *efx = efx_netdev_priv(net_dev);
if (efx->mcdi->fn_flags &
(1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_NO_ACTIVE_PORT)) {
pci_info(efx->pci_dev, "No network port on this PCI function"); return 0;
}
/* Allocate and initialise a struct net_device */
net_dev = alloc_etherdev_mq(sizeof(probe_data), EFX_MAX_CORE_TX_QUEUES); if (!net_dev) return -ENOMEM;
probe_ptr = netdev_priv(net_dev);
*probe_ptr = probe_data;
efx->net_dev = net_dev;
SET_NETDEV_DEV(net_dev, &efx->pci_dev->dev);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.