123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- // 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"
- static void ef100_update_name(struct efx_nic *efx)
- {
- strcpy(efx->name, efx->net_dev->name);
- }
- static int ef100_alloc_vis(struct efx_nic *efx, unsigned int *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.
- */
- unsigned int tx_vis = efx->n_tx_channels + efx->n_extra_tx_channels;
- unsigned int rx_vis = efx->n_rx_channels;
- unsigned int min_vis, max_vis;
- EFX_WARN_ON_PARANOID(efx->tx_queues_per_channel != 1);
- tx_vis += efx->n_xdp_channels * efx->xdp_tx_per_channel;
- max_vis = max(rx_vis, tx_vis);
- /* Currently don't handle resource starvation and only accept
- * our maximum needs and no less.
- */
- min_vis = max_vis;
- return efx_mcdi_alloc_vis(efx, min_vis, max_vis,
- NULL, allocated_vis);
- }
- static int ef100_remap_bar(struct efx_nic *efx, int max_vis)
- {
- unsigned int uc_mem_map_size;
- void __iomem *membase;
- efx->max_vis = max_vis;
- uc_mem_map_size = PAGE_ALIGN(max_vis * efx->vi_stride);
- /* 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.
- */
- static int 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());
- efx_detach_reps(efx);
- netif_stop_queue(net_dev);
- efx_stop_all(efx);
- efx_mcdi_mac_fini_stats(efx);
- efx_disable_interrupts(efx);
- efx_clear_interrupt_affinity(efx);
- efx_nic_fini_interrupt(efx);
- efx_remove_filters(efx);
- efx_fini_napi(efx);
- efx_remove_channels(efx);
- efx_mcdi_free_vis(efx);
- efx_remove_interrupts(efx);
- efx->state = STATE_NET_DOWN;
- return 0;
- }
- /* Context: process, rtnl_lock() held. */
- static int ef100_net_open(struct net_device *net_dev)
- {
- struct efx_nic *efx = efx_netdev_priv(net_dev);
- unsigned int allocated_vis;
- int rc;
- ef100_update_name(efx);
- netif_dbg(efx, ifup, net_dev, "opening device on CPU %d\n",
- raw_smp_processor_id());
- rc = efx_check_disabled(efx);
- if (rc)
- goto fail;
- rc = efx_probe_interrupts(efx);
- if (rc)
- goto fail;
- rc = efx_set_channels(efx);
- if (rc)
- goto fail;
- rc = efx_mcdi_free_vis(efx);
- if (rc)
- goto fail;
- rc = ef100_alloc_vis(efx, &allocated_vis);
- if (rc)
- 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);
- return __ef100_hard_start_xmit(skb, efx, net_dev, NULL);
- }
- netdev_tx_t __ef100_hard_start_xmit(struct sk_buff *skb,
- struct efx_nic *efx,
- struct net_device *net_dev,
- struct efx_rep *efv)
- {
- struct efx_tx_queue *tx_queue;
- struct efx_channel *channel;
- int rc;
- channel = efx_get_tx_channel(efx, skb_get_queue_mapping(skb));
- netif_vdbg(efx, tx_queued, efx->net_dev,
- "%s len %d data %d channel %d\n", __func__,
- skb->len, skb->data_len, channel->channel);
- if (!efx->n_channels || !efx->n_tx_channels || !channel) {
- netif_stop_queue(net_dev);
- dev_kfree_skb_any(skb);
- goto err;
- }
- tx_queue = &channel->tx_queue[0];
- rc = __ef100_enqueue_skb(tx_queue, skb, efv);
- if (rc == 0)
- return NETDEV_TX_OK;
- err:
- net_dev->stats.tx_dropped++;
- return NETDEV_TX_OK;
- }
- static const struct net_device_ops ef100_netdev_ops = {
- .ndo_open = ef100_net_open,
- .ndo_stop = ef100_net_stop,
- .ndo_start_xmit = ef100_hard_start_xmit,
- .ndo_tx_timeout = efx_watchdog,
- .ndo_get_stats64 = efx_net_stats,
- .ndo_change_mtu = efx_change_mtu,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = efx_set_mac_address,
- .ndo_set_rx_mode = efx_set_rx_mode, /* Lookout */
- .ndo_set_features = efx_set_features,
- .ndo_get_phys_port_id = efx_get_phys_port_id,
- .ndo_get_phys_port_name = efx_get_phys_port_name,
- #ifdef CONFIG_RFS_ACCEL
- .ndo_rx_flow_steer = efx_filter_rfs,
- #endif
- #ifdef CONFIG_SFC_SRIOV
- .ndo_setup_tc = efx_tc_setup,
- #endif
- };
- /* Netdev registration
- */
- int ef100_netdev_event(struct notifier_block *this,
- unsigned long event, void *ptr)
- {
- struct efx_nic *efx = container_of(this, struct efx_nic, netdev_notifier);
- struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
- if (efx->net_dev == net_dev &&
- (event == NETDEV_CHANGENAME || event == NETDEV_REGISTER))
- ef100_update_name(efx);
- return NOTIFY_DONE;
- }
- static int ef100_register_netdev(struct efx_nic *efx)
- {
- struct net_device *net_dev = efx->net_dev;
- int rc;
- net_dev->watchdog_timeo = 5 * HZ;
- net_dev->irq = efx->pci_dev->irq;
- net_dev->netdev_ops = &ef100_netdev_ops;
- net_dev->min_mtu = EFX_MIN_MTU;
- net_dev->max_mtu = EFX_MAX_MTU;
- net_dev->ethtool_ops = &ef100_ethtool_ops;
- rtnl_lock();
- rc = dev_alloc_name(net_dev, net_dev->name);
- if (rc < 0)
- goto fail_locked;
- ef100_update_name(efx);
- rc = register_netdevice(net_dev);
- if (rc)
- goto fail_locked;
- /* Always start with carrier off; PHY events will detect the link */
- netif_carrier_off(net_dev);
- efx->state = STATE_NET_DOWN;
- rtnl_unlock();
- efx_init_mcdi_logging(efx);
- return 0;
- fail_locked:
- rtnl_unlock();
- netif_err(efx, drv, efx->net_dev, "could not register net dev\n");
- return rc;
- }
- static void ef100_unregister_netdev(struct efx_nic *efx)
- {
- if (efx_dev_registered(efx)) {
- efx_fini_mcdi_logging(efx);
- efx->state = STATE_PROBED;
- unregister_netdev(efx->net_dev);
- }
- }
- void ef100_remove_netdev(struct efx_probe_data *probe_data)
- {
- struct efx_nic *efx = &probe_data->efx;
- if (!efx->net_dev)
- return;
- rtnl_lock();
- dev_close(efx->net_dev);
- rtnl_unlock();
- unregister_netdevice_notifier(&efx->netdev_notifier);
- #if defined(CONFIG_SFC_SRIOV)
- if (!efx->type->is_vf)
- efx_ef100_pci_sriov_disable(efx, true);
- #endif
- ef100_unregister_netdev(efx);
- #ifdef CONFIG_SFC_SRIOV
- efx_fini_tc(efx);
- #endif
- down_write(&efx->filter_sem);
- efx_mcdi_filter_table_remove(efx);
- up_write(&efx->filter_sem);
- efx_fini_channels(efx);
- kfree(efx->phy_data);
- efx->phy_data = NULL;
- free_netdev(efx->net_dev);
- efx->net_dev = NULL;
- efx->state = STATE_PROBED;
- }
- int ef100_probe_netdev(struct efx_probe_data *probe_data)
- {
- struct efx_nic *efx = &probe_data->efx;
- struct efx_probe_data **probe_ptr;
- struct net_device *net_dev;
- int rc;
- 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);
- /* enable all supported features except rx-fcs and rx-all */
- net_dev->features |= efx->type->offload_features &
- ~(NETIF_F_RXFCS | NETIF_F_RXALL);
- net_dev->hw_features |= efx->type->offload_features;
- net_dev->hw_enc_features |= efx->type->offload_features;
- net_dev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_SG |
- NETIF_F_HIGHDMA | NETIF_F_ALL_TSO;
- netif_set_tso_max_segs(net_dev,
- ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS_DEFAULT);
- efx->mdio.dev = net_dev;
- rc = efx_ef100_init_datapath_caps(efx);
- if (rc < 0)
- goto fail;
- rc = ef100_phy_probe(efx);
- if (rc)
- goto fail;
- rc = efx_init_channels(efx);
- if (rc)
- goto fail;
- down_write(&efx->filter_sem);
- rc = ef100_filter_table_probe(efx);
- up_write(&efx->filter_sem);
- if (rc)
- goto fail;
- netdev_rss_key_fill(efx->rss_context.rx_hash_key,
- sizeof(efx->rss_context.rx_hash_key));
- /* Don't fail init if RSS setup doesn't work. */
- efx_mcdi_push_default_indir_table(efx, efx->n_rx_channels);
- rc = ef100_register_netdev(efx);
- if (rc)
- goto fail;
- if (!efx->type->is_vf) {
- rc = ef100_probe_netdev_pf(efx);
- if (rc)
- goto fail;
- }
- efx->netdev_notifier.notifier_call = ef100_netdev_event;
- rc = register_netdevice_notifier(&efx->netdev_notifier);
- if (rc) {
- netif_err(efx, probe, efx->net_dev,
- "Failed to register netdevice notifier, rc=%d\n", rc);
- goto fail;
- }
- fail:
- return rc;
- }
|