Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
0002 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
0003 
0004 #include <linux/lockdep.h>
0005 #include <linux/netdevice.h>
0006 
0007 #include "nfpcore/nfp_cpp.h"
0008 #include "nfpcore/nfp_nsp.h"
0009 #include "nfp_app.h"
0010 #include "nfp_main.h"
0011 #include "nfp_net.h"
0012 #include "nfp_port.h"
0013 
0014 struct nfp_port *nfp_port_from_netdev(struct net_device *netdev)
0015 {
0016     if (nfp_netdev_is_nfp_net(netdev)) {
0017         struct nfp_net *nn = netdev_priv(netdev);
0018 
0019         return nn->port;
0020     }
0021 
0022     if (nfp_netdev_is_nfp_repr(netdev)) {
0023         struct nfp_repr *repr = netdev_priv(netdev);
0024 
0025         return repr->port;
0026     }
0027 
0028     WARN(1, "Unknown netdev type for nfp_port\n");
0029 
0030     return NULL;
0031 }
0032 
0033 int nfp_port_get_port_parent_id(struct net_device *netdev,
0034                 struct netdev_phys_item_id *ppid)
0035 {
0036     struct nfp_port *port;
0037     const u8 *serial;
0038 
0039     port = nfp_port_from_netdev(netdev);
0040     if (!port)
0041         return -EOPNOTSUPP;
0042 
0043     ppid->id_len = nfp_cpp_serial(port->app->cpp, &serial);
0044     memcpy(&ppid->id, serial, ppid->id_len);
0045 
0046     return 0;
0047 }
0048 
0049 int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type,
0050               void *type_data)
0051 {
0052     struct nfp_port *port;
0053 
0054     port = nfp_port_from_netdev(netdev);
0055     if (!port)
0056         return -EOPNOTSUPP;
0057 
0058     return nfp_app_setup_tc(port->app, netdev, type, type_data);
0059 }
0060 
0061 int nfp_port_set_features(struct net_device *netdev, netdev_features_t features)
0062 {
0063     struct nfp_port *port;
0064 
0065     port = nfp_port_from_netdev(netdev);
0066     if (!port)
0067         return 0;
0068 
0069     if ((netdev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) &&
0070         port->tc_offload_cnt) {
0071         netdev_err(netdev, "Cannot disable HW TC offload while offloads active\n");
0072         return -EBUSY;
0073     }
0074 
0075     return 0;
0076 }
0077 
0078 struct nfp_eth_table_port *__nfp_port_get_eth_port(struct nfp_port *port)
0079 {
0080     if (!port)
0081         return NULL;
0082     if (port->type != NFP_PORT_PHYS_PORT)
0083         return NULL;
0084 
0085     return port->eth_port;
0086 }
0087 
0088 struct nfp_eth_table_port *nfp_port_get_eth_port(struct nfp_port *port)
0089 {
0090     if (!__nfp_port_get_eth_port(port))
0091         return NULL;
0092 
0093     if (test_bit(NFP_PORT_CHANGED, &port->flags))
0094         if (nfp_net_refresh_eth_port(port))
0095             return NULL;
0096 
0097     return __nfp_port_get_eth_port(port);
0098 }
0099 
0100 int
0101 nfp_port_get_phys_port_name(struct net_device *netdev, char *name, size_t len)
0102 {
0103     struct nfp_eth_table_port *eth_port;
0104     struct nfp_port *port;
0105     int n;
0106 
0107     port = nfp_port_from_netdev(netdev);
0108     if (!port)
0109         return -EOPNOTSUPP;
0110 
0111     switch (port->type) {
0112     case NFP_PORT_PHYS_PORT:
0113         eth_port = __nfp_port_get_eth_port(port);
0114         if (!eth_port)
0115             return -EOPNOTSUPP;
0116 
0117         if (!eth_port->is_split)
0118             n = snprintf(name, len, "p%d", eth_port->label_port);
0119         else
0120             n = snprintf(name, len, "p%ds%d", eth_port->label_port,
0121                      eth_port->label_subport);
0122         break;
0123     case NFP_PORT_PF_PORT:
0124         if (!port->pf_split)
0125             n = snprintf(name, len, "pf%d", port->pf_id);
0126         else
0127             n = snprintf(name, len, "pf%ds%d", port->pf_id,
0128                      port->pf_split_id);
0129         break;
0130     case NFP_PORT_VF_PORT:
0131         n = snprintf(name, len, "pf%dvf%d", port->pf_id, port->vf_id);
0132         break;
0133     default:
0134         return -EOPNOTSUPP;
0135     }
0136 
0137     if (n >= len)
0138         return -EINVAL;
0139 
0140     return 0;
0141 }
0142 
0143 /**
0144  * nfp_port_configure() - helper to set the interface configured bit
0145  * @netdev: net_device instance
0146  * @configed:   Desired state
0147  *
0148  * Helper to set the ifup/ifdown state on the PHY only if there is a physical
0149  * interface associated with the netdev.
0150  *
0151  * Return:
0152  * 0 - configuration successful (or no change);
0153  * -ERRNO - configuration failed.
0154  */
0155 int nfp_port_configure(struct net_device *netdev, bool configed)
0156 {
0157     struct nfp_eth_table_port *eth_port;
0158     struct nfp_port *port;
0159     int err;
0160 
0161     port = nfp_port_from_netdev(netdev);
0162     eth_port = __nfp_port_get_eth_port(port);
0163     if (!eth_port)
0164         return 0;
0165     if (port->eth_forced)
0166         return 0;
0167 
0168     err = nfp_eth_set_configured(port->app->cpp, eth_port->index, configed);
0169     return err < 0 && err != -EOPNOTSUPP ? err : 0;
0170 }
0171 
0172 int nfp_port_init_phy_port(struct nfp_pf *pf, struct nfp_app *app,
0173                struct nfp_port *port, unsigned int id)
0174 {
0175     /* Check if vNIC has external port associated and cfg is OK */
0176     if (!pf->eth_tbl || id >= pf->eth_tbl->count) {
0177         nfp_err(app->cpp,
0178             "NSP port entries don't match vNICs (no entry %d)\n",
0179             id);
0180         return -EINVAL;
0181     }
0182     if (pf->eth_tbl->ports[id].override_changed) {
0183         nfp_warn(app->cpp,
0184              "Config changed for port #%d, reboot required before port will be operational\n",
0185              pf->eth_tbl->ports[id].index);
0186         port->type = NFP_PORT_INVALID;
0187         return 0;
0188     }
0189 
0190     port->eth_port = &pf->eth_tbl->ports[id];
0191     port->eth_id = pf->eth_tbl->ports[id].index;
0192     if (pf->mac_stats_mem)
0193         port->eth_stats =
0194             pf->mac_stats_mem + port->eth_id * NFP_MAC_STATS_SIZE;
0195 
0196     return 0;
0197 }
0198 
0199 struct nfp_port *
0200 nfp_port_alloc(struct nfp_app *app, enum nfp_port_type type,
0201            struct net_device *netdev)
0202 {
0203     struct nfp_port *port;
0204 
0205     port = kzalloc(sizeof(*port), GFP_KERNEL);
0206     if (!port)
0207         return ERR_PTR(-ENOMEM);
0208 
0209     port->netdev = netdev;
0210     port->type = type;
0211     port->app = app;
0212 
0213     list_add_tail(&port->port_list, &app->pf->ports);
0214 
0215     return port;
0216 }
0217 
0218 void nfp_port_free(struct nfp_port *port)
0219 {
0220     if (!port)
0221         return;
0222     list_del(&port->port_list);
0223     kfree(port);
0224 }