aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuval Mintz <Yuval.Mintz@qlogic.com>2016-05-11 09:36:21 -0400
committerDavid S. Miller <davem@davemloft.net>2016-05-12 00:04:08 -0400
commiteff169608c250193e72089dc4ab15cb79e0bd68c (patch)
tree1e2c0fef7a427954be8800ee21914e34a6c61d87
parent08feecd7fc709077ce92d21a979f522a5f57170a (diff)
qed*: Support forced MAC
Allows the PF to enforce the VF's mac. i.e., by using `ip link ... vf <x> mac <value>'. While a MAC is forced, PF would prevent the VF from configuring any other MAC. Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_l2.c9
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sriov.c120
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sriov.h1
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_vf.c47
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_vf.h21
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_main.c31
-rw-r--r--include/linux/qed/qed_eth_if.h3
-rw-r--r--include/linux/qed/qed_iov_if.h2
8 files changed, 234 insertions, 0 deletions
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
index 7fb6b82f1a97..8d83250aa5ba 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -1701,6 +1701,14 @@ static void qed_register_eth_ops(struct qed_dev *cdev,
1701 qed_vf_start_iov_wq(cdev); 1701 qed_vf_start_iov_wq(cdev);
1702} 1702}
1703 1703
1704static bool qed_check_mac(struct qed_dev *cdev, u8 *mac)
1705{
1706 if (IS_PF(cdev))
1707 return true;
1708
1709 return qed_vf_check_mac(&cdev->hwfns[0], mac);
1710}
1711
1704static int qed_start_vport(struct qed_dev *cdev, 1712static int qed_start_vport(struct qed_dev *cdev,
1705 struct qed_start_vport_params *params) 1713 struct qed_start_vport_params *params)
1706{ 1714{
@@ -2149,6 +2157,7 @@ static const struct qed_eth_ops qed_eth_ops_pass = {
2149#endif 2157#endif
2150 .fill_dev_info = &qed_fill_eth_dev_info, 2158 .fill_dev_info = &qed_fill_eth_dev_info,
2151 .register_ops = &qed_register_eth_ops, 2159 .register_ops = &qed_register_eth_ops,
2160 .check_mac = &qed_check_mac,
2152 .vport_start = &qed_start_vport, 2161 .vport_start = &qed_start_vport,
2153 .vport_stop = &qed_stop_vport, 2162 .vport_stop = &qed_stop_vport,
2154 .vport_update = &qed_update_vport, 2163 .vport_update = &qed_update_vport,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
index 77d44baa5df3..c1b79190ce4d 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
@@ -1295,6 +1295,29 @@ static int qed_iov_configure_vport_forced(struct qed_hwfn *p_hwfn,
1295 if (!p_vf->vport_instance) 1295 if (!p_vf->vport_instance)
1296 return -EINVAL; 1296 return -EINVAL;
1297 1297
1298 if (events & (1 << MAC_ADDR_FORCED)) {
1299 /* Since there's no way [currently] of removing the MAC,
1300 * we can always assume this means we need to force it.
1301 */
1302 memset(&filter, 0, sizeof(filter));
1303 filter.type = QED_FILTER_MAC;
1304 filter.opcode = QED_FILTER_REPLACE;
1305 filter.is_rx_filter = 1;
1306 filter.is_tx_filter = 1;
1307 filter.vport_to_add_to = p_vf->vport_id;
1308 ether_addr_copy(filter.mac, p_vf->bulletin.p_virt->mac);
1309
1310 rc = qed_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid,
1311 &filter, QED_SPQ_MODE_CB, NULL);
1312 if (rc) {
1313 DP_NOTICE(p_hwfn,
1314 "PF failed to configure MAC for VF\n");
1315 return rc;
1316 }
1317
1318 p_vf->configured_features |= 1 << MAC_ADDR_FORCED;
1319 }
1320
1298 if (events & (1 << VLAN_ADDR_FORCED)) { 1321 if (events & (1 << VLAN_ADDR_FORCED)) {
1299 struct qed_sp_vport_update_params vport_update; 1322 struct qed_sp_vport_update_params vport_update;
1300 u8 removal; 1323 u8 removal;
@@ -2199,6 +2222,16 @@ static void qed_iov_vf_mbx_ucast_filter(struct qed_hwfn *p_hwfn,
2199 goto out; 2222 goto out;
2200 } 2223 }
2201 2224
2225 if ((p_bulletin->valid_bitmap & (1 << MAC_ADDR_FORCED)) &&
2226 (params.type == QED_FILTER_MAC ||
2227 params.type == QED_FILTER_MAC_VLAN)) {
2228 if (!ether_addr_equal(p_bulletin->mac, params.mac) ||
2229 (params.opcode != QED_FILTER_ADD &&
2230 params.opcode != QED_FILTER_REPLACE))
2231 status = PFVF_STATUS_FORCED;
2232 goto out;
2233 }
2234
2202 rc = qed_iov_chk_ucast(p_hwfn, vf->relative_vf_id, &params); 2235 rc = qed_iov_chk_ucast(p_hwfn, vf->relative_vf_id, &params);
2203 if (rc) { 2236 if (rc) {
2204 status = PFVF_STATUS_FAILURE; 2237 status = PFVF_STATUS_FAILURE;
@@ -2702,6 +2735,30 @@ static int qed_iov_copy_vf_msg(struct qed_hwfn *p_hwfn, struct qed_ptt *ptt,
2702 return 0; 2735 return 0;
2703} 2736}
2704 2737
2738static void qed_iov_bulletin_set_forced_mac(struct qed_hwfn *p_hwfn,
2739 u8 *mac, int vfid)
2740{
2741 struct qed_vf_info *vf_info;
2742 u64 feature;
2743
2744 vf_info = qed_iov_get_vf_info(p_hwfn, (u16)vfid, true);
2745 if (!vf_info) {
2746 DP_NOTICE(p_hwfn->cdev,
2747 "Can not set forced MAC, invalid vfid [%d]\n", vfid);
2748 return;
2749 }
2750
2751 feature = 1 << MAC_ADDR_FORCED;
2752 memcpy(vf_info->bulletin.p_virt->mac, mac, ETH_ALEN);
2753
2754 vf_info->bulletin.p_virt->valid_bitmap |= feature;
2755 /* Forced MAC will disable MAC_ADDR */
2756 vf_info->bulletin.p_virt->valid_bitmap &=
2757 ~(1 << VFPF_BULLETIN_MAC_ADDR);
2758
2759 qed_iov_configure_vport_forced(p_hwfn, vf_info, feature);
2760}
2761
2705void qed_iov_bulletin_set_forced_vlan(struct qed_hwfn *p_hwfn, 2762void qed_iov_bulletin_set_forced_vlan(struct qed_hwfn *p_hwfn,
2706 u16 pvid, int vfid) 2763 u16 pvid, int vfid)
2707{ 2764{
@@ -2736,6 +2793,21 @@ bool qed_iov_is_vf_stopped(struct qed_hwfn *p_hwfn, int vfid)
2736 return p_vf_info->state == VF_STOPPED; 2793 return p_vf_info->state == VF_STOPPED;
2737} 2794}
2738 2795
2796static u8 *qed_iov_bulletin_get_forced_mac(struct qed_hwfn *p_hwfn,
2797 u16 rel_vf_id)
2798{
2799 struct qed_vf_info *p_vf;
2800
2801 p_vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, true);
2802 if (!p_vf || !p_vf->bulletin.p_virt)
2803 return NULL;
2804
2805 if (!(p_vf->bulletin.p_virt->valid_bitmap & (1 << MAC_ADDR_FORCED)))
2806 return NULL;
2807
2808 return p_vf->bulletin.p_virt->mac;
2809}
2810
2739u16 qed_iov_bulletin_get_forced_vlan(struct qed_hwfn *p_hwfn, u16 rel_vf_id) 2811u16 qed_iov_bulletin_get_forced_vlan(struct qed_hwfn *p_hwfn, u16 rel_vf_id)
2740{ 2812{
2741 struct qed_vf_info *p_vf; 2813 struct qed_vf_info *p_vf;
@@ -2899,6 +2971,38 @@ static int qed_sriov_configure(struct qed_dev *cdev, int num_vfs_param)
2899 return qed_sriov_disable(cdev, true); 2971 return qed_sriov_disable(cdev, true);
2900} 2972}
2901 2973
2974static int qed_sriov_pf_set_mac(struct qed_dev *cdev, u8 *mac, int vfid)
2975{
2976 int i;
2977
2978 if (!IS_QED_SRIOV(cdev) || !IS_PF_SRIOV_ALLOC(&cdev->hwfns[0])) {
2979 DP_VERBOSE(cdev, QED_MSG_IOV,
2980 "Cannot set a VF MAC; Sriov is not enabled\n");
2981 return -EINVAL;
2982 }
2983
2984 if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true)) {
2985 DP_VERBOSE(cdev, QED_MSG_IOV,
2986 "Cannot set VF[%d] MAC (VF is not active)\n", vfid);
2987 return -EINVAL;
2988 }
2989
2990 for_each_hwfn(cdev, i) {
2991 struct qed_hwfn *hwfn = &cdev->hwfns[i];
2992 struct qed_public_vf_info *vf_info;
2993
2994 vf_info = qed_iov_get_public_vf_info(hwfn, vfid, true);
2995 if (!vf_info)
2996 continue;
2997
2998 /* Set the forced MAC, and schedule the IOV task */
2999 ether_addr_copy(vf_info->forced_mac, mac);
3000 qed_schedule_iov(hwfn, QED_IOV_WQ_SET_UNICAST_FILTER_FLAG);
3001 }
3002
3003 return 0;
3004}
3005
2902static int qed_sriov_pf_set_vlan(struct qed_dev *cdev, u16 vid, int vfid) 3006static int qed_sriov_pf_set_vlan(struct qed_dev *cdev, u16 vid, int vfid)
2903{ 3007{
2904 int i; 3008 int i;
@@ -3000,12 +3104,27 @@ static void qed_handle_pf_set_vf_unicast(struct qed_hwfn *hwfn)
3000 qed_for_each_vf(hwfn, i) { 3104 qed_for_each_vf(hwfn, i) {
3001 struct qed_public_vf_info *info; 3105 struct qed_public_vf_info *info;
3002 bool update = false; 3106 bool update = false;
3107 u8 *mac;
3003 3108
3004 info = qed_iov_get_public_vf_info(hwfn, i, true); 3109 info = qed_iov_get_public_vf_info(hwfn, i, true);
3005 if (!info) 3110 if (!info)
3006 continue; 3111 continue;
3007 3112
3008 /* Update data on bulletin board */ 3113 /* Update data on bulletin board */
3114 mac = qed_iov_bulletin_get_forced_mac(hwfn, i);
3115 if (is_valid_ether_addr(info->forced_mac) &&
3116 (!mac || !ether_addr_equal(mac, info->forced_mac))) {
3117 DP_VERBOSE(hwfn,
3118 QED_MSG_IOV,
3119 "Handling PF setting of VF MAC to VF 0x%02x [Abs 0x%02x]\n",
3120 i,
3121 hwfn->cdev->p_iov_info->first_vf_in_pf + i);
3122
3123 /* Update bulletin board with forced MAC */
3124 qed_iov_bulletin_set_forced_mac(hwfn,
3125 info->forced_mac, i);
3126 update = true;
3127 }
3009 3128
3010 if (qed_iov_bulletin_get_forced_vlan(hwfn, i) ^ 3129 if (qed_iov_bulletin_get_forced_vlan(hwfn, i) ^
3011 info->forced_vlan) { 3130 info->forced_vlan) {
@@ -3133,5 +3252,6 @@ int qed_iov_wq_start(struct qed_dev *cdev)
3133 3252
3134const struct qed_iov_hv_ops qed_iov_ops_pass = { 3253const struct qed_iov_hv_ops qed_iov_ops_pass = {
3135 .configure = &qed_sriov_configure, 3254 .configure = &qed_sriov_configure,
3255 .set_mac = &qed_sriov_pf_set_mac,
3136 .set_vlan = &qed_sriov_pf_set_vlan, 3256 .set_vlan = &qed_sriov_pf_set_vlan,
3137}; 3257};
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.h b/drivers/net/ethernet/qlogic/qed/qed_sriov.h
index e65f403349c2..e38ea985abe1 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.h
@@ -43,6 +43,7 @@ struct qed_public_vf_info {
43 /* These copies will later be reflected in the bulletin board, 43 /* These copies will later be reflected in the bulletin board,
44 * but this copy should be newer. 44 * but this copy should be newer.
45 */ 45 */
46 u8 forced_mac[ETH_ALEN];
46 u16 forced_vlan; 47 u16 forced_vlan;
47 u8 mac[ETH_ALEN]; 48 u8 mac[ETH_ALEN];
48}; 49};
diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c
index 3c8911de3ed4..db14e230c9a4 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_vf.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c
@@ -7,6 +7,7 @@
7 */ 7 */
8 8
9#include <linux/crc32.h> 9#include <linux/crc32.h>
10#include <linux/etherdevice.h>
10#include "qed.h" 11#include "qed.h"
11#include "qed_sriov.h" 12#include "qed_sriov.h"
12#include "qed_vf.h" 13#include "qed_vf.h"
@@ -1004,6 +1005,43 @@ void qed_vf_get_num_vlan_filters(struct qed_hwfn *p_hwfn, u8 *num_vlan_filters)
1004 *num_vlan_filters = p_vf->acquire_resp.resc.num_vlan_filters; 1005 *num_vlan_filters = p_vf->acquire_resp.resc.num_vlan_filters;
1005} 1006}
1006 1007
1008bool qed_vf_check_mac(struct qed_hwfn *p_hwfn, u8 *mac)
1009{
1010 struct qed_bulletin_content *bulletin;
1011
1012 bulletin = &p_hwfn->vf_iov_info->bulletin_shadow;
1013 if (!(bulletin->valid_bitmap & (1 << MAC_ADDR_FORCED)))
1014 return true;
1015
1016 /* Forbid VF from changing a MAC enforced by PF */
1017 if (ether_addr_equal(bulletin->mac, mac))
1018 return false;
1019
1020 return false;
1021}
1022
1023bool qed_vf_bulletin_get_forced_mac(struct qed_hwfn *hwfn,
1024 u8 *dst_mac, u8 *p_is_forced)
1025{
1026 struct qed_bulletin_content *bulletin;
1027
1028 bulletin = &hwfn->vf_iov_info->bulletin_shadow;
1029
1030 if (bulletin->valid_bitmap & (1 << MAC_ADDR_FORCED)) {
1031 if (p_is_forced)
1032 *p_is_forced = 1;
1033 } else if (bulletin->valid_bitmap & (1 << VFPF_BULLETIN_MAC_ADDR)) {
1034 if (p_is_forced)
1035 *p_is_forced = 0;
1036 } else {
1037 return false;
1038 }
1039
1040 ether_addr_copy(dst_mac, bulletin->mac);
1041
1042 return true;
1043}
1044
1007void qed_vf_get_fw_version(struct qed_hwfn *p_hwfn, 1045void qed_vf_get_fw_version(struct qed_hwfn *p_hwfn,
1008 u16 *fw_major, u16 *fw_minor, 1046 u16 *fw_major, u16 *fw_minor,
1009 u16 *fw_rev, u16 *fw_eng) 1047 u16 *fw_rev, u16 *fw_eng)
@@ -1020,6 +1058,15 @@ void qed_vf_get_fw_version(struct qed_hwfn *p_hwfn,
1020 1058
1021static void qed_handle_bulletin_change(struct qed_hwfn *hwfn) 1059static void qed_handle_bulletin_change(struct qed_hwfn *hwfn)
1022{ 1060{
1061 struct qed_eth_cb_ops *ops = hwfn->cdev->protocol_ops.eth;
1062 u8 mac[ETH_ALEN], is_mac_exist, is_mac_forced;
1063 void *cookie = hwfn->cdev->ops_cookie;
1064
1065 is_mac_exist = qed_vf_bulletin_get_forced_mac(hwfn, mac,
1066 &is_mac_forced);
1067 if (is_mac_exist && is_mac_forced && cookie)
1068 ops->force_mac(cookie, mac);
1069
1023 /* Always update link configuration according to bulletin */ 1070 /* Always update link configuration according to bulletin */
1024 qed_link_update(hwfn); 1071 qed_link_update(hwfn);
1025} 1072}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.h b/drivers/net/ethernet/qlogic/qed/qed_vf.h
index 35eced3691ba..b82fda964bbd 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_vf.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_vf.h
@@ -418,6 +418,8 @@ union pfvf_tlvs {
418}; 418};
419 419
420enum qed_bulletin_bit { 420enum qed_bulletin_bit {
421 /* Alert the VF that a forced MAC was set by the PF */
422 MAC_ADDR_FORCED = 0,
421 /* Alert the VF that a forced VLAN was set by the PF */ 423 /* Alert the VF that a forced VLAN was set by the PF */
422 VLAN_ADDR_FORCED = 2, 424 VLAN_ADDR_FORCED = 2,
423 425
@@ -425,6 +427,10 @@ enum qed_bulletin_bit {
425 VFPF_BULLETIN_UNTAGGED_DEFAULT = 3, 427 VFPF_BULLETIN_UNTAGGED_DEFAULT = 3,
426 VFPF_BULLETIN_UNTAGGED_DEFAULT_FORCED = 4, 428 VFPF_BULLETIN_UNTAGGED_DEFAULT_FORCED = 4,
427 429
430 /* Alert the VF that suggested mac was sent by the PF.
431 * MAC_ADDR will be disabled in case MAC_ADDR_FORCED is set.
432 */
433 VFPF_BULLETIN_MAC_ADDR = 5
428}; 434};
429 435
430struct qed_bulletin_content { 436struct qed_bulletin_content {
@@ -602,6 +608,16 @@ void qed_vf_get_num_vlan_filters(struct qed_hwfn *p_hwfn,
602 u8 *num_vlan_filters); 608 u8 *num_vlan_filters);
603 609
604/** 610/**
611 * @brief Check if VF can set a MAC address
612 *
613 * @param p_hwfn
614 * @param mac
615 *
616 * @return bool
617 */
618bool qed_vf_check_mac(struct qed_hwfn *p_hwfn, u8 *mac);
619
620/**
605 * @brief Set firmware version information in dev_info from VFs acquire response tlv 621 * @brief Set firmware version information in dev_info from VFs acquire response tlv
606 * 622 *
607 * @param p_hwfn 623 * @param p_hwfn
@@ -841,6 +857,11 @@ static inline void qed_vf_get_num_vlan_filters(struct qed_hwfn *p_hwfn,
841{ 857{
842} 858}
843 859
860static inline bool qed_vf_check_mac(struct qed_hwfn *p_hwfn, u8 *mac)
861{
862 return false;
863}
864
844static inline void qed_vf_get_fw_version(struct qed_hwfn *p_hwfn, 865static inline void qed_vf_get_fw_version(struct qed_hwfn *p_hwfn,
845 u16 *fw_major, u16 *fw_minor, 866 u16 *fw_major, u16 *fw_minor,
846 u16 *fw_rev, u16 *fw_eng) 867 u16 *fw_rev, u16 *fw_eng)
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 4d59d7e00e42..b326b15d5196 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -118,6 +118,22 @@ static int qede_set_vf_vlan(struct net_device *ndev, int vf, u16 vlan, u8 qos)
118 return edev->ops->iov->set_vlan(edev->cdev, vlan, vf); 118 return edev->ops->iov->set_vlan(edev->cdev, vlan, vf);
119} 119}
120 120
121static int qede_set_vf_mac(struct net_device *ndev, int vfidx, u8 *mac)
122{
123 struct qede_dev *edev = netdev_priv(ndev);
124
125 DP_VERBOSE(edev, QED_MSG_IOV,
126 "Setting MAC %02x:%02x:%02x:%02x:%02x:%02x to VF [%d]\n",
127 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], vfidx);
128
129 if (!is_valid_ether_addr(mac)) {
130 DP_VERBOSE(edev, QED_MSG_IOV, "MAC address isn't valid\n");
131 return -EINVAL;
132 }
133
134 return edev->ops->iov->set_mac(edev->cdev, mac, vfidx);
135}
136
121static int qede_sriov_configure(struct pci_dev *pdev, int num_vfs_param) 137static int qede_sriov_configure(struct pci_dev *pdev, int num_vfs_param)
122{ 138{
123 struct qede_dev *edev = netdev_priv(pci_get_drvdata(pdev)); 139 struct qede_dev *edev = netdev_priv(pci_get_drvdata(pdev));
@@ -138,10 +154,19 @@ static struct pci_driver qede_pci_driver = {
138#endif 154#endif
139}; 155};
140 156
157static void qede_force_mac(void *dev, u8 *mac)
158{
159 struct qede_dev *edev = dev;
160
161 ether_addr_copy(edev->ndev->dev_addr, mac);
162 ether_addr_copy(edev->primary_mac, mac);
163}
164
141static struct qed_eth_cb_ops qede_ll_ops = { 165static struct qed_eth_cb_ops qede_ll_ops = {
142 { 166 {
143 .link_update = qede_link_update, 167 .link_update = qede_link_update,
144 }, 168 },
169 .force_mac = qede_force_mac,
145}; 170};
146 171
147static int qede_netdev_event(struct notifier_block *this, unsigned long event, 172static int qede_netdev_event(struct notifier_block *this, unsigned long event,
@@ -2087,6 +2112,7 @@ static const struct net_device_ops qede_netdev_ops = {
2087 .ndo_validate_addr = eth_validate_addr, 2112 .ndo_validate_addr = eth_validate_addr,
2088 .ndo_change_mtu = qede_change_mtu, 2113 .ndo_change_mtu = qede_change_mtu,
2089#ifdef CONFIG_QED_SRIOV 2114#ifdef CONFIG_QED_SRIOV
2115 .ndo_set_vf_mac = qede_set_vf_mac,
2090 .ndo_set_vf_vlan = qede_set_vf_vlan, 2116 .ndo_set_vf_vlan = qede_set_vf_vlan,
2091#endif 2117#endif
2092 .ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid, 2118 .ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid,
@@ -3512,6 +3538,11 @@ static int qede_set_mac_addr(struct net_device *ndev, void *p)
3512 return -EFAULT; 3538 return -EFAULT;
3513 } 3539 }
3514 3540
3541 if (!edev->ops->check_mac(edev->cdev, addr->sa_data)) {
3542 DP_NOTICE(edev, "qed prevents setting MAC\n");
3543 return -EINVAL;
3544 }
3545
3515 ether_addr_copy(ndev->dev_addr, addr->sa_data); 3546 ether_addr_copy(ndev->dev_addr, addr->sa_data);
3516 3547
3517 if (!netif_running(ndev)) { 3548 if (!netif_running(ndev)) {
diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h
index acfafca43aa5..e0f6e6482031 100644
--- a/include/linux/qed/qed_eth_if.h
+++ b/include/linux/qed/qed_eth_if.h
@@ -122,6 +122,7 @@ struct qed_tunn_params {
122 122
123struct qed_eth_cb_ops { 123struct qed_eth_cb_ops {
124 struct qed_common_cb_ops common; 124 struct qed_common_cb_ops common;
125 void (*force_mac) (void *dev, u8 *mac);
125}; 126};
126 127
127struct qed_eth_ops { 128struct qed_eth_ops {
@@ -137,6 +138,8 @@ struct qed_eth_ops {
137 struct qed_eth_cb_ops *ops, 138 struct qed_eth_cb_ops *ops,
138 void *cookie); 139 void *cookie);
139 140
141 bool(*check_mac) (struct qed_dev *cdev, u8 *mac);
142
140 int (*vport_start)(struct qed_dev *cdev, 143 int (*vport_start)(struct qed_dev *cdev,
141 struct qed_start_vport_params *params); 144 struct qed_start_vport_params *params);
142 145
diff --git a/include/linux/qed/qed_iov_if.h b/include/linux/qed/qed_iov_if.h
index 825c007d50f1..7a67fbf4336a 100644
--- a/include/linux/qed/qed_iov_if.h
+++ b/include/linux/qed/qed_iov_if.h
@@ -15,6 +15,8 @@
15struct qed_iov_hv_ops { 15struct qed_iov_hv_ops {
16 int (*configure)(struct qed_dev *cdev, int num_vfs_param); 16 int (*configure)(struct qed_dev *cdev, int num_vfs_param);
17 17
18 int (*set_mac) (struct qed_dev *cdev, u8 *mac, int vfid);
19
18 int (*set_vlan) (struct qed_dev *cdev, u16 vid, int vfid); 20 int (*set_vlan) (struct qed_dev *cdev, u16 vid, int vfid);
19}; 21};
20 22