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 19e1479556SEdward Cree static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv, 20e1479556SEdward Cree unsigned int i) 2108135eecSEdward Cree { 2208135eecSEdward Cree efv->parent = efx; 23e1479556SEdward Cree efv->idx = i; 2408135eecSEdward Cree INIT_LIST_HEAD(&efv->list); 2508135eecSEdward Cree efv->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE | 2608135eecSEdward Cree NETIF_MSG_LINK | NETIF_MSG_IFDOWN | 2708135eecSEdward Cree NETIF_MSG_IFUP | NETIF_MSG_RX_ERR | 2808135eecSEdward Cree NETIF_MSG_TX_ERR | NETIF_MSG_HW; 2908135eecSEdward Cree return 0; 3008135eecSEdward Cree } 3108135eecSEdward Cree 32f72c38faSEdward Cree static netdev_tx_t efx_ef100_rep_xmit(struct sk_buff *skb, 33f72c38faSEdward Cree struct net_device *dev) 34f72c38faSEdward Cree { 35f72c38faSEdward Cree struct efx_rep *efv = netdev_priv(dev); 36f72c38faSEdward Cree struct efx_nic *efx = efv->parent; 37f72c38faSEdward Cree netdev_tx_t rc; 38f72c38faSEdward Cree 39f72c38faSEdward Cree /* __ef100_hard_start_xmit() will always return success even in the 40f72c38faSEdward Cree * case of TX drops, where it will increment efx's tx_dropped. The 41f72c38faSEdward Cree * efv stats really only count attempted TX, not success/failure. 42f72c38faSEdward Cree */ 43f72c38faSEdward Cree atomic64_inc(&efv->stats.tx_packets); 44f72c38faSEdward Cree atomic64_add(skb->len, &efv->stats.tx_bytes); 45f72c38faSEdward Cree netif_tx_lock(efx->net_dev); 46f72c38faSEdward Cree rc = __ef100_hard_start_xmit(skb, efx, dev, efv); 47f72c38faSEdward Cree netif_tx_unlock(efx->net_dev); 48f72c38faSEdward Cree return rc; 49f72c38faSEdward Cree } 50f72c38faSEdward Cree 51e1479556SEdward Cree static int efx_ef100_rep_get_port_parent_id(struct net_device *dev, 52e1479556SEdward Cree struct netdev_phys_item_id *ppid) 53e1479556SEdward Cree { 54e1479556SEdward Cree struct efx_rep *efv = netdev_priv(dev); 55e1479556SEdward Cree struct efx_nic *efx = efv->parent; 56e1479556SEdward Cree struct ef100_nic_data *nic_data; 57e1479556SEdward Cree 58e1479556SEdward Cree nic_data = efx->nic_data; 59e1479556SEdward Cree /* nic_data->port_id is a u8[] */ 60e1479556SEdward Cree ppid->id_len = sizeof(nic_data->port_id); 61e1479556SEdward Cree memcpy(ppid->id, nic_data->port_id, sizeof(nic_data->port_id)); 62e1479556SEdward Cree return 0; 63e1479556SEdward Cree } 64e1479556SEdward Cree 65e1479556SEdward Cree static int efx_ef100_rep_get_phys_port_name(struct net_device *dev, 66e1479556SEdward Cree char *buf, size_t len) 67e1479556SEdward Cree { 68e1479556SEdward Cree struct efx_rep *efv = netdev_priv(dev); 69e1479556SEdward Cree struct efx_nic *efx = efv->parent; 70e1479556SEdward Cree struct ef100_nic_data *nic_data; 71e1479556SEdward Cree int ret; 72e1479556SEdward Cree 73e1479556SEdward Cree nic_data = efx->nic_data; 74e1479556SEdward Cree ret = snprintf(buf, len, "p%upf%uvf%u", efx->port_num, 75e1479556SEdward Cree nic_data->pf_index, efv->idx); 76e1479556SEdward Cree if (ret >= len) 77e1479556SEdward Cree return -EOPNOTSUPP; 78e1479556SEdward Cree 79e1479556SEdward Cree return 0; 80e1479556SEdward Cree } 81e1479556SEdward Cree 82*a95115c4SEdward Cree static void efx_ef100_rep_get_stats64(struct net_device *dev, 83*a95115c4SEdward Cree struct rtnl_link_stats64 *stats) 84*a95115c4SEdward Cree { 85*a95115c4SEdward Cree struct efx_rep *efv = netdev_priv(dev); 86*a95115c4SEdward Cree 87*a95115c4SEdward Cree stats->rx_packets = atomic64_read(&efv->stats.rx_packets); 88*a95115c4SEdward Cree stats->tx_packets = atomic64_read(&efv->stats.tx_packets); 89*a95115c4SEdward Cree stats->rx_bytes = atomic64_read(&efv->stats.rx_bytes); 90*a95115c4SEdward Cree stats->tx_bytes = atomic64_read(&efv->stats.tx_bytes); 91*a95115c4SEdward Cree stats->rx_dropped = atomic64_read(&efv->stats.rx_dropped); 92*a95115c4SEdward Cree stats->tx_errors = atomic64_read(&efv->stats.tx_errors); 93*a95115c4SEdward Cree } 94*a95115c4SEdward Cree 9508135eecSEdward Cree static const struct net_device_ops efx_ef100_rep_netdev_ops = { 96f72c38faSEdward Cree .ndo_start_xmit = efx_ef100_rep_xmit, 97e1479556SEdward Cree .ndo_get_port_parent_id = efx_ef100_rep_get_port_parent_id, 98e1479556SEdward Cree .ndo_get_phys_port_name = efx_ef100_rep_get_phys_port_name, 99*a95115c4SEdward Cree .ndo_get_stats64 = efx_ef100_rep_get_stats64, 10008135eecSEdward Cree }; 10108135eecSEdward Cree 1025687eb34SEdward Cree static void efx_ef100_rep_get_drvinfo(struct net_device *dev, 1035687eb34SEdward Cree struct ethtool_drvinfo *drvinfo) 1045687eb34SEdward Cree { 1055687eb34SEdward Cree strscpy(drvinfo->driver, EFX_EF100_REP_DRIVER, sizeof(drvinfo->driver)); 1065687eb34SEdward Cree } 1075687eb34SEdward Cree 1085687eb34SEdward Cree static u32 efx_ef100_rep_ethtool_get_msglevel(struct net_device *net_dev) 1095687eb34SEdward Cree { 1105687eb34SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 1115687eb34SEdward Cree 1125687eb34SEdward Cree return efv->msg_enable; 1135687eb34SEdward Cree } 1145687eb34SEdward Cree 1155687eb34SEdward Cree static void efx_ef100_rep_ethtool_set_msglevel(struct net_device *net_dev, 1165687eb34SEdward Cree u32 msg_enable) 1175687eb34SEdward Cree { 1185687eb34SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 1195687eb34SEdward Cree 1205687eb34SEdward Cree efv->msg_enable = msg_enable; 1215687eb34SEdward Cree } 1225687eb34SEdward Cree 12308135eecSEdward Cree static const struct ethtool_ops efx_ef100_rep_ethtool_ops = { 1245687eb34SEdward Cree .get_drvinfo = efx_ef100_rep_get_drvinfo, 1255687eb34SEdward Cree .get_msglevel = efx_ef100_rep_ethtool_get_msglevel, 1265687eb34SEdward Cree .set_msglevel = efx_ef100_rep_ethtool_set_msglevel, 12708135eecSEdward Cree }; 12808135eecSEdward Cree 12908135eecSEdward Cree static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx, 13008135eecSEdward Cree unsigned int i) 13108135eecSEdward Cree { 13208135eecSEdward Cree struct net_device *net_dev; 13308135eecSEdward Cree struct efx_rep *efv; 13408135eecSEdward Cree int rc; 13508135eecSEdward Cree 13608135eecSEdward Cree net_dev = alloc_etherdev_mq(sizeof(*efv), 1); 13708135eecSEdward Cree if (!net_dev) 13808135eecSEdward Cree return ERR_PTR(-ENOMEM); 13908135eecSEdward Cree 14008135eecSEdward Cree efv = netdev_priv(net_dev); 141e1479556SEdward Cree rc = efx_ef100_rep_init_struct(efx, efv, i); 14208135eecSEdward Cree if (rc) 14308135eecSEdward Cree goto fail1; 14408135eecSEdward Cree efv->net_dev = net_dev; 14508135eecSEdward Cree rtnl_lock(); 14608135eecSEdward Cree spin_lock_bh(&efx->vf_reps_lock); 14708135eecSEdward Cree list_add_tail(&efv->list, &efx->vf_reps); 14808135eecSEdward Cree spin_unlock_bh(&efx->vf_reps_lock); 14984e7fc25SEdward Cree if (netif_running(efx->net_dev) && efx->state == STATE_NET_UP) { 15084e7fc25SEdward Cree netif_device_attach(net_dev); 15184e7fc25SEdward Cree netif_carrier_on(net_dev); 15284e7fc25SEdward Cree } else { 15308135eecSEdward Cree netif_carrier_off(net_dev); 15408135eecSEdward Cree netif_tx_stop_all_queues(net_dev); 15584e7fc25SEdward Cree } 15608135eecSEdward Cree rtnl_unlock(); 15708135eecSEdward Cree 15808135eecSEdward Cree net_dev->netdev_ops = &efx_ef100_rep_netdev_ops; 15908135eecSEdward Cree net_dev->ethtool_ops = &efx_ef100_rep_ethtool_ops; 16008135eecSEdward Cree net_dev->min_mtu = EFX_MIN_MTU; 16108135eecSEdward Cree net_dev->max_mtu = EFX_MAX_MTU; 162f72c38faSEdward Cree net_dev->features |= NETIF_F_LLTX; 163f72c38faSEdward Cree net_dev->hw_features |= NETIF_F_LLTX; 16408135eecSEdward Cree return efv; 16508135eecSEdward Cree fail1: 16608135eecSEdward Cree free_netdev(net_dev); 16708135eecSEdward Cree return ERR_PTR(rc); 16808135eecSEdward Cree } 16908135eecSEdward Cree 170da56552dSEdward Cree static int efx_ef100_configure_rep(struct efx_rep *efv) 171da56552dSEdward Cree { 172da56552dSEdward Cree struct efx_nic *efx = efv->parent; 173da56552dSEdward Cree u32 selector; 174da56552dSEdward Cree int rc; 175da56552dSEdward Cree 176da56552dSEdward Cree /* Construct mport selector for corresponding VF */ 177da56552dSEdward Cree efx_mae_mport_vf(efx, efv->idx, &selector); 178da56552dSEdward Cree /* Look up actual mport ID */ 179da56552dSEdward Cree rc = efx_mae_lookup_mport(efx, selector, &efv->mport); 180da56552dSEdward Cree if (rc) 181da56552dSEdward Cree return rc; 182da56552dSEdward Cree pci_dbg(efx->pci_dev, "VF %u has mport ID %#x\n", efv->idx, efv->mport); 183da56552dSEdward Cree /* mport label should fit in 16 bits */ 184da56552dSEdward Cree WARN_ON(efv->mport >> 16); 185da56552dSEdward Cree 186da56552dSEdward Cree return 0; 187da56552dSEdward Cree } 188da56552dSEdward Cree 18908135eecSEdward Cree static void efx_ef100_rep_destroy_netdev(struct efx_rep *efv) 19008135eecSEdward Cree { 19108135eecSEdward Cree struct efx_nic *efx = efv->parent; 19208135eecSEdward Cree 19384e7fc25SEdward Cree rtnl_lock(); 19408135eecSEdward Cree spin_lock_bh(&efx->vf_reps_lock); 19508135eecSEdward Cree list_del(&efv->list); 19608135eecSEdward Cree spin_unlock_bh(&efx->vf_reps_lock); 19784e7fc25SEdward Cree rtnl_unlock(); 19808135eecSEdward Cree free_netdev(efv->net_dev); 19908135eecSEdward Cree } 20008135eecSEdward Cree 20108135eecSEdward Cree int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i) 20208135eecSEdward Cree { 20308135eecSEdward Cree struct efx_rep *efv; 20408135eecSEdward Cree int rc; 20508135eecSEdward Cree 20608135eecSEdward Cree efv = efx_ef100_rep_create_netdev(efx, i); 20708135eecSEdward Cree if (IS_ERR(efv)) { 20808135eecSEdward Cree rc = PTR_ERR(efv); 20908135eecSEdward Cree pci_err(efx->pci_dev, 21008135eecSEdward Cree "Failed to create representor for VF %d, rc %d\n", i, 21108135eecSEdward Cree rc); 21208135eecSEdward Cree return rc; 21308135eecSEdward Cree } 214da56552dSEdward Cree rc = efx_ef100_configure_rep(efv); 215da56552dSEdward Cree if (rc) { 216da56552dSEdward Cree pci_err(efx->pci_dev, 217da56552dSEdward Cree "Failed to configure representor for VF %d, rc %d\n", 218da56552dSEdward Cree i, rc); 219da56552dSEdward Cree goto fail; 220da56552dSEdward Cree } 22108135eecSEdward Cree rc = register_netdev(efv->net_dev); 22208135eecSEdward Cree if (rc) { 22308135eecSEdward Cree pci_err(efx->pci_dev, 22408135eecSEdward Cree "Failed to register representor for VF %d, rc %d\n", 22508135eecSEdward Cree i, rc); 22608135eecSEdward Cree goto fail; 22708135eecSEdward Cree } 22808135eecSEdward Cree pci_dbg(efx->pci_dev, "Representor for VF %d is %s\n", i, 22908135eecSEdward Cree efv->net_dev->name); 23008135eecSEdward Cree return 0; 23108135eecSEdward Cree fail: 23208135eecSEdward Cree efx_ef100_rep_destroy_netdev(efv); 23308135eecSEdward Cree return rc; 23408135eecSEdward Cree } 23508135eecSEdward Cree 23608135eecSEdward Cree void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv) 23708135eecSEdward Cree { 23808135eecSEdward Cree struct net_device *rep_dev; 23908135eecSEdward Cree 24008135eecSEdward Cree rep_dev = efv->net_dev; 24108135eecSEdward Cree if (!rep_dev) 24208135eecSEdward Cree return; 24308135eecSEdward Cree netif_dbg(efx, drv, rep_dev, "Removing VF representor\n"); 24408135eecSEdward Cree unregister_netdev(rep_dev); 24508135eecSEdward Cree efx_ef100_rep_destroy_netdev(efv); 24608135eecSEdward Cree } 24708135eecSEdward Cree 24808135eecSEdward Cree void efx_ef100_fini_vfreps(struct efx_nic *efx) 24908135eecSEdward Cree { 25008135eecSEdward Cree struct ef100_nic_data *nic_data = efx->nic_data; 25108135eecSEdward Cree struct efx_rep *efv, *next; 25208135eecSEdward Cree 25308135eecSEdward Cree if (!nic_data->grp_mae) 25408135eecSEdward Cree return; 25508135eecSEdward Cree 25608135eecSEdward Cree list_for_each_entry_safe(efv, next, &efx->vf_reps, list) 25708135eecSEdward Cree efx_ef100_vfrep_destroy(efx, efv); 25808135eecSEdward Cree } 259