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" 169fe00c80SEdward Cree #include "rx_common.h" 1708135eecSEdward Cree 185687eb34SEdward Cree #define EFX_EF100_REP_DRIVER "efx_ef100_rep" 195687eb34SEdward Cree 209fe00c80SEdward Cree #define EFX_REP_DEFAULT_PSEUDO_RING_SIZE 64 219fe00c80SEdward Cree 2269bb5fa7SEdward Cree static int efx_ef100_rep_poll(struct napi_struct *napi, int weight); 2369bb5fa7SEdward Cree 24e1479556SEdward Cree static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv, 25e1479556SEdward Cree unsigned int i) 2608135eecSEdward Cree { 2708135eecSEdward Cree efv->parent = efx; 28e1479556SEdward Cree efv->idx = i; 2908135eecSEdward Cree INIT_LIST_HEAD(&efv->list); 3067ab160eSEdward Cree efv->dflt.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL; 3167ab160eSEdward Cree INIT_LIST_HEAD(&efv->dflt.acts.list); 3269bb5fa7SEdward Cree INIT_LIST_HEAD(&efv->rx_list); 3369bb5fa7SEdward Cree spin_lock_init(&efv->rx_lock); 3408135eecSEdward Cree efv->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE | 3508135eecSEdward Cree NETIF_MSG_LINK | NETIF_MSG_IFDOWN | 3608135eecSEdward Cree NETIF_MSG_IFUP | NETIF_MSG_RX_ERR | 3708135eecSEdward Cree NETIF_MSG_TX_ERR | NETIF_MSG_HW; 3808135eecSEdward Cree return 0; 3908135eecSEdward Cree } 4008135eecSEdward Cree 4169bb5fa7SEdward Cree static int efx_ef100_rep_open(struct net_device *net_dev) 4269bb5fa7SEdward Cree { 4369bb5fa7SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 4469bb5fa7SEdward Cree 4569bb5fa7SEdward Cree netif_napi_add(net_dev, &efv->napi, efx_ef100_rep_poll, 4669bb5fa7SEdward Cree NAPI_POLL_WEIGHT); 4769bb5fa7SEdward Cree napi_enable(&efv->napi); 4869bb5fa7SEdward Cree return 0; 4969bb5fa7SEdward Cree } 5069bb5fa7SEdward Cree 5169bb5fa7SEdward Cree static int efx_ef100_rep_close(struct net_device *net_dev) 5269bb5fa7SEdward Cree { 5369bb5fa7SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 5469bb5fa7SEdward Cree 5569bb5fa7SEdward Cree napi_disable(&efv->napi); 5669bb5fa7SEdward Cree netif_napi_del(&efv->napi); 5769bb5fa7SEdward Cree return 0; 5869bb5fa7SEdward Cree } 5969bb5fa7SEdward Cree 60f72c38faSEdward Cree static netdev_tx_t efx_ef100_rep_xmit(struct sk_buff *skb, 61f72c38faSEdward Cree struct net_device *dev) 62f72c38faSEdward Cree { 63f72c38faSEdward Cree struct efx_rep *efv = netdev_priv(dev); 64f72c38faSEdward Cree struct efx_nic *efx = efv->parent; 65f72c38faSEdward Cree netdev_tx_t rc; 66f72c38faSEdward Cree 67f72c38faSEdward Cree /* __ef100_hard_start_xmit() will always return success even in the 68f72c38faSEdward Cree * case of TX drops, where it will increment efx's tx_dropped. The 69f72c38faSEdward Cree * efv stats really only count attempted TX, not success/failure. 70f72c38faSEdward Cree */ 71f72c38faSEdward Cree atomic64_inc(&efv->stats.tx_packets); 72f72c38faSEdward Cree atomic64_add(skb->len, &efv->stats.tx_bytes); 73f72c38faSEdward Cree netif_tx_lock(efx->net_dev); 74f72c38faSEdward Cree rc = __ef100_hard_start_xmit(skb, efx, dev, efv); 75f72c38faSEdward Cree netif_tx_unlock(efx->net_dev); 76f72c38faSEdward Cree return rc; 77f72c38faSEdward Cree } 78f72c38faSEdward Cree 79e1479556SEdward Cree static int efx_ef100_rep_get_port_parent_id(struct net_device *dev, 80e1479556SEdward Cree struct netdev_phys_item_id *ppid) 81e1479556SEdward Cree { 82e1479556SEdward Cree struct efx_rep *efv = netdev_priv(dev); 83e1479556SEdward Cree struct efx_nic *efx = efv->parent; 84e1479556SEdward Cree struct ef100_nic_data *nic_data; 85e1479556SEdward Cree 86e1479556SEdward Cree nic_data = efx->nic_data; 87e1479556SEdward Cree /* nic_data->port_id is a u8[] */ 88e1479556SEdward Cree ppid->id_len = sizeof(nic_data->port_id); 89e1479556SEdward Cree memcpy(ppid->id, nic_data->port_id, sizeof(nic_data->port_id)); 90e1479556SEdward Cree return 0; 91e1479556SEdward Cree } 92e1479556SEdward Cree 93e1479556SEdward Cree static int efx_ef100_rep_get_phys_port_name(struct net_device *dev, 94e1479556SEdward Cree char *buf, size_t len) 95e1479556SEdward Cree { 96e1479556SEdward Cree struct efx_rep *efv = netdev_priv(dev); 97e1479556SEdward Cree struct efx_nic *efx = efv->parent; 98e1479556SEdward Cree struct ef100_nic_data *nic_data; 99e1479556SEdward Cree int ret; 100e1479556SEdward Cree 101e1479556SEdward Cree nic_data = efx->nic_data; 102e1479556SEdward Cree ret = snprintf(buf, len, "p%upf%uvf%u", efx->port_num, 103e1479556SEdward Cree nic_data->pf_index, efv->idx); 104e1479556SEdward Cree if (ret >= len) 105e1479556SEdward Cree return -EOPNOTSUPP; 106e1479556SEdward Cree 107e1479556SEdward Cree return 0; 108e1479556SEdward Cree } 109e1479556SEdward Cree 110a95115c4SEdward Cree static void efx_ef100_rep_get_stats64(struct net_device *dev, 111a95115c4SEdward Cree struct rtnl_link_stats64 *stats) 112a95115c4SEdward Cree { 113a95115c4SEdward Cree struct efx_rep *efv = netdev_priv(dev); 114a95115c4SEdward Cree 115a95115c4SEdward Cree stats->rx_packets = atomic64_read(&efv->stats.rx_packets); 116a95115c4SEdward Cree stats->tx_packets = atomic64_read(&efv->stats.tx_packets); 117a95115c4SEdward Cree stats->rx_bytes = atomic64_read(&efv->stats.rx_bytes); 118a95115c4SEdward Cree stats->tx_bytes = atomic64_read(&efv->stats.tx_bytes); 119a95115c4SEdward Cree stats->rx_dropped = atomic64_read(&efv->stats.rx_dropped); 120a95115c4SEdward Cree stats->tx_errors = atomic64_read(&efv->stats.tx_errors); 121a95115c4SEdward Cree } 122a95115c4SEdward Cree 12308135eecSEdward Cree static const struct net_device_ops efx_ef100_rep_netdev_ops = { 12469bb5fa7SEdward Cree .ndo_open = efx_ef100_rep_open, 12569bb5fa7SEdward Cree .ndo_stop = efx_ef100_rep_close, 126f72c38faSEdward Cree .ndo_start_xmit = efx_ef100_rep_xmit, 127e1479556SEdward Cree .ndo_get_port_parent_id = efx_ef100_rep_get_port_parent_id, 128e1479556SEdward Cree .ndo_get_phys_port_name = efx_ef100_rep_get_phys_port_name, 129a95115c4SEdward Cree .ndo_get_stats64 = efx_ef100_rep_get_stats64, 13008135eecSEdward Cree }; 13108135eecSEdward Cree 1325687eb34SEdward Cree static void efx_ef100_rep_get_drvinfo(struct net_device *dev, 1335687eb34SEdward Cree struct ethtool_drvinfo *drvinfo) 1345687eb34SEdward Cree { 1355687eb34SEdward Cree strscpy(drvinfo->driver, EFX_EF100_REP_DRIVER, sizeof(drvinfo->driver)); 1365687eb34SEdward Cree } 1375687eb34SEdward Cree 1385687eb34SEdward Cree static u32 efx_ef100_rep_ethtool_get_msglevel(struct net_device *net_dev) 1395687eb34SEdward Cree { 1405687eb34SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 1415687eb34SEdward Cree 1425687eb34SEdward Cree return efv->msg_enable; 1435687eb34SEdward Cree } 1445687eb34SEdward Cree 1455687eb34SEdward Cree static void efx_ef100_rep_ethtool_set_msglevel(struct net_device *net_dev, 1465687eb34SEdward Cree u32 msg_enable) 1475687eb34SEdward Cree { 1485687eb34SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 1495687eb34SEdward Cree 1505687eb34SEdward Cree efv->msg_enable = msg_enable; 1515687eb34SEdward Cree } 1525687eb34SEdward Cree 153*7267aa6dSEdward Cree static void efx_ef100_rep_ethtool_get_ringparam(struct net_device *net_dev, 154*7267aa6dSEdward Cree struct ethtool_ringparam *ring, 155*7267aa6dSEdward Cree struct kernel_ethtool_ringparam *kring, 156*7267aa6dSEdward Cree struct netlink_ext_ack *ext_ack) 157*7267aa6dSEdward Cree { 158*7267aa6dSEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 159*7267aa6dSEdward Cree 160*7267aa6dSEdward Cree ring->rx_max_pending = U32_MAX; 161*7267aa6dSEdward Cree ring->rx_pending = efv->rx_pring_size; 162*7267aa6dSEdward Cree } 163*7267aa6dSEdward Cree 164*7267aa6dSEdward Cree static int efx_ef100_rep_ethtool_set_ringparam(struct net_device *net_dev, 165*7267aa6dSEdward Cree struct ethtool_ringparam *ring, 166*7267aa6dSEdward Cree struct kernel_ethtool_ringparam *kring, 167*7267aa6dSEdward Cree struct netlink_ext_ack *ext_ack) 168*7267aa6dSEdward Cree { 169*7267aa6dSEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 170*7267aa6dSEdward Cree 171*7267aa6dSEdward Cree if (ring->rx_mini_pending || ring->rx_jumbo_pending || ring->tx_pending) 172*7267aa6dSEdward Cree return -EINVAL; 173*7267aa6dSEdward Cree 174*7267aa6dSEdward Cree efv->rx_pring_size = ring->rx_pending; 175*7267aa6dSEdward Cree return 0; 176*7267aa6dSEdward Cree } 177*7267aa6dSEdward Cree 17808135eecSEdward Cree static const struct ethtool_ops efx_ef100_rep_ethtool_ops = { 1795687eb34SEdward Cree .get_drvinfo = efx_ef100_rep_get_drvinfo, 1805687eb34SEdward Cree .get_msglevel = efx_ef100_rep_ethtool_get_msglevel, 1815687eb34SEdward Cree .set_msglevel = efx_ef100_rep_ethtool_set_msglevel, 182*7267aa6dSEdward Cree .get_ringparam = efx_ef100_rep_ethtool_get_ringparam, 183*7267aa6dSEdward Cree .set_ringparam = efx_ef100_rep_ethtool_set_ringparam, 18408135eecSEdward Cree }; 18508135eecSEdward Cree 18608135eecSEdward Cree static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx, 18708135eecSEdward Cree unsigned int i) 18808135eecSEdward Cree { 18908135eecSEdward Cree struct net_device *net_dev; 19008135eecSEdward Cree struct efx_rep *efv; 19108135eecSEdward Cree int rc; 19208135eecSEdward Cree 19308135eecSEdward Cree net_dev = alloc_etherdev_mq(sizeof(*efv), 1); 19408135eecSEdward Cree if (!net_dev) 19508135eecSEdward Cree return ERR_PTR(-ENOMEM); 19608135eecSEdward Cree 19708135eecSEdward Cree efv = netdev_priv(net_dev); 198e1479556SEdward Cree rc = efx_ef100_rep_init_struct(efx, efv, i); 19908135eecSEdward Cree if (rc) 20008135eecSEdward Cree goto fail1; 20108135eecSEdward Cree efv->net_dev = net_dev; 20208135eecSEdward Cree rtnl_lock(); 20308135eecSEdward Cree spin_lock_bh(&efx->vf_reps_lock); 20408135eecSEdward Cree list_add_tail(&efv->list, &efx->vf_reps); 20508135eecSEdward Cree spin_unlock_bh(&efx->vf_reps_lock); 20684e7fc25SEdward Cree if (netif_running(efx->net_dev) && efx->state == STATE_NET_UP) { 20784e7fc25SEdward Cree netif_device_attach(net_dev); 20884e7fc25SEdward Cree netif_carrier_on(net_dev); 20984e7fc25SEdward Cree } else { 21008135eecSEdward Cree netif_carrier_off(net_dev); 21108135eecSEdward Cree netif_tx_stop_all_queues(net_dev); 21284e7fc25SEdward Cree } 21308135eecSEdward Cree rtnl_unlock(); 21408135eecSEdward Cree 21508135eecSEdward Cree net_dev->netdev_ops = &efx_ef100_rep_netdev_ops; 21608135eecSEdward Cree net_dev->ethtool_ops = &efx_ef100_rep_ethtool_ops; 21708135eecSEdward Cree net_dev->min_mtu = EFX_MIN_MTU; 21808135eecSEdward Cree net_dev->max_mtu = EFX_MAX_MTU; 219f72c38faSEdward Cree net_dev->features |= NETIF_F_LLTX; 220f72c38faSEdward Cree net_dev->hw_features |= NETIF_F_LLTX; 22108135eecSEdward Cree return efv; 22208135eecSEdward Cree fail1: 22308135eecSEdward Cree free_netdev(net_dev); 22408135eecSEdward Cree return ERR_PTR(rc); 22508135eecSEdward Cree } 22608135eecSEdward Cree 227da56552dSEdward Cree static int efx_ef100_configure_rep(struct efx_rep *efv) 228da56552dSEdward Cree { 229da56552dSEdward Cree struct efx_nic *efx = efv->parent; 230da56552dSEdward Cree u32 selector; 231da56552dSEdward Cree int rc; 232da56552dSEdward Cree 2339fe00c80SEdward Cree efv->rx_pring_size = EFX_REP_DEFAULT_PSEUDO_RING_SIZE; 234da56552dSEdward Cree /* Construct mport selector for corresponding VF */ 235da56552dSEdward Cree efx_mae_mport_vf(efx, efv->idx, &selector); 236da56552dSEdward Cree /* Look up actual mport ID */ 237da56552dSEdward Cree rc = efx_mae_lookup_mport(efx, selector, &efv->mport); 238da56552dSEdward Cree if (rc) 239da56552dSEdward Cree return rc; 240da56552dSEdward Cree pci_dbg(efx->pci_dev, "VF %u has mport ID %#x\n", efv->idx, efv->mport); 241da56552dSEdward Cree /* mport label should fit in 16 bits */ 242da56552dSEdward Cree WARN_ON(efv->mport >> 16); 243da56552dSEdward Cree 24467ab160eSEdward Cree return efx_tc_configure_default_rule_rep(efv); 24567ab160eSEdward Cree } 24667ab160eSEdward Cree 24767ab160eSEdward Cree static void efx_ef100_deconfigure_rep(struct efx_rep *efv) 24867ab160eSEdward Cree { 24967ab160eSEdward Cree struct efx_nic *efx = efv->parent; 25067ab160eSEdward Cree 25167ab160eSEdward Cree efx_tc_deconfigure_default_rule(efx, &efv->dflt); 252da56552dSEdward Cree } 253da56552dSEdward Cree 25408135eecSEdward Cree static void efx_ef100_rep_destroy_netdev(struct efx_rep *efv) 25508135eecSEdward Cree { 25608135eecSEdward Cree struct efx_nic *efx = efv->parent; 25708135eecSEdward Cree 25884e7fc25SEdward Cree rtnl_lock(); 25908135eecSEdward Cree spin_lock_bh(&efx->vf_reps_lock); 26008135eecSEdward Cree list_del(&efv->list); 26108135eecSEdward Cree spin_unlock_bh(&efx->vf_reps_lock); 26284e7fc25SEdward Cree rtnl_unlock(); 263f50e8fcdSEdward Cree synchronize_rcu(); 26408135eecSEdward Cree free_netdev(efv->net_dev); 26508135eecSEdward Cree } 26608135eecSEdward Cree 26708135eecSEdward Cree int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i) 26808135eecSEdward Cree { 26908135eecSEdward Cree struct efx_rep *efv; 27008135eecSEdward Cree int rc; 27108135eecSEdward Cree 27208135eecSEdward Cree efv = efx_ef100_rep_create_netdev(efx, i); 27308135eecSEdward Cree if (IS_ERR(efv)) { 27408135eecSEdward Cree rc = PTR_ERR(efv); 27508135eecSEdward Cree pci_err(efx->pci_dev, 27608135eecSEdward Cree "Failed to create representor for VF %d, rc %d\n", i, 27708135eecSEdward Cree rc); 27808135eecSEdward Cree return rc; 27908135eecSEdward Cree } 280da56552dSEdward Cree rc = efx_ef100_configure_rep(efv); 281da56552dSEdward Cree if (rc) { 282da56552dSEdward Cree pci_err(efx->pci_dev, 283da56552dSEdward Cree "Failed to configure representor for VF %d, rc %d\n", 284da56552dSEdward Cree i, rc); 28567ab160eSEdward Cree goto fail1; 286da56552dSEdward Cree } 28708135eecSEdward Cree rc = register_netdev(efv->net_dev); 28808135eecSEdward Cree if (rc) { 28908135eecSEdward Cree pci_err(efx->pci_dev, 29008135eecSEdward Cree "Failed to register representor for VF %d, rc %d\n", 29108135eecSEdward Cree i, rc); 29267ab160eSEdward Cree goto fail2; 29308135eecSEdward Cree } 29408135eecSEdward Cree pci_dbg(efx->pci_dev, "Representor for VF %d is %s\n", i, 29508135eecSEdward Cree efv->net_dev->name); 29608135eecSEdward Cree return 0; 29767ab160eSEdward Cree fail2: 29867ab160eSEdward Cree efx_ef100_deconfigure_rep(efv); 29967ab160eSEdward Cree fail1: 30008135eecSEdward Cree efx_ef100_rep_destroy_netdev(efv); 30108135eecSEdward Cree return rc; 30208135eecSEdward Cree } 30308135eecSEdward Cree 30408135eecSEdward Cree void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv) 30508135eecSEdward Cree { 30608135eecSEdward Cree struct net_device *rep_dev; 30708135eecSEdward Cree 30808135eecSEdward Cree rep_dev = efv->net_dev; 30908135eecSEdward Cree if (!rep_dev) 31008135eecSEdward Cree return; 31108135eecSEdward Cree netif_dbg(efx, drv, rep_dev, "Removing VF representor\n"); 31208135eecSEdward Cree unregister_netdev(rep_dev); 31367ab160eSEdward Cree efx_ef100_deconfigure_rep(efv); 31408135eecSEdward Cree efx_ef100_rep_destroy_netdev(efv); 31508135eecSEdward Cree } 31608135eecSEdward Cree 31708135eecSEdward Cree void efx_ef100_fini_vfreps(struct efx_nic *efx) 31808135eecSEdward Cree { 31908135eecSEdward Cree struct ef100_nic_data *nic_data = efx->nic_data; 32008135eecSEdward Cree struct efx_rep *efv, *next; 32108135eecSEdward Cree 32208135eecSEdward Cree if (!nic_data->grp_mae) 32308135eecSEdward Cree return; 32408135eecSEdward Cree 32508135eecSEdward Cree list_for_each_entry_safe(efv, next, &efx->vf_reps, list) 32608135eecSEdward Cree efx_ef100_vfrep_destroy(efx, efv); 32708135eecSEdward Cree } 32869bb5fa7SEdward Cree 32969bb5fa7SEdward Cree static int efx_ef100_rep_poll(struct napi_struct *napi, int weight) 33069bb5fa7SEdward Cree { 33169bb5fa7SEdward Cree struct efx_rep *efv = container_of(napi, struct efx_rep, napi); 33269bb5fa7SEdward Cree unsigned int read_index; 33369bb5fa7SEdward Cree struct list_head head; 33469bb5fa7SEdward Cree struct sk_buff *skb; 33569bb5fa7SEdward Cree bool need_resched; 33669bb5fa7SEdward Cree int spent = 0; 33769bb5fa7SEdward Cree 33869bb5fa7SEdward Cree INIT_LIST_HEAD(&head); 33969bb5fa7SEdward Cree /* Grab up to 'weight' pending SKBs */ 34069bb5fa7SEdward Cree spin_lock_bh(&efv->rx_lock); 34169bb5fa7SEdward Cree read_index = efv->write_index; 34269bb5fa7SEdward Cree while (spent < weight && !list_empty(&efv->rx_list)) { 34369bb5fa7SEdward Cree skb = list_first_entry(&efv->rx_list, struct sk_buff, list); 34469bb5fa7SEdward Cree list_del(&skb->list); 34569bb5fa7SEdward Cree list_add_tail(&skb->list, &head); 34669bb5fa7SEdward Cree spent++; 34769bb5fa7SEdward Cree } 34869bb5fa7SEdward Cree spin_unlock_bh(&efv->rx_lock); 34969bb5fa7SEdward Cree /* Receive them */ 35069bb5fa7SEdward Cree netif_receive_skb_list(&head); 35169bb5fa7SEdward Cree if (spent < weight) 35269bb5fa7SEdward Cree if (napi_complete_done(napi, spent)) { 35369bb5fa7SEdward Cree spin_lock_bh(&efv->rx_lock); 35469bb5fa7SEdward Cree efv->read_index = read_index; 35569bb5fa7SEdward Cree /* If write_index advanced while we were doing the 35669bb5fa7SEdward Cree * RX, then storing our read_index won't re-prime the 35769bb5fa7SEdward Cree * fake-interrupt. In that case, we need to schedule 35869bb5fa7SEdward Cree * NAPI again to consume the additional packet(s). 35969bb5fa7SEdward Cree */ 36069bb5fa7SEdward Cree need_resched = efv->write_index != read_index; 36169bb5fa7SEdward Cree spin_unlock_bh(&efv->rx_lock); 36269bb5fa7SEdward Cree if (need_resched) 36369bb5fa7SEdward Cree napi_schedule(&efv->napi); 36469bb5fa7SEdward Cree } 36569bb5fa7SEdward Cree return spent; 36669bb5fa7SEdward Cree } 3679fe00c80SEdward Cree 3689fe00c80SEdward Cree void efx_ef100_rep_rx_packet(struct efx_rep *efv, struct efx_rx_buffer *rx_buf) 3699fe00c80SEdward Cree { 3709fe00c80SEdward Cree u8 *eh = efx_rx_buf_va(rx_buf); 3719fe00c80SEdward Cree struct sk_buff *skb; 3729fe00c80SEdward Cree bool primed; 3739fe00c80SEdward Cree 3749fe00c80SEdward Cree /* Don't allow too many queued SKBs to build up, as they consume 3759fe00c80SEdward Cree * GFP_ATOMIC memory. If we overrun, just start dropping. 3769fe00c80SEdward Cree */ 3779fe00c80SEdward Cree if (efv->write_index - READ_ONCE(efv->read_index) > efv->rx_pring_size) { 3789fe00c80SEdward Cree atomic64_inc(&efv->stats.rx_dropped); 3799fe00c80SEdward Cree if (net_ratelimit()) 3809fe00c80SEdward Cree netif_dbg(efv->parent, rx_err, efv->net_dev, 3819fe00c80SEdward Cree "nodesc-dropped packet of length %u\n", 3829fe00c80SEdward Cree rx_buf->len); 3839fe00c80SEdward Cree return; 3849fe00c80SEdward Cree } 3859fe00c80SEdward Cree 3869fe00c80SEdward Cree skb = netdev_alloc_skb(efv->net_dev, rx_buf->len); 3879fe00c80SEdward Cree if (!skb) { 3889fe00c80SEdward Cree atomic64_inc(&efv->stats.rx_dropped); 3899fe00c80SEdward Cree if (net_ratelimit()) 3909fe00c80SEdward Cree netif_dbg(efv->parent, rx_err, efv->net_dev, 3919fe00c80SEdward Cree "noskb-dropped packet of length %u\n", 3929fe00c80SEdward Cree rx_buf->len); 3939fe00c80SEdward Cree return; 3949fe00c80SEdward Cree } 3959fe00c80SEdward Cree memcpy(skb->data, eh, rx_buf->len); 3969fe00c80SEdward Cree __skb_put(skb, rx_buf->len); 3979fe00c80SEdward Cree 3989fe00c80SEdward Cree skb_record_rx_queue(skb, 0); /* rep is single-queue */ 3999fe00c80SEdward Cree 4009fe00c80SEdward Cree /* Move past the ethernet header */ 4019fe00c80SEdward Cree skb->protocol = eth_type_trans(skb, efv->net_dev); 4029fe00c80SEdward Cree 4039fe00c80SEdward Cree skb_checksum_none_assert(skb); 4049fe00c80SEdward Cree 4059fe00c80SEdward Cree atomic64_inc(&efv->stats.rx_packets); 4069fe00c80SEdward Cree atomic64_add(rx_buf->len, &efv->stats.rx_bytes); 4079fe00c80SEdward Cree 4089fe00c80SEdward Cree /* Add it to the rx list */ 4099fe00c80SEdward Cree spin_lock_bh(&efv->rx_lock); 4109fe00c80SEdward Cree primed = efv->read_index == efv->write_index; 4119fe00c80SEdward Cree list_add_tail(&skb->list, &efv->rx_list); 4129fe00c80SEdward Cree efv->write_index++; 4139fe00c80SEdward Cree spin_unlock_bh(&efv->rx_lock); 4149fe00c80SEdward Cree /* Trigger rx work */ 4159fe00c80SEdward Cree if (primed) 4169fe00c80SEdward Cree napi_schedule(&efv->napi); 4179fe00c80SEdward Cree } 418f50e8fcdSEdward Cree 419f50e8fcdSEdward Cree struct efx_rep *efx_ef100_find_rep_by_mport(struct efx_nic *efx, u16 mport) 420f50e8fcdSEdward Cree { 421f50e8fcdSEdward Cree struct efx_rep *efv, *out = NULL; 422f50e8fcdSEdward Cree 423f50e8fcdSEdward Cree /* spinlock guards against list mutation while we're walking it; 424f50e8fcdSEdward Cree * but caller must also hold rcu_read_lock() to ensure the netdev 425f50e8fcdSEdward Cree * isn't freed after we drop the spinlock. 426f50e8fcdSEdward Cree */ 427f50e8fcdSEdward Cree spin_lock_bh(&efx->vf_reps_lock); 428f50e8fcdSEdward Cree list_for_each_entry(efv, &efx->vf_reps, list) 429f50e8fcdSEdward Cree if (efv->mport == mport) { 430f50e8fcdSEdward Cree out = efv; 431f50e8fcdSEdward Cree break; 432f50e8fcdSEdward Cree } 433f50e8fcdSEdward Cree spin_unlock_bh(&efx->vf_reps_lock); 434f50e8fcdSEdward Cree return out; 435f50e8fcdSEdward Cree } 436