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" 1308135eecSEdward Cree #include "ef100_nic.h" 14*da56552dSEdward Cree #include "mae.h" 1508135eecSEdward Cree 165687eb34SEdward Cree #define EFX_EF100_REP_DRIVER "efx_ef100_rep" 175687eb34SEdward Cree 18e1479556SEdward Cree static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv, 19e1479556SEdward Cree unsigned int i) 2008135eecSEdward Cree { 2108135eecSEdward Cree efv->parent = efx; 22e1479556SEdward Cree efv->idx = i; 2308135eecSEdward Cree INIT_LIST_HEAD(&efv->list); 2408135eecSEdward Cree efv->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE | 2508135eecSEdward Cree NETIF_MSG_LINK | NETIF_MSG_IFDOWN | 2608135eecSEdward Cree NETIF_MSG_IFUP | NETIF_MSG_RX_ERR | 2708135eecSEdward Cree NETIF_MSG_TX_ERR | NETIF_MSG_HW; 2808135eecSEdward Cree return 0; 2908135eecSEdward Cree } 3008135eecSEdward Cree 31e1479556SEdward Cree static int efx_ef100_rep_get_port_parent_id(struct net_device *dev, 32e1479556SEdward Cree struct netdev_phys_item_id *ppid) 33e1479556SEdward Cree { 34e1479556SEdward Cree struct efx_rep *efv = netdev_priv(dev); 35e1479556SEdward Cree struct efx_nic *efx = efv->parent; 36e1479556SEdward Cree struct ef100_nic_data *nic_data; 37e1479556SEdward Cree 38e1479556SEdward Cree nic_data = efx->nic_data; 39e1479556SEdward Cree /* nic_data->port_id is a u8[] */ 40e1479556SEdward Cree ppid->id_len = sizeof(nic_data->port_id); 41e1479556SEdward Cree memcpy(ppid->id, nic_data->port_id, sizeof(nic_data->port_id)); 42e1479556SEdward Cree return 0; 43e1479556SEdward Cree } 44e1479556SEdward Cree 45e1479556SEdward Cree static int efx_ef100_rep_get_phys_port_name(struct net_device *dev, 46e1479556SEdward Cree char *buf, size_t len) 47e1479556SEdward Cree { 48e1479556SEdward Cree struct efx_rep *efv = netdev_priv(dev); 49e1479556SEdward Cree struct efx_nic *efx = efv->parent; 50e1479556SEdward Cree struct ef100_nic_data *nic_data; 51e1479556SEdward Cree int ret; 52e1479556SEdward Cree 53e1479556SEdward Cree nic_data = efx->nic_data; 54e1479556SEdward Cree ret = snprintf(buf, len, "p%upf%uvf%u", efx->port_num, 55e1479556SEdward Cree nic_data->pf_index, efv->idx); 56e1479556SEdward Cree if (ret >= len) 57e1479556SEdward Cree return -EOPNOTSUPP; 58e1479556SEdward Cree 59e1479556SEdward Cree return 0; 60e1479556SEdward Cree } 61e1479556SEdward Cree 6208135eecSEdward Cree static const struct net_device_ops efx_ef100_rep_netdev_ops = { 63e1479556SEdward Cree .ndo_get_port_parent_id = efx_ef100_rep_get_port_parent_id, 64e1479556SEdward Cree .ndo_get_phys_port_name = efx_ef100_rep_get_phys_port_name, 6508135eecSEdward Cree }; 6608135eecSEdward Cree 675687eb34SEdward Cree static void efx_ef100_rep_get_drvinfo(struct net_device *dev, 685687eb34SEdward Cree struct ethtool_drvinfo *drvinfo) 695687eb34SEdward Cree { 705687eb34SEdward Cree strscpy(drvinfo->driver, EFX_EF100_REP_DRIVER, sizeof(drvinfo->driver)); 715687eb34SEdward Cree } 725687eb34SEdward Cree 735687eb34SEdward Cree static u32 efx_ef100_rep_ethtool_get_msglevel(struct net_device *net_dev) 745687eb34SEdward Cree { 755687eb34SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 765687eb34SEdward Cree 775687eb34SEdward Cree return efv->msg_enable; 785687eb34SEdward Cree } 795687eb34SEdward Cree 805687eb34SEdward Cree static void efx_ef100_rep_ethtool_set_msglevel(struct net_device *net_dev, 815687eb34SEdward Cree u32 msg_enable) 825687eb34SEdward Cree { 835687eb34SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 845687eb34SEdward Cree 855687eb34SEdward Cree efv->msg_enable = msg_enable; 865687eb34SEdward Cree } 875687eb34SEdward Cree 8808135eecSEdward Cree static const struct ethtool_ops efx_ef100_rep_ethtool_ops = { 895687eb34SEdward Cree .get_drvinfo = efx_ef100_rep_get_drvinfo, 905687eb34SEdward Cree .get_msglevel = efx_ef100_rep_ethtool_get_msglevel, 915687eb34SEdward Cree .set_msglevel = efx_ef100_rep_ethtool_set_msglevel, 9208135eecSEdward Cree }; 9308135eecSEdward Cree 9408135eecSEdward Cree static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx, 9508135eecSEdward Cree unsigned int i) 9608135eecSEdward Cree { 9708135eecSEdward Cree struct net_device *net_dev; 9808135eecSEdward Cree struct efx_rep *efv; 9908135eecSEdward Cree int rc; 10008135eecSEdward Cree 10108135eecSEdward Cree net_dev = alloc_etherdev_mq(sizeof(*efv), 1); 10208135eecSEdward Cree if (!net_dev) 10308135eecSEdward Cree return ERR_PTR(-ENOMEM); 10408135eecSEdward Cree 10508135eecSEdward Cree efv = netdev_priv(net_dev); 106e1479556SEdward Cree rc = efx_ef100_rep_init_struct(efx, efv, i); 10708135eecSEdward Cree if (rc) 10808135eecSEdward Cree goto fail1; 10908135eecSEdward Cree efv->net_dev = net_dev; 11008135eecSEdward Cree rtnl_lock(); 11108135eecSEdward Cree spin_lock_bh(&efx->vf_reps_lock); 11208135eecSEdward Cree list_add_tail(&efv->list, &efx->vf_reps); 11308135eecSEdward Cree spin_unlock_bh(&efx->vf_reps_lock); 11408135eecSEdward Cree netif_carrier_off(net_dev); 11508135eecSEdward Cree netif_tx_stop_all_queues(net_dev); 11608135eecSEdward Cree rtnl_unlock(); 11708135eecSEdward Cree 11808135eecSEdward Cree net_dev->netdev_ops = &efx_ef100_rep_netdev_ops; 11908135eecSEdward Cree net_dev->ethtool_ops = &efx_ef100_rep_ethtool_ops; 12008135eecSEdward Cree net_dev->min_mtu = EFX_MIN_MTU; 12108135eecSEdward Cree net_dev->max_mtu = EFX_MAX_MTU; 12208135eecSEdward Cree return efv; 12308135eecSEdward Cree fail1: 12408135eecSEdward Cree free_netdev(net_dev); 12508135eecSEdward Cree return ERR_PTR(rc); 12608135eecSEdward Cree } 12708135eecSEdward Cree 128*da56552dSEdward Cree static int efx_ef100_configure_rep(struct efx_rep *efv) 129*da56552dSEdward Cree { 130*da56552dSEdward Cree struct efx_nic *efx = efv->parent; 131*da56552dSEdward Cree u32 selector; 132*da56552dSEdward Cree int rc; 133*da56552dSEdward Cree 134*da56552dSEdward Cree /* Construct mport selector for corresponding VF */ 135*da56552dSEdward Cree efx_mae_mport_vf(efx, efv->idx, &selector); 136*da56552dSEdward Cree /* Look up actual mport ID */ 137*da56552dSEdward Cree rc = efx_mae_lookup_mport(efx, selector, &efv->mport); 138*da56552dSEdward Cree if (rc) 139*da56552dSEdward Cree return rc; 140*da56552dSEdward Cree pci_dbg(efx->pci_dev, "VF %u has mport ID %#x\n", efv->idx, efv->mport); 141*da56552dSEdward Cree /* mport label should fit in 16 bits */ 142*da56552dSEdward Cree WARN_ON(efv->mport >> 16); 143*da56552dSEdward Cree 144*da56552dSEdward Cree return 0; 145*da56552dSEdward Cree } 146*da56552dSEdward Cree 14708135eecSEdward Cree static void efx_ef100_rep_destroy_netdev(struct efx_rep *efv) 14808135eecSEdward Cree { 14908135eecSEdward Cree struct efx_nic *efx = efv->parent; 15008135eecSEdward Cree 15108135eecSEdward Cree spin_lock_bh(&efx->vf_reps_lock); 15208135eecSEdward Cree list_del(&efv->list); 15308135eecSEdward Cree spin_unlock_bh(&efx->vf_reps_lock); 15408135eecSEdward Cree free_netdev(efv->net_dev); 15508135eecSEdward Cree } 15608135eecSEdward Cree 15708135eecSEdward Cree int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i) 15808135eecSEdward Cree { 15908135eecSEdward Cree struct efx_rep *efv; 16008135eecSEdward Cree int rc; 16108135eecSEdward Cree 16208135eecSEdward Cree efv = efx_ef100_rep_create_netdev(efx, i); 16308135eecSEdward Cree if (IS_ERR(efv)) { 16408135eecSEdward Cree rc = PTR_ERR(efv); 16508135eecSEdward Cree pci_err(efx->pci_dev, 16608135eecSEdward Cree "Failed to create representor for VF %d, rc %d\n", i, 16708135eecSEdward Cree rc); 16808135eecSEdward Cree return rc; 16908135eecSEdward Cree } 170*da56552dSEdward Cree rc = efx_ef100_configure_rep(efv); 171*da56552dSEdward Cree if (rc) { 172*da56552dSEdward Cree pci_err(efx->pci_dev, 173*da56552dSEdward Cree "Failed to configure representor for VF %d, rc %d\n", 174*da56552dSEdward Cree i, rc); 175*da56552dSEdward Cree goto fail; 176*da56552dSEdward Cree } 17708135eecSEdward Cree rc = register_netdev(efv->net_dev); 17808135eecSEdward Cree if (rc) { 17908135eecSEdward Cree pci_err(efx->pci_dev, 18008135eecSEdward Cree "Failed to register representor for VF %d, rc %d\n", 18108135eecSEdward Cree i, rc); 18208135eecSEdward Cree goto fail; 18308135eecSEdward Cree } 18408135eecSEdward Cree pci_dbg(efx->pci_dev, "Representor for VF %d is %s\n", i, 18508135eecSEdward Cree efv->net_dev->name); 18608135eecSEdward Cree return 0; 18708135eecSEdward Cree fail: 18808135eecSEdward Cree efx_ef100_rep_destroy_netdev(efv); 18908135eecSEdward Cree return rc; 19008135eecSEdward Cree } 19108135eecSEdward Cree 19208135eecSEdward Cree void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv) 19308135eecSEdward Cree { 19408135eecSEdward Cree struct net_device *rep_dev; 19508135eecSEdward Cree 19608135eecSEdward Cree rep_dev = efv->net_dev; 19708135eecSEdward Cree if (!rep_dev) 19808135eecSEdward Cree return; 19908135eecSEdward Cree netif_dbg(efx, drv, rep_dev, "Removing VF representor\n"); 20008135eecSEdward Cree unregister_netdev(rep_dev); 20108135eecSEdward Cree efx_ef100_rep_destroy_netdev(efv); 20208135eecSEdward Cree } 20308135eecSEdward Cree 20408135eecSEdward Cree void efx_ef100_fini_vfreps(struct efx_nic *efx) 20508135eecSEdward Cree { 20608135eecSEdward Cree struct ef100_nic_data *nic_data = efx->nic_data; 20708135eecSEdward Cree struct efx_rep *efv, *next; 20808135eecSEdward Cree 20908135eecSEdward Cree if (!nic_data->grp_mae) 21008135eecSEdward Cree return; 21108135eecSEdward Cree 21208135eecSEdward Cree list_for_each_entry_safe(efv, next, &efx->vf_reps, list) 21308135eecSEdward Cree efx_ef100_vfrep_destroy(efx, efv); 21408135eecSEdward Cree } 215