108135eecSEdward Cree // SPDX-License-Identifier: GPL-2.0-only 208135eecSEdward Cree /**************************************************************************** 308135eecSEdward Cree * Driver for Solarflare network controllers and boards 408135eecSEdward Cree * Copyright 2019 Solarflare Communications Inc. 508135eecSEdward Cree * Copyright 2020-2022 Xilinx Inc. 608135eecSEdward Cree * 708135eecSEdward Cree * This program is free software; you can redistribute it and/or modify it 808135eecSEdward Cree * under the terms of the GNU General Public License version 2 as published 908135eecSEdward Cree * by the Free Software Foundation, incorporated herein by reference. 1008135eecSEdward Cree */ 1108135eecSEdward Cree 1208135eecSEdward Cree #include "ef100_rep.h" 13f72c38faSEdward Cree #include "ef100_netdev.h" 1408135eecSEdward Cree #include "ef100_nic.h" 15da56552dSEdward Cree #include "mae.h" 1608135eecSEdward Cree 175687eb34SEdward Cree #define EFX_EF100_REP_DRIVER "efx_ef100_rep" 185687eb34SEdward Cree 19*69bb5fa7SEdward Cree static int efx_ef100_rep_poll(struct napi_struct *napi, int weight); 20*69bb5fa7SEdward Cree 21e1479556SEdward Cree static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv, 22e1479556SEdward Cree unsigned int i) 2308135eecSEdward Cree { 2408135eecSEdward Cree efv->parent = efx; 25e1479556SEdward Cree efv->idx = i; 2608135eecSEdward Cree INIT_LIST_HEAD(&efv->list); 27*69bb5fa7SEdward Cree INIT_LIST_HEAD(&efv->rx_list); 28*69bb5fa7SEdward Cree spin_lock_init(&efv->rx_lock); 2908135eecSEdward Cree efv->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE | 3008135eecSEdward Cree NETIF_MSG_LINK | NETIF_MSG_IFDOWN | 3108135eecSEdward Cree NETIF_MSG_IFUP | NETIF_MSG_RX_ERR | 3208135eecSEdward Cree NETIF_MSG_TX_ERR | NETIF_MSG_HW; 3308135eecSEdward Cree return 0; 3408135eecSEdward Cree } 3508135eecSEdward Cree 36*69bb5fa7SEdward Cree static int efx_ef100_rep_open(struct net_device *net_dev) 37*69bb5fa7SEdward Cree { 38*69bb5fa7SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 39*69bb5fa7SEdward Cree 40*69bb5fa7SEdward Cree netif_napi_add(net_dev, &efv->napi, efx_ef100_rep_poll, 41*69bb5fa7SEdward Cree NAPI_POLL_WEIGHT); 42*69bb5fa7SEdward Cree napi_enable(&efv->napi); 43*69bb5fa7SEdward Cree return 0; 44*69bb5fa7SEdward Cree } 45*69bb5fa7SEdward Cree 46*69bb5fa7SEdward Cree static int efx_ef100_rep_close(struct net_device *net_dev) 47*69bb5fa7SEdward Cree { 48*69bb5fa7SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 49*69bb5fa7SEdward Cree 50*69bb5fa7SEdward Cree napi_disable(&efv->napi); 51*69bb5fa7SEdward Cree netif_napi_del(&efv->napi); 52*69bb5fa7SEdward Cree return 0; 53*69bb5fa7SEdward Cree } 54*69bb5fa7SEdward Cree 55f72c38faSEdward Cree static netdev_tx_t efx_ef100_rep_xmit(struct sk_buff *skb, 56f72c38faSEdward Cree struct net_device *dev) 57f72c38faSEdward Cree { 58f72c38faSEdward Cree struct efx_rep *efv = netdev_priv(dev); 59f72c38faSEdward Cree struct efx_nic *efx = efv->parent; 60f72c38faSEdward Cree netdev_tx_t rc; 61f72c38faSEdward Cree 62f72c38faSEdward Cree /* __ef100_hard_start_xmit() will always return success even in the 63f72c38faSEdward Cree * case of TX drops, where it will increment efx's tx_dropped. The 64f72c38faSEdward Cree * efv stats really only count attempted TX, not success/failure. 65f72c38faSEdward Cree */ 66f72c38faSEdward Cree atomic64_inc(&efv->stats.tx_packets); 67f72c38faSEdward Cree atomic64_add(skb->len, &efv->stats.tx_bytes); 68f72c38faSEdward Cree netif_tx_lock(efx->net_dev); 69f72c38faSEdward Cree rc = __ef100_hard_start_xmit(skb, efx, dev, efv); 70f72c38faSEdward Cree netif_tx_unlock(efx->net_dev); 71f72c38faSEdward Cree return rc; 72f72c38faSEdward Cree } 73f72c38faSEdward Cree 74e1479556SEdward Cree static int efx_ef100_rep_get_port_parent_id(struct net_device *dev, 75e1479556SEdward Cree struct netdev_phys_item_id *ppid) 76e1479556SEdward Cree { 77e1479556SEdward Cree struct efx_rep *efv = netdev_priv(dev); 78e1479556SEdward Cree struct efx_nic *efx = efv->parent; 79e1479556SEdward Cree struct ef100_nic_data *nic_data; 80e1479556SEdward Cree 81e1479556SEdward Cree nic_data = efx->nic_data; 82e1479556SEdward Cree /* nic_data->port_id is a u8[] */ 83e1479556SEdward Cree ppid->id_len = sizeof(nic_data->port_id); 84e1479556SEdward Cree memcpy(ppid->id, nic_data->port_id, sizeof(nic_data->port_id)); 85e1479556SEdward Cree return 0; 86e1479556SEdward Cree } 87e1479556SEdward Cree 88e1479556SEdward Cree static int efx_ef100_rep_get_phys_port_name(struct net_device *dev, 89e1479556SEdward Cree char *buf, size_t len) 90e1479556SEdward Cree { 91e1479556SEdward Cree struct efx_rep *efv = netdev_priv(dev); 92e1479556SEdward Cree struct efx_nic *efx = efv->parent; 93e1479556SEdward Cree struct ef100_nic_data *nic_data; 94e1479556SEdward Cree int ret; 95e1479556SEdward Cree 96e1479556SEdward Cree nic_data = efx->nic_data; 97e1479556SEdward Cree ret = snprintf(buf, len, "p%upf%uvf%u", efx->port_num, 98e1479556SEdward Cree nic_data->pf_index, efv->idx); 99e1479556SEdward Cree if (ret >= len) 100e1479556SEdward Cree return -EOPNOTSUPP; 101e1479556SEdward Cree 102e1479556SEdward Cree return 0; 103e1479556SEdward Cree } 104e1479556SEdward Cree 105a95115c4SEdward Cree static void efx_ef100_rep_get_stats64(struct net_device *dev, 106a95115c4SEdward Cree struct rtnl_link_stats64 *stats) 107a95115c4SEdward Cree { 108a95115c4SEdward Cree struct efx_rep *efv = netdev_priv(dev); 109a95115c4SEdward Cree 110a95115c4SEdward Cree stats->rx_packets = atomic64_read(&efv->stats.rx_packets); 111a95115c4SEdward Cree stats->tx_packets = atomic64_read(&efv->stats.tx_packets); 112a95115c4SEdward Cree stats->rx_bytes = atomic64_read(&efv->stats.rx_bytes); 113a95115c4SEdward Cree stats->tx_bytes = atomic64_read(&efv->stats.tx_bytes); 114a95115c4SEdward Cree stats->rx_dropped = atomic64_read(&efv->stats.rx_dropped); 115a95115c4SEdward Cree stats->tx_errors = atomic64_read(&efv->stats.tx_errors); 116a95115c4SEdward Cree } 117a95115c4SEdward Cree 11808135eecSEdward Cree static const struct net_device_ops efx_ef100_rep_netdev_ops = { 119*69bb5fa7SEdward Cree .ndo_open = efx_ef100_rep_open, 120*69bb5fa7SEdward Cree .ndo_stop = efx_ef100_rep_close, 121f72c38faSEdward Cree .ndo_start_xmit = efx_ef100_rep_xmit, 122e1479556SEdward Cree .ndo_get_port_parent_id = efx_ef100_rep_get_port_parent_id, 123e1479556SEdward Cree .ndo_get_phys_port_name = efx_ef100_rep_get_phys_port_name, 124a95115c4SEdward Cree .ndo_get_stats64 = efx_ef100_rep_get_stats64, 12508135eecSEdward Cree }; 12608135eecSEdward Cree 1275687eb34SEdward Cree static void efx_ef100_rep_get_drvinfo(struct net_device *dev, 1285687eb34SEdward Cree struct ethtool_drvinfo *drvinfo) 1295687eb34SEdward Cree { 1305687eb34SEdward Cree strscpy(drvinfo->driver, EFX_EF100_REP_DRIVER, sizeof(drvinfo->driver)); 1315687eb34SEdward Cree } 1325687eb34SEdward Cree 1335687eb34SEdward Cree static u32 efx_ef100_rep_ethtool_get_msglevel(struct net_device *net_dev) 1345687eb34SEdward Cree { 1355687eb34SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 1365687eb34SEdward Cree 1375687eb34SEdward Cree return efv->msg_enable; 1385687eb34SEdward Cree } 1395687eb34SEdward Cree 1405687eb34SEdward Cree static void efx_ef100_rep_ethtool_set_msglevel(struct net_device *net_dev, 1415687eb34SEdward Cree u32 msg_enable) 1425687eb34SEdward Cree { 1435687eb34SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 1445687eb34SEdward Cree 1455687eb34SEdward Cree efv->msg_enable = msg_enable; 1465687eb34SEdward Cree } 1475687eb34SEdward Cree 14808135eecSEdward Cree static const struct ethtool_ops efx_ef100_rep_ethtool_ops = { 1495687eb34SEdward Cree .get_drvinfo = efx_ef100_rep_get_drvinfo, 1505687eb34SEdward Cree .get_msglevel = efx_ef100_rep_ethtool_get_msglevel, 1515687eb34SEdward Cree .set_msglevel = efx_ef100_rep_ethtool_set_msglevel, 15208135eecSEdward Cree }; 15308135eecSEdward Cree 15408135eecSEdward Cree static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx, 15508135eecSEdward Cree unsigned int i) 15608135eecSEdward Cree { 15708135eecSEdward Cree struct net_device *net_dev; 15808135eecSEdward Cree struct efx_rep *efv; 15908135eecSEdward Cree int rc; 16008135eecSEdward Cree 16108135eecSEdward Cree net_dev = alloc_etherdev_mq(sizeof(*efv), 1); 16208135eecSEdward Cree if (!net_dev) 16308135eecSEdward Cree return ERR_PTR(-ENOMEM); 16408135eecSEdward Cree 16508135eecSEdward Cree efv = netdev_priv(net_dev); 166e1479556SEdward Cree rc = efx_ef100_rep_init_struct(efx, efv, i); 16708135eecSEdward Cree if (rc) 16808135eecSEdward Cree goto fail1; 16908135eecSEdward Cree efv->net_dev = net_dev; 17008135eecSEdward Cree rtnl_lock(); 17108135eecSEdward Cree spin_lock_bh(&efx->vf_reps_lock); 17208135eecSEdward Cree list_add_tail(&efv->list, &efx->vf_reps); 17308135eecSEdward Cree spin_unlock_bh(&efx->vf_reps_lock); 17484e7fc25SEdward Cree if (netif_running(efx->net_dev) && efx->state == STATE_NET_UP) { 17584e7fc25SEdward Cree netif_device_attach(net_dev); 17684e7fc25SEdward Cree netif_carrier_on(net_dev); 17784e7fc25SEdward Cree } else { 17808135eecSEdward Cree netif_carrier_off(net_dev); 17908135eecSEdward Cree netif_tx_stop_all_queues(net_dev); 18084e7fc25SEdward Cree } 18108135eecSEdward Cree rtnl_unlock(); 18208135eecSEdward Cree 18308135eecSEdward Cree net_dev->netdev_ops = &efx_ef100_rep_netdev_ops; 18408135eecSEdward Cree net_dev->ethtool_ops = &efx_ef100_rep_ethtool_ops; 18508135eecSEdward Cree net_dev->min_mtu = EFX_MIN_MTU; 18608135eecSEdward Cree net_dev->max_mtu = EFX_MAX_MTU; 187f72c38faSEdward Cree net_dev->features |= NETIF_F_LLTX; 188f72c38faSEdward Cree net_dev->hw_features |= NETIF_F_LLTX; 18908135eecSEdward Cree return efv; 19008135eecSEdward Cree fail1: 19108135eecSEdward Cree free_netdev(net_dev); 19208135eecSEdward Cree return ERR_PTR(rc); 19308135eecSEdward Cree } 19408135eecSEdward Cree 195da56552dSEdward Cree static int efx_ef100_configure_rep(struct efx_rep *efv) 196da56552dSEdward Cree { 197da56552dSEdward Cree struct efx_nic *efx = efv->parent; 198da56552dSEdward Cree u32 selector; 199da56552dSEdward Cree int rc; 200da56552dSEdward Cree 201da56552dSEdward Cree /* Construct mport selector for corresponding VF */ 202da56552dSEdward Cree efx_mae_mport_vf(efx, efv->idx, &selector); 203da56552dSEdward Cree /* Look up actual mport ID */ 204da56552dSEdward Cree rc = efx_mae_lookup_mport(efx, selector, &efv->mport); 205da56552dSEdward Cree if (rc) 206da56552dSEdward Cree return rc; 207da56552dSEdward Cree pci_dbg(efx->pci_dev, "VF %u has mport ID %#x\n", efv->idx, efv->mport); 208da56552dSEdward Cree /* mport label should fit in 16 bits */ 209da56552dSEdward Cree WARN_ON(efv->mport >> 16); 210da56552dSEdward Cree 211da56552dSEdward Cree return 0; 212da56552dSEdward Cree } 213da56552dSEdward Cree 21408135eecSEdward Cree static void efx_ef100_rep_destroy_netdev(struct efx_rep *efv) 21508135eecSEdward Cree { 21608135eecSEdward Cree struct efx_nic *efx = efv->parent; 21708135eecSEdward Cree 21884e7fc25SEdward Cree rtnl_lock(); 21908135eecSEdward Cree spin_lock_bh(&efx->vf_reps_lock); 22008135eecSEdward Cree list_del(&efv->list); 22108135eecSEdward Cree spin_unlock_bh(&efx->vf_reps_lock); 22284e7fc25SEdward Cree rtnl_unlock(); 22308135eecSEdward Cree free_netdev(efv->net_dev); 22408135eecSEdward Cree } 22508135eecSEdward Cree 22608135eecSEdward Cree int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i) 22708135eecSEdward Cree { 22808135eecSEdward Cree struct efx_rep *efv; 22908135eecSEdward Cree int rc; 23008135eecSEdward Cree 23108135eecSEdward Cree efv = efx_ef100_rep_create_netdev(efx, i); 23208135eecSEdward Cree if (IS_ERR(efv)) { 23308135eecSEdward Cree rc = PTR_ERR(efv); 23408135eecSEdward Cree pci_err(efx->pci_dev, 23508135eecSEdward Cree "Failed to create representor for VF %d, rc %d\n", i, 23608135eecSEdward Cree rc); 23708135eecSEdward Cree return rc; 23808135eecSEdward Cree } 239da56552dSEdward Cree rc = efx_ef100_configure_rep(efv); 240da56552dSEdward Cree if (rc) { 241da56552dSEdward Cree pci_err(efx->pci_dev, 242da56552dSEdward Cree "Failed to configure representor for VF %d, rc %d\n", 243da56552dSEdward Cree i, rc); 244da56552dSEdward Cree goto fail; 245da56552dSEdward Cree } 24608135eecSEdward Cree rc = register_netdev(efv->net_dev); 24708135eecSEdward Cree if (rc) { 24808135eecSEdward Cree pci_err(efx->pci_dev, 24908135eecSEdward Cree "Failed to register representor for VF %d, rc %d\n", 25008135eecSEdward Cree i, rc); 25108135eecSEdward Cree goto fail; 25208135eecSEdward Cree } 25308135eecSEdward Cree pci_dbg(efx->pci_dev, "Representor for VF %d is %s\n", i, 25408135eecSEdward Cree efv->net_dev->name); 25508135eecSEdward Cree return 0; 25608135eecSEdward Cree fail: 25708135eecSEdward Cree efx_ef100_rep_destroy_netdev(efv); 25808135eecSEdward Cree return rc; 25908135eecSEdward Cree } 26008135eecSEdward Cree 26108135eecSEdward Cree void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv) 26208135eecSEdward Cree { 26308135eecSEdward Cree struct net_device *rep_dev; 26408135eecSEdward Cree 26508135eecSEdward Cree rep_dev = efv->net_dev; 26608135eecSEdward Cree if (!rep_dev) 26708135eecSEdward Cree return; 26808135eecSEdward Cree netif_dbg(efx, drv, rep_dev, "Removing VF representor\n"); 26908135eecSEdward Cree unregister_netdev(rep_dev); 27008135eecSEdward Cree efx_ef100_rep_destroy_netdev(efv); 27108135eecSEdward Cree } 27208135eecSEdward Cree 27308135eecSEdward Cree void efx_ef100_fini_vfreps(struct efx_nic *efx) 27408135eecSEdward Cree { 27508135eecSEdward Cree struct ef100_nic_data *nic_data = efx->nic_data; 27608135eecSEdward Cree struct efx_rep *efv, *next; 27708135eecSEdward Cree 27808135eecSEdward Cree if (!nic_data->grp_mae) 27908135eecSEdward Cree return; 28008135eecSEdward Cree 28108135eecSEdward Cree list_for_each_entry_safe(efv, next, &efx->vf_reps, list) 28208135eecSEdward Cree efx_ef100_vfrep_destroy(efx, efv); 28308135eecSEdward Cree } 284*69bb5fa7SEdward Cree 285*69bb5fa7SEdward Cree static int efx_ef100_rep_poll(struct napi_struct *napi, int weight) 286*69bb5fa7SEdward Cree { 287*69bb5fa7SEdward Cree struct efx_rep *efv = container_of(napi, struct efx_rep, napi); 288*69bb5fa7SEdward Cree unsigned int read_index; 289*69bb5fa7SEdward Cree struct list_head head; 290*69bb5fa7SEdward Cree struct sk_buff *skb; 291*69bb5fa7SEdward Cree bool need_resched; 292*69bb5fa7SEdward Cree int spent = 0; 293*69bb5fa7SEdward Cree 294*69bb5fa7SEdward Cree INIT_LIST_HEAD(&head); 295*69bb5fa7SEdward Cree /* Grab up to 'weight' pending SKBs */ 296*69bb5fa7SEdward Cree spin_lock_bh(&efv->rx_lock); 297*69bb5fa7SEdward Cree read_index = efv->write_index; 298*69bb5fa7SEdward Cree while (spent < weight && !list_empty(&efv->rx_list)) { 299*69bb5fa7SEdward Cree skb = list_first_entry(&efv->rx_list, struct sk_buff, list); 300*69bb5fa7SEdward Cree list_del(&skb->list); 301*69bb5fa7SEdward Cree list_add_tail(&skb->list, &head); 302*69bb5fa7SEdward Cree spent++; 303*69bb5fa7SEdward Cree } 304*69bb5fa7SEdward Cree spin_unlock_bh(&efv->rx_lock); 305*69bb5fa7SEdward Cree /* Receive them */ 306*69bb5fa7SEdward Cree netif_receive_skb_list(&head); 307*69bb5fa7SEdward Cree if (spent < weight) 308*69bb5fa7SEdward Cree if (napi_complete_done(napi, spent)) { 309*69bb5fa7SEdward Cree spin_lock_bh(&efv->rx_lock); 310*69bb5fa7SEdward Cree efv->read_index = read_index; 311*69bb5fa7SEdward Cree /* If write_index advanced while we were doing the 312*69bb5fa7SEdward Cree * RX, then storing our read_index won't re-prime the 313*69bb5fa7SEdward Cree * fake-interrupt. In that case, we need to schedule 314*69bb5fa7SEdward Cree * NAPI again to consume the additional packet(s). 315*69bb5fa7SEdward Cree */ 316*69bb5fa7SEdward Cree need_resched = efv->write_index != read_index; 317*69bb5fa7SEdward Cree spin_unlock_bh(&efv->rx_lock); 318*69bb5fa7SEdward Cree if (need_resched) 319*69bb5fa7SEdward Cree napi_schedule(&efv->napi); 320*69bb5fa7SEdward Cree } 321*69bb5fa7SEdward Cree return spent; 322*69bb5fa7SEdward Cree } 323