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