diff options
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_main.c | 118 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_pp.c | 192 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_pp.h | 15 |
4 files changed, 232 insertions, 96 deletions
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h index 8c5cfb53b178..fe0c29acdbe6 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h | |||
@@ -96,7 +96,7 @@ struct enic { | |||
96 | #ifdef CONFIG_PCI_IOV | 96 | #ifdef CONFIG_PCI_IOV |
97 | u32 num_vfs; | 97 | u32 num_vfs; |
98 | #endif | 98 | #endif |
99 | struct enic_port_profile pp; | 99 | struct enic_port_profile *pp; |
100 | 100 | ||
101 | /* work queue cache line section */ | 101 | /* work queue cache line section */ |
102 | ____cacheline_aligned struct vnic_wq wq[ENIC_WQ_MAX]; | 102 | ____cacheline_aligned struct vnic_wq wq[ENIC_WQ_MAX]; |
@@ -130,5 +130,6 @@ static inline struct device *enic_get_dev(struct enic *enic) | |||
130 | void enic_reset_addr_lists(struct enic *enic); | 130 | void enic_reset_addr_lists(struct enic *enic); |
131 | int enic_sriov_enabled(struct enic *enic); | 131 | int enic_sriov_enabled(struct enic *enic); |
132 | int enic_is_valid_vf(struct enic *enic, int vf); | 132 | int enic_is_valid_vf(struct enic *enic, int vf); |
133 | int enic_is_dynamic(struct enic *enic); | ||
133 | 134 | ||
134 | #endif /* _ENIC_H_ */ | 135 | #endif /* _ENIC_H_ */ |
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 59ba590c0526..aeab6cd44fcf 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c | |||
@@ -122,7 +122,7 @@ static const struct enic_stat enic_rx_stats[] = { | |||
122 | static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats); | 122 | static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats); |
123 | static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats); | 123 | static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats); |
124 | 124 | ||
125 | static int enic_is_dynamic(struct enic *enic) | 125 | int enic_is_dynamic(struct enic *enic) |
126 | { | 126 | { |
127 | return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN; | 127 | return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN; |
128 | } | 128 | } |
@@ -1054,15 +1054,15 @@ static void enic_tx_timeout(struct net_device *netdev) | |||
1054 | static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) | 1054 | static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) |
1055 | { | 1055 | { |
1056 | struct enic *enic = netdev_priv(netdev); | 1056 | struct enic *enic = netdev_priv(netdev); |
1057 | struct enic_port_profile *pp; | ||
1058 | int err; | ||
1057 | 1059 | ||
1058 | if (vf != PORT_SELF_VF) | 1060 | ENIC_PP_BY_INDEX(enic, vf, pp, &err); |
1059 | return -EOPNOTSUPP; | 1061 | if (err) |
1062 | return err; | ||
1060 | 1063 | ||
1061 | /* Ignore the vf argument for now. We can assume the request | ||
1062 | * is coming on a vf. | ||
1063 | */ | ||
1064 | if (is_valid_ether_addr(mac)) { | 1064 | if (is_valid_ether_addr(mac)) { |
1065 | memcpy(enic->pp.vf_mac, mac, ETH_ALEN); | 1065 | memcpy(pp->vf_mac, mac, ETH_ALEN); |
1066 | return 0; | 1066 | return 0; |
1067 | } else | 1067 | } else |
1068 | return -EINVAL; | 1068 | return -EINVAL; |
@@ -1073,71 +1073,74 @@ static int enic_set_vf_port(struct net_device *netdev, int vf, | |||
1073 | { | 1073 | { |
1074 | struct enic *enic = netdev_priv(netdev); | 1074 | struct enic *enic = netdev_priv(netdev); |
1075 | struct enic_port_profile prev_pp; | 1075 | struct enic_port_profile prev_pp; |
1076 | struct enic_port_profile *pp; | ||
1076 | int err = 0, restore_pp = 1; | 1077 | int err = 0, restore_pp = 1; |
1077 | 1078 | ||
1078 | /* don't support VFs, yet */ | 1079 | ENIC_PP_BY_INDEX(enic, vf, pp, &err); |
1079 | if (vf != PORT_SELF_VF) | 1080 | if (err) |
1080 | return -EOPNOTSUPP; | 1081 | return err; |
1081 | 1082 | ||
1082 | if (!port[IFLA_PORT_REQUEST]) | 1083 | if (!port[IFLA_PORT_REQUEST]) |
1083 | return -EOPNOTSUPP; | 1084 | return -EOPNOTSUPP; |
1084 | 1085 | ||
1085 | memcpy(&prev_pp, &enic->pp, sizeof(enic->pp)); | 1086 | memcpy(&prev_pp, pp, sizeof(*enic->pp)); |
1086 | memset(&enic->pp, 0, sizeof(enic->pp)); | 1087 | memset(pp, 0, sizeof(*enic->pp)); |
1087 | 1088 | ||
1088 | enic->pp.set |= ENIC_SET_REQUEST; | 1089 | pp->set |= ENIC_SET_REQUEST; |
1089 | enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]); | 1090 | pp->request = nla_get_u8(port[IFLA_PORT_REQUEST]); |
1090 | 1091 | ||
1091 | if (port[IFLA_PORT_PROFILE]) { | 1092 | if (port[IFLA_PORT_PROFILE]) { |
1092 | enic->pp.set |= ENIC_SET_NAME; | 1093 | pp->set |= ENIC_SET_NAME; |
1093 | memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]), | 1094 | memcpy(pp->name, nla_data(port[IFLA_PORT_PROFILE]), |
1094 | PORT_PROFILE_MAX); | 1095 | PORT_PROFILE_MAX); |
1095 | } | 1096 | } |
1096 | 1097 | ||
1097 | if (port[IFLA_PORT_INSTANCE_UUID]) { | 1098 | if (port[IFLA_PORT_INSTANCE_UUID]) { |
1098 | enic->pp.set |= ENIC_SET_INSTANCE; | 1099 | pp->set |= ENIC_SET_INSTANCE; |
1099 | memcpy(enic->pp.instance_uuid, | 1100 | memcpy(pp->instance_uuid, |
1100 | nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX); | 1101 | nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX); |
1101 | } | 1102 | } |
1102 | 1103 | ||
1103 | if (port[IFLA_PORT_HOST_UUID]) { | 1104 | if (port[IFLA_PORT_HOST_UUID]) { |
1104 | enic->pp.set |= ENIC_SET_HOST; | 1105 | pp->set |= ENIC_SET_HOST; |
1105 | memcpy(enic->pp.host_uuid, | 1106 | memcpy(pp->host_uuid, |
1106 | nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX); | 1107 | nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX); |
1107 | } | 1108 | } |
1108 | 1109 | ||
1109 | /* Special case handling: mac came from IFLA_VF_MAC */ | 1110 | /* Special case handling: mac came from IFLA_VF_MAC */ |
1110 | if (!is_zero_ether_addr(prev_pp.vf_mac)) | 1111 | if (!is_zero_ether_addr(prev_pp.vf_mac)) |
1111 | memcpy(enic->pp.mac_addr, prev_pp.vf_mac, ETH_ALEN); | 1112 | memcpy(pp->mac_addr, prev_pp.vf_mac, ETH_ALEN); |
1112 | 1113 | ||
1113 | if (is_zero_ether_addr(netdev->dev_addr)) | 1114 | if (vf == PORT_SELF_VF && is_zero_ether_addr(netdev->dev_addr)) |
1114 | random_ether_addr(netdev->dev_addr); | 1115 | random_ether_addr(netdev->dev_addr); |
1115 | 1116 | ||
1116 | err = enic_process_set_pp_request(enic, &prev_pp, &restore_pp); | 1117 | err = enic_process_set_pp_request(enic, vf, &prev_pp, &restore_pp); |
1117 | if (err) { | 1118 | if (err) { |
1118 | if (restore_pp) { | 1119 | if (restore_pp) { |
1119 | /* Things are still the way they were: Implicit | 1120 | /* Things are still the way they were: Implicit |
1120 | * DISASSOCIATE failed | 1121 | * DISASSOCIATE failed |
1121 | */ | 1122 | */ |
1122 | memcpy(&enic->pp, &prev_pp, sizeof(enic->pp)); | 1123 | memcpy(pp, &prev_pp, sizeof(*pp)); |
1123 | } else { | 1124 | } else { |
1124 | memset(&enic->pp, 0, sizeof(enic->pp)); | 1125 | memset(pp, 0, sizeof(*pp)); |
1125 | memset(netdev->dev_addr, 0, ETH_ALEN); | 1126 | if (vf == PORT_SELF_VF) |
1127 | memset(netdev->dev_addr, 0, ETH_ALEN); | ||
1126 | } | 1128 | } |
1127 | } else { | 1129 | } else { |
1128 | /* Set flag to indicate that the port assoc/disassoc | 1130 | /* Set flag to indicate that the port assoc/disassoc |
1129 | * request has been sent out to fw | 1131 | * request has been sent out to fw |
1130 | */ | 1132 | */ |
1131 | enic->pp.set |= ENIC_PORT_REQUEST_APPLIED; | 1133 | pp->set |= ENIC_PORT_REQUEST_APPLIED; |
1132 | 1134 | ||
1133 | /* If DISASSOCIATE, clean up all assigned/saved macaddresses */ | 1135 | /* If DISASSOCIATE, clean up all assigned/saved macaddresses */ |
1134 | if (enic->pp.request == PORT_REQUEST_DISASSOCIATE) { | 1136 | if (pp->request == PORT_REQUEST_DISASSOCIATE) { |
1135 | memset(enic->pp.mac_addr, 0, ETH_ALEN); | 1137 | memset(pp->mac_addr, 0, ETH_ALEN); |
1136 | memset(netdev->dev_addr, 0, ETH_ALEN); | 1138 | if (vf == PORT_SELF_VF) |
1139 | memset(netdev->dev_addr, 0, ETH_ALEN); | ||
1137 | } | 1140 | } |
1138 | } | 1141 | } |
1139 | 1142 | ||
1140 | memset(enic->pp.vf_mac, 0, ETH_ALEN); | 1143 | memset(pp->vf_mac, 0, ETH_ALEN); |
1141 | 1144 | ||
1142 | return err; | 1145 | return err; |
1143 | } | 1146 | } |
@@ -1147,26 +1150,31 @@ static int enic_get_vf_port(struct net_device *netdev, int vf, | |||
1147 | { | 1150 | { |
1148 | struct enic *enic = netdev_priv(netdev); | 1151 | struct enic *enic = netdev_priv(netdev); |
1149 | u16 response = PORT_PROFILE_RESPONSE_SUCCESS; | 1152 | u16 response = PORT_PROFILE_RESPONSE_SUCCESS; |
1153 | struct enic_port_profile *pp; | ||
1150 | int err; | 1154 | int err; |
1151 | 1155 | ||
1152 | if (!(enic->pp.set & ENIC_PORT_REQUEST_APPLIED)) | 1156 | ENIC_PP_BY_INDEX(enic, vf, pp, &err); |
1157 | if (err) | ||
1158 | return err; | ||
1159 | |||
1160 | if (!(pp->set & ENIC_PORT_REQUEST_APPLIED)) | ||
1153 | return -ENODATA; | 1161 | return -ENODATA; |
1154 | 1162 | ||
1155 | err = enic_process_get_pp_request(enic, enic->pp.request, &response); | 1163 | err = enic_process_get_pp_request(enic, vf, pp->request, &response); |
1156 | if (err) | 1164 | if (err) |
1157 | return err; | 1165 | return err; |
1158 | 1166 | ||
1159 | NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request); | 1167 | NLA_PUT_U16(skb, IFLA_PORT_REQUEST, pp->request); |
1160 | NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response); | 1168 | NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response); |
1161 | if (enic->pp.set & ENIC_SET_NAME) | 1169 | if (pp->set & ENIC_SET_NAME) |
1162 | NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX, | 1170 | NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX, |
1163 | enic->pp.name); | 1171 | pp->name); |
1164 | if (enic->pp.set & ENIC_SET_INSTANCE) | 1172 | if (pp->set & ENIC_SET_INSTANCE) |
1165 | NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX, | 1173 | NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX, |
1166 | enic->pp.instance_uuid); | 1174 | pp->instance_uuid); |
1167 | if (enic->pp.set & ENIC_SET_HOST) | 1175 | if (pp->set & ENIC_SET_HOST) |
1168 | NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX, | 1176 | NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX, |
1169 | enic->pp.host_uuid); | 1177 | pp->host_uuid); |
1170 | 1178 | ||
1171 | return 0; | 1179 | return 0; |
1172 | 1180 | ||
@@ -1600,10 +1608,9 @@ static int enic_open(struct net_device *netdev) | |||
1600 | for (i = 0; i < enic->rq_count; i++) | 1608 | for (i = 0; i < enic->rq_count; i++) |
1601 | vnic_rq_enable(&enic->rq[i]); | 1609 | vnic_rq_enable(&enic->rq[i]); |
1602 | 1610 | ||
1603 | if (enic_is_dynamic(enic) && !is_zero_ether_addr(enic->pp.mac_addr)) | 1611 | if (!enic_is_dynamic(enic)) |
1604 | enic_dev_add_addr(enic, enic->pp.mac_addr); | ||
1605 | else | ||
1606 | enic_dev_add_station_addr(enic); | 1612 | enic_dev_add_station_addr(enic); |
1613 | |||
1607 | enic_set_rx_mode(netdev); | 1614 | enic_set_rx_mode(netdev); |
1608 | 1615 | ||
1609 | netif_wake_queue(netdev); | 1616 | netif_wake_queue(netdev); |
@@ -1651,9 +1658,8 @@ static int enic_stop(struct net_device *netdev) | |||
1651 | 1658 | ||
1652 | netif_carrier_off(netdev); | 1659 | netif_carrier_off(netdev); |
1653 | netif_tx_disable(netdev); | 1660 | netif_tx_disable(netdev); |
1654 | if (enic_is_dynamic(enic) && !is_zero_ether_addr(enic->pp.mac_addr)) | 1661 | |
1655 | enic_dev_del_addr(enic, enic->pp.mac_addr); | 1662 | if (!enic_is_dynamic(enic)) |
1656 | else | ||
1657 | enic_dev_del_station_addr(enic); | 1663 | enic_dev_del_station_addr(enic); |
1658 | 1664 | ||
1659 | for (i = 0; i < enic->wq_count; i++) { | 1665 | for (i = 0; i < enic->wq_count; i++) { |
@@ -2143,6 +2149,9 @@ static const struct net_device_ops enic_netdev_ops = { | |||
2143 | .ndo_vlan_rx_add_vid = enic_vlan_rx_add_vid, | 2149 | .ndo_vlan_rx_add_vid = enic_vlan_rx_add_vid, |
2144 | .ndo_vlan_rx_kill_vid = enic_vlan_rx_kill_vid, | 2150 | .ndo_vlan_rx_kill_vid = enic_vlan_rx_kill_vid, |
2145 | .ndo_tx_timeout = enic_tx_timeout, | 2151 | .ndo_tx_timeout = enic_tx_timeout, |
2152 | .ndo_set_vf_port = enic_set_vf_port, | ||
2153 | .ndo_get_vf_port = enic_get_vf_port, | ||
2154 | .ndo_set_vf_mac = enic_set_vf_mac, | ||
2146 | #ifdef CONFIG_NET_POLL_CONTROLLER | 2155 | #ifdef CONFIG_NET_POLL_CONTROLLER |
2147 | .ndo_poll_controller = enic_poll_controller, | 2156 | .ndo_poll_controller = enic_poll_controller, |
2148 | #endif | 2157 | #endif |
@@ -2254,6 +2263,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, | |||
2254 | int using_dac = 0; | 2263 | int using_dac = 0; |
2255 | unsigned int i; | 2264 | unsigned int i; |
2256 | int err; | 2265 | int err; |
2266 | int num_pps = 1; | ||
2257 | #ifdef CONFIG_PCI_IOV | 2267 | #ifdef CONFIG_PCI_IOV |
2258 | int pos = 0; | 2268 | int pos = 0; |
2259 | #endif | 2269 | #endif |
@@ -2363,17 +2373,26 @@ static int __devinit enic_probe(struct pci_dev *pdev, | |||
2363 | goto err_out_vnic_unregister; | 2373 | goto err_out_vnic_unregister; |
2364 | } | 2374 | } |
2365 | enic->priv_flags |= ENIC_SRIOV_ENABLED; | 2375 | enic->priv_flags |= ENIC_SRIOV_ENABLED; |
2376 | num_pps = enic->num_vfs; | ||
2366 | } | 2377 | } |
2367 | } | 2378 | } |
2368 | 2379 | ||
2369 | #endif | 2380 | #endif |
2381 | /* Allocate structure for port profiles */ | ||
2382 | enic->pp = kzalloc(num_pps * sizeof(*enic->pp), GFP_KERNEL); | ||
2383 | if (!enic->pp) { | ||
2384 | pr_err("port profile alloc failed, aborting\n"); | ||
2385 | err = -ENOMEM; | ||
2386 | goto err_out_disable_sriov; | ||
2387 | } | ||
2388 | |||
2370 | /* Issue device open to get device in known state | 2389 | /* Issue device open to get device in known state |
2371 | */ | 2390 | */ |
2372 | 2391 | ||
2373 | err = enic_dev_open(enic); | 2392 | err = enic_dev_open(enic); |
2374 | if (err) { | 2393 | if (err) { |
2375 | dev_err(dev, "vNIC dev open failed, aborting\n"); | 2394 | dev_err(dev, "vNIC dev open failed, aborting\n"); |
2376 | goto err_out_disable_sriov; | 2395 | goto err_out_free_pp; |
2377 | } | 2396 | } |
2378 | 2397 | ||
2379 | /* Setup devcmd lock | 2398 | /* Setup devcmd lock |
@@ -2497,6 +2516,8 @@ err_out_dev_deinit: | |||
2497 | enic_dev_deinit(enic); | 2516 | enic_dev_deinit(enic); |
2498 | err_out_dev_close: | 2517 | err_out_dev_close: |
2499 | vnic_dev_close(enic->vdev); | 2518 | vnic_dev_close(enic->vdev); |
2519 | err_out_free_pp: | ||
2520 | kfree(enic->pp); | ||
2500 | err_out_disable_sriov: | 2521 | err_out_disable_sriov: |
2501 | #ifdef CONFIG_PCI_IOV | 2522 | #ifdef CONFIG_PCI_IOV |
2502 | if (enic_sriov_enabled(enic)) { | 2523 | if (enic_sriov_enabled(enic)) { |
@@ -2537,6 +2558,7 @@ static void __devexit enic_remove(struct pci_dev *pdev) | |||
2537 | enic->priv_flags &= ~ENIC_SRIOV_ENABLED; | 2558 | enic->priv_flags &= ~ENIC_SRIOV_ENABLED; |
2538 | } | 2559 | } |
2539 | #endif | 2560 | #endif |
2561 | kfree(enic->pp); | ||
2540 | vnic_dev_unregister(enic->vdev); | 2562 | vnic_dev_unregister(enic->vdev); |
2541 | enic_iounmap(enic); | 2563 | enic_iounmap(enic); |
2542 | pci_release_regions(pdev); | 2564 | pci_release_regions(pdev); |
diff --git a/drivers/net/ethernet/cisco/enic/enic_pp.c b/drivers/net/ethernet/cisco/enic/enic_pp.c index ffaa75dd1ded..22bf03a1829e 100644 --- a/drivers/net/ethernet/cisco/enic/enic_pp.c +++ b/drivers/net/ethernet/cisco/enic/enic_pp.c | |||
@@ -29,10 +29,47 @@ | |||
29 | #include "enic_res.h" | 29 | #include "enic_res.h" |
30 | #include "enic.h" | 30 | #include "enic.h" |
31 | #include "enic_dev.h" | 31 | #include "enic_dev.h" |
32 | #include "enic_pp.h" | ||
32 | 33 | ||
33 | static int enic_set_port_profile(struct enic *enic) | 34 | /* |
35 | * Checks validity of vf index that came in | ||
36 | * port profile request | ||
37 | */ | ||
38 | int enic_is_valid_pp_vf(struct enic *enic, int vf, int *err) | ||
39 | { | ||
40 | if (vf != PORT_SELF_VF) { | ||
41 | #ifdef CONFIG_PCI_IOV | ||
42 | if (enic_sriov_enabled(enic)) { | ||
43 | if (vf < 0 || vf >= enic->num_vfs) { | ||
44 | *err = -EINVAL; | ||
45 | goto err_out; | ||
46 | } | ||
47 | } else { | ||
48 | *err = -EOPNOTSUPP; | ||
49 | goto err_out; | ||
50 | } | ||
51 | #else | ||
52 | *err = -EOPNOTSUPP; | ||
53 | goto err_out; | ||
54 | #endif | ||
55 | } | ||
56 | |||
57 | if (vf == PORT_SELF_VF && !enic_is_dynamic(enic)) { | ||
58 | *err = -EOPNOTSUPP; | ||
59 | goto err_out; | ||
60 | } | ||
61 | |||
62 | *err = 0; | ||
63 | return 1; | ||
64 | |||
65 | err_out: | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static int enic_set_port_profile(struct enic *enic, int vf) | ||
34 | { | 70 | { |
35 | struct net_device *netdev = enic->netdev; | 71 | struct net_device *netdev = enic->netdev; |
72 | struct enic_port_profile *pp; | ||
36 | struct vic_provinfo *vp; | 73 | struct vic_provinfo *vp; |
37 | const u8 oui[3] = VIC_PROVINFO_CISCO_OUI; | 74 | const u8 oui[3] = VIC_PROVINFO_CISCO_OUI; |
38 | const u16 os_type = htons(VIC_GENERIC_PROV_OS_TYPE_LINUX); | 75 | const u16 os_type = htons(VIC_GENERIC_PROV_OS_TYPE_LINUX); |
@@ -41,7 +78,11 @@ static int enic_set_port_profile(struct enic *enic) | |||
41 | u8 *client_mac; | 78 | u8 *client_mac; |
42 | int err; | 79 | int err; |
43 | 80 | ||
44 | if (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name)) | 81 | ENIC_PP_BY_INDEX(enic, vf, pp, &err); |
82 | if (err) | ||
83 | return err; | ||
84 | |||
85 | if (!(pp->set & ENIC_SET_NAME) || !strlen(pp->name)) | ||
45 | return -EINVAL; | 86 | return -EINVAL; |
46 | 87 | ||
47 | vp = vic_provinfo_alloc(GFP_KERNEL, oui, | 88 | vp = vic_provinfo_alloc(GFP_KERNEL, oui, |
@@ -51,12 +92,18 @@ static int enic_set_port_profile(struct enic *enic) | |||
51 | 92 | ||
52 | VIC_PROVINFO_ADD_TLV(vp, | 93 | VIC_PROVINFO_ADD_TLV(vp, |
53 | VIC_GENERIC_PROV_TLV_PORT_PROFILE_NAME_STR, | 94 | VIC_GENERIC_PROV_TLV_PORT_PROFILE_NAME_STR, |
54 | strlen(enic->pp.name) + 1, enic->pp.name); | 95 | strlen(pp->name) + 1, pp->name); |
55 | 96 | ||
56 | if (!is_zero_ether_addr(enic->pp.mac_addr)) | 97 | if (!is_zero_ether_addr(pp->mac_addr)) { |
57 | client_mac = enic->pp.mac_addr; | 98 | client_mac = pp->mac_addr; |
58 | else | 99 | } else if (vf == PORT_SELF_VF) { |
59 | client_mac = netdev->dev_addr; | 100 | client_mac = netdev->dev_addr; |
101 | } else { | ||
102 | netdev_err(netdev, "Cannot find pp mac address " | ||
103 | "for VF %d\n", vf); | ||
104 | err = -EINVAL; | ||
105 | goto add_tlv_failure; | ||
106 | } | ||
60 | 107 | ||
61 | VIC_PROVINFO_ADD_TLV(vp, | 108 | VIC_PROVINFO_ADD_TLV(vp, |
62 | VIC_GENERIC_PROV_TLV_CLIENT_MAC_ADDR, | 109 | VIC_GENERIC_PROV_TLV_CLIENT_MAC_ADDR, |
@@ -67,15 +114,15 @@ static int enic_set_port_profile(struct enic *enic) | |||
67 | VIC_GENERIC_PROV_TLV_CLUSTER_PORT_UUID_STR, | 114 | VIC_GENERIC_PROV_TLV_CLUSTER_PORT_UUID_STR, |
68 | sizeof(client_mac_str), client_mac_str); | 115 | sizeof(client_mac_str), client_mac_str); |
69 | 116 | ||
70 | if (enic->pp.set & ENIC_SET_INSTANCE) { | 117 | if (pp->set & ENIC_SET_INSTANCE) { |
71 | sprintf(uuid_str, "%pUB", enic->pp.instance_uuid); | 118 | sprintf(uuid_str, "%pUB", pp->instance_uuid); |
72 | VIC_PROVINFO_ADD_TLV(vp, | 119 | VIC_PROVINFO_ADD_TLV(vp, |
73 | VIC_GENERIC_PROV_TLV_CLIENT_UUID_STR, | 120 | VIC_GENERIC_PROV_TLV_CLIENT_UUID_STR, |
74 | sizeof(uuid_str), uuid_str); | 121 | sizeof(uuid_str), uuid_str); |
75 | } | 122 | } |
76 | 123 | ||
77 | if (enic->pp.set & ENIC_SET_HOST) { | 124 | if (pp->set & ENIC_SET_HOST) { |
78 | sprintf(uuid_str, "%pUB", enic->pp.host_uuid); | 125 | sprintf(uuid_str, "%pUB", pp->host_uuid); |
79 | VIC_PROVINFO_ADD_TLV(vp, | 126 | VIC_PROVINFO_ADD_TLV(vp, |
80 | VIC_GENERIC_PROV_TLV_HOST_UUID_STR, | 127 | VIC_GENERIC_PROV_TLV_HOST_UUID_STR, |
81 | sizeof(uuid_str), uuid_str); | 128 | sizeof(uuid_str), uuid_str); |
@@ -85,7 +132,9 @@ static int enic_set_port_profile(struct enic *enic) | |||
85 | VIC_GENERIC_PROV_TLV_OS_TYPE, | 132 | VIC_GENERIC_PROV_TLV_OS_TYPE, |
86 | sizeof(os_type), &os_type); | 133 | sizeof(os_type), &os_type); |
87 | 134 | ||
88 | err = enic_dev_status_to_errno(enic_dev_init_prov2(enic, vp)); | 135 | ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_init_prov2, (u8 *)vp, |
136 | vic_provinfo_size(vp)); | ||
137 | err = enic_dev_status_to_errno(err); | ||
89 | 138 | ||
90 | add_tlv_failure: | 139 | add_tlv_failure: |
91 | vic_provinfo_free(vp); | 140 | vic_provinfo_free(vp); |
@@ -93,15 +142,16 @@ add_tlv_failure: | |||
93 | return err; | 142 | return err; |
94 | } | 143 | } |
95 | 144 | ||
96 | static int enic_unset_port_profile(struct enic *enic) | 145 | static int enic_unset_port_profile(struct enic *enic, int vf) |
97 | { | 146 | { |
98 | int err; | 147 | int err; |
99 | 148 | ||
100 | err = enic_vnic_dev_deinit(enic); | 149 | ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_deinit); |
101 | if (err) | 150 | if (err) |
102 | return enic_dev_status_to_errno(err); | 151 | return enic_dev_status_to_errno(err); |
103 | 152 | ||
104 | enic_reset_addr_lists(enic); | 153 | if (vf == PORT_SELF_VF) |
154 | enic_reset_addr_lists(enic); | ||
105 | 155 | ||
106 | return 0; | 156 | return 0; |
107 | } | 157 | } |
@@ -115,17 +165,18 @@ static int enic_are_pp_different(struct enic_port_profile *pp1, | |||
115 | !!memcmp(pp1->mac_addr, pp2->mac_addr, ETH_ALEN); | 165 | !!memcmp(pp1->mac_addr, pp2->mac_addr, ETH_ALEN); |
116 | } | 166 | } |
117 | 167 | ||
118 | static int enic_pp_preassociate(struct enic *enic, | 168 | static int enic_pp_preassociate(struct enic *enic, int vf, |
119 | struct enic_port_profile *prev_pp, int *restore_pp); | 169 | struct enic_port_profile *prev_pp, int *restore_pp); |
120 | static int enic_pp_disassociate(struct enic *enic, | 170 | static int enic_pp_disassociate(struct enic *enic, int vf, |
121 | struct enic_port_profile *prev_pp, int *restore_pp); | 171 | struct enic_port_profile *prev_pp, int *restore_pp); |
122 | static int enic_pp_preassociate_rr(struct enic *enic, | 172 | static int enic_pp_preassociate_rr(struct enic *enic, int vf, |
123 | struct enic_port_profile *prev_pp, int *restore_pp); | 173 | struct enic_port_profile *prev_pp, int *restore_pp); |
124 | static int enic_pp_associate(struct enic *enic, | 174 | static int enic_pp_associate(struct enic *enic, int vf, |
125 | struct enic_port_profile *prev_pp, int *restore_pp); | 175 | struct enic_port_profile *prev_pp, int *restore_pp); |
126 | 176 | ||
127 | static int (*enic_pp_handlers[])(struct enic *enic, | 177 | static int (*enic_pp_handlers[])(struct enic *enic, int vf, |
128 | struct enic_port_profile *prev_state, int *restore_pp) = { | 178 | struct enic_port_profile *prev_state, |
179 | int *restore_pp) = { | ||
129 | [PORT_REQUEST_PREASSOCIATE] = enic_pp_preassociate, | 180 | [PORT_REQUEST_PREASSOCIATE] = enic_pp_preassociate, |
130 | [PORT_REQUEST_PREASSOCIATE_RR] = enic_pp_preassociate_rr, | 181 | [PORT_REQUEST_PREASSOCIATE_RR] = enic_pp_preassociate_rr, |
131 | [PORT_REQUEST_ASSOCIATE] = enic_pp_associate, | 182 | [PORT_REQUEST_ASSOCIATE] = enic_pp_associate, |
@@ -135,28 +186,49 @@ static int (*enic_pp_handlers[])(struct enic *enic, | |||
135 | static const int enic_pp_handlers_count = | 186 | static const int enic_pp_handlers_count = |
136 | sizeof(enic_pp_handlers)/sizeof(*enic_pp_handlers); | 187 | sizeof(enic_pp_handlers)/sizeof(*enic_pp_handlers); |
137 | 188 | ||
138 | static int enic_pp_preassociate(struct enic *enic, | 189 | static int enic_pp_preassociate(struct enic *enic, int vf, |
139 | struct enic_port_profile *prev_pp, int *restore_pp) | 190 | struct enic_port_profile *prev_pp, int *restore_pp) |
140 | { | 191 | { |
141 | return -EOPNOTSUPP; | 192 | return -EOPNOTSUPP; |
142 | } | 193 | } |
143 | 194 | ||
144 | static int enic_pp_disassociate(struct enic *enic, | 195 | static int enic_pp_disassociate(struct enic *enic, int vf, |
145 | struct enic_port_profile *prev_pp, int *restore_pp) | 196 | struct enic_port_profile *prev_pp, int *restore_pp) |
146 | { | 197 | { |
147 | return enic_unset_port_profile(enic); | 198 | struct net_device *netdev = enic->netdev; |
199 | struct enic_port_profile *pp; | ||
200 | int err; | ||
201 | |||
202 | ENIC_PP_BY_INDEX(enic, vf, pp, &err); | ||
203 | if (err) | ||
204 | return err; | ||
205 | |||
206 | /* Deregister mac addresses */ | ||
207 | if (!is_zero_ether_addr(pp->mac_addr)) | ||
208 | ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_del_addr, | ||
209 | pp->mac_addr); | ||
210 | else if (!is_zero_ether_addr(netdev->dev_addr)) | ||
211 | ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_del_addr, | ||
212 | netdev->dev_addr); | ||
213 | |||
214 | return enic_unset_port_profile(enic, vf); | ||
148 | } | 215 | } |
149 | 216 | ||
150 | static int enic_pp_preassociate_rr(struct enic *enic, | 217 | static int enic_pp_preassociate_rr(struct enic *enic, int vf, |
151 | struct enic_port_profile *prev_pp, int *restore_pp) | 218 | struct enic_port_profile *prev_pp, int *restore_pp) |
152 | { | 219 | { |
220 | struct enic_port_profile *pp; | ||
153 | int err; | 221 | int err; |
154 | int active = 0; | 222 | int active = 0; |
155 | 223 | ||
156 | if (enic->pp.request != PORT_REQUEST_ASSOCIATE) { | 224 | ENIC_PP_BY_INDEX(enic, vf, pp, &err); |
225 | if (err) | ||
226 | return err; | ||
227 | |||
228 | if (pp->request != PORT_REQUEST_ASSOCIATE) { | ||
157 | /* If pre-associate is not part of an associate. | 229 | /* If pre-associate is not part of an associate. |
158 | We always disassociate first */ | 230 | We always disassociate first */ |
159 | err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE](enic, | 231 | err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE](enic, vf, |
160 | prev_pp, restore_pp); | 232 | prev_pp, restore_pp); |
161 | if (err) | 233 | if (err) |
162 | return err; | 234 | return err; |
@@ -166,29 +238,39 @@ static int enic_pp_preassociate_rr(struct enic *enic, | |||
166 | 238 | ||
167 | *restore_pp = 0; | 239 | *restore_pp = 0; |
168 | 240 | ||
169 | err = enic_set_port_profile(enic); | 241 | err = enic_set_port_profile(enic, vf); |
170 | if (err) | 242 | if (err) |
171 | return err; | 243 | return err; |
172 | 244 | ||
173 | /* If pre-associate is not part of an associate. */ | 245 | /* If pre-associate is not part of an associate. */ |
174 | if (enic->pp.request != PORT_REQUEST_ASSOCIATE) | 246 | if (pp->request != PORT_REQUEST_ASSOCIATE) { |
175 | err = enic_dev_status_to_errno(enic_dev_enable2(enic, active)); | 247 | /* Enable device as standby */ |
248 | ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_enable2, | ||
249 | active); | ||
250 | err = enic_dev_status_to_errno(err); | ||
251 | } | ||
176 | 252 | ||
177 | return err; | 253 | return err; |
178 | } | 254 | } |
179 | 255 | ||
180 | static int enic_pp_associate(struct enic *enic, | 256 | static int enic_pp_associate(struct enic *enic, int vf, |
181 | struct enic_port_profile *prev_pp, int *restore_pp) | 257 | struct enic_port_profile *prev_pp, int *restore_pp) |
182 | { | 258 | { |
259 | struct net_device *netdev = enic->netdev; | ||
260 | struct enic_port_profile *pp; | ||
183 | int err; | 261 | int err; |
184 | int active = 1; | 262 | int active = 1; |
185 | 263 | ||
264 | ENIC_PP_BY_INDEX(enic, vf, pp, &err); | ||
265 | if (err) | ||
266 | return err; | ||
267 | |||
186 | /* Check if a pre-associate was called before */ | 268 | /* Check if a pre-associate was called before */ |
187 | if (prev_pp->request != PORT_REQUEST_PREASSOCIATE_RR || | 269 | if (prev_pp->request != PORT_REQUEST_PREASSOCIATE_RR || |
188 | (prev_pp->request == PORT_REQUEST_PREASSOCIATE_RR && | 270 | (prev_pp->request == PORT_REQUEST_PREASSOCIATE_RR && |
189 | enic_are_pp_different(prev_pp, &enic->pp))) { | 271 | enic_are_pp_different(prev_pp, pp))) { |
190 | err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE]( | 272 | err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE]( |
191 | enic, prev_pp, restore_pp); | 273 | enic, vf, prev_pp, restore_pp); |
192 | if (err) | 274 | if (err) |
193 | return err; | 275 | return err; |
194 | 276 | ||
@@ -196,28 +278,48 @@ static int enic_pp_associate(struct enic *enic, | |||
196 | } | 278 | } |
197 | 279 | ||
198 | err = enic_pp_handlers[PORT_REQUEST_PREASSOCIATE_RR]( | 280 | err = enic_pp_handlers[PORT_REQUEST_PREASSOCIATE_RR]( |
199 | enic, prev_pp, restore_pp); | 281 | enic, vf, prev_pp, restore_pp); |
200 | if (err) | 282 | if (err) |
201 | return err; | 283 | return err; |
202 | 284 | ||
203 | *restore_pp = 0; | 285 | *restore_pp = 0; |
204 | 286 | ||
205 | return enic_dev_status_to_errno(enic_dev_enable2(enic, active)); | 287 | /* Enable device as active */ |
288 | ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_enable2, active); | ||
289 | err = enic_dev_status_to_errno(err); | ||
290 | if (err) | ||
291 | return err; | ||
292 | |||
293 | /* Register mac address */ | ||
294 | if (!is_zero_ether_addr(pp->mac_addr)) | ||
295 | ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_add_addr, | ||
296 | pp->mac_addr); | ||
297 | else if (!is_zero_ether_addr(netdev->dev_addr)) | ||
298 | ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_add_addr, | ||
299 | netdev->dev_addr); | ||
300 | |||
301 | return 0; | ||
206 | } | 302 | } |
207 | 303 | ||
208 | int enic_process_set_pp_request(struct enic *enic, | 304 | int enic_process_set_pp_request(struct enic *enic, int vf, |
209 | struct enic_port_profile *prev_pp, int *restore_pp) | 305 | struct enic_port_profile *prev_pp, int *restore_pp) |
210 | { | 306 | { |
211 | if (enic->pp.request < enic_pp_handlers_count | 307 | struct enic_port_profile *pp; |
212 | && enic_pp_handlers[enic->pp.request]) | 308 | int err; |
213 | return enic_pp_handlers[enic->pp.request](enic, | 309 | |
214 | prev_pp, restore_pp); | 310 | ENIC_PP_BY_INDEX(enic, vf, pp, &err); |
215 | else | 311 | if (err) |
312 | return err; | ||
313 | |||
314 | if (pp->request >= enic_pp_handlers_count | ||
315 | || !enic_pp_handlers[pp->request]) | ||
216 | return -EOPNOTSUPP; | 316 | return -EOPNOTSUPP; |
317 | |||
318 | return enic_pp_handlers[pp->request](enic, vf, prev_pp, restore_pp); | ||
217 | } | 319 | } |
218 | 320 | ||
219 | int enic_process_get_pp_request(struct enic *enic, int request, | 321 | int enic_process_get_pp_request(struct enic *enic, int vf, |
220 | u16 *response) | 322 | int request, u16 *response) |
221 | { | 323 | { |
222 | int err, status = ERR_SUCCESS; | 324 | int err, status = ERR_SUCCESS; |
223 | 325 | ||
@@ -225,11 +327,13 @@ int enic_process_get_pp_request(struct enic *enic, int request, | |||
225 | 327 | ||
226 | case PORT_REQUEST_PREASSOCIATE_RR: | 328 | case PORT_REQUEST_PREASSOCIATE_RR: |
227 | case PORT_REQUEST_ASSOCIATE: | 329 | case PORT_REQUEST_ASSOCIATE: |
228 | err = enic_dev_enable2_done(enic, &status); | 330 | ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, |
331 | vnic_dev_enable2_done, &status); | ||
229 | break; | 332 | break; |
230 | 333 | ||
231 | case PORT_REQUEST_DISASSOCIATE: | 334 | case PORT_REQUEST_DISASSOCIATE: |
232 | err = enic_dev_deinit_done(enic, &status); | 335 | ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, |
336 | vnic_dev_deinit_done, &status); | ||
233 | break; | 337 | break; |
234 | 338 | ||
235 | default: | 339 | default: |
diff --git a/drivers/net/ethernet/cisco/enic/enic_pp.h b/drivers/net/ethernet/cisco/enic/enic_pp.h index 699e365a944d..a09ff392c1c6 100644 --- a/drivers/net/ethernet/cisco/enic/enic_pp.h +++ b/drivers/net/ethernet/cisco/enic/enic_pp.h | |||
@@ -19,9 +19,18 @@ | |||
19 | #ifndef _ENIC_PP_H_ | 19 | #ifndef _ENIC_PP_H_ |
20 | #define _ENIC_PP_H_ | 20 | #define _ENIC_PP_H_ |
21 | 21 | ||
22 | int enic_process_set_pp_request(struct enic *enic, | 22 | #define ENIC_PP_BY_INDEX(enic, vf, pp, err) \ |
23 | do { \ | ||
24 | if (enic_is_valid_pp_vf(enic, vf, err)) \ | ||
25 | pp = (vf == PORT_SELF_VF) ? enic->pp : enic->pp + vf; \ | ||
26 | else \ | ||
27 | pp = NULL; \ | ||
28 | } while (0) | ||
29 | |||
30 | int enic_process_set_pp_request(struct enic *enic, int vf, | ||
23 | struct enic_port_profile *prev_pp, int *restore_pp); | 31 | struct enic_port_profile *prev_pp, int *restore_pp); |
24 | int enic_process_get_pp_request(struct enic *enic, int request, | 32 | int enic_process_get_pp_request(struct enic *enic, int vf, |
25 | u16 *response); | 33 | int request, u16 *response); |
34 | int enic_is_valid_pp_vf(struct enic *enic, int vf, int *err); | ||
26 | 35 | ||
27 | #endif /* _ENIC_PP_H_ */ | 36 | #endif /* _ENIC_PP_H_ */ |