1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright 2011 Cisco Systems, Inc. All rights reserved. 3 4 #include <linux/kernel.h> 5 #include <linux/string.h> 6 #include <linux/errno.h> 7 #include <linux/types.h> 8 #include <linux/netdevice.h> 9 #include <linux/etherdevice.h> 10 #include <linux/rtnetlink.h> 11 #include <net/ip.h> 12 13 #include "vnic_vic.h" 14 #include "enic_res.h" 15 #include "enic.h" 16 #include "enic_dev.h" 17 #include "enic_pp.h" 18 19 /* 20 * Checks validity of vf index that came in 21 * port profile request 22 */ 23 int enic_is_valid_pp_vf(struct enic *enic, int vf, int *err) 24 { 25 if (vf != PORT_SELF_VF) { 26 #ifdef CONFIG_PCI_IOV 27 if (enic_sriov_enabled(enic)) { 28 if (vf < 0 || vf >= enic->num_vfs) { 29 *err = -EINVAL; 30 goto err_out; 31 } 32 } else { 33 *err = -EOPNOTSUPP; 34 goto err_out; 35 } 36 #else 37 *err = -EOPNOTSUPP; 38 goto err_out; 39 #endif 40 } 41 42 if (vf == PORT_SELF_VF && !enic_is_dynamic(enic)) { 43 *err = -EOPNOTSUPP; 44 goto err_out; 45 } 46 47 *err = 0; 48 return 1; 49 50 err_out: 51 return 0; 52 } 53 54 static int enic_set_port_profile(struct enic *enic, int vf) 55 { 56 struct net_device *netdev = enic->netdev; 57 struct enic_port_profile *pp; 58 struct vic_provinfo *vp; 59 const u8 oui[3] = VIC_PROVINFO_CISCO_OUI; 60 const __be16 os_type = htons(VIC_GENERIC_PROV_OS_TYPE_LINUX); 61 const u8 *client_mac; 62 char uuid_str[38]; 63 char client_mac_str[18]; 64 int err; 65 66 ENIC_PP_BY_INDEX(enic, vf, pp, &err); 67 if (err) 68 return err; 69 70 if (!(pp->set & ENIC_SET_NAME) || !strlen(pp->name)) 71 return -EINVAL; 72 73 vp = vic_provinfo_alloc(GFP_KERNEL, oui, 74 VIC_PROVINFO_GENERIC_TYPE); 75 if (!vp) 76 return -ENOMEM; 77 78 VIC_PROVINFO_ADD_TLV(vp, 79 VIC_GENERIC_PROV_TLV_PORT_PROFILE_NAME_STR, 80 strlen(pp->name) + 1, pp->name); 81 82 if (!is_zero_ether_addr(pp->mac_addr)) { 83 client_mac = pp->mac_addr; 84 } else if (vf == PORT_SELF_VF) { 85 client_mac = netdev->dev_addr; 86 } else { 87 netdev_err(netdev, "Cannot find pp mac address " 88 "for VF %d\n", vf); 89 err = -EINVAL; 90 goto add_tlv_failure; 91 } 92 93 VIC_PROVINFO_ADD_TLV(vp, 94 VIC_GENERIC_PROV_TLV_CLIENT_MAC_ADDR, 95 ETH_ALEN, client_mac); 96 97 snprintf(client_mac_str, sizeof(client_mac_str), "%pM", client_mac); 98 VIC_PROVINFO_ADD_TLV(vp, 99 VIC_GENERIC_PROV_TLV_CLUSTER_PORT_UUID_STR, 100 sizeof(client_mac_str), client_mac_str); 101 102 if (pp->set & ENIC_SET_INSTANCE) { 103 sprintf(uuid_str, "%pUB", pp->instance_uuid); 104 VIC_PROVINFO_ADD_TLV(vp, 105 VIC_GENERIC_PROV_TLV_CLIENT_UUID_STR, 106 sizeof(uuid_str), uuid_str); 107 } 108 109 if (pp->set & ENIC_SET_HOST) { 110 sprintf(uuid_str, "%pUB", pp->host_uuid); 111 VIC_PROVINFO_ADD_TLV(vp, 112 VIC_GENERIC_PROV_TLV_HOST_UUID_STR, 113 sizeof(uuid_str), uuid_str); 114 } 115 116 VIC_PROVINFO_ADD_TLV(vp, 117 VIC_GENERIC_PROV_TLV_OS_TYPE, 118 sizeof(os_type), &os_type); 119 120 ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_init_prov2, (u8 *)vp, 121 vic_provinfo_size(vp)); 122 err = enic_dev_status_to_errno(err); 123 124 add_tlv_failure: 125 vic_provinfo_free(vp); 126 127 return err; 128 } 129 130 static int enic_unset_port_profile(struct enic *enic, int vf) 131 { 132 int err; 133 134 ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_deinit); 135 if (err) 136 return enic_dev_status_to_errno(err); 137 138 if (vf == PORT_SELF_VF) 139 enic_reset_addr_lists(enic); 140 141 return 0; 142 } 143 144 static int enic_are_pp_different(struct enic_port_profile *pp1, 145 struct enic_port_profile *pp2) 146 { 147 return strcmp(pp1->name, pp2->name) | !!memcmp(pp1->instance_uuid, 148 pp2->instance_uuid, PORT_UUID_MAX) | 149 !!memcmp(pp1->host_uuid, pp2->host_uuid, PORT_UUID_MAX) | 150 !ether_addr_equal(pp1->mac_addr, pp2->mac_addr); 151 } 152 153 static int enic_pp_preassociate(struct enic *enic, int vf, 154 struct enic_port_profile *prev_pp, int *restore_pp); 155 static int enic_pp_disassociate(struct enic *enic, int vf, 156 struct enic_port_profile *prev_pp, int *restore_pp); 157 static int enic_pp_preassociate_rr(struct enic *enic, int vf, 158 struct enic_port_profile *prev_pp, int *restore_pp); 159 static int enic_pp_associate(struct enic *enic, int vf, 160 struct enic_port_profile *prev_pp, int *restore_pp); 161 162 static int (*enic_pp_handlers[])(struct enic *enic, int vf, 163 struct enic_port_profile *prev_state, 164 int *restore_pp) = { 165 [PORT_REQUEST_PREASSOCIATE] = enic_pp_preassociate, 166 [PORT_REQUEST_PREASSOCIATE_RR] = enic_pp_preassociate_rr, 167 [PORT_REQUEST_ASSOCIATE] = enic_pp_associate, 168 [PORT_REQUEST_DISASSOCIATE] = enic_pp_disassociate, 169 }; 170 171 static const int enic_pp_handlers_count = 172 ARRAY_SIZE(enic_pp_handlers); 173 174 static int enic_pp_preassociate(struct enic *enic, int vf, 175 struct enic_port_profile *prev_pp, int *restore_pp) 176 { 177 return -EOPNOTSUPP; 178 } 179 180 static int enic_pp_disassociate(struct enic *enic, int vf, 181 struct enic_port_profile *prev_pp, int *restore_pp) 182 { 183 struct net_device *netdev = enic->netdev; 184 struct enic_port_profile *pp; 185 int err; 186 187 ENIC_PP_BY_INDEX(enic, vf, pp, &err); 188 if (err) 189 return err; 190 191 /* Deregister mac addresses */ 192 if (!is_zero_ether_addr(pp->mac_addr)) 193 ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_del_addr, 194 pp->mac_addr); 195 else if (vf == PORT_SELF_VF && !is_zero_ether_addr(netdev->dev_addr)) 196 ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_del_addr, 197 netdev->dev_addr); 198 199 return enic_unset_port_profile(enic, vf); 200 } 201 202 static int enic_pp_preassociate_rr(struct enic *enic, int vf, 203 struct enic_port_profile *prev_pp, int *restore_pp) 204 { 205 struct enic_port_profile *pp; 206 int err; 207 int active = 0; 208 209 ENIC_PP_BY_INDEX(enic, vf, pp, &err); 210 if (err) 211 return err; 212 213 if (pp->request != PORT_REQUEST_ASSOCIATE) { 214 /* If pre-associate is not part of an associate. 215 We always disassociate first */ 216 err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE](enic, vf, 217 prev_pp, restore_pp); 218 if (err) 219 return err; 220 221 *restore_pp = 0; 222 } 223 224 *restore_pp = 0; 225 226 err = enic_set_port_profile(enic, vf); 227 if (err) 228 return err; 229 230 /* If pre-associate is not part of an associate. */ 231 if (pp->request != PORT_REQUEST_ASSOCIATE) { 232 /* Enable device as standby */ 233 ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_enable2, 234 active); 235 err = enic_dev_status_to_errno(err); 236 } 237 238 return err; 239 } 240 241 static int enic_pp_associate(struct enic *enic, int vf, 242 struct enic_port_profile *prev_pp, int *restore_pp) 243 { 244 struct net_device *netdev = enic->netdev; 245 struct enic_port_profile *pp; 246 int err; 247 int active = 1; 248 249 ENIC_PP_BY_INDEX(enic, vf, pp, &err); 250 if (err) 251 return err; 252 253 /* Check if a pre-associate was called before */ 254 if (prev_pp->request != PORT_REQUEST_PREASSOCIATE_RR || 255 (prev_pp->request == PORT_REQUEST_PREASSOCIATE_RR && 256 enic_are_pp_different(prev_pp, pp))) { 257 err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE]( 258 enic, vf, prev_pp, restore_pp); 259 if (err) 260 return err; 261 262 *restore_pp = 0; 263 } 264 265 err = enic_pp_handlers[PORT_REQUEST_PREASSOCIATE_RR]( 266 enic, vf, prev_pp, restore_pp); 267 if (err) 268 return err; 269 270 *restore_pp = 0; 271 272 /* Enable device as active */ 273 ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_enable2, active); 274 err = enic_dev_status_to_errno(err); 275 if (err) 276 return err; 277 278 /* Register mac address */ 279 if (!is_zero_ether_addr(pp->mac_addr)) 280 ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_add_addr, 281 pp->mac_addr); 282 else if (vf == PORT_SELF_VF && !is_zero_ether_addr(netdev->dev_addr)) 283 ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_add_addr, 284 netdev->dev_addr); 285 286 return 0; 287 } 288 289 int enic_process_set_pp_request(struct enic *enic, int vf, 290 struct enic_port_profile *prev_pp, int *restore_pp) 291 { 292 struct enic_port_profile *pp; 293 int err; 294 295 ENIC_PP_BY_INDEX(enic, vf, pp, &err); 296 if (err) 297 return err; 298 299 if (pp->request >= enic_pp_handlers_count 300 || !enic_pp_handlers[pp->request]) 301 return -EOPNOTSUPP; 302 303 return enic_pp_handlers[pp->request](enic, vf, prev_pp, restore_pp); 304 } 305 306 int enic_process_get_pp_request(struct enic *enic, int vf, 307 int request, u16 *response) 308 { 309 int err, status = ERR_SUCCESS; 310 311 switch (request) { 312 313 case PORT_REQUEST_PREASSOCIATE_RR: 314 case PORT_REQUEST_ASSOCIATE: 315 ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, 316 vnic_dev_enable2_done, &status); 317 break; 318 319 case PORT_REQUEST_DISASSOCIATE: 320 ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, 321 vnic_dev_deinit_done, &status); 322 break; 323 324 default: 325 return -EINVAL; 326 } 327 328 if (err) 329 status = err; 330 331 switch (status) { 332 case ERR_SUCCESS: 333 *response = PORT_PROFILE_RESPONSE_SUCCESS; 334 break; 335 case ERR_EINVAL: 336 *response = PORT_PROFILE_RESPONSE_INVALID; 337 break; 338 case ERR_EBADSTATE: 339 *response = PORT_PROFILE_RESPONSE_BADSTATE; 340 break; 341 case ERR_ENOMEM: 342 *response = PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES; 343 break; 344 case ERR_EINPROGRESS: 345 *response = PORT_PROFILE_RESPONSE_INPROGRESS; 346 break; 347 default: 348 *response = PORT_PROFILE_RESPONSE_ERROR; 349 break; 350 } 351 352 return 0; 353 } 354