1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */ 3 4 #include <linux/lockdep.h> 5 #include <linux/netdevice.h> 6 7 #include "nfpcore/nfp_cpp.h" 8 #include "nfpcore/nfp_nsp.h" 9 #include "nfp_app.h" 10 #include "nfp_main.h" 11 #include "nfp_net.h" 12 #include "nfp_port.h" 13 14 struct nfp_port *nfp_port_from_netdev(struct net_device *netdev) 15 { 16 if (nfp_netdev_is_nfp_net(netdev)) { 17 struct nfp_net *nn = netdev_priv(netdev); 18 19 return nn->port; 20 } 21 22 if (nfp_netdev_is_nfp_repr(netdev)) { 23 struct nfp_repr *repr = netdev_priv(netdev); 24 25 return repr->port; 26 } 27 28 WARN(1, "Unknown netdev type for nfp_port\n"); 29 30 return NULL; 31 } 32 33 int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type, 34 void *type_data) 35 { 36 struct nfp_port *port; 37 38 port = nfp_port_from_netdev(netdev); 39 if (!port) 40 return -EOPNOTSUPP; 41 42 return nfp_app_setup_tc(port->app, netdev, type, type_data); 43 } 44 45 int nfp_port_set_features(struct net_device *netdev, netdev_features_t features) 46 { 47 struct nfp_port *port; 48 49 port = nfp_port_from_netdev(netdev); 50 if (!port) 51 return 0; 52 53 if ((netdev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) && 54 port->tc_offload_cnt) { 55 netdev_err(netdev, "Cannot disable HW TC offload while offloads active\n"); 56 return -EBUSY; 57 } 58 59 return 0; 60 } 61 62 struct nfp_port * 63 nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id) 64 { 65 struct nfp_port *port; 66 67 lockdep_assert_held(&pf->lock); 68 69 if (type != NFP_PORT_PHYS_PORT) 70 return NULL; 71 72 list_for_each_entry(port, &pf->ports, port_list) 73 if (port->eth_id == id) 74 return port; 75 76 return NULL; 77 } 78 79 struct nfp_eth_table_port *__nfp_port_get_eth_port(struct nfp_port *port) 80 { 81 if (!port) 82 return NULL; 83 if (port->type != NFP_PORT_PHYS_PORT) 84 return NULL; 85 86 return port->eth_port; 87 } 88 89 struct nfp_eth_table_port *nfp_port_get_eth_port(struct nfp_port *port) 90 { 91 if (!__nfp_port_get_eth_port(port)) 92 return NULL; 93 94 if (test_bit(NFP_PORT_CHANGED, &port->flags)) 95 if (nfp_net_refresh_eth_port(port)) 96 return NULL; 97 98 return __nfp_port_get_eth_port(port); 99 } 100 101 int 102 nfp_port_get_phys_port_name(struct net_device *netdev, char *name, size_t len) 103 { 104 struct nfp_eth_table_port *eth_port; 105 struct nfp_port *port; 106 int n; 107 108 port = nfp_port_from_netdev(netdev); 109 if (!port) 110 return -EOPNOTSUPP; 111 112 switch (port->type) { 113 case NFP_PORT_PHYS_PORT: 114 eth_port = __nfp_port_get_eth_port(port); 115 if (!eth_port) 116 return -EOPNOTSUPP; 117 118 if (!eth_port->is_split) 119 n = snprintf(name, len, "p%d", eth_port->label_port); 120 else 121 n = snprintf(name, len, "p%ds%d", eth_port->label_port, 122 eth_port->label_subport); 123 break; 124 case NFP_PORT_PF_PORT: 125 if (!port->pf_split) 126 n = snprintf(name, len, "pf%d", port->pf_id); 127 else 128 n = snprintf(name, len, "pf%ds%d", port->pf_id, 129 port->pf_split_id); 130 break; 131 case NFP_PORT_VF_PORT: 132 n = snprintf(name, len, "pf%dvf%d", port->pf_id, port->vf_id); 133 break; 134 default: 135 return -EOPNOTSUPP; 136 } 137 138 if (n >= len) 139 return -EINVAL; 140 141 return 0; 142 } 143 144 /** 145 * nfp_port_configure() - helper to set the interface configured bit 146 * @netdev: net_device instance 147 * @configed: Desired state 148 * 149 * Helper to set the ifup/ifdown state on the PHY only if there is a physical 150 * interface associated with the netdev. 151 * 152 * Return: 153 * 0 - configuration successful (or no change); 154 * -ERRNO - configuration failed. 155 */ 156 int nfp_port_configure(struct net_device *netdev, bool configed) 157 { 158 struct nfp_eth_table_port *eth_port; 159 struct nfp_port *port; 160 int err; 161 162 port = nfp_port_from_netdev(netdev); 163 eth_port = __nfp_port_get_eth_port(port); 164 if (!eth_port) 165 return 0; 166 if (port->eth_forced) 167 return 0; 168 169 err = nfp_eth_set_configured(port->app->cpp, eth_port->index, configed); 170 return err < 0 && err != -EOPNOTSUPP ? err : 0; 171 } 172 173 int nfp_port_init_phy_port(struct nfp_pf *pf, struct nfp_app *app, 174 struct nfp_port *port, unsigned int id) 175 { 176 /* Check if vNIC has external port associated and cfg is OK */ 177 if (!pf->eth_tbl || id >= pf->eth_tbl->count) { 178 nfp_err(app->cpp, 179 "NSP port entries don't match vNICs (no entry %d)\n", 180 id); 181 return -EINVAL; 182 } 183 if (pf->eth_tbl->ports[id].override_changed) { 184 nfp_warn(app->cpp, 185 "Config changed for port #%d, reboot required before port will be operational\n", 186 pf->eth_tbl->ports[id].index); 187 port->type = NFP_PORT_INVALID; 188 return 0; 189 } 190 191 port->eth_port = &pf->eth_tbl->ports[id]; 192 port->eth_id = pf->eth_tbl->ports[id].index; 193 if (pf->mac_stats_mem) 194 port->eth_stats = 195 pf->mac_stats_mem + port->eth_id * NFP_MAC_STATS_SIZE; 196 197 return 0; 198 } 199 200 struct nfp_port * 201 nfp_port_alloc(struct nfp_app *app, enum nfp_port_type type, 202 struct net_device *netdev) 203 { 204 struct nfp_port *port; 205 206 port = kzalloc(sizeof(*port), GFP_KERNEL); 207 if (!port) 208 return ERR_PTR(-ENOMEM); 209 210 port->netdev = netdev; 211 port->type = type; 212 port->app = app; 213 214 list_add_tail(&port->port_list, &app->pf->ports); 215 216 return port; 217 } 218 219 void nfp_port_free(struct nfp_port *port) 220 { 221 if (!port) 222 return; 223 list_del(&port->port_list); 224 kfree(port); 225 } 226