Skip to content

Commit 1f5c27e

Browse files
jacob-kellerJeff Kirsher
authored andcommitted
fm10k: use the MAC/VLAN queue for VF<->PF MAC/VLAN requests
Now that we have a working MAC/VLAN queue for handling MAC/VLAN messages from the netdev, replace the default handler for the VF<->PF messages. This new handler is very similar to the default code, but uses the MAC/VLAN queue instead of sending the message directly. Unfortunately we can't easily re-use the default code, so we'll just replace the entire function. This ensures that a VF requesting a large number of VLANs or MAC addresses does not start a reset cycle, as explained in the commit which introduced the message queue. Signed-off-by: Jacob Keller <[email protected]> Reviewed-by: Ngai-mint Kwan <[email protected]> Tested-by: Krishneil Singh <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent fc91736 commit 1f5c27e

File tree

3 files changed

+133
-4
lines changed

3 files changed

+133
-4
lines changed

drivers/net/ethernet/intel/fm10k/fm10k_iov.c

Lines changed: 130 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,133 @@ static s32 fm10k_iov_msg_error(struct fm10k_hw *hw, u32 **results,
3535
return fm10k_tlv_msg_error(hw, results, mbx);
3636
}
3737

38+
/**
39+
* fm10k_iov_msg_queue_mac_vlan - Message handler for MAC/VLAN request from VF
40+
* @hw: Pointer to hardware structure
41+
* @results: Pointer array to message, results[0] is pointer to message
42+
* @mbx: Pointer to mailbox information structure
43+
*
44+
* This function is a custom handler for MAC/VLAN requests from the VF. The
45+
* assumption is that it is acceptable to directly hand off the message from
46+
* the VF to the PF's switch manager. However, we use a MAC/VLAN message
47+
* queue to avoid overloading the mailbox when a large number of requests
48+
* come in.
49+
**/
50+
static s32 fm10k_iov_msg_queue_mac_vlan(struct fm10k_hw *hw, u32 **results,
51+
struct fm10k_mbx_info *mbx)
52+
{
53+
struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx;
54+
struct fm10k_intfc *interface = hw->back;
55+
u8 mac[ETH_ALEN];
56+
u32 *result;
57+
int err = 0;
58+
bool set;
59+
u16 vlan;
60+
u32 vid;
61+
62+
/* we shouldn't be updating rules on a disabled interface */
63+
if (!FM10K_VF_FLAG_ENABLED(vf_info))
64+
err = FM10K_ERR_PARAM;
65+
66+
if (!err && !!results[FM10K_MAC_VLAN_MSG_VLAN]) {
67+
result = results[FM10K_MAC_VLAN_MSG_VLAN];
68+
69+
/* record VLAN id requested */
70+
err = fm10k_tlv_attr_get_u32(result, &vid);
71+
if (err)
72+
return err;
73+
74+
set = !(vid & FM10K_VLAN_CLEAR);
75+
vid &= ~FM10K_VLAN_CLEAR;
76+
77+
/* if the length field has been set, this is a multi-bit
78+
* update request. For multi-bit requests, simply disallow
79+
* them when the pf_vid has been set. In this case, the PF
80+
* should have already cleared the VLAN_TABLE, and if we
81+
* allowed them, it could allow a rogue VF to receive traffic
82+
* on a VLAN it was not assigned. In the single-bit case, we
83+
* need to modify requests for VLAN 0 to use the default PF or
84+
* SW vid when assigned.
85+
*/
86+
87+
if (vid >> 16) {
88+
/* prevent multi-bit requests when PF has
89+
* administratively set the VLAN for this VF
90+
*/
91+
if (vf_info->pf_vid)
92+
return FM10K_ERR_PARAM;
93+
} else {
94+
err = fm10k_iov_select_vid(vf_info, (u16)vid);
95+
if (err < 0)
96+
return err;
97+
98+
vid = err;
99+
}
100+
101+
/* update VSI info for VF in regards to VLAN table */
102+
err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, set);
103+
}
104+
105+
if (!err && !!results[FM10K_MAC_VLAN_MSG_MAC]) {
106+
result = results[FM10K_MAC_VLAN_MSG_MAC];
107+
108+
/* record unicast MAC address requested */
109+
err = fm10k_tlv_attr_get_mac_vlan(result, mac, &vlan);
110+
if (err)
111+
return err;
112+
113+
/* block attempts to set MAC for a locked device */
114+
if (is_valid_ether_addr(vf_info->mac) &&
115+
!ether_addr_equal(mac, vf_info->mac))
116+
return FM10K_ERR_PARAM;
117+
118+
set = !(vlan & FM10K_VLAN_CLEAR);
119+
vlan &= ~FM10K_VLAN_CLEAR;
120+
121+
err = fm10k_iov_select_vid(vf_info, vlan);
122+
if (err < 0)
123+
return err;
124+
125+
vlan = (u16)err;
126+
127+
/* Add this request to the MAC/VLAN queue */
128+
err = fm10k_queue_mac_request(interface, vf_info->glort,
129+
mac, vlan, set);
130+
}
131+
132+
if (!err && !!results[FM10K_MAC_VLAN_MSG_MULTICAST]) {
133+
result = results[FM10K_MAC_VLAN_MSG_MULTICAST];
134+
135+
/* record multicast MAC address requested */
136+
err = fm10k_tlv_attr_get_mac_vlan(result, mac, &vlan);
137+
if (err)
138+
return err;
139+
140+
/* verify that the VF is allowed to request multicast */
141+
if (!(vf_info->vf_flags & FM10K_VF_FLAG_MULTI_ENABLED))
142+
return FM10K_ERR_PARAM;
143+
144+
set = !(vlan & FM10K_VLAN_CLEAR);
145+
vlan &= ~FM10K_VLAN_CLEAR;
146+
147+
err = fm10k_iov_select_vid(vf_info, vlan);
148+
if (err < 0)
149+
return err;
150+
151+
vlan = (u16)err;
152+
153+
/* Add this request to the MAC/VLAN queue */
154+
err = fm10k_queue_mac_request(interface, vf_info->glort,
155+
mac, vlan, set);
156+
}
157+
158+
return err;
159+
}
160+
38161
static const struct fm10k_msg_data iov_mbx_data[] = {
39162
FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test),
40163
FM10K_VF_MSG_MSIX_HANDLER(fm10k_iov_msg_msix_pf),
41-
FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_iov_msg_mac_vlan_pf),
164+
FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_iov_msg_queue_mac_vlan),
42165
FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_iov_msg_lport_state_pf),
43166
FM10K_TLV_MSG_ERROR_HANDLER(fm10k_iov_msg_error),
44167
};
@@ -126,8 +249,10 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface)
126249
hw->mbx.ops.process(hw, &hw->mbx);
127250

