hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/net/ethernet/intel/ice/ice_switch.c
....@@ -19,7 +19,7 @@
1919 * byte 6 = 0x2: to identify it as locally administered SA MAC
2020 * byte 12 = 0x81 & byte 13 = 0x00:
2121 * In case of VLAN filter first two bytes defines ether type (0x8100)
22
- * and remaining two bytes are placeholder for programming a given VLAN id
22
+ * and remaining two bytes are placeholder for programming a given VLAN ID
2323 * In case of Ether type filter it is treated as header without VLAN tag
2424 * and byte 12 and 13 is used to program a given Ether type instead
2525 */
....@@ -29,60 +29,45 @@
2929 0x81, 0, 0, 0};
3030
3131 #define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \
32
- (sizeof(struct ice_aqc_sw_rules_elem) - \
33
- sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
34
- sizeof(struct ice_sw_rule_lkup_rx_tx) + DUMMY_ETH_HDR_LEN - 1)
32
+ (offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr) + \
33
+ (DUMMY_ETH_HDR_LEN * \
34
+ sizeof(((struct ice_sw_rule_lkup_rx_tx *)0)->hdr[0])))
3535 #define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \
36
- (sizeof(struct ice_aqc_sw_rules_elem) - \
37
- sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
38
- sizeof(struct ice_sw_rule_lkup_rx_tx) - 1)
36
+ (offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr))
3937 #define ICE_SW_RULE_LG_ACT_SIZE(n) \
40
- (sizeof(struct ice_aqc_sw_rules_elem) - \
41
- sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
42
- sizeof(struct ice_sw_rule_lg_act) - \
43
- sizeof(((struct ice_sw_rule_lg_act *)0)->act) + \
44
- ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act)))
38
+ (offsetof(struct ice_aqc_sw_rules_elem, pdata.lg_act.act) + \
39
+ ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act[0])))
4540 #define ICE_SW_RULE_VSI_LIST_SIZE(n) \
46
- (sizeof(struct ice_aqc_sw_rules_elem) - \
47
- sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
48
- sizeof(struct ice_sw_rule_vsi_list) - \
49
- sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi) + \
50
- ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi)))
41
+ (offsetof(struct ice_aqc_sw_rules_elem, pdata.vsi_list.vsi) + \
42
+ ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi[0])))
5143
5244 /**
53
- * ice_aq_alloc_free_res - command to allocate/free resources
54
- * @hw: pointer to the hw struct
55
- * @num_entries: number of resource entries in buffer
56
- * @buf: Indirect buffer to hold data parameters and response
57
- * @buf_size: size of buffer for indirect commands
58
- * @opc: pass in the command opcode
59
- * @cd: pointer to command details structure or NULL
45
+ * ice_init_def_sw_recp - initialize the recipe book keeping tables
46
+ * @hw: pointer to the HW struct
6047 *
61
- * Helper function to allocate/free resources using the admin queue commands
48
+ * Allocate memory for the entire recipe table and initialize the structures/
49
+ * entries corresponding to basic recipes.
6250 */
63
-static enum ice_status
64
-ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries,
65
- struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,
66
- enum ice_adminq_opc opc, struct ice_sq_cd *cd)
51
+enum ice_status ice_init_def_sw_recp(struct ice_hw *hw)
6752 {
68
- struct ice_aqc_alloc_free_res_cmd *cmd;
69
- struct ice_aq_desc desc;
53
+ struct ice_sw_recipe *recps;
54
+ u8 i;
7055
71
- cmd = &desc.params.sw_res_ctrl;
56
+ recps = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_NUM_RECIPES,
57
+ sizeof(*recps), GFP_KERNEL);
58
+ if (!recps)
59
+ return ICE_ERR_NO_MEMORY;
7260
73
- if (!buf)
74
- return ICE_ERR_PARAM;
61
+ for (i = 0; i < ICE_SW_LKUP_LAST; i++) {
62
+ recps[i].root_rid = i;
63
+ INIT_LIST_HEAD(&recps[i].filt_rules);
64
+ INIT_LIST_HEAD(&recps[i].filt_replay_rules);
65
+ mutex_init(&recps[i].filt_rule_lock);
66
+ }
7567
76
- if (buf_size < (num_entries * sizeof(buf->elem[0])))
77
- return ICE_ERR_PARAM;
68
+ hw->switch_info->recp_list = recps;
7869
79
- ice_fill_dflt_direct_cmd_desc(&desc, opc);
80
-
81
- desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
82
-
83
- cmd->num_entries = cpu_to_le16(num_entries);
84
-
85
- return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
70
+ return 0;
8671 }
8772
8873 /**
....@@ -94,13 +79,13 @@
9479 * @num_elems: pointer to number of elements
9580 * @cd: pointer to command details structure or NULL
9681 *
97
- * Get switch configuration (0x0200) to be placed in 'buff'.
82
+ * Get switch configuration (0x0200) to be placed in buf.
9883 * This admin command returns information such as initial VSI/port number
9984 * and switch ID it belongs to.
10085 *
10186 * NOTE: *req_desc is both an input/output parameter.
10287 * The caller of this function first calls this function with *request_desc set
103
- * to 0. If the response from f/w has *req_desc set to 0, all the switch
88
+ * to 0. If the response from f/w has *req_desc set to 0, all the switch
10489 * configuration information has been returned; if non-zero (meaning not all
10590 * the information was returned), the caller should call this function again
10691 * with *req_desc set to the previous value returned by f/w to get the
....@@ -111,13 +96,13 @@
11196 * parsing the response buffer.
11297 */
11398 static enum ice_status
114
-ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp *buf,
99
+ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf,
115100 u16 buf_size, u16 *req_desc, u16 *num_elems,
116101 struct ice_sq_cd *cd)
117102 {
118103 struct ice_aqc_get_sw_cfg *cmd;
119
- enum ice_status status;
120104 struct ice_aq_desc desc;
105
+ enum ice_status status;
121106
122107 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
123108 cmd = &desc.params.get_sw_conf;
....@@ -134,29 +119,30 @@
134119
135120 /**
136121 * ice_aq_add_vsi
137
- * @hw: pointer to the hw struct
122
+ * @hw: pointer to the HW struct
138123 * @vsi_ctx: pointer to a VSI context struct
139124 * @cd: pointer to command details structure or NULL
140125 *
141126 * Add a VSI context to the hardware (0x0210)
142127 */
143
-enum ice_status
128
+static enum ice_status
144129 ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
145130 struct ice_sq_cd *cd)
146131 {
147132 struct ice_aqc_add_update_free_vsi_resp *res;
148133 struct ice_aqc_add_get_update_free_vsi *cmd;
149
- enum ice_status status;
150134 struct ice_aq_desc desc;
135
+ enum ice_status status;
151136
152137 cmd = &desc.params.vsi_cmd;
153
- res = (struct ice_aqc_add_update_free_vsi_resp *)&desc.params.raw;
138
+ res = &desc.params.add_update_free_vsi_res;
154139
155140 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi);
156141
157142 if (!vsi_ctx->alloc_from_pool)
158143 cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num |
159144 ICE_AQ_VSI_IS_VALID);
145
+ cmd->vf_id = vsi_ctx->vf_num;
160146
161147 cmd->vsi_flags = cpu_to_le16(vsi_ctx->flags);
162148
....@@ -175,14 +161,50 @@
175161 }
176162
177163 /**
164
+ * ice_aq_free_vsi
165
+ * @hw: pointer to the HW struct
166
+ * @vsi_ctx: pointer to a VSI context struct
167
+ * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
168
+ * @cd: pointer to command details structure or NULL
169
+ *
170
+ * Free VSI context info from hardware (0x0213)
171
+ */
172
+static enum ice_status
173
+ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
174
+ bool keep_vsi_alloc, struct ice_sq_cd *cd)
175
+{
176
+ struct ice_aqc_add_update_free_vsi_resp *resp;
177
+ struct ice_aqc_add_get_update_free_vsi *cmd;
178
+ struct ice_aq_desc desc;
179
+ enum ice_status status;
180
+
181
+ cmd = &desc.params.vsi_cmd;
182
+ resp = &desc.params.add_update_free_vsi_res;
183
+
184
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);
185
+
186
+ cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
187
+ if (keep_vsi_alloc)
188
+ cmd->cmd_flags = cpu_to_le16(ICE_AQ_VSI_KEEP_ALLOC);
189
+
190
+ status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
191
+ if (!status) {
192
+ vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
193
+ vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
194
+ }
195
+
196
+ return status;
197
+}
198
+
199
+/**
178200 * ice_aq_update_vsi
179
- * @hw: pointer to the hw struct
201
+ * @hw: pointer to the HW struct
180202 * @vsi_ctx: pointer to a VSI context struct
181203 * @cd: pointer to command details structure or NULL
182204 *
183205 * Update VSI context in the hardware (0x0211)
184206 */
185
-enum ice_status
207
+static enum ice_status
186208 ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
187209 struct ice_sq_cd *cd)
188210 {
....@@ -192,7 +214,7 @@
192214 enum ice_status status;
193215
194216 cmd = &desc.params.vsi_cmd;
195
- resp = (struct ice_aqc_add_update_free_vsi_resp *)&desc.params.raw;
217
+ resp = &desc.params.add_update_free_vsi_res;
196218
197219 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi);
198220
....@@ -212,45 +234,198 @@
212234 }
213235
214236 /**
215
- * ice_aq_free_vsi
216
- * @hw: pointer to the hw struct
237
+ * ice_is_vsi_valid - check whether the VSI is valid or not
238
+ * @hw: pointer to the HW struct
239
+ * @vsi_handle: VSI handle
240
+ *
241
+ * check whether the VSI is valid or not
242
+ */
243
+bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle)
244
+{
245
+ return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle];
246
+}
247
+
248
+/**
249
+ * ice_get_hw_vsi_num - return the HW VSI number
250
+ * @hw: pointer to the HW struct
251
+ * @vsi_handle: VSI handle
252
+ *
253
+ * return the HW VSI number
254
+ * Caution: call this function only if VSI is valid (ice_is_vsi_valid)
255
+ */
256
+u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle)
257
+{
258
+ return hw->vsi_ctx[vsi_handle]->vsi_num;
259
+}
260
+
261
+/**
262
+ * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle
263
+ * @hw: pointer to the HW struct
264
+ * @vsi_handle: VSI handle
265
+ *
266
+ * return the VSI context entry for a given VSI handle
267
+ */
268
+struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
269
+{
270
+ return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle];
271
+}
272
+
273
+/**
274
+ * ice_save_vsi_ctx - save the VSI context for a given VSI handle
275
+ * @hw: pointer to the HW struct
276
+ * @vsi_handle: VSI handle
277
+ * @vsi: VSI context pointer
278
+ *
279
+ * save the VSI context entry for a given VSI handle
280
+ */
281
+static void
282
+ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
283
+{
284
+ hw->vsi_ctx[vsi_handle] = vsi;
285
+}
286
+
287
+/**
288
+ * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs
289
+ * @hw: pointer to the HW struct
290
+ * @vsi_handle: VSI handle
291
+ */
292
+static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
293
+{
294
+ struct ice_vsi_ctx *vsi;
295
+ u8 i;
296
+
297
+ vsi = ice_get_vsi_ctx(hw, vsi_handle);
298
+ if (!vsi)
299
+ return;
300
+ ice_for_each_traffic_class(i) {
301
+ if (vsi->lan_q_ctx[i]) {
302
+ devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]);
303
+ vsi->lan_q_ctx[i] = NULL;
304
+ }
305
+ }
306
+}
307
+
308
+/**
309
+ * ice_clear_vsi_ctx - clear the VSI context entry
310
+ * @hw: pointer to the HW struct
311
+ * @vsi_handle: VSI handle
312
+ *
313
+ * clear the VSI context entry
314
+ */
315
+static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
316
+{
317
+ struct ice_vsi_ctx *vsi;
318
+
319
+ vsi = ice_get_vsi_ctx(hw, vsi_handle);
320
+ if (vsi) {
321
+ ice_clear_vsi_q_ctx(hw, vsi_handle);
322
+ devm_kfree(ice_hw_to_dev(hw), vsi);
323
+ hw->vsi_ctx[vsi_handle] = NULL;
324
+ }
325
+}
326
+
327
+/**
328
+ * ice_clear_all_vsi_ctx - clear all the VSI context entries
329
+ * @hw: pointer to the HW struct
330
+ */
331
+void ice_clear_all_vsi_ctx(struct ice_hw *hw)
332
+{
333
+ u16 i;
334
+
335
+ for (i = 0; i < ICE_MAX_VSI; i++)
336
+ ice_clear_vsi_ctx(hw, i);
337
+}
338
+
339
+/**
340
+ * ice_add_vsi - add VSI context to the hardware and VSI handle list
341
+ * @hw: pointer to the HW struct
342
+ * @vsi_handle: unique VSI handle provided by drivers
343
+ * @vsi_ctx: pointer to a VSI context struct
344
+ * @cd: pointer to command details structure or NULL
345
+ *
346
+ * Add a VSI context to the hardware also add it into the VSI handle list.
347
+ * If this function gets called after reset for existing VSIs then update
348
+ * with the new HW VSI number in the corresponding VSI handle list entry.
349
+ */
350
+enum ice_status
351
+ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
352
+ struct ice_sq_cd *cd)
353
+{
354
+ struct ice_vsi_ctx *tmp_vsi_ctx;
355
+ enum ice_status status;
356
+
357
+ if (vsi_handle >= ICE_MAX_VSI)
358
+ return ICE_ERR_PARAM;
359
+ status = ice_aq_add_vsi(hw, vsi_ctx, cd);
360
+ if (status)
361
+ return status;
362
+ tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
363
+ if (!tmp_vsi_ctx) {
364
+ /* Create a new VSI context */
365
+ tmp_vsi_ctx = devm_kzalloc(ice_hw_to_dev(hw),
366
+ sizeof(*tmp_vsi_ctx), GFP_KERNEL);
367
+ if (!tmp_vsi_ctx) {
368
+ ice_aq_free_vsi(hw, vsi_ctx, false, cd);
369
+ return ICE_ERR_NO_MEMORY;
370
+ }
371
+ *tmp_vsi_ctx = *vsi_ctx;
372
+ ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx);
373
+ } else {
374
+ /* update with new HW VSI num */
375
+ tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num;
376
+ }
377
+
378
+ return 0;
379
+}
380
+
381
+/**
382
+ * ice_free_vsi- free VSI context from hardware and VSI handle list
383
+ * @hw: pointer to the HW struct
384
+ * @vsi_handle: unique VSI handle
217385 * @vsi_ctx: pointer to a VSI context struct
218386 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
219387 * @cd: pointer to command details structure or NULL
220388 *
221
- * Get VSI context info from hardware (0x0213)
389
+ * Free VSI context info from hardware as well as from VSI handle list
222390 */
223391 enum ice_status
224
-ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
225
- bool keep_vsi_alloc, struct ice_sq_cd *cd)
392
+ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
393
+ bool keep_vsi_alloc, struct ice_sq_cd *cd)
226394 {
227
- struct ice_aqc_add_update_free_vsi_resp *resp;
228
- struct ice_aqc_add_get_update_free_vsi *cmd;
229
- struct ice_aq_desc desc;
230395 enum ice_status status;
231396
232
- cmd = &desc.params.vsi_cmd;
233
- resp = (struct ice_aqc_add_update_free_vsi_resp *)&desc.params.raw;
234
-
235
- ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);
236
-
237
- cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
238
- if (keep_vsi_alloc)
239
- cmd->cmd_flags = cpu_to_le16(ICE_AQ_VSI_KEEP_ALLOC);
240
-
241
- status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
242
- if (!status) {
243
- vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
244
- vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
245
- }
246
-
397
+ if (!ice_is_vsi_valid(hw, vsi_handle))
398
+ return ICE_ERR_PARAM;
399
+ vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
400
+ status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd);
401
+ if (!status)
402
+ ice_clear_vsi_ctx(hw, vsi_handle);
247403 return status;
248404 }
249405
250406 /**
407
+ * ice_update_vsi
408
+ * @hw: pointer to the HW struct
409
+ * @vsi_handle: unique VSI handle
410
+ * @vsi_ctx: pointer to a VSI context struct
411
+ * @cd: pointer to command details structure or NULL
412
+ *
413
+ * Update VSI context in the hardware
414
+ */
415
+enum ice_status
416
+ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
417
+ struct ice_sq_cd *cd)
418
+{
419
+ if (!ice_is_vsi_valid(hw, vsi_handle))
420
+ return ICE_ERR_PARAM;
421
+ vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
422
+ return ice_aq_update_vsi(hw, vsi_ctx, cd);
423
+}
424
+
425
+/**
251426 * ice_aq_alloc_free_vsi_list
252
- * @hw: pointer to the hw struct
253
- * @vsi_list_id: VSI list id returned or used for lookup
427
+ * @hw: pointer to the HW struct
428
+ * @vsi_list_id: VSI list ID returned or used for lookup
254429 * @lkup_type: switch rule filter lookup type
255430 * @opc: switch rules population command type - pass in the command opcode
256431 *
....@@ -266,7 +441,7 @@
266441 enum ice_status status;
267442 u16 buf_len;
268443
269
- buf_len = sizeof(*sw_buf);
444
+ buf_len = struct_size(sw_buf, elem, 1);
270445 sw_buf = devm_kzalloc(ice_hw_to_dev(hw), buf_len, GFP_KERNEL);
271446 if (!sw_buf)
272447 return ICE_ERR_NO_MEMORY;
....@@ -306,7 +481,7 @@
306481
307482 /**
308483 * ice_aq_sw_rules - add/update/remove switch rules
309
- * @hw: pointer to the hw struct
484
+ * @hw: pointer to the HW struct
310485 * @rule_list: pointer to switch rule population list
311486 * @rule_list_sz: total size of the rule list in bytes
312487 * @num_rules: number of switch rules in the rule_list
....@@ -320,6 +495,7 @@
320495 u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
321496 {
322497 struct ice_aq_desc desc;
498
+ enum ice_status status;
323499
324500 if (opc != ice_aqc_opc_add_sw_rules &&
325501 opc != ice_aqc_opc_update_sw_rules &&
....@@ -331,7 +507,12 @@
331507 desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
332508 desc.params.sw_rules.num_rules_fltr_entry_index =
333509 cpu_to_le16(num_rules);
334
- return ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
510
+ status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
511
+ if (opc != ice_aqc_opc_add_sw_rules &&
512
+ hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
513
+ status = ICE_ERR_DOES_NOT_EXIST;
514
+
515
+ return status;
335516 }
336517
337518 /* ice_init_port_info - Initialize port_info with switch configuration data
....@@ -367,7 +548,7 @@
367548 */
368549 enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw)
369550 {
370
- struct ice_aqc_get_sw_cfg_resp *rbuf;
551
+ struct ice_aqc_get_sw_cfg_resp_elem *rbuf;
371552 enum ice_status status;
372553 u16 req_desc = 0;
373554 u16 num_elems;
....@@ -385,19 +566,19 @@
385566 * writing a non-zero value in req_desc
386567 */
387568 do {
569
+ struct ice_aqc_get_sw_cfg_resp_elem *ele;
570
+
388571 status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
389572 &req_desc, &num_elems, NULL);
390573
391574 if (status)
392575 break;
393576
394
- for (i = 0; i < num_elems; i++) {
395
- struct ice_aqc_get_sw_cfg_resp_elem *ele;
577
+ for (i = 0, ele = rbuf; i < num_elems; i++, ele++) {
396578 u16 pf_vf_num, swid, vsi_port_num;
397579 bool is_vf = false;
398
- u8 type;
580
+ u8 res_type;
399581
400
- ele = rbuf[i].elements;
401582 vsi_port_num = le16_to_cpu(ele->vsi_port_num) &
402583 ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
403584
....@@ -410,16 +591,16 @@
410591 ICE_AQC_GET_SW_CONF_RESP_IS_VF)
411592 is_vf = true;
412593
413
- type = le16_to_cpu(ele->vsi_port_num) >>
414
- ICE_AQC_GET_SW_CONF_RESP_TYPE_S;
594
+ res_type = (u8)(le16_to_cpu(ele->vsi_port_num) >>
595
+ ICE_AQC_GET_SW_CONF_RESP_TYPE_S);
415596
416
- if (type == ICE_AQC_GET_SW_CONF_RESP_VSI) {
597
+ if (res_type == ICE_AQC_GET_SW_CONF_RESP_VSI) {
417598 /* FW VSI is not needed. Just continue. */
418599 continue;
419600 }
420601
421602 ice_init_port_info(hw->port_info, vsi_port_num,
422
- type, swid, pf_vf_num, is_vf);
603
+ res_type, swid, pf_vf_num, is_vf);
423604 }
424605 } while (req_desc && !status);
425606
....@@ -430,25 +611,58 @@
430611 /**
431612 * ice_fill_sw_info - Helper function to populate lb_en and lan_en
432613 * @hw: pointer to the hardware structure
433
- * @f_info: filter info structure to fill/update
614
+ * @fi: filter info structure to fill/update
434615 *
435616 * This helper function populates the lb_en and lan_en elements of the provided
436617 * ice_fltr_info struct using the switch's type and characteristics of the
437618 * switch rule being configured.
438619 */
439
-static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *f_info)
620
+static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi)
440621 {
441
- f_info->lb_en = false;
442
- f_info->lan_en = false;
443
- if ((f_info->flag & ICE_FLTR_TX) &&
444
- (f_info->fltr_act == ICE_FWD_TO_VSI ||
445
- f_info->fltr_act == ICE_FWD_TO_VSI_LIST ||
446
- f_info->fltr_act == ICE_FWD_TO_Q ||
447
- f_info->fltr_act == ICE_FWD_TO_QGRP)) {
448
- f_info->lb_en = true;
449
- if (!(hw->evb_veb && f_info->lkup_type == ICE_SW_LKUP_MAC &&
450
- is_unicast_ether_addr(f_info->l_data.mac.mac_addr)))
451
- f_info->lan_en = true;
622
+ fi->lb_en = false;
623
+ fi->lan_en = false;
624
+ if ((fi->flag & ICE_FLTR_TX) &&
625
+ (fi->fltr_act == ICE_FWD_TO_VSI ||
626
+ fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
627
+ fi->fltr_act == ICE_FWD_TO_Q ||
628
+ fi->fltr_act == ICE_FWD_TO_QGRP)) {
629
+ /* Setting LB for prune actions will result in replicated
630
+ * packets to the internal switch that will be dropped.
631
+ */
632
+ if (fi->lkup_type != ICE_SW_LKUP_VLAN)
633
+ fi->lb_en = true;
634
+
635
+ /* Set lan_en to TRUE if
636
+ * 1. The switch is a VEB AND
637
+ * 2
638
+ * 2.1 The lookup is a directional lookup like ethertype,
639
+ * promiscuous, ethertype-MAC, promiscuous-VLAN
640
+ * and default-port OR
641
+ * 2.2 The lookup is VLAN, OR
642
+ * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR
643
+ * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC.
644
+ *
645
+ * OR
646
+ *
647
+ * The switch is a VEPA.
648
+ *
649
+ * In all other cases, the LAN enable has to be set to false.
650
+ */
651
+ if (hw->evb_veb) {
652
+ if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE ||
653
+ fi->lkup_type == ICE_SW_LKUP_PROMISC ||
654
+ fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
655
+ fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
656
+ fi->lkup_type == ICE_SW_LKUP_DFLT ||
657
+ fi->lkup_type == ICE_SW_LKUP_VLAN ||
658
+ (fi->lkup_type == ICE_SW_LKUP_MAC &&
659
+ !is_unicast_ether_addr(fi->l_data.mac.mac_addr)) ||
660
+ (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN &&
661
+ !is_unicast_ether_addr(fi->l_data.mac.mac_addr)))
662
+ fi->lan_en = true;
663
+ } else {
664
+ fi->lan_en = true;
665
+ }
452666 }
453667 }
454668
....@@ -464,8 +678,9 @@
464678 struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc)
465679 {
466680 u16 vlan_id = ICE_MAX_VLAN_ID + 1;
467
- u8 eth_hdr[DUMMY_ETH_HDR_LEN];
468681 void *daddr = NULL;
682
+ u16 eth_hdr_sz;
683
+ u8 *eth_hdr;
469684 u32 act = 0;
470685 __be16 *off;
471686 u8 q_rgn;
....@@ -478,13 +693,16 @@
478693 return;
479694 }
480695
696
+ eth_hdr_sz = sizeof(dummy_eth_header);
697
+ eth_hdr = s_rule->pdata.lkup_tx_rx.hdr;
698
+
481699 /* initialize the ether header with a dummy header */
482
- memcpy(eth_hdr, dummy_eth_header, sizeof(dummy_eth_header));
700
+ memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz);
483701 ice_fill_sw_info(hw, f_info);
484702
485703 switch (f_info->fltr_act) {
486704 case ICE_FWD_TO_VSI:
487
- act |= (f_info->fwd_id.vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
705
+ act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
488706 ICE_SINGLE_ACT_VSI_ID_M;
489707 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
490708 act |= ICE_SINGLE_ACT_VSI_FORWARDING |
....@@ -540,9 +758,9 @@
540758 break;
541759 case ICE_SW_LKUP_ETHERTYPE_MAC:
542760 daddr = f_info->l_data.ethertype_mac.mac_addr;
543
- /* fall-through */
761
+ fallthrough;
544762 case ICE_SW_LKUP_ETHERTYPE:
545
- off = (__be16 *)&eth_hdr[ICE_ETH_ETHTYPE_OFFSET];
763
+ off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
546764 *off = cpu_to_be16(f_info->l_data.ethertype_mac.ethertype);
547765 break;
548766 case ICE_SW_LKUP_MAC_VLAN:
....@@ -551,7 +769,7 @@
551769 break;
552770 case ICE_SW_LKUP_PROMISC_VLAN:
553771 vlan_id = f_info->l_data.mac_vlan.vlan_id;
554
- /* fall-through */
772
+ fallthrough;
555773 case ICE_SW_LKUP_PROMISC:
556774 daddr = f_info->l_data.mac_vlan.mac_addr;
557775 break;
....@@ -569,18 +787,16 @@
569787 s_rule->pdata.lkup_tx_rx.act = cpu_to_le32(act);
570788
571789 if (daddr)
572
- ether_addr_copy(&eth_hdr[ICE_ETH_DA_OFFSET], daddr);
790
+ ether_addr_copy(eth_hdr + ICE_ETH_DA_OFFSET, daddr);
573791
574792 if (!(vlan_id > ICE_MAX_VLAN_ID)) {
575
- off = (__be16 *)&eth_hdr[ICE_ETH_VLAN_TCI_OFFSET];
793
+ off = (__force __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
576794 *off = cpu_to_be16(vlan_id);
577795 }
578796
579797 /* Create the switch rule with the final dummy Ethernet header */
580798 if (opc != ice_aqc_opc_update_sw_rules)
581
- s_rule->pdata.lkup_tx_rx.hdr_len = cpu_to_le16(sizeof(eth_hdr));
582
-
583
- memcpy(s_rule->pdata.lkup_tx_rx.hdr, eth_hdr, sizeof(eth_hdr));
799
+ s_rule->pdata.lkup_tx_rx.hdr_len = cpu_to_le16(eth_hdr_sz);
584800 }
585801
586802 /**
....@@ -588,7 +804,7 @@
588804 * @hw: pointer to the hardware structure
589805 * @m_ent: the management entry for which sw marker needs to be added
590806 * @sw_marker: sw marker to tag the Rx descriptor with
591
- * @l_id: large action resource id
807
+ * @l_id: large action resource ID
592808 *
593809 * Create a large action to hold software marker and update the switch rule
594810 * entry pointed by m_ent with newly created large action
....@@ -600,15 +816,15 @@
600816 struct ice_aqc_sw_rules_elem *lg_act, *rx_tx;
601817 /* For software marker we need 3 large actions
602818 * 1. FWD action: FWD TO VSI or VSI LIST
603
- * 2. GENERIC VALUE action to hold the profile id
604
- * 3. GENERIC VALUE action to hold the software marker id
819
+ * 2. GENERIC VALUE action to hold the profile ID
820
+ * 3. GENERIC VALUE action to hold the software marker ID
605821 */
606822 const u16 num_lg_acts = 3;
607823 enum ice_status status;
608824 u16 lg_act_size;
609825 u16 rules_size;
610
- u16 vsi_info;
611826 u32 act;
827
+ u16 id;
612828
613829 if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
614830 return ICE_ERR_PARAM;
....@@ -616,7 +832,7 @@
616832 /* Create two back-to-back switch rules and submit them to the HW using
617833 * one memory buffer:
618834 * 1. Large Action
619
- * 2. Look up tx rx
835
+ * 2. Look up Tx Rx
620836 */
621837 lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts);
622838 rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
....@@ -634,13 +850,11 @@
634850 /* First action VSI forwarding or VSI list forwarding depending on how
635851 * many VSIs
636852 */
637
- vsi_info = (m_ent->vsi_count > 1) ?
638
- m_ent->fltr_info.fwd_id.vsi_list_id :
639
- m_ent->fltr_info.fwd_id.vsi_id;
853
+ id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
854
+ m_ent->fltr_info.fwd_id.hw_vsi_id;
640855
641856 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
642
- act |= (vsi_info << ICE_LG_ACT_VSI_LIST_ID_S) &
643
- ICE_LG_ACT_VSI_LIST_ID_M;
857
+ act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M;
644858 if (m_ent->vsi_count > 1)
645859 act |= ICE_LG_ACT_VSI_LIST;
646860 lg_act->pdata.lg_act.act[0] = cpu_to_le32(act);
....@@ -661,17 +875,17 @@
661875
662876 lg_act->pdata.lg_act.act[2] = cpu_to_le32(act);
663877
664
- /* call the fill switch rule to fill the lookup tx rx structure */
878
+ /* call the fill switch rule to fill the lookup Tx Rx structure */
665879 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
666880 ice_aqc_opc_update_sw_rules);
667881
668
- /* Update the action to point to the large action id */
882
+ /* Update the action to point to the large action ID */
669883 rx_tx->pdata.lkup_tx_rx.act =
670884 cpu_to_le32(ICE_SINGLE_ACT_PTR |
671885 ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
672886 ICE_SINGLE_ACT_PTR_VAL_M));
673887
674
- /* Use the filter rule id of the previously created rule with single
888
+ /* Use the filter rule ID of the previously created rule with single
675889 * act. Once the update happens, hardware will treat this as large
676890 * action
677891 */
....@@ -692,15 +906,15 @@
692906 /**
693907 * ice_create_vsi_list_map
694908 * @hw: pointer to the hardware structure
695
- * @vsi_array: array of VSIs to form a VSI list
696
- * @num_vsi: num VSI in the array
697
- * @vsi_list_id: VSI list id generated as part of allocate resource
909
+ * @vsi_handle_arr: array of VSI handles to set in the VSI mapping
910
+ * @num_vsi: number of VSI handles in the array
911
+ * @vsi_list_id: VSI list ID generated as part of allocate resource
698912 *
699
- * Helper function to create a new entry of VSI list id to VSI mapping
700
- * using the given VSI list id
913
+ * Helper function to create a new entry of VSI list ID to VSI mapping
914
+ * using the given VSI list ID
701915 */
702916 static struct ice_vsi_list_map_info *
703
-ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_array, u16 num_vsi,
917
+ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
704918 u16 vsi_list_id)
705919 {
706920 struct ice_switch_info *sw = hw->switch_info;
....@@ -712,9 +926,9 @@
712926 return NULL;
713927
714928 v_map->vsi_list_id = vsi_list_id;
715
-
929
+ v_map->ref_cnt = 1;
716930 for (i = 0; i < num_vsi; i++)
717
- set_bit(vsi_array[i], v_map->vsi_map);
931
+ set_bit(vsi_handle_arr[i], v_map->vsi_map);
718932
719933 list_add(&v_map->list_entry, &sw->vsi_list_map_head);
720934 return v_map;
....@@ -723,25 +937,25 @@
723937 /**
724938 * ice_update_vsi_list_rule
725939 * @hw: pointer to the hardware structure
726
- * @vsi_array: array of VSIs to form a VSI list
727
- * @num_vsi: num VSI in the array
728
- * @vsi_list_id: VSI list id generated as part of allocate resource
940
+ * @vsi_handle_arr: array of VSI handles to form a VSI list
941
+ * @num_vsi: number of VSI handles in the array
942
+ * @vsi_list_id: VSI list ID generated as part of allocate resource
729943 * @remove: Boolean value to indicate if this is a remove action
730944 * @opc: switch rules population command type - pass in the command opcode
731945 * @lkup_type: lookup type of the filter
732946 *
733947 * Call AQ command to add a new switch rule or update existing switch rule
734
- * using the given VSI list id
948
+ * using the given VSI list ID
735949 */
736950 static enum ice_status
737
-ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_array, u16 num_vsi,
951
+ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
738952 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
739953 enum ice_sw_lkup_type lkup_type)
740954 {
741955 struct ice_aqc_sw_rules_elem *s_rule;
742956 enum ice_status status;
743957 u16 s_rule_size;
744
- u16 type;
958
+ u16 rule_type;
745959 int i;
746960
747961 if (!num_vsi)
....@@ -753,11 +967,11 @@
753967 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
754968 lkup_type == ICE_SW_LKUP_PROMISC ||
755969 lkup_type == ICE_SW_LKUP_PROMISC_VLAN)
756
- type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
757
- ICE_AQC_SW_RULES_T_VSI_LIST_SET;
970
+ rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
971
+ ICE_AQC_SW_RULES_T_VSI_LIST_SET;
758972 else if (lkup_type == ICE_SW_LKUP_VLAN)
759
- type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
760
- ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
973
+ rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
974
+ ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
761975 else
762976 return ICE_ERR_PARAM;
763977
....@@ -765,38 +979,40 @@
765979 s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
766980 if (!s_rule)
767981 return ICE_ERR_NO_MEMORY;
982
+ for (i = 0; i < num_vsi; i++) {
983
+ if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) {
984
+ status = ICE_ERR_PARAM;
985
+ goto exit;
986
+ }
987
+ /* AQ call requires hw_vsi_id(s) */
988
+ s_rule->pdata.vsi_list.vsi[i] =
989
+ cpu_to_le16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i]));
990
+ }
768991
769
- for (i = 0; i < num_vsi; i++)
770
- s_rule->pdata.vsi_list.vsi[i] = cpu_to_le16(vsi_array[i]);
771
-
772
- s_rule->type = cpu_to_le16(type);
992
+ s_rule->type = cpu_to_le16(rule_type);
773993 s_rule->pdata.vsi_list.number_vsi = cpu_to_le16(num_vsi);
774994 s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_id);
775995
776996 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
777997
998
+exit:
778999 devm_kfree(ice_hw_to_dev(hw), s_rule);
7791000 return status;
7801001 }
7811002
7821003 /**
7831004 * ice_create_vsi_list_rule - Creates and populates a VSI list rule
784
- * @hw: pointer to the hw struct
785
- * @vsi_array: array of VSIs to form a VSI list
786
- * @num_vsi: number of VSIs in the array
1005
+ * @hw: pointer to the HW struct
1006
+ * @vsi_handle_arr: array of VSI handles to form a VSI list
1007
+ * @num_vsi: number of VSI handles in the array
7871008 * @vsi_list_id: stores the ID of the VSI list to be created
7881009 * @lkup_type: switch rule filter's lookup type
7891010 */
7901011 static enum ice_status
791
-ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_array, u16 num_vsi,
1012
+ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
7921013 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
7931014 {
7941015 enum ice_status status;
795
- int i;
796
-
797
- for (i = 0; i < num_vsi; i++)
798
- if (vsi_array[i] >= ICE_MAX_VSI)
799
- return ICE_ERR_OUT_OF_RANGE;
8001016
8011017 status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
8021018 ice_aqc_opc_alloc_res);
....@@ -804,9 +1020,9 @@
8041020 return status;
8051021
8061022 /* Update the newly created VSI list to include the specified VSIs */
807
- return ice_update_vsi_list_rule(hw, vsi_array, num_vsi, *vsi_list_id,
808
- false, ice_aqc_opc_add_sw_rules,
809
- lkup_type);
1023
+ return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi,
1024
+ *vsi_list_id, false,
1025
+ ice_aqc_opc_add_sw_rules, lkup_type);
8101026 }
8111027
8121028 /**
....@@ -822,10 +1038,10 @@
8221038 ice_create_pkt_fwd_rule(struct ice_hw *hw,
8231039 struct ice_fltr_list_entry *f_entry)
8241040 {
825
- struct ice_switch_info *sw = hw->switch_info;
8261041 struct ice_fltr_mgmt_list_entry *fm_entry;
8271042 struct ice_aqc_sw_rules_elem *s_rule;
8281043 enum ice_sw_lkup_type l_type;
1044
+ struct ice_sw_recipe *recp;
8291045 enum ice_status status;
8301046
8311047 s_rule = devm_kzalloc(ice_hw_to_dev(hw),
....@@ -866,31 +1082,9 @@
8661082 * calls remove filter AQ command
8671083 */
8681084 l_type = fm_entry->fltr_info.lkup_type;
869
- if (l_type == ICE_SW_LKUP_MAC) {
870
- mutex_lock(&sw->mac_list_lock);
871
- list_add(&fm_entry->list_entry, &sw->mac_list_head);
872
- mutex_unlock(&sw->mac_list_lock);
873
- } else if (l_type == ICE_SW_LKUP_VLAN) {
874
- mutex_lock(&sw->vlan_list_lock);
875
- list_add(&fm_entry->list_entry, &sw->vlan_list_head);
876
- mutex_unlock(&sw->vlan_list_lock);
877
- } else if (l_type == ICE_SW_LKUP_ETHERTYPE ||
878
- l_type == ICE_SW_LKUP_ETHERTYPE_MAC) {
879
- mutex_lock(&sw->eth_m_list_lock);
880
- list_add(&fm_entry->list_entry, &sw->eth_m_list_head);
881
- mutex_unlock(&sw->eth_m_list_lock);
882
- } else if (l_type == ICE_SW_LKUP_PROMISC ||
883
- l_type == ICE_SW_LKUP_PROMISC_VLAN) {
884
- mutex_lock(&sw->promisc_list_lock);
885
- list_add(&fm_entry->list_entry, &sw->promisc_list_head);
886
- mutex_unlock(&sw->promisc_list_lock);
887
- } else if (fm_entry->fltr_info.lkup_type == ICE_SW_LKUP_MAC_VLAN) {
888
- mutex_lock(&sw->mac_vlan_list_lock);
889
- list_add(&fm_entry->list_entry, &sw->mac_vlan_list_head);
890
- mutex_unlock(&sw->mac_vlan_list_lock);
891
- } else {
892
- status = ICE_ERR_NOT_IMPL;
893
- }
1085
+ recp = &hw->switch_info->recp_list[l_type];
1086
+ list_add(&fm_entry->list_entry, &recp->filt_rules);
1087
+
8941088 ice_create_pkt_fwd_rule_exit:
8951089 devm_kfree(ice_hw_to_dev(hw), s_rule);
8961090 return status;
....@@ -899,19 +1093,15 @@
8991093 /**
9001094 * ice_update_pkt_fwd_rule
9011095 * @hw: pointer to the hardware structure
902
- * @rule_id: rule of previously created switch rule to update
903
- * @vsi_list_id: VSI list id to be updated with
904
- * @f_info: ice_fltr_info to pull other information for switch rule
1096
+ * @f_info: filter information for switch rule
9051097 *
9061098 * Call AQ command to update a previously created switch rule with a
907
- * VSI list id
1099
+ * VSI list ID
9081100 */
9091101 static enum ice_status
910
-ice_update_pkt_fwd_rule(struct ice_hw *hw, u16 rule_id, u16 vsi_list_id,
911
- struct ice_fltr_info f_info)
1102
+ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info)
9121103 {
9131104 struct ice_aqc_sw_rules_elem *s_rule;
914
- struct ice_fltr_info tmp_fltr;
9151105 enum ice_status status;
9161106
9171107 s_rule = devm_kzalloc(ice_hw_to_dev(hw),
....@@ -919,14 +1109,9 @@
9191109 if (!s_rule)
9201110 return ICE_ERR_NO_MEMORY;
9211111
922
- tmp_fltr = f_info;
923
- tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
924
- tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
1112
+ ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules);
9251113
926
- ice_fill_sw_rule(hw, &tmp_fltr, s_rule,
927
- ice_aqc_opc_update_sw_rules);
928
-
929
- s_rule->pdata.lkup_tx_rx.index = cpu_to_le16(rule_id);
1114
+ s_rule->pdata.lkup_tx_rx.index = cpu_to_le16(f_info->fltr_rule_id);
9301115
9311116 /* Update switch rule with new rule set to forward VSI list */
9321117 status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
....@@ -937,7 +1122,48 @@
9371122 }
9381123
9391124 /**
940
- * ice_handle_vsi_list_mgmt
1125
+ * ice_update_sw_rule_bridge_mode
1126
+ * @hw: pointer to the HW struct
1127
+ *
1128
+ * Updates unicast switch filter rules based on VEB/VEPA mode
1129
+ */
1130
+enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw)
1131
+{
1132
+ struct ice_switch_info *sw = hw->switch_info;
1133
+ struct ice_fltr_mgmt_list_entry *fm_entry;
1134
+ enum ice_status status = 0;
1135
+ struct list_head *rule_head;
1136
+ struct mutex *rule_lock; /* Lock to protect filter rule list */
1137
+
1138
+ rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
1139
+ rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
1140
+
1141
+ mutex_lock(rule_lock);
1142
+ list_for_each_entry(fm_entry, rule_head, list_entry) {
1143
+ struct ice_fltr_info *fi = &fm_entry->fltr_info;
1144
+ u8 *addr = fi->l_data.mac.mac_addr;
1145
+
1146
+ /* Update unicast Tx rules to reflect the selected
1147
+ * VEB/VEPA mode
1148
+ */
1149
+ if ((fi->flag & ICE_FLTR_TX) && is_unicast_ether_addr(addr) &&
1150
+ (fi->fltr_act == ICE_FWD_TO_VSI ||
1151
+ fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
1152
+ fi->fltr_act == ICE_FWD_TO_Q ||
1153
+ fi->fltr_act == ICE_FWD_TO_QGRP)) {
1154
+ status = ice_update_pkt_fwd_rule(hw, fi);
1155
+ if (status)
1156
+ break;
1157
+ }
1158
+ }
1159
+
1160
+ mutex_unlock(rule_lock);
1161
+
1162
+ return status;
1163
+}
1164
+
1165
+/**
1166
+ * ice_add_update_vsi_list
9411167 * @hw: pointer to the hardware structure
9421168 * @m_entry: pointer to current filter management list entry
9431169 * @cur_fltr: filter information from the book keeping entry
....@@ -946,22 +1172,22 @@
9461172 * Call AQ command to add or update previously created VSI list with new VSI.
9471173 *
9481174 * Helper function to do book keeping associated with adding filter information
949
- * The algorithm to do the booking keeping is described below :
950
- * When a VSI needs to subscribe to a given filter( MAC/VLAN/Ethtype etc.)
1175
+ * The algorithm to do the book keeping is described below :
1176
+ * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.)
9511177 * if only one VSI has been added till now
9521178 * Allocate a new VSI list and add two VSIs
9531179 * to this list using switch rule command
9541180 * Update the previously created switch rule with the
955
- * newly created VSI list id
1181
+ * newly created VSI list ID
9561182 * if a VSI list was previously created
9571183 * Add the new VSI to the previously created VSI list set
9581184 * using the update switch rule command
9591185 */
9601186 static enum ice_status
961
-ice_handle_vsi_list_mgmt(struct ice_hw *hw,
962
- struct ice_fltr_mgmt_list_entry *m_entry,
963
- struct ice_fltr_info *cur_fltr,
964
- struct ice_fltr_info *new_fltr)
1187
+ice_add_update_vsi_list(struct ice_hw *hw,
1188
+ struct ice_fltr_mgmt_list_entry *m_entry,
1189
+ struct ice_fltr_info *cur_fltr,
1190
+ struct ice_fltr_info *new_fltr)
9651191 {
9661192 enum ice_status status = 0;
9671193 u16 vsi_list_id = 0;
....@@ -981,35 +1207,40 @@
9811207 * a part of a VSI list. So, create a VSI list with the old and
9821208 * new VSIs.
9831209 */
984
- u16 vsi_id_arr[2];
985
- u16 fltr_rule;
1210
+ struct ice_fltr_info tmp_fltr;
1211
+ u16 vsi_handle_arr[2];
9861212
9871213 /* A rule already exists with the new VSI being added */
988
- if (cur_fltr->fwd_id.vsi_id == new_fltr->fwd_id.vsi_id)
1214
+ if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
9891215 return ICE_ERR_ALREADY_EXISTS;
9901216
991
- vsi_id_arr[0] = cur_fltr->fwd_id.vsi_id;
992
- vsi_id_arr[1] = new_fltr->fwd_id.vsi_id;
993
- status = ice_create_vsi_list_rule(hw, &vsi_id_arr[0], 2,
1217
+ vsi_handle_arr[0] = cur_fltr->vsi_handle;
1218
+ vsi_handle_arr[1] = new_fltr->vsi_handle;
1219
+ status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
9941220 &vsi_list_id,
9951221 new_fltr->lkup_type);
9961222 if (status)
9971223 return status;
9981224
999
- fltr_rule = cur_fltr->fltr_rule_id;
1225
+ tmp_fltr = *new_fltr;
1226
+ tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
1227
+ tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
1228
+ tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
10001229 /* Update the previous switch rule of "MAC forward to VSI" to
10011230 * "MAC fwd to VSI list"
10021231 */
1003
- status = ice_update_pkt_fwd_rule(hw, fltr_rule, vsi_list_id,
1004
- *new_fltr);
1232
+ status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
10051233 if (status)
10061234 return status;
10071235
10081236 cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
10091237 cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
10101238 m_entry->vsi_list_info =
1011
- ice_create_vsi_list_map(hw, &vsi_id_arr[0], 2,
1239
+ ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
10121240 vsi_list_id);
1241
+
1242
+ if (!m_entry->vsi_list_info)
1243
+ return ICE_ERR_NO_MEMORY;
10131244
10141245 /* If this entry was large action then the large action needs
10151246 * to be updated to point to FWD to VSI list
....@@ -1020,28 +1251,28 @@
10201251 m_entry->sw_marker_id,
10211252 m_entry->lg_act_idx);
10221253 } else {
1023
- u16 vsi_id = new_fltr->fwd_id.vsi_id;
1254
+ u16 vsi_handle = new_fltr->vsi_handle;
10241255 enum ice_adminq_opc opcode;
10251256
10261257 if (!m_entry->vsi_list_info)
10271258 return ICE_ERR_CFG;
10281259
10291260 /* A rule already exists with the new VSI being added */
1030
- if (test_bit(vsi_id, m_entry->vsi_list_info->vsi_map))
1261
+ if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
10311262 return 0;
10321263
10331264 /* Update the previously created VSI list set with
1034
- * the new VSI id passed in
1265
+ * the new VSI ID passed in
10351266 */
10361267 vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
10371268 opcode = ice_aqc_opc_update_sw_rules;
10381269
1039
- status = ice_update_vsi_list_rule(hw, &vsi_id, 1, vsi_list_id,
1040
- false, opcode,
1270
+ status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
1271
+ vsi_list_id, false, opcode,
10411272 new_fltr->lkup_type);
1042
- /* update VSI list mapping info with new VSI id */
1273
+ /* update VSI list mapping info with new VSI ID */
10431274 if (!status)
1044
- set_bit(vsi_id, m_entry->vsi_list_info->vsi_map);
1275
+ set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map);
10451276 }
10461277 if (!status)
10471278 m_entry->vsi_count++;
....@@ -1049,299 +1280,119 @@
10491280 }
10501281
10511282 /**
1052
- * ice_find_mac_entry
1283
+ * ice_find_rule_entry - Search a rule entry
10531284 * @hw: pointer to the hardware structure
1054
- * @mac_addr: MAC address to search for
1285
+ * @recp_id: lookup type for which the specified rule needs to be searched
1286
+ * @f_info: rule information
10551287 *
1056
- * Helper function to search for a MAC entry using a given MAC address
1057
- * Returns pointer to the entry if found.
1288
+ * Helper function to search for a given rule entry
1289
+ * Returns pointer to entry storing the rule if found
10581290 */
10591291 static struct ice_fltr_mgmt_list_entry *
1060
-ice_find_mac_entry(struct ice_hw *hw, u8 *mac_addr)
1292
+ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info)
10611293 {
1062
- struct ice_fltr_mgmt_list_entry *m_list_itr, *mac_ret = NULL;
1294
+ struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL;
10631295 struct ice_switch_info *sw = hw->switch_info;
1296
+ struct list_head *list_head;
10641297
1065
- mutex_lock(&sw->mac_list_lock);
1066
- list_for_each_entry(m_list_itr, &sw->mac_list_head, list_entry) {
1067
- u8 *buf = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
1068
-
1069
- if (ether_addr_equal(buf, mac_addr)) {
1070
- mac_ret = m_list_itr;
1298
+ list_head = &sw->recp_list[recp_id].filt_rules;
1299
+ list_for_each_entry(list_itr, list_head, list_entry) {
1300
+ if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
1301
+ sizeof(f_info->l_data)) &&
1302
+ f_info->flag == list_itr->fltr_info.flag) {
1303
+ ret = list_itr;
10711304 break;
10721305 }
10731306 }
1074
- mutex_unlock(&sw->mac_list_lock);
1075
- return mac_ret;
1307
+ return ret;
10761308 }
10771309
10781310 /**
1079
- * ice_add_shared_mac - Add one MAC shared filter rule
1311
+ * ice_find_vsi_list_entry - Search VSI list map with VSI count 1
10801312 * @hw: pointer to the hardware structure
1313
+ * @recp_id: lookup type for which VSI lists needs to be searched
1314
+ * @vsi_handle: VSI handle to be found in VSI list
1315
+ * @vsi_list_id: VSI list ID found containing vsi_handle
1316
+ *
1317
+ * Helper function to search a VSI list with single entry containing given VSI
1318
+ * handle element. This can be extended further to search VSI list with more
1319
+ * than 1 vsi_count. Returns pointer to VSI list entry if found.
1320
+ */
1321
+static struct ice_vsi_list_map_info *
1322
+ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle,
1323
+ u16 *vsi_list_id)
1324
+{
1325
+ struct ice_vsi_list_map_info *map_info = NULL;
1326
+ struct ice_switch_info *sw = hw->switch_info;
1327
+ struct ice_fltr_mgmt_list_entry *list_itr;
1328
+ struct list_head *list_head;
1329
+
1330
+ list_head = &sw->recp_list[recp_id].filt_rules;
1331
+ list_for_each_entry(list_itr, list_head, list_entry) {
1332
+ if (list_itr->vsi_count == 1 && list_itr->vsi_list_info) {
1333
+ map_info = list_itr->vsi_list_info;
1334
+ if (test_bit(vsi_handle, map_info->vsi_map)) {
1335
+ *vsi_list_id = map_info->vsi_list_id;
1336
+ return map_info;
1337
+ }
1338
+ }
1339
+ }
1340
+ return NULL;
1341
+}
1342
+
1343
+/**
1344
+ * ice_add_rule_internal - add rule for a given lookup type
1345
+ * @hw: pointer to the hardware structure
1346
+ * @recp_id: lookup type (recipe ID) for which rule has to be added
10811347 * @f_entry: structure containing MAC forwarding information
10821348 *
1083
- * Adds or updates the book keeping list for the MAC addresses
1349
+ * Adds or updates the rule lists for a given recipe
10841350 */
10851351 static enum ice_status
1086
-ice_add_shared_mac(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
1352
+ice_add_rule_internal(struct ice_hw *hw, u8 recp_id,
1353
+ struct ice_fltr_list_entry *f_entry)
10871354 {
1355
+ struct ice_switch_info *sw = hw->switch_info;
10881356 struct ice_fltr_info *new_fltr, *cur_fltr;
10891357 struct ice_fltr_mgmt_list_entry *m_entry;
1358
+ struct mutex *rule_lock; /* Lock to protect filter rule list */
1359
+ enum ice_status status = 0;
10901360
1361
+ if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1362
+ return ICE_ERR_PARAM;
1363
+ f_entry->fltr_info.fwd_id.hw_vsi_id =
1364
+ ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1365
+
1366
+ rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
1367
+
1368
+ mutex_lock(rule_lock);
10911369 new_fltr = &f_entry->fltr_info;
1370
+ if (new_fltr->flag & ICE_FLTR_RX)
1371
+ new_fltr->src = hw->port_info->lport;
1372
+ else if (new_fltr->flag & ICE_FLTR_TX)
1373
+ new_fltr->src = f_entry->fltr_info.fwd_id.hw_vsi_id;
10921374
1093
- m_entry = ice_find_mac_entry(hw, &new_fltr->l_data.mac.mac_addr[0]);
1094
- if (!m_entry)
1375
+ m_entry = ice_find_rule_entry(hw, recp_id, new_fltr);
1376
+ if (!m_entry) {
1377
+ mutex_unlock(rule_lock);
10951378 return ice_create_pkt_fwd_rule(hw, f_entry);
1379
+ }
10961380
10971381 cur_fltr = &m_entry->fltr_info;
1382
+ status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr);
1383
+ mutex_unlock(rule_lock);
10981384
1099
- return ice_handle_vsi_list_mgmt(hw, m_entry, cur_fltr, new_fltr);
1100
-}
1101
-
1102
-/**
1103
- * ice_add_mac - Add a MAC address based filter rule
1104
- * @hw: pointer to the hardware structure
1105
- * @m_list: list of MAC addresses and forwarding information
1106
- *
1107
- * IMPORTANT: When the ucast_shared flag is set to false and m_list has
1108
- * multiple unicast addresses, the function assumes that all the
1109
- * addresses are unique in a given add_mac call. It doesn't
1110
- * check for duplicates in this case, removing duplicates from a given
1111
- * list should be taken care of in the caller of this function.
1112
- */
1113
-enum ice_status
1114
-ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
1115
-{
1116
- struct ice_aqc_sw_rules_elem *s_rule, *r_iter;
1117
- struct ice_fltr_list_entry *m_list_itr;
1118
- u16 elem_sent, total_elem_left;
1119
- enum ice_status status = 0;
1120
- u16 num_unicast = 0;
1121
- u16 s_rule_size;
1122
-
1123
- if (!m_list || !hw)
1124
- return ICE_ERR_PARAM;
1125
-
1126
- list_for_each_entry(m_list_itr, m_list, list_entry) {
1127
- u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
1128
-
1129
- if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
1130
- return ICE_ERR_PARAM;
1131
- if (is_zero_ether_addr(add))
1132
- return ICE_ERR_PARAM;
1133
- if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
1134
- /* Don't overwrite the unicast address */
1135
- if (ice_find_mac_entry(hw, add))
1136
- return ICE_ERR_ALREADY_EXISTS;
1137
- num_unicast++;
1138
- } else if (is_multicast_ether_addr(add) ||
1139
- (is_unicast_ether_addr(add) && hw->ucast_shared)) {
1140
- status = ice_add_shared_mac(hw, m_list_itr);
1141
- if (status) {
1142
- m_list_itr->status = ICE_FLTR_STATUS_FW_FAIL;
1143
- return status;
1144
- }
1145
- m_list_itr->status = ICE_FLTR_STATUS_FW_SUCCESS;
1146
- }
1147
- }
1148
-
1149
- /* Exit if no suitable entries were found for adding bulk switch rule */
1150
- if (!num_unicast)
1151
- return 0;
1152
-
1153
- /* Allocate switch rule buffer for the bulk update for unicast */
1154
- s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
1155
- s_rule = devm_kcalloc(ice_hw_to_dev(hw), num_unicast, s_rule_size,
1156
- GFP_KERNEL);
1157
- if (!s_rule)
1158
- return ICE_ERR_NO_MEMORY;
1159
-
1160
- r_iter = s_rule;
1161
- list_for_each_entry(m_list_itr, m_list, list_entry) {
1162
- struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
1163
- u8 *addr = &f_info->l_data.mac.mac_addr[0];
1164
-
1165
- if (is_unicast_ether_addr(addr)) {
1166
- ice_fill_sw_rule(hw, &m_list_itr->fltr_info,
1167
- r_iter, ice_aqc_opc_add_sw_rules);
1168
- r_iter = (struct ice_aqc_sw_rules_elem *)
1169
- ((u8 *)r_iter + s_rule_size);
1170
- }
1171
- }
1172
-
1173
- /* Call AQ bulk switch rule update for all unicast addresses */
1174
- r_iter = s_rule;
1175
- /* Call AQ switch rule in AQ_MAX chunk */
1176
- for (total_elem_left = num_unicast; total_elem_left > 0;
1177
- total_elem_left -= elem_sent) {
1178
- struct ice_aqc_sw_rules_elem *entry = r_iter;
1179
-
1180
- elem_sent = min(total_elem_left,
1181
- (u16)(ICE_AQ_MAX_BUF_LEN / s_rule_size));
1182
- status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
1183
- elem_sent, ice_aqc_opc_add_sw_rules,
1184
- NULL);
1185
- if (status)
1186
- goto ice_add_mac_exit;
1187
- r_iter = (struct ice_aqc_sw_rules_elem *)
1188
- ((u8 *)r_iter + (elem_sent * s_rule_size));
1189
- }
1190
-
1191
- /* Fill up rule id based on the value returned from FW */
1192
- r_iter = s_rule;
1193
- list_for_each_entry(m_list_itr, m_list, list_entry) {
1194
- struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
1195
- u8 *addr = &f_info->l_data.mac.mac_addr[0];
1196
- struct ice_switch_info *sw = hw->switch_info;
1197
- struct ice_fltr_mgmt_list_entry *fm_entry;
1198
-
1199
- if (is_unicast_ether_addr(addr)) {
1200
- f_info->fltr_rule_id =
1201
- le16_to_cpu(r_iter->pdata.lkup_tx_rx.index);
1202
- f_info->fltr_act = ICE_FWD_TO_VSI;
1203
- /* Create an entry to track this MAC address */
1204
- fm_entry = devm_kzalloc(ice_hw_to_dev(hw),
1205
- sizeof(*fm_entry), GFP_KERNEL);
1206
- if (!fm_entry) {
1207
- status = ICE_ERR_NO_MEMORY;
1208
- goto ice_add_mac_exit;
1209
- }
1210
- fm_entry->fltr_info = *f_info;
1211
- fm_entry->vsi_count = 1;
1212
- /* The book keeping entries will get removed when
1213
- * base driver calls remove filter AQ command
1214
- */
1215
- mutex_lock(&sw->mac_list_lock);
1216
- list_add(&fm_entry->list_entry, &sw->mac_list_head);
1217
- mutex_unlock(&sw->mac_list_lock);
1218
-
1219
- r_iter = (struct ice_aqc_sw_rules_elem *)
1220
- ((u8 *)r_iter + s_rule_size);
1221
- }
1222
- }
1223
-
1224
-ice_add_mac_exit:
1225
- devm_kfree(ice_hw_to_dev(hw), s_rule);
12261385 return status;
1227
-}
1228
-
1229
-/**
1230
- * ice_find_vlan_entry
1231
- * @hw: pointer to the hardware structure
1232
- * @vlan_id: VLAN id to search for
1233
- *
1234
- * Helper function to search for a VLAN entry using a given VLAN id
1235
- * Returns pointer to the entry if found.
1236
- */
1237
-static struct ice_fltr_mgmt_list_entry *
1238
-ice_find_vlan_entry(struct ice_hw *hw, u16 vlan_id)
1239
-{
1240
- struct ice_fltr_mgmt_list_entry *vlan_list_itr, *vlan_ret = NULL;
1241
- struct ice_switch_info *sw = hw->switch_info;
1242
-
1243
- mutex_lock(&sw->vlan_list_lock);
1244
- list_for_each_entry(vlan_list_itr, &sw->vlan_list_head, list_entry)
1245
- if (vlan_list_itr->fltr_info.l_data.vlan.vlan_id == vlan_id) {
1246
- vlan_ret = vlan_list_itr;
1247
- break;
1248
- }
1249
-
1250
- mutex_unlock(&sw->vlan_list_lock);
1251
- return vlan_ret;
1252
-}
1253
-
1254
-/**
1255
- * ice_add_vlan_internal - Add one VLAN based filter rule
1256
- * @hw: pointer to the hardware structure
1257
- * @f_entry: filter entry containing one VLAN information
1258
- */
1259
-static enum ice_status
1260
-ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
1261
-{
1262
- struct ice_fltr_info *new_fltr, *cur_fltr;
1263
- struct ice_fltr_mgmt_list_entry *v_list_itr;
1264
- u16 vlan_id;
1265
-
1266
- new_fltr = &f_entry->fltr_info;
1267
- /* VLAN id should only be 12 bits */
1268
- if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
1269
- return ICE_ERR_PARAM;
1270
-
1271
- vlan_id = new_fltr->l_data.vlan.vlan_id;
1272
- v_list_itr = ice_find_vlan_entry(hw, vlan_id);
1273
- if (!v_list_itr) {
1274
- u16 vsi_id = ICE_VSI_INVAL_ID;
1275
- enum ice_status status;
1276
- u16 vsi_list_id = 0;
1277
-
1278
- if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
1279
- enum ice_sw_lkup_type lkup_type = new_fltr->lkup_type;
1280
-
1281
- /* All VLAN pruning rules use a VSI list.
1282
- * Convert the action to forwarding to a VSI list.
1283
- */
1284
- vsi_id = new_fltr->fwd_id.vsi_id;
1285
- status = ice_create_vsi_list_rule(hw, &vsi_id, 1,
1286
- &vsi_list_id,
1287
- lkup_type);
1288
- if (status)
1289
- return status;
1290
- new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
1291
- new_fltr->fwd_id.vsi_list_id = vsi_list_id;
1292
- }
1293
-
1294
- status = ice_create_pkt_fwd_rule(hw, f_entry);
1295
- if (!status && vsi_id != ICE_VSI_INVAL_ID) {
1296
- v_list_itr = ice_find_vlan_entry(hw, vlan_id);
1297
- if (!v_list_itr)
1298
- return ICE_ERR_DOES_NOT_EXIST;
1299
- v_list_itr->vsi_list_info =
1300
- ice_create_vsi_list_map(hw, &vsi_id, 1,
1301
- vsi_list_id);
1302
- }
1303
-
1304
- return status;
1305
- }
1306
-
1307
- cur_fltr = &v_list_itr->fltr_info;
1308
- return ice_handle_vsi_list_mgmt(hw, v_list_itr, cur_fltr, new_fltr);
1309
-}
1310
-
1311
-/**
1312
- * ice_add_vlan - Add VLAN based filter rule
1313
- * @hw: pointer to the hardware structure
1314
- * @v_list: list of VLAN entries and forwarding information
1315
- */
1316
-enum ice_status
1317
-ice_add_vlan(struct ice_hw *hw, struct list_head *v_list)
1318
-{
1319
- struct ice_fltr_list_entry *v_list_itr;
1320
-
1321
- if (!v_list || !hw)
1322
- return ICE_ERR_PARAM;
1323
-
1324
- list_for_each_entry(v_list_itr, v_list, list_entry) {
1325
- enum ice_status status;
1326
-
1327
- if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
1328
- return ICE_ERR_PARAM;
1329
-
1330
- status = ice_add_vlan_internal(hw, v_list_itr);
1331
- if (status) {
1332
- v_list_itr->status = ICE_FLTR_STATUS_FW_FAIL;
1333
- return status;
1334
- }
1335
- v_list_itr->status = ICE_FLTR_STATUS_FW_SUCCESS;
1336
- }
1337
- return 0;
13381386 }
13391387
13401388 /**
13411389 * ice_remove_vsi_list_rule
13421390 * @hw: pointer to the hardware structure
1343
- * @vsi_list_id: VSI list id generated as part of allocate resource
1391
+ * @vsi_list_id: VSI list ID generated as part of allocate resource
13441392 * @lkup_type: switch rule filter lookup type
1393
+ *
1394
+ * The VSI list should be emptied before this function is called to remove the
1395
+ * VSI list.
13451396 */
13461397 static enum ice_status
13471398 ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
....@@ -1358,241 +1409,291 @@
13581409
13591410 s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
13601411 s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_id);
1361
- /* FW expects number of VSIs in vsi_list resource to be 0 for clear
1362
- * command. Since memory is zero'ed out during initialization, it's not
1363
- * necessary to explicitly initialize the variable to 0.
1364
- */
13651412
1366
- status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1,
1367
- ice_aqc_opc_remove_sw_rules, NULL);
1368
- if (!status)
1369
- /* Free the vsi_list resource that we allocated */
1370
- status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
1371
- ice_aqc_opc_free_res);
1413
+ /* Free the vsi_list resource that we allocated. It is assumed that the
1414
+ * list is empty at this point.
1415
+ */
1416
+ status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
1417
+ ice_aqc_opc_free_res);
13721418
13731419 devm_kfree(ice_hw_to_dev(hw), s_rule);
13741420 return status;
13751421 }
13761422
13771423 /**
1378
- * ice_handle_rem_vsi_list_mgmt
1424
+ * ice_rem_update_vsi_list
13791425 * @hw: pointer to the hardware structure
1380
- * @vsi_id: ID of the VSI to remove
1381
- * @fm_list_itr: filter management entry for which the VSI list management
1382
- * needs to be done
1426
+ * @vsi_handle: VSI handle of the VSI to remove
1427
+ * @fm_list: filter management entry for which the VSI list management needs to
1428
+ * be done
13831429 */
13841430 static enum ice_status
1385
-ice_handle_rem_vsi_list_mgmt(struct ice_hw *hw, u16 vsi_id,
1386
- struct ice_fltr_mgmt_list_entry *fm_list_itr)
1431
+ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
1432
+ struct ice_fltr_mgmt_list_entry *fm_list)
13871433 {
1388
- struct ice_switch_info *sw = hw->switch_info;
1389
- enum ice_status status = 0;
13901434 enum ice_sw_lkup_type lkup_type;
1391
- bool is_last_elem = true;
1392
- bool conv_list = false;
1393
- bool del_list = false;
1435
+ enum ice_status status = 0;
13941436 u16 vsi_list_id;
13951437
1396
- lkup_type = fm_list_itr->fltr_info.lkup_type;
1397
- vsi_list_id = fm_list_itr->fltr_info.fwd_id.vsi_list_id;
1438
+ if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST ||
1439
+ fm_list->vsi_count == 0)
1440
+ return ICE_ERR_PARAM;
13981441
1399
- if (fm_list_itr->vsi_count > 1) {
1400
- status = ice_update_vsi_list_rule(hw, &vsi_id, 1, vsi_list_id,
1401
- true,
1442
+ /* A rule with the VSI being removed does not exist */
1443
+ if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map))
1444
+ return ICE_ERR_DOES_NOT_EXIST;
1445
+
1446
+ lkup_type = fm_list->fltr_info.lkup_type;
1447
+ vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id;
1448
+ status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
1449
+ ice_aqc_opc_update_sw_rules,
1450
+ lkup_type);
1451
+ if (status)
1452
+ return status;
1453
+
1454
+ fm_list->vsi_count--;
1455
+ clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
1456
+
1457
+ if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) {
1458
+ struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info;
1459
+ struct ice_vsi_list_map_info *vsi_list_info =
1460
+ fm_list->vsi_list_info;
1461
+ u16 rem_vsi_handle;
1462
+
1463
+ rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map,
1464
+ ICE_MAX_VSI);
1465
+ if (!ice_is_vsi_valid(hw, rem_vsi_handle))
1466
+ return ICE_ERR_OUT_OF_RANGE;
1467
+
1468
+ /* Make sure VSI list is empty before removing it below */
1469
+ status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
1470
+ vsi_list_id, true,
14021471 ice_aqc_opc_update_sw_rules,
14031472 lkup_type);
14041473 if (status)
14051474 return status;
1406
- fm_list_itr->vsi_count--;
1407
- is_last_elem = false;
1408
- clear_bit(vsi_id, fm_list_itr->vsi_list_info->vsi_map);
1409
- }
14101475
1411
- /* For non-VLAN rules that forward packets to a VSI list, convert them
1412
- * to forwarding packets to a VSI if there is only one VSI left in the
1413
- * list. Unused lists are then removed.
1414
- * VLAN rules need to use VSI lists even with only one VSI.
1415
- */
1416
- if (fm_list_itr->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST) {
1417
- if (lkup_type == ICE_SW_LKUP_VLAN) {
1418
- del_list = is_last_elem;
1419
- } else if (fm_list_itr->vsi_count == 1) {
1420
- conv_list = true;
1421
- del_list = true;
1422
- }
1423
- }
1424
-
1425
- if (del_list) {
1426
- /* Remove the VSI list since it is no longer used */
1427
- struct ice_vsi_list_map_info *vsi_list_info =
1428
- fm_list_itr->vsi_list_info;
1429
-
1430
- status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
1431
- if (status)
1476
+ tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI;
1477
+ tmp_fltr_info.fwd_id.hw_vsi_id =
1478
+ ice_get_hw_vsi_num(hw, rem_vsi_handle);
1479
+ tmp_fltr_info.vsi_handle = rem_vsi_handle;
1480
+ status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info);
1481
+ if (status) {
1482
+ ice_debug(hw, ICE_DBG_SW,
1483
+ "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
1484
+ tmp_fltr_info.fwd_id.hw_vsi_id, status);
14321485 return status;
1486
+ }
14331487
1434
- if (conv_list) {
1435
- u16 rem_vsi_id;
1488
+ fm_list->fltr_info = tmp_fltr_info;
1489
+ }
14361490
1437
- rem_vsi_id = find_first_bit(vsi_list_info->vsi_map,
1438
- ICE_MAX_VSI);
1491
+ if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) ||
1492
+ (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) {
1493
+ struct ice_vsi_list_map_info *vsi_list_info =
1494
+ fm_list->vsi_list_info;
14391495
1440
- /* Error out when the expected last element is not in
1441
- * the VSI list map
1442
- */
1443
- if (rem_vsi_id == ICE_MAX_VSI)
1444
- return ICE_ERR_OUT_OF_RANGE;
1445
-
1446
- /* Change the list entry action from VSI_LIST to VSI */
1447
- fm_list_itr->fltr_info.fltr_act = ICE_FWD_TO_VSI;
1448
- fm_list_itr->fltr_info.fwd_id.vsi_id = rem_vsi_id;
1496
+ /* Remove the VSI list since it is no longer used */
1497
+ status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
1498
+ if (status) {
1499
+ ice_debug(hw, ICE_DBG_SW,
1500
+ "Failed to remove VSI list %d, error %d\n",
1501
+ vsi_list_id, status);
1502
+ return status;
14491503 }
14501504
14511505 list_del(&vsi_list_info->list_entry);
14521506 devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
1453
- fm_list_itr->vsi_list_info = NULL;
1507
+ fm_list->vsi_list_info = NULL;
14541508 }
14551509
1456
- if (conv_list) {
1457
- /* Convert the rule's forward action to forwarding packets to
1458
- * a VSI
1510
+ return status;
1511
+}
1512
+
1513
+/**
1514
+ * ice_remove_rule_internal - Remove a filter rule of a given type
1515
+ * @hw: pointer to the hardware structure
1516
+ * @recp_id: recipe ID for which the rule needs to removed
1517
+ * @f_entry: rule entry containing filter information
1518
+ */
1519
+static enum ice_status
1520
+ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id,
1521
+ struct ice_fltr_list_entry *f_entry)
1522
+{
1523
+ struct ice_switch_info *sw = hw->switch_info;
1524
+ struct ice_fltr_mgmt_list_entry *list_elem;
1525
+ struct mutex *rule_lock; /* Lock to protect filter rule list */
1526
+ enum ice_status status = 0;
1527
+ bool remove_rule = false;
1528
+ u16 vsi_handle;
1529
+
1530
+ if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1531
+ return ICE_ERR_PARAM;
1532
+ f_entry->fltr_info.fwd_id.hw_vsi_id =
1533
+ ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1534
+
1535
+ rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
1536
+ mutex_lock(rule_lock);
1537
+ list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info);
1538
+ if (!list_elem) {
1539
+ status = ICE_ERR_DOES_NOT_EXIST;
1540
+ goto exit;
1541
+ }
1542
+
1543
+ if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) {
1544
+ remove_rule = true;
1545
+ } else if (!list_elem->vsi_list_info) {
1546
+ status = ICE_ERR_DOES_NOT_EXIST;
1547
+ goto exit;
1548
+ } else if (list_elem->vsi_list_info->ref_cnt > 1) {
1549
+ /* a ref_cnt > 1 indicates that the vsi_list is being
1550
+ * shared by multiple rules. Decrement the ref_cnt and
1551
+ * remove this rule, but do not modify the list, as it
1552
+ * is in-use by other rules.
14591553 */
1460
- struct ice_aqc_sw_rules_elem *s_rule;
1461
-
1462
- s_rule = devm_kzalloc(ice_hw_to_dev(hw),
1463
- ICE_SW_RULE_RX_TX_ETH_HDR_SIZE,
1464
- GFP_KERNEL);
1465
- if (!s_rule)
1466
- return ICE_ERR_NO_MEMORY;
1467
-
1468
- ice_fill_sw_rule(hw, &fm_list_itr->fltr_info, s_rule,
1469
- ice_aqc_opc_update_sw_rules);
1470
-
1471
- s_rule->pdata.lkup_tx_rx.index =
1472
- cpu_to_le16(fm_list_itr->fltr_info.fltr_rule_id);
1473
-
1474
- status = ice_aq_sw_rules(hw, s_rule,
1475
- ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
1476
- ice_aqc_opc_update_sw_rules, NULL);
1477
- devm_kfree(ice_hw_to_dev(hw), s_rule);
1554
+ list_elem->vsi_list_info->ref_cnt--;
1555
+ remove_rule = true;
1556
+ } else {
1557
+ /* a ref_cnt of 1 indicates the vsi_list is only used
1558
+ * by one rule. However, the original removal request is only
1559
+ * for a single VSI. Update the vsi_list first, and only
1560
+ * remove the rule if there are no further VSIs in this list.
1561
+ */
1562
+ vsi_handle = f_entry->fltr_info.vsi_handle;
1563
+ status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
14781564 if (status)
1479
- return status;
1565
+ goto exit;
1566
+ /* if VSI count goes to zero after updating the VSI list */
1567
+ if (list_elem->vsi_count == 0)
1568
+ remove_rule = true;
14801569 }
14811570
1482
- if (is_last_elem) {
1571
+ if (remove_rule) {
14831572 /* Remove the lookup rule */
14841573 struct ice_aqc_sw_rules_elem *s_rule;
14851574
14861575 s_rule = devm_kzalloc(ice_hw_to_dev(hw),
14871576 ICE_SW_RULE_RX_TX_NO_HDR_SIZE,
14881577 GFP_KERNEL);
1489
- if (!s_rule)
1490
- return ICE_ERR_NO_MEMORY;
1578
+ if (!s_rule) {
1579
+ status = ICE_ERR_NO_MEMORY;
1580
+ goto exit;
1581
+ }
14911582
1492
- ice_fill_sw_rule(hw, &fm_list_itr->fltr_info, s_rule,
1583
+ ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule,
14931584 ice_aqc_opc_remove_sw_rules);
14941585
14951586 status = ice_aq_sw_rules(hw, s_rule,
14961587 ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1,
14971588 ice_aqc_opc_remove_sw_rules, NULL);
1498
- if (status)
1499
- return status;
15001589
1501
- /* Remove a book keeping entry from the MAC address list */
1502
- mutex_lock(&sw->mac_list_lock);
1503
- list_del(&fm_list_itr->list_entry);
1504
- mutex_unlock(&sw->mac_list_lock);
1505
- devm_kfree(ice_hw_to_dev(hw), fm_list_itr);
1590
+ /* Remove a book keeping from the list */
15061591 devm_kfree(ice_hw_to_dev(hw), s_rule);
1592
+
1593
+ if (status)
1594
+ goto exit;
1595
+
1596
+ list_del(&list_elem->list_entry);
1597
+ devm_kfree(ice_hw_to_dev(hw), list_elem);
15071598 }
1599
+exit:
1600
+ mutex_unlock(rule_lock);
15081601 return status;
15091602 }
15101603
15111604 /**
1512
- * ice_remove_mac_entry
1513
- * @hw: pointer to the hardware structure
1514
- * @f_entry: structure containing MAC forwarding information
1515
- */
1516
-static enum ice_status
1517
-ice_remove_mac_entry(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
1518
-{
1519
- struct ice_fltr_mgmt_list_entry *m_entry;
1520
- u16 vsi_id;
1521
- u8 *add;
1522
-
1523
- add = &f_entry->fltr_info.l_data.mac.mac_addr[0];
1524
-
1525
- m_entry = ice_find_mac_entry(hw, add);
1526
- if (!m_entry)
1527
- return ICE_ERR_PARAM;
1528
-
1529
- vsi_id = f_entry->fltr_info.fwd_id.vsi_id;
1530
- return ice_handle_rem_vsi_list_mgmt(hw, vsi_id, m_entry);
1531
-}
1532
-
1533
-/**
1534
- * ice_remove_mac - remove a MAC address based filter rule
1605
+ * ice_add_mac - Add a MAC address based filter rule
15351606 * @hw: pointer to the hardware structure
15361607 * @m_list: list of MAC addresses and forwarding information
15371608 *
1538
- * This function removes either a MAC filter rule or a specific VSI from a
1539
- * VSI list for a multicast MAC address.
1540
- *
1541
- * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by
1542
- * ice_add_mac. Caller should be aware that this call will only work if all
1543
- * the entries passed into m_list were added previously. It will not attempt to
1544
- * do a partial remove of entries that were found.
1609
+ * IMPORTANT: When the ucast_shared flag is set to false and m_list has
1610
+ * multiple unicast addresses, the function assumes that all the
1611
+ * addresses are unique in a given add_mac call. It doesn't
1612
+ * check for duplicates in this case, removing duplicates from a given
1613
+ * list should be taken care of in the caller of this function.
15451614 */
1546
-enum ice_status
1547
-ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
1615
+enum ice_status ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
15481616 {
15491617 struct ice_aqc_sw_rules_elem *s_rule, *r_iter;
1550
- u8 s_rule_size = ICE_SW_RULE_RX_TX_NO_HDR_SIZE;
1551
- struct ice_switch_info *sw = hw->switch_info;
1552
- struct ice_fltr_mgmt_list_entry *m_entry;
15531618 struct ice_fltr_list_entry *m_list_itr;
1554
- u16 elem_sent, total_elem_left;
1619
+ struct list_head *rule_head;
1620
+ u16 total_elem_left, s_rule_size;
1621
+ struct ice_switch_info *sw;
1622
+ struct mutex *rule_lock; /* Lock to protect filter rule list */
15551623 enum ice_status status = 0;
15561624 u16 num_unicast = 0;
1625
+ u8 elem_sent;
15571626
1558
- if (!m_list)
1627
+ if (!m_list || !hw)
15591628 return ICE_ERR_PARAM;
15601629
1630
+ s_rule = NULL;
1631
+ sw = hw->switch_info;
1632
+ rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
15611633 list_for_each_entry(m_list_itr, m_list, list_entry) {
1562
- u8 *addr = m_list_itr->fltr_info.l_data.mac.mac_addr;
1634
+ u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
1635
+ u16 vsi_handle;
1636
+ u16 hw_vsi_id;
15631637
1564
- if (is_unicast_ether_addr(addr) && !hw->ucast_shared)
1638
+ m_list_itr->fltr_info.flag = ICE_FLTR_TX;
1639
+ vsi_handle = m_list_itr->fltr_info.vsi_handle;
1640
+ if (!ice_is_vsi_valid(hw, vsi_handle))
1641
+ return ICE_ERR_PARAM;
1642
+ hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
1643
+ m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
1644
+ /* update the src in case it is VSI num */
1645
+ if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
1646
+ return ICE_ERR_PARAM;
1647
+ m_list_itr->fltr_info.src = hw_vsi_id;
1648
+ if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
1649
+ is_zero_ether_addr(add))
1650
+ return ICE_ERR_PARAM;
1651
+ if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
1652
+ /* Don't overwrite the unicast address */
1653
+ mutex_lock(rule_lock);
1654
+ if (ice_find_rule_entry(hw, ICE_SW_LKUP_MAC,
1655
+ &m_list_itr->fltr_info)) {
1656
+ mutex_unlock(rule_lock);
1657
+ return ICE_ERR_ALREADY_EXISTS;
1658
+ }
1659
+ mutex_unlock(rule_lock);
15651660 num_unicast++;
1566
- else if (is_multicast_ether_addr(addr) ||
1567
- (is_unicast_ether_addr(addr) && hw->ucast_shared))
1568
- ice_remove_mac_entry(hw, m_list_itr);
1661
+ } else if (is_multicast_ether_addr(add) ||
1662
+ (is_unicast_ether_addr(add) && hw->ucast_shared)) {
1663
+ m_list_itr->status =
1664
+ ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
1665
+ m_list_itr);
1666
+ if (m_list_itr->status)
1667
+ return m_list_itr->status;
1668
+ }
15691669 }
15701670
1571
- /* Exit if no unicast addresses found. Multicast switch rules
1572
- * were added individually
1573
- */
1574
- if (!num_unicast)
1575
- return 0;
1671
+ mutex_lock(rule_lock);
1672
+ /* Exit if no suitable entries were found for adding bulk switch rule */
1673
+ if (!num_unicast) {
1674
+ status = 0;
1675
+ goto ice_add_mac_exit;
1676
+ }
1677
+
1678
+ rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
15761679
15771680 /* Allocate switch rule buffer for the bulk update for unicast */
1681
+ s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
15781682 s_rule = devm_kcalloc(ice_hw_to_dev(hw), num_unicast, s_rule_size,
15791683 GFP_KERNEL);
1580
- if (!s_rule)
1581
- return ICE_ERR_NO_MEMORY;
1684
+ if (!s_rule) {
1685
+ status = ICE_ERR_NO_MEMORY;
1686
+ goto ice_add_mac_exit;
1687
+ }
15821688
15831689 r_iter = s_rule;
15841690 list_for_each_entry(m_list_itr, m_list, list_entry) {
1585
- u8 *addr = m_list_itr->fltr_info.l_data.mac.mac_addr;
1691
+ struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
1692
+ u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
15861693
1587
- if (is_unicast_ether_addr(addr)) {
1588
- m_entry = ice_find_mac_entry(hw, addr);
1589
- if (!m_entry) {
1590
- status = ICE_ERR_DOES_NOT_EXIST;
1591
- goto ice_remove_mac_exit;
1592
- }
1593
-
1594
- ice_fill_sw_rule(hw, &m_entry->fltr_info,
1595
- r_iter, ice_aqc_opc_remove_sw_rules);
1694
+ if (is_unicast_ether_addr(mac_addr)) {
1695
+ ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter,
1696
+ ice_aqc_opc_add_sw_rules);
15961697 r_iter = (struct ice_aqc_sw_rules_elem *)
15971698 ((u8 *)r_iter + s_rule_size);
15981699 }
....@@ -1605,55 +1706,339 @@
16051706 total_elem_left -= elem_sent) {
16061707 struct ice_aqc_sw_rules_elem *entry = r_iter;
16071708
1608
- elem_sent = min(total_elem_left,
1609
- (u16)(ICE_AQ_MAX_BUF_LEN / s_rule_size));
1709
+ elem_sent = min_t(u8, total_elem_left,
1710
+ (ICE_AQ_MAX_BUF_LEN / s_rule_size));
16101711 status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
1611
- elem_sent, ice_aqc_opc_remove_sw_rules,
1712
+ elem_sent, ice_aqc_opc_add_sw_rules,
16121713 NULL);
16131714 if (status)
1614
- break;
1715
+ goto ice_add_mac_exit;
16151716 r_iter = (struct ice_aqc_sw_rules_elem *)
1616
- ((u8 *)r_iter + s_rule_size);
1717
+ ((u8 *)r_iter + (elem_sent * s_rule_size));
16171718 }
16181719
1720
+ /* Fill up rule ID based on the value returned from FW */
1721
+ r_iter = s_rule;
16191722 list_for_each_entry(m_list_itr, m_list, list_entry) {
1620
- u8 *addr = m_list_itr->fltr_info.l_data.mac.mac_addr;
1723
+ struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
1724
+ u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
1725
+ struct ice_fltr_mgmt_list_entry *fm_entry;
16211726
1622
- if (is_unicast_ether_addr(addr)) {
1623
- m_entry = ice_find_mac_entry(hw, addr);
1624
- if (!m_entry)
1625
- return ICE_ERR_OUT_OF_RANGE;
1626
- mutex_lock(&sw->mac_list_lock);
1627
- list_del(&m_entry->list_entry);
1628
- mutex_unlock(&sw->mac_list_lock);
1629
- devm_kfree(ice_hw_to_dev(hw), m_entry);
1727
+ if (is_unicast_ether_addr(mac_addr)) {
1728
+ f_info->fltr_rule_id =
1729
+ le16_to_cpu(r_iter->pdata.lkup_tx_rx.index);
1730
+ f_info->fltr_act = ICE_FWD_TO_VSI;
1731
+ /* Create an entry to track this MAC address */
1732
+ fm_entry = devm_kzalloc(ice_hw_to_dev(hw),
1733
+ sizeof(*fm_entry), GFP_KERNEL);
1734
+ if (!fm_entry) {
1735
+ status = ICE_ERR_NO_MEMORY;
1736
+ goto ice_add_mac_exit;
1737
+ }
1738
+ fm_entry->fltr_info = *f_info;
1739
+ fm_entry->vsi_count = 1;
1740
+ /* The book keeping entries will get removed when
1741
+ * base driver calls remove filter AQ command
1742
+ */
1743
+
1744
+ list_add(&fm_entry->list_entry, rule_head);
1745
+ r_iter = (struct ice_aqc_sw_rules_elem *)
1746
+ ((u8 *)r_iter + s_rule_size);
16301747 }
16311748 }
16321749
1633
-ice_remove_mac_exit:
1634
- devm_kfree(ice_hw_to_dev(hw), s_rule);
1750
+ice_add_mac_exit:
1751
+ mutex_unlock(rule_lock);
1752
+ if (s_rule)
1753
+ devm_kfree(ice_hw_to_dev(hw), s_rule);
16351754 return status;
16361755 }
16371756
16381757 /**
1639
- * ice_cfg_dflt_vsi - add filter rule to set/unset given VSI as default
1640
- * VSI for the switch (represented by swid)
1758
+ * ice_add_vlan_internal - Add one VLAN based filter rule
16411759 * @hw: pointer to the hardware structure
1642
- * @vsi_id: number of VSI to set as default
1643
- * @set: true to add the above mentioned switch rule, false to remove it
1644
- * @direction: ICE_FLTR_RX or ICE_FLTR_TX
1760
+ * @f_entry: filter entry containing one VLAN information
1761
+ */
1762
+static enum ice_status
1763
+ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
1764
+{
1765
+ struct ice_switch_info *sw = hw->switch_info;
1766
+ struct ice_fltr_mgmt_list_entry *v_list_itr;
1767
+ struct ice_fltr_info *new_fltr, *cur_fltr;
1768
+ enum ice_sw_lkup_type lkup_type;
1769
+ u16 vsi_list_id = 0, vsi_handle;
1770
+ struct mutex *rule_lock; /* Lock to protect filter rule list */
1771
+ enum ice_status status = 0;
1772
+
1773
+ if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1774
+ return ICE_ERR_PARAM;
1775
+
1776
+ f_entry->fltr_info.fwd_id.hw_vsi_id =
1777
+ ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1778
+ new_fltr = &f_entry->fltr_info;
1779
+
1780
+ /* VLAN ID should only be 12 bits */
1781
+ if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
1782
+ return ICE_ERR_PARAM;
1783
+
1784
+ if (new_fltr->src_id != ICE_SRC_ID_VSI)
1785
+ return ICE_ERR_PARAM;
1786
+
1787
+ new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
1788
+ lkup_type = new_fltr->lkup_type;
1789
+ vsi_handle = new_fltr->vsi_handle;
1790
+ rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
1791
+ mutex_lock(rule_lock);
1792
+ v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr);
1793
+ if (!v_list_itr) {
1794
+ struct ice_vsi_list_map_info *map_info = NULL;
1795
+
1796
+ if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
1797
+ /* All VLAN pruning rules use a VSI list. Check if
1798
+ * there is already a VSI list containing VSI that we
1799
+ * want to add. If found, use the same vsi_list_id for
1800
+ * this new VLAN rule or else create a new list.
1801
+ */
1802
+ map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN,
1803
+ vsi_handle,
1804
+ &vsi_list_id);
1805
+ if (!map_info) {
1806
+ status = ice_create_vsi_list_rule(hw,
1807
+ &vsi_handle,
1808
+ 1,
1809
+ &vsi_list_id,
1810
+ lkup_type);
1811
+ if (status)
1812
+ goto exit;
1813
+ }
1814
+ /* Convert the action to forwarding to a VSI list. */
1815
+ new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
1816
+ new_fltr->fwd_id.vsi_list_id = vsi_list_id;
1817
+ }
1818
+
1819
+ status = ice_create_pkt_fwd_rule(hw, f_entry);
1820
+ if (!status) {
1821
+ v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN,
1822
+ new_fltr);
1823
+ if (!v_list_itr) {
1824
+ status = ICE_ERR_DOES_NOT_EXIST;
1825
+ goto exit;
1826
+ }
1827
+ /* reuse VSI list for new rule and increment ref_cnt */
1828
+ if (map_info) {
1829
+ v_list_itr->vsi_list_info = map_info;
1830
+ map_info->ref_cnt++;
1831
+ } else {
1832
+ v_list_itr->vsi_list_info =
1833
+ ice_create_vsi_list_map(hw, &vsi_handle,
1834
+ 1, vsi_list_id);
1835
+ }
1836
+ }
1837
+ } else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
1838
+ /* Update existing VSI list to add new VSI ID only if it used
1839
+ * by one VLAN rule.
1840
+ */
1841
+ cur_fltr = &v_list_itr->fltr_info;
1842
+ status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
1843
+ new_fltr);
1844
+ } else {
1845
+ /* If VLAN rule exists and VSI list being used by this rule is
1846
+ * referenced by more than 1 VLAN rule. Then create a new VSI
1847
+ * list appending previous VSI with new VSI and update existing
1848
+ * VLAN rule to point to new VSI list ID
1849
+ */
1850
+ struct ice_fltr_info tmp_fltr;
1851
+ u16 vsi_handle_arr[2];
1852
+ u16 cur_handle;
1853
+
1854
+ /* Current implementation only supports reusing VSI list with
1855
+ * one VSI count. We should never hit below condition
1856
+ */
1857
+ if (v_list_itr->vsi_count > 1 &&
1858
+ v_list_itr->vsi_list_info->ref_cnt > 1) {
1859
+ ice_debug(hw, ICE_DBG_SW,
1860
+ "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n");
1861
+ status = ICE_ERR_CFG;
1862
+ goto exit;
1863
+ }
1864
+
1865
+ cur_handle =
1866
+ find_first_bit(v_list_itr->vsi_list_info->vsi_map,
1867
+ ICE_MAX_VSI);
1868
+
1869
+ /* A rule already exists with the new VSI being added */
1870
+ if (cur_handle == vsi_handle) {
1871
+ status = ICE_ERR_ALREADY_EXISTS;
1872
+ goto exit;
1873
+ }
1874
+
1875
+ vsi_handle_arr[0] = cur_handle;
1876
+ vsi_handle_arr[1] = vsi_handle;
1877
+ status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
1878
+ &vsi_list_id, lkup_type);
1879
+ if (status)
1880
+ goto exit;
1881
+
1882
+ tmp_fltr = v_list_itr->fltr_info;
1883
+ tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
1884
+ tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
1885
+ tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
1886
+ /* Update the previous switch rule to a new VSI list which
1887
+ * includes current VSI that is requested
1888
+ */
1889
+ status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
1890
+ if (status)
1891
+ goto exit;
1892
+
1893
+ /* before overriding VSI list map info. decrement ref_cnt of
1894
+ * previous VSI list
1895
+ */
1896
+ v_list_itr->vsi_list_info->ref_cnt--;
1897
+
1898
+ /* now update to newly created list */
1899
+ v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
1900
+ v_list_itr->vsi_list_info =
1901
+ ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
1902
+ vsi_list_id);
1903
+ v_list_itr->vsi_count++;
1904
+ }
1905
+
1906
+exit:
1907
+ mutex_unlock(rule_lock);
1908
+ return status;
1909
+}
1910
+
1911
+/**
1912
+ * ice_add_vlan - Add VLAN based filter rule
1913
+ * @hw: pointer to the hardware structure
1914
+ * @v_list: list of VLAN entries and forwarding information
1915
+ */
1916
+enum ice_status ice_add_vlan(struct ice_hw *hw, struct list_head *v_list)
1917
+{
1918
+ struct ice_fltr_list_entry *v_list_itr;
1919
+
1920
+ if (!v_list || !hw)
1921
+ return ICE_ERR_PARAM;
1922
+
1923
+ list_for_each_entry(v_list_itr, v_list, list_entry) {
1924
+ if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
1925
+ return ICE_ERR_PARAM;
1926
+ v_list_itr->fltr_info.flag = ICE_FLTR_TX;
1927
+ v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr);
1928
+ if (v_list_itr->status)
1929
+ return v_list_itr->status;
1930
+ }
1931
+ return 0;
1932
+}
1933
+
1934
+/**
1935
+ * ice_add_eth_mac - Add ethertype and MAC based filter rule
1936
+ * @hw: pointer to the hardware structure
1937
+ * @em_list: list of ether type MAC filter, MAC is optional
1938
+ *
1939
+ * This function requires the caller to populate the entries in
1940
+ * the filter list with the necessary fields (including flags to
1941
+ * indicate Tx or Rx rules).
16451942 */
16461943 enum ice_status
1647
-ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_id, bool set, u8 direction)
1944
+ice_add_eth_mac(struct ice_hw *hw, struct list_head *em_list)
1945
+{
1946
+ struct ice_fltr_list_entry *em_list_itr;
1947
+
1948
+ if (!em_list || !hw)
1949
+ return ICE_ERR_PARAM;
1950
+
1951
+ list_for_each_entry(em_list_itr, em_list, list_entry) {
1952
+ enum ice_sw_lkup_type l_type =
1953
+ em_list_itr->fltr_info.lkup_type;
1954
+
1955
+ if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
1956
+ l_type != ICE_SW_LKUP_ETHERTYPE)
1957
+ return ICE_ERR_PARAM;
1958
+
1959
+ em_list_itr->status = ice_add_rule_internal(hw, l_type,
1960
+ em_list_itr);
1961
+ if (em_list_itr->status)
1962
+ return em_list_itr->status;
1963
+ }
1964
+ return 0;
1965
+}
1966
+
1967
+/**
1968
+ * ice_remove_eth_mac - Remove an ethertype (or MAC) based filter rule
1969
+ * @hw: pointer to the hardware structure
1970
+ * @em_list: list of ethertype or ethertype MAC entries
1971
+ */
1972
+enum ice_status
1973
+ice_remove_eth_mac(struct ice_hw *hw, struct list_head *em_list)
1974
+{
1975
+ struct ice_fltr_list_entry *em_list_itr, *tmp;
1976
+
1977
+ if (!em_list || !hw)
1978
+ return ICE_ERR_PARAM;
1979
+
1980
+ list_for_each_entry_safe(em_list_itr, tmp, em_list, list_entry) {
1981
+ enum ice_sw_lkup_type l_type =
1982
+ em_list_itr->fltr_info.lkup_type;
1983
+
1984
+ if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
1985
+ l_type != ICE_SW_LKUP_ETHERTYPE)
1986
+ return ICE_ERR_PARAM;
1987
+
1988
+ em_list_itr->status = ice_remove_rule_internal(hw, l_type,
1989
+ em_list_itr);
1990
+ if (em_list_itr->status)
1991
+ return em_list_itr->status;
1992
+ }
1993
+ return 0;
1994
+}
1995
+
1996
+/**
1997
+ * ice_rem_sw_rule_info
1998
+ * @hw: pointer to the hardware structure
1999
+ * @rule_head: pointer to the switch list structure that we want to delete
2000
+ */
2001
+static void
2002
+ice_rem_sw_rule_info(struct ice_hw *hw, struct list_head *rule_head)
2003
+{
2004
+ if (!list_empty(rule_head)) {
2005
+ struct ice_fltr_mgmt_list_entry *entry;
2006
+ struct ice_fltr_mgmt_list_entry *tmp;
2007
+
2008
+ list_for_each_entry_safe(entry, tmp, rule_head, list_entry) {
2009
+ list_del(&entry->list_entry);
2010
+ devm_kfree(ice_hw_to_dev(hw), entry);
2011
+ }
2012
+ }
2013
+}
2014
+
2015
+/**
2016
+ * ice_cfg_dflt_vsi - change state of VSI to set/clear default
2017
+ * @hw: pointer to the hardware structure
2018
+ * @vsi_handle: VSI handle to set as default
2019
+ * @set: true to add the above mentioned switch rule, false to remove it
2020
+ * @direction: ICE_FLTR_RX or ICE_FLTR_TX
2021
+ *
2022
+ * add filter rule to set/unset given VSI as default VSI for the switch
2023
+ * (represented by swid)
2024
+ */
2025
+enum ice_status
2026
+ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction)
16482027 {
16492028 struct ice_aqc_sw_rules_elem *s_rule;
16502029 struct ice_fltr_info f_info;
16512030 enum ice_adminq_opc opcode;
16522031 enum ice_status status;
16532032 u16 s_rule_size;
2033
+ u16 hw_vsi_id;
2034
+
2035
+ if (!ice_is_vsi_valid(hw, vsi_handle))
2036
+ return ICE_ERR_PARAM;
2037
+ hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
16542038
16552039 s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE :
1656
- ICE_SW_RULE_RX_TX_NO_HDR_SIZE;
2040
+ ICE_SW_RULE_RX_TX_NO_HDR_SIZE;
2041
+
16572042 s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
16582043 if (!s_rule)
16592044 return ICE_ERR_NO_MEMORY;
....@@ -1663,15 +2048,17 @@
16632048 f_info.lkup_type = ICE_SW_LKUP_DFLT;
16642049 f_info.flag = direction;
16652050 f_info.fltr_act = ICE_FWD_TO_VSI;
1666
- f_info.fwd_id.vsi_id = vsi_id;
2051
+ f_info.fwd_id.hw_vsi_id = hw_vsi_id;
16672052
16682053 if (f_info.flag & ICE_FLTR_RX) {
16692054 f_info.src = hw->port_info->lport;
2055
+ f_info.src_id = ICE_SRC_ID_LPORT;
16702056 if (!set)
16712057 f_info.fltr_rule_id =
16722058 hw->port_info->dflt_rx_vsi_rule_id;
16732059 } else if (f_info.flag & ICE_FLTR_TX) {
1674
- f_info.src = vsi_id;
2060
+ f_info.src_id = ICE_SRC_ID_VSI;
2061
+ f_info.src = hw_vsi_id;
16752062 if (!set)
16762063 f_info.fltr_rule_id =
16772064 hw->port_info->dflt_tx_vsi_rule_id;
....@@ -1691,10 +2078,10 @@
16912078 u16 index = le16_to_cpu(s_rule->pdata.lkup_tx_rx.index);
16922079
16932080 if (f_info.flag & ICE_FLTR_TX) {
1694
- hw->port_info->dflt_tx_vsi_num = vsi_id;
2081
+ hw->port_info->dflt_tx_vsi_num = hw_vsi_id;
16952082 hw->port_info->dflt_tx_vsi_rule_id = index;
16962083 } else if (f_info.flag & ICE_FLTR_RX) {
1697
- hw->port_info->dflt_rx_vsi_num = vsi_id;
2084
+ hw->port_info->dflt_rx_vsi_num = hw_vsi_id;
16982085 hw->port_info->dflt_rx_vsi_rule_id = index;
16992086 }
17002087 } else {
....@@ -1713,26 +2100,93 @@
17132100 }
17142101
17152102 /**
1716
- * ice_remove_vlan_internal - Remove one VLAN based filter rule
2103
+ * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry
17172104 * @hw: pointer to the hardware structure
1718
- * @f_entry: filter entry containing one VLAN information
2105
+ * @recp_id: lookup type for which the specified rule needs to be searched
2106
+ * @f_info: rule information
2107
+ *
2108
+ * Helper function to search for a unicast rule entry - this is to be used
2109
+ * to remove unicast MAC filter that is not shared with other VSIs on the
2110
+ * PF switch.
2111
+ *
2112
+ * Returns pointer to entry storing the rule if found
17192113 */
1720
-static enum ice_status
1721
-ice_remove_vlan_internal(struct ice_hw *hw,
1722
- struct ice_fltr_list_entry *f_entry)
2114
+static struct ice_fltr_mgmt_list_entry *
2115
+ice_find_ucast_rule_entry(struct ice_hw *hw, u8 recp_id,
2116
+ struct ice_fltr_info *f_info)
17232117 {
1724
- struct ice_fltr_info *new_fltr;
1725
- struct ice_fltr_mgmt_list_entry *v_list_elem;
1726
- u16 vsi_id;
2118
+ struct ice_switch_info *sw = hw->switch_info;
2119
+ struct ice_fltr_mgmt_list_entry *list_itr;
2120
+ struct list_head *list_head;
17272121
1728
- new_fltr = &f_entry->fltr_info;
2122
+ list_head = &sw->recp_list[recp_id].filt_rules;
2123
+ list_for_each_entry(list_itr, list_head, list_entry) {
2124
+ if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
2125
+ sizeof(f_info->l_data)) &&
2126
+ f_info->fwd_id.hw_vsi_id ==
2127
+ list_itr->fltr_info.fwd_id.hw_vsi_id &&
2128
+ f_info->flag == list_itr->fltr_info.flag)
2129
+ return list_itr;
2130
+ }
2131
+ return NULL;
2132
+}
17292133
1730
- v_list_elem = ice_find_vlan_entry(hw, new_fltr->l_data.vlan.vlan_id);
1731
- if (!v_list_elem)
2134
+/**
2135
+ * ice_remove_mac - remove a MAC address based filter rule
2136
+ * @hw: pointer to the hardware structure
2137
+ * @m_list: list of MAC addresses and forwarding information
2138
+ *
2139
+ * This function removes either a MAC filter rule or a specific VSI from a
2140
+ * VSI list for a multicast MAC address.
2141
+ *
2142
+ * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by
2143
+ * ice_add_mac. Caller should be aware that this call will only work if all
2144
+ * the entries passed into m_list were added previously. It will not attempt to
2145
+ * do a partial remove of entries that were found.
2146
+ */
2147
+enum ice_status ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
2148
+{
2149
+ struct ice_fltr_list_entry *list_itr, *tmp;
2150
+ struct mutex *rule_lock; /* Lock to protect filter rule list */
2151
+
2152
+ if (!m_list)
17322153 return ICE_ERR_PARAM;
17332154
1734
- vsi_id = f_entry->fltr_info.fwd_id.vsi_id;
1735
- return ice_handle_rem_vsi_list_mgmt(hw, vsi_id, v_list_elem);
2155
+ rule_lock = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
2156
+ list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) {
2157
+ enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
2158
+ u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0];
2159
+ u16 vsi_handle;
2160
+
2161
+ if (l_type != ICE_SW_LKUP_MAC)
2162
+ return ICE_ERR_PARAM;
2163
+
2164
+ vsi_handle = list_itr->fltr_info.vsi_handle;
2165
+ if (!ice_is_vsi_valid(hw, vsi_handle))
2166
+ return ICE_ERR_PARAM;
2167
+
2168
+ list_itr->fltr_info.fwd_id.hw_vsi_id =
2169
+ ice_get_hw_vsi_num(hw, vsi_handle);
2170
+ if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
2171
+ /* Don't remove the unicast address that belongs to
2172
+ * another VSI on the switch, since it is not being
2173
+ * shared...
2174
+ */
2175
+ mutex_lock(rule_lock);
2176
+ if (!ice_find_ucast_rule_entry(hw, ICE_SW_LKUP_MAC,
2177
+ &list_itr->fltr_info)) {
2178
+ mutex_unlock(rule_lock);
2179
+ return ICE_ERR_DOES_NOT_EXIST;
2180
+ }
2181
+ mutex_unlock(rule_lock);
2182
+ }
2183
+ list_itr->status = ice_remove_rule_internal(hw,
2184
+ ICE_SW_LKUP_MAC,
2185
+ list_itr);
2186
+ if (list_itr->status)
2187
+ return list_itr->status;
2188
+ }
2189
+ return 0;
17362190 }
17372191
17382192 /**
....@@ -1743,130 +2197,460 @@
17432197 enum ice_status
17442198 ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list)
17452199 {
1746
- struct ice_fltr_list_entry *v_list_itr;
1747
- enum ice_status status = 0;
2200
+ struct ice_fltr_list_entry *v_list_itr, *tmp;
17482201
17492202 if (!v_list || !hw)
17502203 return ICE_ERR_PARAM;
17512204
1752
- list_for_each_entry(v_list_itr, v_list, list_entry) {
1753
- status = ice_remove_vlan_internal(hw, v_list_itr);
1754
- if (status) {
1755
- v_list_itr->status = ICE_FLTR_STATUS_FW_FAIL;
1756
- return status;
1757
- }
1758
- v_list_itr->status = ICE_FLTR_STATUS_FW_SUCCESS;
1759
- }
1760
- return status;
1761
-}
2205
+ list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
2206
+ enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
17622207
1763
-/**
1764
- * ice_add_to_vsi_fltr_list - Add VSI filters to the list
1765
- * @hw: pointer to the hardware structure
1766
- * @vsi_id: ID of VSI to remove filters from
1767
- * @lkup_list_head: pointer to the list that has certain lookup type filters
1768
- * @vsi_list_head: pointer to the list pertaining to VSI with vsi_id
1769
- */
1770
-static enum ice_status
1771
-ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_id,
1772
- struct list_head *lkup_list_head,
1773
- struct list_head *vsi_list_head)
1774
-{
1775
- struct ice_fltr_mgmt_list_entry *fm_entry;
1776
-
1777
- /* check to make sure VSI id is valid and within boundary */
1778
- if (vsi_id >=
1779
- (sizeof(fm_entry->vsi_list_info->vsi_map) * BITS_PER_BYTE - 1))
1780
- return ICE_ERR_PARAM;
1781
-
1782
- list_for_each_entry(fm_entry, lkup_list_head, list_entry) {
1783
- struct ice_fltr_info *fi;
1784
-
1785
- fi = &fm_entry->fltr_info;
1786
- if ((fi->fltr_act == ICE_FWD_TO_VSI &&
1787
- fi->fwd_id.vsi_id == vsi_id) ||
1788
- (fi->fltr_act == ICE_FWD_TO_VSI_LIST &&
1789
- (test_bit(vsi_id, fm_entry->vsi_list_info->vsi_map)))) {
1790
- struct ice_fltr_list_entry *tmp;
1791
-
1792
- /* this memory is freed up in the caller function
1793
- * ice_remove_vsi_lkup_fltr() once filters for
1794
- * this VSI are removed
1795
- */
1796
- tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp),
1797
- GFP_KERNEL);
1798
- if (!tmp)
1799
- return ICE_ERR_NO_MEMORY;
1800
-
1801
- memcpy(&tmp->fltr_info, fi, sizeof(*fi));
1802
-
1803
- /* Expected below fields to be set to ICE_FWD_TO_VSI and
1804
- * the particular VSI id since we are only removing this
1805
- * one VSI
1806
- */
1807
- if (fi->fltr_act == ICE_FWD_TO_VSI_LIST) {
1808
- tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
1809
- tmp->fltr_info.fwd_id.vsi_id = vsi_id;
1810
- }
1811
-
1812
- list_add(&tmp->list_entry, vsi_list_head);
1813
- }
2208
+ if (l_type != ICE_SW_LKUP_VLAN)
2209
+ return ICE_ERR_PARAM;
2210
+ v_list_itr->status = ice_remove_rule_internal(hw,
2211
+ ICE_SW_LKUP_VLAN,
2212
+ v_list_itr);
2213
+ if (v_list_itr->status)
2214
+ return v_list_itr->status;
18142215 }
18152216 return 0;
18162217 }
18172218
18182219 /**
2220
+ * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
2221
+ * @fm_entry: filter entry to inspect
2222
+ * @vsi_handle: VSI handle to compare with filter info
2223
+ */
2224
+static bool
2225
+ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
2226
+{
2227
+ return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
2228
+ fm_entry->fltr_info.vsi_handle == vsi_handle) ||
2229
+ (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
2230
+ fm_entry->vsi_list_info &&
2231
+ (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
2232
+}
2233
+
2234
+/**
2235
+ * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
2236
+ * @hw: pointer to the hardware structure
2237
+ * @vsi_handle: VSI handle to remove filters from
2238
+ * @vsi_list_head: pointer to the list to add entry to
2239
+ * @fi: pointer to fltr_info of filter entry to copy & add
2240
+ *
2241
+ * Helper function, used when creating a list of filters to remove from
2242
+ * a specific VSI. The entry added to vsi_list_head is a COPY of the
2243
+ * original filter entry, with the exception of fltr_info.fltr_act and
2244
+ * fltr_info.fwd_id fields. These are set such that later logic can
2245
+ * extract which VSI to remove the fltr from, and pass on that information.
2246
+ */
2247
+static enum ice_status
2248
+ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
2249
+ struct list_head *vsi_list_head,
2250
+ struct ice_fltr_info *fi)
2251
+{
2252
+ struct ice_fltr_list_entry *tmp;
2253
+
2254
+ /* this memory is freed up in the caller function
2255
+ * once filters for this VSI are removed
2256
+ */
2257
+ tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp), GFP_KERNEL);
2258
+ if (!tmp)
2259
+ return ICE_ERR_NO_MEMORY;
2260
+
2261
+ tmp->fltr_info = *fi;
2262
+
2263
+ /* Overwrite these fields to indicate which VSI to remove filter from,
2264
+ * so find and remove logic can extract the information from the
2265
+ * list entries. Note that original entries will still have proper
2266
+ * values.
2267
+ */
2268
+ tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
2269
+ tmp->fltr_info.vsi_handle = vsi_handle;
2270
+ tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2271
+
2272
+ list_add(&tmp->list_entry, vsi_list_head);
2273
+
2274
+ return 0;
2275
+}
2276
+
2277
+/**
2278
+ * ice_add_to_vsi_fltr_list - Add VSI filters to the list
2279
+ * @hw: pointer to the hardware structure
2280
+ * @vsi_handle: VSI handle to remove filters from
2281
+ * @lkup_list_head: pointer to the list that has certain lookup type filters
2282
+ * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
2283
+ *
2284
+ * Locates all filters in lkup_list_head that are used by the given VSI,
2285
+ * and adds COPIES of those entries to vsi_list_head (intended to be used
2286
+ * to remove the listed filters).
2287
+ * Note that this means all entries in vsi_list_head must be explicitly
2288
+ * deallocated by the caller when done with list.
2289
+ */
2290
+static enum ice_status
2291
+ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
2292
+ struct list_head *lkup_list_head,
2293
+ struct list_head *vsi_list_head)
2294
+{
2295
+ struct ice_fltr_mgmt_list_entry *fm_entry;
2296
+ enum ice_status status = 0;
2297
+
2298
+ /* check to make sure VSI ID is valid and within boundary */
2299
+ if (!ice_is_vsi_valid(hw, vsi_handle))
2300
+ return ICE_ERR_PARAM;
2301
+
2302
+ list_for_each_entry(fm_entry, lkup_list_head, list_entry) {
2303
+ if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))
2304
+ continue;
2305
+
2306
+ status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
2307
+ vsi_list_head,
2308
+ &fm_entry->fltr_info);
2309
+ if (status)
2310
+ return status;
2311
+ }
2312
+ return status;
2313
+}
2314
+
2315
+/**
2316
+ * ice_determine_promisc_mask
2317
+ * @fi: filter info to parse
2318
+ *
2319
+ * Helper function to determine which ICE_PROMISC_ mask corresponds
2320
+ * to given filter into.
2321
+ */
2322
+static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
2323
+{
2324
+ u16 vid = fi->l_data.mac_vlan.vlan_id;
2325
+ u8 *macaddr = fi->l_data.mac.mac_addr;
2326
+ bool is_tx_fltr = false;
2327
+ u8 promisc_mask = 0;
2328
+
2329
+ if (fi->flag == ICE_FLTR_TX)
2330
+ is_tx_fltr = true;
2331
+
2332
+ if (is_broadcast_ether_addr(macaddr))
2333
+ promisc_mask |= is_tx_fltr ?
2334
+ ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
2335
+ else if (is_multicast_ether_addr(macaddr))
2336
+ promisc_mask |= is_tx_fltr ?
2337
+ ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
2338
+ else if (is_unicast_ether_addr(macaddr))
2339
+ promisc_mask |= is_tx_fltr ?
2340
+ ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
2341
+ if (vid)
2342
+ promisc_mask |= is_tx_fltr ?
2343
+ ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
2344
+
2345
+ return promisc_mask;
2346
+}
2347
+
2348
+/**
2349
+ * ice_remove_promisc - Remove promisc based filter rules
2350
+ * @hw: pointer to the hardware structure
2351
+ * @recp_id: recipe ID for which the rule needs to removed
2352
+ * @v_list: list of promisc entries
2353
+ */
2354
+static enum ice_status
2355
+ice_remove_promisc(struct ice_hw *hw, u8 recp_id,
2356
+ struct list_head *v_list)
2357
+{
2358
+ struct ice_fltr_list_entry *v_list_itr, *tmp;
2359
+
2360
+ list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
2361
+ v_list_itr->status =
2362
+ ice_remove_rule_internal(hw, recp_id, v_list_itr);
2363
+ if (v_list_itr->status)
2364
+ return v_list_itr->status;
2365
+ }
2366
+ return 0;
2367
+}
2368
+
2369
+/**
2370
+ * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
2371
+ * @hw: pointer to the hardware structure
2372
+ * @vsi_handle: VSI handle to clear mode
2373
+ * @promisc_mask: mask of promiscuous config bits to clear
2374
+ * @vid: VLAN ID to clear VLAN promiscuous
2375
+ */
2376
+enum ice_status
2377
+ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
2378
+ u16 vid)
2379
+{
2380
+ struct ice_switch_info *sw = hw->switch_info;
2381
+ struct ice_fltr_list_entry *fm_entry, *tmp;
2382
+ struct list_head remove_list_head;
2383
+ struct ice_fltr_mgmt_list_entry *itr;
2384
+ struct list_head *rule_head;
2385
+ struct mutex *rule_lock; /* Lock to protect filter rule list */
2386
+ enum ice_status status = 0;
2387
+ u8 recipe_id;
2388
+
2389
+ if (!ice_is_vsi_valid(hw, vsi_handle))
2390
+ return ICE_ERR_PARAM;
2391
+
2392
+ if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX))
2393
+ recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
2394
+ else
2395
+ recipe_id = ICE_SW_LKUP_PROMISC;
2396
+
2397
+ rule_head = &sw->recp_list[recipe_id].filt_rules;
2398
+ rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
2399
+
2400
+ INIT_LIST_HEAD(&remove_list_head);
2401
+
2402
+ mutex_lock(rule_lock);
2403
+ list_for_each_entry(itr, rule_head, list_entry) {
2404
+ struct ice_fltr_info *fltr_info;
2405
+ u8 fltr_promisc_mask = 0;
2406
+
2407
+ if (!ice_vsi_uses_fltr(itr, vsi_handle))
2408
+ continue;
2409
+ fltr_info = &itr->fltr_info;
2410
+
2411
+ if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN &&
2412
+ vid != fltr_info->l_data.mac_vlan.vlan_id)
2413
+ continue;
2414
+
2415
+ fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info);
2416
+
2417
+ /* Skip if filter is not completely specified by given mask */
2418
+ if (fltr_promisc_mask & ~promisc_mask)
2419
+ continue;
2420
+
2421
+ status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
2422
+ &remove_list_head,
2423
+ fltr_info);
2424
+ if (status) {
2425
+ mutex_unlock(rule_lock);
2426
+ goto free_fltr_list;
2427
+ }
2428
+ }
2429
+ mutex_unlock(rule_lock);
2430
+
2431
+ status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
2432
+
2433
+free_fltr_list:
2434
+ list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
2435
+ list_del(&fm_entry->list_entry);
2436
+ devm_kfree(ice_hw_to_dev(hw), fm_entry);
2437
+ }
2438
+
2439
+ return status;
2440
+}
2441
+
2442
+/**
2443
+ * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
2444
+ * @hw: pointer to the hardware structure
2445
+ * @vsi_handle: VSI handle to configure
2446
+ * @promisc_mask: mask of promiscuous config bits
2447
+ * @vid: VLAN ID to set VLAN promiscuous
2448
+ */
2449
+enum ice_status
2450
+ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
2451
+{
2452
+ enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
2453
+ struct ice_fltr_list_entry f_list_entry;
2454
+ struct ice_fltr_info new_fltr;
2455
+ enum ice_status status = 0;
2456
+ bool is_tx_fltr;
2457
+ u16 hw_vsi_id;
2458
+ int pkt_type;
2459
+ u8 recipe_id;
2460
+
2461
+ if (!ice_is_vsi_valid(hw, vsi_handle))
2462
+ return ICE_ERR_PARAM;
2463
+ hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2464
+
2465
+ memset(&new_fltr, 0, sizeof(new_fltr));
2466
+
2467
+ if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
2468
+ new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
2469
+ new_fltr.l_data.mac_vlan.vlan_id = vid;
2470
+ recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
2471
+ } else {
2472
+ new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
2473
+ recipe_id = ICE_SW_LKUP_PROMISC;
2474
+ }
2475
+
2476
+ /* Separate filters must be set for each direction/packet type
2477
+ * combination, so we will loop over the mask value, store the
2478
+ * individual type, and clear it out in the input mask as it
2479
+ * is found.
2480
+ */
2481
+ while (promisc_mask) {
2482
+ u8 *mac_addr;
2483
+
2484
+ pkt_type = 0;
2485
+ is_tx_fltr = false;
2486
+
2487
+ if (promisc_mask & ICE_PROMISC_UCAST_RX) {
2488
+ promisc_mask &= ~ICE_PROMISC_UCAST_RX;
2489
+ pkt_type = UCAST_FLTR;
2490
+ } else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
2491
+ promisc_mask &= ~ICE_PROMISC_UCAST_TX;
2492
+ pkt_type = UCAST_FLTR;
2493
+ is_tx_fltr = true;
2494
+ } else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
2495
+ promisc_mask &= ~ICE_PROMISC_MCAST_RX;
2496
+ pkt_type = MCAST_FLTR;
2497
+ } else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
2498
+ promisc_mask &= ~ICE_PROMISC_MCAST_TX;
2499
+ pkt_type = MCAST_FLTR;
2500
+ is_tx_fltr = true;
2501
+ } else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
2502
+ promisc_mask &= ~ICE_PROMISC_BCAST_RX;
2503
+ pkt_type = BCAST_FLTR;
2504
+ } else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
2505
+ promisc_mask &= ~ICE_PROMISC_BCAST_TX;
2506
+ pkt_type = BCAST_FLTR;
2507
+ is_tx_fltr = true;
2508
+ }
2509
+
2510
+ /* Check for VLAN promiscuous flag */
2511
+ if (promisc_mask & ICE_PROMISC_VLAN_RX) {
2512
+ promisc_mask &= ~ICE_PROMISC_VLAN_RX;
2513
+ } else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
2514
+ promisc_mask &= ~ICE_PROMISC_VLAN_TX;
2515
+ is_tx_fltr = true;
2516
+ }
2517
+
2518
+ /* Set filter DA based on packet type */
2519
+ mac_addr = new_fltr.l_data.mac.mac_addr;
2520
+ if (pkt_type == BCAST_FLTR) {
2521
+ eth_broadcast_addr(mac_addr);
2522
+ } else if (pkt_type == MCAST_FLTR ||
2523
+ pkt_type == UCAST_FLTR) {
2524
+ /* Use the dummy ether header DA */
2525
+ ether_addr_copy(mac_addr, dummy_eth_header);
2526
+ if (pkt_type == MCAST_FLTR)
2527
+ mac_addr[0] |= 0x1; /* Set multicast bit */
2528
+ }
2529
+
2530
+ /* Need to reset this to zero for all iterations */
2531
+ new_fltr.flag = 0;
2532
+ if (is_tx_fltr) {
2533
+ new_fltr.flag |= ICE_FLTR_TX;
2534
+ new_fltr.src = hw_vsi_id;
2535
+ } else {
2536
+ new_fltr.flag |= ICE_FLTR_RX;
2537
+ new_fltr.src = hw->port_info->lport;
2538
+ }
2539
+
2540
+ new_fltr.fltr_act = ICE_FWD_TO_VSI;
2541
+ new_fltr.vsi_handle = vsi_handle;
2542
+ new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
2543
+ f_list_entry.fltr_info = new_fltr;
2544
+
2545
+ status = ice_add_rule_internal(hw, recipe_id, &f_list_entry);
2546
+ if (status)
2547
+ goto set_promisc_exit;
2548
+ }
2549
+
2550
+set_promisc_exit:
2551
+ return status;
2552
+}
2553
+
2554
+/**
2555
+ * ice_set_vlan_vsi_promisc
2556
+ * @hw: pointer to the hardware structure
2557
+ * @vsi_handle: VSI handle to configure
2558
+ * @promisc_mask: mask of promiscuous config bits
2559
+ * @rm_vlan_promisc: Clear VLANs VSI promisc mode
2560
+ *
2561
+ * Configure VSI with all associated VLANs to given promiscuous mode(s)
2562
+ */
2563
+enum ice_status
2564
+ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
2565
+ bool rm_vlan_promisc)
2566
+{
2567
+ struct ice_switch_info *sw = hw->switch_info;
2568
+ struct ice_fltr_list_entry *list_itr, *tmp;
2569
+ struct list_head vsi_list_head;
2570
+ struct list_head *vlan_head;
2571
+ struct mutex *vlan_lock; /* Lock to protect filter rule list */
2572
+ enum ice_status status;
2573
+ u16 vlan_id;
2574
+
2575
+ INIT_LIST_HEAD(&vsi_list_head);
2576
+ vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
2577
+ vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
2578
+ mutex_lock(vlan_lock);
2579
+ status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
2580
+ &vsi_list_head);
2581
+ mutex_unlock(vlan_lock);
2582
+ if (status)
2583
+ goto free_fltr_list;
2584
+
2585
+ list_for_each_entry(list_itr, &vsi_list_head, list_entry) {
2586
+ vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
2587
+ if (rm_vlan_promisc)
2588
+ status = ice_clear_vsi_promisc(hw, vsi_handle,
2589
+ promisc_mask, vlan_id);
2590
+ else
2591
+ status = ice_set_vsi_promisc(hw, vsi_handle,
2592
+ promisc_mask, vlan_id);
2593
+ if (status && status != -EEXIST)
2594
+ break;
2595
+ }
2596
+
2597
+free_fltr_list:
2598
+ list_for_each_entry_safe(list_itr, tmp, &vsi_list_head, list_entry) {
2599
+ list_del(&list_itr->list_entry);
2600
+ devm_kfree(ice_hw_to_dev(hw), list_itr);
2601
+ }
2602
+ return status;
2603
+}
2604
+
2605
+/**
18192606 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
18202607 * @hw: pointer to the hardware structure
1821
- * @vsi_id: ID of VSI to remove filters from
2608
+ * @vsi_handle: VSI handle to remove filters from
18222609 * @lkup: switch rule filter lookup type
18232610 */
18242611 static void
1825
-ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_id,
2612
+ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
18262613 enum ice_sw_lkup_type lkup)
18272614 {
18282615 struct ice_switch_info *sw = hw->switch_info;
18292616 struct ice_fltr_list_entry *fm_entry;
18302617 struct list_head remove_list_head;
2618
+ struct list_head *rule_head;
18312619 struct ice_fltr_list_entry *tmp;
2620
+ struct mutex *rule_lock; /* Lock to protect filter rule list */
18322621 enum ice_status status;
18332622
18342623 INIT_LIST_HEAD(&remove_list_head);
2624
+ rule_lock = &sw->recp_list[lkup].filt_rule_lock;
2625
+ rule_head = &sw->recp_list[lkup].filt_rules;
2626
+ mutex_lock(rule_lock);
2627
+ status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
2628
+ &remove_list_head);
2629
+ mutex_unlock(rule_lock);
2630
+ if (status)
2631
+ goto free_fltr_list;
2632
+
18352633 switch (lkup) {
18362634 case ICE_SW_LKUP_MAC:
1837
- mutex_lock(&sw->mac_list_lock);
1838
- status = ice_add_to_vsi_fltr_list(hw, vsi_id,
1839
- &sw->mac_list_head,
1840
- &remove_list_head);
1841
- mutex_unlock(&sw->mac_list_lock);
1842
- if (!status) {
1843
- ice_remove_mac(hw, &remove_list_head);
1844
- goto free_fltr_list;
1845
- }
2635
+ ice_remove_mac(hw, &remove_list_head);
18462636 break;
18472637 case ICE_SW_LKUP_VLAN:
1848
- mutex_lock(&sw->vlan_list_lock);
1849
- status = ice_add_to_vsi_fltr_list(hw, vsi_id,
1850
- &sw->vlan_list_head,
1851
- &remove_list_head);
1852
- mutex_unlock(&sw->vlan_list_lock);
1853
- if (!status) {
1854
- ice_remove_vlan(hw, &remove_list_head);
1855
- goto free_fltr_list;
1856
- }
2638
+ ice_remove_vlan(hw, &remove_list_head);
2639
+ break;
2640
+ case ICE_SW_LKUP_PROMISC:
2641
+ case ICE_SW_LKUP_PROMISC_VLAN:
2642
+ ice_remove_promisc(hw, lkup, &remove_list_head);
18572643 break;
18582644 case ICE_SW_LKUP_MAC_VLAN:
18592645 case ICE_SW_LKUP_ETHERTYPE:
18602646 case ICE_SW_LKUP_ETHERTYPE_MAC:
1861
- case ICE_SW_LKUP_PROMISC:
1862
- case ICE_SW_LKUP_PROMISC_VLAN:
18632647 case ICE_SW_LKUP_DFLT:
1864
- ice_debug(hw, ICE_DBG_SW,
1865
- "Remove filters for this lookup type hasn't been implemented yet\n");
2648
+ case ICE_SW_LKUP_LAST:
2649
+ default:
2650
+ ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup);
18662651 break;
18672652 }
18682653
1869
- return;
18702654 free_fltr_list:
18712655 list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
18722656 list_del(&fm_entry->list_entry);
....@@ -1877,16 +2661,196 @@
18772661 /**
18782662 * ice_remove_vsi_fltr - Remove all filters for a VSI
18792663 * @hw: pointer to the hardware structure
1880
- * @vsi_id: ID of VSI to remove filters from
2664
+ * @vsi_handle: VSI handle to remove filters from
18812665 */
1882
-void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_id)
2666
+void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
18832667 {
1884
- ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_MAC);
1885
- ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_MAC_VLAN);
1886
- ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_PROMISC);
1887
- ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_VLAN);
1888
- ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_DFLT);
1889
- ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_ETHERTYPE);
1890
- ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_ETHERTYPE_MAC);
1891
- ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_PROMISC_VLAN);
2668
+ ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC);
2669
+ ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN);
2670
+ ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC);
2671
+ ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN);
2672
+ ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT);
2673
+ ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE);
2674
+ ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC);
2675
+ ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN);
2676
+}
2677
+
2678
+/**
2679
+ * ice_alloc_res_cntr - allocating resource counter
2680
+ * @hw: pointer to the hardware structure
2681
+ * @type: type of resource
2682
+ * @alloc_shared: if set it is shared else dedicated
2683
+ * @num_items: number of entries requested for FD resource type
2684
+ * @counter_id: counter index returned by AQ call
2685
+ */
2686
+enum ice_status
2687
+ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
2688
+ u16 *counter_id)
2689
+{
2690
+ struct ice_aqc_alloc_free_res_elem *buf;
2691
+ enum ice_status status;
2692
+ u16 buf_len;
2693
+
2694
+ /* Allocate resource */
2695
+ buf_len = struct_size(buf, elem, 1);
2696
+ buf = kzalloc(buf_len, GFP_KERNEL);
2697
+ if (!buf)
2698
+ return ICE_ERR_NO_MEMORY;
2699
+
2700
+ buf->num_elems = cpu_to_le16(num_items);
2701
+ buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
2702
+ ICE_AQC_RES_TYPE_M) | alloc_shared);
2703
+
2704
+ status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
2705
+ ice_aqc_opc_alloc_res, NULL);
2706
+ if (status)
2707
+ goto exit;
2708
+
2709
+ *counter_id = le16_to_cpu(buf->elem[0].e.sw_resp);
2710
+
2711
+exit:
2712
+ kfree(buf);
2713
+ return status;
2714
+}
2715
+
2716
+/**
2717
+ * ice_free_res_cntr - free resource counter
2718
+ * @hw: pointer to the hardware structure
2719
+ * @type: type of resource
2720
+ * @alloc_shared: if set it is shared else dedicated
2721
+ * @num_items: number of entries to be freed for FD resource type
2722
+ * @counter_id: counter ID resource which needs to be freed
2723
+ */
2724
+enum ice_status
2725
+ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
2726
+ u16 counter_id)
2727
+{
2728
+ struct ice_aqc_alloc_free_res_elem *buf;
2729
+ enum ice_status status;
2730
+ u16 buf_len;
2731
+
2732
+ /* Free resource */
2733
+ buf_len = struct_size(buf, elem, 1);
2734
+ buf = kzalloc(buf_len, GFP_KERNEL);
2735
+ if (!buf)
2736
+ return ICE_ERR_NO_MEMORY;
2737
+
2738
+ buf->num_elems = cpu_to_le16(num_items);
2739
+ buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
2740
+ ICE_AQC_RES_TYPE_M) | alloc_shared);
2741
+ buf->elem[0].e.sw_resp = cpu_to_le16(counter_id);
2742
+
2743
+ status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
2744
+ ice_aqc_opc_free_res, NULL);
2745
+ if (status)
2746
+ ice_debug(hw, ICE_DBG_SW,
2747
+ "counter resource could not be freed\n");
2748
+
2749
+ kfree(buf);
2750
+ return status;
2751
+}
2752
+
2753
+/**
2754
+ * ice_replay_vsi_fltr - Replay filters for requested VSI
2755
+ * @hw: pointer to the hardware structure
2756
+ * @vsi_handle: driver VSI handle
2757
+ * @recp_id: Recipe ID for which rules need to be replayed
2758
+ * @list_head: list for which filters need to be replayed
2759
+ *
2760
+ * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
2761
+ * It is required to pass valid VSI handle.
2762
+ */
2763
+static enum ice_status
2764
+ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id,
2765
+ struct list_head *list_head)
2766
+{
2767
+ struct ice_fltr_mgmt_list_entry *itr;
2768
+ enum ice_status status = 0;
2769
+ u16 hw_vsi_id;
2770
+
2771
+ if (list_empty(list_head))
2772
+ return status;
2773
+ hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2774
+
2775
+ list_for_each_entry(itr, list_head, list_entry) {
2776
+ struct ice_fltr_list_entry f_entry;
2777
+
2778
+ f_entry.fltr_info = itr->fltr_info;
2779
+ if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
2780
+ itr->fltr_info.vsi_handle == vsi_handle) {
2781
+ /* update the src in case it is VSI num */
2782
+ if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
2783
+ f_entry.fltr_info.src = hw_vsi_id;
2784
+ status = ice_add_rule_internal(hw, recp_id, &f_entry);
2785
+ if (status)
2786
+ goto end;
2787
+ continue;
2788
+ }
2789
+ if (!itr->vsi_list_info ||
2790
+ !test_bit(vsi_handle, itr->vsi_list_info->vsi_map))
2791
+ continue;
2792
+ /* Clearing it so that the logic can add it back */
2793
+ clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
2794
+ f_entry.fltr_info.vsi_handle = vsi_handle;
2795
+ f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
2796
+ /* update the src in case it is VSI num */
2797
+ if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
2798
+ f_entry.fltr_info.src = hw_vsi_id;
2799
+ if (recp_id == ICE_SW_LKUP_VLAN)
2800
+ status = ice_add_vlan_internal(hw, &f_entry);
2801
+ else
2802
+ status = ice_add_rule_internal(hw, recp_id, &f_entry);
2803
+ if (status)
2804
+ goto end;
2805
+ }
2806
+end:
2807
+ return status;
2808
+}
2809
+
2810
+/**
2811
+ * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
2812
+ * @hw: pointer to the hardware structure
2813
+ * @vsi_handle: driver VSI handle
2814
+ *
2815
+ * Replays filters for requested VSI via vsi_handle.
2816
+ */
2817
+enum ice_status ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle)
2818
+{
2819
+ struct ice_switch_info *sw = hw->switch_info;
2820
+ enum ice_status status = 0;
2821
+ u8 i;
2822
+
2823
+ for (i = 0; i < ICE_SW_LKUP_LAST; i++) {
2824
+ struct list_head *head;
2825
+
2826
+ head = &sw->recp_list[i].filt_replay_rules;
2827
+ status = ice_replay_vsi_fltr(hw, vsi_handle, i, head);
2828
+ if (status)
2829
+ return status;
2830
+ }
2831
+ return status;
2832
+}
2833
+
2834
+/**
2835
+ * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
2836
+ * @hw: pointer to the HW struct
2837
+ *
2838
+ * Deletes the filter replay rules.
2839
+ */
2840
+void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
2841
+{
2842
+ struct ice_switch_info *sw = hw->switch_info;
2843
+ u8 i;
2844
+
2845
+ if (!sw)
2846
+ return;
2847
+
2848
+ for (i = 0; i < ICE_SW_LKUP_LAST; i++) {
2849
+ if (!list_empty(&sw->recp_list[i].filt_replay_rules)) {
2850
+ struct list_head *l_head;
2851
+
2852
+ l_head = &sw->recp_list[i].filt_replay_rules;
2853
+ ice_rem_sw_rule_info(hw, l_head);
2854
+ }
2855
+ }
18922856 }