Skip to content

Commit 7425d82

Browse files
Shahed Shaikhdavem330
authored andcommitted
qed* : use trust mode to allow VF to override forced MAC
As per existing behavior, when PF sets a MAC address for a VF (also called as forced MAC), VF is not allowed to change its MAC address afterwards. This puts the limitation on few use cases such as bonding of VFs, where bonding driver asks VF to change its MAC address. This patch uses a VF trust mode to allow VF to change its MAC address in spite PF has set a forced MAC for that VF. Signed-off-by: Shahed Shaikh <shahed.shaikh@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 2ed0212 commit 7425d82

File tree

2 files changed

+195
-18
lines changed

2 files changed

+195
-18
lines changed

drivers/net/ethernet/qlogic/qed/qed_sriov.c

Lines changed: 194 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn,
4848
u8 opcode,
4949
__le16 echo,
5050
union event_ring_data *data, u8 fw_return_code);
51-
51+
static int qed_iov_bulletin_set_mac(struct qed_hwfn *p_hwfn, u8 *mac, int vfid);
5252

5353
static u8 qed_vf_calculate_legacy(struct qed_vf_info *p_vf)
5454
{
@@ -1790,7 +1790,8 @@ static int qed_iov_configure_vport_forced(struct qed_hwfn *p_hwfn,
17901790
if (!p_vf->vport_instance)
17911791
return -EINVAL;
17921792

1793-
if (events & BIT(MAC_ADDR_FORCED)) {
1793+
if ((events & BIT(MAC_ADDR_FORCED)) ||
1794+
p_vf->p_vf_info.is_trusted_configured) {
17941795
/* Since there's no way [currently] of removing the MAC,
17951796
* we can always assume this means we need to force it.
17961797
*/
@@ -1809,8 +1810,12 @@ static int qed_iov_configure_vport_forced(struct qed_hwfn *p_hwfn,
18091810
"PF failed to configure MAC for VF\n");
18101811
return rc;
18111812
}
1812-
1813-
p_vf->configured_features |= 1 << MAC_ADDR_FORCED;
1813+
if (p_vf->p_vf_info.is_trusted_configured)
1814+
p_vf->configured_features |=
1815+
BIT(VFPF_BULLETIN_MAC_ADDR);
1816+
else
1817+
p_vf->configured_features |=
1818+
BIT(MAC_ADDR_FORCED);
18141819
}
18151820

18161821
if (events & BIT(VLAN_ADDR_FORCED)) {
@@ -3170,6 +3175,10 @@ static int qed_iov_vf_update_mac_shadow(struct qed_hwfn *p_hwfn,
31703175
if (p_vf->bulletin.p_virt->valid_bitmap & BIT(MAC_ADDR_FORCED))
31713176
return 0;
31723177

3178+
/* Don't keep track of shadow copy since we don't intend to restore. */
3179+
if (p_vf->p_vf_info.is_trusted_configured)
3180+
return 0;
3181+
31733182
/* First remove entries and then add new ones */
31743183
if (p_params->opcode == QED_FILTER_REMOVE) {
31753184
for (i = 0; i < QED_ETH_VF_NUM_MAC_FILTERS; i++) {
@@ -3244,9 +3253,17 @@ static int qed_iov_chk_ucast(struct qed_hwfn *hwfn,
32443253

32453254
/* No real decision to make; Store the configured MAC */
32463255
if (params->type == QED_FILTER_MAC ||
3247-
params->type == QED_FILTER_MAC_VLAN)
3256+
params->type == QED_FILTER_MAC_VLAN) {
32483257
ether_addr_copy(vf->mac, params->mac);
32493258

3259+
if (vf->is_trusted_configured) {
3260+
qed_iov_bulletin_set_mac(hwfn, vf->mac, vfid);
3261+
3262+
/* Update and post bulleitin again */
3263+
qed_schedule_iov(hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG);
3264+
}
3265+
}
3266+
32503267
return 0;
32513268
}
32523269

@@ -4081,16 +4098,60 @@ static void qed_iov_bulletin_set_forced_mac(struct qed_hwfn *p_hwfn,
40814098
return;
40824099
}
40834100

4084-
feature = 1 << MAC_ADDR_FORCED;
4101+
if (vf_info->p_vf_info.is_trusted_configured) {
4102+
feature = BIT(VFPF_BULLETIN_MAC_ADDR);
4103+
/* Trust mode will disable Forced MAC */
4104+
vf_info->bulletin.p_virt->valid_bitmap &=
4105+
~BIT(MAC_ADDR_FORCED);
4106+
} else {
4107+
feature = BIT(MAC_ADDR_FORCED);
4108+
/* Forced MAC will disable MAC_ADDR */
4109+
vf_info->bulletin.p_virt->valid_bitmap &=
4110+
~BIT(VFPF_BULLETIN_MAC_ADDR);
4111+
}
4112+
40854113
memcpy(vf_info->bulletin.p_virt->mac, mac, ETH_ALEN);
40864114

40874115
vf_info->bulletin.p_virt->valid_bitmap |= feature;
4088-
/* Forced MAC will disable MAC_ADDR */
4089-
vf_info->bulletin.p_virt->valid_bitmap &= ~BIT(VFPF_BULLETIN_MAC_ADDR);
40904116

40914117
qed_iov_configure_vport_forced(p_hwfn, vf_info, feature);
40924118
}
40934119

4120+
static int qed_iov_bulletin_set_mac(struct qed_hwfn *p_hwfn, u8 *mac, int vfid)
4121+
{
4122+
struct qed_vf_info *vf_info;
4123+
u64 feature;
4124+
4125+
vf_info = qed_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4126+
if (!vf_info) {
4127+
DP_NOTICE(p_hwfn->cdev, "Can not set MAC, invalid vfid [%d]\n",
4128+
vfid);
4129+
return -EINVAL;
4130+
}
4131+
4132+
if (vf_info->b_malicious) {
4133+
DP_NOTICE(p_hwfn->cdev, "Can't set MAC to malicious VF [%d]\n",
4134+
vfid);
4135+
return -EINVAL;
4136+
}
4137+
4138+
if (vf_info->bulletin.p_virt->valid_bitmap & BIT(MAC_ADDR_FORCED)) {
4139+
DP_VERBOSE(p_hwfn, QED_MSG_IOV,
4140+
"Can not set MAC, Forced MAC is configured\n");
4141+
return -EINVAL;
4142+
}
4143+
4144+
feature = BIT(VFPF_BULLETIN_MAC_ADDR);
4145+
ether_addr_copy(vf_info->bulletin.p_virt->mac, mac);
4146+
4147+
vf_info->bulletin.p_virt->valid_bitmap |= feature;
4148+
4149+
if (vf_info->p_vf_info.is_trusted_configured)
4150+
qed_iov_configure_vport_forced(p_hwfn, vf_info, feature);
4151+
4152+
return 0;
4153+
}
4154+
40944155
static void qed_iov_bulletin_set_forced_vlan(struct qed_hwfn *p_hwfn,
40954156
u16 pvid, int vfid)
40964157
{
@@ -4204,6 +4265,21 @@ static int qed_iov_spoofchk_set(struct qed_hwfn *p_hwfn, int vfid, bool val)
42044265
return rc;
42054266
}
42064267

4268+
static u8 *qed_iov_bulletin_get_mac(struct qed_hwfn *p_hwfn, u16 rel_vf_id)
4269+
{
4270+
struct qed_vf_info *p_vf;
4271+
4272+
p_vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4273+
if (!p_vf || !p_vf->bulletin.p_virt)
4274+
return NULL;
4275+
4276+
if (!(p_vf->bulletin.p_virt->valid_bitmap &
4277+
BIT(VFPF_BULLETIN_MAC_ADDR)))
4278+
return NULL;
4279+
4280+
return p_vf->bulletin.p_virt->mac;
4281+
}
4282+
42074283
static u8 *qed_iov_bulletin_get_forced_mac(struct qed_hwfn *p_hwfn,
42084284
u16 rel_vf_id)
42094285
{
@@ -4493,8 +4569,12 @@ static int qed_sriov_pf_set_mac(struct qed_dev *cdev, u8 *mac, int vfid)
44934569
if (!vf_info)
44944570
continue;
44954571

4496-
/* Set the forced MAC, and schedule the IOV task */
4497-
ether_addr_copy(vf_info->forced_mac, mac);
4572+
/* Set the MAC, and schedule the IOV task */
4573+
if (vf_info->is_trusted_configured)
4574+
ether_addr_copy(vf_info->mac, mac);
4575+
else
4576+
ether_addr_copy(vf_info->forced_mac, mac);
4577+
44984578
qed_schedule_iov(hwfn, QED_IOV_WQ_SET_UNICAST_FILTER_FLAG);
44994579
}
45004580

@@ -4802,6 +4882,33 @@ static void qed_handle_vf_msg(struct qed_hwfn *hwfn)
48024882
qed_ptt_release(hwfn, ptt);
48034883
}
48044884

4885+
static bool qed_pf_validate_req_vf_mac(struct qed_hwfn *hwfn,
4886+
u8 *mac,
4887+
struct qed_public_vf_info *info)
4888+
{
4889+
if (info->is_trusted_configured) {
4890+
if (is_valid_ether_addr(info->mac) &&
4891+
(!mac || !ether_addr_equal(mac, info->mac)))
4892+
return true;
4893+
} else {
4894+
if (is_valid_ether_addr(info->forced_mac) &&
4895+
(!mac || !ether_addr_equal(mac, info->forced_mac)))
4896+
return true;
4897+
}
4898+
4899+
return false;
4900+
}
4901+
4902+
static void qed_set_bulletin_mac(struct qed_hwfn *hwfn,
4903+
struct qed_public_vf_info *info,
4904+
int vfid)
4905+
{
4906+
if (info->is_trusted_configured)
4907+
qed_iov_bulletin_set_mac(hwfn, info->mac, vfid);
4908+
else
4909+
qed_iov_bulletin_set_forced_mac(hwfn, info->forced_mac, vfid);
4910+
}
4911+
48054912
static void qed_handle_pf_set_vf_unicast(struct qed_hwfn *hwfn)
48064913
{
48074914
int i;
@@ -4816,18 +4923,20 @@ static void qed_handle_pf_set_vf_unicast(struct qed_hwfn *hwfn)
48164923
continue;
48174924

48184925
/* Update data on bulletin board */
4819-
mac = qed_iov_bulletin_get_forced_mac(hwfn, i);
4820-
if (is_valid_ether_addr(info->forced_mac) &&
4821-
(!mac || !ether_addr_equal(mac, info->forced_mac))) {
4926+
if (info->is_trusted_configured)
4927+
mac = qed_iov_bulletin_get_mac(hwfn, i);
4928+
else
4929+
mac = qed_iov_bulletin_get_forced_mac(hwfn, i);
4930+
4931+
if (qed_pf_validate_req_vf_mac(hwfn, mac, info)) {
48224932
DP_VERBOSE(hwfn,
48234933
QED_MSG_IOV,
48244934
"Handling PF setting of VF MAC to VF 0x%02x [Abs 0x%02x]\n",
48254935
i,
48264936
hwfn->cdev->p_iov_info->first_vf_in_pf + i);
48274937

4828-
/* Update bulletin board with forced MAC */
4829-
qed_iov_bulletin_set_forced_mac(hwfn,
4830-
info->forced_mac, i);
4938+
/* Update bulletin board with MAC */
4939+
qed_set_bulletin_mac(hwfn, info, i);
48314940
update = true;
48324941
}
48334942

@@ -4867,6 +4976,72 @@ static void qed_handle_bulletin_post(struct qed_hwfn *hwfn)
48674976
qed_ptt_release(hwfn, ptt);
48684977
}
48694978

4979+
static void qed_update_mac_for_vf_trust_change(struct qed_hwfn *hwfn, int vf_id)
4980+
{
4981+
struct qed_public_vf_info *vf_info;
4982+
struct qed_vf_info *vf;
4983+
u8 *force_mac;
4984+
int i;
4985+
4986+
vf_info = qed_iov_get_public_vf_info(hwfn, vf_id, true);
4987+
vf = qed_iov_get_vf_info(hwfn, vf_id, true);
4988+
4989+
if (!vf_info || !vf)
4990+
return;
4991+
4992+
/* Force MAC converted to generic MAC in case of VF trust on */
4993+
if (vf_info->is_trusted_configured &&
4994+
(vf->bulletin.p_virt->valid_bitmap & BIT(MAC_ADDR_FORCED))) {
4995+
force_mac = qed_iov_bulletin_get_forced_mac(hwfn, vf_id);
4996+
4997+
if (force_mac) {
4998+
/* Clear existing shadow copy of MAC to have a clean
4999+
* slate.
5000+
*/
5001+
for (i = 0; i < QED_ETH_VF_NUM_MAC_FILTERS; i++) {
5002+
if (ether_addr_equal(vf->shadow_config.macs[i],
5003+
vf_info->mac)) {
5004+
memset(vf->shadow_config.macs[i], 0,
5005+
ETH_ALEN);
5006+
DP_VERBOSE(hwfn, QED_MSG_IOV,
5007+
"Shadow MAC %pM removed for VF 0x%02x, VF trust mode is ON\n",
5008+
vf_info->mac, vf_id);
5009+
break;
5010+
}
5011+
}
5012+
5013+
ether_addr_copy(vf_info->mac, force_mac);
5014+
memset(vf_info->forced_mac, 0, ETH_ALEN);
5015+
vf->bulletin.p_virt->valid_bitmap &=
5016+
~BIT(MAC_ADDR_FORCED);
5017+
qed_schedule_iov(hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG);
5018+
}
5019+
}
5020+
5021+
/* Update shadow copy with VF MAC when trust mode is turned off */
5022+
if (!vf_info->is_trusted_configured) {
5023+
u8 empty_mac[ETH_ALEN];
5024+
5025+
memset(empty_mac, 0, ETH_ALEN);
5026+
for (i = 0; i < QED_ETH_VF_NUM_MAC_FILTERS; i++) {
5027+
if (ether_addr_equal(vf->shadow_config.macs[i],
5028+
empty_mac)) {
5029+
ether_addr_copy(vf->shadow_config.macs[i],
5030+
vf_info->mac);
5031+
DP_VERBOSE(hwfn, QED_MSG_IOV,
5032+
"Shadow is updated with %pM for VF 0x%02x, VF trust mode is OFF\n",
5033+
vf_info->mac, vf_id);
5034+
break;
5035+
}
5036+
}
5037+
/* Clear bulletin when trust mode is turned off,
5038+
* to have a clean slate for next (normal) operations.
5039+
*/
5040+
qed_iov_bulletin_set_mac(hwfn, empty_mac, vf_id);
5041+
qed_schedule_iov(hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG);
5042+
}
5043+
}
5044+
48705045
static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
48715046
{
48725047
struct qed_sp_vport_update_params params;
@@ -4890,6 +5065,9 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
48905065
continue;
48915066
vf_info->is_trusted_configured = vf_info->is_trusted_request;
48925067

5068+
/* Handle forced MAC mode */
5069+
qed_update_mac_for_vf_trust_change(hwfn, i);
5070+
48935071
/* Validate that the VF has a configured vport */
48945072
vf = qed_iov_get_vf_info(hwfn, i, true);
48955073
if (!vf->vport_instance)

drivers/net/ethernet/qlogic/qede/qede_filter.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,7 @@ void qede_force_mac(void *dev, u8 *mac, bool forced)
550550

551551
__qede_lock(edev);
552552

553-
/* MAC hints take effect only if we haven't set one already */
554-
if (is_valid_ether_addr(edev->ndev->dev_addr) && !forced) {
553+
if (!is_valid_ether_addr(mac)) {
555554
__qede_unlock(edev);
556555
return;
557556
}

0 commit comments

Comments
 (0)