128251
/* verify port mapping is valid, if not reset port */
129-
if (vf_info->vf_flags && !fm10k_glort_valid_pf(hw, glort))
252+
if (vf_info->vf_flags && !fm10k_glort_valid_pf(hw, glort)) {
130253
hw->iov.ops.reset_lport(hw, vf_info);
254+
fm10k_clear_macvlan_queue(interface, glort, false);
255+
}
131256

132257
/* reset VFs that have mailbox timed out */
133258
if (!mbx->timeout) {
@@ -190,6 +315,7 @@ void fm10k_iov_suspend(struct pci_dev *pdev)
190315

191316
hw->iov.ops.reset_resources(hw, vf_info);
192317
hw->iov.ops.reset_lport(hw, vf_info);
318+
fm10k_clear_macvlan_queue(interface, vf_info->glort, false);
193319
}
194320
}
195321

@@ -414,6 +540,8 @@ static inline void fm10k_reset_vf_info(struct fm10k_intfc *interface,
414540
/* disable LPORT for this VF which clears switch rules */
415541
hw->iov.ops.reset_lport(hw, vf_info);
416542

543+
fm10k_clear_macvlan_queue(interface, vf_info->glort, false);
544+
417545
/* assign new MAC+VLAN for this VF */
418546
hw->iov.ops.assign_default_mac_vlan(hw, vf_info);
419547

drivers/net/ethernet/intel/fm10k/fm10k_pf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1186,7 +1186,7 @@ s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *hw, u32 **results,
11861186
* Will report an error if the VLAN ID is out of range. For VID = 0, it will
11871187
* return either the pf_vid or sw_vid depending on which one is set.
11881188
*/
1189-
static s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid)
1189+
s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid)
11901190
{
11911191
if (!vid)
11921192
return vf_info->pf_vid ? vf_info->pf_vid : vf_info->sw_vid;

drivers/net/ethernet/intel/fm10k/fm10k_pf.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* Intel(R) Ethernet Switch Host Interface Driver
2-
* Copyright(c) 2013 - 2016 Intel Corporation.
2+
* Copyright(c) 2013 - 2017 Intel Corporation.
33
*
44
* This program is free software; you can redistribute it and/or modify it
55
* under the terms and conditions of the GNU General Public License,
@@ -114,6 +114,7 @@ extern const struct fm10k_tlv_attr fm10k_err_msg_attr[];
114114
#define FM10K_PF_MSG_ERR_HANDLER(msg, func) \
115115
FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_##msg, fm10k_err_msg_attr, func)
116116

117+
s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid);
117118
s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *);
118119
s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *, u32 **,
119120
struct fm10k_mbx_info *);

0 commit comments

Comments
 (0)