18c2ecf20Sopenharmony_ci/* bnx2x_sp.c: Qlogic Everest network driver.
28c2ecf20Sopenharmony_ci *
38c2ecf20Sopenharmony_ci * Copyright 2011-2013 Broadcom Corporation
48c2ecf20Sopenharmony_ci * Copyright (c) 2014 QLogic Corporation
58c2ecf20Sopenharmony_ci * All rights reserved
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Unless you and Qlogic execute a separate written software license
88c2ecf20Sopenharmony_ci * agreement governing use of this software, this software is licensed to you
98c2ecf20Sopenharmony_ci * under the terms of the GNU General Public License version 2, available
108c2ecf20Sopenharmony_ci * at http://www.gnu.org/licenses/gpl-2.0.html (the "GPL").
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * Notwithstanding the above, under no circumstances may you combine this
138c2ecf20Sopenharmony_ci * software in any way with any other Qlogic software provided under a
148c2ecf20Sopenharmony_ci * license other than the GPL, without Qlogic's express prior written
158c2ecf20Sopenharmony_ci * consent.
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * Maintained by: Ariel Elior <ariel.elior@qlogic.com>
188c2ecf20Sopenharmony_ci * Written by: Vladislav Zolotarov
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include <linux/module.h>
258c2ecf20Sopenharmony_ci#include <linux/crc32.h>
268c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
278c2ecf20Sopenharmony_ci#include <linux/etherdevice.h>
288c2ecf20Sopenharmony_ci#include <linux/crc32c.h>
298c2ecf20Sopenharmony_ci#include "bnx2x.h"
308c2ecf20Sopenharmony_ci#include "bnx2x_cmn.h"
318c2ecf20Sopenharmony_ci#include "bnx2x_sp.h"
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#define BNX2X_MAX_EMUL_MULTI		16
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/**** Exe Queue interfaces ****/
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/**
388c2ecf20Sopenharmony_ci * bnx2x_exe_queue_init - init the Exe Queue object
398c2ecf20Sopenharmony_ci *
408c2ecf20Sopenharmony_ci * @bp:		driver handle
418c2ecf20Sopenharmony_ci * @o:		pointer to the object
428c2ecf20Sopenharmony_ci * @exe_len:	length
438c2ecf20Sopenharmony_ci * @owner:	pointer to the owner
448c2ecf20Sopenharmony_ci * @validate:	validate function pointer
458c2ecf20Sopenharmony_ci * @remove:	remove function pointer
468c2ecf20Sopenharmony_ci * @optimize:	optimize function pointer
478c2ecf20Sopenharmony_ci * @exec:	execute function pointer
488c2ecf20Sopenharmony_ci * @get:	get function pointer
498c2ecf20Sopenharmony_ci */
508c2ecf20Sopenharmony_cistatic inline void bnx2x_exe_queue_init(struct bnx2x *bp,
518c2ecf20Sopenharmony_ci					struct bnx2x_exe_queue_obj *o,
528c2ecf20Sopenharmony_ci					int exe_len,
538c2ecf20Sopenharmony_ci					union bnx2x_qable_obj *owner,
548c2ecf20Sopenharmony_ci					exe_q_validate validate,
558c2ecf20Sopenharmony_ci					exe_q_remove remove,
568c2ecf20Sopenharmony_ci					exe_q_optimize optimize,
578c2ecf20Sopenharmony_ci					exe_q_execute exec,
588c2ecf20Sopenharmony_ci					exe_q_get get)
598c2ecf20Sopenharmony_ci{
608c2ecf20Sopenharmony_ci	memset(o, 0, sizeof(*o));
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&o->exe_queue);
638c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&o->pending_comp);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	spin_lock_init(&o->lock);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	o->exe_chunk_len = exe_len;
688c2ecf20Sopenharmony_ci	o->owner         = owner;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	/* Owner specific callbacks */
718c2ecf20Sopenharmony_ci	o->validate      = validate;
728c2ecf20Sopenharmony_ci	o->remove        = remove;
738c2ecf20Sopenharmony_ci	o->optimize      = optimize;
748c2ecf20Sopenharmony_ci	o->execute       = exec;
758c2ecf20Sopenharmony_ci	o->get           = get;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Setup the execution queue with the chunk length of %d\n",
788c2ecf20Sopenharmony_ci	   exe_len);
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic inline void bnx2x_exe_queue_free_elem(struct bnx2x *bp,
828c2ecf20Sopenharmony_ci					     struct bnx2x_exeq_elem *elem)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Deleting an exe_queue element\n");
858c2ecf20Sopenharmony_ci	kfree(elem);
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cistatic inline int bnx2x_exe_queue_length(struct bnx2x_exe_queue_obj *o)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *elem;
918c2ecf20Sopenharmony_ci	int cnt = 0;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	spin_lock_bh(&o->lock);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	list_for_each_entry(elem, &o->exe_queue, link)
968c2ecf20Sopenharmony_ci		cnt++;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	spin_unlock_bh(&o->lock);
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	return cnt;
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci/**
1048c2ecf20Sopenharmony_ci * bnx2x_exe_queue_add - add a new element to the execution queue
1058c2ecf20Sopenharmony_ci *
1068c2ecf20Sopenharmony_ci * @bp:		driver handle
1078c2ecf20Sopenharmony_ci * @o:		queue
1088c2ecf20Sopenharmony_ci * @elem:	new command to add
1098c2ecf20Sopenharmony_ci * @restore:	true - do not optimize the command
1108c2ecf20Sopenharmony_ci *
1118c2ecf20Sopenharmony_ci * If the element is optimized or is illegal, frees it.
1128c2ecf20Sopenharmony_ci */
1138c2ecf20Sopenharmony_cistatic inline int bnx2x_exe_queue_add(struct bnx2x *bp,
1148c2ecf20Sopenharmony_ci				      struct bnx2x_exe_queue_obj *o,
1158c2ecf20Sopenharmony_ci				      struct bnx2x_exeq_elem *elem,
1168c2ecf20Sopenharmony_ci				      bool restore)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	int rc;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	spin_lock_bh(&o->lock);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	if (!restore) {
1238c2ecf20Sopenharmony_ci		/* Try to cancel this element queue */
1248c2ecf20Sopenharmony_ci		rc = o->optimize(bp, o->owner, elem);
1258c2ecf20Sopenharmony_ci		if (rc)
1268c2ecf20Sopenharmony_ci			goto free_and_exit;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci		/* Check if this request is ok */
1298c2ecf20Sopenharmony_ci		rc = o->validate(bp, o->owner, elem);
1308c2ecf20Sopenharmony_ci		if (rc) {
1318c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_SP, "Preamble failed: %d\n", rc);
1328c2ecf20Sopenharmony_ci			goto free_and_exit;
1338c2ecf20Sopenharmony_ci		}
1348c2ecf20Sopenharmony_ci	}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	/* If so, add it to the execution queue */
1378c2ecf20Sopenharmony_ci	list_add_tail(&elem->link, &o->exe_queue);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	spin_unlock_bh(&o->lock);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	return 0;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cifree_and_exit:
1448c2ecf20Sopenharmony_ci	bnx2x_exe_queue_free_elem(bp, elem);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	spin_unlock_bh(&o->lock);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	return rc;
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistatic inline void __bnx2x_exe_queue_reset_pending(
1528c2ecf20Sopenharmony_ci	struct bnx2x *bp,
1538c2ecf20Sopenharmony_ci	struct bnx2x_exe_queue_obj *o)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *elem;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	while (!list_empty(&o->pending_comp)) {
1588c2ecf20Sopenharmony_ci		elem = list_first_entry(&o->pending_comp,
1598c2ecf20Sopenharmony_ci					struct bnx2x_exeq_elem, link);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci		list_del(&elem->link);
1628c2ecf20Sopenharmony_ci		bnx2x_exe_queue_free_elem(bp, elem);
1638c2ecf20Sopenharmony_ci	}
1648c2ecf20Sopenharmony_ci}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci/**
1678c2ecf20Sopenharmony_ci * bnx2x_exe_queue_step - execute one execution chunk atomically
1688c2ecf20Sopenharmony_ci *
1698c2ecf20Sopenharmony_ci * @bp:			driver handle
1708c2ecf20Sopenharmony_ci * @o:			queue
1718c2ecf20Sopenharmony_ci * @ramrod_flags:	flags
1728c2ecf20Sopenharmony_ci *
1738c2ecf20Sopenharmony_ci * (Should be called while holding the exe_queue->lock).
1748c2ecf20Sopenharmony_ci */
1758c2ecf20Sopenharmony_cistatic inline int bnx2x_exe_queue_step(struct bnx2x *bp,
1768c2ecf20Sopenharmony_ci				       struct bnx2x_exe_queue_obj *o,
1778c2ecf20Sopenharmony_ci				       unsigned long *ramrod_flags)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *elem, spacer;
1808c2ecf20Sopenharmony_ci	int cur_len = 0, rc;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	memset(&spacer, 0, sizeof(spacer));
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	/* Next step should not be performed until the current is finished,
1858c2ecf20Sopenharmony_ci	 * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to
1868c2ecf20Sopenharmony_ci	 * properly clear object internals without sending any command to the FW
1878c2ecf20Sopenharmony_ci	 * which also implies there won't be any completion to clear the
1888c2ecf20Sopenharmony_ci	 * 'pending' list.
1898c2ecf20Sopenharmony_ci	 */
1908c2ecf20Sopenharmony_ci	if (!list_empty(&o->pending_comp)) {
1918c2ecf20Sopenharmony_ci		if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags)) {
1928c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: resetting a pending_comp list\n");
1938c2ecf20Sopenharmony_ci			__bnx2x_exe_queue_reset_pending(bp, o);
1948c2ecf20Sopenharmony_ci		} else {
1958c2ecf20Sopenharmony_ci			return 1;
1968c2ecf20Sopenharmony_ci		}
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	/* Run through the pending commands list and create a next
2008c2ecf20Sopenharmony_ci	 * execution chunk.
2018c2ecf20Sopenharmony_ci	 */
2028c2ecf20Sopenharmony_ci	while (!list_empty(&o->exe_queue)) {
2038c2ecf20Sopenharmony_ci		elem = list_first_entry(&o->exe_queue, struct bnx2x_exeq_elem,
2048c2ecf20Sopenharmony_ci					link);
2058c2ecf20Sopenharmony_ci		WARN_ON(!elem->cmd_len);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci		if (cur_len + elem->cmd_len <= o->exe_chunk_len) {
2088c2ecf20Sopenharmony_ci			cur_len += elem->cmd_len;
2098c2ecf20Sopenharmony_ci			/* Prevent from both lists being empty when moving an
2108c2ecf20Sopenharmony_ci			 * element. This will allow the call of
2118c2ecf20Sopenharmony_ci			 * bnx2x_exe_queue_empty() without locking.
2128c2ecf20Sopenharmony_ci			 */
2138c2ecf20Sopenharmony_ci			list_add_tail(&spacer.link, &o->pending_comp);
2148c2ecf20Sopenharmony_ci			mb();
2158c2ecf20Sopenharmony_ci			list_move_tail(&elem->link, &o->pending_comp);
2168c2ecf20Sopenharmony_ci			list_del(&spacer.link);
2178c2ecf20Sopenharmony_ci		} else
2188c2ecf20Sopenharmony_ci			break;
2198c2ecf20Sopenharmony_ci	}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	/* Sanity check */
2228c2ecf20Sopenharmony_ci	if (!cur_len)
2238c2ecf20Sopenharmony_ci		return 0;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	rc = o->execute(bp, o->owner, &o->pending_comp, ramrod_flags);
2268c2ecf20Sopenharmony_ci	if (rc < 0)
2278c2ecf20Sopenharmony_ci		/* In case of an error return the commands back to the queue
2288c2ecf20Sopenharmony_ci		 * and reset the pending_comp.
2298c2ecf20Sopenharmony_ci		 */
2308c2ecf20Sopenharmony_ci		list_splice_init(&o->pending_comp, &o->exe_queue);
2318c2ecf20Sopenharmony_ci	else if (!rc)
2328c2ecf20Sopenharmony_ci		/* If zero is returned, means there are no outstanding pending
2338c2ecf20Sopenharmony_ci		 * completions and we may dismiss the pending list.
2348c2ecf20Sopenharmony_ci		 */
2358c2ecf20Sopenharmony_ci		__bnx2x_exe_queue_reset_pending(bp, o);
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	return rc;
2388c2ecf20Sopenharmony_ci}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_cistatic inline bool bnx2x_exe_queue_empty(struct bnx2x_exe_queue_obj *o)
2418c2ecf20Sopenharmony_ci{
2428c2ecf20Sopenharmony_ci	bool empty = list_empty(&o->exe_queue);
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	/* Don't reorder!!! */
2458c2ecf20Sopenharmony_ci	mb();
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	return empty && list_empty(&o->pending_comp);
2488c2ecf20Sopenharmony_ci}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_cistatic inline struct bnx2x_exeq_elem *bnx2x_exe_queue_alloc_elem(
2518c2ecf20Sopenharmony_ci	struct bnx2x *bp)
2528c2ecf20Sopenharmony_ci{
2538c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Allocating a new exe_queue element\n");
2548c2ecf20Sopenharmony_ci	return kzalloc(sizeof(struct bnx2x_exeq_elem), GFP_ATOMIC);
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci/************************ raw_obj functions ***********************************/
2588c2ecf20Sopenharmony_cistatic bool bnx2x_raw_check_pending(struct bnx2x_raw_obj *o)
2598c2ecf20Sopenharmony_ci{
2608c2ecf20Sopenharmony_ci	return !!test_bit(o->state, o->pstate);
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_cistatic void bnx2x_raw_clear_pending(struct bnx2x_raw_obj *o)
2648c2ecf20Sopenharmony_ci{
2658c2ecf20Sopenharmony_ci	smp_mb__before_atomic();
2668c2ecf20Sopenharmony_ci	clear_bit(o->state, o->pstate);
2678c2ecf20Sopenharmony_ci	smp_mb__after_atomic();
2688c2ecf20Sopenharmony_ci}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_cistatic void bnx2x_raw_set_pending(struct bnx2x_raw_obj *o)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	smp_mb__before_atomic();
2738c2ecf20Sopenharmony_ci	set_bit(o->state, o->pstate);
2748c2ecf20Sopenharmony_ci	smp_mb__after_atomic();
2758c2ecf20Sopenharmony_ci}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci/**
2788c2ecf20Sopenharmony_ci * bnx2x_state_wait - wait until the given bit(state) is cleared
2798c2ecf20Sopenharmony_ci *
2808c2ecf20Sopenharmony_ci * @bp:		device handle
2818c2ecf20Sopenharmony_ci * @state:	state which is to be cleared
2828c2ecf20Sopenharmony_ci * @pstate:	state buffer
2838c2ecf20Sopenharmony_ci *
2848c2ecf20Sopenharmony_ci */
2858c2ecf20Sopenharmony_cistatic inline int bnx2x_state_wait(struct bnx2x *bp, int state,
2868c2ecf20Sopenharmony_ci				   unsigned long *pstate)
2878c2ecf20Sopenharmony_ci{
2888c2ecf20Sopenharmony_ci	/* can take a while if any port is running */
2898c2ecf20Sopenharmony_ci	int cnt = 5000;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	if (CHIP_REV_IS_EMUL(bp))
2928c2ecf20Sopenharmony_ci		cnt *= 20;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "waiting for state to become %d\n", state);
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	might_sleep();
2978c2ecf20Sopenharmony_ci	while (cnt--) {
2988c2ecf20Sopenharmony_ci		if (!test_bit(state, pstate)) {
2998c2ecf20Sopenharmony_ci#ifdef BNX2X_STOP_ON_ERROR
3008c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_SP, "exit  (cnt %d)\n", 5000 - cnt);
3018c2ecf20Sopenharmony_ci#endif
3028c2ecf20Sopenharmony_ci			return 0;
3038c2ecf20Sopenharmony_ci		}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci		usleep_range(1000, 2000);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci		if (bp->panic)
3088c2ecf20Sopenharmony_ci			return -EIO;
3098c2ecf20Sopenharmony_ci	}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	/* timeout! */
3128c2ecf20Sopenharmony_ci	BNX2X_ERR("timeout waiting for state %d\n", state);
3138c2ecf20Sopenharmony_ci#ifdef BNX2X_STOP_ON_ERROR
3148c2ecf20Sopenharmony_ci	bnx2x_panic();
3158c2ecf20Sopenharmony_ci#endif
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	return -EBUSY;
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic int bnx2x_raw_wait(struct bnx2x *bp, struct bnx2x_raw_obj *raw)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	return bnx2x_state_wait(bp, raw->state, raw->pstate);
3238c2ecf20Sopenharmony_ci}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci/***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
3268c2ecf20Sopenharmony_ci/* credit handling callbacks */
3278c2ecf20Sopenharmony_cistatic bool bnx2x_get_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int *offset)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	WARN_ON(!mp);
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	return mp->get_entry(mp, offset);
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_cistatic bool bnx2x_get_credit_mac(struct bnx2x_vlan_mac_obj *o)
3378c2ecf20Sopenharmony_ci{
3388c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	WARN_ON(!mp);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	return mp->get(mp, 1);
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic bool bnx2x_get_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int *offset)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	WARN_ON(!vp);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	return vp->get_entry(vp, offset);
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic bool bnx2x_get_credit_vlan(struct bnx2x_vlan_mac_obj *o)
3558c2ecf20Sopenharmony_ci{
3568c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	WARN_ON(!vp);
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	return vp->get(vp, 1);
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_cistatic bool bnx2x_get_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
3648c2ecf20Sopenharmony_ci{
3658c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
3668c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	if (!mp->get(mp, 1))
3698c2ecf20Sopenharmony_ci		return false;
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	if (!vp->get(vp, 1)) {
3728c2ecf20Sopenharmony_ci		mp->put(mp, 1);
3738c2ecf20Sopenharmony_ci		return false;
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	return true;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistatic bool bnx2x_put_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int offset)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	return mp->put_entry(mp, offset);
3848c2ecf20Sopenharmony_ci}
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_cistatic bool bnx2x_put_credit_mac(struct bnx2x_vlan_mac_obj *o)
3878c2ecf20Sopenharmony_ci{
3888c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	return mp->put(mp, 1);
3918c2ecf20Sopenharmony_ci}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_cistatic bool bnx2x_put_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int offset)
3948c2ecf20Sopenharmony_ci{
3958c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	return vp->put_entry(vp, offset);
3988c2ecf20Sopenharmony_ci}
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_cistatic bool bnx2x_put_credit_vlan(struct bnx2x_vlan_mac_obj *o)
4018c2ecf20Sopenharmony_ci{
4028c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	return vp->put(vp, 1);
4058c2ecf20Sopenharmony_ci}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_cistatic bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
4088c2ecf20Sopenharmony_ci{
4098c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
4108c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	if (!mp->put(mp, 1))
4138c2ecf20Sopenharmony_ci		return false;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	if (!vp->put(vp, 1)) {
4168c2ecf20Sopenharmony_ci		mp->get(mp, 1);
4178c2ecf20Sopenharmony_ci		return false;
4188c2ecf20Sopenharmony_ci	}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	return true;
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci/**
4248c2ecf20Sopenharmony_ci * __bnx2x_vlan_mac_h_write_trylock - try getting the vlan mac writer lock
4258c2ecf20Sopenharmony_ci *
4268c2ecf20Sopenharmony_ci * @bp:		device handle
4278c2ecf20Sopenharmony_ci * @o:		vlan_mac object
4288c2ecf20Sopenharmony_ci *
4298c2ecf20Sopenharmony_ci * Context: Non-blocking implementation; should be called under execution
4308c2ecf20Sopenharmony_ci *          queue lock.
4318c2ecf20Sopenharmony_ci */
4328c2ecf20Sopenharmony_cistatic int __bnx2x_vlan_mac_h_write_trylock(struct bnx2x *bp,
4338c2ecf20Sopenharmony_ci					    struct bnx2x_vlan_mac_obj *o)
4348c2ecf20Sopenharmony_ci{
4358c2ecf20Sopenharmony_ci	if (o->head_reader) {
4368c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "vlan_mac_lock writer - There are readers; Busy\n");
4378c2ecf20Sopenharmony_ci		return -EBUSY;
4388c2ecf20Sopenharmony_ci	}
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "vlan_mac_lock writer - Taken\n");
4418c2ecf20Sopenharmony_ci	return 0;
4428c2ecf20Sopenharmony_ci}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci/**
4458c2ecf20Sopenharmony_ci * __bnx2x_vlan_mac_h_exec_pending - execute step instead of a previous step
4468c2ecf20Sopenharmony_ci *
4478c2ecf20Sopenharmony_ci * @bp:		device handle
4488c2ecf20Sopenharmony_ci * @o:		vlan_mac object
4498c2ecf20Sopenharmony_ci *
4508c2ecf20Sopenharmony_ci * details Should be called under execution queue lock; notice it might release
4518c2ecf20Sopenharmony_ci *          and reclaim it during its run.
4528c2ecf20Sopenharmony_ci */
4538c2ecf20Sopenharmony_cistatic void __bnx2x_vlan_mac_h_exec_pending(struct bnx2x *bp,
4548c2ecf20Sopenharmony_ci					    struct bnx2x_vlan_mac_obj *o)
4558c2ecf20Sopenharmony_ci{
4568c2ecf20Sopenharmony_ci	int rc;
4578c2ecf20Sopenharmony_ci	unsigned long ramrod_flags = o->saved_ramrod_flags;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "vlan_mac_lock execute pending command with ramrod flags %lu\n",
4608c2ecf20Sopenharmony_ci	   ramrod_flags);
4618c2ecf20Sopenharmony_ci	o->head_exe_request = false;
4628c2ecf20Sopenharmony_ci	o->saved_ramrod_flags = 0;
4638c2ecf20Sopenharmony_ci	rc = bnx2x_exe_queue_step(bp, &o->exe_queue, &ramrod_flags);
4648c2ecf20Sopenharmony_ci	if ((rc != 0) && (rc != 1)) {
4658c2ecf20Sopenharmony_ci		BNX2X_ERR("execution of pending commands failed with rc %d\n",
4668c2ecf20Sopenharmony_ci			  rc);
4678c2ecf20Sopenharmony_ci#ifdef BNX2X_STOP_ON_ERROR
4688c2ecf20Sopenharmony_ci		bnx2x_panic();
4698c2ecf20Sopenharmony_ci#endif
4708c2ecf20Sopenharmony_ci	}
4718c2ecf20Sopenharmony_ci}
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci/**
4748c2ecf20Sopenharmony_ci * __bnx2x_vlan_mac_h_pend - Pend an execution step which couldn't run
4758c2ecf20Sopenharmony_ci *
4768c2ecf20Sopenharmony_ci * @bp:			device handle
4778c2ecf20Sopenharmony_ci * @o:			vlan_mac object
4788c2ecf20Sopenharmony_ci * @ramrod_flags:	ramrod flags of missed execution
4798c2ecf20Sopenharmony_ci *
4808c2ecf20Sopenharmony_ci * Context: Should be called under execution queue lock.
4818c2ecf20Sopenharmony_ci */
4828c2ecf20Sopenharmony_cistatic void __bnx2x_vlan_mac_h_pend(struct bnx2x *bp,
4838c2ecf20Sopenharmony_ci				    struct bnx2x_vlan_mac_obj *o,
4848c2ecf20Sopenharmony_ci				    unsigned long ramrod_flags)
4858c2ecf20Sopenharmony_ci{
4868c2ecf20Sopenharmony_ci	o->head_exe_request = true;
4878c2ecf20Sopenharmony_ci	o->saved_ramrod_flags = ramrod_flags;
4888c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Placing pending execution with ramrod flags %lu\n",
4898c2ecf20Sopenharmony_ci	   ramrod_flags);
4908c2ecf20Sopenharmony_ci}
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci/**
4938c2ecf20Sopenharmony_ci * __bnx2x_vlan_mac_h_write_unlock - unlock the vlan mac head list writer lock
4948c2ecf20Sopenharmony_ci *
4958c2ecf20Sopenharmony_ci * @bp:			device handle
4968c2ecf20Sopenharmony_ci * @o:			vlan_mac object
4978c2ecf20Sopenharmony_ci *
4988c2ecf20Sopenharmony_ci * Context: Should be called under execution queue lock. Notice if a pending
4998c2ecf20Sopenharmony_ci *          execution exists, it would perform it - possibly releasing and
5008c2ecf20Sopenharmony_ci *          reclaiming the execution queue lock.
5018c2ecf20Sopenharmony_ci */
5028c2ecf20Sopenharmony_cistatic void __bnx2x_vlan_mac_h_write_unlock(struct bnx2x *bp,
5038c2ecf20Sopenharmony_ci					    struct bnx2x_vlan_mac_obj *o)
5048c2ecf20Sopenharmony_ci{
5058c2ecf20Sopenharmony_ci	/* It's possible a new pending execution was added since this writer
5068c2ecf20Sopenharmony_ci	 * executed. If so, execute again. [Ad infinitum]
5078c2ecf20Sopenharmony_ci	 */
5088c2ecf20Sopenharmony_ci	while (o->head_exe_request) {
5098c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "vlan_mac_lock - writer release encountered a pending request\n");
5108c2ecf20Sopenharmony_ci		__bnx2x_vlan_mac_h_exec_pending(bp, o);
5118c2ecf20Sopenharmony_ci	}
5128c2ecf20Sopenharmony_ci}
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci/**
5168c2ecf20Sopenharmony_ci * __bnx2x_vlan_mac_h_read_lock - lock the vlan mac head list reader lock
5178c2ecf20Sopenharmony_ci *
5188c2ecf20Sopenharmony_ci * @bp:			device handle
5198c2ecf20Sopenharmony_ci * @o:			vlan_mac object
5208c2ecf20Sopenharmony_ci *
5218c2ecf20Sopenharmony_ci * Context: Should be called under the execution queue lock. May sleep. May
5228c2ecf20Sopenharmony_ci *          release and reclaim execution queue lock during its run.
5238c2ecf20Sopenharmony_ci */
5248c2ecf20Sopenharmony_cistatic int __bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp,
5258c2ecf20Sopenharmony_ci					struct bnx2x_vlan_mac_obj *o)
5268c2ecf20Sopenharmony_ci{
5278c2ecf20Sopenharmony_ci	/* If we got here, we're holding lock --> no WRITER exists */
5288c2ecf20Sopenharmony_ci	o->head_reader++;
5298c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "vlan_mac_lock - locked reader - number %d\n",
5308c2ecf20Sopenharmony_ci	   o->head_reader);
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	return 0;
5338c2ecf20Sopenharmony_ci}
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci/**
5368c2ecf20Sopenharmony_ci * bnx2x_vlan_mac_h_read_lock - lock the vlan mac head list reader lock
5378c2ecf20Sopenharmony_ci *
5388c2ecf20Sopenharmony_ci * @bp:			device handle
5398c2ecf20Sopenharmony_ci * @o:			vlan_mac object
5408c2ecf20Sopenharmony_ci *
5418c2ecf20Sopenharmony_ci * Context: May sleep. Claims and releases execution queue lock during its run.
5428c2ecf20Sopenharmony_ci */
5438c2ecf20Sopenharmony_ciint bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp,
5448c2ecf20Sopenharmony_ci			       struct bnx2x_vlan_mac_obj *o)
5458c2ecf20Sopenharmony_ci{
5468c2ecf20Sopenharmony_ci	int rc;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	spin_lock_bh(&o->exe_queue.lock);
5498c2ecf20Sopenharmony_ci	rc = __bnx2x_vlan_mac_h_read_lock(bp, o);
5508c2ecf20Sopenharmony_ci	spin_unlock_bh(&o->exe_queue.lock);
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	return rc;
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci/**
5568c2ecf20Sopenharmony_ci * __bnx2x_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock
5578c2ecf20Sopenharmony_ci *
5588c2ecf20Sopenharmony_ci * @bp:			device handle
5598c2ecf20Sopenharmony_ci * @o:			vlan_mac object
5608c2ecf20Sopenharmony_ci *
5618c2ecf20Sopenharmony_ci * Context: Should be called under execution queue lock. Notice if a pending
5628c2ecf20Sopenharmony_ci *          execution exists, it would be performed if this was the last
5638c2ecf20Sopenharmony_ci *          reader. possibly releasing and reclaiming the execution queue lock.
5648c2ecf20Sopenharmony_ci */
5658c2ecf20Sopenharmony_cistatic void __bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp,
5668c2ecf20Sopenharmony_ci					  struct bnx2x_vlan_mac_obj *o)
5678c2ecf20Sopenharmony_ci{
5688c2ecf20Sopenharmony_ci	if (!o->head_reader) {
5698c2ecf20Sopenharmony_ci		BNX2X_ERR("Need to release vlan mac reader lock, but lock isn't taken\n");
5708c2ecf20Sopenharmony_ci#ifdef BNX2X_STOP_ON_ERROR
5718c2ecf20Sopenharmony_ci		bnx2x_panic();
5728c2ecf20Sopenharmony_ci#endif
5738c2ecf20Sopenharmony_ci	} else {
5748c2ecf20Sopenharmony_ci		o->head_reader--;
5758c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "vlan_mac_lock - decreased readers to %d\n",
5768c2ecf20Sopenharmony_ci		   o->head_reader);
5778c2ecf20Sopenharmony_ci	}
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	/* It's possible a new pending execution was added, and that this reader
5808c2ecf20Sopenharmony_ci	 * was last - if so we need to execute the command.
5818c2ecf20Sopenharmony_ci	 */
5828c2ecf20Sopenharmony_ci	if (!o->head_reader && o->head_exe_request) {
5838c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "vlan_mac_lock - reader release encountered a pending request\n");
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci		/* Writer release will do the trick */
5868c2ecf20Sopenharmony_ci		__bnx2x_vlan_mac_h_write_unlock(bp, o);
5878c2ecf20Sopenharmony_ci	}
5888c2ecf20Sopenharmony_ci}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci/**
5918c2ecf20Sopenharmony_ci * bnx2x_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock
5928c2ecf20Sopenharmony_ci *
5938c2ecf20Sopenharmony_ci * @bp:			device handle
5948c2ecf20Sopenharmony_ci * @o:			vlan_mac object
5958c2ecf20Sopenharmony_ci *
5968c2ecf20Sopenharmony_ci * Context: Notice if a pending execution exists, it would be performed if this
5978c2ecf20Sopenharmony_ci *          was the last reader. Claims and releases the execution queue lock
5988c2ecf20Sopenharmony_ci *          during its run.
5998c2ecf20Sopenharmony_ci */
6008c2ecf20Sopenharmony_civoid bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp,
6018c2ecf20Sopenharmony_ci				  struct bnx2x_vlan_mac_obj *o)
6028c2ecf20Sopenharmony_ci{
6038c2ecf20Sopenharmony_ci	spin_lock_bh(&o->exe_queue.lock);
6048c2ecf20Sopenharmony_ci	__bnx2x_vlan_mac_h_read_unlock(bp, o);
6058c2ecf20Sopenharmony_ci	spin_unlock_bh(&o->exe_queue.lock);
6068c2ecf20Sopenharmony_ci}
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_cistatic int bnx2x_get_n_elements(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
6098c2ecf20Sopenharmony_ci				int n, u8 *base, u8 stride, u8 size)
6108c2ecf20Sopenharmony_ci{
6118c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *pos;
6128c2ecf20Sopenharmony_ci	u8 *next = base;
6138c2ecf20Sopenharmony_ci	int counter = 0;
6148c2ecf20Sopenharmony_ci	int read_lock;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "get_n_elements - taking vlan_mac_lock (reader)\n");
6178c2ecf20Sopenharmony_ci	read_lock = bnx2x_vlan_mac_h_read_lock(bp, o);
6188c2ecf20Sopenharmony_ci	if (read_lock != 0)
6198c2ecf20Sopenharmony_ci		BNX2X_ERR("get_n_elements failed to get vlan mac reader lock; Access without lock\n");
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	/* traverse list */
6228c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &o->head, link) {
6238c2ecf20Sopenharmony_ci		if (counter < n) {
6248c2ecf20Sopenharmony_ci			memcpy(next, &pos->u, size);
6258c2ecf20Sopenharmony_ci			counter++;
6268c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_SP, "copied element number %d to address %p element was:\n",
6278c2ecf20Sopenharmony_ci			   counter, next);
6288c2ecf20Sopenharmony_ci			next += stride + size;
6298c2ecf20Sopenharmony_ci		}
6308c2ecf20Sopenharmony_ci	}
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	if (read_lock == 0) {
6338c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "get_n_elements - releasing vlan_mac_lock (reader)\n");
6348c2ecf20Sopenharmony_ci		bnx2x_vlan_mac_h_read_unlock(bp, o);
6358c2ecf20Sopenharmony_ci	}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	return counter * ETH_ALEN;
6388c2ecf20Sopenharmony_ci}
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci/* check_add() callbacks */
6418c2ecf20Sopenharmony_cistatic int bnx2x_check_mac_add(struct bnx2x *bp,
6428c2ecf20Sopenharmony_ci			       struct bnx2x_vlan_mac_obj *o,
6438c2ecf20Sopenharmony_ci			       union bnx2x_classification_ramrod_data *data)
6448c2ecf20Sopenharmony_ci{
6458c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *pos;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Checking MAC %pM for ADD command\n", data->mac.mac);
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	if (!is_valid_ether_addr(data->mac.mac))
6508c2ecf20Sopenharmony_ci		return -EINVAL;
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	/* Check if a requested MAC already exists */
6538c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &o->head, link)
6548c2ecf20Sopenharmony_ci		if (ether_addr_equal(data->mac.mac, pos->u.mac.mac) &&
6558c2ecf20Sopenharmony_ci		    (data->mac.is_inner_mac == pos->u.mac.is_inner_mac))
6568c2ecf20Sopenharmony_ci			return -EEXIST;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	return 0;
6598c2ecf20Sopenharmony_ci}
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_cistatic int bnx2x_check_vlan_add(struct bnx2x *bp,
6628c2ecf20Sopenharmony_ci				struct bnx2x_vlan_mac_obj *o,
6638c2ecf20Sopenharmony_ci				union bnx2x_classification_ramrod_data *data)
6648c2ecf20Sopenharmony_ci{
6658c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *pos;
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Checking VLAN %d for ADD command\n", data->vlan.vlan);
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &o->head, link)
6708c2ecf20Sopenharmony_ci		if (data->vlan.vlan == pos->u.vlan.vlan)
6718c2ecf20Sopenharmony_ci			return -EEXIST;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	return 0;
6748c2ecf20Sopenharmony_ci}
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_cistatic int bnx2x_check_vlan_mac_add(struct bnx2x *bp,
6778c2ecf20Sopenharmony_ci				    struct bnx2x_vlan_mac_obj *o,
6788c2ecf20Sopenharmony_ci				   union bnx2x_classification_ramrod_data *data)
6798c2ecf20Sopenharmony_ci{
6808c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *pos;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Checking VLAN_MAC (%pM, %d) for ADD command\n",
6838c2ecf20Sopenharmony_ci	   data->vlan_mac.mac, data->vlan_mac.vlan);
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &o->head, link)
6868c2ecf20Sopenharmony_ci		if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
6878c2ecf20Sopenharmony_ci		    (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
6888c2ecf20Sopenharmony_ci				  ETH_ALEN)) &&
6898c2ecf20Sopenharmony_ci		    (data->vlan_mac.is_inner_mac ==
6908c2ecf20Sopenharmony_ci		     pos->u.vlan_mac.is_inner_mac))
6918c2ecf20Sopenharmony_ci			return -EEXIST;
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	return 0;
6948c2ecf20Sopenharmony_ci}
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci/* check_del() callbacks */
6978c2ecf20Sopenharmony_cistatic struct bnx2x_vlan_mac_registry_elem *
6988c2ecf20Sopenharmony_ci	bnx2x_check_mac_del(struct bnx2x *bp,
6998c2ecf20Sopenharmony_ci			    struct bnx2x_vlan_mac_obj *o,
7008c2ecf20Sopenharmony_ci			    union bnx2x_classification_ramrod_data *data)
7018c2ecf20Sopenharmony_ci{
7028c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *pos;
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Checking MAC %pM for DEL command\n", data->mac.mac);
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &o->head, link)
7078c2ecf20Sopenharmony_ci		if (ether_addr_equal(data->mac.mac, pos->u.mac.mac) &&
7088c2ecf20Sopenharmony_ci		    (data->mac.is_inner_mac == pos->u.mac.is_inner_mac))
7098c2ecf20Sopenharmony_ci			return pos;
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	return NULL;
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_cistatic struct bnx2x_vlan_mac_registry_elem *
7158c2ecf20Sopenharmony_ci	bnx2x_check_vlan_del(struct bnx2x *bp,
7168c2ecf20Sopenharmony_ci			     struct bnx2x_vlan_mac_obj *o,
7178c2ecf20Sopenharmony_ci			     union bnx2x_classification_ramrod_data *data)
7188c2ecf20Sopenharmony_ci{
7198c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *pos;
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Checking VLAN %d for DEL command\n", data->vlan.vlan);
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &o->head, link)
7248c2ecf20Sopenharmony_ci		if (data->vlan.vlan == pos->u.vlan.vlan)
7258c2ecf20Sopenharmony_ci			return pos;
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	return NULL;
7288c2ecf20Sopenharmony_ci}
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_cistatic struct bnx2x_vlan_mac_registry_elem *
7318c2ecf20Sopenharmony_ci	bnx2x_check_vlan_mac_del(struct bnx2x *bp,
7328c2ecf20Sopenharmony_ci				 struct bnx2x_vlan_mac_obj *o,
7338c2ecf20Sopenharmony_ci				 union bnx2x_classification_ramrod_data *data)
7348c2ecf20Sopenharmony_ci{
7358c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *pos;
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Checking VLAN_MAC (%pM, %d) for DEL command\n",
7388c2ecf20Sopenharmony_ci	   data->vlan_mac.mac, data->vlan_mac.vlan);
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &o->head, link)
7418c2ecf20Sopenharmony_ci		if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
7428c2ecf20Sopenharmony_ci		    (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
7438c2ecf20Sopenharmony_ci			     ETH_ALEN)) &&
7448c2ecf20Sopenharmony_ci		    (data->vlan_mac.is_inner_mac ==
7458c2ecf20Sopenharmony_ci		     pos->u.vlan_mac.is_inner_mac))
7468c2ecf20Sopenharmony_ci			return pos;
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	return NULL;
7498c2ecf20Sopenharmony_ci}
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci/* check_move() callback */
7528c2ecf20Sopenharmony_cistatic bool bnx2x_check_move(struct bnx2x *bp,
7538c2ecf20Sopenharmony_ci			     struct bnx2x_vlan_mac_obj *src_o,
7548c2ecf20Sopenharmony_ci			     struct bnx2x_vlan_mac_obj *dst_o,
7558c2ecf20Sopenharmony_ci			     union bnx2x_classification_ramrod_data *data)
7568c2ecf20Sopenharmony_ci{
7578c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *pos;
7588c2ecf20Sopenharmony_ci	int rc;
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci	/* Check if we can delete the requested configuration from the first
7618c2ecf20Sopenharmony_ci	 * object.
7628c2ecf20Sopenharmony_ci	 */
7638c2ecf20Sopenharmony_ci	pos = src_o->check_del(bp, src_o, data);
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	/*  check if configuration can be added */
7668c2ecf20Sopenharmony_ci	rc = dst_o->check_add(bp, dst_o, data);
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	/* If this classification can not be added (is already set)
7698c2ecf20Sopenharmony_ci	 * or can't be deleted - return an error.
7708c2ecf20Sopenharmony_ci	 */
7718c2ecf20Sopenharmony_ci	if (rc || !pos)
7728c2ecf20Sopenharmony_ci		return false;
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	return true;
7758c2ecf20Sopenharmony_ci}
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_cistatic bool bnx2x_check_move_always_err(
7788c2ecf20Sopenharmony_ci	struct bnx2x *bp,
7798c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *src_o,
7808c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *dst_o,
7818c2ecf20Sopenharmony_ci	union bnx2x_classification_ramrod_data *data)
7828c2ecf20Sopenharmony_ci{
7838c2ecf20Sopenharmony_ci	return false;
7848c2ecf20Sopenharmony_ci}
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_cistatic inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o)
7878c2ecf20Sopenharmony_ci{
7888c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
7898c2ecf20Sopenharmony_ci	u8 rx_tx_flag = 0;
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
7928c2ecf20Sopenharmony_ci	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
7938c2ecf20Sopenharmony_ci		rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_TX_CMD;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
7968c2ecf20Sopenharmony_ci	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
7978c2ecf20Sopenharmony_ci		rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_RX_CMD;
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	return rx_tx_flag;
8008c2ecf20Sopenharmony_ci}
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_cistatic void bnx2x_set_mac_in_nig(struct bnx2x *bp,
8038c2ecf20Sopenharmony_ci				 bool add, unsigned char *dev_addr, int index)
8048c2ecf20Sopenharmony_ci{
8058c2ecf20Sopenharmony_ci	u32 wb_data[2];
8068c2ecf20Sopenharmony_ci	u32 reg_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
8078c2ecf20Sopenharmony_ci			 NIG_REG_LLH0_FUNC_MEM;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	if (!IS_MF_SI(bp) && !IS_MF_AFEX(bp))
8108c2ecf20Sopenharmony_ci		return;
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	if (index > BNX2X_LLH_CAM_MAX_PF_LINE)
8138c2ecf20Sopenharmony_ci		return;
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Going to %s LLH configuration at entry %d\n",
8168c2ecf20Sopenharmony_ci			 (add ? "ADD" : "DELETE"), index);
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	if (add) {
8198c2ecf20Sopenharmony_ci		/* LLH_FUNC_MEM is a u64 WB register */
8208c2ecf20Sopenharmony_ci		reg_offset += 8*index;
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci		wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) |
8238c2ecf20Sopenharmony_ci			      (dev_addr[4] <<  8) |  dev_addr[5]);
8248c2ecf20Sopenharmony_ci		wb_data[1] = ((dev_addr[0] <<  8) |  dev_addr[1]);
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci		REG_WR_DMAE(bp, reg_offset, wb_data, 2);
8278c2ecf20Sopenharmony_ci	}
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	REG_WR(bp, (BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE :
8308c2ecf20Sopenharmony_ci				  NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4*index, add);
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci/**
8348c2ecf20Sopenharmony_ci * bnx2x_vlan_mac_set_cmd_hdr_e2 - set a header in a single classify ramrod
8358c2ecf20Sopenharmony_ci *
8368c2ecf20Sopenharmony_ci * @bp:		device handle
8378c2ecf20Sopenharmony_ci * @o:		queue for which we want to configure this rule
8388c2ecf20Sopenharmony_ci * @add:	if true the command is an ADD command, DEL otherwise
8398c2ecf20Sopenharmony_ci * @opcode:	CLASSIFY_RULE_OPCODE_XXX
8408c2ecf20Sopenharmony_ci * @hdr:	pointer to a header to setup
8418c2ecf20Sopenharmony_ci *
8428c2ecf20Sopenharmony_ci */
8438c2ecf20Sopenharmony_cistatic inline void bnx2x_vlan_mac_set_cmd_hdr_e2(struct bnx2x *bp,
8448c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *o, bool add, int opcode,
8458c2ecf20Sopenharmony_ci	struct eth_classify_cmd_header *hdr)
8468c2ecf20Sopenharmony_ci{
8478c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	hdr->client_id = raw->cl_id;
8508c2ecf20Sopenharmony_ci	hdr->func_id = raw->func_id;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	/* Rx or/and Tx (internal switching) configuration ? */
8538c2ecf20Sopenharmony_ci	hdr->cmd_general_data |=
8548c2ecf20Sopenharmony_ci		bnx2x_vlan_mac_get_rx_tx_flag(o);
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	if (add)
8578c2ecf20Sopenharmony_ci		hdr->cmd_general_data |= ETH_CLASSIFY_CMD_HEADER_IS_ADD;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	hdr->cmd_general_data |=
8608c2ecf20Sopenharmony_ci		(opcode << ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT);
8618c2ecf20Sopenharmony_ci}
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci/**
8648c2ecf20Sopenharmony_ci * bnx2x_vlan_mac_set_rdata_hdr_e2 - set the classify ramrod data header
8658c2ecf20Sopenharmony_ci *
8668c2ecf20Sopenharmony_ci * @cid:	connection id
8678c2ecf20Sopenharmony_ci * @type:	BNX2X_FILTER_XXX_PENDING
8688c2ecf20Sopenharmony_ci * @hdr:	pointer to header to setup
8698c2ecf20Sopenharmony_ci * @rule_cnt:
8708c2ecf20Sopenharmony_ci *
8718c2ecf20Sopenharmony_ci * currently we always configure one rule and echo field to contain a CID and an
8728c2ecf20Sopenharmony_ci * opcode type.
8738c2ecf20Sopenharmony_ci */
8748c2ecf20Sopenharmony_cistatic inline void bnx2x_vlan_mac_set_rdata_hdr_e2(u32 cid, int type,
8758c2ecf20Sopenharmony_ci				struct eth_classify_header *hdr, int rule_cnt)
8768c2ecf20Sopenharmony_ci{
8778c2ecf20Sopenharmony_ci	hdr->echo = cpu_to_le32((cid & BNX2X_SWCID_MASK) |
8788c2ecf20Sopenharmony_ci				(type << BNX2X_SWCID_SHIFT));
8798c2ecf20Sopenharmony_ci	hdr->rule_cnt = (u8)rule_cnt;
8808c2ecf20Sopenharmony_ci}
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci/* hw_config() callbacks */
8838c2ecf20Sopenharmony_cistatic void bnx2x_set_one_mac_e2(struct bnx2x *bp,
8848c2ecf20Sopenharmony_ci				 struct bnx2x_vlan_mac_obj *o,
8858c2ecf20Sopenharmony_ci				 struct bnx2x_exeq_elem *elem, int rule_idx,
8868c2ecf20Sopenharmony_ci				 int cam_offset)
8878c2ecf20Sopenharmony_ci{
8888c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
8898c2ecf20Sopenharmony_ci	struct eth_classify_rules_ramrod_data *data =
8908c2ecf20Sopenharmony_ci		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
8918c2ecf20Sopenharmony_ci	int rule_cnt = rule_idx + 1, cmd = elem->cmd_data.vlan_mac.cmd;
8928c2ecf20Sopenharmony_ci	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
8938c2ecf20Sopenharmony_ci	bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
8948c2ecf20Sopenharmony_ci	unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags;
8958c2ecf20Sopenharmony_ci	u8 *mac = elem->cmd_data.vlan_mac.u.mac.mac;
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	/* Set LLH CAM entry: currently only iSCSI and ETH macs are
8988c2ecf20Sopenharmony_ci	 * relevant. In addition, current implementation is tuned for a
8998c2ecf20Sopenharmony_ci	 * single ETH MAC.
9008c2ecf20Sopenharmony_ci	 *
9018c2ecf20Sopenharmony_ci	 * When multiple unicast ETH MACs PF configuration in switch
9028c2ecf20Sopenharmony_ci	 * independent mode is required (NetQ, multiple netdev MACs,
9038c2ecf20Sopenharmony_ci	 * etc.), consider better utilisation of 8 per function MAC
9048c2ecf20Sopenharmony_ci	 * entries in the LLH register. There is also
9058c2ecf20Sopenharmony_ci	 * NIG_REG_P[01]_LLH_FUNC_MEM2 registers that complete the
9068c2ecf20Sopenharmony_ci	 * total number of CAM entries to 16.
9078c2ecf20Sopenharmony_ci	 *
9088c2ecf20Sopenharmony_ci	 * Currently we won't configure NIG for MACs other than a primary ETH
9098c2ecf20Sopenharmony_ci	 * MAC and iSCSI L2 MAC.
9108c2ecf20Sopenharmony_ci	 *
9118c2ecf20Sopenharmony_ci	 * If this MAC is moving from one Queue to another, no need to change
9128c2ecf20Sopenharmony_ci	 * NIG configuration.
9138c2ecf20Sopenharmony_ci	 */
9148c2ecf20Sopenharmony_ci	if (cmd != BNX2X_VLAN_MAC_MOVE) {
9158c2ecf20Sopenharmony_ci		if (test_bit(BNX2X_ISCSI_ETH_MAC, vlan_mac_flags))
9168c2ecf20Sopenharmony_ci			bnx2x_set_mac_in_nig(bp, add, mac,
9178c2ecf20Sopenharmony_ci					     BNX2X_LLH_CAM_ISCSI_ETH_LINE);
9188c2ecf20Sopenharmony_ci		else if (test_bit(BNX2X_ETH_MAC, vlan_mac_flags))
9198c2ecf20Sopenharmony_ci			bnx2x_set_mac_in_nig(bp, add, mac,
9208c2ecf20Sopenharmony_ci					     BNX2X_LLH_CAM_ETH_LINE);
9218c2ecf20Sopenharmony_ci	}
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	/* Reset the ramrod data buffer for the first rule */
9248c2ecf20Sopenharmony_ci	if (rule_idx == 0)
9258c2ecf20Sopenharmony_ci		memset(data, 0, sizeof(*data));
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci	/* Setup a command header */
9288c2ecf20Sopenharmony_ci	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_MAC,
9298c2ecf20Sopenharmony_ci				      &rule_entry->mac.header);
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "About to %s MAC %pM for Queue %d\n",
9328c2ecf20Sopenharmony_ci	   (add ? "add" : "delete"), mac, raw->cl_id);
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	/* Set a MAC itself */
9358c2ecf20Sopenharmony_ci	bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
9368c2ecf20Sopenharmony_ci			      &rule_entry->mac.mac_mid,
9378c2ecf20Sopenharmony_ci			      &rule_entry->mac.mac_lsb, mac);
9388c2ecf20Sopenharmony_ci	rule_entry->mac.inner_mac =
9398c2ecf20Sopenharmony_ci		cpu_to_le16(elem->cmd_data.vlan_mac.u.mac.is_inner_mac);
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci	/* MOVE: Add a rule that will add this MAC to the target Queue */
9428c2ecf20Sopenharmony_ci	if (cmd == BNX2X_VLAN_MAC_MOVE) {
9438c2ecf20Sopenharmony_ci		rule_entry++;
9448c2ecf20Sopenharmony_ci		rule_cnt++;
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci		/* Setup ramrod data */
9478c2ecf20Sopenharmony_ci		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
9488c2ecf20Sopenharmony_ci					elem->cmd_data.vlan_mac.target_obj,
9498c2ecf20Sopenharmony_ci					      true, CLASSIFY_RULE_OPCODE_MAC,
9508c2ecf20Sopenharmony_ci					      &rule_entry->mac.header);
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci		/* Set a MAC itself */
9538c2ecf20Sopenharmony_ci		bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
9548c2ecf20Sopenharmony_ci				      &rule_entry->mac.mac_mid,
9558c2ecf20Sopenharmony_ci				      &rule_entry->mac.mac_lsb, mac);
9568c2ecf20Sopenharmony_ci		rule_entry->mac.inner_mac =
9578c2ecf20Sopenharmony_ci			cpu_to_le16(elem->cmd_data.vlan_mac.
9588c2ecf20Sopenharmony_ci						u.mac.is_inner_mac);
9598c2ecf20Sopenharmony_ci	}
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci	/* Set the ramrod data header */
9628c2ecf20Sopenharmony_ci	/* TODO: take this to the higher level in order to prevent multiple
9638c2ecf20Sopenharmony_ci		 writing */
9648c2ecf20Sopenharmony_ci	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
9658c2ecf20Sopenharmony_ci					rule_cnt);
9668c2ecf20Sopenharmony_ci}
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci/**
9698c2ecf20Sopenharmony_ci * bnx2x_vlan_mac_set_rdata_hdr_e1x - set a header in a single classify ramrod
9708c2ecf20Sopenharmony_ci *
9718c2ecf20Sopenharmony_ci * @bp:		device handle
9728c2ecf20Sopenharmony_ci * @o:		queue
9738c2ecf20Sopenharmony_ci * @type:	the type of echo
9748c2ecf20Sopenharmony_ci * @cam_offset:	offset in cam memory
9758c2ecf20Sopenharmony_ci * @hdr:	pointer to a header to setup
9768c2ecf20Sopenharmony_ci *
9778c2ecf20Sopenharmony_ci * E1/E1H
9788c2ecf20Sopenharmony_ci */
9798c2ecf20Sopenharmony_cistatic inline void bnx2x_vlan_mac_set_rdata_hdr_e1x(struct bnx2x *bp,
9808c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *o, int type, int cam_offset,
9818c2ecf20Sopenharmony_ci	struct mac_configuration_hdr *hdr)
9828c2ecf20Sopenharmony_ci{
9838c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *r = &o->raw;
9848c2ecf20Sopenharmony_ci
9858c2ecf20Sopenharmony_ci	hdr->length = 1;
9868c2ecf20Sopenharmony_ci	hdr->offset = (u8)cam_offset;
9878c2ecf20Sopenharmony_ci	hdr->client_id = cpu_to_le16(0xff);
9888c2ecf20Sopenharmony_ci	hdr->echo = cpu_to_le32((r->cid & BNX2X_SWCID_MASK) |
9898c2ecf20Sopenharmony_ci				(type << BNX2X_SWCID_SHIFT));
9908c2ecf20Sopenharmony_ci}
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_cistatic inline void bnx2x_vlan_mac_set_cfg_entry_e1x(struct bnx2x *bp,
9938c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *o, bool add, int opcode, u8 *mac,
9948c2ecf20Sopenharmony_ci	u16 vlan_id, struct mac_configuration_entry *cfg_entry)
9958c2ecf20Sopenharmony_ci{
9968c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *r = &o->raw;
9978c2ecf20Sopenharmony_ci	u32 cl_bit_vec = (1 << r->cl_id);
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci	cfg_entry->clients_bit_vector = cpu_to_le32(cl_bit_vec);
10008c2ecf20Sopenharmony_ci	cfg_entry->pf_id = r->func_id;
10018c2ecf20Sopenharmony_ci	cfg_entry->vlan_id = cpu_to_le16(vlan_id);
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	if (add) {
10048c2ecf20Sopenharmony_ci		SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
10058c2ecf20Sopenharmony_ci			 T_ETH_MAC_COMMAND_SET);
10068c2ecf20Sopenharmony_ci		SET_FLAG(cfg_entry->flags,
10078c2ecf20Sopenharmony_ci			 MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE, opcode);
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci		/* Set a MAC in a ramrod data */
10108c2ecf20Sopenharmony_ci		bnx2x_set_fw_mac_addr(&cfg_entry->msb_mac_addr,
10118c2ecf20Sopenharmony_ci				      &cfg_entry->middle_mac_addr,
10128c2ecf20Sopenharmony_ci				      &cfg_entry->lsb_mac_addr, mac);
10138c2ecf20Sopenharmony_ci	} else
10148c2ecf20Sopenharmony_ci		SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
10158c2ecf20Sopenharmony_ci			 T_ETH_MAC_COMMAND_INVALIDATE);
10168c2ecf20Sopenharmony_ci}
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_cistatic inline void bnx2x_vlan_mac_set_rdata_e1x(struct bnx2x *bp,
10198c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *o, int type, int cam_offset, bool add,
10208c2ecf20Sopenharmony_ci	u8 *mac, u16 vlan_id, int opcode, struct mac_configuration_cmd *config)
10218c2ecf20Sopenharmony_ci{
10228c2ecf20Sopenharmony_ci	struct mac_configuration_entry *cfg_entry = &config->config_table[0];
10238c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	bnx2x_vlan_mac_set_rdata_hdr_e1x(bp, o, type, cam_offset,
10268c2ecf20Sopenharmony_ci					 &config->hdr);
10278c2ecf20Sopenharmony_ci	bnx2x_vlan_mac_set_cfg_entry_e1x(bp, o, add, opcode, mac, vlan_id,
10288c2ecf20Sopenharmony_ci					 cfg_entry);
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "%s MAC %pM CLID %d CAM offset %d\n",
10318c2ecf20Sopenharmony_ci			 (add ? "setting" : "clearing"),
10328c2ecf20Sopenharmony_ci			 mac, raw->cl_id, cam_offset);
10338c2ecf20Sopenharmony_ci}
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci/**
10368c2ecf20Sopenharmony_ci * bnx2x_set_one_mac_e1x - fill a single MAC rule ramrod data
10378c2ecf20Sopenharmony_ci *
10388c2ecf20Sopenharmony_ci * @bp:		device handle
10398c2ecf20Sopenharmony_ci * @o:		bnx2x_vlan_mac_obj
10408c2ecf20Sopenharmony_ci * @elem:	bnx2x_exeq_elem
10418c2ecf20Sopenharmony_ci * @rule_idx:	rule_idx
10428c2ecf20Sopenharmony_ci * @cam_offset: cam_offset
10438c2ecf20Sopenharmony_ci */
10448c2ecf20Sopenharmony_cistatic void bnx2x_set_one_mac_e1x(struct bnx2x *bp,
10458c2ecf20Sopenharmony_ci				  struct bnx2x_vlan_mac_obj *o,
10468c2ecf20Sopenharmony_ci				  struct bnx2x_exeq_elem *elem, int rule_idx,
10478c2ecf20Sopenharmony_ci				  int cam_offset)
10488c2ecf20Sopenharmony_ci{
10498c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
10508c2ecf20Sopenharmony_ci	struct mac_configuration_cmd *config =
10518c2ecf20Sopenharmony_ci		(struct mac_configuration_cmd *)(raw->rdata);
10528c2ecf20Sopenharmony_ci	/* 57710 and 57711 do not support MOVE command,
10538c2ecf20Sopenharmony_ci	 * so it's either ADD or DEL
10548c2ecf20Sopenharmony_ci	 */
10558c2ecf20Sopenharmony_ci	bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
10568c2ecf20Sopenharmony_ci		true : false;
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci	/* Reset the ramrod data buffer */
10598c2ecf20Sopenharmony_ci	memset(config, 0, sizeof(*config));
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	bnx2x_vlan_mac_set_rdata_e1x(bp, o, raw->state,
10628c2ecf20Sopenharmony_ci				     cam_offset, add,
10638c2ecf20Sopenharmony_ci				     elem->cmd_data.vlan_mac.u.mac.mac, 0,
10648c2ecf20Sopenharmony_ci				     ETH_VLAN_FILTER_ANY_VLAN, config);
10658c2ecf20Sopenharmony_ci}
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_cistatic void bnx2x_set_one_vlan_e2(struct bnx2x *bp,
10688c2ecf20Sopenharmony_ci				  struct bnx2x_vlan_mac_obj *o,
10698c2ecf20Sopenharmony_ci				  struct bnx2x_exeq_elem *elem, int rule_idx,
10708c2ecf20Sopenharmony_ci				  int cam_offset)
10718c2ecf20Sopenharmony_ci{
10728c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
10738c2ecf20Sopenharmony_ci	struct eth_classify_rules_ramrod_data *data =
10748c2ecf20Sopenharmony_ci		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
10758c2ecf20Sopenharmony_ci	int rule_cnt = rule_idx + 1;
10768c2ecf20Sopenharmony_ci	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
10778c2ecf20Sopenharmony_ci	enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd;
10788c2ecf20Sopenharmony_ci	bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
10798c2ecf20Sopenharmony_ci	u16 vlan = elem->cmd_data.vlan_mac.u.vlan.vlan;
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci	/* Reset the ramrod data buffer for the first rule */
10828c2ecf20Sopenharmony_ci	if (rule_idx == 0)
10838c2ecf20Sopenharmony_ci		memset(data, 0, sizeof(*data));
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci	/* Set a rule header */
10868c2ecf20Sopenharmony_ci	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_VLAN,
10878c2ecf20Sopenharmony_ci				      &rule_entry->vlan.header);
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "About to %s VLAN %d\n", (add ? "add" : "delete"),
10908c2ecf20Sopenharmony_ci			 vlan);
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	/* Set a VLAN itself */
10938c2ecf20Sopenharmony_ci	rule_entry->vlan.vlan = cpu_to_le16(vlan);
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	/* MOVE: Add a rule that will add this MAC to the target Queue */
10968c2ecf20Sopenharmony_ci	if (cmd == BNX2X_VLAN_MAC_MOVE) {
10978c2ecf20Sopenharmony_ci		rule_entry++;
10988c2ecf20Sopenharmony_ci		rule_cnt++;
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci		/* Setup ramrod data */
11018c2ecf20Sopenharmony_ci		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
11028c2ecf20Sopenharmony_ci					elem->cmd_data.vlan_mac.target_obj,
11038c2ecf20Sopenharmony_ci					      true, CLASSIFY_RULE_OPCODE_VLAN,
11048c2ecf20Sopenharmony_ci					      &rule_entry->vlan.header);
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci		/* Set a VLAN itself */
11078c2ecf20Sopenharmony_ci		rule_entry->vlan.vlan = cpu_to_le16(vlan);
11088c2ecf20Sopenharmony_ci	}
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	/* Set the ramrod data header */
11118c2ecf20Sopenharmony_ci	/* TODO: take this to the higher level in order to prevent multiple
11128c2ecf20Sopenharmony_ci		 writing */
11138c2ecf20Sopenharmony_ci	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
11148c2ecf20Sopenharmony_ci					rule_cnt);
11158c2ecf20Sopenharmony_ci}
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_cistatic void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
11188c2ecf20Sopenharmony_ci				      struct bnx2x_vlan_mac_obj *o,
11198c2ecf20Sopenharmony_ci				      struct bnx2x_exeq_elem *elem,
11208c2ecf20Sopenharmony_ci				      int rule_idx, int cam_offset)
11218c2ecf20Sopenharmony_ci{
11228c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
11238c2ecf20Sopenharmony_ci	struct eth_classify_rules_ramrod_data *data =
11248c2ecf20Sopenharmony_ci		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
11258c2ecf20Sopenharmony_ci	int rule_cnt = rule_idx + 1;
11268c2ecf20Sopenharmony_ci	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
11278c2ecf20Sopenharmony_ci	enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd;
11288c2ecf20Sopenharmony_ci	bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
11298c2ecf20Sopenharmony_ci	u16 vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan;
11308c2ecf20Sopenharmony_ci	u8 *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac;
11318c2ecf20Sopenharmony_ci	u16 inner_mac;
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci	/* Reset the ramrod data buffer for the first rule */
11348c2ecf20Sopenharmony_ci	if (rule_idx == 0)
11358c2ecf20Sopenharmony_ci		memset(data, 0, sizeof(*data));
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci	/* Set a rule header */
11388c2ecf20Sopenharmony_ci	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_PAIR,
11398c2ecf20Sopenharmony_ci				      &rule_entry->pair.header);
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	/* Set VLAN and MAC themselves */
11428c2ecf20Sopenharmony_ci	rule_entry->pair.vlan = cpu_to_le16(vlan);
11438c2ecf20Sopenharmony_ci	bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
11448c2ecf20Sopenharmony_ci			      &rule_entry->pair.mac_mid,
11458c2ecf20Sopenharmony_ci			      &rule_entry->pair.mac_lsb, mac);
11468c2ecf20Sopenharmony_ci	inner_mac = elem->cmd_data.vlan_mac.u.vlan_mac.is_inner_mac;
11478c2ecf20Sopenharmony_ci	rule_entry->pair.inner_mac = cpu_to_le16(inner_mac);
11488c2ecf20Sopenharmony_ci	/* MOVE: Add a rule that will add this MAC/VLAN to the target Queue */
11498c2ecf20Sopenharmony_ci	if (cmd == BNX2X_VLAN_MAC_MOVE) {
11508c2ecf20Sopenharmony_ci		struct bnx2x_vlan_mac_obj *target_obj;
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_ci		rule_entry++;
11538c2ecf20Sopenharmony_ci		rule_cnt++;
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci		/* Setup ramrod data */
11568c2ecf20Sopenharmony_ci		target_obj = elem->cmd_data.vlan_mac.target_obj;
11578c2ecf20Sopenharmony_ci		bnx2x_vlan_mac_set_cmd_hdr_e2(bp, target_obj,
11588c2ecf20Sopenharmony_ci					      true, CLASSIFY_RULE_OPCODE_PAIR,
11598c2ecf20Sopenharmony_ci					      &rule_entry->pair.header);
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci		/* Set a VLAN itself */
11628c2ecf20Sopenharmony_ci		rule_entry->pair.vlan = cpu_to_le16(vlan);
11638c2ecf20Sopenharmony_ci		bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
11648c2ecf20Sopenharmony_ci				      &rule_entry->pair.mac_mid,
11658c2ecf20Sopenharmony_ci				      &rule_entry->pair.mac_lsb, mac);
11668c2ecf20Sopenharmony_ci		rule_entry->pair.inner_mac = cpu_to_le16(inner_mac);
11678c2ecf20Sopenharmony_ci	}
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci	/* Set the ramrod data header */
11708c2ecf20Sopenharmony_ci	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
11718c2ecf20Sopenharmony_ci					rule_cnt);
11728c2ecf20Sopenharmony_ci}
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci/**
11758c2ecf20Sopenharmony_ci * bnx2x_set_one_vlan_mac_e1h -
11768c2ecf20Sopenharmony_ci *
11778c2ecf20Sopenharmony_ci * @bp:		device handle
11788c2ecf20Sopenharmony_ci * @o:		bnx2x_vlan_mac_obj
11798c2ecf20Sopenharmony_ci * @elem:	bnx2x_exeq_elem
11808c2ecf20Sopenharmony_ci * @rule_idx:	rule_idx
11818c2ecf20Sopenharmony_ci * @cam_offset:	cam_offset
11828c2ecf20Sopenharmony_ci */
11838c2ecf20Sopenharmony_cistatic void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
11848c2ecf20Sopenharmony_ci				       struct bnx2x_vlan_mac_obj *o,
11858c2ecf20Sopenharmony_ci				       struct bnx2x_exeq_elem *elem,
11868c2ecf20Sopenharmony_ci				       int rule_idx, int cam_offset)
11878c2ecf20Sopenharmony_ci{
11888c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
11898c2ecf20Sopenharmony_ci	struct mac_configuration_cmd *config =
11908c2ecf20Sopenharmony_ci		(struct mac_configuration_cmd *)(raw->rdata);
11918c2ecf20Sopenharmony_ci	/* 57710 and 57711 do not support MOVE command,
11928c2ecf20Sopenharmony_ci	 * so it's either ADD or DEL
11938c2ecf20Sopenharmony_ci	 */
11948c2ecf20Sopenharmony_ci	bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
11958c2ecf20Sopenharmony_ci		true : false;
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci	/* Reset the ramrod data buffer */
11988c2ecf20Sopenharmony_ci	memset(config, 0, sizeof(*config));
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_VLAN_MAC_PENDING,
12018c2ecf20Sopenharmony_ci				     cam_offset, add,
12028c2ecf20Sopenharmony_ci				     elem->cmd_data.vlan_mac.u.vlan_mac.mac,
12038c2ecf20Sopenharmony_ci				     elem->cmd_data.vlan_mac.u.vlan_mac.vlan,
12048c2ecf20Sopenharmony_ci				     ETH_VLAN_FILTER_CLASSIFY, config);
12058c2ecf20Sopenharmony_ci}
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci/**
12088c2ecf20Sopenharmony_ci * bnx2x_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element
12098c2ecf20Sopenharmony_ci *
12108c2ecf20Sopenharmony_ci * @bp:		device handle
12118c2ecf20Sopenharmony_ci * @p:		command parameters
12128c2ecf20Sopenharmony_ci * @ppos:	pointer to the cookie
12138c2ecf20Sopenharmony_ci *
12148c2ecf20Sopenharmony_ci * reconfigure next MAC/VLAN/VLAN-MAC element from the
12158c2ecf20Sopenharmony_ci * previously configured elements list.
12168c2ecf20Sopenharmony_ci *
12178c2ecf20Sopenharmony_ci * from command parameters only RAMROD_COMP_WAIT bit in ramrod_flags is	taken
12188c2ecf20Sopenharmony_ci * into an account
12198c2ecf20Sopenharmony_ci *
12208c2ecf20Sopenharmony_ci * pointer to the cookie  - that should be given back in the next call to make
12218c2ecf20Sopenharmony_ci * function handle the next element. If *ppos is set to NULL it will restart the
12228c2ecf20Sopenharmony_ci * iterator. If returned *ppos == NULL this means that the last element has been
12238c2ecf20Sopenharmony_ci * handled.
12248c2ecf20Sopenharmony_ci *
12258c2ecf20Sopenharmony_ci */
12268c2ecf20Sopenharmony_cistatic int bnx2x_vlan_mac_restore(struct bnx2x *bp,
12278c2ecf20Sopenharmony_ci			   struct bnx2x_vlan_mac_ramrod_params *p,
12288c2ecf20Sopenharmony_ci			   struct bnx2x_vlan_mac_registry_elem **ppos)
12298c2ecf20Sopenharmony_ci{
12308c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *pos;
12318c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci	/* If list is empty - there is nothing to do here */
12348c2ecf20Sopenharmony_ci	if (list_empty(&o->head)) {
12358c2ecf20Sopenharmony_ci		*ppos = NULL;
12368c2ecf20Sopenharmony_ci		return 0;
12378c2ecf20Sopenharmony_ci	}
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	/* make a step... */
12408c2ecf20Sopenharmony_ci	if (*ppos == NULL)
12418c2ecf20Sopenharmony_ci		*ppos = list_first_entry(&o->head,
12428c2ecf20Sopenharmony_ci					 struct bnx2x_vlan_mac_registry_elem,
12438c2ecf20Sopenharmony_ci					 link);
12448c2ecf20Sopenharmony_ci	else
12458c2ecf20Sopenharmony_ci		*ppos = list_next_entry(*ppos, link);
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	pos = *ppos;
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci	/* If it's the last step - return NULL */
12508c2ecf20Sopenharmony_ci	if (list_is_last(&pos->link, &o->head))
12518c2ecf20Sopenharmony_ci		*ppos = NULL;
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_ci	/* Prepare a 'user_req' */
12548c2ecf20Sopenharmony_ci	memcpy(&p->user_req.u, &pos->u, sizeof(pos->u));
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	/* Set the command */
12578c2ecf20Sopenharmony_ci	p->user_req.cmd = BNX2X_VLAN_MAC_ADD;
12588c2ecf20Sopenharmony_ci
12598c2ecf20Sopenharmony_ci	/* Set vlan_mac_flags */
12608c2ecf20Sopenharmony_ci	p->user_req.vlan_mac_flags = pos->vlan_mac_flags;
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ci	/* Set a restore bit */
12638c2ecf20Sopenharmony_ci	__set_bit(RAMROD_RESTORE, &p->ramrod_flags);
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci	return bnx2x_config_vlan_mac(bp, p);
12668c2ecf20Sopenharmony_ci}
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci/* bnx2x_exeq_get_mac/bnx2x_exeq_get_vlan/bnx2x_exeq_get_vlan_mac return a
12698c2ecf20Sopenharmony_ci * pointer to an element with a specific criteria and NULL if such an element
12708c2ecf20Sopenharmony_ci * hasn't been found.
12718c2ecf20Sopenharmony_ci */
12728c2ecf20Sopenharmony_cistatic struct bnx2x_exeq_elem *bnx2x_exeq_get_mac(
12738c2ecf20Sopenharmony_ci	struct bnx2x_exe_queue_obj *o,
12748c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *elem)
12758c2ecf20Sopenharmony_ci{
12768c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *pos;
12778c2ecf20Sopenharmony_ci	struct bnx2x_mac_ramrod_data *data = &elem->cmd_data.vlan_mac.u.mac;
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_ci	/* Check pending for execution commands */
12808c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &o->exe_queue, link)
12818c2ecf20Sopenharmony_ci		if (!memcmp(&pos->cmd_data.vlan_mac.u.mac, data,
12828c2ecf20Sopenharmony_ci			      sizeof(*data)) &&
12838c2ecf20Sopenharmony_ci		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
12848c2ecf20Sopenharmony_ci			return pos;
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_ci	return NULL;
12878c2ecf20Sopenharmony_ci}
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_cistatic struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan(
12908c2ecf20Sopenharmony_ci	struct bnx2x_exe_queue_obj *o,
12918c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *elem)
12928c2ecf20Sopenharmony_ci{
12938c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *pos;
12948c2ecf20Sopenharmony_ci	struct bnx2x_vlan_ramrod_data *data = &elem->cmd_data.vlan_mac.u.vlan;
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ci	/* Check pending for execution commands */
12978c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &o->exe_queue, link)
12988c2ecf20Sopenharmony_ci		if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan, data,
12998c2ecf20Sopenharmony_ci			      sizeof(*data)) &&
13008c2ecf20Sopenharmony_ci		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
13018c2ecf20Sopenharmony_ci			return pos;
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	return NULL;
13048c2ecf20Sopenharmony_ci}
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_cistatic struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan_mac(
13078c2ecf20Sopenharmony_ci	struct bnx2x_exe_queue_obj *o,
13088c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *elem)
13098c2ecf20Sopenharmony_ci{
13108c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *pos;
13118c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_ramrod_data *data =
13128c2ecf20Sopenharmony_ci		&elem->cmd_data.vlan_mac.u.vlan_mac;
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_ci	/* Check pending for execution commands */
13158c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &o->exe_queue, link)
13168c2ecf20Sopenharmony_ci		if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan_mac, data,
13178c2ecf20Sopenharmony_ci			    sizeof(*data)) &&
13188c2ecf20Sopenharmony_ci		    (pos->cmd_data.vlan_mac.cmd ==
13198c2ecf20Sopenharmony_ci		     elem->cmd_data.vlan_mac.cmd))
13208c2ecf20Sopenharmony_ci			return pos;
13218c2ecf20Sopenharmony_ci
13228c2ecf20Sopenharmony_ci	return NULL;
13238c2ecf20Sopenharmony_ci}
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci/**
13268c2ecf20Sopenharmony_ci * bnx2x_validate_vlan_mac_add - check if an ADD command can be executed
13278c2ecf20Sopenharmony_ci *
13288c2ecf20Sopenharmony_ci * @bp:		device handle
13298c2ecf20Sopenharmony_ci * @qo:		bnx2x_qable_obj
13308c2ecf20Sopenharmony_ci * @elem:	bnx2x_exeq_elem
13318c2ecf20Sopenharmony_ci *
13328c2ecf20Sopenharmony_ci * Checks that the requested configuration can be added. If yes and if
13338c2ecf20Sopenharmony_ci * requested, consume CAM credit.
13348c2ecf20Sopenharmony_ci *
13358c2ecf20Sopenharmony_ci * The 'validate' is run after the 'optimize'.
13368c2ecf20Sopenharmony_ci *
13378c2ecf20Sopenharmony_ci */
13388c2ecf20Sopenharmony_cistatic inline int bnx2x_validate_vlan_mac_add(struct bnx2x *bp,
13398c2ecf20Sopenharmony_ci					      union bnx2x_qable_obj *qo,
13408c2ecf20Sopenharmony_ci					      struct bnx2x_exeq_elem *elem)
13418c2ecf20Sopenharmony_ci{
13428c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
13438c2ecf20Sopenharmony_ci	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
13448c2ecf20Sopenharmony_ci	int rc;
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ci	/* Check the registry */
13478c2ecf20Sopenharmony_ci	rc = o->check_add(bp, o, &elem->cmd_data.vlan_mac.u);
13488c2ecf20Sopenharmony_ci	if (rc) {
13498c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "ADD command is not allowed considering current registry state.\n");
13508c2ecf20Sopenharmony_ci		return rc;
13518c2ecf20Sopenharmony_ci	}
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_ci	/* Check if there is a pending ADD command for this
13548c2ecf20Sopenharmony_ci	 * MAC/VLAN/VLAN-MAC. Return an error if there is.
13558c2ecf20Sopenharmony_ci	 */
13568c2ecf20Sopenharmony_ci	if (exeq->get(exeq, elem)) {
13578c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "There is a pending ADD command already\n");
13588c2ecf20Sopenharmony_ci		return -EEXIST;
13598c2ecf20Sopenharmony_ci	}
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci	/* TODO: Check the pending MOVE from other objects where this
13628c2ecf20Sopenharmony_ci	 * object is a destination object.
13638c2ecf20Sopenharmony_ci	 */
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci	/* Consume the credit if not requested not to */
13668c2ecf20Sopenharmony_ci	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
13678c2ecf20Sopenharmony_ci		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
13688c2ecf20Sopenharmony_ci	    o->get_credit(o)))
13698c2ecf20Sopenharmony_ci		return -EINVAL;
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	return 0;
13728c2ecf20Sopenharmony_ci}
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_ci/**
13758c2ecf20Sopenharmony_ci * bnx2x_validate_vlan_mac_del - check if the DEL command can be executed
13768c2ecf20Sopenharmony_ci *
13778c2ecf20Sopenharmony_ci * @bp:		device handle
13788c2ecf20Sopenharmony_ci * @qo:		quable object to check
13798c2ecf20Sopenharmony_ci * @elem:	element that needs to be deleted
13808c2ecf20Sopenharmony_ci *
13818c2ecf20Sopenharmony_ci * Checks that the requested configuration can be deleted. If yes and if
13828c2ecf20Sopenharmony_ci * requested, returns a CAM credit.
13838c2ecf20Sopenharmony_ci *
13848c2ecf20Sopenharmony_ci * The 'validate' is run after the 'optimize'.
13858c2ecf20Sopenharmony_ci */
13868c2ecf20Sopenharmony_cistatic inline int bnx2x_validate_vlan_mac_del(struct bnx2x *bp,
13878c2ecf20Sopenharmony_ci					      union bnx2x_qable_obj *qo,
13888c2ecf20Sopenharmony_ci					      struct bnx2x_exeq_elem *elem)
13898c2ecf20Sopenharmony_ci{
13908c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
13918c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *pos;
13928c2ecf20Sopenharmony_ci	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
13938c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem query_elem;
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	/* If this classification can not be deleted (doesn't exist)
13968c2ecf20Sopenharmony_ci	 * - return a BNX2X_EXIST.
13978c2ecf20Sopenharmony_ci	 */
13988c2ecf20Sopenharmony_ci	pos = o->check_del(bp, o, &elem->cmd_data.vlan_mac.u);
13998c2ecf20Sopenharmony_ci	if (!pos) {
14008c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "DEL command is not allowed considering current registry state\n");
14018c2ecf20Sopenharmony_ci		return -EEXIST;
14028c2ecf20Sopenharmony_ci	}
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	/* Check if there are pending DEL or MOVE commands for this
14058c2ecf20Sopenharmony_ci	 * MAC/VLAN/VLAN-MAC. Return an error if so.
14068c2ecf20Sopenharmony_ci	 */
14078c2ecf20Sopenharmony_ci	memcpy(&query_elem, elem, sizeof(query_elem));
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci	/* Check for MOVE commands */
14108c2ecf20Sopenharmony_ci	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_MOVE;
14118c2ecf20Sopenharmony_ci	if (exeq->get(exeq, &query_elem)) {
14128c2ecf20Sopenharmony_ci		BNX2X_ERR("There is a pending MOVE command already\n");
14138c2ecf20Sopenharmony_ci		return -EINVAL;
14148c2ecf20Sopenharmony_ci	}
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci	/* Check for DEL commands */
14178c2ecf20Sopenharmony_ci	if (exeq->get(exeq, elem)) {
14188c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "There is a pending DEL command already\n");
14198c2ecf20Sopenharmony_ci		return -EEXIST;
14208c2ecf20Sopenharmony_ci	}
14218c2ecf20Sopenharmony_ci
14228c2ecf20Sopenharmony_ci	/* Return the credit to the credit pool if not requested not to */
14238c2ecf20Sopenharmony_ci	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
14248c2ecf20Sopenharmony_ci		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
14258c2ecf20Sopenharmony_ci	    o->put_credit(o))) {
14268c2ecf20Sopenharmony_ci		BNX2X_ERR("Failed to return a credit\n");
14278c2ecf20Sopenharmony_ci		return -EINVAL;
14288c2ecf20Sopenharmony_ci	}
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	return 0;
14318c2ecf20Sopenharmony_ci}
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_ci/**
14348c2ecf20Sopenharmony_ci * bnx2x_validate_vlan_mac_move - check if the MOVE command can be executed
14358c2ecf20Sopenharmony_ci *
14368c2ecf20Sopenharmony_ci * @bp:		device handle
14378c2ecf20Sopenharmony_ci * @qo:		quable object to check (source)
14388c2ecf20Sopenharmony_ci * @elem:	element that needs to be moved
14398c2ecf20Sopenharmony_ci *
14408c2ecf20Sopenharmony_ci * Checks that the requested configuration can be moved. If yes and if
14418c2ecf20Sopenharmony_ci * requested, returns a CAM credit.
14428c2ecf20Sopenharmony_ci *
14438c2ecf20Sopenharmony_ci * The 'validate' is run after the 'optimize'.
14448c2ecf20Sopenharmony_ci */
14458c2ecf20Sopenharmony_cistatic inline int bnx2x_validate_vlan_mac_move(struct bnx2x *bp,
14468c2ecf20Sopenharmony_ci					       union bnx2x_qable_obj *qo,
14478c2ecf20Sopenharmony_ci					       struct bnx2x_exeq_elem *elem)
14488c2ecf20Sopenharmony_ci{
14498c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *src_o = &qo->vlan_mac;
14508c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *dest_o = elem->cmd_data.vlan_mac.target_obj;
14518c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem query_elem;
14528c2ecf20Sopenharmony_ci	struct bnx2x_exe_queue_obj *src_exeq = &src_o->exe_queue;
14538c2ecf20Sopenharmony_ci	struct bnx2x_exe_queue_obj *dest_exeq = &dest_o->exe_queue;
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci	/* Check if we can perform this operation based on the current registry
14568c2ecf20Sopenharmony_ci	 * state.
14578c2ecf20Sopenharmony_ci	 */
14588c2ecf20Sopenharmony_ci	if (!src_o->check_move(bp, src_o, dest_o,
14598c2ecf20Sopenharmony_ci			       &elem->cmd_data.vlan_mac.u)) {
14608c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "MOVE command is not allowed considering current registry state\n");
14618c2ecf20Sopenharmony_ci		return -EINVAL;
14628c2ecf20Sopenharmony_ci	}
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci	/* Check if there is an already pending DEL or MOVE command for the
14658c2ecf20Sopenharmony_ci	 * source object or ADD command for a destination object. Return an
14668c2ecf20Sopenharmony_ci	 * error if so.
14678c2ecf20Sopenharmony_ci	 */
14688c2ecf20Sopenharmony_ci	memcpy(&query_elem, elem, sizeof(query_elem));
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	/* Check DEL on source */
14718c2ecf20Sopenharmony_ci	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
14728c2ecf20Sopenharmony_ci	if (src_exeq->get(src_exeq, &query_elem)) {
14738c2ecf20Sopenharmony_ci		BNX2X_ERR("There is a pending DEL command on the source queue already\n");
14748c2ecf20Sopenharmony_ci		return -EINVAL;
14758c2ecf20Sopenharmony_ci	}
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci	/* Check MOVE on source */
14788c2ecf20Sopenharmony_ci	if (src_exeq->get(src_exeq, elem)) {
14798c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "There is a pending MOVE command already\n");
14808c2ecf20Sopenharmony_ci		return -EEXIST;
14818c2ecf20Sopenharmony_ci	}
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_ci	/* Check ADD on destination */
14848c2ecf20Sopenharmony_ci	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
14858c2ecf20Sopenharmony_ci	if (dest_exeq->get(dest_exeq, &query_elem)) {
14868c2ecf20Sopenharmony_ci		BNX2X_ERR("There is a pending ADD command on the destination queue already\n");
14878c2ecf20Sopenharmony_ci		return -EINVAL;
14888c2ecf20Sopenharmony_ci	}
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci	/* Consume the credit if not requested not to */
14918c2ecf20Sopenharmony_ci	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
14928c2ecf20Sopenharmony_ci		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
14938c2ecf20Sopenharmony_ci	    dest_o->get_credit(dest_o)))
14948c2ecf20Sopenharmony_ci		return -EINVAL;
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
14978c2ecf20Sopenharmony_ci		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
14988c2ecf20Sopenharmony_ci	    src_o->put_credit(src_o))) {
14998c2ecf20Sopenharmony_ci		/* return the credit taken from dest... */
15008c2ecf20Sopenharmony_ci		dest_o->put_credit(dest_o);
15018c2ecf20Sopenharmony_ci		return -EINVAL;
15028c2ecf20Sopenharmony_ci	}
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	return 0;
15058c2ecf20Sopenharmony_ci}
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_cistatic int bnx2x_validate_vlan_mac(struct bnx2x *bp,
15088c2ecf20Sopenharmony_ci				   union bnx2x_qable_obj *qo,
15098c2ecf20Sopenharmony_ci				   struct bnx2x_exeq_elem *elem)
15108c2ecf20Sopenharmony_ci{
15118c2ecf20Sopenharmony_ci	switch (elem->cmd_data.vlan_mac.cmd) {
15128c2ecf20Sopenharmony_ci	case BNX2X_VLAN_MAC_ADD:
15138c2ecf20Sopenharmony_ci		return bnx2x_validate_vlan_mac_add(bp, qo, elem);
15148c2ecf20Sopenharmony_ci	case BNX2X_VLAN_MAC_DEL:
15158c2ecf20Sopenharmony_ci		return bnx2x_validate_vlan_mac_del(bp, qo, elem);
15168c2ecf20Sopenharmony_ci	case BNX2X_VLAN_MAC_MOVE:
15178c2ecf20Sopenharmony_ci		return bnx2x_validate_vlan_mac_move(bp, qo, elem);
15188c2ecf20Sopenharmony_ci	default:
15198c2ecf20Sopenharmony_ci		return -EINVAL;
15208c2ecf20Sopenharmony_ci	}
15218c2ecf20Sopenharmony_ci}
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_cistatic int bnx2x_remove_vlan_mac(struct bnx2x *bp,
15248c2ecf20Sopenharmony_ci				  union bnx2x_qable_obj *qo,
15258c2ecf20Sopenharmony_ci				  struct bnx2x_exeq_elem *elem)
15268c2ecf20Sopenharmony_ci{
15278c2ecf20Sopenharmony_ci	int rc = 0;
15288c2ecf20Sopenharmony_ci
15298c2ecf20Sopenharmony_ci	/* If consumption wasn't required, nothing to do */
15308c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
15318c2ecf20Sopenharmony_ci		     &elem->cmd_data.vlan_mac.vlan_mac_flags))
15328c2ecf20Sopenharmony_ci		return 0;
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_ci	switch (elem->cmd_data.vlan_mac.cmd) {
15358c2ecf20Sopenharmony_ci	case BNX2X_VLAN_MAC_ADD:
15368c2ecf20Sopenharmony_ci	case BNX2X_VLAN_MAC_MOVE:
15378c2ecf20Sopenharmony_ci		rc = qo->vlan_mac.put_credit(&qo->vlan_mac);
15388c2ecf20Sopenharmony_ci		break;
15398c2ecf20Sopenharmony_ci	case BNX2X_VLAN_MAC_DEL:
15408c2ecf20Sopenharmony_ci		rc = qo->vlan_mac.get_credit(&qo->vlan_mac);
15418c2ecf20Sopenharmony_ci		break;
15428c2ecf20Sopenharmony_ci	default:
15438c2ecf20Sopenharmony_ci		return -EINVAL;
15448c2ecf20Sopenharmony_ci	}
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	if (rc != true)
15478c2ecf20Sopenharmony_ci		return -EINVAL;
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci	return 0;
15508c2ecf20Sopenharmony_ci}
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci/**
15538c2ecf20Sopenharmony_ci * bnx2x_wait_vlan_mac - passively wait for 5 seconds until all work completes.
15548c2ecf20Sopenharmony_ci *
15558c2ecf20Sopenharmony_ci * @bp:		device handle
15568c2ecf20Sopenharmony_ci * @o:		bnx2x_vlan_mac_obj
15578c2ecf20Sopenharmony_ci *
15588c2ecf20Sopenharmony_ci */
15598c2ecf20Sopenharmony_cistatic int bnx2x_wait_vlan_mac(struct bnx2x *bp,
15608c2ecf20Sopenharmony_ci			       struct bnx2x_vlan_mac_obj *o)
15618c2ecf20Sopenharmony_ci{
15628c2ecf20Sopenharmony_ci	int cnt = 5000, rc;
15638c2ecf20Sopenharmony_ci	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
15648c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_ci	while (cnt--) {
15678c2ecf20Sopenharmony_ci		/* Wait for the current command to complete */
15688c2ecf20Sopenharmony_ci		rc = raw->wait_comp(bp, raw);
15698c2ecf20Sopenharmony_ci		if (rc)
15708c2ecf20Sopenharmony_ci			return rc;
15718c2ecf20Sopenharmony_ci
15728c2ecf20Sopenharmony_ci		/* Wait until there are no pending commands */
15738c2ecf20Sopenharmony_ci		if (!bnx2x_exe_queue_empty(exeq))
15748c2ecf20Sopenharmony_ci			usleep_range(1000, 2000);
15758c2ecf20Sopenharmony_ci		else
15768c2ecf20Sopenharmony_ci			return 0;
15778c2ecf20Sopenharmony_ci	}
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_ci	return -EBUSY;
15808c2ecf20Sopenharmony_ci}
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_cistatic int __bnx2x_vlan_mac_execute_step(struct bnx2x *bp,
15838c2ecf20Sopenharmony_ci					 struct bnx2x_vlan_mac_obj *o,
15848c2ecf20Sopenharmony_ci					 unsigned long *ramrod_flags)
15858c2ecf20Sopenharmony_ci{
15868c2ecf20Sopenharmony_ci	int rc = 0;
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_ci	spin_lock_bh(&o->exe_queue.lock);
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "vlan_mac_execute_step - trying to take writer lock\n");
15918c2ecf20Sopenharmony_ci	rc = __bnx2x_vlan_mac_h_write_trylock(bp, o);
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci	if (rc != 0) {
15948c2ecf20Sopenharmony_ci		__bnx2x_vlan_mac_h_pend(bp, o, *ramrod_flags);
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_ci		/* Calling function should not differentiate between this case
15978c2ecf20Sopenharmony_ci		 * and the case in which there is already a pending ramrod
15988c2ecf20Sopenharmony_ci		 */
15998c2ecf20Sopenharmony_ci		rc = 1;
16008c2ecf20Sopenharmony_ci	} else {
16018c2ecf20Sopenharmony_ci		rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
16028c2ecf20Sopenharmony_ci	}
16038c2ecf20Sopenharmony_ci	spin_unlock_bh(&o->exe_queue.lock);
16048c2ecf20Sopenharmony_ci
16058c2ecf20Sopenharmony_ci	return rc;
16068c2ecf20Sopenharmony_ci}
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_ci/**
16098c2ecf20Sopenharmony_ci * bnx2x_complete_vlan_mac - complete one VLAN-MAC ramrod
16108c2ecf20Sopenharmony_ci *
16118c2ecf20Sopenharmony_ci * @bp:		device handle
16128c2ecf20Sopenharmony_ci * @o:		bnx2x_vlan_mac_obj
16138c2ecf20Sopenharmony_ci * @cqe:	completion element
16148c2ecf20Sopenharmony_ci * @ramrod_flags: if set schedule next execution chunk
16158c2ecf20Sopenharmony_ci *
16168c2ecf20Sopenharmony_ci */
16178c2ecf20Sopenharmony_cistatic int bnx2x_complete_vlan_mac(struct bnx2x *bp,
16188c2ecf20Sopenharmony_ci				   struct bnx2x_vlan_mac_obj *o,
16198c2ecf20Sopenharmony_ci				   union event_ring_elem *cqe,
16208c2ecf20Sopenharmony_ci				   unsigned long *ramrod_flags)
16218c2ecf20Sopenharmony_ci{
16228c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *r = &o->raw;
16238c2ecf20Sopenharmony_ci	int rc;
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci	/* Clearing the pending list & raw state should be made
16268c2ecf20Sopenharmony_ci	 * atomically (as execution flow assumes they represent the same).
16278c2ecf20Sopenharmony_ci	 */
16288c2ecf20Sopenharmony_ci	spin_lock_bh(&o->exe_queue.lock);
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	/* Reset pending list */
16318c2ecf20Sopenharmony_ci	__bnx2x_exe_queue_reset_pending(bp, &o->exe_queue);
16328c2ecf20Sopenharmony_ci
16338c2ecf20Sopenharmony_ci	/* Clear pending */
16348c2ecf20Sopenharmony_ci	r->clear_pending(r);
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ci	spin_unlock_bh(&o->exe_queue.lock);
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_ci	/* If ramrod failed this is most likely a SW bug */
16398c2ecf20Sopenharmony_ci	if (cqe->message.error)
16408c2ecf20Sopenharmony_ci		return -EINVAL;
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_ci	/* Run the next bulk of pending commands if requested */
16438c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_CONT, ramrod_flags)) {
16448c2ecf20Sopenharmony_ci		rc = __bnx2x_vlan_mac_execute_step(bp, o, ramrod_flags);
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_ci		if (rc < 0)
16478c2ecf20Sopenharmony_ci			return rc;
16488c2ecf20Sopenharmony_ci	}
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ci	/* If there is more work to do return PENDING */
16518c2ecf20Sopenharmony_ci	if (!bnx2x_exe_queue_empty(&o->exe_queue))
16528c2ecf20Sopenharmony_ci		return 1;
16538c2ecf20Sopenharmony_ci
16548c2ecf20Sopenharmony_ci	return 0;
16558c2ecf20Sopenharmony_ci}
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_ci/**
16588c2ecf20Sopenharmony_ci * bnx2x_optimize_vlan_mac - optimize ADD and DEL commands.
16598c2ecf20Sopenharmony_ci *
16608c2ecf20Sopenharmony_ci * @bp:		device handle
16618c2ecf20Sopenharmony_ci * @qo:		bnx2x_qable_obj
16628c2ecf20Sopenharmony_ci * @elem:	bnx2x_exeq_elem
16638c2ecf20Sopenharmony_ci */
16648c2ecf20Sopenharmony_cistatic int bnx2x_optimize_vlan_mac(struct bnx2x *bp,
16658c2ecf20Sopenharmony_ci				   union bnx2x_qable_obj *qo,
16668c2ecf20Sopenharmony_ci				   struct bnx2x_exeq_elem *elem)
16678c2ecf20Sopenharmony_ci{
16688c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem query, *pos;
16698c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
16708c2ecf20Sopenharmony_ci	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	memcpy(&query, elem, sizeof(query));
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci	switch (elem->cmd_data.vlan_mac.cmd) {
16758c2ecf20Sopenharmony_ci	case BNX2X_VLAN_MAC_ADD:
16768c2ecf20Sopenharmony_ci		query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
16778c2ecf20Sopenharmony_ci		break;
16788c2ecf20Sopenharmony_ci	case BNX2X_VLAN_MAC_DEL:
16798c2ecf20Sopenharmony_ci		query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
16808c2ecf20Sopenharmony_ci		break;
16818c2ecf20Sopenharmony_ci	default:
16828c2ecf20Sopenharmony_ci		/* Don't handle anything other than ADD or DEL */
16838c2ecf20Sopenharmony_ci		return 0;
16848c2ecf20Sopenharmony_ci	}
16858c2ecf20Sopenharmony_ci
16868c2ecf20Sopenharmony_ci	/* If we found the appropriate element - delete it */
16878c2ecf20Sopenharmony_ci	pos = exeq->get(exeq, &query);
16888c2ecf20Sopenharmony_ci	if (pos) {
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_ci		/* Return the credit of the optimized command */
16918c2ecf20Sopenharmony_ci		if (!test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
16928c2ecf20Sopenharmony_ci			      &pos->cmd_data.vlan_mac.vlan_mac_flags)) {
16938c2ecf20Sopenharmony_ci			if ((query.cmd_data.vlan_mac.cmd ==
16948c2ecf20Sopenharmony_ci			     BNX2X_VLAN_MAC_ADD) && !o->put_credit(o)) {
16958c2ecf20Sopenharmony_ci				BNX2X_ERR("Failed to return the credit for the optimized ADD command\n");
16968c2ecf20Sopenharmony_ci				return -EINVAL;
16978c2ecf20Sopenharmony_ci			} else if (!o->get_credit(o)) { /* VLAN_MAC_DEL */
16988c2ecf20Sopenharmony_ci				BNX2X_ERR("Failed to recover the credit from the optimized DEL command\n");
16998c2ecf20Sopenharmony_ci				return -EINVAL;
17008c2ecf20Sopenharmony_ci			}
17018c2ecf20Sopenharmony_ci		}
17028c2ecf20Sopenharmony_ci
17038c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "Optimizing %s command\n",
17048c2ecf20Sopenharmony_ci			   (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
17058c2ecf20Sopenharmony_ci			   "ADD" : "DEL");
17068c2ecf20Sopenharmony_ci
17078c2ecf20Sopenharmony_ci		list_del(&pos->link);
17088c2ecf20Sopenharmony_ci		bnx2x_exe_queue_free_elem(bp, pos);
17098c2ecf20Sopenharmony_ci		return 1;
17108c2ecf20Sopenharmony_ci	}
17118c2ecf20Sopenharmony_ci
17128c2ecf20Sopenharmony_ci	return 0;
17138c2ecf20Sopenharmony_ci}
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci/**
17168c2ecf20Sopenharmony_ci * bnx2x_vlan_mac_get_registry_elem - prepare a registry element
17178c2ecf20Sopenharmony_ci *
17188c2ecf20Sopenharmony_ci * @bp:	  device handle
17198c2ecf20Sopenharmony_ci * @o:	vlan object
17208c2ecf20Sopenharmony_ci * @elem: element
17218c2ecf20Sopenharmony_ci * @restore: to restore or not
17228c2ecf20Sopenharmony_ci * @re: registry
17238c2ecf20Sopenharmony_ci *
17248c2ecf20Sopenharmony_ci * prepare a registry element according to the current command request.
17258c2ecf20Sopenharmony_ci */
17268c2ecf20Sopenharmony_cistatic inline int bnx2x_vlan_mac_get_registry_elem(
17278c2ecf20Sopenharmony_ci	struct bnx2x *bp,
17288c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *o,
17298c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *elem,
17308c2ecf20Sopenharmony_ci	bool restore,
17318c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem **re)
17328c2ecf20Sopenharmony_ci{
17338c2ecf20Sopenharmony_ci	enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd;
17348c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *reg_elem;
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ci	/* Allocate a new registry element if needed. */
17378c2ecf20Sopenharmony_ci	if (!restore &&
17388c2ecf20Sopenharmony_ci	    ((cmd == BNX2X_VLAN_MAC_ADD) || (cmd == BNX2X_VLAN_MAC_MOVE))) {
17398c2ecf20Sopenharmony_ci		reg_elem = kzalloc(sizeof(*reg_elem), GFP_ATOMIC);
17408c2ecf20Sopenharmony_ci		if (!reg_elem)
17418c2ecf20Sopenharmony_ci			return -ENOMEM;
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_ci		/* Get a new CAM offset */
17448c2ecf20Sopenharmony_ci		if (!o->get_cam_offset(o, &reg_elem->cam_offset)) {
17458c2ecf20Sopenharmony_ci			/* This shall never happen, because we have checked the
17468c2ecf20Sopenharmony_ci			 * CAM availability in the 'validate'.
17478c2ecf20Sopenharmony_ci			 */
17488c2ecf20Sopenharmony_ci			WARN_ON(1);
17498c2ecf20Sopenharmony_ci			kfree(reg_elem);
17508c2ecf20Sopenharmony_ci			return -EINVAL;
17518c2ecf20Sopenharmony_ci		}
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "Got cam offset %d\n", reg_elem->cam_offset);
17548c2ecf20Sopenharmony_ci
17558c2ecf20Sopenharmony_ci		/* Set a VLAN-MAC data */
17568c2ecf20Sopenharmony_ci		memcpy(&reg_elem->u, &elem->cmd_data.vlan_mac.u,
17578c2ecf20Sopenharmony_ci			  sizeof(reg_elem->u));
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci		/* Copy the flags (needed for DEL and RESTORE flows) */
17608c2ecf20Sopenharmony_ci		reg_elem->vlan_mac_flags =
17618c2ecf20Sopenharmony_ci			elem->cmd_data.vlan_mac.vlan_mac_flags;
17628c2ecf20Sopenharmony_ci	} else /* DEL, RESTORE */
17638c2ecf20Sopenharmony_ci		reg_elem = o->check_del(bp, o, &elem->cmd_data.vlan_mac.u);
17648c2ecf20Sopenharmony_ci
17658c2ecf20Sopenharmony_ci	*re = reg_elem;
17668c2ecf20Sopenharmony_ci	return 0;
17678c2ecf20Sopenharmony_ci}
17688c2ecf20Sopenharmony_ci
17698c2ecf20Sopenharmony_ci/**
17708c2ecf20Sopenharmony_ci * bnx2x_execute_vlan_mac - execute vlan mac command
17718c2ecf20Sopenharmony_ci *
17728c2ecf20Sopenharmony_ci * @bp:			device handle
17738c2ecf20Sopenharmony_ci * @qo:			bnx2x_qable_obj pointer
17748c2ecf20Sopenharmony_ci * @exe_chunk:		chunk
17758c2ecf20Sopenharmony_ci * @ramrod_flags:	flags
17768c2ecf20Sopenharmony_ci *
17778c2ecf20Sopenharmony_ci * go and send a ramrod!
17788c2ecf20Sopenharmony_ci */
17798c2ecf20Sopenharmony_cistatic int bnx2x_execute_vlan_mac(struct bnx2x *bp,
17808c2ecf20Sopenharmony_ci				  union bnx2x_qable_obj *qo,
17818c2ecf20Sopenharmony_ci				  struct list_head *exe_chunk,
17828c2ecf20Sopenharmony_ci				  unsigned long *ramrod_flags)
17838c2ecf20Sopenharmony_ci{
17848c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *elem;
17858c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac, *cam_obj;
17868c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *r = &o->raw;
17878c2ecf20Sopenharmony_ci	int rc, idx = 0;
17888c2ecf20Sopenharmony_ci	bool restore = test_bit(RAMROD_RESTORE, ramrod_flags);
17898c2ecf20Sopenharmony_ci	bool drv_only = test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags);
17908c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *reg_elem;
17918c2ecf20Sopenharmony_ci	enum bnx2x_vlan_mac_cmd cmd;
17928c2ecf20Sopenharmony_ci
17938c2ecf20Sopenharmony_ci	/* If DRIVER_ONLY execution is requested, cleanup a registry
17948c2ecf20Sopenharmony_ci	 * and exit. Otherwise send a ramrod to FW.
17958c2ecf20Sopenharmony_ci	 */
17968c2ecf20Sopenharmony_ci	if (!drv_only) {
17978c2ecf20Sopenharmony_ci		WARN_ON(r->check_pending(r));
17988c2ecf20Sopenharmony_ci
17998c2ecf20Sopenharmony_ci		/* Set pending */
18008c2ecf20Sopenharmony_ci		r->set_pending(r);
18018c2ecf20Sopenharmony_ci
18028c2ecf20Sopenharmony_ci		/* Fill the ramrod data */
18038c2ecf20Sopenharmony_ci		list_for_each_entry(elem, exe_chunk, link) {
18048c2ecf20Sopenharmony_ci			cmd = elem->cmd_data.vlan_mac.cmd;
18058c2ecf20Sopenharmony_ci			/* We will add to the target object in MOVE command, so
18068c2ecf20Sopenharmony_ci			 * change the object for a CAM search.
18078c2ecf20Sopenharmony_ci			 */
18088c2ecf20Sopenharmony_ci			if (cmd == BNX2X_VLAN_MAC_MOVE)
18098c2ecf20Sopenharmony_ci				cam_obj = elem->cmd_data.vlan_mac.target_obj;
18108c2ecf20Sopenharmony_ci			else
18118c2ecf20Sopenharmony_ci				cam_obj = o;
18128c2ecf20Sopenharmony_ci
18138c2ecf20Sopenharmony_ci			rc = bnx2x_vlan_mac_get_registry_elem(bp, cam_obj,
18148c2ecf20Sopenharmony_ci							      elem, restore,
18158c2ecf20Sopenharmony_ci							      &reg_elem);
18168c2ecf20Sopenharmony_ci			if (rc)
18178c2ecf20Sopenharmony_ci				goto error_exit;
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci			WARN_ON(!reg_elem);
18208c2ecf20Sopenharmony_ci
18218c2ecf20Sopenharmony_ci			/* Push a new entry into the registry */
18228c2ecf20Sopenharmony_ci			if (!restore &&
18238c2ecf20Sopenharmony_ci			    ((cmd == BNX2X_VLAN_MAC_ADD) ||
18248c2ecf20Sopenharmony_ci			    (cmd == BNX2X_VLAN_MAC_MOVE)))
18258c2ecf20Sopenharmony_ci				list_add(&reg_elem->link, &cam_obj->head);
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ci			/* Configure a single command in a ramrod data buffer */
18288c2ecf20Sopenharmony_ci			o->set_one_rule(bp, o, elem, idx,
18298c2ecf20Sopenharmony_ci					reg_elem->cam_offset);
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ci			/* MOVE command consumes 2 entries in the ramrod data */
18328c2ecf20Sopenharmony_ci			if (cmd == BNX2X_VLAN_MAC_MOVE)
18338c2ecf20Sopenharmony_ci				idx += 2;
18348c2ecf20Sopenharmony_ci			else
18358c2ecf20Sopenharmony_ci				idx++;
18368c2ecf20Sopenharmony_ci		}
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_ci		/* No need for an explicit memory barrier here as long we would
18398c2ecf20Sopenharmony_ci		 * need to ensure the ordering of writing to the SPQ element
18408c2ecf20Sopenharmony_ci		 * and updating of the SPQ producer which involves a memory
18418c2ecf20Sopenharmony_ci		 * read and we will have to put a full memory barrier there
18428c2ecf20Sopenharmony_ci		 * (inside bnx2x_sp_post()).
18438c2ecf20Sopenharmony_ci		 */
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci		rc = bnx2x_sp_post(bp, o->ramrod_cmd, r->cid,
18468c2ecf20Sopenharmony_ci				   U64_HI(r->rdata_mapping),
18478c2ecf20Sopenharmony_ci				   U64_LO(r->rdata_mapping),
18488c2ecf20Sopenharmony_ci				   ETH_CONNECTION_TYPE);
18498c2ecf20Sopenharmony_ci		if (rc)
18508c2ecf20Sopenharmony_ci			goto error_exit;
18518c2ecf20Sopenharmony_ci	}
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_ci	/* Now, when we are done with the ramrod - clean up the registry */
18548c2ecf20Sopenharmony_ci	list_for_each_entry(elem, exe_chunk, link) {
18558c2ecf20Sopenharmony_ci		cmd = elem->cmd_data.vlan_mac.cmd;
18568c2ecf20Sopenharmony_ci		if ((cmd == BNX2X_VLAN_MAC_DEL) ||
18578c2ecf20Sopenharmony_ci		    (cmd == BNX2X_VLAN_MAC_MOVE)) {
18588c2ecf20Sopenharmony_ci			reg_elem = o->check_del(bp, o,
18598c2ecf20Sopenharmony_ci						&elem->cmd_data.vlan_mac.u);
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci			WARN_ON(!reg_elem);
18628c2ecf20Sopenharmony_ci
18638c2ecf20Sopenharmony_ci			o->put_cam_offset(o, reg_elem->cam_offset);
18648c2ecf20Sopenharmony_ci			list_del(&reg_elem->link);
18658c2ecf20Sopenharmony_ci			kfree(reg_elem);
18668c2ecf20Sopenharmony_ci		}
18678c2ecf20Sopenharmony_ci	}
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_ci	if (!drv_only)
18708c2ecf20Sopenharmony_ci		return 1;
18718c2ecf20Sopenharmony_ci	else
18728c2ecf20Sopenharmony_ci		return 0;
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_cierror_exit:
18758c2ecf20Sopenharmony_ci	r->clear_pending(r);
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_ci	/* Cleanup a registry in case of a failure */
18788c2ecf20Sopenharmony_ci	list_for_each_entry(elem, exe_chunk, link) {
18798c2ecf20Sopenharmony_ci		cmd = elem->cmd_data.vlan_mac.cmd;
18808c2ecf20Sopenharmony_ci
18818c2ecf20Sopenharmony_ci		if (cmd == BNX2X_VLAN_MAC_MOVE)
18828c2ecf20Sopenharmony_ci			cam_obj = elem->cmd_data.vlan_mac.target_obj;
18838c2ecf20Sopenharmony_ci		else
18848c2ecf20Sopenharmony_ci			cam_obj = o;
18858c2ecf20Sopenharmony_ci
18868c2ecf20Sopenharmony_ci		/* Delete all newly added above entries */
18878c2ecf20Sopenharmony_ci		if (!restore &&
18888c2ecf20Sopenharmony_ci		    ((cmd == BNX2X_VLAN_MAC_ADD) ||
18898c2ecf20Sopenharmony_ci		    (cmd == BNX2X_VLAN_MAC_MOVE))) {
18908c2ecf20Sopenharmony_ci			reg_elem = o->check_del(bp, cam_obj,
18918c2ecf20Sopenharmony_ci						&elem->cmd_data.vlan_mac.u);
18928c2ecf20Sopenharmony_ci			if (reg_elem) {
18938c2ecf20Sopenharmony_ci				list_del(&reg_elem->link);
18948c2ecf20Sopenharmony_ci				kfree(reg_elem);
18958c2ecf20Sopenharmony_ci			}
18968c2ecf20Sopenharmony_ci		}
18978c2ecf20Sopenharmony_ci	}
18988c2ecf20Sopenharmony_ci
18998c2ecf20Sopenharmony_ci	return rc;
19008c2ecf20Sopenharmony_ci}
19018c2ecf20Sopenharmony_ci
19028c2ecf20Sopenharmony_cistatic inline int bnx2x_vlan_mac_push_new_cmd(
19038c2ecf20Sopenharmony_ci	struct bnx2x *bp,
19048c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_ramrod_params *p)
19058c2ecf20Sopenharmony_ci{
19068c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *elem;
19078c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
19088c2ecf20Sopenharmony_ci	bool restore = test_bit(RAMROD_RESTORE, &p->ramrod_flags);
19098c2ecf20Sopenharmony_ci
19108c2ecf20Sopenharmony_ci	/* Allocate the execution queue element */
19118c2ecf20Sopenharmony_ci	elem = bnx2x_exe_queue_alloc_elem(bp);
19128c2ecf20Sopenharmony_ci	if (!elem)
19138c2ecf20Sopenharmony_ci		return -ENOMEM;
19148c2ecf20Sopenharmony_ci
19158c2ecf20Sopenharmony_ci	/* Set the command 'length' */
19168c2ecf20Sopenharmony_ci	switch (p->user_req.cmd) {
19178c2ecf20Sopenharmony_ci	case BNX2X_VLAN_MAC_MOVE:
19188c2ecf20Sopenharmony_ci		elem->cmd_len = 2;
19198c2ecf20Sopenharmony_ci		break;
19208c2ecf20Sopenharmony_ci	default:
19218c2ecf20Sopenharmony_ci		elem->cmd_len = 1;
19228c2ecf20Sopenharmony_ci	}
19238c2ecf20Sopenharmony_ci
19248c2ecf20Sopenharmony_ci	/* Fill the object specific info */
19258c2ecf20Sopenharmony_ci	memcpy(&elem->cmd_data.vlan_mac, &p->user_req, sizeof(p->user_req));
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_ci	/* Try to add a new command to the pending list */
19288c2ecf20Sopenharmony_ci	return bnx2x_exe_queue_add(bp, &o->exe_queue, elem, restore);
19298c2ecf20Sopenharmony_ci}
19308c2ecf20Sopenharmony_ci
19318c2ecf20Sopenharmony_ci/**
19328c2ecf20Sopenharmony_ci * bnx2x_config_vlan_mac - configure VLAN/MAC/VLAN_MAC filtering rules.
19338c2ecf20Sopenharmony_ci *
19348c2ecf20Sopenharmony_ci * @bp:	  device handle
19358c2ecf20Sopenharmony_ci * @p:
19368c2ecf20Sopenharmony_ci *
19378c2ecf20Sopenharmony_ci */
19388c2ecf20Sopenharmony_ciint bnx2x_config_vlan_mac(struct bnx2x *bp,
19398c2ecf20Sopenharmony_ci			   struct bnx2x_vlan_mac_ramrod_params *p)
19408c2ecf20Sopenharmony_ci{
19418c2ecf20Sopenharmony_ci	int rc = 0;
19428c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
19438c2ecf20Sopenharmony_ci	unsigned long *ramrod_flags = &p->ramrod_flags;
19448c2ecf20Sopenharmony_ci	bool cont = test_bit(RAMROD_CONT, ramrod_flags);
19458c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ci	/*
19488c2ecf20Sopenharmony_ci	 * Add new elements to the execution list for commands that require it.
19498c2ecf20Sopenharmony_ci	 */
19508c2ecf20Sopenharmony_ci	if (!cont) {
19518c2ecf20Sopenharmony_ci		rc = bnx2x_vlan_mac_push_new_cmd(bp, p);
19528c2ecf20Sopenharmony_ci		if (rc)
19538c2ecf20Sopenharmony_ci			return rc;
19548c2ecf20Sopenharmony_ci	}
19558c2ecf20Sopenharmony_ci
19568c2ecf20Sopenharmony_ci	/* If nothing will be executed further in this iteration we want to
19578c2ecf20Sopenharmony_ci	 * return PENDING if there are pending commands
19588c2ecf20Sopenharmony_ci	 */
19598c2ecf20Sopenharmony_ci	if (!bnx2x_exe_queue_empty(&o->exe_queue))
19608c2ecf20Sopenharmony_ci		rc = 1;
19618c2ecf20Sopenharmony_ci
19628c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags))  {
19638c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: clearing a pending bit.\n");
19648c2ecf20Sopenharmony_ci		raw->clear_pending(raw);
19658c2ecf20Sopenharmony_ci	}
19668c2ecf20Sopenharmony_ci
19678c2ecf20Sopenharmony_ci	/* Execute commands if required */
19688c2ecf20Sopenharmony_ci	if (cont || test_bit(RAMROD_EXEC, ramrod_flags) ||
19698c2ecf20Sopenharmony_ci	    test_bit(RAMROD_COMP_WAIT, ramrod_flags)) {
19708c2ecf20Sopenharmony_ci		rc = __bnx2x_vlan_mac_execute_step(bp, p->vlan_mac_obj,
19718c2ecf20Sopenharmony_ci						   &p->ramrod_flags);
19728c2ecf20Sopenharmony_ci		if (rc < 0)
19738c2ecf20Sopenharmony_ci			return rc;
19748c2ecf20Sopenharmony_ci	}
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_ci	/* RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set
19778c2ecf20Sopenharmony_ci	 * then user want to wait until the last command is done.
19788c2ecf20Sopenharmony_ci	 */
19798c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
19808c2ecf20Sopenharmony_ci		/* Wait maximum for the current exe_queue length iterations plus
19818c2ecf20Sopenharmony_ci		 * one (for the current pending command).
19828c2ecf20Sopenharmony_ci		 */
19838c2ecf20Sopenharmony_ci		int max_iterations = bnx2x_exe_queue_length(&o->exe_queue) + 1;
19848c2ecf20Sopenharmony_ci
19858c2ecf20Sopenharmony_ci		while (!bnx2x_exe_queue_empty(&o->exe_queue) &&
19868c2ecf20Sopenharmony_ci		       max_iterations--) {
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci			/* Wait for the current command to complete */
19898c2ecf20Sopenharmony_ci			rc = raw->wait_comp(bp, raw);
19908c2ecf20Sopenharmony_ci			if (rc)
19918c2ecf20Sopenharmony_ci				return rc;
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci			/* Make a next step */
19948c2ecf20Sopenharmony_ci			rc = __bnx2x_vlan_mac_execute_step(bp,
19958c2ecf20Sopenharmony_ci							   p->vlan_mac_obj,
19968c2ecf20Sopenharmony_ci							   &p->ramrod_flags);
19978c2ecf20Sopenharmony_ci			if (rc < 0)
19988c2ecf20Sopenharmony_ci				return rc;
19998c2ecf20Sopenharmony_ci		}
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_ci		return 0;
20028c2ecf20Sopenharmony_ci	}
20038c2ecf20Sopenharmony_ci
20048c2ecf20Sopenharmony_ci	return rc;
20058c2ecf20Sopenharmony_ci}
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci/**
20088c2ecf20Sopenharmony_ci * bnx2x_vlan_mac_del_all - delete elements with given vlan_mac_flags spec
20098c2ecf20Sopenharmony_ci *
20108c2ecf20Sopenharmony_ci * @bp:			device handle
20118c2ecf20Sopenharmony_ci * @o:			vlan object info
20128c2ecf20Sopenharmony_ci * @vlan_mac_flags:	vlan flags
20138c2ecf20Sopenharmony_ci * @ramrod_flags:	execution flags to be used for this deletion
20148c2ecf20Sopenharmony_ci *
20158c2ecf20Sopenharmony_ci * if the last operation has completed successfully and there are no
20168c2ecf20Sopenharmony_ci * more elements left, positive value if the last operation has completed
20178c2ecf20Sopenharmony_ci * successfully and there are more previously configured elements, negative
20188c2ecf20Sopenharmony_ci * value is current operation has failed.
20198c2ecf20Sopenharmony_ci */
20208c2ecf20Sopenharmony_cistatic int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
20218c2ecf20Sopenharmony_ci				  struct bnx2x_vlan_mac_obj *o,
20228c2ecf20Sopenharmony_ci				  unsigned long *vlan_mac_flags,
20238c2ecf20Sopenharmony_ci				  unsigned long *ramrod_flags)
20248c2ecf20Sopenharmony_ci{
20258c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_registry_elem *pos = NULL;
20268c2ecf20Sopenharmony_ci	struct bnx2x_vlan_mac_ramrod_params p;
20278c2ecf20Sopenharmony_ci	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
20288c2ecf20Sopenharmony_ci	struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
20298c2ecf20Sopenharmony_ci	unsigned long flags;
20308c2ecf20Sopenharmony_ci	int read_lock;
20318c2ecf20Sopenharmony_ci	int rc = 0;
20328c2ecf20Sopenharmony_ci
20338c2ecf20Sopenharmony_ci	/* Clear pending commands first */
20348c2ecf20Sopenharmony_ci
20358c2ecf20Sopenharmony_ci	spin_lock_bh(&exeq->lock);
20368c2ecf20Sopenharmony_ci
20378c2ecf20Sopenharmony_ci	list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
20388c2ecf20Sopenharmony_ci		flags = exeq_pos->cmd_data.vlan_mac.vlan_mac_flags;
20398c2ecf20Sopenharmony_ci		if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
20408c2ecf20Sopenharmony_ci		    BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
20418c2ecf20Sopenharmony_ci			rc = exeq->remove(bp, exeq->owner, exeq_pos);
20428c2ecf20Sopenharmony_ci			if (rc) {
20438c2ecf20Sopenharmony_ci				BNX2X_ERR("Failed to remove command\n");
20448c2ecf20Sopenharmony_ci				spin_unlock_bh(&exeq->lock);
20458c2ecf20Sopenharmony_ci				return rc;
20468c2ecf20Sopenharmony_ci			}
20478c2ecf20Sopenharmony_ci			list_del(&exeq_pos->link);
20488c2ecf20Sopenharmony_ci			bnx2x_exe_queue_free_elem(bp, exeq_pos);
20498c2ecf20Sopenharmony_ci		}
20508c2ecf20Sopenharmony_ci	}
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci	spin_unlock_bh(&exeq->lock);
20538c2ecf20Sopenharmony_ci
20548c2ecf20Sopenharmony_ci	/* Prepare a command request */
20558c2ecf20Sopenharmony_ci	memset(&p, 0, sizeof(p));
20568c2ecf20Sopenharmony_ci	p.vlan_mac_obj = o;
20578c2ecf20Sopenharmony_ci	p.ramrod_flags = *ramrod_flags;
20588c2ecf20Sopenharmony_ci	p.user_req.cmd = BNX2X_VLAN_MAC_DEL;
20598c2ecf20Sopenharmony_ci
20608c2ecf20Sopenharmony_ci	/* Add all but the last VLAN-MAC to the execution queue without actually
20618c2ecf20Sopenharmony_ci	 * execution anything.
20628c2ecf20Sopenharmony_ci	 */
20638c2ecf20Sopenharmony_ci	__clear_bit(RAMROD_COMP_WAIT, &p.ramrod_flags);
20648c2ecf20Sopenharmony_ci	__clear_bit(RAMROD_EXEC, &p.ramrod_flags);
20658c2ecf20Sopenharmony_ci	__clear_bit(RAMROD_CONT, &p.ramrod_flags);
20668c2ecf20Sopenharmony_ci
20678c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "vlan_mac_del_all -- taking vlan_mac_lock (reader)\n");
20688c2ecf20Sopenharmony_ci	read_lock = bnx2x_vlan_mac_h_read_lock(bp, o);
20698c2ecf20Sopenharmony_ci	if (read_lock != 0)
20708c2ecf20Sopenharmony_ci		return read_lock;
20718c2ecf20Sopenharmony_ci
20728c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &o->head, link) {
20738c2ecf20Sopenharmony_ci		flags = pos->vlan_mac_flags;
20748c2ecf20Sopenharmony_ci		if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
20758c2ecf20Sopenharmony_ci		    BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
20768c2ecf20Sopenharmony_ci			p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
20778c2ecf20Sopenharmony_ci			memcpy(&p.user_req.u, &pos->u, sizeof(pos->u));
20788c2ecf20Sopenharmony_ci			rc = bnx2x_config_vlan_mac(bp, &p);
20798c2ecf20Sopenharmony_ci			if (rc < 0) {
20808c2ecf20Sopenharmony_ci				BNX2X_ERR("Failed to add a new DEL command\n");
20818c2ecf20Sopenharmony_ci				bnx2x_vlan_mac_h_read_unlock(bp, o);
20828c2ecf20Sopenharmony_ci				return rc;
20838c2ecf20Sopenharmony_ci			}
20848c2ecf20Sopenharmony_ci		}
20858c2ecf20Sopenharmony_ci	}
20868c2ecf20Sopenharmony_ci
20878c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "vlan_mac_del_all -- releasing vlan_mac_lock (reader)\n");
20888c2ecf20Sopenharmony_ci	bnx2x_vlan_mac_h_read_unlock(bp, o);
20898c2ecf20Sopenharmony_ci
20908c2ecf20Sopenharmony_ci	p.ramrod_flags = *ramrod_flags;
20918c2ecf20Sopenharmony_ci	__set_bit(RAMROD_CONT, &p.ramrod_flags);
20928c2ecf20Sopenharmony_ci
20938c2ecf20Sopenharmony_ci	return bnx2x_config_vlan_mac(bp, &p);
20948c2ecf20Sopenharmony_ci}
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_cistatic inline void bnx2x_init_raw_obj(struct bnx2x_raw_obj *raw, u8 cl_id,
20978c2ecf20Sopenharmony_ci	u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping, int state,
20988c2ecf20Sopenharmony_ci	unsigned long *pstate, bnx2x_obj_type type)
20998c2ecf20Sopenharmony_ci{
21008c2ecf20Sopenharmony_ci	raw->func_id = func_id;
21018c2ecf20Sopenharmony_ci	raw->cid = cid;
21028c2ecf20Sopenharmony_ci	raw->cl_id = cl_id;
21038c2ecf20Sopenharmony_ci	raw->rdata = rdata;
21048c2ecf20Sopenharmony_ci	raw->rdata_mapping = rdata_mapping;
21058c2ecf20Sopenharmony_ci	raw->state = state;
21068c2ecf20Sopenharmony_ci	raw->pstate = pstate;
21078c2ecf20Sopenharmony_ci	raw->obj_type = type;
21088c2ecf20Sopenharmony_ci	raw->check_pending = bnx2x_raw_check_pending;
21098c2ecf20Sopenharmony_ci	raw->clear_pending = bnx2x_raw_clear_pending;
21108c2ecf20Sopenharmony_ci	raw->set_pending = bnx2x_raw_set_pending;
21118c2ecf20Sopenharmony_ci	raw->wait_comp = bnx2x_raw_wait;
21128c2ecf20Sopenharmony_ci}
21138c2ecf20Sopenharmony_ci
21148c2ecf20Sopenharmony_cistatic inline void bnx2x_init_vlan_mac_common(struct bnx2x_vlan_mac_obj *o,
21158c2ecf20Sopenharmony_ci	u8 cl_id, u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping,
21168c2ecf20Sopenharmony_ci	int state, unsigned long *pstate, bnx2x_obj_type type,
21178c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *macs_pool,
21188c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *vlans_pool)
21198c2ecf20Sopenharmony_ci{
21208c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&o->head);
21218c2ecf20Sopenharmony_ci	o->head_reader = 0;
21228c2ecf20Sopenharmony_ci	o->head_exe_request = false;
21238c2ecf20Sopenharmony_ci	o->saved_ramrod_flags = 0;
21248c2ecf20Sopenharmony_ci
21258c2ecf20Sopenharmony_ci	o->macs_pool = macs_pool;
21268c2ecf20Sopenharmony_ci	o->vlans_pool = vlans_pool;
21278c2ecf20Sopenharmony_ci
21288c2ecf20Sopenharmony_ci	o->delete_all = bnx2x_vlan_mac_del_all;
21298c2ecf20Sopenharmony_ci	o->restore = bnx2x_vlan_mac_restore;
21308c2ecf20Sopenharmony_ci	o->complete = bnx2x_complete_vlan_mac;
21318c2ecf20Sopenharmony_ci	o->wait = bnx2x_wait_vlan_mac;
21328c2ecf20Sopenharmony_ci
21338c2ecf20Sopenharmony_ci	bnx2x_init_raw_obj(&o->raw, cl_id, cid, func_id, rdata, rdata_mapping,
21348c2ecf20Sopenharmony_ci			   state, pstate, type);
21358c2ecf20Sopenharmony_ci}
21368c2ecf20Sopenharmony_ci
21378c2ecf20Sopenharmony_civoid bnx2x_init_mac_obj(struct bnx2x *bp,
21388c2ecf20Sopenharmony_ci			struct bnx2x_vlan_mac_obj *mac_obj,
21398c2ecf20Sopenharmony_ci			u8 cl_id, u32 cid, u8 func_id, void *rdata,
21408c2ecf20Sopenharmony_ci			dma_addr_t rdata_mapping, int state,
21418c2ecf20Sopenharmony_ci			unsigned long *pstate, bnx2x_obj_type type,
21428c2ecf20Sopenharmony_ci			struct bnx2x_credit_pool_obj *macs_pool)
21438c2ecf20Sopenharmony_ci{
21448c2ecf20Sopenharmony_ci	union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)mac_obj;
21458c2ecf20Sopenharmony_ci
21468c2ecf20Sopenharmony_ci	bnx2x_init_vlan_mac_common(mac_obj, cl_id, cid, func_id, rdata,
21478c2ecf20Sopenharmony_ci				   rdata_mapping, state, pstate, type,
21488c2ecf20Sopenharmony_ci				   macs_pool, NULL);
21498c2ecf20Sopenharmony_ci
21508c2ecf20Sopenharmony_ci	/* CAM credit pool handling */
21518c2ecf20Sopenharmony_ci	mac_obj->get_credit = bnx2x_get_credit_mac;
21528c2ecf20Sopenharmony_ci	mac_obj->put_credit = bnx2x_put_credit_mac;
21538c2ecf20Sopenharmony_ci	mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
21548c2ecf20Sopenharmony_ci	mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
21558c2ecf20Sopenharmony_ci
21568c2ecf20Sopenharmony_ci	if (CHIP_IS_E1x(bp)) {
21578c2ecf20Sopenharmony_ci		mac_obj->set_one_rule      = bnx2x_set_one_mac_e1x;
21588c2ecf20Sopenharmony_ci		mac_obj->check_del         = bnx2x_check_mac_del;
21598c2ecf20Sopenharmony_ci		mac_obj->check_add         = bnx2x_check_mac_add;
21608c2ecf20Sopenharmony_ci		mac_obj->check_move        = bnx2x_check_move_always_err;
21618c2ecf20Sopenharmony_ci		mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
21628c2ecf20Sopenharmony_ci
21638c2ecf20Sopenharmony_ci		/* Exe Queue */
21648c2ecf20Sopenharmony_ci		bnx2x_exe_queue_init(bp,
21658c2ecf20Sopenharmony_ci				     &mac_obj->exe_queue, 1, qable_obj,
21668c2ecf20Sopenharmony_ci				     bnx2x_validate_vlan_mac,
21678c2ecf20Sopenharmony_ci				     bnx2x_remove_vlan_mac,
21688c2ecf20Sopenharmony_ci				     bnx2x_optimize_vlan_mac,
21698c2ecf20Sopenharmony_ci				     bnx2x_execute_vlan_mac,
21708c2ecf20Sopenharmony_ci				     bnx2x_exeq_get_mac);
21718c2ecf20Sopenharmony_ci	} else {
21728c2ecf20Sopenharmony_ci		mac_obj->set_one_rule      = bnx2x_set_one_mac_e2;
21738c2ecf20Sopenharmony_ci		mac_obj->check_del         = bnx2x_check_mac_del;
21748c2ecf20Sopenharmony_ci		mac_obj->check_add         = bnx2x_check_mac_add;
21758c2ecf20Sopenharmony_ci		mac_obj->check_move        = bnx2x_check_move;
21768c2ecf20Sopenharmony_ci		mac_obj->ramrod_cmd        =
21778c2ecf20Sopenharmony_ci			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
21788c2ecf20Sopenharmony_ci		mac_obj->get_n_elements    = bnx2x_get_n_elements;
21798c2ecf20Sopenharmony_ci
21808c2ecf20Sopenharmony_ci		/* Exe Queue */
21818c2ecf20Sopenharmony_ci		bnx2x_exe_queue_init(bp,
21828c2ecf20Sopenharmony_ci				     &mac_obj->exe_queue, CLASSIFY_RULES_COUNT,
21838c2ecf20Sopenharmony_ci				     qable_obj, bnx2x_validate_vlan_mac,
21848c2ecf20Sopenharmony_ci				     bnx2x_remove_vlan_mac,
21858c2ecf20Sopenharmony_ci				     bnx2x_optimize_vlan_mac,
21868c2ecf20Sopenharmony_ci				     bnx2x_execute_vlan_mac,
21878c2ecf20Sopenharmony_ci				     bnx2x_exeq_get_mac);
21888c2ecf20Sopenharmony_ci	}
21898c2ecf20Sopenharmony_ci}
21908c2ecf20Sopenharmony_ci
21918c2ecf20Sopenharmony_civoid bnx2x_init_vlan_obj(struct bnx2x *bp,
21928c2ecf20Sopenharmony_ci			 struct bnx2x_vlan_mac_obj *vlan_obj,
21938c2ecf20Sopenharmony_ci			 u8 cl_id, u32 cid, u8 func_id, void *rdata,
21948c2ecf20Sopenharmony_ci			 dma_addr_t rdata_mapping, int state,
21958c2ecf20Sopenharmony_ci			 unsigned long *pstate, bnx2x_obj_type type,
21968c2ecf20Sopenharmony_ci			 struct bnx2x_credit_pool_obj *vlans_pool)
21978c2ecf20Sopenharmony_ci{
21988c2ecf20Sopenharmony_ci	union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)vlan_obj;
21998c2ecf20Sopenharmony_ci
22008c2ecf20Sopenharmony_ci	bnx2x_init_vlan_mac_common(vlan_obj, cl_id, cid, func_id, rdata,
22018c2ecf20Sopenharmony_ci				   rdata_mapping, state, pstate, type, NULL,
22028c2ecf20Sopenharmony_ci				   vlans_pool);
22038c2ecf20Sopenharmony_ci
22048c2ecf20Sopenharmony_ci	vlan_obj->get_credit = bnx2x_get_credit_vlan;
22058c2ecf20Sopenharmony_ci	vlan_obj->put_credit = bnx2x_put_credit_vlan;
22068c2ecf20Sopenharmony_ci	vlan_obj->get_cam_offset = bnx2x_get_cam_offset_vlan;
22078c2ecf20Sopenharmony_ci	vlan_obj->put_cam_offset = bnx2x_put_cam_offset_vlan;
22088c2ecf20Sopenharmony_ci
22098c2ecf20Sopenharmony_ci	if (CHIP_IS_E1x(bp)) {
22108c2ecf20Sopenharmony_ci		BNX2X_ERR("Do not support chips others than E2 and newer\n");
22118c2ecf20Sopenharmony_ci		BUG();
22128c2ecf20Sopenharmony_ci	} else {
22138c2ecf20Sopenharmony_ci		vlan_obj->set_one_rule      = bnx2x_set_one_vlan_e2;
22148c2ecf20Sopenharmony_ci		vlan_obj->check_del         = bnx2x_check_vlan_del;
22158c2ecf20Sopenharmony_ci		vlan_obj->check_add         = bnx2x_check_vlan_add;
22168c2ecf20Sopenharmony_ci		vlan_obj->check_move        = bnx2x_check_move;
22178c2ecf20Sopenharmony_ci		vlan_obj->ramrod_cmd        =
22188c2ecf20Sopenharmony_ci			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
22198c2ecf20Sopenharmony_ci		vlan_obj->get_n_elements    = bnx2x_get_n_elements;
22208c2ecf20Sopenharmony_ci
22218c2ecf20Sopenharmony_ci		/* Exe Queue */
22228c2ecf20Sopenharmony_ci		bnx2x_exe_queue_init(bp,
22238c2ecf20Sopenharmony_ci				     &vlan_obj->exe_queue, CLASSIFY_RULES_COUNT,
22248c2ecf20Sopenharmony_ci				     qable_obj, bnx2x_validate_vlan_mac,
22258c2ecf20Sopenharmony_ci				     bnx2x_remove_vlan_mac,
22268c2ecf20Sopenharmony_ci				     bnx2x_optimize_vlan_mac,
22278c2ecf20Sopenharmony_ci				     bnx2x_execute_vlan_mac,
22288c2ecf20Sopenharmony_ci				     bnx2x_exeq_get_vlan);
22298c2ecf20Sopenharmony_ci	}
22308c2ecf20Sopenharmony_ci}
22318c2ecf20Sopenharmony_ci
22328c2ecf20Sopenharmony_civoid bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
22338c2ecf20Sopenharmony_ci			     struct bnx2x_vlan_mac_obj *vlan_mac_obj,
22348c2ecf20Sopenharmony_ci			     u8 cl_id, u32 cid, u8 func_id, void *rdata,
22358c2ecf20Sopenharmony_ci			     dma_addr_t rdata_mapping, int state,
22368c2ecf20Sopenharmony_ci			     unsigned long *pstate, bnx2x_obj_type type,
22378c2ecf20Sopenharmony_ci			     struct bnx2x_credit_pool_obj *macs_pool,
22388c2ecf20Sopenharmony_ci			     struct bnx2x_credit_pool_obj *vlans_pool)
22398c2ecf20Sopenharmony_ci{
22408c2ecf20Sopenharmony_ci	union bnx2x_qable_obj *qable_obj =
22418c2ecf20Sopenharmony_ci		(union bnx2x_qable_obj *)vlan_mac_obj;
22428c2ecf20Sopenharmony_ci
22438c2ecf20Sopenharmony_ci	bnx2x_init_vlan_mac_common(vlan_mac_obj, cl_id, cid, func_id, rdata,
22448c2ecf20Sopenharmony_ci				   rdata_mapping, state, pstate, type,
22458c2ecf20Sopenharmony_ci				   macs_pool, vlans_pool);
22468c2ecf20Sopenharmony_ci
22478c2ecf20Sopenharmony_ci	/* CAM pool handling */
22488c2ecf20Sopenharmony_ci	vlan_mac_obj->get_credit = bnx2x_get_credit_vlan_mac;
22498c2ecf20Sopenharmony_ci	vlan_mac_obj->put_credit = bnx2x_put_credit_vlan_mac;
22508c2ecf20Sopenharmony_ci	/* CAM offset is relevant for 57710 and 57711 chips only which have a
22518c2ecf20Sopenharmony_ci	 * single CAM for both MACs and VLAN-MAC pairs. So the offset
22528c2ecf20Sopenharmony_ci	 * will be taken from MACs' pool object only.
22538c2ecf20Sopenharmony_ci	 */
22548c2ecf20Sopenharmony_ci	vlan_mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
22558c2ecf20Sopenharmony_ci	vlan_mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
22568c2ecf20Sopenharmony_ci
22578c2ecf20Sopenharmony_ci	if (CHIP_IS_E1(bp)) {
22588c2ecf20Sopenharmony_ci		BNX2X_ERR("Do not support chips others than E2\n");
22598c2ecf20Sopenharmony_ci		BUG();
22608c2ecf20Sopenharmony_ci	} else if (CHIP_IS_E1H(bp)) {
22618c2ecf20Sopenharmony_ci		vlan_mac_obj->set_one_rule      = bnx2x_set_one_vlan_mac_e1h;
22628c2ecf20Sopenharmony_ci		vlan_mac_obj->check_del         = bnx2x_check_vlan_mac_del;
22638c2ecf20Sopenharmony_ci		vlan_mac_obj->check_add         = bnx2x_check_vlan_mac_add;
22648c2ecf20Sopenharmony_ci		vlan_mac_obj->check_move        = bnx2x_check_move_always_err;
22658c2ecf20Sopenharmony_ci		vlan_mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_ci		/* Exe Queue */
22688c2ecf20Sopenharmony_ci		bnx2x_exe_queue_init(bp,
22698c2ecf20Sopenharmony_ci				     &vlan_mac_obj->exe_queue, 1, qable_obj,
22708c2ecf20Sopenharmony_ci				     bnx2x_validate_vlan_mac,
22718c2ecf20Sopenharmony_ci				     bnx2x_remove_vlan_mac,
22728c2ecf20Sopenharmony_ci				     bnx2x_optimize_vlan_mac,
22738c2ecf20Sopenharmony_ci				     bnx2x_execute_vlan_mac,
22748c2ecf20Sopenharmony_ci				     bnx2x_exeq_get_vlan_mac);
22758c2ecf20Sopenharmony_ci	} else {
22768c2ecf20Sopenharmony_ci		vlan_mac_obj->set_one_rule      = bnx2x_set_one_vlan_mac_e2;
22778c2ecf20Sopenharmony_ci		vlan_mac_obj->check_del         = bnx2x_check_vlan_mac_del;
22788c2ecf20Sopenharmony_ci		vlan_mac_obj->check_add         = bnx2x_check_vlan_mac_add;
22798c2ecf20Sopenharmony_ci		vlan_mac_obj->check_move        = bnx2x_check_move;
22808c2ecf20Sopenharmony_ci		vlan_mac_obj->ramrod_cmd        =
22818c2ecf20Sopenharmony_ci			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
22828c2ecf20Sopenharmony_ci
22838c2ecf20Sopenharmony_ci		/* Exe Queue */
22848c2ecf20Sopenharmony_ci		bnx2x_exe_queue_init(bp,
22858c2ecf20Sopenharmony_ci				     &vlan_mac_obj->exe_queue,
22868c2ecf20Sopenharmony_ci				     CLASSIFY_RULES_COUNT,
22878c2ecf20Sopenharmony_ci				     qable_obj, bnx2x_validate_vlan_mac,
22888c2ecf20Sopenharmony_ci				     bnx2x_remove_vlan_mac,
22898c2ecf20Sopenharmony_ci				     bnx2x_optimize_vlan_mac,
22908c2ecf20Sopenharmony_ci				     bnx2x_execute_vlan_mac,
22918c2ecf20Sopenharmony_ci				     bnx2x_exeq_get_vlan_mac);
22928c2ecf20Sopenharmony_ci	}
22938c2ecf20Sopenharmony_ci}
22948c2ecf20Sopenharmony_ci/* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
22958c2ecf20Sopenharmony_cistatic inline void __storm_memset_mac_filters(struct bnx2x *bp,
22968c2ecf20Sopenharmony_ci			struct tstorm_eth_mac_filter_config *mac_filters,
22978c2ecf20Sopenharmony_ci			u16 pf_id)
22988c2ecf20Sopenharmony_ci{
22998c2ecf20Sopenharmony_ci	size_t size = sizeof(struct tstorm_eth_mac_filter_config);
23008c2ecf20Sopenharmony_ci
23018c2ecf20Sopenharmony_ci	u32 addr = BAR_TSTRORM_INTMEM +
23028c2ecf20Sopenharmony_ci			TSTORM_MAC_FILTER_CONFIG_OFFSET(pf_id);
23038c2ecf20Sopenharmony_ci
23048c2ecf20Sopenharmony_ci	__storm_memset_struct(bp, addr, size, (u32 *)mac_filters);
23058c2ecf20Sopenharmony_ci}
23068c2ecf20Sopenharmony_ci
23078c2ecf20Sopenharmony_cistatic int bnx2x_set_rx_mode_e1x(struct bnx2x *bp,
23088c2ecf20Sopenharmony_ci				 struct bnx2x_rx_mode_ramrod_params *p)
23098c2ecf20Sopenharmony_ci{
23108c2ecf20Sopenharmony_ci	/* update the bp MAC filter structure */
23118c2ecf20Sopenharmony_ci	u32 mask = (1 << p->cl_id);
23128c2ecf20Sopenharmony_ci
23138c2ecf20Sopenharmony_ci	struct tstorm_eth_mac_filter_config *mac_filters =
23148c2ecf20Sopenharmony_ci		(struct tstorm_eth_mac_filter_config *)p->rdata;
23158c2ecf20Sopenharmony_ci
23168c2ecf20Sopenharmony_ci	/* initial setting is drop-all */
23178c2ecf20Sopenharmony_ci	u8 drop_all_ucast = 1, drop_all_mcast = 1;
23188c2ecf20Sopenharmony_ci	u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
23198c2ecf20Sopenharmony_ci	u8 unmatched_unicast = 0;
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ci    /* In e1x there we only take into account rx accept flag since tx switching
23228c2ecf20Sopenharmony_ci     * isn't enabled. */
23238c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_UNICAST, &p->rx_accept_flags))
23248c2ecf20Sopenharmony_ci		/* accept matched ucast */
23258c2ecf20Sopenharmony_ci		drop_all_ucast = 0;
23268c2ecf20Sopenharmony_ci
23278c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_MULTICAST, &p->rx_accept_flags))
23288c2ecf20Sopenharmony_ci		/* accept matched mcast */
23298c2ecf20Sopenharmony_ci		drop_all_mcast = 0;
23308c2ecf20Sopenharmony_ci
23318c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &p->rx_accept_flags)) {
23328c2ecf20Sopenharmony_ci		/* accept all mcast */
23338c2ecf20Sopenharmony_ci		drop_all_ucast = 0;
23348c2ecf20Sopenharmony_ci		accp_all_ucast = 1;
23358c2ecf20Sopenharmony_ci	}
23368c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &p->rx_accept_flags)) {
23378c2ecf20Sopenharmony_ci		/* accept all mcast */
23388c2ecf20Sopenharmony_ci		drop_all_mcast = 0;
23398c2ecf20Sopenharmony_ci		accp_all_mcast = 1;
23408c2ecf20Sopenharmony_ci	}
23418c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_BROADCAST, &p->rx_accept_flags))
23428c2ecf20Sopenharmony_ci		/* accept (all) bcast */
23438c2ecf20Sopenharmony_ci		accp_all_bcast = 1;
23448c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_UNMATCHED, &p->rx_accept_flags))
23458c2ecf20Sopenharmony_ci		/* accept unmatched unicasts */
23468c2ecf20Sopenharmony_ci		unmatched_unicast = 1;
23478c2ecf20Sopenharmony_ci
23488c2ecf20Sopenharmony_ci	mac_filters->ucast_drop_all = drop_all_ucast ?
23498c2ecf20Sopenharmony_ci		mac_filters->ucast_drop_all | mask :
23508c2ecf20Sopenharmony_ci		mac_filters->ucast_drop_all & ~mask;
23518c2ecf20Sopenharmony_ci
23528c2ecf20Sopenharmony_ci	mac_filters->mcast_drop_all = drop_all_mcast ?
23538c2ecf20Sopenharmony_ci		mac_filters->mcast_drop_all | mask :
23548c2ecf20Sopenharmony_ci		mac_filters->mcast_drop_all & ~mask;
23558c2ecf20Sopenharmony_ci
23568c2ecf20Sopenharmony_ci	mac_filters->ucast_accept_all = accp_all_ucast ?
23578c2ecf20Sopenharmony_ci		mac_filters->ucast_accept_all | mask :
23588c2ecf20Sopenharmony_ci		mac_filters->ucast_accept_all & ~mask;
23598c2ecf20Sopenharmony_ci
23608c2ecf20Sopenharmony_ci	mac_filters->mcast_accept_all = accp_all_mcast ?
23618c2ecf20Sopenharmony_ci		mac_filters->mcast_accept_all | mask :
23628c2ecf20Sopenharmony_ci		mac_filters->mcast_accept_all & ~mask;
23638c2ecf20Sopenharmony_ci
23648c2ecf20Sopenharmony_ci	mac_filters->bcast_accept_all = accp_all_bcast ?
23658c2ecf20Sopenharmony_ci		mac_filters->bcast_accept_all | mask :
23668c2ecf20Sopenharmony_ci		mac_filters->bcast_accept_all & ~mask;
23678c2ecf20Sopenharmony_ci
23688c2ecf20Sopenharmony_ci	mac_filters->unmatched_unicast = unmatched_unicast ?
23698c2ecf20Sopenharmony_ci		mac_filters->unmatched_unicast | mask :
23708c2ecf20Sopenharmony_ci		mac_filters->unmatched_unicast & ~mask;
23718c2ecf20Sopenharmony_ci
23728c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "drop_ucast 0x%x\ndrop_mcast 0x%x\n accp_ucast 0x%x\n"
23738c2ecf20Sopenharmony_ci			 "accp_mcast 0x%x\naccp_bcast 0x%x\n",
23748c2ecf20Sopenharmony_ci	   mac_filters->ucast_drop_all, mac_filters->mcast_drop_all,
23758c2ecf20Sopenharmony_ci	   mac_filters->ucast_accept_all, mac_filters->mcast_accept_all,
23768c2ecf20Sopenharmony_ci	   mac_filters->bcast_accept_all);
23778c2ecf20Sopenharmony_ci
23788c2ecf20Sopenharmony_ci	/* write the MAC filter structure*/
23798c2ecf20Sopenharmony_ci	__storm_memset_mac_filters(bp, mac_filters, p->func_id);
23808c2ecf20Sopenharmony_ci
23818c2ecf20Sopenharmony_ci	/* The operation is completed */
23828c2ecf20Sopenharmony_ci	clear_bit(p->state, p->pstate);
23838c2ecf20Sopenharmony_ci	smp_mb__after_atomic();
23848c2ecf20Sopenharmony_ci
23858c2ecf20Sopenharmony_ci	return 0;
23868c2ecf20Sopenharmony_ci}
23878c2ecf20Sopenharmony_ci
23888c2ecf20Sopenharmony_ci/* Setup ramrod data */
23898c2ecf20Sopenharmony_cistatic inline void bnx2x_rx_mode_set_rdata_hdr_e2(u32 cid,
23908c2ecf20Sopenharmony_ci				struct eth_classify_header *hdr,
23918c2ecf20Sopenharmony_ci				u8 rule_cnt)
23928c2ecf20Sopenharmony_ci{
23938c2ecf20Sopenharmony_ci	hdr->echo = cpu_to_le32(cid);
23948c2ecf20Sopenharmony_ci	hdr->rule_cnt = rule_cnt;
23958c2ecf20Sopenharmony_ci}
23968c2ecf20Sopenharmony_ci
23978c2ecf20Sopenharmony_cistatic inline void bnx2x_rx_mode_set_cmd_state_e2(struct bnx2x *bp,
23988c2ecf20Sopenharmony_ci				unsigned long *accept_flags,
23998c2ecf20Sopenharmony_ci				struct eth_filter_rules_cmd *cmd,
24008c2ecf20Sopenharmony_ci				bool clear_accept_all)
24018c2ecf20Sopenharmony_ci{
24028c2ecf20Sopenharmony_ci	u16 state;
24038c2ecf20Sopenharmony_ci
24048c2ecf20Sopenharmony_ci	/* start with 'drop-all' */
24058c2ecf20Sopenharmony_ci	state = ETH_FILTER_RULES_CMD_UCAST_DROP_ALL |
24068c2ecf20Sopenharmony_ci		ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
24078c2ecf20Sopenharmony_ci
24088c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_UNICAST, accept_flags))
24098c2ecf20Sopenharmony_ci		state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
24108c2ecf20Sopenharmony_ci
24118c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_MULTICAST, accept_flags))
24128c2ecf20Sopenharmony_ci		state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
24138c2ecf20Sopenharmony_ci
24148c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, accept_flags)) {
24158c2ecf20Sopenharmony_ci		state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
24168c2ecf20Sopenharmony_ci		state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
24178c2ecf20Sopenharmony_ci	}
24188c2ecf20Sopenharmony_ci
24198c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, accept_flags)) {
24208c2ecf20Sopenharmony_ci		state |= ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
24218c2ecf20Sopenharmony_ci		state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
24228c2ecf20Sopenharmony_ci	}
24238c2ecf20Sopenharmony_ci
24248c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_BROADCAST, accept_flags))
24258c2ecf20Sopenharmony_ci		state |= ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
24268c2ecf20Sopenharmony_ci
24278c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_UNMATCHED, accept_flags)) {
24288c2ecf20Sopenharmony_ci		state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
24298c2ecf20Sopenharmony_ci		state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
24308c2ecf20Sopenharmony_ci	}
24318c2ecf20Sopenharmony_ci
24328c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_ACCEPT_ANY_VLAN, accept_flags))
24338c2ecf20Sopenharmony_ci		state |= ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN;
24348c2ecf20Sopenharmony_ci
24358c2ecf20Sopenharmony_ci	/* Clear ACCEPT_ALL_XXX flags for FCoE L2 Queue */
24368c2ecf20Sopenharmony_ci	if (clear_accept_all) {
24378c2ecf20Sopenharmony_ci		state &= ~ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
24388c2ecf20Sopenharmony_ci		state &= ~ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
24398c2ecf20Sopenharmony_ci		state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
24408c2ecf20Sopenharmony_ci		state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
24418c2ecf20Sopenharmony_ci	}
24428c2ecf20Sopenharmony_ci
24438c2ecf20Sopenharmony_ci	cmd->state = cpu_to_le16(state);
24448c2ecf20Sopenharmony_ci}
24458c2ecf20Sopenharmony_ci
24468c2ecf20Sopenharmony_cistatic int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
24478c2ecf20Sopenharmony_ci				struct bnx2x_rx_mode_ramrod_params *p)
24488c2ecf20Sopenharmony_ci{
24498c2ecf20Sopenharmony_ci	struct eth_filter_rules_ramrod_data *data = p->rdata;
24508c2ecf20Sopenharmony_ci	int rc;
24518c2ecf20Sopenharmony_ci	u8 rule_idx = 0;
24528c2ecf20Sopenharmony_ci
24538c2ecf20Sopenharmony_ci	/* Reset the ramrod data buffer */
24548c2ecf20Sopenharmony_ci	memset(data, 0, sizeof(*data));
24558c2ecf20Sopenharmony_ci
24568c2ecf20Sopenharmony_ci	/* Setup ramrod data */
24578c2ecf20Sopenharmony_ci
24588c2ecf20Sopenharmony_ci	/* Tx (internal switching) */
24598c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
24608c2ecf20Sopenharmony_ci		data->rules[rule_idx].client_id = p->cl_id;
24618c2ecf20Sopenharmony_ci		data->rules[rule_idx].func_id = p->func_id;
24628c2ecf20Sopenharmony_ci
24638c2ecf20Sopenharmony_ci		data->rules[rule_idx].cmd_general_data =
24648c2ecf20Sopenharmony_ci			ETH_FILTER_RULES_CMD_TX_CMD;
24658c2ecf20Sopenharmony_ci
24668c2ecf20Sopenharmony_ci		bnx2x_rx_mode_set_cmd_state_e2(bp, &p->tx_accept_flags,
24678c2ecf20Sopenharmony_ci					       &(data->rules[rule_idx++]),
24688c2ecf20Sopenharmony_ci					       false);
24698c2ecf20Sopenharmony_ci	}
24708c2ecf20Sopenharmony_ci
24718c2ecf20Sopenharmony_ci	/* Rx */
24728c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
24738c2ecf20Sopenharmony_ci		data->rules[rule_idx].client_id = p->cl_id;
24748c2ecf20Sopenharmony_ci		data->rules[rule_idx].func_id = p->func_id;
24758c2ecf20Sopenharmony_ci
24768c2ecf20Sopenharmony_ci		data->rules[rule_idx].cmd_general_data =
24778c2ecf20Sopenharmony_ci			ETH_FILTER_RULES_CMD_RX_CMD;
24788c2ecf20Sopenharmony_ci
24798c2ecf20Sopenharmony_ci		bnx2x_rx_mode_set_cmd_state_e2(bp, &p->rx_accept_flags,
24808c2ecf20Sopenharmony_ci					       &(data->rules[rule_idx++]),
24818c2ecf20Sopenharmony_ci					       false);
24828c2ecf20Sopenharmony_ci	}
24838c2ecf20Sopenharmony_ci
24848c2ecf20Sopenharmony_ci	/* If FCoE Queue configuration has been requested configure the Rx and
24858c2ecf20Sopenharmony_ci	 * internal switching modes for this queue in separate rules.
24868c2ecf20Sopenharmony_ci	 *
24878c2ecf20Sopenharmony_ci	 * FCoE queue shell never be set to ACCEPT_ALL packets of any sort:
24888c2ecf20Sopenharmony_ci	 * MCAST_ALL, UCAST_ALL, BCAST_ALL and UNMATCHED.
24898c2ecf20Sopenharmony_ci	 */
24908c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_RX_MODE_FCOE_ETH, &p->rx_mode_flags)) {
24918c2ecf20Sopenharmony_ci		/*  Tx (internal switching) */
24928c2ecf20Sopenharmony_ci		if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
24938c2ecf20Sopenharmony_ci			data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
24948c2ecf20Sopenharmony_ci			data->rules[rule_idx].func_id = p->func_id;
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci			data->rules[rule_idx].cmd_general_data =
24978c2ecf20Sopenharmony_ci						ETH_FILTER_RULES_CMD_TX_CMD;
24988c2ecf20Sopenharmony_ci
24998c2ecf20Sopenharmony_ci			bnx2x_rx_mode_set_cmd_state_e2(bp, &p->tx_accept_flags,
25008c2ecf20Sopenharmony_ci						       &(data->rules[rule_idx]),
25018c2ecf20Sopenharmony_ci						       true);
25028c2ecf20Sopenharmony_ci			rule_idx++;
25038c2ecf20Sopenharmony_ci		}
25048c2ecf20Sopenharmony_ci
25058c2ecf20Sopenharmony_ci		/* Rx */
25068c2ecf20Sopenharmony_ci		if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
25078c2ecf20Sopenharmony_ci			data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
25088c2ecf20Sopenharmony_ci			data->rules[rule_idx].func_id = p->func_id;
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_ci			data->rules[rule_idx].cmd_general_data =
25118c2ecf20Sopenharmony_ci						ETH_FILTER_RULES_CMD_RX_CMD;
25128c2ecf20Sopenharmony_ci
25138c2ecf20Sopenharmony_ci			bnx2x_rx_mode_set_cmd_state_e2(bp, &p->rx_accept_flags,
25148c2ecf20Sopenharmony_ci						       &(data->rules[rule_idx]),
25158c2ecf20Sopenharmony_ci						       true);
25168c2ecf20Sopenharmony_ci			rule_idx++;
25178c2ecf20Sopenharmony_ci		}
25188c2ecf20Sopenharmony_ci	}
25198c2ecf20Sopenharmony_ci
25208c2ecf20Sopenharmony_ci	/* Set the ramrod header (most importantly - number of rules to
25218c2ecf20Sopenharmony_ci	 * configure).
25228c2ecf20Sopenharmony_ci	 */
25238c2ecf20Sopenharmony_ci	bnx2x_rx_mode_set_rdata_hdr_e2(p->cid, &data->header, rule_idx);
25248c2ecf20Sopenharmony_ci
25258c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "About to configure %d rules, rx_accept_flags 0x%lx, tx_accept_flags 0x%lx\n",
25268c2ecf20Sopenharmony_ci			 data->header.rule_cnt, p->rx_accept_flags,
25278c2ecf20Sopenharmony_ci			 p->tx_accept_flags);
25288c2ecf20Sopenharmony_ci
25298c2ecf20Sopenharmony_ci	/* No need for an explicit memory barrier here as long as we
25308c2ecf20Sopenharmony_ci	 * ensure the ordering of writing to the SPQ element
25318c2ecf20Sopenharmony_ci	 * and updating of the SPQ producer which involves a memory
25328c2ecf20Sopenharmony_ci	 * read. If the memory read is removed we will have to put a
25338c2ecf20Sopenharmony_ci	 * full memory barrier there (inside bnx2x_sp_post()).
25348c2ecf20Sopenharmony_ci	 */
25358c2ecf20Sopenharmony_ci
25368c2ecf20Sopenharmony_ci	/* Send a ramrod */
25378c2ecf20Sopenharmony_ci	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_FILTER_RULES, p->cid,
25388c2ecf20Sopenharmony_ci			   U64_HI(p->rdata_mapping),
25398c2ecf20Sopenharmony_ci			   U64_LO(p->rdata_mapping),
25408c2ecf20Sopenharmony_ci			   ETH_CONNECTION_TYPE);
25418c2ecf20Sopenharmony_ci	if (rc)
25428c2ecf20Sopenharmony_ci		return rc;
25438c2ecf20Sopenharmony_ci
25448c2ecf20Sopenharmony_ci	/* Ramrod completion is pending */
25458c2ecf20Sopenharmony_ci	return 1;
25468c2ecf20Sopenharmony_ci}
25478c2ecf20Sopenharmony_ci
25488c2ecf20Sopenharmony_cistatic int bnx2x_wait_rx_mode_comp_e2(struct bnx2x *bp,
25498c2ecf20Sopenharmony_ci				      struct bnx2x_rx_mode_ramrod_params *p)
25508c2ecf20Sopenharmony_ci{
25518c2ecf20Sopenharmony_ci	return bnx2x_state_wait(bp, p->state, p->pstate);
25528c2ecf20Sopenharmony_ci}
25538c2ecf20Sopenharmony_ci
25548c2ecf20Sopenharmony_cistatic int bnx2x_empty_rx_mode_wait(struct bnx2x *bp,
25558c2ecf20Sopenharmony_ci				    struct bnx2x_rx_mode_ramrod_params *p)
25568c2ecf20Sopenharmony_ci{
25578c2ecf20Sopenharmony_ci	/* Do nothing */
25588c2ecf20Sopenharmony_ci	return 0;
25598c2ecf20Sopenharmony_ci}
25608c2ecf20Sopenharmony_ci
25618c2ecf20Sopenharmony_ciint bnx2x_config_rx_mode(struct bnx2x *bp,
25628c2ecf20Sopenharmony_ci			 struct bnx2x_rx_mode_ramrod_params *p)
25638c2ecf20Sopenharmony_ci{
25648c2ecf20Sopenharmony_ci	int rc;
25658c2ecf20Sopenharmony_ci
25668c2ecf20Sopenharmony_ci	/* Configure the new classification in the chip */
25678c2ecf20Sopenharmony_ci	rc = p->rx_mode_obj->config_rx_mode(bp, p);
25688c2ecf20Sopenharmony_ci	if (rc < 0)
25698c2ecf20Sopenharmony_ci		return rc;
25708c2ecf20Sopenharmony_ci
25718c2ecf20Sopenharmony_ci	/* Wait for a ramrod completion if was requested */
25728c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
25738c2ecf20Sopenharmony_ci		rc = p->rx_mode_obj->wait_comp(bp, p);
25748c2ecf20Sopenharmony_ci		if (rc)
25758c2ecf20Sopenharmony_ci			return rc;
25768c2ecf20Sopenharmony_ci	}
25778c2ecf20Sopenharmony_ci
25788c2ecf20Sopenharmony_ci	return rc;
25798c2ecf20Sopenharmony_ci}
25808c2ecf20Sopenharmony_ci
25818c2ecf20Sopenharmony_civoid bnx2x_init_rx_mode_obj(struct bnx2x *bp,
25828c2ecf20Sopenharmony_ci			    struct bnx2x_rx_mode_obj *o)
25838c2ecf20Sopenharmony_ci{
25848c2ecf20Sopenharmony_ci	if (CHIP_IS_E1x(bp)) {
25858c2ecf20Sopenharmony_ci		o->wait_comp      = bnx2x_empty_rx_mode_wait;
25868c2ecf20Sopenharmony_ci		o->config_rx_mode = bnx2x_set_rx_mode_e1x;
25878c2ecf20Sopenharmony_ci	} else {
25888c2ecf20Sopenharmony_ci		o->wait_comp      = bnx2x_wait_rx_mode_comp_e2;
25898c2ecf20Sopenharmony_ci		o->config_rx_mode = bnx2x_set_rx_mode_e2;
25908c2ecf20Sopenharmony_ci	}
25918c2ecf20Sopenharmony_ci}
25928c2ecf20Sopenharmony_ci
25938c2ecf20Sopenharmony_ci/********************* Multicast verbs: SET, CLEAR ****************************/
25948c2ecf20Sopenharmony_cistatic inline u8 bnx2x_mcast_bin_from_mac(u8 *mac)
25958c2ecf20Sopenharmony_ci{
25968c2ecf20Sopenharmony_ci	return (crc32c_le(0, mac, ETH_ALEN) >> 24) & 0xff;
25978c2ecf20Sopenharmony_ci}
25988c2ecf20Sopenharmony_ci
25998c2ecf20Sopenharmony_cistruct bnx2x_mcast_mac_elem {
26008c2ecf20Sopenharmony_ci	struct list_head link;
26018c2ecf20Sopenharmony_ci	u8 mac[ETH_ALEN];
26028c2ecf20Sopenharmony_ci	u8 pad[2]; /* For a natural alignment of the following buffer */
26038c2ecf20Sopenharmony_ci};
26048c2ecf20Sopenharmony_ci
26058c2ecf20Sopenharmony_cistruct bnx2x_mcast_bin_elem {
26068c2ecf20Sopenharmony_ci	struct list_head link;
26078c2ecf20Sopenharmony_ci	int bin;
26088c2ecf20Sopenharmony_ci	int type; /* BNX2X_MCAST_CMD_SET_{ADD, DEL} */
26098c2ecf20Sopenharmony_ci};
26108c2ecf20Sopenharmony_ci
26118c2ecf20Sopenharmony_ciunion bnx2x_mcast_elem {
26128c2ecf20Sopenharmony_ci	struct bnx2x_mcast_bin_elem bin_elem;
26138c2ecf20Sopenharmony_ci	struct bnx2x_mcast_mac_elem mac_elem;
26148c2ecf20Sopenharmony_ci};
26158c2ecf20Sopenharmony_ci
26168c2ecf20Sopenharmony_cistruct bnx2x_mcast_elem_group {
26178c2ecf20Sopenharmony_ci	struct list_head mcast_group_link;
26188c2ecf20Sopenharmony_ci	union bnx2x_mcast_elem mcast_elems[];
26198c2ecf20Sopenharmony_ci};
26208c2ecf20Sopenharmony_ci
26218c2ecf20Sopenharmony_ci#define MCAST_MAC_ELEMS_PER_PG \
26228c2ecf20Sopenharmony_ci	((PAGE_SIZE - sizeof(struct bnx2x_mcast_elem_group)) / \
26238c2ecf20Sopenharmony_ci	sizeof(union bnx2x_mcast_elem))
26248c2ecf20Sopenharmony_ci
26258c2ecf20Sopenharmony_cistruct bnx2x_pending_mcast_cmd {
26268c2ecf20Sopenharmony_ci	struct list_head link;
26278c2ecf20Sopenharmony_ci	struct list_head group_head;
26288c2ecf20Sopenharmony_ci	int type; /* BNX2X_MCAST_CMD_X */
26298c2ecf20Sopenharmony_ci	union {
26308c2ecf20Sopenharmony_ci		struct list_head macs_head;
26318c2ecf20Sopenharmony_ci		u32 macs_num; /* Needed for DEL command */
26328c2ecf20Sopenharmony_ci		int next_bin; /* Needed for RESTORE flow with aprox match */
26338c2ecf20Sopenharmony_ci	} data;
26348c2ecf20Sopenharmony_ci
26358c2ecf20Sopenharmony_ci	bool set_convert; /* in case type == BNX2X_MCAST_CMD_SET, this is set
26368c2ecf20Sopenharmony_ci			   * when macs_head had been converted to a list of
26378c2ecf20Sopenharmony_ci			   * bnx2x_mcast_bin_elem.
26388c2ecf20Sopenharmony_ci			   */
26398c2ecf20Sopenharmony_ci
26408c2ecf20Sopenharmony_ci	bool done; /* set to true, when the command has been handled,
26418c2ecf20Sopenharmony_ci		    * practically used in 57712 handling only, where one pending
26428c2ecf20Sopenharmony_ci		    * command may be handled in a few operations. As long as for
26438c2ecf20Sopenharmony_ci		    * other chips every operation handling is completed in a
26448c2ecf20Sopenharmony_ci		    * single ramrod, there is no need to utilize this field.
26458c2ecf20Sopenharmony_ci		    */
26468c2ecf20Sopenharmony_ci};
26478c2ecf20Sopenharmony_ci
26488c2ecf20Sopenharmony_cistatic int bnx2x_mcast_wait(struct bnx2x *bp,
26498c2ecf20Sopenharmony_ci			    struct bnx2x_mcast_obj *o)
26508c2ecf20Sopenharmony_ci{
26518c2ecf20Sopenharmony_ci	if (bnx2x_state_wait(bp, o->sched_state, o->raw.pstate) ||
26528c2ecf20Sopenharmony_ci			o->raw.wait_comp(bp, &o->raw))
26538c2ecf20Sopenharmony_ci		return -EBUSY;
26548c2ecf20Sopenharmony_ci
26558c2ecf20Sopenharmony_ci	return 0;
26568c2ecf20Sopenharmony_ci}
26578c2ecf20Sopenharmony_ci
26588c2ecf20Sopenharmony_cistatic void bnx2x_free_groups(struct list_head *mcast_group_list)
26598c2ecf20Sopenharmony_ci{
26608c2ecf20Sopenharmony_ci	struct bnx2x_mcast_elem_group *current_mcast_group;
26618c2ecf20Sopenharmony_ci
26628c2ecf20Sopenharmony_ci	while (!list_empty(mcast_group_list)) {
26638c2ecf20Sopenharmony_ci		current_mcast_group = list_first_entry(mcast_group_list,
26648c2ecf20Sopenharmony_ci				      struct bnx2x_mcast_elem_group,
26658c2ecf20Sopenharmony_ci				      mcast_group_link);
26668c2ecf20Sopenharmony_ci		list_del(&current_mcast_group->mcast_group_link);
26678c2ecf20Sopenharmony_ci		free_page((unsigned long)current_mcast_group);
26688c2ecf20Sopenharmony_ci	}
26698c2ecf20Sopenharmony_ci}
26708c2ecf20Sopenharmony_ci
26718c2ecf20Sopenharmony_cistatic int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
26728c2ecf20Sopenharmony_ci				   struct bnx2x_mcast_obj *o,
26738c2ecf20Sopenharmony_ci				   struct bnx2x_mcast_ramrod_params *p,
26748c2ecf20Sopenharmony_ci				   enum bnx2x_mcast_cmd cmd)
26758c2ecf20Sopenharmony_ci{
26768c2ecf20Sopenharmony_ci	struct bnx2x_pending_mcast_cmd *new_cmd;
26778c2ecf20Sopenharmony_ci	struct bnx2x_mcast_list_elem *pos;
26788c2ecf20Sopenharmony_ci	struct bnx2x_mcast_elem_group *elem_group;
26798c2ecf20Sopenharmony_ci	struct bnx2x_mcast_mac_elem *mac_elem;
26808c2ecf20Sopenharmony_ci	int total_elems = 0, macs_list_len = 0, offset = 0;
26818c2ecf20Sopenharmony_ci
26828c2ecf20Sopenharmony_ci	/* When adding MACs we'll need to store their values */
26838c2ecf20Sopenharmony_ci	if (cmd == BNX2X_MCAST_CMD_ADD || cmd == BNX2X_MCAST_CMD_SET)
26848c2ecf20Sopenharmony_ci		macs_list_len = p->mcast_list_len;
26858c2ecf20Sopenharmony_ci
26868c2ecf20Sopenharmony_ci	/* If the command is empty ("handle pending commands only"), break */
26878c2ecf20Sopenharmony_ci	if (!p->mcast_list_len)
26888c2ecf20Sopenharmony_ci		return 0;
26898c2ecf20Sopenharmony_ci
26908c2ecf20Sopenharmony_ci	/* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */
26918c2ecf20Sopenharmony_ci	new_cmd = kzalloc(sizeof(*new_cmd), GFP_ATOMIC);
26928c2ecf20Sopenharmony_ci	if (!new_cmd)
26938c2ecf20Sopenharmony_ci		return -ENOMEM;
26948c2ecf20Sopenharmony_ci
26958c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&new_cmd->data.macs_head);
26968c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&new_cmd->group_head);
26978c2ecf20Sopenharmony_ci	new_cmd->type = cmd;
26988c2ecf20Sopenharmony_ci	new_cmd->done = false;
26998c2ecf20Sopenharmony_ci
27008c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "About to enqueue a new %d command. macs_list_len=%d\n",
27018c2ecf20Sopenharmony_ci	   cmd, macs_list_len);
27028c2ecf20Sopenharmony_ci
27038c2ecf20Sopenharmony_ci	switch (cmd) {
27048c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_ADD:
27058c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_SET:
27068c2ecf20Sopenharmony_ci		/* For a set command, we need to allocate sufficient memory for
27078c2ecf20Sopenharmony_ci		 * all the bins, since we can't analyze at this point how much
27088c2ecf20Sopenharmony_ci		 * memory would be required.
27098c2ecf20Sopenharmony_ci		 */
27108c2ecf20Sopenharmony_ci		total_elems = macs_list_len;
27118c2ecf20Sopenharmony_ci		if (cmd == BNX2X_MCAST_CMD_SET) {
27128c2ecf20Sopenharmony_ci			if (total_elems < BNX2X_MCAST_BINS_NUM)
27138c2ecf20Sopenharmony_ci				total_elems = BNX2X_MCAST_BINS_NUM;
27148c2ecf20Sopenharmony_ci		}
27158c2ecf20Sopenharmony_ci		while (total_elems > 0) {
27168c2ecf20Sopenharmony_ci			elem_group = (struct bnx2x_mcast_elem_group *)
27178c2ecf20Sopenharmony_ci				     __get_free_page(GFP_ATOMIC | __GFP_ZERO);
27188c2ecf20Sopenharmony_ci			if (!elem_group) {
27198c2ecf20Sopenharmony_ci				bnx2x_free_groups(&new_cmd->group_head);
27208c2ecf20Sopenharmony_ci				kfree(new_cmd);
27218c2ecf20Sopenharmony_ci				return -ENOMEM;
27228c2ecf20Sopenharmony_ci			}
27238c2ecf20Sopenharmony_ci			total_elems -= MCAST_MAC_ELEMS_PER_PG;
27248c2ecf20Sopenharmony_ci			list_add_tail(&elem_group->mcast_group_link,
27258c2ecf20Sopenharmony_ci				      &new_cmd->group_head);
27268c2ecf20Sopenharmony_ci		}
27278c2ecf20Sopenharmony_ci		elem_group = list_first_entry(&new_cmd->group_head,
27288c2ecf20Sopenharmony_ci					      struct bnx2x_mcast_elem_group,
27298c2ecf20Sopenharmony_ci					      mcast_group_link);
27308c2ecf20Sopenharmony_ci		list_for_each_entry(pos, &p->mcast_list, link) {
27318c2ecf20Sopenharmony_ci			mac_elem = &elem_group->mcast_elems[offset].mac_elem;
27328c2ecf20Sopenharmony_ci			memcpy(mac_elem->mac, pos->mac, ETH_ALEN);
27338c2ecf20Sopenharmony_ci			/* Push the MACs of the current command into the pending
27348c2ecf20Sopenharmony_ci			 * command MACs list: FIFO
27358c2ecf20Sopenharmony_ci			 */
27368c2ecf20Sopenharmony_ci			list_add_tail(&mac_elem->link,
27378c2ecf20Sopenharmony_ci				      &new_cmd->data.macs_head);
27388c2ecf20Sopenharmony_ci			offset++;
27398c2ecf20Sopenharmony_ci			if (offset == MCAST_MAC_ELEMS_PER_PG) {
27408c2ecf20Sopenharmony_ci				offset = 0;
27418c2ecf20Sopenharmony_ci				elem_group = list_next_entry(elem_group,
27428c2ecf20Sopenharmony_ci							     mcast_group_link);
27438c2ecf20Sopenharmony_ci			}
27448c2ecf20Sopenharmony_ci		}
27458c2ecf20Sopenharmony_ci		break;
27468c2ecf20Sopenharmony_ci
27478c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_DEL:
27488c2ecf20Sopenharmony_ci		new_cmd->data.macs_num = p->mcast_list_len;
27498c2ecf20Sopenharmony_ci		break;
27508c2ecf20Sopenharmony_ci
27518c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_RESTORE:
27528c2ecf20Sopenharmony_ci		new_cmd->data.next_bin = 0;
27538c2ecf20Sopenharmony_ci		break;
27548c2ecf20Sopenharmony_ci
27558c2ecf20Sopenharmony_ci	default:
27568c2ecf20Sopenharmony_ci		kfree(new_cmd);
27578c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown command: %d\n", cmd);
27588c2ecf20Sopenharmony_ci		return -EINVAL;
27598c2ecf20Sopenharmony_ci	}
27608c2ecf20Sopenharmony_ci
27618c2ecf20Sopenharmony_ci	/* Push the new pending command to the tail of the pending list: FIFO */
27628c2ecf20Sopenharmony_ci	list_add_tail(&new_cmd->link, &o->pending_cmds_head);
27638c2ecf20Sopenharmony_ci
27648c2ecf20Sopenharmony_ci	o->set_sched(o);
27658c2ecf20Sopenharmony_ci
27668c2ecf20Sopenharmony_ci	return 1;
27678c2ecf20Sopenharmony_ci}
27688c2ecf20Sopenharmony_ci
27698c2ecf20Sopenharmony_ci/**
27708c2ecf20Sopenharmony_ci * bnx2x_mcast_get_next_bin - get the next set bin (index)
27718c2ecf20Sopenharmony_ci *
27728c2ecf20Sopenharmony_ci * @o:		multicast object info
27738c2ecf20Sopenharmony_ci * @last:	index to start looking from (including)
27748c2ecf20Sopenharmony_ci *
27758c2ecf20Sopenharmony_ci * returns the next found (set) bin or a negative value if none is found.
27768c2ecf20Sopenharmony_ci */
27778c2ecf20Sopenharmony_cistatic inline int bnx2x_mcast_get_next_bin(struct bnx2x_mcast_obj *o, int last)
27788c2ecf20Sopenharmony_ci{
27798c2ecf20Sopenharmony_ci	int i, j, inner_start = last % BIT_VEC64_ELEM_SZ;
27808c2ecf20Sopenharmony_ci
27818c2ecf20Sopenharmony_ci	for (i = last / BIT_VEC64_ELEM_SZ; i < BNX2X_MCAST_VEC_SZ; i++) {
27828c2ecf20Sopenharmony_ci		if (o->registry.aprox_match.vec[i])
27838c2ecf20Sopenharmony_ci			for (j = inner_start; j < BIT_VEC64_ELEM_SZ; j++) {
27848c2ecf20Sopenharmony_ci				int cur_bit = j + BIT_VEC64_ELEM_SZ * i;
27858c2ecf20Sopenharmony_ci				if (BIT_VEC64_TEST_BIT(o->registry.aprox_match.
27868c2ecf20Sopenharmony_ci						       vec, cur_bit)) {
27878c2ecf20Sopenharmony_ci					return cur_bit;
27888c2ecf20Sopenharmony_ci				}
27898c2ecf20Sopenharmony_ci			}
27908c2ecf20Sopenharmony_ci		inner_start = 0;
27918c2ecf20Sopenharmony_ci	}
27928c2ecf20Sopenharmony_ci
27938c2ecf20Sopenharmony_ci	/* None found */
27948c2ecf20Sopenharmony_ci	return -1;
27958c2ecf20Sopenharmony_ci}
27968c2ecf20Sopenharmony_ci
27978c2ecf20Sopenharmony_ci/**
27988c2ecf20Sopenharmony_ci * bnx2x_mcast_clear_first_bin - find the first set bin and clear it
27998c2ecf20Sopenharmony_ci *
28008c2ecf20Sopenharmony_ci * @o:
28018c2ecf20Sopenharmony_ci *
28028c2ecf20Sopenharmony_ci * returns the index of the found bin or -1 if none is found
28038c2ecf20Sopenharmony_ci */
28048c2ecf20Sopenharmony_cistatic inline int bnx2x_mcast_clear_first_bin(struct bnx2x_mcast_obj *o)
28058c2ecf20Sopenharmony_ci{
28068c2ecf20Sopenharmony_ci	int cur_bit = bnx2x_mcast_get_next_bin(o, 0);
28078c2ecf20Sopenharmony_ci
28088c2ecf20Sopenharmony_ci	if (cur_bit >= 0)
28098c2ecf20Sopenharmony_ci		BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, cur_bit);
28108c2ecf20Sopenharmony_ci
28118c2ecf20Sopenharmony_ci	return cur_bit;
28128c2ecf20Sopenharmony_ci}
28138c2ecf20Sopenharmony_ci
28148c2ecf20Sopenharmony_cistatic inline u8 bnx2x_mcast_get_rx_tx_flag(struct bnx2x_mcast_obj *o)
28158c2ecf20Sopenharmony_ci{
28168c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
28178c2ecf20Sopenharmony_ci	u8 rx_tx_flag = 0;
28188c2ecf20Sopenharmony_ci
28198c2ecf20Sopenharmony_ci	if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
28208c2ecf20Sopenharmony_ci	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
28218c2ecf20Sopenharmony_ci		rx_tx_flag |= ETH_MULTICAST_RULES_CMD_TX_CMD;
28228c2ecf20Sopenharmony_ci
28238c2ecf20Sopenharmony_ci	if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
28248c2ecf20Sopenharmony_ci	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
28258c2ecf20Sopenharmony_ci		rx_tx_flag |= ETH_MULTICAST_RULES_CMD_RX_CMD;
28268c2ecf20Sopenharmony_ci
28278c2ecf20Sopenharmony_ci	return rx_tx_flag;
28288c2ecf20Sopenharmony_ci}
28298c2ecf20Sopenharmony_ci
28308c2ecf20Sopenharmony_cistatic void bnx2x_mcast_set_one_rule_e2(struct bnx2x *bp,
28318c2ecf20Sopenharmony_ci					struct bnx2x_mcast_obj *o, int idx,
28328c2ecf20Sopenharmony_ci					union bnx2x_mcast_config_data *cfg_data,
28338c2ecf20Sopenharmony_ci					enum bnx2x_mcast_cmd cmd)
28348c2ecf20Sopenharmony_ci{
28358c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *r = &o->raw;
28368c2ecf20Sopenharmony_ci	struct eth_multicast_rules_ramrod_data *data =
28378c2ecf20Sopenharmony_ci		(struct eth_multicast_rules_ramrod_data *)(r->rdata);
28388c2ecf20Sopenharmony_ci	u8 func_id = r->func_id;
28398c2ecf20Sopenharmony_ci	u8 rx_tx_add_flag = bnx2x_mcast_get_rx_tx_flag(o);
28408c2ecf20Sopenharmony_ci	int bin;
28418c2ecf20Sopenharmony_ci
28428c2ecf20Sopenharmony_ci	if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE) ||
28438c2ecf20Sopenharmony_ci	    (cmd == BNX2X_MCAST_CMD_SET_ADD))
28448c2ecf20Sopenharmony_ci		rx_tx_add_flag |= ETH_MULTICAST_RULES_CMD_IS_ADD;
28458c2ecf20Sopenharmony_ci
28468c2ecf20Sopenharmony_ci	data->rules[idx].cmd_general_data |= rx_tx_add_flag;
28478c2ecf20Sopenharmony_ci
28488c2ecf20Sopenharmony_ci	/* Get a bin and update a bins' vector */
28498c2ecf20Sopenharmony_ci	switch (cmd) {
28508c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_ADD:
28518c2ecf20Sopenharmony_ci		bin = bnx2x_mcast_bin_from_mac(cfg_data->mac);
28528c2ecf20Sopenharmony_ci		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin);
28538c2ecf20Sopenharmony_ci		break;
28548c2ecf20Sopenharmony_ci
28558c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_DEL:
28568c2ecf20Sopenharmony_ci		/* If there were no more bins to clear
28578c2ecf20Sopenharmony_ci		 * (bnx2x_mcast_clear_first_bin() returns -1) then we would
28588c2ecf20Sopenharmony_ci		 * clear any (0xff) bin.
28598c2ecf20Sopenharmony_ci		 * See bnx2x_mcast_validate_e2() for explanation when it may
28608c2ecf20Sopenharmony_ci		 * happen.
28618c2ecf20Sopenharmony_ci		 */
28628c2ecf20Sopenharmony_ci		bin = bnx2x_mcast_clear_first_bin(o);
28638c2ecf20Sopenharmony_ci		break;
28648c2ecf20Sopenharmony_ci
28658c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_RESTORE:
28668c2ecf20Sopenharmony_ci		bin = cfg_data->bin;
28678c2ecf20Sopenharmony_ci		break;
28688c2ecf20Sopenharmony_ci
28698c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_SET_ADD:
28708c2ecf20Sopenharmony_ci		bin = cfg_data->bin;
28718c2ecf20Sopenharmony_ci		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin);
28728c2ecf20Sopenharmony_ci		break;
28738c2ecf20Sopenharmony_ci
28748c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_SET_DEL:
28758c2ecf20Sopenharmony_ci		bin = cfg_data->bin;
28768c2ecf20Sopenharmony_ci		BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, bin);
28778c2ecf20Sopenharmony_ci		break;
28788c2ecf20Sopenharmony_ci
28798c2ecf20Sopenharmony_ci	default:
28808c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown command: %d\n", cmd);
28818c2ecf20Sopenharmony_ci		return;
28828c2ecf20Sopenharmony_ci	}
28838c2ecf20Sopenharmony_ci
28848c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "%s bin %d\n",
28858c2ecf20Sopenharmony_ci			 ((rx_tx_add_flag & ETH_MULTICAST_RULES_CMD_IS_ADD) ?
28868c2ecf20Sopenharmony_ci			 "Setting"  : "Clearing"), bin);
28878c2ecf20Sopenharmony_ci
28888c2ecf20Sopenharmony_ci	data->rules[idx].bin_id    = (u8)bin;
28898c2ecf20Sopenharmony_ci	data->rules[idx].func_id   = func_id;
28908c2ecf20Sopenharmony_ci	data->rules[idx].engine_id = o->engine_id;
28918c2ecf20Sopenharmony_ci}
28928c2ecf20Sopenharmony_ci
28938c2ecf20Sopenharmony_ci/**
28948c2ecf20Sopenharmony_ci * bnx2x_mcast_handle_restore_cmd_e2 - restore configuration from the registry
28958c2ecf20Sopenharmony_ci *
28968c2ecf20Sopenharmony_ci * @bp:		device handle
28978c2ecf20Sopenharmony_ci * @o:		multicast object info
28988c2ecf20Sopenharmony_ci * @start_bin:	index in the registry to start from (including)
28998c2ecf20Sopenharmony_ci * @rdata_idx:	index in the ramrod data to start from
29008c2ecf20Sopenharmony_ci *
29018c2ecf20Sopenharmony_ci * returns last handled bin index or -1 if all bins have been handled
29028c2ecf20Sopenharmony_ci */
29038c2ecf20Sopenharmony_cistatic inline int bnx2x_mcast_handle_restore_cmd_e2(
29048c2ecf20Sopenharmony_ci	struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_bin,
29058c2ecf20Sopenharmony_ci	int *rdata_idx)
29068c2ecf20Sopenharmony_ci{
29078c2ecf20Sopenharmony_ci	int cur_bin, cnt = *rdata_idx;
29088c2ecf20Sopenharmony_ci	union bnx2x_mcast_config_data cfg_data = {NULL};
29098c2ecf20Sopenharmony_ci
29108c2ecf20Sopenharmony_ci	/* go through the registry and configure the bins from it */
29118c2ecf20Sopenharmony_ci	for (cur_bin = bnx2x_mcast_get_next_bin(o, start_bin); cur_bin >= 0;
29128c2ecf20Sopenharmony_ci	    cur_bin = bnx2x_mcast_get_next_bin(o, cur_bin + 1)) {
29138c2ecf20Sopenharmony_ci
29148c2ecf20Sopenharmony_ci		cfg_data.bin = (u8)cur_bin;
29158c2ecf20Sopenharmony_ci		o->set_one_rule(bp, o, cnt, &cfg_data,
29168c2ecf20Sopenharmony_ci				BNX2X_MCAST_CMD_RESTORE);
29178c2ecf20Sopenharmony_ci
29188c2ecf20Sopenharmony_ci		cnt++;
29198c2ecf20Sopenharmony_ci
29208c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "About to configure a bin %d\n", cur_bin);
29218c2ecf20Sopenharmony_ci
29228c2ecf20Sopenharmony_ci		/* Break if we reached the maximum number
29238c2ecf20Sopenharmony_ci		 * of rules.
29248c2ecf20Sopenharmony_ci		 */
29258c2ecf20Sopenharmony_ci		if (cnt >= o->max_cmd_len)
29268c2ecf20Sopenharmony_ci			break;
29278c2ecf20Sopenharmony_ci	}
29288c2ecf20Sopenharmony_ci
29298c2ecf20Sopenharmony_ci	*rdata_idx = cnt;
29308c2ecf20Sopenharmony_ci
29318c2ecf20Sopenharmony_ci	return cur_bin;
29328c2ecf20Sopenharmony_ci}
29338c2ecf20Sopenharmony_ci
29348c2ecf20Sopenharmony_cistatic inline void bnx2x_mcast_hdl_pending_add_e2(struct bnx2x *bp,
29358c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
29368c2ecf20Sopenharmony_ci	int *line_idx)
29378c2ecf20Sopenharmony_ci{
29388c2ecf20Sopenharmony_ci	struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n;
29398c2ecf20Sopenharmony_ci	int cnt = *line_idx;
29408c2ecf20Sopenharmony_ci	union bnx2x_mcast_config_data cfg_data = {NULL};
29418c2ecf20Sopenharmony_ci
29428c2ecf20Sopenharmony_ci	list_for_each_entry_safe(pmac_pos, pmac_pos_n, &cmd_pos->data.macs_head,
29438c2ecf20Sopenharmony_ci				 link) {
29448c2ecf20Sopenharmony_ci
29458c2ecf20Sopenharmony_ci		cfg_data.mac = &pmac_pos->mac[0];
29468c2ecf20Sopenharmony_ci		o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
29478c2ecf20Sopenharmony_ci
29488c2ecf20Sopenharmony_ci		cnt++;
29498c2ecf20Sopenharmony_ci
29508c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
29518c2ecf20Sopenharmony_ci		   pmac_pos->mac);
29528c2ecf20Sopenharmony_ci
29538c2ecf20Sopenharmony_ci		list_del(&pmac_pos->link);
29548c2ecf20Sopenharmony_ci
29558c2ecf20Sopenharmony_ci		/* Break if we reached the maximum number
29568c2ecf20Sopenharmony_ci		 * of rules.
29578c2ecf20Sopenharmony_ci		 */
29588c2ecf20Sopenharmony_ci		if (cnt >= o->max_cmd_len)
29598c2ecf20Sopenharmony_ci			break;
29608c2ecf20Sopenharmony_ci	}
29618c2ecf20Sopenharmony_ci
29628c2ecf20Sopenharmony_ci	*line_idx = cnt;
29638c2ecf20Sopenharmony_ci
29648c2ecf20Sopenharmony_ci	/* if no more MACs to configure - we are done */
29658c2ecf20Sopenharmony_ci	if (list_empty(&cmd_pos->data.macs_head))
29668c2ecf20Sopenharmony_ci		cmd_pos->done = true;
29678c2ecf20Sopenharmony_ci}
29688c2ecf20Sopenharmony_ci
29698c2ecf20Sopenharmony_cistatic inline void bnx2x_mcast_hdl_pending_del_e2(struct bnx2x *bp,
29708c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
29718c2ecf20Sopenharmony_ci	int *line_idx)
29728c2ecf20Sopenharmony_ci{
29738c2ecf20Sopenharmony_ci	int cnt = *line_idx;
29748c2ecf20Sopenharmony_ci
29758c2ecf20Sopenharmony_ci	while (cmd_pos->data.macs_num) {
29768c2ecf20Sopenharmony_ci		o->set_one_rule(bp, o, cnt, NULL, cmd_pos->type);
29778c2ecf20Sopenharmony_ci
29788c2ecf20Sopenharmony_ci		cnt++;
29798c2ecf20Sopenharmony_ci
29808c2ecf20Sopenharmony_ci		cmd_pos->data.macs_num--;
29818c2ecf20Sopenharmony_ci
29828c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "Deleting MAC. %d left,cnt is %d\n",
29838c2ecf20Sopenharmony_ci		   cmd_pos->data.macs_num, cnt);
29848c2ecf20Sopenharmony_ci
29858c2ecf20Sopenharmony_ci		/* Break if we reached the maximum
29868c2ecf20Sopenharmony_ci		 * number of rules.
29878c2ecf20Sopenharmony_ci		 */
29888c2ecf20Sopenharmony_ci		if (cnt >= o->max_cmd_len)
29898c2ecf20Sopenharmony_ci			break;
29908c2ecf20Sopenharmony_ci	}
29918c2ecf20Sopenharmony_ci
29928c2ecf20Sopenharmony_ci	*line_idx = cnt;
29938c2ecf20Sopenharmony_ci
29948c2ecf20Sopenharmony_ci	/* If we cleared all bins - we are done */
29958c2ecf20Sopenharmony_ci	if (!cmd_pos->data.macs_num)
29968c2ecf20Sopenharmony_ci		cmd_pos->done = true;
29978c2ecf20Sopenharmony_ci}
29988c2ecf20Sopenharmony_ci
29998c2ecf20Sopenharmony_cistatic inline void bnx2x_mcast_hdl_pending_restore_e2(struct bnx2x *bp,
30008c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
30018c2ecf20Sopenharmony_ci	int *line_idx)
30028c2ecf20Sopenharmony_ci{
30038c2ecf20Sopenharmony_ci	cmd_pos->data.next_bin = o->hdl_restore(bp, o, cmd_pos->data.next_bin,
30048c2ecf20Sopenharmony_ci						line_idx);
30058c2ecf20Sopenharmony_ci
30068c2ecf20Sopenharmony_ci	if (cmd_pos->data.next_bin < 0)
30078c2ecf20Sopenharmony_ci		/* If o->set_restore returned -1 we are done */
30088c2ecf20Sopenharmony_ci		cmd_pos->done = true;
30098c2ecf20Sopenharmony_ci	else
30108c2ecf20Sopenharmony_ci		/* Start from the next bin next time */
30118c2ecf20Sopenharmony_ci		cmd_pos->data.next_bin++;
30128c2ecf20Sopenharmony_ci}
30138c2ecf20Sopenharmony_ci
30148c2ecf20Sopenharmony_cistatic void
30158c2ecf20Sopenharmony_cibnx2x_mcast_hdl_pending_set_e2_convert(struct bnx2x *bp,
30168c2ecf20Sopenharmony_ci				       struct bnx2x_mcast_obj *o,
30178c2ecf20Sopenharmony_ci				       struct bnx2x_pending_mcast_cmd *cmd_pos)
30188c2ecf20Sopenharmony_ci{
30198c2ecf20Sopenharmony_ci	u64 cur[BNX2X_MCAST_VEC_SZ], req[BNX2X_MCAST_VEC_SZ];
30208c2ecf20Sopenharmony_ci	struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n;
30218c2ecf20Sopenharmony_ci	struct bnx2x_mcast_bin_elem *p_item;
30228c2ecf20Sopenharmony_ci	struct bnx2x_mcast_elem_group *elem_group;
30238c2ecf20Sopenharmony_ci	int cnt = 0, mac_cnt = 0, offset = 0, i;
30248c2ecf20Sopenharmony_ci
30258c2ecf20Sopenharmony_ci	memset(req, 0, sizeof(u64) * BNX2X_MCAST_VEC_SZ);
30268c2ecf20Sopenharmony_ci	memcpy(cur, o->registry.aprox_match.vec,
30278c2ecf20Sopenharmony_ci	       sizeof(u64) * BNX2X_MCAST_VEC_SZ);
30288c2ecf20Sopenharmony_ci
30298c2ecf20Sopenharmony_ci	/* Fill `current' with the required set of bins to configure */
30308c2ecf20Sopenharmony_ci	list_for_each_entry_safe(pmac_pos, pmac_pos_n, &cmd_pos->data.macs_head,
30318c2ecf20Sopenharmony_ci				 link) {
30328c2ecf20Sopenharmony_ci		int bin = bnx2x_mcast_bin_from_mac(pmac_pos->mac);
30338c2ecf20Sopenharmony_ci
30348c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "Set contains %pM mcast MAC\n",
30358c2ecf20Sopenharmony_ci		   pmac_pos->mac);
30368c2ecf20Sopenharmony_ci
30378c2ecf20Sopenharmony_ci		BIT_VEC64_SET_BIT(req, bin);
30388c2ecf20Sopenharmony_ci		list_del(&pmac_pos->link);
30398c2ecf20Sopenharmony_ci		mac_cnt++;
30408c2ecf20Sopenharmony_ci	}
30418c2ecf20Sopenharmony_ci
30428c2ecf20Sopenharmony_ci	/* We no longer have use for the MACs; Need to re-use memory for
30438c2ecf20Sopenharmony_ci	 * a list that will be used to configure bins.
30448c2ecf20Sopenharmony_ci	 */
30458c2ecf20Sopenharmony_ci	cmd_pos->set_convert = true;
30468c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&cmd_pos->data.macs_head);
30478c2ecf20Sopenharmony_ci	elem_group = list_first_entry(&cmd_pos->group_head,
30488c2ecf20Sopenharmony_ci				      struct bnx2x_mcast_elem_group,
30498c2ecf20Sopenharmony_ci				      mcast_group_link);
30508c2ecf20Sopenharmony_ci	for (i = 0; i < BNX2X_MCAST_BINS_NUM; i++) {
30518c2ecf20Sopenharmony_ci		bool b_current = !!BIT_VEC64_TEST_BIT(cur, i);
30528c2ecf20Sopenharmony_ci		bool b_required = !!BIT_VEC64_TEST_BIT(req, i);
30538c2ecf20Sopenharmony_ci
30548c2ecf20Sopenharmony_ci		if (b_current == b_required)
30558c2ecf20Sopenharmony_ci			continue;
30568c2ecf20Sopenharmony_ci
30578c2ecf20Sopenharmony_ci		p_item = &elem_group->mcast_elems[offset].bin_elem;
30588c2ecf20Sopenharmony_ci		p_item->bin = i;
30598c2ecf20Sopenharmony_ci		p_item->type = b_required ? BNX2X_MCAST_CMD_SET_ADD
30608c2ecf20Sopenharmony_ci					  : BNX2X_MCAST_CMD_SET_DEL;
30618c2ecf20Sopenharmony_ci		list_add_tail(&p_item->link , &cmd_pos->data.macs_head);
30628c2ecf20Sopenharmony_ci		cnt++;
30638c2ecf20Sopenharmony_ci		offset++;
30648c2ecf20Sopenharmony_ci		if (offset == MCAST_MAC_ELEMS_PER_PG) {
30658c2ecf20Sopenharmony_ci			offset = 0;
30668c2ecf20Sopenharmony_ci			elem_group = list_next_entry(elem_group,
30678c2ecf20Sopenharmony_ci						     mcast_group_link);
30688c2ecf20Sopenharmony_ci		}
30698c2ecf20Sopenharmony_ci	}
30708c2ecf20Sopenharmony_ci
30718c2ecf20Sopenharmony_ci	/* We now definitely know how many commands are hiding here.
30728c2ecf20Sopenharmony_ci	 * Also need to correct the disruption we've added to guarantee this
30738c2ecf20Sopenharmony_ci	 * would be enqueued.
30748c2ecf20Sopenharmony_ci	 */
30758c2ecf20Sopenharmony_ci	o->total_pending_num -= (o->max_cmd_len + mac_cnt);
30768c2ecf20Sopenharmony_ci	o->total_pending_num += cnt;
30778c2ecf20Sopenharmony_ci
30788c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "o->total_pending_num=%d\n", o->total_pending_num);
30798c2ecf20Sopenharmony_ci}
30808c2ecf20Sopenharmony_ci
30818c2ecf20Sopenharmony_cistatic void
30828c2ecf20Sopenharmony_cibnx2x_mcast_hdl_pending_set_e2(struct bnx2x *bp,
30838c2ecf20Sopenharmony_ci			       struct bnx2x_mcast_obj *o,
30848c2ecf20Sopenharmony_ci			       struct bnx2x_pending_mcast_cmd *cmd_pos,
30858c2ecf20Sopenharmony_ci			       int *cnt)
30868c2ecf20Sopenharmony_ci{
30878c2ecf20Sopenharmony_ci	union bnx2x_mcast_config_data cfg_data = {NULL};
30888c2ecf20Sopenharmony_ci	struct bnx2x_mcast_bin_elem *p_item, *p_item_n;
30898c2ecf20Sopenharmony_ci
30908c2ecf20Sopenharmony_ci	/* This is actually a 2-part scheme - it starts by converting the MACs
30918c2ecf20Sopenharmony_ci	 * into a list of bins to be added/removed, and correcting the numbers
30928c2ecf20Sopenharmony_ci	 * on the object. this is now allowed, as we're now sure that all
30938c2ecf20Sopenharmony_ci	 * previous configured requests have already applied.
30948c2ecf20Sopenharmony_ci	 * The second part is actually adding rules for the newly introduced
30958c2ecf20Sopenharmony_ci	 * entries [like all the rest of the hdl_pending functions].
30968c2ecf20Sopenharmony_ci	 */
30978c2ecf20Sopenharmony_ci	if (!cmd_pos->set_convert)
30988c2ecf20Sopenharmony_ci		bnx2x_mcast_hdl_pending_set_e2_convert(bp, o, cmd_pos);
30998c2ecf20Sopenharmony_ci
31008c2ecf20Sopenharmony_ci	list_for_each_entry_safe(p_item, p_item_n, &cmd_pos->data.macs_head,
31018c2ecf20Sopenharmony_ci				 link) {
31028c2ecf20Sopenharmony_ci		cfg_data.bin = (u8)p_item->bin;
31038c2ecf20Sopenharmony_ci		o->set_one_rule(bp, o, *cnt, &cfg_data, p_item->type);
31048c2ecf20Sopenharmony_ci		(*cnt)++;
31058c2ecf20Sopenharmony_ci
31068c2ecf20Sopenharmony_ci		list_del(&p_item->link);
31078c2ecf20Sopenharmony_ci
31088c2ecf20Sopenharmony_ci		/* Break if we reached the maximum number of rules. */
31098c2ecf20Sopenharmony_ci		if (*cnt >= o->max_cmd_len)
31108c2ecf20Sopenharmony_ci			break;
31118c2ecf20Sopenharmony_ci	}
31128c2ecf20Sopenharmony_ci
31138c2ecf20Sopenharmony_ci	/* if no more MACs to configure - we are done */
31148c2ecf20Sopenharmony_ci	if (list_empty(&cmd_pos->data.macs_head))
31158c2ecf20Sopenharmony_ci		cmd_pos->done = true;
31168c2ecf20Sopenharmony_ci}
31178c2ecf20Sopenharmony_ci
31188c2ecf20Sopenharmony_cistatic inline int bnx2x_mcast_handle_pending_cmds_e2(struct bnx2x *bp,
31198c2ecf20Sopenharmony_ci				struct bnx2x_mcast_ramrod_params *p)
31208c2ecf20Sopenharmony_ci{
31218c2ecf20Sopenharmony_ci	struct bnx2x_pending_mcast_cmd *cmd_pos, *cmd_pos_n;
31228c2ecf20Sopenharmony_ci	int cnt = 0;
31238c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o = p->mcast_obj;
31248c2ecf20Sopenharmony_ci
31258c2ecf20Sopenharmony_ci	list_for_each_entry_safe(cmd_pos, cmd_pos_n, &o->pending_cmds_head,
31268c2ecf20Sopenharmony_ci				 link) {
31278c2ecf20Sopenharmony_ci		switch (cmd_pos->type) {
31288c2ecf20Sopenharmony_ci		case BNX2X_MCAST_CMD_ADD:
31298c2ecf20Sopenharmony_ci			bnx2x_mcast_hdl_pending_add_e2(bp, o, cmd_pos, &cnt);
31308c2ecf20Sopenharmony_ci			break;
31318c2ecf20Sopenharmony_ci
31328c2ecf20Sopenharmony_ci		case BNX2X_MCAST_CMD_DEL:
31338c2ecf20Sopenharmony_ci			bnx2x_mcast_hdl_pending_del_e2(bp, o, cmd_pos, &cnt);
31348c2ecf20Sopenharmony_ci			break;
31358c2ecf20Sopenharmony_ci
31368c2ecf20Sopenharmony_ci		case BNX2X_MCAST_CMD_RESTORE:
31378c2ecf20Sopenharmony_ci			bnx2x_mcast_hdl_pending_restore_e2(bp, o, cmd_pos,
31388c2ecf20Sopenharmony_ci							   &cnt);
31398c2ecf20Sopenharmony_ci			break;
31408c2ecf20Sopenharmony_ci
31418c2ecf20Sopenharmony_ci		case BNX2X_MCAST_CMD_SET:
31428c2ecf20Sopenharmony_ci			bnx2x_mcast_hdl_pending_set_e2(bp, o, cmd_pos, &cnt);
31438c2ecf20Sopenharmony_ci			break;
31448c2ecf20Sopenharmony_ci
31458c2ecf20Sopenharmony_ci		default:
31468c2ecf20Sopenharmony_ci			BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
31478c2ecf20Sopenharmony_ci			return -EINVAL;
31488c2ecf20Sopenharmony_ci		}
31498c2ecf20Sopenharmony_ci
31508c2ecf20Sopenharmony_ci		/* If the command has been completed - remove it from the list
31518c2ecf20Sopenharmony_ci		 * and free the memory
31528c2ecf20Sopenharmony_ci		 */
31538c2ecf20Sopenharmony_ci		if (cmd_pos->done) {
31548c2ecf20Sopenharmony_ci			list_del(&cmd_pos->link);
31558c2ecf20Sopenharmony_ci			bnx2x_free_groups(&cmd_pos->group_head);
31568c2ecf20Sopenharmony_ci			kfree(cmd_pos);
31578c2ecf20Sopenharmony_ci		}
31588c2ecf20Sopenharmony_ci
31598c2ecf20Sopenharmony_ci		/* Break if we reached the maximum number of rules */
31608c2ecf20Sopenharmony_ci		if (cnt >= o->max_cmd_len)
31618c2ecf20Sopenharmony_ci			break;
31628c2ecf20Sopenharmony_ci	}
31638c2ecf20Sopenharmony_ci
31648c2ecf20Sopenharmony_ci	return cnt;
31658c2ecf20Sopenharmony_ci}
31668c2ecf20Sopenharmony_ci
31678c2ecf20Sopenharmony_cistatic inline void bnx2x_mcast_hdl_add(struct bnx2x *bp,
31688c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
31698c2ecf20Sopenharmony_ci	int *line_idx)
31708c2ecf20Sopenharmony_ci{
31718c2ecf20Sopenharmony_ci	struct bnx2x_mcast_list_elem *mlist_pos;
31728c2ecf20Sopenharmony_ci	union bnx2x_mcast_config_data cfg_data = {NULL};
31738c2ecf20Sopenharmony_ci	int cnt = *line_idx;
31748c2ecf20Sopenharmony_ci
31758c2ecf20Sopenharmony_ci	list_for_each_entry(mlist_pos, &p->mcast_list, link) {
31768c2ecf20Sopenharmony_ci		cfg_data.mac = mlist_pos->mac;
31778c2ecf20Sopenharmony_ci		o->set_one_rule(bp, o, cnt, &cfg_data, BNX2X_MCAST_CMD_ADD);
31788c2ecf20Sopenharmony_ci
31798c2ecf20Sopenharmony_ci		cnt++;
31808c2ecf20Sopenharmony_ci
31818c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
31828c2ecf20Sopenharmony_ci		   mlist_pos->mac);
31838c2ecf20Sopenharmony_ci	}
31848c2ecf20Sopenharmony_ci
31858c2ecf20Sopenharmony_ci	*line_idx = cnt;
31868c2ecf20Sopenharmony_ci}
31878c2ecf20Sopenharmony_ci
31888c2ecf20Sopenharmony_cistatic inline void bnx2x_mcast_hdl_del(struct bnx2x *bp,
31898c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
31908c2ecf20Sopenharmony_ci	int *line_idx)
31918c2ecf20Sopenharmony_ci{
31928c2ecf20Sopenharmony_ci	int cnt = *line_idx, i;
31938c2ecf20Sopenharmony_ci
31948c2ecf20Sopenharmony_ci	for (i = 0; i < p->mcast_list_len; i++) {
31958c2ecf20Sopenharmony_ci		o->set_one_rule(bp, o, cnt, NULL, BNX2X_MCAST_CMD_DEL);
31968c2ecf20Sopenharmony_ci
31978c2ecf20Sopenharmony_ci		cnt++;
31988c2ecf20Sopenharmony_ci
31998c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "Deleting MAC. %d left\n",
32008c2ecf20Sopenharmony_ci				 p->mcast_list_len - i - 1);
32018c2ecf20Sopenharmony_ci	}
32028c2ecf20Sopenharmony_ci
32038c2ecf20Sopenharmony_ci	*line_idx = cnt;
32048c2ecf20Sopenharmony_ci}
32058c2ecf20Sopenharmony_ci
32068c2ecf20Sopenharmony_ci/**
32078c2ecf20Sopenharmony_ci * bnx2x_mcast_handle_current_cmd - send command if room
32088c2ecf20Sopenharmony_ci *
32098c2ecf20Sopenharmony_ci * @bp:		device handle
32108c2ecf20Sopenharmony_ci * @p:		ramrod mcast info
32118c2ecf20Sopenharmony_ci * @cmd:	command
32128c2ecf20Sopenharmony_ci * @start_cnt:	first line in the ramrod data that may be used
32138c2ecf20Sopenharmony_ci *
32148c2ecf20Sopenharmony_ci * This function is called iff there is enough place for the current command in
32158c2ecf20Sopenharmony_ci * the ramrod data.
32168c2ecf20Sopenharmony_ci * Returns number of lines filled in the ramrod data in total.
32178c2ecf20Sopenharmony_ci */
32188c2ecf20Sopenharmony_cistatic inline int bnx2x_mcast_handle_current_cmd(struct bnx2x *bp,
32198c2ecf20Sopenharmony_ci			struct bnx2x_mcast_ramrod_params *p,
32208c2ecf20Sopenharmony_ci			enum bnx2x_mcast_cmd cmd,
32218c2ecf20Sopenharmony_ci			int start_cnt)
32228c2ecf20Sopenharmony_ci{
32238c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o = p->mcast_obj;
32248c2ecf20Sopenharmony_ci	int cnt = start_cnt;
32258c2ecf20Sopenharmony_ci
32268c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
32278c2ecf20Sopenharmony_ci
32288c2ecf20Sopenharmony_ci	switch (cmd) {
32298c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_ADD:
32308c2ecf20Sopenharmony_ci		bnx2x_mcast_hdl_add(bp, o, p, &cnt);
32318c2ecf20Sopenharmony_ci		break;
32328c2ecf20Sopenharmony_ci
32338c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_DEL:
32348c2ecf20Sopenharmony_ci		bnx2x_mcast_hdl_del(bp, o, p, &cnt);
32358c2ecf20Sopenharmony_ci		break;
32368c2ecf20Sopenharmony_ci
32378c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_RESTORE:
32388c2ecf20Sopenharmony_ci		o->hdl_restore(bp, o, 0, &cnt);
32398c2ecf20Sopenharmony_ci		break;
32408c2ecf20Sopenharmony_ci
32418c2ecf20Sopenharmony_ci	default:
32428c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown command: %d\n", cmd);
32438c2ecf20Sopenharmony_ci		return -EINVAL;
32448c2ecf20Sopenharmony_ci	}
32458c2ecf20Sopenharmony_ci
32468c2ecf20Sopenharmony_ci	/* The current command has been handled */
32478c2ecf20Sopenharmony_ci	p->mcast_list_len = 0;
32488c2ecf20Sopenharmony_ci
32498c2ecf20Sopenharmony_ci	return cnt;
32508c2ecf20Sopenharmony_ci}
32518c2ecf20Sopenharmony_ci
32528c2ecf20Sopenharmony_cistatic int bnx2x_mcast_validate_e2(struct bnx2x *bp,
32538c2ecf20Sopenharmony_ci				   struct bnx2x_mcast_ramrod_params *p,
32548c2ecf20Sopenharmony_ci				   enum bnx2x_mcast_cmd cmd)
32558c2ecf20Sopenharmony_ci{
32568c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o = p->mcast_obj;
32578c2ecf20Sopenharmony_ci	int reg_sz = o->get_registry_size(o);
32588c2ecf20Sopenharmony_ci
32598c2ecf20Sopenharmony_ci	switch (cmd) {
32608c2ecf20Sopenharmony_ci	/* DEL command deletes all currently configured MACs */
32618c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_DEL:
32628c2ecf20Sopenharmony_ci		o->set_registry_size(o, 0);
32638c2ecf20Sopenharmony_ci		fallthrough;
32648c2ecf20Sopenharmony_ci
32658c2ecf20Sopenharmony_ci	/* RESTORE command will restore the entire multicast configuration */
32668c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_RESTORE:
32678c2ecf20Sopenharmony_ci		/* Here we set the approximate amount of work to do, which in
32688c2ecf20Sopenharmony_ci		 * fact may be only less as some MACs in postponed ADD
32698c2ecf20Sopenharmony_ci		 * command(s) scheduled before this command may fall into
32708c2ecf20Sopenharmony_ci		 * the same bin and the actual number of bins set in the
32718c2ecf20Sopenharmony_ci		 * registry would be less than we estimated here. See
32728c2ecf20Sopenharmony_ci		 * bnx2x_mcast_set_one_rule_e2() for further details.
32738c2ecf20Sopenharmony_ci		 */
32748c2ecf20Sopenharmony_ci		p->mcast_list_len = reg_sz;
32758c2ecf20Sopenharmony_ci		break;
32768c2ecf20Sopenharmony_ci
32778c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_ADD:
32788c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_CONT:
32798c2ecf20Sopenharmony_ci		/* Here we assume that all new MACs will fall into new bins.
32808c2ecf20Sopenharmony_ci		 * However we will correct the real registry size after we
32818c2ecf20Sopenharmony_ci		 * handle all pending commands.
32828c2ecf20Sopenharmony_ci		 */
32838c2ecf20Sopenharmony_ci		o->set_registry_size(o, reg_sz + p->mcast_list_len);
32848c2ecf20Sopenharmony_ci		break;
32858c2ecf20Sopenharmony_ci
32868c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_SET:
32878c2ecf20Sopenharmony_ci		/* We can only learn how many commands would actually be used
32888c2ecf20Sopenharmony_ci		 * when this is being configured. So for now, simply guarantee
32898c2ecf20Sopenharmony_ci		 * the command will be enqueued [to refrain from adding logic
32908c2ecf20Sopenharmony_ci		 * that handles this and THEN learns it needs several ramrods].
32918c2ecf20Sopenharmony_ci		 * Just like for ADD/Cont, the mcast_list_len might be an over
32928c2ecf20Sopenharmony_ci		 * estimation; or even more so, since we don't take into
32938c2ecf20Sopenharmony_ci		 * account the possibility of removal of existing bins.
32948c2ecf20Sopenharmony_ci		 */
32958c2ecf20Sopenharmony_ci		o->set_registry_size(o, reg_sz + p->mcast_list_len);
32968c2ecf20Sopenharmony_ci		o->total_pending_num += o->max_cmd_len;
32978c2ecf20Sopenharmony_ci		break;
32988c2ecf20Sopenharmony_ci
32998c2ecf20Sopenharmony_ci	default:
33008c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown command: %d\n", cmd);
33018c2ecf20Sopenharmony_ci		return -EINVAL;
33028c2ecf20Sopenharmony_ci	}
33038c2ecf20Sopenharmony_ci
33048c2ecf20Sopenharmony_ci	/* Increase the total number of MACs pending to be configured */
33058c2ecf20Sopenharmony_ci	o->total_pending_num += p->mcast_list_len;
33068c2ecf20Sopenharmony_ci
33078c2ecf20Sopenharmony_ci	return 0;
33088c2ecf20Sopenharmony_ci}
33098c2ecf20Sopenharmony_ci
33108c2ecf20Sopenharmony_cistatic void bnx2x_mcast_revert_e2(struct bnx2x *bp,
33118c2ecf20Sopenharmony_ci				      struct bnx2x_mcast_ramrod_params *p,
33128c2ecf20Sopenharmony_ci				  int old_num_bins,
33138c2ecf20Sopenharmony_ci				  enum bnx2x_mcast_cmd cmd)
33148c2ecf20Sopenharmony_ci{
33158c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o = p->mcast_obj;
33168c2ecf20Sopenharmony_ci
33178c2ecf20Sopenharmony_ci	o->set_registry_size(o, old_num_bins);
33188c2ecf20Sopenharmony_ci	o->total_pending_num -= p->mcast_list_len;
33198c2ecf20Sopenharmony_ci
33208c2ecf20Sopenharmony_ci	if (cmd == BNX2X_MCAST_CMD_SET)
33218c2ecf20Sopenharmony_ci		o->total_pending_num -= o->max_cmd_len;
33228c2ecf20Sopenharmony_ci}
33238c2ecf20Sopenharmony_ci
33248c2ecf20Sopenharmony_ci/**
33258c2ecf20Sopenharmony_ci * bnx2x_mcast_set_rdata_hdr_e2 - sets a header values
33268c2ecf20Sopenharmony_ci *
33278c2ecf20Sopenharmony_ci * @bp:		device handle
33288c2ecf20Sopenharmony_ci * @p:		ramrod parameters
33298c2ecf20Sopenharmony_ci * @len:	number of rules to handle
33308c2ecf20Sopenharmony_ci */
33318c2ecf20Sopenharmony_cistatic inline void bnx2x_mcast_set_rdata_hdr_e2(struct bnx2x *bp,
33328c2ecf20Sopenharmony_ci					struct bnx2x_mcast_ramrod_params *p,
33338c2ecf20Sopenharmony_ci					u8 len)
33348c2ecf20Sopenharmony_ci{
33358c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
33368c2ecf20Sopenharmony_ci	struct eth_multicast_rules_ramrod_data *data =
33378c2ecf20Sopenharmony_ci		(struct eth_multicast_rules_ramrod_data *)(r->rdata);
33388c2ecf20Sopenharmony_ci
33398c2ecf20Sopenharmony_ci	data->header.echo = cpu_to_le32((r->cid & BNX2X_SWCID_MASK) |
33408c2ecf20Sopenharmony_ci					(BNX2X_FILTER_MCAST_PENDING <<
33418c2ecf20Sopenharmony_ci					 BNX2X_SWCID_SHIFT));
33428c2ecf20Sopenharmony_ci	data->header.rule_cnt = len;
33438c2ecf20Sopenharmony_ci}
33448c2ecf20Sopenharmony_ci
33458c2ecf20Sopenharmony_ci/**
33468c2ecf20Sopenharmony_ci * bnx2x_mcast_refresh_registry_e2 - recalculate the actual number of set bins
33478c2ecf20Sopenharmony_ci *
33488c2ecf20Sopenharmony_ci * @bp:		device handle
33498c2ecf20Sopenharmony_ci * @o:
33508c2ecf20Sopenharmony_ci *
33518c2ecf20Sopenharmony_ci * Recalculate the actual number of set bins in the registry using Brian
33528c2ecf20Sopenharmony_ci * Kernighan's algorithm: it's execution complexity is as a number of set bins.
33538c2ecf20Sopenharmony_ci *
33548c2ecf20Sopenharmony_ci * returns 0 for the compliance with bnx2x_mcast_refresh_registry_e1().
33558c2ecf20Sopenharmony_ci */
33568c2ecf20Sopenharmony_cistatic inline int bnx2x_mcast_refresh_registry_e2(struct bnx2x *bp,
33578c2ecf20Sopenharmony_ci						  struct bnx2x_mcast_obj *o)
33588c2ecf20Sopenharmony_ci{
33598c2ecf20Sopenharmony_ci	int i, cnt = 0;
33608c2ecf20Sopenharmony_ci	u64 elem;
33618c2ecf20Sopenharmony_ci
33628c2ecf20Sopenharmony_ci	for (i = 0; i < BNX2X_MCAST_VEC_SZ; i++) {
33638c2ecf20Sopenharmony_ci		elem = o->registry.aprox_match.vec[i];
33648c2ecf20Sopenharmony_ci		for (; elem; cnt++)
33658c2ecf20Sopenharmony_ci			elem &= elem - 1;
33668c2ecf20Sopenharmony_ci	}
33678c2ecf20Sopenharmony_ci
33688c2ecf20Sopenharmony_ci	o->set_registry_size(o, cnt);
33698c2ecf20Sopenharmony_ci
33708c2ecf20Sopenharmony_ci	return 0;
33718c2ecf20Sopenharmony_ci}
33728c2ecf20Sopenharmony_ci
33738c2ecf20Sopenharmony_cistatic int bnx2x_mcast_setup_e2(struct bnx2x *bp,
33748c2ecf20Sopenharmony_ci				struct bnx2x_mcast_ramrod_params *p,
33758c2ecf20Sopenharmony_ci				enum bnx2x_mcast_cmd cmd)
33768c2ecf20Sopenharmony_ci{
33778c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &p->mcast_obj->raw;
33788c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o = p->mcast_obj;
33798c2ecf20Sopenharmony_ci	struct eth_multicast_rules_ramrod_data *data =
33808c2ecf20Sopenharmony_ci		(struct eth_multicast_rules_ramrod_data *)(raw->rdata);
33818c2ecf20Sopenharmony_ci	int cnt = 0, rc;
33828c2ecf20Sopenharmony_ci
33838c2ecf20Sopenharmony_ci	/* Reset the ramrod data buffer */
33848c2ecf20Sopenharmony_ci	memset(data, 0, sizeof(*data));
33858c2ecf20Sopenharmony_ci
33868c2ecf20Sopenharmony_ci	cnt = bnx2x_mcast_handle_pending_cmds_e2(bp, p);
33878c2ecf20Sopenharmony_ci
33888c2ecf20Sopenharmony_ci	/* If there are no more pending commands - clear SCHEDULED state */
33898c2ecf20Sopenharmony_ci	if (list_empty(&o->pending_cmds_head))
33908c2ecf20Sopenharmony_ci		o->clear_sched(o);
33918c2ecf20Sopenharmony_ci
33928c2ecf20Sopenharmony_ci	/* The below may be true iff there was enough room in ramrod
33938c2ecf20Sopenharmony_ci	 * data for all pending commands and for the current
33948c2ecf20Sopenharmony_ci	 * command. Otherwise the current command would have been added
33958c2ecf20Sopenharmony_ci	 * to the pending commands and p->mcast_list_len would have been
33968c2ecf20Sopenharmony_ci	 * zeroed.
33978c2ecf20Sopenharmony_ci	 */
33988c2ecf20Sopenharmony_ci	if (p->mcast_list_len > 0)
33998c2ecf20Sopenharmony_ci		cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, cnt);
34008c2ecf20Sopenharmony_ci
34018c2ecf20Sopenharmony_ci	/* We've pulled out some MACs - update the total number of
34028c2ecf20Sopenharmony_ci	 * outstanding.
34038c2ecf20Sopenharmony_ci	 */
34048c2ecf20Sopenharmony_ci	o->total_pending_num -= cnt;
34058c2ecf20Sopenharmony_ci
34068c2ecf20Sopenharmony_ci	/* send a ramrod */
34078c2ecf20Sopenharmony_ci	WARN_ON(o->total_pending_num < 0);
34088c2ecf20Sopenharmony_ci	WARN_ON(cnt > o->max_cmd_len);
34098c2ecf20Sopenharmony_ci
34108c2ecf20Sopenharmony_ci	bnx2x_mcast_set_rdata_hdr_e2(bp, p, (u8)cnt);
34118c2ecf20Sopenharmony_ci
34128c2ecf20Sopenharmony_ci	/* Update a registry size if there are no more pending operations.
34138c2ecf20Sopenharmony_ci	 *
34148c2ecf20Sopenharmony_ci	 * We don't want to change the value of the registry size if there are
34158c2ecf20Sopenharmony_ci	 * pending operations because we want it to always be equal to the
34168c2ecf20Sopenharmony_ci	 * exact or the approximate number (see bnx2x_mcast_validate_e2()) of
34178c2ecf20Sopenharmony_ci	 * set bins after the last requested operation in order to properly
34188c2ecf20Sopenharmony_ci	 * evaluate the size of the next DEL/RESTORE operation.
34198c2ecf20Sopenharmony_ci	 *
34208c2ecf20Sopenharmony_ci	 * Note that we update the registry itself during command(s) handling
34218c2ecf20Sopenharmony_ci	 * - see bnx2x_mcast_set_one_rule_e2(). That's because for 57712 we
34228c2ecf20Sopenharmony_ci	 * aggregate multiple commands (ADD/DEL/RESTORE) into one ramrod but
34238c2ecf20Sopenharmony_ci	 * with a limited amount of update commands (per MAC/bin) and we don't
34248c2ecf20Sopenharmony_ci	 * know in this scope what the actual state of bins configuration is
34258c2ecf20Sopenharmony_ci	 * going to be after this ramrod.
34268c2ecf20Sopenharmony_ci	 */
34278c2ecf20Sopenharmony_ci	if (!o->total_pending_num)
34288c2ecf20Sopenharmony_ci		bnx2x_mcast_refresh_registry_e2(bp, o);
34298c2ecf20Sopenharmony_ci
34308c2ecf20Sopenharmony_ci	/* If CLEAR_ONLY was requested - don't send a ramrod and clear
34318c2ecf20Sopenharmony_ci	 * RAMROD_PENDING status immediately. due to the SET option, it's also
34328c2ecf20Sopenharmony_ci	 * possible that after evaluating the differences there's no need for
34338c2ecf20Sopenharmony_ci	 * a ramrod. In that case, we can skip it as well.
34348c2ecf20Sopenharmony_ci	 */
34358c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags) || !cnt) {
34368c2ecf20Sopenharmony_ci		raw->clear_pending(raw);
34378c2ecf20Sopenharmony_ci		return 0;
34388c2ecf20Sopenharmony_ci	} else {
34398c2ecf20Sopenharmony_ci		/* No need for an explicit memory barrier here as long as we
34408c2ecf20Sopenharmony_ci		 * ensure the ordering of writing to the SPQ element
34418c2ecf20Sopenharmony_ci		 * and updating of the SPQ producer which involves a memory
34428c2ecf20Sopenharmony_ci		 * read. If the memory read is removed we will have to put a
34438c2ecf20Sopenharmony_ci		 * full memory barrier there (inside bnx2x_sp_post()).
34448c2ecf20Sopenharmony_ci		 */
34458c2ecf20Sopenharmony_ci
34468c2ecf20Sopenharmony_ci		/* Send a ramrod */
34478c2ecf20Sopenharmony_ci		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_MULTICAST_RULES,
34488c2ecf20Sopenharmony_ci				   raw->cid, U64_HI(raw->rdata_mapping),
34498c2ecf20Sopenharmony_ci				   U64_LO(raw->rdata_mapping),
34508c2ecf20Sopenharmony_ci				   ETH_CONNECTION_TYPE);
34518c2ecf20Sopenharmony_ci		if (rc)
34528c2ecf20Sopenharmony_ci			return rc;
34538c2ecf20Sopenharmony_ci
34548c2ecf20Sopenharmony_ci		/* Ramrod completion is pending */
34558c2ecf20Sopenharmony_ci		return 1;
34568c2ecf20Sopenharmony_ci	}
34578c2ecf20Sopenharmony_ci}
34588c2ecf20Sopenharmony_ci
34598c2ecf20Sopenharmony_cistatic int bnx2x_mcast_validate_e1h(struct bnx2x *bp,
34608c2ecf20Sopenharmony_ci				    struct bnx2x_mcast_ramrod_params *p,
34618c2ecf20Sopenharmony_ci				    enum bnx2x_mcast_cmd cmd)
34628c2ecf20Sopenharmony_ci{
34638c2ecf20Sopenharmony_ci	if (cmd == BNX2X_MCAST_CMD_SET) {
34648c2ecf20Sopenharmony_ci		BNX2X_ERR("Can't use `set' command on e1h!\n");
34658c2ecf20Sopenharmony_ci		return -EINVAL;
34668c2ecf20Sopenharmony_ci	}
34678c2ecf20Sopenharmony_ci
34688c2ecf20Sopenharmony_ci	/* Mark, that there is a work to do */
34698c2ecf20Sopenharmony_ci	if ((cmd == BNX2X_MCAST_CMD_DEL) || (cmd == BNX2X_MCAST_CMD_RESTORE))
34708c2ecf20Sopenharmony_ci		p->mcast_list_len = 1;
34718c2ecf20Sopenharmony_ci
34728c2ecf20Sopenharmony_ci	return 0;
34738c2ecf20Sopenharmony_ci}
34748c2ecf20Sopenharmony_ci
34758c2ecf20Sopenharmony_cistatic void bnx2x_mcast_revert_e1h(struct bnx2x *bp,
34768c2ecf20Sopenharmony_ci				       struct bnx2x_mcast_ramrod_params *p,
34778c2ecf20Sopenharmony_ci				       int old_num_bins,
34788c2ecf20Sopenharmony_ci				       enum bnx2x_mcast_cmd cmd)
34798c2ecf20Sopenharmony_ci{
34808c2ecf20Sopenharmony_ci	/* Do nothing */
34818c2ecf20Sopenharmony_ci}
34828c2ecf20Sopenharmony_ci
34838c2ecf20Sopenharmony_ci#define BNX2X_57711_SET_MC_FILTER(filter, bit) \
34848c2ecf20Sopenharmony_cido { \
34858c2ecf20Sopenharmony_ci	(filter)[(bit) >> 5] |= (1 << ((bit) & 0x1f)); \
34868c2ecf20Sopenharmony_ci} while (0)
34878c2ecf20Sopenharmony_ci
34888c2ecf20Sopenharmony_cistatic inline void bnx2x_mcast_hdl_add_e1h(struct bnx2x *bp,
34898c2ecf20Sopenharmony_ci					   struct bnx2x_mcast_obj *o,
34908c2ecf20Sopenharmony_ci					   struct bnx2x_mcast_ramrod_params *p,
34918c2ecf20Sopenharmony_ci					   u32 *mc_filter)
34928c2ecf20Sopenharmony_ci{
34938c2ecf20Sopenharmony_ci	struct bnx2x_mcast_list_elem *mlist_pos;
34948c2ecf20Sopenharmony_ci	int bit;
34958c2ecf20Sopenharmony_ci
34968c2ecf20Sopenharmony_ci	list_for_each_entry(mlist_pos, &p->mcast_list, link) {
34978c2ecf20Sopenharmony_ci		bit = bnx2x_mcast_bin_from_mac(mlist_pos->mac);
34988c2ecf20Sopenharmony_ci		BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
34998c2ecf20Sopenharmony_ci
35008c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC, bin %d\n",
35018c2ecf20Sopenharmony_ci		   mlist_pos->mac, bit);
35028c2ecf20Sopenharmony_ci
35038c2ecf20Sopenharmony_ci		/* bookkeeping... */
35048c2ecf20Sopenharmony_ci		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec,
35058c2ecf20Sopenharmony_ci				  bit);
35068c2ecf20Sopenharmony_ci	}
35078c2ecf20Sopenharmony_ci}
35088c2ecf20Sopenharmony_ci
35098c2ecf20Sopenharmony_cistatic inline void bnx2x_mcast_hdl_restore_e1h(struct bnx2x *bp,
35108c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
35118c2ecf20Sopenharmony_ci	u32 *mc_filter)
35128c2ecf20Sopenharmony_ci{
35138c2ecf20Sopenharmony_ci	int bit;
35148c2ecf20Sopenharmony_ci
35158c2ecf20Sopenharmony_ci	for (bit = bnx2x_mcast_get_next_bin(o, 0);
35168c2ecf20Sopenharmony_ci	     bit >= 0;
35178c2ecf20Sopenharmony_ci	     bit = bnx2x_mcast_get_next_bin(o, bit + 1)) {
35188c2ecf20Sopenharmony_ci		BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
35198c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "About to set bin %d\n", bit);
35208c2ecf20Sopenharmony_ci	}
35218c2ecf20Sopenharmony_ci}
35228c2ecf20Sopenharmony_ci
35238c2ecf20Sopenharmony_ci/* On 57711 we write the multicast MACs' approximate match
35248c2ecf20Sopenharmony_ci * table by directly into the TSTORM's internal RAM. So we don't
35258c2ecf20Sopenharmony_ci * really need to handle any tricks to make it work.
35268c2ecf20Sopenharmony_ci */
35278c2ecf20Sopenharmony_cistatic int bnx2x_mcast_setup_e1h(struct bnx2x *bp,
35288c2ecf20Sopenharmony_ci				 struct bnx2x_mcast_ramrod_params *p,
35298c2ecf20Sopenharmony_ci				 enum bnx2x_mcast_cmd cmd)
35308c2ecf20Sopenharmony_ci{
35318c2ecf20Sopenharmony_ci	int i;
35328c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o = p->mcast_obj;
35338c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *r = &o->raw;
35348c2ecf20Sopenharmony_ci
35358c2ecf20Sopenharmony_ci	/* If CLEAR_ONLY has been requested - clear the registry
35368c2ecf20Sopenharmony_ci	 * and clear a pending bit.
35378c2ecf20Sopenharmony_ci	 */
35388c2ecf20Sopenharmony_ci	if (!test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
35398c2ecf20Sopenharmony_ci		u32 mc_filter[MC_HASH_SIZE] = {0};
35408c2ecf20Sopenharmony_ci
35418c2ecf20Sopenharmony_ci		/* Set the multicast filter bits before writing it into
35428c2ecf20Sopenharmony_ci		 * the internal memory.
35438c2ecf20Sopenharmony_ci		 */
35448c2ecf20Sopenharmony_ci		switch (cmd) {
35458c2ecf20Sopenharmony_ci		case BNX2X_MCAST_CMD_ADD:
35468c2ecf20Sopenharmony_ci			bnx2x_mcast_hdl_add_e1h(bp, o, p, mc_filter);
35478c2ecf20Sopenharmony_ci			break;
35488c2ecf20Sopenharmony_ci
35498c2ecf20Sopenharmony_ci		case BNX2X_MCAST_CMD_DEL:
35508c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_SP,
35518c2ecf20Sopenharmony_ci			   "Invalidating multicast MACs configuration\n");
35528c2ecf20Sopenharmony_ci
35538c2ecf20Sopenharmony_ci			/* clear the registry */
35548c2ecf20Sopenharmony_ci			memset(o->registry.aprox_match.vec, 0,
35558c2ecf20Sopenharmony_ci			       sizeof(o->registry.aprox_match.vec));
35568c2ecf20Sopenharmony_ci			break;
35578c2ecf20Sopenharmony_ci
35588c2ecf20Sopenharmony_ci		case BNX2X_MCAST_CMD_RESTORE:
35598c2ecf20Sopenharmony_ci			bnx2x_mcast_hdl_restore_e1h(bp, o, p, mc_filter);
35608c2ecf20Sopenharmony_ci			break;
35618c2ecf20Sopenharmony_ci
35628c2ecf20Sopenharmony_ci		default:
35638c2ecf20Sopenharmony_ci			BNX2X_ERR("Unknown command: %d\n", cmd);
35648c2ecf20Sopenharmony_ci			return -EINVAL;
35658c2ecf20Sopenharmony_ci		}
35668c2ecf20Sopenharmony_ci
35678c2ecf20Sopenharmony_ci		/* Set the mcast filter in the internal memory */
35688c2ecf20Sopenharmony_ci		for (i = 0; i < MC_HASH_SIZE; i++)
35698c2ecf20Sopenharmony_ci			REG_WR(bp, MC_HASH_OFFSET(bp, i), mc_filter[i]);
35708c2ecf20Sopenharmony_ci	} else
35718c2ecf20Sopenharmony_ci		/* clear the registry */
35728c2ecf20Sopenharmony_ci		memset(o->registry.aprox_match.vec, 0,
35738c2ecf20Sopenharmony_ci		       sizeof(o->registry.aprox_match.vec));
35748c2ecf20Sopenharmony_ci
35758c2ecf20Sopenharmony_ci	/* We are done */
35768c2ecf20Sopenharmony_ci	r->clear_pending(r);
35778c2ecf20Sopenharmony_ci
35788c2ecf20Sopenharmony_ci	return 0;
35798c2ecf20Sopenharmony_ci}
35808c2ecf20Sopenharmony_ci
35818c2ecf20Sopenharmony_cistatic int bnx2x_mcast_validate_e1(struct bnx2x *bp,
35828c2ecf20Sopenharmony_ci				   struct bnx2x_mcast_ramrod_params *p,
35838c2ecf20Sopenharmony_ci				   enum bnx2x_mcast_cmd cmd)
35848c2ecf20Sopenharmony_ci{
35858c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o = p->mcast_obj;
35868c2ecf20Sopenharmony_ci	int reg_sz = o->get_registry_size(o);
35878c2ecf20Sopenharmony_ci
35888c2ecf20Sopenharmony_ci	if (cmd == BNX2X_MCAST_CMD_SET) {
35898c2ecf20Sopenharmony_ci		BNX2X_ERR("Can't use `set' command on e1!\n");
35908c2ecf20Sopenharmony_ci		return -EINVAL;
35918c2ecf20Sopenharmony_ci	}
35928c2ecf20Sopenharmony_ci
35938c2ecf20Sopenharmony_ci	switch (cmd) {
35948c2ecf20Sopenharmony_ci	/* DEL command deletes all currently configured MACs */
35958c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_DEL:
35968c2ecf20Sopenharmony_ci		o->set_registry_size(o, 0);
35978c2ecf20Sopenharmony_ci		fallthrough;
35988c2ecf20Sopenharmony_ci
35998c2ecf20Sopenharmony_ci	/* RESTORE command will restore the entire multicast configuration */
36008c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_RESTORE:
36018c2ecf20Sopenharmony_ci		p->mcast_list_len = reg_sz;
36028c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "Command %d, p->mcast_list_len=%d\n",
36038c2ecf20Sopenharmony_ci		   cmd, p->mcast_list_len);
36048c2ecf20Sopenharmony_ci		break;
36058c2ecf20Sopenharmony_ci
36068c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_ADD:
36078c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_CONT:
36088c2ecf20Sopenharmony_ci		/* Multicast MACs on 57710 are configured as unicast MACs and
36098c2ecf20Sopenharmony_ci		 * there is only a limited number of CAM entries for that
36108c2ecf20Sopenharmony_ci		 * matter.
36118c2ecf20Sopenharmony_ci		 */
36128c2ecf20Sopenharmony_ci		if (p->mcast_list_len > o->max_cmd_len) {
36138c2ecf20Sopenharmony_ci			BNX2X_ERR("Can't configure more than %d multicast MACs on 57710\n",
36148c2ecf20Sopenharmony_ci				  o->max_cmd_len);
36158c2ecf20Sopenharmony_ci			return -EINVAL;
36168c2ecf20Sopenharmony_ci		}
36178c2ecf20Sopenharmony_ci		/* Every configured MAC should be cleared if DEL command is
36188c2ecf20Sopenharmony_ci		 * called. Only the last ADD command is relevant as long as
36198c2ecf20Sopenharmony_ci		 * every ADD commands overrides the previous configuration.
36208c2ecf20Sopenharmony_ci		 */
36218c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
36228c2ecf20Sopenharmony_ci		if (p->mcast_list_len > 0)
36238c2ecf20Sopenharmony_ci			o->set_registry_size(o, p->mcast_list_len);
36248c2ecf20Sopenharmony_ci
36258c2ecf20Sopenharmony_ci		break;
36268c2ecf20Sopenharmony_ci
36278c2ecf20Sopenharmony_ci	default:
36288c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown command: %d\n", cmd);
36298c2ecf20Sopenharmony_ci		return -EINVAL;
36308c2ecf20Sopenharmony_ci	}
36318c2ecf20Sopenharmony_ci
36328c2ecf20Sopenharmony_ci	/* We want to ensure that commands are executed one by one for 57710.
36338c2ecf20Sopenharmony_ci	 * Therefore each none-empty command will consume o->max_cmd_len.
36348c2ecf20Sopenharmony_ci	 */
36358c2ecf20Sopenharmony_ci	if (p->mcast_list_len)
36368c2ecf20Sopenharmony_ci		o->total_pending_num += o->max_cmd_len;
36378c2ecf20Sopenharmony_ci
36388c2ecf20Sopenharmony_ci	return 0;
36398c2ecf20Sopenharmony_ci}
36408c2ecf20Sopenharmony_ci
36418c2ecf20Sopenharmony_cistatic void bnx2x_mcast_revert_e1(struct bnx2x *bp,
36428c2ecf20Sopenharmony_ci				      struct bnx2x_mcast_ramrod_params *p,
36438c2ecf20Sopenharmony_ci				   int old_num_macs,
36448c2ecf20Sopenharmony_ci				   enum bnx2x_mcast_cmd cmd)
36458c2ecf20Sopenharmony_ci{
36468c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o = p->mcast_obj;
36478c2ecf20Sopenharmony_ci
36488c2ecf20Sopenharmony_ci	o->set_registry_size(o, old_num_macs);
36498c2ecf20Sopenharmony_ci
36508c2ecf20Sopenharmony_ci	/* If current command hasn't been handled yet and we are
36518c2ecf20Sopenharmony_ci	 * here means that it's meant to be dropped and we have to
36528c2ecf20Sopenharmony_ci	 * update the number of outstanding MACs accordingly.
36538c2ecf20Sopenharmony_ci	 */
36548c2ecf20Sopenharmony_ci	if (p->mcast_list_len)
36558c2ecf20Sopenharmony_ci		o->total_pending_num -= o->max_cmd_len;
36568c2ecf20Sopenharmony_ci}
36578c2ecf20Sopenharmony_ci
36588c2ecf20Sopenharmony_cistatic void bnx2x_mcast_set_one_rule_e1(struct bnx2x *bp,
36598c2ecf20Sopenharmony_ci					struct bnx2x_mcast_obj *o, int idx,
36608c2ecf20Sopenharmony_ci					union bnx2x_mcast_config_data *cfg_data,
36618c2ecf20Sopenharmony_ci					enum bnx2x_mcast_cmd cmd)
36628c2ecf20Sopenharmony_ci{
36638c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *r = &o->raw;
36648c2ecf20Sopenharmony_ci	struct mac_configuration_cmd *data =
36658c2ecf20Sopenharmony_ci		(struct mac_configuration_cmd *)(r->rdata);
36668c2ecf20Sopenharmony_ci
36678c2ecf20Sopenharmony_ci	/* copy mac */
36688c2ecf20Sopenharmony_ci	if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE)) {
36698c2ecf20Sopenharmony_ci		bnx2x_set_fw_mac_addr(&data->config_table[idx].msb_mac_addr,
36708c2ecf20Sopenharmony_ci				      &data->config_table[idx].middle_mac_addr,
36718c2ecf20Sopenharmony_ci				      &data->config_table[idx].lsb_mac_addr,
36728c2ecf20Sopenharmony_ci				      cfg_data->mac);
36738c2ecf20Sopenharmony_ci
36748c2ecf20Sopenharmony_ci		data->config_table[idx].vlan_id = 0;
36758c2ecf20Sopenharmony_ci		data->config_table[idx].pf_id = r->func_id;
36768c2ecf20Sopenharmony_ci		data->config_table[idx].clients_bit_vector =
36778c2ecf20Sopenharmony_ci			cpu_to_le32(1 << r->cl_id);
36788c2ecf20Sopenharmony_ci
36798c2ecf20Sopenharmony_ci		SET_FLAG(data->config_table[idx].flags,
36808c2ecf20Sopenharmony_ci			 MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
36818c2ecf20Sopenharmony_ci			 T_ETH_MAC_COMMAND_SET);
36828c2ecf20Sopenharmony_ci	}
36838c2ecf20Sopenharmony_ci}
36848c2ecf20Sopenharmony_ci
36858c2ecf20Sopenharmony_ci/**
36868c2ecf20Sopenharmony_ci * bnx2x_mcast_set_rdata_hdr_e1  - set header values in mac_configuration_cmd
36878c2ecf20Sopenharmony_ci *
36888c2ecf20Sopenharmony_ci * @bp:		device handle
36898c2ecf20Sopenharmony_ci * @p:		ramrod parameters
36908c2ecf20Sopenharmony_ci * @len:	number of rules to handle
36918c2ecf20Sopenharmony_ci */
36928c2ecf20Sopenharmony_cistatic inline void bnx2x_mcast_set_rdata_hdr_e1(struct bnx2x *bp,
36938c2ecf20Sopenharmony_ci					struct bnx2x_mcast_ramrod_params *p,
36948c2ecf20Sopenharmony_ci					u8 len)
36958c2ecf20Sopenharmony_ci{
36968c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
36978c2ecf20Sopenharmony_ci	struct mac_configuration_cmd *data =
36988c2ecf20Sopenharmony_ci		(struct mac_configuration_cmd *)(r->rdata);
36998c2ecf20Sopenharmony_ci
37008c2ecf20Sopenharmony_ci	u8 offset = (CHIP_REV_IS_SLOW(bp) ?
37018c2ecf20Sopenharmony_ci		     BNX2X_MAX_EMUL_MULTI*(1 + r->func_id) :
37028c2ecf20Sopenharmony_ci		     BNX2X_MAX_MULTICAST*(1 + r->func_id));
37038c2ecf20Sopenharmony_ci
37048c2ecf20Sopenharmony_ci	data->hdr.offset = offset;
37058c2ecf20Sopenharmony_ci	data->hdr.client_id = cpu_to_le16(0xff);
37068c2ecf20Sopenharmony_ci	data->hdr.echo = cpu_to_le32((r->cid & BNX2X_SWCID_MASK) |
37078c2ecf20Sopenharmony_ci				     (BNX2X_FILTER_MCAST_PENDING <<
37088c2ecf20Sopenharmony_ci				      BNX2X_SWCID_SHIFT));
37098c2ecf20Sopenharmony_ci	data->hdr.length = len;
37108c2ecf20Sopenharmony_ci}
37118c2ecf20Sopenharmony_ci
37128c2ecf20Sopenharmony_ci/**
37138c2ecf20Sopenharmony_ci * bnx2x_mcast_handle_restore_cmd_e1 - restore command for 57710
37148c2ecf20Sopenharmony_ci *
37158c2ecf20Sopenharmony_ci * @bp:		device handle
37168c2ecf20Sopenharmony_ci * @o:		multicast info
37178c2ecf20Sopenharmony_ci * @start_idx:	index in the registry to start from
37188c2ecf20Sopenharmony_ci * @rdata_idx:	index in the ramrod data to start from
37198c2ecf20Sopenharmony_ci *
37208c2ecf20Sopenharmony_ci * restore command for 57710 is like all other commands - always a stand alone
37218c2ecf20Sopenharmony_ci * command - start_idx and rdata_idx will always be 0. This function will always
37228c2ecf20Sopenharmony_ci * succeed.
37238c2ecf20Sopenharmony_ci * returns -1 to comply with 57712 variant.
37248c2ecf20Sopenharmony_ci */
37258c2ecf20Sopenharmony_cistatic inline int bnx2x_mcast_handle_restore_cmd_e1(
37268c2ecf20Sopenharmony_ci	struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_idx,
37278c2ecf20Sopenharmony_ci	int *rdata_idx)
37288c2ecf20Sopenharmony_ci{
37298c2ecf20Sopenharmony_ci	struct bnx2x_mcast_mac_elem *elem;
37308c2ecf20Sopenharmony_ci	int i = 0;
37318c2ecf20Sopenharmony_ci	union bnx2x_mcast_config_data cfg_data = {NULL};
37328c2ecf20Sopenharmony_ci
37338c2ecf20Sopenharmony_ci	/* go through the registry and configure the MACs from it. */
37348c2ecf20Sopenharmony_ci	list_for_each_entry(elem, &o->registry.exact_match.macs, link) {
37358c2ecf20Sopenharmony_ci		cfg_data.mac = &elem->mac[0];
37368c2ecf20Sopenharmony_ci		o->set_one_rule(bp, o, i, &cfg_data, BNX2X_MCAST_CMD_RESTORE);
37378c2ecf20Sopenharmony_ci
37388c2ecf20Sopenharmony_ci		i++;
37398c2ecf20Sopenharmony_ci
37408c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
37418c2ecf20Sopenharmony_ci		   cfg_data.mac);
37428c2ecf20Sopenharmony_ci	}
37438c2ecf20Sopenharmony_ci
37448c2ecf20Sopenharmony_ci	*rdata_idx = i;
37458c2ecf20Sopenharmony_ci
37468c2ecf20Sopenharmony_ci	return -1;
37478c2ecf20Sopenharmony_ci}
37488c2ecf20Sopenharmony_ci
37498c2ecf20Sopenharmony_cistatic inline int bnx2x_mcast_handle_pending_cmds_e1(
37508c2ecf20Sopenharmony_ci	struct bnx2x *bp, struct bnx2x_mcast_ramrod_params *p)
37518c2ecf20Sopenharmony_ci{
37528c2ecf20Sopenharmony_ci	struct bnx2x_pending_mcast_cmd *cmd_pos;
37538c2ecf20Sopenharmony_ci	struct bnx2x_mcast_mac_elem *pmac_pos;
37548c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o = p->mcast_obj;
37558c2ecf20Sopenharmony_ci	union bnx2x_mcast_config_data cfg_data = {NULL};
37568c2ecf20Sopenharmony_ci	int cnt = 0;
37578c2ecf20Sopenharmony_ci
37588c2ecf20Sopenharmony_ci	/* If nothing to be done - return */
37598c2ecf20Sopenharmony_ci	if (list_empty(&o->pending_cmds_head))
37608c2ecf20Sopenharmony_ci		return 0;
37618c2ecf20Sopenharmony_ci
37628c2ecf20Sopenharmony_ci	/* Handle the first command */
37638c2ecf20Sopenharmony_ci	cmd_pos = list_first_entry(&o->pending_cmds_head,
37648c2ecf20Sopenharmony_ci				   struct bnx2x_pending_mcast_cmd, link);
37658c2ecf20Sopenharmony_ci
37668c2ecf20Sopenharmony_ci	switch (cmd_pos->type) {
37678c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_ADD:
37688c2ecf20Sopenharmony_ci		list_for_each_entry(pmac_pos, &cmd_pos->data.macs_head, link) {
37698c2ecf20Sopenharmony_ci			cfg_data.mac = &pmac_pos->mac[0];
37708c2ecf20Sopenharmony_ci			o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
37718c2ecf20Sopenharmony_ci
37728c2ecf20Sopenharmony_ci			cnt++;
37738c2ecf20Sopenharmony_ci
37748c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
37758c2ecf20Sopenharmony_ci			   pmac_pos->mac);
37768c2ecf20Sopenharmony_ci		}
37778c2ecf20Sopenharmony_ci		break;
37788c2ecf20Sopenharmony_ci
37798c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_DEL:
37808c2ecf20Sopenharmony_ci		cnt = cmd_pos->data.macs_num;
37818c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "About to delete %d multicast MACs\n", cnt);
37828c2ecf20Sopenharmony_ci		break;
37838c2ecf20Sopenharmony_ci
37848c2ecf20Sopenharmony_ci	case BNX2X_MCAST_CMD_RESTORE:
37858c2ecf20Sopenharmony_ci		o->hdl_restore(bp, o, 0, &cnt);
37868c2ecf20Sopenharmony_ci		break;
37878c2ecf20Sopenharmony_ci
37888c2ecf20Sopenharmony_ci	default:
37898c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
37908c2ecf20Sopenharmony_ci		return -EINVAL;
37918c2ecf20Sopenharmony_ci	}
37928c2ecf20Sopenharmony_ci
37938c2ecf20Sopenharmony_ci	list_del(&cmd_pos->link);
37948c2ecf20Sopenharmony_ci	bnx2x_free_groups(&cmd_pos->group_head);
37958c2ecf20Sopenharmony_ci	kfree(cmd_pos);
37968c2ecf20Sopenharmony_ci
37978c2ecf20Sopenharmony_ci	return cnt;
37988c2ecf20Sopenharmony_ci}
37998c2ecf20Sopenharmony_ci
38008c2ecf20Sopenharmony_ci/**
38018c2ecf20Sopenharmony_ci * bnx2x_get_fw_mac_addr - revert the bnx2x_set_fw_mac_addr().
38028c2ecf20Sopenharmony_ci *
38038c2ecf20Sopenharmony_ci * @fw_hi: address
38048c2ecf20Sopenharmony_ci * @fw_mid: address
38058c2ecf20Sopenharmony_ci * @fw_lo: address
38068c2ecf20Sopenharmony_ci * @mac: mac address
38078c2ecf20Sopenharmony_ci */
38088c2ecf20Sopenharmony_cistatic inline void bnx2x_get_fw_mac_addr(__le16 *fw_hi, __le16 *fw_mid,
38098c2ecf20Sopenharmony_ci					 __le16 *fw_lo, u8 *mac)
38108c2ecf20Sopenharmony_ci{
38118c2ecf20Sopenharmony_ci	mac[1] = ((u8 *)fw_hi)[0];
38128c2ecf20Sopenharmony_ci	mac[0] = ((u8 *)fw_hi)[1];
38138c2ecf20Sopenharmony_ci	mac[3] = ((u8 *)fw_mid)[0];
38148c2ecf20Sopenharmony_ci	mac[2] = ((u8 *)fw_mid)[1];
38158c2ecf20Sopenharmony_ci	mac[5] = ((u8 *)fw_lo)[0];
38168c2ecf20Sopenharmony_ci	mac[4] = ((u8 *)fw_lo)[1];
38178c2ecf20Sopenharmony_ci}
38188c2ecf20Sopenharmony_ci
38198c2ecf20Sopenharmony_ci/**
38208c2ecf20Sopenharmony_ci * bnx2x_mcast_refresh_registry_e1 -
38218c2ecf20Sopenharmony_ci *
38228c2ecf20Sopenharmony_ci * @bp:		device handle
38238c2ecf20Sopenharmony_ci * @o:		multicast info
38248c2ecf20Sopenharmony_ci *
38258c2ecf20Sopenharmony_ci * Check the ramrod data first entry flag to see if it's a DELETE or ADD command
38268c2ecf20Sopenharmony_ci * and update the registry correspondingly: if ADD - allocate a memory and add
38278c2ecf20Sopenharmony_ci * the entries to the registry (list), if DELETE - clear the registry and free
38288c2ecf20Sopenharmony_ci * the memory.
38298c2ecf20Sopenharmony_ci */
38308c2ecf20Sopenharmony_cistatic inline int bnx2x_mcast_refresh_registry_e1(struct bnx2x *bp,
38318c2ecf20Sopenharmony_ci						  struct bnx2x_mcast_obj *o)
38328c2ecf20Sopenharmony_ci{
38338c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
38348c2ecf20Sopenharmony_ci	struct bnx2x_mcast_mac_elem *elem;
38358c2ecf20Sopenharmony_ci	struct mac_configuration_cmd *data =
38368c2ecf20Sopenharmony_ci			(struct mac_configuration_cmd *)(raw->rdata);
38378c2ecf20Sopenharmony_ci
38388c2ecf20Sopenharmony_ci	/* If first entry contains a SET bit - the command was ADD,
38398c2ecf20Sopenharmony_ci	 * otherwise - DEL_ALL
38408c2ecf20Sopenharmony_ci	 */
38418c2ecf20Sopenharmony_ci	if (GET_FLAG(data->config_table[0].flags,
38428c2ecf20Sopenharmony_ci			MAC_CONFIGURATION_ENTRY_ACTION_TYPE)) {
38438c2ecf20Sopenharmony_ci		int i, len = data->hdr.length;
38448c2ecf20Sopenharmony_ci
38458c2ecf20Sopenharmony_ci		/* Break if it was a RESTORE command */
38468c2ecf20Sopenharmony_ci		if (!list_empty(&o->registry.exact_match.macs))
38478c2ecf20Sopenharmony_ci			return 0;
38488c2ecf20Sopenharmony_ci
38498c2ecf20Sopenharmony_ci		elem = kcalloc(len, sizeof(*elem), GFP_ATOMIC);
38508c2ecf20Sopenharmony_ci		if (!elem) {
38518c2ecf20Sopenharmony_ci			BNX2X_ERR("Failed to allocate registry memory\n");
38528c2ecf20Sopenharmony_ci			return -ENOMEM;
38538c2ecf20Sopenharmony_ci		}
38548c2ecf20Sopenharmony_ci
38558c2ecf20Sopenharmony_ci		for (i = 0; i < len; i++, elem++) {
38568c2ecf20Sopenharmony_ci			bnx2x_get_fw_mac_addr(
38578c2ecf20Sopenharmony_ci				&data->config_table[i].msb_mac_addr,
38588c2ecf20Sopenharmony_ci				&data->config_table[i].middle_mac_addr,
38598c2ecf20Sopenharmony_ci				&data->config_table[i].lsb_mac_addr,
38608c2ecf20Sopenharmony_ci				elem->mac);
38618c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_SP, "Adding registry entry for [%pM]\n",
38628c2ecf20Sopenharmony_ci			   elem->mac);
38638c2ecf20Sopenharmony_ci			list_add_tail(&elem->link,
38648c2ecf20Sopenharmony_ci				      &o->registry.exact_match.macs);
38658c2ecf20Sopenharmony_ci		}
38668c2ecf20Sopenharmony_ci	} else {
38678c2ecf20Sopenharmony_ci		elem = list_first_entry(&o->registry.exact_match.macs,
38688c2ecf20Sopenharmony_ci					struct bnx2x_mcast_mac_elem, link);
38698c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "Deleting a registry\n");
38708c2ecf20Sopenharmony_ci		kfree(elem);
38718c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&o->registry.exact_match.macs);
38728c2ecf20Sopenharmony_ci	}
38738c2ecf20Sopenharmony_ci
38748c2ecf20Sopenharmony_ci	return 0;
38758c2ecf20Sopenharmony_ci}
38768c2ecf20Sopenharmony_ci
38778c2ecf20Sopenharmony_cistatic int bnx2x_mcast_setup_e1(struct bnx2x *bp,
38788c2ecf20Sopenharmony_ci				struct bnx2x_mcast_ramrod_params *p,
38798c2ecf20Sopenharmony_ci				enum bnx2x_mcast_cmd cmd)
38808c2ecf20Sopenharmony_ci{
38818c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o = p->mcast_obj;
38828c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *raw = &o->raw;
38838c2ecf20Sopenharmony_ci	struct mac_configuration_cmd *data =
38848c2ecf20Sopenharmony_ci		(struct mac_configuration_cmd *)(raw->rdata);
38858c2ecf20Sopenharmony_ci	int cnt = 0, i, rc;
38868c2ecf20Sopenharmony_ci
38878c2ecf20Sopenharmony_ci	/* Reset the ramrod data buffer */
38888c2ecf20Sopenharmony_ci	memset(data, 0, sizeof(*data));
38898c2ecf20Sopenharmony_ci
38908c2ecf20Sopenharmony_ci	/* First set all entries as invalid */
38918c2ecf20Sopenharmony_ci	for (i = 0; i < o->max_cmd_len ; i++)
38928c2ecf20Sopenharmony_ci		SET_FLAG(data->config_table[i].flags,
38938c2ecf20Sopenharmony_ci			 MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
38948c2ecf20Sopenharmony_ci			 T_ETH_MAC_COMMAND_INVALIDATE);
38958c2ecf20Sopenharmony_ci
38968c2ecf20Sopenharmony_ci	/* Handle pending commands first */
38978c2ecf20Sopenharmony_ci	cnt = bnx2x_mcast_handle_pending_cmds_e1(bp, p);
38988c2ecf20Sopenharmony_ci
38998c2ecf20Sopenharmony_ci	/* If there are no more pending commands - clear SCHEDULED state */
39008c2ecf20Sopenharmony_ci	if (list_empty(&o->pending_cmds_head))
39018c2ecf20Sopenharmony_ci		o->clear_sched(o);
39028c2ecf20Sopenharmony_ci
39038c2ecf20Sopenharmony_ci	/* The below may be true iff there were no pending commands */
39048c2ecf20Sopenharmony_ci	if (!cnt)
39058c2ecf20Sopenharmony_ci		cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, 0);
39068c2ecf20Sopenharmony_ci
39078c2ecf20Sopenharmony_ci	/* For 57710 every command has o->max_cmd_len length to ensure that
39088c2ecf20Sopenharmony_ci	 * commands are done one at a time.
39098c2ecf20Sopenharmony_ci	 */
39108c2ecf20Sopenharmony_ci	o->total_pending_num -= o->max_cmd_len;
39118c2ecf20Sopenharmony_ci
39128c2ecf20Sopenharmony_ci	/* send a ramrod */
39138c2ecf20Sopenharmony_ci
39148c2ecf20Sopenharmony_ci	WARN_ON(cnt > o->max_cmd_len);
39158c2ecf20Sopenharmony_ci
39168c2ecf20Sopenharmony_ci	/* Set ramrod header (in particular, a number of entries to update) */
39178c2ecf20Sopenharmony_ci	bnx2x_mcast_set_rdata_hdr_e1(bp, p, (u8)cnt);
39188c2ecf20Sopenharmony_ci
39198c2ecf20Sopenharmony_ci	/* update a registry: we need the registry contents to be always up
39208c2ecf20Sopenharmony_ci	 * to date in order to be able to execute a RESTORE opcode. Here
39218c2ecf20Sopenharmony_ci	 * we use the fact that for 57710 we sent one command at a time
39228c2ecf20Sopenharmony_ci	 * hence we may take the registry update out of the command handling
39238c2ecf20Sopenharmony_ci	 * and do it in a simpler way here.
39248c2ecf20Sopenharmony_ci	 */
39258c2ecf20Sopenharmony_ci	rc = bnx2x_mcast_refresh_registry_e1(bp, o);
39268c2ecf20Sopenharmony_ci	if (rc)
39278c2ecf20Sopenharmony_ci		return rc;
39288c2ecf20Sopenharmony_ci
39298c2ecf20Sopenharmony_ci	/* If CLEAR_ONLY was requested - don't send a ramrod and clear
39308c2ecf20Sopenharmony_ci	 * RAMROD_PENDING status immediately.
39318c2ecf20Sopenharmony_ci	 */
39328c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
39338c2ecf20Sopenharmony_ci		raw->clear_pending(raw);
39348c2ecf20Sopenharmony_ci		return 0;
39358c2ecf20Sopenharmony_ci	} else {
39368c2ecf20Sopenharmony_ci		/* No need for an explicit memory barrier here as long as we
39378c2ecf20Sopenharmony_ci		 * ensure the ordering of writing to the SPQ element
39388c2ecf20Sopenharmony_ci		 * and updating of the SPQ producer which involves a memory
39398c2ecf20Sopenharmony_ci		 * read. If the memory read is removed we will have to put a
39408c2ecf20Sopenharmony_ci		 * full memory barrier there (inside bnx2x_sp_post()).
39418c2ecf20Sopenharmony_ci		 */
39428c2ecf20Sopenharmony_ci
39438c2ecf20Sopenharmony_ci		/* Send a ramrod */
39448c2ecf20Sopenharmony_ci		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, raw->cid,
39458c2ecf20Sopenharmony_ci				   U64_HI(raw->rdata_mapping),
39468c2ecf20Sopenharmony_ci				   U64_LO(raw->rdata_mapping),
39478c2ecf20Sopenharmony_ci				   ETH_CONNECTION_TYPE);
39488c2ecf20Sopenharmony_ci		if (rc)
39498c2ecf20Sopenharmony_ci			return rc;
39508c2ecf20Sopenharmony_ci
39518c2ecf20Sopenharmony_ci		/* Ramrod completion is pending */
39528c2ecf20Sopenharmony_ci		return 1;
39538c2ecf20Sopenharmony_ci	}
39548c2ecf20Sopenharmony_ci}
39558c2ecf20Sopenharmony_ci
39568c2ecf20Sopenharmony_cistatic int bnx2x_mcast_get_registry_size_exact(struct bnx2x_mcast_obj *o)
39578c2ecf20Sopenharmony_ci{
39588c2ecf20Sopenharmony_ci	return o->registry.exact_match.num_macs_set;
39598c2ecf20Sopenharmony_ci}
39608c2ecf20Sopenharmony_ci
39618c2ecf20Sopenharmony_cistatic int bnx2x_mcast_get_registry_size_aprox(struct bnx2x_mcast_obj *o)
39628c2ecf20Sopenharmony_ci{
39638c2ecf20Sopenharmony_ci	return o->registry.aprox_match.num_bins_set;
39648c2ecf20Sopenharmony_ci}
39658c2ecf20Sopenharmony_ci
39668c2ecf20Sopenharmony_cistatic void bnx2x_mcast_set_registry_size_exact(struct bnx2x_mcast_obj *o,
39678c2ecf20Sopenharmony_ci						int n)
39688c2ecf20Sopenharmony_ci{
39698c2ecf20Sopenharmony_ci	o->registry.exact_match.num_macs_set = n;
39708c2ecf20Sopenharmony_ci}
39718c2ecf20Sopenharmony_ci
39728c2ecf20Sopenharmony_cistatic void bnx2x_mcast_set_registry_size_aprox(struct bnx2x_mcast_obj *o,
39738c2ecf20Sopenharmony_ci						int n)
39748c2ecf20Sopenharmony_ci{
39758c2ecf20Sopenharmony_ci	o->registry.aprox_match.num_bins_set = n;
39768c2ecf20Sopenharmony_ci}
39778c2ecf20Sopenharmony_ci
39788c2ecf20Sopenharmony_ciint bnx2x_config_mcast(struct bnx2x *bp,
39798c2ecf20Sopenharmony_ci		       struct bnx2x_mcast_ramrod_params *p,
39808c2ecf20Sopenharmony_ci		       enum bnx2x_mcast_cmd cmd)
39818c2ecf20Sopenharmony_ci{
39828c2ecf20Sopenharmony_ci	struct bnx2x_mcast_obj *o = p->mcast_obj;
39838c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *r = &o->raw;
39848c2ecf20Sopenharmony_ci	int rc = 0, old_reg_size;
39858c2ecf20Sopenharmony_ci
39868c2ecf20Sopenharmony_ci	/* This is needed to recover number of currently configured mcast macs
39878c2ecf20Sopenharmony_ci	 * in case of failure.
39888c2ecf20Sopenharmony_ci	 */
39898c2ecf20Sopenharmony_ci	old_reg_size = o->get_registry_size(o);
39908c2ecf20Sopenharmony_ci
39918c2ecf20Sopenharmony_ci	/* Do some calculations and checks */
39928c2ecf20Sopenharmony_ci	rc = o->validate(bp, p, cmd);
39938c2ecf20Sopenharmony_ci	if (rc)
39948c2ecf20Sopenharmony_ci		return rc;
39958c2ecf20Sopenharmony_ci
39968c2ecf20Sopenharmony_ci	/* Return if there is no work to do */
39978c2ecf20Sopenharmony_ci	if ((!p->mcast_list_len) && (!o->check_sched(o)))
39988c2ecf20Sopenharmony_ci		return 0;
39998c2ecf20Sopenharmony_ci
40008c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "o->total_pending_num=%d p->mcast_list_len=%d o->max_cmd_len=%d\n",
40018c2ecf20Sopenharmony_ci	   o->total_pending_num, p->mcast_list_len, o->max_cmd_len);
40028c2ecf20Sopenharmony_ci
40038c2ecf20Sopenharmony_ci	/* Enqueue the current command to the pending list if we can't complete
40048c2ecf20Sopenharmony_ci	 * it in the current iteration
40058c2ecf20Sopenharmony_ci	 */
40068c2ecf20Sopenharmony_ci	if (r->check_pending(r) ||
40078c2ecf20Sopenharmony_ci	    ((o->max_cmd_len > 0) && (o->total_pending_num > o->max_cmd_len))) {
40088c2ecf20Sopenharmony_ci		rc = o->enqueue_cmd(bp, p->mcast_obj, p, cmd);
40098c2ecf20Sopenharmony_ci		if (rc < 0)
40108c2ecf20Sopenharmony_ci			goto error_exit1;
40118c2ecf20Sopenharmony_ci
40128c2ecf20Sopenharmony_ci		/* As long as the current command is in a command list we
40138c2ecf20Sopenharmony_ci		 * don't need to handle it separately.
40148c2ecf20Sopenharmony_ci		 */
40158c2ecf20Sopenharmony_ci		p->mcast_list_len = 0;
40168c2ecf20Sopenharmony_ci	}
40178c2ecf20Sopenharmony_ci
40188c2ecf20Sopenharmony_ci	if (!r->check_pending(r)) {
40198c2ecf20Sopenharmony_ci
40208c2ecf20Sopenharmony_ci		/* Set 'pending' state */
40218c2ecf20Sopenharmony_ci		r->set_pending(r);
40228c2ecf20Sopenharmony_ci
40238c2ecf20Sopenharmony_ci		/* Configure the new classification in the chip */
40248c2ecf20Sopenharmony_ci		rc = o->config_mcast(bp, p, cmd);
40258c2ecf20Sopenharmony_ci		if (rc < 0)
40268c2ecf20Sopenharmony_ci			goto error_exit2;
40278c2ecf20Sopenharmony_ci
40288c2ecf20Sopenharmony_ci		/* Wait for a ramrod completion if was requested */
40298c2ecf20Sopenharmony_ci		if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
40308c2ecf20Sopenharmony_ci			rc = o->wait_comp(bp, o);
40318c2ecf20Sopenharmony_ci	}
40328c2ecf20Sopenharmony_ci
40338c2ecf20Sopenharmony_ci	return rc;
40348c2ecf20Sopenharmony_ci
40358c2ecf20Sopenharmony_cierror_exit2:
40368c2ecf20Sopenharmony_ci	r->clear_pending(r);
40378c2ecf20Sopenharmony_ci
40388c2ecf20Sopenharmony_cierror_exit1:
40398c2ecf20Sopenharmony_ci	o->revert(bp, p, old_reg_size, cmd);
40408c2ecf20Sopenharmony_ci
40418c2ecf20Sopenharmony_ci	return rc;
40428c2ecf20Sopenharmony_ci}
40438c2ecf20Sopenharmony_ci
40448c2ecf20Sopenharmony_cistatic void bnx2x_mcast_clear_sched(struct bnx2x_mcast_obj *o)
40458c2ecf20Sopenharmony_ci{
40468c2ecf20Sopenharmony_ci	smp_mb__before_atomic();
40478c2ecf20Sopenharmony_ci	clear_bit(o->sched_state, o->raw.pstate);
40488c2ecf20Sopenharmony_ci	smp_mb__after_atomic();
40498c2ecf20Sopenharmony_ci}
40508c2ecf20Sopenharmony_ci
40518c2ecf20Sopenharmony_cistatic void bnx2x_mcast_set_sched(struct bnx2x_mcast_obj *o)
40528c2ecf20Sopenharmony_ci{
40538c2ecf20Sopenharmony_ci	smp_mb__before_atomic();
40548c2ecf20Sopenharmony_ci	set_bit(o->sched_state, o->raw.pstate);
40558c2ecf20Sopenharmony_ci	smp_mb__after_atomic();
40568c2ecf20Sopenharmony_ci}
40578c2ecf20Sopenharmony_ci
40588c2ecf20Sopenharmony_cistatic bool bnx2x_mcast_check_sched(struct bnx2x_mcast_obj *o)
40598c2ecf20Sopenharmony_ci{
40608c2ecf20Sopenharmony_ci	return !!test_bit(o->sched_state, o->raw.pstate);
40618c2ecf20Sopenharmony_ci}
40628c2ecf20Sopenharmony_ci
40638c2ecf20Sopenharmony_cistatic bool bnx2x_mcast_check_pending(struct bnx2x_mcast_obj *o)
40648c2ecf20Sopenharmony_ci{
40658c2ecf20Sopenharmony_ci	return o->raw.check_pending(&o->raw) || o->check_sched(o);
40668c2ecf20Sopenharmony_ci}
40678c2ecf20Sopenharmony_ci
40688c2ecf20Sopenharmony_civoid bnx2x_init_mcast_obj(struct bnx2x *bp,
40698c2ecf20Sopenharmony_ci			  struct bnx2x_mcast_obj *mcast_obj,
40708c2ecf20Sopenharmony_ci			  u8 mcast_cl_id, u32 mcast_cid, u8 func_id,
40718c2ecf20Sopenharmony_ci			  u8 engine_id, void *rdata, dma_addr_t rdata_mapping,
40728c2ecf20Sopenharmony_ci			  int state, unsigned long *pstate, bnx2x_obj_type type)
40738c2ecf20Sopenharmony_ci{
40748c2ecf20Sopenharmony_ci	memset(mcast_obj, 0, sizeof(*mcast_obj));
40758c2ecf20Sopenharmony_ci
40768c2ecf20Sopenharmony_ci	bnx2x_init_raw_obj(&mcast_obj->raw, mcast_cl_id, mcast_cid, func_id,
40778c2ecf20Sopenharmony_ci			   rdata, rdata_mapping, state, pstate, type);
40788c2ecf20Sopenharmony_ci
40798c2ecf20Sopenharmony_ci	mcast_obj->engine_id = engine_id;
40808c2ecf20Sopenharmony_ci
40818c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&mcast_obj->pending_cmds_head);
40828c2ecf20Sopenharmony_ci
40838c2ecf20Sopenharmony_ci	mcast_obj->sched_state = BNX2X_FILTER_MCAST_SCHED;
40848c2ecf20Sopenharmony_ci	mcast_obj->check_sched = bnx2x_mcast_check_sched;
40858c2ecf20Sopenharmony_ci	mcast_obj->set_sched = bnx2x_mcast_set_sched;
40868c2ecf20Sopenharmony_ci	mcast_obj->clear_sched = bnx2x_mcast_clear_sched;
40878c2ecf20Sopenharmony_ci
40888c2ecf20Sopenharmony_ci	if (CHIP_IS_E1(bp)) {
40898c2ecf20Sopenharmony_ci		mcast_obj->config_mcast      = bnx2x_mcast_setup_e1;
40908c2ecf20Sopenharmony_ci		mcast_obj->enqueue_cmd       = bnx2x_mcast_enqueue_cmd;
40918c2ecf20Sopenharmony_ci		mcast_obj->hdl_restore       =
40928c2ecf20Sopenharmony_ci			bnx2x_mcast_handle_restore_cmd_e1;
40938c2ecf20Sopenharmony_ci		mcast_obj->check_pending     = bnx2x_mcast_check_pending;
40948c2ecf20Sopenharmony_ci
40958c2ecf20Sopenharmony_ci		if (CHIP_REV_IS_SLOW(bp))
40968c2ecf20Sopenharmony_ci			mcast_obj->max_cmd_len = BNX2X_MAX_EMUL_MULTI;
40978c2ecf20Sopenharmony_ci		else
40988c2ecf20Sopenharmony_ci			mcast_obj->max_cmd_len = BNX2X_MAX_MULTICAST;
40998c2ecf20Sopenharmony_ci
41008c2ecf20Sopenharmony_ci		mcast_obj->wait_comp         = bnx2x_mcast_wait;
41018c2ecf20Sopenharmony_ci		mcast_obj->set_one_rule      = bnx2x_mcast_set_one_rule_e1;
41028c2ecf20Sopenharmony_ci		mcast_obj->validate          = bnx2x_mcast_validate_e1;
41038c2ecf20Sopenharmony_ci		mcast_obj->revert            = bnx2x_mcast_revert_e1;
41048c2ecf20Sopenharmony_ci		mcast_obj->get_registry_size =
41058c2ecf20Sopenharmony_ci			bnx2x_mcast_get_registry_size_exact;
41068c2ecf20Sopenharmony_ci		mcast_obj->set_registry_size =
41078c2ecf20Sopenharmony_ci			bnx2x_mcast_set_registry_size_exact;
41088c2ecf20Sopenharmony_ci
41098c2ecf20Sopenharmony_ci		/* 57710 is the only chip that uses the exact match for mcast
41108c2ecf20Sopenharmony_ci		 * at the moment.
41118c2ecf20Sopenharmony_ci		 */
41128c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&mcast_obj->registry.exact_match.macs);
41138c2ecf20Sopenharmony_ci
41148c2ecf20Sopenharmony_ci	} else if (CHIP_IS_E1H(bp)) {
41158c2ecf20Sopenharmony_ci		mcast_obj->config_mcast  = bnx2x_mcast_setup_e1h;
41168c2ecf20Sopenharmony_ci		mcast_obj->enqueue_cmd   = NULL;
41178c2ecf20Sopenharmony_ci		mcast_obj->hdl_restore   = NULL;
41188c2ecf20Sopenharmony_ci		mcast_obj->check_pending = bnx2x_mcast_check_pending;
41198c2ecf20Sopenharmony_ci
41208c2ecf20Sopenharmony_ci		/* 57711 doesn't send a ramrod, so it has unlimited credit
41218c2ecf20Sopenharmony_ci		 * for one command.
41228c2ecf20Sopenharmony_ci		 */
41238c2ecf20Sopenharmony_ci		mcast_obj->max_cmd_len       = -1;
41248c2ecf20Sopenharmony_ci		mcast_obj->wait_comp         = bnx2x_mcast_wait;
41258c2ecf20Sopenharmony_ci		mcast_obj->set_one_rule      = NULL;
41268c2ecf20Sopenharmony_ci		mcast_obj->validate          = bnx2x_mcast_validate_e1h;
41278c2ecf20Sopenharmony_ci		mcast_obj->revert            = bnx2x_mcast_revert_e1h;
41288c2ecf20Sopenharmony_ci		mcast_obj->get_registry_size =
41298c2ecf20Sopenharmony_ci			bnx2x_mcast_get_registry_size_aprox;
41308c2ecf20Sopenharmony_ci		mcast_obj->set_registry_size =
41318c2ecf20Sopenharmony_ci			bnx2x_mcast_set_registry_size_aprox;
41328c2ecf20Sopenharmony_ci	} else {
41338c2ecf20Sopenharmony_ci		mcast_obj->config_mcast      = bnx2x_mcast_setup_e2;
41348c2ecf20Sopenharmony_ci		mcast_obj->enqueue_cmd       = bnx2x_mcast_enqueue_cmd;
41358c2ecf20Sopenharmony_ci		mcast_obj->hdl_restore       =
41368c2ecf20Sopenharmony_ci			bnx2x_mcast_handle_restore_cmd_e2;
41378c2ecf20Sopenharmony_ci		mcast_obj->check_pending     = bnx2x_mcast_check_pending;
41388c2ecf20Sopenharmony_ci		/* TODO: There should be a proper HSI define for this number!!!
41398c2ecf20Sopenharmony_ci		 */
41408c2ecf20Sopenharmony_ci		mcast_obj->max_cmd_len       = 16;
41418c2ecf20Sopenharmony_ci		mcast_obj->wait_comp         = bnx2x_mcast_wait;
41428c2ecf20Sopenharmony_ci		mcast_obj->set_one_rule      = bnx2x_mcast_set_one_rule_e2;
41438c2ecf20Sopenharmony_ci		mcast_obj->validate          = bnx2x_mcast_validate_e2;
41448c2ecf20Sopenharmony_ci		mcast_obj->revert            = bnx2x_mcast_revert_e2;
41458c2ecf20Sopenharmony_ci		mcast_obj->get_registry_size =
41468c2ecf20Sopenharmony_ci			bnx2x_mcast_get_registry_size_aprox;
41478c2ecf20Sopenharmony_ci		mcast_obj->set_registry_size =
41488c2ecf20Sopenharmony_ci			bnx2x_mcast_set_registry_size_aprox;
41498c2ecf20Sopenharmony_ci	}
41508c2ecf20Sopenharmony_ci}
41518c2ecf20Sopenharmony_ci
41528c2ecf20Sopenharmony_ci/*************************** Credit handling **********************************/
41538c2ecf20Sopenharmony_ci
41548c2ecf20Sopenharmony_ci/**
41558c2ecf20Sopenharmony_ci * atomic_add_ifless - add if the result is less than a given value.
41568c2ecf20Sopenharmony_ci *
41578c2ecf20Sopenharmony_ci * @v:	pointer of type atomic_t
41588c2ecf20Sopenharmony_ci * @a:	the amount to add to v...
41598c2ecf20Sopenharmony_ci * @u:	...if (v + a) is less than u.
41608c2ecf20Sopenharmony_ci *
41618c2ecf20Sopenharmony_ci * returns true if (v + a) was less than u, and false otherwise.
41628c2ecf20Sopenharmony_ci *
41638c2ecf20Sopenharmony_ci */
41648c2ecf20Sopenharmony_cistatic inline bool __atomic_add_ifless(atomic_t *v, int a, int u)
41658c2ecf20Sopenharmony_ci{
41668c2ecf20Sopenharmony_ci	int c, old;
41678c2ecf20Sopenharmony_ci
41688c2ecf20Sopenharmony_ci	c = atomic_read(v);
41698c2ecf20Sopenharmony_ci	for (;;) {
41708c2ecf20Sopenharmony_ci		if (unlikely(c + a >= u))
41718c2ecf20Sopenharmony_ci			return false;
41728c2ecf20Sopenharmony_ci
41738c2ecf20Sopenharmony_ci		old = atomic_cmpxchg((v), c, c + a);
41748c2ecf20Sopenharmony_ci		if (likely(old == c))
41758c2ecf20Sopenharmony_ci			break;
41768c2ecf20Sopenharmony_ci		c = old;
41778c2ecf20Sopenharmony_ci	}
41788c2ecf20Sopenharmony_ci
41798c2ecf20Sopenharmony_ci	return true;
41808c2ecf20Sopenharmony_ci}
41818c2ecf20Sopenharmony_ci
41828c2ecf20Sopenharmony_ci/**
41838c2ecf20Sopenharmony_ci * atomic_dec_ifmoe - dec if the result is more or equal than a given value.
41848c2ecf20Sopenharmony_ci *
41858c2ecf20Sopenharmony_ci * @v:	pointer of type atomic_t
41868c2ecf20Sopenharmony_ci * @a:	the amount to dec from v...
41878c2ecf20Sopenharmony_ci * @u:	...if (v - a) is more or equal than u.
41888c2ecf20Sopenharmony_ci *
41898c2ecf20Sopenharmony_ci * returns true if (v - a) was more or equal than u, and false
41908c2ecf20Sopenharmony_ci * otherwise.
41918c2ecf20Sopenharmony_ci */
41928c2ecf20Sopenharmony_cistatic inline bool __atomic_dec_ifmoe(atomic_t *v, int a, int u)
41938c2ecf20Sopenharmony_ci{
41948c2ecf20Sopenharmony_ci	int c, old;
41958c2ecf20Sopenharmony_ci
41968c2ecf20Sopenharmony_ci	c = atomic_read(v);
41978c2ecf20Sopenharmony_ci	for (;;) {
41988c2ecf20Sopenharmony_ci		if (unlikely(c - a < u))
41998c2ecf20Sopenharmony_ci			return false;
42008c2ecf20Sopenharmony_ci
42018c2ecf20Sopenharmony_ci		old = atomic_cmpxchg((v), c, c - a);
42028c2ecf20Sopenharmony_ci		if (likely(old == c))
42038c2ecf20Sopenharmony_ci			break;
42048c2ecf20Sopenharmony_ci		c = old;
42058c2ecf20Sopenharmony_ci	}
42068c2ecf20Sopenharmony_ci
42078c2ecf20Sopenharmony_ci	return true;
42088c2ecf20Sopenharmony_ci}
42098c2ecf20Sopenharmony_ci
42108c2ecf20Sopenharmony_cistatic bool bnx2x_credit_pool_get(struct bnx2x_credit_pool_obj *o, int cnt)
42118c2ecf20Sopenharmony_ci{
42128c2ecf20Sopenharmony_ci	bool rc;
42138c2ecf20Sopenharmony_ci
42148c2ecf20Sopenharmony_ci	smp_mb();
42158c2ecf20Sopenharmony_ci	rc = __atomic_dec_ifmoe(&o->credit, cnt, 0);
42168c2ecf20Sopenharmony_ci	smp_mb();
42178c2ecf20Sopenharmony_ci
42188c2ecf20Sopenharmony_ci	return rc;
42198c2ecf20Sopenharmony_ci}
42208c2ecf20Sopenharmony_ci
42218c2ecf20Sopenharmony_cistatic bool bnx2x_credit_pool_put(struct bnx2x_credit_pool_obj *o, int cnt)
42228c2ecf20Sopenharmony_ci{
42238c2ecf20Sopenharmony_ci	bool rc;
42248c2ecf20Sopenharmony_ci
42258c2ecf20Sopenharmony_ci	smp_mb();
42268c2ecf20Sopenharmony_ci
42278c2ecf20Sopenharmony_ci	/* Don't let to refill if credit + cnt > pool_sz */
42288c2ecf20Sopenharmony_ci	rc = __atomic_add_ifless(&o->credit, cnt, o->pool_sz + 1);
42298c2ecf20Sopenharmony_ci
42308c2ecf20Sopenharmony_ci	smp_mb();
42318c2ecf20Sopenharmony_ci
42328c2ecf20Sopenharmony_ci	return rc;
42338c2ecf20Sopenharmony_ci}
42348c2ecf20Sopenharmony_ci
42358c2ecf20Sopenharmony_cistatic int bnx2x_credit_pool_check(struct bnx2x_credit_pool_obj *o)
42368c2ecf20Sopenharmony_ci{
42378c2ecf20Sopenharmony_ci	int cur_credit;
42388c2ecf20Sopenharmony_ci
42398c2ecf20Sopenharmony_ci	smp_mb();
42408c2ecf20Sopenharmony_ci	cur_credit = atomic_read(&o->credit);
42418c2ecf20Sopenharmony_ci
42428c2ecf20Sopenharmony_ci	return cur_credit;
42438c2ecf20Sopenharmony_ci}
42448c2ecf20Sopenharmony_ci
42458c2ecf20Sopenharmony_cistatic bool bnx2x_credit_pool_always_true(struct bnx2x_credit_pool_obj *o,
42468c2ecf20Sopenharmony_ci					  int cnt)
42478c2ecf20Sopenharmony_ci{
42488c2ecf20Sopenharmony_ci	return true;
42498c2ecf20Sopenharmony_ci}
42508c2ecf20Sopenharmony_ci
42518c2ecf20Sopenharmony_cistatic bool bnx2x_credit_pool_get_entry(
42528c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *o,
42538c2ecf20Sopenharmony_ci	int *offset)
42548c2ecf20Sopenharmony_ci{
42558c2ecf20Sopenharmony_ci	int idx, vec, i;
42568c2ecf20Sopenharmony_ci
42578c2ecf20Sopenharmony_ci	*offset = -1;
42588c2ecf20Sopenharmony_ci
42598c2ecf20Sopenharmony_ci	/* Find "internal cam-offset" then add to base for this object... */
42608c2ecf20Sopenharmony_ci	for (vec = 0; vec < BNX2X_POOL_VEC_SIZE; vec++) {
42618c2ecf20Sopenharmony_ci
42628c2ecf20Sopenharmony_ci		/* Skip the current vector if there are no free entries in it */
42638c2ecf20Sopenharmony_ci		if (!o->pool_mirror[vec])
42648c2ecf20Sopenharmony_ci			continue;
42658c2ecf20Sopenharmony_ci
42668c2ecf20Sopenharmony_ci		/* If we've got here we are going to find a free entry */
42678c2ecf20Sopenharmony_ci		for (idx = vec * BIT_VEC64_ELEM_SZ, i = 0;
42688c2ecf20Sopenharmony_ci		      i < BIT_VEC64_ELEM_SZ; idx++, i++)
42698c2ecf20Sopenharmony_ci
42708c2ecf20Sopenharmony_ci			if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) {
42718c2ecf20Sopenharmony_ci				/* Got one!! */
42728c2ecf20Sopenharmony_ci				BIT_VEC64_CLEAR_BIT(o->pool_mirror, idx);
42738c2ecf20Sopenharmony_ci				*offset = o->base_pool_offset + idx;
42748c2ecf20Sopenharmony_ci				return true;
42758c2ecf20Sopenharmony_ci			}
42768c2ecf20Sopenharmony_ci	}
42778c2ecf20Sopenharmony_ci
42788c2ecf20Sopenharmony_ci	return false;
42798c2ecf20Sopenharmony_ci}
42808c2ecf20Sopenharmony_ci
42818c2ecf20Sopenharmony_cistatic bool bnx2x_credit_pool_put_entry(
42828c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *o,
42838c2ecf20Sopenharmony_ci	int offset)
42848c2ecf20Sopenharmony_ci{
42858c2ecf20Sopenharmony_ci	if (offset < o->base_pool_offset)
42868c2ecf20Sopenharmony_ci		return false;
42878c2ecf20Sopenharmony_ci
42888c2ecf20Sopenharmony_ci	offset -= o->base_pool_offset;
42898c2ecf20Sopenharmony_ci
42908c2ecf20Sopenharmony_ci	if (offset >= o->pool_sz)
42918c2ecf20Sopenharmony_ci		return false;
42928c2ecf20Sopenharmony_ci
42938c2ecf20Sopenharmony_ci	/* Return the entry to the pool */
42948c2ecf20Sopenharmony_ci	BIT_VEC64_SET_BIT(o->pool_mirror, offset);
42958c2ecf20Sopenharmony_ci
42968c2ecf20Sopenharmony_ci	return true;
42978c2ecf20Sopenharmony_ci}
42988c2ecf20Sopenharmony_ci
42998c2ecf20Sopenharmony_cistatic bool bnx2x_credit_pool_put_entry_always_true(
43008c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *o,
43018c2ecf20Sopenharmony_ci	int offset)
43028c2ecf20Sopenharmony_ci{
43038c2ecf20Sopenharmony_ci	return true;
43048c2ecf20Sopenharmony_ci}
43058c2ecf20Sopenharmony_ci
43068c2ecf20Sopenharmony_cistatic bool bnx2x_credit_pool_get_entry_always_true(
43078c2ecf20Sopenharmony_ci	struct bnx2x_credit_pool_obj *o,
43088c2ecf20Sopenharmony_ci	int *offset)
43098c2ecf20Sopenharmony_ci{
43108c2ecf20Sopenharmony_ci	*offset = -1;
43118c2ecf20Sopenharmony_ci	return true;
43128c2ecf20Sopenharmony_ci}
43138c2ecf20Sopenharmony_ci/**
43148c2ecf20Sopenharmony_ci * bnx2x_init_credit_pool - initialize credit pool internals.
43158c2ecf20Sopenharmony_ci *
43168c2ecf20Sopenharmony_ci * @p:		credit pool
43178c2ecf20Sopenharmony_ci * @base:	Base entry in the CAM to use.
43188c2ecf20Sopenharmony_ci * @credit:	pool size.
43198c2ecf20Sopenharmony_ci *
43208c2ecf20Sopenharmony_ci * If base is negative no CAM entries handling will be performed.
43218c2ecf20Sopenharmony_ci * If credit is negative pool operations will always succeed (unlimited pool).
43228c2ecf20Sopenharmony_ci *
43238c2ecf20Sopenharmony_ci */
43248c2ecf20Sopenharmony_civoid bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj *p,
43258c2ecf20Sopenharmony_ci			    int base, int credit)
43268c2ecf20Sopenharmony_ci{
43278c2ecf20Sopenharmony_ci	/* Zero the object first */
43288c2ecf20Sopenharmony_ci	memset(p, 0, sizeof(*p));
43298c2ecf20Sopenharmony_ci
43308c2ecf20Sopenharmony_ci	/* Set the table to all 1s */
43318c2ecf20Sopenharmony_ci	memset(&p->pool_mirror, 0xff, sizeof(p->pool_mirror));
43328c2ecf20Sopenharmony_ci
43338c2ecf20Sopenharmony_ci	/* Init a pool as full */
43348c2ecf20Sopenharmony_ci	atomic_set(&p->credit, credit);
43358c2ecf20Sopenharmony_ci
43368c2ecf20Sopenharmony_ci	/* The total poll size */
43378c2ecf20Sopenharmony_ci	p->pool_sz = credit;
43388c2ecf20Sopenharmony_ci
43398c2ecf20Sopenharmony_ci	p->base_pool_offset = base;
43408c2ecf20Sopenharmony_ci
43418c2ecf20Sopenharmony_ci	/* Commit the change */
43428c2ecf20Sopenharmony_ci	smp_mb();
43438c2ecf20Sopenharmony_ci
43448c2ecf20Sopenharmony_ci	p->check = bnx2x_credit_pool_check;
43458c2ecf20Sopenharmony_ci
43468c2ecf20Sopenharmony_ci	/* if pool credit is negative - disable the checks */
43478c2ecf20Sopenharmony_ci	if (credit >= 0) {
43488c2ecf20Sopenharmony_ci		p->put      = bnx2x_credit_pool_put;
43498c2ecf20Sopenharmony_ci		p->get      = bnx2x_credit_pool_get;
43508c2ecf20Sopenharmony_ci		p->put_entry = bnx2x_credit_pool_put_entry;
43518c2ecf20Sopenharmony_ci		p->get_entry = bnx2x_credit_pool_get_entry;
43528c2ecf20Sopenharmony_ci	} else {
43538c2ecf20Sopenharmony_ci		p->put      = bnx2x_credit_pool_always_true;
43548c2ecf20Sopenharmony_ci		p->get      = bnx2x_credit_pool_always_true;
43558c2ecf20Sopenharmony_ci		p->put_entry = bnx2x_credit_pool_put_entry_always_true;
43568c2ecf20Sopenharmony_ci		p->get_entry = bnx2x_credit_pool_get_entry_always_true;
43578c2ecf20Sopenharmony_ci	}
43588c2ecf20Sopenharmony_ci
43598c2ecf20Sopenharmony_ci	/* If base is negative - disable entries handling */
43608c2ecf20Sopenharmony_ci	if (base < 0) {
43618c2ecf20Sopenharmony_ci		p->put_entry = bnx2x_credit_pool_put_entry_always_true;
43628c2ecf20Sopenharmony_ci		p->get_entry = bnx2x_credit_pool_get_entry_always_true;
43638c2ecf20Sopenharmony_ci	}
43648c2ecf20Sopenharmony_ci}
43658c2ecf20Sopenharmony_ci
43668c2ecf20Sopenharmony_civoid bnx2x_init_mac_credit_pool(struct bnx2x *bp,
43678c2ecf20Sopenharmony_ci				struct bnx2x_credit_pool_obj *p, u8 func_id,
43688c2ecf20Sopenharmony_ci				u8 func_num)
43698c2ecf20Sopenharmony_ci{
43708c2ecf20Sopenharmony_ci/* TODO: this will be defined in consts as well... */
43718c2ecf20Sopenharmony_ci#define BNX2X_CAM_SIZE_EMUL 5
43728c2ecf20Sopenharmony_ci
43738c2ecf20Sopenharmony_ci	int cam_sz;
43748c2ecf20Sopenharmony_ci
43758c2ecf20Sopenharmony_ci	if (CHIP_IS_E1(bp)) {
43768c2ecf20Sopenharmony_ci		/* In E1, Multicast is saved in cam... */
43778c2ecf20Sopenharmony_ci		if (!CHIP_REV_IS_SLOW(bp))
43788c2ecf20Sopenharmony_ci			cam_sz = (MAX_MAC_CREDIT_E1 / 2) - BNX2X_MAX_MULTICAST;
43798c2ecf20Sopenharmony_ci		else
43808c2ecf20Sopenharmony_ci			cam_sz = BNX2X_CAM_SIZE_EMUL - BNX2X_MAX_EMUL_MULTI;
43818c2ecf20Sopenharmony_ci
43828c2ecf20Sopenharmony_ci		bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
43838c2ecf20Sopenharmony_ci
43848c2ecf20Sopenharmony_ci	} else if (CHIP_IS_E1H(bp)) {
43858c2ecf20Sopenharmony_ci		/* CAM credit is equaly divided between all active functions
43868c2ecf20Sopenharmony_ci		 * on the PORT!.
43878c2ecf20Sopenharmony_ci		 */
43888c2ecf20Sopenharmony_ci		if ((func_num > 0)) {
43898c2ecf20Sopenharmony_ci			if (!CHIP_REV_IS_SLOW(bp))
43908c2ecf20Sopenharmony_ci				cam_sz = (MAX_MAC_CREDIT_E1H / (2*func_num));
43918c2ecf20Sopenharmony_ci			else
43928c2ecf20Sopenharmony_ci				cam_sz = BNX2X_CAM_SIZE_EMUL;
43938c2ecf20Sopenharmony_ci			bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
43948c2ecf20Sopenharmony_ci		} else {
43958c2ecf20Sopenharmony_ci			/* this should never happen! Block MAC operations. */
43968c2ecf20Sopenharmony_ci			bnx2x_init_credit_pool(p, 0, 0);
43978c2ecf20Sopenharmony_ci		}
43988c2ecf20Sopenharmony_ci
43998c2ecf20Sopenharmony_ci	} else {
44008c2ecf20Sopenharmony_ci
44018c2ecf20Sopenharmony_ci		/* CAM credit is equaly divided between all active functions
44028c2ecf20Sopenharmony_ci		 * on the PATH.
44038c2ecf20Sopenharmony_ci		 */
44048c2ecf20Sopenharmony_ci		if (func_num > 0) {
44058c2ecf20Sopenharmony_ci			if (!CHIP_REV_IS_SLOW(bp))
44068c2ecf20Sopenharmony_ci				cam_sz = PF_MAC_CREDIT_E2(bp, func_num);
44078c2ecf20Sopenharmony_ci			else
44088c2ecf20Sopenharmony_ci				cam_sz = BNX2X_CAM_SIZE_EMUL;
44098c2ecf20Sopenharmony_ci
44108c2ecf20Sopenharmony_ci			/* No need for CAM entries handling for 57712 and
44118c2ecf20Sopenharmony_ci			 * newer.
44128c2ecf20Sopenharmony_ci			 */
44138c2ecf20Sopenharmony_ci			bnx2x_init_credit_pool(p, -1, cam_sz);
44148c2ecf20Sopenharmony_ci		} else {
44158c2ecf20Sopenharmony_ci			/* this should never happen! Block MAC operations. */
44168c2ecf20Sopenharmony_ci			bnx2x_init_credit_pool(p, 0, 0);
44178c2ecf20Sopenharmony_ci		}
44188c2ecf20Sopenharmony_ci	}
44198c2ecf20Sopenharmony_ci}
44208c2ecf20Sopenharmony_ci
44218c2ecf20Sopenharmony_civoid bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
44228c2ecf20Sopenharmony_ci				 struct bnx2x_credit_pool_obj *p,
44238c2ecf20Sopenharmony_ci				 u8 func_id,
44248c2ecf20Sopenharmony_ci				 u8 func_num)
44258c2ecf20Sopenharmony_ci{
44268c2ecf20Sopenharmony_ci	if (CHIP_IS_E1x(bp)) {
44278c2ecf20Sopenharmony_ci		/* There is no VLAN credit in HW on 57710 and 57711 only
44288c2ecf20Sopenharmony_ci		 * MAC / MAC-VLAN can be set
44298c2ecf20Sopenharmony_ci		 */
44308c2ecf20Sopenharmony_ci		bnx2x_init_credit_pool(p, 0, -1);
44318c2ecf20Sopenharmony_ci	} else {
44328c2ecf20Sopenharmony_ci		/* CAM credit is equally divided between all active functions
44338c2ecf20Sopenharmony_ci		 * on the PATH.
44348c2ecf20Sopenharmony_ci		 */
44358c2ecf20Sopenharmony_ci		if (func_num > 0) {
44368c2ecf20Sopenharmony_ci			int credit = PF_VLAN_CREDIT_E2(bp, func_num);
44378c2ecf20Sopenharmony_ci
44388c2ecf20Sopenharmony_ci			bnx2x_init_credit_pool(p, -1/*unused for E2*/, credit);
44398c2ecf20Sopenharmony_ci		} else
44408c2ecf20Sopenharmony_ci			/* this should never happen! Block VLAN operations. */
44418c2ecf20Sopenharmony_ci			bnx2x_init_credit_pool(p, 0, 0);
44428c2ecf20Sopenharmony_ci	}
44438c2ecf20Sopenharmony_ci}
44448c2ecf20Sopenharmony_ci
44458c2ecf20Sopenharmony_ci/****************** RSS Configuration ******************/
44468c2ecf20Sopenharmony_ci/**
44478c2ecf20Sopenharmony_ci * bnx2x_debug_print_ind_table - prints the indirection table configuration.
44488c2ecf20Sopenharmony_ci *
44498c2ecf20Sopenharmony_ci * @bp:		driver handle
44508c2ecf20Sopenharmony_ci * @p:		pointer to rss configuration
44518c2ecf20Sopenharmony_ci *
44528c2ecf20Sopenharmony_ci * Prints it when NETIF_MSG_IFUP debug level is configured.
44538c2ecf20Sopenharmony_ci */
44548c2ecf20Sopenharmony_cistatic inline void bnx2x_debug_print_ind_table(struct bnx2x *bp,
44558c2ecf20Sopenharmony_ci					struct bnx2x_config_rss_params *p)
44568c2ecf20Sopenharmony_ci{
44578c2ecf20Sopenharmony_ci	int i;
44588c2ecf20Sopenharmony_ci
44598c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Setting indirection table to:\n");
44608c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "0x0000: ");
44618c2ecf20Sopenharmony_ci	for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
44628c2ecf20Sopenharmony_ci		DP_CONT(BNX2X_MSG_SP, "0x%02x ", p->ind_table[i]);
44638c2ecf20Sopenharmony_ci
44648c2ecf20Sopenharmony_ci		/* Print 4 bytes in a line */
44658c2ecf20Sopenharmony_ci		if ((i + 1 < T_ETH_INDIRECTION_TABLE_SIZE) &&
44668c2ecf20Sopenharmony_ci		    (((i + 1) & 0x3) == 0)) {
44678c2ecf20Sopenharmony_ci			DP_CONT(BNX2X_MSG_SP, "\n");
44688c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_SP, "0x%04x: ", i + 1);
44698c2ecf20Sopenharmony_ci		}
44708c2ecf20Sopenharmony_ci	}
44718c2ecf20Sopenharmony_ci
44728c2ecf20Sopenharmony_ci	DP_CONT(BNX2X_MSG_SP, "\n");
44738c2ecf20Sopenharmony_ci}
44748c2ecf20Sopenharmony_ci
44758c2ecf20Sopenharmony_ci/**
44768c2ecf20Sopenharmony_ci * bnx2x_setup_rss - configure RSS
44778c2ecf20Sopenharmony_ci *
44788c2ecf20Sopenharmony_ci * @bp:		device handle
44798c2ecf20Sopenharmony_ci * @p:		rss configuration
44808c2ecf20Sopenharmony_ci *
44818c2ecf20Sopenharmony_ci * sends on UPDATE ramrod for that matter.
44828c2ecf20Sopenharmony_ci */
44838c2ecf20Sopenharmony_cistatic int bnx2x_setup_rss(struct bnx2x *bp,
44848c2ecf20Sopenharmony_ci			   struct bnx2x_config_rss_params *p)
44858c2ecf20Sopenharmony_ci{
44868c2ecf20Sopenharmony_ci	struct bnx2x_rss_config_obj *o = p->rss_obj;
44878c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *r = &o->raw;
44888c2ecf20Sopenharmony_ci	struct eth_rss_update_ramrod_data *data =
44898c2ecf20Sopenharmony_ci		(struct eth_rss_update_ramrod_data *)(r->rdata);
44908c2ecf20Sopenharmony_ci	u16 caps = 0;
44918c2ecf20Sopenharmony_ci	u8 rss_mode = 0;
44928c2ecf20Sopenharmony_ci	int rc;
44938c2ecf20Sopenharmony_ci
44948c2ecf20Sopenharmony_ci	memset(data, 0, sizeof(*data));
44958c2ecf20Sopenharmony_ci
44968c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Configuring RSS\n");
44978c2ecf20Sopenharmony_ci
44988c2ecf20Sopenharmony_ci	/* Set an echo field */
44998c2ecf20Sopenharmony_ci	data->echo = cpu_to_le32((r->cid & BNX2X_SWCID_MASK) |
45008c2ecf20Sopenharmony_ci				 (r->state << BNX2X_SWCID_SHIFT));
45018c2ecf20Sopenharmony_ci
45028c2ecf20Sopenharmony_ci	/* RSS mode */
45038c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_RSS_MODE_DISABLED, &p->rss_flags))
45048c2ecf20Sopenharmony_ci		rss_mode = ETH_RSS_MODE_DISABLED;
45058c2ecf20Sopenharmony_ci	else if (test_bit(BNX2X_RSS_MODE_REGULAR, &p->rss_flags))
45068c2ecf20Sopenharmony_ci		rss_mode = ETH_RSS_MODE_REGULAR;
45078c2ecf20Sopenharmony_ci
45088c2ecf20Sopenharmony_ci	data->rss_mode = rss_mode;
45098c2ecf20Sopenharmony_ci
45108c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "rss_mode=%d\n", rss_mode);
45118c2ecf20Sopenharmony_ci
45128c2ecf20Sopenharmony_ci	/* RSS capabilities */
45138c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_RSS_IPV4, &p->rss_flags))
45148c2ecf20Sopenharmony_ci		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY;
45158c2ecf20Sopenharmony_ci
45168c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_RSS_IPV4_TCP, &p->rss_flags))
45178c2ecf20Sopenharmony_ci		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY;
45188c2ecf20Sopenharmony_ci
45198c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_RSS_IPV4_UDP, &p->rss_flags))
45208c2ecf20Sopenharmony_ci		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY;
45218c2ecf20Sopenharmony_ci
45228c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_RSS_IPV6, &p->rss_flags))
45238c2ecf20Sopenharmony_ci		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY;
45248c2ecf20Sopenharmony_ci
45258c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_RSS_IPV6_TCP, &p->rss_flags))
45268c2ecf20Sopenharmony_ci		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY;
45278c2ecf20Sopenharmony_ci
45288c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_RSS_IPV6_UDP, &p->rss_flags))
45298c2ecf20Sopenharmony_ci		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY;
45308c2ecf20Sopenharmony_ci
45318c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_RSS_IPV4_VXLAN, &p->rss_flags))
45328c2ecf20Sopenharmony_ci		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_VXLAN_CAPABILITY;
45338c2ecf20Sopenharmony_ci
45348c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_RSS_IPV6_VXLAN, &p->rss_flags))
45358c2ecf20Sopenharmony_ci		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_VXLAN_CAPABILITY;
45368c2ecf20Sopenharmony_ci
45378c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_RSS_TUNN_INNER_HDRS, &p->rss_flags))
45388c2ecf20Sopenharmony_ci		caps |= ETH_RSS_UPDATE_RAMROD_DATA_TUNN_INNER_HDRS_CAPABILITY;
45398c2ecf20Sopenharmony_ci
45408c2ecf20Sopenharmony_ci	/* RSS keys */
45418c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_RSS_SET_SRCH, &p->rss_flags)) {
45428c2ecf20Sopenharmony_ci		u8 *dst = (u8 *)(data->rss_key) + sizeof(data->rss_key);
45438c2ecf20Sopenharmony_ci		const u8 *src = (const u8 *)p->rss_key;
45448c2ecf20Sopenharmony_ci		int i;
45458c2ecf20Sopenharmony_ci
45468c2ecf20Sopenharmony_ci		/* Apparently, bnx2x reads this array in reverse order
45478c2ecf20Sopenharmony_ci		 * We need to byte swap rss_key to comply with Toeplitz specs.
45488c2ecf20Sopenharmony_ci		 */
45498c2ecf20Sopenharmony_ci		for (i = 0; i < sizeof(data->rss_key); i++)
45508c2ecf20Sopenharmony_ci			*--dst = *src++;
45518c2ecf20Sopenharmony_ci
45528c2ecf20Sopenharmony_ci		caps |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
45538c2ecf20Sopenharmony_ci	}
45548c2ecf20Sopenharmony_ci
45558c2ecf20Sopenharmony_ci	data->capabilities = cpu_to_le16(caps);
45568c2ecf20Sopenharmony_ci
45578c2ecf20Sopenharmony_ci	/* Hashing mask */
45588c2ecf20Sopenharmony_ci	data->rss_result_mask = p->rss_result_mask;
45598c2ecf20Sopenharmony_ci
45608c2ecf20Sopenharmony_ci	/* RSS engine ID */
45618c2ecf20Sopenharmony_ci	data->rss_engine_id = o->engine_id;
45628c2ecf20Sopenharmony_ci
45638c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "rss_engine_id=%d\n", data->rss_engine_id);
45648c2ecf20Sopenharmony_ci
45658c2ecf20Sopenharmony_ci	/* Indirection table */
45668c2ecf20Sopenharmony_ci	memcpy(data->indirection_table, p->ind_table,
45678c2ecf20Sopenharmony_ci		  T_ETH_INDIRECTION_TABLE_SIZE);
45688c2ecf20Sopenharmony_ci
45698c2ecf20Sopenharmony_ci	/* Remember the last configuration */
45708c2ecf20Sopenharmony_ci	memcpy(o->ind_table, p->ind_table, T_ETH_INDIRECTION_TABLE_SIZE);
45718c2ecf20Sopenharmony_ci
45728c2ecf20Sopenharmony_ci	/* Print the indirection table */
45738c2ecf20Sopenharmony_ci	if (netif_msg_ifup(bp))
45748c2ecf20Sopenharmony_ci		bnx2x_debug_print_ind_table(bp, p);
45758c2ecf20Sopenharmony_ci
45768c2ecf20Sopenharmony_ci	/* No need for an explicit memory barrier here as long as we
45778c2ecf20Sopenharmony_ci	 * ensure the ordering of writing to the SPQ element
45788c2ecf20Sopenharmony_ci	 * and updating of the SPQ producer which involves a memory
45798c2ecf20Sopenharmony_ci	 * read. If the memory read is removed we will have to put a
45808c2ecf20Sopenharmony_ci	 * full memory barrier there (inside bnx2x_sp_post()).
45818c2ecf20Sopenharmony_ci	 */
45828c2ecf20Sopenharmony_ci
45838c2ecf20Sopenharmony_ci	/* Send a ramrod */
45848c2ecf20Sopenharmony_ci	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_RSS_UPDATE, r->cid,
45858c2ecf20Sopenharmony_ci			   U64_HI(r->rdata_mapping),
45868c2ecf20Sopenharmony_ci			   U64_LO(r->rdata_mapping),
45878c2ecf20Sopenharmony_ci			   ETH_CONNECTION_TYPE);
45888c2ecf20Sopenharmony_ci
45898c2ecf20Sopenharmony_ci	if (rc < 0)
45908c2ecf20Sopenharmony_ci		return rc;
45918c2ecf20Sopenharmony_ci
45928c2ecf20Sopenharmony_ci	return 1;
45938c2ecf20Sopenharmony_ci}
45948c2ecf20Sopenharmony_ci
45958c2ecf20Sopenharmony_civoid bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
45968c2ecf20Sopenharmony_ci			     u8 *ind_table)
45978c2ecf20Sopenharmony_ci{
45988c2ecf20Sopenharmony_ci	memcpy(ind_table, rss_obj->ind_table, sizeof(rss_obj->ind_table));
45998c2ecf20Sopenharmony_ci}
46008c2ecf20Sopenharmony_ci
46018c2ecf20Sopenharmony_ciint bnx2x_config_rss(struct bnx2x *bp,
46028c2ecf20Sopenharmony_ci		     struct bnx2x_config_rss_params *p)
46038c2ecf20Sopenharmony_ci{
46048c2ecf20Sopenharmony_ci	int rc;
46058c2ecf20Sopenharmony_ci	struct bnx2x_rss_config_obj *o = p->rss_obj;
46068c2ecf20Sopenharmony_ci	struct bnx2x_raw_obj *r = &o->raw;
46078c2ecf20Sopenharmony_ci
46088c2ecf20Sopenharmony_ci	/* Do nothing if only driver cleanup was requested */
46098c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
46108c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "Not configuring RSS ramrod_flags=%lx\n",
46118c2ecf20Sopenharmony_ci		   p->ramrod_flags);
46128c2ecf20Sopenharmony_ci		return 0;
46138c2ecf20Sopenharmony_ci	}
46148c2ecf20Sopenharmony_ci
46158c2ecf20Sopenharmony_ci	r->set_pending(r);
46168c2ecf20Sopenharmony_ci
46178c2ecf20Sopenharmony_ci	rc = o->config_rss(bp, p);
46188c2ecf20Sopenharmony_ci	if (rc < 0) {
46198c2ecf20Sopenharmony_ci		r->clear_pending(r);
46208c2ecf20Sopenharmony_ci		return rc;
46218c2ecf20Sopenharmony_ci	}
46228c2ecf20Sopenharmony_ci
46238c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
46248c2ecf20Sopenharmony_ci		rc = r->wait_comp(bp, r);
46258c2ecf20Sopenharmony_ci
46268c2ecf20Sopenharmony_ci	return rc;
46278c2ecf20Sopenharmony_ci}
46288c2ecf20Sopenharmony_ci
46298c2ecf20Sopenharmony_civoid bnx2x_init_rss_config_obj(struct bnx2x *bp,
46308c2ecf20Sopenharmony_ci			       struct bnx2x_rss_config_obj *rss_obj,
46318c2ecf20Sopenharmony_ci			       u8 cl_id, u32 cid, u8 func_id, u8 engine_id,
46328c2ecf20Sopenharmony_ci			       void *rdata, dma_addr_t rdata_mapping,
46338c2ecf20Sopenharmony_ci			       int state, unsigned long *pstate,
46348c2ecf20Sopenharmony_ci			       bnx2x_obj_type type)
46358c2ecf20Sopenharmony_ci{
46368c2ecf20Sopenharmony_ci	bnx2x_init_raw_obj(&rss_obj->raw, cl_id, cid, func_id, rdata,
46378c2ecf20Sopenharmony_ci			   rdata_mapping, state, pstate, type);
46388c2ecf20Sopenharmony_ci
46398c2ecf20Sopenharmony_ci	rss_obj->engine_id  = engine_id;
46408c2ecf20Sopenharmony_ci	rss_obj->config_rss = bnx2x_setup_rss;
46418c2ecf20Sopenharmony_ci}
46428c2ecf20Sopenharmony_ci
46438c2ecf20Sopenharmony_ci/********************** Queue state object ***********************************/
46448c2ecf20Sopenharmony_ci
46458c2ecf20Sopenharmony_ci/**
46468c2ecf20Sopenharmony_ci * bnx2x_queue_state_change - perform Queue state change transition
46478c2ecf20Sopenharmony_ci *
46488c2ecf20Sopenharmony_ci * @bp:		device handle
46498c2ecf20Sopenharmony_ci * @params:	parameters to perform the transition
46508c2ecf20Sopenharmony_ci *
46518c2ecf20Sopenharmony_ci * returns 0 in case of successfully completed transition, negative error
46528c2ecf20Sopenharmony_ci * code in case of failure, positive (EBUSY) value if there is a completion
46538c2ecf20Sopenharmony_ci * to that is still pending (possible only if RAMROD_COMP_WAIT is
46548c2ecf20Sopenharmony_ci * not set in params->ramrod_flags for asynchronous commands).
46558c2ecf20Sopenharmony_ci *
46568c2ecf20Sopenharmony_ci */
46578c2ecf20Sopenharmony_ciint bnx2x_queue_state_change(struct bnx2x *bp,
46588c2ecf20Sopenharmony_ci			     struct bnx2x_queue_state_params *params)
46598c2ecf20Sopenharmony_ci{
46608c2ecf20Sopenharmony_ci	struct bnx2x_queue_sp_obj *o = params->q_obj;
46618c2ecf20Sopenharmony_ci	int rc, pending_bit;
46628c2ecf20Sopenharmony_ci	unsigned long *pending = &o->pending;
46638c2ecf20Sopenharmony_ci
46648c2ecf20Sopenharmony_ci	/* Check that the requested transition is legal */
46658c2ecf20Sopenharmony_ci	rc = o->check_transition(bp, o, params);
46668c2ecf20Sopenharmony_ci	if (rc) {
46678c2ecf20Sopenharmony_ci		BNX2X_ERR("check transition returned an error. rc %d\n", rc);
46688c2ecf20Sopenharmony_ci		return -EINVAL;
46698c2ecf20Sopenharmony_ci	}
46708c2ecf20Sopenharmony_ci
46718c2ecf20Sopenharmony_ci	/* Set "pending" bit */
46728c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "pending bit was=%lx\n", o->pending);
46738c2ecf20Sopenharmony_ci	pending_bit = o->set_pending(o, params);
46748c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "pending bit now=%lx\n", o->pending);
46758c2ecf20Sopenharmony_ci
46768c2ecf20Sopenharmony_ci	/* Don't send a command if only driver cleanup was requested */
46778c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags))
46788c2ecf20Sopenharmony_ci		o->complete_cmd(bp, o, pending_bit);
46798c2ecf20Sopenharmony_ci	else {
46808c2ecf20Sopenharmony_ci		/* Send a ramrod */
46818c2ecf20Sopenharmony_ci		rc = o->send_cmd(bp, params);
46828c2ecf20Sopenharmony_ci		if (rc) {
46838c2ecf20Sopenharmony_ci			o->next_state = BNX2X_Q_STATE_MAX;
46848c2ecf20Sopenharmony_ci			clear_bit(pending_bit, pending);
46858c2ecf20Sopenharmony_ci			smp_mb__after_atomic();
46868c2ecf20Sopenharmony_ci			return rc;
46878c2ecf20Sopenharmony_ci		}
46888c2ecf20Sopenharmony_ci
46898c2ecf20Sopenharmony_ci		if (test_bit(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
46908c2ecf20Sopenharmony_ci			rc = o->wait_comp(bp, o, pending_bit);
46918c2ecf20Sopenharmony_ci			if (rc)
46928c2ecf20Sopenharmony_ci				return rc;
46938c2ecf20Sopenharmony_ci
46948c2ecf20Sopenharmony_ci			return 0;
46958c2ecf20Sopenharmony_ci		}
46968c2ecf20Sopenharmony_ci	}
46978c2ecf20Sopenharmony_ci
46988c2ecf20Sopenharmony_ci	return !!test_bit(pending_bit, pending);
46998c2ecf20Sopenharmony_ci}
47008c2ecf20Sopenharmony_ci
47018c2ecf20Sopenharmony_cistatic int bnx2x_queue_set_pending(struct bnx2x_queue_sp_obj *obj,
47028c2ecf20Sopenharmony_ci				   struct bnx2x_queue_state_params *params)
47038c2ecf20Sopenharmony_ci{
47048c2ecf20Sopenharmony_ci	enum bnx2x_queue_cmd cmd = params->cmd, bit;
47058c2ecf20Sopenharmony_ci
47068c2ecf20Sopenharmony_ci	/* ACTIVATE and DEACTIVATE commands are implemented on top of
47078c2ecf20Sopenharmony_ci	 * UPDATE command.
47088c2ecf20Sopenharmony_ci	 */
47098c2ecf20Sopenharmony_ci	if ((cmd == BNX2X_Q_CMD_ACTIVATE) ||
47108c2ecf20Sopenharmony_ci	    (cmd == BNX2X_Q_CMD_DEACTIVATE))
47118c2ecf20Sopenharmony_ci		bit = BNX2X_Q_CMD_UPDATE;
47128c2ecf20Sopenharmony_ci	else
47138c2ecf20Sopenharmony_ci		bit = cmd;
47148c2ecf20Sopenharmony_ci
47158c2ecf20Sopenharmony_ci	set_bit(bit, &obj->pending);
47168c2ecf20Sopenharmony_ci	return bit;
47178c2ecf20Sopenharmony_ci}
47188c2ecf20Sopenharmony_ci
47198c2ecf20Sopenharmony_cistatic int bnx2x_queue_wait_comp(struct bnx2x *bp,
47208c2ecf20Sopenharmony_ci				 struct bnx2x_queue_sp_obj *o,
47218c2ecf20Sopenharmony_ci				 enum bnx2x_queue_cmd cmd)
47228c2ecf20Sopenharmony_ci{
47238c2ecf20Sopenharmony_ci	return bnx2x_state_wait(bp, cmd, &o->pending);
47248c2ecf20Sopenharmony_ci}
47258c2ecf20Sopenharmony_ci
47268c2ecf20Sopenharmony_ci/**
47278c2ecf20Sopenharmony_ci * bnx2x_queue_comp_cmd - complete the state change command.
47288c2ecf20Sopenharmony_ci *
47298c2ecf20Sopenharmony_ci * @bp:		device handle
47308c2ecf20Sopenharmony_ci * @o:		queue info
47318c2ecf20Sopenharmony_ci * @cmd:	command to exec
47328c2ecf20Sopenharmony_ci *
47338c2ecf20Sopenharmony_ci * Checks that the arrived completion is expected.
47348c2ecf20Sopenharmony_ci */
47358c2ecf20Sopenharmony_cistatic int bnx2x_queue_comp_cmd(struct bnx2x *bp,
47368c2ecf20Sopenharmony_ci				struct bnx2x_queue_sp_obj *o,
47378c2ecf20Sopenharmony_ci				enum bnx2x_queue_cmd cmd)
47388c2ecf20Sopenharmony_ci{
47398c2ecf20Sopenharmony_ci	unsigned long cur_pending = o->pending;
47408c2ecf20Sopenharmony_ci
47418c2ecf20Sopenharmony_ci	if (!test_and_clear_bit(cmd, &cur_pending)) {
47428c2ecf20Sopenharmony_ci		BNX2X_ERR("Bad MC reply %d for queue %d in state %d pending 0x%lx, next_state %d\n",
47438c2ecf20Sopenharmony_ci			  cmd, o->cids[BNX2X_PRIMARY_CID_INDEX],
47448c2ecf20Sopenharmony_ci			  o->state, cur_pending, o->next_state);
47458c2ecf20Sopenharmony_ci		return -EINVAL;
47468c2ecf20Sopenharmony_ci	}
47478c2ecf20Sopenharmony_ci
47488c2ecf20Sopenharmony_ci	if (o->next_tx_only >= o->max_cos)
47498c2ecf20Sopenharmony_ci		/* >= because tx only must always be smaller than cos since the
47508c2ecf20Sopenharmony_ci		 * primary connection supports COS 0
47518c2ecf20Sopenharmony_ci		 */
47528c2ecf20Sopenharmony_ci		BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d",
47538c2ecf20Sopenharmony_ci			   o->next_tx_only, o->max_cos);
47548c2ecf20Sopenharmony_ci
47558c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP,
47568c2ecf20Sopenharmony_ci	   "Completing command %d for queue %d, setting state to %d\n",
47578c2ecf20Sopenharmony_ci	   cmd, o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_state);
47588c2ecf20Sopenharmony_ci
47598c2ecf20Sopenharmony_ci	if (o->next_tx_only)  /* print num tx-only if any exist */
47608c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "primary cid %d: num tx-only cons %d\n",
47618c2ecf20Sopenharmony_ci		   o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_tx_only);
47628c2ecf20Sopenharmony_ci
47638c2ecf20Sopenharmony_ci	o->state = o->next_state;
47648c2ecf20Sopenharmony_ci	o->num_tx_only = o->next_tx_only;
47658c2ecf20Sopenharmony_ci	o->next_state = BNX2X_Q_STATE_MAX;
47668c2ecf20Sopenharmony_ci
47678c2ecf20Sopenharmony_ci	/* It's important that o->state and o->next_state are
47688c2ecf20Sopenharmony_ci	 * updated before o->pending.
47698c2ecf20Sopenharmony_ci	 */
47708c2ecf20Sopenharmony_ci	wmb();
47718c2ecf20Sopenharmony_ci
47728c2ecf20Sopenharmony_ci	clear_bit(cmd, &o->pending);
47738c2ecf20Sopenharmony_ci	smp_mb__after_atomic();
47748c2ecf20Sopenharmony_ci
47758c2ecf20Sopenharmony_ci	return 0;
47768c2ecf20Sopenharmony_ci}
47778c2ecf20Sopenharmony_ci
47788c2ecf20Sopenharmony_cistatic void bnx2x_q_fill_setup_data_e2(struct bnx2x *bp,
47798c2ecf20Sopenharmony_ci				struct bnx2x_queue_state_params *cmd_params,
47808c2ecf20Sopenharmony_ci				struct client_init_ramrod_data *data)
47818c2ecf20Sopenharmony_ci{
47828c2ecf20Sopenharmony_ci	struct bnx2x_queue_setup_params *params = &cmd_params->params.setup;
47838c2ecf20Sopenharmony_ci
47848c2ecf20Sopenharmony_ci	/* Rx data */
47858c2ecf20Sopenharmony_ci
47868c2ecf20Sopenharmony_ci	/* IPv6 TPA supported for E2 and above only */
47878c2ecf20Sopenharmony_ci	data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA_IPV6, &params->flags) *
47888c2ecf20Sopenharmony_ci				CLIENT_INIT_RX_DATA_TPA_EN_IPV6;
47898c2ecf20Sopenharmony_ci}
47908c2ecf20Sopenharmony_ci
47918c2ecf20Sopenharmony_cistatic void bnx2x_q_fill_init_general_data(struct bnx2x *bp,
47928c2ecf20Sopenharmony_ci				struct bnx2x_queue_sp_obj *o,
47938c2ecf20Sopenharmony_ci				struct bnx2x_general_setup_params *params,
47948c2ecf20Sopenharmony_ci				struct client_init_general_data *gen_data,
47958c2ecf20Sopenharmony_ci				unsigned long *flags)
47968c2ecf20Sopenharmony_ci{
47978c2ecf20Sopenharmony_ci	gen_data->client_id = o->cl_id;
47988c2ecf20Sopenharmony_ci
47998c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_Q_FLG_STATS, flags)) {
48008c2ecf20Sopenharmony_ci		gen_data->statistics_counter_id =
48018c2ecf20Sopenharmony_ci					params->stat_id;
48028c2ecf20Sopenharmony_ci		gen_data->statistics_en_flg = 1;
48038c2ecf20Sopenharmony_ci		gen_data->statistics_zero_flg =
48048c2ecf20Sopenharmony_ci			test_bit(BNX2X_Q_FLG_ZERO_STATS, flags);
48058c2ecf20Sopenharmony_ci	} else
48068c2ecf20Sopenharmony_ci		gen_data->statistics_counter_id =
48078c2ecf20Sopenharmony_ci					DISABLE_STATISTIC_COUNTER_ID_VALUE;
48088c2ecf20Sopenharmony_ci
48098c2ecf20Sopenharmony_ci	gen_data->is_fcoe_flg = test_bit(BNX2X_Q_FLG_FCOE, flags);
48108c2ecf20Sopenharmony_ci	gen_data->activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE, flags);
48118c2ecf20Sopenharmony_ci	gen_data->sp_client_id = params->spcl_id;
48128c2ecf20Sopenharmony_ci	gen_data->mtu = cpu_to_le16(params->mtu);
48138c2ecf20Sopenharmony_ci	gen_data->func_id = o->func_id;
48148c2ecf20Sopenharmony_ci
48158c2ecf20Sopenharmony_ci	gen_data->cos = params->cos;
48168c2ecf20Sopenharmony_ci
48178c2ecf20Sopenharmony_ci	gen_data->traffic_type =
48188c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_FCOE, flags) ?
48198c2ecf20Sopenharmony_ci		LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
48208c2ecf20Sopenharmony_ci
48218c2ecf20Sopenharmony_ci	gen_data->fp_hsi_ver = params->fp_hsi;
48228c2ecf20Sopenharmony_ci
48238c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d\n",
48248c2ecf20Sopenharmony_ci	   gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg);
48258c2ecf20Sopenharmony_ci}
48268c2ecf20Sopenharmony_ci
48278c2ecf20Sopenharmony_cistatic void bnx2x_q_fill_init_tx_data(struct bnx2x_queue_sp_obj *o,
48288c2ecf20Sopenharmony_ci				struct bnx2x_txq_setup_params *params,
48298c2ecf20Sopenharmony_ci				struct client_init_tx_data *tx_data,
48308c2ecf20Sopenharmony_ci				unsigned long *flags)
48318c2ecf20Sopenharmony_ci{
48328c2ecf20Sopenharmony_ci	tx_data->enforce_security_flg =
48338c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_TX_SEC, flags);
48348c2ecf20Sopenharmony_ci	tx_data->default_vlan =
48358c2ecf20Sopenharmony_ci		cpu_to_le16(params->default_vlan);
48368c2ecf20Sopenharmony_ci	tx_data->default_vlan_flg =
48378c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_DEF_VLAN, flags);
48388c2ecf20Sopenharmony_ci	tx_data->tx_switching_flg =
48398c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_TX_SWITCH, flags);
48408c2ecf20Sopenharmony_ci	tx_data->anti_spoofing_flg =
48418c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_ANTI_SPOOF, flags);
48428c2ecf20Sopenharmony_ci	tx_data->force_default_pri_flg =
48438c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_FORCE_DEFAULT_PRI, flags);
48448c2ecf20Sopenharmony_ci	tx_data->refuse_outband_vlan_flg =
48458c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_REFUSE_OUTBAND_VLAN, flags);
48468c2ecf20Sopenharmony_ci	tx_data->tunnel_lso_inc_ip_id =
48478c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_TUN_INC_INNER_IP_ID, flags);
48488c2ecf20Sopenharmony_ci	tx_data->tunnel_non_lso_pcsum_location =
48498c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_PCSUM_ON_PKT, flags) ? CSUM_ON_PKT :
48508c2ecf20Sopenharmony_ci							    CSUM_ON_BD;
48518c2ecf20Sopenharmony_ci
48528c2ecf20Sopenharmony_ci	tx_data->tx_status_block_id = params->fw_sb_id;
48538c2ecf20Sopenharmony_ci	tx_data->tx_sb_index_number = params->sb_cq_index;
48548c2ecf20Sopenharmony_ci	tx_data->tss_leading_client_id = params->tss_leading_cl_id;
48558c2ecf20Sopenharmony_ci
48568c2ecf20Sopenharmony_ci	tx_data->tx_bd_page_base.lo =
48578c2ecf20Sopenharmony_ci		cpu_to_le32(U64_LO(params->dscr_map));
48588c2ecf20Sopenharmony_ci	tx_data->tx_bd_page_base.hi =
48598c2ecf20Sopenharmony_ci		cpu_to_le32(U64_HI(params->dscr_map));
48608c2ecf20Sopenharmony_ci
48618c2ecf20Sopenharmony_ci	/* Don't configure any Tx switching mode during queue SETUP */
48628c2ecf20Sopenharmony_ci	tx_data->state = 0;
48638c2ecf20Sopenharmony_ci}
48648c2ecf20Sopenharmony_ci
48658c2ecf20Sopenharmony_cistatic void bnx2x_q_fill_init_pause_data(struct bnx2x_queue_sp_obj *o,
48668c2ecf20Sopenharmony_ci				struct rxq_pause_params *params,
48678c2ecf20Sopenharmony_ci				struct client_init_rx_data *rx_data)
48688c2ecf20Sopenharmony_ci{
48698c2ecf20Sopenharmony_ci	/* flow control data */
48708c2ecf20Sopenharmony_ci	rx_data->cqe_pause_thr_low = cpu_to_le16(params->rcq_th_lo);
48718c2ecf20Sopenharmony_ci	rx_data->cqe_pause_thr_high = cpu_to_le16(params->rcq_th_hi);
48728c2ecf20Sopenharmony_ci	rx_data->bd_pause_thr_low = cpu_to_le16(params->bd_th_lo);
48738c2ecf20Sopenharmony_ci	rx_data->bd_pause_thr_high = cpu_to_le16(params->bd_th_hi);
48748c2ecf20Sopenharmony_ci	rx_data->sge_pause_thr_low = cpu_to_le16(params->sge_th_lo);
48758c2ecf20Sopenharmony_ci	rx_data->sge_pause_thr_high = cpu_to_le16(params->sge_th_hi);
48768c2ecf20Sopenharmony_ci	rx_data->rx_cos_mask = cpu_to_le16(params->pri_map);
48778c2ecf20Sopenharmony_ci}
48788c2ecf20Sopenharmony_ci
48798c2ecf20Sopenharmony_cistatic void bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj *o,
48808c2ecf20Sopenharmony_ci				struct bnx2x_rxq_setup_params *params,
48818c2ecf20Sopenharmony_ci				struct client_init_rx_data *rx_data,
48828c2ecf20Sopenharmony_ci				unsigned long *flags)
48838c2ecf20Sopenharmony_ci{
48848c2ecf20Sopenharmony_ci	rx_data->tpa_en = test_bit(BNX2X_Q_FLG_TPA, flags) *
48858c2ecf20Sopenharmony_ci				CLIENT_INIT_RX_DATA_TPA_EN_IPV4;
48868c2ecf20Sopenharmony_ci	rx_data->tpa_en |= test_bit(BNX2X_Q_FLG_TPA_GRO, flags) *
48878c2ecf20Sopenharmony_ci				CLIENT_INIT_RX_DATA_TPA_MODE;
48888c2ecf20Sopenharmony_ci	rx_data->vmqueue_mode_en_flg = 0;
48898c2ecf20Sopenharmony_ci
48908c2ecf20Sopenharmony_ci	rx_data->cache_line_alignment_log_size =
48918c2ecf20Sopenharmony_ci		params->cache_line_log;
48928c2ecf20Sopenharmony_ci	rx_data->enable_dynamic_hc =
48938c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_DHC, flags);
48948c2ecf20Sopenharmony_ci	rx_data->max_sges_for_packet = params->max_sges_pkt;
48958c2ecf20Sopenharmony_ci	rx_data->client_qzone_id = params->cl_qzone_id;
48968c2ecf20Sopenharmony_ci	rx_data->max_agg_size = cpu_to_le16(params->tpa_agg_sz);
48978c2ecf20Sopenharmony_ci
48988c2ecf20Sopenharmony_ci	/* Always start in DROP_ALL mode */
48998c2ecf20Sopenharmony_ci	rx_data->state = cpu_to_le16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL |
49008c2ecf20Sopenharmony_ci				     CLIENT_INIT_RX_DATA_MCAST_DROP_ALL);
49018c2ecf20Sopenharmony_ci
49028c2ecf20Sopenharmony_ci	/* We don't set drop flags */
49038c2ecf20Sopenharmony_ci	rx_data->drop_ip_cs_err_flg = 0;
49048c2ecf20Sopenharmony_ci	rx_data->drop_tcp_cs_err_flg = 0;
49058c2ecf20Sopenharmony_ci	rx_data->drop_ttl0_flg = 0;
49068c2ecf20Sopenharmony_ci	rx_data->drop_udp_cs_err_flg = 0;
49078c2ecf20Sopenharmony_ci	rx_data->inner_vlan_removal_enable_flg =
49088c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_VLAN, flags);
49098c2ecf20Sopenharmony_ci	rx_data->outer_vlan_removal_enable_flg =
49108c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_OV, flags);
49118c2ecf20Sopenharmony_ci	rx_data->status_block_id = params->fw_sb_id;
49128c2ecf20Sopenharmony_ci	rx_data->rx_sb_index_number = params->sb_cq_index;
49138c2ecf20Sopenharmony_ci	rx_data->max_tpa_queues = params->max_tpa_queues;
49148c2ecf20Sopenharmony_ci	rx_data->max_bytes_on_bd = cpu_to_le16(params->buf_sz);
49158c2ecf20Sopenharmony_ci	rx_data->sge_buff_size = cpu_to_le16(params->sge_buf_sz);
49168c2ecf20Sopenharmony_ci	rx_data->bd_page_base.lo =
49178c2ecf20Sopenharmony_ci		cpu_to_le32(U64_LO(params->dscr_map));
49188c2ecf20Sopenharmony_ci	rx_data->bd_page_base.hi =
49198c2ecf20Sopenharmony_ci		cpu_to_le32(U64_HI(params->dscr_map));
49208c2ecf20Sopenharmony_ci	rx_data->sge_page_base.lo =
49218c2ecf20Sopenharmony_ci		cpu_to_le32(U64_LO(params->sge_map));
49228c2ecf20Sopenharmony_ci	rx_data->sge_page_base.hi =
49238c2ecf20Sopenharmony_ci		cpu_to_le32(U64_HI(params->sge_map));
49248c2ecf20Sopenharmony_ci	rx_data->cqe_page_base.lo =
49258c2ecf20Sopenharmony_ci		cpu_to_le32(U64_LO(params->rcq_map));
49268c2ecf20Sopenharmony_ci	rx_data->cqe_page_base.hi =
49278c2ecf20Sopenharmony_ci		cpu_to_le32(U64_HI(params->rcq_map));
49288c2ecf20Sopenharmony_ci	rx_data->is_leading_rss = test_bit(BNX2X_Q_FLG_LEADING_RSS, flags);
49298c2ecf20Sopenharmony_ci
49308c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_Q_FLG_MCAST, flags)) {
49318c2ecf20Sopenharmony_ci		rx_data->approx_mcast_engine_id = params->mcast_engine_id;
49328c2ecf20Sopenharmony_ci		rx_data->is_approx_mcast = 1;
49338c2ecf20Sopenharmony_ci	}
49348c2ecf20Sopenharmony_ci
49358c2ecf20Sopenharmony_ci	rx_data->rss_engine_id = params->rss_engine_id;
49368c2ecf20Sopenharmony_ci
49378c2ecf20Sopenharmony_ci	/* silent vlan removal */
49388c2ecf20Sopenharmony_ci	rx_data->silent_vlan_removal_flg =
49398c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, flags);
49408c2ecf20Sopenharmony_ci	rx_data->silent_vlan_value =
49418c2ecf20Sopenharmony_ci		cpu_to_le16(params->silent_removal_value);
49428c2ecf20Sopenharmony_ci	rx_data->silent_vlan_mask =
49438c2ecf20Sopenharmony_ci		cpu_to_le16(params->silent_removal_mask);
49448c2ecf20Sopenharmony_ci}
49458c2ecf20Sopenharmony_ci
49468c2ecf20Sopenharmony_ci/* initialize the general, tx and rx parts of a queue object */
49478c2ecf20Sopenharmony_cistatic void bnx2x_q_fill_setup_data_cmn(struct bnx2x *bp,
49488c2ecf20Sopenharmony_ci				struct bnx2x_queue_state_params *cmd_params,
49498c2ecf20Sopenharmony_ci				struct client_init_ramrod_data *data)
49508c2ecf20Sopenharmony_ci{
49518c2ecf20Sopenharmony_ci	bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj,
49528c2ecf20Sopenharmony_ci				       &cmd_params->params.setup.gen_params,
49538c2ecf20Sopenharmony_ci				       &data->general,
49548c2ecf20Sopenharmony_ci				       &cmd_params->params.setup.flags);
49558c2ecf20Sopenharmony_ci
49568c2ecf20Sopenharmony_ci	bnx2x_q_fill_init_tx_data(cmd_params->q_obj,
49578c2ecf20Sopenharmony_ci				  &cmd_params->params.setup.txq_params,
49588c2ecf20Sopenharmony_ci				  &data->tx,
49598c2ecf20Sopenharmony_ci				  &cmd_params->params.setup.flags);
49608c2ecf20Sopenharmony_ci
49618c2ecf20Sopenharmony_ci	bnx2x_q_fill_init_rx_data(cmd_params->q_obj,
49628c2ecf20Sopenharmony_ci				  &cmd_params->params.setup.rxq_params,
49638c2ecf20Sopenharmony_ci				  &data->rx,
49648c2ecf20Sopenharmony_ci				  &cmd_params->params.setup.flags);
49658c2ecf20Sopenharmony_ci
49668c2ecf20Sopenharmony_ci	bnx2x_q_fill_init_pause_data(cmd_params->q_obj,
49678c2ecf20Sopenharmony_ci				     &cmd_params->params.setup.pause_params,
49688c2ecf20Sopenharmony_ci				     &data->rx);
49698c2ecf20Sopenharmony_ci}
49708c2ecf20Sopenharmony_ci
49718c2ecf20Sopenharmony_ci/* initialize the general and tx parts of a tx-only queue object */
49728c2ecf20Sopenharmony_cistatic void bnx2x_q_fill_setup_tx_only(struct bnx2x *bp,
49738c2ecf20Sopenharmony_ci				struct bnx2x_queue_state_params *cmd_params,
49748c2ecf20Sopenharmony_ci				struct tx_queue_init_ramrod_data *data)
49758c2ecf20Sopenharmony_ci{
49768c2ecf20Sopenharmony_ci	bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj,
49778c2ecf20Sopenharmony_ci				       &cmd_params->params.tx_only.gen_params,
49788c2ecf20Sopenharmony_ci				       &data->general,
49798c2ecf20Sopenharmony_ci				       &cmd_params->params.tx_only.flags);
49808c2ecf20Sopenharmony_ci
49818c2ecf20Sopenharmony_ci	bnx2x_q_fill_init_tx_data(cmd_params->q_obj,
49828c2ecf20Sopenharmony_ci				  &cmd_params->params.tx_only.txq_params,
49838c2ecf20Sopenharmony_ci				  &data->tx,
49848c2ecf20Sopenharmony_ci				  &cmd_params->params.tx_only.flags);
49858c2ecf20Sopenharmony_ci
49868c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "cid %d, tx bd page lo %x hi %x",
49878c2ecf20Sopenharmony_ci			 cmd_params->q_obj->cids[0],
49888c2ecf20Sopenharmony_ci			 data->tx.tx_bd_page_base.lo,
49898c2ecf20Sopenharmony_ci			 data->tx.tx_bd_page_base.hi);
49908c2ecf20Sopenharmony_ci}
49918c2ecf20Sopenharmony_ci
49928c2ecf20Sopenharmony_ci/**
49938c2ecf20Sopenharmony_ci * bnx2x_q_init - init HW/FW queue
49948c2ecf20Sopenharmony_ci *
49958c2ecf20Sopenharmony_ci * @bp:		device handle
49968c2ecf20Sopenharmony_ci * @params:
49978c2ecf20Sopenharmony_ci *
49988c2ecf20Sopenharmony_ci * HW/FW initial Queue configuration:
49998c2ecf20Sopenharmony_ci *      - HC: Rx and Tx
50008c2ecf20Sopenharmony_ci *      - CDU context validation
50018c2ecf20Sopenharmony_ci *
50028c2ecf20Sopenharmony_ci */
50038c2ecf20Sopenharmony_cistatic inline int bnx2x_q_init(struct bnx2x *bp,
50048c2ecf20Sopenharmony_ci			       struct bnx2x_queue_state_params *params)
50058c2ecf20Sopenharmony_ci{
50068c2ecf20Sopenharmony_ci	struct bnx2x_queue_sp_obj *o = params->q_obj;
50078c2ecf20Sopenharmony_ci	struct bnx2x_queue_init_params *init = &params->params.init;
50088c2ecf20Sopenharmony_ci	u16 hc_usec;
50098c2ecf20Sopenharmony_ci	u8 cos;
50108c2ecf20Sopenharmony_ci
50118c2ecf20Sopenharmony_ci	/* Tx HC configuration */
50128c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_Q_TYPE_HAS_TX, &o->type) &&
50138c2ecf20Sopenharmony_ci	    test_bit(BNX2X_Q_FLG_HC, &init->tx.flags)) {
50148c2ecf20Sopenharmony_ci		hc_usec = init->tx.hc_rate ? 1000000 / init->tx.hc_rate : 0;
50158c2ecf20Sopenharmony_ci
50168c2ecf20Sopenharmony_ci		bnx2x_update_coalesce_sb_index(bp, init->tx.fw_sb_id,
50178c2ecf20Sopenharmony_ci			init->tx.sb_cq_index,
50188c2ecf20Sopenharmony_ci			!test_bit(BNX2X_Q_FLG_HC_EN, &init->tx.flags),
50198c2ecf20Sopenharmony_ci			hc_usec);
50208c2ecf20Sopenharmony_ci	}
50218c2ecf20Sopenharmony_ci
50228c2ecf20Sopenharmony_ci	/* Rx HC configuration */
50238c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_Q_TYPE_HAS_RX, &o->type) &&
50248c2ecf20Sopenharmony_ci	    test_bit(BNX2X_Q_FLG_HC, &init->rx.flags)) {
50258c2ecf20Sopenharmony_ci		hc_usec = init->rx.hc_rate ? 1000000 / init->rx.hc_rate : 0;
50268c2ecf20Sopenharmony_ci
50278c2ecf20Sopenharmony_ci		bnx2x_update_coalesce_sb_index(bp, init->rx.fw_sb_id,
50288c2ecf20Sopenharmony_ci			init->rx.sb_cq_index,
50298c2ecf20Sopenharmony_ci			!test_bit(BNX2X_Q_FLG_HC_EN, &init->rx.flags),
50308c2ecf20Sopenharmony_ci			hc_usec);
50318c2ecf20Sopenharmony_ci	}
50328c2ecf20Sopenharmony_ci
50338c2ecf20Sopenharmony_ci	/* Set CDU context validation values */
50348c2ecf20Sopenharmony_ci	for (cos = 0; cos < o->max_cos; cos++) {
50358c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d\n",
50368c2ecf20Sopenharmony_ci				 o->cids[cos], cos);
50378c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "context pointer %p\n", init->cxts[cos]);
50388c2ecf20Sopenharmony_ci		bnx2x_set_ctx_validation(bp, init->cxts[cos], o->cids[cos]);
50398c2ecf20Sopenharmony_ci	}
50408c2ecf20Sopenharmony_ci
50418c2ecf20Sopenharmony_ci	/* As no ramrod is sent, complete the command immediately  */
50428c2ecf20Sopenharmony_ci	o->complete_cmd(bp, o, BNX2X_Q_CMD_INIT);
50438c2ecf20Sopenharmony_ci
50448c2ecf20Sopenharmony_ci	smp_mb();
50458c2ecf20Sopenharmony_ci
50468c2ecf20Sopenharmony_ci	return 0;
50478c2ecf20Sopenharmony_ci}
50488c2ecf20Sopenharmony_ci
50498c2ecf20Sopenharmony_cistatic inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp,
50508c2ecf20Sopenharmony_ci					struct bnx2x_queue_state_params *params)
50518c2ecf20Sopenharmony_ci{
50528c2ecf20Sopenharmony_ci	struct bnx2x_queue_sp_obj *o = params->q_obj;
50538c2ecf20Sopenharmony_ci	struct client_init_ramrod_data *rdata =
50548c2ecf20Sopenharmony_ci		(struct client_init_ramrod_data *)o->rdata;
50558c2ecf20Sopenharmony_ci	dma_addr_t data_mapping = o->rdata_mapping;
50568c2ecf20Sopenharmony_ci	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
50578c2ecf20Sopenharmony_ci
50588c2ecf20Sopenharmony_ci	/* Clear the ramrod data */
50598c2ecf20Sopenharmony_ci	memset(rdata, 0, sizeof(*rdata));
50608c2ecf20Sopenharmony_ci
50618c2ecf20Sopenharmony_ci	/* Fill the ramrod data */
50628c2ecf20Sopenharmony_ci	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
50638c2ecf20Sopenharmony_ci
50648c2ecf20Sopenharmony_ci	/* No need for an explicit memory barrier here as long as we
50658c2ecf20Sopenharmony_ci	 * ensure the ordering of writing to the SPQ element
50668c2ecf20Sopenharmony_ci	 * and updating of the SPQ producer which involves a memory
50678c2ecf20Sopenharmony_ci	 * read. If the memory read is removed we will have to put a
50688c2ecf20Sopenharmony_ci	 * full memory barrier there (inside bnx2x_sp_post()).
50698c2ecf20Sopenharmony_ci	 */
50708c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
50718c2ecf20Sopenharmony_ci			     U64_HI(data_mapping),
50728c2ecf20Sopenharmony_ci			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
50738c2ecf20Sopenharmony_ci}
50748c2ecf20Sopenharmony_ci
50758c2ecf20Sopenharmony_cistatic inline int bnx2x_q_send_setup_e2(struct bnx2x *bp,
50768c2ecf20Sopenharmony_ci					struct bnx2x_queue_state_params *params)
50778c2ecf20Sopenharmony_ci{
50788c2ecf20Sopenharmony_ci	struct bnx2x_queue_sp_obj *o = params->q_obj;
50798c2ecf20Sopenharmony_ci	struct client_init_ramrod_data *rdata =
50808c2ecf20Sopenharmony_ci		(struct client_init_ramrod_data *)o->rdata;
50818c2ecf20Sopenharmony_ci	dma_addr_t data_mapping = o->rdata_mapping;
50828c2ecf20Sopenharmony_ci	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
50838c2ecf20Sopenharmony_ci
50848c2ecf20Sopenharmony_ci	/* Clear the ramrod data */
50858c2ecf20Sopenharmony_ci	memset(rdata, 0, sizeof(*rdata));
50868c2ecf20Sopenharmony_ci
50878c2ecf20Sopenharmony_ci	/* Fill the ramrod data */
50888c2ecf20Sopenharmony_ci	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
50898c2ecf20Sopenharmony_ci	bnx2x_q_fill_setup_data_e2(bp, params, rdata);
50908c2ecf20Sopenharmony_ci
50918c2ecf20Sopenharmony_ci	/* No need for an explicit memory barrier here as long as we
50928c2ecf20Sopenharmony_ci	 * ensure the ordering of writing to the SPQ element
50938c2ecf20Sopenharmony_ci	 * and updating of the SPQ producer which involves a memory
50948c2ecf20Sopenharmony_ci	 * read. If the memory read is removed we will have to put a
50958c2ecf20Sopenharmony_ci	 * full memory barrier there (inside bnx2x_sp_post()).
50968c2ecf20Sopenharmony_ci	 */
50978c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
50988c2ecf20Sopenharmony_ci			     U64_HI(data_mapping),
50998c2ecf20Sopenharmony_ci			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
51008c2ecf20Sopenharmony_ci}
51018c2ecf20Sopenharmony_ci
51028c2ecf20Sopenharmony_cistatic inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
51038c2ecf20Sopenharmony_ci				  struct bnx2x_queue_state_params *params)
51048c2ecf20Sopenharmony_ci{
51058c2ecf20Sopenharmony_ci	struct bnx2x_queue_sp_obj *o = params->q_obj;
51068c2ecf20Sopenharmony_ci	struct tx_queue_init_ramrod_data *rdata =
51078c2ecf20Sopenharmony_ci		(struct tx_queue_init_ramrod_data *)o->rdata;
51088c2ecf20Sopenharmony_ci	dma_addr_t data_mapping = o->rdata_mapping;
51098c2ecf20Sopenharmony_ci	int ramrod = RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP;
51108c2ecf20Sopenharmony_ci	struct bnx2x_queue_setup_tx_only_params *tx_only_params =
51118c2ecf20Sopenharmony_ci		&params->params.tx_only;
51128c2ecf20Sopenharmony_ci	u8 cid_index = tx_only_params->cid_index;
51138c2ecf20Sopenharmony_ci
51148c2ecf20Sopenharmony_ci	if (cid_index >= o->max_cos) {
51158c2ecf20Sopenharmony_ci		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
51168c2ecf20Sopenharmony_ci			  o->cl_id, cid_index);
51178c2ecf20Sopenharmony_ci		return -EINVAL;
51188c2ecf20Sopenharmony_ci	}
51198c2ecf20Sopenharmony_ci
51208c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d\n",
51218c2ecf20Sopenharmony_ci			 tx_only_params->gen_params.cos,
51228c2ecf20Sopenharmony_ci			 tx_only_params->gen_params.spcl_id);
51238c2ecf20Sopenharmony_ci
51248c2ecf20Sopenharmony_ci	/* Clear the ramrod data */
51258c2ecf20Sopenharmony_ci	memset(rdata, 0, sizeof(*rdata));
51268c2ecf20Sopenharmony_ci
51278c2ecf20Sopenharmony_ci	/* Fill the ramrod data */
51288c2ecf20Sopenharmony_ci	bnx2x_q_fill_setup_tx_only(bp, params, rdata);
51298c2ecf20Sopenharmony_ci
51308c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "sending tx-only ramrod: cid %d, client-id %d, sp-client id %d, cos %d\n",
51318c2ecf20Sopenharmony_ci			 o->cids[cid_index], rdata->general.client_id,
51328c2ecf20Sopenharmony_ci			 rdata->general.sp_client_id, rdata->general.cos);
51338c2ecf20Sopenharmony_ci
51348c2ecf20Sopenharmony_ci	/* No need for an explicit memory barrier here as long as we
51358c2ecf20Sopenharmony_ci	 * ensure the ordering of writing to the SPQ element
51368c2ecf20Sopenharmony_ci	 * and updating of the SPQ producer which involves a memory
51378c2ecf20Sopenharmony_ci	 * read. If the memory read is removed we will have to put a
51388c2ecf20Sopenharmony_ci	 * full memory barrier there (inside bnx2x_sp_post()).
51398c2ecf20Sopenharmony_ci	 */
51408c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, ramrod, o->cids[cid_index],
51418c2ecf20Sopenharmony_ci			     U64_HI(data_mapping),
51428c2ecf20Sopenharmony_ci			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
51438c2ecf20Sopenharmony_ci}
51448c2ecf20Sopenharmony_ci
51458c2ecf20Sopenharmony_cistatic void bnx2x_q_fill_update_data(struct bnx2x *bp,
51468c2ecf20Sopenharmony_ci				     struct bnx2x_queue_sp_obj *obj,
51478c2ecf20Sopenharmony_ci				     struct bnx2x_queue_update_params *params,
51488c2ecf20Sopenharmony_ci				     struct client_update_ramrod_data *data)
51498c2ecf20Sopenharmony_ci{
51508c2ecf20Sopenharmony_ci	/* Client ID of the client to update */
51518c2ecf20Sopenharmony_ci	data->client_id = obj->cl_id;
51528c2ecf20Sopenharmony_ci
51538c2ecf20Sopenharmony_ci	/* Function ID of the client to update */
51548c2ecf20Sopenharmony_ci	data->func_id = obj->func_id;
51558c2ecf20Sopenharmony_ci
51568c2ecf20Sopenharmony_ci	/* Default VLAN value */
51578c2ecf20Sopenharmony_ci	data->default_vlan = cpu_to_le16(params->def_vlan);
51588c2ecf20Sopenharmony_ci
51598c2ecf20Sopenharmony_ci	/* Inner VLAN stripping */
51608c2ecf20Sopenharmony_ci	data->inner_vlan_removal_enable_flg =
51618c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM, &params->update_flags);
51628c2ecf20Sopenharmony_ci	data->inner_vlan_removal_change_flg =
51638c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG,
51648c2ecf20Sopenharmony_ci			 &params->update_flags);
51658c2ecf20Sopenharmony_ci
51668c2ecf20Sopenharmony_ci	/* Outer VLAN stripping */
51678c2ecf20Sopenharmony_ci	data->outer_vlan_removal_enable_flg =
51688c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM, &params->update_flags);
51698c2ecf20Sopenharmony_ci	data->outer_vlan_removal_change_flg =
51708c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM_CHNG,
51718c2ecf20Sopenharmony_ci			 &params->update_flags);
51728c2ecf20Sopenharmony_ci
51738c2ecf20Sopenharmony_ci	/* Drop packets that have source MAC that doesn't belong to this
51748c2ecf20Sopenharmony_ci	 * Queue.
51758c2ecf20Sopenharmony_ci	 */
51768c2ecf20Sopenharmony_ci	data->anti_spoofing_enable_flg =
51778c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF, &params->update_flags);
51788c2ecf20Sopenharmony_ci	data->anti_spoofing_change_flg =
51798c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF_CHNG, &params->update_flags);
51808c2ecf20Sopenharmony_ci
51818c2ecf20Sopenharmony_ci	/* Activate/Deactivate */
51828c2ecf20Sopenharmony_ci	data->activate_flg =
51838c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_ACTIVATE, &params->update_flags);
51848c2ecf20Sopenharmony_ci	data->activate_change_flg =
51858c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &params->update_flags);
51868c2ecf20Sopenharmony_ci
51878c2ecf20Sopenharmony_ci	/* Enable default VLAN */
51888c2ecf20Sopenharmony_ci	data->default_vlan_enable_flg =
51898c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN, &params->update_flags);
51908c2ecf20Sopenharmony_ci	data->default_vlan_change_flg =
51918c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
51928c2ecf20Sopenharmony_ci			 &params->update_flags);
51938c2ecf20Sopenharmony_ci
51948c2ecf20Sopenharmony_ci	/* silent vlan removal */
51958c2ecf20Sopenharmony_ci	data->silent_vlan_change_flg =
51968c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
51978c2ecf20Sopenharmony_ci			 &params->update_flags);
51988c2ecf20Sopenharmony_ci	data->silent_vlan_removal_flg =
51998c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM, &params->update_flags);
52008c2ecf20Sopenharmony_ci	data->silent_vlan_value = cpu_to_le16(params->silent_removal_value);
52018c2ecf20Sopenharmony_ci	data->silent_vlan_mask = cpu_to_le16(params->silent_removal_mask);
52028c2ecf20Sopenharmony_ci
52038c2ecf20Sopenharmony_ci	/* tx switching */
52048c2ecf20Sopenharmony_ci	data->tx_switching_flg =
52058c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_TX_SWITCHING, &params->update_flags);
52068c2ecf20Sopenharmony_ci	data->tx_switching_change_flg =
52078c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_TX_SWITCHING_CHNG,
52088c2ecf20Sopenharmony_ci			 &params->update_flags);
52098c2ecf20Sopenharmony_ci
52108c2ecf20Sopenharmony_ci	/* PTP */
52118c2ecf20Sopenharmony_ci	data->handle_ptp_pkts_flg =
52128c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_PTP_PKTS, &params->update_flags);
52138c2ecf20Sopenharmony_ci	data->handle_ptp_pkts_change_flg =
52148c2ecf20Sopenharmony_ci		test_bit(BNX2X_Q_UPDATE_PTP_PKTS_CHNG, &params->update_flags);
52158c2ecf20Sopenharmony_ci}
52168c2ecf20Sopenharmony_ci
52178c2ecf20Sopenharmony_cistatic inline int bnx2x_q_send_update(struct bnx2x *bp,
52188c2ecf20Sopenharmony_ci				      struct bnx2x_queue_state_params *params)
52198c2ecf20Sopenharmony_ci{
52208c2ecf20Sopenharmony_ci	struct bnx2x_queue_sp_obj *o = params->q_obj;
52218c2ecf20Sopenharmony_ci	struct client_update_ramrod_data *rdata =
52228c2ecf20Sopenharmony_ci		(struct client_update_ramrod_data *)o->rdata;
52238c2ecf20Sopenharmony_ci	dma_addr_t data_mapping = o->rdata_mapping;
52248c2ecf20Sopenharmony_ci	struct bnx2x_queue_update_params *update_params =
52258c2ecf20Sopenharmony_ci		&params->params.update;
52268c2ecf20Sopenharmony_ci	u8 cid_index = update_params->cid_index;
52278c2ecf20Sopenharmony_ci
52288c2ecf20Sopenharmony_ci	if (cid_index >= o->max_cos) {
52298c2ecf20Sopenharmony_ci		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
52308c2ecf20Sopenharmony_ci			  o->cl_id, cid_index);
52318c2ecf20Sopenharmony_ci		return -EINVAL;
52328c2ecf20Sopenharmony_ci	}
52338c2ecf20Sopenharmony_ci
52348c2ecf20Sopenharmony_ci	/* Clear the ramrod data */
52358c2ecf20Sopenharmony_ci	memset(rdata, 0, sizeof(*rdata));
52368c2ecf20Sopenharmony_ci
52378c2ecf20Sopenharmony_ci	/* Fill the ramrod data */
52388c2ecf20Sopenharmony_ci	bnx2x_q_fill_update_data(bp, o, update_params, rdata);
52398c2ecf20Sopenharmony_ci
52408c2ecf20Sopenharmony_ci	/* No need for an explicit memory barrier here as long as we
52418c2ecf20Sopenharmony_ci	 * ensure the ordering of writing to the SPQ element
52428c2ecf20Sopenharmony_ci	 * and updating of the SPQ producer which involves a memory
52438c2ecf20Sopenharmony_ci	 * read. If the memory read is removed we will have to put a
52448c2ecf20Sopenharmony_ci	 * full memory barrier there (inside bnx2x_sp_post()).
52458c2ecf20Sopenharmony_ci	 */
52468c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
52478c2ecf20Sopenharmony_ci			     o->cids[cid_index], U64_HI(data_mapping),
52488c2ecf20Sopenharmony_ci			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
52498c2ecf20Sopenharmony_ci}
52508c2ecf20Sopenharmony_ci
52518c2ecf20Sopenharmony_ci/**
52528c2ecf20Sopenharmony_ci * bnx2x_q_send_deactivate - send DEACTIVATE command
52538c2ecf20Sopenharmony_ci *
52548c2ecf20Sopenharmony_ci * @bp:		device handle
52558c2ecf20Sopenharmony_ci * @params:
52568c2ecf20Sopenharmony_ci *
52578c2ecf20Sopenharmony_ci * implemented using the UPDATE command.
52588c2ecf20Sopenharmony_ci */
52598c2ecf20Sopenharmony_cistatic inline int bnx2x_q_send_deactivate(struct bnx2x *bp,
52608c2ecf20Sopenharmony_ci					struct bnx2x_queue_state_params *params)
52618c2ecf20Sopenharmony_ci{
52628c2ecf20Sopenharmony_ci	struct bnx2x_queue_update_params *update = &params->params.update;
52638c2ecf20Sopenharmony_ci
52648c2ecf20Sopenharmony_ci	memset(update, 0, sizeof(*update));
52658c2ecf20Sopenharmony_ci
52668c2ecf20Sopenharmony_ci	__set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
52678c2ecf20Sopenharmony_ci
52688c2ecf20Sopenharmony_ci	return bnx2x_q_send_update(bp, params);
52698c2ecf20Sopenharmony_ci}
52708c2ecf20Sopenharmony_ci
52718c2ecf20Sopenharmony_ci/**
52728c2ecf20Sopenharmony_ci * bnx2x_q_send_activate - send ACTIVATE command
52738c2ecf20Sopenharmony_ci *
52748c2ecf20Sopenharmony_ci * @bp:		device handle
52758c2ecf20Sopenharmony_ci * @params:
52768c2ecf20Sopenharmony_ci *
52778c2ecf20Sopenharmony_ci * implemented using the UPDATE command.
52788c2ecf20Sopenharmony_ci */
52798c2ecf20Sopenharmony_cistatic inline int bnx2x_q_send_activate(struct bnx2x *bp,
52808c2ecf20Sopenharmony_ci					struct bnx2x_queue_state_params *params)
52818c2ecf20Sopenharmony_ci{
52828c2ecf20Sopenharmony_ci	struct bnx2x_queue_update_params *update = &params->params.update;
52838c2ecf20Sopenharmony_ci
52848c2ecf20Sopenharmony_ci	memset(update, 0, sizeof(*update));
52858c2ecf20Sopenharmony_ci
52868c2ecf20Sopenharmony_ci	__set_bit(BNX2X_Q_UPDATE_ACTIVATE, &update->update_flags);
52878c2ecf20Sopenharmony_ci	__set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
52888c2ecf20Sopenharmony_ci
52898c2ecf20Sopenharmony_ci	return bnx2x_q_send_update(bp, params);
52908c2ecf20Sopenharmony_ci}
52918c2ecf20Sopenharmony_ci
52928c2ecf20Sopenharmony_cistatic void bnx2x_q_fill_update_tpa_data(struct bnx2x *bp,
52938c2ecf20Sopenharmony_ci				struct bnx2x_queue_sp_obj *obj,
52948c2ecf20Sopenharmony_ci				struct bnx2x_queue_update_tpa_params *params,
52958c2ecf20Sopenharmony_ci				struct tpa_update_ramrod_data *data)
52968c2ecf20Sopenharmony_ci{
52978c2ecf20Sopenharmony_ci	data->client_id = obj->cl_id;
52988c2ecf20Sopenharmony_ci	data->complete_on_both_clients = params->complete_on_both_clients;
52998c2ecf20Sopenharmony_ci	data->dont_verify_rings_pause_thr_flg =
53008c2ecf20Sopenharmony_ci		params->dont_verify_thr;
53018c2ecf20Sopenharmony_ci	data->max_agg_size = cpu_to_le16(params->max_agg_sz);
53028c2ecf20Sopenharmony_ci	data->max_sges_for_packet = params->max_sges_pkt;
53038c2ecf20Sopenharmony_ci	data->max_tpa_queues = params->max_tpa_queues;
53048c2ecf20Sopenharmony_ci	data->sge_buff_size = cpu_to_le16(params->sge_buff_sz);
53058c2ecf20Sopenharmony_ci	data->sge_page_base_hi = cpu_to_le32(U64_HI(params->sge_map));
53068c2ecf20Sopenharmony_ci	data->sge_page_base_lo = cpu_to_le32(U64_LO(params->sge_map));
53078c2ecf20Sopenharmony_ci	data->sge_pause_thr_high = cpu_to_le16(params->sge_pause_thr_high);
53088c2ecf20Sopenharmony_ci	data->sge_pause_thr_low = cpu_to_le16(params->sge_pause_thr_low);
53098c2ecf20Sopenharmony_ci	data->tpa_mode = params->tpa_mode;
53108c2ecf20Sopenharmony_ci	data->update_ipv4 = params->update_ipv4;
53118c2ecf20Sopenharmony_ci	data->update_ipv6 = params->update_ipv6;
53128c2ecf20Sopenharmony_ci}
53138c2ecf20Sopenharmony_ci
53148c2ecf20Sopenharmony_cistatic inline int bnx2x_q_send_update_tpa(struct bnx2x *bp,
53158c2ecf20Sopenharmony_ci					struct bnx2x_queue_state_params *params)
53168c2ecf20Sopenharmony_ci{
53178c2ecf20Sopenharmony_ci	struct bnx2x_queue_sp_obj *o = params->q_obj;
53188c2ecf20Sopenharmony_ci	struct tpa_update_ramrod_data *rdata =
53198c2ecf20Sopenharmony_ci		(struct tpa_update_ramrod_data *)o->rdata;
53208c2ecf20Sopenharmony_ci	dma_addr_t data_mapping = o->rdata_mapping;
53218c2ecf20Sopenharmony_ci	struct bnx2x_queue_update_tpa_params *update_tpa_params =
53228c2ecf20Sopenharmony_ci		&params->params.update_tpa;
53238c2ecf20Sopenharmony_ci	u16 type;
53248c2ecf20Sopenharmony_ci
53258c2ecf20Sopenharmony_ci	/* Clear the ramrod data */
53268c2ecf20Sopenharmony_ci	memset(rdata, 0, sizeof(*rdata));
53278c2ecf20Sopenharmony_ci
53288c2ecf20Sopenharmony_ci	/* Fill the ramrod data */
53298c2ecf20Sopenharmony_ci	bnx2x_q_fill_update_tpa_data(bp, o, update_tpa_params, rdata);
53308c2ecf20Sopenharmony_ci
53318c2ecf20Sopenharmony_ci	/* Add the function id inside the type, so that sp post function
53328c2ecf20Sopenharmony_ci	 * doesn't automatically add the PF func-id, this is required
53338c2ecf20Sopenharmony_ci	 * for operations done by PFs on behalf of their VFs
53348c2ecf20Sopenharmony_ci	 */
53358c2ecf20Sopenharmony_ci	type = ETH_CONNECTION_TYPE |
53368c2ecf20Sopenharmony_ci		((o->func_id) << SPE_HDR_FUNCTION_ID_SHIFT);
53378c2ecf20Sopenharmony_ci
53388c2ecf20Sopenharmony_ci	/* No need for an explicit memory barrier here as long as we
53398c2ecf20Sopenharmony_ci	 * ensure the ordering of writing to the SPQ element
53408c2ecf20Sopenharmony_ci	 * and updating of the SPQ producer which involves a memory
53418c2ecf20Sopenharmony_ci	 * read. If the memory read is removed we will have to put a
53428c2ecf20Sopenharmony_ci	 * full memory barrier there (inside bnx2x_sp_post()).
53438c2ecf20Sopenharmony_ci	 */
53448c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TPA_UPDATE,
53458c2ecf20Sopenharmony_ci			     o->cids[BNX2X_PRIMARY_CID_INDEX],
53468c2ecf20Sopenharmony_ci			     U64_HI(data_mapping),
53478c2ecf20Sopenharmony_ci			     U64_LO(data_mapping), type);
53488c2ecf20Sopenharmony_ci}
53498c2ecf20Sopenharmony_ci
53508c2ecf20Sopenharmony_cistatic inline int bnx2x_q_send_halt(struct bnx2x *bp,
53518c2ecf20Sopenharmony_ci				    struct bnx2x_queue_state_params *params)
53528c2ecf20Sopenharmony_ci{
53538c2ecf20Sopenharmony_ci	struct bnx2x_queue_sp_obj *o = params->q_obj;
53548c2ecf20Sopenharmony_ci
53558c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT,
53568c2ecf20Sopenharmony_ci			     o->cids[BNX2X_PRIMARY_CID_INDEX], 0, o->cl_id,
53578c2ecf20Sopenharmony_ci			     ETH_CONNECTION_TYPE);
53588c2ecf20Sopenharmony_ci}
53598c2ecf20Sopenharmony_ci
53608c2ecf20Sopenharmony_cistatic inline int bnx2x_q_send_cfc_del(struct bnx2x *bp,
53618c2ecf20Sopenharmony_ci				       struct bnx2x_queue_state_params *params)
53628c2ecf20Sopenharmony_ci{
53638c2ecf20Sopenharmony_ci	struct bnx2x_queue_sp_obj *o = params->q_obj;
53648c2ecf20Sopenharmony_ci	u8 cid_idx = params->params.cfc_del.cid_index;
53658c2ecf20Sopenharmony_ci
53668c2ecf20Sopenharmony_ci	if (cid_idx >= o->max_cos) {
53678c2ecf20Sopenharmony_ci		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
53688c2ecf20Sopenharmony_ci			  o->cl_id, cid_idx);
53698c2ecf20Sopenharmony_ci		return -EINVAL;
53708c2ecf20Sopenharmony_ci	}
53718c2ecf20Sopenharmony_ci
53728c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL,
53738c2ecf20Sopenharmony_ci			     o->cids[cid_idx], 0, 0, NONE_CONNECTION_TYPE);
53748c2ecf20Sopenharmony_ci}
53758c2ecf20Sopenharmony_ci
53768c2ecf20Sopenharmony_cistatic inline int bnx2x_q_send_terminate(struct bnx2x *bp,
53778c2ecf20Sopenharmony_ci					struct bnx2x_queue_state_params *params)
53788c2ecf20Sopenharmony_ci{
53798c2ecf20Sopenharmony_ci	struct bnx2x_queue_sp_obj *o = params->q_obj;
53808c2ecf20Sopenharmony_ci	u8 cid_index = params->params.terminate.cid_index;
53818c2ecf20Sopenharmony_ci
53828c2ecf20Sopenharmony_ci	if (cid_index >= o->max_cos) {
53838c2ecf20Sopenharmony_ci		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
53848c2ecf20Sopenharmony_ci			  o->cl_id, cid_index);
53858c2ecf20Sopenharmony_ci		return -EINVAL;
53868c2ecf20Sopenharmony_ci	}
53878c2ecf20Sopenharmony_ci
53888c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE,
53898c2ecf20Sopenharmony_ci			     o->cids[cid_index], 0, 0, ETH_CONNECTION_TYPE);
53908c2ecf20Sopenharmony_ci}
53918c2ecf20Sopenharmony_ci
53928c2ecf20Sopenharmony_cistatic inline int bnx2x_q_send_empty(struct bnx2x *bp,
53938c2ecf20Sopenharmony_ci				     struct bnx2x_queue_state_params *params)
53948c2ecf20Sopenharmony_ci{
53958c2ecf20Sopenharmony_ci	struct bnx2x_queue_sp_obj *o = params->q_obj;
53968c2ecf20Sopenharmony_ci
53978c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_EMPTY,
53988c2ecf20Sopenharmony_ci			     o->cids[BNX2X_PRIMARY_CID_INDEX], 0, 0,
53998c2ecf20Sopenharmony_ci			     ETH_CONNECTION_TYPE);
54008c2ecf20Sopenharmony_ci}
54018c2ecf20Sopenharmony_ci
54028c2ecf20Sopenharmony_cistatic inline int bnx2x_queue_send_cmd_cmn(struct bnx2x *bp,
54038c2ecf20Sopenharmony_ci					struct bnx2x_queue_state_params *params)
54048c2ecf20Sopenharmony_ci{
54058c2ecf20Sopenharmony_ci	switch (params->cmd) {
54068c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_INIT:
54078c2ecf20Sopenharmony_ci		return bnx2x_q_init(bp, params);
54088c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_SETUP_TX_ONLY:
54098c2ecf20Sopenharmony_ci		return bnx2x_q_send_setup_tx_only(bp, params);
54108c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_DEACTIVATE:
54118c2ecf20Sopenharmony_ci		return bnx2x_q_send_deactivate(bp, params);
54128c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_ACTIVATE:
54138c2ecf20Sopenharmony_ci		return bnx2x_q_send_activate(bp, params);
54148c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_UPDATE:
54158c2ecf20Sopenharmony_ci		return bnx2x_q_send_update(bp, params);
54168c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_UPDATE_TPA:
54178c2ecf20Sopenharmony_ci		return bnx2x_q_send_update_tpa(bp, params);
54188c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_HALT:
54198c2ecf20Sopenharmony_ci		return bnx2x_q_send_halt(bp, params);
54208c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_CFC_DEL:
54218c2ecf20Sopenharmony_ci		return bnx2x_q_send_cfc_del(bp, params);
54228c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_TERMINATE:
54238c2ecf20Sopenharmony_ci		return bnx2x_q_send_terminate(bp, params);
54248c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_EMPTY:
54258c2ecf20Sopenharmony_ci		return bnx2x_q_send_empty(bp, params);
54268c2ecf20Sopenharmony_ci	default:
54278c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown command: %d\n", params->cmd);
54288c2ecf20Sopenharmony_ci		return -EINVAL;
54298c2ecf20Sopenharmony_ci	}
54308c2ecf20Sopenharmony_ci}
54318c2ecf20Sopenharmony_ci
54328c2ecf20Sopenharmony_cistatic int bnx2x_queue_send_cmd_e1x(struct bnx2x *bp,
54338c2ecf20Sopenharmony_ci				    struct bnx2x_queue_state_params *params)
54348c2ecf20Sopenharmony_ci{
54358c2ecf20Sopenharmony_ci	switch (params->cmd) {
54368c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_SETUP:
54378c2ecf20Sopenharmony_ci		return bnx2x_q_send_setup_e1x(bp, params);
54388c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_INIT:
54398c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_SETUP_TX_ONLY:
54408c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_DEACTIVATE:
54418c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_ACTIVATE:
54428c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_UPDATE:
54438c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_UPDATE_TPA:
54448c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_HALT:
54458c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_CFC_DEL:
54468c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_TERMINATE:
54478c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_EMPTY:
54488c2ecf20Sopenharmony_ci		return bnx2x_queue_send_cmd_cmn(bp, params);
54498c2ecf20Sopenharmony_ci	default:
54508c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown command: %d\n", params->cmd);
54518c2ecf20Sopenharmony_ci		return -EINVAL;
54528c2ecf20Sopenharmony_ci	}
54538c2ecf20Sopenharmony_ci}
54548c2ecf20Sopenharmony_ci
54558c2ecf20Sopenharmony_cistatic int bnx2x_queue_send_cmd_e2(struct bnx2x *bp,
54568c2ecf20Sopenharmony_ci				   struct bnx2x_queue_state_params *params)
54578c2ecf20Sopenharmony_ci{
54588c2ecf20Sopenharmony_ci	switch (params->cmd) {
54598c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_SETUP:
54608c2ecf20Sopenharmony_ci		return bnx2x_q_send_setup_e2(bp, params);
54618c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_INIT:
54628c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_SETUP_TX_ONLY:
54638c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_DEACTIVATE:
54648c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_ACTIVATE:
54658c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_UPDATE:
54668c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_UPDATE_TPA:
54678c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_HALT:
54688c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_CFC_DEL:
54698c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_TERMINATE:
54708c2ecf20Sopenharmony_ci	case BNX2X_Q_CMD_EMPTY:
54718c2ecf20Sopenharmony_ci		return bnx2x_queue_send_cmd_cmn(bp, params);
54728c2ecf20Sopenharmony_ci	default:
54738c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown command: %d\n", params->cmd);
54748c2ecf20Sopenharmony_ci		return -EINVAL;
54758c2ecf20Sopenharmony_ci	}
54768c2ecf20Sopenharmony_ci}
54778c2ecf20Sopenharmony_ci
54788c2ecf20Sopenharmony_ci/**
54798c2ecf20Sopenharmony_ci * bnx2x_queue_chk_transition - check state machine of a regular Queue
54808c2ecf20Sopenharmony_ci *
54818c2ecf20Sopenharmony_ci * @bp:		device handle
54828c2ecf20Sopenharmony_ci * @o:		queue info
54838c2ecf20Sopenharmony_ci * @params:	queue state
54848c2ecf20Sopenharmony_ci *
54858c2ecf20Sopenharmony_ci * (not Forwarding)
54868c2ecf20Sopenharmony_ci * It both checks if the requested command is legal in a current
54878c2ecf20Sopenharmony_ci * state and, if it's legal, sets a `next_state' in the object
54888c2ecf20Sopenharmony_ci * that will be used in the completion flow to set the `state'
54898c2ecf20Sopenharmony_ci * of the object.
54908c2ecf20Sopenharmony_ci *
54918c2ecf20Sopenharmony_ci * returns 0 if a requested command is a legal transition,
54928c2ecf20Sopenharmony_ci *         -EINVAL otherwise.
54938c2ecf20Sopenharmony_ci */
54948c2ecf20Sopenharmony_cistatic int bnx2x_queue_chk_transition(struct bnx2x *bp,
54958c2ecf20Sopenharmony_ci				      struct bnx2x_queue_sp_obj *o,
54968c2ecf20Sopenharmony_ci				      struct bnx2x_queue_state_params *params)
54978c2ecf20Sopenharmony_ci{
54988c2ecf20Sopenharmony_ci	enum bnx2x_q_state state = o->state, next_state = BNX2X_Q_STATE_MAX;
54998c2ecf20Sopenharmony_ci	enum bnx2x_queue_cmd cmd = params->cmd;
55008c2ecf20Sopenharmony_ci	struct bnx2x_queue_update_params *update_params =
55018c2ecf20Sopenharmony_ci		 &params->params.update;
55028c2ecf20Sopenharmony_ci	u8 next_tx_only = o->num_tx_only;
55038c2ecf20Sopenharmony_ci
55048c2ecf20Sopenharmony_ci	/* Forget all pending for completion commands if a driver only state
55058c2ecf20Sopenharmony_ci	 * transition has been requested.
55068c2ecf20Sopenharmony_ci	 */
55078c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
55088c2ecf20Sopenharmony_ci		o->pending = 0;
55098c2ecf20Sopenharmony_ci		o->next_state = BNX2X_Q_STATE_MAX;
55108c2ecf20Sopenharmony_ci	}
55118c2ecf20Sopenharmony_ci
55128c2ecf20Sopenharmony_ci	/* Don't allow a next state transition if we are in the middle of
55138c2ecf20Sopenharmony_ci	 * the previous one.
55148c2ecf20Sopenharmony_ci	 */
55158c2ecf20Sopenharmony_ci	if (o->pending) {
55168c2ecf20Sopenharmony_ci		BNX2X_ERR("Blocking transition since pending was %lx\n",
55178c2ecf20Sopenharmony_ci			  o->pending);
55188c2ecf20Sopenharmony_ci		return -EBUSY;
55198c2ecf20Sopenharmony_ci	}
55208c2ecf20Sopenharmony_ci
55218c2ecf20Sopenharmony_ci	switch (state) {
55228c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_RESET:
55238c2ecf20Sopenharmony_ci		if (cmd == BNX2X_Q_CMD_INIT)
55248c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_INITIALIZED;
55258c2ecf20Sopenharmony_ci
55268c2ecf20Sopenharmony_ci		break;
55278c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_INITIALIZED:
55288c2ecf20Sopenharmony_ci		if (cmd == BNX2X_Q_CMD_SETUP) {
55298c2ecf20Sopenharmony_ci			if (test_bit(BNX2X_Q_FLG_ACTIVE,
55308c2ecf20Sopenharmony_ci				     &params->params.setup.flags))
55318c2ecf20Sopenharmony_ci				next_state = BNX2X_Q_STATE_ACTIVE;
55328c2ecf20Sopenharmony_ci			else
55338c2ecf20Sopenharmony_ci				next_state = BNX2X_Q_STATE_INACTIVE;
55348c2ecf20Sopenharmony_ci		}
55358c2ecf20Sopenharmony_ci
55368c2ecf20Sopenharmony_ci		break;
55378c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_ACTIVE:
55388c2ecf20Sopenharmony_ci		if (cmd == BNX2X_Q_CMD_DEACTIVATE)
55398c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_INACTIVE;
55408c2ecf20Sopenharmony_ci
55418c2ecf20Sopenharmony_ci		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
55428c2ecf20Sopenharmony_ci			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
55438c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_ACTIVE;
55448c2ecf20Sopenharmony_ci
55458c2ecf20Sopenharmony_ci		else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) {
55468c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_MULTI_COS;
55478c2ecf20Sopenharmony_ci			next_tx_only = 1;
55488c2ecf20Sopenharmony_ci		}
55498c2ecf20Sopenharmony_ci
55508c2ecf20Sopenharmony_ci		else if (cmd == BNX2X_Q_CMD_HALT)
55518c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_STOPPED;
55528c2ecf20Sopenharmony_ci
55538c2ecf20Sopenharmony_ci		else if (cmd == BNX2X_Q_CMD_UPDATE) {
55548c2ecf20Sopenharmony_ci			/* If "active" state change is requested, update the
55558c2ecf20Sopenharmony_ci			 *  state accordingly.
55568c2ecf20Sopenharmony_ci			 */
55578c2ecf20Sopenharmony_ci			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
55588c2ecf20Sopenharmony_ci				     &update_params->update_flags) &&
55598c2ecf20Sopenharmony_ci			    !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
55608c2ecf20Sopenharmony_ci				      &update_params->update_flags))
55618c2ecf20Sopenharmony_ci				next_state = BNX2X_Q_STATE_INACTIVE;
55628c2ecf20Sopenharmony_ci			else
55638c2ecf20Sopenharmony_ci				next_state = BNX2X_Q_STATE_ACTIVE;
55648c2ecf20Sopenharmony_ci		}
55658c2ecf20Sopenharmony_ci
55668c2ecf20Sopenharmony_ci		break;
55678c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_MULTI_COS:
55688c2ecf20Sopenharmony_ci		if (cmd == BNX2X_Q_CMD_TERMINATE)
55698c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_MCOS_TERMINATED;
55708c2ecf20Sopenharmony_ci
55718c2ecf20Sopenharmony_ci		else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) {
55728c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_MULTI_COS;
55738c2ecf20Sopenharmony_ci			next_tx_only = o->num_tx_only + 1;
55748c2ecf20Sopenharmony_ci		}
55758c2ecf20Sopenharmony_ci
55768c2ecf20Sopenharmony_ci		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
55778c2ecf20Sopenharmony_ci			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
55788c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_MULTI_COS;
55798c2ecf20Sopenharmony_ci
55808c2ecf20Sopenharmony_ci		else if (cmd == BNX2X_Q_CMD_UPDATE) {
55818c2ecf20Sopenharmony_ci			/* If "active" state change is requested, update the
55828c2ecf20Sopenharmony_ci			 *  state accordingly.
55838c2ecf20Sopenharmony_ci			 */
55848c2ecf20Sopenharmony_ci			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
55858c2ecf20Sopenharmony_ci				     &update_params->update_flags) &&
55868c2ecf20Sopenharmony_ci			    !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
55878c2ecf20Sopenharmony_ci				      &update_params->update_flags))
55888c2ecf20Sopenharmony_ci				next_state = BNX2X_Q_STATE_INACTIVE;
55898c2ecf20Sopenharmony_ci			else
55908c2ecf20Sopenharmony_ci				next_state = BNX2X_Q_STATE_MULTI_COS;
55918c2ecf20Sopenharmony_ci		}
55928c2ecf20Sopenharmony_ci
55938c2ecf20Sopenharmony_ci		break;
55948c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_MCOS_TERMINATED:
55958c2ecf20Sopenharmony_ci		if (cmd == BNX2X_Q_CMD_CFC_DEL) {
55968c2ecf20Sopenharmony_ci			next_tx_only = o->num_tx_only - 1;
55978c2ecf20Sopenharmony_ci			if (next_tx_only == 0)
55988c2ecf20Sopenharmony_ci				next_state = BNX2X_Q_STATE_ACTIVE;
55998c2ecf20Sopenharmony_ci			else
56008c2ecf20Sopenharmony_ci				next_state = BNX2X_Q_STATE_MULTI_COS;
56018c2ecf20Sopenharmony_ci		}
56028c2ecf20Sopenharmony_ci
56038c2ecf20Sopenharmony_ci		break;
56048c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_INACTIVE:
56058c2ecf20Sopenharmony_ci		if (cmd == BNX2X_Q_CMD_ACTIVATE)
56068c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_ACTIVE;
56078c2ecf20Sopenharmony_ci
56088c2ecf20Sopenharmony_ci		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
56098c2ecf20Sopenharmony_ci			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
56108c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_INACTIVE;
56118c2ecf20Sopenharmony_ci
56128c2ecf20Sopenharmony_ci		else if (cmd == BNX2X_Q_CMD_HALT)
56138c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_STOPPED;
56148c2ecf20Sopenharmony_ci
56158c2ecf20Sopenharmony_ci		else if (cmd == BNX2X_Q_CMD_UPDATE) {
56168c2ecf20Sopenharmony_ci			/* If "active" state change is requested, update the
56178c2ecf20Sopenharmony_ci			 * state accordingly.
56188c2ecf20Sopenharmony_ci			 */
56198c2ecf20Sopenharmony_ci			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
56208c2ecf20Sopenharmony_ci				     &update_params->update_flags) &&
56218c2ecf20Sopenharmony_ci			    test_bit(BNX2X_Q_UPDATE_ACTIVATE,
56228c2ecf20Sopenharmony_ci				     &update_params->update_flags)){
56238c2ecf20Sopenharmony_ci				if (o->num_tx_only == 0)
56248c2ecf20Sopenharmony_ci					next_state = BNX2X_Q_STATE_ACTIVE;
56258c2ecf20Sopenharmony_ci				else /* tx only queues exist for this queue */
56268c2ecf20Sopenharmony_ci					next_state = BNX2X_Q_STATE_MULTI_COS;
56278c2ecf20Sopenharmony_ci			} else
56288c2ecf20Sopenharmony_ci				next_state = BNX2X_Q_STATE_INACTIVE;
56298c2ecf20Sopenharmony_ci		}
56308c2ecf20Sopenharmony_ci
56318c2ecf20Sopenharmony_ci		break;
56328c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_STOPPED:
56338c2ecf20Sopenharmony_ci		if (cmd == BNX2X_Q_CMD_TERMINATE)
56348c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_TERMINATED;
56358c2ecf20Sopenharmony_ci
56368c2ecf20Sopenharmony_ci		break;
56378c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_TERMINATED:
56388c2ecf20Sopenharmony_ci		if (cmd == BNX2X_Q_CMD_CFC_DEL)
56398c2ecf20Sopenharmony_ci			next_state = BNX2X_Q_STATE_RESET;
56408c2ecf20Sopenharmony_ci
56418c2ecf20Sopenharmony_ci		break;
56428c2ecf20Sopenharmony_ci	default:
56438c2ecf20Sopenharmony_ci		BNX2X_ERR("Illegal state: %d\n", state);
56448c2ecf20Sopenharmony_ci	}
56458c2ecf20Sopenharmony_ci
56468c2ecf20Sopenharmony_ci	/* Transition is assured */
56478c2ecf20Sopenharmony_ci	if (next_state != BNX2X_Q_STATE_MAX) {
56488c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "Good state transition: %d(%d)->%d\n",
56498c2ecf20Sopenharmony_ci				 state, cmd, next_state);
56508c2ecf20Sopenharmony_ci		o->next_state = next_state;
56518c2ecf20Sopenharmony_ci		o->next_tx_only = next_tx_only;
56528c2ecf20Sopenharmony_ci		return 0;
56538c2ecf20Sopenharmony_ci	}
56548c2ecf20Sopenharmony_ci
56558c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Bad state transition request: %d %d\n", state, cmd);
56568c2ecf20Sopenharmony_ci
56578c2ecf20Sopenharmony_ci	return -EINVAL;
56588c2ecf20Sopenharmony_ci}
56598c2ecf20Sopenharmony_ci
56608c2ecf20Sopenharmony_civoid bnx2x_init_queue_obj(struct bnx2x *bp,
56618c2ecf20Sopenharmony_ci			  struct bnx2x_queue_sp_obj *obj,
56628c2ecf20Sopenharmony_ci			  u8 cl_id, u32 *cids, u8 cid_cnt, u8 func_id,
56638c2ecf20Sopenharmony_ci			  void *rdata,
56648c2ecf20Sopenharmony_ci			  dma_addr_t rdata_mapping, unsigned long type)
56658c2ecf20Sopenharmony_ci{
56668c2ecf20Sopenharmony_ci	memset(obj, 0, sizeof(*obj));
56678c2ecf20Sopenharmony_ci
56688c2ecf20Sopenharmony_ci	/* We support only BNX2X_MULTI_TX_COS Tx CoS at the moment */
56698c2ecf20Sopenharmony_ci	BUG_ON(BNX2X_MULTI_TX_COS < cid_cnt);
56708c2ecf20Sopenharmony_ci
56718c2ecf20Sopenharmony_ci	memcpy(obj->cids, cids, sizeof(obj->cids[0]) * cid_cnt);
56728c2ecf20Sopenharmony_ci	obj->max_cos = cid_cnt;
56738c2ecf20Sopenharmony_ci	obj->cl_id = cl_id;
56748c2ecf20Sopenharmony_ci	obj->func_id = func_id;
56758c2ecf20Sopenharmony_ci	obj->rdata = rdata;
56768c2ecf20Sopenharmony_ci	obj->rdata_mapping = rdata_mapping;
56778c2ecf20Sopenharmony_ci	obj->type = type;
56788c2ecf20Sopenharmony_ci	obj->next_state = BNX2X_Q_STATE_MAX;
56798c2ecf20Sopenharmony_ci
56808c2ecf20Sopenharmony_ci	if (CHIP_IS_E1x(bp))
56818c2ecf20Sopenharmony_ci		obj->send_cmd = bnx2x_queue_send_cmd_e1x;
56828c2ecf20Sopenharmony_ci	else
56838c2ecf20Sopenharmony_ci		obj->send_cmd = bnx2x_queue_send_cmd_e2;
56848c2ecf20Sopenharmony_ci
56858c2ecf20Sopenharmony_ci	obj->check_transition = bnx2x_queue_chk_transition;
56868c2ecf20Sopenharmony_ci
56878c2ecf20Sopenharmony_ci	obj->complete_cmd = bnx2x_queue_comp_cmd;
56888c2ecf20Sopenharmony_ci	obj->wait_comp = bnx2x_queue_wait_comp;
56898c2ecf20Sopenharmony_ci	obj->set_pending = bnx2x_queue_set_pending;
56908c2ecf20Sopenharmony_ci}
56918c2ecf20Sopenharmony_ci
56928c2ecf20Sopenharmony_ci/* return a queue object's logical state*/
56938c2ecf20Sopenharmony_ciint bnx2x_get_q_logical_state(struct bnx2x *bp,
56948c2ecf20Sopenharmony_ci			       struct bnx2x_queue_sp_obj *obj)
56958c2ecf20Sopenharmony_ci{
56968c2ecf20Sopenharmony_ci	switch (obj->state) {
56978c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_ACTIVE:
56988c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_MULTI_COS:
56998c2ecf20Sopenharmony_ci		return BNX2X_Q_LOGICAL_STATE_ACTIVE;
57008c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_RESET:
57018c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_INITIALIZED:
57028c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_MCOS_TERMINATED:
57038c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_INACTIVE:
57048c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_STOPPED:
57058c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_TERMINATED:
57068c2ecf20Sopenharmony_ci	case BNX2X_Q_STATE_FLRED:
57078c2ecf20Sopenharmony_ci		return BNX2X_Q_LOGICAL_STATE_STOPPED;
57088c2ecf20Sopenharmony_ci	default:
57098c2ecf20Sopenharmony_ci		return -EINVAL;
57108c2ecf20Sopenharmony_ci	}
57118c2ecf20Sopenharmony_ci}
57128c2ecf20Sopenharmony_ci
57138c2ecf20Sopenharmony_ci/********************** Function state object *********************************/
57148c2ecf20Sopenharmony_cienum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
57158c2ecf20Sopenharmony_ci					   struct bnx2x_func_sp_obj *o)
57168c2ecf20Sopenharmony_ci{
57178c2ecf20Sopenharmony_ci	/* in the middle of transaction - return INVALID state */
57188c2ecf20Sopenharmony_ci	if (o->pending)
57198c2ecf20Sopenharmony_ci		return BNX2X_F_STATE_MAX;
57208c2ecf20Sopenharmony_ci
57218c2ecf20Sopenharmony_ci	/* unsure the order of reading of o->pending and o->state
57228c2ecf20Sopenharmony_ci	 * o->pending should be read first
57238c2ecf20Sopenharmony_ci	 */
57248c2ecf20Sopenharmony_ci	rmb();
57258c2ecf20Sopenharmony_ci
57268c2ecf20Sopenharmony_ci	return o->state;
57278c2ecf20Sopenharmony_ci}
57288c2ecf20Sopenharmony_ci
57298c2ecf20Sopenharmony_cistatic int bnx2x_func_wait_comp(struct bnx2x *bp,
57308c2ecf20Sopenharmony_ci				struct bnx2x_func_sp_obj *o,
57318c2ecf20Sopenharmony_ci				enum bnx2x_func_cmd cmd)
57328c2ecf20Sopenharmony_ci{
57338c2ecf20Sopenharmony_ci	return bnx2x_state_wait(bp, cmd, &o->pending);
57348c2ecf20Sopenharmony_ci}
57358c2ecf20Sopenharmony_ci
57368c2ecf20Sopenharmony_ci/**
57378c2ecf20Sopenharmony_ci * bnx2x_func_state_change_comp - complete the state machine transition
57388c2ecf20Sopenharmony_ci *
57398c2ecf20Sopenharmony_ci * @bp:		device handle
57408c2ecf20Sopenharmony_ci * @o:		function info
57418c2ecf20Sopenharmony_ci * @cmd:	more info
57428c2ecf20Sopenharmony_ci *
57438c2ecf20Sopenharmony_ci * Called on state change transition. Completes the state
57448c2ecf20Sopenharmony_ci * machine transition only - no HW interaction.
57458c2ecf20Sopenharmony_ci */
57468c2ecf20Sopenharmony_cistatic inline int bnx2x_func_state_change_comp(struct bnx2x *bp,
57478c2ecf20Sopenharmony_ci					       struct bnx2x_func_sp_obj *o,
57488c2ecf20Sopenharmony_ci					       enum bnx2x_func_cmd cmd)
57498c2ecf20Sopenharmony_ci{
57508c2ecf20Sopenharmony_ci	unsigned long cur_pending = o->pending;
57518c2ecf20Sopenharmony_ci
57528c2ecf20Sopenharmony_ci	if (!test_and_clear_bit(cmd, &cur_pending)) {
57538c2ecf20Sopenharmony_ci		BNX2X_ERR("Bad MC reply %d for func %d in state %d pending 0x%lx, next_state %d\n",
57548c2ecf20Sopenharmony_ci			  cmd, BP_FUNC(bp), o->state,
57558c2ecf20Sopenharmony_ci			  cur_pending, o->next_state);
57568c2ecf20Sopenharmony_ci		return -EINVAL;
57578c2ecf20Sopenharmony_ci	}
57588c2ecf20Sopenharmony_ci
57598c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP,
57608c2ecf20Sopenharmony_ci	   "Completing command %d for func %d, setting state to %d\n",
57618c2ecf20Sopenharmony_ci	   cmd, BP_FUNC(bp), o->next_state);
57628c2ecf20Sopenharmony_ci
57638c2ecf20Sopenharmony_ci	o->state = o->next_state;
57648c2ecf20Sopenharmony_ci	o->next_state = BNX2X_F_STATE_MAX;
57658c2ecf20Sopenharmony_ci
57668c2ecf20Sopenharmony_ci	/* It's important that o->state and o->next_state are
57678c2ecf20Sopenharmony_ci	 * updated before o->pending.
57688c2ecf20Sopenharmony_ci	 */
57698c2ecf20Sopenharmony_ci	wmb();
57708c2ecf20Sopenharmony_ci
57718c2ecf20Sopenharmony_ci	clear_bit(cmd, &o->pending);
57728c2ecf20Sopenharmony_ci	smp_mb__after_atomic();
57738c2ecf20Sopenharmony_ci
57748c2ecf20Sopenharmony_ci	return 0;
57758c2ecf20Sopenharmony_ci}
57768c2ecf20Sopenharmony_ci
57778c2ecf20Sopenharmony_ci/**
57788c2ecf20Sopenharmony_ci * bnx2x_func_comp_cmd - complete the state change command
57798c2ecf20Sopenharmony_ci *
57808c2ecf20Sopenharmony_ci * @bp:		device handle
57818c2ecf20Sopenharmony_ci * @o:		function info
57828c2ecf20Sopenharmony_ci * @cmd:	more info
57838c2ecf20Sopenharmony_ci *
57848c2ecf20Sopenharmony_ci * Checks that the arrived completion is expected.
57858c2ecf20Sopenharmony_ci */
57868c2ecf20Sopenharmony_cistatic int bnx2x_func_comp_cmd(struct bnx2x *bp,
57878c2ecf20Sopenharmony_ci			       struct bnx2x_func_sp_obj *o,
57888c2ecf20Sopenharmony_ci			       enum bnx2x_func_cmd cmd)
57898c2ecf20Sopenharmony_ci{
57908c2ecf20Sopenharmony_ci	/* Complete the state machine part first, check if it's a
57918c2ecf20Sopenharmony_ci	 * legal completion.
57928c2ecf20Sopenharmony_ci	 */
57938c2ecf20Sopenharmony_ci	int rc = bnx2x_func_state_change_comp(bp, o, cmd);
57948c2ecf20Sopenharmony_ci	return rc;
57958c2ecf20Sopenharmony_ci}
57968c2ecf20Sopenharmony_ci
57978c2ecf20Sopenharmony_ci/**
57988c2ecf20Sopenharmony_ci * bnx2x_func_chk_transition - perform function state machine transition
57998c2ecf20Sopenharmony_ci *
58008c2ecf20Sopenharmony_ci * @bp:		device handle
58018c2ecf20Sopenharmony_ci * @o:		function info
58028c2ecf20Sopenharmony_ci * @params:	state parameters
58038c2ecf20Sopenharmony_ci *
58048c2ecf20Sopenharmony_ci * It both checks if the requested command is legal in a current
58058c2ecf20Sopenharmony_ci * state and, if it's legal, sets a `next_state' in the object
58068c2ecf20Sopenharmony_ci * that will be used in the completion flow to set the `state'
58078c2ecf20Sopenharmony_ci * of the object.
58088c2ecf20Sopenharmony_ci *
58098c2ecf20Sopenharmony_ci * returns 0 if a requested command is a legal transition,
58108c2ecf20Sopenharmony_ci *         -EINVAL otherwise.
58118c2ecf20Sopenharmony_ci */
58128c2ecf20Sopenharmony_cistatic int bnx2x_func_chk_transition(struct bnx2x *bp,
58138c2ecf20Sopenharmony_ci				     struct bnx2x_func_sp_obj *o,
58148c2ecf20Sopenharmony_ci				     struct bnx2x_func_state_params *params)
58158c2ecf20Sopenharmony_ci{
58168c2ecf20Sopenharmony_ci	enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX;
58178c2ecf20Sopenharmony_ci	enum bnx2x_func_cmd cmd = params->cmd;
58188c2ecf20Sopenharmony_ci
58198c2ecf20Sopenharmony_ci	/* Forget all pending for completion commands if a driver only state
58208c2ecf20Sopenharmony_ci	 * transition has been requested.
58218c2ecf20Sopenharmony_ci	 */
58228c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
58238c2ecf20Sopenharmony_ci		o->pending = 0;
58248c2ecf20Sopenharmony_ci		o->next_state = BNX2X_F_STATE_MAX;
58258c2ecf20Sopenharmony_ci	}
58268c2ecf20Sopenharmony_ci
58278c2ecf20Sopenharmony_ci	/* Don't allow a next state transition if we are in the middle of
58288c2ecf20Sopenharmony_ci	 * the previous one.
58298c2ecf20Sopenharmony_ci	 */
58308c2ecf20Sopenharmony_ci	if (o->pending)
58318c2ecf20Sopenharmony_ci		return -EBUSY;
58328c2ecf20Sopenharmony_ci
58338c2ecf20Sopenharmony_ci	switch (state) {
58348c2ecf20Sopenharmony_ci	case BNX2X_F_STATE_RESET:
58358c2ecf20Sopenharmony_ci		if (cmd == BNX2X_F_CMD_HW_INIT)
58368c2ecf20Sopenharmony_ci			next_state = BNX2X_F_STATE_INITIALIZED;
58378c2ecf20Sopenharmony_ci
58388c2ecf20Sopenharmony_ci		break;
58398c2ecf20Sopenharmony_ci	case BNX2X_F_STATE_INITIALIZED:
58408c2ecf20Sopenharmony_ci		if (cmd == BNX2X_F_CMD_START)
58418c2ecf20Sopenharmony_ci			next_state = BNX2X_F_STATE_STARTED;
58428c2ecf20Sopenharmony_ci
58438c2ecf20Sopenharmony_ci		else if (cmd == BNX2X_F_CMD_HW_RESET)
58448c2ecf20Sopenharmony_ci			next_state = BNX2X_F_STATE_RESET;
58458c2ecf20Sopenharmony_ci
58468c2ecf20Sopenharmony_ci		break;
58478c2ecf20Sopenharmony_ci	case BNX2X_F_STATE_STARTED:
58488c2ecf20Sopenharmony_ci		if (cmd == BNX2X_F_CMD_STOP)
58498c2ecf20Sopenharmony_ci			next_state = BNX2X_F_STATE_INITIALIZED;
58508c2ecf20Sopenharmony_ci		/* afex ramrods can be sent only in started mode, and only
58518c2ecf20Sopenharmony_ci		 * if not pending for function_stop ramrod completion
58528c2ecf20Sopenharmony_ci		 * for these events - next state remained STARTED.
58538c2ecf20Sopenharmony_ci		 */
58548c2ecf20Sopenharmony_ci		else if ((cmd == BNX2X_F_CMD_AFEX_UPDATE) &&
58558c2ecf20Sopenharmony_ci			 (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
58568c2ecf20Sopenharmony_ci			next_state = BNX2X_F_STATE_STARTED;
58578c2ecf20Sopenharmony_ci
58588c2ecf20Sopenharmony_ci		else if ((cmd == BNX2X_F_CMD_AFEX_VIFLISTS) &&
58598c2ecf20Sopenharmony_ci			 (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
58608c2ecf20Sopenharmony_ci			next_state = BNX2X_F_STATE_STARTED;
58618c2ecf20Sopenharmony_ci
58628c2ecf20Sopenharmony_ci		/* Switch_update ramrod can be sent in either started or
58638c2ecf20Sopenharmony_ci		 * tx_stopped state, and it doesn't change the state.
58648c2ecf20Sopenharmony_ci		 */
58658c2ecf20Sopenharmony_ci		else if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) &&
58668c2ecf20Sopenharmony_ci			 (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
58678c2ecf20Sopenharmony_ci			next_state = BNX2X_F_STATE_STARTED;
58688c2ecf20Sopenharmony_ci
58698c2ecf20Sopenharmony_ci		else if ((cmd == BNX2X_F_CMD_SET_TIMESYNC) &&
58708c2ecf20Sopenharmony_ci			 (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
58718c2ecf20Sopenharmony_ci			next_state = BNX2X_F_STATE_STARTED;
58728c2ecf20Sopenharmony_ci
58738c2ecf20Sopenharmony_ci		else if (cmd == BNX2X_F_CMD_TX_STOP)
58748c2ecf20Sopenharmony_ci			next_state = BNX2X_F_STATE_TX_STOPPED;
58758c2ecf20Sopenharmony_ci
58768c2ecf20Sopenharmony_ci		break;
58778c2ecf20Sopenharmony_ci	case BNX2X_F_STATE_TX_STOPPED:
58788c2ecf20Sopenharmony_ci		if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) &&
58798c2ecf20Sopenharmony_ci		    (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
58808c2ecf20Sopenharmony_ci			next_state = BNX2X_F_STATE_TX_STOPPED;
58818c2ecf20Sopenharmony_ci
58828c2ecf20Sopenharmony_ci		else if ((cmd == BNX2X_F_CMD_SET_TIMESYNC) &&
58838c2ecf20Sopenharmony_ci			 (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
58848c2ecf20Sopenharmony_ci			next_state = BNX2X_F_STATE_TX_STOPPED;
58858c2ecf20Sopenharmony_ci
58868c2ecf20Sopenharmony_ci		else if (cmd == BNX2X_F_CMD_TX_START)
58878c2ecf20Sopenharmony_ci			next_state = BNX2X_F_STATE_STARTED;
58888c2ecf20Sopenharmony_ci
58898c2ecf20Sopenharmony_ci		break;
58908c2ecf20Sopenharmony_ci	default:
58918c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown state: %d\n", state);
58928c2ecf20Sopenharmony_ci	}
58938c2ecf20Sopenharmony_ci
58948c2ecf20Sopenharmony_ci	/* Transition is assured */
58958c2ecf20Sopenharmony_ci	if (next_state != BNX2X_F_STATE_MAX) {
58968c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_SP, "Good function state transition: %d(%d)->%d\n",
58978c2ecf20Sopenharmony_ci				 state, cmd, next_state);
58988c2ecf20Sopenharmony_ci		o->next_state = next_state;
58998c2ecf20Sopenharmony_ci		return 0;
59008c2ecf20Sopenharmony_ci	}
59018c2ecf20Sopenharmony_ci
59028c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "Bad function state transition request: %d %d\n",
59038c2ecf20Sopenharmony_ci			 state, cmd);
59048c2ecf20Sopenharmony_ci
59058c2ecf20Sopenharmony_ci	return -EINVAL;
59068c2ecf20Sopenharmony_ci}
59078c2ecf20Sopenharmony_ci
59088c2ecf20Sopenharmony_ci/**
59098c2ecf20Sopenharmony_ci * bnx2x_func_init_func - performs HW init at function stage
59108c2ecf20Sopenharmony_ci *
59118c2ecf20Sopenharmony_ci * @bp:		device handle
59128c2ecf20Sopenharmony_ci * @drv:
59138c2ecf20Sopenharmony_ci *
59148c2ecf20Sopenharmony_ci * Init HW when the current phase is
59158c2ecf20Sopenharmony_ci * FW_MSG_CODE_DRV_LOAD_FUNCTION: initialize only FUNCTION-only
59168c2ecf20Sopenharmony_ci * HW blocks.
59178c2ecf20Sopenharmony_ci */
59188c2ecf20Sopenharmony_cistatic inline int bnx2x_func_init_func(struct bnx2x *bp,
59198c2ecf20Sopenharmony_ci				       const struct bnx2x_func_sp_drv_ops *drv)
59208c2ecf20Sopenharmony_ci{
59218c2ecf20Sopenharmony_ci	return drv->init_hw_func(bp);
59228c2ecf20Sopenharmony_ci}
59238c2ecf20Sopenharmony_ci
59248c2ecf20Sopenharmony_ci/**
59258c2ecf20Sopenharmony_ci * bnx2x_func_init_port - performs HW init at port stage
59268c2ecf20Sopenharmony_ci *
59278c2ecf20Sopenharmony_ci * @bp:		device handle
59288c2ecf20Sopenharmony_ci * @drv:
59298c2ecf20Sopenharmony_ci *
59308c2ecf20Sopenharmony_ci * Init HW when the current phase is
59318c2ecf20Sopenharmony_ci * FW_MSG_CODE_DRV_LOAD_PORT: initialize PORT-only and
59328c2ecf20Sopenharmony_ci * FUNCTION-only HW blocks.
59338c2ecf20Sopenharmony_ci *
59348c2ecf20Sopenharmony_ci */
59358c2ecf20Sopenharmony_cistatic inline int bnx2x_func_init_port(struct bnx2x *bp,
59368c2ecf20Sopenharmony_ci				       const struct bnx2x_func_sp_drv_ops *drv)
59378c2ecf20Sopenharmony_ci{
59388c2ecf20Sopenharmony_ci	int rc = drv->init_hw_port(bp);
59398c2ecf20Sopenharmony_ci	if (rc)
59408c2ecf20Sopenharmony_ci		return rc;
59418c2ecf20Sopenharmony_ci
59428c2ecf20Sopenharmony_ci	return bnx2x_func_init_func(bp, drv);
59438c2ecf20Sopenharmony_ci}
59448c2ecf20Sopenharmony_ci
59458c2ecf20Sopenharmony_ci/**
59468c2ecf20Sopenharmony_ci * bnx2x_func_init_cmn_chip - performs HW init at chip-common stage
59478c2ecf20Sopenharmony_ci *
59488c2ecf20Sopenharmony_ci * @bp:		device handle
59498c2ecf20Sopenharmony_ci * @drv:
59508c2ecf20Sopenharmony_ci *
59518c2ecf20Sopenharmony_ci * Init HW when the current phase is
59528c2ecf20Sopenharmony_ci * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON_CHIP,
59538c2ecf20Sopenharmony_ci * PORT-only and FUNCTION-only HW blocks.
59548c2ecf20Sopenharmony_ci */
59558c2ecf20Sopenharmony_cistatic inline int bnx2x_func_init_cmn_chip(struct bnx2x *bp,
59568c2ecf20Sopenharmony_ci					const struct bnx2x_func_sp_drv_ops *drv)
59578c2ecf20Sopenharmony_ci{
59588c2ecf20Sopenharmony_ci	int rc = drv->init_hw_cmn_chip(bp);
59598c2ecf20Sopenharmony_ci	if (rc)
59608c2ecf20Sopenharmony_ci		return rc;
59618c2ecf20Sopenharmony_ci
59628c2ecf20Sopenharmony_ci	return bnx2x_func_init_port(bp, drv);
59638c2ecf20Sopenharmony_ci}
59648c2ecf20Sopenharmony_ci
59658c2ecf20Sopenharmony_ci/**
59668c2ecf20Sopenharmony_ci * bnx2x_func_init_cmn - performs HW init at common stage
59678c2ecf20Sopenharmony_ci *
59688c2ecf20Sopenharmony_ci * @bp:		device handle
59698c2ecf20Sopenharmony_ci * @drv:
59708c2ecf20Sopenharmony_ci *
59718c2ecf20Sopenharmony_ci * Init HW when the current phase is
59728c2ecf20Sopenharmony_ci * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON,
59738c2ecf20Sopenharmony_ci * PORT-only and FUNCTION-only HW blocks.
59748c2ecf20Sopenharmony_ci */
59758c2ecf20Sopenharmony_cistatic inline int bnx2x_func_init_cmn(struct bnx2x *bp,
59768c2ecf20Sopenharmony_ci				      const struct bnx2x_func_sp_drv_ops *drv)
59778c2ecf20Sopenharmony_ci{
59788c2ecf20Sopenharmony_ci	int rc = drv->init_hw_cmn(bp);
59798c2ecf20Sopenharmony_ci	if (rc)
59808c2ecf20Sopenharmony_ci		return rc;
59818c2ecf20Sopenharmony_ci
59828c2ecf20Sopenharmony_ci	return bnx2x_func_init_port(bp, drv);
59838c2ecf20Sopenharmony_ci}
59848c2ecf20Sopenharmony_ci
59858c2ecf20Sopenharmony_cistatic int bnx2x_func_hw_init(struct bnx2x *bp,
59868c2ecf20Sopenharmony_ci			      struct bnx2x_func_state_params *params)
59878c2ecf20Sopenharmony_ci{
59888c2ecf20Sopenharmony_ci	u32 load_code = params->params.hw_init.load_phase;
59898c2ecf20Sopenharmony_ci	struct bnx2x_func_sp_obj *o = params->f_obj;
59908c2ecf20Sopenharmony_ci	const struct bnx2x_func_sp_drv_ops *drv = o->drv;
59918c2ecf20Sopenharmony_ci	int rc = 0;
59928c2ecf20Sopenharmony_ci
59938c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "function %d  load_code %x\n",
59948c2ecf20Sopenharmony_ci			 BP_ABS_FUNC(bp), load_code);
59958c2ecf20Sopenharmony_ci
59968c2ecf20Sopenharmony_ci	/* Prepare buffers for unzipping the FW */
59978c2ecf20Sopenharmony_ci	rc = drv->gunzip_init(bp);
59988c2ecf20Sopenharmony_ci	if (rc)
59998c2ecf20Sopenharmony_ci		return rc;
60008c2ecf20Sopenharmony_ci
60018c2ecf20Sopenharmony_ci	/* Prepare FW */
60028c2ecf20Sopenharmony_ci	rc = drv->init_fw(bp);
60038c2ecf20Sopenharmony_ci	if (rc) {
60048c2ecf20Sopenharmony_ci		BNX2X_ERR("Error loading firmware\n");
60058c2ecf20Sopenharmony_ci		goto init_err;
60068c2ecf20Sopenharmony_ci	}
60078c2ecf20Sopenharmony_ci
60088c2ecf20Sopenharmony_ci	/* Handle the beginning of COMMON_XXX pases separately... */
60098c2ecf20Sopenharmony_ci	switch (load_code) {
60108c2ecf20Sopenharmony_ci	case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
60118c2ecf20Sopenharmony_ci		rc = bnx2x_func_init_cmn_chip(bp, drv);
60128c2ecf20Sopenharmony_ci		if (rc)
60138c2ecf20Sopenharmony_ci			goto init_err;
60148c2ecf20Sopenharmony_ci
60158c2ecf20Sopenharmony_ci		break;
60168c2ecf20Sopenharmony_ci	case FW_MSG_CODE_DRV_LOAD_COMMON:
60178c2ecf20Sopenharmony_ci		rc = bnx2x_func_init_cmn(bp, drv);
60188c2ecf20Sopenharmony_ci		if (rc)
60198c2ecf20Sopenharmony_ci			goto init_err;
60208c2ecf20Sopenharmony_ci
60218c2ecf20Sopenharmony_ci		break;
60228c2ecf20Sopenharmony_ci	case FW_MSG_CODE_DRV_LOAD_PORT:
60238c2ecf20Sopenharmony_ci		rc = bnx2x_func_init_port(bp, drv);
60248c2ecf20Sopenharmony_ci		if (rc)
60258c2ecf20Sopenharmony_ci			goto init_err;
60268c2ecf20Sopenharmony_ci
60278c2ecf20Sopenharmony_ci		break;
60288c2ecf20Sopenharmony_ci	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
60298c2ecf20Sopenharmony_ci		rc = bnx2x_func_init_func(bp, drv);
60308c2ecf20Sopenharmony_ci		if (rc)
60318c2ecf20Sopenharmony_ci			goto init_err;
60328c2ecf20Sopenharmony_ci
60338c2ecf20Sopenharmony_ci		break;
60348c2ecf20Sopenharmony_ci	default:
60358c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
60368c2ecf20Sopenharmony_ci		rc = -EINVAL;
60378c2ecf20Sopenharmony_ci	}
60388c2ecf20Sopenharmony_ci
60398c2ecf20Sopenharmony_ciinit_err:
60408c2ecf20Sopenharmony_ci	drv->gunzip_end(bp);
60418c2ecf20Sopenharmony_ci
60428c2ecf20Sopenharmony_ci	/* In case of success, complete the command immediately: no ramrods
60438c2ecf20Sopenharmony_ci	 * have been sent.
60448c2ecf20Sopenharmony_ci	 */
60458c2ecf20Sopenharmony_ci	if (!rc)
60468c2ecf20Sopenharmony_ci		o->complete_cmd(bp, o, BNX2X_F_CMD_HW_INIT);
60478c2ecf20Sopenharmony_ci
60488c2ecf20Sopenharmony_ci	return rc;
60498c2ecf20Sopenharmony_ci}
60508c2ecf20Sopenharmony_ci
60518c2ecf20Sopenharmony_ci/**
60528c2ecf20Sopenharmony_ci * bnx2x_func_reset_func - reset HW at function stage
60538c2ecf20Sopenharmony_ci *
60548c2ecf20Sopenharmony_ci * @bp:		device handle
60558c2ecf20Sopenharmony_ci * @drv:
60568c2ecf20Sopenharmony_ci *
60578c2ecf20Sopenharmony_ci * Reset HW at FW_MSG_CODE_DRV_UNLOAD_FUNCTION stage: reset only
60588c2ecf20Sopenharmony_ci * FUNCTION-only HW blocks.
60598c2ecf20Sopenharmony_ci */
60608c2ecf20Sopenharmony_cistatic inline void bnx2x_func_reset_func(struct bnx2x *bp,
60618c2ecf20Sopenharmony_ci					const struct bnx2x_func_sp_drv_ops *drv)
60628c2ecf20Sopenharmony_ci{
60638c2ecf20Sopenharmony_ci	drv->reset_hw_func(bp);
60648c2ecf20Sopenharmony_ci}
60658c2ecf20Sopenharmony_ci
60668c2ecf20Sopenharmony_ci/**
60678c2ecf20Sopenharmony_ci * bnx2x_func_reset_port - reset HW at port stage
60688c2ecf20Sopenharmony_ci *
60698c2ecf20Sopenharmony_ci * @bp:		device handle
60708c2ecf20Sopenharmony_ci * @drv:
60718c2ecf20Sopenharmony_ci *
60728c2ecf20Sopenharmony_ci * Reset HW at FW_MSG_CODE_DRV_UNLOAD_PORT stage: reset
60738c2ecf20Sopenharmony_ci * FUNCTION-only and PORT-only HW blocks.
60748c2ecf20Sopenharmony_ci *
60758c2ecf20Sopenharmony_ci *                 !!!IMPORTANT!!!
60768c2ecf20Sopenharmony_ci *
60778c2ecf20Sopenharmony_ci * It's important to call reset_port before reset_func() as the last thing
60788c2ecf20Sopenharmony_ci * reset_func does is pf_disable() thus disabling PGLUE_B, which
60798c2ecf20Sopenharmony_ci * makes impossible any DMAE transactions.
60808c2ecf20Sopenharmony_ci */
60818c2ecf20Sopenharmony_cistatic inline void bnx2x_func_reset_port(struct bnx2x *bp,
60828c2ecf20Sopenharmony_ci					const struct bnx2x_func_sp_drv_ops *drv)
60838c2ecf20Sopenharmony_ci{
60848c2ecf20Sopenharmony_ci	drv->reset_hw_port(bp);
60858c2ecf20Sopenharmony_ci	bnx2x_func_reset_func(bp, drv);
60868c2ecf20Sopenharmony_ci}
60878c2ecf20Sopenharmony_ci
60888c2ecf20Sopenharmony_ci/**
60898c2ecf20Sopenharmony_ci * bnx2x_func_reset_cmn - reset HW at common stage
60908c2ecf20Sopenharmony_ci *
60918c2ecf20Sopenharmony_ci * @bp:		device handle
60928c2ecf20Sopenharmony_ci * @drv:
60938c2ecf20Sopenharmony_ci *
60948c2ecf20Sopenharmony_ci * Reset HW at FW_MSG_CODE_DRV_UNLOAD_COMMON and
60958c2ecf20Sopenharmony_ci * FW_MSG_CODE_DRV_UNLOAD_COMMON_CHIP stages: reset COMMON,
60968c2ecf20Sopenharmony_ci * COMMON_CHIP, FUNCTION-only and PORT-only HW blocks.
60978c2ecf20Sopenharmony_ci */
60988c2ecf20Sopenharmony_cistatic inline void bnx2x_func_reset_cmn(struct bnx2x *bp,
60998c2ecf20Sopenharmony_ci					const struct bnx2x_func_sp_drv_ops *drv)
61008c2ecf20Sopenharmony_ci{
61018c2ecf20Sopenharmony_ci	bnx2x_func_reset_port(bp, drv);
61028c2ecf20Sopenharmony_ci	drv->reset_hw_cmn(bp);
61038c2ecf20Sopenharmony_ci}
61048c2ecf20Sopenharmony_ci
61058c2ecf20Sopenharmony_cistatic inline int bnx2x_func_hw_reset(struct bnx2x *bp,
61068c2ecf20Sopenharmony_ci				      struct bnx2x_func_state_params *params)
61078c2ecf20Sopenharmony_ci{
61088c2ecf20Sopenharmony_ci	u32 reset_phase = params->params.hw_reset.reset_phase;
61098c2ecf20Sopenharmony_ci	struct bnx2x_func_sp_obj *o = params->f_obj;
61108c2ecf20Sopenharmony_ci	const struct bnx2x_func_sp_drv_ops *drv = o->drv;
61118c2ecf20Sopenharmony_ci
61128c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "function %d  reset_phase %x\n", BP_ABS_FUNC(bp),
61138c2ecf20Sopenharmony_ci			 reset_phase);
61148c2ecf20Sopenharmony_ci
61158c2ecf20Sopenharmony_ci	switch (reset_phase) {
61168c2ecf20Sopenharmony_ci	case FW_MSG_CODE_DRV_UNLOAD_COMMON:
61178c2ecf20Sopenharmony_ci		bnx2x_func_reset_cmn(bp, drv);
61188c2ecf20Sopenharmony_ci		break;
61198c2ecf20Sopenharmony_ci	case FW_MSG_CODE_DRV_UNLOAD_PORT:
61208c2ecf20Sopenharmony_ci		bnx2x_func_reset_port(bp, drv);
61218c2ecf20Sopenharmony_ci		break;
61228c2ecf20Sopenharmony_ci	case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
61238c2ecf20Sopenharmony_ci		bnx2x_func_reset_func(bp, drv);
61248c2ecf20Sopenharmony_ci		break;
61258c2ecf20Sopenharmony_ci	default:
61268c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown reset_phase (0x%x) from MCP\n",
61278c2ecf20Sopenharmony_ci			   reset_phase);
61288c2ecf20Sopenharmony_ci		break;
61298c2ecf20Sopenharmony_ci	}
61308c2ecf20Sopenharmony_ci
61318c2ecf20Sopenharmony_ci	/* Complete the command immediately: no ramrods have been sent. */
61328c2ecf20Sopenharmony_ci	o->complete_cmd(bp, o, BNX2X_F_CMD_HW_RESET);
61338c2ecf20Sopenharmony_ci
61348c2ecf20Sopenharmony_ci	return 0;
61358c2ecf20Sopenharmony_ci}
61368c2ecf20Sopenharmony_ci
61378c2ecf20Sopenharmony_cistatic inline int bnx2x_func_send_start(struct bnx2x *bp,
61388c2ecf20Sopenharmony_ci					struct bnx2x_func_state_params *params)
61398c2ecf20Sopenharmony_ci{
61408c2ecf20Sopenharmony_ci	struct bnx2x_func_sp_obj *o = params->f_obj;
61418c2ecf20Sopenharmony_ci	struct function_start_data *rdata =
61428c2ecf20Sopenharmony_ci		(struct function_start_data *)o->rdata;
61438c2ecf20Sopenharmony_ci	dma_addr_t data_mapping = o->rdata_mapping;
61448c2ecf20Sopenharmony_ci	struct bnx2x_func_start_params *start_params = &params->params.start;
61458c2ecf20Sopenharmony_ci
61468c2ecf20Sopenharmony_ci	memset(rdata, 0, sizeof(*rdata));
61478c2ecf20Sopenharmony_ci
61488c2ecf20Sopenharmony_ci	/* Fill the ramrod data with provided parameters */
61498c2ecf20Sopenharmony_ci	rdata->function_mode	= (u8)start_params->mf_mode;
61508c2ecf20Sopenharmony_ci	rdata->sd_vlan_tag	= cpu_to_le16(start_params->sd_vlan_tag);
61518c2ecf20Sopenharmony_ci	rdata->path_id		= BP_PATH(bp);
61528c2ecf20Sopenharmony_ci	rdata->network_cos_mode	= start_params->network_cos_mode;
61538c2ecf20Sopenharmony_ci	rdata->dmae_cmd_id	= BNX2X_FW_DMAE_C;
61548c2ecf20Sopenharmony_ci
61558c2ecf20Sopenharmony_ci	rdata->vxlan_dst_port	= cpu_to_le16(start_params->vxlan_dst_port);
61568c2ecf20Sopenharmony_ci	rdata->geneve_dst_port	= cpu_to_le16(start_params->geneve_dst_port);
61578c2ecf20Sopenharmony_ci	rdata->inner_clss_l2gre	= start_params->inner_clss_l2gre;
61588c2ecf20Sopenharmony_ci	rdata->inner_clss_l2geneve = start_params->inner_clss_l2geneve;
61598c2ecf20Sopenharmony_ci	rdata->inner_clss_vxlan	= start_params->inner_clss_vxlan;
61608c2ecf20Sopenharmony_ci	rdata->inner_rss	= start_params->inner_rss;
61618c2ecf20Sopenharmony_ci
61628c2ecf20Sopenharmony_ci	rdata->sd_accept_mf_clss_fail = start_params->class_fail;
61638c2ecf20Sopenharmony_ci	if (start_params->class_fail_ethtype) {
61648c2ecf20Sopenharmony_ci		rdata->sd_accept_mf_clss_fail_match_ethtype = 1;
61658c2ecf20Sopenharmony_ci		rdata->sd_accept_mf_clss_fail_ethtype =
61668c2ecf20Sopenharmony_ci			cpu_to_le16(start_params->class_fail_ethtype);
61678c2ecf20Sopenharmony_ci	}
61688c2ecf20Sopenharmony_ci
61698c2ecf20Sopenharmony_ci	rdata->sd_vlan_force_pri_flg = start_params->sd_vlan_force_pri;
61708c2ecf20Sopenharmony_ci	rdata->sd_vlan_force_pri_val = start_params->sd_vlan_force_pri_val;
61718c2ecf20Sopenharmony_ci	if (start_params->sd_vlan_eth_type)
61728c2ecf20Sopenharmony_ci		rdata->sd_vlan_eth_type =
61738c2ecf20Sopenharmony_ci			cpu_to_le16(start_params->sd_vlan_eth_type);
61748c2ecf20Sopenharmony_ci	else
61758c2ecf20Sopenharmony_ci		rdata->sd_vlan_eth_type =
61768c2ecf20Sopenharmony_ci			cpu_to_le16(0x8100);
61778c2ecf20Sopenharmony_ci
61788c2ecf20Sopenharmony_ci	rdata->no_added_tags = start_params->no_added_tags;
61798c2ecf20Sopenharmony_ci
61808c2ecf20Sopenharmony_ci	rdata->c2s_pri_tt_valid = start_params->c2s_pri_valid;
61818c2ecf20Sopenharmony_ci	if (rdata->c2s_pri_tt_valid) {
61828c2ecf20Sopenharmony_ci		memcpy(rdata->c2s_pri_trans_table.val,
61838c2ecf20Sopenharmony_ci		       start_params->c2s_pri,
61848c2ecf20Sopenharmony_ci		       MAX_VLAN_PRIORITIES);
61858c2ecf20Sopenharmony_ci		rdata->c2s_pri_default = start_params->c2s_pri_default;
61868c2ecf20Sopenharmony_ci	}
61878c2ecf20Sopenharmony_ci	/* No need for an explicit memory barrier here as long we would
61888c2ecf20Sopenharmony_ci	 * need to ensure the ordering of writing to the SPQ element
61898c2ecf20Sopenharmony_ci	 * and updating of the SPQ producer which involves a memory
61908c2ecf20Sopenharmony_ci	 * read and we will have to put a full memory barrier there
61918c2ecf20Sopenharmony_ci	 * (inside bnx2x_sp_post()).
61928c2ecf20Sopenharmony_ci	 */
61938c2ecf20Sopenharmony_ci
61948c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0,
61958c2ecf20Sopenharmony_ci			     U64_HI(data_mapping),
61968c2ecf20Sopenharmony_ci			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
61978c2ecf20Sopenharmony_ci}
61988c2ecf20Sopenharmony_ci
61998c2ecf20Sopenharmony_cistatic inline int bnx2x_func_send_switch_update(struct bnx2x *bp,
62008c2ecf20Sopenharmony_ci					struct bnx2x_func_state_params *params)
62018c2ecf20Sopenharmony_ci{
62028c2ecf20Sopenharmony_ci	struct bnx2x_func_sp_obj *o = params->f_obj;
62038c2ecf20Sopenharmony_ci	struct function_update_data *rdata =
62048c2ecf20Sopenharmony_ci		(struct function_update_data *)o->rdata;
62058c2ecf20Sopenharmony_ci	dma_addr_t data_mapping = o->rdata_mapping;
62068c2ecf20Sopenharmony_ci	struct bnx2x_func_switch_update_params *switch_update_params =
62078c2ecf20Sopenharmony_ci		&params->params.switch_update;
62088c2ecf20Sopenharmony_ci
62098c2ecf20Sopenharmony_ci	memset(rdata, 0, sizeof(*rdata));
62108c2ecf20Sopenharmony_ci
62118c2ecf20Sopenharmony_ci	/* Fill the ramrod data with provided parameters */
62128c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_F_UPDATE_TX_SWITCH_SUSPEND_CHNG,
62138c2ecf20Sopenharmony_ci		     &switch_update_params->changes)) {
62148c2ecf20Sopenharmony_ci		rdata->tx_switch_suspend_change_flg = 1;
62158c2ecf20Sopenharmony_ci		rdata->tx_switch_suspend =
62168c2ecf20Sopenharmony_ci			test_bit(BNX2X_F_UPDATE_TX_SWITCH_SUSPEND,
62178c2ecf20Sopenharmony_ci				 &switch_update_params->changes);
62188c2ecf20Sopenharmony_ci	}
62198c2ecf20Sopenharmony_ci
62208c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_F_UPDATE_SD_VLAN_TAG_CHNG,
62218c2ecf20Sopenharmony_ci		     &switch_update_params->changes)) {
62228c2ecf20Sopenharmony_ci		rdata->sd_vlan_tag_change_flg = 1;
62238c2ecf20Sopenharmony_ci		rdata->sd_vlan_tag =
62248c2ecf20Sopenharmony_ci			cpu_to_le16(switch_update_params->vlan);
62258c2ecf20Sopenharmony_ci	}
62268c2ecf20Sopenharmony_ci
62278c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_F_UPDATE_SD_VLAN_ETH_TYPE_CHNG,
62288c2ecf20Sopenharmony_ci		     &switch_update_params->changes)) {
62298c2ecf20Sopenharmony_ci		rdata->sd_vlan_eth_type_change_flg = 1;
62308c2ecf20Sopenharmony_ci		rdata->sd_vlan_eth_type =
62318c2ecf20Sopenharmony_ci			cpu_to_le16(switch_update_params->vlan_eth_type);
62328c2ecf20Sopenharmony_ci	}
62338c2ecf20Sopenharmony_ci
62348c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_F_UPDATE_VLAN_FORCE_PRIO_CHNG,
62358c2ecf20Sopenharmony_ci		     &switch_update_params->changes)) {
62368c2ecf20Sopenharmony_ci		rdata->sd_vlan_force_pri_change_flg = 1;
62378c2ecf20Sopenharmony_ci		if (test_bit(BNX2X_F_UPDATE_VLAN_FORCE_PRIO_FLAG,
62388c2ecf20Sopenharmony_ci			     &switch_update_params->changes))
62398c2ecf20Sopenharmony_ci			rdata->sd_vlan_force_pri_flg = 1;
62408c2ecf20Sopenharmony_ci		rdata->sd_vlan_force_pri_flg =
62418c2ecf20Sopenharmony_ci			switch_update_params->vlan_force_prio;
62428c2ecf20Sopenharmony_ci	}
62438c2ecf20Sopenharmony_ci
62448c2ecf20Sopenharmony_ci	if (test_bit(BNX2X_F_UPDATE_TUNNEL_CFG_CHNG,
62458c2ecf20Sopenharmony_ci		     &switch_update_params->changes)) {
62468c2ecf20Sopenharmony_ci		rdata->update_tunn_cfg_flg = 1;
62478c2ecf20Sopenharmony_ci		if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_L2GRE,
62488c2ecf20Sopenharmony_ci			     &switch_update_params->changes))
62498c2ecf20Sopenharmony_ci			rdata->inner_clss_l2gre = 1;
62508c2ecf20Sopenharmony_ci		if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_VXLAN,
62518c2ecf20Sopenharmony_ci			     &switch_update_params->changes))
62528c2ecf20Sopenharmony_ci			rdata->inner_clss_vxlan = 1;
62538c2ecf20Sopenharmony_ci		if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_L2GENEVE,
62548c2ecf20Sopenharmony_ci			     &switch_update_params->changes))
62558c2ecf20Sopenharmony_ci			rdata->inner_clss_l2geneve = 1;
62568c2ecf20Sopenharmony_ci		if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_RSS,
62578c2ecf20Sopenharmony_ci			     &switch_update_params->changes))
62588c2ecf20Sopenharmony_ci			rdata->inner_rss = 1;
62598c2ecf20Sopenharmony_ci		rdata->vxlan_dst_port =
62608c2ecf20Sopenharmony_ci			cpu_to_le16(switch_update_params->vxlan_dst_port);
62618c2ecf20Sopenharmony_ci		rdata->geneve_dst_port =
62628c2ecf20Sopenharmony_ci			cpu_to_le16(switch_update_params->geneve_dst_port);
62638c2ecf20Sopenharmony_ci	}
62648c2ecf20Sopenharmony_ci
62658c2ecf20Sopenharmony_ci	rdata->echo = SWITCH_UPDATE;
62668c2ecf20Sopenharmony_ci
62678c2ecf20Sopenharmony_ci	/* No need for an explicit memory barrier here as long as we
62688c2ecf20Sopenharmony_ci	 * ensure the ordering of writing to the SPQ element
62698c2ecf20Sopenharmony_ci	 * and updating of the SPQ producer which involves a memory
62708c2ecf20Sopenharmony_ci	 * read. If the memory read is removed we will have to put a
62718c2ecf20Sopenharmony_ci	 * full memory barrier there (inside bnx2x_sp_post()).
62728c2ecf20Sopenharmony_ci	 */
62738c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
62748c2ecf20Sopenharmony_ci			     U64_HI(data_mapping),
62758c2ecf20Sopenharmony_ci			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
62768c2ecf20Sopenharmony_ci}
62778c2ecf20Sopenharmony_ci
62788c2ecf20Sopenharmony_cistatic inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
62798c2ecf20Sopenharmony_ci					 struct bnx2x_func_state_params *params)
62808c2ecf20Sopenharmony_ci{
62818c2ecf20Sopenharmony_ci	struct bnx2x_func_sp_obj *o = params->f_obj;
62828c2ecf20Sopenharmony_ci	struct function_update_data *rdata =
62838c2ecf20Sopenharmony_ci		(struct function_update_data *)o->afex_rdata;
62848c2ecf20Sopenharmony_ci	dma_addr_t data_mapping = o->afex_rdata_mapping;
62858c2ecf20Sopenharmony_ci	struct bnx2x_func_afex_update_params *afex_update_params =
62868c2ecf20Sopenharmony_ci		&params->params.afex_update;
62878c2ecf20Sopenharmony_ci
62888c2ecf20Sopenharmony_ci	memset(rdata, 0, sizeof(*rdata));
62898c2ecf20Sopenharmony_ci
62908c2ecf20Sopenharmony_ci	/* Fill the ramrod data with provided parameters */
62918c2ecf20Sopenharmony_ci	rdata->vif_id_change_flg = 1;
62928c2ecf20Sopenharmony_ci	rdata->vif_id = cpu_to_le16(afex_update_params->vif_id);
62938c2ecf20Sopenharmony_ci	rdata->afex_default_vlan_change_flg = 1;
62948c2ecf20Sopenharmony_ci	rdata->afex_default_vlan =
62958c2ecf20Sopenharmony_ci		cpu_to_le16(afex_update_params->afex_default_vlan);
62968c2ecf20Sopenharmony_ci	rdata->allowed_priorities_change_flg = 1;
62978c2ecf20Sopenharmony_ci	rdata->allowed_priorities = afex_update_params->allowed_priorities;
62988c2ecf20Sopenharmony_ci	rdata->echo = AFEX_UPDATE;
62998c2ecf20Sopenharmony_ci
63008c2ecf20Sopenharmony_ci	/* No need for an explicit memory barrier here as long as we
63018c2ecf20Sopenharmony_ci	 * ensure the ordering of writing to the SPQ element
63028c2ecf20Sopenharmony_ci	 * and updating of the SPQ producer which involves a memory
63038c2ecf20Sopenharmony_ci	 * read. If the memory read is removed we will have to put a
63048c2ecf20Sopenharmony_ci	 * full memory barrier there (inside bnx2x_sp_post()).
63058c2ecf20Sopenharmony_ci	 */
63068c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP,
63078c2ecf20Sopenharmony_ci	   "afex: sending func_update vif_id 0x%x dvlan 0x%x prio 0x%x\n",
63088c2ecf20Sopenharmony_ci	   rdata->vif_id,
63098c2ecf20Sopenharmony_ci	   rdata->afex_default_vlan, rdata->allowed_priorities);
63108c2ecf20Sopenharmony_ci
63118c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
63128c2ecf20Sopenharmony_ci			     U64_HI(data_mapping),
63138c2ecf20Sopenharmony_ci			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
63148c2ecf20Sopenharmony_ci}
63158c2ecf20Sopenharmony_ci
63168c2ecf20Sopenharmony_cistatic
63178c2ecf20Sopenharmony_ciinline int bnx2x_func_send_afex_viflists(struct bnx2x *bp,
63188c2ecf20Sopenharmony_ci					 struct bnx2x_func_state_params *params)
63198c2ecf20Sopenharmony_ci{
63208c2ecf20Sopenharmony_ci	struct bnx2x_func_sp_obj *o = params->f_obj;
63218c2ecf20Sopenharmony_ci	struct afex_vif_list_ramrod_data *rdata =
63228c2ecf20Sopenharmony_ci		(struct afex_vif_list_ramrod_data *)o->afex_rdata;
63238c2ecf20Sopenharmony_ci	struct bnx2x_func_afex_viflists_params *afex_vif_params =
63248c2ecf20Sopenharmony_ci		&params->params.afex_viflists;
63258c2ecf20Sopenharmony_ci	u64 *p_rdata = (u64 *)rdata;
63268c2ecf20Sopenharmony_ci
63278c2ecf20Sopenharmony_ci	memset(rdata, 0, sizeof(*rdata));
63288c2ecf20Sopenharmony_ci
63298c2ecf20Sopenharmony_ci	/* Fill the ramrod data with provided parameters */
63308c2ecf20Sopenharmony_ci	rdata->vif_list_index = cpu_to_le16(afex_vif_params->vif_list_index);
63318c2ecf20Sopenharmony_ci	rdata->func_bit_map          = afex_vif_params->func_bit_map;
63328c2ecf20Sopenharmony_ci	rdata->afex_vif_list_command = afex_vif_params->afex_vif_list_command;
63338c2ecf20Sopenharmony_ci	rdata->func_to_clear         = afex_vif_params->func_to_clear;
63348c2ecf20Sopenharmony_ci
63358c2ecf20Sopenharmony_ci	/* send in echo type of sub command */
63368c2ecf20Sopenharmony_ci	rdata->echo = afex_vif_params->afex_vif_list_command;
63378c2ecf20Sopenharmony_ci
63388c2ecf20Sopenharmony_ci	/*  No need for an explicit memory barrier here as long we would
63398c2ecf20Sopenharmony_ci	 *  need to ensure the ordering of writing to the SPQ element
63408c2ecf20Sopenharmony_ci	 *  and updating of the SPQ producer which involves a memory
63418c2ecf20Sopenharmony_ci	 *  read and we will have to put a full memory barrier there
63428c2ecf20Sopenharmony_ci	 *  (inside bnx2x_sp_post()).
63438c2ecf20Sopenharmony_ci	 */
63448c2ecf20Sopenharmony_ci
63458c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_SP, "afex: ramrod lists, cmd 0x%x index 0x%x func_bit_map 0x%x func_to_clr 0x%x\n",
63468c2ecf20Sopenharmony_ci	   rdata->afex_vif_list_command, rdata->vif_list_index,
63478c2ecf20Sopenharmony_ci	   rdata->func_bit_map, rdata->func_to_clear);
63488c2ecf20Sopenharmony_ci
63498c2ecf20Sopenharmony_ci	/* this ramrod sends data directly and not through DMA mapping */
63508c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_AFEX_VIF_LISTS, 0,
63518c2ecf20Sopenharmony_ci			     U64_HI(*p_rdata), U64_LO(*p_rdata),
63528c2ecf20Sopenharmony_ci			     NONE_CONNECTION_TYPE);
63538c2ecf20Sopenharmony_ci}
63548c2ecf20Sopenharmony_ci
63558c2ecf20Sopenharmony_cistatic inline int bnx2x_func_send_stop(struct bnx2x *bp,
63568c2ecf20Sopenharmony_ci				       struct bnx2x_func_state_params *params)
63578c2ecf20Sopenharmony_ci{
63588c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0,
63598c2ecf20Sopenharmony_ci			     NONE_CONNECTION_TYPE);
63608c2ecf20Sopenharmony_ci}
63618c2ecf20Sopenharmony_ci
63628c2ecf20Sopenharmony_cistatic inline int bnx2x_func_send_tx_stop(struct bnx2x *bp,
63638c2ecf20Sopenharmony_ci				       struct bnx2x_func_state_params *params)
63648c2ecf20Sopenharmony_ci{
63658c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, 0, 0, 0,
63668c2ecf20Sopenharmony_ci			     NONE_CONNECTION_TYPE);
63678c2ecf20Sopenharmony_ci}
63688c2ecf20Sopenharmony_cistatic inline int bnx2x_func_send_tx_start(struct bnx2x *bp,
63698c2ecf20Sopenharmony_ci				       struct bnx2x_func_state_params *params)
63708c2ecf20Sopenharmony_ci{
63718c2ecf20Sopenharmony_ci	struct bnx2x_func_sp_obj *o = params->f_obj;
63728c2ecf20Sopenharmony_ci	struct flow_control_configuration *rdata =
63738c2ecf20Sopenharmony_ci		(struct flow_control_configuration *)o->rdata;
63748c2ecf20Sopenharmony_ci	dma_addr_t data_mapping = o->rdata_mapping;
63758c2ecf20Sopenharmony_ci	struct bnx2x_func_tx_start_params *tx_start_params =
63768c2ecf20Sopenharmony_ci		&params->params.tx_start;
63778c2ecf20Sopenharmony_ci	int i;
63788c2ecf20Sopenharmony_ci
63798c2ecf20Sopenharmony_ci	memset(rdata, 0, sizeof(*rdata));
63808c2ecf20Sopenharmony_ci
63818c2ecf20Sopenharmony_ci	rdata->dcb_enabled = tx_start_params->dcb_enabled;
63828c2ecf20Sopenharmony_ci	rdata->dcb_version = tx_start_params->dcb_version;
63838c2ecf20Sopenharmony_ci	rdata->dont_add_pri_0_en = tx_start_params->dont_add_pri_0_en;
63848c2ecf20Sopenharmony_ci
63858c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(rdata->traffic_type_to_priority_cos); i++)
63868c2ecf20Sopenharmony_ci		rdata->traffic_type_to_priority_cos[i] =
63878c2ecf20Sopenharmony_ci			tx_start_params->traffic_type_to_priority_cos[i];
63888c2ecf20Sopenharmony_ci
63898c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_TRAFFIC_TYPES; i++)
63908c2ecf20Sopenharmony_ci		rdata->dcb_outer_pri[i] = tx_start_params->dcb_outer_pri[i];
63918c2ecf20Sopenharmony_ci	/* No need for an explicit memory barrier here as long as we
63928c2ecf20Sopenharmony_ci	 * ensure the ordering of writing to the SPQ element
63938c2ecf20Sopenharmony_ci	 * and updating of the SPQ producer which involves a memory
63948c2ecf20Sopenharmony_ci	 * read. If the memory read is removed we will have to put a
63958c2ecf20Sopenharmony_ci	 * full memory barrier there (inside bnx2x_sp_post()).
63968c2ecf20Sopenharmony_ci	 */
63978c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0,
63988c2ecf20Sopenharmony_ci			     U64_HI(data_mapping),
63998c2ecf20Sopenharmony_ci			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
64008c2ecf20Sopenharmony_ci}
64018c2ecf20Sopenharmony_ci
64028c2ecf20Sopenharmony_cistatic inline
64038c2ecf20Sopenharmony_ciint bnx2x_func_send_set_timesync(struct bnx2x *bp,
64048c2ecf20Sopenharmony_ci				 struct bnx2x_func_state_params *params)
64058c2ecf20Sopenharmony_ci{
64068c2ecf20Sopenharmony_ci	struct bnx2x_func_sp_obj *o = params->f_obj;
64078c2ecf20Sopenharmony_ci	struct set_timesync_ramrod_data *rdata =
64088c2ecf20Sopenharmony_ci		(struct set_timesync_ramrod_data *)o->rdata;
64098c2ecf20Sopenharmony_ci	dma_addr_t data_mapping = o->rdata_mapping;
64108c2ecf20Sopenharmony_ci	struct bnx2x_func_set_timesync_params *set_timesync_params =
64118c2ecf20Sopenharmony_ci		&params->params.set_timesync;
64128c2ecf20Sopenharmony_ci
64138c2ecf20Sopenharmony_ci	memset(rdata, 0, sizeof(*rdata));
64148c2ecf20Sopenharmony_ci
64158c2ecf20Sopenharmony_ci	/* Fill the ramrod data with provided parameters */
64168c2ecf20Sopenharmony_ci	rdata->drift_adjust_cmd = set_timesync_params->drift_adjust_cmd;
64178c2ecf20Sopenharmony_ci	rdata->offset_cmd = set_timesync_params->offset_cmd;
64188c2ecf20Sopenharmony_ci	rdata->add_sub_drift_adjust_value =
64198c2ecf20Sopenharmony_ci		set_timesync_params->add_sub_drift_adjust_value;
64208c2ecf20Sopenharmony_ci	rdata->drift_adjust_value = set_timesync_params->drift_adjust_value;
64218c2ecf20Sopenharmony_ci	rdata->drift_adjust_period = set_timesync_params->drift_adjust_period;
64228c2ecf20Sopenharmony_ci	rdata->offset_delta.lo =
64238c2ecf20Sopenharmony_ci		cpu_to_le32(U64_LO(set_timesync_params->offset_delta));
64248c2ecf20Sopenharmony_ci	rdata->offset_delta.hi =
64258c2ecf20Sopenharmony_ci		cpu_to_le32(U64_HI(set_timesync_params->offset_delta));
64268c2ecf20Sopenharmony_ci
64278c2ecf20Sopenharmony_ci	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",
64288c2ecf20Sopenharmony_ci	   rdata->drift_adjust_cmd, rdata->offset_cmd,
64298c2ecf20Sopenharmony_ci	   rdata->add_sub_drift_adjust_value, rdata->drift_adjust_value,
64308c2ecf20Sopenharmony_ci	   rdata->drift_adjust_period, rdata->offset_delta.lo,
64318c2ecf20Sopenharmony_ci	   rdata->offset_delta.hi);
64328c2ecf20Sopenharmony_ci
64338c2ecf20Sopenharmony_ci	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_TIMESYNC, 0,
64348c2ecf20Sopenharmony_ci			     U64_HI(data_mapping),
64358c2ecf20Sopenharmony_ci			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
64368c2ecf20Sopenharmony_ci}
64378c2ecf20Sopenharmony_ci
64388c2ecf20Sopenharmony_cistatic int bnx2x_func_send_cmd(struct bnx2x *bp,
64398c2ecf20Sopenharmony_ci			       struct bnx2x_func_state_params *params)
64408c2ecf20Sopenharmony_ci{
64418c2ecf20Sopenharmony_ci	switch (params->cmd) {
64428c2ecf20Sopenharmony_ci	case BNX2X_F_CMD_HW_INIT:
64438c2ecf20Sopenharmony_ci		return bnx2x_func_hw_init(bp, params);
64448c2ecf20Sopenharmony_ci	case BNX2X_F_CMD_START:
64458c2ecf20Sopenharmony_ci		return bnx2x_func_send_start(bp, params);
64468c2ecf20Sopenharmony_ci	case BNX2X_F_CMD_STOP:
64478c2ecf20Sopenharmony_ci		return bnx2x_func_send_stop(bp, params);
64488c2ecf20Sopenharmony_ci	case BNX2X_F_CMD_HW_RESET:
64498c2ecf20Sopenharmony_ci		return bnx2x_func_hw_reset(bp, params);
64508c2ecf20Sopenharmony_ci	case BNX2X_F_CMD_AFEX_UPDATE:
64518c2ecf20Sopenharmony_ci		return bnx2x_func_send_afex_update(bp, params);
64528c2ecf20Sopenharmony_ci	case BNX2X_F_CMD_AFEX_VIFLISTS:
64538c2ecf20Sopenharmony_ci		return bnx2x_func_send_afex_viflists(bp, params);
64548c2ecf20Sopenharmony_ci	case BNX2X_F_CMD_TX_STOP:
64558c2ecf20Sopenharmony_ci		return bnx2x_func_send_tx_stop(bp, params);
64568c2ecf20Sopenharmony_ci	case BNX2X_F_CMD_TX_START:
64578c2ecf20Sopenharmony_ci		return bnx2x_func_send_tx_start(bp, params);
64588c2ecf20Sopenharmony_ci	case BNX2X_F_CMD_SWITCH_UPDATE:
64598c2ecf20Sopenharmony_ci		return bnx2x_func_send_switch_update(bp, params);
64608c2ecf20Sopenharmony_ci	case BNX2X_F_CMD_SET_TIMESYNC:
64618c2ecf20Sopenharmony_ci		return bnx2x_func_send_set_timesync(bp, params);
64628c2ecf20Sopenharmony_ci	default:
64638c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown command: %d\n", params->cmd);
64648c2ecf20Sopenharmony_ci		return -EINVAL;
64658c2ecf20Sopenharmony_ci	}
64668c2ecf20Sopenharmony_ci}
64678c2ecf20Sopenharmony_ci
64688c2ecf20Sopenharmony_civoid bnx2x_init_func_obj(struct bnx2x *bp,
64698c2ecf20Sopenharmony_ci			 struct bnx2x_func_sp_obj *obj,
64708c2ecf20Sopenharmony_ci			 void *rdata, dma_addr_t rdata_mapping,
64718c2ecf20Sopenharmony_ci			 void *afex_rdata, dma_addr_t afex_rdata_mapping,
64728c2ecf20Sopenharmony_ci			 struct bnx2x_func_sp_drv_ops *drv_iface)
64738c2ecf20Sopenharmony_ci{
64748c2ecf20Sopenharmony_ci	memset(obj, 0, sizeof(*obj));
64758c2ecf20Sopenharmony_ci
64768c2ecf20Sopenharmony_ci	mutex_init(&obj->one_pending_mutex);
64778c2ecf20Sopenharmony_ci
64788c2ecf20Sopenharmony_ci	obj->rdata = rdata;
64798c2ecf20Sopenharmony_ci	obj->rdata_mapping = rdata_mapping;
64808c2ecf20Sopenharmony_ci	obj->afex_rdata = afex_rdata;
64818c2ecf20Sopenharmony_ci	obj->afex_rdata_mapping = afex_rdata_mapping;
64828c2ecf20Sopenharmony_ci	obj->send_cmd = bnx2x_func_send_cmd;
64838c2ecf20Sopenharmony_ci	obj->check_transition = bnx2x_func_chk_transition;
64848c2ecf20Sopenharmony_ci	obj->complete_cmd = bnx2x_func_comp_cmd;
64858c2ecf20Sopenharmony_ci	obj->wait_comp = bnx2x_func_wait_comp;
64868c2ecf20Sopenharmony_ci
64878c2ecf20Sopenharmony_ci	obj->drv = drv_iface;
64888c2ecf20Sopenharmony_ci}
64898c2ecf20Sopenharmony_ci
64908c2ecf20Sopenharmony_ci/**
64918c2ecf20Sopenharmony_ci * bnx2x_func_state_change - perform Function state change transition
64928c2ecf20Sopenharmony_ci *
64938c2ecf20Sopenharmony_ci * @bp:		device handle
64948c2ecf20Sopenharmony_ci * @params:	parameters to perform the transaction
64958c2ecf20Sopenharmony_ci *
64968c2ecf20Sopenharmony_ci * returns 0 in case of successfully completed transition,
64978c2ecf20Sopenharmony_ci *         negative error code in case of failure, positive
64988c2ecf20Sopenharmony_ci *         (EBUSY) value if there is a completion to that is
64998c2ecf20Sopenharmony_ci *         still pending (possible only if RAMROD_COMP_WAIT is
65008c2ecf20Sopenharmony_ci *         not set in params->ramrod_flags for asynchronous
65018c2ecf20Sopenharmony_ci *         commands).
65028c2ecf20Sopenharmony_ci */
65038c2ecf20Sopenharmony_ciint bnx2x_func_state_change(struct bnx2x *bp,
65048c2ecf20Sopenharmony_ci			    struct bnx2x_func_state_params *params)
65058c2ecf20Sopenharmony_ci{
65068c2ecf20Sopenharmony_ci	struct bnx2x_func_sp_obj *o = params->f_obj;
65078c2ecf20Sopenharmony_ci	int rc, cnt = 300;
65088c2ecf20Sopenharmony_ci	enum bnx2x_func_cmd cmd = params->cmd;
65098c2ecf20Sopenharmony_ci	unsigned long *pending = &o->pending;
65108c2ecf20Sopenharmony_ci
65118c2ecf20Sopenharmony_ci	mutex_lock(&o->one_pending_mutex);
65128c2ecf20Sopenharmony_ci
65138c2ecf20Sopenharmony_ci	/* Check that the requested transition is legal */
65148c2ecf20Sopenharmony_ci	rc = o->check_transition(bp, o, params);
65158c2ecf20Sopenharmony_ci	if ((rc == -EBUSY) &&
65168c2ecf20Sopenharmony_ci	    (test_bit(RAMROD_RETRY, &params->ramrod_flags))) {
65178c2ecf20Sopenharmony_ci		while ((rc == -EBUSY) && (--cnt > 0)) {
65188c2ecf20Sopenharmony_ci			mutex_unlock(&o->one_pending_mutex);
65198c2ecf20Sopenharmony_ci			msleep(10);
65208c2ecf20Sopenharmony_ci			mutex_lock(&o->one_pending_mutex);
65218c2ecf20Sopenharmony_ci			rc = o->check_transition(bp, o, params);
65228c2ecf20Sopenharmony_ci		}
65238c2ecf20Sopenharmony_ci		if (rc == -EBUSY) {
65248c2ecf20Sopenharmony_ci			mutex_unlock(&o->one_pending_mutex);
65258c2ecf20Sopenharmony_ci			BNX2X_ERR("timeout waiting for previous ramrod completion\n");
65268c2ecf20Sopenharmony_ci			return rc;
65278c2ecf20Sopenharmony_ci		}
65288c2ecf20Sopenharmony_ci	} else if (rc) {
65298c2ecf20Sopenharmony_ci		mutex_unlock(&o->one_pending_mutex);
65308c2ecf20Sopenharmony_ci		return rc;
65318c2ecf20Sopenharmony_ci	}
65328c2ecf20Sopenharmony_ci
65338c2ecf20Sopenharmony_ci	/* Set "pending" bit */
65348c2ecf20Sopenharmony_ci	set_bit(cmd, pending);
65358c2ecf20Sopenharmony_ci
65368c2ecf20Sopenharmony_ci	/* Don't send a command if only driver cleanup was requested */
65378c2ecf20Sopenharmony_ci	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
65388c2ecf20Sopenharmony_ci		bnx2x_func_state_change_comp(bp, o, cmd);
65398c2ecf20Sopenharmony_ci		mutex_unlock(&o->one_pending_mutex);
65408c2ecf20Sopenharmony_ci	} else {
65418c2ecf20Sopenharmony_ci		/* Send a ramrod */
65428c2ecf20Sopenharmony_ci		rc = o->send_cmd(bp, params);
65438c2ecf20Sopenharmony_ci
65448c2ecf20Sopenharmony_ci		mutex_unlock(&o->one_pending_mutex);
65458c2ecf20Sopenharmony_ci
65468c2ecf20Sopenharmony_ci		if (rc) {
65478c2ecf20Sopenharmony_ci			o->next_state = BNX2X_F_STATE_MAX;
65488c2ecf20Sopenharmony_ci			clear_bit(cmd, pending);
65498c2ecf20Sopenharmony_ci			smp_mb__after_atomic();
65508c2ecf20Sopenharmony_ci			return rc;
65518c2ecf20Sopenharmony_ci		}
65528c2ecf20Sopenharmony_ci
65538c2ecf20Sopenharmony_ci		if (test_bit(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
65548c2ecf20Sopenharmony_ci			rc = o->wait_comp(bp, o, cmd);
65558c2ecf20Sopenharmony_ci			if (rc)
65568c2ecf20Sopenharmony_ci				return rc;
65578c2ecf20Sopenharmony_ci
65588c2ecf20Sopenharmony_ci			return 0;
65598c2ecf20Sopenharmony_ci		}
65608c2ecf20Sopenharmony_ci	}
65618c2ecf20Sopenharmony_ci
65628c2ecf20Sopenharmony_ci	return !!test_bit(cmd, pending);
65638c2ecf20Sopenharmony_ci}
6564