@@ -35,10 +35,133 @@ static s32 fm10k_iov_msg_error(struct fm10k_hw *hw, u32 **results,
35
35
return fm10k_tlv_msg_error (hw , results , mbx );
36
36
}
37
37
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
+
38
161
static const struct fm10k_msg_data iov_mbx_data [] = {
39
162
FM10K_TLV_MSG_TEST_HANDLER (fm10k_tlv_msg_test ),
40
163
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 ),
42
165
FM10K_VF_MSG_LPORT_STATE_HANDLER (fm10k_iov_msg_lport_state_pf ),
43
166
FM10K_TLV_MSG_ERROR_HANDLER (fm10k_iov_msg_error ),
44
167
};
@@ -126,8 +249,10 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface)
126
249
hw -> mbx .ops .process (hw , & hw -> mbx );
127
250
128
251
/* 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 )) {
130
253
hw -> iov .ops .reset_lport (hw , vf_info );
254
+ fm10k_clear_macvlan_queue (interface , glort , false);
255
+ }
131
256
132
257
/* reset VFs that have mailbox timed out */
133
258
if (!mbx -> timeout ) {
@@ -190,6 +315,7 @@ void fm10k_iov_suspend(struct pci_dev *pdev)
190
315
191
316
hw -> iov .ops .reset_resources (hw , vf_info );
192
317
hw -> iov .ops .reset_lport (hw , vf_info );
318
+ fm10k_clear_macvlan_queue (interface , vf_info -> glort , false);
193
319
}
194
320
}
195
321
@@ -414,6 +540,8 @@ static inline void fm10k_reset_vf_info(struct fm10k_intfc *interface,
414
540
/* disable LPORT for this VF which clears switch rules */
415
541
hw -> iov .ops .reset_lport (hw , vf_info );
416
542
543
+ fm10k_clear_macvlan_queue (interface , vf_info -> glort , false);
544
+
417
545
/* assign new MAC+VLAN for this VF */
418
546
hw -> iov .ops .assign_default_mac_vlan (hw , vf_info );
419
547
0 commit comments