0001
0002
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
0145
0146
0147
0148
0149
0150
0151
0152
0153
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
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 }