diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/enic/enic.h | 1 | ||||
-rw-r--r-- | drivers/net/enic/enic_main.c | 79 |
2 files changed, 57 insertions, 23 deletions
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index bd473a9d739a..577067eef652 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h | |||
@@ -62,6 +62,7 @@ struct enic_port_profile { | |||
62 | u8 instance_uuid[PORT_UUID_MAX]; | 62 | u8 instance_uuid[PORT_UUID_MAX]; |
63 | u8 host_uuid[PORT_UUID_MAX]; | 63 | u8 host_uuid[PORT_UUID_MAX]; |
64 | u8 vf_mac[ETH_ALEN]; | 64 | u8 vf_mac[ETH_ALEN]; |
65 | u8 mac_addr[ETH_ALEN]; | ||
65 | }; | 66 | }; |
66 | 67 | ||
67 | /* Per-instance private data structure */ | 68 | /* Per-instance private data structure */ |
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index ddeffb5192ae..21be989e6a14 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c | |||
@@ -1278,9 +1278,14 @@ static int enic_set_port_profile(struct enic *enic, u8 *mac) | |||
1278 | VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR, | 1278 | VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR, |
1279 | strlen(enic->pp.name) + 1, enic->pp.name); | 1279 | strlen(enic->pp.name) + 1, enic->pp.name); |
1280 | 1280 | ||
1281 | vic_provinfo_add_tlv(vp, | 1281 | if (!is_zero_ether_addr(enic->pp.mac_addr)) |
1282 | VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR, | 1282 | vic_provinfo_add_tlv(vp, |
1283 | ETH_ALEN, mac); | 1283 | VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR, |
1284 | ETH_ALEN, enic->pp.mac_addr); | ||
1285 | else | ||
1286 | vic_provinfo_add_tlv(vp, | ||
1287 | VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR, | ||
1288 | ETH_ALEN, mac); | ||
1284 | 1289 | ||
1285 | if (enic->pp.set & ENIC_SET_INSTANCE) { | 1290 | if (enic->pp.set & ENIC_SET_INSTANCE) { |
1286 | sprintf(uuid_str, "%pUB", enic->pp.instance_uuid); | 1291 | sprintf(uuid_str, "%pUB", enic->pp.instance_uuid); |
@@ -1300,16 +1305,18 @@ static int enic_set_port_profile(struct enic *enic, u8 *mac) | |||
1300 | vic_provinfo_free(vp); | 1305 | vic_provinfo_free(vp); |
1301 | if (err) | 1306 | if (err) |
1302 | return err; | 1307 | return err; |
1308 | |||
1309 | enic->pp.set |= ENIC_SET_APPLIED; | ||
1303 | break; | 1310 | break; |
1304 | 1311 | ||
1305 | case PORT_REQUEST_DISASSOCIATE: | 1312 | case PORT_REQUEST_DISASSOCIATE: |
1313 | enic->pp.set &= ~ENIC_SET_APPLIED; | ||
1306 | break; | 1314 | break; |
1307 | 1315 | ||
1308 | default: | 1316 | default: |
1309 | return -EINVAL; | 1317 | return -EINVAL; |
1310 | } | 1318 | } |
1311 | 1319 | ||
1312 | enic->pp.set |= ENIC_SET_APPLIED; | ||
1313 | return 0; | 1320 | return 0; |
1314 | } | 1321 | } |
1315 | 1322 | ||
@@ -1317,29 +1324,31 @@ static int enic_set_vf_port(struct net_device *netdev, int vf, | |||
1317 | struct nlattr *port[]) | 1324 | struct nlattr *port[]) |
1318 | { | 1325 | { |
1319 | struct enic *enic = netdev_priv(netdev); | 1326 | struct enic *enic = netdev_priv(netdev); |
1327 | struct enic_port_profile new_pp; | ||
1328 | int err = 0; | ||
1320 | 1329 | ||
1321 | memset(&enic->pp, 0, sizeof(enic->pp)); | 1330 | memset(&new_pp, 0, sizeof(new_pp)); |
1322 | 1331 | ||
1323 | if (port[IFLA_PORT_REQUEST]) { | 1332 | if (port[IFLA_PORT_REQUEST]) { |
1324 | enic->pp.set |= ENIC_SET_REQUEST; | 1333 | new_pp.set |= ENIC_SET_REQUEST; |
1325 | enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]); | 1334 | new_pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]); |
1326 | } | 1335 | } |
1327 | 1336 | ||
1328 | if (port[IFLA_PORT_PROFILE]) { | 1337 | if (port[IFLA_PORT_PROFILE]) { |
1329 | enic->pp.set |= ENIC_SET_NAME; | 1338 | new_pp.set |= ENIC_SET_NAME; |
1330 | memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]), | 1339 | memcpy(new_pp.name, nla_data(port[IFLA_PORT_PROFILE]), |
1331 | PORT_PROFILE_MAX); | 1340 | PORT_PROFILE_MAX); |
1332 | } | 1341 | } |
1333 | 1342 | ||
1334 | if (port[IFLA_PORT_INSTANCE_UUID]) { | 1343 | if (port[IFLA_PORT_INSTANCE_UUID]) { |
1335 | enic->pp.set |= ENIC_SET_INSTANCE; | 1344 | new_pp.set |= ENIC_SET_INSTANCE; |
1336 | memcpy(enic->pp.instance_uuid, | 1345 | memcpy(new_pp.instance_uuid, |
1337 | nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX); | 1346 | nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX); |
1338 | } | 1347 | } |
1339 | 1348 | ||
1340 | if (port[IFLA_PORT_HOST_UUID]) { | 1349 | if (port[IFLA_PORT_HOST_UUID]) { |
1341 | enic->pp.set |= ENIC_SET_HOST; | 1350 | new_pp.set |= ENIC_SET_HOST; |
1342 | memcpy(enic->pp.host_uuid, | 1351 | memcpy(new_pp.host_uuid, |
1343 | nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX); | 1352 | nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX); |
1344 | } | 1353 | } |
1345 | 1354 | ||
@@ -1347,21 +1356,39 @@ static int enic_set_vf_port(struct net_device *netdev, int vf, | |||
1347 | if (vf != PORT_SELF_VF) | 1356 | if (vf != PORT_SELF_VF) |
1348 | return -EOPNOTSUPP; | 1357 | return -EOPNOTSUPP; |
1349 | 1358 | ||
1350 | if (!(enic->pp.set & ENIC_SET_REQUEST)) | 1359 | if (!(new_pp.set & ENIC_SET_REQUEST)) |
1351 | return -EOPNOTSUPP; | 1360 | return -EOPNOTSUPP; |
1352 | 1361 | ||
1353 | if (enic->pp.request == PORT_REQUEST_ASSOCIATE) { | 1362 | if (new_pp.request == PORT_REQUEST_ASSOCIATE) { |
1354 | 1363 | /* Special case handling */ | |
1355 | /* If the interface mac addr hasn't been assigned, | 1364 | if (!is_zero_ether_addr(enic->pp.vf_mac)) |
1356 | * assign a random mac addr before setting port- | 1365 | memcpy(new_pp.mac_addr, enic->pp.vf_mac, ETH_ALEN); |
1357 | * profile. | ||
1358 | */ | ||
1359 | 1366 | ||
1360 | if (is_zero_ether_addr(netdev->dev_addr)) | 1367 | if (is_zero_ether_addr(netdev->dev_addr)) |
1361 | random_ether_addr(netdev->dev_addr); | 1368 | random_ether_addr(netdev->dev_addr); |
1369 | } else if (new_pp.request == PORT_REQUEST_DISASSOCIATE) { | ||
1370 | if (!is_zero_ether_addr(enic->pp.mac_addr)) | ||
1371 | enic_dev_del_addr(enic, enic->pp.mac_addr); | ||
1362 | } | 1372 | } |
1363 | 1373 | ||
1364 | return enic_set_port_profile(enic, netdev->dev_addr); | 1374 | memcpy(&enic->pp, &new_pp, sizeof(struct enic_port_profile)); |
1375 | |||
1376 | err = enic_set_port_profile(enic, netdev->dev_addr); | ||
1377 | if (err) | ||
1378 | goto set_port_profile_cleanup; | ||
1379 | |||
1380 | if (!is_zero_ether_addr(enic->pp.mac_addr)) | ||
1381 | enic_dev_add_addr(enic, enic->pp.mac_addr); | ||
1382 | |||
1383 | set_port_profile_cleanup: | ||
1384 | memset(enic->pp.vf_mac, 0, ETH_ALEN); | ||
1385 | |||
1386 | if (err || enic->pp.request == PORT_REQUEST_DISASSOCIATE) { | ||
1387 | memset(netdev->dev_addr, 0, ETH_ALEN); | ||
1388 | memset(enic->pp.mac_addr, 0, ETH_ALEN); | ||
1389 | } | ||
1390 | |||
1391 | return err; | ||
1365 | } | 1392 | } |
1366 | 1393 | ||
1367 | static int enic_get_vf_port(struct net_device *netdev, int vf, | 1394 | static int enic_get_vf_port(struct net_device *netdev, int vf, |
@@ -1941,7 +1968,10 @@ static int enic_open(struct net_device *netdev) | |||
1941 | for (i = 0; i < enic->rq_count; i++) | 1968 | for (i = 0; i < enic->rq_count; i++) |
1942 | vnic_rq_enable(&enic->rq[i]); | 1969 | vnic_rq_enable(&enic->rq[i]); |
1943 | 1970 | ||
1944 | enic_dev_add_station_addr(enic); | 1971 | if (enic_is_dynamic(enic) && !is_zero_ether_addr(enic->pp.mac_addr)) |
1972 | enic_dev_add_addr(enic, enic->pp.mac_addr); | ||
1973 | else | ||
1974 | enic_dev_add_station_addr(enic); | ||
1945 | enic_set_rx_mode(netdev); | 1975 | enic_set_rx_mode(netdev); |
1946 | 1976 | ||
1947 | netif_wake_queue(netdev); | 1977 | netif_wake_queue(netdev); |
@@ -1989,7 +2019,10 @@ static int enic_stop(struct net_device *netdev) | |||
1989 | 2019 | ||
1990 | netif_carrier_off(netdev); | 2020 | netif_carrier_off(netdev); |
1991 | netif_tx_disable(netdev); | 2021 | netif_tx_disable(netdev); |
1992 | enic_dev_del_station_addr(enic); | 2022 | if (enic_is_dynamic(enic) && !is_zero_ether_addr(enic->pp.mac_addr)) |
2023 | enic_dev_del_addr(enic, enic->pp.mac_addr); | ||
2024 | else | ||
2025 | enic_dev_del_station_addr(enic); | ||
1993 | 2026 | ||
1994 | for (i = 0; i < enic->wq_count; i++) { | 2027 | for (i = 0; i < enic->wq_count; i++) { |
1995 | err = vnic_wq_disable(&enic->wq[i]); | 2028 | err = vnic_wq_disable(&enic->wq[i]); |