]>
Commit | Line | Data |
---|---|---|
4ad79e13 | 1 | /* bnx2x_sp.c: Qlogic Everest network driver. |
619c5cb6 | 2 | * |
4ad79e13 YM |
3 | * Copyright 2011-2013 Broadcom Corporation |
4 | * Copyright (c) 2014 QLogic Corporation | |
5 | * All rights reserved | |
619c5cb6 | 6 | * |
4ad79e13 | 7 | * Unless you and Qlogic execute a separate written software license |
619c5cb6 VZ |
8 | * agreement governing use of this software, this software is licensed to you |
9 | * under the terms of the GNU General Public License version 2, available | |
4ad79e13 | 10 | * at http://www.gnu.org/licenses/gpl-2.0.html (the "GPL"). |
619c5cb6 VZ |
11 | * |
12 | * Notwithstanding the above, under no circumstances may you combine this | |
4ad79e13 YM |
13 | * software in any way with any other Qlogic software provided under a |
14 | * license other than the GPL, without Qlogic's express prior written | |
619c5cb6 VZ |
15 | * consent. |
16 | * | |
08f6dd89 | 17 | * Maintained by: Ariel Elior <[email protected]> |
619c5cb6 VZ |
18 | * Written by: Vladislav Zolotarov |
19 | * | |
20 | */ | |
f1deab50 JP |
21 | |
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
23 | ||
042181f5 VZ |
24 | #include <linux/module.h> |
25 | #include <linux/crc32.h> | |
26 | #include <linux/netdevice.h> | |
27 | #include <linux/etherdevice.h> | |
28 | #include <linux/crc32c.h> | |
29 | #include "bnx2x.h" | |
30 | #include "bnx2x_cmn.h" | |
31 | #include "bnx2x_sp.h" | |
32 | ||
619c5cb6 VZ |
33 | #define BNX2X_MAX_EMUL_MULTI 16 |
34 | ||
35 | /**** Exe Queue interfaces ****/ | |
042181f5 VZ |
36 | |
37 | /** | |
619c5cb6 | 38 | * bnx2x_exe_queue_init - init the Exe Queue object |
042181f5 | 39 | * |
16a5fd92 | 40 | * @o: pointer to the object |
619c5cb6 | 41 | * @exe_len: length |
16a5fd92 | 42 | * @owner: pointer to the owner |
619c5cb6 VZ |
43 | * @validate: validate function pointer |
44 | * @optimize: optimize function pointer | |
45 | * @exec: execute function pointer | |
46 | * @get: get function pointer | |
042181f5 | 47 | */ |
619c5cb6 VZ |
48 | static inline void bnx2x_exe_queue_init(struct bnx2x *bp, |
49 | struct bnx2x_exe_queue_obj *o, | |
50 | int exe_len, | |
51 | union bnx2x_qable_obj *owner, | |
52 | exe_q_validate validate, | |
460a25cd | 53 | exe_q_remove remove, |
619c5cb6 VZ |
54 | exe_q_optimize optimize, |
55 | exe_q_execute exec, | |
56 | exe_q_get get) | |
042181f5 | 57 | { |
619c5cb6 | 58 | memset(o, 0, sizeof(*o)); |
042181f5 | 59 | |
619c5cb6 VZ |
60 | INIT_LIST_HEAD(&o->exe_queue); |
61 | INIT_LIST_HEAD(&o->pending_comp); | |
042181f5 | 62 | |
619c5cb6 | 63 | spin_lock_init(&o->lock); |
042181f5 | 64 | |
619c5cb6 VZ |
65 | o->exe_chunk_len = exe_len; |
66 | o->owner = owner; | |
042181f5 | 67 | |
619c5cb6 VZ |
68 | /* Owner specific callbacks */ |
69 | o->validate = validate; | |
460a25cd | 70 | o->remove = remove; |
619c5cb6 VZ |
71 | o->optimize = optimize; |
72 | o->execute = exec; | |
73 | o->get = get; | |
042181f5 | 74 | |
51c1a580 MS |
75 | DP(BNX2X_MSG_SP, "Setup the execution queue with the chunk length of %d\n", |
76 | exe_len); | |
042181f5 VZ |
77 | } |
78 | ||
619c5cb6 VZ |
79 | static inline void bnx2x_exe_queue_free_elem(struct bnx2x *bp, |
80 | struct bnx2x_exeq_elem *elem) | |
81 | { | |
82 | DP(BNX2X_MSG_SP, "Deleting an exe_queue element\n"); | |
83 | kfree(elem); | |
84 | } | |
042181f5 | 85 | |
619c5cb6 | 86 | static inline int bnx2x_exe_queue_length(struct bnx2x_exe_queue_obj *o) |
042181f5 | 87 | { |
619c5cb6 VZ |
88 | struct bnx2x_exeq_elem *elem; |
89 | int cnt = 0; | |
90 | ||
91 | spin_lock_bh(&o->lock); | |
92 | ||
93 | list_for_each_entry(elem, &o->exe_queue, link) | |
94 | cnt++; | |
95 | ||
96 | spin_unlock_bh(&o->lock); | |
97 | ||
98 | return cnt; | |
042181f5 VZ |
99 | } |
100 | ||
619c5cb6 VZ |
101 | /** |
102 | * bnx2x_exe_queue_add - add a new element to the execution queue | |
103 | * | |
104 | * @bp: driver handle | |
105 | * @o: queue | |
106 | * @cmd: new command to add | |
107 | * @restore: true - do not optimize the command | |
042181f5 | 108 | * |
619c5cb6 | 109 | * If the element is optimized or is illegal, frees it. |
042181f5 | 110 | */ |
619c5cb6 VZ |
111 | static inline int bnx2x_exe_queue_add(struct bnx2x *bp, |
112 | struct bnx2x_exe_queue_obj *o, | |
113 | struct bnx2x_exeq_elem *elem, | |
114 | bool restore) | |
042181f5 | 115 | { |
619c5cb6 | 116 | int rc; |
042181f5 | 117 | |
619c5cb6 | 118 | spin_lock_bh(&o->lock); |
042181f5 | 119 | |
619c5cb6 VZ |
120 | if (!restore) { |
121 | /* Try to cancel this element queue */ | |
122 | rc = o->optimize(bp, o->owner, elem); | |
123 | if (rc) | |
124 | goto free_and_exit; | |
125 | ||
126 | /* Check if this request is ok */ | |
127 | rc = o->validate(bp, o->owner, elem); | |
128 | if (rc) { | |
2384d6aa | 129 | DP(BNX2X_MSG_SP, "Preamble failed: %d\n", rc); |
619c5cb6 | 130 | goto free_and_exit; |
042181f5 VZ |
131 | } |
132 | } | |
133 | ||
619c5cb6 VZ |
134 | /* If so, add it to the execution queue */ |
135 | list_add_tail(&elem->link, &o->exe_queue); | |
042181f5 | 136 | |
619c5cb6 | 137 | spin_unlock_bh(&o->lock); |
042181f5 | 138 | |
619c5cb6 | 139 | return 0; |
042181f5 | 140 | |
619c5cb6 VZ |
141 | free_and_exit: |
142 | bnx2x_exe_queue_free_elem(bp, elem); | |
042181f5 | 143 | |
619c5cb6 | 144 | spin_unlock_bh(&o->lock); |
042181f5 | 145 | |
619c5cb6 | 146 | return rc; |
619c5cb6 | 147 | } |
042181f5 | 148 | |
619c5cb6 VZ |
149 | static inline void __bnx2x_exe_queue_reset_pending( |
150 | struct bnx2x *bp, | |
151 | struct bnx2x_exe_queue_obj *o) | |
152 | { | |
153 | struct bnx2x_exeq_elem *elem; | |
042181f5 | 154 | |
619c5cb6 VZ |
155 | while (!list_empty(&o->pending_comp)) { |
156 | elem = list_first_entry(&o->pending_comp, | |
157 | struct bnx2x_exeq_elem, link); | |
042181f5 | 158 | |
619c5cb6 VZ |
159 | list_del(&elem->link); |
160 | bnx2x_exe_queue_free_elem(bp, elem); | |
161 | } | |
042181f5 VZ |
162 | } |
163 | ||
619c5cb6 VZ |
164 | /** |
165 | * bnx2x_exe_queue_step - execute one execution chunk atomically | |
166 | * | |
167 | * @bp: driver handle | |
168 | * @o: queue | |
169 | * @ramrod_flags: flags | |
170 | * | |
8b09be5f | 171 | * (Should be called while holding the exe_queue->lock). |
619c5cb6 VZ |
172 | */ |
173 | static inline int bnx2x_exe_queue_step(struct bnx2x *bp, | |
174 | struct bnx2x_exe_queue_obj *o, | |
175 | unsigned long *ramrod_flags) | |
042181f5 | 176 | { |
619c5cb6 VZ |
177 | struct bnx2x_exeq_elem *elem, spacer; |
178 | int cur_len = 0, rc; | |
042181f5 | 179 | |
619c5cb6 | 180 | memset(&spacer, 0, sizeof(spacer)); |
042181f5 | 181 | |
16a5fd92 | 182 | /* Next step should not be performed until the current is finished, |
619c5cb6 VZ |
183 | * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to |
184 | * properly clear object internals without sending any command to the FW | |
185 | * which also implies there won't be any completion to clear the | |
186 | * 'pending' list. | |
187 | */ | |
188 | if (!list_empty(&o->pending_comp)) { | |
189 | if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags)) { | |
51c1a580 | 190 | DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: resetting a pending_comp list\n"); |
619c5cb6 VZ |
191 | __bnx2x_exe_queue_reset_pending(bp, o); |
192 | } else { | |
619c5cb6 VZ |
193 | return 1; |
194 | } | |
195 | } | |
042181f5 | 196 | |
16a5fd92 | 197 | /* Run through the pending commands list and create a next |
619c5cb6 VZ |
198 | * execution chunk. |
199 | */ | |
200 | while (!list_empty(&o->exe_queue)) { | |
201 | elem = list_first_entry(&o->exe_queue, struct bnx2x_exeq_elem, | |
202 | link); | |
203 | WARN_ON(!elem->cmd_len); | |
042181f5 | 204 | |
619c5cb6 VZ |
205 | if (cur_len + elem->cmd_len <= o->exe_chunk_len) { |
206 | cur_len += elem->cmd_len; | |
16a5fd92 | 207 | /* Prevent from both lists being empty when moving an |
619c5cb6 VZ |
208 | * element. This will allow the call of |
209 | * bnx2x_exe_queue_empty() without locking. | |
042181f5 | 210 | */ |
619c5cb6 VZ |
211 | list_add_tail(&spacer.link, &o->pending_comp); |
212 | mb(); | |
7933aa5c | 213 | list_move_tail(&elem->link, &o->pending_comp); |
619c5cb6 VZ |
214 | list_del(&spacer.link); |
215 | } else | |
216 | break; | |
042181f5 | 217 | } |
042181f5 | 218 | |
619c5cb6 | 219 | /* Sanity check */ |
8b09be5f | 220 | if (!cur_len) |
619c5cb6 | 221 | return 0; |
042181f5 | 222 | |
619c5cb6 VZ |
223 | rc = o->execute(bp, o->owner, &o->pending_comp, ramrod_flags); |
224 | if (rc < 0) | |
16a5fd92 YM |
225 | /* In case of an error return the commands back to the queue |
226 | * and reset the pending_comp. | |
619c5cb6 VZ |
227 | */ |
228 | list_splice_init(&o->pending_comp, &o->exe_queue); | |
229 | else if (!rc) | |
16a5fd92 | 230 | /* If zero is returned, means there are no outstanding pending |
619c5cb6 VZ |
231 | * completions and we may dismiss the pending list. |
232 | */ | |
233 | __bnx2x_exe_queue_reset_pending(bp, o); | |
042181f5 | 234 | |
619c5cb6 VZ |
235 | return rc; |
236 | } | |
042181f5 | 237 | |
619c5cb6 VZ |
238 | static inline bool bnx2x_exe_queue_empty(struct bnx2x_exe_queue_obj *o) |
239 | { | |
240 | bool empty = list_empty(&o->exe_queue); | |
042181f5 | 241 | |
619c5cb6 VZ |
242 | /* Don't reorder!!! */ |
243 | mb(); | |
042181f5 | 244 | |
619c5cb6 VZ |
245 | return empty && list_empty(&o->pending_comp); |
246 | } | |
042181f5 | 247 | |
619c5cb6 VZ |
248 | static inline struct bnx2x_exeq_elem *bnx2x_exe_queue_alloc_elem( |
249 | struct bnx2x *bp) | |
250 | { | |
251 | DP(BNX2X_MSG_SP, "Allocating a new exe_queue element\n"); | |
252 | return kzalloc(sizeof(struct bnx2x_exeq_elem), GFP_ATOMIC); | |
253 | } | |
042181f5 | 254 | |
619c5cb6 VZ |
255 | /************************ raw_obj functions ***********************************/ |
256 | static bool bnx2x_raw_check_pending(struct bnx2x_raw_obj *o) | |
257 | { | |
258 | return !!test_bit(o->state, o->pstate); | |
042181f5 VZ |
259 | } |
260 | ||
619c5cb6 | 261 | static void bnx2x_raw_clear_pending(struct bnx2x_raw_obj *o) |
042181f5 | 262 | { |
4e857c58 | 263 | smp_mb__before_atomic(); |
619c5cb6 | 264 | clear_bit(o->state, o->pstate); |
4e857c58 | 265 | smp_mb__after_atomic(); |
619c5cb6 | 266 | } |
042181f5 | 267 | |
619c5cb6 VZ |
268 | static void bnx2x_raw_set_pending(struct bnx2x_raw_obj *o) |
269 | { | |
4e857c58 | 270 | smp_mb__before_atomic(); |
619c5cb6 | 271 | set_bit(o->state, o->pstate); |
4e857c58 | 272 | smp_mb__after_atomic(); |
619c5cb6 | 273 | } |
042181f5 | 274 | |
619c5cb6 VZ |
275 | /** |
276 | * bnx2x_state_wait - wait until the given bit(state) is cleared | |
277 | * | |
278 | * @bp: device handle | |
279 | * @state: state which is to be cleared | |
280 | * @state_p: state buffer | |
281 | * | |
282 | */ | |
283 | static inline int bnx2x_state_wait(struct bnx2x *bp, int state, | |
284 | unsigned long *pstate) | |
285 | { | |
286 | /* can take a while if any port is running */ | |
287 | int cnt = 5000; | |
042181f5 | 288 | |
619c5cb6 VZ |
289 | if (CHIP_REV_IS_EMUL(bp)) |
290 | cnt *= 20; | |
042181f5 | 291 | |
619c5cb6 VZ |
292 | DP(BNX2X_MSG_SP, "waiting for state to become %d\n", state); |
293 | ||
294 | might_sleep(); | |
295 | while (cnt--) { | |
296 | if (!test_bit(state, pstate)) { | |
297 | #ifdef BNX2X_STOP_ON_ERROR | |
298 | DP(BNX2X_MSG_SP, "exit (cnt %d)\n", 5000 - cnt); | |
042181f5 | 299 | #endif |
619c5cb6 VZ |
300 | return 0; |
301 | } | |
042181f5 | 302 | |
0926d499 | 303 | usleep_range(1000, 2000); |
042181f5 | 304 | |
619c5cb6 VZ |
305 | if (bp->panic) |
306 | return -EIO; | |
307 | } | |
042181f5 | 308 | |
619c5cb6 VZ |
309 | /* timeout! */ |
310 | BNX2X_ERR("timeout waiting for state %d\n", state); | |
311 | #ifdef BNX2X_STOP_ON_ERROR | |
312 | bnx2x_panic(); | |
313 | #endif | |
042181f5 | 314 | |
619c5cb6 VZ |
315 | return -EBUSY; |
316 | } | |
042181f5 | 317 | |
619c5cb6 VZ |
318 | static int bnx2x_raw_wait(struct bnx2x *bp, struct bnx2x_raw_obj *raw) |
319 | { | |
320 | return bnx2x_state_wait(bp, raw->state, raw->pstate); | |
042181f5 VZ |
321 | } |
322 | ||
619c5cb6 VZ |
323 | /***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/ |
324 | /* credit handling callbacks */ | |
325 | static bool bnx2x_get_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int *offset) | |
042181f5 | 326 | { |
619c5cb6 VZ |
327 | struct bnx2x_credit_pool_obj *mp = o->macs_pool; |
328 | ||
329 | WARN_ON(!mp); | |
330 | ||
331 | return mp->get_entry(mp, offset); | |
042181f5 VZ |
332 | } |
333 | ||
619c5cb6 | 334 | static bool bnx2x_get_credit_mac(struct bnx2x_vlan_mac_obj *o) |
042181f5 | 335 | { |
619c5cb6 VZ |
336 | struct bnx2x_credit_pool_obj *mp = o->macs_pool; |
337 | ||
338 | WARN_ON(!mp); | |
339 | ||
340 | return mp->get(mp, 1); | |
042181f5 VZ |
341 | } |
342 | ||
619c5cb6 | 343 | static bool bnx2x_get_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int *offset) |
042181f5 | 344 | { |
619c5cb6 | 345 | struct bnx2x_credit_pool_obj *vp = o->vlans_pool; |
042181f5 | 346 | |
619c5cb6 | 347 | WARN_ON(!vp); |
042181f5 | 348 | |
619c5cb6 | 349 | return vp->get_entry(vp, offset); |
042181f5 VZ |
350 | } |
351 | ||
619c5cb6 | 352 | static bool bnx2x_get_credit_vlan(struct bnx2x_vlan_mac_obj *o) |
042181f5 | 353 | { |
619c5cb6 | 354 | struct bnx2x_credit_pool_obj *vp = o->vlans_pool; |
042181f5 | 355 | |
619c5cb6 | 356 | WARN_ON(!vp); |
042181f5 | 357 | |
619c5cb6 | 358 | return vp->get(vp, 1); |
042181f5 | 359 | } |
05cc5a39 YM |
360 | |
361 | static bool bnx2x_get_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o) | |
362 | { | |
363 | struct bnx2x_credit_pool_obj *mp = o->macs_pool; | |
364 | struct bnx2x_credit_pool_obj *vp = o->vlans_pool; | |
365 | ||
366 | if (!mp->get(mp, 1)) | |
367 | return false; | |
368 | ||
369 | if (!vp->get(vp, 1)) { | |
370 | mp->put(mp, 1); | |
371 | return false; | |
372 | } | |
373 | ||
374 | return true; | |
375 | } | |
376 | ||
619c5cb6 VZ |
377 | static bool bnx2x_put_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int offset) |
378 | { | |
379 | struct bnx2x_credit_pool_obj *mp = o->macs_pool; | |
380 | ||
381 | return mp->put_entry(mp, offset); | |
382 | } | |
042181f5 | 383 | |
619c5cb6 | 384 | static bool bnx2x_put_credit_mac(struct bnx2x_vlan_mac_obj *o) |
042181f5 | 385 | { |
619c5cb6 | 386 | struct bnx2x_credit_pool_obj *mp = o->macs_pool; |
042181f5 | 387 | |
619c5cb6 | 388 | return mp->put(mp, 1); |
042181f5 VZ |
389 | } |
390 | ||
619c5cb6 | 391 | static bool bnx2x_put_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int offset) |
042181f5 | 392 | { |
619c5cb6 VZ |
393 | struct bnx2x_credit_pool_obj *vp = o->vlans_pool; |
394 | ||
395 | return vp->put_entry(vp, offset); | |
396 | } | |
042181f5 | 397 | |
619c5cb6 VZ |
398 | static bool bnx2x_put_credit_vlan(struct bnx2x_vlan_mac_obj *o) |
399 | { | |
400 | struct bnx2x_credit_pool_obj *vp = o->vlans_pool; | |
042181f5 | 401 | |
619c5cb6 | 402 | return vp->put(vp, 1); |
042181f5 VZ |
403 | } |
404 | ||
05cc5a39 YM |
405 | static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o) |
406 | { | |
407 | struct bnx2x_credit_pool_obj *mp = o->macs_pool; | |
408 | struct bnx2x_credit_pool_obj *vp = o->vlans_pool; | |
409 | ||
410 | if (!mp->put(mp, 1)) | |
411 | return false; | |
412 | ||
413 | if (!vp->put(vp, 1)) { | |
414 | mp->get(mp, 1); | |
415 | return false; | |
416 | } | |
417 | ||
418 | return true; | |
419 | } | |
420 | ||
8b09be5f YM |
421 | /** |
422 | * __bnx2x_vlan_mac_h_write_trylock - try getting the vlan mac writer lock | |
423 | * | |
424 | * @bp: device handle | |
425 | * @o: vlan_mac object | |
426 | * | |
427 | * @details: Non-blocking implementation; should be called under execution | |
428 | * queue lock. | |
429 | */ | |
430 | static int __bnx2x_vlan_mac_h_write_trylock(struct bnx2x *bp, | |
431 | struct bnx2x_vlan_mac_obj *o) | |
432 | { | |
433 | if (o->head_reader) { | |
434 | DP(BNX2X_MSG_SP, "vlan_mac_lock writer - There are readers; Busy\n"); | |
435 | return -EBUSY; | |
436 | } | |
437 | ||
438 | DP(BNX2X_MSG_SP, "vlan_mac_lock writer - Taken\n"); | |
439 | return 0; | |
440 | } | |
441 | ||
442 | /** | |
443 | * __bnx2x_vlan_mac_h_exec_pending - execute step instead of a previous step | |
444 | * | |
445 | * @bp: device handle | |
446 | * @o: vlan_mac object | |
447 | * | |
448 | * @details Should be called under execution queue lock; notice it might release | |
449 | * and reclaim it during its run. | |
450 | */ | |
451 | static void __bnx2x_vlan_mac_h_exec_pending(struct bnx2x *bp, | |
452 | struct bnx2x_vlan_mac_obj *o) | |
453 | { | |
454 | int rc; | |
455 | unsigned long ramrod_flags = o->saved_ramrod_flags; | |
456 | ||
457 | DP(BNX2X_MSG_SP, "vlan_mac_lock execute pending command with ramrod flags %lu\n", | |
458 | ramrod_flags); | |
459 | o->head_exe_request = false; | |
460 | o->saved_ramrod_flags = 0; | |
461 | rc = bnx2x_exe_queue_step(bp, &o->exe_queue, &ramrod_flags); | |
9d18d270 | 462 | if ((rc != 0) && (rc != 1)) { |
8b09be5f YM |
463 | BNX2X_ERR("execution of pending commands failed with rc %d\n", |
464 | rc); | |
465 | #ifdef BNX2X_STOP_ON_ERROR | |
466 | bnx2x_panic(); | |
467 | #endif | |
468 | } | |
469 | } | |
470 | ||
471 | /** | |
472 | * __bnx2x_vlan_mac_h_pend - Pend an execution step which couldn't run | |
473 | * | |
474 | * @bp: device handle | |
475 | * @o: vlan_mac object | |
476 | * @ramrod_flags: ramrod flags of missed execution | |
477 | * | |
478 | * @details Should be called under execution queue lock. | |
479 | */ | |
480 | static void __bnx2x_vlan_mac_h_pend(struct bnx2x *bp, | |
481 | struct bnx2x_vlan_mac_obj *o, | |
482 | unsigned long ramrod_flags) | |
483 | { | |
484 | o->head_exe_request = true; | |
485 | o->saved_ramrod_flags = ramrod_flags; | |
486 | DP(BNX2X_MSG_SP, "Placing pending execution with ramrod flags %lu\n", | |
487 | ramrod_flags); | |
488 | } | |
489 | ||
490 | /** | |
491 | * __bnx2x_vlan_mac_h_write_unlock - unlock the vlan mac head list writer lock | |
492 | * | |
493 | * @bp: device handle | |
494 | * @o: vlan_mac object | |
495 | * | |
496 | * @details Should be called under execution queue lock. Notice if a pending | |
497 | * execution exists, it would perform it - possibly releasing and | |
498 | * reclaiming the execution queue lock. | |
499 | */ | |
500 | static void __bnx2x_vlan_mac_h_write_unlock(struct bnx2x *bp, | |
501 | struct bnx2x_vlan_mac_obj *o) | |
502 | { | |
503 | /* It's possible a new pending execution was added since this writer | |
504 | * executed. If so, execute again. [Ad infinitum] | |
505 | */ | |
506 | while (o->head_exe_request) { | |
507 | DP(BNX2X_MSG_SP, "vlan_mac_lock - writer release encountered a pending request\n"); | |
508 | __bnx2x_vlan_mac_h_exec_pending(bp, o); | |
509 | } | |
510 | } | |
511 | ||
8b09be5f YM |
512 | |
513 | /** | |
514 | * __bnx2x_vlan_mac_h_read_lock - lock the vlan mac head list reader lock | |
515 | * | |
516 | * @bp: device handle | |
517 | * @o: vlan_mac object | |
518 | * | |
519 | * @details Should be called under the execution queue lock. May sleep. May | |
520 | * release and reclaim execution queue lock during its run. | |
521 | */ | |
522 | static int __bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp, | |
523 | struct bnx2x_vlan_mac_obj *o) | |
524 | { | |
525 | /* If we got here, we're holding lock --> no WRITER exists */ | |
526 | o->head_reader++; | |
527 | DP(BNX2X_MSG_SP, "vlan_mac_lock - locked reader - number %d\n", | |
528 | o->head_reader); | |
529 | ||
530 | return 0; | |
531 | } | |
532 | ||
533 | /** | |
534 | * bnx2x_vlan_mac_h_read_lock - lock the vlan mac head list reader lock | |
535 | * | |
536 | * @bp: device handle | |
537 | * @o: vlan_mac object | |
538 | * | |
539 | * @details May sleep. Claims and releases execution queue lock during its run. | |
540 | */ | |
541 | int bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp, | |
542 | struct bnx2x_vlan_mac_obj *o) | |
543 | { | |
544 | int rc; | |
545 | ||
546 | spin_lock_bh(&o->exe_queue.lock); | |
547 | rc = __bnx2x_vlan_mac_h_read_lock(bp, o); | |
548 | spin_unlock_bh(&o->exe_queue.lock); | |
549 | ||
550 | return rc; | |
551 | } | |
552 | ||
553 | /** | |
554 | * __bnx2x_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock | |
555 | * | |
556 | * @bp: device handle | |
557 | * @o: vlan_mac object | |
558 | * | |
559 | * @details Should be called under execution queue lock. Notice if a pending | |
560 | * execution exists, it would be performed if this was the last | |
561 | * reader. possibly releasing and reclaiming the execution queue lock. | |
562 | */ | |
563 | static void __bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp, | |
564 | struct bnx2x_vlan_mac_obj *o) | |
565 | { | |
566 | if (!o->head_reader) { | |
567 | BNX2X_ERR("Need to release vlan mac reader lock, but lock isn't taken\n"); | |
568 | #ifdef BNX2X_STOP_ON_ERROR | |
569 | bnx2x_panic(); | |
570 | #endif | |
571 | } else { | |
572 | o->head_reader--; | |
573 | DP(BNX2X_MSG_SP, "vlan_mac_lock - decreased readers to %d\n", | |
574 | o->head_reader); | |
575 | } | |
576 | ||
577 | /* It's possible a new pending execution was added, and that this reader | |
578 | * was last - if so we need to execute the command. | |
579 | */ | |
580 | if (!o->head_reader && o->head_exe_request) { | |
581 | DP(BNX2X_MSG_SP, "vlan_mac_lock - reader release encountered a pending request\n"); | |
582 | ||
583 | /* Writer release will do the trick */ | |
584 | __bnx2x_vlan_mac_h_write_unlock(bp, o); | |
585 | } | |
586 | } | |
587 | ||
588 | /** | |
589 | * bnx2x_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock | |
590 | * | |
591 | * @bp: device handle | |
592 | * @o: vlan_mac object | |
593 | * | |
594 | * @details Notice if a pending execution exists, it would be performed if this | |
595 | * was the last reader. Claims and releases the execution queue lock | |
596 | * during its run. | |
597 | */ | |
598 | void bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp, | |
599 | struct bnx2x_vlan_mac_obj *o) | |
600 | { | |
601 | spin_lock_bh(&o->exe_queue.lock); | |
602 | __bnx2x_vlan_mac_h_read_unlock(bp, o); | |
603 | spin_unlock_bh(&o->exe_queue.lock); | |
604 | } | |
605 | ||
ed5162a0 | 606 | static int bnx2x_get_n_elements(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o, |
3ec9f9ca | 607 | int n, u8 *base, u8 stride, u8 size) |
ed5162a0 AE |
608 | { |
609 | struct bnx2x_vlan_mac_registry_elem *pos; | |
3ec9f9ca | 610 | u8 *next = base; |
ed5162a0 | 611 | int counter = 0; |
8b09be5f YM |
612 | int read_lock; |
613 | ||
614 | DP(BNX2X_MSG_SP, "get_n_elements - taking vlan_mac_lock (reader)\n"); | |
615 | read_lock = bnx2x_vlan_mac_h_read_lock(bp, o); | |
616 | if (read_lock != 0) | |
617 | BNX2X_ERR("get_n_elements failed to get vlan mac reader lock; Access without lock\n"); | |
ed5162a0 AE |
618 | |
619 | /* traverse list */ | |
620 | list_for_each_entry(pos, &o->head, link) { | |
621 | if (counter < n) { | |
3ec9f9ca | 622 | memcpy(next, &pos->u, size); |
ed5162a0 | 623 | counter++; |
3ec9f9ca AE |
624 | DP(BNX2X_MSG_SP, "copied element number %d to address %p element was:\n", |
625 | counter, next); | |
626 | next += stride + size; | |
ed5162a0 AE |
627 | } |
628 | } | |
8b09be5f YM |
629 | |
630 | if (read_lock == 0) { | |
631 | DP(BNX2X_MSG_SP, "get_n_elements - releasing vlan_mac_lock (reader)\n"); | |
632 | bnx2x_vlan_mac_h_read_unlock(bp, o); | |
633 | } | |
634 | ||
ed5162a0 AE |
635 | return counter * ETH_ALEN; |
636 | } | |
637 | ||
619c5cb6 | 638 | /* check_add() callbacks */ |
51c1a580 MS |
639 | static int bnx2x_check_mac_add(struct bnx2x *bp, |
640 | struct bnx2x_vlan_mac_obj *o, | |
619c5cb6 | 641 | union bnx2x_classification_ramrod_data *data) |
042181f5 | 642 | { |
619c5cb6 VZ |
643 | struct bnx2x_vlan_mac_registry_elem *pos; |
644 | ||
51c1a580 MS |
645 | DP(BNX2X_MSG_SP, "Checking MAC %pM for ADD command\n", data->mac.mac); |
646 | ||
619c5cb6 VZ |
647 | if (!is_valid_ether_addr(data->mac.mac)) |
648 | return -EINVAL; | |
042181f5 | 649 | |
619c5cb6 VZ |
650 | /* Check if a requested MAC already exists */ |
651 | list_for_each_entry(pos, &o->head, link) | |
8fd90de8 | 652 | if (ether_addr_equal(data->mac.mac, pos->u.mac.mac) && |
91226790 | 653 | (data->mac.is_inner_mac == pos->u.mac.is_inner_mac)) |
619c5cb6 | 654 | return -EEXIST; |
042181f5 | 655 | |
619c5cb6 | 656 | return 0; |
042181f5 VZ |
657 | } |
658 | ||
51c1a580 MS |
659 | static int bnx2x_check_vlan_add(struct bnx2x *bp, |
660 | struct bnx2x_vlan_mac_obj *o, | |
619c5cb6 | 661 | union bnx2x_classification_ramrod_data *data) |
042181f5 | 662 | { |
619c5cb6 | 663 | struct bnx2x_vlan_mac_registry_elem *pos; |
042181f5 | 664 | |
51c1a580 MS |
665 | DP(BNX2X_MSG_SP, "Checking VLAN %d for ADD command\n", data->vlan.vlan); |
666 | ||
619c5cb6 VZ |
667 | list_for_each_entry(pos, &o->head, link) |
668 | if (data->vlan.vlan == pos->u.vlan.vlan) | |
669 | return -EEXIST; | |
042181f5 | 670 | |
619c5cb6 | 671 | return 0; |
042181f5 VZ |
672 | } |
673 | ||
05cc5a39 YM |
674 | static int bnx2x_check_vlan_mac_add(struct bnx2x *bp, |
675 | struct bnx2x_vlan_mac_obj *o, | |
676 | union bnx2x_classification_ramrod_data *data) | |
677 | { | |
678 | struct bnx2x_vlan_mac_registry_elem *pos; | |
679 | ||
680 | DP(BNX2X_MSG_SP, "Checking VLAN_MAC (%pM, %d) for ADD command\n", | |
681 | data->vlan_mac.mac, data->vlan_mac.vlan); | |
682 | ||
683 | list_for_each_entry(pos, &o->head, link) | |
684 | if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) && | |
685 | (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac, | |
686 | ETH_ALEN)) && | |
687 | (data->vlan_mac.is_inner_mac == | |
688 | pos->u.vlan_mac.is_inner_mac)) | |
689 | return -EEXIST; | |
690 | ||
691 | return 0; | |
692 | } | |
693 | ||
619c5cb6 VZ |
694 | /* check_del() callbacks */ |
695 | static struct bnx2x_vlan_mac_registry_elem * | |
51c1a580 MS |
696 | bnx2x_check_mac_del(struct bnx2x *bp, |
697 | struct bnx2x_vlan_mac_obj *o, | |
619c5cb6 | 698 | union bnx2x_classification_ramrod_data *data) |
042181f5 | 699 | { |
619c5cb6 VZ |
700 | struct bnx2x_vlan_mac_registry_elem *pos; |
701 | ||
51c1a580 MS |
702 | DP(BNX2X_MSG_SP, "Checking MAC %pM for DEL command\n", data->mac.mac); |
703 | ||
619c5cb6 | 704 | list_for_each_entry(pos, &o->head, link) |
8fd90de8 | 705 | if (ether_addr_equal(data->mac.mac, pos->u.mac.mac) && |
91226790 | 706 | (data->mac.is_inner_mac == pos->u.mac.is_inner_mac)) |
619c5cb6 | 707 | return pos; |
042181f5 | 708 | |
619c5cb6 | 709 | return NULL; |
042181f5 VZ |
710 | } |
711 | ||
619c5cb6 | 712 | static struct bnx2x_vlan_mac_registry_elem * |
51c1a580 MS |
713 | bnx2x_check_vlan_del(struct bnx2x *bp, |
714 | struct bnx2x_vlan_mac_obj *o, | |
619c5cb6 | 715 | union bnx2x_classification_ramrod_data *data) |
042181f5 | 716 | { |
619c5cb6 | 717 | struct bnx2x_vlan_mac_registry_elem *pos; |
042181f5 | 718 | |
51c1a580 MS |
719 | DP(BNX2X_MSG_SP, "Checking VLAN %d for DEL command\n", data->vlan.vlan); |
720 | ||
619c5cb6 VZ |
721 | list_for_each_entry(pos, &o->head, link) |
722 | if (data->vlan.vlan == pos->u.vlan.vlan) | |
723 | return pos; | |
724 | ||
725 | return NULL; | |
042181f5 VZ |
726 | } |
727 | ||
05cc5a39 YM |
728 | static struct bnx2x_vlan_mac_registry_elem * |
729 | bnx2x_check_vlan_mac_del(struct bnx2x *bp, | |
730 | struct bnx2x_vlan_mac_obj *o, | |
731 | union bnx2x_classification_ramrod_data *data) | |
732 | { | |
733 | struct bnx2x_vlan_mac_registry_elem *pos; | |
734 | ||
735 | DP(BNX2X_MSG_SP, "Checking VLAN_MAC (%pM, %d) for DEL command\n", | |
736 | data->vlan_mac.mac, data->vlan_mac.vlan); | |
737 | ||
738 | list_for_each_entry(pos, &o->head, link) | |
739 | if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) && | |
740 | (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac, | |
741 | ETH_ALEN)) && | |
742 | (data->vlan_mac.is_inner_mac == | |
743 | pos->u.vlan_mac.is_inner_mac)) | |
744 | return pos; | |
745 | ||
746 | return NULL; | |
747 | } | |
748 | ||
619c5cb6 | 749 | /* check_move() callback */ |
51c1a580 MS |
750 | static bool bnx2x_check_move(struct bnx2x *bp, |
751 | struct bnx2x_vlan_mac_obj *src_o, | |
619c5cb6 VZ |
752 | struct bnx2x_vlan_mac_obj *dst_o, |
753 | union bnx2x_classification_ramrod_data *data) | |
042181f5 | 754 | { |
619c5cb6 VZ |
755 | struct bnx2x_vlan_mac_registry_elem *pos; |
756 | int rc; | |
757 | ||
758 | /* Check if we can delete the requested configuration from the first | |
759 | * object. | |
760 | */ | |
51c1a580 | 761 | pos = src_o->check_del(bp, src_o, data); |
619c5cb6 VZ |
762 | |
763 | /* check if configuration can be added */ | |
51c1a580 | 764 | rc = dst_o->check_add(bp, dst_o, data); |
619c5cb6 VZ |
765 | |
766 | /* If this classification can not be added (is already set) | |
767 | * or can't be deleted - return an error. | |
768 | */ | |
769 | if (rc || !pos) | |
770 | return false; | |
771 | ||
772 | return true; | |
042181f5 VZ |
773 | } |
774 | ||
619c5cb6 | 775 | static bool bnx2x_check_move_always_err( |
51c1a580 | 776 | struct bnx2x *bp, |
619c5cb6 VZ |
777 | struct bnx2x_vlan_mac_obj *src_o, |
778 | struct bnx2x_vlan_mac_obj *dst_o, | |
779 | union bnx2x_classification_ramrod_data *data) | |
042181f5 | 780 | { |
619c5cb6 | 781 | return false; |
042181f5 VZ |
782 | } |
783 | ||
619c5cb6 | 784 | static inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o) |
042181f5 | 785 | { |
619c5cb6 VZ |
786 | struct bnx2x_raw_obj *raw = &o->raw; |
787 | u8 rx_tx_flag = 0; | |
042181f5 | 788 | |
619c5cb6 VZ |
789 | if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) || |
790 | (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX)) | |
791 | rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_TX_CMD; | |
042181f5 | 792 | |
619c5cb6 VZ |
793 | if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) || |
794 | (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX)) | |
795 | rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_RX_CMD; | |
796 | ||
797 | return rx_tx_flag; | |
042181f5 VZ |
798 | } |
799 | ||
a8f47eb7 | 800 | static void bnx2x_set_mac_in_nig(struct bnx2x *bp, |
801 | bool add, unsigned char *dev_addr, int index) | |
042181f5 | 802 | { |
619c5cb6 VZ |
803 | u32 wb_data[2]; |
804 | u32 reg_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM : | |
805 | NIG_REG_LLH0_FUNC_MEM; | |
806 | ||
a3348722 BW |
807 | if (!IS_MF_SI(bp) && !IS_MF_AFEX(bp)) |
808 | return; | |
809 | ||
810 | if (index > BNX2X_LLH_CAM_MAX_PF_LINE) | |
619c5cb6 VZ |
811 | return; |
812 | ||
813 | DP(BNX2X_MSG_SP, "Going to %s LLH configuration at entry %d\n", | |
814 | (add ? "ADD" : "DELETE"), index); | |
815 | ||
816 | if (add) { | |
817 | /* LLH_FUNC_MEM is a u64 WB register */ | |
818 | reg_offset += 8*index; | |
042181f5 | 819 | |
619c5cb6 VZ |
820 | wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) | |
821 | (dev_addr[4] << 8) | dev_addr[5]); | |
822 | wb_data[1] = ((dev_addr[0] << 8) | dev_addr[1]); | |
042181f5 | 823 | |
619c5cb6 VZ |
824 | REG_WR_DMAE(bp, reg_offset, wb_data, 2); |
825 | } | |
042181f5 | 826 | |
619c5cb6 VZ |
827 | REG_WR(bp, (BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE : |
828 | NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4*index, add); | |
829 | } | |
042181f5 | 830 | |
619c5cb6 VZ |
831 | /** |
832 | * bnx2x_vlan_mac_set_cmd_hdr_e2 - set a header in a single classify ramrod | |
833 | * | |
834 | * @bp: device handle | |
835 | * @o: queue for which we want to configure this rule | |
836 | * @add: if true the command is an ADD command, DEL otherwise | |
837 | * @opcode: CLASSIFY_RULE_OPCODE_XXX | |
838 | * @hdr: pointer to a header to setup | |
839 | * | |
840 | */ | |
841 | static inline void bnx2x_vlan_mac_set_cmd_hdr_e2(struct bnx2x *bp, | |
842 | struct bnx2x_vlan_mac_obj *o, bool add, int opcode, | |
843 | struct eth_classify_cmd_header *hdr) | |
844 | { | |
845 | struct bnx2x_raw_obj *raw = &o->raw; | |
042181f5 | 846 | |
619c5cb6 VZ |
847 | hdr->client_id = raw->cl_id; |
848 | hdr->func_id = raw->func_id; | |
042181f5 | 849 | |
619c5cb6 VZ |
850 | /* Rx or/and Tx (internal switching) configuration ? */ |
851 | hdr->cmd_general_data |= | |
852 | bnx2x_vlan_mac_get_rx_tx_flag(o); | |
042181f5 | 853 | |
619c5cb6 VZ |
854 | if (add) |
855 | hdr->cmd_general_data |= ETH_CLASSIFY_CMD_HEADER_IS_ADD; | |
042181f5 | 856 | |
619c5cb6 VZ |
857 | hdr->cmd_general_data |= |
858 | (opcode << ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT); | |
859 | } | |
042181f5 | 860 | |
619c5cb6 VZ |
861 | /** |
862 | * bnx2x_vlan_mac_set_rdata_hdr_e2 - set the classify ramrod data header | |
863 | * | |
864 | * @cid: connection id | |
865 | * @type: BNX2X_FILTER_XXX_PENDING | |
16a5fd92 | 866 | * @hdr: pointer to header to setup |
619c5cb6 VZ |
867 | * @rule_cnt: |
868 | * | |
869 | * currently we always configure one rule and echo field to contain a CID and an | |
870 | * opcode type. | |
871 | */ | |
872 | static inline void bnx2x_vlan_mac_set_rdata_hdr_e2(u32 cid, int type, | |
873 | struct eth_classify_header *hdr, int rule_cnt) | |
874 | { | |
86564c3f YM |
875 | hdr->echo = cpu_to_le32((cid & BNX2X_SWCID_MASK) | |
876 | (type << BNX2X_SWCID_SHIFT)); | |
619c5cb6 VZ |
877 | hdr->rule_cnt = (u8)rule_cnt; |
878 | } | |
042181f5 | 879 | |
619c5cb6 VZ |
880 | /* hw_config() callbacks */ |
881 | static void bnx2x_set_one_mac_e2(struct bnx2x *bp, | |
882 | struct bnx2x_vlan_mac_obj *o, | |
883 | struct bnx2x_exeq_elem *elem, int rule_idx, | |
884 | int cam_offset) | |
885 | { | |
886 | struct bnx2x_raw_obj *raw = &o->raw; | |
887 | struct eth_classify_rules_ramrod_data *data = | |
888 | (struct eth_classify_rules_ramrod_data *)(raw->rdata); | |
889 | int rule_cnt = rule_idx + 1, cmd = elem->cmd_data.vlan_mac.cmd; | |
890 | union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx]; | |
891 | bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false; | |
892 | unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags; | |
893 | u8 *mac = elem->cmd_data.vlan_mac.u.mac.mac; | |
894 | ||
16a5fd92 | 895 | /* Set LLH CAM entry: currently only iSCSI and ETH macs are |
619c5cb6 VZ |
896 | * relevant. In addition, current implementation is tuned for a |
897 | * single ETH MAC. | |
898 | * | |
899 | * When multiple unicast ETH MACs PF configuration in switch | |
900 | * independent mode is required (NetQ, multiple netdev MACs, | |
901 | * etc.), consider better utilisation of 8 per function MAC | |
902 | * entries in the LLH register. There is also | |
903 | * NIG_REG_P[01]_LLH_FUNC_MEM2 registers that complete the | |
904 | * total number of CAM entries to 16. | |
905 | * | |
906 | * Currently we won't configure NIG for MACs other than a primary ETH | |
907 | * MAC and iSCSI L2 MAC. | |
908 | * | |
909 | * If this MAC is moving from one Queue to another, no need to change | |
910 | * NIG configuration. | |
911 | */ | |
912 | if (cmd != BNX2X_VLAN_MAC_MOVE) { | |
913 | if (test_bit(BNX2X_ISCSI_ETH_MAC, vlan_mac_flags)) | |
914 | bnx2x_set_mac_in_nig(bp, add, mac, | |
0a52fd01 | 915 | BNX2X_LLH_CAM_ISCSI_ETH_LINE); |
619c5cb6 | 916 | else if (test_bit(BNX2X_ETH_MAC, vlan_mac_flags)) |
0a52fd01 YM |
917 | bnx2x_set_mac_in_nig(bp, add, mac, |
918 | BNX2X_LLH_CAM_ETH_LINE); | |
042181f5 VZ |
919 | } |
920 | ||
619c5cb6 VZ |
921 | /* Reset the ramrod data buffer for the first rule */ |
922 | if (rule_idx == 0) | |
923 | memset(data, 0, sizeof(*data)); | |
924 | ||
925 | /* Setup a command header */ | |
926 | bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_MAC, | |
927 | &rule_entry->mac.header); | |
928 | ||
0f9dad10 | 929 | DP(BNX2X_MSG_SP, "About to %s MAC %pM for Queue %d\n", |
51c1a580 | 930 | (add ? "add" : "delete"), mac, raw->cl_id); |
619c5cb6 VZ |
931 | |
932 | /* Set a MAC itself */ | |
933 | bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb, | |
934 | &rule_entry->mac.mac_mid, | |
935 | &rule_entry->mac.mac_lsb, mac); | |
91226790 DK |
936 | rule_entry->mac.inner_mac = |
937 | cpu_to_le16(elem->cmd_data.vlan_mac.u.mac.is_inner_mac); | |
619c5cb6 VZ |
938 | |
939 | /* MOVE: Add a rule that will add this MAC to the target Queue */ | |
940 | if (cmd == BNX2X_VLAN_MAC_MOVE) { | |
941 | rule_entry++; | |
942 | rule_cnt++; | |
943 | ||
944 | /* Setup ramrod data */ | |
945 | bnx2x_vlan_mac_set_cmd_hdr_e2(bp, | |
946 | elem->cmd_data.vlan_mac.target_obj, | |
947 | true, CLASSIFY_RULE_OPCODE_MAC, | |
948 | &rule_entry->mac.header); | |
949 | ||
950 | /* Set a MAC itself */ | |
951 | bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb, | |
952 | &rule_entry->mac.mac_mid, | |
953 | &rule_entry->mac.mac_lsb, mac); | |
91226790 DK |
954 | rule_entry->mac.inner_mac = |
955 | cpu_to_le16(elem->cmd_data.vlan_mac. | |
956 | u.mac.is_inner_mac); | |
042181f5 | 957 | } |
619c5cb6 VZ |
958 | |
959 | /* Set the ramrod data header */ | |
960 | /* TODO: take this to the higher level in order to prevent multiple | |
961 | writing */ | |
962 | bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header, | |
963 | rule_cnt); | |
042181f5 VZ |
964 | } |
965 | ||
619c5cb6 VZ |
966 | /** |
967 | * bnx2x_vlan_mac_set_rdata_hdr_e1x - set a header in a single classify ramrod | |
968 | * | |
969 | * @bp: device handle | |
970 | * @o: queue | |
971 | * @type: | |
972 | * @cam_offset: offset in cam memory | |
973 | * @hdr: pointer to a header to setup | |
974 | * | |
975 | * E1/E1H | |
976 | */ | |
977 | static inline void bnx2x_vlan_mac_set_rdata_hdr_e1x(struct bnx2x *bp, | |
978 | struct bnx2x_vlan_mac_obj *o, int type, int cam_offset, | |
979 | struct mac_configuration_hdr *hdr) | |
042181f5 | 980 | { |
619c5cb6 | 981 | struct bnx2x_raw_obj *r = &o->raw; |
042181f5 | 982 | |
619c5cb6 VZ |
983 | hdr->length = 1; |
984 | hdr->offset = (u8)cam_offset; | |
86564c3f YM |
985 | hdr->client_id = cpu_to_le16(0xff); |
986 | hdr->echo = cpu_to_le32((r->cid & BNX2X_SWCID_MASK) | | |
987 | (type << BNX2X_SWCID_SHIFT)); | |
619c5cb6 | 988 | } |
042181f5 | 989 | |
619c5cb6 VZ |
990 | static inline void bnx2x_vlan_mac_set_cfg_entry_e1x(struct bnx2x *bp, |
991 | struct bnx2x_vlan_mac_obj *o, bool add, int opcode, u8 *mac, | |
992 | u16 vlan_id, struct mac_configuration_entry *cfg_entry) | |
993 | { | |
994 | struct bnx2x_raw_obj *r = &o->raw; | |
995 | u32 cl_bit_vec = (1 << r->cl_id); | |
996 | ||
997 | cfg_entry->clients_bit_vector = cpu_to_le32(cl_bit_vec); | |
998 | cfg_entry->pf_id = r->func_id; | |
999 | cfg_entry->vlan_id = cpu_to_le16(vlan_id); | |
1000 | ||
1001 | if (add) { | |
1002 | SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE, | |
1003 | T_ETH_MAC_COMMAND_SET); | |
1004 | SET_FLAG(cfg_entry->flags, | |
1005 | MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE, opcode); | |
1006 | ||
1007 | /* Set a MAC in a ramrod data */ | |
1008 | bnx2x_set_fw_mac_addr(&cfg_entry->msb_mac_addr, | |
1009 | &cfg_entry->middle_mac_addr, | |
1010 | &cfg_entry->lsb_mac_addr, mac); | |
1011 | } else | |
1012 | SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE, | |
1013 | T_ETH_MAC_COMMAND_INVALIDATE); | |
1014 | } | |
042181f5 | 1015 | |
619c5cb6 VZ |
1016 | static inline void bnx2x_vlan_mac_set_rdata_e1x(struct bnx2x *bp, |
1017 | struct bnx2x_vlan_mac_obj *o, int type, int cam_offset, bool add, | |
1018 | u8 *mac, u16 vlan_id, int opcode, struct mac_configuration_cmd *config) | |
1019 | { | |
1020 | struct mac_configuration_entry *cfg_entry = &config->config_table[0]; | |
1021 | struct bnx2x_raw_obj *raw = &o->raw; | |
042181f5 | 1022 | |
619c5cb6 VZ |
1023 | bnx2x_vlan_mac_set_rdata_hdr_e1x(bp, o, type, cam_offset, |
1024 | &config->hdr); | |
1025 | bnx2x_vlan_mac_set_cfg_entry_e1x(bp, o, add, opcode, mac, vlan_id, | |
1026 | cfg_entry); | |
042181f5 | 1027 | |
0f9dad10 | 1028 | DP(BNX2X_MSG_SP, "%s MAC %pM CLID %d CAM offset %d\n", |
51c1a580 | 1029 | (add ? "setting" : "clearing"), |
0f9dad10 | 1030 | mac, raw->cl_id, cam_offset); |
042181f5 VZ |
1031 | } |
1032 | ||
619c5cb6 VZ |
1033 | /** |
1034 | * bnx2x_set_one_mac_e1x - fill a single MAC rule ramrod data | |
1035 | * | |
1036 | * @bp: device handle | |
1037 | * @o: bnx2x_vlan_mac_obj | |
1038 | * @elem: bnx2x_exeq_elem | |
1039 | * @rule_idx: rule_idx | |
1040 | * @cam_offset: cam_offset | |
1041 | */ | |
1042 | static void bnx2x_set_one_mac_e1x(struct bnx2x *bp, | |
1043 | struct bnx2x_vlan_mac_obj *o, | |
1044 | struct bnx2x_exeq_elem *elem, int rule_idx, | |
1045 | int cam_offset) | |
042181f5 | 1046 | { |
619c5cb6 VZ |
1047 | struct bnx2x_raw_obj *raw = &o->raw; |
1048 | struct mac_configuration_cmd *config = | |
1049 | (struct mac_configuration_cmd *)(raw->rdata); | |
16a5fd92 | 1050 | /* 57710 and 57711 do not support MOVE command, |
619c5cb6 VZ |
1051 | * so it's either ADD or DEL |
1052 | */ | |
1053 | bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ? | |
1054 | true : false; | |
042181f5 | 1055 | |
619c5cb6 VZ |
1056 | /* Reset the ramrod data buffer */ |
1057 | memset(config, 0, sizeof(*config)); | |
042181f5 | 1058 | |
33ac338c | 1059 | bnx2x_vlan_mac_set_rdata_e1x(bp, o, raw->state, |
619c5cb6 VZ |
1060 | cam_offset, add, |
1061 | elem->cmd_data.vlan_mac.u.mac.mac, 0, | |
1062 | ETH_VLAN_FILTER_ANY_VLAN, config); | |
1063 | } | |
042181f5 | 1064 | |
619c5cb6 VZ |
1065 | static void bnx2x_set_one_vlan_e2(struct bnx2x *bp, |
1066 | struct bnx2x_vlan_mac_obj *o, | |
1067 | struct bnx2x_exeq_elem *elem, int rule_idx, | |
1068 | int cam_offset) | |
1069 | { | |
1070 | struct bnx2x_raw_obj *raw = &o->raw; | |
1071 | struct eth_classify_rules_ramrod_data *data = | |
1072 | (struct eth_classify_rules_ramrod_data *)(raw->rdata); | |
1073 | int rule_cnt = rule_idx + 1; | |
1074 | union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx]; | |
86564c3f | 1075 | enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd; |
619c5cb6 VZ |
1076 | bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false; |
1077 | u16 vlan = elem->cmd_data.vlan_mac.u.vlan.vlan; | |
1078 | ||
1079 | /* Reset the ramrod data buffer for the first rule */ | |
1080 | if (rule_idx == 0) | |
1081 | memset(data, 0, sizeof(*data)); | |
1082 | ||
1083 | /* Set a rule header */ | |
1084 | bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_VLAN, | |
1085 | &rule_entry->vlan.header); | |
1086 | ||
1087 | DP(BNX2X_MSG_SP, "About to %s VLAN %d\n", (add ? "add" : "delete"), | |
1088 | vlan); | |
1089 | ||
1090 | /* Set a VLAN itself */ | |
1091 | rule_entry->vlan.vlan = cpu_to_le16(vlan); | |
1092 | ||
1093 | /* MOVE: Add a rule that will add this MAC to the target Queue */ | |
1094 | if (cmd == BNX2X_VLAN_MAC_MOVE) { | |
1095 | rule_entry++; | |
1096 | rule_cnt++; | |
1097 | ||
1098 | /* Setup ramrod data */ | |
1099 | bnx2x_vlan_mac_set_cmd_hdr_e2(bp, | |
1100 | elem->cmd_data.vlan_mac.target_obj, | |
1101 | true, CLASSIFY_RULE_OPCODE_VLAN, | |
1102 | &rule_entry->vlan.header); | |
1103 | ||
1104 | /* Set a VLAN itself */ | |
1105 | rule_entry->vlan.vlan = cpu_to_le16(vlan); | |
1106 | } | |
042181f5 | 1107 | |
619c5cb6 VZ |
1108 | /* Set the ramrod data header */ |
1109 | /* TODO: take this to the higher level in order to prevent multiple | |
1110 | writing */ | |
1111 | bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header, | |
1112 | rule_cnt); | |
1113 | } | |
042181f5 | 1114 | |
05cc5a39 YM |
1115 | static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp, |
1116 | struct bnx2x_vlan_mac_obj *o, | |
1117 | struct bnx2x_exeq_elem *elem, | |
1118 | int rule_idx, int cam_offset) | |
1119 | { | |
1120 | struct bnx2x_raw_obj *raw = &o->raw; | |
1121 | struct eth_classify_rules_ramrod_data *data = | |
1122 | (struct eth_classify_rules_ramrod_data *)(raw->rdata); | |
1123 | int rule_cnt = rule_idx + 1; | |
1124 | union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx]; | |
1125 | enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd; | |
1126 | bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false; | |
1127 | u16 vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan; | |
1128 | u8 *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac; | |
1129 | u16 inner_mac; | |
1130 | ||
1131 | /* Reset the ramrod data buffer for the first rule */ | |
1132 | if (rule_idx == 0) | |
1133 | memset(data, 0, sizeof(*data)); | |
1134 | ||
1135 | /* Set a rule header */ | |
1136 | bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_PAIR, | |
1137 | &rule_entry->pair.header); | |
1138 | ||
1139 | /* Set VLAN and MAC themselves */ | |
1140 | rule_entry->pair.vlan = cpu_to_le16(vlan); | |
1141 | bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb, | |
1142 | &rule_entry->pair.mac_mid, | |
1143 | &rule_entry->pair.mac_lsb, mac); | |
1144 | inner_mac = elem->cmd_data.vlan_mac.u.vlan_mac.is_inner_mac; | |
1145 | rule_entry->pair.inner_mac = cpu_to_le16(inner_mac); | |
1146 | /* MOVE: Add a rule that will add this MAC/VLAN to the target Queue */ | |
1147 | if (cmd == BNX2X_VLAN_MAC_MOVE) { | |
1148 | struct bnx2x_vlan_mac_obj *target_obj; | |
1149 | ||
1150 | rule_entry++; | |
1151 | rule_cnt++; | |
1152 | ||
1153 | /* Setup ramrod data */ | |
1154 | target_obj = elem->cmd_data.vlan_mac.target_obj; | |
1155 | bnx2x_vlan_mac_set_cmd_hdr_e2(bp, target_obj, | |
1156 | true, CLASSIFY_RULE_OPCODE_PAIR, | |
1157 | &rule_entry->pair.header); | |
1158 | ||
1159 | /* Set a VLAN itself */ | |
1160 | rule_entry->pair.vlan = cpu_to_le16(vlan); | |
1161 | bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb, | |
1162 | &rule_entry->pair.mac_mid, | |
1163 | &rule_entry->pair.mac_lsb, mac); | |
1164 | rule_entry->pair.inner_mac = cpu_to_le16(inner_mac); | |
1165 | } | |
1166 | ||
1167 | /* Set the ramrod data header */ | |
1168 | bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header, | |
1169 | rule_cnt); | |
1170 | } | |
1171 | ||
1172 | /** | |
1173 | * bnx2x_set_one_vlan_mac_e1h - | |
1174 | * | |
1175 | * @bp: device handle | |
1176 | * @o: bnx2x_vlan_mac_obj | |
1177 | * @elem: bnx2x_exeq_elem | |
1178 | * @rule_idx: rule_idx | |
1179 | * @cam_offset: cam_offset | |
1180 | */ | |
1181 | static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp, | |
1182 | struct bnx2x_vlan_mac_obj *o, | |
1183 | struct bnx2x_exeq_elem *elem, | |
1184 | int rule_idx, int cam_offset) | |
1185 | { | |
1186 | struct bnx2x_raw_obj *raw = &o->raw; | |
1187 | struct mac_configuration_cmd *config = | |
1188 | (struct mac_configuration_cmd *)(raw->rdata); | |
1189 | /* 57710 and 57711 do not support MOVE command, | |
1190 | * so it's either ADD or DEL | |
1191 | */ | |
1192 | bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ? | |
1193 | true : false; | |
1194 | ||
1195 | /* Reset the ramrod data buffer */ | |
1196 | memset(config, 0, sizeof(*config)); | |
1197 | ||
1198 | bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_VLAN_MAC_PENDING, | |
1199 | cam_offset, add, | |
1200 | elem->cmd_data.vlan_mac.u.vlan_mac.mac, | |
1201 | elem->cmd_data.vlan_mac.u.vlan_mac.vlan, | |
1202 | ETH_VLAN_FILTER_CLASSIFY, config); | |
1203 | } | |
1204 | ||
619c5cb6 VZ |
1205 | /** |
1206 | * bnx2x_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element | |
1207 | * | |
1208 | * @bp: device handle | |
1209 | * @p: command parameters | |
16a5fd92 | 1210 | * @ppos: pointer to the cookie |
619c5cb6 VZ |
1211 | * |
1212 | * reconfigure next MAC/VLAN/VLAN-MAC element from the | |
1213 | * previously configured elements list. | |
1214 | * | |
1215 | * from command parameters only RAMROD_COMP_WAIT bit in ramrod_flags is taken | |
1216 | * into an account | |
1217 | * | |
16a5fd92 | 1218 | * pointer to the cookie - that should be given back in the next call to make |
619c5cb6 VZ |
1219 | * function handle the next element. If *ppos is set to NULL it will restart the |
1220 | * iterator. If returned *ppos == NULL this means that the last element has been | |
1221 | * handled. | |
1222 | * | |
1223 | */ | |
1224 | static int bnx2x_vlan_mac_restore(struct bnx2x *bp, | |
1225 | struct bnx2x_vlan_mac_ramrod_params *p, | |
1226 | struct bnx2x_vlan_mac_registry_elem **ppos) | |
1227 | { | |
1228 | struct bnx2x_vlan_mac_registry_elem *pos; | |
1229 | struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj; | |
1230 | ||
1231 | /* If list is empty - there is nothing to do here */ | |
1232 | if (list_empty(&o->head)) { | |
1233 | *ppos = NULL; | |
1234 | return 0; | |
1235 | } | |
1236 | ||
1237 | /* make a step... */ | |
1238 | if (*ppos == NULL) | |
1239 | *ppos = list_first_entry(&o->head, | |
1240 | struct bnx2x_vlan_mac_registry_elem, | |
1241 | link); | |
1242 | else | |
1243 | *ppos = list_next_entry(*ppos, link); | |
1244 | ||
1245 | pos = *ppos; | |
1246 | ||
1247 | /* If it's the last step - return NULL */ | |
1248 | if (list_is_last(&pos->link, &o->head)) | |
1249 | *ppos = NULL; | |
1250 | ||
1251 | /* Prepare a 'user_req' */ | |
1252 | memcpy(&p->user_req.u, &pos->u, sizeof(pos->u)); | |
1253 | ||
1254 | /* Set the command */ | |
1255 | p->user_req.cmd = BNX2X_VLAN_MAC_ADD; | |
1256 | ||
1257 | /* Set vlan_mac_flags */ | |
1258 | p->user_req.vlan_mac_flags = pos->vlan_mac_flags; | |
1259 | ||
1260 | /* Set a restore bit */ | |
1261 | __set_bit(RAMROD_RESTORE, &p->ramrod_flags); | |
1262 | ||
1263 | return bnx2x_config_vlan_mac(bp, p); | |
1264 | } | |
1265 | ||
16a5fd92 | 1266 | /* bnx2x_exeq_get_mac/bnx2x_exeq_get_vlan/bnx2x_exeq_get_vlan_mac return a |
619c5cb6 VZ |
1267 | * pointer to an element with a specific criteria and NULL if such an element |
1268 | * hasn't been found. | |
1269 | */ | |
1270 | static struct bnx2x_exeq_elem *bnx2x_exeq_get_mac( | |
1271 | struct bnx2x_exe_queue_obj *o, | |
1272 | struct bnx2x_exeq_elem *elem) | |
1273 | { | |
1274 | struct bnx2x_exeq_elem *pos; | |
1275 | struct bnx2x_mac_ramrod_data *data = &elem->cmd_data.vlan_mac.u.mac; | |
1276 | ||
1277 | /* Check pending for execution commands */ | |
1278 | list_for_each_entry(pos, &o->exe_queue, link) | |
1279 | if (!memcmp(&pos->cmd_data.vlan_mac.u.mac, data, | |
1280 | sizeof(*data)) && | |
1281 | (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd)) | |
1282 | return pos; | |
1283 | ||
1284 | return NULL; | |
1285 | } | |
1286 | ||
1287 | static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan( | |
1288 | struct bnx2x_exe_queue_obj *o, | |
1289 | struct bnx2x_exeq_elem *elem) | |
1290 | { | |
1291 | struct bnx2x_exeq_elem *pos; | |
1292 | struct bnx2x_vlan_ramrod_data *data = &elem->cmd_data.vlan_mac.u.vlan; | |
1293 | ||
1294 | /* Check pending for execution commands */ | |
1295 | list_for_each_entry(pos, &o->exe_queue, link) | |
1296 | if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan, data, | |
1297 | sizeof(*data)) && | |
1298 | (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd)) | |
1299 | return pos; | |
1300 | ||
1301 | return NULL; | |
1302 | } | |
1303 | ||
05cc5a39 YM |
1304 | static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan_mac( |
1305 | struct bnx2x_exe_queue_obj *o, | |
1306 | struct bnx2x_exeq_elem *elem) | |
1307 | { | |
1308 | struct bnx2x_exeq_elem *pos; | |
1309 | struct bnx2x_vlan_mac_ramrod_data *data = | |
1310 | &elem->cmd_data.vlan_mac.u.vlan_mac; | |
1311 | ||
1312 | /* Check pending for execution commands */ | |
1313 | list_for_each_entry(pos, &o->exe_queue, link) | |
1314 | if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan_mac, data, | |
1315 | sizeof(*data)) && | |
1316 | (pos->cmd_data.vlan_mac.cmd == | |
1317 | elem->cmd_data.vlan_mac.cmd)) | |
1318 | return pos; | |
1319 | ||
1320 | return NULL; | |
1321 | } | |
1322 | ||
619c5cb6 VZ |
1323 | /** |
1324 | * bnx2x_validate_vlan_mac_add - check if an ADD command can be executed | |
1325 | * | |
1326 | * @bp: device handle | |
1327 | * @qo: bnx2x_qable_obj | |
1328 | * @elem: bnx2x_exeq_elem | |
1329 | * | |
1330 | * Checks that the requested configuration can be added. If yes and if | |
1331 | * requested, consume CAM credit. | |
1332 | * | |
1333 | * The 'validate' is run after the 'optimize'. | |
1334 | * | |
1335 | */ | |
1336 | static inline int bnx2x_validate_vlan_mac_add(struct bnx2x *bp, | |
1337 | union bnx2x_qable_obj *qo, | |
1338 | struct bnx2x_exeq_elem *elem) | |
1339 | { | |
1340 | struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac; | |
1341 | struct bnx2x_exe_queue_obj *exeq = &o->exe_queue; | |
1342 | int rc; | |
1343 | ||
1344 | /* Check the registry */ | |
51c1a580 | 1345 | rc = o->check_add(bp, o, &elem->cmd_data.vlan_mac.u); |
619c5cb6 | 1346 | if (rc) { |
51c1a580 | 1347 | DP(BNX2X_MSG_SP, "ADD command is not allowed considering current registry state.\n"); |
619c5cb6 VZ |
1348 | return rc; |
1349 | } | |
1350 | ||
16a5fd92 | 1351 | /* Check if there is a pending ADD command for this |
619c5cb6 VZ |
1352 | * MAC/VLAN/VLAN-MAC. Return an error if there is. |
1353 | */ | |
1354 | if (exeq->get(exeq, elem)) { | |
1355 | DP(BNX2X_MSG_SP, "There is a pending ADD command already\n"); | |
1356 | return -EEXIST; | |
1357 | } | |
1358 | ||
16a5fd92 | 1359 | /* TODO: Check the pending MOVE from other objects where this |
619c5cb6 VZ |
1360 | * object is a destination object. |
1361 | */ | |
1362 | ||
1363 | /* Consume the credit if not requested not to */ | |
1364 | if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT, | |
1365 | &elem->cmd_data.vlan_mac.vlan_mac_flags) || | |
1366 | o->get_credit(o))) | |
1367 | return -EINVAL; | |
1368 | ||
1369 | return 0; | |
1370 | } | |
1371 | ||
1372 | /** | |
1373 | * bnx2x_validate_vlan_mac_del - check if the DEL command can be executed | |
1374 | * | |
1375 | * @bp: device handle | |
1376 | * @qo: quable object to check | |
1377 | * @elem: element that needs to be deleted | |
1378 | * | |
1379 | * Checks that the requested configuration can be deleted. If yes and if | |
1380 | * requested, returns a CAM credit. | |
1381 | * | |
1382 | * The 'validate' is run after the 'optimize'. | |
1383 | */ | |
1384 | static inline int bnx2x_validate_vlan_mac_del(struct bnx2x *bp, | |
1385 | union bnx2x_qable_obj *qo, | |
1386 | struct bnx2x_exeq_elem *elem) | |
1387 | { | |
1388 | struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac; | |
1389 | struct bnx2x_vlan_mac_registry_elem *pos; | |
1390 | struct bnx2x_exe_queue_obj *exeq = &o->exe_queue; | |
1391 | struct bnx2x_exeq_elem query_elem; | |
1392 | ||
1393 | /* If this classification can not be deleted (doesn't exist) | |
1394 | * - return a BNX2X_EXIST. | |
1395 | */ | |
51c1a580 | 1396 | pos = o->check_del(bp, o, &elem->cmd_data.vlan_mac.u); |
619c5cb6 | 1397 | if (!pos) { |
51c1a580 | 1398 | DP(BNX2X_MSG_SP, "DEL command is not allowed considering current registry state\n"); |
619c5cb6 VZ |
1399 | return -EEXIST; |
1400 | } | |
1401 | ||
16a5fd92 | 1402 | /* Check if there are pending DEL or MOVE commands for this |
619c5cb6 VZ |
1403 | * MAC/VLAN/VLAN-MAC. Return an error if so. |
1404 | */ | |
1405 | memcpy(&query_elem, elem, sizeof(query_elem)); | |
1406 | ||
1407 | /* Check for MOVE commands */ | |
1408 | query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_MOVE; | |
1409 | if (exeq->get(exeq, &query_elem)) { | |
1410 | BNX2X_ERR("There is a pending MOVE command already\n"); | |
1411 | return -EINVAL; | |
1412 | } | |
1413 | ||
1414 | /* Check for DEL commands */ | |
1415 | if (exeq->get(exeq, elem)) { | |
1416 | DP(BNX2X_MSG_SP, "There is a pending DEL command already\n"); | |
1417 | return -EEXIST; | |
1418 | } | |
1419 | ||
1420 | /* Return the credit to the credit pool if not requested not to */ | |
1421 | if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT, | |
1422 | &elem->cmd_data.vlan_mac.vlan_mac_flags) || | |
1423 | o->put_credit(o))) { | |
1424 | BNX2X_ERR("Failed to return a credit\n"); | |
1425 | return -EINVAL; | |
1426 | } | |
1427 | ||
1428 | return 0; | |
1429 | } | |
1430 | ||
1431 | /** | |
1432 | * bnx2x_validate_vlan_mac_move - check if the MOVE command can be executed | |
1433 | * | |
1434 | * @bp: device handle | |
1435 | * @qo: quable object to check (source) | |
1436 | * @elem: element that needs to be moved | |
1437 | * | |
1438 | * Checks that the requested configuration can be moved. If yes and if | |
1439 | * requested, returns a CAM credit. | |
1440 | * | |
1441 | * The 'validate' is run after the 'optimize'. | |
1442 | */ | |
1443 | static inline int bnx2x_validate_vlan_mac_move(struct bnx2x *bp, | |
1444 | union bnx2x_qable_obj *qo, | |
1445 | struct bnx2x_exeq_elem *elem) | |
1446 | { | |
1447 | struct bnx2x_vlan_mac_obj *src_o = &qo->vlan_mac; | |
1448 | struct bnx2x_vlan_mac_obj *dest_o = elem->cmd_data.vlan_mac.target_obj; | |
1449 | struct bnx2x_exeq_elem query_elem; | |
1450 | struct bnx2x_exe_queue_obj *src_exeq = &src_o->exe_queue; | |
1451 | struct bnx2x_exe_queue_obj *dest_exeq = &dest_o->exe_queue; | |
1452 | ||
16a5fd92 | 1453 | /* Check if we can perform this operation based on the current registry |
619c5cb6 VZ |
1454 | * state. |
1455 | */ | |
51c1a580 MS |
1456 | if (!src_o->check_move(bp, src_o, dest_o, |
1457 | &elem->cmd_data.vlan_mac.u)) { | |
1458 | DP(BNX2X_MSG_SP, "MOVE command is not allowed considering current registry state\n"); | |
619c5cb6 VZ |
1459 | return -EINVAL; |
1460 | } | |
1461 | ||
16a5fd92 | 1462 | /* Check if there is an already pending DEL or MOVE command for the |
619c5cb6 VZ |
1463 | * source object or ADD command for a destination object. Return an |
1464 | * error if so. | |
1465 | */ | |
1466 | memcpy(&query_elem, elem, sizeof(query_elem)); | |
1467 | ||
1468 | /* Check DEL on source */ | |
1469 | query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL; | |
1470 | if (src_exeq->get(src_exeq, &query_elem)) { | |
51c1a580 | 1471 | BNX2X_ERR("There is a pending DEL command on the source queue already\n"); |
619c5cb6 VZ |
1472 | return -EINVAL; |
1473 | } | |
1474 | ||
1475 | /* Check MOVE on source */ | |
1476 | if (src_exeq->get(src_exeq, elem)) { | |
1477 | DP(BNX2X_MSG_SP, "There is a pending MOVE command already\n"); | |
1478 | return -EEXIST; | |
1479 | } | |
1480 | ||
1481 | /* Check ADD on destination */ | |
1482 | query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD; | |
1483 | if (dest_exeq->get(dest_exeq, &query_elem)) { | |
51c1a580 | 1484 | BNX2X_ERR("There is a pending ADD command on the destination queue already\n"); |
619c5cb6 VZ |
1485 | return -EINVAL; |
1486 | } | |
1487 | ||
1488 | /* Consume the credit if not requested not to */ | |
1489 | if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT_DEST, | |
1490 | &elem->cmd_data.vlan_mac.vlan_mac_flags) || | |
1491 | dest_o->get_credit(dest_o))) | |
1492 | return -EINVAL; | |
1493 | ||
1494 | if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT, | |
1495 | &elem->cmd_data.vlan_mac.vlan_mac_flags) || | |
1496 | src_o->put_credit(src_o))) { | |
1497 | /* return the credit taken from dest... */ | |
1498 | dest_o->put_credit(dest_o); | |
1499 | return -EINVAL; | |
1500 | } | |
1501 | ||
1502 | return 0; | |
1503 | } | |
1504 | ||
1505 | static int bnx2x_validate_vlan_mac(struct bnx2x *bp, | |
1506 | union bnx2x_qable_obj *qo, | |
1507 | struct bnx2x_exeq_elem *elem) | |
1508 | { | |
1509 | switch (elem->cmd_data.vlan_mac.cmd) { | |
1510 | case BNX2X_VLAN_MAC_ADD: | |
1511 | return bnx2x_validate_vlan_mac_add(bp, qo, elem); | |
1512 | case BNX2X_VLAN_MAC_DEL: | |
1513 | return bnx2x_validate_vlan_mac_del(bp, qo, elem); | |
1514 | case BNX2X_VLAN_MAC_MOVE: | |
1515 | return bnx2x_validate_vlan_mac_move(bp, qo, elem); | |
1516 | default: | |
1517 | return -EINVAL; | |
1518 | } | |
1519 | } | |
1520 | ||
460a25cd YM |
1521 | static int bnx2x_remove_vlan_mac(struct bnx2x *bp, |
1522 | union bnx2x_qable_obj *qo, | |
1523 | struct bnx2x_exeq_elem *elem) | |
1524 | { | |
1525 | int rc = 0; | |
1526 | ||
1527 | /* If consumption wasn't required, nothing to do */ | |
1528 | if (test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT, | |
1529 | &elem->cmd_data.vlan_mac.vlan_mac_flags)) | |
1530 | return 0; | |
1531 | ||
1532 | switch (elem->cmd_data.vlan_mac.cmd) { | |
1533 | case BNX2X_VLAN_MAC_ADD: | |
1534 | case BNX2X_VLAN_MAC_MOVE: | |
1535 | rc = qo->vlan_mac.put_credit(&qo->vlan_mac); | |
1536 | break; | |
1537 | case BNX2X_VLAN_MAC_DEL: | |
1538 | rc = qo->vlan_mac.get_credit(&qo->vlan_mac); | |
1539 | break; | |
1540 | default: | |
1541 | return -EINVAL; | |
1542 | } | |
1543 | ||
1544 | if (rc != true) | |
1545 | return -EINVAL; | |
1546 | ||
1547 | return 0; | |
1548 | } | |
1549 | ||
619c5cb6 | 1550 | /** |
16a5fd92 | 1551 | * bnx2x_wait_vlan_mac - passively wait for 5 seconds until all work completes. |
619c5cb6 VZ |
1552 | * |
1553 | * @bp: device handle | |
1554 | * @o: bnx2x_vlan_mac_obj | |
1555 | * | |
1556 | */ | |
1557 | static int bnx2x_wait_vlan_mac(struct bnx2x *bp, | |
1558 | struct bnx2x_vlan_mac_obj *o) | |
1559 | { | |
1560 | int cnt = 5000, rc; | |
1561 | struct bnx2x_exe_queue_obj *exeq = &o->exe_queue; | |
1562 | struct bnx2x_raw_obj *raw = &o->raw; | |
1563 | ||
1564 | while (cnt--) { | |
1565 | /* Wait for the current command to complete */ | |
1566 | rc = raw->wait_comp(bp, raw); | |
1567 | if (rc) | |
1568 | return rc; | |
1569 | ||
1570 | /* Wait until there are no pending commands */ | |
1571 | if (!bnx2x_exe_queue_empty(exeq)) | |
0926d499 | 1572 | usleep_range(1000, 2000); |
619c5cb6 VZ |
1573 | else |
1574 | return 0; | |
1575 | } | |
1576 | ||
1577 | return -EBUSY; | |
1578 | } | |
1579 | ||
8b09be5f YM |
1580 | static int __bnx2x_vlan_mac_execute_step(struct bnx2x *bp, |
1581 | struct bnx2x_vlan_mac_obj *o, | |
1582 | unsigned long *ramrod_flags) | |
1583 | { | |
1584 | int rc = 0; | |
1585 | ||
1586 | spin_lock_bh(&o->exe_queue.lock); | |
1587 | ||
1588 | DP(BNX2X_MSG_SP, "vlan_mac_execute_step - trying to take writer lock\n"); | |
1589 | rc = __bnx2x_vlan_mac_h_write_trylock(bp, o); | |
1590 | ||
1591 | if (rc != 0) { | |
1592 | __bnx2x_vlan_mac_h_pend(bp, o, *ramrod_flags); | |
1593 | ||
8ac1ed79 | 1594 | /* Calling function should not differentiate between this case |
8b09be5f YM |
1595 | * and the case in which there is already a pending ramrod |
1596 | */ | |
1597 | rc = 1; | |
1598 | } else { | |
1599 | rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags); | |
1600 | } | |
1601 | spin_unlock_bh(&o->exe_queue.lock); | |
1602 | ||
1603 | return rc; | |
1604 | } | |
1605 | ||
619c5cb6 VZ |
1606 | /** |
1607 | * bnx2x_complete_vlan_mac - complete one VLAN-MAC ramrod | |
1608 | * | |
1609 | * @bp: device handle | |
1610 | * @o: bnx2x_vlan_mac_obj | |
1611 | * @cqe: | |
1612 | * @cont: if true schedule next execution chunk | |
1613 | * | |
1614 | */ | |
1615 | static int bnx2x_complete_vlan_mac(struct bnx2x *bp, | |
1616 | struct bnx2x_vlan_mac_obj *o, | |
1617 | union event_ring_elem *cqe, | |
1618 | unsigned long *ramrod_flags) | |
1619 | { | |
1620 | struct bnx2x_raw_obj *r = &o->raw; | |
1621 | int rc; | |
1622 | ||
8b09be5f YM |
1623 | /* Clearing the pending list & raw state should be made |
1624 | * atomically (as execution flow assumes they represent the same). | |
1625 | */ | |
1626 | spin_lock_bh(&o->exe_queue.lock); | |
1627 | ||
619c5cb6 | 1628 | /* Reset pending list */ |
8b09be5f | 1629 | __bnx2x_exe_queue_reset_pending(bp, &o->exe_queue); |
619c5cb6 VZ |
1630 | |
1631 | /* Clear pending */ | |
1632 | r->clear_pending(r); | |
1633 | ||
8b09be5f YM |
1634 | spin_unlock_bh(&o->exe_queue.lock); |
1635 | ||
619c5cb6 VZ |
1636 | /* If ramrod failed this is most likely a SW bug */ |
1637 | if (cqe->message.error) | |
1638 | return -EINVAL; | |
1639 | ||
2de67439 | 1640 | /* Run the next bulk of pending commands if requested */ |
619c5cb6 | 1641 | if (test_bit(RAMROD_CONT, ramrod_flags)) { |
8b09be5f YM |
1642 | rc = __bnx2x_vlan_mac_execute_step(bp, o, ramrod_flags); |
1643 | ||
619c5cb6 VZ |
1644 | if (rc < 0) |
1645 | return rc; | |
1646 | } | |
1647 | ||
1648 | /* If there is more work to do return PENDING */ | |
1649 | if (!bnx2x_exe_queue_empty(&o->exe_queue)) | |
1650 | return 1; | |
1651 | ||
1652 | return 0; | |
1653 | } | |
1654 | ||
1655 | /** | |
1656 | * bnx2x_optimize_vlan_mac - optimize ADD and DEL commands. | |
1657 | * | |
1658 | * @bp: device handle | |
1659 | * @o: bnx2x_qable_obj | |
1660 | * @elem: bnx2x_exeq_elem | |
1661 | */ | |
1662 | static int bnx2x_optimize_vlan_mac(struct bnx2x *bp, | |
1663 | union bnx2x_qable_obj *qo, | |
1664 | struct bnx2x_exeq_elem *elem) | |
1665 | { | |
1666 | struct bnx2x_exeq_elem query, *pos; | |
1667 | struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac; | |
1668 | struct bnx2x_exe_queue_obj *exeq = &o->exe_queue; | |
1669 | ||
1670 | memcpy(&query, elem, sizeof(query)); | |
1671 | ||
1672 | switch (elem->cmd_data.vlan_mac.cmd) { | |
1673 | case BNX2X_VLAN_MAC_ADD: | |
1674 | query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL; | |
1675 | break; | |
1676 | case BNX2X_VLAN_MAC_DEL: | |
1677 | query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD; | |
1678 | break; | |
1679 | default: | |
1680 | /* Don't handle anything other than ADD or DEL */ | |
1681 | return 0; | |
1682 | } | |
1683 | ||
1684 | /* If we found the appropriate element - delete it */ | |
1685 | pos = exeq->get(exeq, &query); | |
1686 | if (pos) { | |
1687 | ||
1688 | /* Return the credit of the optimized command */ | |
1689 | if (!test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT, | |
1690 | &pos->cmd_data.vlan_mac.vlan_mac_flags)) { | |
1691 | if ((query.cmd_data.vlan_mac.cmd == | |
1692 | BNX2X_VLAN_MAC_ADD) && !o->put_credit(o)) { | |
51c1a580 | 1693 | BNX2X_ERR("Failed to return the credit for the optimized ADD command\n"); |
619c5cb6 VZ |
1694 | return -EINVAL; |
1695 | } else if (!o->get_credit(o)) { /* VLAN_MAC_DEL */ | |
51c1a580 | 1696 | BNX2X_ERR("Failed to recover the credit from the optimized DEL command\n"); |
619c5cb6 VZ |
1697 | return -EINVAL; |
1698 | } | |
1699 | } | |
1700 | ||
1701 | DP(BNX2X_MSG_SP, "Optimizing %s command\n", | |
1702 | (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ? | |
1703 | "ADD" : "DEL"); | |
1704 | ||
1705 | list_del(&pos->link); | |
1706 | bnx2x_exe_queue_free_elem(bp, pos); | |
1707 | return 1; | |
1708 | } | |
1709 | ||
1710 | return 0; | |
1711 | } | |
1712 | ||
1713 | /** | |
1714 | * bnx2x_vlan_mac_get_registry_elem - prepare a registry element | |
1715 | * | |
1716 | * @bp: device handle | |
1717 | * @o: | |
1718 | * @elem: | |
1719 | * @restore: | |
1720 | * @re: | |
1721 | * | |
1722 | * prepare a registry element according to the current command request. | |
1723 | */ | |
1724 | static inline int bnx2x_vlan_mac_get_registry_elem( | |
1725 | struct bnx2x *bp, | |
1726 | struct bnx2x_vlan_mac_obj *o, | |
1727 | struct bnx2x_exeq_elem *elem, | |
1728 | bool restore, | |
1729 | struct bnx2x_vlan_mac_registry_elem **re) | |
1730 | { | |
86564c3f | 1731 | enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd; |
619c5cb6 VZ |
1732 | struct bnx2x_vlan_mac_registry_elem *reg_elem; |
1733 | ||
1734 | /* Allocate a new registry element if needed. */ | |
1735 | if (!restore && | |
1736 | ((cmd == BNX2X_VLAN_MAC_ADD) || (cmd == BNX2X_VLAN_MAC_MOVE))) { | |
1737 | reg_elem = kzalloc(sizeof(*reg_elem), GFP_ATOMIC); | |
1738 | if (!reg_elem) | |
1739 | return -ENOMEM; | |
1740 | ||
1741 | /* Get a new CAM offset */ | |
1742 | if (!o->get_cam_offset(o, ®_elem->cam_offset)) { | |
16a5fd92 YM |
1743 | /* This shall never happen, because we have checked the |
1744 | * CAM availability in the 'validate'. | |
619c5cb6 VZ |
1745 | */ |
1746 | WARN_ON(1); | |
1747 | kfree(reg_elem); | |
1748 | return -EINVAL; | |
1749 | } | |
1750 | ||
1751 | DP(BNX2X_MSG_SP, "Got cam offset %d\n", reg_elem->cam_offset); | |
1752 | ||
1753 | /* Set a VLAN-MAC data */ | |
1754 | memcpy(®_elem->u, &elem->cmd_data.vlan_mac.u, | |
1755 | sizeof(reg_elem->u)); | |
1756 | ||
1757 | /* Copy the flags (needed for DEL and RESTORE flows) */ | |
1758 | reg_elem->vlan_mac_flags = | |
1759 | elem->cmd_data.vlan_mac.vlan_mac_flags; | |
1760 | } else /* DEL, RESTORE */ | |
51c1a580 | 1761 | reg_elem = o->check_del(bp, o, &elem->cmd_data.vlan_mac.u); |
619c5cb6 VZ |
1762 | |
1763 | *re = reg_elem; | |
1764 | return 0; | |
1765 | } | |
1766 | ||
1767 | /** | |
1768 | * bnx2x_execute_vlan_mac - execute vlan mac command | |
1769 | * | |
1770 | * @bp: device handle | |
1771 | * @qo: | |
1772 | * @exe_chunk: | |
1773 | * @ramrod_flags: | |
1774 | * | |
1775 | * go and send a ramrod! | |
1776 | */ | |
1777 | static int bnx2x_execute_vlan_mac(struct bnx2x *bp, | |
1778 | union bnx2x_qable_obj *qo, | |
1779 | struct list_head *exe_chunk, | |
1780 | unsigned long *ramrod_flags) | |
1781 | { | |
1782 | struct bnx2x_exeq_elem *elem; | |
1783 | struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac, *cam_obj; | |
1784 | struct bnx2x_raw_obj *r = &o->raw; | |
1785 | int rc, idx = 0; | |
1786 | bool restore = test_bit(RAMROD_RESTORE, ramrod_flags); | |
1787 | bool drv_only = test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags); | |
1788 | struct bnx2x_vlan_mac_registry_elem *reg_elem; | |
86564c3f | 1789 | enum bnx2x_vlan_mac_cmd cmd; |
619c5cb6 | 1790 | |
16a5fd92 | 1791 | /* If DRIVER_ONLY execution is requested, cleanup a registry |
619c5cb6 VZ |
1792 | * and exit. Otherwise send a ramrod to FW. |
1793 | */ | |
1794 | if (!drv_only) { | |
1795 | WARN_ON(r->check_pending(r)); | |
1796 | ||
1797 | /* Set pending */ | |
1798 | r->set_pending(r); | |
1799 | ||
16a5fd92 | 1800 | /* Fill the ramrod data */ |
619c5cb6 VZ |
1801 | list_for_each_entry(elem, exe_chunk, link) { |
1802 | cmd = elem->cmd_data.vlan_mac.cmd; | |
16a5fd92 | 1803 | /* We will add to the target object in MOVE command, so |
619c5cb6 VZ |
1804 | * change the object for a CAM search. |
1805 | */ | |
1806 | if (cmd == BNX2X_VLAN_MAC_MOVE) | |
1807 | cam_obj = elem->cmd_data.vlan_mac.target_obj; | |
1808 | else | |
1809 | cam_obj = o; | |
1810 | ||
1811 | rc = bnx2x_vlan_mac_get_registry_elem(bp, cam_obj, | |
1812 | elem, restore, | |
1813 | ®_elem); | |
1814 | if (rc) | |
1815 | goto error_exit; | |
1816 | ||
1817 | WARN_ON(!reg_elem); | |
1818 | ||
1819 | /* Push a new entry into the registry */ | |
1820 | if (!restore && | |
1821 | ((cmd == BNX2X_VLAN_MAC_ADD) || | |
1822 | (cmd == BNX2X_VLAN_MAC_MOVE))) | |
1823 | list_add(®_elem->link, &cam_obj->head); | |
1824 | ||
1825 | /* Configure a single command in a ramrod data buffer */ | |
1826 | o->set_one_rule(bp, o, elem, idx, | |
1827 | reg_elem->cam_offset); | |
1828 | ||
1829 | /* MOVE command consumes 2 entries in the ramrod data */ | |
1830 | if (cmd == BNX2X_VLAN_MAC_MOVE) | |
1831 | idx += 2; | |
1832 | else | |
1833 | idx++; | |
1834 | } | |
1835 | ||
16a5fd92 YM |
1836 | /* No need for an explicit memory barrier here as long we would |
1837 | * need to ensure the ordering of writing to the SPQ element | |
1838 | * and updating of the SPQ producer which involves a memory | |
1839 | * read and we will have to put a full memory barrier there | |
1840 | * (inside bnx2x_sp_post()). | |
53e51e2f | 1841 | */ |
619c5cb6 VZ |
1842 | |
1843 | rc = bnx2x_sp_post(bp, o->ramrod_cmd, r->cid, | |
1844 | U64_HI(r->rdata_mapping), | |
1845 | U64_LO(r->rdata_mapping), | |
1846 | ETH_CONNECTION_TYPE); | |
1847 | if (rc) | |
1848 | goto error_exit; | |
1849 | } | |
1850 | ||
1851 | /* Now, when we are done with the ramrod - clean up the registry */ | |
1852 | list_for_each_entry(elem, exe_chunk, link) { | |
1853 | cmd = elem->cmd_data.vlan_mac.cmd; | |
1854 | if ((cmd == BNX2X_VLAN_MAC_DEL) || | |
1855 | (cmd == BNX2X_VLAN_MAC_MOVE)) { | |
51c1a580 MS |
1856 | reg_elem = o->check_del(bp, o, |
1857 | &elem->cmd_data.vlan_mac.u); | |
619c5cb6 VZ |
1858 | |
1859 | WARN_ON(!reg_elem); | |
1860 | ||
1861 | o->put_cam_offset(o, reg_elem->cam_offset); | |
1862 | list_del(®_elem->link); | |
1863 | kfree(reg_elem); | |
1864 | } | |
1865 | } | |
1866 | ||
1867 | if (!drv_only) | |
1868 | return 1; | |
1869 | else | |
1870 | return 0; | |
1871 | ||
1872 | error_exit: | |
1873 | r->clear_pending(r); | |
1874 | ||
1875 | /* Cleanup a registry in case of a failure */ | |
1876 | list_for_each_entry(elem, exe_chunk, link) { | |
1877 | cmd = elem->cmd_data.vlan_mac.cmd; | |
1878 | ||
1879 | if (cmd == BNX2X_VLAN_MAC_MOVE) | |
1880 | cam_obj = elem->cmd_data.vlan_mac.target_obj; | |
1881 | else | |
1882 | cam_obj = o; | |
1883 | ||
1884 | /* Delete all newly added above entries */ | |
1885 | if (!restore && | |
1886 | ((cmd == BNX2X_VLAN_MAC_ADD) || | |
1887 | (cmd == BNX2X_VLAN_MAC_MOVE))) { | |
51c1a580 | 1888 | reg_elem = o->check_del(bp, cam_obj, |
619c5cb6 VZ |
1889 | &elem->cmd_data.vlan_mac.u); |
1890 | if (reg_elem) { | |
1891 | list_del(®_elem->link); | |
1892 | kfree(reg_elem); | |
1893 | } | |
1894 | } | |
1895 | } | |
1896 | ||
1897 | return rc; | |
1898 | } | |
1899 | ||
1900 | static inline int bnx2x_vlan_mac_push_new_cmd( | |
1901 | struct bnx2x *bp, | |
1902 | struct bnx2x_vlan_mac_ramrod_params *p) | |
1903 | { | |
1904 | struct bnx2x_exeq_elem *elem; | |
1905 | struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj; | |
1906 | bool restore = test_bit(RAMROD_RESTORE, &p->ramrod_flags); | |
1907 | ||
1908 | /* Allocate the execution queue element */ | |
1909 | elem = bnx2x_exe_queue_alloc_elem(bp); | |
1910 | if (!elem) | |
1911 | return -ENOMEM; | |
1912 | ||
1913 | /* Set the command 'length' */ | |
1914 | switch (p->user_req.cmd) { | |
1915 | case BNX2X_VLAN_MAC_MOVE: | |
1916 | elem->cmd_len = 2; | |
1917 | break; | |
1918 | default: | |
1919 | elem->cmd_len = 1; | |
1920 | } | |
1921 | ||
1922 | /* Fill the object specific info */ | |
1923 | memcpy(&elem->cmd_data.vlan_mac, &p->user_req, sizeof(p->user_req)); | |
1924 | ||
1925 | /* Try to add a new command to the pending list */ | |
1926 | return bnx2x_exe_queue_add(bp, &o->exe_queue, elem, restore); | |
1927 | } | |
1928 | ||
1929 | /** | |
1930 | * bnx2x_config_vlan_mac - configure VLAN/MAC/VLAN_MAC filtering rules. | |
1931 | * | |
1932 | * @bp: device handle | |
1933 | * @p: | |
1934 | * | |
1935 | */ | |
8b09be5f YM |
1936 | int bnx2x_config_vlan_mac(struct bnx2x *bp, |
1937 | struct bnx2x_vlan_mac_ramrod_params *p) | |
619c5cb6 VZ |
1938 | { |
1939 | int rc = 0; | |
1940 | struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj; | |
1941 | unsigned long *ramrod_flags = &p->ramrod_flags; | |
1942 | bool cont = test_bit(RAMROD_CONT, ramrod_flags); | |
1943 | struct bnx2x_raw_obj *raw = &o->raw; | |
1944 | ||
1945 | /* | |
1946 | * Add new elements to the execution list for commands that require it. | |
1947 | */ | |
1948 | if (!cont) { | |
1949 | rc = bnx2x_vlan_mac_push_new_cmd(bp, p); | |
1950 | if (rc) | |
1951 | return rc; | |
1952 | } | |
1953 | ||
16a5fd92 | 1954 | /* If nothing will be executed further in this iteration we want to |
619c5cb6 VZ |
1955 | * return PENDING if there are pending commands |
1956 | */ | |
1957 | if (!bnx2x_exe_queue_empty(&o->exe_queue)) | |
1958 | rc = 1; | |
1959 | ||
79616895 | 1960 | if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags)) { |
51c1a580 | 1961 | DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: clearing a pending bit.\n"); |
79616895 VZ |
1962 | raw->clear_pending(raw); |
1963 | } | |
1964 | ||
619c5cb6 VZ |
1965 | /* Execute commands if required */ |
1966 | if (cont || test_bit(RAMROD_EXEC, ramrod_flags) || | |
1967 | test_bit(RAMROD_COMP_WAIT, ramrod_flags)) { | |
8b09be5f YM |
1968 | rc = __bnx2x_vlan_mac_execute_step(bp, p->vlan_mac_obj, |
1969 | &p->ramrod_flags); | |
619c5cb6 VZ |
1970 | if (rc < 0) |
1971 | return rc; | |
1972 | } | |
1973 | ||
16a5fd92 | 1974 | /* RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set |
619c5cb6 VZ |
1975 | * then user want to wait until the last command is done. |
1976 | */ | |
1977 | if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) { | |
16a5fd92 | 1978 | /* Wait maximum for the current exe_queue length iterations plus |
619c5cb6 VZ |
1979 | * one (for the current pending command). |
1980 | */ | |
1981 | int max_iterations = bnx2x_exe_queue_length(&o->exe_queue) + 1; | |
1982 | ||
1983 | while (!bnx2x_exe_queue_empty(&o->exe_queue) && | |
1984 | max_iterations--) { | |
1985 | ||
1986 | /* Wait for the current command to complete */ | |
1987 | rc = raw->wait_comp(bp, raw); | |
1988 | if (rc) | |
1989 | return rc; | |
1990 | ||
1991 | /* Make a next step */ | |
8b09be5f YM |
1992 | rc = __bnx2x_vlan_mac_execute_step(bp, |
1993 | p->vlan_mac_obj, | |
1994 | &p->ramrod_flags); | |
619c5cb6 VZ |
1995 | if (rc < 0) |
1996 | return rc; | |
1997 | } | |
1998 | ||
1999 | return 0; | |
2000 | } | |
2001 | ||
2002 | return rc; | |
2003 | } | |
2004 | ||
619c5cb6 VZ |
2005 | /** |
2006 | * bnx2x_vlan_mac_del_all - delete elements with given vlan_mac_flags spec | |
2007 | * | |
2008 | * @bp: device handle | |
2009 | * @o: | |
2010 | * @vlan_mac_flags: | |
2011 | * @ramrod_flags: execution flags to be used for this deletion | |
2012 | * | |
2013 | * if the last operation has completed successfully and there are no | |
16a5fd92 | 2014 | * more elements left, positive value if the last operation has completed |
619c5cb6 VZ |
2015 | * successfully and there are more previously configured elements, negative |
2016 | * value is current operation has failed. | |
2017 | */ | |
2018 | static int bnx2x_vlan_mac_del_all(struct bnx2x *bp, | |
2019 | struct bnx2x_vlan_mac_obj *o, | |
2020 | unsigned long *vlan_mac_flags, | |
2021 | unsigned long *ramrod_flags) | |
2022 | { | |
2023 | struct bnx2x_vlan_mac_registry_elem *pos = NULL; | |
619c5cb6 VZ |
2024 | struct bnx2x_vlan_mac_ramrod_params p; |
2025 | struct bnx2x_exe_queue_obj *exeq = &o->exe_queue; | |
2026 | struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n; | |
e8379c79 | 2027 | unsigned long flags; |
8b09be5f YM |
2028 | int read_lock; |
2029 | int rc = 0; | |
619c5cb6 VZ |
2030 | |
2031 | /* Clear pending commands first */ | |
2032 | ||
2033 | spin_lock_bh(&exeq->lock); | |
2034 | ||
2035 | list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) { | |
e8379c79 YM |
2036 | flags = exeq_pos->cmd_data.vlan_mac.vlan_mac_flags; |
2037 | if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) == | |
2038 | BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) { | |
460a25cd YM |
2039 | rc = exeq->remove(bp, exeq->owner, exeq_pos); |
2040 | if (rc) { | |
2041 | BNX2X_ERR("Failed to remove command\n"); | |
a44acd55 | 2042 | spin_unlock_bh(&exeq->lock); |
460a25cd YM |
2043 | return rc; |
2044 | } | |
619c5cb6 | 2045 | list_del(&exeq_pos->link); |
07ef7bec | 2046 | bnx2x_exe_queue_free_elem(bp, exeq_pos); |
460a25cd | 2047 | } |
619c5cb6 VZ |
2048 | } |
2049 | ||
2050 | spin_unlock_bh(&exeq->lock); | |
2051 | ||
2052 | /* Prepare a command request */ | |
2053 | memset(&p, 0, sizeof(p)); | |
2054 | p.vlan_mac_obj = o; | |
2055 | p.ramrod_flags = *ramrod_flags; | |
2056 | p.user_req.cmd = BNX2X_VLAN_MAC_DEL; | |
2057 | ||
16a5fd92 | 2058 | /* Add all but the last VLAN-MAC to the execution queue without actually |
619c5cb6 VZ |
2059 | * execution anything. |
2060 | */ | |
2061 | __clear_bit(RAMROD_COMP_WAIT, &p.ramrod_flags); | |
2062 | __clear_bit(RAMROD_EXEC, &p.ramrod_flags); | |
2063 | __clear_bit(RAMROD_CONT, &p.ramrod_flags); | |
2064 | ||
8b09be5f YM |
2065 | DP(BNX2X_MSG_SP, "vlan_mac_del_all -- taking vlan_mac_lock (reader)\n"); |
2066 | read_lock = bnx2x_vlan_mac_h_read_lock(bp, o); | |
2067 | if (read_lock != 0) | |
2068 | return read_lock; | |
2069 | ||
619c5cb6 | 2070 | list_for_each_entry(pos, &o->head, link) { |
e8379c79 YM |
2071 | flags = pos->vlan_mac_flags; |
2072 | if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) == | |
2073 | BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) { | |
619c5cb6 VZ |
2074 | p.user_req.vlan_mac_flags = pos->vlan_mac_flags; |
2075 | memcpy(&p.user_req.u, &pos->u, sizeof(pos->u)); | |
2076 | rc = bnx2x_config_vlan_mac(bp, &p); | |
2077 | if (rc < 0) { | |
2078 | BNX2X_ERR("Failed to add a new DEL command\n"); | |
8b09be5f | 2079 | bnx2x_vlan_mac_h_read_unlock(bp, o); |
619c5cb6 VZ |
2080 | return rc; |
2081 | } | |
2082 | } | |
2083 | } | |
2084 | ||
8b09be5f YM |
2085 | DP(BNX2X_MSG_SP, "vlan_mac_del_all -- releasing vlan_mac_lock (reader)\n"); |
2086 | bnx2x_vlan_mac_h_read_unlock(bp, o); | |
2087 | ||
619c5cb6 VZ |
2088 | p.ramrod_flags = *ramrod_flags; |
2089 | __set_bit(RAMROD_CONT, &p.ramrod_flags); | |
2090 | ||
2091 | return bnx2x_config_vlan_mac(bp, &p); | |
2092 | } | |
2093 | ||
2094 | static inline void bnx2x_init_raw_obj(struct bnx2x_raw_obj *raw, u8 cl_id, | |
2095 | u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping, int state, | |
2096 | unsigned long *pstate, bnx2x_obj_type type) | |
2097 | { | |
2098 | raw->func_id = func_id; | |
2099 | raw->cid = cid; | |
2100 | raw->cl_id = cl_id; | |
2101 | raw->rdata = rdata; | |
2102 | raw->rdata_mapping = rdata_mapping; | |
2103 | raw->state = state; | |
2104 | raw->pstate = pstate; | |
2105 | raw->obj_type = type; | |
2106 | raw->check_pending = bnx2x_raw_check_pending; | |
2107 | raw->clear_pending = bnx2x_raw_clear_pending; | |
2108 | raw->set_pending = bnx2x_raw_set_pending; | |
2109 | raw->wait_comp = bnx2x_raw_wait; | |
2110 | } | |
2111 | ||
2112 | static inline void bnx2x_init_vlan_mac_common(struct bnx2x_vlan_mac_obj *o, | |
2113 | u8 cl_id, u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping, | |
2114 | int state, unsigned long *pstate, bnx2x_obj_type type, | |
2115 | struct bnx2x_credit_pool_obj *macs_pool, | |
2116 | struct bnx2x_credit_pool_obj *vlans_pool) | |
2117 | { | |
2118 | INIT_LIST_HEAD(&o->head); | |
8b09be5f YM |
2119 | o->head_reader = 0; |
2120 | o->head_exe_request = false; | |
2121 | o->saved_ramrod_flags = 0; | |
619c5cb6 VZ |
2122 | |
2123 | o->macs_pool = macs_pool; | |
2124 | o->vlans_pool = vlans_pool; | |
2125 | ||
2126 | o->delete_all = bnx2x_vlan_mac_del_all; | |
2127 | o->restore = bnx2x_vlan_mac_restore; | |
2128 | o->complete = bnx2x_complete_vlan_mac; | |
2129 | o->wait = bnx2x_wait_vlan_mac; | |
2130 | ||
2131 | bnx2x_init_raw_obj(&o->raw, cl_id, cid, func_id, rdata, rdata_mapping, | |
2132 | state, pstate, type); | |
2133 | } | |
2134 | ||
619c5cb6 VZ |
2135 | void bnx2x_init_mac_obj(struct bnx2x *bp, |
2136 | struct bnx2x_vlan_mac_obj *mac_obj, | |
2137 | u8 cl_id, u32 cid, u8 func_id, void *rdata, | |
2138 | dma_addr_t rdata_mapping, int state, | |
2139 | unsigned long *pstate, bnx2x_obj_type type, | |
2140 | struct bnx2x_credit_pool_obj *macs_pool) | |
2141 | { | |
2142 | union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)mac_obj; | |
2143 | ||
2144 | bnx2x_init_vlan_mac_common(mac_obj, cl_id, cid, func_id, rdata, | |
2145 | rdata_mapping, state, pstate, type, | |
2146 | macs_pool, NULL); | |
2147 | ||
2148 | /* CAM credit pool handling */ | |
2149 | mac_obj->get_credit = bnx2x_get_credit_mac; | |
2150 | mac_obj->put_credit = bnx2x_put_credit_mac; | |
2151 | mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac; | |
2152 | mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac; | |
2153 | ||
2154 | if (CHIP_IS_E1x(bp)) { | |
2155 | mac_obj->set_one_rule = bnx2x_set_one_mac_e1x; | |
2156 | mac_obj->check_del = bnx2x_check_mac_del; | |
2157 | mac_obj->check_add = bnx2x_check_mac_add; | |
2158 | mac_obj->check_move = bnx2x_check_move_always_err; | |
2159 | mac_obj->ramrod_cmd = RAMROD_CMD_ID_ETH_SET_MAC; | |
2160 | ||
2161 | /* Exe Queue */ | |
2162 | bnx2x_exe_queue_init(bp, | |
2163 | &mac_obj->exe_queue, 1, qable_obj, | |
2164 | bnx2x_validate_vlan_mac, | |
460a25cd | 2165 | bnx2x_remove_vlan_mac, |
619c5cb6 VZ |
2166 | bnx2x_optimize_vlan_mac, |
2167 | bnx2x_execute_vlan_mac, | |
2168 | bnx2x_exeq_get_mac); | |
2169 | } else { | |
2170 | mac_obj->set_one_rule = bnx2x_set_one_mac_e2; | |
2171 | mac_obj->check_del = bnx2x_check_mac_del; | |
2172 | mac_obj->check_add = bnx2x_check_mac_add; | |
2173 | mac_obj->check_move = bnx2x_check_move; | |
2174 | mac_obj->ramrod_cmd = | |
2175 | RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES; | |
ed5162a0 | 2176 | mac_obj->get_n_elements = bnx2x_get_n_elements; |
619c5cb6 VZ |
2177 | |
2178 | /* Exe Queue */ | |
2179 | bnx2x_exe_queue_init(bp, | |
2180 | &mac_obj->exe_queue, CLASSIFY_RULES_COUNT, | |
2181 | qable_obj, bnx2x_validate_vlan_mac, | |
460a25cd | 2182 | bnx2x_remove_vlan_mac, |
619c5cb6 VZ |
2183 | bnx2x_optimize_vlan_mac, |
2184 | bnx2x_execute_vlan_mac, | |
2185 | bnx2x_exeq_get_mac); | |
2186 | } | |
2187 | } | |
2188 | ||
2189 | void bnx2x_init_vlan_obj(struct bnx2x *bp, | |
2190 | struct bnx2x_vlan_mac_obj *vlan_obj, | |
2191 | u8 cl_id, u32 cid, u8 func_id, void *rdata, | |
2192 | dma_addr_t rdata_mapping, int state, | |
2193 | unsigned long *pstate, bnx2x_obj_type type, | |
2194 | struct bnx2x_credit_pool_obj *vlans_pool) | |
2195 | { | |
2196 | union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)vlan_obj; | |
2197 | ||
2198 | bnx2x_init_vlan_mac_common(vlan_obj, cl_id, cid, func_id, rdata, | |
2199 | rdata_mapping, state, pstate, type, NULL, | |
2200 | vlans_pool); | |
2201 | ||
2202 | vlan_obj->get_credit = bnx2x_get_credit_vlan; | |
2203 | vlan_obj->put_credit = bnx2x_put_credit_vlan; | |
2204 | vlan_obj->get_cam_offset = bnx2x_get_cam_offset_vlan; | |
2205 | vlan_obj->put_cam_offset = bnx2x_put_cam_offset_vlan; | |
2206 | ||
2207 | if (CHIP_IS_E1x(bp)) { | |
2208 | BNX2X_ERR("Do not support chips others than E2 and newer\n"); | |
2209 | BUG(); | |
2210 | } else { | |
2211 | vlan_obj->set_one_rule = bnx2x_set_one_vlan_e2; | |
2212 | vlan_obj->check_del = bnx2x_check_vlan_del; | |
2213 | vlan_obj->check_add = bnx2x_check_vlan_add; | |
2214 | vlan_obj->check_move = bnx2x_check_move; | |
2215 | vlan_obj->ramrod_cmd = | |
2216 | RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES; | |
3ec9f9ca | 2217 | vlan_obj->get_n_elements = bnx2x_get_n_elements; |
619c5cb6 VZ |
2218 | |
2219 | /* Exe Queue */ | |
2220 | bnx2x_exe_queue_init(bp, | |
2221 | &vlan_obj->exe_queue, CLASSIFY_RULES_COUNT, | |
2222 | qable_obj, bnx2x_validate_vlan_mac, | |
460a25cd | 2223 | bnx2x_remove_vlan_mac, |
619c5cb6 VZ |
2224 | bnx2x_optimize_vlan_mac, |
2225 | bnx2x_execute_vlan_mac, | |
2226 | bnx2x_exeq_get_vlan); | |
2227 | } | |
2228 | } | |
2229 | ||
05cc5a39 YM |
2230 | void bnx2x_init_vlan_mac_obj(struct bnx2x *bp, |
2231 | struct bnx2x_vlan_mac_obj *vlan_mac_obj, | |
2232 | u8 cl_id, u32 cid, u8 func_id, void *rdata, | |
2233 | dma_addr_t rdata_mapping, int state, | |
2234 | unsigned long *pstate, bnx2x_obj_type type, | |
2235 | struct bnx2x_credit_pool_obj *macs_pool, | |
2236 | struct bnx2x_credit_pool_obj *vlans_pool) | |
2237 | { | |
2238 | union bnx2x_qable_obj *qable_obj = | |
2239 | (union bnx2x_qable_obj *)vlan_mac_obj; | |
2240 | ||
2241 | bnx2x_init_vlan_mac_common(vlan_mac_obj, cl_id, cid, func_id, rdata, | |
2242 | rdata_mapping, state, pstate, type, | |
2243 | macs_pool, vlans_pool); | |
2244 | ||
2245 | /* CAM pool handling */ | |
2246 | vlan_mac_obj->get_credit = bnx2x_get_credit_vlan_mac; | |
2247 | vlan_mac_obj->put_credit = bnx2x_put_credit_vlan_mac; | |
2248 | /* CAM offset is relevant for 57710 and 57711 chips only which have a | |
2249 | * single CAM for both MACs and VLAN-MAC pairs. So the offset | |
2250 | * will be taken from MACs' pool object only. | |
2251 | */ | |
2252 | vlan_mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac; | |
2253 | vlan_mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac; | |
2254 | ||
2255 | if (CHIP_IS_E1(bp)) { | |
2256 | BNX2X_ERR("Do not support chips others than E2\n"); | |
2257 | BUG(); | |
2258 | } else if (CHIP_IS_E1H(bp)) { | |
2259 | vlan_mac_obj->set_one_rule = bnx2x_set_one_vlan_mac_e1h; | |
2260 | vlan_mac_obj->check_del = bnx2x_check_vlan_mac_del; | |
2261 | vlan_mac_obj->check_add = bnx2x_check_vlan_mac_add; | |
2262 | vlan_mac_obj->check_move = bnx2x_check_move_always_err; | |
2263 | vlan_mac_obj->ramrod_cmd = RAMROD_CMD_ID_ETH_SET_MAC; | |
2264 | ||
2265 | /* Exe Queue */ | |
2266 | bnx2x_exe_queue_init(bp, | |
2267 | &vlan_mac_obj->exe_queue, 1, qable_obj, | |
2268 | bnx2x_validate_vlan_mac, | |
2269 | bnx2x_remove_vlan_mac, | |
2270 | bnx2x_optimize_vlan_mac, | |
2271 | bnx2x_execute_vlan_mac, | |
2272 | bnx2x_exeq_get_vlan_mac); | |
2273 | } else { | |
2274 | vlan_mac_obj->set_one_rule = bnx2x_set_one_vlan_mac_e2; | |
2275 | vlan_mac_obj->check_del = bnx2x_check_vlan_mac_del; | |
2276 | vlan_mac_obj->check_add = bnx2x_check_vlan_mac_add; | |
2277 | vlan_mac_obj->check_move = bnx2x_check_move; | |
2278 | vlan_mac_obj->ramrod_cmd = | |
2279 | RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES; | |
2280 | ||
2281 | /* Exe Queue */ | |
2282 | bnx2x_exe_queue_init(bp, | |
2283 | &vlan_mac_obj->exe_queue, | |
2284 | CLASSIFY_RULES_COUNT, | |
2285 | qable_obj, bnx2x_validate_vlan_mac, | |
2286 | bnx2x_remove_vlan_mac, | |
2287 | bnx2x_optimize_vlan_mac, | |
2288 | bnx2x_execute_vlan_mac, | |
2289 | bnx2x_exeq_get_vlan_mac); | |
2290 | } | |
2291 | } | |
619c5cb6 VZ |
2292 | /* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */ |
2293 | static inline void __storm_memset_mac_filters(struct bnx2x *bp, | |
2294 | struct tstorm_eth_mac_filter_config *mac_filters, | |
2295 | u16 pf_id) | |
2296 | { | |
2297 | size_t size = sizeof(struct tstorm_eth_mac_filter_config); | |
2298 | ||
2299 | u32 addr = BAR_TSTRORM_INTMEM + | |
2300 | TSTORM_MAC_FILTER_CONFIG_OFFSET(pf_id); | |
2301 | ||
2302 | __storm_memset_struct(bp, addr, size, (u32 *)mac_filters); | |
2303 | } | |
2304 | ||
2305 | static int bnx2x_set_rx_mode_e1x(struct bnx2x *bp, | |
2306 | struct bnx2x_rx_mode_ramrod_params *p) | |
2307 | { | |
2de67439 | 2308 | /* update the bp MAC filter structure */ |
619c5cb6 VZ |
2309 | u32 mask = (1 << p->cl_id); |
2310 | ||
2311 | struct tstorm_eth_mac_filter_config *mac_filters = | |
2312 | (struct tstorm_eth_mac_filter_config *)p->rdata; | |
2313 | ||
16a5fd92 | 2314 | /* initial setting is drop-all */ |
619c5cb6 VZ |
2315 | u8 drop_all_ucast = 1, drop_all_mcast = 1; |
2316 | u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0; | |
2317 | u8 unmatched_unicast = 0; | |
2318 | ||
16a5fd92 | 2319 | /* In e1x there we only take into account rx accept flag since tx switching |
619c5cb6 VZ |
2320 | * isn't enabled. */ |
2321 | if (test_bit(BNX2X_ACCEPT_UNICAST, &p->rx_accept_flags)) | |
2322 | /* accept matched ucast */ | |
2323 | drop_all_ucast = 0; | |
2324 | ||
2325 | if (test_bit(BNX2X_ACCEPT_MULTICAST, &p->rx_accept_flags)) | |
2326 | /* accept matched mcast */ | |
2327 | drop_all_mcast = 0; | |
2328 | ||
2329 | if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &p->rx_accept_flags)) { | |
2330 | /* accept all mcast */ | |
2331 | drop_all_ucast = 0; | |
2332 | accp_all_ucast = 1; | |
2333 | } | |
2334 | if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &p->rx_accept_flags)) { | |
2335 | /* accept all mcast */ | |
2336 | drop_all_mcast = 0; | |
2337 | accp_all_mcast = 1; | |
2338 | } | |
2339 | if (test_bit(BNX2X_ACCEPT_BROADCAST, &p->rx_accept_flags)) | |
2340 | /* accept (all) bcast */ | |
2341 | accp_all_bcast = 1; | |
2342 | if (test_bit(BNX2X_ACCEPT_UNMATCHED, &p->rx_accept_flags)) | |
2343 | /* accept unmatched unicasts */ | |
2344 | unmatched_unicast = 1; | |
2345 | ||
2346 | mac_filters->ucast_drop_all = drop_all_ucast ? | |
2347 | mac_filters->ucast_drop_all | mask : | |
2348 | mac_filters->ucast_drop_all & ~mask; | |
2349 | ||
2350 | mac_filters->mcast_drop_all = drop_all_mcast ? | |
2351 | mac_filters->mcast_drop_all | mask : | |
2352 | mac_filters->mcast_drop_all & ~mask; | |
2353 | ||
2354 | mac_filters->ucast_accept_all = accp_all_ucast ? | |
2355 | mac_filters->ucast_accept_all | mask : | |
2356 | mac_filters->ucast_accept_all & ~mask; | |
2357 | ||
2358 | mac_filters->mcast_accept_all = accp_all_mcast ? | |
2359 | mac_filters->mcast_accept_all | mask : | |
2360 | mac_filters->mcast_accept_all & ~mask; | |
2361 | ||
2362 | mac_filters->bcast_accept_all = accp_all_bcast ? | |
2363 | mac_filters->bcast_accept_all | mask : | |
2364 | mac_filters->bcast_accept_all & ~mask; | |
2365 | ||
2366 | mac_filters->unmatched_unicast = unmatched_unicast ? | |
2367 | mac_filters->unmatched_unicast | mask : | |
2368 | mac_filters->unmatched_unicast & ~mask; | |
2369 | ||
2370 | DP(BNX2X_MSG_SP, "drop_ucast 0x%x\ndrop_mcast 0x%x\n accp_ucast 0x%x\n" | |
2de67439 | 2371 | "accp_mcast 0x%x\naccp_bcast 0x%x\n", |
51c1a580 MS |
2372 | mac_filters->ucast_drop_all, mac_filters->mcast_drop_all, |
2373 | mac_filters->ucast_accept_all, mac_filters->mcast_accept_all, | |
2374 | mac_filters->bcast_accept_all); | |
619c5cb6 VZ |
2375 | |
2376 | /* write the MAC filter structure*/ | |
2377 | __storm_memset_mac_filters(bp, mac_filters, p->func_id); | |
2378 | ||
2379 | /* The operation is completed */ | |
2380 | clear_bit(p->state, p->pstate); | |
4e857c58 | 2381 | smp_mb__after_atomic(); |
619c5cb6 VZ |
2382 | |
2383 | return 0; | |
2384 | } | |
2385 | ||
2386 | /* Setup ramrod data */ | |
2387 | static inline void bnx2x_rx_mode_set_rdata_hdr_e2(u32 cid, | |
2388 | struct eth_classify_header *hdr, | |
2389 | u8 rule_cnt) | |
2390 | { | |
86564c3f | 2391 | hdr->echo = cpu_to_le32(cid); |
619c5cb6 VZ |
2392 | hdr->rule_cnt = rule_cnt; |
2393 | } | |
2394 | ||
2395 | static inline void bnx2x_rx_mode_set_cmd_state_e2(struct bnx2x *bp, | |
924d75ab | 2396 | unsigned long *accept_flags, |
619c5cb6 VZ |
2397 | struct eth_filter_rules_cmd *cmd, |
2398 | bool clear_accept_all) | |
2399 | { | |
2400 | u16 state; | |
2401 | ||
2402 | /* start with 'drop-all' */ | |
2403 | state = ETH_FILTER_RULES_CMD_UCAST_DROP_ALL | | |
2404 | ETH_FILTER_RULES_CMD_MCAST_DROP_ALL; | |
2405 | ||
924d75ab YM |
2406 | if (test_bit(BNX2X_ACCEPT_UNICAST, accept_flags)) |
2407 | state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL; | |
619c5cb6 | 2408 | |
924d75ab YM |
2409 | if (test_bit(BNX2X_ACCEPT_MULTICAST, accept_flags)) |
2410 | state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL; | |
619c5cb6 | 2411 | |
924d75ab YM |
2412 | if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, accept_flags)) { |
2413 | state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL; | |
2414 | state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL; | |
2415 | } | |
619c5cb6 | 2416 | |
924d75ab YM |
2417 | if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, accept_flags)) { |
2418 | state |= ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL; | |
2419 | state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL; | |
2420 | } | |
619c5cb6 | 2421 | |
924d75ab YM |
2422 | if (test_bit(BNX2X_ACCEPT_BROADCAST, accept_flags)) |
2423 | state |= ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL; | |
2424 | ||
2425 | if (test_bit(BNX2X_ACCEPT_UNMATCHED, accept_flags)) { | |
2426 | state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL; | |
2427 | state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED; | |
619c5cb6 VZ |
2428 | } |
2429 | ||
924d75ab YM |
2430 | if (test_bit(BNX2X_ACCEPT_ANY_VLAN, accept_flags)) |
2431 | state |= ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN; | |
2432 | ||
619c5cb6 VZ |
2433 | /* Clear ACCEPT_ALL_XXX flags for FCoE L2 Queue */ |
2434 | if (clear_accept_all) { | |
2435 | state &= ~ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL; | |
2436 | state &= ~ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL; | |
2437 | state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL; | |
2438 | state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED; | |
2439 | } | |
2440 | ||
2441 | cmd->state = cpu_to_le16(state); | |
619c5cb6 VZ |
2442 | } |
2443 | ||
2444 | static int bnx2x_set_rx_mode_e2(struct bnx2x *bp, | |
2445 | struct bnx2x_rx_mode_ramrod_params *p) | |
2446 | { | |
2447 | struct eth_filter_rules_ramrod_data *data = p->rdata; | |
2448 | int rc; | |
2449 | u8 rule_idx = 0; | |
2450 | ||
2451 | /* Reset the ramrod data buffer */ | |
2452 | memset(data, 0, sizeof(*data)); | |
2453 | ||
2454 | /* Setup ramrod data */ | |
2455 | ||
2456 | /* Tx (internal switching) */ | |
2457 | if (test_bit(RAMROD_TX, &p->ramrod_flags)) { | |
2458 | data->rules[rule_idx].client_id = p->cl_id; | |
2459 | data->rules[rule_idx].func_id = p->func_id; | |
2460 | ||
2461 | data->rules[rule_idx].cmd_general_data = | |
2462 | ETH_FILTER_RULES_CMD_TX_CMD; | |
2463 | ||
924d75ab YM |
2464 | bnx2x_rx_mode_set_cmd_state_e2(bp, &p->tx_accept_flags, |
2465 | &(data->rules[rule_idx++]), | |
2466 | false); | |
619c5cb6 VZ |
2467 | } |
2468 | ||
2469 | /* Rx */ | |
2470 | if (test_bit(RAMROD_RX, &p->ramrod_flags)) { | |
2471 | data->rules[rule_idx].client_id = p->cl_id; | |
2472 | data->rules[rule_idx].func_id = p->func_id; | |
2473 | ||
2474 | data->rules[rule_idx].cmd_general_data = | |
2475 | ETH_FILTER_RULES_CMD_RX_CMD; | |
2476 | ||
924d75ab YM |
2477 | bnx2x_rx_mode_set_cmd_state_e2(bp, &p->rx_accept_flags, |
2478 | &(data->rules[rule_idx++]), | |
2479 | false); | |
619c5cb6 VZ |
2480 | } |
2481 | ||
16a5fd92 | 2482 | /* If FCoE Queue configuration has been requested configure the Rx and |
619c5cb6 VZ |
2483 | * internal switching modes for this queue in separate rules. |
2484 | * | |
2485 | * FCoE queue shell never be set to ACCEPT_ALL packets of any sort: | |
2486 | * MCAST_ALL, UCAST_ALL, BCAST_ALL and UNMATCHED. | |
2487 | */ | |
2488 | if (test_bit(BNX2X_RX_MODE_FCOE_ETH, &p->rx_mode_flags)) { | |
2489 | /* Tx (internal switching) */ | |
2490 | if (test_bit(RAMROD_TX, &p->ramrod_flags)) { | |
2491 | data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id); | |
2492 | data->rules[rule_idx].func_id = p->func_id; | |
2493 | ||
2494 | data->rules[rule_idx].cmd_general_data = | |
2495 | ETH_FILTER_RULES_CMD_TX_CMD; | |
2496 | ||
924d75ab YM |
2497 | bnx2x_rx_mode_set_cmd_state_e2(bp, &p->tx_accept_flags, |
2498 | &(data->rules[rule_idx]), | |
619c5cb6 | 2499 | true); |
924d75ab | 2500 | rule_idx++; |
619c5cb6 VZ |
2501 | } |
2502 | ||
2503 | /* Rx */ | |
2504 | if (test_bit(RAMROD_RX, &p->ramrod_flags)) { | |
2505 | data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id); | |
2506 | data->rules[rule_idx].func_id = p->func_id; | |
2507 | ||
2508 | data->rules[rule_idx].cmd_general_data = | |
2509 | ETH_FILTER_RULES_CMD_RX_CMD; | |
2510 | ||
924d75ab YM |
2511 | bnx2x_rx_mode_set_cmd_state_e2(bp, &p->rx_accept_flags, |
2512 | &(data->rules[rule_idx]), | |
619c5cb6 | 2513 | true); |
924d75ab | 2514 | rule_idx++; |
619c5cb6 VZ |
2515 | } |
2516 | } | |
2517 | ||
16a5fd92 | 2518 | /* Set the ramrod header (most importantly - number of rules to |
619c5cb6 VZ |
2519 | * configure). |
2520 | */ | |
2521 | bnx2x_rx_mode_set_rdata_hdr_e2(p->cid, &data->header, rule_idx); | |
2522 | ||
51c1a580 | 2523 | DP(BNX2X_MSG_SP, "About to configure %d rules, rx_accept_flags 0x%lx, tx_accept_flags 0x%lx\n", |
619c5cb6 VZ |
2524 | data->header.rule_cnt, p->rx_accept_flags, |
2525 | p->tx_accept_flags); | |
2526 | ||
14a94ebd MK |
2527 | /* No need for an explicit memory barrier here as long as we |
2528 | * ensure the ordering of writing to the SPQ element | |
16a5fd92 | 2529 | * and updating of the SPQ producer which involves a memory |
14a94ebd MK |
2530 | * read. If the memory read is removed we will have to put a |
2531 | * full memory barrier there (inside bnx2x_sp_post()). | |
53e51e2f | 2532 | */ |
619c5cb6 VZ |
2533 | |
2534 | /* Send a ramrod */ | |
2535 | rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_FILTER_RULES, p->cid, | |
2536 | U64_HI(p->rdata_mapping), | |
2537 | U64_LO(p->rdata_mapping), | |
2538 | ETH_CONNECTION_TYPE); | |
2539 | if (rc) | |
2540 | return rc; | |
2541 | ||
2542 | /* Ramrod completion is pending */ | |
2543 | return 1; | |
2544 | } | |
2545 | ||
2546 | static int bnx2x_wait_rx_mode_comp_e2(struct bnx2x *bp, | |
2547 | struct bnx2x_rx_mode_ramrod_params *p) | |
2548 | { | |
2549 | return bnx2x_state_wait(bp, p->state, p->pstate); | |
2550 | } | |
2551 | ||
2552 | static int bnx2x_empty_rx_mode_wait(struct bnx2x *bp, | |
2553 | struct bnx2x_rx_mode_ramrod_params *p) | |
2554 | { | |
2555 | /* Do nothing */ | |
2556 | return 0; | |
2557 | } | |
2558 | ||
2559 | int bnx2x_config_rx_mode(struct bnx2x *bp, | |
2560 | struct bnx2x_rx_mode_ramrod_params *p) | |
2561 | { | |
2562 | int rc; | |
2563 | ||
2564 | /* Configure the new classification in the chip */ | |
2565 | rc = p->rx_mode_obj->config_rx_mode(bp, p); | |
2566 | if (rc < 0) | |
2567 | return rc; | |
2568 | ||
2569 | /* Wait for a ramrod completion if was requested */ | |
2570 | if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) { | |
2571 | rc = p->rx_mode_obj->wait_comp(bp, p); | |
2572 | if (rc) | |
2573 | return rc; | |
2574 | } | |
2575 | ||
2576 | return rc; | |
2577 | } | |
2578 | ||
2579 | void bnx2x_init_rx_mode_obj(struct bnx2x *bp, | |
2580 | struct bnx2x_rx_mode_obj *o) | |
2581 | { | |
2582 | if (CHIP_IS_E1x(bp)) { | |
2583 | o->wait_comp = bnx2x_empty_rx_mode_wait; | |
2584 | o->config_rx_mode = bnx2x_set_rx_mode_e1x; | |
2585 | } else { | |
2586 | o->wait_comp = bnx2x_wait_rx_mode_comp_e2; | |
2587 | o->config_rx_mode = bnx2x_set_rx_mode_e2; | |
2588 | } | |
2589 | } | |
2590 | ||
2591 | /********************* Multicast verbs: SET, CLEAR ****************************/ | |
2592 | static inline u8 bnx2x_mcast_bin_from_mac(u8 *mac) | |
2593 | { | |
2594 | return (crc32c_le(0, mac, ETH_ALEN) >> 24) & 0xff; | |
2595 | } | |
2596 | ||
2597 | struct bnx2x_mcast_mac_elem { | |
2598 | struct list_head link; | |
2599 | u8 mac[ETH_ALEN]; | |
2600 | u8 pad[2]; /* For a natural alignment of the following buffer */ | |
2601 | }; | |
2602 | ||
c7b7b483 YM |
2603 | struct bnx2x_mcast_bin_elem { |
2604 | struct list_head link; | |
2605 | int bin; | |
2606 | int type; /* BNX2X_MCAST_CMD_SET_{ADD, DEL} */ | |
2607 | }; | |
2608 | ||
3129e159 JB |
2609 | union bnx2x_mcast_elem { |
2610 | struct bnx2x_mcast_bin_elem bin_elem; | |
2611 | struct bnx2x_mcast_mac_elem mac_elem; | |
2612 | }; | |
2613 | ||
2614 | struct bnx2x_mcast_elem_group { | |
2615 | struct list_head mcast_group_link; | |
2616 | union bnx2x_mcast_elem mcast_elems[]; | |
2617 | }; | |
2618 | ||
2619 | #define MCAST_MAC_ELEMS_PER_PG \ | |
2620 | ((PAGE_SIZE - sizeof(struct bnx2x_mcast_elem_group)) / \ | |
2621 | sizeof(union bnx2x_mcast_elem)) | |
2622 | ||
619c5cb6 VZ |
2623 | struct bnx2x_pending_mcast_cmd { |
2624 | struct list_head link; | |
3129e159 | 2625 | struct list_head group_head; |
619c5cb6 VZ |
2626 | int type; /* BNX2X_MCAST_CMD_X */ |
2627 | union { | |
2628 | struct list_head macs_head; | |
2629 | u32 macs_num; /* Needed for DEL command */ | |
2630 | int next_bin; /* Needed for RESTORE flow with aprox match */ | |
2631 | } data; | |
2632 | ||
c7b7b483 YM |
2633 | bool set_convert; /* in case type == BNX2X_MCAST_CMD_SET, this is set |
2634 | * when macs_head had been converted to a list of | |
2635 | * bnx2x_mcast_bin_elem. | |
2636 | */ | |
2637 | ||
619c5cb6 VZ |
2638 | bool done; /* set to true, when the command has been handled, |
2639 | * practically used in 57712 handling only, where one pending | |
2640 | * command may be handled in a few operations. As long as for | |
2641 | * other chips every operation handling is completed in a | |
2642 | * single ramrod, there is no need to utilize this field. | |
2643 | */ | |
2644 | }; | |
2645 | ||
2646 | static int bnx2x_mcast_wait(struct bnx2x *bp, | |
2647 | struct bnx2x_mcast_obj *o) | |
2648 | { | |
2649 | if (bnx2x_state_wait(bp, o->sched_state, o->raw.pstate) || | |
2650 | o->raw.wait_comp(bp, &o->raw)) | |
2651 | return -EBUSY; | |
2652 | ||
2653 | return 0; | |
2654 | } | |
2655 | ||
3129e159 JB |
2656 | static void bnx2x_free_groups(struct list_head *mcast_group_list) |
2657 | { | |
2658 | struct bnx2x_mcast_elem_group *current_mcast_group; | |
2659 | ||
2660 | while (!list_empty(mcast_group_list)) { | |
2661 | current_mcast_group = list_first_entry(mcast_group_list, | |
2662 | struct bnx2x_mcast_elem_group, | |
2663 | mcast_group_link); | |
2664 | list_del(¤t_mcast_group->mcast_group_link); | |
2665 | free_page((unsigned long)current_mcast_group); | |
2666 | } | |
2667 | } | |
2668 | ||
619c5cb6 VZ |
2669 | static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp, |
2670 | struct bnx2x_mcast_obj *o, | |
2671 | struct bnx2x_mcast_ramrod_params *p, | |
86564c3f | 2672 | enum bnx2x_mcast_cmd cmd) |
619c5cb6 | 2673 | { |
619c5cb6 | 2674 | struct bnx2x_pending_mcast_cmd *new_cmd; |
619c5cb6 | 2675 | struct bnx2x_mcast_list_elem *pos; |
3129e159 JB |
2676 | struct bnx2x_mcast_elem_group *elem_group; |
2677 | struct bnx2x_mcast_mac_elem *mac_elem; | |
2678 | int total_elems = 0, macs_list_len = 0, offset = 0; | |
c7b7b483 YM |
2679 | |
2680 | /* When adding MACs we'll need to store their values */ | |
2681 | if (cmd == BNX2X_MCAST_CMD_ADD || cmd == BNX2X_MCAST_CMD_SET) | |
2682 | macs_list_len = p->mcast_list_len; | |
619c5cb6 VZ |
2683 | |
2684 | /* If the command is empty ("handle pending commands only"), break */ | |
2685 | if (!p->mcast_list_len) | |
2686 | return 0; | |
2687 | ||
619c5cb6 | 2688 | /* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */ |
3129e159 | 2689 | new_cmd = kzalloc(sizeof(*new_cmd), GFP_ATOMIC); |
619c5cb6 VZ |
2690 | if (!new_cmd) |
2691 | return -ENOMEM; | |
2692 | ||
619c5cb6 | 2693 | INIT_LIST_HEAD(&new_cmd->data.macs_head); |
3129e159 | 2694 | INIT_LIST_HEAD(&new_cmd->group_head); |
619c5cb6 VZ |
2695 | new_cmd->type = cmd; |
2696 | new_cmd->done = false; | |
2697 | ||
3129e159 JB |
2698 | DP(BNX2X_MSG_SP, "About to enqueue a new %d command. macs_list_len=%d\n", |
2699 | cmd, macs_list_len); | |
2700 | ||
619c5cb6 VZ |
2701 | switch (cmd) { |
2702 | case BNX2X_MCAST_CMD_ADD: | |
c7b7b483 | 2703 | case BNX2X_MCAST_CMD_SET: |
3129e159 JB |
2704 | /* For a set command, we need to allocate sufficient memory for |
2705 | * all the bins, since we can't analyze at this point how much | |
2706 | * memory would be required. | |
619c5cb6 | 2707 | */ |
3129e159 JB |
2708 | total_elems = macs_list_len; |
2709 | if (cmd == BNX2X_MCAST_CMD_SET) { | |
2710 | if (total_elems < BNX2X_MCAST_BINS_NUM) | |
2711 | total_elems = BNX2X_MCAST_BINS_NUM; | |
2712 | } | |
2713 | while (total_elems > 0) { | |
2714 | elem_group = (struct bnx2x_mcast_elem_group *) | |
2715 | __get_free_page(GFP_ATOMIC | __GFP_ZERO); | |
2716 | if (!elem_group) { | |
3129e159 | 2717 | bnx2x_free_groups(&new_cmd->group_head); |
e96e0ede | 2718 | kfree(new_cmd); |
3129e159 JB |
2719 | return -ENOMEM; |
2720 | } | |
2721 | total_elems -= MCAST_MAC_ELEMS_PER_PG; | |
2722 | list_add_tail(&elem_group->mcast_group_link, | |
2723 | &new_cmd->group_head); | |
2724 | } | |
2725 | elem_group = list_first_entry(&new_cmd->group_head, | |
2726 | struct bnx2x_mcast_elem_group, | |
2727 | mcast_group_link); | |
619c5cb6 | 2728 | list_for_each_entry(pos, &p->mcast_list, link) { |
3129e159 JB |
2729 | mac_elem = &elem_group->mcast_elems[offset].mac_elem; |
2730 | memcpy(mac_elem->mac, pos->mac, ETH_ALEN); | |
2731 | /* Push the MACs of the current command into the pending | |
2732 | * command MACs list: FIFO | |
2733 | */ | |
2734 | list_add_tail(&mac_elem->link, | |
2735 | &new_cmd->data.macs_head); | |
2736 | offset++; | |
2737 | if (offset == MCAST_MAC_ELEMS_PER_PG) { | |
2738 | offset = 0; | |
2739 | elem_group = list_next_entry(elem_group, | |
2740 | mcast_group_link); | |
2741 | } | |
619c5cb6 | 2742 | } |
619c5cb6 VZ |
2743 | break; |
2744 | ||
2745 | case BNX2X_MCAST_CMD_DEL: | |
2746 | new_cmd->data.macs_num = p->mcast_list_len; | |
2747 | break; | |
2748 | ||
2749 | case BNX2X_MCAST_CMD_RESTORE: | |
2750 | new_cmd->data.next_bin = 0; | |
2751 | break; | |
2752 | ||
2753 | default: | |
8b6d5c09 | 2754 | kfree(new_cmd); |
619c5cb6 VZ |
2755 | BNX2X_ERR("Unknown command: %d\n", cmd); |
2756 | return -EINVAL; | |
2757 | } | |
2758 | ||
2759 | /* Push the new pending command to the tail of the pending list: FIFO */ | |
2760 | list_add_tail(&new_cmd->link, &o->pending_cmds_head); | |
2761 | ||
2762 | o->set_sched(o); | |
2763 | ||
2764 | return 1; | |
2765 | } | |
2766 | ||
2767 | /** | |
2768 | * bnx2x_mcast_get_next_bin - get the next set bin (index) | |
2769 | * | |
2770 | * @o: | |
2771 | * @last: index to start looking from (including) | |
2772 | * | |
2773 | * returns the next found (set) bin or a negative value if none is found. | |
2774 | */ | |
2775 | static inline int bnx2x_mcast_get_next_bin(struct bnx2x_mcast_obj *o, int last) | |
2776 | { | |
2777 | int i, j, inner_start = last % BIT_VEC64_ELEM_SZ; | |
2778 | ||
2779 | for (i = last / BIT_VEC64_ELEM_SZ; i < BNX2X_MCAST_VEC_SZ; i++) { | |
2780 | if (o->registry.aprox_match.vec[i]) | |
2781 | for (j = inner_start; j < BIT_VEC64_ELEM_SZ; j++) { | |
2782 | int cur_bit = j + BIT_VEC64_ELEM_SZ * i; | |
2783 | if (BIT_VEC64_TEST_BIT(o->registry.aprox_match. | |
2784 | vec, cur_bit)) { | |
2785 | return cur_bit; | |
2786 | } | |
2787 | } | |
2788 | inner_start = 0; | |
2789 | } | |
2790 | ||
2791 | /* None found */ | |
2792 | return -1; | |
2793 | } | |
2794 | ||
2795 | /** | |
2796 | * bnx2x_mcast_clear_first_bin - find the first set bin and clear it | |
2797 | * | |
2798 | * @o: | |
2799 | * | |
2800 | * returns the index of the found bin or -1 if none is found | |
2801 | */ | |
2802 | static inline int bnx2x_mcast_clear_first_bin(struct bnx2x_mcast_obj *o) | |
2803 | { | |
2804 | int cur_bit = bnx2x_mcast_get_next_bin(o, 0); | |
2805 | ||
2806 | if (cur_bit >= 0) | |
2807 | BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, cur_bit); | |
2808 | ||
2809 | return cur_bit; | |
2810 | } | |
2811 | ||
2812 | static inline u8 bnx2x_mcast_get_rx_tx_flag(struct bnx2x_mcast_obj *o) | |
2813 | { | |
2814 | struct bnx2x_raw_obj *raw = &o->raw; | |
2815 | u8 rx_tx_flag = 0; | |
2816 | ||
2817 | if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) || | |
2818 | (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX)) | |
2819 | rx_tx_flag |= ETH_MULTICAST_RULES_CMD_TX_CMD; | |
2820 | ||
2821 | if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) || | |
2822 | (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX)) | |
2823 | rx_tx_flag |= ETH_MULTICAST_RULES_CMD_RX_CMD; | |
2824 | ||
2825 | return rx_tx_flag; | |
2826 | } | |
2827 | ||
2828 | static void bnx2x_mcast_set_one_rule_e2(struct bnx2x *bp, | |
2829 | struct bnx2x_mcast_obj *o, int idx, | |
2830 | union bnx2x_mcast_config_data *cfg_data, | |
86564c3f | 2831 | enum bnx2x_mcast_cmd cmd) |
619c5cb6 VZ |
2832 | { |
2833 | struct bnx2x_raw_obj *r = &o->raw; | |
2834 | struct eth_multicast_rules_ramrod_data *data = | |
2835 | (struct eth_multicast_rules_ramrod_data *)(r->rdata); | |
2836 | u8 func_id = r->func_id; | |
2837 | u8 rx_tx_add_flag = bnx2x_mcast_get_rx_tx_flag(o); | |
2838 | int bin; | |
2839 | ||
c7b7b483 YM |
2840 | if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE) || |
2841 | (cmd == BNX2X_MCAST_CMD_SET_ADD)) | |
619c5cb6 VZ |
2842 | rx_tx_add_flag |= ETH_MULTICAST_RULES_CMD_IS_ADD; |
2843 | ||
2844 | data->rules[idx].cmd_general_data |= rx_tx_add_flag; | |
2845 | ||
2846 | /* Get a bin and update a bins' vector */ | |
2847 | switch (cmd) { | |
2848 | case BNX2X_MCAST_CMD_ADD: | |
2849 | bin = bnx2x_mcast_bin_from_mac(cfg_data->mac); | |
2850 | BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin); | |
2851 | break; | |
2852 | ||
2853 | case BNX2X_MCAST_CMD_DEL: | |
2854 | /* If there were no more bins to clear | |
2855 | * (bnx2x_mcast_clear_first_bin() returns -1) then we would | |
2856 | * clear any (0xff) bin. | |
2857 | * See bnx2x_mcast_validate_e2() for explanation when it may | |
2858 | * happen. | |
2859 | */ | |
2860 | bin = bnx2x_mcast_clear_first_bin(o); | |
2861 | break; | |
2862 | ||
2863 | case BNX2X_MCAST_CMD_RESTORE: | |
2864 | bin = cfg_data->bin; | |
2865 | break; | |
2866 | ||
c7b7b483 YM |
2867 | case BNX2X_MCAST_CMD_SET_ADD: |
2868 | bin = cfg_data->bin; | |
2869 | BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin); | |
2870 | break; | |
2871 | ||
2872 | case BNX2X_MCAST_CMD_SET_DEL: | |
2873 | bin = cfg_data->bin; | |
2874 | BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, bin); | |
2875 | break; | |
2876 | ||
619c5cb6 VZ |
2877 | default: |
2878 | BNX2X_ERR("Unknown command: %d\n", cmd); | |
2879 | return; | |
2880 | } | |
2881 | ||
2882 | DP(BNX2X_MSG_SP, "%s bin %d\n", | |
2883 | ((rx_tx_add_flag & ETH_MULTICAST_RULES_CMD_IS_ADD) ? | |
2884 | "Setting" : "Clearing"), bin); | |
2885 | ||
2886 | data->rules[idx].bin_id = (u8)bin; | |
2887 | data->rules[idx].func_id = func_id; | |
2888 | data->rules[idx].engine_id = o->engine_id; | |
2889 | } | |
2890 | ||
2891 | /** | |
2892 | * bnx2x_mcast_handle_restore_cmd_e2 - restore configuration from the registry | |
2893 | * | |
2894 | * @bp: device handle | |
2895 | * @o: | |
2896 | * @start_bin: index in the registry to start from (including) | |
2897 | * @rdata_idx: index in the ramrod data to start from | |
2898 | * | |
2899 | * returns last handled bin index or -1 if all bins have been handled | |
2900 | */ | |
2901 | static inline int bnx2x_mcast_handle_restore_cmd_e2( | |
2902 | struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_bin, | |
2903 | int *rdata_idx) | |
2904 | { | |
2905 | int cur_bin, cnt = *rdata_idx; | |
86564c3f | 2906 | union bnx2x_mcast_config_data cfg_data = {NULL}; |
619c5cb6 VZ |
2907 | |
2908 | /* go through the registry and configure the bins from it */ | |
2909 | for (cur_bin = bnx2x_mcast_get_next_bin(o, start_bin); cur_bin >= 0; | |
2910 | cur_bin = bnx2x_mcast_get_next_bin(o, cur_bin + 1)) { | |
2911 | ||
2912 | cfg_data.bin = (u8)cur_bin; | |
2913 | o->set_one_rule(bp, o, cnt, &cfg_data, | |
2914 | BNX2X_MCAST_CMD_RESTORE); | |
2915 | ||
2916 | cnt++; | |
2917 | ||
2918 | DP(BNX2X_MSG_SP, "About to configure a bin %d\n", cur_bin); | |
2919 | ||
2920 | /* Break if we reached the maximum number | |
2921 | * of rules. | |
2922 | */ | |
2923 | if (cnt >= o->max_cmd_len) | |
2924 | break; | |
2925 | } | |
2926 | ||
2927 | *rdata_idx = cnt; | |
2928 | ||
2929 | return cur_bin; | |
2930 | } | |
2931 | ||
2932 | static inline void bnx2x_mcast_hdl_pending_add_e2(struct bnx2x *bp, | |
2933 | struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos, | |
2934 | int *line_idx) | |
2935 | { | |
2936 | struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n; | |
2937 | int cnt = *line_idx; | |
86564c3f | 2938 | union bnx2x_mcast_config_data cfg_data = {NULL}; |
619c5cb6 VZ |
2939 | |
2940 | list_for_each_entry_safe(pmac_pos, pmac_pos_n, &cmd_pos->data.macs_head, | |
2941 | link) { | |
2942 | ||
2943 | cfg_data.mac = &pmac_pos->mac[0]; | |
2944 | o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type); | |
2945 | ||
2946 | cnt++; | |
2947 | ||
0f9dad10 | 2948 | DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n", |
51c1a580 | 2949 | pmac_pos->mac); |
619c5cb6 VZ |
2950 | |
2951 | list_del(&pmac_pos->link); | |
2952 | ||
2953 | /* Break if we reached the maximum number | |
2954 | * of rules. | |
2955 | */ | |
2956 | if (cnt >= o->max_cmd_len) | |
2957 | break; | |
2958 | } | |
2959 | ||
2960 | *line_idx = cnt; | |
2961 | ||
2962 | /* if no more MACs to configure - we are done */ | |
2963 | if (list_empty(&cmd_pos->data.macs_head)) | |
2964 | cmd_pos->done = true; | |
2965 | } | |
2966 | ||
2967 | static inline void bnx2x_mcast_hdl_pending_del_e2(struct bnx2x *bp, | |
2968 | struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos, | |
2969 | int *line_idx) | |
2970 | { | |
2971 | int cnt = *line_idx; | |
2972 | ||
2973 | while (cmd_pos->data.macs_num) { | |
2974 | o->set_one_rule(bp, o, cnt, NULL, cmd_pos->type); | |
2975 | ||
2976 | cnt++; | |
2977 | ||
2978 | cmd_pos->data.macs_num--; | |
2979 | ||
2980 | DP(BNX2X_MSG_SP, "Deleting MAC. %d left,cnt is %d\n", | |
2981 | cmd_pos->data.macs_num, cnt); | |
2982 | ||
2983 | /* Break if we reached the maximum | |
2984 | * number of rules. | |
2985 | */ | |
2986 | if (cnt >= o->max_cmd_len) | |
2987 | break; | |
2988 | } | |
2989 | ||
2990 | *line_idx = cnt; | |
2991 | ||
2992 | /* If we cleared all bins - we are done */ | |
2993 | if (!cmd_pos->data.macs_num) | |
2994 | cmd_pos->done = true; | |
2995 | } | |
2996 | ||
2997 | static inline void bnx2x_mcast_hdl_pending_restore_e2(struct bnx2x *bp, | |
2998 | struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos, | |
2999 | int *line_idx) | |
3000 | { | |
3001 | cmd_pos->data.next_bin = o->hdl_restore(bp, o, cmd_pos->data.next_bin, | |
3002 | line_idx); | |
3003 | ||
3004 | if (cmd_pos->data.next_bin < 0) | |
3005 | /* If o->set_restore returned -1 we are done */ | |
3006 | cmd_pos->done = true; | |
3007 | else | |
3008 | /* Start from the next bin next time */ | |
3009 | cmd_pos->data.next_bin++; | |
3010 | } | |
3011 | ||
c7b7b483 YM |
3012 | static void |
3013 | bnx2x_mcast_hdl_pending_set_e2_convert(struct bnx2x *bp, | |
3014 | struct bnx2x_mcast_obj *o, | |
3015 | struct bnx2x_pending_mcast_cmd *cmd_pos) | |
3016 | { | |
3017 | u64 cur[BNX2X_MCAST_VEC_SZ], req[BNX2X_MCAST_VEC_SZ]; | |
3018 | struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n; | |
3019 | struct bnx2x_mcast_bin_elem *p_item; | |
3129e159 JB |
3020 | struct bnx2x_mcast_elem_group *elem_group; |
3021 | int cnt = 0, mac_cnt = 0, offset = 0, i; | |
c7b7b483 YM |
3022 | |
3023 | memset(req, 0, sizeof(u64) * BNX2X_MCAST_VEC_SZ); | |
3024 | memcpy(cur, o->registry.aprox_match.vec, | |
3025 | sizeof(u64) * BNX2X_MCAST_VEC_SZ); | |
3026 | ||
3027 | /* Fill `current' with the required set of bins to configure */ | |
3028 | list_for_each_entry_safe(pmac_pos, pmac_pos_n, &cmd_pos->data.macs_head, | |
3029 | link) { | |
3030 | int bin = bnx2x_mcast_bin_from_mac(pmac_pos->mac); | |
3031 | ||
3032 | DP(BNX2X_MSG_SP, "Set contains %pM mcast MAC\n", | |
3033 | pmac_pos->mac); | |
3034 | ||
3035 | BIT_VEC64_SET_BIT(req, bin); | |
3036 | list_del(&pmac_pos->link); | |
3037 | mac_cnt++; | |
3038 | } | |
3039 | ||
3040 | /* We no longer have use for the MACs; Need to re-use memory for | |
3041 | * a list that will be used to configure bins. | |
3042 | */ | |
3043 | cmd_pos->set_convert = true; | |
c7b7b483 | 3044 | INIT_LIST_HEAD(&cmd_pos->data.macs_head); |
3129e159 JB |
3045 | elem_group = list_first_entry(&cmd_pos->group_head, |
3046 | struct bnx2x_mcast_elem_group, | |
3047 | mcast_group_link); | |
c7b7b483 YM |
3048 | for (i = 0; i < BNX2X_MCAST_BINS_NUM; i++) { |
3049 | bool b_current = !!BIT_VEC64_TEST_BIT(cur, i); | |
3050 | bool b_required = !!BIT_VEC64_TEST_BIT(req, i); | |
3051 | ||
3052 | if (b_current == b_required) | |
3053 | continue; | |
3054 | ||
3129e159 | 3055 | p_item = &elem_group->mcast_elems[offset].bin_elem; |
c7b7b483 YM |
3056 | p_item->bin = i; |
3057 | p_item->type = b_required ? BNX2X_MCAST_CMD_SET_ADD | |
3058 | : BNX2X_MCAST_CMD_SET_DEL; | |
3059 | list_add_tail(&p_item->link , &cmd_pos->data.macs_head); | |
c7b7b483 | 3060 | cnt++; |
3129e159 JB |
3061 | offset++; |
3062 | if (offset == MCAST_MAC_ELEMS_PER_PG) { | |
3063 | offset = 0; | |
3064 | elem_group = list_next_entry(elem_group, | |
3065 | mcast_group_link); | |
3066 | } | |
c7b7b483 YM |
3067 | } |
3068 | ||
3069 | /* We now definitely know how many commands are hiding here. | |
3070 | * Also need to correct the disruption we've added to guarantee this | |
3071 | * would be enqueued. | |
3072 | */ | |
3073 | o->total_pending_num -= (o->max_cmd_len + mac_cnt); | |
3074 | o->total_pending_num += cnt; | |
3075 | ||
3076 | DP(BNX2X_MSG_SP, "o->total_pending_num=%d\n", o->total_pending_num); | |
3077 | } | |
3078 | ||
3079 | static void | |
3080 | bnx2x_mcast_hdl_pending_set_e2(struct bnx2x *bp, | |
3081 | struct bnx2x_mcast_obj *o, | |
3082 | struct bnx2x_pending_mcast_cmd *cmd_pos, | |
3083 | int *cnt) | |
3084 | { | |
3085 | union bnx2x_mcast_config_data cfg_data = {NULL}; | |
3086 | struct bnx2x_mcast_bin_elem *p_item, *p_item_n; | |
3087 | ||
3088 | /* This is actually a 2-part scheme - it starts by converting the MACs | |
3089 | * into a list of bins to be added/removed, and correcting the numbers | |
3090 | * on the object. this is now allowed, as we're now sure that all | |
3091 | * previous configured requests have already applied. | |
3092 | * The second part is actually adding rules for the newly introduced | |
3093 | * entries [like all the rest of the hdl_pending functions]. | |
3094 | */ | |
3095 | if (!cmd_pos->set_convert) | |
3096 | bnx2x_mcast_hdl_pending_set_e2_convert(bp, o, cmd_pos); | |
3097 | ||
3098 | list_for_each_entry_safe(p_item, p_item_n, &cmd_pos->data.macs_head, | |
3099 | link) { | |
3100 | cfg_data.bin = (u8)p_item->bin; | |
3101 | o->set_one_rule(bp, o, *cnt, &cfg_data, p_item->type); | |
3102 | (*cnt)++; | |
3103 | ||
3104 | list_del(&p_item->link); | |
3105 | ||
3106 | /* Break if we reached the maximum number of rules. */ | |
3107 | if (*cnt >= o->max_cmd_len) | |
3108 | break; | |
3109 | } | |
3110 | ||
3111 | /* if no more MACs to configure - we are done */ | |
3112 | if (list_empty(&cmd_pos->data.macs_head)) | |
3113 | cmd_pos->done = true; | |
3114 | } | |
3115 | ||
619c5cb6 VZ |
3116 | static inline int bnx2x_mcast_handle_pending_cmds_e2(struct bnx2x *bp, |
3117 | struct bnx2x_mcast_ramrod_params *p) | |
3118 | { | |
3119 | struct bnx2x_pending_mcast_cmd *cmd_pos, *cmd_pos_n; | |
3120 | int cnt = 0; | |
3121 | struct bnx2x_mcast_obj *o = p->mcast_obj; | |
3122 | ||
3123 | list_for_each_entry_safe(cmd_pos, cmd_pos_n, &o->pending_cmds_head, | |
3124 | link) { | |
3125 | switch (cmd_pos->type) { | |
3126 | case BNX2X_MCAST_CMD_ADD: | |
3127 | bnx2x_mcast_hdl_pending_add_e2(bp, o, cmd_pos, &cnt); | |
3128 | break; | |
3129 | ||
3130 | case BNX2X_MCAST_CMD_DEL: | |
3131 | bnx2x_mcast_hdl_pending_del_e2(bp, o, cmd_pos, &cnt); | |
3132 | break; | |
3133 | ||
3134 | case BNX2X_MCAST_CMD_RESTORE: | |
3135 | bnx2x_mcast_hdl_pending_restore_e2(bp, o, cmd_pos, | |
3136 | &cnt); | |
3137 | break; | |
3138 | ||
c7b7b483 YM |
3139 | case BNX2X_MCAST_CMD_SET: |
3140 | bnx2x_mcast_hdl_pending_set_e2(bp, o, cmd_pos, &cnt); | |
3141 | break; | |
3142 | ||
619c5cb6 VZ |
3143 | default: |
3144 | BNX2X_ERR("Unknown command: %d\n", cmd_pos->type); | |
3145 | return -EINVAL; | |
3146 | } | |
3147 | ||
3148 | /* If the command has been completed - remove it from the list | |
3149 | * and free the memory | |
3150 | */ | |
3151 | if (cmd_pos->done) { | |
3152 | list_del(&cmd_pos->link); | |
3129e159 | 3153 | bnx2x_free_groups(&cmd_pos->group_head); |
619c5cb6 VZ |
3154 | kfree(cmd_pos); |
3155 | } | |
3156 | ||
3157 | /* Break if we reached the maximum number of rules */ | |
3158 | if (cnt >= o->max_cmd_len) | |
3159 | break; | |
3160 | } | |
3161 | ||
3162 | return cnt; | |
3163 | } | |
3164 | ||
3165 | static inline void bnx2x_mcast_hdl_add(struct bnx2x *bp, | |
3166 | struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p, | |
3167 | int *line_idx) | |
3168 | { | |
3169 | struct bnx2x_mcast_list_elem *mlist_pos; | |
86564c3f | 3170 | union bnx2x_mcast_config_data cfg_data = {NULL}; |
619c5cb6 VZ |
3171 | int cnt = *line_idx; |
3172 | ||
3173 | list_for_each_entry(mlist_pos, &p->mcast_list, link) { | |
3174 | cfg_data.mac = mlist_pos->mac; | |
3175 | o->set_one_rule(bp, o, cnt, &cfg_data, BNX2X_MCAST_CMD_ADD); | |
3176 | ||
3177 | cnt++; | |
3178 | ||
0f9dad10 | 3179 | DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n", |
2de67439 | 3180 | mlist_pos->mac); |
619c5cb6 VZ |
3181 | } |
3182 | ||
3183 | *line_idx = cnt; | |
3184 | } | |
3185 | ||
3186 | static inline void bnx2x_mcast_hdl_del(struct bnx2x *bp, | |
3187 | struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p, | |
3188 | int *line_idx) | |
3189 | { | |
3190 | int cnt = *line_idx, i; | |
3191 | ||
3192 | for (i = 0; i < p->mcast_list_len; i++) { | |
3193 | o->set_one_rule(bp, o, cnt, NULL, BNX2X_MCAST_CMD_DEL); | |
3194 | ||
3195 | cnt++; | |
3196 | ||
3197 | DP(BNX2X_MSG_SP, "Deleting MAC. %d left\n", | |
3198 | p->mcast_list_len - i - 1); | |
3199 | } | |
3200 | ||
3201 | *line_idx = cnt; | |
3202 | } | |
3203 | ||
3204 | /** | |
3205 | * bnx2x_mcast_handle_current_cmd - | |
3206 | * | |
3207 | * @bp: device handle | |
3208 | * @p: | |
3209 | * @cmd: | |
3210 | * @start_cnt: first line in the ramrod data that may be used | |
3211 | * | |
3212 | * This function is called iff there is enough place for the current command in | |
3213 | * the ramrod data. | |
3214 | * Returns number of lines filled in the ramrod data in total. | |
3215 | */ | |
3216 | static inline int bnx2x_mcast_handle_current_cmd(struct bnx2x *bp, | |
86564c3f YM |
3217 | struct bnx2x_mcast_ramrod_params *p, |
3218 | enum bnx2x_mcast_cmd cmd, | |
619c5cb6 VZ |
3219 | int start_cnt) |
3220 | { | |
3221 | struct bnx2x_mcast_obj *o = p->mcast_obj; | |
3222 | int cnt = start_cnt; | |
3223 | ||
3224 | DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len); | |
3225 | ||
3226 | switch (cmd) { | |
3227 | case BNX2X_MCAST_CMD_ADD: | |
3228 | bnx2x_mcast_hdl_add(bp, o, p, &cnt); | |
3229 | break; | |
3230 | ||
3231 | case BNX2X_MCAST_CMD_DEL: | |
3232 | bnx2x_mcast_hdl_del(bp, o, p, &cnt); | |
3233 | break; | |
3234 | ||
3235 | case BNX2X_MCAST_CMD_RESTORE: | |
3236 | o->hdl_restore(bp, o, 0, &cnt); | |
3237 | break; | |
3238 | ||
3239 | default: | |
3240 | BNX2X_ERR("Unknown command: %d\n", cmd); | |
3241 | return -EINVAL; | |
3242 | } | |
3243 | ||
3244 | /* The current command has been handled */ | |
3245 | p->mcast_list_len = 0; | |
3246 | ||
3247 | return cnt; | |
3248 | } | |
3249 | ||
3250 | static int bnx2x_mcast_validate_e2(struct bnx2x *bp, | |
3251 | struct bnx2x_mcast_ramrod_params *p, | |
86564c3f | 3252 | enum bnx2x_mcast_cmd cmd) |
619c5cb6 VZ |
3253 | { |
3254 | struct bnx2x_mcast_obj *o = p->mcast_obj; | |
3255 | int reg_sz = o->get_registry_size(o); | |
3256 | ||
3257 | switch (cmd) { | |
3258 | /* DEL command deletes all currently configured MACs */ | |
3259 | case BNX2X_MCAST_CMD_DEL: | |
3260 | o->set_registry_size(o, 0); | |
83607344 | 3261 | /* fall through */ |
619c5cb6 VZ |
3262 | |
3263 | /* RESTORE command will restore the entire multicast configuration */ | |
3264 | case BNX2X_MCAST_CMD_RESTORE: | |
3265 | /* Here we set the approximate amount of work to do, which in | |
3266 | * fact may be only less as some MACs in postponed ADD | |
3267 | * command(s) scheduled before this command may fall into | |
3268 | * the same bin and the actual number of bins set in the | |
3269 | * registry would be less than we estimated here. See | |
3270 | * bnx2x_mcast_set_one_rule_e2() for further details. | |
3271 | */ | |
3272 | p->mcast_list_len = reg_sz; | |
3273 | break; | |
3274 | ||
3275 | case BNX2X_MCAST_CMD_ADD: | |
3276 | case BNX2X_MCAST_CMD_CONT: | |
3277 | /* Here we assume that all new MACs will fall into new bins. | |
3278 | * However we will correct the real registry size after we | |
3279 | * handle all pending commands. | |
3280 | */ | |
3281 | o->set_registry_size(o, reg_sz + p->mcast_list_len); | |
3282 | break; | |
3283 | ||
c7b7b483 YM |
3284 | case BNX2X_MCAST_CMD_SET: |
3285 | /* We can only learn how many commands would actually be used | |
3286 | * when this is being configured. So for now, simply guarantee | |
3287 | * the command will be enqueued [to refrain from adding logic | |
3288 | * that handles this and THEN learns it needs several ramrods]. | |
3289 | * Just like for ADD/Cont, the mcast_list_len might be an over | |
3290 | * estimation; or even more so, since we don't take into | |
3291 | * account the possibility of removal of existing bins. | |
3292 | */ | |
3293 | o->set_registry_size(o, reg_sz + p->mcast_list_len); | |
3294 | o->total_pending_num += o->max_cmd_len; | |
3295 | break; | |
3296 | ||
619c5cb6 VZ |
3297 | default: |
3298 | BNX2X_ERR("Unknown command: %d\n", cmd); | |
3299 | return -EINVAL; | |
619c5cb6 VZ |
3300 | } |
3301 | ||
3302 | /* Increase the total number of MACs pending to be configured */ | |
3303 | o->total_pending_num += p->mcast_list_len; | |
3304 | ||
3305 | return 0; | |
3306 | } | |
3307 | ||
3308 | static void bnx2x_mcast_revert_e2(struct bnx2x *bp, | |
3309 | struct bnx2x_mcast_ramrod_params *p, | |
c7b7b483 YM |
3310 | int old_num_bins, |
3311 | enum bnx2x_mcast_cmd cmd) | |
619c5cb6 VZ |
3312 | { |
3313 | struct bnx2x_mcast_obj *o = p->mcast_obj; | |
3314 | ||
3315 | o->set_registry_size(o, old_num_bins); | |
3316 | o->total_pending_num -= p->mcast_list_len; | |
c7b7b483 YM |
3317 | |
3318 | if (cmd == BNX2X_MCAST_CMD_SET) | |
3319 | o->total_pending_num -= o->max_cmd_len; | |
619c5cb6 VZ |
3320 | } |
3321 | ||
3322 | /** | |
3323 | * bnx2x_mcast_set_rdata_hdr_e2 - sets a header values | |
3324 | * | |
3325 | * @bp: device handle | |
3326 | * @p: | |
3327 | * @len: number of rules to handle | |
3328 | */ | |
3329 | static inline void bnx2x_mcast_set_rdata_hdr_e2(struct bnx2x *bp, | |
3330 | struct bnx2x_mcast_ramrod_params *p, | |
3331 | u8 len) | |
3332 | { | |
3333 | struct bnx2x_raw_obj *r = &p->mcast_obj->raw; | |
3334 | struct eth_multicast_rules_ramrod_data *data = | |
3335 | (struct eth_multicast_rules_ramrod_data *)(r->rdata); | |
3336 | ||
86564c3f YM |
3337 | data->header.echo = cpu_to_le32((r->cid & BNX2X_SWCID_MASK) | |
3338 | (BNX2X_FILTER_MCAST_PENDING << | |
3339 | BNX2X_SWCID_SHIFT)); | |
619c5cb6 VZ |
3340 | data->header.rule_cnt = len; |
3341 | } | |
3342 | ||
3343 | /** | |
3344 | * bnx2x_mcast_refresh_registry_e2 - recalculate the actual number of set bins | |
3345 | * | |
3346 | * @bp: device handle | |
3347 | * @o: | |
3348 | * | |
3349 | * Recalculate the actual number of set bins in the registry using Brian | |
3350 | * Kernighan's algorithm: it's execution complexity is as a number of set bins. | |
3351 | * | |
3352 | * returns 0 for the compliance with bnx2x_mcast_refresh_registry_e1(). | |
3353 | */ | |
3354 | static inline int bnx2x_mcast_refresh_registry_e2(struct bnx2x *bp, | |
3355 | struct bnx2x_mcast_obj *o) | |
3356 | { | |
3357 | int i, cnt = 0; | |
3358 | u64 elem; | |
3359 | ||
3360 | for (i = 0; i < BNX2X_MCAST_VEC_SZ; i++) { | |
3361 | elem = o->registry.aprox_match.vec[i]; | |
3362 | for (; elem; cnt++) | |
3363 | elem &= elem - 1; | |
3364 | } | |
3365 | ||
3366 | o->set_registry_size(o, cnt); | |
3367 | ||
3368 | return 0; | |
3369 | } | |
3370 | ||
3371 | static int bnx2x_mcast_setup_e2(struct bnx2x *bp, | |
3372 | struct bnx2x_mcast_ramrod_params *p, | |
86564c3f | 3373 | enum bnx2x_mcast_cmd cmd) |
619c5cb6 VZ |
3374 | { |
3375 | struct bnx2x_raw_obj *raw = &p->mcast_obj->raw; | |
3376 | struct bnx2x_mcast_obj *o = p->mcast_obj; | |
3377 | struct eth_multicast_rules_ramrod_data *data = | |
3378 | (struct eth_multicast_rules_ramrod_data *)(raw->rdata); | |
3379 | int cnt = 0, rc; | |
3380 | ||
3381 | /* Reset the ramrod data buffer */ | |
3382 | memset(data, 0, sizeof(*data)); | |
3383 | ||
3384 | cnt = bnx2x_mcast_handle_pending_cmds_e2(bp, p); | |
3385 | ||
3386 | /* If there are no more pending commands - clear SCHEDULED state */ | |
3387 | if (list_empty(&o->pending_cmds_head)) | |
3388 | o->clear_sched(o); | |
3389 | ||
3390 | /* The below may be true iff there was enough room in ramrod | |
3391 | * data for all pending commands and for the current | |
3392 | * command. Otherwise the current command would have been added | |
3393 | * to the pending commands and p->mcast_list_len would have been | |
3394 | * zeroed. | |
3395 | */ | |
3396 | if (p->mcast_list_len > 0) | |
3397 | cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, cnt); | |
3398 | ||
3399 | /* We've pulled out some MACs - update the total number of | |
3400 | * outstanding. | |
3401 | */ | |
3402 | o->total_pending_num -= cnt; | |
3403 | ||
3404 | /* send a ramrod */ | |
3405 | WARN_ON(o->total_pending_num < 0); | |
3406 | WARN_ON(cnt > o->max_cmd_len); | |
3407 | ||
3408 | bnx2x_mcast_set_rdata_hdr_e2(bp, p, (u8)cnt); | |
3409 | ||
3410 | /* Update a registry size if there are no more pending operations. | |
3411 | * | |
3412 | * We don't want to change the value of the registry size if there are | |
3413 | * pending operations because we want it to always be equal to the | |
3414 | * exact or the approximate number (see bnx2x_mcast_validate_e2()) of | |
3415 | * set bins after the last requested operation in order to properly | |
3416 | * evaluate the size of the next DEL/RESTORE operation. | |
3417 | * | |
3418 | * Note that we update the registry itself during command(s) handling | |
3419 | * - see bnx2x_mcast_set_one_rule_e2(). That's because for 57712 we | |
3420 | * aggregate multiple commands (ADD/DEL/RESTORE) into one ramrod but | |
3421 | * with a limited amount of update commands (per MAC/bin) and we don't | |
3422 | * know in this scope what the actual state of bins configuration is | |
3423 | * going to be after this ramrod. | |
3424 | */ | |
3425 | if (!o->total_pending_num) | |
3426 | bnx2x_mcast_refresh_registry_e2(bp, o); | |
3427 | ||
16a5fd92 | 3428 | /* If CLEAR_ONLY was requested - don't send a ramrod and clear |
c7b7b483 YM |
3429 | * RAMROD_PENDING status immediately. due to the SET option, it's also |
3430 | * possible that after evaluating the differences there's no need for | |
3431 | * a ramrod. In that case, we can skip it as well. | |
619c5cb6 | 3432 | */ |
c7b7b483 | 3433 | if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags) || !cnt) { |
619c5cb6 VZ |
3434 | raw->clear_pending(raw); |
3435 | return 0; | |
3436 | } else { | |
14a94ebd MK |
3437 | /* No need for an explicit memory barrier here as long as we |
3438 | * ensure the ordering of writing to the SPQ element | |
16a5fd92 | 3439 | * and updating of the SPQ producer which involves a memory |
14a94ebd MK |
3440 | * read. If the memory read is removed we will have to put a |
3441 | * full memory barrier there (inside bnx2x_sp_post()). | |
53e51e2f VZ |
3442 | */ |
3443 | ||
619c5cb6 VZ |
3444 | /* Send a ramrod */ |
3445 | rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_MULTICAST_RULES, | |
3446 | raw->cid, U64_HI(raw->rdata_mapping), | |
3447 | U64_LO(raw->rdata_mapping), | |
3448 | ETH_CONNECTION_TYPE); | |
3449 | if (rc) | |
3450 | return rc; | |
3451 | ||
3452 | /* Ramrod completion is pending */ | |
3453 | return 1; | |
3454 | } | |
3455 | } | |
3456 | ||
3457 | static int bnx2x_mcast_validate_e1h(struct bnx2x *bp, | |
3458 | struct bnx2x_mcast_ramrod_params *p, | |
86564c3f | 3459 | enum bnx2x_mcast_cmd cmd) |
619c5cb6 | 3460 | { |
c7b7b483 YM |
3461 | if (cmd == BNX2X_MCAST_CMD_SET) { |
3462 | BNX2X_ERR("Can't use `set' command on e1h!\n"); | |
3463 | return -EINVAL; | |
3464 | } | |
3465 | ||
619c5cb6 VZ |
3466 | /* Mark, that there is a work to do */ |
3467 | if ((cmd == BNX2X_MCAST_CMD_DEL) || (cmd == BNX2X_MCAST_CMD_RESTORE)) | |
3468 | p->mcast_list_len = 1; | |
3469 | ||
3470 | return 0; | |
3471 | } | |
3472 | ||
3473 | static void bnx2x_mcast_revert_e1h(struct bnx2x *bp, | |
3474 | struct bnx2x_mcast_ramrod_params *p, | |
c7b7b483 YM |
3475 | int old_num_bins, |
3476 | enum bnx2x_mcast_cmd cmd) | |
619c5cb6 VZ |
3477 | { |
3478 | /* Do nothing */ | |
3479 | } | |
3480 | ||
3481 | #define BNX2X_57711_SET_MC_FILTER(filter, bit) \ | |
3482 | do { \ | |
3483 | (filter)[(bit) >> 5] |= (1 << ((bit) & 0x1f)); \ | |
3484 | } while (0) | |
3485 | ||
3486 | static inline void bnx2x_mcast_hdl_add_e1h(struct bnx2x *bp, | |
3487 | struct bnx2x_mcast_obj *o, | |
3488 | struct bnx2x_mcast_ramrod_params *p, | |
3489 | u32 *mc_filter) | |
3490 | { | |
3491 | struct bnx2x_mcast_list_elem *mlist_pos; | |
3492 | int bit; | |
3493 | ||
3494 | list_for_each_entry(mlist_pos, &p->mcast_list, link) { | |
3495 | bit = bnx2x_mcast_bin_from_mac(mlist_pos->mac); | |
3496 | BNX2X_57711_SET_MC_FILTER(mc_filter, bit); | |
3497 | ||
0f9dad10 | 3498 | DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC, bin %d\n", |
2de67439 | 3499 | mlist_pos->mac, bit); |
619c5cb6 VZ |
3500 | |
3501 | /* bookkeeping... */ | |
3502 | BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, | |
3503 | bit); | |
3504 | } | |
3505 | } | |
3506 | ||
3507 | static inline void bnx2x_mcast_hdl_restore_e1h(struct bnx2x *bp, | |
3508 | struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p, | |
3509 | u32 *mc_filter) | |
3510 | { | |
3511 | int bit; | |
3512 | ||
3513 | for (bit = bnx2x_mcast_get_next_bin(o, 0); | |
3514 | bit >= 0; | |
3515 | bit = bnx2x_mcast_get_next_bin(o, bit + 1)) { | |
3516 | BNX2X_57711_SET_MC_FILTER(mc_filter, bit); | |
3517 | DP(BNX2X_MSG_SP, "About to set bin %d\n", bit); | |
3518 | } | |
3519 | } | |
3520 | ||
16a5fd92 | 3521 | /* On 57711 we write the multicast MACs' approximate match |
619c5cb6 VZ |
3522 | * table by directly into the TSTORM's internal RAM. So we don't |
3523 | * really need to handle any tricks to make it work. | |
3524 | */ | |
3525 | static int bnx2x_mcast_setup_e1h(struct bnx2x *bp, | |
3526 | struct bnx2x_mcast_ramrod_params *p, | |
86564c3f | 3527 | enum bnx2x_mcast_cmd cmd) |
619c5cb6 VZ |
3528 | { |
3529 | int i; | |
3530 | struct bnx2x_mcast_obj *o = p->mcast_obj; | |
3531 | struct bnx2x_raw_obj *r = &o->raw; | |
3532 | ||
3533 | /* If CLEAR_ONLY has been requested - clear the registry | |
3534 | * and clear a pending bit. | |
3535 | */ | |
3536 | if (!test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) { | |
3537 | u32 mc_filter[MC_HASH_SIZE] = {0}; | |
3538 | ||
3539 | /* Set the multicast filter bits before writing it into | |
3540 | * the internal memory. | |
3541 | */ | |
3542 | switch (cmd) { | |
3543 | case BNX2X_MCAST_CMD_ADD: | |
3544 | bnx2x_mcast_hdl_add_e1h(bp, o, p, mc_filter); | |
3545 | break; | |
3546 | ||
3547 | case BNX2X_MCAST_CMD_DEL: | |
94f05b0f JP |
3548 | DP(BNX2X_MSG_SP, |
3549 | "Invalidating multicast MACs configuration\n"); | |
619c5cb6 VZ |
3550 | |
3551 | /* clear the registry */ | |
3552 | memset(o->registry.aprox_match.vec, 0, | |
3553 | sizeof(o->registry.aprox_match.vec)); | |
3554 | break; | |
3555 | ||
3556 | case BNX2X_MCAST_CMD_RESTORE: | |
3557 | bnx2x_mcast_hdl_restore_e1h(bp, o, p, mc_filter); | |
3558 | break; | |
3559 | ||
3560 | default: | |
3561 | BNX2X_ERR("Unknown command: %d\n", cmd); | |
3562 | return -EINVAL; | |
3563 | } | |
3564 | ||
3565 | /* Set the mcast filter in the internal memory */ | |
3566 | for (i = 0; i < MC_HASH_SIZE; i++) | |
3567 | REG_WR(bp, MC_HASH_OFFSET(bp, i), mc_filter[i]); | |
3568 | } else | |
3569 | /* clear the registry */ | |
3570 | memset(o->registry.aprox_match.vec, 0, | |
3571 | sizeof(o->registry.aprox_match.vec)); | |
3572 | ||
3573 | /* We are done */ | |
3574 | r->clear_pending(r); | |
3575 | ||
3576 | return 0; | |
3577 | } | |
3578 | ||
3579 | static int bnx2x_mcast_validate_e1(struct bnx2x *bp, | |
3580 | struct bnx2x_mcast_ramrod_params *p, | |
86564c3f | 3581 | enum bnx2x_mcast_cmd cmd) |
619c5cb6 VZ |
3582 | { |
3583 | struct bnx2x_mcast_obj *o = p->mcast_obj; | |
3584 | int reg_sz = o->get_registry_size(o); | |
3585 | ||
c7b7b483 YM |
3586 | if (cmd == BNX2X_MCAST_CMD_SET) { |
3587 | BNX2X_ERR("Can't use `set' command on e1!\n"); | |
3588 | return -EINVAL; | |
3589 | } | |
3590 | ||
619c5cb6 VZ |
3591 | switch (cmd) { |
3592 | /* DEL command deletes all currently configured MACs */ | |
3593 | case BNX2X_MCAST_CMD_DEL: | |
3594 | o->set_registry_size(o, 0); | |
83607344 | 3595 | /* fall through */ |
619c5cb6 VZ |
3596 | |
3597 | /* RESTORE command will restore the entire multicast configuration */ | |
3598 | case BNX2X_MCAST_CMD_RESTORE: | |
3599 | p->mcast_list_len = reg_sz; | |
3600 | DP(BNX2X_MSG_SP, "Command %d, p->mcast_list_len=%d\n", | |
3601 | cmd, p->mcast_list_len); | |
3602 | break; | |
3603 | ||
3604 | case BNX2X_MCAST_CMD_ADD: | |
3605 | case BNX2X_MCAST_CMD_CONT: | |
3606 | /* Multicast MACs on 57710 are configured as unicast MACs and | |
3607 | * there is only a limited number of CAM entries for that | |
3608 | * matter. | |
3609 | */ | |
3610 | if (p->mcast_list_len > o->max_cmd_len) { | |
51c1a580 MS |
3611 | BNX2X_ERR("Can't configure more than %d multicast MACs on 57710\n", |
3612 | o->max_cmd_len); | |
619c5cb6 VZ |
3613 | return -EINVAL; |
3614 | } | |
3615 | /* Every configured MAC should be cleared if DEL command is | |
3616 | * called. Only the last ADD command is relevant as long as | |
3617 | * every ADD commands overrides the previous configuration. | |
3618 | */ | |
3619 | DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len); | |
3620 | if (p->mcast_list_len > 0) | |
3621 | o->set_registry_size(o, p->mcast_list_len); | |
3622 | ||
3623 | break; | |
3624 | ||
3625 | default: | |
3626 | BNX2X_ERR("Unknown command: %d\n", cmd); | |
3627 | return -EINVAL; | |
619c5cb6 VZ |
3628 | } |
3629 | ||
3630 | /* We want to ensure that commands are executed one by one for 57710. | |
3631 | * Therefore each none-empty command will consume o->max_cmd_len. | |
3632 | */ | |
3633 | if (p->mcast_list_len) | |
3634 | o->total_pending_num += o->max_cmd_len; | |
3635 | ||
3636 | return 0; | |
3637 | } | |
3638 | ||
3639 | static void bnx2x_mcast_revert_e1(struct bnx2x *bp, | |
3640 | struct bnx2x_mcast_ramrod_params *p, | |
c7b7b483 YM |
3641 | int old_num_macs, |
3642 | enum bnx2x_mcast_cmd cmd) | |
619c5cb6 VZ |
3643 | { |
3644 | struct bnx2x_mcast_obj *o = p->mcast_obj; | |
3645 | ||
3646 | o->set_registry_size(o, old_num_macs); | |
3647 | ||
3648 | /* If current command hasn't been handled yet and we are | |
3649 | * here means that it's meant to be dropped and we have to | |
16a5fd92 | 3650 | * update the number of outstanding MACs accordingly. |
619c5cb6 VZ |
3651 | */ |
3652 | if (p->mcast_list_len) | |
3653 | o->total_pending_num -= o->max_cmd_len; | |
3654 | } | |
3655 | ||
3656 | static void bnx2x_mcast_set_one_rule_e1(struct bnx2x *bp, | |
3657 | struct bnx2x_mcast_obj *o, int idx, | |
3658 | union bnx2x_mcast_config_data *cfg_data, | |
86564c3f | 3659 | enum bnx2x_mcast_cmd cmd) |
619c5cb6 VZ |
3660 | { |
3661 | struct bnx2x_raw_obj *r = &o->raw; | |
3662 | struct mac_configuration_cmd *data = | |
3663 | (struct mac_configuration_cmd *)(r->rdata); | |
3664 | ||
3665 | /* copy mac */ | |
3666 | if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE)) { | |
3667 | bnx2x_set_fw_mac_addr(&data->config_table[idx].msb_mac_addr, | |
3668 | &data->config_table[idx].middle_mac_addr, | |
3669 | &data->config_table[idx].lsb_mac_addr, | |
3670 | cfg_data->mac); | |
3671 | ||
3672 | data->config_table[idx].vlan_id = 0; | |
3673 | data->config_table[idx].pf_id = r->func_id; | |
3674 | data->config_table[idx].clients_bit_vector = | |
3675 | cpu_to_le32(1 << r->cl_id); | |
3676 | ||
3677 | SET_FLAG(data->config_table[idx].flags, | |
3678 | MAC_CONFIGURATION_ENTRY_ACTION_TYPE, | |
3679 | T_ETH_MAC_COMMAND_SET); | |
3680 | } | |
3681 | } | |
3682 | ||
3683 | /** | |
3684 | * bnx2x_mcast_set_rdata_hdr_e1 - set header values in mac_configuration_cmd | |
3685 | * | |
3686 | * @bp: device handle | |
3687 | * @p: | |
3688 | * @len: number of rules to handle | |
3689 | */ | |
3690 | static inline void bnx2x_mcast_set_rdata_hdr_e1(struct bnx2x *bp, | |
3691 | struct bnx2x_mcast_ramrod_params *p, | |
3692 | u8 len) | |
3693 | { | |
3694 | struct bnx2x_raw_obj *r = &p->mcast_obj->raw; | |
3695 | struct mac_configuration_cmd *data = | |
3696 | (struct mac_configuration_cmd *)(r->rdata); | |
3697 | ||
3698 | u8 offset = (CHIP_REV_IS_SLOW(bp) ? | |
3699 | BNX2X_MAX_EMUL_MULTI*(1 + r->func_id) : | |
3700 | BNX2X_MAX_MULTICAST*(1 + r->func_id)); | |
3701 | ||
3702 | data->hdr.offset = offset; | |
86564c3f YM |
3703 | data->hdr.client_id = cpu_to_le16(0xff); |
3704 | data->hdr.echo = cpu_to_le32((r->cid & BNX2X_SWCID_MASK) | | |
3705 | (BNX2X_FILTER_MCAST_PENDING << | |
3706 | BNX2X_SWCID_SHIFT)); | |
619c5cb6 VZ |
3707 | data->hdr.length = len; |
3708 | } | |
3709 | ||
3710 | /** | |
3711 | * bnx2x_mcast_handle_restore_cmd_e1 - restore command for 57710 | |
3712 | * | |
3713 | * @bp: device handle | |
3714 | * @o: | |
3715 | * @start_idx: index in the registry to start from | |
3716 | * @rdata_idx: index in the ramrod data to start from | |
3717 | * | |
3718 | * restore command for 57710 is like all other commands - always a stand alone | |
3719 | * command - start_idx and rdata_idx will always be 0. This function will always | |
3720 | * succeed. | |
3721 | * returns -1 to comply with 57712 variant. | |
3722 | */ | |
3723 | static inline int bnx2x_mcast_handle_restore_cmd_e1( | |
3724 | struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_idx, | |
3725 | int *rdata_idx) | |
3726 | { | |
3727 | struct bnx2x_mcast_mac_elem *elem; | |
3728 | int i = 0; | |
86564c3f | 3729 | union bnx2x_mcast_config_data cfg_data = {NULL}; |
619c5cb6 VZ |
3730 | |
3731 | /* go through the registry and configure the MACs from it. */ | |
3732 | list_for_each_entry(elem, &o->registry.exact_match.macs, link) { | |
3733 | cfg_data.mac = &elem->mac[0]; | |
3734 | o->set_one_rule(bp, o, i, &cfg_data, BNX2X_MCAST_CMD_RESTORE); | |
3735 | ||
3736 | i++; | |
3737 | ||
0f9dad10 | 3738 | DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n", |
2de67439 | 3739 | cfg_data.mac); |
619c5cb6 VZ |
3740 | } |
3741 | ||
3742 | *rdata_idx = i; | |
3743 | ||
3744 | return -1; | |
3745 | } | |
3746 | ||
619c5cb6 VZ |
3747 | static inline int bnx2x_mcast_handle_pending_cmds_e1( |
3748 | struct bnx2x *bp, struct bnx2x_mcast_ramrod_params *p) | |
3749 | { | |
3750 | struct bnx2x_pending_mcast_cmd *cmd_pos; | |
3751 | struct bnx2x_mcast_mac_elem *pmac_pos; | |
3752 | struct bnx2x_mcast_obj *o = p->mcast_obj; | |
86564c3f | 3753 | union bnx2x_mcast_config_data cfg_data = {NULL}; |
619c5cb6 VZ |
3754 | int cnt = 0; |
3755 | ||
619c5cb6 VZ |
3756 | /* If nothing to be done - return */ |
3757 | if (list_empty(&o->pending_cmds_head)) | |
3758 | return 0; | |
3759 | ||
3760 | /* Handle the first command */ | |
3761 | cmd_pos = list_first_entry(&o->pending_cmds_head, | |
3762 | struct bnx2x_pending_mcast_cmd, link); | |
3763 | ||
3764 | switch (cmd_pos->type) { | |
3765 | case BNX2X_MCAST_CMD_ADD: | |
3766 | list_for_each_entry(pmac_pos, &cmd_pos->data.macs_head, link) { | |
3767 | cfg_data.mac = &pmac_pos->mac[0]; | |
3768 | o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type); | |
3769 | ||
3770 | cnt++; | |
3771 | ||
0f9dad10 | 3772 | DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n", |
2de67439 | 3773 | pmac_pos->mac); |
619c5cb6 VZ |
3774 | } |
3775 | break; | |
3776 | ||
3777 | case BNX2X_MCAST_CMD_DEL: | |
3778 | cnt = cmd_pos->data.macs_num; | |
3779 | DP(BNX2X_MSG_SP, "About to delete %d multicast MACs\n", cnt); | |
3780 | break; | |
3781 | ||
3782 | case BNX2X_MCAST_CMD_RESTORE: | |
3783 | o->hdl_restore(bp, o, 0, &cnt); | |
3784 | break; | |
3785 | ||
3786 | default: | |
3787 | BNX2X_ERR("Unknown command: %d\n", cmd_pos->type); | |
3788 | return -EINVAL; | |
3789 | } | |
3790 | ||
3791 | list_del(&cmd_pos->link); | |
3129e159 | 3792 | bnx2x_free_groups(&cmd_pos->group_head); |
619c5cb6 VZ |
3793 | kfree(cmd_pos); |
3794 | ||
3795 | return cnt; | |
3796 | } | |
3797 | ||
3798 | /** | |
3799 | * bnx2x_get_fw_mac_addr - revert the bnx2x_set_fw_mac_addr(). | |
3800 | * | |
3801 | * @fw_hi: | |
3802 | * @fw_mid: | |
3803 | * @fw_lo: | |
3804 | * @mac: | |
3805 | */ | |
3806 | static inline void bnx2x_get_fw_mac_addr(__le16 *fw_hi, __le16 *fw_mid, | |
3807 | __le16 *fw_lo, u8 *mac) | |
3808 | { | |
3809 | mac[1] = ((u8 *)fw_hi)[0]; | |
3810 | mac[0] = ((u8 *)fw_hi)[1]; | |
3811 | mac[3] = ((u8 *)fw_mid)[0]; | |
3812 | mac[2] = ((u8 *)fw_mid)[1]; | |
3813 | mac[5] = ((u8 *)fw_lo)[0]; | |
3814 | mac[4] = ((u8 *)fw_lo)[1]; | |
3815 | } | |
3816 | ||
3817 | /** | |
3818 | * bnx2x_mcast_refresh_registry_e1 - | |
3819 | * | |
3820 | * @bp: device handle | |
3821 | * @cnt: | |
3822 | * | |
3823 | * Check the ramrod data first entry flag to see if it's a DELETE or ADD command | |
3824 | * and update the registry correspondingly: if ADD - allocate a memory and add | |
3825 | * the entries to the registry (list), if DELETE - clear the registry and free | |
3826 | * the memory. | |
3827 | */ | |
3828 | static inline int bnx2x_mcast_refresh_registry_e1(struct bnx2x *bp, | |
3829 | struct bnx2x_mcast_obj *o) | |
3830 | { | |
3831 | struct bnx2x_raw_obj *raw = &o->raw; | |
3832 | struct bnx2x_mcast_mac_elem *elem; | |
3833 | struct mac_configuration_cmd *data = | |
3834 | (struct mac_configuration_cmd *)(raw->rdata); | |
3835 | ||
3836 | /* If first entry contains a SET bit - the command was ADD, | |
3837 | * otherwise - DEL_ALL | |
3838 | */ | |
3839 | if (GET_FLAG(data->config_table[0].flags, | |
3840 | MAC_CONFIGURATION_ENTRY_ACTION_TYPE)) { | |
3841 | int i, len = data->hdr.length; | |
3842 | ||
3843 | /* Break if it was a RESTORE command */ | |
3844 | if (!list_empty(&o->registry.exact_match.macs)) | |
3845 | return 0; | |
3846 | ||
01e23742 | 3847 | elem = kcalloc(len, sizeof(*elem), GFP_ATOMIC); |
619c5cb6 VZ |
3848 | if (!elem) { |
3849 | BNX2X_ERR("Failed to allocate registry memory\n"); | |
3850 | return -ENOMEM; | |
3851 | } | |
3852 | ||
3853 | for (i = 0; i < len; i++, elem++) { | |
3854 | bnx2x_get_fw_mac_addr( | |
3855 | &data->config_table[i].msb_mac_addr, | |
3856 | &data->config_table[i].middle_mac_addr, | |
3857 | &data->config_table[i].lsb_mac_addr, | |
3858 | elem->mac); | |
0f9dad10 | 3859 | DP(BNX2X_MSG_SP, "Adding registry entry for [%pM]\n", |
51c1a580 | 3860 | elem->mac); |
619c5cb6 VZ |
3861 | list_add_tail(&elem->link, |
3862 | &o->registry.exact_match.macs); | |
3863 | } | |
3864 | } else { | |
3865 | elem = list_first_entry(&o->registry.exact_match.macs, | |
3866 | struct bnx2x_mcast_mac_elem, link); | |
3867 | DP(BNX2X_MSG_SP, "Deleting a registry\n"); | |
3868 | kfree(elem); | |
3869 | INIT_LIST_HEAD(&o->registry.exact_match.macs); | |
3870 | } | |
3871 | ||
3872 | return 0; | |
3873 | } | |
3874 | ||
3875 | static int bnx2x_mcast_setup_e1(struct bnx2x *bp, | |
3876 | struct bnx2x_mcast_ramrod_params *p, | |
86564c3f | 3877 | enum bnx2x_mcast_cmd cmd) |
619c5cb6 VZ |
3878 | { |
3879 | struct bnx2x_mcast_obj *o = p->mcast_obj; | |
3880 | struct bnx2x_raw_obj *raw = &o->raw; | |
3881 | struct mac_configuration_cmd *data = | |
3882 | (struct mac_configuration_cmd *)(raw->rdata); | |
3883 | int cnt = 0, i, rc; | |
3884 | ||
3885 | /* Reset the ramrod data buffer */ | |
3886 | memset(data, 0, sizeof(*data)); | |
3887 | ||
3888 | /* First set all entries as invalid */ | |
3889 | for (i = 0; i < o->max_cmd_len ; i++) | |
3890 | SET_FLAG(data->config_table[i].flags, | |
3891 | MAC_CONFIGURATION_ENTRY_ACTION_TYPE, | |
3892 | T_ETH_MAC_COMMAND_INVALIDATE); | |
3893 | ||
3894 | /* Handle pending commands first */ | |
3895 | cnt = bnx2x_mcast_handle_pending_cmds_e1(bp, p); | |
3896 | ||
3897 | /* If there are no more pending commands - clear SCHEDULED state */ | |
3898 | if (list_empty(&o->pending_cmds_head)) | |
3899 | o->clear_sched(o); | |
3900 | ||
3901 | /* The below may be true iff there were no pending commands */ | |
3902 | if (!cnt) | |
3903 | cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, 0); | |
3904 | ||
3905 | /* For 57710 every command has o->max_cmd_len length to ensure that | |
3906 | * commands are done one at a time. | |
3907 | */ | |
3908 | o->total_pending_num -= o->max_cmd_len; | |
3909 | ||
3910 | /* send a ramrod */ | |
3911 | ||
3912 | WARN_ON(cnt > o->max_cmd_len); | |
3913 | ||
3914 | /* Set ramrod header (in particular, a number of entries to update) */ | |
3915 | bnx2x_mcast_set_rdata_hdr_e1(bp, p, (u8)cnt); | |
3916 | ||
3917 | /* update a registry: we need the registry contents to be always up | |
3918 | * to date in order to be able to execute a RESTORE opcode. Here | |
3919 | * we use the fact that for 57710 we sent one command at a time | |
3920 | * hence we may take the registry update out of the command handling | |
3921 | * and do it in a simpler way here. | |
3922 | */ | |
3923 | rc = bnx2x_mcast_refresh_registry_e1(bp, o); | |
3924 | if (rc) | |
3925 | return rc; | |
3926 | ||
16a5fd92 | 3927 | /* If CLEAR_ONLY was requested - don't send a ramrod and clear |
619c5cb6 VZ |
3928 | * RAMROD_PENDING status immediately. |
3929 | */ | |
3930 | if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) { | |
3931 | raw->clear_pending(raw); | |
3932 | return 0; | |
3933 | } else { | |
14a94ebd MK |
3934 | /* No need for an explicit memory barrier here as long as we |
3935 | * ensure the ordering of writing to the SPQ element | |
16a5fd92 | 3936 | * and updating of the SPQ producer which involves a memory |
14a94ebd MK |
3937 | * read. If the memory read is removed we will have to put a |
3938 | * full memory barrier there (inside bnx2x_sp_post()). | |
53e51e2f VZ |
3939 | */ |
3940 | ||
619c5cb6 VZ |
3941 | /* Send a ramrod */ |
3942 | rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, raw->cid, | |
3943 | U64_HI(raw->rdata_mapping), | |
3944 | U64_LO(raw->rdata_mapping), | |
3945 | ETH_CONNECTION_TYPE); | |
3946 | if (rc) | |
3947 | return rc; | |
3948 | ||
3949 | /* Ramrod completion is pending */ | |
3950 | return 1; | |
3951 | } | |
619c5cb6 VZ |
3952 | } |
3953 | ||
3954 | static int bnx2x_mcast_get_registry_size_exact(struct bnx2x_mcast_obj *o) | |
3955 | { | |
3956 | return o->registry.exact_match.num_macs_set; | |
3957 | } | |
3958 | ||
3959 | static int bnx2x_mcast_get_registry_size_aprox(struct bnx2x_mcast_obj *o) | |
3960 | { | |
3961 | return o->registry.aprox_match.num_bins_set; | |
3962 | } | |
3963 | ||
3964 | static void bnx2x_mcast_set_registry_size_exact(struct bnx2x_mcast_obj *o, | |
3965 | int n) | |
3966 | { | |
3967 | o->registry.exact_match.num_macs_set = n; | |
3968 | } | |
3969 | ||
3970 | static void bnx2x_mcast_set_registry_size_aprox(struct bnx2x_mcast_obj *o, | |
3971 | int n) | |
3972 | { | |
3973 | o->registry.aprox_match.num_bins_set = n; | |
3974 | } | |
3975 | ||
3976 | int bnx2x_config_mcast(struct bnx2x *bp, | |
3977 | struct bnx2x_mcast_ramrod_params *p, | |
86564c3f | 3978 | enum bnx2x_mcast_cmd cmd) |
619c5cb6 VZ |
3979 | { |
3980 | struct bnx2x_mcast_obj *o = p->mcast_obj; | |
3981 | struct bnx2x_raw_obj *r = &o->raw; | |
3982 | int rc = 0, old_reg_size; | |
3983 | ||
3984 | /* This is needed to recover number of currently configured mcast macs | |
3985 | * in case of failure. | |
3986 | */ | |
3987 | old_reg_size = o->get_registry_size(o); | |
3988 | ||
3989 | /* Do some calculations and checks */ | |
3990 | rc = o->validate(bp, p, cmd); | |
3991 | if (rc) | |
3992 | return rc; | |
3993 | ||
3994 | /* Return if there is no work to do */ | |
3995 | if ((!p->mcast_list_len) && (!o->check_sched(o))) | |
3996 | return 0; | |
3997 | ||
51c1a580 MS |
3998 | DP(BNX2X_MSG_SP, "o->total_pending_num=%d p->mcast_list_len=%d o->max_cmd_len=%d\n", |
3999 | o->total_pending_num, p->mcast_list_len, o->max_cmd_len); | |
619c5cb6 VZ |
4000 | |
4001 | /* Enqueue the current command to the pending list if we can't complete | |
4002 | * it in the current iteration | |
4003 | */ | |
4004 | if (r->check_pending(r) || | |
4005 | ((o->max_cmd_len > 0) && (o->total_pending_num > o->max_cmd_len))) { | |
4006 | rc = o->enqueue_cmd(bp, p->mcast_obj, p, cmd); | |
4007 | if (rc < 0) | |
4008 | goto error_exit1; | |
4009 | ||
4010 | /* As long as the current command is in a command list we | |
4011 | * don't need to handle it separately. | |
4012 | */ | |
4013 | p->mcast_list_len = 0; | |
4014 | } | |
4015 | ||
4016 | if (!r->check_pending(r)) { | |
4017 | ||
4018 | /* Set 'pending' state */ | |
4019 | r->set_pending(r); | |
4020 | ||
4021 | /* Configure the new classification in the chip */ | |
4022 | rc = o->config_mcast(bp, p, cmd); | |
4023 | if (rc < 0) | |
4024 | goto error_exit2; | |
4025 | ||
4026 | /* Wait for a ramrod completion if was requested */ | |
4027 | if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) | |
4028 | rc = o->wait_comp(bp, o); | |
4029 | } | |
4030 | ||
4031 | return rc; | |
4032 | ||
4033 | error_exit2: | |
4034 | r->clear_pending(r); | |
4035 | ||
4036 | error_exit1: | |
c7b7b483 | 4037 | o->revert(bp, p, old_reg_size, cmd); |
619c5cb6 VZ |
4038 | |
4039 | return rc; | |
4040 | } | |
4041 | ||
4042 | static void bnx2x_mcast_clear_sched(struct bnx2x_mcast_obj *o) | |
4043 | { | |
4e857c58 | 4044 | smp_mb__before_atomic(); |
619c5cb6 | 4045 | clear_bit(o->sched_state, o->raw.pstate); |
4e857c58 | 4046 | smp_mb__after_atomic(); |
619c5cb6 VZ |
4047 | } |
4048 | ||
4049 | static void bnx2x_mcast_set_sched(struct bnx2x_mcast_obj *o) | |
4050 | { | |
4e857c58 | 4051 | smp_mb__before_atomic(); |
619c5cb6 | 4052 | set_bit(o->sched_state, o->raw.pstate); |
4e857c58 | 4053 | smp_mb__after_atomic(); |
619c5cb6 VZ |
4054 | } |
4055 | ||
4056 | static bool bnx2x_mcast_check_sched(struct bnx2x_mcast_obj *o) | |
4057 | { | |
4058 | return !!test_bit(o->sched_state, o->raw.pstate); | |
4059 | } | |
4060 | ||
4061 | static bool bnx2x_mcast_check_pending(struct bnx2x_mcast_obj *o) | |
4062 | { | |
4063 | return o->raw.check_pending(&o->raw) || o->check_sched(o); | |
4064 | } | |
4065 | ||
4066 | void bnx2x_init_mcast_obj(struct bnx2x *bp, | |
4067 | struct bnx2x_mcast_obj *mcast_obj, | |
4068 | u8 mcast_cl_id, u32 mcast_cid, u8 func_id, | |
4069 | u8 engine_id, void *rdata, dma_addr_t rdata_mapping, | |
4070 | int state, unsigned long *pstate, bnx2x_obj_type type) | |
4071 | { | |
4072 | memset(mcast_obj, 0, sizeof(*mcast_obj)); | |
4073 | ||
4074 | bnx2x_init_raw_obj(&mcast_obj->raw, mcast_cl_id, mcast_cid, func_id, | |
4075 | rdata, rdata_mapping, state, pstate, type); | |
4076 | ||
4077 | mcast_obj->engine_id = engine_id; | |
4078 | ||
4079 | INIT_LIST_HEAD(&mcast_obj->pending_cmds_head); | |
4080 | ||
4081 | mcast_obj->sched_state = BNX2X_FILTER_MCAST_SCHED; | |
4082 | mcast_obj->check_sched = bnx2x_mcast_check_sched; | |
4083 | mcast_obj->set_sched = bnx2x_mcast_set_sched; | |
4084 | mcast_obj->clear_sched = bnx2x_mcast_clear_sched; | |
4085 | ||
4086 | if (CHIP_IS_E1(bp)) { | |
4087 | mcast_obj->config_mcast = bnx2x_mcast_setup_e1; | |
4088 | mcast_obj->enqueue_cmd = bnx2x_mcast_enqueue_cmd; | |
4089 | mcast_obj->hdl_restore = | |
4090 | bnx2x_mcast_handle_restore_cmd_e1; | |
4091 | mcast_obj->check_pending = bnx2x_mcast_check_pending; | |
4092 | ||
4093 | if (CHIP_REV_IS_SLOW(bp)) | |
4094 | mcast_obj->max_cmd_len = BNX2X_MAX_EMUL_MULTI; | |
4095 | else | |
4096 | mcast_obj->max_cmd_len = BNX2X_MAX_MULTICAST; | |
4097 | ||
4098 | mcast_obj->wait_comp = bnx2x_mcast_wait; | |
4099 | mcast_obj->set_one_rule = bnx2x_mcast_set_one_rule_e1; | |
4100 | mcast_obj->validate = bnx2x_mcast_validate_e1; | |
4101 | mcast_obj->revert = bnx2x_mcast_revert_e1; | |
4102 | mcast_obj->get_registry_size = | |
4103 | bnx2x_mcast_get_registry_size_exact; | |
4104 | mcast_obj->set_registry_size = | |
4105 | bnx2x_mcast_set_registry_size_exact; | |
4106 | ||
4107 | /* 57710 is the only chip that uses the exact match for mcast | |
4108 | * at the moment. | |
4109 | */ | |
4110 | INIT_LIST_HEAD(&mcast_obj->registry.exact_match.macs); | |
4111 | ||
4112 | } else if (CHIP_IS_E1H(bp)) { | |
4113 | mcast_obj->config_mcast = bnx2x_mcast_setup_e1h; | |
4114 | mcast_obj->enqueue_cmd = NULL; | |
4115 | mcast_obj->hdl_restore = NULL; | |
4116 | mcast_obj->check_pending = bnx2x_mcast_check_pending; | |
4117 | ||
4118 | /* 57711 doesn't send a ramrod, so it has unlimited credit | |
4119 | * for one command. | |
4120 | */ | |
4121 | mcast_obj->max_cmd_len = -1; | |
4122 | mcast_obj->wait_comp = bnx2x_mcast_wait; | |
4123 | mcast_obj->set_one_rule = NULL; | |
4124 | mcast_obj->validate = bnx2x_mcast_validate_e1h; | |
4125 | mcast_obj->revert = bnx2x_mcast_revert_e1h; | |
4126 | mcast_obj->get_registry_size = | |
4127 | bnx2x_mcast_get_registry_size_aprox; | |
4128 | mcast_obj->set_registry_size = | |
4129 | bnx2x_mcast_set_registry_size_aprox; | |
4130 | } else { | |
4131 | mcast_obj->config_mcast = bnx2x_mcast_setup_e2; | |
4132 | mcast_obj->enqueue_cmd = bnx2x_mcast_enqueue_cmd; | |
4133 | mcast_obj->hdl_restore = | |
4134 | bnx2x_mcast_handle_restore_cmd_e2; | |
4135 | mcast_obj->check_pending = bnx2x_mcast_check_pending; | |
4136 | /* TODO: There should be a proper HSI define for this number!!! | |
4137 | */ | |
4138 | mcast_obj->max_cmd_len = 16; | |
4139 | mcast_obj->wait_comp = bnx2x_mcast_wait; | |
4140 | mcast_obj->set_one_rule = bnx2x_mcast_set_one_rule_e2; | |
4141 | mcast_obj->validate = bnx2x_mcast_validate_e2; | |
4142 | mcast_obj->revert = bnx2x_mcast_revert_e2; | |
4143 | mcast_obj->get_registry_size = | |
4144 | bnx2x_mcast_get_registry_size_aprox; | |
4145 | mcast_obj->set_registry_size = | |
4146 | bnx2x_mcast_set_registry_size_aprox; | |
4147 | } | |
4148 | } | |
4149 | ||
4150 | /*************************** Credit handling **********************************/ | |
4151 | ||
4152 | /** | |
4153 | * atomic_add_ifless - add if the result is less than a given value. | |
4154 | * | |
4155 | * @v: pointer of type atomic_t | |
4156 | * @a: the amount to add to v... | |
4157 | * @u: ...if (v + a) is less than u. | |
4158 | * | |
4159 | * returns true if (v + a) was less than u, and false otherwise. | |
4160 | * | |
4161 | */ | |
4162 | static inline bool __atomic_add_ifless(atomic_t *v, int a, int u) | |
4163 | { | |
4164 | int c, old; | |
4165 | ||
4166 | c = atomic_read(v); | |
4167 | for (;;) { | |
4168 | if (unlikely(c + a >= u)) | |
4169 | return false; | |
4170 | ||
4171 | old = atomic_cmpxchg((v), c, c + a); | |
4172 | if (likely(old == c)) | |
4173 | break; | |
4174 | c = old; | |
4175 | } | |
4176 | ||
4177 | return true; | |
4178 | } | |
4179 | ||
4180 | /** | |
4181 | * atomic_dec_ifmoe - dec if the result is more or equal than a given value. | |
4182 | * | |
4183 | * @v: pointer of type atomic_t | |
4184 | * @a: the amount to dec from v... | |
4185 | * @u: ...if (v - a) is more or equal than u. | |
4186 | * | |
4187 | * returns true if (v - a) was more or equal than u, and false | |
4188 | * otherwise. | |
4189 | */ | |
4190 | static inline bool __atomic_dec_ifmoe(atomic_t *v, int a, int u) | |
4191 | { | |
4192 | int c, old; | |
4193 | ||
4194 | c = atomic_read(v); | |
4195 | for (;;) { | |
4196 | if (unlikely(c - a < u)) | |
4197 | return false; | |
4198 | ||
4199 | old = atomic_cmpxchg((v), c, c - a); | |
4200 | if (likely(old == c)) | |
4201 | break; | |
4202 | c = old; | |
4203 | } | |
4204 | ||
4205 | return true; | |
4206 | } | |
4207 | ||
4208 | static bool bnx2x_credit_pool_get(struct bnx2x_credit_pool_obj *o, int cnt) | |
4209 | { | |
4210 | bool rc; | |
4211 | ||
4212 | smp_mb(); | |
4213 | rc = __atomic_dec_ifmoe(&o->credit, cnt, 0); | |
4214 | smp_mb(); | |
4215 | ||
4216 | return rc; | |
4217 | } | |
4218 | ||
4219 | static bool bnx2x_credit_pool_put(struct bnx2x_credit_pool_obj *o, int cnt) | |
4220 | { | |
4221 | bool rc; | |
4222 | ||
4223 | smp_mb(); | |
4224 | ||
4225 | /* Don't let to refill if credit + cnt > pool_sz */ | |
4226 | rc = __atomic_add_ifless(&o->credit, cnt, o->pool_sz + 1); | |
4227 | ||
4228 | smp_mb(); | |
4229 | ||
4230 | return rc; | |
4231 | } | |
4232 | ||
4233 | static int bnx2x_credit_pool_check(struct bnx2x_credit_pool_obj *o) | |
4234 | { | |
4235 | int cur_credit; | |
4236 | ||
4237 | smp_mb(); | |
4238 | cur_credit = atomic_read(&o->credit); | |
4239 | ||
4240 | return cur_credit; | |
4241 | } | |
4242 | ||
4243 | static bool bnx2x_credit_pool_always_true(struct bnx2x_credit_pool_obj *o, | |
4244 | int cnt) | |
4245 | { | |
4246 | return true; | |
4247 | } | |
4248 | ||
619c5cb6 VZ |
4249 | static bool bnx2x_credit_pool_get_entry( |
4250 | struct bnx2x_credit_pool_obj *o, | |
4251 | int *offset) | |
4252 | { | |
4253 | int idx, vec, i; | |
4254 | ||
4255 | *offset = -1; | |
4256 | ||
4257 | /* Find "internal cam-offset" then add to base for this object... */ | |
4258 | for (vec = 0; vec < BNX2X_POOL_VEC_SIZE; vec++) { | |
4259 | ||
4260 | /* Skip the current vector if there are no free entries in it */ | |
4261 | if (!o->pool_mirror[vec]) | |
4262 | continue; | |
4263 | ||
4264 | /* If we've got here we are going to find a free entry */ | |
c54e9bd3 | 4265 | for (idx = vec * BIT_VEC64_ELEM_SZ, i = 0; |
619c5cb6 VZ |
4266 | i < BIT_VEC64_ELEM_SZ; idx++, i++) |
4267 | ||
4268 | if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) { | |
4269 | /* Got one!! */ | |
4270 | BIT_VEC64_CLEAR_BIT(o->pool_mirror, idx); | |
4271 | *offset = o->base_pool_offset + idx; | |
4272 | return true; | |
4273 | } | |
4274 | } | |
4275 | ||
4276 | return false; | |
4277 | } | |
4278 | ||
4279 | static bool bnx2x_credit_pool_put_entry( | |
4280 | struct bnx2x_credit_pool_obj *o, | |
4281 | int offset) | |
4282 | { | |
4283 | if (offset < o->base_pool_offset) | |
4284 | return false; | |
4285 | ||
4286 | offset -= o->base_pool_offset; | |
4287 | ||
4288 | if (offset >= o->pool_sz) | |
4289 | return false; | |
4290 | ||
4291 | /* Return the entry to the pool */ | |
4292 | BIT_VEC64_SET_BIT(o->pool_mirror, offset); | |
4293 | ||
4294 | return true; | |
4295 | } | |
4296 | ||
4297 | static bool bnx2x_credit_pool_put_entry_always_true( | |
4298 | struct bnx2x_credit_pool_obj *o, | |
4299 | int offset) | |
4300 | { | |
4301 | return true; | |
4302 | } | |
4303 | ||
4304 | static bool bnx2x_credit_pool_get_entry_always_true( | |
4305 | struct bnx2x_credit_pool_obj *o, | |
4306 | int *offset) | |
4307 | { | |
4308 | *offset = -1; | |
4309 | return true; | |
4310 | } | |
4311 | /** | |
4312 | * bnx2x_init_credit_pool - initialize credit pool internals. | |
4313 | * | |
4314 | * @p: | |
4315 | * @base: Base entry in the CAM to use. | |
4316 | * @credit: pool size. | |
4317 | * | |
4318 | * If base is negative no CAM entries handling will be performed. | |
4319 | * If credit is negative pool operations will always succeed (unlimited pool). | |
4320 | * | |
4321 | */ | |
05cc5a39 YM |
4322 | void bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj *p, |
4323 | int base, int credit) | |
619c5cb6 VZ |
4324 | { |
4325 | /* Zero the object first */ | |
4326 | memset(p, 0, sizeof(*p)); | |
4327 | ||
4328 | /* Set the table to all 1s */ | |
4329 | memset(&p->pool_mirror, 0xff, sizeof(p->pool_mirror)); | |
4330 | ||
4331 | /* Init a pool as full */ | |
4332 | atomic_set(&p->credit, credit); | |
4333 | ||
4334 | /* The total poll size */ | |
4335 | p->pool_sz = credit; | |
4336 | ||
4337 | p->base_pool_offset = base; | |
4338 | ||
4339 | /* Commit the change */ | |
4340 | smp_mb(); | |
4341 | ||
4342 | p->check = bnx2x_credit_pool_check; | |
4343 | ||
4344 | /* if pool credit is negative - disable the checks */ | |
4345 | if (credit >= 0) { | |
4346 | p->put = bnx2x_credit_pool_put; | |
4347 | p->get = bnx2x_credit_pool_get; | |
4348 | p->put_entry = bnx2x_credit_pool_put_entry; | |
4349 | p->get_entry = bnx2x_credit_pool_get_entry; | |
4350 | } else { | |
4351 | p->put = bnx2x_credit_pool_always_true; | |
4352 | p->get = bnx2x_credit_pool_always_true; | |
4353 | p->put_entry = bnx2x_credit_pool_put_entry_always_true; | |
4354 | p->get_entry = bnx2x_credit_pool_get_entry_always_true; | |
4355 | } | |
4356 | ||
4357 | /* If base is negative - disable entries handling */ | |
4358 | if (base < 0) { | |
4359 | p->put_entry = bnx2x_credit_pool_put_entry_always_true; | |
4360 | p->get_entry = bnx2x_credit_pool_get_entry_always_true; | |
4361 | } | |
4362 | } | |
4363 | ||
4364 | void bnx2x_init_mac_credit_pool(struct bnx2x *bp, | |
4365 | struct bnx2x_credit_pool_obj *p, u8 func_id, | |
4366 | u8 func_num) | |
4367 | { | |
4368 | /* TODO: this will be defined in consts as well... */ | |
4369 | #define BNX2X_CAM_SIZE_EMUL 5 | |
4370 | ||
4371 | int cam_sz; | |
4372 | ||
4373 | if (CHIP_IS_E1(bp)) { | |
4374 | /* In E1, Multicast is saved in cam... */ | |
4375 | if (!CHIP_REV_IS_SLOW(bp)) | |
4376 | cam_sz = (MAX_MAC_CREDIT_E1 / 2) - BNX2X_MAX_MULTICAST; | |
4377 | else | |
4378 | cam_sz = BNX2X_CAM_SIZE_EMUL - BNX2X_MAX_EMUL_MULTI; | |
4379 | ||
4380 | bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz); | |
4381 | ||
4382 | } else if (CHIP_IS_E1H(bp)) { | |
4383 | /* CAM credit is equaly divided between all active functions | |
4384 | * on the PORT!. | |
4385 | */ | |
4386 | if ((func_num > 0)) { | |
4387 | if (!CHIP_REV_IS_SLOW(bp)) | |
4388 | cam_sz = (MAX_MAC_CREDIT_E1H / (2*func_num)); | |
4389 | else | |
4390 | cam_sz = BNX2X_CAM_SIZE_EMUL; | |
4391 | bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz); | |
4392 | } else { | |
4393 | /* this should never happen! Block MAC operations. */ | |
4394 | bnx2x_init_credit_pool(p, 0, 0); | |
4395 | } | |
4396 | ||
4397 | } else { | |
4398 | ||
16a5fd92 | 4399 | /* CAM credit is equaly divided between all active functions |
619c5cb6 VZ |
4400 | * on the PATH. |
4401 | */ | |
05cc5a39 | 4402 | if (func_num > 0) { |
619c5cb6 | 4403 | if (!CHIP_REV_IS_SLOW(bp)) |
05cc5a39 | 4404 | cam_sz = PF_MAC_CREDIT_E2(bp, func_num); |
619c5cb6 VZ |
4405 | else |
4406 | cam_sz = BNX2X_CAM_SIZE_EMUL; | |
4407 | ||
16a5fd92 | 4408 | /* No need for CAM entries handling for 57712 and |
619c5cb6 VZ |
4409 | * newer. |
4410 | */ | |
4411 | bnx2x_init_credit_pool(p, -1, cam_sz); | |
4412 | } else { | |
4413 | /* this should never happen! Block MAC operations. */ | |
4414 | bnx2x_init_credit_pool(p, 0, 0); | |
4415 | } | |
619c5cb6 VZ |
4416 | } |
4417 | } | |
4418 | ||
4419 | void bnx2x_init_vlan_credit_pool(struct bnx2x *bp, | |
4420 | struct bnx2x_credit_pool_obj *p, | |
4421 | u8 func_id, | |
4422 | u8 func_num) | |
4423 | { | |
4424 | if (CHIP_IS_E1x(bp)) { | |
16a5fd92 | 4425 | /* There is no VLAN credit in HW on 57710 and 57711 only |
619c5cb6 VZ |
4426 | * MAC / MAC-VLAN can be set |
4427 | */ | |
4428 | bnx2x_init_credit_pool(p, 0, -1); | |
4429 | } else { | |
16a5fd92 | 4430 | /* CAM credit is equally divided between all active functions |
619c5cb6 VZ |
4431 | * on the PATH. |
4432 | */ | |
4433 | if (func_num > 0) { | |
05cc5a39 YM |
4434 | int credit = PF_VLAN_CREDIT_E2(bp, func_num); |
4435 | ||
4436 | bnx2x_init_credit_pool(p, -1/*unused for E2*/, credit); | |
619c5cb6 VZ |
4437 | } else |
4438 | /* this should never happen! Block VLAN operations. */ | |
4439 | bnx2x_init_credit_pool(p, 0, 0); | |
4440 | } | |
4441 | } | |
4442 | ||
4443 | /****************** RSS Configuration ******************/ | |
4444 | /** | |
4445 | * bnx2x_debug_print_ind_table - prints the indirection table configuration. | |
4446 | * | |
16a5fd92 | 4447 | * @bp: driver handle |
619c5cb6 VZ |
4448 | * @p: pointer to rss configuration |
4449 | * | |
4450 | * Prints it when NETIF_MSG_IFUP debug level is configured. | |
4451 | */ | |
4452 | static inline void bnx2x_debug_print_ind_table(struct bnx2x *bp, | |
4453 | struct bnx2x_config_rss_params *p) | |
4454 | { | |
042181f5 VZ |
4455 | int i; |
4456 | ||
619c5cb6 VZ |
4457 | DP(BNX2X_MSG_SP, "Setting indirection table to:\n"); |
4458 | DP(BNX2X_MSG_SP, "0x0000: "); | |
4459 | for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) { | |
4460 | DP_CONT(BNX2X_MSG_SP, "0x%02x ", p->ind_table[i]); | |
4461 | ||
4462 | /* Print 4 bytes in a line */ | |
4463 | if ((i + 1 < T_ETH_INDIRECTION_TABLE_SIZE) && | |
4464 | (((i + 1) & 0x3) == 0)) { | |
4465 | DP_CONT(BNX2X_MSG_SP, "\n"); | |
4466 | DP(BNX2X_MSG_SP, "0x%04x: ", i + 1); | |
4467 | } | |
4468 | } | |
4469 | ||
4470 | DP_CONT(BNX2X_MSG_SP, "\n"); | |
4471 | } | |
4472 | ||
4473 | /** | |
4474 | * bnx2x_setup_rss - configure RSS | |
4475 | * | |
4476 | * @bp: device handle | |
4477 | * @p: rss configuration | |
4478 | * | |
4479 | * sends on UPDATE ramrod for that matter. | |
4480 | */ | |
4481 | static int bnx2x_setup_rss(struct bnx2x *bp, | |
4482 | struct bnx2x_config_rss_params *p) | |
4483 | { | |
4484 | struct bnx2x_rss_config_obj *o = p->rss_obj; | |
4485 | struct bnx2x_raw_obj *r = &o->raw; | |
4486 | struct eth_rss_update_ramrod_data *data = | |
4487 | (struct eth_rss_update_ramrod_data *)(r->rdata); | |
e42780b6 | 4488 | u16 caps = 0; |
619c5cb6 VZ |
4489 | u8 rss_mode = 0; |
4490 | int rc; | |
4491 | ||
4492 | memset(data, 0, sizeof(*data)); | |
4493 | ||
4494 | DP(BNX2X_MSG_SP, "Configuring RSS\n"); | |
4495 | ||
4496 | /* Set an echo field */ | |
86564c3f YM |
4497 | data->echo = cpu_to_le32((r->cid & BNX2X_SWCID_MASK) | |
4498 | (r->state << BNX2X_SWCID_SHIFT)); | |
619c5cb6 VZ |
4499 | |
4500 | /* RSS mode */ | |
4501 | if (test_bit(BNX2X_RSS_MODE_DISABLED, &p->rss_flags)) | |
4502 | rss_mode = ETH_RSS_MODE_DISABLED; | |
4503 | else if (test_bit(BNX2X_RSS_MODE_REGULAR, &p->rss_flags)) | |
4504 | rss_mode = ETH_RSS_MODE_REGULAR; | |
619c5cb6 VZ |
4505 | |
4506 | data->rss_mode = rss_mode; | |
4507 | ||
4508 | DP(BNX2X_MSG_SP, "rss_mode=%d\n", rss_mode); | |
4509 | ||
4510 | /* RSS capabilities */ | |
4511 | if (test_bit(BNX2X_RSS_IPV4, &p->rss_flags)) | |
e42780b6 | 4512 | caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY; |
619c5cb6 VZ |
4513 | |
4514 | if (test_bit(BNX2X_RSS_IPV4_TCP, &p->rss_flags)) | |
e42780b6 | 4515 | caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY; |
619c5cb6 | 4516 | |
5d317c6a | 4517 | if (test_bit(BNX2X_RSS_IPV4_UDP, &p->rss_flags)) |
e42780b6 | 4518 | caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY; |
5d317c6a | 4519 | |
619c5cb6 | 4520 | if (test_bit(BNX2X_RSS_IPV6, &p->rss_flags)) |
e42780b6 | 4521 | caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY; |
619c5cb6 VZ |
4522 | |
4523 | if (test_bit(BNX2X_RSS_IPV6_TCP, &p->rss_flags)) | |
e42780b6 | 4524 | caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY; |
619c5cb6 | 4525 | |
5d317c6a | 4526 | if (test_bit(BNX2X_RSS_IPV6_UDP, &p->rss_flags)) |
e42780b6 DK |
4527 | caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY; |
4528 | ||
28311f8e YM |
4529 | if (test_bit(BNX2X_RSS_IPV4_VXLAN, &p->rss_flags)) |
4530 | caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_VXLAN_CAPABILITY; | |
4531 | ||
4532 | if (test_bit(BNX2X_RSS_IPV6_VXLAN, &p->rss_flags)) | |
4533 | caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_VXLAN_CAPABILITY; | |
4534 | ||
4535 | if (test_bit(BNX2X_RSS_TUNN_INNER_HDRS, &p->rss_flags)) | |
4536 | caps |= ETH_RSS_UPDATE_RAMROD_DATA_TUNN_INNER_HDRS_CAPABILITY; | |
e42780b6 | 4537 | |
56daf66d YM |
4538 | /* RSS keys */ |
4539 | if (test_bit(BNX2X_RSS_SET_SRCH, &p->rss_flags)) { | |
d682d2bd ED |
4540 | u8 *dst = (u8 *)(data->rss_key) + sizeof(data->rss_key); |
4541 | const u8 *src = (const u8 *)p->rss_key; | |
4542 | int i; | |
4543 | ||
4544 | /* Apparently, bnx2x reads this array in reverse order | |
4545 | * We need to byte swap rss_key to comply with Toeplitz specs. | |
4546 | */ | |
4547 | for (i = 0; i < sizeof(data->rss_key); i++) | |
4548 | *--dst = *src++; | |
4549 | ||
56daf66d YM |
4550 | caps |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY; |
4551 | } | |
4552 | ||
e42780b6 | 4553 | data->capabilities = cpu_to_le16(caps); |
5d317c6a | 4554 | |
619c5cb6 VZ |
4555 | /* Hashing mask */ |
4556 | data->rss_result_mask = p->rss_result_mask; | |
4557 | ||
4558 | /* RSS engine ID */ | |
4559 | data->rss_engine_id = o->engine_id; | |
4560 | ||
4561 | DP(BNX2X_MSG_SP, "rss_engine_id=%d\n", data->rss_engine_id); | |
4562 | ||
4563 | /* Indirection table */ | |
4564 | memcpy(data->indirection_table, p->ind_table, | |
4565 | T_ETH_INDIRECTION_TABLE_SIZE); | |
4566 | ||
4567 | /* Remember the last configuration */ | |
4568 | memcpy(o->ind_table, p->ind_table, T_ETH_INDIRECTION_TABLE_SIZE); | |
4569 | ||
4570 | /* Print the indirection table */ | |
4571 | if (netif_msg_ifup(bp)) | |
4572 | bnx2x_debug_print_ind_table(bp, p); | |
4573 | ||
14a94ebd MK |
4574 | /* No need for an explicit memory barrier here as long as we |
4575 | * ensure the ordering of writing to the SPQ element | |
16a5fd92 | 4576 | * and updating of the SPQ producer which involves a memory |
14a94ebd MK |
4577 | * read. If the memory read is removed we will have to put a |
4578 | * full memory barrier there (inside bnx2x_sp_post()). | |
53e51e2f | 4579 | */ |
619c5cb6 VZ |
4580 | |
4581 | /* Send a ramrod */ | |
4582 | rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_RSS_UPDATE, r->cid, | |
4583 | U64_HI(r->rdata_mapping), | |
4584 | U64_LO(r->rdata_mapping), | |
4585 | ETH_CONNECTION_TYPE); | |
4586 | ||
4587 | if (rc < 0) | |
4588 | return rc; | |
4589 | ||
4590 | return 1; | |
4591 | } | |
4592 | ||
4593 | void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj, | |
4594 | u8 *ind_table) | |
4595 | { | |
4596 | memcpy(ind_table, rss_obj->ind_table, sizeof(rss_obj->ind_table)); | |
4597 | } | |
4598 | ||
4599 | int bnx2x_config_rss(struct bnx2x *bp, | |
4600 | struct bnx2x_config_rss_params *p) | |
4601 | { | |
4602 | int rc; | |
4603 | struct bnx2x_rss_config_obj *o = p->rss_obj; | |
4604 | struct bnx2x_raw_obj *r = &o->raw; | |
4605 | ||
4606 | /* Do nothing if only driver cleanup was requested */ | |
5b622918 MK |
4607 | if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) { |
4608 | DP(BNX2X_MSG_SP, "Not configuring RSS ramrod_flags=%lx\n", | |
4609 | p->ramrod_flags); | |
619c5cb6 | 4610 | return 0; |
5b622918 | 4611 | } |
619c5cb6 VZ |
4612 | |
4613 | r->set_pending(r); | |
4614 | ||
4615 | rc = o->config_rss(bp, p); | |
4616 | if (rc < 0) { | |
4617 | r->clear_pending(r); | |
4618 | return rc; | |
4619 | } | |
4620 | ||
4621 | if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) | |
4622 | rc = r->wait_comp(bp, r); | |
4623 | ||
4624 | return rc; | |
4625 | } | |
4626 | ||
619c5cb6 VZ |
4627 | void bnx2x_init_rss_config_obj(struct bnx2x *bp, |
4628 | struct bnx2x_rss_config_obj *rss_obj, | |
4629 | u8 cl_id, u32 cid, u8 func_id, u8 engine_id, | |
4630 | void *rdata, dma_addr_t rdata_mapping, | |
4631 | int state, unsigned long *pstate, | |
4632 | bnx2x_obj_type type) | |
4633 | { | |
4634 | bnx2x_init_raw_obj(&rss_obj->raw, cl_id, cid, func_id, rdata, | |
4635 | rdata_mapping, state, pstate, type); | |
4636 | ||
4637 | rss_obj->engine_id = engine_id; | |
4638 | rss_obj->config_rss = bnx2x_setup_rss; | |
4639 | } | |
4640 | ||
4641 | /********************** Queue state object ***********************************/ | |
4642 | ||
4643 | /** | |
4644 | * bnx2x_queue_state_change - perform Queue state change transition | |
4645 | * | |
4646 | * @bp: device handle | |
4647 | * @params: parameters to perform the transition | |
4648 | * | |
4649 | * returns 0 in case of successfully completed transition, negative error | |
4650 | * code in case of failure, positive (EBUSY) value if there is a completion | |
4651 | * to that is still pending (possible only if RAMROD_COMP_WAIT is | |
4652 | * not set in params->ramrod_flags for asynchronous commands). | |
4653 | * | |
4654 | */ | |
4655 | int bnx2x_queue_state_change(struct bnx2x *bp, | |
4656 | struct bnx2x_queue_state_params *params) | |
4657 | { | |
4658 | struct bnx2x_queue_sp_obj *o = params->q_obj; | |
4659 | int rc, pending_bit; | |
4660 | unsigned long *pending = &o->pending; | |
4661 | ||
4662 | /* Check that the requested transition is legal */ | |
04c46736 YM |
4663 | rc = o->check_transition(bp, o, params); |
4664 | if (rc) { | |
4665 | BNX2X_ERR("check transition returned an error. rc %d\n", rc); | |
619c5cb6 | 4666 | return -EINVAL; |
04c46736 | 4667 | } |
619c5cb6 VZ |
4668 | |
4669 | /* Set "pending" bit */ | |
04c46736 | 4670 | DP(BNX2X_MSG_SP, "pending bit was=%lx\n", o->pending); |
619c5cb6 | 4671 | pending_bit = o->set_pending(o, params); |
04c46736 | 4672 | DP(BNX2X_MSG_SP, "pending bit now=%lx\n", o->pending); |
619c5cb6 VZ |
4673 | |
4674 | /* Don't send a command if only driver cleanup was requested */ | |
4675 | if (test_bit(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) | |
4676 | o->complete_cmd(bp, o, pending_bit); | |
4677 | else { | |
4678 | /* Send a ramrod */ | |
4679 | rc = o->send_cmd(bp, params); | |
4680 | if (rc) { | |
4681 | o->next_state = BNX2X_Q_STATE_MAX; | |
4682 | clear_bit(pending_bit, pending); | |
4e857c58 | 4683 | smp_mb__after_atomic(); |
619c5cb6 VZ |
4684 | return rc; |
4685 | } | |
4686 | ||
4687 | if (test_bit(RAMROD_COMP_WAIT, ¶ms->ramrod_flags)) { | |
4688 | rc = o->wait_comp(bp, o, pending_bit); | |
4689 | if (rc) | |
4690 | return rc; | |
4691 | ||
4692 | return 0; | |
4693 | } | |
4694 | } | |
4695 | ||
4696 | return !!test_bit(pending_bit, pending); | |
4697 | } | |
4698 | ||
619c5cb6 VZ |
4699 | static int bnx2x_queue_set_pending(struct bnx2x_queue_sp_obj *obj, |
4700 | struct bnx2x_queue_state_params *params) | |
4701 | { | |
4702 | enum bnx2x_queue_cmd cmd = params->cmd, bit; | |
4703 | ||
4704 | /* ACTIVATE and DEACTIVATE commands are implemented on top of | |
4705 | * UPDATE command. | |
4706 | */ | |
4707 | if ((cmd == BNX2X_Q_CMD_ACTIVATE) || | |
4708 | (cmd == BNX2X_Q_CMD_DEACTIVATE)) | |
4709 | bit = BNX2X_Q_CMD_UPDATE; | |
4710 | else | |
4711 | bit = cmd; | |
4712 | ||
4713 | set_bit(bit, &obj->pending); | |
4714 | return bit; | |
4715 | } | |
4716 | ||
4717 | static int bnx2x_queue_wait_comp(struct bnx2x *bp, | |
4718 | struct bnx2x_queue_sp_obj *o, | |
4719 | enum bnx2x_queue_cmd cmd) | |
4720 | { | |
4721 | return bnx2x_state_wait(bp, cmd, &o->pending); | |
4722 | } | |
4723 | ||
4724 | /** | |
4725 | * bnx2x_queue_comp_cmd - complete the state change command. | |
4726 | * | |
4727 | * @bp: device handle | |
4728 | * @o: | |
4729 | * @cmd: | |
4730 | * | |
4731 | * Checks that the arrived completion is expected. | |
4732 | */ | |
4733 | static int bnx2x_queue_comp_cmd(struct bnx2x *bp, | |
4734 | struct bnx2x_queue_sp_obj *o, | |
4735 | enum bnx2x_queue_cmd cmd) | |
4736 | { | |
4737 | unsigned long cur_pending = o->pending; | |
4738 | ||
4739 | if (!test_and_clear_bit(cmd, &cur_pending)) { | |
51c1a580 MS |
4740 | BNX2X_ERR("Bad MC reply %d for queue %d in state %d pending 0x%lx, next_state %d\n", |
4741 | cmd, o->cids[BNX2X_PRIMARY_CID_INDEX], | |
619c5cb6 VZ |
4742 | o->state, cur_pending, o->next_state); |
4743 | return -EINVAL; | |
4744 | } | |
4745 | ||
6383c0b3 | 4746 | if (o->next_tx_only >= o->max_cos) |
16a5fd92 | 4747 | /* >= because tx only must always be smaller than cos since the |
02582e9b | 4748 | * primary connection supports COS 0 |
6383c0b3 AE |
4749 | */ |
4750 | BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d", | |
4751 | o->next_tx_only, o->max_cos); | |
4752 | ||
51c1a580 MS |
4753 | DP(BNX2X_MSG_SP, |
4754 | "Completing command %d for queue %d, setting state to %d\n", | |
4755 | cmd, o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_state); | |
6383c0b3 AE |
4756 | |
4757 | if (o->next_tx_only) /* print num tx-only if any exist */ | |
94f05b0f | 4758 | DP(BNX2X_MSG_SP, "primary cid %d: num tx-only cons %d\n", |
51c1a580 | 4759 | o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_tx_only); |
619c5cb6 VZ |
4760 | |
4761 | o->state = o->next_state; | |
6383c0b3 | 4762 | o->num_tx_only = o->next_tx_only; |
619c5cb6 VZ |
4763 | o->next_state = BNX2X_Q_STATE_MAX; |
4764 | ||
4765 | /* It's important that o->state and o->next_state are | |
4766 | * updated before o->pending. | |
4767 | */ | |
4768 | wmb(); | |
4769 | ||
4770 | clear_bit(cmd, &o->pending); | |
4e857c58 | 4771 | smp_mb__after_atomic(); |
619c5cb6 VZ |
4772 | |
4773 | return 0; | |
4774 | } | |
4775 | ||
4776 | static void bnx2x_q_fill_setup_data_e2(struct bnx2x *bp, | |
4777 | struct bnx2x_queue_state_params *cmd_params, | |
4778 | struct client_init_ramrod_data *data) | |
4779 | { | |
4780 | struct bnx2x_queue_setup_params *params = &cmd_params->params.setup; | |
4781 | ||
4782 | /* Rx data */ | |
4783 | ||
4784 | /* IPv6 TPA supported for E2 and above only */ | |
f5219d8e | 4785 | data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA_IPV6, ¶ms->flags) * |
619c5cb6 VZ |
4786 | CLIENT_INIT_RX_DATA_TPA_EN_IPV6; |
4787 | } | |
4788 | ||
6383c0b3 AE |
4789 | static void bnx2x_q_fill_init_general_data(struct bnx2x *bp, |
4790 | struct bnx2x_queue_sp_obj *o, | |
4791 | struct bnx2x_general_setup_params *params, | |
4792 | struct client_init_general_data *gen_data, | |
4793 | unsigned long *flags) | |
4794 | { | |
4795 | gen_data->client_id = o->cl_id; | |
4796 | ||
4797 | if (test_bit(BNX2X_Q_FLG_STATS, flags)) { | |
4798 | gen_data->statistics_counter_id = | |
4799 | params->stat_id; | |
4800 | gen_data->statistics_en_flg = 1; | |
4801 | gen_data->statistics_zero_flg = | |
4802 | test_bit(BNX2X_Q_FLG_ZERO_STATS, flags); | |
619c5cb6 | 4803 | } else |
6383c0b3 | 4804 | gen_data->statistics_counter_id = |
619c5cb6 VZ |
4805 | DISABLE_STATISTIC_COUNTER_ID_VALUE; |
4806 | ||
6383c0b3 AE |
4807 | gen_data->is_fcoe_flg = test_bit(BNX2X_Q_FLG_FCOE, flags); |
4808 | gen_data->activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE, flags); | |
4809 | gen_data->sp_client_id = params->spcl_id; | |
4810 | gen_data->mtu = cpu_to_le16(params->mtu); | |
4811 | gen_data->func_id = o->func_id; | |
619c5cb6 | 4812 | |
6383c0b3 | 4813 | gen_data->cos = params->cos; |
619c5cb6 | 4814 | |
6383c0b3 AE |
4815 | gen_data->traffic_type = |
4816 | test_bit(BNX2X_Q_FLG_FCOE, flags) ? | |
619c5cb6 VZ |
4817 | LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW; |
4818 | ||
02dc4025 | 4819 | gen_data->fp_hsi_ver = params->fp_hsi; |
e42780b6 | 4820 | |
94f05b0f | 4821 | DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d\n", |
6383c0b3 AE |
4822 | gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg); |
4823 | } | |
4824 | ||
4825 | static void bnx2x_q_fill_init_tx_data(struct bnx2x_queue_sp_obj *o, | |
4826 | struct bnx2x_txq_setup_params *params, | |
4827 | struct client_init_tx_data *tx_data, | |
4828 | unsigned long *flags) | |
4829 | { | |
4830 | tx_data->enforce_security_flg = | |
4831 | test_bit(BNX2X_Q_FLG_TX_SEC, flags); | |
4832 | tx_data->default_vlan = | |
4833 | cpu_to_le16(params->default_vlan); | |
4834 | tx_data->default_vlan_flg = | |
4835 | test_bit(BNX2X_Q_FLG_DEF_VLAN, flags); | |
4836 | tx_data->tx_switching_flg = | |
4837 | test_bit(BNX2X_Q_FLG_TX_SWITCH, flags); | |
4838 | tx_data->anti_spoofing_flg = | |
4839 | test_bit(BNX2X_Q_FLG_ANTI_SPOOF, flags); | |
a3348722 BW |
4840 | tx_data->force_default_pri_flg = |
4841 | test_bit(BNX2X_Q_FLG_FORCE_DEFAULT_PRI, flags); | |
e42780b6 DK |
4842 | tx_data->refuse_outband_vlan_flg = |
4843 | test_bit(BNX2X_Q_FLG_REFUSE_OUTBAND_VLAN, flags); | |
e287a75c DK |
4844 | tx_data->tunnel_lso_inc_ip_id = |
4845 | test_bit(BNX2X_Q_FLG_TUN_INC_INNER_IP_ID, flags); | |
91226790 | 4846 | tx_data->tunnel_non_lso_pcsum_location = |
e42780b6 DK |
4847 | test_bit(BNX2X_Q_FLG_PCSUM_ON_PKT, flags) ? CSUM_ON_PKT : |
4848 | CSUM_ON_BD; | |
91226790 | 4849 | |
6383c0b3 AE |
4850 | tx_data->tx_status_block_id = params->fw_sb_id; |
4851 | tx_data->tx_sb_index_number = params->sb_cq_index; | |
4852 | tx_data->tss_leading_client_id = params->tss_leading_cl_id; | |
4853 | ||
4854 | tx_data->tx_bd_page_base.lo = | |
4855 | cpu_to_le32(U64_LO(params->dscr_map)); | |
4856 | tx_data->tx_bd_page_base.hi = | |
4857 | cpu_to_le32(U64_HI(params->dscr_map)); | |
4858 | ||
4859 | /* Don't configure any Tx switching mode during queue SETUP */ | |
4860 | tx_data->state = 0; | |
4861 | } | |
4862 | ||
4863 | static void bnx2x_q_fill_init_pause_data(struct bnx2x_queue_sp_obj *o, | |
4864 | struct rxq_pause_params *params, | |
4865 | struct client_init_rx_data *rx_data) | |
4866 | { | |
4867 | /* flow control data */ | |
4868 | rx_data->cqe_pause_thr_low = cpu_to_le16(params->rcq_th_lo); | |
4869 | rx_data->cqe_pause_thr_high = cpu_to_le16(params->rcq_th_hi); | |
4870 | rx_data->bd_pause_thr_low = cpu_to_le16(params->bd_th_lo); | |
4871 | rx_data->bd_pause_thr_high = cpu_to_le16(params->bd_th_hi); | |
4872 | rx_data->sge_pause_thr_low = cpu_to_le16(params->sge_th_lo); | |
4873 | rx_data->sge_pause_thr_high = cpu_to_le16(params->sge_th_hi); | |
4874 | rx_data->rx_cos_mask = cpu_to_le16(params->pri_map); | |
4875 | } | |
4876 | ||
4877 | static void bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj *o, | |
4878 | struct bnx2x_rxq_setup_params *params, | |
4879 | struct client_init_rx_data *rx_data, | |
4880 | unsigned long *flags) | |
4881 | { | |
6383c0b3 | 4882 | rx_data->tpa_en = test_bit(BNX2X_Q_FLG_TPA, flags) * |
619c5cb6 | 4883 | CLIENT_INIT_RX_DATA_TPA_EN_IPV4; |
621b4d66 DK |
4884 | rx_data->tpa_en |= test_bit(BNX2X_Q_FLG_TPA_GRO, flags) * |
4885 | CLIENT_INIT_RX_DATA_TPA_MODE; | |
6383c0b3 | 4886 | rx_data->vmqueue_mode_en_flg = 0; |
619c5cb6 | 4887 | |
6383c0b3 AE |
4888 | rx_data->cache_line_alignment_log_size = |
4889 | params->cache_line_log; | |
4890 | rx_data->enable_dynamic_hc = | |
4891 | test_bit(BNX2X_Q_FLG_DHC, flags); | |
4892 | rx_data->max_sges_for_packet = params->max_sges_pkt; | |
4893 | rx_data->client_qzone_id = params->cl_qzone_id; | |
4894 | rx_data->max_agg_size = cpu_to_le16(params->tpa_agg_sz); | |
619c5cb6 VZ |
4895 | |
4896 | /* Always start in DROP_ALL mode */ | |
6383c0b3 | 4897 | rx_data->state = cpu_to_le16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL | |
619c5cb6 VZ |
4898 | CLIENT_INIT_RX_DATA_MCAST_DROP_ALL); |
4899 | ||
4900 | /* We don't set drop flags */ | |
6383c0b3 AE |
4901 | rx_data->drop_ip_cs_err_flg = 0; |
4902 | rx_data->drop_tcp_cs_err_flg = 0; | |
4903 | rx_data->drop_ttl0_flg = 0; | |
4904 | rx_data->drop_udp_cs_err_flg = 0; | |
4905 | rx_data->inner_vlan_removal_enable_flg = | |
4906 | test_bit(BNX2X_Q_FLG_VLAN, flags); | |
4907 | rx_data->outer_vlan_removal_enable_flg = | |
4908 | test_bit(BNX2X_Q_FLG_OV, flags); | |
4909 | rx_data->status_block_id = params->fw_sb_id; | |
4910 | rx_data->rx_sb_index_number = params->sb_cq_index; | |
4911 | rx_data->max_tpa_queues = params->max_tpa_queues; | |
4912 | rx_data->max_bytes_on_bd = cpu_to_le16(params->buf_sz); | |
4913 | rx_data->sge_buff_size = cpu_to_le16(params->sge_buf_sz); | |
4914 | rx_data->bd_page_base.lo = | |
4915 | cpu_to_le32(U64_LO(params->dscr_map)); | |
4916 | rx_data->bd_page_base.hi = | |
4917 | cpu_to_le32(U64_HI(params->dscr_map)); | |
4918 | rx_data->sge_page_base.lo = | |
4919 | cpu_to_le32(U64_LO(params->sge_map)); | |
4920 | rx_data->sge_page_base.hi = | |
4921 | cpu_to_le32(U64_HI(params->sge_map)); | |
4922 | rx_data->cqe_page_base.lo = | |
4923 | cpu_to_le32(U64_LO(params->rcq_map)); | |
4924 | rx_data->cqe_page_base.hi = | |
4925 | cpu_to_le32(U64_HI(params->rcq_map)); | |
4926 | rx_data->is_leading_rss = test_bit(BNX2X_Q_FLG_LEADING_RSS, flags); | |
4927 | ||
4928 | if (test_bit(BNX2X_Q_FLG_MCAST, flags)) { | |
259afa1f | 4929 | rx_data->approx_mcast_engine_id = params->mcast_engine_id; |
6383c0b3 | 4930 | rx_data->is_approx_mcast = 1; |
619c5cb6 VZ |
4931 | } |
4932 | ||
6383c0b3 | 4933 | rx_data->rss_engine_id = params->rss_engine_id; |
619c5cb6 VZ |
4934 | |
4935 | /* silent vlan removal */ | |
6383c0b3 AE |
4936 | rx_data->silent_vlan_removal_flg = |
4937 | test_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, flags); | |
4938 | rx_data->silent_vlan_value = | |
4939 | cpu_to_le16(params->silent_removal_value); | |
4940 | rx_data->silent_vlan_mask = | |
4941 | cpu_to_le16(params->silent_removal_mask); | |
619c5cb6 VZ |
4942 | } |
4943 | ||
6383c0b3 AE |
4944 | /* initialize the general, tx and rx parts of a queue object */ |
4945 | static void bnx2x_q_fill_setup_data_cmn(struct bnx2x *bp, | |
4946 | struct bnx2x_queue_state_params *cmd_params, | |
4947 | struct client_init_ramrod_data *data) | |
4948 | { | |
4949 | bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj, | |
4950 | &cmd_params->params.setup.gen_params, | |
4951 | &data->general, | |
4952 | &cmd_params->params.setup.flags); | |
4953 | ||
4954 | bnx2x_q_fill_init_tx_data(cmd_params->q_obj, | |
4955 | &cmd_params->params.setup.txq_params, | |
4956 | &data->tx, | |
4957 | &cmd_params->params.setup.flags); | |
4958 | ||
4959 | bnx2x_q_fill_init_rx_data(cmd_params->q_obj, | |
4960 | &cmd_params->params.setup.rxq_params, | |
4961 | &data->rx, | |
4962 | &cmd_params->params.setup.flags); | |
4963 | ||
4964 | bnx2x_q_fill_init_pause_data(cmd_params->q_obj, | |
4965 | &cmd_params->params.setup.pause_params, | |
4966 | &data->rx); | |
4967 | } | |
4968 | ||
4969 | /* initialize the general and tx parts of a tx-only queue object */ | |
4970 | static void bnx2x_q_fill_setup_tx_only(struct bnx2x *bp, | |
4971 | struct bnx2x_queue_state_params *cmd_params, | |
4972 | struct tx_queue_init_ramrod_data *data) | |
4973 | { | |
4974 | bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj, | |
4975 | &cmd_params->params.tx_only.gen_params, | |
4976 | &data->general, | |
4977 | &cmd_params->params.tx_only.flags); | |
4978 | ||
4979 | bnx2x_q_fill_init_tx_data(cmd_params->q_obj, | |
4980 | &cmd_params->params.tx_only.txq_params, | |
4981 | &data->tx, | |
4982 | &cmd_params->params.tx_only.flags); | |
4983 | ||
51c1a580 MS |
4984 | DP(BNX2X_MSG_SP, "cid %d, tx bd page lo %x hi %x", |
4985 | cmd_params->q_obj->cids[0], | |
4986 | data->tx.tx_bd_page_base.lo, | |
4987 | data->tx.tx_bd_page_base.hi); | |
6383c0b3 | 4988 | } |
619c5cb6 VZ |
4989 | |
4990 | /** | |
4991 | * bnx2x_q_init - init HW/FW queue | |
4992 | * | |
4993 | * @bp: device handle | |
4994 | * @params: | |
4995 | * | |
4996 | * HW/FW initial Queue configuration: | |
4997 | * - HC: Rx and Tx | |
4998 | * - CDU context validation | |
4999 | * | |
5000 | */ | |
5001 | static inline int bnx2x_q_init(struct bnx2x *bp, | |
5002 | struct bnx2x_queue_state_params *params) | |
5003 | { | |
5004 | struct bnx2x_queue_sp_obj *o = params->q_obj; | |
5005 | struct bnx2x_queue_init_params *init = ¶ms->params.init; | |
5006 | u16 hc_usec; | |
6383c0b3 | 5007 | u8 cos; |
619c5cb6 VZ |
5008 | |
5009 | /* Tx HC configuration */ | |
5010 | if (test_bit(BNX2X_Q_TYPE_HAS_TX, &o->type) && | |
5011 | test_bit(BNX2X_Q_FLG_HC, &init->tx.flags)) { | |
5012 | hc_usec = init->tx.hc_rate ? 1000000 / init->tx.hc_rate : 0; | |
5013 | ||
5014 | bnx2x_update_coalesce_sb_index(bp, init->tx.fw_sb_id, | |
5015 | init->tx.sb_cq_index, | |
5016 | !test_bit(BNX2X_Q_FLG_HC_EN, &init->tx.flags), | |
5017 | hc_usec); | |
5018 | } | |
5019 | ||
5020 | /* Rx HC configuration */ | |
5021 | if (test_bit(BNX2X_Q_TYPE_HAS_RX, &o->type) && | |
5022 | test_bit(BNX2X_Q_FLG_HC, &init->rx.flags)) { | |
5023 | hc_usec = init->rx.hc_rate ? 1000000 / init->rx.hc_rate : 0; | |
5024 | ||
5025 | bnx2x_update_coalesce_sb_index(bp, init->rx.fw_sb_id, | |
5026 | init->rx.sb_cq_index, | |
5027 | !test_bit(BNX2X_Q_FLG_HC_EN, &init->rx.flags), | |
5028 | hc_usec); | |
5029 | } | |
5030 | ||
5031 | /* Set CDU context validation values */ | |
6383c0b3 | 5032 | for (cos = 0; cos < o->max_cos; cos++) { |
94f05b0f | 5033 | DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d\n", |
6383c0b3 | 5034 | o->cids[cos], cos); |
94f05b0f | 5035 | DP(BNX2X_MSG_SP, "context pointer %p\n", init->cxts[cos]); |
6383c0b3 AE |
5036 | bnx2x_set_ctx_validation(bp, init->cxts[cos], o->cids[cos]); |
5037 | } | |
619c5cb6 VZ |
5038 | |
5039 | /* As no ramrod is sent, complete the command immediately */ | |
5040 | o->complete_cmd(bp, o, BNX2X_Q_CMD_INIT); | |
5041 | ||
5042 | mmiowb(); | |
5043 | smp_mb(); | |
5044 | ||
5045 | return 0; | |
5046 | } | |
5047 | ||
5048 | static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp, | |
5049 | struct bnx2x_queue_state_params *params) | |
5050 | { | |
5051 | struct bnx2x_queue_sp_obj *o = params->q_obj; | |
5052 | struct client_init_ramrod_data *rdata = | |
5053 | (struct client_init_ramrod_data *)o->rdata; | |
5054 | dma_addr_t data_mapping = o->rdata_mapping; | |
5055 | int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP; | |
5056 | ||
5057 | /* Clear the ramrod data */ | |
5058 | memset(rdata, 0, sizeof(*rdata)); | |
5059 | ||
5060 | /* Fill the ramrod data */ | |
5061 | bnx2x_q_fill_setup_data_cmn(bp, params, rdata); | |
5062 | ||
14a94ebd MK |
5063 | /* No need for an explicit memory barrier here as long as we |
5064 | * ensure the ordering of writing to the SPQ element | |
16a5fd92 | 5065 | * and updating of the SPQ producer which involves a memory |
14a94ebd MK |
5066 | * read. If the memory read is removed we will have to put a |
5067 | * full memory barrier there (inside bnx2x_sp_post()). | |
53e51e2f | 5068 | */ |
6383c0b3 AE |
5069 | return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX], |
5070 | U64_HI(data_mapping), | |
619c5cb6 VZ |
5071 | U64_LO(data_mapping), ETH_CONNECTION_TYPE); |
5072 | } | |
5073 | ||
5074 | static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp, | |
5075 | struct bnx2x_queue_state_params *params) | |
5076 | { | |
5077 | struct bnx2x_queue_sp_obj *o = params->q_obj; | |
5078 | struct client_init_ramrod_data *rdata = | |
5079 | (struct client_init_ramrod_data *)o->rdata; | |
5080 | dma_addr_t data_mapping = o->rdata_mapping; | |
5081 | int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP; | |
5082 | ||
5083 | /* Clear the ramrod data */ | |
5084 | memset(rdata, 0, sizeof(*rdata)); | |
5085 | ||
5086 | /* Fill the ramrod data */ | |
5087 | bnx2x_q_fill_setup_data_cmn(bp, params, rdata); | |
5088 | bnx2x_q_fill_setup_data_e2(bp, params, rdata); | |
5089 | ||
14a94ebd MK |
5090 | /* No need for an explicit memory barrier here as long as we |
5091 | * ensure the ordering of writing to the SPQ element | |
16a5fd92 | 5092 | * and updating of the SPQ producer which involves a memory |
14a94ebd MK |
5093 | * read. If the memory read is removed we will have to put a |
5094 | * full memory barrier there (inside bnx2x_sp_post()). | |
53e51e2f | 5095 | */ |
6383c0b3 AE |
5096 | return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX], |
5097 | U64_HI(data_mapping), | |
5098 | U64_LO(data_mapping), ETH_CONNECTION_TYPE); | |
5099 | } | |
5100 | ||
5101 | static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp, | |
5102 | struct bnx2x_queue_state_params *params) | |
5103 | { | |
5104 | struct bnx2x_queue_sp_obj *o = params->q_obj; | |
5105 | struct tx_queue_init_ramrod_data *rdata = | |
5106 | (struct tx_queue_init_ramrod_data *)o->rdata; | |
5107 | dma_addr_t data_mapping = o->rdata_mapping; | |
5108 | int ramrod = RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP; | |
5109 | struct bnx2x_queue_setup_tx_only_params *tx_only_params = | |
5110 | ¶ms->params.tx_only; | |
5111 | u8 cid_index = tx_only_params->cid_index; | |
5112 | ||
6383c0b3 AE |
5113 | if (cid_index >= o->max_cos) { |
5114 | BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", | |
5115 | o->cl_id, cid_index); | |
5116 | return -EINVAL; | |
5117 | } | |
5118 | ||
94f05b0f | 5119 | DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d\n", |
6383c0b3 AE |
5120 | tx_only_params->gen_params.cos, |
5121 | tx_only_params->gen_params.spcl_id); | |
5122 | ||
5123 | /* Clear the ramrod data */ | |
5124 | memset(rdata, 0, sizeof(*rdata)); | |
5125 | ||
5126 | /* Fill the ramrod data */ | |
5127 | bnx2x_q_fill_setup_tx_only(bp, params, rdata); | |
5128 | ||
51c1a580 MS |
5129 | DP(BNX2X_MSG_SP, "sending tx-only ramrod: cid %d, client-id %d, sp-client id %d, cos %d\n", |
5130 | o->cids[cid_index], rdata->general.client_id, | |
6383c0b3 AE |
5131 | rdata->general.sp_client_id, rdata->general.cos); |
5132 | ||
14a94ebd MK |
5133 | /* No need for an explicit memory barrier here as long as we |
5134 | * ensure the ordering of writing to the SPQ element | |
16a5fd92 | 5135 | * and updating of the SPQ producer which involves a memory |
14a94ebd MK |
5136 | * read. If the memory read is removed we will have to put a |
5137 | * full memory barrier there (inside bnx2x_sp_post()). | |
6383c0b3 | 5138 | */ |
6383c0b3 AE |
5139 | return bnx2x_sp_post(bp, ramrod, o->cids[cid_index], |
5140 | U64_HI(data_mapping), | |
619c5cb6 VZ |
5141 | U64_LO(data_mapping), ETH_CONNECTION_TYPE); |
5142 | } | |
5143 | ||
5144 | static void bnx2x_q_fill_update_data(struct bnx2x *bp, | |
5145 | struct bnx2x_queue_sp_obj *obj, | |
5146 | struct bnx2x_queue_update_params *params, | |
5147 | struct client_update_ramrod_data *data) | |
5148 | { | |
5149 | /* Client ID of the client to update */ | |
5150 | data->client_id = obj->cl_id; | |
5151 | ||
5152 | /* Function ID of the client to update */ | |
5153 | data->func_id = obj->func_id; | |
5154 | ||
5155 | /* Default VLAN value */ | |
5156 | data->default_vlan = cpu_to_le16(params->def_vlan); | |
5157 | ||
5158 | /* Inner VLAN stripping */ | |
5159 | data->inner_vlan_removal_enable_flg = | |
5160 | test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM, ¶ms->update_flags); | |
5161 | data->inner_vlan_removal_change_flg = | |
5162 | test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG, | |
5163 | ¶ms->update_flags); | |
5164 | ||
16a5fd92 | 5165 | /* Outer VLAN stripping */ |
619c5cb6 VZ |
5166 | data->outer_vlan_removal_enable_flg = |
5167 | test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM, ¶ms->update_flags); | |
5168 | data->outer_vlan_removal_change_flg = | |
5169 | test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM_CHNG, | |
5170 | ¶ms->update_flags); | |
5171 | ||
5172 | /* Drop packets that have source MAC that doesn't belong to this | |
5173 | * Queue. | |
5174 | */ | |
5175 | data->anti_spoofing_enable_flg = | |
5176 | test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF, ¶ms->update_flags); | |
5177 | data->anti_spoofing_change_flg = | |
5178 | test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF_CHNG, ¶ms->update_flags); | |
5179 | ||
5180 | /* Activate/Deactivate */ | |
5181 | data->activate_flg = | |
5182 | test_bit(BNX2X_Q_UPDATE_ACTIVATE, ¶ms->update_flags); | |
5183 | data->activate_change_flg = | |
5184 | test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, ¶ms->update_flags); | |
5185 | ||
5186 | /* Enable default VLAN */ | |
5187 | data->default_vlan_enable_flg = | |
5188 | test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN, ¶ms->update_flags); | |
5189 | data->default_vlan_change_flg = | |
5190 | test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG, | |
5191 | ¶ms->update_flags); | |
5192 | ||
5193 | /* silent vlan removal */ | |
5194 | data->silent_vlan_change_flg = | |
5195 | test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG, | |
5196 | ¶ms->update_flags); | |
5197 | data->silent_vlan_removal_flg = | |
5198 | test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM, ¶ms->update_flags); | |
5199 | data->silent_vlan_value = cpu_to_le16(params->silent_removal_value); | |
5200 | data->silent_vlan_mask = cpu_to_le16(params->silent_removal_mask); | |
c14db202 YM |
5201 | |
5202 | /* tx switching */ | |
5203 | data->tx_switching_flg = | |
5204 | test_bit(BNX2X_Q_UPDATE_TX_SWITCHING, ¶ms->update_flags); | |
5205 | data->tx_switching_change_flg = | |
5206 | test_bit(BNX2X_Q_UPDATE_TX_SWITCHING_CHNG, | |
5207 | ¶ms->update_flags); | |
eeed018c MK |
5208 | |
5209 | /* PTP */ | |
5210 | data->handle_ptp_pkts_flg = | |
5211 | test_bit(BNX2X_Q_UPDATE_PTP_PKTS, ¶ms->update_flags); | |
5212 | data->handle_ptp_pkts_change_flg = | |
5213 | test_bit(BNX2X_Q_UPDATE_PTP_PKTS_CHNG, ¶ms->update_flags); | |
619c5cb6 VZ |
5214 | } |
5215 | ||
5216 | static inline int bnx2x_q_send_update(struct bnx2x *bp, | |
5217 | struct bnx2x_queue_state_params *params) | |
5218 | { | |
5219 | struct bnx2x_queue_sp_obj *o = params->q_obj; | |
5220 | struct client_update_ramrod_data *rdata = | |
5221 | (struct client_update_ramrod_data *)o->rdata; | |
5222 | dma_addr_t data_mapping = o->rdata_mapping; | |
6383c0b3 AE |
5223 | struct bnx2x_queue_update_params *update_params = |
5224 | ¶ms->params.update; | |
5225 | u8 cid_index = update_params->cid_index; | |
5226 | ||
5227 | if (cid_index >= o->max_cos) { | |
5228 | BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", | |
5229 | o->cl_id, cid_index); | |
5230 | return -EINVAL; | |
5231 | } | |
5232 | ||
619c5cb6 VZ |
5233 | /* Clear the ramrod data */ |
5234 | memset(rdata, 0, sizeof(*rdata)); | |
5235 | ||
5236 | /* Fill the ramrod data */ | |
6383c0b3 | 5237 | bnx2x_q_fill_update_data(bp, o, update_params, rdata); |
619c5cb6 | 5238 | |
14a94ebd MK |
5239 | /* No need for an explicit memory barrier here as long as we |
5240 | * ensure the ordering of writing to the SPQ element | |
16a5fd92 | 5241 | * and updating of the SPQ producer which involves a memory |
14a94ebd MK |
5242 | * read. If the memory read is removed we will have to put a |
5243 | * full memory barrier there (inside bnx2x_sp_post()). | |
53e51e2f | 5244 | */ |
6383c0b3 AE |
5245 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE, |
5246 | o->cids[cid_index], U64_HI(data_mapping), | |
619c5cb6 VZ |
5247 | U64_LO(data_mapping), ETH_CONNECTION_TYPE); |
5248 | } | |
5249 | ||
5250 | /** | |
5251 | * bnx2x_q_send_deactivate - send DEACTIVATE command | |
5252 | * | |
5253 | * @bp: device handle | |
5254 | * @params: | |
5255 | * | |
5256 | * implemented using the UPDATE command. | |
5257 | */ | |
5258 | static inline int bnx2x_q_send_deactivate(struct bnx2x *bp, | |
5259 | struct bnx2x_queue_state_params *params) | |
5260 | { | |
5261 | struct bnx2x_queue_update_params *update = ¶ms->params.update; | |
5262 | ||
5263 | memset(update, 0, sizeof(*update)); | |
5264 | ||
5265 | __set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags); | |
5266 | ||
5267 | return bnx2x_q_send_update(bp, params); | |
5268 | } | |
5269 | ||
5270 | /** | |
5271 | * bnx2x_q_send_activate - send ACTIVATE command | |
5272 | * | |
5273 | * @bp: device handle | |
5274 | * @params: | |
5275 | * | |
5276 | * implemented using the UPDATE command. | |
5277 | */ | |
5278 | static inline int bnx2x_q_send_activate(struct bnx2x *bp, | |
5279 | struct bnx2x_queue_state_params *params) | |
5280 | { | |
5281 | struct bnx2x_queue_update_params *update = ¶ms->params.update; | |
5282 | ||
5283 | memset(update, 0, sizeof(*update)); | |
5284 | ||
5285 | __set_bit(BNX2X_Q_UPDATE_ACTIVATE, &update->update_flags); | |
5286 | __set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags); | |
5287 | ||
5288 | return bnx2x_q_send_update(bp, params); | |
5289 | } | |
5290 | ||
14a94ebd MK |
5291 | static void bnx2x_q_fill_update_tpa_data(struct bnx2x *bp, |
5292 | struct bnx2x_queue_sp_obj *obj, | |
5293 | struct bnx2x_queue_update_tpa_params *params, | |
5294 | struct tpa_update_ramrod_data *data) | |
5295 | { | |
5296 | data->client_id = obj->cl_id; | |
5297 | data->complete_on_both_clients = params->complete_on_both_clients; | |
5298 | data->dont_verify_rings_pause_thr_flg = | |
5299 | params->dont_verify_thr; | |
5300 | data->max_agg_size = cpu_to_le16(params->max_agg_sz); | |
5301 | data->max_sges_for_packet = params->max_sges_pkt; | |
5302 | data->max_tpa_queues = params->max_tpa_queues; | |
5303 | data->sge_buff_size = cpu_to_le16(params->sge_buff_sz); | |
5304 | data->sge_page_base_hi = cpu_to_le32(U64_HI(params->sge_map)); | |
5305 | data->sge_page_base_lo = cpu_to_le32(U64_LO(params->sge_map)); | |
5306 | data->sge_pause_thr_high = cpu_to_le16(params->sge_pause_thr_high); | |
5307 | data->sge_pause_thr_low = cpu_to_le16(params->sge_pause_thr_low); | |
5308 | data->tpa_mode = params->tpa_mode; | |
5309 | data->update_ipv4 = params->update_ipv4; | |
5310 | data->update_ipv6 = params->update_ipv6; | |
5311 | } | |
5312 | ||
619c5cb6 VZ |
5313 | static inline int bnx2x_q_send_update_tpa(struct bnx2x *bp, |
5314 | struct bnx2x_queue_state_params *params) | |
5315 | { | |
14a94ebd MK |
5316 | struct bnx2x_queue_sp_obj *o = params->q_obj; |
5317 | struct tpa_update_ramrod_data *rdata = | |
5318 | (struct tpa_update_ramrod_data *)o->rdata; | |
5319 | dma_addr_t data_mapping = o->rdata_mapping; | |
5320 | struct bnx2x_queue_update_tpa_params *update_tpa_params = | |
5321 | ¶ms->params.update_tpa; | |
5322 | u16 type; | |
5323 | ||
5324 | /* Clear the ramrod data */ | |
5325 | memset(rdata, 0, sizeof(*rdata)); | |
5326 | ||
5327 | /* Fill the ramrod data */ | |
5328 | bnx2x_q_fill_update_tpa_data(bp, o, update_tpa_params, rdata); | |
5329 | ||
5330 | /* Add the function id inside the type, so that sp post function | |
5331 | * doesn't automatically add the PF func-id, this is required | |
5332 | * for operations done by PFs on behalf of their VFs | |
5333 | */ | |
5334 | type = ETH_CONNECTION_TYPE | | |
5335 | ((o->func_id) << SPE_HDR_FUNCTION_ID_SHIFT); | |
5336 | ||
5337 | /* No need for an explicit memory barrier here as long as we | |
5338 | * ensure the ordering of writing to the SPQ element | |
5339 | * and updating of the SPQ producer which involves a memory | |
5340 | * read. If the memory read is removed we will have to put a | |
5341 | * full memory barrier there (inside bnx2x_sp_post()). | |
5342 | */ | |
5343 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TPA_UPDATE, | |
5344 | o->cids[BNX2X_PRIMARY_CID_INDEX], | |
5345 | U64_HI(data_mapping), | |
5346 | U64_LO(data_mapping), type); | |
619c5cb6 VZ |
5347 | } |
5348 | ||
5349 | static inline int bnx2x_q_send_halt(struct bnx2x *bp, | |
5350 | struct bnx2x_queue_state_params *params) | |
5351 | { | |
5352 | struct bnx2x_queue_sp_obj *o = params->q_obj; | |
5353 | ||
6383c0b3 AE |
5354 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, |
5355 | o->cids[BNX2X_PRIMARY_CID_INDEX], 0, o->cl_id, | |
619c5cb6 VZ |
5356 | ETH_CONNECTION_TYPE); |
5357 | } | |
5358 | ||
5359 | static inline int bnx2x_q_send_cfc_del(struct bnx2x *bp, | |
5360 | struct bnx2x_queue_state_params *params) | |
5361 | { | |
5362 | struct bnx2x_queue_sp_obj *o = params->q_obj; | |
6383c0b3 | 5363 | u8 cid_idx = params->params.cfc_del.cid_index; |
619c5cb6 | 5364 | |
6383c0b3 AE |
5365 | if (cid_idx >= o->max_cos) { |
5366 | BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", | |
5367 | o->cl_id, cid_idx); | |
5368 | return -EINVAL; | |
5369 | } | |
5370 | ||
5371 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL, | |
5372 | o->cids[cid_idx], 0, 0, NONE_CONNECTION_TYPE); | |
619c5cb6 VZ |
5373 | } |
5374 | ||
5375 | static inline int bnx2x_q_send_terminate(struct bnx2x *bp, | |
5376 | struct bnx2x_queue_state_params *params) | |
5377 | { | |
5378 | struct bnx2x_queue_sp_obj *o = params->q_obj; | |
6383c0b3 | 5379 | u8 cid_index = params->params.terminate.cid_index; |
619c5cb6 | 5380 | |
6383c0b3 AE |
5381 | if (cid_index >= o->max_cos) { |
5382 | BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", | |
5383 | o->cl_id, cid_index); | |
5384 | return -EINVAL; | |
5385 | } | |
5386 | ||
5387 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE, | |
5388 | o->cids[cid_index], 0, 0, ETH_CONNECTION_TYPE); | |
619c5cb6 VZ |
5389 | } |
5390 | ||
5391 | static inline int bnx2x_q_send_empty(struct bnx2x *bp, | |
5392 | struct bnx2x_queue_state_params *params) | |
5393 | { | |
5394 | struct bnx2x_queue_sp_obj *o = params->q_obj; | |
5395 | ||
6383c0b3 AE |
5396 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_EMPTY, |
5397 | o->cids[BNX2X_PRIMARY_CID_INDEX], 0, 0, | |
619c5cb6 VZ |
5398 | ETH_CONNECTION_TYPE); |
5399 | } | |
5400 | ||
5401 | static inline int bnx2x_queue_send_cmd_cmn(struct bnx2x *bp, | |
5402 | struct bnx2x_queue_state_params *params) | |
5403 | { | |
5404 | switch (params->cmd) { | |
5405 | case BNX2X_Q_CMD_INIT: | |
5406 | return bnx2x_q_init(bp, params); | |
6383c0b3 AE |
5407 | case BNX2X_Q_CMD_SETUP_TX_ONLY: |
5408 | return bnx2x_q_send_setup_tx_only(bp, params); | |
619c5cb6 VZ |
5409 | case BNX2X_Q_CMD_DEACTIVATE: |
5410 | return bnx2x_q_send_deactivate(bp, params); | |
5411 | case BNX2X_Q_CMD_ACTIVATE: | |
5412 | return bnx2x_q_send_activate(bp, params); | |
5413 | case BNX2X_Q_CMD_UPDATE: | |
5414 | return bnx2x_q_send_update(bp, params); | |
5415 | case BNX2X_Q_CMD_UPDATE_TPA: | |
5416 | return bnx2x_q_send_update_tpa(bp, params); | |
5417 | case BNX2X_Q_CMD_HALT: | |
5418 | return bnx2x_q_send_halt(bp, params); | |
5419 | case BNX2X_Q_CMD_CFC_DEL: | |
5420 | return bnx2x_q_send_cfc_del(bp, params); | |
5421 | case BNX2X_Q_CMD_TERMINATE: | |
5422 | return bnx2x_q_send_terminate(bp, params); | |
5423 | case BNX2X_Q_CMD_EMPTY: | |
5424 | return bnx2x_q_send_empty(bp, params); | |
5425 | default: | |
5426 | BNX2X_ERR("Unknown command: %d\n", params->cmd); | |
5427 | return -EINVAL; | |
5428 | } | |
5429 | } | |
5430 | ||
5431 | static int bnx2x_queue_send_cmd_e1x(struct bnx2x *bp, | |
5432 | struct bnx2x_queue_state_params *params) | |
5433 | { | |
5434 | switch (params->cmd) { | |
5435 | case BNX2X_Q_CMD_SETUP: | |
5436 | return bnx2x_q_send_setup_e1x(bp, params); | |
5437 | case BNX2X_Q_CMD_INIT: | |
6383c0b3 | 5438 | case BNX2X_Q_CMD_SETUP_TX_ONLY: |
619c5cb6 VZ |
5439 | case BNX2X_Q_CMD_DEACTIVATE: |
5440 | case BNX2X_Q_CMD_ACTIVATE: | |
5441 | case BNX2X_Q_CMD_UPDATE: | |
5442 | case BNX2X_Q_CMD_UPDATE_TPA: | |
5443 | case BNX2X_Q_CMD_HALT: | |
5444 | case BNX2X_Q_CMD_CFC_DEL: | |
5445 | case BNX2X_Q_CMD_TERMINATE: | |
5446 | case BNX2X_Q_CMD_EMPTY: | |
5447 | return bnx2x_queue_send_cmd_cmn(bp, params); | |
5448 | default: | |
5449 | BNX2X_ERR("Unknown command: %d\n", params->cmd); | |
5450 | return -EINVAL; | |
5451 | } | |
5452 | } | |
5453 | ||
5454 | static int bnx2x_queue_send_cmd_e2(struct bnx2x *bp, | |
5455 | struct bnx2x_queue_state_params *params) | |
5456 | { | |
5457 | switch (params->cmd) { | |
5458 | case BNX2X_Q_CMD_SETUP: | |
5459 | return bnx2x_q_send_setup_e2(bp, params); | |
5460 | case BNX2X_Q_CMD_INIT: | |
6383c0b3 | 5461 | case BNX2X_Q_CMD_SETUP_TX_ONLY: |
619c5cb6 VZ |
5462 | case BNX2X_Q_CMD_DEACTIVATE: |
5463 | case BNX2X_Q_CMD_ACTIVATE: | |
5464 | case BNX2X_Q_CMD_UPDATE: | |
5465 | case BNX2X_Q_CMD_UPDATE_TPA: | |
5466 | case BNX2X_Q_CMD_HALT: | |
5467 | case BNX2X_Q_CMD_CFC_DEL: | |
5468 | case BNX2X_Q_CMD_TERMINATE: | |
5469 | case BNX2X_Q_CMD_EMPTY: | |
5470 | return bnx2x_queue_send_cmd_cmn(bp, params); | |
5471 | default: | |
5472 | BNX2X_ERR("Unknown command: %d\n", params->cmd); | |
5473 | return -EINVAL; | |
5474 | } | |
5475 | } | |
5476 | ||
5477 | /** | |
5478 | * bnx2x_queue_chk_transition - check state machine of a regular Queue | |
5479 | * | |
5480 | * @bp: device handle | |
5481 | * @o: | |
5482 | * @params: | |
5483 | * | |
5484 | * (not Forwarding) | |
5485 | * It both checks if the requested command is legal in a current | |
5486 | * state and, if it's legal, sets a `next_state' in the object | |
5487 | * that will be used in the completion flow to set the `state' | |
5488 | * of the object. | |
5489 | * | |
5490 | * returns 0 if a requested command is a legal transition, | |
5491 | * -EINVAL otherwise. | |
5492 | */ | |
5493 | static int bnx2x_queue_chk_transition(struct bnx2x *bp, | |
5494 | struct bnx2x_queue_sp_obj *o, | |
5495 | struct bnx2x_queue_state_params *params) | |
5496 | { | |
5497 | enum bnx2x_q_state state = o->state, next_state = BNX2X_Q_STATE_MAX; | |
5498 | enum bnx2x_queue_cmd cmd = params->cmd; | |
6383c0b3 AE |
5499 | struct bnx2x_queue_update_params *update_params = |
5500 | ¶ms->params.update; | |
5501 | u8 next_tx_only = o->num_tx_only; | |
619c5cb6 | 5502 | |
16a5fd92 | 5503 | /* Forget all pending for completion commands if a driver only state |
6debea87 DK |
5504 | * transition has been requested. |
5505 | */ | |
5506 | if (test_bit(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) { | |
5507 | o->pending = 0; | |
5508 | o->next_state = BNX2X_Q_STATE_MAX; | |
5509 | } | |
5510 | ||
16a5fd92 | 5511 | /* Don't allow a next state transition if we are in the middle of |
6debea87 DK |
5512 | * the previous one. |
5513 | */ | |
04c46736 YM |
5514 | if (o->pending) { |
5515 | BNX2X_ERR("Blocking transition since pending was %lx\n", | |
5516 | o->pending); | |
6debea87 | 5517 | return -EBUSY; |
04c46736 | 5518 | } |
6debea87 | 5519 | |
619c5cb6 VZ |
5520 | switch (state) { |
5521 | case BNX2X_Q_STATE_RESET: | |
5522 | if (cmd == BNX2X_Q_CMD_INIT) | |
5523 | next_state = BNX2X_Q_STATE_INITIALIZED; | |
5524 | ||
5525 | break; | |
5526 | case BNX2X_Q_STATE_INITIALIZED: | |
5527 | if (cmd == BNX2X_Q_CMD_SETUP) { | |
5528 | if (test_bit(BNX2X_Q_FLG_ACTIVE, | |
5529 | ¶ms->params.setup.flags)) | |
5530 | next_state = BNX2X_Q_STATE_ACTIVE; | |
5531 | else | |
5532 | next_state = BNX2X_Q_STATE_INACTIVE; | |
5533 | } | |
5534 | ||
5535 | break; | |
5536 | case BNX2X_Q_STATE_ACTIVE: | |
5537 | if (cmd == BNX2X_Q_CMD_DEACTIVATE) | |
5538 | next_state = BNX2X_Q_STATE_INACTIVE; | |
5539 | ||
5540 | else if ((cmd == BNX2X_Q_CMD_EMPTY) || | |
5541 | (cmd == BNX2X_Q_CMD_UPDATE_TPA)) | |
5542 | next_state = BNX2X_Q_STATE_ACTIVE; | |
5543 | ||
6383c0b3 AE |
5544 | else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) { |
5545 | next_state = BNX2X_Q_STATE_MULTI_COS; | |
5546 | next_tx_only = 1; | |
5547 | } | |
5548 | ||
619c5cb6 VZ |
5549 | else if (cmd == BNX2X_Q_CMD_HALT) |
5550 | next_state = BNX2X_Q_STATE_STOPPED; | |
5551 | ||
5552 | else if (cmd == BNX2X_Q_CMD_UPDATE) { | |
6383c0b3 AE |
5553 | /* If "active" state change is requested, update the |
5554 | * state accordingly. | |
5555 | */ | |
5556 | if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, | |
5557 | &update_params->update_flags) && | |
5558 | !test_bit(BNX2X_Q_UPDATE_ACTIVATE, | |
5559 | &update_params->update_flags)) | |
5560 | next_state = BNX2X_Q_STATE_INACTIVE; | |
5561 | else | |
5562 | next_state = BNX2X_Q_STATE_ACTIVE; | |
5563 | } | |
5564 | ||
5565 | break; | |
5566 | case BNX2X_Q_STATE_MULTI_COS: | |
5567 | if (cmd == BNX2X_Q_CMD_TERMINATE) | |
5568 | next_state = BNX2X_Q_STATE_MCOS_TERMINATED; | |
5569 | ||
5570 | else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) { | |
5571 | next_state = BNX2X_Q_STATE_MULTI_COS; | |
5572 | next_tx_only = o->num_tx_only + 1; | |
5573 | } | |
5574 | ||
5575 | else if ((cmd == BNX2X_Q_CMD_EMPTY) || | |
5576 | (cmd == BNX2X_Q_CMD_UPDATE_TPA)) | |
5577 | next_state = BNX2X_Q_STATE_MULTI_COS; | |
619c5cb6 | 5578 | |
6383c0b3 | 5579 | else if (cmd == BNX2X_Q_CMD_UPDATE) { |
619c5cb6 VZ |
5580 | /* If "active" state change is requested, update the |
5581 | * state accordingly. | |
5582 | */ | |
5583 | if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, | |
5584 | &update_params->update_flags) && | |
5585 | !test_bit(BNX2X_Q_UPDATE_ACTIVATE, | |
5586 | &update_params->update_flags)) | |
5587 | next_state = BNX2X_Q_STATE_INACTIVE; | |
5588 | else | |
6383c0b3 AE |
5589 | next_state = BNX2X_Q_STATE_MULTI_COS; |
5590 | } | |
5591 | ||
5592 | break; | |
5593 | case BNX2X_Q_STATE_MCOS_TERMINATED: | |
5594 | if (cmd == BNX2X_Q_CMD_CFC_DEL) { | |
5595 | next_tx_only = o->num_tx_only - 1; | |
5596 | if (next_tx_only == 0) | |
619c5cb6 | 5597 | next_state = BNX2X_Q_STATE_ACTIVE; |
6383c0b3 AE |
5598 | else |
5599 | next_state = BNX2X_Q_STATE_MULTI_COS; | |
619c5cb6 VZ |
5600 | } |
5601 | ||
5602 | break; | |
5603 | case BNX2X_Q_STATE_INACTIVE: | |
5604 | if (cmd == BNX2X_Q_CMD_ACTIVATE) | |
5605 | next_state = BNX2X_Q_STATE_ACTIVE; | |
5606 | ||
5607 | else if ((cmd == BNX2X_Q_CMD_EMPTY) || | |
5608 | (cmd == BNX2X_Q_CMD_UPDATE_TPA)) | |
5609 | next_state = BNX2X_Q_STATE_INACTIVE; | |
5610 | ||
5611 | else if (cmd == BNX2X_Q_CMD_HALT) | |
5612 | next_state = BNX2X_Q_STATE_STOPPED; | |
5613 | ||
5614 | else if (cmd == BNX2X_Q_CMD_UPDATE) { | |
619c5cb6 VZ |
5615 | /* If "active" state change is requested, update the |
5616 | * state accordingly. | |
5617 | */ | |
5618 | if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, | |
5619 | &update_params->update_flags) && | |
5620 | test_bit(BNX2X_Q_UPDATE_ACTIVATE, | |
6383c0b3 AE |
5621 | &update_params->update_flags)){ |
5622 | if (o->num_tx_only == 0) | |
5623 | next_state = BNX2X_Q_STATE_ACTIVE; | |
5624 | else /* tx only queues exist for this queue */ | |
5625 | next_state = BNX2X_Q_STATE_MULTI_COS; | |
5626 | } else | |
619c5cb6 VZ |
5627 | next_state = BNX2X_Q_STATE_INACTIVE; |
5628 | } | |
5629 | ||
5630 | break; | |
5631 | case BNX2X_Q_STATE_STOPPED: | |
5632 | if (cmd == BNX2X_Q_CMD_TERMINATE) | |
5633 | next_state = BNX2X_Q_STATE_TERMINATED; | |
5634 | ||
5635 | break; | |
5636 | case BNX2X_Q_STATE_TERMINATED: | |
5637 | if (cmd == BNX2X_Q_CMD_CFC_DEL) | |
5638 | next_state = BNX2X_Q_STATE_RESET; | |
5639 | ||
5640 | break; | |
5641 | default: | |
5642 | BNX2X_ERR("Illegal state: %d\n", state); | |
5643 | } | |
5644 | ||
5645 | /* Transition is assured */ | |
5646 | if (next_state != BNX2X_Q_STATE_MAX) { | |
5647 | DP(BNX2X_MSG_SP, "Good state transition: %d(%d)->%d\n", | |
5648 | state, cmd, next_state); | |
5649 | o->next_state = next_state; | |
6383c0b3 | 5650 | o->next_tx_only = next_tx_only; |
619c5cb6 VZ |
5651 | return 0; |
5652 | } | |
5653 | ||
5654 | DP(BNX2X_MSG_SP, "Bad state transition request: %d %d\n", state, cmd); | |
5655 | ||
5656 | return -EINVAL; | |
5657 | } | |
5658 | ||
5659 | void bnx2x_init_queue_obj(struct bnx2x *bp, | |
5660 | struct bnx2x_queue_sp_obj *obj, | |
6383c0b3 AE |
5661 | u8 cl_id, u32 *cids, u8 cid_cnt, u8 func_id, |
5662 | void *rdata, | |
619c5cb6 VZ |
5663 | dma_addr_t rdata_mapping, unsigned long type) |
5664 | { | |
5665 | memset(obj, 0, sizeof(*obj)); | |
5666 | ||
6383c0b3 AE |
5667 | /* We support only BNX2X_MULTI_TX_COS Tx CoS at the moment */ |
5668 | BUG_ON(BNX2X_MULTI_TX_COS < cid_cnt); | |
5669 | ||
5670 | memcpy(obj->cids, cids, sizeof(obj->cids[0]) * cid_cnt); | |
5671 | obj->max_cos = cid_cnt; | |
619c5cb6 VZ |
5672 | obj->cl_id = cl_id; |
5673 | obj->func_id = func_id; | |
5674 | obj->rdata = rdata; | |
5675 | obj->rdata_mapping = rdata_mapping; | |
5676 | obj->type = type; | |
5677 | obj->next_state = BNX2X_Q_STATE_MAX; | |
5678 | ||
5679 | if (CHIP_IS_E1x(bp)) | |
5680 | obj->send_cmd = bnx2x_queue_send_cmd_e1x; | |
5681 | else | |
5682 | obj->send_cmd = bnx2x_queue_send_cmd_e2; | |
5683 | ||
5684 | obj->check_transition = bnx2x_queue_chk_transition; | |
5685 | ||
5686 | obj->complete_cmd = bnx2x_queue_comp_cmd; | |
5687 | obj->wait_comp = bnx2x_queue_wait_comp; | |
5688 | obj->set_pending = bnx2x_queue_set_pending; | |
5689 | } | |
5690 | ||
67c431a5 AE |
5691 | /* return a queue object's logical state*/ |
5692 | int bnx2x_get_q_logical_state(struct bnx2x *bp, | |
5693 | struct bnx2x_queue_sp_obj *obj) | |
5694 | { | |
5695 | switch (obj->state) { | |
5696 | case BNX2X_Q_STATE_ACTIVE: | |
5697 | case BNX2X_Q_STATE_MULTI_COS: | |
5698 | return BNX2X_Q_LOGICAL_STATE_ACTIVE; | |
5699 | case BNX2X_Q_STATE_RESET: | |
5700 | case BNX2X_Q_STATE_INITIALIZED: | |
5701 | case BNX2X_Q_STATE_MCOS_TERMINATED: | |
5702 | case BNX2X_Q_STATE_INACTIVE: | |
5703 | case BNX2X_Q_STATE_STOPPED: | |
5704 | case BNX2X_Q_STATE_TERMINATED: | |
5705 | case BNX2X_Q_STATE_FLRED: | |
5706 | return BNX2X_Q_LOGICAL_STATE_STOPPED; | |
5707 | default: | |
5708 | return -EINVAL; | |
5709 | } | |
5710 | } | |
5711 | ||
619c5cb6 | 5712 | /********************** Function state object *********************************/ |
6debea87 DK |
5713 | enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp, |
5714 | struct bnx2x_func_sp_obj *o) | |
5715 | { | |
5716 | /* in the middle of transaction - return INVALID state */ | |
5717 | if (o->pending) | |
5718 | return BNX2X_F_STATE_MAX; | |
5719 | ||
16a5fd92 | 5720 | /* unsure the order of reading of o->pending and o->state |
6debea87 DK |
5721 | * o->pending should be read first |
5722 | */ | |
5723 | rmb(); | |
5724 | ||
5725 | return o->state; | |
5726 | } | |
619c5cb6 VZ |
5727 | |
5728 | static int bnx2x_func_wait_comp(struct bnx2x *bp, | |
5729 | struct bnx2x_func_sp_obj *o, | |
5730 | enum bnx2x_func_cmd cmd) | |
5731 | { | |
5732 | return bnx2x_state_wait(bp, cmd, &o->pending); | |
5733 | } | |
5734 | ||
5735 | /** | |
5736 | * bnx2x_func_state_change_comp - complete the state machine transition | |
5737 | * | |
5738 | * @bp: device handle | |
5739 | * @o: | |
5740 | * @cmd: | |
5741 | * | |
5742 | * Called on state change transition. Completes the state | |
5743 | * machine transition only - no HW interaction. | |
5744 | */ | |
5745 | static inline int bnx2x_func_state_change_comp(struct bnx2x *bp, | |
5746 | struct bnx2x_func_sp_obj *o, | |
5747 | enum bnx2x_func_cmd cmd) | |
5748 | { | |
5749 | unsigned long cur_pending = o->pending; | |
5750 | ||
5751 | if (!test_and_clear_bit(cmd, &cur_pending)) { | |
51c1a580 MS |
5752 | BNX2X_ERR("Bad MC reply %d for func %d in state %d pending 0x%lx, next_state %d\n", |
5753 | cmd, BP_FUNC(bp), o->state, | |
5754 | cur_pending, o->next_state); | |
619c5cb6 VZ |
5755 | return -EINVAL; |
5756 | } | |
5757 | ||
94f05b0f JP |
5758 | DP(BNX2X_MSG_SP, |
5759 | "Completing command %d for func %d, setting state to %d\n", | |
5760 | cmd, BP_FUNC(bp), o->next_state); | |
619c5cb6 VZ |
5761 | |
5762 | o->state = o->next_state; | |
5763 | o->next_state = BNX2X_F_STATE_MAX; | |
5764 | ||
5765 | /* It's important that o->state and o->next_state are | |
5766 | * updated before o->pending. | |
5767 | */ | |
5768 | wmb(); | |
5769 | ||
5770 | clear_bit(cmd, &o->pending); | |
4e857c58 | 5771 | smp_mb__after_atomic(); |
619c5cb6 VZ |
5772 | |
5773 | return 0; | |
5774 | } | |
5775 | ||
5776 | /** | |
5777 | * bnx2x_func_comp_cmd - complete the state change command | |
5778 | * | |
5779 | * @bp: device handle | |
5780 | * @o: | |
5781 | * @cmd: | |
5782 | * | |
5783 | * Checks that the arrived completion is expected. | |
5784 | */ | |
5785 | static int bnx2x_func_comp_cmd(struct bnx2x *bp, | |
5786 | struct bnx2x_func_sp_obj *o, | |
5787 | enum bnx2x_func_cmd cmd) | |
5788 | { | |
5789 | /* Complete the state machine part first, check if it's a | |
5790 | * legal completion. | |
5791 | */ | |
5792 | int rc = bnx2x_func_state_change_comp(bp, o, cmd); | |
5793 | return rc; | |
5794 | } | |
5795 | ||
5796 | /** | |
5797 | * bnx2x_func_chk_transition - perform function state machine transition | |
5798 | * | |
5799 | * @bp: device handle | |
5800 | * @o: | |
5801 | * @params: | |
5802 | * | |
5803 | * It both checks if the requested command is legal in a current | |
5804 | * state and, if it's legal, sets a `next_state' in the object | |
5805 | * that will be used in the completion flow to set the `state' | |
5806 | * of the object. | |
5807 | * | |
5808 | * returns 0 if a requested command is a legal transition, | |
5809 | * -EINVAL otherwise. | |
5810 | */ | |
5811 | static int bnx2x_func_chk_transition(struct bnx2x *bp, | |
5812 | struct bnx2x_func_sp_obj *o, | |
5813 | struct bnx2x_func_state_params *params) | |
5814 | { | |
5815 | enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX; | |
5816 | enum bnx2x_func_cmd cmd = params->cmd; | |
5817 | ||
16a5fd92 | 5818 | /* Forget all pending for completion commands if a driver only state |
6debea87 DK |
5819 | * transition has been requested. |
5820 | */ | |
5821 | if (test_bit(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) { | |
5822 | o->pending = 0; | |
5823 | o->next_state = BNX2X_F_STATE_MAX; | |
5824 | } | |
5825 | ||
16a5fd92 | 5826 | /* Don't allow a next state transition if we are in the middle of |
6debea87 DK |
5827 | * the previous one. |
5828 | */ | |
5829 | if (o->pending) | |
5830 | return -EBUSY; | |
5831 | ||
619c5cb6 VZ |
5832 | switch (state) { |
5833 | case BNX2X_F_STATE_RESET: | |
5834 | if (cmd == BNX2X_F_CMD_HW_INIT) | |
5835 | next_state = BNX2X_F_STATE_INITIALIZED; | |
5836 | ||
5837 | break; | |
5838 | case BNX2X_F_STATE_INITIALIZED: | |
5839 | if (cmd == BNX2X_F_CMD_START) | |
5840 | next_state = BNX2X_F_STATE_STARTED; | |
5841 | ||
5842 | else if (cmd == BNX2X_F_CMD_HW_RESET) | |
5843 | next_state = BNX2X_F_STATE_RESET; | |
5844 | ||
5845 | break; | |
5846 | case BNX2X_F_STATE_STARTED: | |
5847 | if (cmd == BNX2X_F_CMD_STOP) | |
5848 | next_state = BNX2X_F_STATE_INITIALIZED; | |
a3348722 BW |
5849 | /* afex ramrods can be sent only in started mode, and only |
5850 | * if not pending for function_stop ramrod completion | |
5851 | * for these events - next state remained STARTED. | |
5852 | */ | |
5853 | else if ((cmd == BNX2X_F_CMD_AFEX_UPDATE) && | |
5854 | (!test_bit(BNX2X_F_CMD_STOP, &o->pending))) | |
5855 | next_state = BNX2X_F_STATE_STARTED; | |
5856 | ||
5857 | else if ((cmd == BNX2X_F_CMD_AFEX_VIFLISTS) && | |
5858 | (!test_bit(BNX2X_F_CMD_STOP, &o->pending))) | |
5859 | next_state = BNX2X_F_STATE_STARTED; | |
55c11941 MS |
5860 | |
5861 | /* Switch_update ramrod can be sent in either started or | |
5862 | * tx_stopped state, and it doesn't change the state. | |
5863 | */ | |
5864 | else if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) && | |
5865 | (!test_bit(BNX2X_F_CMD_STOP, &o->pending))) | |
5866 | next_state = BNX2X_F_STATE_STARTED; | |
5867 | ||
eeed018c MK |
5868 | else if ((cmd == BNX2X_F_CMD_SET_TIMESYNC) && |
5869 | (!test_bit(BNX2X_F_CMD_STOP, &o->pending))) | |
5870 | next_state = BNX2X_F_STATE_STARTED; | |
5871 | ||
6debea87 DK |
5872 | else if (cmd == BNX2X_F_CMD_TX_STOP) |
5873 | next_state = BNX2X_F_STATE_TX_STOPPED; | |
5874 | ||
5875 | break; | |
5876 | case BNX2X_F_STATE_TX_STOPPED: | |
55c11941 MS |
5877 | if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) && |
5878 | (!test_bit(BNX2X_F_CMD_STOP, &o->pending))) | |
5879 | next_state = BNX2X_F_STATE_TX_STOPPED; | |
5880 | ||
eeed018c MK |
5881 | else if ((cmd == BNX2X_F_CMD_SET_TIMESYNC) && |
5882 | (!test_bit(BNX2X_F_CMD_STOP, &o->pending))) | |
5883 | next_state = BNX2X_F_STATE_TX_STOPPED; | |
5884 | ||
55c11941 | 5885 | else if (cmd == BNX2X_F_CMD_TX_START) |
6debea87 | 5886 | next_state = BNX2X_F_STATE_STARTED; |
619c5cb6 VZ |
5887 | |
5888 | break; | |
5889 | default: | |
5890 | BNX2X_ERR("Unknown state: %d\n", state); | |
5891 | } | |
5892 | ||
5893 | /* Transition is assured */ | |
5894 | if (next_state != BNX2X_F_STATE_MAX) { | |
5895 | DP(BNX2X_MSG_SP, "Good function state transition: %d(%d)->%d\n", | |
5896 | state, cmd, next_state); | |
5897 | o->next_state = next_state; | |
5898 | return 0; | |
5899 | } | |
5900 | ||
5901 | DP(BNX2X_MSG_SP, "Bad function state transition request: %d %d\n", | |
5902 | state, cmd); | |
5903 | ||
5904 | return -EINVAL; | |
5905 | } | |
5906 | ||
5907 | /** | |
5908 | * bnx2x_func_init_func - performs HW init at function stage | |
5909 | * | |
5910 | * @bp: device handle | |
5911 | * @drv: | |
5912 | * | |
5913 | * Init HW when the current phase is | |
5914 | * FW_MSG_CODE_DRV_LOAD_FUNCTION: initialize only FUNCTION-only | |
5915 | * HW blocks. | |
5916 | */ | |
5917 | static inline int bnx2x_func_init_func(struct bnx2x *bp, | |
5918 | const struct bnx2x_func_sp_drv_ops *drv) | |
5919 | { | |
5920 | return drv->init_hw_func(bp); | |
5921 | } | |
5922 | ||
5923 | /** | |
5924 | * bnx2x_func_init_port - performs HW init at port stage | |
5925 | * | |
5926 | * @bp: device handle | |
5927 | * @drv: | |
5928 | * | |
5929 | * Init HW when the current phase is | |
5930 | * FW_MSG_CODE_DRV_LOAD_PORT: initialize PORT-only and | |
5931 | * FUNCTION-only HW blocks. | |
5932 | * | |
5933 | */ | |
5934 | static inline int bnx2x_func_init_port(struct bnx2x *bp, | |
5935 | const struct bnx2x_func_sp_drv_ops *drv) | |
5936 | { | |
5937 | int rc = drv->init_hw_port(bp); | |
5938 | if (rc) | |
5939 | return rc; | |
5940 | ||
5941 | return bnx2x_func_init_func(bp, drv); | |
5942 | } | |
5943 | ||
5944 | /** | |
5945 | * bnx2x_func_init_cmn_chip - performs HW init at chip-common stage | |
5946 | * | |
5947 | * @bp: device handle | |
5948 | * @drv: | |
5949 | * | |
5950 | * Init HW when the current phase is | |
5951 | * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON_CHIP, | |
5952 | * PORT-only and FUNCTION-only HW blocks. | |
5953 | */ | |
5954 | static inline int bnx2x_func_init_cmn_chip(struct bnx2x *bp, | |
5955 | const struct bnx2x_func_sp_drv_ops *drv) | |
5956 | { | |
5957 | int rc = drv->init_hw_cmn_chip(bp); | |
5958 | if (rc) | |
5959 | return rc; | |
5960 | ||
5961 | return bnx2x_func_init_port(bp, drv); | |
5962 | } | |
5963 | ||
5964 | /** | |
5965 | * bnx2x_func_init_cmn - performs HW init at common stage | |
5966 | * | |
5967 | * @bp: device handle | |
5968 | * @drv: | |
5969 | * | |
5970 | * Init HW when the current phase is | |
5971 | * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON, | |
5972 | * PORT-only and FUNCTION-only HW blocks. | |
5973 | */ | |
5974 | static inline int bnx2x_func_init_cmn(struct bnx2x *bp, | |
5975 | const struct bnx2x_func_sp_drv_ops *drv) | |
5976 | { | |
5977 | int rc = drv->init_hw_cmn(bp); | |
5978 | if (rc) | |
5979 | return rc; | |
5980 | ||
5981 | return bnx2x_func_init_port(bp, drv); | |
5982 | } | |
5983 | ||
5984 | static int bnx2x_func_hw_init(struct bnx2x *bp, | |
5985 | struct bnx2x_func_state_params *params) | |
5986 | { | |
5987 | u32 load_code = params->params.hw_init.load_phase; | |
5988 | struct bnx2x_func_sp_obj *o = params->f_obj; | |
5989 | const struct bnx2x_func_sp_drv_ops *drv = o->drv; | |
5990 | int rc = 0; | |
5991 | ||
5992 | DP(BNX2X_MSG_SP, "function %d load_code %x\n", | |
5993 | BP_ABS_FUNC(bp), load_code); | |
5994 | ||
5995 | /* Prepare buffers for unzipping the FW */ | |
5996 | rc = drv->gunzip_init(bp); | |
5997 | if (rc) | |
5998 | return rc; | |
5999 | ||
6000 | /* Prepare FW */ | |
6001 | rc = drv->init_fw(bp); | |
6002 | if (rc) { | |
6003 | BNX2X_ERR("Error loading firmware\n"); | |
eb2afd4a | 6004 | goto init_err; |
619c5cb6 VZ |
6005 | } |
6006 | ||
16a5fd92 | 6007 | /* Handle the beginning of COMMON_XXX pases separately... */ |
619c5cb6 VZ |
6008 | switch (load_code) { |
6009 | case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: | |
6010 | rc = bnx2x_func_init_cmn_chip(bp, drv); | |
6011 | if (rc) | |
eb2afd4a | 6012 | goto init_err; |
619c5cb6 VZ |
6013 | |
6014 | break; | |
6015 | case FW_MSG_CODE_DRV_LOAD_COMMON: | |
6016 | rc = bnx2x_func_init_cmn(bp, drv); | |
6017 | if (rc) | |
eb2afd4a | 6018 | goto init_err; |
619c5cb6 VZ |
6019 | |
6020 | break; | |
6021 | case FW_MSG_CODE_DRV_LOAD_PORT: | |
6022 | rc = bnx2x_func_init_port(bp, drv); | |
6023 | if (rc) | |
eb2afd4a | 6024 | goto init_err; |
619c5cb6 VZ |
6025 | |
6026 | break; | |
6027 | case FW_MSG_CODE_DRV_LOAD_FUNCTION: | |
6028 | rc = bnx2x_func_init_func(bp, drv); | |
6029 | if (rc) | |
eb2afd4a | 6030 | goto init_err; |
619c5cb6 VZ |
6031 | |
6032 | break; | |
6033 | default: | |
6034 | BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code); | |
6035 | rc = -EINVAL; | |
6036 | } | |
6037 | ||
eb2afd4a | 6038 | init_err: |
619c5cb6 VZ |
6039 | drv->gunzip_end(bp); |
6040 | ||
16a5fd92 | 6041 | /* In case of success, complete the command immediately: no ramrods |
619c5cb6 VZ |
6042 | * have been sent. |
6043 | */ | |
6044 | if (!rc) | |
6045 | o->complete_cmd(bp, o, BNX2X_F_CMD_HW_INIT); | |
6046 | ||
6047 | return rc; | |
6048 | } | |
6049 | ||
6050 | /** | |
6051 | * bnx2x_func_reset_func - reset HW at function stage | |
6052 | * | |
6053 | * @bp: device handle | |
6054 | * @drv: | |
6055 | * | |
6056 | * Reset HW at FW_MSG_CODE_DRV_UNLOAD_FUNCTION stage: reset only | |
6057 | * FUNCTION-only HW blocks. | |
6058 | */ | |
6059 | static inline void bnx2x_func_reset_func(struct bnx2x *bp, | |
6060 | const struct bnx2x_func_sp_drv_ops *drv) | |
6061 | { | |
6062 | drv->reset_hw_func(bp); | |
6063 | } | |
6064 | ||
6065 | /** | |
16a5fd92 | 6066 | * bnx2x_func_reset_port - reset HW at port stage |
619c5cb6 VZ |
6067 | * |
6068 | * @bp: device handle | |
6069 | * @drv: | |
6070 | * | |
6071 | * Reset HW at FW_MSG_CODE_DRV_UNLOAD_PORT stage: reset | |
6072 | * FUNCTION-only and PORT-only HW blocks. | |
6073 | * | |
6074 | * !!!IMPORTANT!!! | |
6075 | * | |
6076 | * It's important to call reset_port before reset_func() as the last thing | |
6077 | * reset_func does is pf_disable() thus disabling PGLUE_B, which | |
6078 | * makes impossible any DMAE transactions. | |
6079 | */ | |
6080 | static inline void bnx2x_func_reset_port(struct bnx2x *bp, | |
6081 | const struct bnx2x_func_sp_drv_ops *drv) | |
6082 | { | |
6083 | drv->reset_hw_port(bp); | |
6084 | bnx2x_func_reset_func(bp, drv); | |
6085 | } | |
6086 | ||
6087 | /** | |
16a5fd92 | 6088 | * bnx2x_func_reset_cmn - reset HW at common stage |
619c5cb6 VZ |
6089 | * |
6090 | * @bp: device handle | |
6091 | * @drv: | |
6092 | * | |
6093 | * Reset HW at FW_MSG_CODE_DRV_UNLOAD_COMMON and | |
6094 | * FW_MSG_CODE_DRV_UNLOAD_COMMON_CHIP stages: reset COMMON, | |
6095 | * COMMON_CHIP, FUNCTION-only and PORT-only HW blocks. | |
6096 | */ | |
6097 | static inline void bnx2x_func_reset_cmn(struct bnx2x *bp, | |
6098 | const struct bnx2x_func_sp_drv_ops *drv) | |
6099 | { | |
6100 | bnx2x_func_reset_port(bp, drv); | |
6101 | drv->reset_hw_cmn(bp); | |
6102 | } | |
6103 | ||
619c5cb6 VZ |
6104 | static inline int bnx2x_func_hw_reset(struct bnx2x *bp, |
6105 | struct bnx2x_func_state_params *params) | |
6106 | { | |
6107 | u32 reset_phase = params->params.hw_reset.reset_phase; | |
6108 | struct bnx2x_func_sp_obj *o = params->f_obj; | |
6109 | const struct bnx2x_func_sp_drv_ops *drv = o->drv; | |
6110 | ||
6111 | DP(BNX2X_MSG_SP, "function %d reset_phase %x\n", BP_ABS_FUNC(bp), | |
6112 | reset_phase); | |
6113 | ||
6114 | switch (reset_phase) { | |
6115 | case FW_MSG_CODE_DRV_UNLOAD_COMMON: | |
6116 | bnx2x_func_reset_cmn(bp, drv); | |
6117 | break; | |
6118 | case FW_MSG_CODE_DRV_UNLOAD_PORT: | |
6119 | bnx2x_func_reset_port(bp, drv); | |
6120 | break; | |
6121 | case FW_MSG_CODE_DRV_UNLOAD_FUNCTION: | |
6122 | bnx2x_func_reset_func(bp, drv); | |
6123 | break; | |
6124 | default: | |
6125 | BNX2X_ERR("Unknown reset_phase (0x%x) from MCP\n", | |
6126 | reset_phase); | |
6127 | break; | |
6128 | } | |
6129 | ||
16a5fd92 | 6130 | /* Complete the command immediately: no ramrods have been sent. */ |
619c5cb6 VZ |
6131 | o->complete_cmd(bp, o, BNX2X_F_CMD_HW_RESET); |
6132 | ||
6133 | return 0; | |
6134 | } | |
6135 | ||
6136 | static inline int bnx2x_func_send_start(struct bnx2x *bp, | |
6137 | struct bnx2x_func_state_params *params) | |
6138 | { | |
6139 | struct bnx2x_func_sp_obj *o = params->f_obj; | |
6140 | struct function_start_data *rdata = | |
6141 | (struct function_start_data *)o->rdata; | |
6142 | dma_addr_t data_mapping = o->rdata_mapping; | |
6143 | struct bnx2x_func_start_params *start_params = ¶ms->params.start; | |
6144 | ||
6145 | memset(rdata, 0, sizeof(*rdata)); | |
6146 | ||
6147 | /* Fill the ramrod data with provided parameters */ | |
1bc277f7 DK |
6148 | rdata->function_mode = (u8)start_params->mf_mode; |
6149 | rdata->sd_vlan_tag = cpu_to_le16(start_params->sd_vlan_tag); | |
6150 | rdata->path_id = BP_PATH(bp); | |
6151 | rdata->network_cos_mode = start_params->network_cos_mode; | |
77e461d1 | 6152 | rdata->dmae_cmd_id = BNX2X_FW_DMAE_C; |
28311f8e YM |
6153 | |
6154 | rdata->vxlan_dst_port = cpu_to_le16(start_params->vxlan_dst_port); | |
6155 | rdata->geneve_dst_port = cpu_to_le16(start_params->geneve_dst_port); | |
6156 | rdata->inner_clss_l2gre = start_params->inner_clss_l2gre; | |
6157 | rdata->inner_clss_l2geneve = start_params->inner_clss_l2geneve; | |
6158 | rdata->inner_clss_vxlan = start_params->inner_clss_vxlan; | |
6159 | rdata->inner_rss = start_params->inner_rss; | |
6160 | ||
7609647e YM |
6161 | rdata->sd_accept_mf_clss_fail = start_params->class_fail; |
6162 | if (start_params->class_fail_ethtype) { | |
6163 | rdata->sd_accept_mf_clss_fail_match_ethtype = 1; | |
6164 | rdata->sd_accept_mf_clss_fail_ethtype = | |
6165 | cpu_to_le16(start_params->class_fail_ethtype); | |
6166 | } | |
6167 | ||
6168 | rdata->sd_vlan_force_pri_flg = start_params->sd_vlan_force_pri; | |
6169 | rdata->sd_vlan_force_pri_val = start_params->sd_vlan_force_pri_val; | |
6170 | if (start_params->sd_vlan_eth_type) | |
6171 | rdata->sd_vlan_eth_type = | |
6172 | cpu_to_le16(start_params->sd_vlan_eth_type); | |
6173 | else | |
6174 | rdata->sd_vlan_eth_type = | |
6175 | cpu_to_le16(0x8100); | |
1bc277f7 | 6176 | |
7609647e | 6177 | rdata->no_added_tags = start_params->no_added_tags; |
28311f8e YM |
6178 | |
6179 | rdata->c2s_pri_tt_valid = start_params->c2s_pri_valid; | |
6180 | if (rdata->c2s_pri_tt_valid) { | |
6181 | memcpy(rdata->c2s_pri_trans_table.val, | |
6182 | start_params->c2s_pri, | |
6183 | MAX_VLAN_PRIORITIES); | |
6184 | rdata->c2s_pri_default = start_params->c2s_pri_default; | |
6185 | } | |
1bc277f7 DK |
6186 | /* No need for an explicit memory barrier here as long we would |
6187 | * need to ensure the ordering of writing to the SPQ element | |
6188 | * and updating of the SPQ producer which involves a memory | |
6189 | * read and we will have to put a full memory barrier there | |
6190 | * (inside bnx2x_sp_post()). | |
53e51e2f | 6191 | */ |
619c5cb6 VZ |
6192 | |
6193 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0, | |
6194 | U64_HI(data_mapping), | |
6195 | U64_LO(data_mapping), NONE_CONNECTION_TYPE); | |
6196 | } | |
6197 | ||
55c11941 MS |
6198 | static inline int bnx2x_func_send_switch_update(struct bnx2x *bp, |
6199 | struct bnx2x_func_state_params *params) | |
6200 | { | |
6201 | struct bnx2x_func_sp_obj *o = params->f_obj; | |
6202 | struct function_update_data *rdata = | |
6203 | (struct function_update_data *)o->rdata; | |
6204 | dma_addr_t data_mapping = o->rdata_mapping; | |
6205 | struct bnx2x_func_switch_update_params *switch_update_params = | |
6206 | ¶ms->params.switch_update; | |
6207 | ||
6208 | memset(rdata, 0, sizeof(*rdata)); | |
6209 | ||
6210 | /* Fill the ramrod data with provided parameters */ | |
e42780b6 DK |
6211 | if (test_bit(BNX2X_F_UPDATE_TX_SWITCH_SUSPEND_CHNG, |
6212 | &switch_update_params->changes)) { | |
6213 | rdata->tx_switch_suspend_change_flg = 1; | |
6214 | rdata->tx_switch_suspend = | |
6215 | test_bit(BNX2X_F_UPDATE_TX_SWITCH_SUSPEND, | |
6216 | &switch_update_params->changes); | |
6217 | } | |
6218 | ||
7609647e YM |
6219 | if (test_bit(BNX2X_F_UPDATE_SD_VLAN_TAG_CHNG, |
6220 | &switch_update_params->changes)) { | |
6221 | rdata->sd_vlan_tag_change_flg = 1; | |
6222 | rdata->sd_vlan_tag = | |
6223 | cpu_to_le16(switch_update_params->vlan); | |
6224 | } | |
6225 | ||
6226 | if (test_bit(BNX2X_F_UPDATE_SD_VLAN_ETH_TYPE_CHNG, | |
6227 | &switch_update_params->changes)) { | |
6228 | rdata->sd_vlan_eth_type_change_flg = 1; | |
6229 | rdata->sd_vlan_eth_type = | |
6230 | cpu_to_le16(switch_update_params->vlan_eth_type); | |
6231 | } | |
6232 | ||
6233 | if (test_bit(BNX2X_F_UPDATE_VLAN_FORCE_PRIO_CHNG, | |
6234 | &switch_update_params->changes)) { | |
6235 | rdata->sd_vlan_force_pri_change_flg = 1; | |
6236 | if (test_bit(BNX2X_F_UPDATE_VLAN_FORCE_PRIO_FLAG, | |
6237 | &switch_update_params->changes)) | |
6238 | rdata->sd_vlan_force_pri_flg = 1; | |
6239 | rdata->sd_vlan_force_pri_flg = | |
6240 | switch_update_params->vlan_force_prio; | |
6241 | } | |
6242 | ||
e42780b6 DK |
6243 | if (test_bit(BNX2X_F_UPDATE_TUNNEL_CFG_CHNG, |
6244 | &switch_update_params->changes)) { | |
6245 | rdata->update_tunn_cfg_flg = 1; | |
28311f8e YM |
6246 | if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_L2GRE, |
6247 | &switch_update_params->changes)) | |
6248 | rdata->inner_clss_l2gre = 1; | |
6249 | if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_VXLAN, | |
6250 | &switch_update_params->changes)) | |
6251 | rdata->inner_clss_vxlan = 1; | |
6252 | if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_L2GENEVE, | |
e42780b6 | 6253 | &switch_update_params->changes)) |
28311f8e YM |
6254 | rdata->inner_clss_l2geneve = 1; |
6255 | if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_RSS, | |
e42780b6 | 6256 | &switch_update_params->changes)) |
28311f8e YM |
6257 | rdata->inner_rss = 1; |
6258 | rdata->vxlan_dst_port = | |
6259 | cpu_to_le16(switch_update_params->vxlan_dst_port); | |
6260 | rdata->geneve_dst_port = | |
6261 | cpu_to_le16(switch_update_params->geneve_dst_port); | |
e42780b6 DK |
6262 | } |
6263 | ||
55c11941 MS |
6264 | rdata->echo = SWITCH_UPDATE; |
6265 | ||
14a94ebd MK |
6266 | /* No need for an explicit memory barrier here as long as we |
6267 | * ensure the ordering of writing to the SPQ element | |
6268 | * and updating of the SPQ producer which involves a memory | |
6269 | * read. If the memory read is removed we will have to put a | |
6270 | * full memory barrier there (inside bnx2x_sp_post()). | |
6271 | */ | |
55c11941 MS |
6272 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0, |
6273 | U64_HI(data_mapping), | |
6274 | U64_LO(data_mapping), NONE_CONNECTION_TYPE); | |
6275 | } | |
6276 | ||
a3348722 BW |
6277 | static inline int bnx2x_func_send_afex_update(struct bnx2x *bp, |
6278 | struct bnx2x_func_state_params *params) | |
6279 | { | |
6280 | struct bnx2x_func_sp_obj *o = params->f_obj; | |
6281 | struct function_update_data *rdata = | |
6282 | (struct function_update_data *)o->afex_rdata; | |
6283 | dma_addr_t data_mapping = o->afex_rdata_mapping; | |
6284 | struct bnx2x_func_afex_update_params *afex_update_params = | |
6285 | ¶ms->params.afex_update; | |
6286 | ||
6287 | memset(rdata, 0, sizeof(*rdata)); | |
6288 | ||
6289 | /* Fill the ramrod data with provided parameters */ | |
6290 | rdata->vif_id_change_flg = 1; | |
6291 | rdata->vif_id = cpu_to_le16(afex_update_params->vif_id); | |
6292 | rdata->afex_default_vlan_change_flg = 1; | |
6293 | rdata->afex_default_vlan = | |
6294 | cpu_to_le16(afex_update_params->afex_default_vlan); | |
6295 | rdata->allowed_priorities_change_flg = 1; | |
6296 | rdata->allowed_priorities = afex_update_params->allowed_priorities; | |
55c11941 | 6297 | rdata->echo = AFEX_UPDATE; |
a3348722 | 6298 | |
14a94ebd MK |
6299 | /* No need for an explicit memory barrier here as long as we |
6300 | * ensure the ordering of writing to the SPQ element | |
6301 | * and updating of the SPQ producer which involves a memory | |
6302 | * read. If the memory read is removed we will have to put a | |
6303 | * full memory barrier there (inside bnx2x_sp_post()). | |
a3348722 BW |
6304 | */ |
6305 | DP(BNX2X_MSG_SP, | |
6306 | "afex: sending func_update vif_id 0x%x dvlan 0x%x prio 0x%x\n", | |
6307 | rdata->vif_id, | |
6308 | rdata->afex_default_vlan, rdata->allowed_priorities); | |
6309 | ||
6310 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0, | |
6311 | U64_HI(data_mapping), | |
6312 | U64_LO(data_mapping), NONE_CONNECTION_TYPE); | |
6313 | } | |
6314 | ||
6315 | static | |
6316 | inline int bnx2x_func_send_afex_viflists(struct bnx2x *bp, | |
6317 | struct bnx2x_func_state_params *params) | |
6318 | { | |
6319 | struct bnx2x_func_sp_obj *o = params->f_obj; | |
6320 | struct afex_vif_list_ramrod_data *rdata = | |
6321 | (struct afex_vif_list_ramrod_data *)o->afex_rdata; | |
86564c3f | 6322 | struct bnx2x_func_afex_viflists_params *afex_vif_params = |
a3348722 BW |
6323 | ¶ms->params.afex_viflists; |
6324 | u64 *p_rdata = (u64 *)rdata; | |
6325 | ||
6326 | memset(rdata, 0, sizeof(*rdata)); | |
6327 | ||
6328 | /* Fill the ramrod data with provided parameters */ | |
86564c3f YM |
6329 | rdata->vif_list_index = cpu_to_le16(afex_vif_params->vif_list_index); |
6330 | rdata->func_bit_map = afex_vif_params->func_bit_map; | |
6331 | rdata->afex_vif_list_command = afex_vif_params->afex_vif_list_command; | |
6332 | rdata->func_to_clear = afex_vif_params->func_to_clear; | |
a3348722 BW |
6333 | |
6334 | /* send in echo type of sub command */ | |
86564c3f | 6335 | rdata->echo = afex_vif_params->afex_vif_list_command; |
a3348722 BW |
6336 | |
6337 | /* No need for an explicit memory barrier here as long we would | |
6338 | * need to ensure the ordering of writing to the SPQ element | |
6339 | * and updating of the SPQ producer which involves a memory | |
6340 | * read and we will have to put a full memory barrier there | |
6341 | * (inside bnx2x_sp_post()). | |
6342 | */ | |
6343 | ||
6344 | DP(BNX2X_MSG_SP, "afex: ramrod lists, cmd 0x%x index 0x%x func_bit_map 0x%x func_to_clr 0x%x\n", | |
6345 | rdata->afex_vif_list_command, rdata->vif_list_index, | |
6346 | rdata->func_bit_map, rdata->func_to_clear); | |
6347 | ||
6348 | /* this ramrod sends data directly and not through DMA mapping */ | |
6349 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_AFEX_VIF_LISTS, 0, | |
6350 | U64_HI(*p_rdata), U64_LO(*p_rdata), | |
6351 | NONE_CONNECTION_TYPE); | |
6352 | } | |
6353 | ||
619c5cb6 VZ |
6354 | static inline int bnx2x_func_send_stop(struct bnx2x *bp, |
6355 | struct bnx2x_func_state_params *params) | |
6356 | { | |
6357 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0, | |
6358 | NONE_CONNECTION_TYPE); | |
6359 | } | |
6360 | ||
6debea87 DK |
6361 | static inline int bnx2x_func_send_tx_stop(struct bnx2x *bp, |
6362 | struct bnx2x_func_state_params *params) | |
6363 | { | |
6364 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, 0, 0, 0, | |
6365 | NONE_CONNECTION_TYPE); | |
6366 | } | |
6367 | static inline int bnx2x_func_send_tx_start(struct bnx2x *bp, | |
6368 | struct bnx2x_func_state_params *params) | |
6369 | { | |
6370 | struct bnx2x_func_sp_obj *o = params->f_obj; | |
6371 | struct flow_control_configuration *rdata = | |
6372 | (struct flow_control_configuration *)o->rdata; | |
6373 | dma_addr_t data_mapping = o->rdata_mapping; | |
6374 | struct bnx2x_func_tx_start_params *tx_start_params = | |
6375 | ¶ms->params.tx_start; | |
6376 | int i; | |
6377 | ||
6378 | memset(rdata, 0, sizeof(*rdata)); | |
6379 | ||
6380 | rdata->dcb_enabled = tx_start_params->dcb_enabled; | |
6381 | rdata->dcb_version = tx_start_params->dcb_version; | |
6382 | rdata->dont_add_pri_0_en = tx_start_params->dont_add_pri_0_en; | |
6383 | ||
6384 | for (i = 0; i < ARRAY_SIZE(rdata->traffic_type_to_priority_cos); i++) | |
6385 | rdata->traffic_type_to_priority_cos[i] = | |
6386 | tx_start_params->traffic_type_to_priority_cos[i]; | |
6387 | ||
28311f8e YM |
6388 | for (i = 0; i < MAX_TRAFFIC_TYPES; i++) |
6389 | rdata->dcb_outer_pri[i] = tx_start_params->dcb_outer_pri[i]; | |
14a94ebd MK |
6390 | /* No need for an explicit memory barrier here as long as we |
6391 | * ensure the ordering of writing to the SPQ element | |
6392 | * and updating of the SPQ producer which involves a memory | |
6393 | * read. If the memory read is removed we will have to put a | |
6394 | * full memory barrier there (inside bnx2x_sp_post()). | |
6395 | */ | |
6debea87 DK |
6396 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0, |
6397 | U64_HI(data_mapping), | |
6398 | U64_LO(data_mapping), NONE_CONNECTION_TYPE); | |
6399 | } | |
6400 | ||
eeed018c MK |
6401 | static inline |
6402 | int bnx2x_func_send_set_timesync(struct bnx2x *bp, | |
6403 | struct bnx2x_func_state_params *params) | |
6404 | { | |
6405 | struct bnx2x_func_sp_obj *o = params->f_obj; | |
6406 | struct set_timesync_ramrod_data *rdata = | |
6407 | (struct set_timesync_ramrod_data *)o->rdata; | |
6408 | dma_addr_t data_mapping = o->rdata_mapping; | |
6409 | struct bnx2x_func_set_timesync_params *set_timesync_params = | |
6410 | ¶ms->params.set_timesync; | |
6411 | ||
6412 | memset(rdata, 0, sizeof(*rdata)); | |
6413 | ||
6414 | /* Fill the ramrod data with provided parameters */ | |
6415 | rdata->drift_adjust_cmd = set_timesync_params->drift_adjust_cmd; | |
6416 | rdata->offset_cmd = set_timesync_params->offset_cmd; | |
6417 | rdata->add_sub_drift_adjust_value = | |
6418 | set_timesync_params->add_sub_drift_adjust_value; | |
6419 | rdata->drift_adjust_value = set_timesync_params->drift_adjust_value; | |
6420 | rdata->drift_adjust_period = set_timesync_params->drift_adjust_period; | |
8f15c613 MK |
6421 | rdata->offset_delta.lo = |
6422 | cpu_to_le32(U64_LO(set_timesync_params->offset_delta)); | |
6423 | rdata->offset_delta.hi = | |
6424 | cpu_to_le32(U64_HI(set_timesync_params->offset_delta)); | |
eeed018c MK |
6425 | |
6426 | DP(BNX2X_MSG_SP, "Set timesync command params: drift_cmd = %d, offset_cmd = %d, add_sub_drift = %d, drift_val = %d, drift_period = %d, offset_lo = %d, offset_hi = %d\n", | |
6427 | rdata->drift_adjust_cmd, rdata->offset_cmd, | |
6428 | rdata->add_sub_drift_adjust_value, rdata->drift_adjust_value, | |
6429 | rdata->drift_adjust_period, rdata->offset_delta.lo, | |
6430 | rdata->offset_delta.hi); | |
6431 | ||
6432 | return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_TIMESYNC, 0, | |
6433 | U64_HI(data_mapping), | |
6434 | U64_LO(data_mapping), NONE_CONNECTION_TYPE); | |
6435 | } | |
6436 | ||
619c5cb6 VZ |
6437 | static int bnx2x_func_send_cmd(struct bnx2x *bp, |
6438 | struct bnx2x_func_state_params *params) | |
6439 | { | |
6440 | switch (params->cmd) { | |
6441 | case BNX2X_F_CMD_HW_INIT: | |
6442 | return bnx2x_func_hw_init(bp, params); | |
6443 | case BNX2X_F_CMD_START: | |
6444 | return bnx2x_func_send_start(bp, params); | |
6445 | case BNX2X_F_CMD_STOP: | |
6446 | return bnx2x_func_send_stop(bp, params); | |
6447 | case BNX2X_F_CMD_HW_RESET: | |
6448 | return bnx2x_func_hw_reset(bp, params); | |
a3348722 BW |
6449 | case BNX2X_F_CMD_AFEX_UPDATE: |
6450 | return bnx2x_func_send_afex_update(bp, params); | |
6451 | case BNX2X_F_CMD_AFEX_VIFLISTS: | |
6452 | return bnx2x_func_send_afex_viflists(bp, params); | |
6debea87 DK |
6453 | case BNX2X_F_CMD_TX_STOP: |
6454 | return bnx2x_func_send_tx_stop(bp, params); | |
6455 | case BNX2X_F_CMD_TX_START: | |
6456 | return bnx2x_func_send_tx_start(bp, params); | |
55c11941 MS |
6457 | case BNX2X_F_CMD_SWITCH_UPDATE: |
6458 | return bnx2x_func_send_switch_update(bp, params); | |
eeed018c MK |
6459 | case BNX2X_F_CMD_SET_TIMESYNC: |
6460 | return bnx2x_func_send_set_timesync(bp, params); | |
619c5cb6 VZ |
6461 | default: |
6462 | BNX2X_ERR("Unknown command: %d\n", params->cmd); | |
6463 | return -EINVAL; | |
6464 | } | |
6465 | } | |
6466 | ||
6467 | void bnx2x_init_func_obj(struct bnx2x *bp, | |
6468 | struct bnx2x_func_sp_obj *obj, | |
6469 | void *rdata, dma_addr_t rdata_mapping, | |
a3348722 | 6470 | void *afex_rdata, dma_addr_t afex_rdata_mapping, |
619c5cb6 VZ |
6471 | struct bnx2x_func_sp_drv_ops *drv_iface) |
6472 | { | |
6473 | memset(obj, 0, sizeof(*obj)); | |
6474 | ||
6475 | mutex_init(&obj->one_pending_mutex); | |
6476 | ||
6477 | obj->rdata = rdata; | |
6478 | obj->rdata_mapping = rdata_mapping; | |
a3348722 BW |
6479 | obj->afex_rdata = afex_rdata; |
6480 | obj->afex_rdata_mapping = afex_rdata_mapping; | |
619c5cb6 VZ |
6481 | obj->send_cmd = bnx2x_func_send_cmd; |
6482 | obj->check_transition = bnx2x_func_chk_transition; | |
6483 | obj->complete_cmd = bnx2x_func_comp_cmd; | |
6484 | obj->wait_comp = bnx2x_func_wait_comp; | |
6485 | ||
6486 | obj->drv = drv_iface; | |
6487 | } | |
6488 | ||
6489 | /** | |
6490 | * bnx2x_func_state_change - perform Function state change transition | |
6491 | * | |
6492 | * @bp: device handle | |
6493 | * @params: parameters to perform the transaction | |
6494 | * | |
6495 | * returns 0 in case of successfully completed transition, | |
6496 | * negative error code in case of failure, positive | |
6497 | * (EBUSY) value if there is a completion to that is | |
6498 | * still pending (possible only if RAMROD_COMP_WAIT is | |
6499 | * not set in params->ramrod_flags for asynchronous | |
6500 | * commands). | |
6501 | */ | |
6502 | int bnx2x_func_state_change(struct bnx2x *bp, | |
6503 | struct bnx2x_func_state_params *params) | |
6504 | { | |
6505 | struct bnx2x_func_sp_obj *o = params->f_obj; | |
55c11941 | 6506 | int rc, cnt = 300; |
619c5cb6 VZ |
6507 | enum bnx2x_func_cmd cmd = params->cmd; |
6508 | unsigned long *pending = &o->pending; | |
6509 | ||
6510 | mutex_lock(&o->one_pending_mutex); | |
6511 | ||
6512 | /* Check that the requested transition is legal */ | |
55c11941 MS |
6513 | rc = o->check_transition(bp, o, params); |
6514 | if ((rc == -EBUSY) && | |
6515 | (test_bit(RAMROD_RETRY, ¶ms->ramrod_flags))) { | |
6516 | while ((rc == -EBUSY) && (--cnt > 0)) { | |
6517 | mutex_unlock(&o->one_pending_mutex); | |
6518 | msleep(10); | |
6519 | mutex_lock(&o->one_pending_mutex); | |
6520 | rc = o->check_transition(bp, o, params); | |
6521 | } | |
6522 | if (rc == -EBUSY) { | |
6523 | mutex_unlock(&o->one_pending_mutex); | |
6524 | BNX2X_ERR("timeout waiting for previous ramrod completion\n"); | |
6525 | return rc; | |
6526 | } | |
6527 | } else if (rc) { | |
619c5cb6 | 6528 | mutex_unlock(&o->one_pending_mutex); |
55c11941 | 6529 | return rc; |
619c5cb6 VZ |
6530 | } |
6531 | ||
6532 | /* Set "pending" bit */ | |
6533 | set_bit(cmd, pending); | |
6534 | ||
6535 | /* Don't send a command if only driver cleanup was requested */ | |
6536 | if (test_bit(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) { | |
6537 | bnx2x_func_state_change_comp(bp, o, cmd); | |
6538 | mutex_unlock(&o->one_pending_mutex); | |
6539 | } else { | |
6540 | /* Send a ramrod */ | |
6541 | rc = o->send_cmd(bp, params); | |
6542 | ||
6543 | mutex_unlock(&o->one_pending_mutex); | |
6544 | ||
6545 | if (rc) { | |
6546 | o->next_state = BNX2X_F_STATE_MAX; | |
6547 | clear_bit(cmd, pending); | |
4e857c58 | 6548 | smp_mb__after_atomic(); |
619c5cb6 VZ |
6549 | return rc; |
6550 | } | |
6551 | ||
6552 | if (test_bit(RAMROD_COMP_WAIT, ¶ms->ramrod_flags)) { | |
6553 | rc = o->wait_comp(bp, o, cmd); | |
6554 | if (rc) | |
6555 | return rc; | |
6556 | ||
6557 | return 0; | |
6558 | } | |
6559 | } | |
042181f5 | 6560 | |
619c5cb6 | 6561 | return !!test_bit(cmd, pending); |
042181f5 | 6562 | } |