xref: /freebsd/sys/dev/bxe/ecore_sp.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
14e400768SDavid Christensen /*-
2*7282444bSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause
3*7282444bSPedro F. Giffuni  *
44ef8ebfdSDavid C Somayajulu  * Copyright (c) 2007-2017 QLogic Corporation. All rights reserved.
54e400768SDavid Christensen  *
64e400768SDavid Christensen  * Redistribution and use in source and binary forms, with or without
74e400768SDavid Christensen  * modification, are permitted provided that the following conditions
84e400768SDavid Christensen  * are met:
94e400768SDavid Christensen  *
104e400768SDavid Christensen  * 1. Redistributions of source code must retain the above copyright
114e400768SDavid Christensen  *    notice, this list of conditions and the following disclaimer.
124e400768SDavid Christensen  * 2. Redistributions in binary form must reproduce the above copyright
134e400768SDavid Christensen  *    notice, this list of conditions and the following disclaimer in the
144e400768SDavid Christensen  *    documentation and/or other materials provided with the distribution.
154e400768SDavid Christensen  *
164ef8ebfdSDavid C Somayajulu  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
174e400768SDavid Christensen  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
184e400768SDavid Christensen  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
194e400768SDavid Christensen  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
204e400768SDavid Christensen  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
214e400768SDavid Christensen  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
224e400768SDavid Christensen  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
234e400768SDavid Christensen  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
244e400768SDavid Christensen  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
254e400768SDavid Christensen  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
264e400768SDavid Christensen  * THE POSSIBILITY OF SUCH DAMAGE.
274e400768SDavid Christensen  */
284e400768SDavid Christensen 
294e400768SDavid Christensen #include <sys/cdefs.h>
304e400768SDavid Christensen #include "bxe.h"
314e400768SDavid Christensen #include "ecore_init.h"
324e400768SDavid Christensen 
334ef8ebfdSDavid C Somayajulu 
344ef8ebfdSDavid C Somayajulu 
354ef8ebfdSDavid C Somayajulu 
364e400768SDavid Christensen /**** Exe Queue interfaces ****/
374e400768SDavid Christensen 
384e400768SDavid Christensen /**
394e400768SDavid Christensen  * ecore_exe_queue_init - init the Exe Queue object
404e400768SDavid Christensen  *
414e400768SDavid Christensen  * @o:		pointer to the object
424e400768SDavid Christensen  * @exe_len:	length
434e400768SDavid Christensen  * @owner:	pointer to the owner
444e400768SDavid Christensen  * @validate:	validate function pointer
454e400768SDavid Christensen  * @optimize:	optimize function pointer
464e400768SDavid Christensen  * @exec:	execute function pointer
474e400768SDavid Christensen  * @get:	get function pointer
484e400768SDavid Christensen  */
ecore_exe_queue_init(struct bxe_softc * sc,struct ecore_exe_queue_obj * o,int exe_len,union ecore_qable_obj * owner,exe_q_validate validate,exe_q_remove remove,exe_q_optimize optimize,exe_q_execute exec,exe_q_get get)494e400768SDavid Christensen static inline void ecore_exe_queue_init(struct bxe_softc *sc,
504e400768SDavid Christensen 					struct ecore_exe_queue_obj *o,
514e400768SDavid Christensen 					int exe_len,
524e400768SDavid Christensen 					union ecore_qable_obj *owner,
534e400768SDavid Christensen 					exe_q_validate validate,
544e400768SDavid Christensen 					exe_q_remove remove,
554e400768SDavid Christensen 					exe_q_optimize optimize,
564e400768SDavid Christensen 					exe_q_execute exec,
574e400768SDavid Christensen 					exe_q_get get)
584e400768SDavid Christensen {
594e400768SDavid Christensen 	ECORE_MEMSET(o, 0, sizeof(*o));
604e400768SDavid Christensen 
614e400768SDavid Christensen 	ECORE_LIST_INIT(&o->exe_queue);
624e400768SDavid Christensen 	ECORE_LIST_INIT(&o->pending_comp);
634e400768SDavid Christensen 
644e400768SDavid Christensen 	ECORE_SPIN_LOCK_INIT(&o->lock, sc);
654e400768SDavid Christensen 
664e400768SDavid Christensen 	o->exe_chunk_len = exe_len;
674e400768SDavid Christensen 	o->owner         = owner;
684e400768SDavid Christensen 
694e400768SDavid Christensen 	/* Owner specific callbacks */
704e400768SDavid Christensen 	o->validate      = validate;
714e400768SDavid Christensen 	o->remove        = remove;
724e400768SDavid Christensen 	o->optimize      = optimize;
734e400768SDavid Christensen 	o->execute       = exec;
744e400768SDavid Christensen 	o->get           = get;
754e400768SDavid Christensen 
764e400768SDavid Christensen 	ECORE_MSG(sc, "Setup the execution queue with the chunk length of %d\n",
774e400768SDavid Christensen 		  exe_len);
784e400768SDavid Christensen }
794e400768SDavid Christensen 
ecore_exe_queue_free_elem(struct bxe_softc * sc,struct ecore_exeq_elem * elem)804e400768SDavid Christensen static inline void ecore_exe_queue_free_elem(struct bxe_softc *sc,
814e400768SDavid Christensen 					     struct ecore_exeq_elem *elem)
824e400768SDavid Christensen {
834e400768SDavid Christensen 	ECORE_MSG(sc, "Deleting an exe_queue element\n");
844e400768SDavid Christensen 	ECORE_FREE(sc, elem, sizeof(*elem));
854e400768SDavid Christensen }
864e400768SDavid Christensen 
ecore_exe_queue_length(struct ecore_exe_queue_obj * o)874e400768SDavid Christensen static inline int ecore_exe_queue_length(struct ecore_exe_queue_obj *o)
884e400768SDavid Christensen {
894e400768SDavid Christensen 	struct ecore_exeq_elem *elem;
904e400768SDavid Christensen 	int cnt = 0;
914e400768SDavid Christensen 
924e400768SDavid Christensen 	ECORE_SPIN_LOCK_BH(&o->lock);
934e400768SDavid Christensen 
944e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(elem, &o->exe_queue, link,
954e400768SDavid Christensen 				  struct ecore_exeq_elem)
964e400768SDavid Christensen 		cnt++;
974e400768SDavid Christensen 
984e400768SDavid Christensen 	ECORE_SPIN_UNLOCK_BH(&o->lock);
994e400768SDavid Christensen 
1004e400768SDavid Christensen 	return cnt;
1014e400768SDavid Christensen }
1024e400768SDavid Christensen 
1034e400768SDavid Christensen /**
1044e400768SDavid Christensen  * ecore_exe_queue_add - add a new element to the execution queue
1054e400768SDavid Christensen  *
1064e400768SDavid Christensen  * @sc:		driver handle
1074e400768SDavid Christensen  * @o:		queue
1084e400768SDavid Christensen  * @cmd:	new command to add
1094e400768SDavid Christensen  * @restore:	true - do not optimize the command
1104e400768SDavid Christensen  *
1114e400768SDavid Christensen  * If the element is optimized or is illegal, frees it.
1124e400768SDavid Christensen  */
ecore_exe_queue_add(struct bxe_softc * sc,struct ecore_exe_queue_obj * o,struct ecore_exeq_elem * elem,bool restore)1134e400768SDavid Christensen static inline int ecore_exe_queue_add(struct bxe_softc *sc,
1144e400768SDavid Christensen 				      struct ecore_exe_queue_obj *o,
1154e400768SDavid Christensen 				      struct ecore_exeq_elem *elem,
1164e400768SDavid Christensen 				      bool restore)
1174e400768SDavid Christensen {
1184e400768SDavid Christensen 	int rc;
1194e400768SDavid Christensen 
1204e400768SDavid Christensen 	ECORE_SPIN_LOCK_BH(&o->lock);
1214e400768SDavid Christensen 
1224e400768SDavid Christensen 	if (!restore) {
1234e400768SDavid Christensen 		/* Try to cancel this element queue */
1244e400768SDavid Christensen 		rc = o->optimize(sc, o->owner, elem);
1254e400768SDavid Christensen 		if (rc)
1264e400768SDavid Christensen 			goto free_and_exit;
1274e400768SDavid Christensen 
1284e400768SDavid Christensen 		/* Check if this request is ok */
1294e400768SDavid Christensen 		rc = o->validate(sc, o->owner, elem);
1304e400768SDavid Christensen 		if (rc) {
1314e400768SDavid Christensen 			ECORE_MSG(sc, "Preamble failed: %d\n", rc);
1324e400768SDavid Christensen 			goto free_and_exit;
1334e400768SDavid Christensen 		}
1344e400768SDavid Christensen 	}
1354e400768SDavid Christensen 
1364e400768SDavid Christensen 	/* If so, add it to the execution queue */
1374e400768SDavid Christensen 	ECORE_LIST_PUSH_TAIL(&elem->link, &o->exe_queue);
1384e400768SDavid Christensen 
1394e400768SDavid Christensen 	ECORE_SPIN_UNLOCK_BH(&o->lock);
1404e400768SDavid Christensen 
1414e400768SDavid Christensen 	return ECORE_SUCCESS;
1424e400768SDavid Christensen 
1434e400768SDavid Christensen free_and_exit:
1444e400768SDavid Christensen 	ecore_exe_queue_free_elem(sc, elem);
1454e400768SDavid Christensen 
1464e400768SDavid Christensen 	ECORE_SPIN_UNLOCK_BH(&o->lock);
1474e400768SDavid Christensen 
1484e400768SDavid Christensen 	return rc;
1494e400768SDavid Christensen }
1504e400768SDavid Christensen 
__ecore_exe_queue_reset_pending(struct bxe_softc * sc,struct ecore_exe_queue_obj * o)1514e400768SDavid Christensen static inline void __ecore_exe_queue_reset_pending(
1524e400768SDavid Christensen 	struct bxe_softc *sc,
1534e400768SDavid Christensen 	struct ecore_exe_queue_obj *o)
1544e400768SDavid Christensen {
1554e400768SDavid Christensen 	struct ecore_exeq_elem *elem;
1564e400768SDavid Christensen 
1574e400768SDavid Christensen 	while (!ECORE_LIST_IS_EMPTY(&o->pending_comp)) {
1584e400768SDavid Christensen 		elem = ECORE_LIST_FIRST_ENTRY(&o->pending_comp,
1594e400768SDavid Christensen 					      struct ecore_exeq_elem,
1604e400768SDavid Christensen 					      link);
1614e400768SDavid Christensen 
1624e400768SDavid Christensen 		ECORE_LIST_REMOVE_ENTRY(&elem->link, &o->pending_comp);
1634e400768SDavid Christensen 		ecore_exe_queue_free_elem(sc, elem);
1644e400768SDavid Christensen 	}
1654e400768SDavid Christensen }
1664e400768SDavid Christensen 
1674e400768SDavid Christensen /**
1684e400768SDavid Christensen  * ecore_exe_queue_step - execute one execution chunk atomically
1694e400768SDavid Christensen  *
1704e400768SDavid Christensen  * @sc:			driver handle
1714e400768SDavid Christensen  * @o:			queue
1724e400768SDavid Christensen  * @ramrod_flags:	flags
1734e400768SDavid Christensen  *
1744e400768SDavid Christensen  * (Should be called while holding the exe_queue->lock).
1754e400768SDavid Christensen  */
ecore_exe_queue_step(struct bxe_softc * sc,struct ecore_exe_queue_obj * o,unsigned long * ramrod_flags)1764e400768SDavid Christensen static inline int ecore_exe_queue_step(struct bxe_softc *sc,
1774e400768SDavid Christensen 				       struct ecore_exe_queue_obj *o,
1784e400768SDavid Christensen 				       unsigned long *ramrod_flags)
1794e400768SDavid Christensen {
1804e400768SDavid Christensen 	struct ecore_exeq_elem *elem, spacer;
1814e400768SDavid Christensen 	int cur_len = 0, rc;
1824e400768SDavid Christensen 
1834e400768SDavid Christensen 	ECORE_MEMSET(&spacer, 0, sizeof(spacer));
1844e400768SDavid Christensen 
1854e400768SDavid Christensen 	/* Next step should not be performed until the current is finished,
1864e400768SDavid Christensen 	 * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to
1874e400768SDavid Christensen 	 * properly clear object internals without sending any command to the FW
1884e400768SDavid Christensen 	 * which also implies there won't be any completion to clear the
1894e400768SDavid Christensen 	 * 'pending' list.
1904e400768SDavid Christensen 	 */
1914e400768SDavid Christensen 	if (!ECORE_LIST_IS_EMPTY(&o->pending_comp)) {
1924e400768SDavid Christensen 		if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, ramrod_flags)) {
1934e400768SDavid Christensen 			ECORE_MSG(sc, "RAMROD_DRV_CLR_ONLY requested: resetting a pending_comp list\n");
1944e400768SDavid Christensen 			__ecore_exe_queue_reset_pending(sc, o);
1954e400768SDavid Christensen 		} else {
1964e400768SDavid Christensen 			return ECORE_PENDING;
1974e400768SDavid Christensen 		}
1984e400768SDavid Christensen 	}
1994e400768SDavid Christensen 
2004e400768SDavid Christensen 	/* Run through the pending commands list and create a next
2014e400768SDavid Christensen 	 * execution chunk.
2024e400768SDavid Christensen 	 */
2034e400768SDavid Christensen 	while (!ECORE_LIST_IS_EMPTY(&o->exe_queue)) {
2044e400768SDavid Christensen 		elem = ECORE_LIST_FIRST_ENTRY(&o->exe_queue,
2054e400768SDavid Christensen 					      struct ecore_exeq_elem,
2064e400768SDavid Christensen 					      link);
2074e400768SDavid Christensen 		ECORE_DBG_BREAK_IF(!elem->cmd_len);
2084e400768SDavid Christensen 
2094e400768SDavid Christensen 		if (cur_len + elem->cmd_len <= o->exe_chunk_len) {
2104e400768SDavid Christensen 			cur_len += elem->cmd_len;
2114e400768SDavid Christensen 			/* Prevent from both lists being empty when moving an
2124e400768SDavid Christensen 			 * element. This will allow the call of
2134e400768SDavid Christensen 			 * ecore_exe_queue_empty() without locking.
2144e400768SDavid Christensen 			 */
2154e400768SDavid Christensen 			ECORE_LIST_PUSH_TAIL(&spacer.link, &o->pending_comp);
2164e400768SDavid Christensen 			mb();
2174e400768SDavid Christensen 			ECORE_LIST_REMOVE_ENTRY(&elem->link, &o->exe_queue);
2184e400768SDavid Christensen 			ECORE_LIST_PUSH_TAIL(&elem->link, &o->pending_comp);
2194e400768SDavid Christensen 			ECORE_LIST_REMOVE_ENTRY(&spacer.link, &o->pending_comp);
2204e400768SDavid Christensen 		} else
2214e400768SDavid Christensen 			break;
2224e400768SDavid Christensen 	}
2234e400768SDavid Christensen 
2244e400768SDavid Christensen 	/* Sanity check */
2254e400768SDavid Christensen 	if (!cur_len)
2264e400768SDavid Christensen 		return ECORE_SUCCESS;
2274e400768SDavid Christensen 
2284e400768SDavid Christensen 	rc = o->execute(sc, o->owner, &o->pending_comp, ramrod_flags);
2294e400768SDavid Christensen 	if (rc < 0)
2304e400768SDavid Christensen 		/* In case of an error return the commands back to the queue
2314e400768SDavid Christensen 		 *  and reset the pending_comp.
2324e400768SDavid Christensen 		 */
2334e400768SDavid Christensen 		ECORE_LIST_SPLICE_INIT(&o->pending_comp, &o->exe_queue);
2344e400768SDavid Christensen 	else if (!rc)
2354e400768SDavid Christensen 		/* If zero is returned, means there are no outstanding pending
2364e400768SDavid Christensen 		 * completions and we may dismiss the pending list.
2374e400768SDavid Christensen 		 */
2384e400768SDavid Christensen 		__ecore_exe_queue_reset_pending(sc, o);
2394e400768SDavid Christensen 
2404e400768SDavid Christensen 	return rc;
2414e400768SDavid Christensen }
2424e400768SDavid Christensen 
ecore_exe_queue_empty(struct ecore_exe_queue_obj * o)2434e400768SDavid Christensen static inline bool ecore_exe_queue_empty(struct ecore_exe_queue_obj *o)
2444e400768SDavid Christensen {
2454e400768SDavid Christensen 	bool empty = ECORE_LIST_IS_EMPTY(&o->exe_queue);
2464e400768SDavid Christensen 
2474e400768SDavid Christensen 	/* Don't reorder!!! */
2484e400768SDavid Christensen 	mb();
2494e400768SDavid Christensen 
2504e400768SDavid Christensen 	return empty && ECORE_LIST_IS_EMPTY(&o->pending_comp);
2514e400768SDavid Christensen }
2524e400768SDavid Christensen 
ecore_exe_queue_alloc_elem(struct bxe_softc * sc)2534e400768SDavid Christensen static inline struct ecore_exeq_elem *ecore_exe_queue_alloc_elem(
2544e400768SDavid Christensen 	struct bxe_softc *sc)
2554e400768SDavid Christensen {
2564e400768SDavid Christensen 	ECORE_MSG(sc, "Allocating a new exe_queue element\n");
2574e400768SDavid Christensen 	return ECORE_ZALLOC(sizeof(struct ecore_exeq_elem), GFP_ATOMIC,
2584e400768SDavid Christensen 			    sc);
2594e400768SDavid Christensen }
2604e400768SDavid Christensen 
2614e400768SDavid Christensen /************************ raw_obj functions ***********************************/
ecore_raw_check_pending(struct ecore_raw_obj * o)2624e400768SDavid Christensen static bool ecore_raw_check_pending(struct ecore_raw_obj *o)
2634e400768SDavid Christensen {
2644e400768SDavid Christensen 	/*
2654e400768SDavid Christensen      * !! converts the value returned by ECORE_TEST_BIT such that it
2664e400768SDavid Christensen      * is guaranteed not to be truncated regardless of bool definition.
2674e400768SDavid Christensen 	 *
2684e400768SDavid Christensen 	 * Note we cannot simply define the function's return value type
2694e400768SDavid Christensen      * to match the type returned by ECORE_TEST_BIT, as it varies by
2704e400768SDavid Christensen      * platform/implementation.
2714e400768SDavid Christensen 	 */
2724e400768SDavid Christensen 
2734e400768SDavid Christensen 	return !!ECORE_TEST_BIT(o->state, o->pstate);
2744e400768SDavid Christensen }
2754e400768SDavid Christensen 
ecore_raw_clear_pending(struct ecore_raw_obj * o)2764e400768SDavid Christensen static void ecore_raw_clear_pending(struct ecore_raw_obj *o)
2774e400768SDavid Christensen {
2784e400768SDavid Christensen 	ECORE_SMP_MB_BEFORE_CLEAR_BIT();
2794e400768SDavid Christensen 	ECORE_CLEAR_BIT(o->state, o->pstate);
2804e400768SDavid Christensen 	ECORE_SMP_MB_AFTER_CLEAR_BIT();
2814e400768SDavid Christensen }
2824e400768SDavid Christensen 
ecore_raw_set_pending(struct ecore_raw_obj * o)2834e400768SDavid Christensen static void ecore_raw_set_pending(struct ecore_raw_obj *o)
2844e400768SDavid Christensen {
2854e400768SDavid Christensen 	ECORE_SMP_MB_BEFORE_CLEAR_BIT();
2864e400768SDavid Christensen 	ECORE_SET_BIT(o->state, o->pstate);
2874e400768SDavid Christensen 	ECORE_SMP_MB_AFTER_CLEAR_BIT();
2884e400768SDavid Christensen }
2894e400768SDavid Christensen 
2904e400768SDavid Christensen /**
2914e400768SDavid Christensen  * ecore_state_wait - wait until the given bit(state) is cleared
2924e400768SDavid Christensen  *
2934e400768SDavid Christensen  * @sc:		device handle
2944e400768SDavid Christensen  * @state:	state which is to be cleared
2954e400768SDavid Christensen  * @state_p:	state buffer
2964e400768SDavid Christensen  *
2974e400768SDavid Christensen  */
ecore_state_wait(struct bxe_softc * sc,int state,unsigned long * pstate)2984e400768SDavid Christensen static inline int ecore_state_wait(struct bxe_softc *sc, int state,
2994e400768SDavid Christensen 				   unsigned long *pstate)
3004e400768SDavid Christensen {
3014e400768SDavid Christensen 	/* can take a while if any port is running */
3024e400768SDavid Christensen 	int cnt = 5000;
3034e400768SDavid Christensen 
3044e400768SDavid Christensen 
3054e400768SDavid Christensen 	if (CHIP_REV_IS_EMUL(sc))
3064e400768SDavid Christensen 		cnt *= 20;
3074e400768SDavid Christensen 
3084e400768SDavid Christensen 	ECORE_MSG(sc, "waiting for state to become %d\n", state);
3094e400768SDavid Christensen 
3104e400768SDavid Christensen 	ECORE_MIGHT_SLEEP();
3114e400768SDavid Christensen 	while (cnt--) {
3124e400768SDavid Christensen 		if (!ECORE_TEST_BIT(state, pstate)) {
3134e400768SDavid Christensen #ifdef ECORE_STOP_ON_ERROR
3144e400768SDavid Christensen 			ECORE_MSG(sc, "exit  (cnt %d)\n", 5000 - cnt);
3154e400768SDavid Christensen #endif
3164e400768SDavid Christensen 			return ECORE_SUCCESS;
3174e400768SDavid Christensen 		}
3184e400768SDavid Christensen 
3194e400768SDavid Christensen 		ECORE_WAIT(sc, delay_us);
3204e400768SDavid Christensen 
3214e400768SDavid Christensen 		if (sc->panic)
3224e400768SDavid Christensen 			return ECORE_IO;
3234e400768SDavid Christensen 	}
3244e400768SDavid Christensen 
3254e400768SDavid Christensen 	/* timeout! */
3264e400768SDavid Christensen 	ECORE_ERR("timeout waiting for state %d\n", state);
3274e400768SDavid Christensen #ifdef ECORE_STOP_ON_ERROR
3284e400768SDavid Christensen 	ecore_panic();
3294e400768SDavid Christensen #endif
3304e400768SDavid Christensen 
3314e400768SDavid Christensen 	return ECORE_TIMEOUT;
3324e400768SDavid Christensen }
3334e400768SDavid Christensen 
ecore_raw_wait(struct bxe_softc * sc,struct ecore_raw_obj * raw)3344e400768SDavid Christensen static int ecore_raw_wait(struct bxe_softc *sc, struct ecore_raw_obj *raw)
3354e400768SDavid Christensen {
3364e400768SDavid Christensen 	return ecore_state_wait(sc, raw->state, raw->pstate);
3374e400768SDavid Christensen }
3384e400768SDavid Christensen 
3394e400768SDavid Christensen /***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
3404e400768SDavid Christensen /* credit handling callbacks */
ecore_get_cam_offset_mac(struct ecore_vlan_mac_obj * o,int * offset)3414e400768SDavid Christensen static bool ecore_get_cam_offset_mac(struct ecore_vlan_mac_obj *o, int *offset)
3424e400768SDavid Christensen {
3434e400768SDavid Christensen 	struct ecore_credit_pool_obj *mp = o->macs_pool;
3444e400768SDavid Christensen 
3454e400768SDavid Christensen 	ECORE_DBG_BREAK_IF(!mp);
3464e400768SDavid Christensen 
3474e400768SDavid Christensen 	return mp->get_entry(mp, offset);
3484e400768SDavid Christensen }
3494e400768SDavid Christensen 
ecore_get_credit_mac(struct ecore_vlan_mac_obj * o)3504e400768SDavid Christensen static bool ecore_get_credit_mac(struct ecore_vlan_mac_obj *o)
3514e400768SDavid Christensen {
3524e400768SDavid Christensen 	struct ecore_credit_pool_obj *mp = o->macs_pool;
3534e400768SDavid Christensen 
3544e400768SDavid Christensen 	ECORE_DBG_BREAK_IF(!mp);
3554e400768SDavid Christensen 
3564e400768SDavid Christensen 	return mp->get(mp, 1);
3574e400768SDavid Christensen }
3584e400768SDavid Christensen 
ecore_get_cam_offset_vlan(struct ecore_vlan_mac_obj * o,int * offset)3594e400768SDavid Christensen static bool ecore_get_cam_offset_vlan(struct ecore_vlan_mac_obj *o, int *offset)
3604e400768SDavid Christensen {
3614e400768SDavid Christensen 	struct ecore_credit_pool_obj *vp = o->vlans_pool;
3624e400768SDavid Christensen 
3634e400768SDavid Christensen 	ECORE_DBG_BREAK_IF(!vp);
3644e400768SDavid Christensen 
3654e400768SDavid Christensen 	return vp->get_entry(vp, offset);
3664e400768SDavid Christensen }
3674e400768SDavid Christensen 
ecore_get_credit_vlan(struct ecore_vlan_mac_obj * o)3684e400768SDavid Christensen static bool ecore_get_credit_vlan(struct ecore_vlan_mac_obj *o)
3694e400768SDavid Christensen {
3704e400768SDavid Christensen 	struct ecore_credit_pool_obj *vp = o->vlans_pool;
3714e400768SDavid Christensen 
3724e400768SDavid Christensen 	ECORE_DBG_BREAK_IF(!vp);
3734e400768SDavid Christensen 
3744e400768SDavid Christensen 	return vp->get(vp, 1);
3754e400768SDavid Christensen }
3764e400768SDavid Christensen 
ecore_get_credit_vlan_mac(struct ecore_vlan_mac_obj * o)3774e400768SDavid Christensen static bool ecore_get_credit_vlan_mac(struct ecore_vlan_mac_obj *o)
3784e400768SDavid Christensen {
3794e400768SDavid Christensen 	struct ecore_credit_pool_obj *mp = o->macs_pool;
3804e400768SDavid Christensen 	struct ecore_credit_pool_obj *vp = o->vlans_pool;
3814e400768SDavid Christensen 
3824e400768SDavid Christensen 	if (!mp->get(mp, 1))
3834e400768SDavid Christensen 		return FALSE;
3844e400768SDavid Christensen 
3854e400768SDavid Christensen 	if (!vp->get(vp, 1)) {
3864e400768SDavid Christensen 		mp->put(mp, 1);
3874e400768SDavid Christensen 		return FALSE;
3884e400768SDavid Christensen 	}
3894e400768SDavid Christensen 
3904e400768SDavid Christensen 	return TRUE;
3914e400768SDavid Christensen }
3924e400768SDavid Christensen 
ecore_put_cam_offset_mac(struct ecore_vlan_mac_obj * o,int offset)3934e400768SDavid Christensen static bool ecore_put_cam_offset_mac(struct ecore_vlan_mac_obj *o, int offset)
3944e400768SDavid Christensen {
3954e400768SDavid Christensen 	struct ecore_credit_pool_obj *mp = o->macs_pool;
3964e400768SDavid Christensen 
3974e400768SDavid Christensen 	return mp->put_entry(mp, offset);
3984e400768SDavid Christensen }
3994e400768SDavid Christensen 
ecore_put_credit_mac(struct ecore_vlan_mac_obj * o)4004e400768SDavid Christensen static bool ecore_put_credit_mac(struct ecore_vlan_mac_obj *o)
4014e400768SDavid Christensen {
4024e400768SDavid Christensen 	struct ecore_credit_pool_obj *mp = o->macs_pool;
4034e400768SDavid Christensen 
4044e400768SDavid Christensen 	return mp->put(mp, 1);
4054e400768SDavid Christensen }
4064e400768SDavid Christensen 
ecore_put_cam_offset_vlan(struct ecore_vlan_mac_obj * o,int offset)4074e400768SDavid Christensen static bool ecore_put_cam_offset_vlan(struct ecore_vlan_mac_obj *o, int offset)
4084e400768SDavid Christensen {
4094e400768SDavid Christensen 	struct ecore_credit_pool_obj *vp = o->vlans_pool;
4104e400768SDavid Christensen 
4114e400768SDavid Christensen 	return vp->put_entry(vp, offset);
4124e400768SDavid Christensen }
4134e400768SDavid Christensen 
ecore_put_credit_vlan(struct ecore_vlan_mac_obj * o)4144e400768SDavid Christensen static bool ecore_put_credit_vlan(struct ecore_vlan_mac_obj *o)
4154e400768SDavid Christensen {
4164e400768SDavid Christensen 	struct ecore_credit_pool_obj *vp = o->vlans_pool;
4174e400768SDavid Christensen 
4184e400768SDavid Christensen 	return vp->put(vp, 1);
4194e400768SDavid Christensen }
4204e400768SDavid Christensen 
ecore_put_credit_vlan_mac(struct ecore_vlan_mac_obj * o)4214e400768SDavid Christensen static bool ecore_put_credit_vlan_mac(struct ecore_vlan_mac_obj *o)
4224e400768SDavid Christensen {
4234e400768SDavid Christensen 	struct ecore_credit_pool_obj *mp = o->macs_pool;
4244e400768SDavid Christensen 	struct ecore_credit_pool_obj *vp = o->vlans_pool;
4254e400768SDavid Christensen 
4264e400768SDavid Christensen 	if (!mp->put(mp, 1))
4274e400768SDavid Christensen 		return FALSE;
4284e400768SDavid Christensen 
4294e400768SDavid Christensen 	if (!vp->put(vp, 1)) {
4304e400768SDavid Christensen 		mp->get(mp, 1);
4314e400768SDavid Christensen 		return FALSE;
4324e400768SDavid Christensen 	}
4334e400768SDavid Christensen 
4344e400768SDavid Christensen 	return TRUE;
4354e400768SDavid Christensen }
4364e400768SDavid Christensen 
4374e400768SDavid Christensen /**
4384e400768SDavid Christensen  * __ecore_vlan_mac_h_write_trylock - try getting the writer lock on vlan mac
4394e400768SDavid Christensen  * head list.
4404e400768SDavid Christensen  *
4414e400768SDavid Christensen  * @sc:		device handle
4424e400768SDavid Christensen  * @o:		vlan_mac object
4434e400768SDavid Christensen  *
4444e400768SDavid Christensen  * @details: Non-blocking implementation; should be called under execution
4454e400768SDavid Christensen  *           queue lock.
4464e400768SDavid Christensen  */
__ecore_vlan_mac_h_write_trylock(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o)4474e400768SDavid Christensen static int __ecore_vlan_mac_h_write_trylock(struct bxe_softc *sc,
4484e400768SDavid Christensen 					    struct ecore_vlan_mac_obj *o)
4494e400768SDavid Christensen {
4504e400768SDavid Christensen 	if (o->head_reader) {
4514e400768SDavid Christensen 		ECORE_MSG(sc, "vlan_mac_lock writer - There are readers; Busy\n");
4524e400768SDavid Christensen 		return ECORE_BUSY;
4534e400768SDavid Christensen 	}
4544e400768SDavid Christensen 
4554e400768SDavid Christensen 	ECORE_MSG(sc, "vlan_mac_lock writer - Taken\n");
4564e400768SDavid Christensen 	return ECORE_SUCCESS;
4574e400768SDavid Christensen }
4584e400768SDavid Christensen 
4594e400768SDavid Christensen /**
4604e400768SDavid Christensen  * __ecore_vlan_mac_h_exec_pending - execute step instead of a previous step
4614e400768SDavid Christensen  * which wasn't able to run due to a taken lock on vlan mac head list.
4624e400768SDavid Christensen  *
4634e400768SDavid Christensen  * @sc:		device handle
4644e400768SDavid Christensen  * @o:		vlan_mac object
4654e400768SDavid Christensen  *
4664e400768SDavid Christensen  * @details Should be called under execution queue lock; notice it might release
4674e400768SDavid Christensen  *          and reclaim it during its run.
4684e400768SDavid Christensen  */
__ecore_vlan_mac_h_exec_pending(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o)4694e400768SDavid Christensen static void __ecore_vlan_mac_h_exec_pending(struct bxe_softc *sc,
4704e400768SDavid Christensen 					    struct ecore_vlan_mac_obj *o)
4714e400768SDavid Christensen {
4724e400768SDavid Christensen 	int rc;
4734e400768SDavid Christensen 	unsigned long ramrod_flags = o->saved_ramrod_flags;
4744e400768SDavid Christensen 
4754e400768SDavid Christensen 	ECORE_MSG(sc, "vlan_mac_lock execute pending command with ramrod flags %lu\n",
4764e400768SDavid Christensen 		  ramrod_flags);
4774e400768SDavid Christensen 	o->head_exe_request = FALSE;
4784e400768SDavid Christensen 	o->saved_ramrod_flags = 0;
4795e33becaSEric Davis 	rc = ecore_exe_queue_step(sc, &o->exe_queue, &ramrod_flags);
4809987f305SDavid C Somayajulu 	if ((rc != ECORE_SUCCESS) && (rc != ECORE_PENDING)) {
4814e400768SDavid Christensen 		ECORE_ERR("execution of pending commands failed with rc %d\n",
4824e400768SDavid Christensen 			  rc);
4834e400768SDavid Christensen #ifdef ECORE_STOP_ON_ERROR
4844e400768SDavid Christensen 		ecore_panic();
4854e400768SDavid Christensen #endif
4864e400768SDavid Christensen 	}
4874e400768SDavid Christensen }
4884e400768SDavid Christensen 
4894e400768SDavid Christensen /**
4904e400768SDavid Christensen  * __ecore_vlan_mac_h_pend - Pend an execution step which couldn't have been
4914e400768SDavid Christensen  * called due to vlan mac head list lock being taken.
4924e400768SDavid Christensen  *
4934e400768SDavid Christensen  * @sc:			device handle
4944e400768SDavid Christensen  * @o:			vlan_mac object
4954e400768SDavid Christensen  * @ramrod_flags:	ramrod flags of missed execution
4964e400768SDavid Christensen  *
4974e400768SDavid Christensen  * @details Should be called under execution queue lock.
4984e400768SDavid Christensen  */
__ecore_vlan_mac_h_pend(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,unsigned long ramrod_flags)4994e400768SDavid Christensen static void __ecore_vlan_mac_h_pend(struct bxe_softc *sc,
5004e400768SDavid Christensen 				    struct ecore_vlan_mac_obj *o,
5014e400768SDavid Christensen 				    unsigned long ramrod_flags)
5024e400768SDavid Christensen {
5034e400768SDavid Christensen 	o->head_exe_request = TRUE;
5044e400768SDavid Christensen 	o->saved_ramrod_flags = ramrod_flags;
5054e400768SDavid Christensen 	ECORE_MSG(sc, "Placing pending execution with ramrod flags %lu\n",
5064e400768SDavid Christensen 		  ramrod_flags);
5074e400768SDavid Christensen }
5084e400768SDavid Christensen 
5094e400768SDavid Christensen /**
5104e400768SDavid Christensen  * __ecore_vlan_mac_h_write_unlock - unlock the vlan mac head list writer lock
5114e400768SDavid Christensen  *
5124e400768SDavid Christensen  * @sc:			device handle
5134e400768SDavid Christensen  * @o:			vlan_mac object
5144e400768SDavid Christensen  *
5154e400768SDavid Christensen  * @details Should be called under execution queue lock. Notice if a pending
5164e400768SDavid Christensen  *          execution exists, it would perform it - possibly releasing and
5174e400768SDavid Christensen  *          reclaiming the execution queue lock.
5184e400768SDavid Christensen  */
__ecore_vlan_mac_h_write_unlock(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o)5194e400768SDavid Christensen static void __ecore_vlan_mac_h_write_unlock(struct bxe_softc *sc,
5204e400768SDavid Christensen 					    struct ecore_vlan_mac_obj *o)
5214e400768SDavid Christensen {
5224e400768SDavid Christensen 	/* It's possible a new pending execution was added since this writer
5234e400768SDavid Christensen 	 * executed. If so, execute again. [Ad infinitum]
5244e400768SDavid Christensen 	 */
5254e400768SDavid Christensen 	while(o->head_exe_request) {
5264e400768SDavid Christensen 		ECORE_MSG(sc, "vlan_mac_lock - writer release encountered a pending request\n");
5274e400768SDavid Christensen 		__ecore_vlan_mac_h_exec_pending(sc, o);
5284e400768SDavid Christensen 	}
5294e400768SDavid Christensen }
5304e400768SDavid Christensen 
5314e400768SDavid Christensen /**
5324e400768SDavid Christensen  * ecore_vlan_mac_h_write_unlock - unlock the vlan mac head list writer lock
5334e400768SDavid Christensen  *
5344e400768SDavid Christensen  * @sc:			device handle
5354e400768SDavid Christensen  * @o:			vlan_mac object
5364e400768SDavid Christensen  *
5374e400768SDavid Christensen  * @details Notice if a pending execution exists, it would perform it -
5384e400768SDavid Christensen  *          possibly releasing and reclaiming the execution queue lock.
5394e400768SDavid Christensen  */
ecore_vlan_mac_h_write_unlock(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o)5404e400768SDavid Christensen void ecore_vlan_mac_h_write_unlock(struct bxe_softc *sc,
5414e400768SDavid Christensen 				   struct ecore_vlan_mac_obj *o)
5424e400768SDavid Christensen {
5434e400768SDavid Christensen 	ECORE_SPIN_LOCK_BH(&o->exe_queue.lock);
5444e400768SDavid Christensen 	__ecore_vlan_mac_h_write_unlock(sc, o);
5454e400768SDavid Christensen 	ECORE_SPIN_UNLOCK_BH(&o->exe_queue.lock);
5464e400768SDavid Christensen }
5474e400768SDavid Christensen 
5484e400768SDavid Christensen /**
5494e400768SDavid Christensen  * __ecore_vlan_mac_h_read_lock - lock the vlan mac head list reader lock
5504e400768SDavid Christensen  *
5514e400768SDavid Christensen  * @sc:			device handle
5524e400768SDavid Christensen  * @o:			vlan_mac object
5534e400768SDavid Christensen  *
5544e400768SDavid Christensen  * @details Should be called under the execution queue lock. May sleep. May
5554e400768SDavid Christensen  *          release and reclaim execution queue lock during its run.
5564e400768SDavid Christensen  */
__ecore_vlan_mac_h_read_lock(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o)5574e400768SDavid Christensen static int __ecore_vlan_mac_h_read_lock(struct bxe_softc *sc,
5584e400768SDavid Christensen 					struct ecore_vlan_mac_obj *o)
5594e400768SDavid Christensen {
5604e400768SDavid Christensen 	/* If we got here, we're holding lock --> no WRITER exists */
5614e400768SDavid Christensen 	o->head_reader++;
5624e400768SDavid Christensen 	ECORE_MSG(sc, "vlan_mac_lock - locked reader - number %d\n",
5634e400768SDavid Christensen 		  o->head_reader);
5644e400768SDavid Christensen 
5654e400768SDavid Christensen 	return ECORE_SUCCESS;
5664e400768SDavid Christensen }
5674e400768SDavid Christensen 
5684e400768SDavid Christensen /**
5694e400768SDavid Christensen  * ecore_vlan_mac_h_read_lock - lock the vlan mac head list reader lock
5704e400768SDavid Christensen  *
5714e400768SDavid Christensen  * @sc:			device handle
5724e400768SDavid Christensen  * @o:			vlan_mac object
5734e400768SDavid Christensen  *
5744e400768SDavid Christensen  * @details May sleep. Claims and releases execution queue lock during its run.
5754e400768SDavid Christensen  */
ecore_vlan_mac_h_read_lock(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o)5764e400768SDavid Christensen int ecore_vlan_mac_h_read_lock(struct bxe_softc *sc,
5774e400768SDavid Christensen 			       struct ecore_vlan_mac_obj *o)
5784e400768SDavid Christensen {
5794e400768SDavid Christensen 	int rc;
5804e400768SDavid Christensen 
5814e400768SDavid Christensen 	ECORE_SPIN_LOCK_BH(&o->exe_queue.lock);
5824e400768SDavid Christensen 	rc = __ecore_vlan_mac_h_read_lock(sc, o);
5834e400768SDavid Christensen 	ECORE_SPIN_UNLOCK_BH(&o->exe_queue.lock);
5844e400768SDavid Christensen 
5854e400768SDavid Christensen 	return rc;
5864e400768SDavid Christensen }
5874e400768SDavid Christensen 
5884e400768SDavid Christensen /**
5894e400768SDavid Christensen  * __ecore_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock
5904e400768SDavid Christensen  *
5914e400768SDavid Christensen  * @sc:			device handle
5924e400768SDavid Christensen  * @o:			vlan_mac object
5934e400768SDavid Christensen  *
5944e400768SDavid Christensen  * @details Should be called under execution queue lock. Notice if a pending
5954e400768SDavid Christensen  *          execution exists, it would be performed if this was the last
5964e400768SDavid Christensen  *          reader. possibly releasing and reclaiming the execution queue lock.
5974e400768SDavid Christensen  */
__ecore_vlan_mac_h_read_unlock(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o)5984e400768SDavid Christensen static void __ecore_vlan_mac_h_read_unlock(struct bxe_softc *sc,
5994e400768SDavid Christensen 					  struct ecore_vlan_mac_obj *o)
6004e400768SDavid Christensen {
6014e400768SDavid Christensen 	if (!o->head_reader) {
6024e400768SDavid Christensen 		ECORE_ERR("Need to release vlan mac reader lock, but lock isn't taken\n");
6034e400768SDavid Christensen #ifdef ECORE_STOP_ON_ERROR
6044e400768SDavid Christensen 		ecore_panic();
6054e400768SDavid Christensen #endif
6064e400768SDavid Christensen 	} else {
6074e400768SDavid Christensen 		o->head_reader--;
6084e400768SDavid Christensen 		ECORE_MSG(sc, "vlan_mac_lock - decreased readers to %d\n",
6094e400768SDavid Christensen 			  o->head_reader);
6104e400768SDavid Christensen 	}
6114e400768SDavid Christensen 
6124e400768SDavid Christensen 	/* It's possible a new pending execution was added, and that this reader
6134e400768SDavid Christensen 	 * was last - if so we need to execute the command.
6144e400768SDavid Christensen 	 */
6154e400768SDavid Christensen 	if (!o->head_reader && o->head_exe_request) {
6164e400768SDavid Christensen 		ECORE_MSG(sc, "vlan_mac_lock - reader release encountered a pending request\n");
6174e400768SDavid Christensen 
6184e400768SDavid Christensen 		/* Writer release will do the trick */
6194e400768SDavid Christensen 		__ecore_vlan_mac_h_write_unlock(sc, o);
6204e400768SDavid Christensen 	}
6214e400768SDavid Christensen }
6224e400768SDavid Christensen 
6234e400768SDavid Christensen /**
6244e400768SDavid Christensen  * ecore_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock
6254e400768SDavid Christensen  *
6264e400768SDavid Christensen  * @sc:			device handle
6274e400768SDavid Christensen  * @o:			vlan_mac object
6284e400768SDavid Christensen  *
6294e400768SDavid Christensen  * @details Notice if a pending execution exists, it would be performed if this
6304e400768SDavid Christensen  *          was the last reader. Claims and releases the execution queue lock
6314e400768SDavid Christensen  *          during its run.
6324e400768SDavid Christensen  */
ecore_vlan_mac_h_read_unlock(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o)6334e400768SDavid Christensen void ecore_vlan_mac_h_read_unlock(struct bxe_softc *sc,
6344e400768SDavid Christensen 				  struct ecore_vlan_mac_obj *o)
6354e400768SDavid Christensen {
6364e400768SDavid Christensen 	ECORE_SPIN_LOCK_BH(&o->exe_queue.lock);
6374e400768SDavid Christensen 	__ecore_vlan_mac_h_read_unlock(sc, o);
6384e400768SDavid Christensen 	ECORE_SPIN_UNLOCK_BH(&o->exe_queue.lock);
6394e400768SDavid Christensen }
6404e400768SDavid Christensen 
6414e400768SDavid Christensen /**
6424e400768SDavid Christensen  * ecore_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock
6434e400768SDavid Christensen  *
6444e400768SDavid Christensen  * @sc:			device handle
6454e400768SDavid Christensen  * @o:			vlan_mac object
6464e400768SDavid Christensen  * @n:			number of elements to get
6474e400768SDavid Christensen  * @base:		base address for element placement
6484e400768SDavid Christensen  * @stride:		stride between elements (in bytes)
6494e400768SDavid Christensen  */
ecore_get_n_elements(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,int n,uint8_t * base,uint8_t stride,uint8_t size)6504e400768SDavid Christensen static int ecore_get_n_elements(struct bxe_softc *sc, struct ecore_vlan_mac_obj *o,
6514e400768SDavid Christensen 				 int n, uint8_t *base, uint8_t stride, uint8_t size)
6524e400768SDavid Christensen {
6534e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *pos;
6544e400768SDavid Christensen 	uint8_t *next = base;
6555e33becaSEric Davis 	int counter = 0;
6565e33becaSEric Davis 	int read_lock;
6574e400768SDavid Christensen 
6584e400768SDavid Christensen 	ECORE_MSG(sc, "get_n_elements - taking vlan_mac_lock (reader)\n");
6594e400768SDavid Christensen 	read_lock = ecore_vlan_mac_h_read_lock(sc, o);
6604e400768SDavid Christensen 	if (read_lock != ECORE_SUCCESS)
6614e400768SDavid Christensen 		ECORE_ERR("get_n_elements failed to get vlan mac reader lock; Access without lock\n");
6624e400768SDavid Christensen 
6634e400768SDavid Christensen 	/* traverse list */
6644e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link,
6654e400768SDavid Christensen 				  struct ecore_vlan_mac_registry_elem) {
6664e400768SDavid Christensen 		if (counter < n) {
6674e400768SDavid Christensen 			ECORE_MEMCPY(next, &pos->u, size);
6684e400768SDavid Christensen 			counter++;
6695e33becaSEric Davis 			ECORE_MSG(sc, "copied element number %d to address %p element was:\n",
6704e400768SDavid Christensen 				  counter, next);
6714e400768SDavid Christensen 			next += stride + size;
6724e400768SDavid Christensen 		}
6734e400768SDavid Christensen 	}
6744e400768SDavid Christensen 
6754e400768SDavid Christensen 	if (read_lock == ECORE_SUCCESS) {
6764e400768SDavid Christensen 		ECORE_MSG(sc, "get_n_elements - releasing vlan_mac_lock (reader)\n");
6774e400768SDavid Christensen 		ecore_vlan_mac_h_read_unlock(sc, o);
6784e400768SDavid Christensen 	}
6794e400768SDavid Christensen 
6804e400768SDavid Christensen 	return counter * ETH_ALEN;
6814e400768SDavid Christensen }
6824e400768SDavid Christensen 
6834e400768SDavid Christensen /* check_add() callbacks */
ecore_check_mac_add(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,union ecore_classification_ramrod_data * data)6844e400768SDavid Christensen static int ecore_check_mac_add(struct bxe_softc *sc,
6854e400768SDavid Christensen 			       struct ecore_vlan_mac_obj *o,
6864e400768SDavid Christensen 			       union ecore_classification_ramrod_data *data)
6874e400768SDavid Christensen {
6884e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *pos;
6894e400768SDavid Christensen 
6904e400768SDavid Christensen 	ECORE_MSG(sc, "Checking MAC %02x:%02x:%02x:%02x:%02x:%02x for ADD command\n", data->mac.mac[0], data->mac.mac[1], data->mac.mac[2], data->mac.mac[3], data->mac.mac[4], data->mac.mac[5]);
6914e400768SDavid Christensen 
6924e400768SDavid Christensen 	if (!ECORE_IS_VALID_ETHER_ADDR(data->mac.mac))
6934e400768SDavid Christensen 		return ECORE_INVAL;
6944e400768SDavid Christensen 
6954e400768SDavid Christensen 	/* Check if a requested MAC already exists */
6964e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link,
6974e400768SDavid Christensen 				  struct ecore_vlan_mac_registry_elem)
6984e400768SDavid Christensen 		if (!ECORE_MEMCMP(data->mac.mac, pos->u.mac.mac, ETH_ALEN) &&
6994e400768SDavid Christensen 		    (data->mac.is_inner_mac == pos->u.mac.is_inner_mac))
7004e400768SDavid Christensen 			return ECORE_EXISTS;
7014e400768SDavid Christensen 
7024e400768SDavid Christensen 	return ECORE_SUCCESS;
7034e400768SDavid Christensen }
7044e400768SDavid Christensen 
ecore_check_vlan_add(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,union ecore_classification_ramrod_data * data)7054e400768SDavid Christensen static int ecore_check_vlan_add(struct bxe_softc *sc,
7064e400768SDavid Christensen 				struct ecore_vlan_mac_obj *o,
7074e400768SDavid Christensen 				union ecore_classification_ramrod_data *data)
7084e400768SDavid Christensen {
7094e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *pos;
7104e400768SDavid Christensen 
7114e400768SDavid Christensen 	ECORE_MSG(sc, "Checking VLAN %d for ADD command\n", data->vlan.vlan);
7124e400768SDavid Christensen 
7134e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link,
7144e400768SDavid Christensen 				  struct ecore_vlan_mac_registry_elem)
7154e400768SDavid Christensen 		if (data->vlan.vlan == pos->u.vlan.vlan)
7164e400768SDavid Christensen 			return ECORE_EXISTS;
7174e400768SDavid Christensen 
7184e400768SDavid Christensen 	return ECORE_SUCCESS;
7194e400768SDavid Christensen }
7204e400768SDavid Christensen 
ecore_check_vlan_mac_add(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,union ecore_classification_ramrod_data * data)7214e400768SDavid Christensen static int ecore_check_vlan_mac_add(struct bxe_softc *sc,
7224e400768SDavid Christensen 				    struct ecore_vlan_mac_obj *o,
7234e400768SDavid Christensen 				   union ecore_classification_ramrod_data *data)
7244e400768SDavid Christensen {
7254e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *pos;
7264e400768SDavid Christensen 
7274e400768SDavid Christensen 	ECORE_MSG(sc, "Checking VLAN_MAC (%02x:%02x:%02x:%02x:%02x:%02x, %d) for ADD command\n",
7284e400768SDavid Christensen 		  data->vlan_mac.mac[0], data->vlan_mac.mac[1], data->vlan_mac.mac[2], data->vlan_mac.mac[3], data->vlan_mac.mac[4], data->vlan_mac.mac[5], data->vlan_mac.vlan);
7294e400768SDavid Christensen 
7304e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link,
7314e400768SDavid Christensen 				  struct ecore_vlan_mac_registry_elem)
7324e400768SDavid Christensen 		if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
7334e400768SDavid Christensen 		    (!ECORE_MEMCMP(data->vlan_mac.mac, pos->u.vlan_mac.mac,
7344e400768SDavid Christensen 				  ETH_ALEN)) &&
7354e400768SDavid Christensen 		    (data->vlan_mac.is_inner_mac ==
7364e400768SDavid Christensen 		     pos->u.vlan_mac.is_inner_mac))
7374e400768SDavid Christensen 			return ECORE_EXISTS;
7384e400768SDavid Christensen 
7394e400768SDavid Christensen 	return ECORE_SUCCESS;
7404e400768SDavid Christensen }
7414e400768SDavid Christensen 
ecore_check_vxlan_fltr_add(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,union ecore_classification_ramrod_data * data)7424ef8ebfdSDavid C Somayajulu static int ecore_check_vxlan_fltr_add(struct bxe_softc *sc,
7434ef8ebfdSDavid C Somayajulu 				struct ecore_vlan_mac_obj *o,
7444ef8ebfdSDavid C Somayajulu 				union ecore_classification_ramrod_data *data)
7454ef8ebfdSDavid C Somayajulu {
7464ef8ebfdSDavid C Somayajulu 	struct ecore_vlan_mac_registry_elem *pos;
7474ef8ebfdSDavid C Somayajulu 
7484ef8ebfdSDavid C Somayajulu 	ECORE_MSG(sc, "Checking VXLAN_FLTR (Inner:%pM, %d) for ADD command\n",
7494ef8ebfdSDavid C Somayajulu 		  data->vxlan_fltr.innermac, data->vxlan_fltr.vni);
7504ef8ebfdSDavid C Somayajulu 
7514ef8ebfdSDavid C Somayajulu 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link,
7524ef8ebfdSDavid C Somayajulu 				  struct ecore_vlan_mac_registry_elem)
7534ef8ebfdSDavid C Somayajulu 		if ((!ECORE_MEMCMP(data->vxlan_fltr.innermac,
7544ef8ebfdSDavid C Somayajulu 			       pos->u.vxlan_fltr.innermac,
7554ef8ebfdSDavid C Somayajulu 			       ETH_ALEN)) &&
7564ef8ebfdSDavid C Somayajulu 			     (data->vxlan_fltr.vni == pos->u.vxlan_fltr.vni))
7574ef8ebfdSDavid C Somayajulu 			return ECORE_EXISTS;
7584ef8ebfdSDavid C Somayajulu 
7594ef8ebfdSDavid C Somayajulu 	return ECORE_SUCCESS;
7604ef8ebfdSDavid C Somayajulu }
7614ef8ebfdSDavid C Somayajulu 
7624e400768SDavid Christensen /* check_del() callbacks */
7634e400768SDavid Christensen static struct ecore_vlan_mac_registry_elem *
ecore_check_mac_del(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,union ecore_classification_ramrod_data * data)7644e400768SDavid Christensen 	ecore_check_mac_del(struct bxe_softc *sc,
7654e400768SDavid Christensen 			    struct ecore_vlan_mac_obj *o,
7664e400768SDavid Christensen 			    union ecore_classification_ramrod_data *data)
7674e400768SDavid Christensen {
7684e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *pos;
7694e400768SDavid Christensen 
7704e400768SDavid Christensen 	ECORE_MSG(sc, "Checking MAC %02x:%02x:%02x:%02x:%02x:%02x for DEL command\n", data->mac.mac[0], data->mac.mac[1], data->mac.mac[2], data->mac.mac[3], data->mac.mac[4], data->mac.mac[5]);
7714e400768SDavid Christensen 
7724e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link,
7734e400768SDavid Christensen 				  struct ecore_vlan_mac_registry_elem)
7744e400768SDavid Christensen 		if ((!ECORE_MEMCMP(data->mac.mac, pos->u.mac.mac, ETH_ALEN)) &&
7754e400768SDavid Christensen 		    (data->mac.is_inner_mac == pos->u.mac.is_inner_mac))
7764e400768SDavid Christensen 			return pos;
7774e400768SDavid Christensen 
7784e400768SDavid Christensen 	return NULL;
7794e400768SDavid Christensen }
7804e400768SDavid Christensen 
7814e400768SDavid Christensen static struct ecore_vlan_mac_registry_elem *
ecore_check_vlan_del(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,union ecore_classification_ramrod_data * data)7824e400768SDavid Christensen 	ecore_check_vlan_del(struct bxe_softc *sc,
7834e400768SDavid Christensen 			     struct ecore_vlan_mac_obj *o,
7844e400768SDavid Christensen 			     union ecore_classification_ramrod_data *data)
7854e400768SDavid Christensen {
7864e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *pos;
7874e400768SDavid Christensen 
7884e400768SDavid Christensen 	ECORE_MSG(sc, "Checking VLAN %d for DEL command\n", data->vlan.vlan);
7894e400768SDavid Christensen 
7904e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link,
7914e400768SDavid Christensen 				  struct ecore_vlan_mac_registry_elem)
7924e400768SDavid Christensen 		if (data->vlan.vlan == pos->u.vlan.vlan)
7934e400768SDavid Christensen 			return pos;
7944e400768SDavid Christensen 
7954e400768SDavid Christensen 	return NULL;
7964e400768SDavid Christensen }
7974e400768SDavid Christensen 
7984e400768SDavid Christensen static struct ecore_vlan_mac_registry_elem *
ecore_check_vlan_mac_del(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,union ecore_classification_ramrod_data * data)7994e400768SDavid Christensen 	ecore_check_vlan_mac_del(struct bxe_softc *sc,
8004e400768SDavid Christensen 				 struct ecore_vlan_mac_obj *o,
8014e400768SDavid Christensen 				 union ecore_classification_ramrod_data *data)
8024e400768SDavid Christensen {
8034e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *pos;
8044e400768SDavid Christensen 
8054e400768SDavid Christensen 	ECORE_MSG(sc, "Checking VLAN_MAC (%02x:%02x:%02x:%02x:%02x:%02x, %d) for DEL command\n",
8064e400768SDavid Christensen 		  data->vlan_mac.mac[0], data->vlan_mac.mac[1], data->vlan_mac.mac[2], data->vlan_mac.mac[3], data->vlan_mac.mac[4], data->vlan_mac.mac[5], data->vlan_mac.vlan);
8074e400768SDavid Christensen 
8084e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link,
8094e400768SDavid Christensen 				  struct ecore_vlan_mac_registry_elem)
8104e400768SDavid Christensen 		if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
8114e400768SDavid Christensen 		    (!ECORE_MEMCMP(data->vlan_mac.mac, pos->u.vlan_mac.mac,
8124e400768SDavid Christensen 			     ETH_ALEN)) &&
8134e400768SDavid Christensen 		    (data->vlan_mac.is_inner_mac ==
8144e400768SDavid Christensen 		     pos->u.vlan_mac.is_inner_mac))
8154e400768SDavid Christensen 			return pos;
8164e400768SDavid Christensen 
8174e400768SDavid Christensen 	return NULL;
8184e400768SDavid Christensen }
8194e400768SDavid Christensen 
8204ef8ebfdSDavid C Somayajulu static struct ecore_vlan_mac_registry_elem *
ecore_check_vxlan_fltr_del(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,union ecore_classification_ramrod_data * data)8214ef8ebfdSDavid C Somayajulu 	ecore_check_vxlan_fltr_del
8224ef8ebfdSDavid C Somayajulu 			(struct bxe_softc *sc,
8234ef8ebfdSDavid C Somayajulu 			struct ecore_vlan_mac_obj *o,
8244ef8ebfdSDavid C Somayajulu 			union ecore_classification_ramrod_data *data)
8254ef8ebfdSDavid C Somayajulu {
8264ef8ebfdSDavid C Somayajulu 	struct ecore_vlan_mac_registry_elem *pos;
8274ef8ebfdSDavid C Somayajulu 
8284ef8ebfdSDavid C Somayajulu 	ECORE_MSG(sc, "Checking VXLAN_FLTR (Inner:%pM, %d) for DEL command\n",
8294ef8ebfdSDavid C Somayajulu 		  data->vxlan_fltr.innermac, data->vxlan_fltr.vni);
8304ef8ebfdSDavid C Somayajulu 
8314ef8ebfdSDavid C Somayajulu 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link,
8324ef8ebfdSDavid C Somayajulu 				  struct ecore_vlan_mac_registry_elem)
8334ef8ebfdSDavid C Somayajulu 		if ((!ECORE_MEMCMP(data->vxlan_fltr.innermac,
8344ef8ebfdSDavid C Somayajulu 			       pos->u.vxlan_fltr.innermac,
8354ef8ebfdSDavid C Somayajulu 			       ETH_ALEN)) &&
8364ef8ebfdSDavid C Somayajulu 			       (data->vxlan_fltr.vni == pos->u.vxlan_fltr.vni))
8374ef8ebfdSDavid C Somayajulu 			return pos;
8384ef8ebfdSDavid C Somayajulu 
8394ef8ebfdSDavid C Somayajulu 	return NULL;
8404ef8ebfdSDavid C Somayajulu }
8414ef8ebfdSDavid C Somayajulu 
8424e400768SDavid Christensen /* check_move() callback */
ecore_check_move(struct bxe_softc * sc,struct ecore_vlan_mac_obj * src_o,struct ecore_vlan_mac_obj * dst_o,union ecore_classification_ramrod_data * data)8434e400768SDavid Christensen static bool ecore_check_move(struct bxe_softc *sc,
8444e400768SDavid Christensen 			     struct ecore_vlan_mac_obj *src_o,
8454e400768SDavid Christensen 			     struct ecore_vlan_mac_obj *dst_o,
8464e400768SDavid Christensen 			     union ecore_classification_ramrod_data *data)
8474e400768SDavid Christensen {
8484e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *pos;
8494e400768SDavid Christensen 	int rc;
8504e400768SDavid Christensen 
8514e400768SDavid Christensen 	/* Check if we can delete the requested configuration from the first
8524e400768SDavid Christensen 	 * object.
8534e400768SDavid Christensen 	 */
8544e400768SDavid Christensen 	pos = src_o->check_del(sc, src_o, data);
8554e400768SDavid Christensen 
8564e400768SDavid Christensen 	/*  check if configuration can be added */
8574e400768SDavid Christensen 	rc = dst_o->check_add(sc, dst_o, data);
8584e400768SDavid Christensen 
8594e400768SDavid Christensen 	/* If this classification can not be added (is already set)
8604e400768SDavid Christensen 	 * or can't be deleted - return an error.
8614e400768SDavid Christensen 	 */
8624e400768SDavid Christensen 	if (rc || !pos)
8634e400768SDavid Christensen 		return FALSE;
8644e400768SDavid Christensen 
8654e400768SDavid Christensen 	return TRUE;
8664e400768SDavid Christensen }
8674e400768SDavid Christensen 
ecore_check_move_always_err(struct bxe_softc * sc,struct ecore_vlan_mac_obj * src_o,struct ecore_vlan_mac_obj * dst_o,union ecore_classification_ramrod_data * data)8684e400768SDavid Christensen static bool ecore_check_move_always_err(
8694e400768SDavid Christensen 	struct bxe_softc *sc,
8704e400768SDavid Christensen 	struct ecore_vlan_mac_obj *src_o,
8714e400768SDavid Christensen 	struct ecore_vlan_mac_obj *dst_o,
8724e400768SDavid Christensen 	union ecore_classification_ramrod_data *data)
8734e400768SDavid Christensen {
8744e400768SDavid Christensen 	return FALSE;
8754e400768SDavid Christensen }
8764e400768SDavid Christensen 
ecore_vlan_mac_get_rx_tx_flag(struct ecore_vlan_mac_obj * o)8774e400768SDavid Christensen static inline uint8_t ecore_vlan_mac_get_rx_tx_flag(struct ecore_vlan_mac_obj *o)
8784e400768SDavid Christensen {
8794e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
8804e400768SDavid Christensen 	uint8_t rx_tx_flag = 0;
8814e400768SDavid Christensen 
8824e400768SDavid Christensen 	if ((raw->obj_type == ECORE_OBJ_TYPE_TX) ||
8834e400768SDavid Christensen 	    (raw->obj_type == ECORE_OBJ_TYPE_RX_TX))
8844e400768SDavid Christensen 		rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_TX_CMD;
8854e400768SDavid Christensen 
8864e400768SDavid Christensen 	if ((raw->obj_type == ECORE_OBJ_TYPE_RX) ||
8874e400768SDavid Christensen 	    (raw->obj_type == ECORE_OBJ_TYPE_RX_TX))
8884e400768SDavid Christensen 		rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_RX_CMD;
8894e400768SDavid Christensen 
8904e400768SDavid Christensen 	return rx_tx_flag;
8914e400768SDavid Christensen }
8924e400768SDavid Christensen 
ecore_set_mac_in_nig(struct bxe_softc * sc,bool add,unsigned char * dev_addr,int index)8934e400768SDavid Christensen void ecore_set_mac_in_nig(struct bxe_softc *sc,
8944e400768SDavid Christensen 			  bool add, unsigned char *dev_addr, int index)
8954e400768SDavid Christensen {
8964e400768SDavid Christensen 	uint32_t wb_data[2];
8974e400768SDavid Christensen 	uint32_t reg_offset = ECORE_PORT_ID(sc) ? NIG_REG_LLH1_FUNC_MEM :
8984e400768SDavid Christensen 			 NIG_REG_LLH0_FUNC_MEM;
8994e400768SDavid Christensen 
9004e400768SDavid Christensen 	if (!ECORE_IS_MF_SI_MODE(sc) && !IS_MF_AFEX(sc))
9014e400768SDavid Christensen 		return;
9024e400768SDavid Christensen 
9034e400768SDavid Christensen 	if (index > ECORE_LLH_CAM_MAX_PF_LINE)
9044e400768SDavid Christensen 		return;
9054e400768SDavid Christensen 
9064e400768SDavid Christensen 	ECORE_MSG(sc, "Going to %s LLH configuration at entry %d\n",
9074e400768SDavid Christensen 		  (add ? "ADD" : "DELETE"), index);
9084e400768SDavid Christensen 
9094e400768SDavid Christensen 	if (add) {
9104e400768SDavid Christensen 		/* LLH_FUNC_MEM is a uint64_t WB register */
9114e400768SDavid Christensen 		reg_offset += 8*index;
9124e400768SDavid Christensen 
9134e400768SDavid Christensen 		wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) |
9144e400768SDavid Christensen 			      (dev_addr[4] <<  8) |  dev_addr[5]);
9154e400768SDavid Christensen 		wb_data[1] = ((dev_addr[0] <<  8) |  dev_addr[1]);
9164e400768SDavid Christensen 
9174e400768SDavid Christensen 		ECORE_REG_WR_DMAE_LEN(sc, reg_offset, wb_data, 2);
9184e400768SDavid Christensen 	}
9194e400768SDavid Christensen 
9204e400768SDavid Christensen 	REG_WR(sc, (ECORE_PORT_ID(sc) ? NIG_REG_LLH1_FUNC_MEM_ENABLE :
9214e400768SDavid Christensen 				  NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4*index, add);
9224e400768SDavid Christensen }
9234e400768SDavid Christensen 
9244e400768SDavid Christensen /**
9254e400768SDavid Christensen  * ecore_vlan_mac_set_cmd_hdr_e2 - set a header in a single classify ramrod
9264e400768SDavid Christensen  *
9274e400768SDavid Christensen  * @sc:		device handle
9284e400768SDavid Christensen  * @o:		queue for which we want to configure this rule
9294e400768SDavid Christensen  * @add:	if TRUE the command is an ADD command, DEL otherwise
9304e400768SDavid Christensen  * @opcode:	CLASSIFY_RULE_OPCODE_XXX
9314e400768SDavid Christensen  * @hdr:	pointer to a header to setup
9324e400768SDavid Christensen  *
9334e400768SDavid Christensen  */
ecore_vlan_mac_set_cmd_hdr_e2(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,bool add,int opcode,struct eth_classify_cmd_header * hdr)9344e400768SDavid Christensen static inline void ecore_vlan_mac_set_cmd_hdr_e2(struct bxe_softc *sc,
9354e400768SDavid Christensen 	struct ecore_vlan_mac_obj *o, bool add, int opcode,
9364e400768SDavid Christensen 	struct eth_classify_cmd_header *hdr)
9374e400768SDavid Christensen {
9384e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
9394e400768SDavid Christensen 
9404e400768SDavid Christensen 	hdr->client_id = raw->cl_id;
9414e400768SDavid Christensen 	hdr->func_id = raw->func_id;
9424e400768SDavid Christensen 
9434e400768SDavid Christensen 	/* Rx or/and Tx (internal switching) configuration ? */
9444e400768SDavid Christensen 	hdr->cmd_general_data |=
9454e400768SDavid Christensen 		ecore_vlan_mac_get_rx_tx_flag(o);
9464e400768SDavid Christensen 
9474e400768SDavid Christensen 	if (add)
9484e400768SDavid Christensen 		hdr->cmd_general_data |= ETH_CLASSIFY_CMD_HEADER_IS_ADD;
9494e400768SDavid Christensen 
9504e400768SDavid Christensen 	hdr->cmd_general_data |=
9514e400768SDavid Christensen 		(opcode << ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT);
9524e400768SDavid Christensen }
9534e400768SDavid Christensen 
9544e400768SDavid Christensen /**
9554e400768SDavid Christensen  * ecore_vlan_mac_set_rdata_hdr_e2 - set the classify ramrod data header
9564e400768SDavid Christensen  *
9574e400768SDavid Christensen  * @cid:	connection id
9584e400768SDavid Christensen  * @type:	ECORE_FILTER_XXX_PENDING
9594e400768SDavid Christensen  * @hdr:	pointer to header to setup
9604e400768SDavid Christensen  * @rule_cnt:
9614e400768SDavid Christensen  *
9624e400768SDavid Christensen  * currently we always configure one rule and echo field to contain a CID and an
9634e400768SDavid Christensen  * opcode type.
9644e400768SDavid Christensen  */
ecore_vlan_mac_set_rdata_hdr_e2(uint32_t cid,int type,struct eth_classify_header * hdr,int rule_cnt)9654e400768SDavid Christensen static inline void ecore_vlan_mac_set_rdata_hdr_e2(uint32_t cid, int type,
9664e400768SDavid Christensen 				struct eth_classify_header *hdr, int rule_cnt)
9674e400768SDavid Christensen {
9684e400768SDavid Christensen 	hdr->echo = ECORE_CPU_TO_LE32((cid & ECORE_SWCID_MASK) |
9694e400768SDavid Christensen 				(type << ECORE_SWCID_SHIFT));
9704e400768SDavid Christensen 	hdr->rule_cnt = (uint8_t)rule_cnt;
9714e400768SDavid Christensen }
9724e400768SDavid Christensen 
9734e400768SDavid Christensen /* hw_config() callbacks */
ecore_set_one_mac_e2(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,struct ecore_exeq_elem * elem,int rule_idx,int cam_offset)9744e400768SDavid Christensen static void ecore_set_one_mac_e2(struct bxe_softc *sc,
9754e400768SDavid Christensen 				 struct ecore_vlan_mac_obj *o,
9764e400768SDavid Christensen 				 struct ecore_exeq_elem *elem, int rule_idx,
9774e400768SDavid Christensen 				 int cam_offset)
9784e400768SDavid Christensen {
9794e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
9804e400768SDavid Christensen 	struct eth_classify_rules_ramrod_data *data =
9814e400768SDavid Christensen 		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
9824e400768SDavid Christensen 	int rule_cnt = rule_idx + 1, cmd = elem->cmd_data.vlan_mac.cmd;
9834e400768SDavid Christensen 	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
9844e400768SDavid Christensen 	bool add = (cmd == ECORE_VLAN_MAC_ADD) ? TRUE : FALSE;
9854e400768SDavid Christensen 	unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags;
9864e400768SDavid Christensen 	uint8_t *mac = elem->cmd_data.vlan_mac.u.mac.mac;
9874e400768SDavid Christensen 
9884e400768SDavid Christensen 	/* Set LLH CAM entry: currently only iSCSI and ETH macs are
9894e400768SDavid Christensen 	 * relevant. In addition, current implementation is tuned for a
9904e400768SDavid Christensen 	 * single ETH MAC.
9914e400768SDavid Christensen 	 *
9924e400768SDavid Christensen 	 * When multiple unicast ETH MACs PF configuration in switch
9934e400768SDavid Christensen 	 * independent mode is required (NetQ, multiple netdev MACs,
9944e400768SDavid Christensen 	 * etc.), consider better utilisation of 8 per function MAC
9954e400768SDavid Christensen 	 * entries in the LLH register. There is also
9964e400768SDavid Christensen 	 * NIG_REG_P[01]_LLH_FUNC_MEM2 registers that complete the
9974e400768SDavid Christensen 	 * total number of CAM entries to 16.
9984e400768SDavid Christensen 	 *
9994e400768SDavid Christensen 	 * Currently we won't configure NIG for MACs other than a primary ETH
10004e400768SDavid Christensen 	 * MAC and iSCSI L2 MAC.
10014e400768SDavid Christensen 	 *
10024e400768SDavid Christensen 	 * If this MAC is moving from one Queue to another, no need to change
10034e400768SDavid Christensen 	 * NIG configuration.
10044e400768SDavid Christensen 	 */
10054e400768SDavid Christensen 	if (cmd != ECORE_VLAN_MAC_MOVE) {
10064e400768SDavid Christensen 		if (ECORE_TEST_BIT(ECORE_ISCSI_ETH_MAC, vlan_mac_flags))
10074e400768SDavid Christensen 			ecore_set_mac_in_nig(sc, add, mac,
10084e400768SDavid Christensen 					     ECORE_LLH_CAM_ISCSI_ETH_LINE);
10094e400768SDavid Christensen 		else if (ECORE_TEST_BIT(ECORE_ETH_MAC, vlan_mac_flags))
10104e400768SDavid Christensen 			ecore_set_mac_in_nig(sc, add, mac,
10114e400768SDavid Christensen 					     ECORE_LLH_CAM_ETH_LINE);
10124e400768SDavid Christensen 	}
10134e400768SDavid Christensen 
10144e400768SDavid Christensen 	/* Reset the ramrod data buffer for the first rule */
10154e400768SDavid Christensen 	if (rule_idx == 0)
10164e400768SDavid Christensen 		ECORE_MEMSET(data, 0, sizeof(*data));
10174e400768SDavid Christensen 
10184e400768SDavid Christensen 	/* Setup a command header */
10194e400768SDavid Christensen 	ecore_vlan_mac_set_cmd_hdr_e2(sc, o, add, CLASSIFY_RULE_OPCODE_MAC,
10204e400768SDavid Christensen 				      &rule_entry->mac.header);
10214e400768SDavid Christensen 
10224e400768SDavid Christensen 	ECORE_MSG(sc, "About to %s MAC %02x:%02x:%02x:%02x:%02x:%02x for Queue %d\n",
10234e400768SDavid Christensen 		  (add ? "add" : "delete"), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], raw->cl_id);
10244e400768SDavid Christensen 
10254e400768SDavid Christensen 	/* Set a MAC itself */
10264e400768SDavid Christensen 	ecore_set_fw_mac_addr(&rule_entry->mac.mac_msb,
10274e400768SDavid Christensen 			      &rule_entry->mac.mac_mid,
10284e400768SDavid Christensen 			      &rule_entry->mac.mac_lsb, mac);
10294e400768SDavid Christensen 	rule_entry->mac.inner_mac =
10304ef8ebfdSDavid C Somayajulu 		ECORE_CPU_TO_LE16(elem->cmd_data.vlan_mac.u.mac.is_inner_mac);
10314e400768SDavid Christensen 
10324e400768SDavid Christensen 	/* MOVE: Add a rule that will add this MAC to the target Queue */
10334e400768SDavid Christensen 	if (cmd == ECORE_VLAN_MAC_MOVE) {
10344e400768SDavid Christensen 		rule_entry++;
10354e400768SDavid Christensen 		rule_cnt++;
10364e400768SDavid Christensen 
10374e400768SDavid Christensen 		/* Setup ramrod data */
10384e400768SDavid Christensen 		ecore_vlan_mac_set_cmd_hdr_e2(sc,
10394e400768SDavid Christensen 					elem->cmd_data.vlan_mac.target_obj,
10404e400768SDavid Christensen 					      TRUE, CLASSIFY_RULE_OPCODE_MAC,
10414e400768SDavid Christensen 					      &rule_entry->mac.header);
10424e400768SDavid Christensen 
10434e400768SDavid Christensen 		/* Set a MAC itself */
10444e400768SDavid Christensen 		ecore_set_fw_mac_addr(&rule_entry->mac.mac_msb,
10454e400768SDavid Christensen 				      &rule_entry->mac.mac_mid,
10464e400768SDavid Christensen 				      &rule_entry->mac.mac_lsb, mac);
10474e400768SDavid Christensen 		rule_entry->mac.inner_mac =
10484ef8ebfdSDavid C Somayajulu 			ECORE_CPU_TO_LE16(elem->cmd_data.vlan_mac.
10494ef8ebfdSDavid C Somayajulu 				       u.mac.is_inner_mac);
10504e400768SDavid Christensen 	}
10514e400768SDavid Christensen 
10524e400768SDavid Christensen 	/* Set the ramrod data header */
10534e400768SDavid Christensen 	/* TODO: take this to the higher level in order to prevent multiple
10544e400768SDavid Christensen 		 writing */
10554e400768SDavid Christensen 	ecore_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
10564e400768SDavid Christensen 					rule_cnt);
10574e400768SDavid Christensen }
10584e400768SDavid Christensen 
10594e400768SDavid Christensen /**
10604e400768SDavid Christensen  * ecore_vlan_mac_set_rdata_hdr_e1x - set a header in a single classify ramrod
10614e400768SDavid Christensen  *
10624e400768SDavid Christensen  * @sc:		device handle
10634e400768SDavid Christensen  * @o:		queue
10644e400768SDavid Christensen  * @type:
10654e400768SDavid Christensen  * @cam_offset:	offset in cam memory
10664e400768SDavid Christensen  * @hdr:	pointer to a header to setup
10674e400768SDavid Christensen  *
10684e400768SDavid Christensen  * E1/E1H
10694e400768SDavid Christensen  */
ecore_vlan_mac_set_rdata_hdr_e1x(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,int type,int cam_offset,struct mac_configuration_hdr * hdr)10704e400768SDavid Christensen static inline void ecore_vlan_mac_set_rdata_hdr_e1x(struct bxe_softc *sc,
10714e400768SDavid Christensen 	struct ecore_vlan_mac_obj *o, int type, int cam_offset,
10724e400768SDavid Christensen 	struct mac_configuration_hdr *hdr)
10734e400768SDavid Christensen {
10744e400768SDavid Christensen 	struct ecore_raw_obj *r = &o->raw;
10754e400768SDavid Christensen 
10764e400768SDavid Christensen 	hdr->length = 1;
10774e400768SDavid Christensen 	hdr->offset = (uint8_t)cam_offset;
10784e400768SDavid Christensen 	hdr->client_id = ECORE_CPU_TO_LE16(0xff);
10794e400768SDavid Christensen 	hdr->echo = ECORE_CPU_TO_LE32((r->cid & ECORE_SWCID_MASK) |
10804e400768SDavid Christensen 				(type << ECORE_SWCID_SHIFT));
10814e400768SDavid Christensen }
10824e400768SDavid Christensen 
ecore_vlan_mac_set_cfg_entry_e1x(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,bool add,int opcode,uint8_t * mac,uint16_t vlan_id,struct mac_configuration_entry * cfg_entry)10834e400768SDavid Christensen static inline void ecore_vlan_mac_set_cfg_entry_e1x(struct bxe_softc *sc,
10844e400768SDavid Christensen 	struct ecore_vlan_mac_obj *o, bool add, int opcode, uint8_t *mac,
10854e400768SDavid Christensen 	uint16_t vlan_id, struct mac_configuration_entry *cfg_entry)
10864e400768SDavid Christensen {
10874e400768SDavid Christensen 	struct ecore_raw_obj *r = &o->raw;
10884e400768SDavid Christensen 	uint32_t cl_bit_vec = (1 << r->cl_id);
10894e400768SDavid Christensen 
10904e400768SDavid Christensen 	cfg_entry->clients_bit_vector = ECORE_CPU_TO_LE32(cl_bit_vec);
10914e400768SDavid Christensen 	cfg_entry->pf_id = r->func_id;
10924e400768SDavid Christensen 	cfg_entry->vlan_id = ECORE_CPU_TO_LE16(vlan_id);
10934e400768SDavid Christensen 
10944e400768SDavid Christensen 	if (add) {
10954e400768SDavid Christensen 		ECORE_SET_FLAG(cfg_entry->flags,
10964e400768SDavid Christensen 			       MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
10974e400768SDavid Christensen 			       T_ETH_MAC_COMMAND_SET);
10984e400768SDavid Christensen 		ECORE_SET_FLAG(cfg_entry->flags,
10994e400768SDavid Christensen 			       MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE,
11004e400768SDavid Christensen 			       opcode);
11014e400768SDavid Christensen 
11024e400768SDavid Christensen 		/* Set a MAC in a ramrod data */
11034e400768SDavid Christensen 		ecore_set_fw_mac_addr(&cfg_entry->msb_mac_addr,
11044e400768SDavid Christensen 				      &cfg_entry->middle_mac_addr,
11054e400768SDavid Christensen 				      &cfg_entry->lsb_mac_addr, mac);
11064e400768SDavid Christensen 	} else
11074e400768SDavid Christensen 		ECORE_SET_FLAG(cfg_entry->flags,
11084e400768SDavid Christensen 			       MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
11094e400768SDavid Christensen 			       T_ETH_MAC_COMMAND_INVALIDATE);
11104e400768SDavid Christensen }
11114e400768SDavid Christensen 
ecore_vlan_mac_set_rdata_e1x(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,int type,int cam_offset,bool add,uint8_t * mac,uint16_t vlan_id,int opcode,struct mac_configuration_cmd * config)11124e400768SDavid Christensen static inline void ecore_vlan_mac_set_rdata_e1x(struct bxe_softc *sc,
11134e400768SDavid Christensen 	struct ecore_vlan_mac_obj *o, int type, int cam_offset, bool add,
11144e400768SDavid Christensen 	uint8_t *mac, uint16_t vlan_id, int opcode, struct mac_configuration_cmd *config)
11154e400768SDavid Christensen {
11164e400768SDavid Christensen 	struct mac_configuration_entry *cfg_entry = &config->config_table[0];
11174e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
11184e400768SDavid Christensen 
11194e400768SDavid Christensen 	ecore_vlan_mac_set_rdata_hdr_e1x(sc, o, type, cam_offset,
11204e400768SDavid Christensen 					 &config->hdr);
11214e400768SDavid Christensen 	ecore_vlan_mac_set_cfg_entry_e1x(sc, o, add, opcode, mac, vlan_id,
11224e400768SDavid Christensen 					 cfg_entry);
11234e400768SDavid Christensen 
11244e400768SDavid Christensen 	ECORE_MSG(sc, "%s MAC %02x:%02x:%02x:%02x:%02x:%02x CLID %d CAM offset %d\n",
11254e400768SDavid Christensen 		  (add ? "setting" : "clearing"),
11264e400768SDavid Christensen 		  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], raw->cl_id, cam_offset);
11274e400768SDavid Christensen }
11284e400768SDavid Christensen 
11294e400768SDavid Christensen /**
11304e400768SDavid Christensen  * ecore_set_one_mac_e1x - fill a single MAC rule ramrod data
11314e400768SDavid Christensen  *
11324e400768SDavid Christensen  * @sc:		device handle
11334e400768SDavid Christensen  * @o:		ecore_vlan_mac_obj
11344e400768SDavid Christensen  * @elem:	ecore_exeq_elem
11354e400768SDavid Christensen  * @rule_idx:	rule_idx
11364e400768SDavid Christensen  * @cam_offset: cam_offset
11374e400768SDavid Christensen  */
ecore_set_one_mac_e1x(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,struct ecore_exeq_elem * elem,int rule_idx,int cam_offset)11384e400768SDavid Christensen static void ecore_set_one_mac_e1x(struct bxe_softc *sc,
11394e400768SDavid Christensen 				  struct ecore_vlan_mac_obj *o,
11404e400768SDavid Christensen 				  struct ecore_exeq_elem *elem, int rule_idx,
11414e400768SDavid Christensen 				  int cam_offset)
11424e400768SDavid Christensen {
11434e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
11444e400768SDavid Christensen 	struct mac_configuration_cmd *config =
11454e400768SDavid Christensen 		(struct mac_configuration_cmd *)(raw->rdata);
11464e400768SDavid Christensen 	/* 57710 and 57711 do not support MOVE command,
11474e400768SDavid Christensen 	 * so it's either ADD or DEL
11484e400768SDavid Christensen 	 */
11494e400768SDavid Christensen 	bool add = (elem->cmd_data.vlan_mac.cmd == ECORE_VLAN_MAC_ADD) ?
11504e400768SDavid Christensen 		TRUE : FALSE;
11514e400768SDavid Christensen 
11524e400768SDavid Christensen 	/* Reset the ramrod data buffer */
11534e400768SDavid Christensen 	ECORE_MEMSET(config, 0, sizeof(*config));
11544e400768SDavid Christensen 
11554e400768SDavid Christensen 	ecore_vlan_mac_set_rdata_e1x(sc, o, raw->state,
11564e400768SDavid Christensen 				     cam_offset, add,
11574e400768SDavid Christensen 				     elem->cmd_data.vlan_mac.u.mac.mac, 0,
11584e400768SDavid Christensen 				     ETH_VLAN_FILTER_ANY_VLAN, config);
11594e400768SDavid Christensen }
11604e400768SDavid Christensen 
ecore_set_one_vlan_e2(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,struct ecore_exeq_elem * elem,int rule_idx,int cam_offset)11614e400768SDavid Christensen static void ecore_set_one_vlan_e2(struct bxe_softc *sc,
11624e400768SDavid Christensen 				  struct ecore_vlan_mac_obj *o,
11634e400768SDavid Christensen 				  struct ecore_exeq_elem *elem, int rule_idx,
11644e400768SDavid Christensen 				  int cam_offset)
11654e400768SDavid Christensen {
11664e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
11674e400768SDavid Christensen 	struct eth_classify_rules_ramrod_data *data =
11684e400768SDavid Christensen 		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
11694e400768SDavid Christensen 	int rule_cnt = rule_idx + 1;
11704e400768SDavid Christensen 	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
11714e400768SDavid Christensen 	enum ecore_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd;
11724e400768SDavid Christensen 	bool add = (cmd == ECORE_VLAN_MAC_ADD) ? TRUE : FALSE;
11734e400768SDavid Christensen 	uint16_t vlan = elem->cmd_data.vlan_mac.u.vlan.vlan;
11744e400768SDavid Christensen 
11754e400768SDavid Christensen 	/* Reset the ramrod data buffer for the first rule */
11764e400768SDavid Christensen 	if (rule_idx == 0)
11774e400768SDavid Christensen 		ECORE_MEMSET(data, 0, sizeof(*data));
11784e400768SDavid Christensen 
11794e400768SDavid Christensen 	/* Set a rule header */
11804e400768SDavid Christensen 	ecore_vlan_mac_set_cmd_hdr_e2(sc, o, add, CLASSIFY_RULE_OPCODE_VLAN,
11814e400768SDavid Christensen 				      &rule_entry->vlan.header);
11824e400768SDavid Christensen 
11834e400768SDavid Christensen 	ECORE_MSG(sc, "About to %s VLAN %d\n", (add ? "add" : "delete"),
11844e400768SDavid Christensen 		  vlan);
11854e400768SDavid Christensen 
11864e400768SDavid Christensen 	/* Set a VLAN itself */
11874e400768SDavid Christensen 	rule_entry->vlan.vlan = ECORE_CPU_TO_LE16(vlan);
11884e400768SDavid Christensen 
11894e400768SDavid Christensen 	/* MOVE: Add a rule that will add this MAC to the target Queue */
11904e400768SDavid Christensen 	if (cmd == ECORE_VLAN_MAC_MOVE) {
11914e400768SDavid Christensen 		rule_entry++;
11924e400768SDavid Christensen 		rule_cnt++;
11934e400768SDavid Christensen 
11944e400768SDavid Christensen 		/* Setup ramrod data */
11954e400768SDavid Christensen 		ecore_vlan_mac_set_cmd_hdr_e2(sc,
11964e400768SDavid Christensen 					elem->cmd_data.vlan_mac.target_obj,
11974e400768SDavid Christensen 					      TRUE, CLASSIFY_RULE_OPCODE_VLAN,
11984e400768SDavid Christensen 					      &rule_entry->vlan.header);
11994e400768SDavid Christensen 
12004e400768SDavid Christensen 		/* Set a VLAN itself */
12014e400768SDavid Christensen 		rule_entry->vlan.vlan = ECORE_CPU_TO_LE16(vlan);
12024e400768SDavid Christensen 	}
12034e400768SDavid Christensen 
12044e400768SDavid Christensen 	/* Set the ramrod data header */
12054e400768SDavid Christensen 	/* TODO: take this to the higher level in order to prevent multiple
12064e400768SDavid Christensen 		 writing */
12074e400768SDavid Christensen 	ecore_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
12084e400768SDavid Christensen 					rule_cnt);
12094e400768SDavid Christensen }
12104e400768SDavid Christensen 
ecore_set_one_vlan_mac_e2(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,struct ecore_exeq_elem * elem,int rule_idx,int cam_offset)12114e400768SDavid Christensen static void ecore_set_one_vlan_mac_e2(struct bxe_softc *sc,
12124e400768SDavid Christensen 				      struct ecore_vlan_mac_obj *o,
12134e400768SDavid Christensen 				      struct ecore_exeq_elem *elem,
12144e400768SDavid Christensen 				      int rule_idx, int cam_offset)
12154e400768SDavid Christensen {
12164e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
12174e400768SDavid Christensen 	struct eth_classify_rules_ramrod_data *data =
12184e400768SDavid Christensen 		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
12194e400768SDavid Christensen 	int rule_cnt = rule_idx + 1;
12204e400768SDavid Christensen 	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
12214e400768SDavid Christensen 	enum ecore_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd;
12224e400768SDavid Christensen 	bool add = (cmd == ECORE_VLAN_MAC_ADD) ? TRUE : FALSE;
12234e400768SDavid Christensen 	uint16_t vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan;
12244e400768SDavid Christensen 	uint8_t *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac;
12254e400768SDavid Christensen 
12264e400768SDavid Christensen 	/* Reset the ramrod data buffer for the first rule */
12274e400768SDavid Christensen 	if (rule_idx == 0)
12284e400768SDavid Christensen 		ECORE_MEMSET(data, 0, sizeof(*data));
12294e400768SDavid Christensen 
12304e400768SDavid Christensen 	/* Set a rule header */
12314e400768SDavid Christensen 	ecore_vlan_mac_set_cmd_hdr_e2(sc, o, add, CLASSIFY_RULE_OPCODE_PAIR,
12324e400768SDavid Christensen 				      &rule_entry->pair.header);
12334e400768SDavid Christensen 
12344e400768SDavid Christensen 	/* Set VLAN and MAC themselves */
12354e400768SDavid Christensen 	rule_entry->pair.vlan = ECORE_CPU_TO_LE16(vlan);
12364e400768SDavid Christensen 	ecore_set_fw_mac_addr(&rule_entry->pair.mac_msb,
12374e400768SDavid Christensen 			      &rule_entry->pair.mac_mid,
12384e400768SDavid Christensen 			      &rule_entry->pair.mac_lsb, mac);
12394e400768SDavid Christensen 	rule_entry->pair.inner_mac =
12404e400768SDavid Christensen 			elem->cmd_data.vlan_mac.u.vlan_mac.is_inner_mac;
12414e400768SDavid Christensen 	/* MOVE: Add a rule that will add this MAC to the target Queue */
12424e400768SDavid Christensen 	if (cmd == ECORE_VLAN_MAC_MOVE) {
12434e400768SDavid Christensen 		rule_entry++;
12444e400768SDavid Christensen 		rule_cnt++;
12454e400768SDavid Christensen 
12464e400768SDavid Christensen 		/* Setup ramrod data */
12474e400768SDavid Christensen 		ecore_vlan_mac_set_cmd_hdr_e2(sc,
12484e400768SDavid Christensen 					elem->cmd_data.vlan_mac.target_obj,
12494e400768SDavid Christensen 					      TRUE, CLASSIFY_RULE_OPCODE_PAIR,
12504e400768SDavid Christensen 					      &rule_entry->pair.header);
12514e400768SDavid Christensen 
12524e400768SDavid Christensen 		/* Set a VLAN itself */
12534e400768SDavid Christensen 		rule_entry->pair.vlan = ECORE_CPU_TO_LE16(vlan);
12544e400768SDavid Christensen 		ecore_set_fw_mac_addr(&rule_entry->pair.mac_msb,
12554e400768SDavid Christensen 				      &rule_entry->pair.mac_mid,
12564e400768SDavid Christensen 				      &rule_entry->pair.mac_lsb, mac);
12574e400768SDavid Christensen 		rule_entry->pair.inner_mac =
12584e400768SDavid Christensen 			elem->cmd_data.vlan_mac.u.vlan_mac.is_inner_mac;
12594e400768SDavid Christensen 	}
12604e400768SDavid Christensen 
12614e400768SDavid Christensen 	/* Set the ramrod data header */
12624e400768SDavid Christensen 	/* TODO: take this to the higher level in order to prevent multiple
12634e400768SDavid Christensen 		 writing */
12644e400768SDavid Christensen 	ecore_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
12654e400768SDavid Christensen 					rule_cnt);
12664e400768SDavid Christensen }
12674e400768SDavid Christensen 
ecore_set_one_vxlan_fltr_e2(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,struct ecore_exeq_elem * elem,int rule_idx,int cam_offset)12684ef8ebfdSDavid C Somayajulu static void ecore_set_one_vxlan_fltr_e2(struct bxe_softc *sc,
12694ef8ebfdSDavid C Somayajulu 						struct ecore_vlan_mac_obj *o,
12704ef8ebfdSDavid C Somayajulu 						struct ecore_exeq_elem *elem,
12714ef8ebfdSDavid C Somayajulu 						int rule_idx, int cam_offset)
12724ef8ebfdSDavid C Somayajulu {
12734ef8ebfdSDavid C Somayajulu 	struct ecore_raw_obj *raw = &o->raw;
12744ef8ebfdSDavid C Somayajulu 	struct eth_classify_rules_ramrod_data *data =
12754ef8ebfdSDavid C Somayajulu 		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
12764ef8ebfdSDavid C Somayajulu 	int rule_cnt = rule_idx + 1;
12774ef8ebfdSDavid C Somayajulu 	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
12784ef8ebfdSDavid C Somayajulu 	enum ecore_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd;
12794ef8ebfdSDavid C Somayajulu 	bool add = (cmd == ECORE_VLAN_MAC_ADD) ? TRUE : FALSE;
12804ef8ebfdSDavid C Somayajulu 	uint32_t vni = elem->cmd_data.vlan_mac.u.vxlan_fltr.vni;
12814ef8ebfdSDavid C Somayajulu 	uint8_t *mac = elem->cmd_data.vlan_mac.u.vxlan_fltr.innermac;
12824ef8ebfdSDavid C Somayajulu 
12834ef8ebfdSDavid C Somayajulu 	/* Reset the ramrod data buffer for the first rule */
12844ef8ebfdSDavid C Somayajulu 	if (rule_idx == 0)
12854ef8ebfdSDavid C Somayajulu 		ECORE_MEMSET(data, 0, sizeof(*data));
12864ef8ebfdSDavid C Somayajulu 
12874ef8ebfdSDavid C Somayajulu 	/* Set a rule header */
12884ef8ebfdSDavid C Somayajulu 	ecore_vlan_mac_set_cmd_hdr_e2(sc, o, add,
12894ef8ebfdSDavid C Somayajulu 				      CLASSIFY_RULE_OPCODE_IMAC_VNI,
12904ef8ebfdSDavid C Somayajulu 				      &rule_entry->imac_vni.header);
12914ef8ebfdSDavid C Somayajulu 
12924ef8ebfdSDavid C Somayajulu 	/* Set VLAN and MAC themselves */
12934ef8ebfdSDavid C Somayajulu 	rule_entry->imac_vni.vni = vni;
12944ef8ebfdSDavid C Somayajulu 	ecore_set_fw_mac_addr(&rule_entry->imac_vni.imac_msb,
12954ef8ebfdSDavid C Somayajulu 			      &rule_entry->imac_vni.imac_mid,
12964ef8ebfdSDavid C Somayajulu 			      &rule_entry->imac_vni.imac_lsb, mac);
12974ef8ebfdSDavid C Somayajulu 
12984ef8ebfdSDavid C Somayajulu 	/* MOVE: Add a rule that will add this MAC to the target Queue */
12994ef8ebfdSDavid C Somayajulu 	if (cmd == ECORE_VLAN_MAC_MOVE) {
13004ef8ebfdSDavid C Somayajulu 		rule_entry++;
13014ef8ebfdSDavid C Somayajulu 		rule_cnt++;
13024ef8ebfdSDavid C Somayajulu 
13034ef8ebfdSDavid C Somayajulu 		/* Setup ramrod data */
13044ef8ebfdSDavid C Somayajulu 		ecore_vlan_mac_set_cmd_hdr_e2(sc,
13054ef8ebfdSDavid C Somayajulu 					      elem->cmd_data.vlan_mac.target_obj,
13064ef8ebfdSDavid C Somayajulu 					      TRUE, CLASSIFY_RULE_OPCODE_IMAC_VNI,
13074ef8ebfdSDavid C Somayajulu 					      &rule_entry->imac_vni.header);
13084ef8ebfdSDavid C Somayajulu 
13094ef8ebfdSDavid C Somayajulu 		/* Set a VLAN itself */
13104ef8ebfdSDavid C Somayajulu 		rule_entry->imac_vni.vni = vni;
13114ef8ebfdSDavid C Somayajulu 		ecore_set_fw_mac_addr(&rule_entry->imac_vni.imac_msb,
13124ef8ebfdSDavid C Somayajulu 				      &rule_entry->imac_vni.imac_mid,
13134ef8ebfdSDavid C Somayajulu 				      &rule_entry->imac_vni.imac_lsb, mac);
13144ef8ebfdSDavid C Somayajulu 	}
13154ef8ebfdSDavid C Somayajulu 
13164ef8ebfdSDavid C Somayajulu 	/* Set the ramrod data header */
13174ef8ebfdSDavid C Somayajulu 	/* TODO: take this to the higher level in order to prevent multiple
13184ef8ebfdSDavid C Somayajulu 	   * writing
13194ef8ebfdSDavid C Somayajulu 	*/
13204ef8ebfdSDavid C Somayajulu 	ecore_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state,
13214ef8ebfdSDavid C Somayajulu 					&data->header, rule_cnt);
13224ef8ebfdSDavid C Somayajulu }
13234ef8ebfdSDavid C Somayajulu 
13244e400768SDavid Christensen /**
13254e400768SDavid Christensen  * ecore_set_one_vlan_mac_e1h -
13264e400768SDavid Christensen  *
13274e400768SDavid Christensen  * @sc:		device handle
13284e400768SDavid Christensen  * @o:		ecore_vlan_mac_obj
13294e400768SDavid Christensen  * @elem:	ecore_exeq_elem
13304e400768SDavid Christensen  * @rule_idx:	rule_idx
13314e400768SDavid Christensen  * @cam_offset:	cam_offset
13324e400768SDavid Christensen  */
ecore_set_one_vlan_mac_e1h(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,struct ecore_exeq_elem * elem,int rule_idx,int cam_offset)13334e400768SDavid Christensen static void ecore_set_one_vlan_mac_e1h(struct bxe_softc *sc,
13344e400768SDavid Christensen 				       struct ecore_vlan_mac_obj *o,
13354e400768SDavid Christensen 				       struct ecore_exeq_elem *elem,
13364e400768SDavid Christensen 				       int rule_idx, int cam_offset)
13374e400768SDavid Christensen {
13384e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
13394e400768SDavid Christensen 	struct mac_configuration_cmd *config =
13404e400768SDavid Christensen 		(struct mac_configuration_cmd *)(raw->rdata);
13414e400768SDavid Christensen 	/* 57710 and 57711 do not support MOVE command,
13424e400768SDavid Christensen 	 * so it's either ADD or DEL
13434e400768SDavid Christensen 	 */
13444e400768SDavid Christensen 	bool add = (elem->cmd_data.vlan_mac.cmd == ECORE_VLAN_MAC_ADD) ?
13454e400768SDavid Christensen 		TRUE : FALSE;
13464e400768SDavid Christensen 
13474e400768SDavid Christensen 	/* Reset the ramrod data buffer */
13484e400768SDavid Christensen 	ECORE_MEMSET(config, 0, sizeof(*config));
13494e400768SDavid Christensen 
13504e400768SDavid Christensen 	ecore_vlan_mac_set_rdata_e1x(sc, o, ECORE_FILTER_VLAN_MAC_PENDING,
13514e400768SDavid Christensen 				     cam_offset, add,
13524e400768SDavid Christensen 				     elem->cmd_data.vlan_mac.u.vlan_mac.mac,
13534e400768SDavid Christensen 				     elem->cmd_data.vlan_mac.u.vlan_mac.vlan,
13544e400768SDavid Christensen 				     ETH_VLAN_FILTER_CLASSIFY, config);
13554e400768SDavid Christensen }
13564e400768SDavid Christensen 
13574e400768SDavid Christensen #define list_next_entry(pos, member) \
13584e400768SDavid Christensen 	list_entry((pos)->member.next, typeof(*(pos)), member)
13594e400768SDavid Christensen 
13604e400768SDavid Christensen /**
13614e400768SDavid Christensen  * ecore_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element
13624e400768SDavid Christensen  *
13634e400768SDavid Christensen  * @sc:		device handle
13644e400768SDavid Christensen  * @p:		command parameters
13654e400768SDavid Christensen  * @ppos:	pointer to the cookie
13664e400768SDavid Christensen  *
13674e400768SDavid Christensen  * reconfigure next MAC/VLAN/VLAN-MAC element from the
13684e400768SDavid Christensen  * previously configured elements list.
13694e400768SDavid Christensen  *
13704e400768SDavid Christensen  * from command parameters only RAMROD_COMP_WAIT bit in ramrod_flags is	taken
13714e400768SDavid Christensen  * into an account
13724e400768SDavid Christensen  *
13734e400768SDavid Christensen  * pointer to the cookie  - that should be given back in the next call to make
13744e400768SDavid Christensen  * function handle the next element. If *ppos is set to NULL it will restart the
13754e400768SDavid Christensen  * iterator. If returned *ppos == NULL this means that the last element has been
13764e400768SDavid Christensen  * handled.
13774e400768SDavid Christensen  *
13784e400768SDavid Christensen  */
ecore_vlan_mac_restore(struct bxe_softc * sc,struct ecore_vlan_mac_ramrod_params * p,struct ecore_vlan_mac_registry_elem ** ppos)13794e400768SDavid Christensen static int ecore_vlan_mac_restore(struct bxe_softc *sc,
13804e400768SDavid Christensen 			   struct ecore_vlan_mac_ramrod_params *p,
13814e400768SDavid Christensen 			   struct ecore_vlan_mac_registry_elem **ppos)
13824e400768SDavid Christensen {
13834e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *pos;
13844e400768SDavid Christensen 	struct ecore_vlan_mac_obj *o = p->vlan_mac_obj;
13854e400768SDavid Christensen 
13864e400768SDavid Christensen 	/* If list is empty - there is nothing to do here */
13874e400768SDavid Christensen 	if (ECORE_LIST_IS_EMPTY(&o->head)) {
13884e400768SDavid Christensen 		*ppos = NULL;
13894e400768SDavid Christensen 		return 0;
13904e400768SDavid Christensen 	}
13914e400768SDavid Christensen 
13924e400768SDavid Christensen 	/* make a step... */
13934e400768SDavid Christensen 	if (*ppos == NULL)
13944e400768SDavid Christensen 		*ppos = ECORE_LIST_FIRST_ENTRY(&o->head,
13954e400768SDavid Christensen 					    struct ecore_vlan_mac_registry_elem,
13964e400768SDavid Christensen 					       link);
13974e400768SDavid Christensen 	else
13984e400768SDavid Christensen 		*ppos = ECORE_LIST_NEXT(*ppos, link,
13994e400768SDavid Christensen 					struct ecore_vlan_mac_registry_elem);
14004e400768SDavid Christensen 
14014e400768SDavid Christensen 	pos = *ppos;
14024e400768SDavid Christensen 
14034e400768SDavid Christensen 	/* If it's the last step - return NULL */
14044e400768SDavid Christensen 	if (ECORE_LIST_IS_LAST(&pos->link, &o->head))
14054e400768SDavid Christensen 		*ppos = NULL;
14064e400768SDavid Christensen 
14074e400768SDavid Christensen 	/* Prepare a 'user_req' */
14084e400768SDavid Christensen 	ECORE_MEMCPY(&p->user_req.u, &pos->u, sizeof(pos->u));
14094e400768SDavid Christensen 
14104e400768SDavid Christensen 	/* Set the command */
14114e400768SDavid Christensen 	p->user_req.cmd = ECORE_VLAN_MAC_ADD;
14124e400768SDavid Christensen 
14134e400768SDavid Christensen 	/* Set vlan_mac_flags */
14144e400768SDavid Christensen 	p->user_req.vlan_mac_flags = pos->vlan_mac_flags;
14154e400768SDavid Christensen 
14164e400768SDavid Christensen 	/* Set a restore bit */
14174e400768SDavid Christensen 	ECORE_SET_BIT_NA(RAMROD_RESTORE, &p->ramrod_flags);
14184e400768SDavid Christensen 
14194e400768SDavid Christensen 	return ecore_config_vlan_mac(sc, p);
14204e400768SDavid Christensen }
14214e400768SDavid Christensen 
14224e400768SDavid Christensen /* ecore_exeq_get_mac/ecore_exeq_get_vlan/ecore_exeq_get_vlan_mac return a
14234e400768SDavid Christensen  * pointer to an element with a specific criteria and NULL if such an element
14244e400768SDavid Christensen  * hasn't been found.
14254e400768SDavid Christensen  */
ecore_exeq_get_mac(struct ecore_exe_queue_obj * o,struct ecore_exeq_elem * elem)14264e400768SDavid Christensen static struct ecore_exeq_elem *ecore_exeq_get_mac(
14274e400768SDavid Christensen 	struct ecore_exe_queue_obj *o,
14284e400768SDavid Christensen 	struct ecore_exeq_elem *elem)
14294e400768SDavid Christensen {
14304e400768SDavid Christensen 	struct ecore_exeq_elem *pos;
14314e400768SDavid Christensen 	struct ecore_mac_ramrod_data *data = &elem->cmd_data.vlan_mac.u.mac;
14324e400768SDavid Christensen 
14334e400768SDavid Christensen 	/* Check pending for execution commands */
14344e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->exe_queue, link,
14354e400768SDavid Christensen 				  struct ecore_exeq_elem)
14364e400768SDavid Christensen 		if (!ECORE_MEMCMP(&pos->cmd_data.vlan_mac.u.mac, data,
14374e400768SDavid Christensen 			      sizeof(*data)) &&
14384e400768SDavid Christensen 		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
14394e400768SDavid Christensen 			return pos;
14404e400768SDavid Christensen 
14414e400768SDavid Christensen 	return NULL;
14424e400768SDavid Christensen }
14434e400768SDavid Christensen 
ecore_exeq_get_vlan(struct ecore_exe_queue_obj * o,struct ecore_exeq_elem * elem)14444e400768SDavid Christensen static struct ecore_exeq_elem *ecore_exeq_get_vlan(
14454e400768SDavid Christensen 	struct ecore_exe_queue_obj *o,
14464e400768SDavid Christensen 	struct ecore_exeq_elem *elem)
14474e400768SDavid Christensen {
14484e400768SDavid Christensen 	struct ecore_exeq_elem *pos;
14494e400768SDavid Christensen 	struct ecore_vlan_ramrod_data *data = &elem->cmd_data.vlan_mac.u.vlan;
14504e400768SDavid Christensen 
14514e400768SDavid Christensen 	/* Check pending for execution commands */
14524e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->exe_queue, link,
14534e400768SDavid Christensen 				  struct ecore_exeq_elem)
14544e400768SDavid Christensen 		if (!ECORE_MEMCMP(&pos->cmd_data.vlan_mac.u.vlan, data,
14554e400768SDavid Christensen 			      sizeof(*data)) &&
14564e400768SDavid Christensen 		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
14574e400768SDavid Christensen 			return pos;
14584e400768SDavid Christensen 
14594e400768SDavid Christensen 	return NULL;
14604e400768SDavid Christensen }
14614e400768SDavid Christensen 
ecore_exeq_get_vlan_mac(struct ecore_exe_queue_obj * o,struct ecore_exeq_elem * elem)14624e400768SDavid Christensen static struct ecore_exeq_elem *ecore_exeq_get_vlan_mac(
14634e400768SDavid Christensen 	struct ecore_exe_queue_obj *o,
14644e400768SDavid Christensen 	struct ecore_exeq_elem *elem)
14654e400768SDavid Christensen {
14664e400768SDavid Christensen 	struct ecore_exeq_elem *pos;
14674e400768SDavid Christensen 	struct ecore_vlan_mac_ramrod_data *data =
14684e400768SDavid Christensen 		&elem->cmd_data.vlan_mac.u.vlan_mac;
14694e400768SDavid Christensen 
14704e400768SDavid Christensen 	/* Check pending for execution commands */
14714e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->exe_queue, link,
14724e400768SDavid Christensen 				  struct ecore_exeq_elem)
14734e400768SDavid Christensen 		if (!ECORE_MEMCMP(&pos->cmd_data.vlan_mac.u.vlan_mac, data,
14744e400768SDavid Christensen 			      sizeof(*data)) &&
14754e400768SDavid Christensen 		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
14764e400768SDavid Christensen 			return pos;
14774e400768SDavid Christensen 
14784e400768SDavid Christensen 	return NULL;
14794e400768SDavid Christensen }
14804e400768SDavid Christensen 
ecore_exeq_get_vxlan_fltr(struct ecore_exe_queue_obj * o,struct ecore_exeq_elem * elem)14814ef8ebfdSDavid C Somayajulu static struct ecore_exeq_elem *ecore_exeq_get_vxlan_fltr
14824ef8ebfdSDavid C Somayajulu 			(struct ecore_exe_queue_obj *o,
14834ef8ebfdSDavid C Somayajulu 			struct ecore_exeq_elem *elem)
14844ef8ebfdSDavid C Somayajulu {
14854ef8ebfdSDavid C Somayajulu 	struct ecore_exeq_elem *pos;
14864ef8ebfdSDavid C Somayajulu 	struct ecore_vxlan_fltr_ramrod_data *data =
14874ef8ebfdSDavid C Somayajulu 		&elem->cmd_data.vlan_mac.u.vxlan_fltr;
14884ef8ebfdSDavid C Somayajulu 
14894ef8ebfdSDavid C Somayajulu 	/* Check pending for execution commands */
14904ef8ebfdSDavid C Somayajulu 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->exe_queue, link,
14914ef8ebfdSDavid C Somayajulu 				  struct ecore_exeq_elem)
14924ef8ebfdSDavid C Somayajulu 		if (!ECORE_MEMCMP(&pos->cmd_data.vlan_mac.u.vxlan_fltr, data,
14934ef8ebfdSDavid C Somayajulu 			      sizeof(*data)) &&
14944ef8ebfdSDavid C Somayajulu 			      (pos->cmd_data.vlan_mac.cmd ==
14954ef8ebfdSDavid C Somayajulu 			      elem->cmd_data.vlan_mac.cmd))
14964ef8ebfdSDavid C Somayajulu 			return pos;
14974ef8ebfdSDavid C Somayajulu 
14984ef8ebfdSDavid C Somayajulu 	return NULL;
14994ef8ebfdSDavid C Somayajulu }
15004ef8ebfdSDavid C Somayajulu 
15014e400768SDavid Christensen /**
15024e400768SDavid Christensen  * ecore_validate_vlan_mac_add - check if an ADD command can be executed
15034e400768SDavid Christensen  *
15044e400768SDavid Christensen  * @sc:		device handle
15054e400768SDavid Christensen  * @qo:		ecore_qable_obj
15064e400768SDavid Christensen  * @elem:	ecore_exeq_elem
15074e400768SDavid Christensen  *
15084e400768SDavid Christensen  * Checks that the requested configuration can be added. If yes and if
15094e400768SDavid Christensen  * requested, consume CAM credit.
15104e400768SDavid Christensen  *
15114e400768SDavid Christensen  * The 'validate' is run after the 'optimize'.
15124e400768SDavid Christensen  *
15134e400768SDavid Christensen  */
ecore_validate_vlan_mac_add(struct bxe_softc * sc,union ecore_qable_obj * qo,struct ecore_exeq_elem * elem)15144e400768SDavid Christensen static inline int ecore_validate_vlan_mac_add(struct bxe_softc *sc,
15154e400768SDavid Christensen 					      union ecore_qable_obj *qo,
15164e400768SDavid Christensen 					      struct ecore_exeq_elem *elem)
15174e400768SDavid Christensen {
15184e400768SDavid Christensen 	struct ecore_vlan_mac_obj *o = &qo->vlan_mac;
15194e400768SDavid Christensen 	struct ecore_exe_queue_obj *exeq = &o->exe_queue;
15204e400768SDavid Christensen 	int rc;
15214e400768SDavid Christensen 
15224e400768SDavid Christensen 	/* Check the registry */
15234e400768SDavid Christensen 	rc = o->check_add(sc, o, &elem->cmd_data.vlan_mac.u);
15244e400768SDavid Christensen 	if (rc) {
15254e400768SDavid Christensen 		ECORE_MSG(sc, "ADD command is not allowed considering current registry state.\n");
15264e400768SDavid Christensen 		return rc;
15274e400768SDavid Christensen 	}
15284e400768SDavid Christensen 
15294e400768SDavid Christensen 	/* Check if there is a pending ADD command for this
15304e400768SDavid Christensen 	 * MAC/VLAN/VLAN-MAC. Return an error if there is.
15314e400768SDavid Christensen 	 */
15324e400768SDavid Christensen 	if (exeq->get(exeq, elem)) {
15334e400768SDavid Christensen 		ECORE_MSG(sc, "There is a pending ADD command already\n");
15344e400768SDavid Christensen 		return ECORE_EXISTS;
15354e400768SDavid Christensen 	}
15364e400768SDavid Christensen 
15374e400768SDavid Christensen 	/* TODO: Check the pending MOVE from other objects where this
15384e400768SDavid Christensen 	 * object is a destination object.
15394e400768SDavid Christensen 	 */
15404e400768SDavid Christensen 
15414e400768SDavid Christensen 	/* Consume the credit if not requested not to */
15424e400768SDavid Christensen 	if (!(ECORE_TEST_BIT(ECORE_DONT_CONSUME_CAM_CREDIT,
15434e400768SDavid Christensen 			     &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
15444e400768SDavid Christensen 	    o->get_credit(o)))
15454e400768SDavid Christensen 		return ECORE_INVAL;
15464e400768SDavid Christensen 
15474e400768SDavid Christensen 	return ECORE_SUCCESS;
15484e400768SDavid Christensen }
15494e400768SDavid Christensen 
15504e400768SDavid Christensen /**
15514e400768SDavid Christensen  * ecore_validate_vlan_mac_del - check if the DEL command can be executed
15524e400768SDavid Christensen  *
15534e400768SDavid Christensen  * @sc:		device handle
15544e400768SDavid Christensen  * @qo:		quable object to check
15554e400768SDavid Christensen  * @elem:	element that needs to be deleted
15564e400768SDavid Christensen  *
15574e400768SDavid Christensen  * Checks that the requested configuration can be deleted. If yes and if
15584e400768SDavid Christensen  * requested, returns a CAM credit.
15594e400768SDavid Christensen  *
15604e400768SDavid Christensen  * The 'validate' is run after the 'optimize'.
15614e400768SDavid Christensen  */
ecore_validate_vlan_mac_del(struct bxe_softc * sc,union ecore_qable_obj * qo,struct ecore_exeq_elem * elem)15624e400768SDavid Christensen static inline int ecore_validate_vlan_mac_del(struct bxe_softc *sc,
15634e400768SDavid Christensen 					      union ecore_qable_obj *qo,
15644e400768SDavid Christensen 					      struct ecore_exeq_elem *elem)
15654e400768SDavid Christensen {
15664e400768SDavid Christensen 	struct ecore_vlan_mac_obj *o = &qo->vlan_mac;
15674e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *pos;
15684e400768SDavid Christensen 	struct ecore_exe_queue_obj *exeq = &o->exe_queue;
15694e400768SDavid Christensen 	struct ecore_exeq_elem query_elem;
15704e400768SDavid Christensen 
15714e400768SDavid Christensen 	/* If this classification can not be deleted (doesn't exist)
15724e400768SDavid Christensen 	 * - return a ECORE_EXIST.
15734e400768SDavid Christensen 	 */
15744e400768SDavid Christensen 	pos = o->check_del(sc, o, &elem->cmd_data.vlan_mac.u);
15754e400768SDavid Christensen 	if (!pos) {
15764e400768SDavid Christensen 		ECORE_MSG(sc, "DEL command is not allowed considering current registry state\n");
15774e400768SDavid Christensen 		return ECORE_EXISTS;
15784e400768SDavid Christensen 	}
15794e400768SDavid Christensen 
15804e400768SDavid Christensen 	/* Check if there are pending DEL or MOVE commands for this
15814e400768SDavid Christensen 	 * MAC/VLAN/VLAN-MAC. Return an error if so.
15824e400768SDavid Christensen 	 */
15834e400768SDavid Christensen 	ECORE_MEMCPY(&query_elem, elem, sizeof(query_elem));
15844e400768SDavid Christensen 
15854e400768SDavid Christensen 	/* Check for MOVE commands */
15864e400768SDavid Christensen 	query_elem.cmd_data.vlan_mac.cmd = ECORE_VLAN_MAC_MOVE;
15874e400768SDavid Christensen 	if (exeq->get(exeq, &query_elem)) {
15884e400768SDavid Christensen 		ECORE_ERR("There is a pending MOVE command already\n");
15894e400768SDavid Christensen 		return ECORE_INVAL;
15904e400768SDavid Christensen 	}
15914e400768SDavid Christensen 
15924e400768SDavid Christensen 	/* Check for DEL commands */
15934e400768SDavid Christensen 	if (exeq->get(exeq, elem)) {
15944e400768SDavid Christensen 		ECORE_MSG(sc, "There is a pending DEL command already\n");
15954e400768SDavid Christensen 		return ECORE_EXISTS;
15964e400768SDavid Christensen 	}
15974e400768SDavid Christensen 
15984e400768SDavid Christensen 	/* Return the credit to the credit pool if not requested not to */
15994e400768SDavid Christensen 	if (!(ECORE_TEST_BIT(ECORE_DONT_CONSUME_CAM_CREDIT,
16004e400768SDavid Christensen 			     &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
16014e400768SDavid Christensen 	    o->put_credit(o))) {
16024e400768SDavid Christensen 		ECORE_ERR("Failed to return a credit\n");
16034e400768SDavid Christensen 		return ECORE_INVAL;
16044e400768SDavid Christensen 	}
16054e400768SDavid Christensen 
16064e400768SDavid Christensen 	return ECORE_SUCCESS;
16074e400768SDavid Christensen }
16084e400768SDavid Christensen 
16094e400768SDavid Christensen /**
16104e400768SDavid Christensen  * ecore_validate_vlan_mac_move - check if the MOVE command can be executed
16114e400768SDavid Christensen  *
16124e400768SDavid Christensen  * @sc:		device handle
16134e400768SDavid Christensen  * @qo:		quable object to check (source)
16144e400768SDavid Christensen  * @elem:	element that needs to be moved
16154e400768SDavid Christensen  *
16164e400768SDavid Christensen  * Checks that the requested configuration can be moved. If yes and if
16174e400768SDavid Christensen  * requested, returns a CAM credit.
16184e400768SDavid Christensen  *
16194e400768SDavid Christensen  * The 'validate' is run after the 'optimize'.
16204e400768SDavid Christensen  */
ecore_validate_vlan_mac_move(struct bxe_softc * sc,union ecore_qable_obj * qo,struct ecore_exeq_elem * elem)16214e400768SDavid Christensen static inline int ecore_validate_vlan_mac_move(struct bxe_softc *sc,
16224e400768SDavid Christensen 					       union ecore_qable_obj *qo,
16234e400768SDavid Christensen 					       struct ecore_exeq_elem *elem)
16244e400768SDavid Christensen {
16254e400768SDavid Christensen 	struct ecore_vlan_mac_obj *src_o = &qo->vlan_mac;
16264e400768SDavid Christensen 	struct ecore_vlan_mac_obj *dest_o = elem->cmd_data.vlan_mac.target_obj;
16274e400768SDavid Christensen 	struct ecore_exeq_elem query_elem;
16284e400768SDavid Christensen 	struct ecore_exe_queue_obj *src_exeq = &src_o->exe_queue;
16294e400768SDavid Christensen 	struct ecore_exe_queue_obj *dest_exeq = &dest_o->exe_queue;
16304e400768SDavid Christensen 
16314e400768SDavid Christensen 	/* Check if we can perform this operation based on the current registry
16324e400768SDavid Christensen 	 * state.
16334e400768SDavid Christensen 	 */
16344e400768SDavid Christensen 	if (!src_o->check_move(sc, src_o, dest_o,
16354e400768SDavid Christensen 			       &elem->cmd_data.vlan_mac.u)) {
16364e400768SDavid Christensen 		ECORE_MSG(sc, "MOVE command is not allowed considering current registry state\n");
16374e400768SDavid Christensen 		return ECORE_INVAL;
16384e400768SDavid Christensen 	}
16394e400768SDavid Christensen 
16404e400768SDavid Christensen 	/* Check if there is an already pending DEL or MOVE command for the
16414e400768SDavid Christensen 	 * source object or ADD command for a destination object. Return an
16424e400768SDavid Christensen 	 * error if so.
16434e400768SDavid Christensen 	 */
16444e400768SDavid Christensen 	ECORE_MEMCPY(&query_elem, elem, sizeof(query_elem));
16454e400768SDavid Christensen 
16464e400768SDavid Christensen 	/* Check DEL on source */
16474e400768SDavid Christensen 	query_elem.cmd_data.vlan_mac.cmd = ECORE_VLAN_MAC_DEL;
16484e400768SDavid Christensen 	if (src_exeq->get(src_exeq, &query_elem)) {
16494e400768SDavid Christensen 		ECORE_ERR("There is a pending DEL command on the source queue already\n");
16504e400768SDavid Christensen 		return ECORE_INVAL;
16514e400768SDavid Christensen 	}
16524e400768SDavid Christensen 
16534e400768SDavid Christensen 	/* Check MOVE on source */
16544e400768SDavid Christensen 	if (src_exeq->get(src_exeq, elem)) {
16554e400768SDavid Christensen 		ECORE_MSG(sc, "There is a pending MOVE command already\n");
16564e400768SDavid Christensen 		return ECORE_EXISTS;
16574e400768SDavid Christensen 	}
16584e400768SDavid Christensen 
16594e400768SDavid Christensen 	/* Check ADD on destination */
16604e400768SDavid Christensen 	query_elem.cmd_data.vlan_mac.cmd = ECORE_VLAN_MAC_ADD;
16614e400768SDavid Christensen 	if (dest_exeq->get(dest_exeq, &query_elem)) {
16624e400768SDavid Christensen 		ECORE_ERR("There is a pending ADD command on the destination queue already\n");
16634e400768SDavid Christensen 		return ECORE_INVAL;
16644e400768SDavid Christensen 	}
16654e400768SDavid Christensen 
16664e400768SDavid Christensen 	/* Consume the credit if not requested not to */
16674e400768SDavid Christensen 	if (!(ECORE_TEST_BIT(ECORE_DONT_CONSUME_CAM_CREDIT_DEST,
16684e400768SDavid Christensen 			     &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
16694e400768SDavid Christensen 	    dest_o->get_credit(dest_o)))
16704e400768SDavid Christensen 		return ECORE_INVAL;
16714e400768SDavid Christensen 
16724e400768SDavid Christensen 	if (!(ECORE_TEST_BIT(ECORE_DONT_CONSUME_CAM_CREDIT,
16734e400768SDavid Christensen 			     &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
16744e400768SDavid Christensen 	    src_o->put_credit(src_o))) {
16754e400768SDavid Christensen 		/* return the credit taken from dest... */
16764e400768SDavid Christensen 		dest_o->put_credit(dest_o);
16774e400768SDavid Christensen 		return ECORE_INVAL;
16784e400768SDavid Christensen 	}
16794e400768SDavid Christensen 
16804e400768SDavid Christensen 	return ECORE_SUCCESS;
16814e400768SDavid Christensen }
16824e400768SDavid Christensen 
ecore_validate_vlan_mac(struct bxe_softc * sc,union ecore_qable_obj * qo,struct ecore_exeq_elem * elem)16834e400768SDavid Christensen static int ecore_validate_vlan_mac(struct bxe_softc *sc,
16844e400768SDavid Christensen 				   union ecore_qable_obj *qo,
16854e400768SDavid Christensen 				   struct ecore_exeq_elem *elem)
16864e400768SDavid Christensen {
16874e400768SDavid Christensen 	switch (elem->cmd_data.vlan_mac.cmd) {
16884e400768SDavid Christensen 	case ECORE_VLAN_MAC_ADD:
16894e400768SDavid Christensen 		return ecore_validate_vlan_mac_add(sc, qo, elem);
16904e400768SDavid Christensen 	case ECORE_VLAN_MAC_DEL:
16914e400768SDavid Christensen 		return ecore_validate_vlan_mac_del(sc, qo, elem);
16924e400768SDavid Christensen 	case ECORE_VLAN_MAC_MOVE:
16934e400768SDavid Christensen 		return ecore_validate_vlan_mac_move(sc, qo, elem);
16944e400768SDavid Christensen 	default:
16954e400768SDavid Christensen 		return ECORE_INVAL;
16964e400768SDavid Christensen 	}
16974e400768SDavid Christensen }
16984e400768SDavid Christensen 
ecore_remove_vlan_mac(struct bxe_softc * sc,union ecore_qable_obj * qo,struct ecore_exeq_elem * elem)16994e400768SDavid Christensen static int ecore_remove_vlan_mac(struct bxe_softc *sc,
17004e400768SDavid Christensen 				  union ecore_qable_obj *qo,
17014e400768SDavid Christensen 				  struct ecore_exeq_elem *elem)
17024e400768SDavid Christensen {
17034e400768SDavid Christensen 	int rc = 0;
17044e400768SDavid Christensen 
17054e400768SDavid Christensen 	/* If consumption wasn't required, nothing to do */
17064e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_DONT_CONSUME_CAM_CREDIT,
17074e400768SDavid Christensen 			   &elem->cmd_data.vlan_mac.vlan_mac_flags))
17084e400768SDavid Christensen 		return ECORE_SUCCESS;
17094e400768SDavid Christensen 
17104e400768SDavid Christensen 	switch (elem->cmd_data.vlan_mac.cmd) {
17114e400768SDavid Christensen 	case ECORE_VLAN_MAC_ADD:
17124e400768SDavid Christensen 	case ECORE_VLAN_MAC_MOVE:
17134e400768SDavid Christensen 		rc = qo->vlan_mac.put_credit(&qo->vlan_mac);
17144e400768SDavid Christensen 		break;
17154e400768SDavid Christensen 	case ECORE_VLAN_MAC_DEL:
17164e400768SDavid Christensen 		rc = qo->vlan_mac.get_credit(&qo->vlan_mac);
17174e400768SDavid Christensen 		break;
17184e400768SDavid Christensen 	default:
17194e400768SDavid Christensen 		return ECORE_INVAL;
17204e400768SDavid Christensen 	}
17214e400768SDavid Christensen 
17224e400768SDavid Christensen 	if (rc != TRUE)
17234e400768SDavid Christensen 		return ECORE_INVAL;
17244e400768SDavid Christensen 
17254e400768SDavid Christensen 	return ECORE_SUCCESS;
17264e400768SDavid Christensen }
17274e400768SDavid Christensen 
17284e400768SDavid Christensen /**
17294e400768SDavid Christensen  * ecore_wait_vlan_mac - passively wait for 5 seconds until all work completes.
17304e400768SDavid Christensen  *
17314e400768SDavid Christensen  * @sc:		device handle
17324e400768SDavid Christensen  * @o:		ecore_vlan_mac_obj
17334e400768SDavid Christensen  *
17344e400768SDavid Christensen  */
ecore_wait_vlan_mac(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o)17354e400768SDavid Christensen static int ecore_wait_vlan_mac(struct bxe_softc *sc,
17364e400768SDavid Christensen 			       struct ecore_vlan_mac_obj *o)
17374e400768SDavid Christensen {
17384e400768SDavid Christensen 	int cnt = 5000, rc;
17394e400768SDavid Christensen 	struct ecore_exe_queue_obj *exeq = &o->exe_queue;
17404e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
17414e400768SDavid Christensen 
17424e400768SDavid Christensen 	while (cnt--) {
17434e400768SDavid Christensen 		/* Wait for the current command to complete */
17444e400768SDavid Christensen 		rc = raw->wait_comp(sc, raw);
17454e400768SDavid Christensen 		if (rc)
17464e400768SDavid Christensen 			return rc;
17474e400768SDavid Christensen 
17484e400768SDavid Christensen 		/* Wait until there are no pending commands */
17494e400768SDavid Christensen 		if (!ecore_exe_queue_empty(exeq))
17504e400768SDavid Christensen 			ECORE_WAIT(sc, 1000);
17514e400768SDavid Christensen 		else
17524e400768SDavid Christensen 			return ECORE_SUCCESS;
17534e400768SDavid Christensen 	}
17544e400768SDavid Christensen 
17554e400768SDavid Christensen 	return ECORE_TIMEOUT;
17564e400768SDavid Christensen }
17574e400768SDavid Christensen 
__ecore_vlan_mac_execute_step(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,unsigned long * ramrod_flags)17584e400768SDavid Christensen static int __ecore_vlan_mac_execute_step(struct bxe_softc *sc,
17594e400768SDavid Christensen 					 struct ecore_vlan_mac_obj *o,
17604e400768SDavid Christensen 					 unsigned long *ramrod_flags)
17614e400768SDavid Christensen {
17624e400768SDavid Christensen 	int rc = ECORE_SUCCESS;
17634e400768SDavid Christensen 
17644e400768SDavid Christensen 	ECORE_SPIN_LOCK_BH(&o->exe_queue.lock);
17654e400768SDavid Christensen 
17664e400768SDavid Christensen 	ECORE_MSG(sc, "vlan_mac_execute_step - trying to take writer lock\n");
17674e400768SDavid Christensen 	rc = __ecore_vlan_mac_h_write_trylock(sc, o);
17684e400768SDavid Christensen 
17694e400768SDavid Christensen 	if (rc != ECORE_SUCCESS) {
17704e400768SDavid Christensen 		__ecore_vlan_mac_h_pend(sc, o, *ramrod_flags);
17714e400768SDavid Christensen 
17724e400768SDavid Christensen 		/** Calling function should not diffrentiate between this case
17734e400768SDavid Christensen 		 *  and the case in which there is already a pending ramrod
17744e400768SDavid Christensen 		 */
17754e400768SDavid Christensen 		rc = ECORE_PENDING;
17764e400768SDavid Christensen 	} else {
17775e33becaSEric Davis 		rc = ecore_exe_queue_step(sc, &o->exe_queue, ramrod_flags);
17784e400768SDavid Christensen 	}
17794e400768SDavid Christensen 	ECORE_SPIN_UNLOCK_BH(&o->exe_queue.lock);
17804e400768SDavid Christensen 
17814e400768SDavid Christensen 	return rc;
17824e400768SDavid Christensen }
17834e400768SDavid Christensen 
17844e400768SDavid Christensen /**
17854e400768SDavid Christensen  * ecore_complete_vlan_mac - complete one VLAN-MAC ramrod
17864e400768SDavid Christensen  *
17874e400768SDavid Christensen  * @sc:		device handle
17884e400768SDavid Christensen  * @o:		ecore_vlan_mac_obj
17894e400768SDavid Christensen  * @cqe:
17904e400768SDavid Christensen  * @cont:	if TRUE schedule next execution chunk
17914e400768SDavid Christensen  *
17924e400768SDavid Christensen  */
ecore_complete_vlan_mac(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,union event_ring_elem * cqe,unsigned long * ramrod_flags)17934e400768SDavid Christensen static int ecore_complete_vlan_mac(struct bxe_softc *sc,
17944e400768SDavid Christensen 				   struct ecore_vlan_mac_obj *o,
17954e400768SDavid Christensen 				   union event_ring_elem *cqe,
17964e400768SDavid Christensen 				   unsigned long *ramrod_flags)
17974e400768SDavid Christensen {
17984e400768SDavid Christensen 	struct ecore_raw_obj *r = &o->raw;
17994e400768SDavid Christensen 	int rc;
18004e400768SDavid Christensen 
18015e33becaSEric Davis 	/* Clearing the pending list & raw state should be made
18025e33becaSEric Davis 	 * atomically (as execution flow assumes they represent the same)
18035e33becaSEric Davis 	 */
18045e33becaSEric Davis 	ECORE_SPIN_LOCK_BH(&o->exe_queue.lock);
18055e33becaSEric Davis 
18064e400768SDavid Christensen 	/* Reset pending list */
18075e33becaSEric Davis 	__ecore_exe_queue_reset_pending(sc, &o->exe_queue);
18084e400768SDavid Christensen 
18094e400768SDavid Christensen 	/* Clear pending */
18104e400768SDavid Christensen 	r->clear_pending(r);
18114e400768SDavid Christensen 
18125e33becaSEric Davis 	ECORE_SPIN_UNLOCK_BH(&o->exe_queue.lock);
18135e33becaSEric Davis 
18144e400768SDavid Christensen 	/* If ramrod failed this is most likely a SW bug */
18154e400768SDavid Christensen 	if (cqe->message.error)
18164e400768SDavid Christensen 		return ECORE_INVAL;
18174e400768SDavid Christensen 
18184e400768SDavid Christensen 	/* Run the next bulk of pending commands if requested */
18194e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_CONT, ramrod_flags)) {
18204e400768SDavid Christensen 		rc = __ecore_vlan_mac_execute_step(sc, o, ramrod_flags);
18214e400768SDavid Christensen 		if (rc < 0)
18224e400768SDavid Christensen 			return rc;
18234e400768SDavid Christensen 	}
18244e400768SDavid Christensen 
18254e400768SDavid Christensen 	/* If there is more work to do return PENDING */
18264e400768SDavid Christensen 	if (!ecore_exe_queue_empty(&o->exe_queue))
18274e400768SDavid Christensen 		return ECORE_PENDING;
18284e400768SDavid Christensen 
18294e400768SDavid Christensen 	return ECORE_SUCCESS;
18304e400768SDavid Christensen }
18314e400768SDavid Christensen 
18324e400768SDavid Christensen /**
18334e400768SDavid Christensen  * ecore_optimize_vlan_mac - optimize ADD and DEL commands.
18344e400768SDavid Christensen  *
18354e400768SDavid Christensen  * @sc:		device handle
18364e400768SDavid Christensen  * @o:		ecore_qable_obj
18374e400768SDavid Christensen  * @elem:	ecore_exeq_elem
18384e400768SDavid Christensen  */
ecore_optimize_vlan_mac(struct bxe_softc * sc,union ecore_qable_obj * qo,struct ecore_exeq_elem * elem)18394e400768SDavid Christensen static int ecore_optimize_vlan_mac(struct bxe_softc *sc,
18404e400768SDavid Christensen 				   union ecore_qable_obj *qo,
18414e400768SDavid Christensen 				   struct ecore_exeq_elem *elem)
18424e400768SDavid Christensen {
18434e400768SDavid Christensen 	struct ecore_exeq_elem query, *pos;
18444e400768SDavid Christensen 	struct ecore_vlan_mac_obj *o = &qo->vlan_mac;
18454e400768SDavid Christensen 	struct ecore_exe_queue_obj *exeq = &o->exe_queue;
18464e400768SDavid Christensen 
18474e400768SDavid Christensen 	ECORE_MEMCPY(&query, elem, sizeof(query));
18484e400768SDavid Christensen 
18494e400768SDavid Christensen 	switch (elem->cmd_data.vlan_mac.cmd) {
18504e400768SDavid Christensen 	case ECORE_VLAN_MAC_ADD:
18514e400768SDavid Christensen 		query.cmd_data.vlan_mac.cmd = ECORE_VLAN_MAC_DEL;
18524e400768SDavid Christensen 		break;
18534e400768SDavid Christensen 	case ECORE_VLAN_MAC_DEL:
18544e400768SDavid Christensen 		query.cmd_data.vlan_mac.cmd = ECORE_VLAN_MAC_ADD;
18554e400768SDavid Christensen 		break;
18564e400768SDavid Christensen 	default:
18574e400768SDavid Christensen 		/* Don't handle anything other than ADD or DEL */
18584e400768SDavid Christensen 		return 0;
18594e400768SDavid Christensen 	}
18604e400768SDavid Christensen 
18614e400768SDavid Christensen 	/* If we found the appropriate element - delete it */
18624e400768SDavid Christensen 	pos = exeq->get(exeq, &query);
18634e400768SDavid Christensen 	if (pos) {
18644e400768SDavid Christensen 
18654e400768SDavid Christensen 		/* Return the credit of the optimized command */
18664e400768SDavid Christensen 		if (!ECORE_TEST_BIT(ECORE_DONT_CONSUME_CAM_CREDIT,
18674e400768SDavid Christensen 				     &pos->cmd_data.vlan_mac.vlan_mac_flags)) {
18684e400768SDavid Christensen 			if ((query.cmd_data.vlan_mac.cmd ==
18694e400768SDavid Christensen 			     ECORE_VLAN_MAC_ADD) && !o->put_credit(o)) {
18704e400768SDavid Christensen 				ECORE_ERR("Failed to return the credit for the optimized ADD command\n");
18714e400768SDavid Christensen 				return ECORE_INVAL;
18724e400768SDavid Christensen 			} else if (!o->get_credit(o)) { /* VLAN_MAC_DEL */
18734e400768SDavid Christensen 				ECORE_ERR("Failed to recover the credit from the optimized DEL command\n");
18744e400768SDavid Christensen 				return ECORE_INVAL;
18754e400768SDavid Christensen 			}
18764e400768SDavid Christensen 		}
18774e400768SDavid Christensen 
18784e400768SDavid Christensen 		ECORE_MSG(sc, "Optimizing %s command\n",
18794e400768SDavid Christensen 			  (elem->cmd_data.vlan_mac.cmd == ECORE_VLAN_MAC_ADD) ?
18804e400768SDavid Christensen 			  "ADD" : "DEL");
18814e400768SDavid Christensen 
18824e400768SDavid Christensen 		ECORE_LIST_REMOVE_ENTRY(&pos->link, &exeq->exe_queue);
18834e400768SDavid Christensen 		ecore_exe_queue_free_elem(sc, pos);
18844e400768SDavid Christensen 		return 1;
18854e400768SDavid Christensen 	}
18864e400768SDavid Christensen 
18874e400768SDavid Christensen 	return 0;
18884e400768SDavid Christensen }
18894e400768SDavid Christensen 
18904e400768SDavid Christensen /**
18914e400768SDavid Christensen  * ecore_vlan_mac_get_registry_elem - prepare a registry element
18924e400768SDavid Christensen  *
18934e400768SDavid Christensen  * @sc:	  device handle
18944e400768SDavid Christensen  * @o:
18954e400768SDavid Christensen  * @elem:
18964e400768SDavid Christensen  * @restore:
18974e400768SDavid Christensen  * @re:
18984e400768SDavid Christensen  *
18994e400768SDavid Christensen  * prepare a registry element according to the current command request.
19004e400768SDavid Christensen  */
ecore_vlan_mac_get_registry_elem(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,struct ecore_exeq_elem * elem,bool restore,struct ecore_vlan_mac_registry_elem ** re)19014e400768SDavid Christensen static inline int ecore_vlan_mac_get_registry_elem(
19024e400768SDavid Christensen 	struct bxe_softc *sc,
19034e400768SDavid Christensen 	struct ecore_vlan_mac_obj *o,
19044e400768SDavid Christensen 	struct ecore_exeq_elem *elem,
19054e400768SDavid Christensen 	bool restore,
19064e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem **re)
19074e400768SDavid Christensen {
19084e400768SDavid Christensen 	enum ecore_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd;
19094e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *reg_elem;
19104e400768SDavid Christensen 
19114e400768SDavid Christensen 	/* Allocate a new registry element if needed. */
19124e400768SDavid Christensen 	if (!restore &&
19134e400768SDavid Christensen 	    ((cmd == ECORE_VLAN_MAC_ADD) || (cmd == ECORE_VLAN_MAC_MOVE))) {
19144e400768SDavid Christensen 		reg_elem = ECORE_ZALLOC(sizeof(*reg_elem), GFP_ATOMIC, sc);
19154e400768SDavid Christensen 		if (!reg_elem)
19164e400768SDavid Christensen 			return ECORE_NOMEM;
19174e400768SDavid Christensen 
19184e400768SDavid Christensen 		/* Get a new CAM offset */
19194e400768SDavid Christensen 		if (!o->get_cam_offset(o, &reg_elem->cam_offset)) {
19204e400768SDavid Christensen 			/* This shall never happen, because we have checked the
19214e400768SDavid Christensen 			 * CAM availability in the 'validate'.
19224e400768SDavid Christensen 			 */
19234e400768SDavid Christensen 			ECORE_DBG_BREAK_IF(1);
19244e400768SDavid Christensen 			ECORE_FREE(sc, reg_elem, sizeof(*reg_elem));
19254e400768SDavid Christensen 			return ECORE_INVAL;
19264e400768SDavid Christensen 		}
19274e400768SDavid Christensen 
19284e400768SDavid Christensen 		ECORE_MSG(sc, "Got cam offset %d\n", reg_elem->cam_offset);
19294e400768SDavid Christensen 
19304e400768SDavid Christensen 		/* Set a VLAN-MAC data */
19314e400768SDavid Christensen 		ECORE_MEMCPY(&reg_elem->u, &elem->cmd_data.vlan_mac.u,
19324e400768SDavid Christensen 			  sizeof(reg_elem->u));
19334e400768SDavid Christensen 
19344e400768SDavid Christensen 		/* Copy the flags (needed for DEL and RESTORE flows) */
19354e400768SDavid Christensen 		reg_elem->vlan_mac_flags =
19364e400768SDavid Christensen 			elem->cmd_data.vlan_mac.vlan_mac_flags;
19374e400768SDavid Christensen 	} else /* DEL, RESTORE */
19384e400768SDavid Christensen 		reg_elem = o->check_del(sc, o, &elem->cmd_data.vlan_mac.u);
19394e400768SDavid Christensen 
19404e400768SDavid Christensen 	*re = reg_elem;
19414e400768SDavid Christensen 	return ECORE_SUCCESS;
19424e400768SDavid Christensen }
19434e400768SDavid Christensen 
19444e400768SDavid Christensen /**
19454e400768SDavid Christensen  * ecore_execute_vlan_mac - execute vlan mac command
19464e400768SDavid Christensen  *
19474e400768SDavid Christensen  * @sc:			device handle
19484e400768SDavid Christensen  * @qo:
19494e400768SDavid Christensen  * @exe_chunk:
19504e400768SDavid Christensen  * @ramrod_flags:
19514e400768SDavid Christensen  *
19524e400768SDavid Christensen  * go and send a ramrod!
19534e400768SDavid Christensen  */
ecore_execute_vlan_mac(struct bxe_softc * sc,union ecore_qable_obj * qo,ecore_list_t * exe_chunk,unsigned long * ramrod_flags)19544e400768SDavid Christensen static int ecore_execute_vlan_mac(struct bxe_softc *sc,
19554e400768SDavid Christensen 				  union ecore_qable_obj *qo,
19564e400768SDavid Christensen 				  ecore_list_t *exe_chunk,
19574e400768SDavid Christensen 				  unsigned long *ramrod_flags)
19584e400768SDavid Christensen {
19594e400768SDavid Christensen 	struct ecore_exeq_elem *elem;
19604e400768SDavid Christensen 	struct ecore_vlan_mac_obj *o = &qo->vlan_mac, *cam_obj;
19614e400768SDavid Christensen 	struct ecore_raw_obj *r = &o->raw;
19624e400768SDavid Christensen 	int rc, idx = 0;
19634e400768SDavid Christensen 	bool restore = ECORE_TEST_BIT(RAMROD_RESTORE, ramrod_flags);
19644e400768SDavid Christensen 	bool drv_only = ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, ramrod_flags);
19654e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *reg_elem;
19664e400768SDavid Christensen 	enum ecore_vlan_mac_cmd cmd;
19674e400768SDavid Christensen 
19684e400768SDavid Christensen 	/* If DRIVER_ONLY execution is requested, cleanup a registry
19694e400768SDavid Christensen 	 * and exit. Otherwise send a ramrod to FW.
19704e400768SDavid Christensen 	 */
19714e400768SDavid Christensen 	if (!drv_only) {
19725e33becaSEric Davis 		ECORE_DBG_BREAK_IF(r->check_pending(r));
19734e400768SDavid Christensen 
19744e400768SDavid Christensen 		/* Set pending */
19754e400768SDavid Christensen 		r->set_pending(r);
19764e400768SDavid Christensen 
19774e400768SDavid Christensen 		/* Fill the ramrod data */
19784e400768SDavid Christensen 		ECORE_LIST_FOR_EACH_ENTRY(elem, exe_chunk, link,
19794e400768SDavid Christensen 					  struct ecore_exeq_elem) {
19804e400768SDavid Christensen 			cmd = elem->cmd_data.vlan_mac.cmd;
19814e400768SDavid Christensen 			/* We will add to the target object in MOVE command, so
19824e400768SDavid Christensen 			 * change the object for a CAM search.
19834e400768SDavid Christensen 			 */
19844e400768SDavid Christensen 			if (cmd == ECORE_VLAN_MAC_MOVE)
19854e400768SDavid Christensen 				cam_obj = elem->cmd_data.vlan_mac.target_obj;
19864e400768SDavid Christensen 			else
19874e400768SDavid Christensen 				cam_obj = o;
19884e400768SDavid Christensen 
19894e400768SDavid Christensen 			rc = ecore_vlan_mac_get_registry_elem(sc, cam_obj,
19904e400768SDavid Christensen 							      elem, restore,
19914e400768SDavid Christensen 							      &reg_elem);
19924e400768SDavid Christensen 			if (rc)
19934e400768SDavid Christensen 				goto error_exit;
19944e400768SDavid Christensen 
19954e400768SDavid Christensen 			ECORE_DBG_BREAK_IF(!reg_elem);
19964e400768SDavid Christensen 
19974e400768SDavid Christensen 			/* Push a new entry into the registry */
19984e400768SDavid Christensen 			if (!restore &&
19994e400768SDavid Christensen 			    ((cmd == ECORE_VLAN_MAC_ADD) ||
20004e400768SDavid Christensen 			    (cmd == ECORE_VLAN_MAC_MOVE)))
20014e400768SDavid Christensen 				ECORE_LIST_PUSH_HEAD(&reg_elem->link,
20024e400768SDavid Christensen 						     &cam_obj->head);
20034e400768SDavid Christensen 
20044e400768SDavid Christensen 			/* Configure a single command in a ramrod data buffer */
20054e400768SDavid Christensen 			o->set_one_rule(sc, o, elem, idx,
20064e400768SDavid Christensen 					reg_elem->cam_offset);
20074e400768SDavid Christensen 
20084e400768SDavid Christensen 			/* MOVE command consumes 2 entries in the ramrod data */
20094e400768SDavid Christensen 			if (cmd == ECORE_VLAN_MAC_MOVE)
20104e400768SDavid Christensen 				idx += 2;
20114e400768SDavid Christensen 			else
20124e400768SDavid Christensen 				idx++;
20134e400768SDavid Christensen 		}
20144e400768SDavid Christensen 
20154ef8ebfdSDavid C Somayajulu 		/* No need for an explicit memory barrier here as long as we
20164ef8ebfdSDavid C Somayajulu 		 * ensure the ordering of writing to the SPQ element
20174e400768SDavid Christensen 		 *  and updating of the SPQ producer which involves a memory
20184ef8ebfdSDavid C Somayajulu 		 * read. If the memory read is removed we will have to put a
20194ef8ebfdSDavid C Somayajulu 		 * full memory barrier there (inside ecore_sp_post()).
20204e400768SDavid Christensen 		 */
20214e400768SDavid Christensen 		rc = ecore_sp_post(sc, o->ramrod_cmd, r->cid,
20224e400768SDavid Christensen 				   r->rdata_mapping,
20234e400768SDavid Christensen 				   ETH_CONNECTION_TYPE);
20244e400768SDavid Christensen 		if (rc)
20254e400768SDavid Christensen 			goto error_exit;
20264e400768SDavid Christensen 	}
20274e400768SDavid Christensen 
20284e400768SDavid Christensen 	/* Now, when we are done with the ramrod - clean up the registry */
20294e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(elem, exe_chunk, link,
20304e400768SDavid Christensen 				  struct ecore_exeq_elem) {
20314e400768SDavid Christensen 		cmd = elem->cmd_data.vlan_mac.cmd;
20324e400768SDavid Christensen 		if ((cmd == ECORE_VLAN_MAC_DEL) ||
20334e400768SDavid Christensen 		    (cmd == ECORE_VLAN_MAC_MOVE)) {
20344e400768SDavid Christensen 			reg_elem = o->check_del(sc, o,
20354e400768SDavid Christensen 						&elem->cmd_data.vlan_mac.u);
20364e400768SDavid Christensen 
20374e400768SDavid Christensen 			ECORE_DBG_BREAK_IF(!reg_elem);
20384e400768SDavid Christensen 
20394e400768SDavid Christensen 			o->put_cam_offset(o, reg_elem->cam_offset);
20404e400768SDavid Christensen 			ECORE_LIST_REMOVE_ENTRY(&reg_elem->link, &o->head);
20414e400768SDavid Christensen 			ECORE_FREE(sc, reg_elem, sizeof(*reg_elem));
20424e400768SDavid Christensen 		}
20434e400768SDavid Christensen 	}
20444e400768SDavid Christensen 
20454e400768SDavid Christensen 	if (!drv_only)
20464e400768SDavid Christensen 		return ECORE_PENDING;
20474e400768SDavid Christensen 	else
20484e400768SDavid Christensen 		return ECORE_SUCCESS;
20494e400768SDavid Christensen 
20504e400768SDavid Christensen error_exit:
20514e400768SDavid Christensen 	r->clear_pending(r);
20524e400768SDavid Christensen 
20534e400768SDavid Christensen 	/* Cleanup a registry in case of a failure */
20544e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(elem, exe_chunk, link,
20554e400768SDavid Christensen 				  struct ecore_exeq_elem) {
20564e400768SDavid Christensen 		cmd = elem->cmd_data.vlan_mac.cmd;
20574e400768SDavid Christensen 
20584e400768SDavid Christensen 		if (cmd == ECORE_VLAN_MAC_MOVE)
20594e400768SDavid Christensen 			cam_obj = elem->cmd_data.vlan_mac.target_obj;
20604e400768SDavid Christensen 		else
20614e400768SDavid Christensen 			cam_obj = o;
20624e400768SDavid Christensen 
20634e400768SDavid Christensen 		/* Delete all newly added above entries */
20644e400768SDavid Christensen 		if (!restore &&
20654e400768SDavid Christensen 		    ((cmd == ECORE_VLAN_MAC_ADD) ||
20664e400768SDavid Christensen 		    (cmd == ECORE_VLAN_MAC_MOVE))) {
20674e400768SDavid Christensen 			reg_elem = o->check_del(sc, cam_obj,
20684e400768SDavid Christensen 						&elem->cmd_data.vlan_mac.u);
20694e400768SDavid Christensen 			if (reg_elem) {
20704e400768SDavid Christensen 				ECORE_LIST_REMOVE_ENTRY(&reg_elem->link,
20714e400768SDavid Christensen 							&cam_obj->head);
20724e400768SDavid Christensen 				ECORE_FREE(sc, reg_elem, sizeof(*reg_elem));
20734e400768SDavid Christensen 			}
20744e400768SDavid Christensen 		}
20754e400768SDavid Christensen 	}
20764e400768SDavid Christensen 
20774e400768SDavid Christensen 	return rc;
20784e400768SDavid Christensen }
20794e400768SDavid Christensen 
ecore_vlan_mac_push_new_cmd(struct bxe_softc * sc,struct ecore_vlan_mac_ramrod_params * p)20804e400768SDavid Christensen static inline int ecore_vlan_mac_push_new_cmd(
20814e400768SDavid Christensen 	struct bxe_softc *sc,
20824e400768SDavid Christensen 	struct ecore_vlan_mac_ramrod_params *p)
20834e400768SDavid Christensen {
20844e400768SDavid Christensen 	struct ecore_exeq_elem *elem;
20854e400768SDavid Christensen 	struct ecore_vlan_mac_obj *o = p->vlan_mac_obj;
20864e400768SDavid Christensen 	bool restore = ECORE_TEST_BIT(RAMROD_RESTORE, &p->ramrod_flags);
20874e400768SDavid Christensen 
20884e400768SDavid Christensen 	/* Allocate the execution queue element */
20894e400768SDavid Christensen 	elem = ecore_exe_queue_alloc_elem(sc);
20904e400768SDavid Christensen 	if (!elem)
20914e400768SDavid Christensen 		return ECORE_NOMEM;
20924e400768SDavid Christensen 
20934e400768SDavid Christensen 	/* Set the command 'length' */
20944e400768SDavid Christensen 	switch (p->user_req.cmd) {
20954e400768SDavid Christensen 	case ECORE_VLAN_MAC_MOVE:
20964e400768SDavid Christensen 		elem->cmd_len = 2;
20974e400768SDavid Christensen 		break;
20984e400768SDavid Christensen 	default:
20994e400768SDavid Christensen 		elem->cmd_len = 1;
21004e400768SDavid Christensen 	}
21014e400768SDavid Christensen 
21024e400768SDavid Christensen 	/* Fill the object specific info */
21034e400768SDavid Christensen 	ECORE_MEMCPY(&elem->cmd_data.vlan_mac, &p->user_req, sizeof(p->user_req));
21044e400768SDavid Christensen 
21054e400768SDavid Christensen 	/* Try to add a new command to the pending list */
21064e400768SDavid Christensen 	return ecore_exe_queue_add(sc, &o->exe_queue, elem, restore);
21074e400768SDavid Christensen }
21084e400768SDavid Christensen 
21094e400768SDavid Christensen /**
21104e400768SDavid Christensen  * ecore_config_vlan_mac - configure VLAN/MAC/VLAN_MAC filtering rules.
21114e400768SDavid Christensen  *
21124e400768SDavid Christensen  * @sc:	  device handle
21134e400768SDavid Christensen  * @p:
21144e400768SDavid Christensen  *
21154e400768SDavid Christensen  */
ecore_config_vlan_mac(struct bxe_softc * sc,struct ecore_vlan_mac_ramrod_params * p)21164e400768SDavid Christensen int ecore_config_vlan_mac(struct bxe_softc *sc,
21174e400768SDavid Christensen 			   struct ecore_vlan_mac_ramrod_params *p)
21184e400768SDavid Christensen {
21194e400768SDavid Christensen 	int rc = ECORE_SUCCESS;
21204e400768SDavid Christensen 	struct ecore_vlan_mac_obj *o = p->vlan_mac_obj;
21214e400768SDavid Christensen 	unsigned long *ramrod_flags = &p->ramrod_flags;
21224e400768SDavid Christensen 	bool cont = ECORE_TEST_BIT(RAMROD_CONT, ramrod_flags);
21234e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
21244e400768SDavid Christensen 
21254e400768SDavid Christensen 	/*
21264e400768SDavid Christensen 	 * Add new elements to the execution list for commands that require it.
21274e400768SDavid Christensen 	 */
21284e400768SDavid Christensen 	if (!cont) {
21294e400768SDavid Christensen 		rc = ecore_vlan_mac_push_new_cmd(sc, p);
21304e400768SDavid Christensen 		if (rc)
21314e400768SDavid Christensen 			return rc;
21324e400768SDavid Christensen 	}
21334e400768SDavid Christensen 
21344e400768SDavid Christensen 	/* If nothing will be executed further in this iteration we want to
21354e400768SDavid Christensen 	 * return PENDING if there are pending commands
21364e400768SDavid Christensen 	 */
21374e400768SDavid Christensen 	if (!ecore_exe_queue_empty(&o->exe_queue))
21384e400768SDavid Christensen 		rc = ECORE_PENDING;
21394e400768SDavid Christensen 
21404e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, ramrod_flags))  {
21414e400768SDavid Christensen 		ECORE_MSG(sc, "RAMROD_DRV_CLR_ONLY requested: clearing a pending bit.\n");
21424e400768SDavid Christensen 		raw->clear_pending(raw);
21434e400768SDavid Christensen 	}
21444e400768SDavid Christensen 
21454e400768SDavid Christensen 	/* Execute commands if required */
21464e400768SDavid Christensen 	if (cont || ECORE_TEST_BIT(RAMROD_EXEC, ramrod_flags) ||
21474e400768SDavid Christensen 	    ECORE_TEST_BIT(RAMROD_COMP_WAIT, ramrod_flags)) {
21484e400768SDavid Christensen 		rc = __ecore_vlan_mac_execute_step(sc, p->vlan_mac_obj,
21494e400768SDavid Christensen 						   &p->ramrod_flags);
21504e400768SDavid Christensen 		if (rc < 0)
21514e400768SDavid Christensen 			return rc;
21524e400768SDavid Christensen 	}
21534e400768SDavid Christensen 
21544e400768SDavid Christensen 	/* RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set
21554e400768SDavid Christensen 	 * then user want to wait until the last command is done.
21564e400768SDavid Christensen 	 */
21574e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
21584e400768SDavid Christensen 		/* Wait maximum for the current exe_queue length iterations plus
21594e400768SDavid Christensen 		 * one (for the current pending command).
21604e400768SDavid Christensen 		 */
21614e400768SDavid Christensen 		int max_iterations = ecore_exe_queue_length(&o->exe_queue) + 1;
21624e400768SDavid Christensen 
21634e400768SDavid Christensen 		while (!ecore_exe_queue_empty(&o->exe_queue) &&
21644e400768SDavid Christensen 		       max_iterations--) {
21654e400768SDavid Christensen 
21664e400768SDavid Christensen 			/* Wait for the current command to complete */
21674e400768SDavid Christensen 			rc = raw->wait_comp(sc, raw);
21684e400768SDavid Christensen 			if (rc)
21694e400768SDavid Christensen 				return rc;
21704e400768SDavid Christensen 
21714e400768SDavid Christensen 			/* Make a next step */
21724e400768SDavid Christensen 			rc = __ecore_vlan_mac_execute_step(sc,
21734e400768SDavid Christensen 							   p->vlan_mac_obj,
21744e400768SDavid Christensen 							   &p->ramrod_flags);
21754e400768SDavid Christensen 			if (rc < 0)
21764e400768SDavid Christensen 				return rc;
21774e400768SDavid Christensen 		}
21784e400768SDavid Christensen 
21794e400768SDavid Christensen 		return ECORE_SUCCESS;
21804e400768SDavid Christensen 	}
21814e400768SDavid Christensen 
21824e400768SDavid Christensen 	return rc;
21834e400768SDavid Christensen }
21844e400768SDavid Christensen 
21854e400768SDavid Christensen /**
21864e400768SDavid Christensen  * ecore_vlan_mac_del_all - delete elements with given vlan_mac_flags spec
21874e400768SDavid Christensen  *
21884e400768SDavid Christensen  * @sc:			device handle
21894e400768SDavid Christensen  * @o:
21904e400768SDavid Christensen  * @vlan_mac_flags:
21914e400768SDavid Christensen  * @ramrod_flags:	execution flags to be used for this deletion
21924e400768SDavid Christensen  *
21934e400768SDavid Christensen  * if the last operation has completed successfully and there are no
21944e400768SDavid Christensen  * more elements left, positive value if the last operation has completed
21954e400768SDavid Christensen  * successfully and there are more previously configured elements, negative
21964e400768SDavid Christensen  * value is current operation has failed.
21974e400768SDavid Christensen  */
ecore_vlan_mac_del_all(struct bxe_softc * sc,struct ecore_vlan_mac_obj * o,unsigned long * vlan_mac_flags,unsigned long * ramrod_flags)21984e400768SDavid Christensen static int ecore_vlan_mac_del_all(struct bxe_softc *sc,
21994e400768SDavid Christensen 				  struct ecore_vlan_mac_obj *o,
22004e400768SDavid Christensen 				  unsigned long *vlan_mac_flags,
22014e400768SDavid Christensen 				  unsigned long *ramrod_flags)
22024e400768SDavid Christensen {
22034e400768SDavid Christensen 	struct ecore_vlan_mac_registry_elem *pos = NULL;
22044e400768SDavid Christensen 	struct ecore_vlan_mac_ramrod_params p;
22054e400768SDavid Christensen 	struct ecore_exe_queue_obj *exeq = &o->exe_queue;
22064e400768SDavid Christensen 	struct ecore_exeq_elem *exeq_pos, *exeq_pos_n;
22074ef8ebfdSDavid C Somayajulu 	unsigned long flags;
22085e33becaSEric Davis 	int read_lock;
22095e33becaSEric Davis 	int rc = 0;
22104e400768SDavid Christensen 
22114e400768SDavid Christensen 	/* Clear pending commands first */
22124e400768SDavid Christensen 
22134e400768SDavid Christensen 	ECORE_SPIN_LOCK_BH(&exeq->lock);
22144e400768SDavid Christensen 
22154e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY_SAFE(exeq_pos, exeq_pos_n,
22164e400768SDavid Christensen 				       &exeq->exe_queue, link,
22174e400768SDavid Christensen 				       struct ecore_exeq_elem) {
22184ef8ebfdSDavid C Somayajulu 		flags = exeq_pos->cmd_data.vlan_mac.vlan_mac_flags;
22194ef8ebfdSDavid C Somayajulu 		if (ECORE_VLAN_MAC_CMP_FLAGS(flags) ==
22204ef8ebfdSDavid C Somayajulu 		    ECORE_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
22214e400768SDavid Christensen 			rc = exeq->remove(sc, exeq->owner, exeq_pos);
22224e400768SDavid Christensen 			if (rc) {
22234e400768SDavid Christensen 				ECORE_ERR("Failed to remove command\n");
22244e400768SDavid Christensen 				ECORE_SPIN_UNLOCK_BH(&exeq->lock);
22254e400768SDavid Christensen 				return rc;
22264e400768SDavid Christensen 			}
22274e400768SDavid Christensen 			ECORE_LIST_REMOVE_ENTRY(&exeq_pos->link,
22284e400768SDavid Christensen 						&exeq->exe_queue);
22294e400768SDavid Christensen 			ecore_exe_queue_free_elem(sc, exeq_pos);
22304e400768SDavid Christensen 		}
22314e400768SDavid Christensen 	}
22324e400768SDavid Christensen 
22334e400768SDavid Christensen 	ECORE_SPIN_UNLOCK_BH(&exeq->lock);
22344e400768SDavid Christensen 
22354e400768SDavid Christensen 	/* Prepare a command request */
22364e400768SDavid Christensen 	ECORE_MEMSET(&p, 0, sizeof(p));
22374e400768SDavid Christensen 	p.vlan_mac_obj = o;
22384e400768SDavid Christensen 	p.ramrod_flags = *ramrod_flags;
22394e400768SDavid Christensen 	p.user_req.cmd = ECORE_VLAN_MAC_DEL;
22404e400768SDavid Christensen 
22414e400768SDavid Christensen 	/* Add all but the last VLAN-MAC to the execution queue without actually
22424e400768SDavid Christensen 	 * execution anything.
22434e400768SDavid Christensen 	 */
22444e400768SDavid Christensen 	ECORE_CLEAR_BIT_NA(RAMROD_COMP_WAIT, &p.ramrod_flags);
22454e400768SDavid Christensen 	ECORE_CLEAR_BIT_NA(RAMROD_EXEC, &p.ramrod_flags);
22464e400768SDavid Christensen 	ECORE_CLEAR_BIT_NA(RAMROD_CONT, &p.ramrod_flags);
22474e400768SDavid Christensen 
22484e400768SDavid Christensen 	ECORE_MSG(sc, "vlan_mac_del_all -- taking vlan_mac_lock (reader)\n");
22494e400768SDavid Christensen 	read_lock = ecore_vlan_mac_h_read_lock(sc, o);
22504e400768SDavid Christensen 	if (read_lock != ECORE_SUCCESS)
22514e400768SDavid Christensen 		return read_lock;
22524e400768SDavid Christensen 
22534e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link,
22544e400768SDavid Christensen 				  struct ecore_vlan_mac_registry_elem) {
22554ef8ebfdSDavid C Somayajulu 		flags = pos->vlan_mac_flags;
22564ef8ebfdSDavid C Somayajulu 		if (ECORE_VLAN_MAC_CMP_FLAGS(flags) ==
22574ef8ebfdSDavid C Somayajulu 		    ECORE_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
22584e400768SDavid Christensen 			p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
22594e400768SDavid Christensen 			ECORE_MEMCPY(&p.user_req.u, &pos->u, sizeof(pos->u));
22604e400768SDavid Christensen 			rc = ecore_config_vlan_mac(sc, &p);
22614e400768SDavid Christensen 			if (rc < 0) {
22624e400768SDavid Christensen 				ECORE_ERR("Failed to add a new DEL command\n");
22634e400768SDavid Christensen 				ecore_vlan_mac_h_read_unlock(sc, o);
22644e400768SDavid Christensen 				return rc;
22654e400768SDavid Christensen 			}
22664e400768SDavid Christensen 		}
22674e400768SDavid Christensen 	}
22684e400768SDavid Christensen 
22694e400768SDavid Christensen 	ECORE_MSG(sc, "vlan_mac_del_all -- releasing vlan_mac_lock (reader)\n");
22704e400768SDavid Christensen 	ecore_vlan_mac_h_read_unlock(sc, o);
22714e400768SDavid Christensen 
22724e400768SDavid Christensen 	p.ramrod_flags = *ramrod_flags;
22734e400768SDavid Christensen 	ECORE_SET_BIT_NA(RAMROD_CONT, &p.ramrod_flags);
22744e400768SDavid Christensen 
22754e400768SDavid Christensen 	return ecore_config_vlan_mac(sc, &p);
22764e400768SDavid Christensen }
22774e400768SDavid Christensen 
ecore_init_raw_obj(struct ecore_raw_obj * raw,uint8_t cl_id,uint32_t cid,uint8_t func_id,void * rdata,ecore_dma_addr_t rdata_mapping,int state,unsigned long * pstate,ecore_obj_type type)22784e400768SDavid Christensen static inline void ecore_init_raw_obj(struct ecore_raw_obj *raw, uint8_t cl_id,
22794e400768SDavid Christensen 	uint32_t cid, uint8_t func_id, void *rdata, ecore_dma_addr_t rdata_mapping, int state,
22804e400768SDavid Christensen 	unsigned long *pstate, ecore_obj_type type)
22814e400768SDavid Christensen {
22824e400768SDavid Christensen 	raw->func_id = func_id;
22834e400768SDavid Christensen 	raw->cid = cid;
22844e400768SDavid Christensen 	raw->cl_id = cl_id;
22854e400768SDavid Christensen 	raw->rdata = rdata;
22864e400768SDavid Christensen 	raw->rdata_mapping = rdata_mapping;
22874e400768SDavid Christensen 	raw->state = state;
22884e400768SDavid Christensen 	raw->pstate = pstate;
22894e400768SDavid Christensen 	raw->obj_type = type;
22904e400768SDavid Christensen 	raw->check_pending = ecore_raw_check_pending;
22914e400768SDavid Christensen 	raw->clear_pending = ecore_raw_clear_pending;
22924e400768SDavid Christensen 	raw->set_pending = ecore_raw_set_pending;
22934e400768SDavid Christensen 	raw->wait_comp = ecore_raw_wait;
22944e400768SDavid Christensen }
22954e400768SDavid Christensen 
ecore_init_vlan_mac_common(struct ecore_vlan_mac_obj * o,uint8_t cl_id,uint32_t cid,uint8_t func_id,void * rdata,ecore_dma_addr_t rdata_mapping,int state,unsigned long * pstate,ecore_obj_type type,struct ecore_credit_pool_obj * macs_pool,struct ecore_credit_pool_obj * vlans_pool)22964e400768SDavid Christensen static inline void ecore_init_vlan_mac_common(struct ecore_vlan_mac_obj *o,
22974e400768SDavid Christensen 	uint8_t cl_id, uint32_t cid, uint8_t func_id, void *rdata, ecore_dma_addr_t rdata_mapping,
22984e400768SDavid Christensen 	int state, unsigned long *pstate, ecore_obj_type type,
22994e400768SDavid Christensen 	struct ecore_credit_pool_obj *macs_pool,
23004e400768SDavid Christensen 	struct ecore_credit_pool_obj *vlans_pool)
23014e400768SDavid Christensen {
23024e400768SDavid Christensen 	ECORE_LIST_INIT(&o->head);
23034e400768SDavid Christensen 	o->head_reader = 0;
23044e400768SDavid Christensen 	o->head_exe_request = FALSE;
23054e400768SDavid Christensen 	o->saved_ramrod_flags = 0;
23064e400768SDavid Christensen 
23074e400768SDavid Christensen 	o->macs_pool = macs_pool;
23084e400768SDavid Christensen 	o->vlans_pool = vlans_pool;
23094e400768SDavid Christensen 
23104e400768SDavid Christensen 	o->delete_all = ecore_vlan_mac_del_all;
23114e400768SDavid Christensen 	o->restore = ecore_vlan_mac_restore;
23124e400768SDavid Christensen 	o->complete = ecore_complete_vlan_mac;
23134e400768SDavid Christensen 	o->wait = ecore_wait_vlan_mac;
23144e400768SDavid Christensen 
23154e400768SDavid Christensen 	ecore_init_raw_obj(&o->raw, cl_id, cid, func_id, rdata, rdata_mapping,
23164e400768SDavid Christensen 			   state, pstate, type);
23174e400768SDavid Christensen }
23184e400768SDavid Christensen 
ecore_init_mac_obj(struct bxe_softc * sc,struct ecore_vlan_mac_obj * mac_obj,uint8_t cl_id,uint32_t cid,uint8_t func_id,void * rdata,ecore_dma_addr_t rdata_mapping,int state,unsigned long * pstate,ecore_obj_type type,struct ecore_credit_pool_obj * macs_pool)23194e400768SDavid Christensen void ecore_init_mac_obj(struct bxe_softc *sc,
23204e400768SDavid Christensen 			struct ecore_vlan_mac_obj *mac_obj,
23214e400768SDavid Christensen 			uint8_t cl_id, uint32_t cid, uint8_t func_id, void *rdata,
23224e400768SDavid Christensen 			ecore_dma_addr_t rdata_mapping, int state,
23234e400768SDavid Christensen 			unsigned long *pstate, ecore_obj_type type,
23244e400768SDavid Christensen 			struct ecore_credit_pool_obj *macs_pool)
23254e400768SDavid Christensen {
23264e400768SDavid Christensen 	union ecore_qable_obj *qable_obj = (union ecore_qable_obj *)mac_obj;
23274e400768SDavid Christensen 
23284e400768SDavid Christensen 	ecore_init_vlan_mac_common(mac_obj, cl_id, cid, func_id, rdata,
23294e400768SDavid Christensen 				   rdata_mapping, state, pstate, type,
23304e400768SDavid Christensen 				   macs_pool, NULL);
23314e400768SDavid Christensen 
23324e400768SDavid Christensen 	/* CAM credit pool handling */
23334e400768SDavid Christensen 	mac_obj->get_credit = ecore_get_credit_mac;
23344e400768SDavid Christensen 	mac_obj->put_credit = ecore_put_credit_mac;
23354e400768SDavid Christensen 	mac_obj->get_cam_offset = ecore_get_cam_offset_mac;
23364e400768SDavid Christensen 	mac_obj->put_cam_offset = ecore_put_cam_offset_mac;
23374e400768SDavid Christensen 
23384e400768SDavid Christensen 	if (CHIP_IS_E1x(sc)) {
23394e400768SDavid Christensen 		mac_obj->set_one_rule      = ecore_set_one_mac_e1x;
23404e400768SDavid Christensen 		mac_obj->check_del         = ecore_check_mac_del;
23414e400768SDavid Christensen 		mac_obj->check_add         = ecore_check_mac_add;
23424e400768SDavid Christensen 		mac_obj->check_move        = ecore_check_move_always_err;
23434e400768SDavid Christensen 		mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
23444e400768SDavid Christensen 
23454e400768SDavid Christensen 		/* Exe Queue */
23464e400768SDavid Christensen 		ecore_exe_queue_init(sc,
23474e400768SDavid Christensen 				     &mac_obj->exe_queue, 1, qable_obj,
23484e400768SDavid Christensen 				     ecore_validate_vlan_mac,
23494e400768SDavid Christensen 				     ecore_remove_vlan_mac,
23504e400768SDavid Christensen 				     ecore_optimize_vlan_mac,
23514e400768SDavid Christensen 				     ecore_execute_vlan_mac,
23524e400768SDavid Christensen 				     ecore_exeq_get_mac);
23534e400768SDavid Christensen 	} else {
23544e400768SDavid Christensen 		mac_obj->set_one_rule      = ecore_set_one_mac_e2;
23554e400768SDavid Christensen 		mac_obj->check_del         = ecore_check_mac_del;
23564e400768SDavid Christensen 		mac_obj->check_add         = ecore_check_mac_add;
23574e400768SDavid Christensen 		mac_obj->check_move        = ecore_check_move;
23584e400768SDavid Christensen 		mac_obj->ramrod_cmd        =
23594e400768SDavid Christensen 			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
23604e400768SDavid Christensen 		mac_obj->get_n_elements    = ecore_get_n_elements;
23614e400768SDavid Christensen 
23624e400768SDavid Christensen 		/* Exe Queue */
23634e400768SDavid Christensen 		ecore_exe_queue_init(sc,
23644e400768SDavid Christensen 				     &mac_obj->exe_queue, CLASSIFY_RULES_COUNT,
23654e400768SDavid Christensen 				     qable_obj, ecore_validate_vlan_mac,
23664e400768SDavid Christensen 				     ecore_remove_vlan_mac,
23674e400768SDavid Christensen 				     ecore_optimize_vlan_mac,
23684e400768SDavid Christensen 				     ecore_execute_vlan_mac,
23694e400768SDavid Christensen 				     ecore_exeq_get_mac);
23704e400768SDavid Christensen 	}
23714e400768SDavid Christensen }
23724e400768SDavid Christensen 
ecore_init_vlan_obj(struct bxe_softc * sc,struct ecore_vlan_mac_obj * vlan_obj,uint8_t cl_id,uint32_t cid,uint8_t func_id,void * rdata,ecore_dma_addr_t rdata_mapping,int state,unsigned long * pstate,ecore_obj_type type,struct ecore_credit_pool_obj * vlans_pool)23734e400768SDavid Christensen void ecore_init_vlan_obj(struct bxe_softc *sc,
23744e400768SDavid Christensen 			 struct ecore_vlan_mac_obj *vlan_obj,
23754e400768SDavid Christensen 			 uint8_t cl_id, uint32_t cid, uint8_t func_id, void *rdata,
23764e400768SDavid Christensen 			 ecore_dma_addr_t rdata_mapping, int state,
23774e400768SDavid Christensen 			 unsigned long *pstate, ecore_obj_type type,
23784e400768SDavid Christensen 			 struct ecore_credit_pool_obj *vlans_pool)
23794e400768SDavid Christensen {
23804e400768SDavid Christensen 	union ecore_qable_obj *qable_obj = (union ecore_qable_obj *)vlan_obj;
23814e400768SDavid Christensen 
23824e400768SDavid Christensen 	ecore_init_vlan_mac_common(vlan_obj, cl_id, cid, func_id, rdata,
23834e400768SDavid Christensen 				   rdata_mapping, state, pstate, type, NULL,
23844e400768SDavid Christensen 				   vlans_pool);
23854e400768SDavid Christensen 
23864e400768SDavid Christensen 	vlan_obj->get_credit = ecore_get_credit_vlan;
23874e400768SDavid Christensen 	vlan_obj->put_credit = ecore_put_credit_vlan;
23884e400768SDavid Christensen 	vlan_obj->get_cam_offset = ecore_get_cam_offset_vlan;
23894e400768SDavid Christensen 	vlan_obj->put_cam_offset = ecore_put_cam_offset_vlan;
23904e400768SDavid Christensen 
23914e400768SDavid Christensen 	if (CHIP_IS_E1x(sc)) {
23924e400768SDavid Christensen 		ECORE_ERR("Do not support chips others than E2 and newer\n");
23934e400768SDavid Christensen 		ECORE_BUG();
23944e400768SDavid Christensen 	} else {
23954e400768SDavid Christensen 		vlan_obj->set_one_rule      = ecore_set_one_vlan_e2;
23964e400768SDavid Christensen 		vlan_obj->check_del         = ecore_check_vlan_del;
23974e400768SDavid Christensen 		vlan_obj->check_add         = ecore_check_vlan_add;
23984e400768SDavid Christensen 		vlan_obj->check_move        = ecore_check_move;
23994e400768SDavid Christensen 		vlan_obj->ramrod_cmd        =
24004e400768SDavid Christensen 			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
24014e400768SDavid Christensen 		vlan_obj->get_n_elements    = ecore_get_n_elements;
24024e400768SDavid Christensen 
24034e400768SDavid Christensen 		/* Exe Queue */
24044e400768SDavid Christensen 		ecore_exe_queue_init(sc,
24054e400768SDavid Christensen 				     &vlan_obj->exe_queue, CLASSIFY_RULES_COUNT,
24064e400768SDavid Christensen 				     qable_obj, ecore_validate_vlan_mac,
24074e400768SDavid Christensen 				     ecore_remove_vlan_mac,
24084e400768SDavid Christensen 				     ecore_optimize_vlan_mac,
24094e400768SDavid Christensen 				     ecore_execute_vlan_mac,
24104e400768SDavid Christensen 				     ecore_exeq_get_vlan);
24114e400768SDavid Christensen 	}
24124e400768SDavid Christensen }
24134e400768SDavid Christensen 
ecore_init_vlan_mac_obj(struct bxe_softc * sc,struct ecore_vlan_mac_obj * vlan_mac_obj,uint8_t cl_id,uint32_t cid,uint8_t func_id,void * rdata,ecore_dma_addr_t rdata_mapping,int state,unsigned long * pstate,ecore_obj_type type,struct ecore_credit_pool_obj * macs_pool,struct ecore_credit_pool_obj * vlans_pool)24144e400768SDavid Christensen void ecore_init_vlan_mac_obj(struct bxe_softc *sc,
24154e400768SDavid Christensen 			     struct ecore_vlan_mac_obj *vlan_mac_obj,
24164e400768SDavid Christensen 			     uint8_t cl_id, uint32_t cid, uint8_t func_id, void *rdata,
24174e400768SDavid Christensen 			     ecore_dma_addr_t rdata_mapping, int state,
24184e400768SDavid Christensen 			     unsigned long *pstate, ecore_obj_type type,
24194e400768SDavid Christensen 			     struct ecore_credit_pool_obj *macs_pool,
24204e400768SDavid Christensen 			     struct ecore_credit_pool_obj *vlans_pool)
24214e400768SDavid Christensen {
24224e400768SDavid Christensen 	union ecore_qable_obj *qable_obj =
24234e400768SDavid Christensen 		(union ecore_qable_obj *)vlan_mac_obj;
24244e400768SDavid Christensen 
24254e400768SDavid Christensen 	ecore_init_vlan_mac_common(vlan_mac_obj, cl_id, cid, func_id, rdata,
24264e400768SDavid Christensen 				   rdata_mapping, state, pstate, type,
24274e400768SDavid Christensen 				   macs_pool, vlans_pool);
24284e400768SDavid Christensen 
24294e400768SDavid Christensen 	/* CAM pool handling */
24304e400768SDavid Christensen 	vlan_mac_obj->get_credit = ecore_get_credit_vlan_mac;
24314e400768SDavid Christensen 	vlan_mac_obj->put_credit = ecore_put_credit_vlan_mac;
24324e400768SDavid Christensen 	/* CAM offset is relevant for 57710 and 57711 chips only which have a
24334e400768SDavid Christensen 	 * single CAM for both MACs and VLAN-MAC pairs. So the offset
24344e400768SDavid Christensen 	 * will be taken from MACs' pool object only.
24354e400768SDavid Christensen 	 */
24364e400768SDavid Christensen 	vlan_mac_obj->get_cam_offset = ecore_get_cam_offset_mac;
24374e400768SDavid Christensen 	vlan_mac_obj->put_cam_offset = ecore_put_cam_offset_mac;
24384e400768SDavid Christensen 
24394e400768SDavid Christensen 	if (CHIP_IS_E1(sc)) {
24404e400768SDavid Christensen 		ECORE_ERR("Do not support chips others than E2\n");
24414e400768SDavid Christensen 		ECORE_BUG();
24424e400768SDavid Christensen 	} else if (CHIP_IS_E1H(sc)) {
24434e400768SDavid Christensen 		vlan_mac_obj->set_one_rule      = ecore_set_one_vlan_mac_e1h;
24444e400768SDavid Christensen 		vlan_mac_obj->check_del         = ecore_check_vlan_mac_del;
24454e400768SDavid Christensen 		vlan_mac_obj->check_add         = ecore_check_vlan_mac_add;
24464e400768SDavid Christensen 		vlan_mac_obj->check_move        = ecore_check_move_always_err;
24474e400768SDavid Christensen 		vlan_mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
24484e400768SDavid Christensen 
24494e400768SDavid Christensen 		/* Exe Queue */
24504e400768SDavid Christensen 		ecore_exe_queue_init(sc,
24514e400768SDavid Christensen 				     &vlan_mac_obj->exe_queue, 1, qable_obj,
24524e400768SDavid Christensen 				     ecore_validate_vlan_mac,
24534e400768SDavid Christensen 				     ecore_remove_vlan_mac,
24544e400768SDavid Christensen 				     ecore_optimize_vlan_mac,
24554e400768SDavid Christensen 				     ecore_execute_vlan_mac,
24564e400768SDavid Christensen 				     ecore_exeq_get_vlan_mac);
24574e400768SDavid Christensen 	} else {
24584e400768SDavid Christensen 		vlan_mac_obj->set_one_rule      = ecore_set_one_vlan_mac_e2;
24594e400768SDavid Christensen 		vlan_mac_obj->check_del         = ecore_check_vlan_mac_del;
24604e400768SDavid Christensen 		vlan_mac_obj->check_add         = ecore_check_vlan_mac_add;
24614e400768SDavid Christensen 		vlan_mac_obj->check_move        = ecore_check_move;
24624e400768SDavid Christensen 		vlan_mac_obj->ramrod_cmd        =
24634e400768SDavid Christensen 			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
24644e400768SDavid Christensen 
24654e400768SDavid Christensen 		/* Exe Queue */
24664e400768SDavid Christensen 		ecore_exe_queue_init(sc,
24674e400768SDavid Christensen 				     &vlan_mac_obj->exe_queue,
24684e400768SDavid Christensen 				     CLASSIFY_RULES_COUNT,
24694e400768SDavid Christensen 				     qable_obj, ecore_validate_vlan_mac,
24704e400768SDavid Christensen 				     ecore_remove_vlan_mac,
24714e400768SDavid Christensen 				     ecore_optimize_vlan_mac,
24724e400768SDavid Christensen 				     ecore_execute_vlan_mac,
24734e400768SDavid Christensen 				     ecore_exeq_get_vlan_mac);
24744e400768SDavid Christensen 	}
24754e400768SDavid Christensen }
24764e400768SDavid Christensen 
ecore_init_vxlan_fltr_obj(struct bxe_softc * sc,struct ecore_vlan_mac_obj * vlan_mac_obj,uint8_t cl_id,uint32_t cid,uint8_t func_id,void * rdata,ecore_dma_addr_t rdata_mapping,int state,unsigned long * pstate,ecore_obj_type type,struct ecore_credit_pool_obj * macs_pool,struct ecore_credit_pool_obj * vlans_pool)24774ef8ebfdSDavid C Somayajulu void ecore_init_vxlan_fltr_obj(struct bxe_softc *sc,
24784ef8ebfdSDavid C Somayajulu 				struct ecore_vlan_mac_obj *vlan_mac_obj,
24794ef8ebfdSDavid C Somayajulu 				uint8_t cl_id, uint32_t cid, uint8_t func_id, void *rdata,
24804ef8ebfdSDavid C Somayajulu 				ecore_dma_addr_t rdata_mapping, int state,
24814ef8ebfdSDavid C Somayajulu 				unsigned long *pstate, ecore_obj_type type,
24824ef8ebfdSDavid C Somayajulu 				struct ecore_credit_pool_obj *macs_pool,
24834ef8ebfdSDavid C Somayajulu 				struct ecore_credit_pool_obj *vlans_pool)
24844ef8ebfdSDavid C Somayajulu {
24854ef8ebfdSDavid C Somayajulu 	union ecore_qable_obj *qable_obj =
24864ef8ebfdSDavid C Somayajulu 		(union ecore_qable_obj *)vlan_mac_obj;
24874ef8ebfdSDavid C Somayajulu 
24884ef8ebfdSDavid C Somayajulu 	ecore_init_vlan_mac_common(vlan_mac_obj, cl_id, cid, func_id,
24894ef8ebfdSDavid C Somayajulu 				   rdata, rdata_mapping, state, pstate,
24904ef8ebfdSDavid C Somayajulu 				   type, macs_pool, vlans_pool);
24914ef8ebfdSDavid C Somayajulu 
24924ef8ebfdSDavid C Somayajulu 	/* CAM pool handling */
24934ef8ebfdSDavid C Somayajulu 	vlan_mac_obj->get_credit = ecore_get_credit_vlan_mac;
24944ef8ebfdSDavid C Somayajulu 	vlan_mac_obj->put_credit = ecore_put_credit_vlan_mac;
24954ef8ebfdSDavid C Somayajulu 	/* CAM offset is relevant for 57710 and 57711 chips only which have a
24964ef8ebfdSDavid C Somayajulu 	 * single CAM for both MACs and VLAN-MAC pairs. So the offset
24974ef8ebfdSDavid C Somayajulu 	 * will be taken from MACs' pool object only.
24984ef8ebfdSDavid C Somayajulu 	 */
24994ef8ebfdSDavid C Somayajulu 	vlan_mac_obj->get_cam_offset = ecore_get_cam_offset_mac;
25004ef8ebfdSDavid C Somayajulu 	vlan_mac_obj->put_cam_offset = ecore_put_cam_offset_mac;
25014ef8ebfdSDavid C Somayajulu 
25024ef8ebfdSDavid C Somayajulu 	if (CHIP_IS_E1x(sc)) {
25034ef8ebfdSDavid C Somayajulu 		ECORE_ERR("Do not support chips others than E2/E3\n");
25044ef8ebfdSDavid C Somayajulu 		ECORE_BUG();
25054ef8ebfdSDavid C Somayajulu 	} else {
25064ef8ebfdSDavid C Somayajulu 		vlan_mac_obj->set_one_rule      = ecore_set_one_vxlan_fltr_e2;
25074ef8ebfdSDavid C Somayajulu 		vlan_mac_obj->check_del         = ecore_check_vxlan_fltr_del;
25084ef8ebfdSDavid C Somayajulu 		vlan_mac_obj->check_add         = ecore_check_vxlan_fltr_add;
25094ef8ebfdSDavid C Somayajulu 		vlan_mac_obj->check_move        = ecore_check_move;
25104ef8ebfdSDavid C Somayajulu 		vlan_mac_obj->ramrod_cmd        =
25114ef8ebfdSDavid C Somayajulu 			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
25124ef8ebfdSDavid C Somayajulu 
25134ef8ebfdSDavid C Somayajulu 		/* Exe Queue */
25144ef8ebfdSDavid C Somayajulu 		ecore_exe_queue_init(sc,
25154ef8ebfdSDavid C Somayajulu 				     &vlan_mac_obj->exe_queue,
25164ef8ebfdSDavid C Somayajulu 				     CLASSIFY_RULES_COUNT,
25174ef8ebfdSDavid C Somayajulu 				     qable_obj, ecore_validate_vlan_mac,
25184ef8ebfdSDavid C Somayajulu 				     ecore_remove_vlan_mac,
25194ef8ebfdSDavid C Somayajulu 				     ecore_optimize_vlan_mac,
25204ef8ebfdSDavid C Somayajulu 				     ecore_execute_vlan_mac,
25214ef8ebfdSDavid C Somayajulu 				     ecore_exeq_get_vxlan_fltr);
25224ef8ebfdSDavid C Somayajulu 	}
25234ef8ebfdSDavid C Somayajulu }
25244ef8ebfdSDavid C Somayajulu 
25254e400768SDavid Christensen /* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
__storm_memset_mac_filters(struct bxe_softc * sc,struct tstorm_eth_mac_filter_config * mac_filters,uint16_t pf_id)25264e400768SDavid Christensen static inline void __storm_memset_mac_filters(struct bxe_softc *sc,
25274e400768SDavid Christensen 			struct tstorm_eth_mac_filter_config *mac_filters,
25284e400768SDavid Christensen 			uint16_t pf_id)
25294e400768SDavid Christensen {
25304e400768SDavid Christensen 	size_t size = sizeof(struct tstorm_eth_mac_filter_config);
25314e400768SDavid Christensen 
25324e400768SDavid Christensen 	uint32_t addr = BAR_TSTRORM_INTMEM +
25334e400768SDavid Christensen 			TSTORM_MAC_FILTER_CONFIG_OFFSET(pf_id);
25344e400768SDavid Christensen 
25354e400768SDavid Christensen 	ecore_storm_memset_struct(sc, addr, size, (uint32_t *)mac_filters);
25364e400768SDavid Christensen }
25374e400768SDavid Christensen 
ecore_set_rx_mode_e1x(struct bxe_softc * sc,struct ecore_rx_mode_ramrod_params * p)25384e400768SDavid Christensen static int ecore_set_rx_mode_e1x(struct bxe_softc *sc,
25394e400768SDavid Christensen 				 struct ecore_rx_mode_ramrod_params *p)
25404e400768SDavid Christensen {
25414e400768SDavid Christensen 	/* update the sc MAC filter structure */
25424e400768SDavid Christensen 	uint32_t mask = (1 << p->cl_id);
25434e400768SDavid Christensen 
25444e400768SDavid Christensen 	struct tstorm_eth_mac_filter_config *mac_filters =
25454e400768SDavid Christensen 		(struct tstorm_eth_mac_filter_config *)p->rdata;
25464e400768SDavid Christensen 
25474e400768SDavid Christensen 	/* initial setting is drop-all */
25484e400768SDavid Christensen 	uint8_t drop_all_ucast = 1, drop_all_mcast = 1;
25494e400768SDavid Christensen 	uint8_t accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
25504e400768SDavid Christensen 	uint8_t unmatched_unicast = 0;
25514e400768SDavid Christensen 
25524e400768SDavid Christensen     /* In e1x there we only take into account rx accept flag since tx switching
25534e400768SDavid Christensen      * isn't enabled. */
25544e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_UNICAST, &p->rx_accept_flags))
25554e400768SDavid Christensen 		/* accept matched ucast */
25564e400768SDavid Christensen 		drop_all_ucast = 0;
25574e400768SDavid Christensen 
25584e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_MULTICAST, &p->rx_accept_flags))
25594e400768SDavid Christensen 		/* accept matched mcast */
25604e400768SDavid Christensen 		drop_all_mcast = 0;
25614e400768SDavid Christensen 
25624e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_ALL_UNICAST, &p->rx_accept_flags)) {
25634e400768SDavid Christensen 		/* accept all mcast */
25644e400768SDavid Christensen 		drop_all_ucast = 0;
25654e400768SDavid Christensen 		accp_all_ucast = 1;
25664e400768SDavid Christensen 	}
25674e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_ALL_MULTICAST, &p->rx_accept_flags)) {
25684e400768SDavid Christensen 		/* accept all mcast */
25694e400768SDavid Christensen 		drop_all_mcast = 0;
25704e400768SDavid Christensen 		accp_all_mcast = 1;
25714e400768SDavid Christensen 	}
25724e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_BROADCAST, &p->rx_accept_flags))
25734e400768SDavid Christensen 		/* accept (all) bcast */
25744e400768SDavid Christensen 		accp_all_bcast = 1;
25754e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_UNMATCHED, &p->rx_accept_flags))
25764e400768SDavid Christensen 		/* accept unmatched unicasts */
25774e400768SDavid Christensen 		unmatched_unicast = 1;
25784e400768SDavid Christensen 
25794e400768SDavid Christensen 	mac_filters->ucast_drop_all = drop_all_ucast ?
25804e400768SDavid Christensen 		mac_filters->ucast_drop_all | mask :
25814e400768SDavid Christensen 		mac_filters->ucast_drop_all & ~mask;
25824e400768SDavid Christensen 
25834e400768SDavid Christensen 	mac_filters->mcast_drop_all = drop_all_mcast ?
25844e400768SDavid Christensen 		mac_filters->mcast_drop_all | mask :
25854e400768SDavid Christensen 		mac_filters->mcast_drop_all & ~mask;
25864e400768SDavid Christensen 
25874e400768SDavid Christensen 	mac_filters->ucast_accept_all = accp_all_ucast ?
25884e400768SDavid Christensen 		mac_filters->ucast_accept_all | mask :
25894e400768SDavid Christensen 		mac_filters->ucast_accept_all & ~mask;
25904e400768SDavid Christensen 
25914e400768SDavid Christensen 	mac_filters->mcast_accept_all = accp_all_mcast ?
25924e400768SDavid Christensen 		mac_filters->mcast_accept_all | mask :
25934e400768SDavid Christensen 		mac_filters->mcast_accept_all & ~mask;
25944e400768SDavid Christensen 
25954e400768SDavid Christensen 	mac_filters->bcast_accept_all = accp_all_bcast ?
25964e400768SDavid Christensen 		mac_filters->bcast_accept_all | mask :
25974e400768SDavid Christensen 		mac_filters->bcast_accept_all & ~mask;
25984e400768SDavid Christensen 
25994e400768SDavid Christensen 	mac_filters->unmatched_unicast = unmatched_unicast ?
26004e400768SDavid Christensen 		mac_filters->unmatched_unicast | mask :
26014e400768SDavid Christensen 		mac_filters->unmatched_unicast & ~mask;
26024e400768SDavid Christensen 
26034e400768SDavid Christensen 	ECORE_MSG(sc, "drop_ucast 0x%x\ndrop_mcast 0x%x\n accp_ucast 0x%x\n"
26044e400768SDavid Christensen 			 "accp_mcast 0x%x\naccp_bcast 0x%x\n",
26054e400768SDavid Christensen 	   mac_filters->ucast_drop_all, mac_filters->mcast_drop_all,
26064e400768SDavid Christensen 	   mac_filters->ucast_accept_all, mac_filters->mcast_accept_all,
26074e400768SDavid Christensen 	   mac_filters->bcast_accept_all);
26084e400768SDavid Christensen 
26094e400768SDavid Christensen 	/* write the MAC filter structure*/
26104e400768SDavid Christensen 	__storm_memset_mac_filters(sc, mac_filters, p->func_id);
26114e400768SDavid Christensen 
26124e400768SDavid Christensen 	/* The operation is completed */
26134e400768SDavid Christensen 	ECORE_CLEAR_BIT(p->state, p->pstate);
26144e400768SDavid Christensen 	ECORE_SMP_MB_AFTER_CLEAR_BIT();
26154e400768SDavid Christensen 
26164e400768SDavid Christensen 	return ECORE_SUCCESS;
26174e400768SDavid Christensen }
26184e400768SDavid Christensen 
26194e400768SDavid Christensen /* Setup ramrod data */
ecore_rx_mode_set_rdata_hdr_e2(uint32_t cid,struct eth_classify_header * hdr,uint8_t rule_cnt)26204e400768SDavid Christensen static inline void ecore_rx_mode_set_rdata_hdr_e2(uint32_t cid,
26214e400768SDavid Christensen 				struct eth_classify_header *hdr,
26224e400768SDavid Christensen 				uint8_t rule_cnt)
26234e400768SDavid Christensen {
26244e400768SDavid Christensen 	hdr->echo = ECORE_CPU_TO_LE32(cid);
26254e400768SDavid Christensen 	hdr->rule_cnt = rule_cnt;
26264e400768SDavid Christensen }
26274e400768SDavid Christensen 
ecore_rx_mode_set_cmd_state_e2(struct bxe_softc * sc,unsigned long * accept_flags,struct eth_filter_rules_cmd * cmd,bool clear_accept_all)26284e400768SDavid Christensen static inline void ecore_rx_mode_set_cmd_state_e2(struct bxe_softc *sc,
26294e400768SDavid Christensen 				unsigned long *accept_flags,
26304e400768SDavid Christensen 				struct eth_filter_rules_cmd *cmd,
26314e400768SDavid Christensen 				bool clear_accept_all)
26324e400768SDavid Christensen {
26334e400768SDavid Christensen 	uint16_t state;
26344e400768SDavid Christensen 
26354e400768SDavid Christensen 	/* start with 'drop-all' */
26364e400768SDavid Christensen 	state = ETH_FILTER_RULES_CMD_UCAST_DROP_ALL |
26374e400768SDavid Christensen 		ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
26384e400768SDavid Christensen 
26394e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_UNICAST, accept_flags))
26404e400768SDavid Christensen 		state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
26414e400768SDavid Christensen 
26424e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_MULTICAST, accept_flags))
26434e400768SDavid Christensen 		state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
26444e400768SDavid Christensen 
26454e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_ALL_UNICAST, accept_flags)) {
26464e400768SDavid Christensen 		state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
26474e400768SDavid Christensen 		state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
26484e400768SDavid Christensen 	}
26494e400768SDavid Christensen 
26504e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_ALL_MULTICAST, accept_flags)) {
26514e400768SDavid Christensen 		state |= ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
26524e400768SDavid Christensen 		state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
26534e400768SDavid Christensen 	}
26544e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_BROADCAST, accept_flags))
26554e400768SDavid Christensen 		state |= ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
26564e400768SDavid Christensen 
26574e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_UNMATCHED, accept_flags)) {
26584e400768SDavid Christensen 		state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
26594e400768SDavid Christensen 		state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
26604e400768SDavid Christensen 	}
26614e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_ACCEPT_ANY_VLAN, accept_flags))
26624e400768SDavid Christensen 		state |= ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN;
26634e400768SDavid Christensen 
26644e400768SDavid Christensen 	/* Clear ACCEPT_ALL_XXX flags for FCoE L2 Queue */
26654e400768SDavid Christensen 	if (clear_accept_all) {
26664e400768SDavid Christensen 		state &= ~ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
26674e400768SDavid Christensen 		state &= ~ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
26684e400768SDavid Christensen 		state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
26694e400768SDavid Christensen 		state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
26704e400768SDavid Christensen 	}
26714e400768SDavid Christensen 
26724e400768SDavid Christensen 	cmd->state = ECORE_CPU_TO_LE16(state);
26734e400768SDavid Christensen }
26744e400768SDavid Christensen 
ecore_set_rx_mode_e2(struct bxe_softc * sc,struct ecore_rx_mode_ramrod_params * p)26754e400768SDavid Christensen static int ecore_set_rx_mode_e2(struct bxe_softc *sc,
26764e400768SDavid Christensen 				struct ecore_rx_mode_ramrod_params *p)
26774e400768SDavid Christensen {
26784e400768SDavid Christensen 	struct eth_filter_rules_ramrod_data *data = p->rdata;
26794e400768SDavid Christensen 	int rc;
26804e400768SDavid Christensen 	uint8_t rule_idx = 0;
26814e400768SDavid Christensen 
26824e400768SDavid Christensen 	/* Reset the ramrod data buffer */
26834e400768SDavid Christensen 	ECORE_MEMSET(data, 0, sizeof(*data));
26844e400768SDavid Christensen 
26854e400768SDavid Christensen 	/* Setup ramrod data */
26864e400768SDavid Christensen 
26874e400768SDavid Christensen 	/* Tx (internal switching) */
26884e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_TX, &p->ramrod_flags)) {
26894e400768SDavid Christensen 		data->rules[rule_idx].client_id = p->cl_id;
26904e400768SDavid Christensen 		data->rules[rule_idx].func_id = p->func_id;
26914e400768SDavid Christensen 
26924e400768SDavid Christensen 		data->rules[rule_idx].cmd_general_data =
26934e400768SDavid Christensen 			ETH_FILTER_RULES_CMD_TX_CMD;
26944e400768SDavid Christensen 
26954e400768SDavid Christensen 		ecore_rx_mode_set_cmd_state_e2(sc, &p->tx_accept_flags,
26965e33becaSEric Davis 					       &(data->rules[rule_idx++]),
26975e33becaSEric Davis 					       FALSE);
26984e400768SDavid Christensen 	}
26994e400768SDavid Christensen 
27004e400768SDavid Christensen 	/* Rx */
27014e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_RX, &p->ramrod_flags)) {
27024e400768SDavid Christensen 		data->rules[rule_idx].client_id = p->cl_id;
27034e400768SDavid Christensen 		data->rules[rule_idx].func_id = p->func_id;
27044e400768SDavid Christensen 
27054e400768SDavid Christensen 		data->rules[rule_idx].cmd_general_data =
27064e400768SDavid Christensen 			ETH_FILTER_RULES_CMD_RX_CMD;
27074e400768SDavid Christensen 
27084e400768SDavid Christensen 		ecore_rx_mode_set_cmd_state_e2(sc, &p->rx_accept_flags,
27095e33becaSEric Davis 					       &(data->rules[rule_idx++]),
27105e33becaSEric Davis 					       FALSE);
27114e400768SDavid Christensen 	}
27124e400768SDavid Christensen 
27134e400768SDavid Christensen 	/* If FCoE Queue configuration has been requested configure the Rx and
27144e400768SDavid Christensen 	 * internal switching modes for this queue in separate rules.
27154e400768SDavid Christensen 	 *
27164e400768SDavid Christensen 	 * FCoE queue shell never be set to ACCEPT_ALL packets of any sort:
27174e400768SDavid Christensen 	 * MCAST_ALL, UCAST_ALL, BCAST_ALL and UNMATCHED.
27184e400768SDavid Christensen 	 */
27194e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_RX_MODE_FCOE_ETH, &p->rx_mode_flags)) {
27204e400768SDavid Christensen 		/*  Tx (internal switching) */
27214e400768SDavid Christensen 		if (ECORE_TEST_BIT(RAMROD_TX, &p->ramrod_flags)) {
27224e400768SDavid Christensen 			data->rules[rule_idx].client_id = ECORE_FCOE_CID(sc);
27234e400768SDavid Christensen 			data->rules[rule_idx].func_id = p->func_id;
27244e400768SDavid Christensen 
27254e400768SDavid Christensen 			data->rules[rule_idx].cmd_general_data =
27264e400768SDavid Christensen 						ETH_FILTER_RULES_CMD_TX_CMD;
27274e400768SDavid Christensen 
27285e33becaSEric Davis 			ecore_rx_mode_set_cmd_state_e2(sc, &p->tx_accept_flags,
27295e33becaSEric Davis 						       &(data->rules[rule_idx]),
27304e400768SDavid Christensen 						       TRUE);
27315e33becaSEric Davis 			rule_idx++;
27324e400768SDavid Christensen 		}
27334e400768SDavid Christensen 
27344e400768SDavid Christensen 		/* Rx */
27354e400768SDavid Christensen 		if (ECORE_TEST_BIT(RAMROD_RX, &p->ramrod_flags)) {
27364e400768SDavid Christensen 			data->rules[rule_idx].client_id = ECORE_FCOE_CID(sc);
27374e400768SDavid Christensen 			data->rules[rule_idx].func_id = p->func_id;
27384e400768SDavid Christensen 
27394e400768SDavid Christensen 			data->rules[rule_idx].cmd_general_data =
27404e400768SDavid Christensen 						ETH_FILTER_RULES_CMD_RX_CMD;
27414e400768SDavid Christensen 
27425e33becaSEric Davis 			ecore_rx_mode_set_cmd_state_e2(sc, &p->rx_accept_flags,
27435e33becaSEric Davis 						       &(data->rules[rule_idx]),
27444e400768SDavid Christensen 						       TRUE);
27455e33becaSEric Davis 			rule_idx++;
27464e400768SDavid Christensen 		}
27474e400768SDavid Christensen 	}
27484e400768SDavid Christensen 
27494e400768SDavid Christensen 	/* Set the ramrod header (most importantly - number of rules to
27504e400768SDavid Christensen 	 * configure).
27514e400768SDavid Christensen 	 */
27524e400768SDavid Christensen 	ecore_rx_mode_set_rdata_hdr_e2(p->cid, &data->header, rule_idx);
27534e400768SDavid Christensen 
27544e400768SDavid Christensen 	ECORE_MSG(sc, "About to configure %d rules, rx_accept_flags 0x%lx, tx_accept_flags 0x%lx\n",
27554e400768SDavid Christensen 		  data->header.rule_cnt, p->rx_accept_flags,
27564e400768SDavid Christensen 		  p->tx_accept_flags);
27574e400768SDavid Christensen 
27584ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
27594ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
27604e400768SDavid Christensen 	 * and updating of the SPQ producer which involves a memory
27614ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
27624ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
27634e400768SDavid Christensen 	 */
27644e400768SDavid Christensen 
27654e400768SDavid Christensen 	/* Send a ramrod */
27664e400768SDavid Christensen 	rc = ecore_sp_post(sc,
27674e400768SDavid Christensen 			   RAMROD_CMD_ID_ETH_FILTER_RULES,
27684e400768SDavid Christensen 			   p->cid,
27694e400768SDavid Christensen 			   p->rdata_mapping,
27704e400768SDavid Christensen 			   ETH_CONNECTION_TYPE);
27714e400768SDavid Christensen 	if (rc)
27724e400768SDavid Christensen 		return rc;
27734e400768SDavid Christensen 
27744e400768SDavid Christensen 	/* Ramrod completion is pending */
27754e400768SDavid Christensen 	return ECORE_PENDING;
27764e400768SDavid Christensen }
27774e400768SDavid Christensen 
ecore_wait_rx_mode_comp_e2(struct bxe_softc * sc,struct ecore_rx_mode_ramrod_params * p)27784e400768SDavid Christensen static int ecore_wait_rx_mode_comp_e2(struct bxe_softc *sc,
27794e400768SDavid Christensen 				      struct ecore_rx_mode_ramrod_params *p)
27804e400768SDavid Christensen {
27814e400768SDavid Christensen 	return ecore_state_wait(sc, p->state, p->pstate);
27824e400768SDavid Christensen }
27834e400768SDavid Christensen 
ecore_empty_rx_mode_wait(struct bxe_softc * sc,struct ecore_rx_mode_ramrod_params * p)27844e400768SDavid Christensen static int ecore_empty_rx_mode_wait(struct bxe_softc *sc,
27854e400768SDavid Christensen 				    struct ecore_rx_mode_ramrod_params *p)
27864e400768SDavid Christensen {
27874e400768SDavid Christensen 	/* Do nothing */
27884e400768SDavid Christensen 	return ECORE_SUCCESS;
27894e400768SDavid Christensen }
27904e400768SDavid Christensen 
ecore_config_rx_mode(struct bxe_softc * sc,struct ecore_rx_mode_ramrod_params * p)27914e400768SDavid Christensen int ecore_config_rx_mode(struct bxe_softc *sc,
27924e400768SDavid Christensen 			 struct ecore_rx_mode_ramrod_params *p)
27934e400768SDavid Christensen {
27944e400768SDavid Christensen 	int rc;
27954e400768SDavid Christensen 
27964e400768SDavid Christensen 	/* Configure the new classification in the chip */
27974e400768SDavid Christensen 	rc = p->rx_mode_obj->config_rx_mode(sc, p);
27984e400768SDavid Christensen 	if (rc < 0)
27994e400768SDavid Christensen 		return rc;
28004e400768SDavid Christensen 
28014e400768SDavid Christensen 	/* Wait for a ramrod completion if was requested */
28024e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
28034e400768SDavid Christensen 		rc = p->rx_mode_obj->wait_comp(sc, p);
28044e400768SDavid Christensen 		if (rc)
28054e400768SDavid Christensen 			return rc;
28064e400768SDavid Christensen 	}
28074e400768SDavid Christensen 
28084e400768SDavid Christensen 	return rc;
28094e400768SDavid Christensen }
28104e400768SDavid Christensen 
ecore_init_rx_mode_obj(struct bxe_softc * sc,struct ecore_rx_mode_obj * o)28114e400768SDavid Christensen void ecore_init_rx_mode_obj(struct bxe_softc *sc,
28124e400768SDavid Christensen 			    struct ecore_rx_mode_obj *o)
28134e400768SDavid Christensen {
28144e400768SDavid Christensen 	if (CHIP_IS_E1x(sc)) {
28154e400768SDavid Christensen 		o->wait_comp      = ecore_empty_rx_mode_wait;
28164e400768SDavid Christensen 		o->config_rx_mode = ecore_set_rx_mode_e1x;
28174e400768SDavid Christensen 	} else {
28184e400768SDavid Christensen 		o->wait_comp      = ecore_wait_rx_mode_comp_e2;
28194e400768SDavid Christensen 		o->config_rx_mode = ecore_set_rx_mode_e2;
28204e400768SDavid Christensen 	}
28214e400768SDavid Christensen }
28224e400768SDavid Christensen 
28234e400768SDavid Christensen /********************* Multicast verbs: SET, CLEAR ****************************/
ecore_mcast_bin_from_mac(uint8_t * mac)28244e400768SDavid Christensen static inline uint8_t ecore_mcast_bin_from_mac(uint8_t *mac)
28254e400768SDavid Christensen {
28264e400768SDavid Christensen 	return (ECORE_CRC32_LE(0, mac, ETH_ALEN) >> 24) & 0xff;
28274e400768SDavid Christensen }
28284e400768SDavid Christensen 
28294e400768SDavid Christensen struct ecore_mcast_mac_elem {
28304e400768SDavid Christensen 	ecore_list_entry_t link;
28314e400768SDavid Christensen 	uint8_t mac[ETH_ALEN];
28324e400768SDavid Christensen 	uint8_t pad[2]; /* For a natural alignment of the following buffer */
28334e400768SDavid Christensen };
28344e400768SDavid Christensen 
28354e400768SDavid Christensen struct ecore_pending_mcast_cmd {
28364e400768SDavid Christensen 	ecore_list_entry_t link;
28374e400768SDavid Christensen 	int type; /* ECORE_MCAST_CMD_X */
28384e400768SDavid Christensen 	union {
28394e400768SDavid Christensen 		ecore_list_t macs_head;
28404e400768SDavid Christensen 		uint32_t macs_num; /* Needed for DEL command */
28414e400768SDavid Christensen 		int next_bin; /* Needed for RESTORE flow with aprox match */
28424e400768SDavid Christensen 	} data;
28434e400768SDavid Christensen 
28444e400768SDavid Christensen 	bool done; /* set to TRUE, when the command has been handled,
28454e400768SDavid Christensen 		    * practically used in 57712 handling only, where one pending
28464e400768SDavid Christensen 		    * command may be handled in a few operations. As long as for
28474e400768SDavid Christensen 		    * other chips every operation handling is completed in a
28484e400768SDavid Christensen 		    * single ramrod, there is no need to utilize this field.
28494e400768SDavid Christensen 		    */
28504e400768SDavid Christensen };
28514e400768SDavid Christensen 
ecore_mcast_wait(struct bxe_softc * sc,struct ecore_mcast_obj * o)28524e400768SDavid Christensen static int ecore_mcast_wait(struct bxe_softc *sc,
28534e400768SDavid Christensen 			    struct ecore_mcast_obj *o)
28544e400768SDavid Christensen {
28554e400768SDavid Christensen 	if (ecore_state_wait(sc, o->sched_state, o->raw.pstate) ||
28564e400768SDavid Christensen 			o->raw.wait_comp(sc, &o->raw))
28574e400768SDavid Christensen 		return ECORE_TIMEOUT;
28584e400768SDavid Christensen 
28594e400768SDavid Christensen 	return ECORE_SUCCESS;
28604e400768SDavid Christensen }
28614e400768SDavid Christensen 
ecore_mcast_enqueue_cmd(struct bxe_softc * sc,struct ecore_mcast_obj * o,struct ecore_mcast_ramrod_params * p,enum ecore_mcast_cmd cmd)28624e400768SDavid Christensen static int ecore_mcast_enqueue_cmd(struct bxe_softc *sc,
28634e400768SDavid Christensen 				   struct ecore_mcast_obj *o,
28644e400768SDavid Christensen 				   struct ecore_mcast_ramrod_params *p,
28654e400768SDavid Christensen 				   enum ecore_mcast_cmd cmd)
28664e400768SDavid Christensen {
28674e400768SDavid Christensen 	int total_sz;
28684e400768SDavid Christensen 	struct ecore_pending_mcast_cmd *new_cmd;
28694e400768SDavid Christensen 	struct ecore_mcast_mac_elem *cur_mac = NULL;
28704e400768SDavid Christensen 	struct ecore_mcast_list_elem *pos;
28714e400768SDavid Christensen 	int macs_list_len = ((cmd == ECORE_MCAST_CMD_ADD) ?
28724e400768SDavid Christensen 			     p->mcast_list_len : 0);
28734e400768SDavid Christensen 
28744e400768SDavid Christensen 	/* If the command is empty ("handle pending commands only"), break */
28754e400768SDavid Christensen 	if (!p->mcast_list_len)
28764e400768SDavid Christensen 		return ECORE_SUCCESS;
28774e400768SDavid Christensen 
28784e400768SDavid Christensen 	total_sz = sizeof(*new_cmd) +
28794e400768SDavid Christensen 		macs_list_len * sizeof(struct ecore_mcast_mac_elem);
28804e400768SDavid Christensen 
28814e400768SDavid Christensen 	/* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */
28824e400768SDavid Christensen 	new_cmd = ECORE_ZALLOC(total_sz, GFP_ATOMIC, sc);
28834e400768SDavid Christensen 
28844e400768SDavid Christensen 	if (!new_cmd)
28854e400768SDavid Christensen 		return ECORE_NOMEM;
28864e400768SDavid Christensen 
28875e33becaSEric Davis 	ECORE_MSG(sc, "About to enqueue a new %d command. macs_list_len=%d\n",
28884e400768SDavid Christensen 		  cmd, macs_list_len);
28894e400768SDavid Christensen 
28904e400768SDavid Christensen 	ECORE_LIST_INIT(&new_cmd->data.macs_head);
28914e400768SDavid Christensen 
28924e400768SDavid Christensen 	new_cmd->type = cmd;
28934e400768SDavid Christensen 	new_cmd->done = FALSE;
28944e400768SDavid Christensen 
28954e400768SDavid Christensen 	switch (cmd) {
28964e400768SDavid Christensen 	case ECORE_MCAST_CMD_ADD:
28974e400768SDavid Christensen 		cur_mac = (struct ecore_mcast_mac_elem *)
28984e400768SDavid Christensen 			  ((uint8_t *)new_cmd + sizeof(*new_cmd));
28994e400768SDavid Christensen 
29004e400768SDavid Christensen 		/* Push the MACs of the current command into the pending command
29014e400768SDavid Christensen 		 * MACs list: FIFO
29024e400768SDavid Christensen 		 */
29034e400768SDavid Christensen 		ECORE_LIST_FOR_EACH_ENTRY(pos, &p->mcast_list, link,
29044e400768SDavid Christensen 					  struct ecore_mcast_list_elem) {
29054e400768SDavid Christensen 			ECORE_MEMCPY(cur_mac->mac, pos->mac, ETH_ALEN);
29064e400768SDavid Christensen 			ECORE_LIST_PUSH_TAIL(&cur_mac->link,
29074e400768SDavid Christensen 					     &new_cmd->data.macs_head);
29084e400768SDavid Christensen 			cur_mac++;
29094e400768SDavid Christensen 		}
29104e400768SDavid Christensen 
29114e400768SDavid Christensen 		break;
29124e400768SDavid Christensen 
29134e400768SDavid Christensen 	case ECORE_MCAST_CMD_DEL:
29144e400768SDavid Christensen 		new_cmd->data.macs_num = p->mcast_list_len;
29154e400768SDavid Christensen 		break;
29164e400768SDavid Christensen 
29174e400768SDavid Christensen 	case ECORE_MCAST_CMD_RESTORE:
29184e400768SDavid Christensen 		new_cmd->data.next_bin = 0;
29194e400768SDavid Christensen 		break;
29204e400768SDavid Christensen 
29214e400768SDavid Christensen 	default:
29224e400768SDavid Christensen 		ECORE_FREE(sc, new_cmd, total_sz);
29234e400768SDavid Christensen 		ECORE_ERR("Unknown command: %d\n", cmd);
29244e400768SDavid Christensen 		return ECORE_INVAL;
29254e400768SDavid Christensen 	}
29264e400768SDavid Christensen 
29274e400768SDavid Christensen 	/* Push the new pending command to the tail of the pending list: FIFO */
29284e400768SDavid Christensen 	ECORE_LIST_PUSH_TAIL(&new_cmd->link, &o->pending_cmds_head);
29294e400768SDavid Christensen 
29304e400768SDavid Christensen 	o->set_sched(o);
29314e400768SDavid Christensen 
29324e400768SDavid Christensen 	return ECORE_PENDING;
29334e400768SDavid Christensen }
29344e400768SDavid Christensen 
29354e400768SDavid Christensen /**
29364e400768SDavid Christensen  * ecore_mcast_get_next_bin - get the next set bin (index)
29374e400768SDavid Christensen  *
29384e400768SDavid Christensen  * @o:
29394e400768SDavid Christensen  * @last:	index to start looking from (including)
29404e400768SDavid Christensen  *
29414e400768SDavid Christensen  * returns the next found (set) bin or a negative value if none is found.
29424e400768SDavid Christensen  */
ecore_mcast_get_next_bin(struct ecore_mcast_obj * o,int last)29434e400768SDavid Christensen static inline int ecore_mcast_get_next_bin(struct ecore_mcast_obj *o, int last)
29444e400768SDavid Christensen {
29454e400768SDavid Christensen 	int i, j, inner_start = last % BIT_VEC64_ELEM_SZ;
29464e400768SDavid Christensen 
29474e400768SDavid Christensen 	for (i = last / BIT_VEC64_ELEM_SZ; i < ECORE_MCAST_VEC_SZ; i++) {
29484e400768SDavid Christensen 		if (o->registry.aprox_match.vec[i])
29494e400768SDavid Christensen 			for (j = inner_start; j < BIT_VEC64_ELEM_SZ; j++) {
29504e400768SDavid Christensen 				int cur_bit = j + BIT_VEC64_ELEM_SZ * i;
29514e400768SDavid Christensen 				if (BIT_VEC64_TEST_BIT(o->registry.aprox_match.
29524e400768SDavid Christensen 						       vec, cur_bit)) {
29534e400768SDavid Christensen 					return cur_bit;
29544e400768SDavid Christensen 				}
29554e400768SDavid Christensen 			}
29564e400768SDavid Christensen 		inner_start = 0;
29574e400768SDavid Christensen 	}
29584e400768SDavid Christensen 
29594e400768SDavid Christensen 	/* None found */
29604e400768SDavid Christensen 	return -1;
29614e400768SDavid Christensen }
29624e400768SDavid Christensen 
29634e400768SDavid Christensen /**
29644e400768SDavid Christensen  * ecore_mcast_clear_first_bin - find the first set bin and clear it
29654e400768SDavid Christensen  *
29664e400768SDavid Christensen  * @o:
29674e400768SDavid Christensen  *
29684e400768SDavid Christensen  * returns the index of the found bin or -1 if none is found
29694e400768SDavid Christensen  */
ecore_mcast_clear_first_bin(struct ecore_mcast_obj * o)29704e400768SDavid Christensen static inline int ecore_mcast_clear_first_bin(struct ecore_mcast_obj *o)
29714e400768SDavid Christensen {
29724e400768SDavid Christensen 	int cur_bit = ecore_mcast_get_next_bin(o, 0);
29734e400768SDavid Christensen 
29744e400768SDavid Christensen 	if (cur_bit >= 0)
29754e400768SDavid Christensen 		BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, cur_bit);
29764e400768SDavid Christensen 
29774e400768SDavid Christensen 	return cur_bit;
29784e400768SDavid Christensen }
29794e400768SDavid Christensen 
ecore_mcast_get_rx_tx_flag(struct ecore_mcast_obj * o)29804e400768SDavid Christensen static inline uint8_t ecore_mcast_get_rx_tx_flag(struct ecore_mcast_obj *o)
29814e400768SDavid Christensen {
29824e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
29834e400768SDavid Christensen 	uint8_t rx_tx_flag = 0;
29844e400768SDavid Christensen 
29854e400768SDavid Christensen 	if ((raw->obj_type == ECORE_OBJ_TYPE_TX) ||
29864e400768SDavid Christensen 	    (raw->obj_type == ECORE_OBJ_TYPE_RX_TX))
29874e400768SDavid Christensen 		rx_tx_flag |= ETH_MULTICAST_RULES_CMD_TX_CMD;
29884e400768SDavid Christensen 
29894e400768SDavid Christensen 	if ((raw->obj_type == ECORE_OBJ_TYPE_RX) ||
29904e400768SDavid Christensen 	    (raw->obj_type == ECORE_OBJ_TYPE_RX_TX))
29914e400768SDavid Christensen 		rx_tx_flag |= ETH_MULTICAST_RULES_CMD_RX_CMD;
29924e400768SDavid Christensen 
29934e400768SDavid Christensen 	return rx_tx_flag;
29944e400768SDavid Christensen }
29954e400768SDavid Christensen 
ecore_mcast_set_one_rule_e2(struct bxe_softc * sc,struct ecore_mcast_obj * o,int idx,union ecore_mcast_config_data * cfg_data,enum ecore_mcast_cmd cmd)29964e400768SDavid Christensen static void ecore_mcast_set_one_rule_e2(struct bxe_softc *sc,
29974e400768SDavid Christensen 					struct ecore_mcast_obj *o, int idx,
29984e400768SDavid Christensen 					union ecore_mcast_config_data *cfg_data,
29994e400768SDavid Christensen 					enum ecore_mcast_cmd cmd)
30004e400768SDavid Christensen {
30014e400768SDavid Christensen 	struct ecore_raw_obj *r = &o->raw;
30024e400768SDavid Christensen 	struct eth_multicast_rules_ramrod_data *data =
30034e400768SDavid Christensen 		(struct eth_multicast_rules_ramrod_data *)(r->rdata);
30044e400768SDavid Christensen 	uint8_t func_id = r->func_id;
30054e400768SDavid Christensen 	uint8_t rx_tx_add_flag = ecore_mcast_get_rx_tx_flag(o);
30064e400768SDavid Christensen 	int bin;
30074e400768SDavid Christensen 
30084e400768SDavid Christensen 	if ((cmd == ECORE_MCAST_CMD_ADD) || (cmd == ECORE_MCAST_CMD_RESTORE))
30094e400768SDavid Christensen 		rx_tx_add_flag |= ETH_MULTICAST_RULES_CMD_IS_ADD;
30104e400768SDavid Christensen 
30114e400768SDavid Christensen 	data->rules[idx].cmd_general_data |= rx_tx_add_flag;
30124e400768SDavid Christensen 
30134e400768SDavid Christensen 	/* Get a bin and update a bins' vector */
30144e400768SDavid Christensen 	switch (cmd) {
30154e400768SDavid Christensen 	case ECORE_MCAST_CMD_ADD:
30164e400768SDavid Christensen 		bin = ecore_mcast_bin_from_mac(cfg_data->mac);
30174e400768SDavid Christensen 		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin);
30184e400768SDavid Christensen 		break;
30194e400768SDavid Christensen 
30204e400768SDavid Christensen 	case ECORE_MCAST_CMD_DEL:
30214e400768SDavid Christensen 		/* If there were no more bins to clear
30224e400768SDavid Christensen 		 * (ecore_mcast_clear_first_bin() returns -1) then we would
30234e400768SDavid Christensen 		 * clear any (0xff) bin.
30244e400768SDavid Christensen 		 * See ecore_mcast_validate_e2() for explanation when it may
30254e400768SDavid Christensen 		 * happen.
30264e400768SDavid Christensen 		 */
30274e400768SDavid Christensen 		bin = ecore_mcast_clear_first_bin(o);
30284e400768SDavid Christensen 		break;
30294e400768SDavid Christensen 
30304e400768SDavid Christensen 	case ECORE_MCAST_CMD_RESTORE:
30314e400768SDavid Christensen 		bin = cfg_data->bin;
30324e400768SDavid Christensen 		break;
30334e400768SDavid Christensen 
30344e400768SDavid Christensen 	default:
30354e400768SDavid Christensen 		ECORE_ERR("Unknown command: %d\n", cmd);
30364e400768SDavid Christensen 		return;
30374e400768SDavid Christensen 	}
30384e400768SDavid Christensen 
30394e400768SDavid Christensen 	ECORE_MSG(sc, "%s bin %d\n",
30404e400768SDavid Christensen 		  ((rx_tx_add_flag & ETH_MULTICAST_RULES_CMD_IS_ADD) ?
30414e400768SDavid Christensen 		   "Setting"  : "Clearing"), bin);
30424e400768SDavid Christensen 
30434e400768SDavid Christensen 	data->rules[idx].bin_id    = (uint8_t)bin;
30444e400768SDavid Christensen 	data->rules[idx].func_id   = func_id;
30454e400768SDavid Christensen 	data->rules[idx].engine_id = o->engine_id;
30464e400768SDavid Christensen }
30474e400768SDavid Christensen 
30484e400768SDavid Christensen /**
30494e400768SDavid Christensen  * ecore_mcast_handle_restore_cmd_e2 - restore configuration from the registry
30504e400768SDavid Christensen  *
30514e400768SDavid Christensen  * @sc:		device handle
30524e400768SDavid Christensen  * @o:
30534e400768SDavid Christensen  * @start_bin:	index in the registry to start from (including)
30544e400768SDavid Christensen  * @rdata_idx:	index in the ramrod data to start from
30554e400768SDavid Christensen  *
30564e400768SDavid Christensen  * returns last handled bin index or -1 if all bins have been handled
30574e400768SDavid Christensen  */
ecore_mcast_handle_restore_cmd_e2(struct bxe_softc * sc,struct ecore_mcast_obj * o,int start_bin,int * rdata_idx)30584e400768SDavid Christensen static inline int ecore_mcast_handle_restore_cmd_e2(
30594e400768SDavid Christensen 	struct bxe_softc *sc, struct ecore_mcast_obj *o , int start_bin,
30604e400768SDavid Christensen 	int *rdata_idx)
30614e400768SDavid Christensen {
30624e400768SDavid Christensen 	int cur_bin, cnt = *rdata_idx;
30634e400768SDavid Christensen 	union ecore_mcast_config_data cfg_data = {NULL};
30644e400768SDavid Christensen 
30654e400768SDavid Christensen 	/* go through the registry and configure the bins from it */
30664e400768SDavid Christensen 	for (cur_bin = ecore_mcast_get_next_bin(o, start_bin); cur_bin >= 0;
30674e400768SDavid Christensen 	    cur_bin = ecore_mcast_get_next_bin(o, cur_bin + 1)) {
30684e400768SDavid Christensen 
30694e400768SDavid Christensen 		cfg_data.bin = (uint8_t)cur_bin;
30704e400768SDavid Christensen 		o->set_one_rule(sc, o, cnt, &cfg_data,
30714e400768SDavid Christensen 				ECORE_MCAST_CMD_RESTORE);
30724e400768SDavid Christensen 
30734e400768SDavid Christensen 		cnt++;
30744e400768SDavid Christensen 
30754e400768SDavid Christensen 		ECORE_MSG(sc, "About to configure a bin %d\n", cur_bin);
30764e400768SDavid Christensen 
30774e400768SDavid Christensen 		/* Break if we reached the maximum number
30784e400768SDavid Christensen 		 * of rules.
30794e400768SDavid Christensen 		 */
30804e400768SDavid Christensen 		if (cnt >= o->max_cmd_len)
30814e400768SDavid Christensen 			break;
30824e400768SDavid Christensen 	}
30834e400768SDavid Christensen 
30844e400768SDavid Christensen 	*rdata_idx = cnt;
30854e400768SDavid Christensen 
30864e400768SDavid Christensen 	return cur_bin;
30874e400768SDavid Christensen }
30884e400768SDavid Christensen 
ecore_mcast_hdl_pending_add_e2(struct bxe_softc * sc,struct ecore_mcast_obj * o,struct ecore_pending_mcast_cmd * cmd_pos,int * line_idx)30894e400768SDavid Christensen static inline void ecore_mcast_hdl_pending_add_e2(struct bxe_softc *sc,
30904e400768SDavid Christensen 	struct ecore_mcast_obj *o, struct ecore_pending_mcast_cmd *cmd_pos,
30914e400768SDavid Christensen 	int *line_idx)
30924e400768SDavid Christensen {
30934e400768SDavid Christensen 	struct ecore_mcast_mac_elem *pmac_pos, *pmac_pos_n;
30944e400768SDavid Christensen 	int cnt = *line_idx;
30954e400768SDavid Christensen 	union ecore_mcast_config_data cfg_data = {NULL};
30964e400768SDavid Christensen 
30974e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY_SAFE(pmac_pos, pmac_pos_n,
30984e400768SDavid Christensen 		&cmd_pos->data.macs_head, link, struct ecore_mcast_mac_elem) {
30994e400768SDavid Christensen 
31004e400768SDavid Christensen 		cfg_data.mac = &pmac_pos->mac[0];
31014e400768SDavid Christensen 		o->set_one_rule(sc, o, cnt, &cfg_data, cmd_pos->type);
31024e400768SDavid Christensen 
31034e400768SDavid Christensen 		cnt++;
31044e400768SDavid Christensen 
31054e400768SDavid Christensen 		ECORE_MSG(sc, "About to configure %02x:%02x:%02x:%02x:%02x:%02x mcast MAC\n",
31064e400768SDavid Christensen 			  pmac_pos->mac[0], pmac_pos->mac[1], pmac_pos->mac[2], pmac_pos->mac[3], pmac_pos->mac[4], pmac_pos->mac[5]);
31074e400768SDavid Christensen 
31084e400768SDavid Christensen 		ECORE_LIST_REMOVE_ENTRY(&pmac_pos->link,
31094e400768SDavid Christensen 					&cmd_pos->data.macs_head);
31104e400768SDavid Christensen 
31114e400768SDavid Christensen 		/* Break if we reached the maximum number
31124e400768SDavid Christensen 		 * of rules.
31134e400768SDavid Christensen 		 */
31144e400768SDavid Christensen 		if (cnt >= o->max_cmd_len)
31154e400768SDavid Christensen 			break;
31164e400768SDavid Christensen 	}
31174e400768SDavid Christensen 
31184e400768SDavid Christensen 	*line_idx = cnt;
31194e400768SDavid Christensen 
31204e400768SDavid Christensen 	/* if no more MACs to configure - we are done */
31214e400768SDavid Christensen 	if (ECORE_LIST_IS_EMPTY(&cmd_pos->data.macs_head))
31224e400768SDavid Christensen 		cmd_pos->done = TRUE;
31234e400768SDavid Christensen }
31244e400768SDavid Christensen 
ecore_mcast_hdl_pending_del_e2(struct bxe_softc * sc,struct ecore_mcast_obj * o,struct ecore_pending_mcast_cmd * cmd_pos,int * line_idx)31254e400768SDavid Christensen static inline void ecore_mcast_hdl_pending_del_e2(struct bxe_softc *sc,
31264e400768SDavid Christensen 	struct ecore_mcast_obj *o, struct ecore_pending_mcast_cmd *cmd_pos,
31274e400768SDavid Christensen 	int *line_idx)
31284e400768SDavid Christensen {
31294e400768SDavid Christensen 	int cnt = *line_idx;
31304e400768SDavid Christensen 
31314e400768SDavid Christensen 	while (cmd_pos->data.macs_num) {
31324e400768SDavid Christensen 		o->set_one_rule(sc, o, cnt, NULL, cmd_pos->type);
31334e400768SDavid Christensen 
31344e400768SDavid Christensen 		cnt++;
31354e400768SDavid Christensen 
31364e400768SDavid Christensen 		cmd_pos->data.macs_num--;
31374e400768SDavid Christensen 
31384e400768SDavid Christensen 		  ECORE_MSG(sc, "Deleting MAC. %d left,cnt is %d\n",
31394e400768SDavid Christensen 				  cmd_pos->data.macs_num, cnt);
31404e400768SDavid Christensen 
31414e400768SDavid Christensen 		/* Break if we reached the maximum
31424e400768SDavid Christensen 		 * number of rules.
31434e400768SDavid Christensen 		 */
31444e400768SDavid Christensen 		if (cnt >= o->max_cmd_len)
31454e400768SDavid Christensen 			break;
31464e400768SDavid Christensen 	}
31474e400768SDavid Christensen 
31484e400768SDavid Christensen 	*line_idx = cnt;
31494e400768SDavid Christensen 
31504e400768SDavid Christensen 	/* If we cleared all bins - we are done */
31514e400768SDavid Christensen 	if (!cmd_pos->data.macs_num)
31524e400768SDavid Christensen 		cmd_pos->done = TRUE;
31534e400768SDavid Christensen }
31544e400768SDavid Christensen 
ecore_mcast_hdl_pending_restore_e2(struct bxe_softc * sc,struct ecore_mcast_obj * o,struct ecore_pending_mcast_cmd * cmd_pos,int * line_idx)31554e400768SDavid Christensen static inline void ecore_mcast_hdl_pending_restore_e2(struct bxe_softc *sc,
31564e400768SDavid Christensen 	struct ecore_mcast_obj *o, struct ecore_pending_mcast_cmd *cmd_pos,
31574e400768SDavid Christensen 	int *line_idx)
31584e400768SDavid Christensen {
31594e400768SDavid Christensen 	cmd_pos->data.next_bin = o->hdl_restore(sc, o, cmd_pos->data.next_bin,
31604e400768SDavid Christensen 						line_idx);
31614e400768SDavid Christensen 
31624e400768SDavid Christensen 	if (cmd_pos->data.next_bin < 0)
31634e400768SDavid Christensen 		/* If o->set_restore returned -1 we are done */
31644e400768SDavid Christensen 		cmd_pos->done = TRUE;
31654e400768SDavid Christensen 	else
31664e400768SDavid Christensen 		/* Start from the next bin next time */
31674e400768SDavid Christensen 		cmd_pos->data.next_bin++;
31684e400768SDavid Christensen }
31694e400768SDavid Christensen 
ecore_mcast_handle_pending_cmds_e2(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p)31704e400768SDavid Christensen static inline int ecore_mcast_handle_pending_cmds_e2(struct bxe_softc *sc,
31714e400768SDavid Christensen 				struct ecore_mcast_ramrod_params *p)
31724e400768SDavid Christensen {
31734e400768SDavid Christensen 	struct ecore_pending_mcast_cmd *cmd_pos, *cmd_pos_n;
31744e400768SDavid Christensen 	int cnt = 0;
31754e400768SDavid Christensen 	struct ecore_mcast_obj *o = p->mcast_obj;
31764e400768SDavid Christensen 
31774e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY_SAFE(cmd_pos, cmd_pos_n,
31784e400768SDavid Christensen 		&o->pending_cmds_head, link, struct ecore_pending_mcast_cmd) {
31794e400768SDavid Christensen 		switch (cmd_pos->type) {
31804e400768SDavid Christensen 		case ECORE_MCAST_CMD_ADD:
31814e400768SDavid Christensen 			ecore_mcast_hdl_pending_add_e2(sc, o, cmd_pos, &cnt);
31824e400768SDavid Christensen 			break;
31834e400768SDavid Christensen 
31844e400768SDavid Christensen 		case ECORE_MCAST_CMD_DEL:
31854e400768SDavid Christensen 			ecore_mcast_hdl_pending_del_e2(sc, o, cmd_pos, &cnt);
31864e400768SDavid Christensen 			break;
31874e400768SDavid Christensen 
31884e400768SDavid Christensen 		case ECORE_MCAST_CMD_RESTORE:
31894e400768SDavid Christensen 			ecore_mcast_hdl_pending_restore_e2(sc, o, cmd_pos,
31904e400768SDavid Christensen 							   &cnt);
31914e400768SDavid Christensen 			break;
31924e400768SDavid Christensen 
31934e400768SDavid Christensen 		default:
31944e400768SDavid Christensen 			ECORE_ERR("Unknown command: %d\n", cmd_pos->type);
31954e400768SDavid Christensen 			return ECORE_INVAL;
31964e400768SDavid Christensen 		}
31974e400768SDavid Christensen 
31984e400768SDavid Christensen 		/* If the command has been completed - remove it from the list
31994e400768SDavid Christensen 		 * and free the memory
32004e400768SDavid Christensen 		 */
32014e400768SDavid Christensen 		if (cmd_pos->done) {
32024e400768SDavid Christensen 			ECORE_LIST_REMOVE_ENTRY(&cmd_pos->link,
32034e400768SDavid Christensen 						&o->pending_cmds_head);
32044e400768SDavid Christensen 			ECORE_FREE(sc, cmd_pos, cmd_pos->alloc_len);
32054e400768SDavid Christensen 		}
32064e400768SDavid Christensen 
32074e400768SDavid Christensen 		/* Break if we reached the maximum number of rules */
32084e400768SDavid Christensen 		if (cnt >= o->max_cmd_len)
32094e400768SDavid Christensen 			break;
32104e400768SDavid Christensen 	}
32114e400768SDavid Christensen 
32124e400768SDavid Christensen 	return cnt;
32134e400768SDavid Christensen }
32144e400768SDavid Christensen 
ecore_mcast_hdl_add(struct bxe_softc * sc,struct ecore_mcast_obj * o,struct ecore_mcast_ramrod_params * p,int * line_idx)32154e400768SDavid Christensen static inline void ecore_mcast_hdl_add(struct bxe_softc *sc,
32164e400768SDavid Christensen 	struct ecore_mcast_obj *o, struct ecore_mcast_ramrod_params *p,
32174e400768SDavid Christensen 	int *line_idx)
32184e400768SDavid Christensen {
32194e400768SDavid Christensen 	struct ecore_mcast_list_elem *mlist_pos;
32204e400768SDavid Christensen 	union ecore_mcast_config_data cfg_data = {NULL};
32214e400768SDavid Christensen 	int cnt = *line_idx;
32224e400768SDavid Christensen 
32234e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(mlist_pos, &p->mcast_list, link,
32244e400768SDavid Christensen 				  struct ecore_mcast_list_elem) {
32254e400768SDavid Christensen 		cfg_data.mac = mlist_pos->mac;
32264e400768SDavid Christensen 		o->set_one_rule(sc, o, cnt, &cfg_data, ECORE_MCAST_CMD_ADD);
32274e400768SDavid Christensen 
32284e400768SDavid Christensen 		cnt++;
32294e400768SDavid Christensen 
32304e400768SDavid Christensen 		ECORE_MSG(sc, "About to configure %02x:%02x:%02x:%02x:%02x:%02x mcast MAC\n",
32314e400768SDavid Christensen 			  mlist_pos->mac[0], mlist_pos->mac[1], mlist_pos->mac[2], mlist_pos->mac[3], mlist_pos->mac[4], mlist_pos->mac[5]);
32324e400768SDavid Christensen 	}
32334e400768SDavid Christensen 
32344e400768SDavid Christensen 	*line_idx = cnt;
32354e400768SDavid Christensen }
32364e400768SDavid Christensen 
ecore_mcast_hdl_del(struct bxe_softc * sc,struct ecore_mcast_obj * o,struct ecore_mcast_ramrod_params * p,int * line_idx)32374e400768SDavid Christensen static inline void ecore_mcast_hdl_del(struct bxe_softc *sc,
32384e400768SDavid Christensen 	struct ecore_mcast_obj *o, struct ecore_mcast_ramrod_params *p,
32394e400768SDavid Christensen 	int *line_idx)
32404e400768SDavid Christensen {
32414e400768SDavid Christensen 	int cnt = *line_idx, i;
32424e400768SDavid Christensen 
32434e400768SDavid Christensen 	for (i = 0; i < p->mcast_list_len; i++) {
32444e400768SDavid Christensen 		o->set_one_rule(sc, o, cnt, NULL, ECORE_MCAST_CMD_DEL);
32454e400768SDavid Christensen 
32464e400768SDavid Christensen 		cnt++;
32474e400768SDavid Christensen 
32484e400768SDavid Christensen 		ECORE_MSG(sc, "Deleting MAC. %d left\n",
32494e400768SDavid Christensen 			  p->mcast_list_len - i - 1);
32504e400768SDavid Christensen 	}
32514e400768SDavid Christensen 
32524e400768SDavid Christensen 	*line_idx = cnt;
32534e400768SDavid Christensen }
32544e400768SDavid Christensen 
32554e400768SDavid Christensen /**
32564e400768SDavid Christensen  * ecore_mcast_handle_current_cmd -
32574e400768SDavid Christensen  *
32584e400768SDavid Christensen  * @sc:		device handle
32594e400768SDavid Christensen  * @p:
32604e400768SDavid Christensen  * @cmd:
32614e400768SDavid Christensen  * @start_cnt:	first line in the ramrod data that may be used
32624e400768SDavid Christensen  *
32634e400768SDavid Christensen  * This function is called iff there is enough place for the current command in
32644e400768SDavid Christensen  * the ramrod data.
32654e400768SDavid Christensen  * Returns number of lines filled in the ramrod data in total.
32664e400768SDavid Christensen  */
ecore_mcast_handle_current_cmd(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,enum ecore_mcast_cmd cmd,int start_cnt)32674e400768SDavid Christensen static inline int ecore_mcast_handle_current_cmd(struct bxe_softc *sc,
32684e400768SDavid Christensen 			struct ecore_mcast_ramrod_params *p,
32694e400768SDavid Christensen 			enum ecore_mcast_cmd cmd,
32704e400768SDavid Christensen 			int start_cnt)
32714e400768SDavid Christensen {
32724e400768SDavid Christensen 	struct ecore_mcast_obj *o = p->mcast_obj;
32734e400768SDavid Christensen 	int cnt = start_cnt;
32744e400768SDavid Christensen 
32754e400768SDavid Christensen 	ECORE_MSG(sc, "p->mcast_list_len=%d\n", p->mcast_list_len);
32764e400768SDavid Christensen 
32774e400768SDavid Christensen 	switch (cmd) {
32784e400768SDavid Christensen 	case ECORE_MCAST_CMD_ADD:
32794e400768SDavid Christensen 		ecore_mcast_hdl_add(sc, o, p, &cnt);
32804e400768SDavid Christensen 		break;
32814e400768SDavid Christensen 
32824e400768SDavid Christensen 	case ECORE_MCAST_CMD_DEL:
32834e400768SDavid Christensen 		ecore_mcast_hdl_del(sc, o, p, &cnt);
32844e400768SDavid Christensen 		break;
32854e400768SDavid Christensen 
32864e400768SDavid Christensen 	case ECORE_MCAST_CMD_RESTORE:
32874e400768SDavid Christensen 		o->hdl_restore(sc, o, 0, &cnt);
32884e400768SDavid Christensen 		break;
32894e400768SDavid Christensen 
32904e400768SDavid Christensen 	default:
32914e400768SDavid Christensen 		ECORE_ERR("Unknown command: %d\n", cmd);
32924e400768SDavid Christensen 		return ECORE_INVAL;
32934e400768SDavid Christensen 	}
32944e400768SDavid Christensen 
32954e400768SDavid Christensen 	/* The current command has been handled */
32964e400768SDavid Christensen 	p->mcast_list_len = 0;
32974e400768SDavid Christensen 
32984e400768SDavid Christensen 	return cnt;
32994e400768SDavid Christensen }
33004e400768SDavid Christensen 
ecore_mcast_validate_e2(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,enum ecore_mcast_cmd cmd)33014e400768SDavid Christensen static int ecore_mcast_validate_e2(struct bxe_softc *sc,
33024e400768SDavid Christensen 				   struct ecore_mcast_ramrod_params *p,
33034e400768SDavid Christensen 				   enum ecore_mcast_cmd cmd)
33044e400768SDavid Christensen {
33054e400768SDavid Christensen 	struct ecore_mcast_obj *o = p->mcast_obj;
33064e400768SDavid Christensen 	int reg_sz = o->get_registry_size(o);
33074e400768SDavid Christensen 
33084e400768SDavid Christensen 	switch (cmd) {
33094e400768SDavid Christensen 	/* DEL command deletes all currently configured MACs */
33104e400768SDavid Christensen 	case ECORE_MCAST_CMD_DEL:
33114e400768SDavid Christensen 		o->set_registry_size(o, 0);
33124e400768SDavid Christensen 		/* Don't break */
33134e400768SDavid Christensen 
33144e400768SDavid Christensen 	/* RESTORE command will restore the entire multicast configuration */
33154e400768SDavid Christensen 	case ECORE_MCAST_CMD_RESTORE:
33164e400768SDavid Christensen 		/* Here we set the approximate amount of work to do, which in
33174e400768SDavid Christensen 		 * fact may be only less as some MACs in postponed ADD
33184e400768SDavid Christensen 		 * command(s) scheduled before this command may fall into
33194e400768SDavid Christensen 		 * the same bin and the actual number of bins set in the
33204e400768SDavid Christensen 		 * registry would be less than we estimated here. See
33214e400768SDavid Christensen 		 * ecore_mcast_set_one_rule_e2() for further details.
33224e400768SDavid Christensen 		 */
33234e400768SDavid Christensen 		p->mcast_list_len = reg_sz;
33244e400768SDavid Christensen 		break;
33254e400768SDavid Christensen 
33264e400768SDavid Christensen 	case ECORE_MCAST_CMD_ADD:
33274e400768SDavid Christensen 	case ECORE_MCAST_CMD_CONT:
33284e400768SDavid Christensen 		/* Here we assume that all new MACs will fall into new bins.
33294e400768SDavid Christensen 		 * However we will correct the real registry size after we
33304e400768SDavid Christensen 		 * handle all pending commands.
33314e400768SDavid Christensen 		 */
33324e400768SDavid Christensen 		o->set_registry_size(o, reg_sz + p->mcast_list_len);
33334e400768SDavid Christensen 		break;
33344e400768SDavid Christensen 
33354e400768SDavid Christensen 	default:
33364e400768SDavid Christensen 		ECORE_ERR("Unknown command: %d\n", cmd);
33374e400768SDavid Christensen 		return ECORE_INVAL;
33384e400768SDavid Christensen 	}
33394e400768SDavid Christensen 
33404e400768SDavid Christensen 	/* Increase the total number of MACs pending to be configured */
33414e400768SDavid Christensen 	o->total_pending_num += p->mcast_list_len;
33424e400768SDavid Christensen 
33434e400768SDavid Christensen 	return ECORE_SUCCESS;
33444e400768SDavid Christensen }
33454e400768SDavid Christensen 
ecore_mcast_revert_e2(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,int old_num_bins)33464e400768SDavid Christensen static void ecore_mcast_revert_e2(struct bxe_softc *sc,
33474e400768SDavid Christensen 				      struct ecore_mcast_ramrod_params *p,
33484e400768SDavid Christensen 				      int old_num_bins)
33494e400768SDavid Christensen {
33504e400768SDavid Christensen 	struct ecore_mcast_obj *o = p->mcast_obj;
33514e400768SDavid Christensen 
33524e400768SDavid Christensen 	o->set_registry_size(o, old_num_bins);
33534e400768SDavid Christensen 	o->total_pending_num -= p->mcast_list_len;
33544e400768SDavid Christensen }
33554e400768SDavid Christensen 
33564e400768SDavid Christensen /**
33574e400768SDavid Christensen  * ecore_mcast_set_rdata_hdr_e2 - sets a header values
33584e400768SDavid Christensen  *
33594e400768SDavid Christensen  * @sc:		device handle
33604e400768SDavid Christensen  * @p:
33614e400768SDavid Christensen  * @len:	number of rules to handle
33624e400768SDavid Christensen  */
ecore_mcast_set_rdata_hdr_e2(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,uint8_t len)33634e400768SDavid Christensen static inline void ecore_mcast_set_rdata_hdr_e2(struct bxe_softc *sc,
33644e400768SDavid Christensen 					struct ecore_mcast_ramrod_params *p,
33654e400768SDavid Christensen 					uint8_t len)
33664e400768SDavid Christensen {
33674e400768SDavid Christensen 	struct ecore_raw_obj *r = &p->mcast_obj->raw;
33684e400768SDavid Christensen 	struct eth_multicast_rules_ramrod_data *data =
33694e400768SDavid Christensen 		(struct eth_multicast_rules_ramrod_data *)(r->rdata);
33704e400768SDavid Christensen 
33714e400768SDavid Christensen 	data->header.echo = ECORE_CPU_TO_LE32((r->cid & ECORE_SWCID_MASK) |
33724e400768SDavid Christensen 					(ECORE_FILTER_MCAST_PENDING <<
33734e400768SDavid Christensen 					 ECORE_SWCID_SHIFT));
33744e400768SDavid Christensen 	data->header.rule_cnt = len;
33754e400768SDavid Christensen }
33764e400768SDavid Christensen 
33774e400768SDavid Christensen /**
33784e400768SDavid Christensen  * ecore_mcast_refresh_registry_e2 - recalculate the actual number of set bins
33794e400768SDavid Christensen  *
33804e400768SDavid Christensen  * @sc:		device handle
33814e400768SDavid Christensen  * @o:
33824e400768SDavid Christensen  *
33834e400768SDavid Christensen  * Recalculate the actual number of set bins in the registry using Brian
33844e400768SDavid Christensen  * Kernighan's algorithm: it's execution complexity is as a number of set bins.
33854e400768SDavid Christensen  *
33864e400768SDavid Christensen  * returns 0 for the compliance with ecore_mcast_refresh_registry_e1().
33874e400768SDavid Christensen  */
ecore_mcast_refresh_registry_e2(struct bxe_softc * sc,struct ecore_mcast_obj * o)33884e400768SDavid Christensen static inline int ecore_mcast_refresh_registry_e2(struct bxe_softc *sc,
33894e400768SDavid Christensen 						  struct ecore_mcast_obj *o)
33904e400768SDavid Christensen {
33914e400768SDavid Christensen 	int i, cnt = 0;
33924e400768SDavid Christensen 	uint64_t elem;
33934e400768SDavid Christensen 
33944e400768SDavid Christensen 	for (i = 0; i < ECORE_MCAST_VEC_SZ; i++) {
33954e400768SDavid Christensen 		elem = o->registry.aprox_match.vec[i];
33964e400768SDavid Christensen 		for (; elem; cnt++)
33974e400768SDavid Christensen 			elem &= elem - 1;
33984e400768SDavid Christensen 	}
33994e400768SDavid Christensen 
34004e400768SDavid Christensen 	o->set_registry_size(o, cnt);
34014e400768SDavid Christensen 
34024e400768SDavid Christensen 	return ECORE_SUCCESS;
34034e400768SDavid Christensen }
34044e400768SDavid Christensen 
ecore_mcast_setup_e2(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,enum ecore_mcast_cmd cmd)34054e400768SDavid Christensen static int ecore_mcast_setup_e2(struct bxe_softc *sc,
34064e400768SDavid Christensen 				struct ecore_mcast_ramrod_params *p,
34074e400768SDavid Christensen 				enum ecore_mcast_cmd cmd)
34084e400768SDavid Christensen {
34094e400768SDavid Christensen 	struct ecore_raw_obj *raw = &p->mcast_obj->raw;
34104e400768SDavid Christensen 	struct ecore_mcast_obj *o = p->mcast_obj;
34114e400768SDavid Christensen 	struct eth_multicast_rules_ramrod_data *data =
34124e400768SDavid Christensen 		(struct eth_multicast_rules_ramrod_data *)(raw->rdata);
34134e400768SDavid Christensen 	int cnt = 0, rc;
34144e400768SDavid Christensen 
34154e400768SDavid Christensen 	/* Reset the ramrod data buffer */
34164e400768SDavid Christensen 	ECORE_MEMSET(data, 0, sizeof(*data));
34174e400768SDavid Christensen 
34184e400768SDavid Christensen 	cnt = ecore_mcast_handle_pending_cmds_e2(sc, p);
34194e400768SDavid Christensen 
34204e400768SDavid Christensen 	/* If there are no more pending commands - clear SCHEDULED state */
34214e400768SDavid Christensen 	if (ECORE_LIST_IS_EMPTY(&o->pending_cmds_head))
34224e400768SDavid Christensen 		o->clear_sched(o);
34234e400768SDavid Christensen 
34244e400768SDavid Christensen 	/* The below may be TRUE iff there was enough room in ramrod
34254e400768SDavid Christensen 	 * data for all pending commands and for the current
34264e400768SDavid Christensen 	 * command. Otherwise the current command would have been added
34274e400768SDavid Christensen 	 * to the pending commands and p->mcast_list_len would have been
34284e400768SDavid Christensen 	 * zeroed.
34294e400768SDavid Christensen 	 */
34304e400768SDavid Christensen 	if (p->mcast_list_len > 0)
34314e400768SDavid Christensen 		cnt = ecore_mcast_handle_current_cmd(sc, p, cmd, cnt);
34324e400768SDavid Christensen 
34334e400768SDavid Christensen 	/* We've pulled out some MACs - update the total number of
34344e400768SDavid Christensen 	 * outstanding.
34354e400768SDavid Christensen 	 */
34364e400768SDavid Christensen 	o->total_pending_num -= cnt;
34374e400768SDavid Christensen 
34384e400768SDavid Christensen 	/* send a ramrod */
34394e400768SDavid Christensen 	ECORE_DBG_BREAK_IF(o->total_pending_num < 0);
34404e400768SDavid Christensen 	ECORE_DBG_BREAK_IF(cnt > o->max_cmd_len);
34414e400768SDavid Christensen 
34424e400768SDavid Christensen 	ecore_mcast_set_rdata_hdr_e2(sc, p, (uint8_t)cnt);
34434e400768SDavid Christensen 
34444e400768SDavid Christensen 	/* Update a registry size if there are no more pending operations.
34454e400768SDavid Christensen 	 *
34464e400768SDavid Christensen 	 * We don't want to change the value of the registry size if there are
34474e400768SDavid Christensen 	 * pending operations because we want it to always be equal to the
34484e400768SDavid Christensen 	 * exact or the approximate number (see ecore_mcast_validate_e2()) of
34494e400768SDavid Christensen 	 * set bins after the last requested operation in order to properly
34504e400768SDavid Christensen 	 * evaluate the size of the next DEL/RESTORE operation.
34514e400768SDavid Christensen 	 *
34524e400768SDavid Christensen 	 * Note that we update the registry itself during command(s) handling
34534e400768SDavid Christensen 	 * - see ecore_mcast_set_one_rule_e2(). That's because for 57712 we
34544e400768SDavid Christensen 	 * aggregate multiple commands (ADD/DEL/RESTORE) into one ramrod but
34554e400768SDavid Christensen 	 * with a limited amount of update commands (per MAC/bin) and we don't
34564e400768SDavid Christensen 	 * know in this scope what the actual state of bins configuration is
34574e400768SDavid Christensen 	 * going to be after this ramrod.
34584e400768SDavid Christensen 	 */
34594e400768SDavid Christensen 	if (!o->total_pending_num)
34604e400768SDavid Christensen 		ecore_mcast_refresh_registry_e2(sc, o);
34614e400768SDavid Christensen 
34624e400768SDavid Christensen 	/* If CLEAR_ONLY was requested - don't send a ramrod and clear
34634e400768SDavid Christensen 	 * RAMROD_PENDING status immediately.
34644e400768SDavid Christensen 	 */
34654e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
34664e400768SDavid Christensen 		raw->clear_pending(raw);
34674e400768SDavid Christensen 		return ECORE_SUCCESS;
34684e400768SDavid Christensen 	} else {
34694ef8ebfdSDavid C Somayajulu 		/* No need for an explicit memory barrier here as long as we
34704ef8ebfdSDavid C Somayajulu 		 * ensure the ordering of writing to the SPQ element
34714e400768SDavid Christensen 		 * and updating of the SPQ producer which involves a memory
34724ef8ebfdSDavid C Somayajulu 		 * read. If the memory read is removed we will have to put a
34734ef8ebfdSDavid C Somayajulu 		 * full memory barrier there (inside ecore_sp_post()).
34744e400768SDavid Christensen 		 */
34754e400768SDavid Christensen 
34764e400768SDavid Christensen 		/* Send a ramrod */
34774e400768SDavid Christensen 		rc = ecore_sp_post( sc,
34784e400768SDavid Christensen 				    RAMROD_CMD_ID_ETH_MULTICAST_RULES,
34794e400768SDavid Christensen 				    raw->cid,
34804e400768SDavid Christensen 				    raw->rdata_mapping,
34814e400768SDavid Christensen 				    ETH_CONNECTION_TYPE);
34824e400768SDavid Christensen 		if (rc)
34834e400768SDavid Christensen 			return rc;
34844e400768SDavid Christensen 
34854e400768SDavid Christensen 		/* Ramrod completion is pending */
34864e400768SDavid Christensen 		return ECORE_PENDING;
34874e400768SDavid Christensen 	}
34884e400768SDavid Christensen }
34894e400768SDavid Christensen 
ecore_mcast_validate_e1h(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,enum ecore_mcast_cmd cmd)34904e400768SDavid Christensen static int ecore_mcast_validate_e1h(struct bxe_softc *sc,
34914e400768SDavid Christensen 				    struct ecore_mcast_ramrod_params *p,
34924e400768SDavid Christensen 				    enum ecore_mcast_cmd cmd)
34934e400768SDavid Christensen {
34944e400768SDavid Christensen 	/* Mark, that there is a work to do */
34954e400768SDavid Christensen 	if ((cmd == ECORE_MCAST_CMD_DEL) || (cmd == ECORE_MCAST_CMD_RESTORE))
34964e400768SDavid Christensen 		p->mcast_list_len = 1;
34974e400768SDavid Christensen 
34984e400768SDavid Christensen 	return ECORE_SUCCESS;
34994e400768SDavid Christensen }
35004e400768SDavid Christensen 
ecore_mcast_revert_e1h(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,int old_num_bins)35014e400768SDavid Christensen static void ecore_mcast_revert_e1h(struct bxe_softc *sc,
35024e400768SDavid Christensen 				       struct ecore_mcast_ramrod_params *p,
35034e400768SDavid Christensen 				       int old_num_bins)
35044e400768SDavid Christensen {
35054e400768SDavid Christensen 	/* Do nothing */
35064e400768SDavid Christensen }
35074e400768SDavid Christensen 
35084e400768SDavid Christensen #define ECORE_57711_SET_MC_FILTER(filter, bit) \
35094e400768SDavid Christensen do { \
35104e400768SDavid Christensen 	(filter)[(bit) >> 5] |= (1 << ((bit) & 0x1f)); \
35114e400768SDavid Christensen } while (0)
35124e400768SDavid Christensen 
ecore_mcast_hdl_add_e1h(struct bxe_softc * sc,struct ecore_mcast_obj * o,struct ecore_mcast_ramrod_params * p,uint32_t * mc_filter)35134e400768SDavid Christensen static inline void ecore_mcast_hdl_add_e1h(struct bxe_softc *sc,
35144e400768SDavid Christensen 					   struct ecore_mcast_obj *o,
35154e400768SDavid Christensen 					   struct ecore_mcast_ramrod_params *p,
35164e400768SDavid Christensen 					   uint32_t *mc_filter)
35174e400768SDavid Christensen {
35184e400768SDavid Christensen 	struct ecore_mcast_list_elem *mlist_pos;
35194e400768SDavid Christensen 	int bit;
35204e400768SDavid Christensen 
35214e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(mlist_pos, &p->mcast_list, link,
35224e400768SDavid Christensen 				  struct ecore_mcast_list_elem) {
35234e400768SDavid Christensen 		bit = ecore_mcast_bin_from_mac(mlist_pos->mac);
35244e400768SDavid Christensen 		ECORE_57711_SET_MC_FILTER(mc_filter, bit);
35254e400768SDavid Christensen 
35264e400768SDavid Christensen 		ECORE_MSG(sc, "About to configure %02x:%02x:%02x:%02x:%02x:%02x mcast MAC, bin %d\n",
35274e400768SDavid Christensen 			  mlist_pos->mac[0], mlist_pos->mac[1], mlist_pos->mac[2], mlist_pos->mac[3], mlist_pos->mac[4], mlist_pos->mac[5], bit);
35284e400768SDavid Christensen 
35294e400768SDavid Christensen 		/* bookkeeping... */
35304e400768SDavid Christensen 		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec,
35314e400768SDavid Christensen 				  bit);
35324e400768SDavid Christensen 	}
35334e400768SDavid Christensen }
35344e400768SDavid Christensen 
ecore_mcast_hdl_restore_e1h(struct bxe_softc * sc,struct ecore_mcast_obj * o,struct ecore_mcast_ramrod_params * p,uint32_t * mc_filter)35354e400768SDavid Christensen static inline void ecore_mcast_hdl_restore_e1h(struct bxe_softc *sc,
35364e400768SDavid Christensen 	struct ecore_mcast_obj *o, struct ecore_mcast_ramrod_params *p,
35374e400768SDavid Christensen 	uint32_t *mc_filter)
35384e400768SDavid Christensen {
35394e400768SDavid Christensen 	int bit;
35404e400768SDavid Christensen 
35414e400768SDavid Christensen 	for (bit = ecore_mcast_get_next_bin(o, 0);
35424e400768SDavid Christensen 	     bit >= 0;
35434e400768SDavid Christensen 	     bit = ecore_mcast_get_next_bin(o, bit + 1)) {
35444e400768SDavid Christensen 		ECORE_57711_SET_MC_FILTER(mc_filter, bit);
35454e400768SDavid Christensen 		ECORE_MSG(sc, "About to set bin %d\n", bit);
35464e400768SDavid Christensen 	}
35474e400768SDavid Christensen }
35484e400768SDavid Christensen 
35494e400768SDavid Christensen /* On 57711 we write the multicast MACs' approximate match
35504e400768SDavid Christensen  * table by directly into the TSTORM's internal RAM. So we don't
35514e400768SDavid Christensen  * really need to handle any tricks to make it work.
35524e400768SDavid Christensen  */
ecore_mcast_setup_e1h(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,enum ecore_mcast_cmd cmd)35534e400768SDavid Christensen static int ecore_mcast_setup_e1h(struct bxe_softc *sc,
35544e400768SDavid Christensen 				 struct ecore_mcast_ramrod_params *p,
35554e400768SDavid Christensen 				 enum ecore_mcast_cmd cmd)
35564e400768SDavid Christensen {
35574e400768SDavid Christensen 	int i;
35584e400768SDavid Christensen 	struct ecore_mcast_obj *o = p->mcast_obj;
35594e400768SDavid Christensen 	struct ecore_raw_obj *r = &o->raw;
35604e400768SDavid Christensen 
35614e400768SDavid Christensen 	/* If CLEAR_ONLY has been requested - clear the registry
35624e400768SDavid Christensen 	 * and clear a pending bit.
35634e400768SDavid Christensen 	 */
35644e400768SDavid Christensen 	if (!ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
35654e400768SDavid Christensen 		uint32_t mc_filter[ECORE_MC_HASH_SIZE] = {0};
35664e400768SDavid Christensen 
35674e400768SDavid Christensen 		/* Set the multicast filter bits before writing it into
35684e400768SDavid Christensen 		 * the internal memory.
35694e400768SDavid Christensen 		 */
35704e400768SDavid Christensen 		switch (cmd) {
35714e400768SDavid Christensen 		case ECORE_MCAST_CMD_ADD:
35724e400768SDavid Christensen 			ecore_mcast_hdl_add_e1h(sc, o, p, mc_filter);
35734e400768SDavid Christensen 			break;
35744e400768SDavid Christensen 
35754e400768SDavid Christensen 		case ECORE_MCAST_CMD_DEL:
35764e400768SDavid Christensen 			ECORE_MSG(sc,
35774e400768SDavid Christensen 				  "Invalidating multicast MACs configuration\n");
35784e400768SDavid Christensen 
35794e400768SDavid Christensen 			/* clear the registry */
35804e400768SDavid Christensen 			ECORE_MEMSET(o->registry.aprox_match.vec, 0,
35814e400768SDavid Christensen 			       sizeof(o->registry.aprox_match.vec));
35824e400768SDavid Christensen 			break;
35834e400768SDavid Christensen 
35844e400768SDavid Christensen 		case ECORE_MCAST_CMD_RESTORE:
35854e400768SDavid Christensen 			ecore_mcast_hdl_restore_e1h(sc, o, p, mc_filter);
35864e400768SDavid Christensen 			break;
35874e400768SDavid Christensen 
35884e400768SDavid Christensen 		default:
35894e400768SDavid Christensen 			ECORE_ERR("Unknown command: %d\n", cmd);
35904e400768SDavid Christensen 			return ECORE_INVAL;
35914e400768SDavid Christensen 		}
35924e400768SDavid Christensen 
35934e400768SDavid Christensen 		/* Set the mcast filter in the internal memory */
35944e400768SDavid Christensen 		for (i = 0; i < ECORE_MC_HASH_SIZE; i++)
35954e400768SDavid Christensen 			REG_WR(sc, ECORE_MC_HASH_OFFSET(sc, i), mc_filter[i]);
35964e400768SDavid Christensen 	} else
35974e400768SDavid Christensen 		/* clear the registry */
35984e400768SDavid Christensen 		ECORE_MEMSET(o->registry.aprox_match.vec, 0,
35994e400768SDavid Christensen 		       sizeof(o->registry.aprox_match.vec));
36004e400768SDavid Christensen 
36014e400768SDavid Christensen 	/* We are done */
36024e400768SDavid Christensen 	r->clear_pending(r);
36034e400768SDavid Christensen 
36044e400768SDavid Christensen 	return ECORE_SUCCESS;
36054e400768SDavid Christensen }
36064e400768SDavid Christensen 
ecore_mcast_validate_e1(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,enum ecore_mcast_cmd cmd)36074e400768SDavid Christensen static int ecore_mcast_validate_e1(struct bxe_softc *sc,
36084e400768SDavid Christensen 				   struct ecore_mcast_ramrod_params *p,
36094e400768SDavid Christensen 				   enum ecore_mcast_cmd cmd)
36104e400768SDavid Christensen {
36114e400768SDavid Christensen 	struct ecore_mcast_obj *o = p->mcast_obj;
36124e400768SDavid Christensen 	int reg_sz = o->get_registry_size(o);
36134e400768SDavid Christensen 
36144e400768SDavid Christensen 	switch (cmd) {
36154e400768SDavid Christensen 	/* DEL command deletes all currently configured MACs */
36164e400768SDavid Christensen 	case ECORE_MCAST_CMD_DEL:
36174e400768SDavid Christensen 		o->set_registry_size(o, 0);
36184e400768SDavid Christensen 		/* Don't break */
36194e400768SDavid Christensen 
36204e400768SDavid Christensen 	/* RESTORE command will restore the entire multicast configuration */
36214e400768SDavid Christensen 	case ECORE_MCAST_CMD_RESTORE:
36224e400768SDavid Christensen 		p->mcast_list_len = reg_sz;
36234e400768SDavid Christensen 		  ECORE_MSG(sc, "Command %d, p->mcast_list_len=%d\n",
36244e400768SDavid Christensen 				  cmd, p->mcast_list_len);
36254e400768SDavid Christensen 		break;
36264e400768SDavid Christensen 
36274e400768SDavid Christensen 	case ECORE_MCAST_CMD_ADD:
36284e400768SDavid Christensen 	case ECORE_MCAST_CMD_CONT:
36294e400768SDavid Christensen 		/* Multicast MACs on 57710 are configured as unicast MACs and
36304e400768SDavid Christensen 		 * there is only a limited number of CAM entries for that
36314e400768SDavid Christensen 		 * matter.
36324e400768SDavid Christensen 		 */
36334e400768SDavid Christensen 		if (p->mcast_list_len > o->max_cmd_len) {
36344e400768SDavid Christensen 			ECORE_ERR("Can't configure more than %d multicast MACs on 57710\n",
36354e400768SDavid Christensen 				  o->max_cmd_len);
36364e400768SDavid Christensen 			return ECORE_INVAL;
36374e400768SDavid Christensen 		}
36384e400768SDavid Christensen 		/* Every configured MAC should be cleared if DEL command is
36394e400768SDavid Christensen 		 * called. Only the last ADD command is relevant as long as
36404e400768SDavid Christensen 		 * every ADD commands overrides the previous configuration.
36414e400768SDavid Christensen 		 */
36424e400768SDavid Christensen 		ECORE_MSG(sc, "p->mcast_list_len=%d\n", p->mcast_list_len);
36434e400768SDavid Christensen 		if (p->mcast_list_len > 0)
36444e400768SDavid Christensen 			o->set_registry_size(o, p->mcast_list_len);
36454e400768SDavid Christensen 
36464e400768SDavid Christensen 		break;
36474e400768SDavid Christensen 
36484e400768SDavid Christensen 	default:
36494e400768SDavid Christensen 		ECORE_ERR("Unknown command: %d\n", cmd);
36504e400768SDavid Christensen 		return ECORE_INVAL;
36514e400768SDavid Christensen 	}
36524e400768SDavid Christensen 
36534e400768SDavid Christensen 	/* We want to ensure that commands are executed one by one for 57710.
36544e400768SDavid Christensen 	 * Therefore each none-empty command will consume o->max_cmd_len.
36554e400768SDavid Christensen 	 */
36564e400768SDavid Christensen 	if (p->mcast_list_len)
36574e400768SDavid Christensen 		o->total_pending_num += o->max_cmd_len;
36584e400768SDavid Christensen 
36594e400768SDavid Christensen 	return ECORE_SUCCESS;
36604e400768SDavid Christensen }
36614e400768SDavid Christensen 
ecore_mcast_revert_e1(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,int old_num_macs)36624e400768SDavid Christensen static void ecore_mcast_revert_e1(struct bxe_softc *sc,
36634e400768SDavid Christensen 				      struct ecore_mcast_ramrod_params *p,
36644e400768SDavid Christensen 				      int old_num_macs)
36654e400768SDavid Christensen {
36664e400768SDavid Christensen 	struct ecore_mcast_obj *o = p->mcast_obj;
36674e400768SDavid Christensen 
36684e400768SDavid Christensen 	o->set_registry_size(o, old_num_macs);
36694e400768SDavid Christensen 
36704e400768SDavid Christensen 	/* If current command hasn't been handled yet and we are
36714e400768SDavid Christensen 	 * here means that it's meant to be dropped and we have to
36724e400768SDavid Christensen 	 * update the number of outstanding MACs accordingly.
36734e400768SDavid Christensen 	 */
36744e400768SDavid Christensen 	if (p->mcast_list_len)
36754e400768SDavid Christensen 		o->total_pending_num -= o->max_cmd_len;
36764e400768SDavid Christensen }
36774e400768SDavid Christensen 
ecore_mcast_set_one_rule_e1(struct bxe_softc * sc,struct ecore_mcast_obj * o,int idx,union ecore_mcast_config_data * cfg_data,enum ecore_mcast_cmd cmd)36784e400768SDavid Christensen static void ecore_mcast_set_one_rule_e1(struct bxe_softc *sc,
36794e400768SDavid Christensen 					struct ecore_mcast_obj *o, int idx,
36804e400768SDavid Christensen 					union ecore_mcast_config_data *cfg_data,
36814e400768SDavid Christensen 					enum ecore_mcast_cmd cmd)
36824e400768SDavid Christensen {
36834e400768SDavid Christensen 	struct ecore_raw_obj *r = &o->raw;
36844e400768SDavid Christensen 	struct mac_configuration_cmd *data =
36854e400768SDavid Christensen 		(struct mac_configuration_cmd *)(r->rdata);
36864e400768SDavid Christensen 
36874e400768SDavid Christensen 	/* copy mac */
36884e400768SDavid Christensen 	if ((cmd == ECORE_MCAST_CMD_ADD) || (cmd == ECORE_MCAST_CMD_RESTORE)) {
36894e400768SDavid Christensen 		ecore_set_fw_mac_addr(&data->config_table[idx].msb_mac_addr,
36904e400768SDavid Christensen 				      &data->config_table[idx].middle_mac_addr,
36914e400768SDavid Christensen 				      &data->config_table[idx].lsb_mac_addr,
36924e400768SDavid Christensen 				      cfg_data->mac);
36934e400768SDavid Christensen 
36944e400768SDavid Christensen 		data->config_table[idx].vlan_id = 0;
36954e400768SDavid Christensen 		data->config_table[idx].pf_id = r->func_id;
36964e400768SDavid Christensen 		data->config_table[idx].clients_bit_vector =
36974e400768SDavid Christensen 			ECORE_CPU_TO_LE32(1 << r->cl_id);
36984e400768SDavid Christensen 
36994e400768SDavid Christensen 		ECORE_SET_FLAG(data->config_table[idx].flags,
37004e400768SDavid Christensen 			       MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
37014e400768SDavid Christensen 			       T_ETH_MAC_COMMAND_SET);
37024e400768SDavid Christensen 	}
37034e400768SDavid Christensen }
37044e400768SDavid Christensen 
37054e400768SDavid Christensen /**
37064e400768SDavid Christensen  * ecore_mcast_set_rdata_hdr_e1  - set header values in mac_configuration_cmd
37074e400768SDavid Christensen  *
37084e400768SDavid Christensen  * @sc:		device handle
37094e400768SDavid Christensen  * @p:
37104e400768SDavid Christensen  * @len:	number of rules to handle
37114e400768SDavid Christensen  */
ecore_mcast_set_rdata_hdr_e1(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,uint8_t len)37124e400768SDavid Christensen static inline void ecore_mcast_set_rdata_hdr_e1(struct bxe_softc *sc,
37134e400768SDavid Christensen 					struct ecore_mcast_ramrod_params *p,
37144e400768SDavid Christensen 					uint8_t len)
37154e400768SDavid Christensen {
37164e400768SDavid Christensen 	struct ecore_raw_obj *r = &p->mcast_obj->raw;
37174e400768SDavid Christensen 	struct mac_configuration_cmd *data =
37184e400768SDavid Christensen 		(struct mac_configuration_cmd *)(r->rdata);
37194e400768SDavid Christensen 
37204e400768SDavid Christensen 	uint8_t offset = (CHIP_REV_IS_SLOW(sc) ?
37214e400768SDavid Christensen 		     ECORE_MAX_EMUL_MULTI*(1 + r->func_id) :
37224e400768SDavid Christensen 		     ECORE_MAX_MULTICAST*(1 + r->func_id));
37234e400768SDavid Christensen 
37244e400768SDavid Christensen 	data->hdr.offset = offset;
37254e400768SDavid Christensen 	data->hdr.client_id = ECORE_CPU_TO_LE16(0xff);
37264e400768SDavid Christensen 	data->hdr.echo = ECORE_CPU_TO_LE32((r->cid & ECORE_SWCID_MASK) |
37274e400768SDavid Christensen 				     (ECORE_FILTER_MCAST_PENDING <<
37284e400768SDavid Christensen 				      ECORE_SWCID_SHIFT));
37294e400768SDavid Christensen 	data->hdr.length = len;
37304e400768SDavid Christensen }
37314e400768SDavid Christensen 
37324e400768SDavid Christensen /**
37334e400768SDavid Christensen  * ecore_mcast_handle_restore_cmd_e1 - restore command for 57710
37344e400768SDavid Christensen  *
37354e400768SDavid Christensen  * @sc:		device handle
37364e400768SDavid Christensen  * @o:
37374e400768SDavid Christensen  * @start_idx:	index in the registry to start from
37384e400768SDavid Christensen  * @rdata_idx:	index in the ramrod data to start from
37394e400768SDavid Christensen  *
37404e400768SDavid Christensen  * restore command for 57710 is like all other commands - always a stand alone
37414e400768SDavid Christensen  * command - start_idx and rdata_idx will always be 0. This function will always
37424e400768SDavid Christensen  * succeed.
37434e400768SDavid Christensen  * returns -1 to comply with 57712 variant.
37444e400768SDavid Christensen  */
ecore_mcast_handle_restore_cmd_e1(struct bxe_softc * sc,struct ecore_mcast_obj * o,int start_idx,int * rdata_idx)37454e400768SDavid Christensen static inline int ecore_mcast_handle_restore_cmd_e1(
37464e400768SDavid Christensen 	struct bxe_softc *sc, struct ecore_mcast_obj *o , int start_idx,
37474e400768SDavid Christensen 	int *rdata_idx)
37484e400768SDavid Christensen {
37494e400768SDavid Christensen 	struct ecore_mcast_mac_elem *elem;
37504e400768SDavid Christensen 	int i = 0;
37514e400768SDavid Christensen 	union ecore_mcast_config_data cfg_data = {NULL};
37524e400768SDavid Christensen 
37534e400768SDavid Christensen 	/* go through the registry and configure the MACs from it. */
37544e400768SDavid Christensen 	ECORE_LIST_FOR_EACH_ENTRY(elem, &o->registry.exact_match.macs, link,
37554e400768SDavid Christensen 				  struct ecore_mcast_mac_elem) {
37564e400768SDavid Christensen 		cfg_data.mac = &elem->mac[0];
37574e400768SDavid Christensen 		o->set_one_rule(sc, o, i, &cfg_data, ECORE_MCAST_CMD_RESTORE);
37584e400768SDavid Christensen 
37594e400768SDavid Christensen 		i++;
37604e400768SDavid Christensen 
37614e400768SDavid Christensen 		ECORE_MSG(sc, "About to configure %02x:%02x:%02x:%02x:%02x:%02x mcast MAC\n",
37624e400768SDavid Christensen 			  cfg_data.mac[0], cfg_data.mac[1], cfg_data.mac[2], cfg_data.mac[3], cfg_data.mac[4], cfg_data.mac[5]);
37634e400768SDavid Christensen 	}
37644e400768SDavid Christensen 
37654e400768SDavid Christensen 	*rdata_idx = i;
37664e400768SDavid Christensen 
37674e400768SDavid Christensen 	return -1;
37684e400768SDavid Christensen }
37694e400768SDavid Christensen 
ecore_mcast_handle_pending_cmds_e1(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p)37704e400768SDavid Christensen static inline int ecore_mcast_handle_pending_cmds_e1(
37714e400768SDavid Christensen 	struct bxe_softc *sc, struct ecore_mcast_ramrod_params *p)
37724e400768SDavid Christensen {
37734e400768SDavid Christensen 	struct ecore_pending_mcast_cmd *cmd_pos;
37744e400768SDavid Christensen 	struct ecore_mcast_mac_elem *pmac_pos;
37754e400768SDavid Christensen 	struct ecore_mcast_obj *o = p->mcast_obj;
37764e400768SDavid Christensen 	union ecore_mcast_config_data cfg_data = {NULL};
37774e400768SDavid Christensen 	int cnt = 0;
37784e400768SDavid Christensen 
37794e400768SDavid Christensen 	/* If nothing to be done - return */
37804e400768SDavid Christensen 	if (ECORE_LIST_IS_EMPTY(&o->pending_cmds_head))
37814e400768SDavid Christensen 		return 0;
37824e400768SDavid Christensen 
37834e400768SDavid Christensen 	/* Handle the first command */
37844e400768SDavid Christensen 	cmd_pos = ECORE_LIST_FIRST_ENTRY(&o->pending_cmds_head,
37854e400768SDavid Christensen 					 struct ecore_pending_mcast_cmd, link);
37864e400768SDavid Christensen 
37874e400768SDavid Christensen 	switch (cmd_pos->type) {
37884e400768SDavid Christensen 	case ECORE_MCAST_CMD_ADD:
37894e400768SDavid Christensen 		ECORE_LIST_FOR_EACH_ENTRY(pmac_pos, &cmd_pos->data.macs_head,
37904e400768SDavid Christensen 					  link, struct ecore_mcast_mac_elem) {
37914e400768SDavid Christensen 			cfg_data.mac = &pmac_pos->mac[0];
37924e400768SDavid Christensen 			o->set_one_rule(sc, o, cnt, &cfg_data, cmd_pos->type);
37934e400768SDavid Christensen 
37944e400768SDavid Christensen 			cnt++;
37954e400768SDavid Christensen 
37964e400768SDavid Christensen 			ECORE_MSG(sc, "About to configure %02x:%02x:%02x:%02x:%02x:%02x mcast MAC\n",
37974e400768SDavid Christensen 				  pmac_pos->mac[0], pmac_pos->mac[1], pmac_pos->mac[2], pmac_pos->mac[3], pmac_pos->mac[4], pmac_pos->mac[5]);
37984e400768SDavid Christensen 		}
37994e400768SDavid Christensen 		break;
38004e400768SDavid Christensen 
38014e400768SDavid Christensen 	case ECORE_MCAST_CMD_DEL:
38024e400768SDavid Christensen 		cnt = cmd_pos->data.macs_num;
38034e400768SDavid Christensen 		ECORE_MSG(sc, "About to delete %d multicast MACs\n", cnt);
38044e400768SDavid Christensen 		break;
38054e400768SDavid Christensen 
38064e400768SDavid Christensen 	case ECORE_MCAST_CMD_RESTORE:
38074e400768SDavid Christensen 		o->hdl_restore(sc, o, 0, &cnt);
38084e400768SDavid Christensen 		break;
38094e400768SDavid Christensen 
38104e400768SDavid Christensen 	default:
38114e400768SDavid Christensen 		ECORE_ERR("Unknown command: %d\n", cmd_pos->type);
38124e400768SDavid Christensen 		return ECORE_INVAL;
38134e400768SDavid Christensen 	}
38144e400768SDavid Christensen 
38154e400768SDavid Christensen 	ECORE_LIST_REMOVE_ENTRY(&cmd_pos->link, &o->pending_cmds_head);
38164e400768SDavid Christensen 	ECORE_FREE(sc, cmd_pos, cmd_pos->alloc_len);
38174e400768SDavid Christensen 
38184e400768SDavid Christensen 	return cnt;
38194e400768SDavid Christensen }
38204e400768SDavid Christensen 
38214e400768SDavid Christensen /**
38224e400768SDavid Christensen  * ecore_get_fw_mac_addr - revert the ecore_set_fw_mac_addr().
38234e400768SDavid Christensen  *
38244e400768SDavid Christensen  * @fw_hi:
38254e400768SDavid Christensen  * @fw_mid:
38264e400768SDavid Christensen  * @fw_lo:
38274e400768SDavid Christensen  * @mac:
38284e400768SDavid Christensen  */
ecore_get_fw_mac_addr(uint16_t * fw_hi,uint16_t * fw_mid,uint16_t * fw_lo,uint8_t * mac)38294e400768SDavid Christensen static inline void ecore_get_fw_mac_addr(uint16_t *fw_hi, uint16_t *fw_mid,
38304e400768SDavid Christensen 					 uint16_t *fw_lo, uint8_t *mac)
38314e400768SDavid Christensen {
38324e400768SDavid Christensen 	mac[1] = ((uint8_t *)fw_hi)[0];
38334e400768SDavid Christensen 	mac[0] = ((uint8_t *)fw_hi)[1];
38344e400768SDavid Christensen 	mac[3] = ((uint8_t *)fw_mid)[0];
38354e400768SDavid Christensen 	mac[2] = ((uint8_t *)fw_mid)[1];
38364e400768SDavid Christensen 	mac[5] = ((uint8_t *)fw_lo)[0];
38374e400768SDavid Christensen 	mac[4] = ((uint8_t *)fw_lo)[1];
38384e400768SDavid Christensen }
38394e400768SDavid Christensen 
38404e400768SDavid Christensen /**
38414e400768SDavid Christensen  * ecore_mcast_refresh_registry_e1 -
38424e400768SDavid Christensen  *
38434e400768SDavid Christensen  * @sc:		device handle
38444e400768SDavid Christensen  * @cnt:
38454e400768SDavid Christensen  *
38464e400768SDavid Christensen  * Check the ramrod data first entry flag to see if it's a DELETE or ADD command
38474e400768SDavid Christensen  * and update the registry correspondingly: if ADD - allocate a memory and add
38484e400768SDavid Christensen  * the entries to the registry (list), if DELETE - clear the registry and free
38494e400768SDavid Christensen  * the memory.
38504e400768SDavid Christensen  */
ecore_mcast_refresh_registry_e1(struct bxe_softc * sc,struct ecore_mcast_obj * o)38514e400768SDavid Christensen static inline int ecore_mcast_refresh_registry_e1(struct bxe_softc *sc,
38524e400768SDavid Christensen 						  struct ecore_mcast_obj *o)
38534e400768SDavid Christensen {
38544e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
38554e400768SDavid Christensen 	struct ecore_mcast_mac_elem *elem;
38564e400768SDavid Christensen 	struct mac_configuration_cmd *data =
38574e400768SDavid Christensen 			(struct mac_configuration_cmd *)(raw->rdata);
38584e400768SDavid Christensen 
38594e400768SDavid Christensen 	/* If first entry contains a SET bit - the command was ADD,
38604e400768SDavid Christensen 	 * otherwise - DEL_ALL
38614e400768SDavid Christensen 	 */
38624e400768SDavid Christensen 	if (ECORE_GET_FLAG(data->config_table[0].flags,
38634e400768SDavid Christensen 			MAC_CONFIGURATION_ENTRY_ACTION_TYPE)) {
38644e400768SDavid Christensen 		int i, len = data->hdr.length;
38654e400768SDavid Christensen 
38664e400768SDavid Christensen 		/* Break if it was a RESTORE command */
38674e400768SDavid Christensen 		if (!ECORE_LIST_IS_EMPTY(&o->registry.exact_match.macs))
38684e400768SDavid Christensen 			return ECORE_SUCCESS;
38694e400768SDavid Christensen 
38704e400768SDavid Christensen 		elem = ECORE_CALLOC(len, sizeof(*elem), GFP_ATOMIC, sc);
38714e400768SDavid Christensen 		if (!elem) {
38724e400768SDavid Christensen 			ECORE_ERR("Failed to allocate registry memory\n");
38734e400768SDavid Christensen 			return ECORE_NOMEM;
38744e400768SDavid Christensen 		}
38754e400768SDavid Christensen 
38764e400768SDavid Christensen 		for (i = 0; i < len; i++, elem++) {
38774e400768SDavid Christensen 			ecore_get_fw_mac_addr(
38784e400768SDavid Christensen 				&data->config_table[i].msb_mac_addr,
38794e400768SDavid Christensen 				&data->config_table[i].middle_mac_addr,
38804e400768SDavid Christensen 				&data->config_table[i].lsb_mac_addr,
38814e400768SDavid Christensen 				elem->mac);
38824e400768SDavid Christensen 			ECORE_MSG(sc, "Adding registry entry for [%02x:%02x:%02x:%02x:%02x:%02x]\n",
38834e400768SDavid Christensen 				  elem->mac[0], elem->mac[1], elem->mac[2], elem->mac[3], elem->mac[4], elem->mac[5]);
38844e400768SDavid Christensen 			ECORE_LIST_PUSH_TAIL(&elem->link,
38854e400768SDavid Christensen 					     &o->registry.exact_match.macs);
38864e400768SDavid Christensen 		}
38874e400768SDavid Christensen 	} else {
38884e400768SDavid Christensen 		elem = ECORE_LIST_FIRST_ENTRY(&o->registry.exact_match.macs,
38894e400768SDavid Christensen 					      struct ecore_mcast_mac_elem,
38904e400768SDavid Christensen 					      link);
38914e400768SDavid Christensen 		ECORE_MSG(sc, "Deleting a registry\n");
38924e400768SDavid Christensen 		ECORE_FREE(sc, elem, sizeof(*elem));
38934e400768SDavid Christensen 		ECORE_LIST_INIT(&o->registry.exact_match.macs);
38944e400768SDavid Christensen 	}
38954e400768SDavid Christensen 
38964e400768SDavid Christensen 	return ECORE_SUCCESS;
38974e400768SDavid Christensen }
38984e400768SDavid Christensen 
ecore_mcast_setup_e1(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,enum ecore_mcast_cmd cmd)38994e400768SDavid Christensen static int ecore_mcast_setup_e1(struct bxe_softc *sc,
39004e400768SDavid Christensen 				struct ecore_mcast_ramrod_params *p,
39014e400768SDavid Christensen 				enum ecore_mcast_cmd cmd)
39024e400768SDavid Christensen {
39034e400768SDavid Christensen 	struct ecore_mcast_obj *o = p->mcast_obj;
39044e400768SDavid Christensen 	struct ecore_raw_obj *raw = &o->raw;
39054e400768SDavid Christensen 	struct mac_configuration_cmd *data =
39064e400768SDavid Christensen 		(struct mac_configuration_cmd *)(raw->rdata);
39074e400768SDavid Christensen 	int cnt = 0, i, rc;
39084e400768SDavid Christensen 
39094e400768SDavid Christensen 	/* Reset the ramrod data buffer */
39104e400768SDavid Christensen 	ECORE_MEMSET(data, 0, sizeof(*data));
39114e400768SDavid Christensen 
39124e400768SDavid Christensen 	/* First set all entries as invalid */
39134e400768SDavid Christensen 	for (i = 0; i < o->max_cmd_len ; i++)
39144e400768SDavid Christensen 		ECORE_SET_FLAG(data->config_table[i].flags,
39154e400768SDavid Christensen 			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
39164e400768SDavid Christensen 			T_ETH_MAC_COMMAND_INVALIDATE);
39174e400768SDavid Christensen 
39184e400768SDavid Christensen 	/* Handle pending commands first */
39194e400768SDavid Christensen 	cnt = ecore_mcast_handle_pending_cmds_e1(sc, p);
39204e400768SDavid Christensen 
39214e400768SDavid Christensen 	/* If there are no more pending commands - clear SCHEDULED state */
39224e400768SDavid Christensen 	if (ECORE_LIST_IS_EMPTY(&o->pending_cmds_head))
39234e400768SDavid Christensen 		o->clear_sched(o);
39244e400768SDavid Christensen 
39254e400768SDavid Christensen 	/* The below may be TRUE iff there were no pending commands */
39264e400768SDavid Christensen 	if (!cnt)
39274e400768SDavid Christensen 		cnt = ecore_mcast_handle_current_cmd(sc, p, cmd, 0);
39284e400768SDavid Christensen 
39294e400768SDavid Christensen 	/* For 57710 every command has o->max_cmd_len length to ensure that
39304e400768SDavid Christensen 	 * commands are done one at a time.
39314e400768SDavid Christensen 	 */
39324e400768SDavid Christensen 	o->total_pending_num -= o->max_cmd_len;
39334e400768SDavid Christensen 
39344e400768SDavid Christensen 	/* send a ramrod */
39354e400768SDavid Christensen 
39364e400768SDavid Christensen 	ECORE_DBG_BREAK_IF(cnt > o->max_cmd_len);
39374e400768SDavid Christensen 
39384e400768SDavid Christensen 	/* Set ramrod header (in particular, a number of entries to update) */
39394e400768SDavid Christensen 	ecore_mcast_set_rdata_hdr_e1(sc, p, (uint8_t)cnt);
39404e400768SDavid Christensen 
39414e400768SDavid Christensen 	/* update a registry: we need the registry contents to be always up
39424e400768SDavid Christensen 	 * to date in order to be able to execute a RESTORE opcode. Here
39434e400768SDavid Christensen 	 * we use the fact that for 57710 we sent one command at a time
39444e400768SDavid Christensen 	 * hence we may take the registry update out of the command handling
39454e400768SDavid Christensen 	 * and do it in a simpler way here.
39464e400768SDavid Christensen 	 */
39474e400768SDavid Christensen 	rc = ecore_mcast_refresh_registry_e1(sc, o);
39484e400768SDavid Christensen 	if (rc)
39494e400768SDavid Christensen 		return rc;
39504e400768SDavid Christensen 
39514e400768SDavid Christensen 	/* If CLEAR_ONLY was requested - don't send a ramrod and clear
39524e400768SDavid Christensen 	 * RAMROD_PENDING status immediately.
39534e400768SDavid Christensen 	 */
39544e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
39554e400768SDavid Christensen 		raw->clear_pending(raw);
39564e400768SDavid Christensen 		return ECORE_SUCCESS;
39574e400768SDavid Christensen 	} else {
39584ef8ebfdSDavid C Somayajulu 		/* No need for an explicit memory barrier here as long as we
39594ef8ebfdSDavid C Somayajulu 		 * ensure the ordering of writing to the SPQ element
39604e400768SDavid Christensen 		 * and updating of the SPQ producer which involves a memory
39614ef8ebfdSDavid C Somayajulu 		 * read. If the memory read is removed we will have to put a
39624ef8ebfdSDavid C Somayajulu 		 * full memory barrier there (inside ecore_sp_post()).
39634e400768SDavid Christensen 		 */
39644e400768SDavid Christensen 
39654e400768SDavid Christensen 		/* Send a ramrod */
39664e400768SDavid Christensen 		rc = ecore_sp_post( sc,
39674e400768SDavid Christensen 				    RAMROD_CMD_ID_ETH_SET_MAC,
39684e400768SDavid Christensen 				    raw->cid,
39694e400768SDavid Christensen 				    raw->rdata_mapping,
39704e400768SDavid Christensen 				    ETH_CONNECTION_TYPE);
39714e400768SDavid Christensen 		if (rc)
39724e400768SDavid Christensen 			return rc;
39734e400768SDavid Christensen 
39744e400768SDavid Christensen 		/* Ramrod completion is pending */
39754e400768SDavid Christensen 		return ECORE_PENDING;
39764e400768SDavid Christensen 	}
39774e400768SDavid Christensen }
39784e400768SDavid Christensen 
ecore_mcast_get_registry_size_exact(struct ecore_mcast_obj * o)39794e400768SDavid Christensen static int ecore_mcast_get_registry_size_exact(struct ecore_mcast_obj *o)
39804e400768SDavid Christensen {
39814e400768SDavid Christensen 	return o->registry.exact_match.num_macs_set;
39824e400768SDavid Christensen }
39834e400768SDavid Christensen 
ecore_mcast_get_registry_size_aprox(struct ecore_mcast_obj * o)39844e400768SDavid Christensen static int ecore_mcast_get_registry_size_aprox(struct ecore_mcast_obj *o)
39854e400768SDavid Christensen {
39864e400768SDavid Christensen 	return o->registry.aprox_match.num_bins_set;
39874e400768SDavid Christensen }
39884e400768SDavid Christensen 
ecore_mcast_set_registry_size_exact(struct ecore_mcast_obj * o,int n)39894e400768SDavid Christensen static void ecore_mcast_set_registry_size_exact(struct ecore_mcast_obj *o,
39904e400768SDavid Christensen 						int n)
39914e400768SDavid Christensen {
39924e400768SDavid Christensen 	o->registry.exact_match.num_macs_set = n;
39934e400768SDavid Christensen }
39944e400768SDavid Christensen 
ecore_mcast_set_registry_size_aprox(struct ecore_mcast_obj * o,int n)39954e400768SDavid Christensen static void ecore_mcast_set_registry_size_aprox(struct ecore_mcast_obj *o,
39964e400768SDavid Christensen 						int n)
39974e400768SDavid Christensen {
39984e400768SDavid Christensen 	o->registry.aprox_match.num_bins_set = n;
39994e400768SDavid Christensen }
40004e400768SDavid Christensen 
ecore_config_mcast(struct bxe_softc * sc,struct ecore_mcast_ramrod_params * p,enum ecore_mcast_cmd cmd)40014e400768SDavid Christensen int ecore_config_mcast(struct bxe_softc *sc,
40024e400768SDavid Christensen 		       struct ecore_mcast_ramrod_params *p,
40034e400768SDavid Christensen 		       enum ecore_mcast_cmd cmd)
40044e400768SDavid Christensen {
40054e400768SDavid Christensen 	struct ecore_mcast_obj *o = p->mcast_obj;
40064e400768SDavid Christensen 	struct ecore_raw_obj *r = &o->raw;
40074e400768SDavid Christensen 	int rc = 0, old_reg_size;
40084e400768SDavid Christensen 
40094e400768SDavid Christensen 	/* This is needed to recover number of currently configured mcast macs
40104e400768SDavid Christensen 	 * in case of failure.
40114e400768SDavid Christensen 	 */
40124e400768SDavid Christensen 	old_reg_size = o->get_registry_size(o);
40134e400768SDavid Christensen 
40144e400768SDavid Christensen 	/* Do some calculations and checks */
40154e400768SDavid Christensen 	rc = o->validate(sc, p, cmd);
40164e400768SDavid Christensen 	if (rc)
40174e400768SDavid Christensen 		return rc;
40184e400768SDavid Christensen 
40194e400768SDavid Christensen 	/* Return if there is no work to do */
40204e400768SDavid Christensen 	if ((!p->mcast_list_len) && (!o->check_sched(o)))
40214e400768SDavid Christensen 		return ECORE_SUCCESS;
40224e400768SDavid Christensen 
40234e400768SDavid Christensen 	ECORE_MSG(sc, "o->total_pending_num=%d p->mcast_list_len=%d o->max_cmd_len=%d\n",
40244e400768SDavid Christensen 		  o->total_pending_num, p->mcast_list_len, o->max_cmd_len);
40254e400768SDavid Christensen 
40264e400768SDavid Christensen 	/* Enqueue the current command to the pending list if we can't complete
40274e400768SDavid Christensen 	 * it in the current iteration
40284e400768SDavid Christensen 	 */
40294e400768SDavid Christensen 	if (r->check_pending(r) ||
40304e400768SDavid Christensen 	    ((o->max_cmd_len > 0) && (o->total_pending_num > o->max_cmd_len))) {
40314e400768SDavid Christensen 		rc = o->enqueue_cmd(sc, p->mcast_obj, p, cmd);
40324e400768SDavid Christensen 		if (rc < 0)
40334e400768SDavid Christensen 			goto error_exit1;
40344e400768SDavid Christensen 
40354e400768SDavid Christensen 		/* As long as the current command is in a command list we
40364e400768SDavid Christensen 		 * don't need to handle it separately.
40374e400768SDavid Christensen 		 */
40384e400768SDavid Christensen 		p->mcast_list_len = 0;
40394e400768SDavid Christensen 	}
40404e400768SDavid Christensen 
40414e400768SDavid Christensen 	if (!r->check_pending(r)) {
40424e400768SDavid Christensen 
40434e400768SDavid Christensen 		/* Set 'pending' state */
40444e400768SDavid Christensen 		r->set_pending(r);
40454e400768SDavid Christensen 
40464e400768SDavid Christensen 		/* Configure the new classification in the chip */
40474e400768SDavid Christensen 		rc = o->config_mcast(sc, p, cmd);
40484e400768SDavid Christensen 		if (rc < 0)
40494e400768SDavid Christensen 			goto error_exit2;
40504e400768SDavid Christensen 
40514e400768SDavid Christensen 		/* Wait for a ramrod completion if was requested */
40524e400768SDavid Christensen 		if (ECORE_TEST_BIT(RAMROD_COMP_WAIT, &p->ramrod_flags))
40534e400768SDavid Christensen 			rc = o->wait_comp(sc, o);
40544e400768SDavid Christensen 	}
40554e400768SDavid Christensen 
40564e400768SDavid Christensen 	return rc;
40574e400768SDavid Christensen 
40584e400768SDavid Christensen error_exit2:
40594e400768SDavid Christensen 	r->clear_pending(r);
40604e400768SDavid Christensen 
40614e400768SDavid Christensen error_exit1:
40624e400768SDavid Christensen 	o->revert(sc, p, old_reg_size);
40634e400768SDavid Christensen 
40644e400768SDavid Christensen 	return rc;
40654e400768SDavid Christensen }
40664e400768SDavid Christensen 
ecore_mcast_clear_sched(struct ecore_mcast_obj * o)40674e400768SDavid Christensen static void ecore_mcast_clear_sched(struct ecore_mcast_obj *o)
40684e400768SDavid Christensen {
40694e400768SDavid Christensen 	ECORE_SMP_MB_BEFORE_CLEAR_BIT();
40704e400768SDavid Christensen 	ECORE_CLEAR_BIT(o->sched_state, o->raw.pstate);
40714e400768SDavid Christensen 	ECORE_SMP_MB_AFTER_CLEAR_BIT();
40724e400768SDavid Christensen }
40734e400768SDavid Christensen 
ecore_mcast_set_sched(struct ecore_mcast_obj * o)40744e400768SDavid Christensen static void ecore_mcast_set_sched(struct ecore_mcast_obj *o)
40754e400768SDavid Christensen {
40764e400768SDavid Christensen 	ECORE_SMP_MB_BEFORE_CLEAR_BIT();
40774e400768SDavid Christensen 	ECORE_SET_BIT(o->sched_state, o->raw.pstate);
40784e400768SDavid Christensen 	ECORE_SMP_MB_AFTER_CLEAR_BIT();
40794e400768SDavid Christensen }
40804e400768SDavid Christensen 
ecore_mcast_check_sched(struct ecore_mcast_obj * o)40814e400768SDavid Christensen static bool ecore_mcast_check_sched(struct ecore_mcast_obj *o)
40824e400768SDavid Christensen {
40834e400768SDavid Christensen 	return !!ECORE_TEST_BIT(o->sched_state, o->raw.pstate);
40844e400768SDavid Christensen }
40854e400768SDavid Christensen 
ecore_mcast_check_pending(struct ecore_mcast_obj * o)40864e400768SDavid Christensen static bool ecore_mcast_check_pending(struct ecore_mcast_obj *o)
40874e400768SDavid Christensen {
40884e400768SDavid Christensen 	return o->raw.check_pending(&o->raw) || o->check_sched(o);
40894e400768SDavid Christensen }
40904e400768SDavid Christensen 
ecore_init_mcast_obj(struct bxe_softc * sc,struct ecore_mcast_obj * mcast_obj,uint8_t mcast_cl_id,uint32_t mcast_cid,uint8_t func_id,uint8_t engine_id,void * rdata,ecore_dma_addr_t rdata_mapping,int state,unsigned long * pstate,ecore_obj_type type)40914e400768SDavid Christensen void ecore_init_mcast_obj(struct bxe_softc *sc,
40924e400768SDavid Christensen 			  struct ecore_mcast_obj *mcast_obj,
40934e400768SDavid Christensen 			  uint8_t mcast_cl_id, uint32_t mcast_cid, uint8_t func_id,
40944e400768SDavid Christensen 			  uint8_t engine_id, void *rdata, ecore_dma_addr_t rdata_mapping,
40954e400768SDavid Christensen 			  int state, unsigned long *pstate, ecore_obj_type type)
40964e400768SDavid Christensen {
40974e400768SDavid Christensen 	ECORE_MEMSET(mcast_obj, 0, sizeof(*mcast_obj));
40984e400768SDavid Christensen 
40994e400768SDavid Christensen 	ecore_init_raw_obj(&mcast_obj->raw, mcast_cl_id, mcast_cid, func_id,
41004e400768SDavid Christensen 			   rdata, rdata_mapping, state, pstate, type);
41014e400768SDavid Christensen 
41024e400768SDavid Christensen 	mcast_obj->engine_id = engine_id;
41034e400768SDavid Christensen 
41044e400768SDavid Christensen 	ECORE_LIST_INIT(&mcast_obj->pending_cmds_head);
41054e400768SDavid Christensen 
41064e400768SDavid Christensen 	mcast_obj->sched_state = ECORE_FILTER_MCAST_SCHED;
41074e400768SDavid Christensen 	mcast_obj->check_sched = ecore_mcast_check_sched;
41084e400768SDavid Christensen 	mcast_obj->set_sched = ecore_mcast_set_sched;
41094e400768SDavid Christensen 	mcast_obj->clear_sched = ecore_mcast_clear_sched;
41104e400768SDavid Christensen 
41114e400768SDavid Christensen 	if (CHIP_IS_E1(sc)) {
41124e400768SDavid Christensen 		mcast_obj->config_mcast      = ecore_mcast_setup_e1;
41134e400768SDavid Christensen 		mcast_obj->enqueue_cmd       = ecore_mcast_enqueue_cmd;
41144e400768SDavid Christensen 		mcast_obj->hdl_restore       =
41154e400768SDavid Christensen 			ecore_mcast_handle_restore_cmd_e1;
41164e400768SDavid Christensen 		mcast_obj->check_pending     = ecore_mcast_check_pending;
41174e400768SDavid Christensen 
41184e400768SDavid Christensen 		if (CHIP_REV_IS_SLOW(sc))
41194e400768SDavid Christensen 			mcast_obj->max_cmd_len = ECORE_MAX_EMUL_MULTI;
41204e400768SDavid Christensen 		else
41214e400768SDavid Christensen 			mcast_obj->max_cmd_len = ECORE_MAX_MULTICAST;
41224e400768SDavid Christensen 
41234e400768SDavid Christensen 		mcast_obj->wait_comp         = ecore_mcast_wait;
41244e400768SDavid Christensen 		mcast_obj->set_one_rule      = ecore_mcast_set_one_rule_e1;
41254e400768SDavid Christensen 		mcast_obj->validate          = ecore_mcast_validate_e1;
41264e400768SDavid Christensen 		mcast_obj->revert            = ecore_mcast_revert_e1;
41274e400768SDavid Christensen 		mcast_obj->get_registry_size =
41284e400768SDavid Christensen 			ecore_mcast_get_registry_size_exact;
41294e400768SDavid Christensen 		mcast_obj->set_registry_size =
41304e400768SDavid Christensen 			ecore_mcast_set_registry_size_exact;
41314e400768SDavid Christensen 
41324e400768SDavid Christensen 		/* 57710 is the only chip that uses the exact match for mcast
41334e400768SDavid Christensen 		 * at the moment.
41344e400768SDavid Christensen 		 */
41354e400768SDavid Christensen 		ECORE_LIST_INIT(&mcast_obj->registry.exact_match.macs);
41364e400768SDavid Christensen 
41374e400768SDavid Christensen 	} else if (CHIP_IS_E1H(sc)) {
41384e400768SDavid Christensen 		mcast_obj->config_mcast  = ecore_mcast_setup_e1h;
41394e400768SDavid Christensen 		mcast_obj->enqueue_cmd   = NULL;
41404e400768SDavid Christensen 		mcast_obj->hdl_restore   = NULL;
41414e400768SDavid Christensen 		mcast_obj->check_pending = ecore_mcast_check_pending;
41424e400768SDavid Christensen 
41434e400768SDavid Christensen 		/* 57711 doesn't send a ramrod, so it has unlimited credit
41444e400768SDavid Christensen 		 * for one command.
41454e400768SDavid Christensen 		 */
41464e400768SDavid Christensen 		mcast_obj->max_cmd_len       = -1;
41474e400768SDavid Christensen 		mcast_obj->wait_comp         = ecore_mcast_wait;
41484e400768SDavid Christensen 		mcast_obj->set_one_rule      = NULL;
41494e400768SDavid Christensen 		mcast_obj->validate          = ecore_mcast_validate_e1h;
41504e400768SDavid Christensen 		mcast_obj->revert            = ecore_mcast_revert_e1h;
41514e400768SDavid Christensen 		mcast_obj->get_registry_size =
41524e400768SDavid Christensen 			ecore_mcast_get_registry_size_aprox;
41534e400768SDavid Christensen 		mcast_obj->set_registry_size =
41544e400768SDavid Christensen 			ecore_mcast_set_registry_size_aprox;
41554e400768SDavid Christensen 	} else {
41564e400768SDavid Christensen 		mcast_obj->config_mcast      = ecore_mcast_setup_e2;
41574e400768SDavid Christensen 		mcast_obj->enqueue_cmd       = ecore_mcast_enqueue_cmd;
41584e400768SDavid Christensen 		mcast_obj->hdl_restore       =
41594e400768SDavid Christensen 			ecore_mcast_handle_restore_cmd_e2;
41604e400768SDavid Christensen 		mcast_obj->check_pending     = ecore_mcast_check_pending;
41614e400768SDavid Christensen 		/* TODO: There should be a proper HSI define for this number!!!
41624e400768SDavid Christensen 		 */
41634e400768SDavid Christensen 		mcast_obj->max_cmd_len       = 16;
41644e400768SDavid Christensen 		mcast_obj->wait_comp         = ecore_mcast_wait;
41654e400768SDavid Christensen 		mcast_obj->set_one_rule      = ecore_mcast_set_one_rule_e2;
41664e400768SDavid Christensen 		mcast_obj->validate          = ecore_mcast_validate_e2;
41674e400768SDavid Christensen 		mcast_obj->revert            = ecore_mcast_revert_e2;
41684e400768SDavid Christensen 		mcast_obj->get_registry_size =
41694e400768SDavid Christensen 			ecore_mcast_get_registry_size_aprox;
41704e400768SDavid Christensen 		mcast_obj->set_registry_size =
41714e400768SDavid Christensen 			ecore_mcast_set_registry_size_aprox;
41724e400768SDavid Christensen 	}
41734e400768SDavid Christensen }
41744e400768SDavid Christensen 
41754e400768SDavid Christensen /*************************** Credit handling **********************************/
41764e400768SDavid Christensen 
41774e400768SDavid Christensen /**
41784e400768SDavid Christensen  * atomic_add_ifless - add if the result is less than a given value.
41794e400768SDavid Christensen  *
41804e400768SDavid Christensen  * @v:	pointer of type ecore_atomic_t
41814e400768SDavid Christensen  * @a:	the amount to add to v...
41824e400768SDavid Christensen  * @u:	...if (v + a) is less than u.
41834e400768SDavid Christensen  *
41844e400768SDavid Christensen  * returns TRUE if (v + a) was less than u, and FALSE otherwise.
41854e400768SDavid Christensen  *
41864e400768SDavid Christensen  */
__atomic_add_ifless(ecore_atomic_t * v,int a,int u)41874e400768SDavid Christensen static inline bool __atomic_add_ifless(ecore_atomic_t *v, int a, int u)
41884e400768SDavid Christensen {
41894e400768SDavid Christensen 	int c, old;
41904e400768SDavid Christensen 
41914e400768SDavid Christensen 	c = ECORE_ATOMIC_READ(v);
41924e400768SDavid Christensen 	for (;;) {
41934e400768SDavid Christensen 		if (ECORE_UNLIKELY(c + a >= u))
41944e400768SDavid Christensen 			return FALSE;
41954e400768SDavid Christensen 
41964e400768SDavid Christensen 		old = ECORE_ATOMIC_CMPXCHG((v), c, c + a);
41974e400768SDavid Christensen 		if (ECORE_LIKELY(old == c))
41984e400768SDavid Christensen 			break;
41994e400768SDavid Christensen 		c = old;
42004e400768SDavid Christensen 	}
42014e400768SDavid Christensen 
42024e400768SDavid Christensen 	return TRUE;
42034e400768SDavid Christensen }
42044e400768SDavid Christensen 
42054e400768SDavid Christensen /**
42064e400768SDavid Christensen  * atomic_dec_ifmoe - dec if the result is more or equal than a given value.
42074e400768SDavid Christensen  *
42084e400768SDavid Christensen  * @v:	pointer of type ecore_atomic_t
42094e400768SDavid Christensen  * @a:	the amount to dec from v...
42104e400768SDavid Christensen  * @u:	...if (v - a) is more or equal than u.
42114e400768SDavid Christensen  *
42124e400768SDavid Christensen  * returns TRUE if (v - a) was more or equal than u, and FALSE
42134e400768SDavid Christensen  * otherwise.
42144e400768SDavid Christensen  */
__atomic_dec_ifmoe(ecore_atomic_t * v,int a,int u)42154e400768SDavid Christensen static inline bool __atomic_dec_ifmoe(ecore_atomic_t *v, int a, int u)
42164e400768SDavid Christensen {
42174e400768SDavid Christensen 	int c, old;
42184e400768SDavid Christensen 
42194e400768SDavid Christensen 	c = ECORE_ATOMIC_READ(v);
42204e400768SDavid Christensen 	for (;;) {
42214e400768SDavid Christensen 		if (ECORE_UNLIKELY(c - a < u))
42224e400768SDavid Christensen 			return FALSE;
42234e400768SDavid Christensen 
42244e400768SDavid Christensen 		old = ECORE_ATOMIC_CMPXCHG((v), c, c - a);
42254e400768SDavid Christensen 		if (ECORE_LIKELY(old == c))
42264e400768SDavid Christensen 			break;
42274e400768SDavid Christensen 		c = old;
42284e400768SDavid Christensen 	}
42294e400768SDavid Christensen 
42304e400768SDavid Christensen 	return TRUE;
42314e400768SDavid Christensen }
42324e400768SDavid Christensen 
ecore_credit_pool_get(struct ecore_credit_pool_obj * o,int cnt)42334e400768SDavid Christensen static bool ecore_credit_pool_get(struct ecore_credit_pool_obj *o, int cnt)
42344e400768SDavid Christensen {
42354e400768SDavid Christensen 	bool rc;
42364e400768SDavid Christensen 
42374e400768SDavid Christensen 	ECORE_SMP_MB();
42384e400768SDavid Christensen 	rc = __atomic_dec_ifmoe(&o->credit, cnt, 0);
42394e400768SDavid Christensen 	ECORE_SMP_MB();
42404e400768SDavid Christensen 
42414e400768SDavid Christensen 	return rc;
42424e400768SDavid Christensen }
42434e400768SDavid Christensen 
ecore_credit_pool_put(struct ecore_credit_pool_obj * o,int cnt)42444e400768SDavid Christensen static bool ecore_credit_pool_put(struct ecore_credit_pool_obj *o, int cnt)
42454e400768SDavid Christensen {
42464e400768SDavid Christensen 	bool rc;
42474e400768SDavid Christensen 
42484e400768SDavid Christensen 	ECORE_SMP_MB();
42494e400768SDavid Christensen 
42504e400768SDavid Christensen 	/* Don't let to refill if credit + cnt > pool_sz */
42514e400768SDavid Christensen 	rc = __atomic_add_ifless(&o->credit, cnt, o->pool_sz + 1);
42524e400768SDavid Christensen 
42534e400768SDavid Christensen 	ECORE_SMP_MB();
42544e400768SDavid Christensen 
42554e400768SDavid Christensen 	return rc;
42564e400768SDavid Christensen }
42574e400768SDavid Christensen 
ecore_credit_pool_check(struct ecore_credit_pool_obj * o)42584e400768SDavid Christensen static int ecore_credit_pool_check(struct ecore_credit_pool_obj *o)
42594e400768SDavid Christensen {
42604e400768SDavid Christensen 	int cur_credit;
42614e400768SDavid Christensen 
42624e400768SDavid Christensen 	ECORE_SMP_MB();
42634e400768SDavid Christensen 	cur_credit = ECORE_ATOMIC_READ(&o->credit);
42644e400768SDavid Christensen 
42654e400768SDavid Christensen 	return cur_credit;
42664e400768SDavid Christensen }
42674e400768SDavid Christensen 
ecore_credit_pool_always_TRUE(struct ecore_credit_pool_obj * o,int cnt)42684e400768SDavid Christensen static bool ecore_credit_pool_always_TRUE(struct ecore_credit_pool_obj *o,
42694e400768SDavid Christensen 					  int cnt)
42704e400768SDavid Christensen {
42714e400768SDavid Christensen 	return TRUE;
42724e400768SDavid Christensen }
42734e400768SDavid Christensen 
ecore_credit_pool_get_entry(struct ecore_credit_pool_obj * o,int * offset)42744e400768SDavid Christensen static bool ecore_credit_pool_get_entry(
42754e400768SDavid Christensen 	struct ecore_credit_pool_obj *o,
42764e400768SDavid Christensen 	int *offset)
42774e400768SDavid Christensen {
42784e400768SDavid Christensen 	int idx, vec, i;
42794e400768SDavid Christensen 
42804e400768SDavid Christensen 	*offset = -1;
42814e400768SDavid Christensen 
42824e400768SDavid Christensen 	/* Find "internal cam-offset" then add to base for this object... */
42834e400768SDavid Christensen 	for (vec = 0; vec < ECORE_POOL_VEC_SIZE; vec++) {
42844e400768SDavid Christensen 
42854e400768SDavid Christensen 		/* Skip the current vector if there are no free entries in it */
42864e400768SDavid Christensen 		if (!o->pool_mirror[vec])
42874e400768SDavid Christensen 			continue;
42884e400768SDavid Christensen 
42894e400768SDavid Christensen 		/* If we've got here we are going to find a free entry */
42904e400768SDavid Christensen 		for (idx = vec * BIT_VEC64_ELEM_SZ, i = 0;
42914e400768SDavid Christensen 		      i < BIT_VEC64_ELEM_SZ; idx++, i++)
42924e400768SDavid Christensen 
42934e400768SDavid Christensen 			if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) {
42944e400768SDavid Christensen 				/* Got one!! */
42954e400768SDavid Christensen 				BIT_VEC64_CLEAR_BIT(o->pool_mirror, idx);
42964e400768SDavid Christensen 				*offset = o->base_pool_offset + idx;
42974e400768SDavid Christensen 				return TRUE;
42984e400768SDavid Christensen 			}
42994e400768SDavid Christensen 	}
43004e400768SDavid Christensen 
43014e400768SDavid Christensen 	return FALSE;
43024e400768SDavid Christensen }
43034e400768SDavid Christensen 
ecore_credit_pool_put_entry(struct ecore_credit_pool_obj * o,int offset)43044e400768SDavid Christensen static bool ecore_credit_pool_put_entry(
43054e400768SDavid Christensen 	struct ecore_credit_pool_obj *o,
43064e400768SDavid Christensen 	int offset)
43074e400768SDavid Christensen {
43084e400768SDavid Christensen 	if (offset < o->base_pool_offset)
43094e400768SDavid Christensen 		return FALSE;
43104e400768SDavid Christensen 
43114e400768SDavid Christensen 	offset -= o->base_pool_offset;
43124e400768SDavid Christensen 
43134e400768SDavid Christensen 	if (offset >= o->pool_sz)
43144e400768SDavid Christensen 		return FALSE;
43154e400768SDavid Christensen 
43164e400768SDavid Christensen 	/* Return the entry to the pool */
43174e400768SDavid Christensen 	BIT_VEC64_SET_BIT(o->pool_mirror, offset);
43184e400768SDavid Christensen 
43194e400768SDavid Christensen 	return TRUE;
43204e400768SDavid Christensen }
43214e400768SDavid Christensen 
ecore_credit_pool_put_entry_always_TRUE(struct ecore_credit_pool_obj * o,int offset)43224e400768SDavid Christensen static bool ecore_credit_pool_put_entry_always_TRUE(
43234e400768SDavid Christensen 	struct ecore_credit_pool_obj *o,
43244e400768SDavid Christensen 	int offset)
43254e400768SDavid Christensen {
43264e400768SDavid Christensen 	return TRUE;
43274e400768SDavid Christensen }
43284e400768SDavid Christensen 
ecore_credit_pool_get_entry_always_TRUE(struct ecore_credit_pool_obj * o,int * offset)43294e400768SDavid Christensen static bool ecore_credit_pool_get_entry_always_TRUE(
43304e400768SDavid Christensen 	struct ecore_credit_pool_obj *o,
43314e400768SDavid Christensen 	int *offset)
43324e400768SDavid Christensen {
43334e400768SDavid Christensen 	*offset = -1;
43344e400768SDavid Christensen 	return TRUE;
43354e400768SDavid Christensen }
43364e400768SDavid Christensen /**
43374e400768SDavid Christensen  * ecore_init_credit_pool - initialize credit pool internals.
43384e400768SDavid Christensen  *
43394e400768SDavid Christensen  * @p:
43404e400768SDavid Christensen  * @base:	Base entry in the CAM to use.
43414e400768SDavid Christensen  * @credit:	pool size.
43424e400768SDavid Christensen  *
43434e400768SDavid Christensen  * If base is negative no CAM entries handling will be performed.
43444e400768SDavid Christensen  * If credit is negative pool operations will always succeed (unlimited pool).
43454e400768SDavid Christensen  *
43464e400768SDavid Christensen  */
ecore_init_credit_pool(struct ecore_credit_pool_obj * p,int base,int credit)43474ef8ebfdSDavid C Somayajulu void ecore_init_credit_pool(struct ecore_credit_pool_obj *p,
43484e400768SDavid Christensen 					  int base, int credit)
43494e400768SDavid Christensen {
43504e400768SDavid Christensen 	/* Zero the object first */
43514e400768SDavid Christensen 	ECORE_MEMSET(p, 0, sizeof(*p));
43524e400768SDavid Christensen 
43534e400768SDavid Christensen 	/* Set the table to all 1s */
43544e400768SDavid Christensen 	ECORE_MEMSET(&p->pool_mirror, 0xff, sizeof(p->pool_mirror));
43554e400768SDavid Christensen 
43564e400768SDavid Christensen 	/* Init a pool as full */
43574e400768SDavid Christensen 	ECORE_ATOMIC_SET(&p->credit, credit);
43584e400768SDavid Christensen 
43594e400768SDavid Christensen 	/* The total poll size */
43604e400768SDavid Christensen 	p->pool_sz = credit;
43614e400768SDavid Christensen 
43624e400768SDavid Christensen 	p->base_pool_offset = base;
43634e400768SDavid Christensen 
43644e400768SDavid Christensen 	/* Commit the change */
43654e400768SDavid Christensen 	ECORE_SMP_MB();
43664e400768SDavid Christensen 
43674e400768SDavid Christensen 	p->check = ecore_credit_pool_check;
43684e400768SDavid Christensen 
43694e400768SDavid Christensen 	/* if pool credit is negative - disable the checks */
43704e400768SDavid Christensen 	if (credit >= 0) {
43714e400768SDavid Christensen 		p->put      = ecore_credit_pool_put;
43724e400768SDavid Christensen 		p->get      = ecore_credit_pool_get;
43734e400768SDavid Christensen 		p->put_entry = ecore_credit_pool_put_entry;
43744e400768SDavid Christensen 		p->get_entry = ecore_credit_pool_get_entry;
43754e400768SDavid Christensen 	} else {
43764e400768SDavid Christensen 		p->put      = ecore_credit_pool_always_TRUE;
43774e400768SDavid Christensen 		p->get      = ecore_credit_pool_always_TRUE;
43784e400768SDavid Christensen 		p->put_entry = ecore_credit_pool_put_entry_always_TRUE;
43794e400768SDavid Christensen 		p->get_entry = ecore_credit_pool_get_entry_always_TRUE;
43804e400768SDavid Christensen 	}
43814e400768SDavid Christensen 
43824e400768SDavid Christensen 	/* If base is negative - disable entries handling */
43834e400768SDavid Christensen 	if (base < 0) {
43844e400768SDavid Christensen 		p->put_entry = ecore_credit_pool_put_entry_always_TRUE;
43854e400768SDavid Christensen 		p->get_entry = ecore_credit_pool_get_entry_always_TRUE;
43864e400768SDavid Christensen 	}
43874e400768SDavid Christensen }
43884e400768SDavid Christensen 
ecore_init_mac_credit_pool(struct bxe_softc * sc,struct ecore_credit_pool_obj * p,uint8_t func_id,uint8_t func_num)43894e400768SDavid Christensen void ecore_init_mac_credit_pool(struct bxe_softc *sc,
43904e400768SDavid Christensen 				struct ecore_credit_pool_obj *p, uint8_t func_id,
43914e400768SDavid Christensen 				uint8_t func_num)
43924e400768SDavid Christensen {
43934e400768SDavid Christensen /* TODO: this will be defined in consts as well... */
43944e400768SDavid Christensen #define ECORE_CAM_SIZE_EMUL 5
43954e400768SDavid Christensen 
43964e400768SDavid Christensen 	int cam_sz;
43974e400768SDavid Christensen 
43984e400768SDavid Christensen 	if (CHIP_IS_E1(sc)) {
43994e400768SDavid Christensen 		/* In E1, Multicast is saved in cam... */
44004e400768SDavid Christensen 		if (!CHIP_REV_IS_SLOW(sc))
44014e400768SDavid Christensen 			cam_sz = (MAX_MAC_CREDIT_E1 / 2) - ECORE_MAX_MULTICAST;
44024e400768SDavid Christensen 		else
44034e400768SDavid Christensen 			cam_sz = ECORE_CAM_SIZE_EMUL - ECORE_MAX_EMUL_MULTI;
44044e400768SDavid Christensen 
44054e400768SDavid Christensen 		ecore_init_credit_pool(p, func_id * cam_sz, cam_sz);
44064e400768SDavid Christensen 
44074e400768SDavid Christensen 	} else if (CHIP_IS_E1H(sc)) {
44084e400768SDavid Christensen 		/* CAM credit is equally divided between all active functions
44094e400768SDavid Christensen 		 * on the PORT!.
44104e400768SDavid Christensen 		 */
44114e400768SDavid Christensen 		if ((func_num > 0)) {
44124e400768SDavid Christensen 			if (!CHIP_REV_IS_SLOW(sc))
44134e400768SDavid Christensen 				cam_sz = (MAX_MAC_CREDIT_E1H / (2*func_num));
44144e400768SDavid Christensen 			else
44154e400768SDavid Christensen 				cam_sz = ECORE_CAM_SIZE_EMUL;
44164e400768SDavid Christensen 			ecore_init_credit_pool(p, func_id * cam_sz, cam_sz);
44174e400768SDavid Christensen 		} else {
44184e400768SDavid Christensen 			/* this should never happen! Block MAC operations. */
44194e400768SDavid Christensen 			ecore_init_credit_pool(p, 0, 0);
44204e400768SDavid Christensen 		}
44214e400768SDavid Christensen 	} else {
44224e400768SDavid Christensen 		/*
44234e400768SDavid Christensen 		 * CAM credit is equaly divided between all active functions
44244e400768SDavid Christensen 		 * on the PATH.
44254e400768SDavid Christensen 		 */
44264ef8ebfdSDavid C Somayajulu 		if (func_num > 0) {
44274e400768SDavid Christensen 			if (!CHIP_REV_IS_SLOW(sc))
44284ef8ebfdSDavid C Somayajulu 				cam_sz = PF_MAC_CREDIT_E2(sc, func_num);
44294e400768SDavid Christensen 			else
44304e400768SDavid Christensen 				cam_sz = ECORE_CAM_SIZE_EMUL;
44314e400768SDavid Christensen 
44324e400768SDavid Christensen 			/* No need for CAM entries handling for 57712 and
44334e400768SDavid Christensen 			 * newer.
44344e400768SDavid Christensen 			 */
44354e400768SDavid Christensen 			ecore_init_credit_pool(p, -1, cam_sz);
44364e400768SDavid Christensen 		} else {
44374e400768SDavid Christensen 			/* this should never happen! Block MAC operations. */
44384e400768SDavid Christensen 			ecore_init_credit_pool(p, 0, 0);
44394e400768SDavid Christensen 		}
44404e400768SDavid Christensen 	}
44414e400768SDavid Christensen }
44424e400768SDavid Christensen 
ecore_init_vlan_credit_pool(struct bxe_softc * sc,struct ecore_credit_pool_obj * p,uint8_t func_id,uint8_t func_num)44434e400768SDavid Christensen void ecore_init_vlan_credit_pool(struct bxe_softc *sc,
44444e400768SDavid Christensen 				 struct ecore_credit_pool_obj *p,
44454e400768SDavid Christensen 				 uint8_t func_id,
44464e400768SDavid Christensen 				 uint8_t func_num)
44474e400768SDavid Christensen {
44484e400768SDavid Christensen 	if (CHIP_IS_E1x(sc)) {
44494e400768SDavid Christensen 		/* There is no VLAN credit in HW on 57710 and 57711 only
44504e400768SDavid Christensen 		 * MAC / MAC-VLAN can be set
44514e400768SDavid Christensen 		 */
44524e400768SDavid Christensen 		ecore_init_credit_pool(p, 0, -1);
44534e400768SDavid Christensen 	} else {
44544e400768SDavid Christensen 		/* CAM credit is equally divided between all active functions
44554e400768SDavid Christensen 		 * on the PATH.
44564e400768SDavid Christensen 		 */
44574e400768SDavid Christensen 		if (func_num > 0) {
44584ef8ebfdSDavid C Somayajulu 			int credit = PF_VLAN_CREDIT_E2(sc, func_num);
44594ef8ebfdSDavid C Somayajulu 
44604ef8ebfdSDavid C Somayajulu 			ecore_init_credit_pool(p, -1/*unused for E2*/, credit);
44614e400768SDavid Christensen 		} else
44624e400768SDavid Christensen 			/* this should never happen! Block VLAN operations. */
44634e400768SDavid Christensen 			ecore_init_credit_pool(p, 0, 0);
44644e400768SDavid Christensen 	}
44654e400768SDavid Christensen }
44664e400768SDavid Christensen 
44674e400768SDavid Christensen /****************** RSS Configuration ******************/
44684e400768SDavid Christensen 
44694e400768SDavid Christensen /**
44704e400768SDavid Christensen  * ecore_setup_rss - configure RSS
44714e400768SDavid Christensen  *
44724e400768SDavid Christensen  * @sc:		device handle
44734e400768SDavid Christensen  * @p:		rss configuration
44744e400768SDavid Christensen  *
44754e400768SDavid Christensen  * sends on UPDATE ramrod for that matter.
44764e400768SDavid Christensen  */
ecore_setup_rss(struct bxe_softc * sc,struct ecore_config_rss_params * p)44774e400768SDavid Christensen static int ecore_setup_rss(struct bxe_softc *sc,
44784e400768SDavid Christensen 			   struct ecore_config_rss_params *p)
44794e400768SDavid Christensen {
44804e400768SDavid Christensen 	struct ecore_rss_config_obj *o = p->rss_obj;
44814e400768SDavid Christensen 	struct ecore_raw_obj *r = &o->raw;
44824e400768SDavid Christensen 	struct eth_rss_update_ramrod_data *data =
44834e400768SDavid Christensen 		(struct eth_rss_update_ramrod_data *)(r->rdata);
44844ef8ebfdSDavid C Somayajulu 	uint16_t caps = 0;
44854e400768SDavid Christensen 	uint8_t rss_mode = 0;
44864e400768SDavid Christensen 	int rc;
44874e400768SDavid Christensen 
44884e400768SDavid Christensen 	ECORE_MEMSET(data, 0, sizeof(*data));
44894e400768SDavid Christensen 
44904e400768SDavid Christensen 	ECORE_MSG(sc, "Configuring RSS\n");
44914e400768SDavid Christensen 
44924e400768SDavid Christensen 	/* Set an echo field */
44934e400768SDavid Christensen 	data->echo = ECORE_CPU_TO_LE32((r->cid & ECORE_SWCID_MASK) |
44944e400768SDavid Christensen 				 (r->state << ECORE_SWCID_SHIFT));
44954e400768SDavid Christensen 
44964e400768SDavid Christensen 	/* RSS mode */
44974e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_RSS_MODE_DISABLED, &p->rss_flags))
44984e400768SDavid Christensen 		rss_mode = ETH_RSS_MODE_DISABLED;
44994e400768SDavid Christensen 	else if (ECORE_TEST_BIT(ECORE_RSS_MODE_REGULAR, &p->rss_flags))
45004e400768SDavid Christensen 		rss_mode = ETH_RSS_MODE_REGULAR;
45014e400768SDavid Christensen 
45024e400768SDavid Christensen 	data->rss_mode = rss_mode;
45034e400768SDavid Christensen 
45044e400768SDavid Christensen 	ECORE_MSG(sc, "rss_mode=%d\n", rss_mode);
45054e400768SDavid Christensen 
45064e400768SDavid Christensen 	/* RSS capabilities */
45074e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_RSS_IPV4, &p->rss_flags))
45084ef8ebfdSDavid C Somayajulu 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY;
45094e400768SDavid Christensen 
45104e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_RSS_IPV4_TCP, &p->rss_flags))
45114ef8ebfdSDavid C Somayajulu 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY;
45124e400768SDavid Christensen 
45134e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_RSS_IPV4_UDP, &p->rss_flags))
45144ef8ebfdSDavid C Somayajulu 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY;
45154e400768SDavid Christensen 
45164e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_RSS_IPV6, &p->rss_flags))
45174ef8ebfdSDavid C Somayajulu 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY;
45184e400768SDavid Christensen 
45194e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_RSS_IPV6_TCP, &p->rss_flags))
45204ef8ebfdSDavid C Somayajulu 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY;
45214e400768SDavid Christensen 
45224e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_RSS_IPV6_UDP, &p->rss_flags))
45234ef8ebfdSDavid C Somayajulu 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY;
45244e400768SDavid Christensen 
45254ef8ebfdSDavid C Somayajulu 	if (ECORE_TEST_BIT(ECORE_RSS_IPV4_VXLAN, &p->rss_flags))
45264ef8ebfdSDavid C Somayajulu 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_VXLAN_CAPABILITY;
45274ef8ebfdSDavid C Somayajulu 
45284ef8ebfdSDavid C Somayajulu 	if (ECORE_TEST_BIT(ECORE_RSS_IPV6_VXLAN, &p->rss_flags))
45294ef8ebfdSDavid C Somayajulu 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_VXLAN_CAPABILITY;
45304ef8ebfdSDavid C Somayajulu 
45314ef8ebfdSDavid C Somayajulu 	if (ECORE_TEST_BIT(ECORE_RSS_TUNN_INNER_HDRS, &p->rss_flags))
45324ef8ebfdSDavid C Somayajulu 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_TUNN_INNER_HDRS_CAPABILITY;
45334ef8ebfdSDavid C Somayajulu 
45344ef8ebfdSDavid C Somayajulu 	/* RSS keys */
45354ef8ebfdSDavid C Somayajulu 	if (ECORE_TEST_BIT(ECORE_RSS_SET_SRCH, &p->rss_flags)) {
45364ef8ebfdSDavid C Somayajulu 		ECORE_MEMCPY(&data->rss_key[0], &p->rss_key[0],
45374ef8ebfdSDavid C Somayajulu 		       sizeof(data->rss_key));
45384ef8ebfdSDavid C Somayajulu 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
45394e400768SDavid Christensen 	}
45404e400768SDavid Christensen 
45414ef8ebfdSDavid C Somayajulu 	data->capabilities = ECORE_CPU_TO_LE16(caps);
45424ef8ebfdSDavid C Somayajulu 
45434e400768SDavid Christensen 	/* Hashing mask */
45444e400768SDavid Christensen 	data->rss_result_mask = p->rss_result_mask;
45454e400768SDavid Christensen 
45464e400768SDavid Christensen 	/* RSS engine ID */
45474e400768SDavid Christensen 	data->rss_engine_id = o->engine_id;
45484e400768SDavid Christensen 
45494e400768SDavid Christensen 	ECORE_MSG(sc, "rss_engine_id=%d\n", data->rss_engine_id);
45504e400768SDavid Christensen 
45514e400768SDavid Christensen 	/* Indirection table */
45524e400768SDavid Christensen 	ECORE_MEMCPY(data->indirection_table, p->ind_table,
45534e400768SDavid Christensen 		  T_ETH_INDIRECTION_TABLE_SIZE);
45544e400768SDavid Christensen 
45554e400768SDavid Christensen 	/* Remember the last configuration */
45564e400768SDavid Christensen 	ECORE_MEMCPY(o->ind_table, p->ind_table, T_ETH_INDIRECTION_TABLE_SIZE);
45574e400768SDavid Christensen 
45584e400768SDavid Christensen 
45594ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
45604ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
45614e400768SDavid Christensen 	 * and updating of the SPQ producer which involves a memory
45624ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
45634ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
45644e400768SDavid Christensen 	 */
45654e400768SDavid Christensen 
45664e400768SDavid Christensen 	/* Send a ramrod */
45674e400768SDavid Christensen 	rc = ecore_sp_post(sc,
45684e400768SDavid Christensen 			     RAMROD_CMD_ID_ETH_RSS_UPDATE,
45694e400768SDavid Christensen 			     r->cid,
45704e400768SDavid Christensen 			     r->rdata_mapping,
45714e400768SDavid Christensen 			     ETH_CONNECTION_TYPE);
45724e400768SDavid Christensen 
45734e400768SDavid Christensen 	if (rc < 0)
45744e400768SDavid Christensen 		return rc;
45754e400768SDavid Christensen 
45764e400768SDavid Christensen 	return ECORE_PENDING;
45774e400768SDavid Christensen }
45784e400768SDavid Christensen 
ecore_get_rss_ind_table(struct ecore_rss_config_obj * rss_obj,uint8_t * ind_table)45794e400768SDavid Christensen void ecore_get_rss_ind_table(struct ecore_rss_config_obj *rss_obj,
45804e400768SDavid Christensen 			     uint8_t *ind_table)
45814e400768SDavid Christensen {
45824e400768SDavid Christensen 	ECORE_MEMCPY(ind_table, rss_obj->ind_table, sizeof(rss_obj->ind_table));
45834e400768SDavid Christensen }
45844e400768SDavid Christensen 
ecore_config_rss(struct bxe_softc * sc,struct ecore_config_rss_params * p)45854e400768SDavid Christensen int ecore_config_rss(struct bxe_softc *sc,
45864e400768SDavid Christensen 		     struct ecore_config_rss_params *p)
45874e400768SDavid Christensen {
45884e400768SDavid Christensen 	int rc;
45894e400768SDavid Christensen 	struct ecore_rss_config_obj *o = p->rss_obj;
45904e400768SDavid Christensen 	struct ecore_raw_obj *r = &o->raw;
45914e400768SDavid Christensen 
45924e400768SDavid Christensen 	/* Do nothing if only driver cleanup was requested */
4593ae02949dSEric Davis 	if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
4594ae02949dSEric Davis 		ECORE_MSG(sc, "Not configuring RSS ramrod_flags=%lx\n",
4595ae02949dSEric Davis 			  p->ramrod_flags);
45964e400768SDavid Christensen 		return ECORE_SUCCESS;
4597ae02949dSEric Davis 	}
45984e400768SDavid Christensen 
45994e400768SDavid Christensen 	r->set_pending(r);
46004e400768SDavid Christensen 
46014e400768SDavid Christensen 	rc = o->config_rss(sc, p);
46024e400768SDavid Christensen 	if (rc < 0) {
46034e400768SDavid Christensen 		r->clear_pending(r);
46044e400768SDavid Christensen 		return rc;
46054e400768SDavid Christensen 	}
46064e400768SDavid Christensen 
46074e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_COMP_WAIT, &p->ramrod_flags))
46084e400768SDavid Christensen 		rc = r->wait_comp(sc, r);
46094e400768SDavid Christensen 
46104e400768SDavid Christensen 	return rc;
46114e400768SDavid Christensen }
46124e400768SDavid Christensen 
ecore_init_rss_config_obj(struct bxe_softc * sc,struct ecore_rss_config_obj * rss_obj,uint8_t cl_id,uint32_t cid,uint8_t func_id,uint8_t engine_id,void * rdata,ecore_dma_addr_t rdata_mapping,int state,unsigned long * pstate,ecore_obj_type type)46134e400768SDavid Christensen void ecore_init_rss_config_obj(struct bxe_softc *sc,
46144e400768SDavid Christensen 			       struct ecore_rss_config_obj *rss_obj,
46154e400768SDavid Christensen 			       uint8_t cl_id, uint32_t cid, uint8_t func_id, uint8_t engine_id,
46164e400768SDavid Christensen 			       void *rdata, ecore_dma_addr_t rdata_mapping,
46174e400768SDavid Christensen 			       int state, unsigned long *pstate,
46184e400768SDavid Christensen 			       ecore_obj_type type)
46194e400768SDavid Christensen {
46204e400768SDavid Christensen 	ecore_init_raw_obj(&rss_obj->raw, cl_id, cid, func_id, rdata,
46214e400768SDavid Christensen 			   rdata_mapping, state, pstate, type);
46224e400768SDavid Christensen 
46234e400768SDavid Christensen 	rss_obj->engine_id  = engine_id;
46244e400768SDavid Christensen 	rss_obj->config_rss = ecore_setup_rss;
46254e400768SDavid Christensen }
46264e400768SDavid Christensen 
46275e33becaSEric Davis 
46284e400768SDavid Christensen /********************** Queue state object ***********************************/
46294e400768SDavid Christensen 
46304e400768SDavid Christensen /**
46314e400768SDavid Christensen  * ecore_queue_state_change - perform Queue state change transition
46324e400768SDavid Christensen  *
46334e400768SDavid Christensen  * @sc:		device handle
46344e400768SDavid Christensen  * @params:	parameters to perform the transition
46354e400768SDavid Christensen  *
46364e400768SDavid Christensen  * returns 0 in case of successfully completed transition, negative error
46374e400768SDavid Christensen  * code in case of failure, positive (EBUSY) value if there is a completion
46384e400768SDavid Christensen  * to that is still pending (possible only if RAMROD_COMP_WAIT is
46394e400768SDavid Christensen  * not set in params->ramrod_flags for asynchronous commands).
46404e400768SDavid Christensen  *
46414e400768SDavid Christensen  */
ecore_queue_state_change(struct bxe_softc * sc,struct ecore_queue_state_params * params)46424e400768SDavid Christensen int ecore_queue_state_change(struct bxe_softc *sc,
46434e400768SDavid Christensen 			     struct ecore_queue_state_params *params)
46444e400768SDavid Christensen {
46454e400768SDavid Christensen 	struct ecore_queue_sp_obj *o = params->q_obj;
46464e400768SDavid Christensen 	int rc, pending_bit;
46474e400768SDavid Christensen 	unsigned long *pending = &o->pending;
46484e400768SDavid Christensen 
46494e400768SDavid Christensen 	/* Check that the requested transition is legal */
46504e400768SDavid Christensen 	rc = o->check_transition(sc, o, params);
46514e400768SDavid Christensen 	if (rc) {
46524e400768SDavid Christensen 		ECORE_ERR("check transition returned an error. rc %d\n", rc);
46534e400768SDavid Christensen 		return ECORE_INVAL;
46544e400768SDavid Christensen 	}
46554e400768SDavid Christensen 
46564e400768SDavid Christensen 	/* Set "pending" bit */
46574e400768SDavid Christensen 	ECORE_MSG(sc, "pending bit was=%lx\n", o->pending);
46584e400768SDavid Christensen 	pending_bit = o->set_pending(o, params);
46594e400768SDavid Christensen 	ECORE_MSG(sc, "pending bit now=%lx\n", o->pending);
46604e400768SDavid Christensen 
46614e400768SDavid Christensen 	/* Don't send a command if only driver cleanup was requested */
46624e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags))
46634e400768SDavid Christensen 		o->complete_cmd(sc, o, pending_bit);
46644e400768SDavid Christensen 	else {
46654e400768SDavid Christensen 		/* Send a ramrod */
46664e400768SDavid Christensen 		rc = o->send_cmd(sc, params);
46674e400768SDavid Christensen 		if (rc) {
46684e400768SDavid Christensen 			o->next_state = ECORE_Q_STATE_MAX;
46694e400768SDavid Christensen 			ECORE_CLEAR_BIT(pending_bit, pending);
46704e400768SDavid Christensen 			ECORE_SMP_MB_AFTER_CLEAR_BIT();
46714e400768SDavid Christensen 			return rc;
46724e400768SDavid Christensen 		}
46734e400768SDavid Christensen 
46744e400768SDavid Christensen 		if (ECORE_TEST_BIT(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
46754e400768SDavid Christensen 			rc = o->wait_comp(sc, o, pending_bit);
46764e400768SDavid Christensen 			if (rc)
46774e400768SDavid Christensen 				return rc;
46784e400768SDavid Christensen 
46794e400768SDavid Christensen 			return ECORE_SUCCESS;
46804e400768SDavid Christensen 		}
46814e400768SDavid Christensen 	}
46824e400768SDavid Christensen 
46834e400768SDavid Christensen 	return ECORE_RET_PENDING(pending_bit, pending);
46844e400768SDavid Christensen }
46854e400768SDavid Christensen 
ecore_queue_set_pending(struct ecore_queue_sp_obj * obj,struct ecore_queue_state_params * params)46864e400768SDavid Christensen static int ecore_queue_set_pending(struct ecore_queue_sp_obj *obj,
46874e400768SDavid Christensen 				   struct ecore_queue_state_params *params)
46884e400768SDavid Christensen {
46894e400768SDavid Christensen 	enum ecore_queue_cmd cmd = params->cmd, bit;
46904e400768SDavid Christensen 
46914e400768SDavid Christensen 	/* ACTIVATE and DEACTIVATE commands are implemented on top of
46924e400768SDavid Christensen 	 * UPDATE command.
46934e400768SDavid Christensen 	 */
46944e400768SDavid Christensen 	if ((cmd == ECORE_Q_CMD_ACTIVATE) ||
46954e400768SDavid Christensen 	    (cmd == ECORE_Q_CMD_DEACTIVATE))
46964e400768SDavid Christensen 		bit = ECORE_Q_CMD_UPDATE;
46974e400768SDavid Christensen 	else
46984e400768SDavid Christensen 		bit = cmd;
46994e400768SDavid Christensen 
47004e400768SDavid Christensen 	ECORE_SET_BIT(bit, &obj->pending);
47014e400768SDavid Christensen 	return bit;
47024e400768SDavid Christensen }
47034e400768SDavid Christensen 
ecore_queue_wait_comp(struct bxe_softc * sc,struct ecore_queue_sp_obj * o,enum ecore_queue_cmd cmd)47044e400768SDavid Christensen static int ecore_queue_wait_comp(struct bxe_softc *sc,
47054e400768SDavid Christensen 				 struct ecore_queue_sp_obj *o,
47064e400768SDavid Christensen 				 enum ecore_queue_cmd cmd)
47074e400768SDavid Christensen {
47084e400768SDavid Christensen 	return ecore_state_wait(sc, cmd, &o->pending);
47094e400768SDavid Christensen }
47104e400768SDavid Christensen 
47114e400768SDavid Christensen /**
47124e400768SDavid Christensen  * ecore_queue_comp_cmd - complete the state change command.
47134e400768SDavid Christensen  *
47144e400768SDavid Christensen  * @sc:		device handle
47154e400768SDavid Christensen  * @o:
47164e400768SDavid Christensen  * @cmd:
47174e400768SDavid Christensen  *
47184e400768SDavid Christensen  * Checks that the arrived completion is expected.
47194e400768SDavid Christensen  */
ecore_queue_comp_cmd(struct bxe_softc * sc,struct ecore_queue_sp_obj * o,enum ecore_queue_cmd cmd)47204e400768SDavid Christensen static int ecore_queue_comp_cmd(struct bxe_softc *sc,
47214e400768SDavid Christensen 				struct ecore_queue_sp_obj *o,
47224e400768SDavid Christensen 				enum ecore_queue_cmd cmd)
47234e400768SDavid Christensen {
47244e400768SDavid Christensen 	unsigned long cur_pending = o->pending;
47254e400768SDavid Christensen 
47264e400768SDavid Christensen 	if (!ECORE_TEST_AND_CLEAR_BIT(cmd, &cur_pending)) {
47274e400768SDavid Christensen 		ECORE_ERR("Bad MC reply %d for queue %d in state %d pending 0x%lx, next_state %d\n",
47284e400768SDavid Christensen 			  cmd, o->cids[ECORE_PRIMARY_CID_INDEX],
47294e400768SDavid Christensen 			  o->state, cur_pending, o->next_state);
47304e400768SDavid Christensen 		return ECORE_INVAL;
47314e400768SDavid Christensen 	}
47324e400768SDavid Christensen 
47334e400768SDavid Christensen 	if (o->next_tx_only >= o->max_cos)
47344e400768SDavid Christensen 		/* >= because tx only must always be smaller than cos since the
47354e400768SDavid Christensen 		 * primary connection supports COS 0
47364e400768SDavid Christensen 		 */
47374e400768SDavid Christensen 		ECORE_ERR("illegal value for next tx_only: %d. max cos was %d",
47384e400768SDavid Christensen 			  o->next_tx_only, o->max_cos);
47394e400768SDavid Christensen 
47404e400768SDavid Christensen 	ECORE_MSG(sc,
47414e400768SDavid Christensen 		  "Completing command %d for queue %d, setting state to %d\n",
47424e400768SDavid Christensen 		  cmd, o->cids[ECORE_PRIMARY_CID_INDEX], o->next_state);
47434e400768SDavid Christensen 
47444e400768SDavid Christensen 	if (o->next_tx_only)  /* print num tx-only if any exist */
47454e400768SDavid Christensen 		ECORE_MSG(sc, "primary cid %d: num tx-only cons %d\n",
47464e400768SDavid Christensen 			  o->cids[ECORE_PRIMARY_CID_INDEX], o->next_tx_only);
47474e400768SDavid Christensen 
47484e400768SDavid Christensen 	o->state = o->next_state;
47494e400768SDavid Christensen 	o->num_tx_only = o->next_tx_only;
47504e400768SDavid Christensen 	o->next_state = ECORE_Q_STATE_MAX;
47514e400768SDavid Christensen 
47524e400768SDavid Christensen 	/* It's important that o->state and o->next_state are
47534e400768SDavid Christensen 	 * updated before o->pending.
47544e400768SDavid Christensen 	 */
47554e400768SDavid Christensen 	wmb();
47564e400768SDavid Christensen 
47574e400768SDavid Christensen 	ECORE_CLEAR_BIT(cmd, &o->pending);
47584e400768SDavid Christensen 	ECORE_SMP_MB_AFTER_CLEAR_BIT();
47594e400768SDavid Christensen 
47604e400768SDavid Christensen 	return ECORE_SUCCESS;
47614e400768SDavid Christensen }
47624e400768SDavid Christensen 
ecore_q_fill_setup_data_e2(struct bxe_softc * sc,struct ecore_queue_state_params * cmd_params,struct client_init_ramrod_data * data)47634e400768SDavid Christensen static void ecore_q_fill_setup_data_e2(struct bxe_softc *sc,
47644e400768SDavid Christensen 				struct ecore_queue_state_params *cmd_params,
47654e400768SDavid Christensen 				struct client_init_ramrod_data *data)
47664e400768SDavid Christensen {
47674e400768SDavid Christensen 	struct ecore_queue_setup_params *params = &cmd_params->params.setup;
47684e400768SDavid Christensen 
47694e400768SDavid Christensen 	/* Rx data */
47704e400768SDavid Christensen 
47714e400768SDavid Christensen 	/* IPv6 TPA supported for E2 and above only */
47724e400768SDavid Christensen 	data->rx.tpa_en |= ECORE_TEST_BIT(ECORE_Q_FLG_TPA_IPV6,
47734e400768SDavid Christensen 					  &params->flags) *
47744e400768SDavid Christensen 				CLIENT_INIT_RX_DATA_TPA_EN_IPV6;
47754e400768SDavid Christensen }
47764e400768SDavid Christensen 
ecore_q_fill_init_general_data(struct bxe_softc * sc,struct ecore_queue_sp_obj * o,struct ecore_general_setup_params * params,struct client_init_general_data * gen_data,unsigned long * flags)47774e400768SDavid Christensen static void ecore_q_fill_init_general_data(struct bxe_softc *sc,
47784e400768SDavid Christensen 				struct ecore_queue_sp_obj *o,
47794e400768SDavid Christensen 				struct ecore_general_setup_params *params,
47804e400768SDavid Christensen 				struct client_init_general_data *gen_data,
47814e400768SDavid Christensen 				unsigned long *flags)
47824e400768SDavid Christensen {
47834e400768SDavid Christensen 	gen_data->client_id = o->cl_id;
47844e400768SDavid Christensen 
47854e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_Q_FLG_STATS, flags)) {
47864e400768SDavid Christensen 		gen_data->statistics_counter_id =
47874e400768SDavid Christensen 					params->stat_id;
47884e400768SDavid Christensen 		gen_data->statistics_en_flg = 1;
47894e400768SDavid Christensen 		gen_data->statistics_zero_flg =
47904e400768SDavid Christensen 			ECORE_TEST_BIT(ECORE_Q_FLG_ZERO_STATS, flags);
47914e400768SDavid Christensen 	} else
47924e400768SDavid Christensen 		gen_data->statistics_counter_id =
47934e400768SDavid Christensen 					DISABLE_STATISTIC_COUNTER_ID_VALUE;
47944e400768SDavid Christensen 
47954e400768SDavid Christensen 	gen_data->is_fcoe_flg = ECORE_TEST_BIT(ECORE_Q_FLG_FCOE,
47964e400768SDavid Christensen 						   flags);
47974e400768SDavid Christensen 	gen_data->activate_flg = ECORE_TEST_BIT(ECORE_Q_FLG_ACTIVE,
47984e400768SDavid Christensen 						    flags);
47994e400768SDavid Christensen 	gen_data->sp_client_id = params->spcl_id;
48004e400768SDavid Christensen 	gen_data->mtu = ECORE_CPU_TO_LE16(params->mtu);
48014e400768SDavid Christensen 	gen_data->func_id = o->func_id;
48024e400768SDavid Christensen 
48034e400768SDavid Christensen 	gen_data->cos = params->cos;
48044e400768SDavid Christensen 
48054e400768SDavid Christensen 	gen_data->traffic_type =
48064e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_FCOE, flags) ?
48074e400768SDavid Christensen 		LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
48084e400768SDavid Christensen 
48094ef8ebfdSDavid C Somayajulu 	gen_data->fp_hsi_ver = params->fp_hsi;
48104ef8ebfdSDavid C Somayajulu 
48114e400768SDavid Christensen 	ECORE_MSG(sc, "flags: active %d, cos %d, stats en %d\n",
48124e400768SDavid Christensen 		  gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg);
48134e400768SDavid Christensen }
48144e400768SDavid Christensen 
ecore_q_fill_init_tx_data(struct ecore_queue_sp_obj * o,struct ecore_txq_setup_params * params,struct client_init_tx_data * tx_data,unsigned long * flags)48154e400768SDavid Christensen static void ecore_q_fill_init_tx_data(struct ecore_queue_sp_obj *o,
48164e400768SDavid Christensen 				struct ecore_txq_setup_params *params,
48174e400768SDavid Christensen 				struct client_init_tx_data *tx_data,
48184e400768SDavid Christensen 				unsigned long *flags)
48194e400768SDavid Christensen {
48204e400768SDavid Christensen 	tx_data->enforce_security_flg =
48214e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_TX_SEC, flags);
48224e400768SDavid Christensen 	tx_data->default_vlan =
48234e400768SDavid Christensen 		ECORE_CPU_TO_LE16(params->default_vlan);
48244e400768SDavid Christensen 	tx_data->default_vlan_flg =
48254e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_DEF_VLAN, flags);
48264e400768SDavid Christensen 	tx_data->tx_switching_flg =
48274e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_TX_SWITCH, flags);
48284e400768SDavid Christensen 	tx_data->anti_spoofing_flg =
48294e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_ANTI_SPOOF, flags);
48304e400768SDavid Christensen 	tx_data->force_default_pri_flg =
48314e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_FORCE_DEFAULT_PRI, flags);
48324e400768SDavid Christensen 	tx_data->refuse_outband_vlan_flg =
48334e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_REFUSE_OUTBAND_VLAN, flags);
48344e400768SDavid Christensen 	tx_data->tunnel_lso_inc_ip_id =
48354e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_TUN_INC_INNER_IP_ID, flags);
48364e400768SDavid Christensen 	tx_data->tunnel_non_lso_pcsum_location =
48374e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_PCSUM_ON_PKT, flags) ? CSUM_ON_PKT :
48384e400768SDavid Christensen 							    CSUM_ON_BD;
48394e400768SDavid Christensen 
48404e400768SDavid Christensen 	tx_data->tx_status_block_id = params->fw_sb_id;
48414e400768SDavid Christensen 	tx_data->tx_sb_index_number = params->sb_cq_index;
48424e400768SDavid Christensen 	tx_data->tss_leading_client_id = params->tss_leading_cl_id;
48434e400768SDavid Christensen 
48444e400768SDavid Christensen 	tx_data->tx_bd_page_base.lo =
48454e400768SDavid Christensen 		ECORE_CPU_TO_LE32(U64_LO(params->dscr_map));
48464e400768SDavid Christensen 	tx_data->tx_bd_page_base.hi =
48474e400768SDavid Christensen 		ECORE_CPU_TO_LE32(U64_HI(params->dscr_map));
48484e400768SDavid Christensen 
48494e400768SDavid Christensen 	/* Don't configure any Tx switching mode during queue SETUP */
48504e400768SDavid Christensen 	tx_data->state = 0;
48514e400768SDavid Christensen }
48524e400768SDavid Christensen 
ecore_q_fill_init_pause_data(struct ecore_queue_sp_obj * o,struct rxq_pause_params * params,struct client_init_rx_data * rx_data)48534e400768SDavid Christensen static void ecore_q_fill_init_pause_data(struct ecore_queue_sp_obj *o,
48544e400768SDavid Christensen 				struct rxq_pause_params *params,
48554e400768SDavid Christensen 				struct client_init_rx_data *rx_data)
48564e400768SDavid Christensen {
48574e400768SDavid Christensen 	/* flow control data */
48584e400768SDavid Christensen 	rx_data->cqe_pause_thr_low = ECORE_CPU_TO_LE16(params->rcq_th_lo);
48594e400768SDavid Christensen 	rx_data->cqe_pause_thr_high = ECORE_CPU_TO_LE16(params->rcq_th_hi);
48604e400768SDavid Christensen 	rx_data->bd_pause_thr_low = ECORE_CPU_TO_LE16(params->bd_th_lo);
48614e400768SDavid Christensen 	rx_data->bd_pause_thr_high = ECORE_CPU_TO_LE16(params->bd_th_hi);
48624e400768SDavid Christensen 	rx_data->sge_pause_thr_low = ECORE_CPU_TO_LE16(params->sge_th_lo);
48634e400768SDavid Christensen 	rx_data->sge_pause_thr_high = ECORE_CPU_TO_LE16(params->sge_th_hi);
48644e400768SDavid Christensen 	rx_data->rx_cos_mask = ECORE_CPU_TO_LE16(params->pri_map);
48654e400768SDavid Christensen }
48664e400768SDavid Christensen 
ecore_q_fill_init_rx_data(struct ecore_queue_sp_obj * o,struct ecore_rxq_setup_params * params,struct client_init_rx_data * rx_data,unsigned long * flags)48674e400768SDavid Christensen static void ecore_q_fill_init_rx_data(struct ecore_queue_sp_obj *o,
48684e400768SDavid Christensen 				struct ecore_rxq_setup_params *params,
48694e400768SDavid Christensen 				struct client_init_rx_data *rx_data,
48704e400768SDavid Christensen 				unsigned long *flags)
48714e400768SDavid Christensen {
48724e400768SDavid Christensen 	rx_data->tpa_en = ECORE_TEST_BIT(ECORE_Q_FLG_TPA, flags) *
48734e400768SDavid Christensen 				CLIENT_INIT_RX_DATA_TPA_EN_IPV4;
48744e400768SDavid Christensen 	rx_data->tpa_en |= ECORE_TEST_BIT(ECORE_Q_FLG_TPA_GRO, flags) *
48754e400768SDavid Christensen 				CLIENT_INIT_RX_DATA_TPA_MODE;
48764e400768SDavid Christensen 	rx_data->vmqueue_mode_en_flg = 0;
48774e400768SDavid Christensen 
48784e400768SDavid Christensen 	rx_data->extra_data_over_sgl_en_flg =
48794e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_OOO, flags);
48804e400768SDavid Christensen 	rx_data->cache_line_alignment_log_size =
48814e400768SDavid Christensen 		params->cache_line_log;
48824e400768SDavid Christensen 	rx_data->enable_dynamic_hc =
48834e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_DHC, flags);
48844e400768SDavid Christensen 	rx_data->max_sges_for_packet = params->max_sges_pkt;
48854e400768SDavid Christensen 	rx_data->client_qzone_id = params->cl_qzone_id;
48864e400768SDavid Christensen 	rx_data->max_agg_size = ECORE_CPU_TO_LE16(params->tpa_agg_sz);
48874e400768SDavid Christensen 
48884e400768SDavid Christensen 	/* Always start in DROP_ALL mode */
48894e400768SDavid Christensen 	rx_data->state = ECORE_CPU_TO_LE16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL |
48904e400768SDavid Christensen 				     CLIENT_INIT_RX_DATA_MCAST_DROP_ALL);
48914e400768SDavid Christensen 
48924e400768SDavid Christensen 	/* We don't set drop flags */
48934e400768SDavid Christensen 	rx_data->drop_ip_cs_err_flg = 0;
48944e400768SDavid Christensen 	rx_data->drop_tcp_cs_err_flg = 0;
48954e400768SDavid Christensen 	rx_data->drop_ttl0_flg = 0;
48964e400768SDavid Christensen 	rx_data->drop_udp_cs_err_flg = 0;
48974e400768SDavid Christensen 	rx_data->inner_vlan_removal_enable_flg =
48984e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_VLAN, flags);
48994e400768SDavid Christensen 	rx_data->outer_vlan_removal_enable_flg =
49004e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_OV, flags);
49014e400768SDavid Christensen 	rx_data->status_block_id = params->fw_sb_id;
49024e400768SDavid Christensen 	rx_data->rx_sb_index_number = params->sb_cq_index;
49034e400768SDavid Christensen 	rx_data->max_tpa_queues = params->max_tpa_queues;
49044e400768SDavid Christensen 	rx_data->max_bytes_on_bd = ECORE_CPU_TO_LE16(params->buf_sz);
49054e400768SDavid Christensen 	rx_data->sge_buff_size = ECORE_CPU_TO_LE16(params->sge_buf_sz);
49064e400768SDavid Christensen 	rx_data->bd_page_base.lo =
49074e400768SDavid Christensen 		ECORE_CPU_TO_LE32(U64_LO(params->dscr_map));
49084e400768SDavid Christensen 	rx_data->bd_page_base.hi =
49094e400768SDavid Christensen 		ECORE_CPU_TO_LE32(U64_HI(params->dscr_map));
49104e400768SDavid Christensen 	rx_data->sge_page_base.lo =
49114e400768SDavid Christensen 		ECORE_CPU_TO_LE32(U64_LO(params->sge_map));
49124e400768SDavid Christensen 	rx_data->sge_page_base.hi =
49134e400768SDavid Christensen 		ECORE_CPU_TO_LE32(U64_HI(params->sge_map));
49144e400768SDavid Christensen 	rx_data->cqe_page_base.lo =
49154e400768SDavid Christensen 		ECORE_CPU_TO_LE32(U64_LO(params->rcq_map));
49164e400768SDavid Christensen 	rx_data->cqe_page_base.hi =
49174e400768SDavid Christensen 		ECORE_CPU_TO_LE32(U64_HI(params->rcq_map));
49184e400768SDavid Christensen 	rx_data->is_leading_rss = ECORE_TEST_BIT(ECORE_Q_FLG_LEADING_RSS,
49194e400768SDavid Christensen 						 flags);
49204e400768SDavid Christensen 
49214e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_Q_FLG_MCAST, flags)) {
49224e400768SDavid Christensen 		rx_data->approx_mcast_engine_id = params->mcast_engine_id;
49234e400768SDavid Christensen 		rx_data->is_approx_mcast = 1;
49244e400768SDavid Christensen 	}
49254e400768SDavid Christensen 
49264e400768SDavid Christensen 	rx_data->rss_engine_id = params->rss_engine_id;
49274e400768SDavid Christensen 
49284e400768SDavid Christensen 	/* silent vlan removal */
49294e400768SDavid Christensen 	rx_data->silent_vlan_removal_flg =
49304e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_FLG_SILENT_VLAN_REM, flags);
49314e400768SDavid Christensen 	rx_data->silent_vlan_value =
49324e400768SDavid Christensen 		ECORE_CPU_TO_LE16(params->silent_removal_value);
49334e400768SDavid Christensen 	rx_data->silent_vlan_mask =
49344e400768SDavid Christensen 		ECORE_CPU_TO_LE16(params->silent_removal_mask);
49354e400768SDavid Christensen }
49364e400768SDavid Christensen 
49374e400768SDavid Christensen /* initialize the general, tx and rx parts of a queue object */
ecore_q_fill_setup_data_cmn(struct bxe_softc * sc,struct ecore_queue_state_params * cmd_params,struct client_init_ramrod_data * data)49384e400768SDavid Christensen static void ecore_q_fill_setup_data_cmn(struct bxe_softc *sc,
49394e400768SDavid Christensen 				struct ecore_queue_state_params *cmd_params,
49404e400768SDavid Christensen 				struct client_init_ramrod_data *data)
49414e400768SDavid Christensen {
49424e400768SDavid Christensen 	ecore_q_fill_init_general_data(sc, cmd_params->q_obj,
49434e400768SDavid Christensen 				       &cmd_params->params.setup.gen_params,
49444e400768SDavid Christensen 				       &data->general,
49454e400768SDavid Christensen 				       &cmd_params->params.setup.flags);
49464e400768SDavid Christensen 
49474e400768SDavid Christensen 	ecore_q_fill_init_tx_data(cmd_params->q_obj,
49484e400768SDavid Christensen 				  &cmd_params->params.setup.txq_params,
49494e400768SDavid Christensen 				  &data->tx,
49504e400768SDavid Christensen 				  &cmd_params->params.setup.flags);
49514e400768SDavid Christensen 
49524e400768SDavid Christensen 	ecore_q_fill_init_rx_data(cmd_params->q_obj,
49534e400768SDavid Christensen 				  &cmd_params->params.setup.rxq_params,
49544e400768SDavid Christensen 				  &data->rx,
49554e400768SDavid Christensen 				  &cmd_params->params.setup.flags);
49564e400768SDavid Christensen 
49574e400768SDavid Christensen 	ecore_q_fill_init_pause_data(cmd_params->q_obj,
49584e400768SDavid Christensen 				     &cmd_params->params.setup.pause_params,
49594e400768SDavid Christensen 				     &data->rx);
49604e400768SDavid Christensen }
49614e400768SDavid Christensen 
49624e400768SDavid Christensen /* initialize the general and tx parts of a tx-only queue object */
ecore_q_fill_setup_tx_only(struct bxe_softc * sc,struct ecore_queue_state_params * cmd_params,struct tx_queue_init_ramrod_data * data)49634e400768SDavid Christensen static void ecore_q_fill_setup_tx_only(struct bxe_softc *sc,
49644e400768SDavid Christensen 				struct ecore_queue_state_params *cmd_params,
49654e400768SDavid Christensen 				struct tx_queue_init_ramrod_data *data)
49664e400768SDavid Christensen {
49674e400768SDavid Christensen 	ecore_q_fill_init_general_data(sc, cmd_params->q_obj,
49684e400768SDavid Christensen 				       &cmd_params->params.tx_only.gen_params,
49694e400768SDavid Christensen 				       &data->general,
49704e400768SDavid Christensen 				       &cmd_params->params.tx_only.flags);
49714e400768SDavid Christensen 
49724e400768SDavid Christensen 	ecore_q_fill_init_tx_data(cmd_params->q_obj,
49734e400768SDavid Christensen 				  &cmd_params->params.tx_only.txq_params,
49744e400768SDavid Christensen 				  &data->tx,
49754e400768SDavid Christensen 				  &cmd_params->params.tx_only.flags);
49764e400768SDavid Christensen 
49774e400768SDavid Christensen 	ECORE_MSG(sc, "cid %d, tx bd page lo %x hi %x",
49784e400768SDavid Christensen 		  cmd_params->q_obj->cids[0],
49794e400768SDavid Christensen 		  data->tx.tx_bd_page_base.lo,
49804e400768SDavid Christensen 		  data->tx.tx_bd_page_base.hi);
49814e400768SDavid Christensen }
49824e400768SDavid Christensen 
49834e400768SDavid Christensen /**
49844e400768SDavid Christensen  * ecore_q_init - init HW/FW queue
49854e400768SDavid Christensen  *
49864e400768SDavid Christensen  * @sc:		device handle
49874e400768SDavid Christensen  * @params:
49884e400768SDavid Christensen  *
49894e400768SDavid Christensen  * HW/FW initial Queue configuration:
49904e400768SDavid Christensen  *      - HC: Rx and Tx
49914e400768SDavid Christensen  *      - CDU context validation
49924e400768SDavid Christensen  *
49934e400768SDavid Christensen  */
ecore_q_init(struct bxe_softc * sc,struct ecore_queue_state_params * params)49944e400768SDavid Christensen static inline int ecore_q_init(struct bxe_softc *sc,
49954e400768SDavid Christensen 			       struct ecore_queue_state_params *params)
49964e400768SDavid Christensen {
49974e400768SDavid Christensen 	struct ecore_queue_sp_obj *o = params->q_obj;
49984e400768SDavid Christensen 	struct ecore_queue_init_params *init = &params->params.init;
49994e400768SDavid Christensen 	uint16_t hc_usec;
50004e400768SDavid Christensen 	uint8_t cos;
50014e400768SDavid Christensen 
50024e400768SDavid Christensen 	/* Tx HC configuration */
50034e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_Q_TYPE_HAS_TX, &o->type) &&
50044e400768SDavid Christensen 	    ECORE_TEST_BIT(ECORE_Q_FLG_HC, &init->tx.flags)) {
50054e400768SDavid Christensen 		hc_usec = init->tx.hc_rate ? 1000000 / init->tx.hc_rate : 0;
50064e400768SDavid Christensen 
50074e400768SDavid Christensen 		ECORE_UPDATE_COALESCE_SB_INDEX(sc, init->tx.fw_sb_id,
50084e400768SDavid Christensen 			init->tx.sb_cq_index,
50094e400768SDavid Christensen 			!ECORE_TEST_BIT(ECORE_Q_FLG_HC_EN, &init->tx.flags),
50104e400768SDavid Christensen 			hc_usec);
50114e400768SDavid Christensen 	}
50124e400768SDavid Christensen 
50134e400768SDavid Christensen 	/* Rx HC configuration */
50144e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_Q_TYPE_HAS_RX, &o->type) &&
50154e400768SDavid Christensen 	    ECORE_TEST_BIT(ECORE_Q_FLG_HC, &init->rx.flags)) {
50164e400768SDavid Christensen 		hc_usec = init->rx.hc_rate ? 1000000 / init->rx.hc_rate : 0;
50174e400768SDavid Christensen 
50184e400768SDavid Christensen 		ECORE_UPDATE_COALESCE_SB_INDEX(sc, init->rx.fw_sb_id,
50194e400768SDavid Christensen 			init->rx.sb_cq_index,
50204e400768SDavid Christensen 			!ECORE_TEST_BIT(ECORE_Q_FLG_HC_EN, &init->rx.flags),
50214e400768SDavid Christensen 			hc_usec);
50224e400768SDavid Christensen 	}
50234e400768SDavid Christensen 
50244e400768SDavid Christensen 	/* Set CDU context validation values */
50254e400768SDavid Christensen 	for (cos = 0; cos < o->max_cos; cos++) {
50264e400768SDavid Christensen 		ECORE_MSG(sc, "setting context validation. cid %d, cos %d\n",
50274e400768SDavid Christensen 			  o->cids[cos], cos);
50284e400768SDavid Christensen 		ECORE_MSG(sc, "context pointer %p\n", init->cxts[cos]);
50294e400768SDavid Christensen 		ECORE_SET_CTX_VALIDATION(sc, init->cxts[cos], o->cids[cos]);
50304e400768SDavid Christensen 	}
50314e400768SDavid Christensen 
50324e400768SDavid Christensen 	/* As no ramrod is sent, complete the command immediately  */
50334e400768SDavid Christensen 	o->complete_cmd(sc, o, ECORE_Q_CMD_INIT);
50344e400768SDavid Christensen 
50354e400768SDavid Christensen 	ECORE_MMIOWB();
50364e400768SDavid Christensen 	ECORE_SMP_MB();
50374e400768SDavid Christensen 
50384e400768SDavid Christensen 	return ECORE_SUCCESS;
50394e400768SDavid Christensen }
50404e400768SDavid Christensen 
ecore_q_send_setup_e1x(struct bxe_softc * sc,struct ecore_queue_state_params * params)50414e400768SDavid Christensen static inline int ecore_q_send_setup_e1x(struct bxe_softc *sc,
50424e400768SDavid Christensen 					struct ecore_queue_state_params *params)
50434e400768SDavid Christensen {
50444e400768SDavid Christensen 	struct ecore_queue_sp_obj *o = params->q_obj;
50454e400768SDavid Christensen 	struct client_init_ramrod_data *rdata =
50464e400768SDavid Christensen 		(struct client_init_ramrod_data *)o->rdata;
50474e400768SDavid Christensen 	ecore_dma_addr_t data_mapping = o->rdata_mapping;
50484e400768SDavid Christensen 	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
50494e400768SDavid Christensen 
50504e400768SDavid Christensen 	/* Clear the ramrod data */
50514e400768SDavid Christensen 	ECORE_MEMSET(rdata, 0, sizeof(*rdata));
50524e400768SDavid Christensen 
50534e400768SDavid Christensen 	/* Fill the ramrod data */
50544e400768SDavid Christensen 	ecore_q_fill_setup_data_cmn(sc, params, rdata);
50554e400768SDavid Christensen 
50564ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
50574ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
50584e400768SDavid Christensen 	 * and updating of the SPQ producer which involves a memory
50594ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
50604ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
50614e400768SDavid Christensen 	 */
50624e400768SDavid Christensen 	return ecore_sp_post(sc,
50634e400768SDavid Christensen 			     ramrod,
50644e400768SDavid Christensen 			     o->cids[ECORE_PRIMARY_CID_INDEX],
50654e400768SDavid Christensen 			     data_mapping,
50664e400768SDavid Christensen 			     ETH_CONNECTION_TYPE);
50674e400768SDavid Christensen }
50684e400768SDavid Christensen 
ecore_q_send_setup_e2(struct bxe_softc * sc,struct ecore_queue_state_params * params)50694e400768SDavid Christensen static inline int ecore_q_send_setup_e2(struct bxe_softc *sc,
50704e400768SDavid Christensen 					struct ecore_queue_state_params *params)
50714e400768SDavid Christensen {
50724e400768SDavid Christensen 	struct ecore_queue_sp_obj *o = params->q_obj;
50734e400768SDavid Christensen 	struct client_init_ramrod_data *rdata =
50744e400768SDavid Christensen 		(struct client_init_ramrod_data *)o->rdata;
50754e400768SDavid Christensen 	ecore_dma_addr_t data_mapping = o->rdata_mapping;
50764e400768SDavid Christensen 	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
50774e400768SDavid Christensen 
50784e400768SDavid Christensen 	/* Clear the ramrod data */
50794e400768SDavid Christensen 	ECORE_MEMSET(rdata, 0, sizeof(*rdata));
50804e400768SDavid Christensen 
50814e400768SDavid Christensen 	/* Fill the ramrod data */
50824e400768SDavid Christensen 	ecore_q_fill_setup_data_cmn(sc, params, rdata);
50834e400768SDavid Christensen 	ecore_q_fill_setup_data_e2(sc, params, rdata);
50844e400768SDavid Christensen 
50854ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
50864ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
50874e400768SDavid Christensen 	 * and updating of the SPQ producer which involves a memory
50884ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
50894ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
50904e400768SDavid Christensen 	 */
50914e400768SDavid Christensen 	return ecore_sp_post(sc,
50924e400768SDavid Christensen 			     ramrod,
50934e400768SDavid Christensen 			     o->cids[ECORE_PRIMARY_CID_INDEX],
50944e400768SDavid Christensen 			     data_mapping,
50954e400768SDavid Christensen 			     ETH_CONNECTION_TYPE);
50964e400768SDavid Christensen }
50974e400768SDavid Christensen 
ecore_q_send_setup_tx_only(struct bxe_softc * sc,struct ecore_queue_state_params * params)50984e400768SDavid Christensen static inline int ecore_q_send_setup_tx_only(struct bxe_softc *sc,
50994e400768SDavid Christensen 				  struct ecore_queue_state_params *params)
51004e400768SDavid Christensen {
51014e400768SDavid Christensen 	struct ecore_queue_sp_obj *o = params->q_obj;
51024e400768SDavid Christensen 	struct tx_queue_init_ramrod_data *rdata =
51034e400768SDavid Christensen 		(struct tx_queue_init_ramrod_data *)o->rdata;
51044e400768SDavid Christensen 	ecore_dma_addr_t data_mapping = o->rdata_mapping;
51054e400768SDavid Christensen 	int ramrod = RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP;
51064e400768SDavid Christensen 	struct ecore_queue_setup_tx_only_params *tx_only_params =
51074e400768SDavid Christensen 		&params->params.tx_only;
51084e400768SDavid Christensen 	uint8_t cid_index = tx_only_params->cid_index;
51094e400768SDavid Christensen 
51104e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_Q_TYPE_FWD, &o->type))
51114e400768SDavid Christensen 		ramrod = RAMROD_CMD_ID_ETH_FORWARD_SETUP;
51124e400768SDavid Christensen 	ECORE_MSG(sc, "sending forward tx-only ramrod");
51134e400768SDavid Christensen 
51144e400768SDavid Christensen 	if (cid_index >= o->max_cos) {
51154e400768SDavid Christensen 		ECORE_ERR("queue[%d]: cid_index (%d) is out of range\n",
51164e400768SDavid Christensen 			  o->cl_id, cid_index);
51174e400768SDavid Christensen 		return ECORE_INVAL;
51184e400768SDavid Christensen 	}
51194e400768SDavid Christensen 
51204e400768SDavid Christensen 	ECORE_MSG(sc, "parameters received: cos: %d sp-id: %d\n",
51214e400768SDavid Christensen 		  tx_only_params->gen_params.cos,
51224e400768SDavid Christensen 		  tx_only_params->gen_params.spcl_id);
51234e400768SDavid Christensen 
51244e400768SDavid Christensen 	/* Clear the ramrod data */
51254e400768SDavid Christensen 	ECORE_MEMSET(rdata, 0, sizeof(*rdata));
51264e400768SDavid Christensen 
51274e400768SDavid Christensen 	/* Fill the ramrod data */
51284e400768SDavid Christensen 	ecore_q_fill_setup_tx_only(sc, params, rdata);
51294e400768SDavid Christensen 
51304e400768SDavid Christensen 	ECORE_MSG(sc, "sending tx-only ramrod: cid %d, client-id %d, sp-client id %d, cos %d\n",
51314e400768SDavid Christensen 		  o->cids[cid_index], rdata->general.client_id,
51324e400768SDavid Christensen 		  rdata->general.sp_client_id, rdata->general.cos);
51334e400768SDavid Christensen 
51344ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
51354ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
51364e400768SDavid Christensen 	 * and updating of the SPQ producer which involves a memory
51374ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
51384ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
51394e400768SDavid Christensen 	 */
51404e400768SDavid Christensen 	return ecore_sp_post(sc, ramrod, o->cids[cid_index],
51414e400768SDavid Christensen 			     data_mapping, ETH_CONNECTION_TYPE);
51424e400768SDavid Christensen }
51434e400768SDavid Christensen 
ecore_q_fill_update_data(struct bxe_softc * sc,struct ecore_queue_sp_obj * obj,struct ecore_queue_update_params * params,struct client_update_ramrod_data * data)51444e400768SDavid Christensen static void ecore_q_fill_update_data(struct bxe_softc *sc,
51454e400768SDavid Christensen 				     struct ecore_queue_sp_obj *obj,
51464e400768SDavid Christensen 				     struct ecore_queue_update_params *params,
51474e400768SDavid Christensen 				     struct client_update_ramrod_data *data)
51484e400768SDavid Christensen {
51494e400768SDavid Christensen 	/* Client ID of the client to update */
51504e400768SDavid Christensen 	data->client_id = obj->cl_id;
51514e400768SDavid Christensen 
51524e400768SDavid Christensen 	/* Function ID of the client to update */
51534e400768SDavid Christensen 	data->func_id = obj->func_id;
51544e400768SDavid Christensen 
51554e400768SDavid Christensen 	/* Default VLAN value */
51564e400768SDavid Christensen 	data->default_vlan = ECORE_CPU_TO_LE16(params->def_vlan);
51574e400768SDavid Christensen 
51584e400768SDavid Christensen 	/* Inner VLAN stripping */
51594e400768SDavid Christensen 	data->inner_vlan_removal_enable_flg =
51604e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_IN_VLAN_REM,
51614e400768SDavid Christensen 			       &params->update_flags);
51624e400768SDavid Christensen 	data->inner_vlan_removal_change_flg =
51634e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_IN_VLAN_REM_CHNG,
51644e400768SDavid Christensen 		       &params->update_flags);
51654e400768SDavid Christensen 
51664e400768SDavid Christensen 	/* Outer VLAN stripping */
51674e400768SDavid Christensen 	data->outer_vlan_removal_enable_flg =
51684e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_OUT_VLAN_REM,
51694e400768SDavid Christensen 			       &params->update_flags);
51704e400768SDavid Christensen 	data->outer_vlan_removal_change_flg =
51714e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_OUT_VLAN_REM_CHNG,
51724e400768SDavid Christensen 		       &params->update_flags);
51734e400768SDavid Christensen 
51744e400768SDavid Christensen 	/* Drop packets that have source MAC that doesn't belong to this
51754e400768SDavid Christensen 	 * Queue.
51764e400768SDavid Christensen 	 */
51774e400768SDavid Christensen 	data->anti_spoofing_enable_flg =
51784e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_ANTI_SPOOF,
51794e400768SDavid Christensen 			       &params->update_flags);
51804e400768SDavid Christensen 	data->anti_spoofing_change_flg =
51814e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_ANTI_SPOOF_CHNG,
51824e400768SDavid Christensen 		       &params->update_flags);
51834e400768SDavid Christensen 
51844e400768SDavid Christensen 	/* Activate/Deactivate */
51854e400768SDavid Christensen 	data->activate_flg =
51864e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE, &params->update_flags);
51874e400768SDavid Christensen 	data->activate_change_flg =
51884e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE_CHNG,
51894e400768SDavid Christensen 			       &params->update_flags);
51904e400768SDavid Christensen 
51914e400768SDavid Christensen 	/* Enable default VLAN */
51924e400768SDavid Christensen 	data->default_vlan_enable_flg =
51934e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_DEF_VLAN_EN,
51944e400768SDavid Christensen 			       &params->update_flags);
51954e400768SDavid Christensen 	data->default_vlan_change_flg =
51964e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_DEF_VLAN_EN_CHNG,
51974e400768SDavid Christensen 		       &params->update_flags);
51984e400768SDavid Christensen 
51994e400768SDavid Christensen 	/* silent vlan removal */
52004e400768SDavid Christensen 	data->silent_vlan_change_flg =
52014e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_SILENT_VLAN_REM_CHNG,
52024e400768SDavid Christensen 			       &params->update_flags);
52034e400768SDavid Christensen 	data->silent_vlan_removal_flg =
52044e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_SILENT_VLAN_REM,
52054e400768SDavid Christensen 			       &params->update_flags);
52064e400768SDavid Christensen 	data->silent_vlan_value = ECORE_CPU_TO_LE16(params->silent_removal_value);
52074e400768SDavid Christensen 	data->silent_vlan_mask = ECORE_CPU_TO_LE16(params->silent_removal_mask);
52084e400768SDavid Christensen 
52094e400768SDavid Christensen 	/* tx switching */
52104e400768SDavid Christensen 	data->tx_switching_flg =
52114e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_TX_SWITCHING,
52124e400768SDavid Christensen 			       &params->update_flags);
52134e400768SDavid Christensen 	data->tx_switching_change_flg =
52144e400768SDavid Christensen 		ECORE_TEST_BIT(ECORE_Q_UPDATE_TX_SWITCHING_CHNG,
52154e400768SDavid Christensen 			       &params->update_flags);
52164ef8ebfdSDavid C Somayajulu 
52174ef8ebfdSDavid C Somayajulu 	/* PTP */
52184ef8ebfdSDavid C Somayajulu 	data->handle_ptp_pkts_flg =
52194ef8ebfdSDavid C Somayajulu 		ECORE_TEST_BIT(ECORE_Q_UPDATE_PTP_PKTS,
52204ef8ebfdSDavid C Somayajulu 			       &params->update_flags);
52214ef8ebfdSDavid C Somayajulu 	data->handle_ptp_pkts_change_flg =
52224ef8ebfdSDavid C Somayajulu 		ECORE_TEST_BIT(ECORE_Q_UPDATE_PTP_PKTS_CHNG,
52234ef8ebfdSDavid C Somayajulu 			       &params->update_flags);
52244e400768SDavid Christensen }
52254e400768SDavid Christensen 
ecore_q_send_update(struct bxe_softc * sc,struct ecore_queue_state_params * params)52264e400768SDavid Christensen static inline int ecore_q_send_update(struct bxe_softc *sc,
52274e400768SDavid Christensen 				      struct ecore_queue_state_params *params)
52284e400768SDavid Christensen {
52294e400768SDavid Christensen 	struct ecore_queue_sp_obj *o = params->q_obj;
52304e400768SDavid Christensen 	struct client_update_ramrod_data *rdata =
52314e400768SDavid Christensen 		(struct client_update_ramrod_data *)o->rdata;
52324e400768SDavid Christensen 	ecore_dma_addr_t data_mapping = o->rdata_mapping;
52334e400768SDavid Christensen 	struct ecore_queue_update_params *update_params =
52344e400768SDavid Christensen 		&params->params.update;
52354e400768SDavid Christensen 	uint8_t cid_index = update_params->cid_index;
52364e400768SDavid Christensen 
52374e400768SDavid Christensen 	if (cid_index >= o->max_cos) {
52384e400768SDavid Christensen 		ECORE_ERR("queue[%d]: cid_index (%d) is out of range\n",
52394e400768SDavid Christensen 			  o->cl_id, cid_index);
52404e400768SDavid Christensen 		return ECORE_INVAL;
52414e400768SDavid Christensen 	}
52424e400768SDavid Christensen 
52434e400768SDavid Christensen 	/* Clear the ramrod data */
52444e400768SDavid Christensen 	ECORE_MEMSET(rdata, 0, sizeof(*rdata));
52454e400768SDavid Christensen 
52464e400768SDavid Christensen 	/* Fill the ramrod data */
52474e400768SDavid Christensen 	ecore_q_fill_update_data(sc, o, update_params, rdata);
52484e400768SDavid Christensen 
52494ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
52504ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
52514e400768SDavid Christensen 	 * and updating of the SPQ producer which involves a memory
52524ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
52534ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
52544e400768SDavid Christensen 	 */
52554e400768SDavid Christensen 	return ecore_sp_post(sc, RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
52564e400768SDavid Christensen 			     o->cids[cid_index], data_mapping,
52574e400768SDavid Christensen 			     ETH_CONNECTION_TYPE);
52584e400768SDavid Christensen }
52594e400768SDavid Christensen 
52604e400768SDavid Christensen /**
52614e400768SDavid Christensen  * ecore_q_send_deactivate - send DEACTIVATE command
52624e400768SDavid Christensen  *
52634e400768SDavid Christensen  * @sc:		device handle
52644e400768SDavid Christensen  * @params:
52654e400768SDavid Christensen  *
52664e400768SDavid Christensen  * implemented using the UPDATE command.
52674e400768SDavid Christensen  */
ecore_q_send_deactivate(struct bxe_softc * sc,struct ecore_queue_state_params * params)52684e400768SDavid Christensen static inline int ecore_q_send_deactivate(struct bxe_softc *sc,
52694e400768SDavid Christensen 					struct ecore_queue_state_params *params)
52704e400768SDavid Christensen {
52714e400768SDavid Christensen 	struct ecore_queue_update_params *update = &params->params.update;
52724e400768SDavid Christensen 
52734e400768SDavid Christensen 	ECORE_MEMSET(update, 0, sizeof(*update));
52744e400768SDavid Christensen 
52754e400768SDavid Christensen 	ECORE_SET_BIT_NA(ECORE_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
52764e400768SDavid Christensen 
52774e400768SDavid Christensen 	return ecore_q_send_update(sc, params);
52784e400768SDavid Christensen }
52794e400768SDavid Christensen 
52804e400768SDavid Christensen /**
52814e400768SDavid Christensen  * ecore_q_send_activate - send ACTIVATE command
52824e400768SDavid Christensen  *
52834e400768SDavid Christensen  * @sc:		device handle
52844e400768SDavid Christensen  * @params:
52854e400768SDavid Christensen  *
52864e400768SDavid Christensen  * implemented using the UPDATE command.
52874e400768SDavid Christensen  */
ecore_q_send_activate(struct bxe_softc * sc,struct ecore_queue_state_params * params)52884e400768SDavid Christensen static inline int ecore_q_send_activate(struct bxe_softc *sc,
52894e400768SDavid Christensen 					struct ecore_queue_state_params *params)
52904e400768SDavid Christensen {
52914e400768SDavid Christensen 	struct ecore_queue_update_params *update = &params->params.update;
52924e400768SDavid Christensen 
52934e400768SDavid Christensen 	ECORE_MEMSET(update, 0, sizeof(*update));
52944e400768SDavid Christensen 
52954e400768SDavid Christensen 	ECORE_SET_BIT_NA(ECORE_Q_UPDATE_ACTIVATE, &update->update_flags);
52964e400768SDavid Christensen 	ECORE_SET_BIT_NA(ECORE_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
52974e400768SDavid Christensen 
52984e400768SDavid Christensen 	return ecore_q_send_update(sc, params);
52994e400768SDavid Christensen }
53004e400768SDavid Christensen 
ecore_q_fill_update_tpa_data(struct bxe_softc * sc,struct ecore_queue_sp_obj * obj,struct ecore_queue_update_tpa_params * params,struct tpa_update_ramrod_data * data)53014ef8ebfdSDavid C Somayajulu static void ecore_q_fill_update_tpa_data(struct bxe_softc *sc,
53024ef8ebfdSDavid C Somayajulu 				struct ecore_queue_sp_obj *obj,
53034ef8ebfdSDavid C Somayajulu 				struct ecore_queue_update_tpa_params *params,
53044ef8ebfdSDavid C Somayajulu 				struct tpa_update_ramrod_data *data)
53054ef8ebfdSDavid C Somayajulu {
53064ef8ebfdSDavid C Somayajulu 	data->client_id = obj->cl_id;
53074ef8ebfdSDavid C Somayajulu 	data->complete_on_both_clients = params->complete_on_both_clients;
53084ef8ebfdSDavid C Somayajulu 	data->dont_verify_rings_pause_thr_flg =
53094ef8ebfdSDavid C Somayajulu 		params->dont_verify_thr;
53104ef8ebfdSDavid C Somayajulu 	data->max_agg_size = ECORE_CPU_TO_LE16(params->max_agg_sz);
53114ef8ebfdSDavid C Somayajulu 	data->max_sges_for_packet = params->max_sges_pkt;
53124ef8ebfdSDavid C Somayajulu 	data->max_tpa_queues = params->max_tpa_queues;
53134ef8ebfdSDavid C Somayajulu 	data->sge_buff_size = ECORE_CPU_TO_LE16(params->sge_buff_sz);
53144ef8ebfdSDavid C Somayajulu 	data->sge_page_base_hi = ECORE_CPU_TO_LE32(U64_HI(params->sge_map));
53154ef8ebfdSDavid C Somayajulu 	data->sge_page_base_lo = ECORE_CPU_TO_LE32(U64_LO(params->sge_map));
53164ef8ebfdSDavid C Somayajulu 	data->sge_pause_thr_high = ECORE_CPU_TO_LE16(params->sge_pause_thr_high);
53174ef8ebfdSDavid C Somayajulu 	data->sge_pause_thr_low = ECORE_CPU_TO_LE16(params->sge_pause_thr_low);
53184ef8ebfdSDavid C Somayajulu 	data->tpa_mode = params->tpa_mode;
53194ef8ebfdSDavid C Somayajulu 	data->update_ipv4 = params->update_ipv4;
53204ef8ebfdSDavid C Somayajulu 	data->update_ipv6 = params->update_ipv6;
53214ef8ebfdSDavid C Somayajulu }
53224ef8ebfdSDavid C Somayajulu 
ecore_q_send_update_tpa(struct bxe_softc * sc,struct ecore_queue_state_params * params)53234e400768SDavid Christensen static inline int ecore_q_send_update_tpa(struct bxe_softc *sc,
53244e400768SDavid Christensen 					struct ecore_queue_state_params *params)
53254e400768SDavid Christensen {
53264ef8ebfdSDavid C Somayajulu 	struct ecore_queue_sp_obj *o = params->q_obj;
53274ef8ebfdSDavid C Somayajulu 	struct tpa_update_ramrod_data *rdata =
53284ef8ebfdSDavid C Somayajulu 		(struct tpa_update_ramrod_data *)o->rdata;
53294ef8ebfdSDavid C Somayajulu 	ecore_dma_addr_t data_mapping = o->rdata_mapping;
53304ef8ebfdSDavid C Somayajulu 	struct ecore_queue_update_tpa_params *update_tpa_params =
53314ef8ebfdSDavid C Somayajulu 		&params->params.update_tpa;
53324ef8ebfdSDavid C Somayajulu 	uint16_t type;
53334ef8ebfdSDavid C Somayajulu 
53344ef8ebfdSDavid C Somayajulu 	/* Clear the ramrod data */
53354ef8ebfdSDavid C Somayajulu 	ECORE_MEMSET(rdata, 0, sizeof(*rdata));
53364ef8ebfdSDavid C Somayajulu 
53374ef8ebfdSDavid C Somayajulu 	/* Fill the ramrod data */
53384ef8ebfdSDavid C Somayajulu 	ecore_q_fill_update_tpa_data(sc, o, update_tpa_params, rdata);
53394ef8ebfdSDavid C Somayajulu 
53404ef8ebfdSDavid C Somayajulu 	/* Add the function id inside the type, so that sp post function
53414ef8ebfdSDavid C Somayajulu 	 * doesn't automatically add the PF func-id, this is required
53424ef8ebfdSDavid C Somayajulu 	 * for operations done by PFs on behalf of their VFs
53434ef8ebfdSDavid C Somayajulu 	 */
53444ef8ebfdSDavid C Somayajulu 	type = ETH_CONNECTION_TYPE |
53454ef8ebfdSDavid C Somayajulu 		((o->func_id) << SPE_HDR_T_FUNCTION_ID_SHIFT);
53464ef8ebfdSDavid C Somayajulu 
53474ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
53484ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
53494ef8ebfdSDavid C Somayajulu 	 * and updating of the SPQ producer which involves a memory
53504ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
53514ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
53524ef8ebfdSDavid C Somayajulu 	 */
53534ef8ebfdSDavid C Somayajulu 	return ecore_sp_post(sc, RAMROD_CMD_ID_ETH_TPA_UPDATE,
53544ef8ebfdSDavid C Somayajulu 			     o->cids[ECORE_PRIMARY_CID_INDEX],
53554ef8ebfdSDavid C Somayajulu 			     data_mapping, type);
53564e400768SDavid Christensen }
53574e400768SDavid Christensen 
ecore_q_send_halt(struct bxe_softc * sc,struct ecore_queue_state_params * params)53584e400768SDavid Christensen static inline int ecore_q_send_halt(struct bxe_softc *sc,
53594e400768SDavid Christensen 				    struct ecore_queue_state_params *params)
53604e400768SDavid Christensen {
53614e400768SDavid Christensen 	struct ecore_queue_sp_obj *o = params->q_obj;
53624e400768SDavid Christensen 
53634e400768SDavid Christensen 	/* build eth_halt_ramrod_data.client_id in a big-endian friendly way */
53644e400768SDavid Christensen 	ecore_dma_addr_t data_mapping = 0;
53654e400768SDavid Christensen 	data_mapping = (ecore_dma_addr_t)o->cl_id;
53664e400768SDavid Christensen 
53674ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
53684ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
53694ef8ebfdSDavid C Somayajulu 	 * and updating of the SPQ producer which involves a memory
53704ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
53714ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
53724ef8ebfdSDavid C Somayajulu 	 */
53734e400768SDavid Christensen 	return ecore_sp_post(sc,
53744e400768SDavid Christensen 			     RAMROD_CMD_ID_ETH_HALT,
53754e400768SDavid Christensen 			     o->cids[ECORE_PRIMARY_CID_INDEX],
53764e400768SDavid Christensen 			     data_mapping,
53774e400768SDavid Christensen 			     ETH_CONNECTION_TYPE);
53784e400768SDavid Christensen }
53794e400768SDavid Christensen 
ecore_q_send_cfc_del(struct bxe_softc * sc,struct ecore_queue_state_params * params)53804e400768SDavid Christensen static inline int ecore_q_send_cfc_del(struct bxe_softc *sc,
53814e400768SDavid Christensen 				       struct ecore_queue_state_params *params)
53824e400768SDavid Christensen {
53834e400768SDavid Christensen 	struct ecore_queue_sp_obj *o = params->q_obj;
53844e400768SDavid Christensen 	uint8_t cid_idx = params->params.cfc_del.cid_index;
53854e400768SDavid Christensen 
53864e400768SDavid Christensen 	if (cid_idx >= o->max_cos) {
53874e400768SDavid Christensen 		ECORE_ERR("queue[%d]: cid_index (%d) is out of range\n",
53884e400768SDavid Christensen 			  o->cl_id, cid_idx);
53894e400768SDavid Christensen 		return ECORE_INVAL;
53904e400768SDavid Christensen 	}
53914e400768SDavid Christensen 
53924e400768SDavid Christensen 	return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_CFC_DEL,
53934e400768SDavid Christensen 			     o->cids[cid_idx], 0,
53944e400768SDavid Christensen 			     NONE_CONNECTION_TYPE);
53954e400768SDavid Christensen }
53964e400768SDavid Christensen 
ecore_q_send_terminate(struct bxe_softc * sc,struct ecore_queue_state_params * params)53974e400768SDavid Christensen static inline int ecore_q_send_terminate(struct bxe_softc *sc,
53984e400768SDavid Christensen 					struct ecore_queue_state_params *params)
53994e400768SDavid Christensen {
54004e400768SDavid Christensen 	struct ecore_queue_sp_obj *o = params->q_obj;
54014e400768SDavid Christensen 	uint8_t cid_index = params->params.terminate.cid_index;
54024e400768SDavid Christensen 
54034e400768SDavid Christensen 	if (cid_index >= o->max_cos) {
54044e400768SDavid Christensen 		ECORE_ERR("queue[%d]: cid_index (%d) is out of range\n",
54054e400768SDavid Christensen 			  o->cl_id, cid_index);
54064e400768SDavid Christensen 		return ECORE_INVAL;
54074e400768SDavid Christensen 	}
54084e400768SDavid Christensen 
54094e400768SDavid Christensen 	return ecore_sp_post(sc, RAMROD_CMD_ID_ETH_TERMINATE,
54104e400768SDavid Christensen 			     o->cids[cid_index], 0,
54114e400768SDavid Christensen 			     ETH_CONNECTION_TYPE);
54124e400768SDavid Christensen }
54134e400768SDavid Christensen 
ecore_q_send_empty(struct bxe_softc * sc,struct ecore_queue_state_params * params)54144e400768SDavid Christensen static inline int ecore_q_send_empty(struct bxe_softc *sc,
54154e400768SDavid Christensen 				     struct ecore_queue_state_params *params)
54164e400768SDavid Christensen {
54174e400768SDavid Christensen 	struct ecore_queue_sp_obj *o = params->q_obj;
54184e400768SDavid Christensen 
54194e400768SDavid Christensen 	return ecore_sp_post(sc, RAMROD_CMD_ID_ETH_EMPTY,
54204e400768SDavid Christensen 			     o->cids[ECORE_PRIMARY_CID_INDEX], 0,
54214e400768SDavid Christensen 			     ETH_CONNECTION_TYPE);
54224e400768SDavid Christensen }
54234e400768SDavid Christensen 
ecore_queue_send_cmd_cmn(struct bxe_softc * sc,struct ecore_queue_state_params * params)54244e400768SDavid Christensen static inline int ecore_queue_send_cmd_cmn(struct bxe_softc *sc,
54254e400768SDavid Christensen 					struct ecore_queue_state_params *params)
54264e400768SDavid Christensen {
54274e400768SDavid Christensen 	switch (params->cmd) {
54284e400768SDavid Christensen 	case ECORE_Q_CMD_INIT:
54294e400768SDavid Christensen 		return ecore_q_init(sc, params);
54304e400768SDavid Christensen 	case ECORE_Q_CMD_SETUP_TX_ONLY:
54314e400768SDavid Christensen 		return ecore_q_send_setup_tx_only(sc, params);
54324e400768SDavid Christensen 	case ECORE_Q_CMD_DEACTIVATE:
54334e400768SDavid Christensen 		return ecore_q_send_deactivate(sc, params);
54344e400768SDavid Christensen 	case ECORE_Q_CMD_ACTIVATE:
54354e400768SDavid Christensen 		return ecore_q_send_activate(sc, params);
54364e400768SDavid Christensen 	case ECORE_Q_CMD_UPDATE:
54374e400768SDavid Christensen 		return ecore_q_send_update(sc, params);
54384e400768SDavid Christensen 	case ECORE_Q_CMD_UPDATE_TPA:
54394e400768SDavid Christensen 		return ecore_q_send_update_tpa(sc, params);
54404e400768SDavid Christensen 	case ECORE_Q_CMD_HALT:
54414e400768SDavid Christensen 		return ecore_q_send_halt(sc, params);
54424e400768SDavid Christensen 	case ECORE_Q_CMD_CFC_DEL:
54434e400768SDavid Christensen 		return ecore_q_send_cfc_del(sc, params);
54444e400768SDavid Christensen 	case ECORE_Q_CMD_TERMINATE:
54454e400768SDavid Christensen 		return ecore_q_send_terminate(sc, params);
54464e400768SDavid Christensen 	case ECORE_Q_CMD_EMPTY:
54474e400768SDavid Christensen 		return ecore_q_send_empty(sc, params);
54484e400768SDavid Christensen 	default:
54494e400768SDavid Christensen 		ECORE_ERR("Unknown command: %d\n", params->cmd);
54504e400768SDavid Christensen 		return ECORE_INVAL;
54514e400768SDavid Christensen 	}
54524e400768SDavid Christensen }
54534e400768SDavid Christensen 
ecore_queue_send_cmd_e1x(struct bxe_softc * sc,struct ecore_queue_state_params * params)54544e400768SDavid Christensen static int ecore_queue_send_cmd_e1x(struct bxe_softc *sc,
54554e400768SDavid Christensen 				    struct ecore_queue_state_params *params)
54564e400768SDavid Christensen {
54574e400768SDavid Christensen 	switch (params->cmd) {
54584e400768SDavid Christensen 	case ECORE_Q_CMD_SETUP:
54594e400768SDavid Christensen 		return ecore_q_send_setup_e1x(sc, params);
54604e400768SDavid Christensen 	case ECORE_Q_CMD_INIT:
54614e400768SDavid Christensen 	case ECORE_Q_CMD_SETUP_TX_ONLY:
54624e400768SDavid Christensen 	case ECORE_Q_CMD_DEACTIVATE:
54634e400768SDavid Christensen 	case ECORE_Q_CMD_ACTIVATE:
54644e400768SDavid Christensen 	case ECORE_Q_CMD_UPDATE:
54654e400768SDavid Christensen 	case ECORE_Q_CMD_UPDATE_TPA:
54664e400768SDavid Christensen 	case ECORE_Q_CMD_HALT:
54674e400768SDavid Christensen 	case ECORE_Q_CMD_CFC_DEL:
54684e400768SDavid Christensen 	case ECORE_Q_CMD_TERMINATE:
54694e400768SDavid Christensen 	case ECORE_Q_CMD_EMPTY:
54704e400768SDavid Christensen 		return ecore_queue_send_cmd_cmn(sc, params);
54714e400768SDavid Christensen 	default:
54724e400768SDavid Christensen 		ECORE_ERR("Unknown command: %d\n", params->cmd);
54734e400768SDavid Christensen 		return ECORE_INVAL;
54744e400768SDavid Christensen 	}
54754e400768SDavid Christensen }
54764e400768SDavid Christensen 
ecore_queue_send_cmd_e2(struct bxe_softc * sc,struct ecore_queue_state_params * params)54774e400768SDavid Christensen static int ecore_queue_send_cmd_e2(struct bxe_softc *sc,
54784e400768SDavid Christensen 				   struct ecore_queue_state_params *params)
54794e400768SDavid Christensen {
54804e400768SDavid Christensen 	switch (params->cmd) {
54814e400768SDavid Christensen 	case ECORE_Q_CMD_SETUP:
54824e400768SDavid Christensen 		return ecore_q_send_setup_e2(sc, params);
54834e400768SDavid Christensen 	case ECORE_Q_CMD_INIT:
54844e400768SDavid Christensen 	case ECORE_Q_CMD_SETUP_TX_ONLY:
54854e400768SDavid Christensen 	case ECORE_Q_CMD_DEACTIVATE:
54864e400768SDavid Christensen 	case ECORE_Q_CMD_ACTIVATE:
54874e400768SDavid Christensen 	case ECORE_Q_CMD_UPDATE:
54884e400768SDavid Christensen 	case ECORE_Q_CMD_UPDATE_TPA:
54894e400768SDavid Christensen 	case ECORE_Q_CMD_HALT:
54904e400768SDavid Christensen 	case ECORE_Q_CMD_CFC_DEL:
54914e400768SDavid Christensen 	case ECORE_Q_CMD_TERMINATE:
54924e400768SDavid Christensen 	case ECORE_Q_CMD_EMPTY:
54934e400768SDavid Christensen 		return ecore_queue_send_cmd_cmn(sc, params);
54944e400768SDavid Christensen 	default:
54954e400768SDavid Christensen 		ECORE_ERR("Unknown command: %d\n", params->cmd);
54964e400768SDavid Christensen 		return ECORE_INVAL;
54974e400768SDavid Christensen 	}
54984e400768SDavid Christensen }
54994e400768SDavid Christensen 
55004e400768SDavid Christensen /**
55014e400768SDavid Christensen  * ecore_queue_chk_transition - check state machine of a regular Queue
55024e400768SDavid Christensen  *
55034e400768SDavid Christensen  * @sc:		device handle
55044e400768SDavid Christensen  * @o:
55054e400768SDavid Christensen  * @params:
55064e400768SDavid Christensen  *
55074e400768SDavid Christensen  * (not Forwarding)
55084e400768SDavid Christensen  * It both checks if the requested command is legal in a current
55094e400768SDavid Christensen  * state and, if it's legal, sets a `next_state' in the object
55104e400768SDavid Christensen  * that will be used in the completion flow to set the `state'
55114e400768SDavid Christensen  * of the object.
55124e400768SDavid Christensen  *
55134e400768SDavid Christensen  * returns 0 if a requested command is a legal transition,
55144e400768SDavid Christensen  *         ECORE_INVAL otherwise.
55154e400768SDavid Christensen  */
ecore_queue_chk_transition(struct bxe_softc * sc,struct ecore_queue_sp_obj * o,struct ecore_queue_state_params * params)55164e400768SDavid Christensen static int ecore_queue_chk_transition(struct bxe_softc *sc,
55174e400768SDavid Christensen 				      struct ecore_queue_sp_obj *o,
55184e400768SDavid Christensen 				      struct ecore_queue_state_params *params)
55194e400768SDavid Christensen {
55204e400768SDavid Christensen 	enum ecore_q_state state = o->state, next_state = ECORE_Q_STATE_MAX;
55214e400768SDavid Christensen 	enum ecore_queue_cmd cmd = params->cmd;
55224e400768SDavid Christensen 	struct ecore_queue_update_params *update_params =
55234e400768SDavid Christensen 		 &params->params.update;
55244e400768SDavid Christensen 	uint8_t next_tx_only = o->num_tx_only;
55254e400768SDavid Christensen 
55264e400768SDavid Christensen 	/* Forget all pending for completion commands if a driver only state
55274e400768SDavid Christensen 	 * transition has been requested.
55284e400768SDavid Christensen 	 */
55294e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
55304e400768SDavid Christensen 		o->pending = 0;
55314e400768SDavid Christensen 		o->next_state = ECORE_Q_STATE_MAX;
55324e400768SDavid Christensen 	}
55334e400768SDavid Christensen 
55344e400768SDavid Christensen 	/* Don't allow a next state transition if we are in the middle of
55354e400768SDavid Christensen 	 * the previous one.
55364e400768SDavid Christensen 	 */
55374e400768SDavid Christensen 	if (o->pending) {
55384e400768SDavid Christensen 		ECORE_ERR("Blocking transition since pending was %lx\n",
55394e400768SDavid Christensen 			  o->pending);
55404e400768SDavid Christensen 		return ECORE_BUSY;
55414e400768SDavid Christensen 	}
55424e400768SDavid Christensen 
55434e400768SDavid Christensen 	switch (state) {
55444e400768SDavid Christensen 	case ECORE_Q_STATE_RESET:
55454e400768SDavid Christensen 		if (cmd == ECORE_Q_CMD_INIT)
55464e400768SDavid Christensen 			next_state = ECORE_Q_STATE_INITIALIZED;
55474e400768SDavid Christensen 
55484e400768SDavid Christensen 		break;
55494e400768SDavid Christensen 	case ECORE_Q_STATE_INITIALIZED:
55504e400768SDavid Christensen 		if (cmd == ECORE_Q_CMD_SETUP) {
55514e400768SDavid Christensen 			if (ECORE_TEST_BIT(ECORE_Q_FLG_ACTIVE,
55524e400768SDavid Christensen 					   &params->params.setup.flags))
55534e400768SDavid Christensen 				next_state = ECORE_Q_STATE_ACTIVE;
55544e400768SDavid Christensen 			else
55554e400768SDavid Christensen 				next_state = ECORE_Q_STATE_INACTIVE;
55564e400768SDavid Christensen 		}
55574e400768SDavid Christensen 
55584e400768SDavid Christensen 		break;
55594e400768SDavid Christensen 	case ECORE_Q_STATE_ACTIVE:
55604e400768SDavid Christensen 		if (cmd == ECORE_Q_CMD_DEACTIVATE)
55614e400768SDavid Christensen 			next_state = ECORE_Q_STATE_INACTIVE;
55624e400768SDavid Christensen 
55634e400768SDavid Christensen 		else if ((cmd == ECORE_Q_CMD_EMPTY) ||
55644e400768SDavid Christensen 			 (cmd == ECORE_Q_CMD_UPDATE_TPA))
55654e400768SDavid Christensen 			next_state = ECORE_Q_STATE_ACTIVE;
55664e400768SDavid Christensen 
55674e400768SDavid Christensen 		else if (cmd == ECORE_Q_CMD_SETUP_TX_ONLY) {
55684e400768SDavid Christensen 			next_state = ECORE_Q_STATE_MULTI_COS;
55694e400768SDavid Christensen 			next_tx_only = 1;
55704e400768SDavid Christensen 		}
55714e400768SDavid Christensen 
55724e400768SDavid Christensen 		else if (cmd == ECORE_Q_CMD_HALT)
55734e400768SDavid Christensen 			next_state = ECORE_Q_STATE_STOPPED;
55744e400768SDavid Christensen 
55754e400768SDavid Christensen 		else if (cmd == ECORE_Q_CMD_UPDATE) {
55764e400768SDavid Christensen 			/* If "active" state change is requested, update the
55774e400768SDavid Christensen 			 *  state accordingly.
55784e400768SDavid Christensen 			 */
55794e400768SDavid Christensen 			if (ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE_CHNG,
55804e400768SDavid Christensen 					   &update_params->update_flags) &&
55814e400768SDavid Christensen 			    !ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE,
55824e400768SDavid Christensen 					    &update_params->update_flags))
55834e400768SDavid Christensen 				next_state = ECORE_Q_STATE_INACTIVE;
55844e400768SDavid Christensen 			else
55854e400768SDavid Christensen 				next_state = ECORE_Q_STATE_ACTIVE;
55864e400768SDavid Christensen 		}
55874e400768SDavid Christensen 
55884e400768SDavid Christensen 		break;
55894e400768SDavid Christensen 	case ECORE_Q_STATE_MULTI_COS:
55904e400768SDavid Christensen 		if (cmd == ECORE_Q_CMD_TERMINATE)
55914e400768SDavid Christensen 			next_state = ECORE_Q_STATE_MCOS_TERMINATED;
55924e400768SDavid Christensen 
55934e400768SDavid Christensen 		else if (cmd == ECORE_Q_CMD_SETUP_TX_ONLY) {
55944e400768SDavid Christensen 			next_state = ECORE_Q_STATE_MULTI_COS;
55954e400768SDavid Christensen 			next_tx_only = o->num_tx_only + 1;
55964e400768SDavid Christensen 		}
55974e400768SDavid Christensen 
55984e400768SDavid Christensen 		else if ((cmd == ECORE_Q_CMD_EMPTY) ||
55994e400768SDavid Christensen 			 (cmd == ECORE_Q_CMD_UPDATE_TPA))
56004e400768SDavid Christensen 			next_state = ECORE_Q_STATE_MULTI_COS;
56014e400768SDavid Christensen 
56024e400768SDavid Christensen 		else if (cmd == ECORE_Q_CMD_UPDATE) {
56034e400768SDavid Christensen 			/* If "active" state change is requested, update the
56044e400768SDavid Christensen 			 *  state accordingly.
56054e400768SDavid Christensen 			 */
56064e400768SDavid Christensen 			if (ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE_CHNG,
56074e400768SDavid Christensen 					   &update_params->update_flags) &&
56084e400768SDavid Christensen 			    !ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE,
56094e400768SDavid Christensen 					    &update_params->update_flags))
56104e400768SDavid Christensen 				next_state = ECORE_Q_STATE_INACTIVE;
56114e400768SDavid Christensen 			else
56124e400768SDavid Christensen 				next_state = ECORE_Q_STATE_MULTI_COS;
56134e400768SDavid Christensen 		}
56144e400768SDavid Christensen 
56154e400768SDavid Christensen 		break;
56164e400768SDavid Christensen 	case ECORE_Q_STATE_MCOS_TERMINATED:
56174e400768SDavid Christensen 		if (cmd == ECORE_Q_CMD_CFC_DEL) {
56184e400768SDavid Christensen 			next_tx_only = o->num_tx_only - 1;
56194e400768SDavid Christensen 			if (next_tx_only == 0)
56204e400768SDavid Christensen 				next_state = ECORE_Q_STATE_ACTIVE;
56214e400768SDavid Christensen 			else
56224e400768SDavid Christensen 				next_state = ECORE_Q_STATE_MULTI_COS;
56234e400768SDavid Christensen 		}
56244e400768SDavid Christensen 
56254e400768SDavid Christensen 		break;
56264e400768SDavid Christensen 	case ECORE_Q_STATE_INACTIVE:
56274e400768SDavid Christensen 		if (cmd == ECORE_Q_CMD_ACTIVATE)
56284e400768SDavid Christensen 			next_state = ECORE_Q_STATE_ACTIVE;
56294e400768SDavid Christensen 
56304e400768SDavid Christensen 		else if ((cmd == ECORE_Q_CMD_EMPTY) ||
56314e400768SDavid Christensen 			 (cmd == ECORE_Q_CMD_UPDATE_TPA))
56324e400768SDavid Christensen 			next_state = ECORE_Q_STATE_INACTIVE;
56334e400768SDavid Christensen 
56344e400768SDavid Christensen 		else if (cmd == ECORE_Q_CMD_HALT)
56354e400768SDavid Christensen 			next_state = ECORE_Q_STATE_STOPPED;
56364e400768SDavid Christensen 
56374e400768SDavid Christensen 		else if (cmd == ECORE_Q_CMD_UPDATE) {
56384e400768SDavid Christensen 			/* If "active" state change is requested, update the
56394e400768SDavid Christensen 			 * state accordingly.
56404e400768SDavid Christensen 			 */
56414e400768SDavid Christensen 			if (ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE_CHNG,
56424e400768SDavid Christensen 					   &update_params->update_flags) &&
56434e400768SDavid Christensen 			    ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE,
56444e400768SDavid Christensen 					   &update_params->update_flags)){
56454e400768SDavid Christensen 				if (o->num_tx_only == 0)
56464e400768SDavid Christensen 					next_state = ECORE_Q_STATE_ACTIVE;
56474e400768SDavid Christensen 				else /* tx only queues exist for this queue */
56484e400768SDavid Christensen 					next_state = ECORE_Q_STATE_MULTI_COS;
56494e400768SDavid Christensen 			} else
56504e400768SDavid Christensen 				next_state = ECORE_Q_STATE_INACTIVE;
56514e400768SDavid Christensen 		}
56524e400768SDavid Christensen 
56534e400768SDavid Christensen 		break;
56544e400768SDavid Christensen 	case ECORE_Q_STATE_STOPPED:
56554e400768SDavid Christensen 		if (cmd == ECORE_Q_CMD_TERMINATE)
56564e400768SDavid Christensen 			next_state = ECORE_Q_STATE_TERMINATED;
56574e400768SDavid Christensen 
56584e400768SDavid Christensen 		break;
56594e400768SDavid Christensen 	case ECORE_Q_STATE_TERMINATED:
56604e400768SDavid Christensen 		if (cmd == ECORE_Q_CMD_CFC_DEL)
56614e400768SDavid Christensen 			next_state = ECORE_Q_STATE_RESET;
56624e400768SDavid Christensen 
56634e400768SDavid Christensen 		break;
56644e400768SDavid Christensen 	default:
56654e400768SDavid Christensen 		ECORE_ERR("Illegal state: %d\n", state);
56664e400768SDavid Christensen 	}
56674e400768SDavid Christensen 
56684e400768SDavid Christensen 	/* Transition is assured */
56694e400768SDavid Christensen 	if (next_state != ECORE_Q_STATE_MAX) {
56704e400768SDavid Christensen 		ECORE_MSG(sc, "Good state transition: %d(%d)->%d\n",
56714e400768SDavid Christensen 			  state, cmd, next_state);
56724e400768SDavid Christensen 		o->next_state = next_state;
56734e400768SDavid Christensen 		o->next_tx_only = next_tx_only;
56744e400768SDavid Christensen 		return ECORE_SUCCESS;
56754e400768SDavid Christensen 	}
56764e400768SDavid Christensen 
56774e400768SDavid Christensen 	ECORE_MSG(sc, "Bad state transition request: %d %d\n", state, cmd);
56784e400768SDavid Christensen 
56794e400768SDavid Christensen 	return ECORE_INVAL;
56804e400768SDavid Christensen }
56814e400768SDavid Christensen 
56824e400768SDavid Christensen /**
56834e400768SDavid Christensen  * ecore_queue_chk_fwd_transition - check state machine of a Forwarding Queue.
56844e400768SDavid Christensen  *
56854e400768SDavid Christensen  * @sc:		device handle
56864e400768SDavid Christensen  * @o:
56874e400768SDavid Christensen  * @params:
56884e400768SDavid Christensen  *
56894e400768SDavid Christensen  * It both checks if the requested command is legal in a current
56904e400768SDavid Christensen  * state and, if it's legal, sets a `next_state' in the object
56914e400768SDavid Christensen  * that will be used in the completion flow to set the `state'
56924e400768SDavid Christensen  * of the object.
56934e400768SDavid Christensen  *
56944e400768SDavid Christensen  * returns 0 if a requested command is a legal transition,
56954e400768SDavid Christensen  *         ECORE_INVAL otherwise.
56964e400768SDavid Christensen  */
ecore_queue_chk_fwd_transition(struct bxe_softc * sc,struct ecore_queue_sp_obj * o,struct ecore_queue_state_params * params)56974e400768SDavid Christensen static int ecore_queue_chk_fwd_transition(struct bxe_softc *sc,
56984e400768SDavid Christensen 					  struct ecore_queue_sp_obj *o,
56994e400768SDavid Christensen 					struct ecore_queue_state_params *params)
57004e400768SDavid Christensen {
57014e400768SDavid Christensen 	enum ecore_q_state state = o->state, next_state = ECORE_Q_STATE_MAX;
57024e400768SDavid Christensen 	enum ecore_queue_cmd cmd = params->cmd;
57034e400768SDavid Christensen 
57044e400768SDavid Christensen 	switch (state) {
57054e400768SDavid Christensen 	case ECORE_Q_STATE_RESET:
57064e400768SDavid Christensen 		if (cmd == ECORE_Q_CMD_INIT)
57074e400768SDavid Christensen 			next_state = ECORE_Q_STATE_INITIALIZED;
57084e400768SDavid Christensen 
57094e400768SDavid Christensen 		break;
57104e400768SDavid Christensen 	case ECORE_Q_STATE_INITIALIZED:
57114e400768SDavid Christensen 		if (cmd == ECORE_Q_CMD_SETUP_TX_ONLY) {
57124e400768SDavid Christensen 			if (ECORE_TEST_BIT(ECORE_Q_FLG_ACTIVE,
57134e400768SDavid Christensen 					   &params->params.tx_only.flags))
57144e400768SDavid Christensen 				next_state = ECORE_Q_STATE_ACTIVE;
57154e400768SDavid Christensen 			else
57164e400768SDavid Christensen 				next_state = ECORE_Q_STATE_INACTIVE;
57174e400768SDavid Christensen 		}
57184e400768SDavid Christensen 
57194e400768SDavid Christensen 		break;
57204e400768SDavid Christensen 	case ECORE_Q_STATE_ACTIVE:
57214e400768SDavid Christensen 	case ECORE_Q_STATE_INACTIVE:
57224e400768SDavid Christensen 		if (cmd == ECORE_Q_CMD_CFC_DEL)
57234e400768SDavid Christensen 			next_state = ECORE_Q_STATE_RESET;
57244e400768SDavid Christensen 
57254e400768SDavid Christensen 		break;
57264e400768SDavid Christensen 	default:
57274e400768SDavid Christensen 		ECORE_ERR("Illegal state: %d\n", state);
57284e400768SDavid Christensen 	}
57294e400768SDavid Christensen 
57304e400768SDavid Christensen 	/* Transition is assured */
57314e400768SDavid Christensen 	if (next_state != ECORE_Q_STATE_MAX) {
57324e400768SDavid Christensen 		ECORE_MSG(sc, "Good state transition: %d(%d)->%d\n",
57334e400768SDavid Christensen 			  state, cmd, next_state);
57344e400768SDavid Christensen 		o->next_state = next_state;
57354e400768SDavid Christensen 		return ECORE_SUCCESS;
57364e400768SDavid Christensen 	}
57374e400768SDavid Christensen 
57384e400768SDavid Christensen 	ECORE_MSG(sc, "Bad state transition request: %d %d\n", state, cmd);
57394e400768SDavid Christensen 	return ECORE_INVAL;
57404e400768SDavid Christensen }
57414e400768SDavid Christensen 
ecore_init_queue_obj(struct bxe_softc * sc,struct ecore_queue_sp_obj * obj,uint8_t cl_id,uint32_t * cids,uint8_t cid_cnt,uint8_t func_id,void * rdata,ecore_dma_addr_t rdata_mapping,unsigned long type)57424e400768SDavid Christensen void ecore_init_queue_obj(struct bxe_softc *sc,
57434e400768SDavid Christensen 			  struct ecore_queue_sp_obj *obj,
57444e400768SDavid Christensen 			  uint8_t cl_id, uint32_t *cids, uint8_t cid_cnt, uint8_t func_id,
57454e400768SDavid Christensen 			  void *rdata,
57464e400768SDavid Christensen 			  ecore_dma_addr_t rdata_mapping, unsigned long type)
57474e400768SDavid Christensen {
57484e400768SDavid Christensen 	ECORE_MEMSET(obj, 0, sizeof(*obj));
57494e400768SDavid Christensen 
57504e400768SDavid Christensen 	/* We support only ECORE_MULTI_TX_COS Tx CoS at the moment */
57514e400768SDavid Christensen 	ECORE_BUG_ON(ECORE_MULTI_TX_COS < cid_cnt);
57524e400768SDavid Christensen 
57534e400768SDavid Christensen 	memcpy(obj->cids, cids, sizeof(obj->cids[0]) * cid_cnt);
57544e400768SDavid Christensen 	obj->max_cos = cid_cnt;
57554e400768SDavid Christensen 	obj->cl_id = cl_id;
57564e400768SDavid Christensen 	obj->func_id = func_id;
57574e400768SDavid Christensen 	obj->rdata = rdata;
57584e400768SDavid Christensen 	obj->rdata_mapping = rdata_mapping;
57594e400768SDavid Christensen 	obj->type = type;
57604e400768SDavid Christensen 	obj->next_state = ECORE_Q_STATE_MAX;
57614e400768SDavid Christensen 
57624e400768SDavid Christensen 	if (CHIP_IS_E1x(sc))
57634e400768SDavid Christensen 		obj->send_cmd = ecore_queue_send_cmd_e1x;
57644e400768SDavid Christensen 	else
57654e400768SDavid Christensen 		obj->send_cmd = ecore_queue_send_cmd_e2;
57664e400768SDavid Christensen 
57674e400768SDavid Christensen 	if (ECORE_TEST_BIT(ECORE_Q_TYPE_FWD, &type))
57684e400768SDavid Christensen 		obj->check_transition = ecore_queue_chk_fwd_transition;
57694e400768SDavid Christensen 	else
57704e400768SDavid Christensen 	obj->check_transition = ecore_queue_chk_transition;
57714e400768SDavid Christensen 
57724e400768SDavid Christensen 	obj->complete_cmd = ecore_queue_comp_cmd;
57734e400768SDavid Christensen 	obj->wait_comp = ecore_queue_wait_comp;
57744e400768SDavid Christensen 	obj->set_pending = ecore_queue_set_pending;
57754e400768SDavid Christensen }
57764e400768SDavid Christensen 
57774e400768SDavid Christensen /* return a queue object's logical state*/
ecore_get_q_logical_state(struct bxe_softc * sc,struct ecore_queue_sp_obj * obj)57784e400768SDavid Christensen int ecore_get_q_logical_state(struct bxe_softc *sc,
57794e400768SDavid Christensen 			       struct ecore_queue_sp_obj *obj)
57804e400768SDavid Christensen {
57814e400768SDavid Christensen 	switch (obj->state) {
57824e400768SDavid Christensen 	case ECORE_Q_STATE_ACTIVE:
57834e400768SDavid Christensen 	case ECORE_Q_STATE_MULTI_COS:
57844e400768SDavid Christensen 		return ECORE_Q_LOGICAL_STATE_ACTIVE;
57854e400768SDavid Christensen 	case ECORE_Q_STATE_RESET:
57864e400768SDavid Christensen 	case ECORE_Q_STATE_INITIALIZED:
57874e400768SDavid Christensen 	case ECORE_Q_STATE_MCOS_TERMINATED:
57884e400768SDavid Christensen 	case ECORE_Q_STATE_INACTIVE:
57894e400768SDavid Christensen 	case ECORE_Q_STATE_STOPPED:
57904e400768SDavid Christensen 	case ECORE_Q_STATE_TERMINATED:
57914e400768SDavid Christensen 	case ECORE_Q_STATE_FLRED:
57924e400768SDavid Christensen 		return ECORE_Q_LOGICAL_STATE_STOPPED;
57934e400768SDavid Christensen 	default:
57944e400768SDavid Christensen 		return ECORE_INVAL;
57954e400768SDavid Christensen 	}
57964e400768SDavid Christensen }
57974e400768SDavid Christensen 
57984e400768SDavid Christensen /********************** Function state object *********************************/
ecore_func_get_state(struct bxe_softc * sc,struct ecore_func_sp_obj * o)57994e400768SDavid Christensen enum ecore_func_state ecore_func_get_state(struct bxe_softc *sc,
58004e400768SDavid Christensen 					   struct ecore_func_sp_obj *o)
58014e400768SDavid Christensen {
58024e400768SDavid Christensen 	/* in the middle of transaction - return INVALID state */
58034e400768SDavid Christensen 	if (o->pending)
58044e400768SDavid Christensen 		return ECORE_F_STATE_MAX;
58054e400768SDavid Christensen 
58064e400768SDavid Christensen 	/* unsure the order of reading of o->pending and o->state
58074e400768SDavid Christensen 	 * o->pending should be read first
58084e400768SDavid Christensen 	 */
58094e400768SDavid Christensen 	rmb();
58104e400768SDavid Christensen 
58114e400768SDavid Christensen 	return o->state;
58124e400768SDavid Christensen }
58134e400768SDavid Christensen 
ecore_func_wait_comp(struct bxe_softc * sc,struct ecore_func_sp_obj * o,enum ecore_func_cmd cmd)58144e400768SDavid Christensen static int ecore_func_wait_comp(struct bxe_softc *sc,
58154e400768SDavid Christensen 				struct ecore_func_sp_obj *o,
58164e400768SDavid Christensen 				enum ecore_func_cmd cmd)
58174e400768SDavid Christensen {
58184e400768SDavid Christensen 	return ecore_state_wait(sc, cmd, &o->pending);
58194e400768SDavid Christensen }
58204e400768SDavid Christensen 
58214e400768SDavid Christensen /**
58224e400768SDavid Christensen  * ecore_func_state_change_comp - complete the state machine transition
58234e400768SDavid Christensen  *
58244e400768SDavid Christensen  * @sc:		device handle
58254e400768SDavid Christensen  * @o:
58264e400768SDavid Christensen  * @cmd:
58274e400768SDavid Christensen  *
58284e400768SDavid Christensen  * Called on state change transition. Completes the state
58294e400768SDavid Christensen  * machine transition only - no HW interaction.
58304e400768SDavid Christensen  */
ecore_func_state_change_comp(struct bxe_softc * sc,struct ecore_func_sp_obj * o,enum ecore_func_cmd cmd)58314e400768SDavid Christensen static inline int ecore_func_state_change_comp(struct bxe_softc *sc,
58324e400768SDavid Christensen 					       struct ecore_func_sp_obj *o,
58334e400768SDavid Christensen 					       enum ecore_func_cmd cmd)
58344e400768SDavid Christensen {
58354e400768SDavid Christensen 	unsigned long cur_pending = o->pending;
58364e400768SDavid Christensen 
58374e400768SDavid Christensen 	if (!ECORE_TEST_AND_CLEAR_BIT(cmd, &cur_pending)) {
58384e400768SDavid Christensen 		ECORE_ERR("Bad MC reply %d for func %d in state %d pending 0x%lx, next_state %d\n",
58394e400768SDavid Christensen 			  cmd, ECORE_FUNC_ID(sc), o->state,
58404e400768SDavid Christensen 			  cur_pending, o->next_state);
58414e400768SDavid Christensen 		return ECORE_INVAL;
58424e400768SDavid Christensen 	}
58434e400768SDavid Christensen 
58444e400768SDavid Christensen 	ECORE_MSG(sc,
58454e400768SDavid Christensen 		  "Completing command %d for func %d, setting state to %d\n",
58464e400768SDavid Christensen 		  cmd, ECORE_FUNC_ID(sc), o->next_state);
58474e400768SDavid Christensen 
58484e400768SDavid Christensen 	o->state = o->next_state;
58494e400768SDavid Christensen 	o->next_state = ECORE_F_STATE_MAX;
58504e400768SDavid Christensen 
58514e400768SDavid Christensen 	/* It's important that o->state and o->next_state are
58524e400768SDavid Christensen 	 * updated before o->pending.
58534e400768SDavid Christensen 	 */
58544e400768SDavid Christensen 	wmb();
58554e400768SDavid Christensen 
58564e400768SDavid Christensen 	ECORE_CLEAR_BIT(cmd, &o->pending);
58574e400768SDavid Christensen 	ECORE_SMP_MB_AFTER_CLEAR_BIT();
58584e400768SDavid Christensen 
58594e400768SDavid Christensen 	return ECORE_SUCCESS;
58604e400768SDavid Christensen }
58614e400768SDavid Christensen 
58624e400768SDavid Christensen /**
58634e400768SDavid Christensen  * ecore_func_comp_cmd - complete the state change command
58644e400768SDavid Christensen  *
58654e400768SDavid Christensen  * @sc:		device handle
58664e400768SDavid Christensen  * @o:
58674e400768SDavid Christensen  * @cmd:
58684e400768SDavid Christensen  *
58694e400768SDavid Christensen  * Checks that the arrived completion is expected.
58704e400768SDavid Christensen  */
ecore_func_comp_cmd(struct bxe_softc * sc,struct ecore_func_sp_obj * o,enum ecore_func_cmd cmd)58714e400768SDavid Christensen static int ecore_func_comp_cmd(struct bxe_softc *sc,
58724e400768SDavid Christensen 			       struct ecore_func_sp_obj *o,
58734e400768SDavid Christensen 			       enum ecore_func_cmd cmd)
58744e400768SDavid Christensen {
58754e400768SDavid Christensen 	/* Complete the state machine part first, check if it's a
58764e400768SDavid Christensen 	 * legal completion.
58774e400768SDavid Christensen 	 */
58784e400768SDavid Christensen 	int rc = ecore_func_state_change_comp(sc, o, cmd);
58794e400768SDavid Christensen 	return rc;
58804e400768SDavid Christensen }
58814e400768SDavid Christensen 
58824e400768SDavid Christensen /**
58834e400768SDavid Christensen  * ecore_func_chk_transition - perform function state machine transition
58844e400768SDavid Christensen  *
58854e400768SDavid Christensen  * @sc:		device handle
58864e400768SDavid Christensen  * @o:
58874e400768SDavid Christensen  * @params:
58884e400768SDavid Christensen  *
58894e400768SDavid Christensen  * It both checks if the requested command is legal in a current
58904e400768SDavid Christensen  * state and, if it's legal, sets a `next_state' in the object
58914e400768SDavid Christensen  * that will be used in the completion flow to set the `state'
58924e400768SDavid Christensen  * of the object.
58934e400768SDavid Christensen  *
58944e400768SDavid Christensen  * returns 0 if a requested command is a legal transition,
58954e400768SDavid Christensen  *         ECORE_INVAL otherwise.
58964e400768SDavid Christensen  */
ecore_func_chk_transition(struct bxe_softc * sc,struct ecore_func_sp_obj * o,struct ecore_func_state_params * params)58974e400768SDavid Christensen static int ecore_func_chk_transition(struct bxe_softc *sc,
58984e400768SDavid Christensen 				     struct ecore_func_sp_obj *o,
58994e400768SDavid Christensen 				     struct ecore_func_state_params *params)
59004e400768SDavid Christensen {
59014e400768SDavid Christensen 	enum ecore_func_state state = o->state, next_state = ECORE_F_STATE_MAX;
59024e400768SDavid Christensen 	enum ecore_func_cmd cmd = params->cmd;
59034e400768SDavid Christensen 
59044e400768SDavid Christensen 	/* Forget all pending for completion commands if a driver only state
59054e400768SDavid Christensen 	 * transition has been requested.
59064e400768SDavid Christensen 	 */
59074e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
59084e400768SDavid Christensen 		o->pending = 0;
59094e400768SDavid Christensen 		o->next_state = ECORE_F_STATE_MAX;
59104e400768SDavid Christensen 	}
59114e400768SDavid Christensen 
59124e400768SDavid Christensen 	/* Don't allow a next state transition if we are in the middle of
59134e400768SDavid Christensen 	 * the previous one.
59144e400768SDavid Christensen 	 */
59154e400768SDavid Christensen 	if (o->pending)
59164e400768SDavid Christensen 		return ECORE_BUSY;
59174e400768SDavid Christensen 
59184e400768SDavid Christensen 	switch (state) {
59194e400768SDavid Christensen 	case ECORE_F_STATE_RESET:
59204e400768SDavid Christensen 		if (cmd == ECORE_F_CMD_HW_INIT)
59214e400768SDavid Christensen 			next_state = ECORE_F_STATE_INITIALIZED;
59224e400768SDavid Christensen 
59234e400768SDavid Christensen 		break;
59244e400768SDavid Christensen 	case ECORE_F_STATE_INITIALIZED:
59254e400768SDavid Christensen 		if (cmd == ECORE_F_CMD_START)
59264e400768SDavid Christensen 			next_state = ECORE_F_STATE_STARTED;
59274e400768SDavid Christensen 
59284e400768SDavid Christensen 		else if (cmd == ECORE_F_CMD_HW_RESET)
59294e400768SDavid Christensen 			next_state = ECORE_F_STATE_RESET;
59304e400768SDavid Christensen 
59314e400768SDavid Christensen 		break;
59324e400768SDavid Christensen 	case ECORE_F_STATE_STARTED:
59334e400768SDavid Christensen 		if (cmd == ECORE_F_CMD_STOP)
59344e400768SDavid Christensen 			next_state = ECORE_F_STATE_INITIALIZED;
59354e400768SDavid Christensen 		/* afex ramrods can be sent only in started mode, and only
59364e400768SDavid Christensen 		 * if not pending for function_stop ramrod completion
59374e400768SDavid Christensen 		 * for these events - next state remained STARTED.
59384e400768SDavid Christensen 		 */
59394e400768SDavid Christensen 		else if ((cmd == ECORE_F_CMD_AFEX_UPDATE) &&
59404e400768SDavid Christensen 			 (!ECORE_TEST_BIT(ECORE_F_CMD_STOP, &o->pending)))
59414e400768SDavid Christensen 			next_state = ECORE_F_STATE_STARTED;
59424e400768SDavid Christensen 
59434e400768SDavid Christensen 		else if ((cmd == ECORE_F_CMD_AFEX_VIFLISTS) &&
59444e400768SDavid Christensen 			 (!ECORE_TEST_BIT(ECORE_F_CMD_STOP, &o->pending)))
59454e400768SDavid Christensen 			next_state = ECORE_F_STATE_STARTED;
59464e400768SDavid Christensen 
59474e400768SDavid Christensen 		/* Switch_update ramrod can be sent in either started or
59484e400768SDavid Christensen 		 * tx_stopped state, and it doesn't change the state.
59494e400768SDavid Christensen 		 */
59504e400768SDavid Christensen 		else if ((cmd == ECORE_F_CMD_SWITCH_UPDATE) &&
59514e400768SDavid Christensen 			 (!ECORE_TEST_BIT(ECORE_F_CMD_STOP, &o->pending)))
59524e400768SDavid Christensen 			next_state = ECORE_F_STATE_STARTED;
59534e400768SDavid Christensen 
59544ef8ebfdSDavid C Somayajulu 		else if ((cmd == ECORE_F_CMD_SET_TIMESYNC) &&
59554ef8ebfdSDavid C Somayajulu 			 (!ECORE_TEST_BIT(ECORE_F_CMD_STOP, &o->pending)))
59564ef8ebfdSDavid C Somayajulu 			next_state = ECORE_F_STATE_STARTED;
59574ef8ebfdSDavid C Somayajulu 
59584e400768SDavid Christensen 		else if (cmd == ECORE_F_CMD_TX_STOP)
59594e400768SDavid Christensen 			next_state = ECORE_F_STATE_TX_STOPPED;
59604e400768SDavid Christensen 
59614e400768SDavid Christensen 		break;
59624e400768SDavid Christensen 	case ECORE_F_STATE_TX_STOPPED:
59634e400768SDavid Christensen 		if ((cmd == ECORE_F_CMD_SWITCH_UPDATE) &&
59644e400768SDavid Christensen 		    (!ECORE_TEST_BIT(ECORE_F_CMD_STOP, &o->pending)))
59654e400768SDavid Christensen 			next_state = ECORE_F_STATE_TX_STOPPED;
59664e400768SDavid Christensen 
59674ef8ebfdSDavid C Somayajulu 		else if ((cmd == ECORE_F_CMD_SET_TIMESYNC) &&
59684ef8ebfdSDavid C Somayajulu 		    (!ECORE_TEST_BIT(ECORE_F_CMD_STOP, &o->pending)))
59694ef8ebfdSDavid C Somayajulu 			next_state = ECORE_F_STATE_TX_STOPPED;
59704ef8ebfdSDavid C Somayajulu 
59714e400768SDavid Christensen 		else if (cmd == ECORE_F_CMD_TX_START)
59724e400768SDavid Christensen 			next_state = ECORE_F_STATE_STARTED;
59734e400768SDavid Christensen 
59744e400768SDavid Christensen 		break;
59754e400768SDavid Christensen 	default:
59764e400768SDavid Christensen 		ECORE_ERR("Unknown state: %d\n", state);
59774e400768SDavid Christensen 	}
59784e400768SDavid Christensen 
59794e400768SDavid Christensen 	/* Transition is assured */
59804e400768SDavid Christensen 	if (next_state != ECORE_F_STATE_MAX) {
59814e400768SDavid Christensen 		ECORE_MSG(sc, "Good function state transition: %d(%d)->%d\n",
59824e400768SDavid Christensen 			  state, cmd, next_state);
59834e400768SDavid Christensen 		o->next_state = next_state;
59844e400768SDavid Christensen 		return ECORE_SUCCESS;
59854e400768SDavid Christensen 	}
59864e400768SDavid Christensen 
59874e400768SDavid Christensen 	ECORE_MSG(sc, "Bad function state transition request: %d %d\n",
59884e400768SDavid Christensen 		  state, cmd);
59894e400768SDavid Christensen 
59904e400768SDavid Christensen 	return ECORE_INVAL;
59914e400768SDavid Christensen }
59924e400768SDavid Christensen 
59934e400768SDavid Christensen /**
59944e400768SDavid Christensen  * ecore_func_init_func - performs HW init at function stage
59954e400768SDavid Christensen  *
59964e400768SDavid Christensen  * @sc:		device handle
59974e400768SDavid Christensen  * @drv:
59984e400768SDavid Christensen  *
59994e400768SDavid Christensen  * Init HW when the current phase is
60004e400768SDavid Christensen  * FW_MSG_CODE_DRV_LOAD_FUNCTION: initialize only FUNCTION-only
60014e400768SDavid Christensen  * HW blocks.
60024e400768SDavid Christensen  */
ecore_func_init_func(struct bxe_softc * sc,const struct ecore_func_sp_drv_ops * drv)60034e400768SDavid Christensen static inline int ecore_func_init_func(struct bxe_softc *sc,
60044e400768SDavid Christensen 				       const struct ecore_func_sp_drv_ops *drv)
60054e400768SDavid Christensen {
60064e400768SDavid Christensen 	return drv->init_hw_func(sc);
60074e400768SDavid Christensen }
60084e400768SDavid Christensen 
60094e400768SDavid Christensen /**
60104e400768SDavid Christensen  * ecore_func_init_port - performs HW init at port stage
60114e400768SDavid Christensen  *
60124e400768SDavid Christensen  * @sc:		device handle
60134e400768SDavid Christensen  * @drv:
60144e400768SDavid Christensen  *
60154e400768SDavid Christensen  * Init HW when the current phase is
60164e400768SDavid Christensen  * FW_MSG_CODE_DRV_LOAD_PORT: initialize PORT-only and
60174e400768SDavid Christensen  * FUNCTION-only HW blocks.
60184e400768SDavid Christensen  *
60194e400768SDavid Christensen  */
ecore_func_init_port(struct bxe_softc * sc,const struct ecore_func_sp_drv_ops * drv)60204e400768SDavid Christensen static inline int ecore_func_init_port(struct bxe_softc *sc,
60214e400768SDavid Christensen 				       const struct ecore_func_sp_drv_ops *drv)
60224e400768SDavid Christensen {
60234e400768SDavid Christensen 	int rc = drv->init_hw_port(sc);
60244e400768SDavid Christensen 	if (rc)
60254e400768SDavid Christensen 		return rc;
60264e400768SDavid Christensen 
60274e400768SDavid Christensen 	return ecore_func_init_func(sc, drv);
60284e400768SDavid Christensen }
60294e400768SDavid Christensen 
60304e400768SDavid Christensen /**
60314e400768SDavid Christensen  * ecore_func_init_cmn_chip - performs HW init at chip-common stage
60324e400768SDavid Christensen  *
60334e400768SDavid Christensen  * @sc:		device handle
60344e400768SDavid Christensen  * @drv:
60354e400768SDavid Christensen  *
60364e400768SDavid Christensen  * Init HW when the current phase is
60374e400768SDavid Christensen  * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON_CHIP,
60384e400768SDavid Christensen  * PORT-only and FUNCTION-only HW blocks.
60394e400768SDavid Christensen  */
ecore_func_init_cmn_chip(struct bxe_softc * sc,const struct ecore_func_sp_drv_ops * drv)60404e400768SDavid Christensen static inline int ecore_func_init_cmn_chip(struct bxe_softc *sc,
60414e400768SDavid Christensen 					const struct ecore_func_sp_drv_ops *drv)
60424e400768SDavid Christensen {
60434e400768SDavid Christensen 	int rc = drv->init_hw_cmn_chip(sc);
60444e400768SDavid Christensen 	if (rc)
60454e400768SDavid Christensen 		return rc;
60464e400768SDavid Christensen 
60474e400768SDavid Christensen 	return ecore_func_init_port(sc, drv);
60484e400768SDavid Christensen }
60494e400768SDavid Christensen 
60504e400768SDavid Christensen /**
60514e400768SDavid Christensen  * ecore_func_init_cmn - performs HW init at common stage
60524e400768SDavid Christensen  *
60534e400768SDavid Christensen  * @sc:		device handle
60544e400768SDavid Christensen  * @drv:
60554e400768SDavid Christensen  *
60564e400768SDavid Christensen  * Init HW when the current phase is
60574e400768SDavid Christensen  * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON,
60584e400768SDavid Christensen  * PORT-only and FUNCTION-only HW blocks.
60594e400768SDavid Christensen  */
ecore_func_init_cmn(struct bxe_softc * sc,const struct ecore_func_sp_drv_ops * drv)60604e400768SDavid Christensen static inline int ecore_func_init_cmn(struct bxe_softc *sc,
60614e400768SDavid Christensen 				      const struct ecore_func_sp_drv_ops *drv)
60624e400768SDavid Christensen {
60634e400768SDavid Christensen 	int rc = drv->init_hw_cmn(sc);
60644e400768SDavid Christensen 	if (rc)
60654e400768SDavid Christensen 		return rc;
60664e400768SDavid Christensen 
60674e400768SDavid Christensen 	return ecore_func_init_port(sc, drv);
60684e400768SDavid Christensen }
60694e400768SDavid Christensen 
ecore_func_hw_init(struct bxe_softc * sc,struct ecore_func_state_params * params)60704e400768SDavid Christensen static int ecore_func_hw_init(struct bxe_softc *sc,
60714e400768SDavid Christensen 			      struct ecore_func_state_params *params)
60724e400768SDavid Christensen {
60734e400768SDavid Christensen 	uint32_t load_code = params->params.hw_init.load_phase;
60744e400768SDavid Christensen 	struct ecore_func_sp_obj *o = params->f_obj;
60754e400768SDavid Christensen 	const struct ecore_func_sp_drv_ops *drv = o->drv;
60764e400768SDavid Christensen 	int rc = 0;
60774e400768SDavid Christensen 
60784e400768SDavid Christensen 	ECORE_MSG(sc, "function %d  load_code %x\n",
60794e400768SDavid Christensen 		  ECORE_ABS_FUNC_ID(sc), load_code);
60804e400768SDavid Christensen 
60814e400768SDavid Christensen 	/* Prepare buffers for unzipping the FW */
60824e400768SDavid Christensen 	rc = drv->gunzip_init(sc);
60834e400768SDavid Christensen 	if (rc)
60844e400768SDavid Christensen 		return rc;
60854e400768SDavid Christensen 
60864e400768SDavid Christensen 	/* Prepare FW */
60874e400768SDavid Christensen 	rc = drv->init_fw(sc);
60884e400768SDavid Christensen 	if (rc) {
60894e400768SDavid Christensen 		ECORE_ERR("Error loading firmware\n");
60904e400768SDavid Christensen 		goto init_err;
60914e400768SDavid Christensen 	}
60924e400768SDavid Christensen 
60934e400768SDavid Christensen 	/* Handle the beginning of COMMON_XXX pases separately... */
60944e400768SDavid Christensen 	switch (load_code) {
60954e400768SDavid Christensen 	case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
60964e400768SDavid Christensen 		rc = ecore_func_init_cmn_chip(sc, drv);
60974e400768SDavid Christensen 		if (rc)
60984e400768SDavid Christensen 			goto init_err;
60994e400768SDavid Christensen 
61004e400768SDavid Christensen 		break;
61014e400768SDavid Christensen 	case FW_MSG_CODE_DRV_LOAD_COMMON:
61024e400768SDavid Christensen 		rc = ecore_func_init_cmn(sc, drv);
61034e400768SDavid Christensen 		if (rc)
61044e400768SDavid Christensen 			goto init_err;
61054e400768SDavid Christensen 
61064e400768SDavid Christensen 		break;
61074e400768SDavid Christensen 	case FW_MSG_CODE_DRV_LOAD_PORT:
61084e400768SDavid Christensen 		rc = ecore_func_init_port(sc, drv);
61094e400768SDavid Christensen 		if (rc)
61104e400768SDavid Christensen 			goto init_err;
61114e400768SDavid Christensen 
61124e400768SDavid Christensen 		break;
61134e400768SDavid Christensen 	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
61144e400768SDavid Christensen 		rc = ecore_func_init_func(sc, drv);
61154e400768SDavid Christensen 		if (rc)
61164e400768SDavid Christensen 			goto init_err;
61174e400768SDavid Christensen 
61184e400768SDavid Christensen 		break;
61194e400768SDavid Christensen 	default:
61204e400768SDavid Christensen 		ECORE_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
61214e400768SDavid Christensen 		rc = ECORE_INVAL;
61224e400768SDavid Christensen 	}
61234e400768SDavid Christensen 
61244e400768SDavid Christensen init_err:
61254e400768SDavid Christensen 	drv->gunzip_end(sc);
61264e400768SDavid Christensen 
61274e400768SDavid Christensen 	/* In case of success, complete the command immediately: no ramrods
61284e400768SDavid Christensen 	 * have been sent.
61294e400768SDavid Christensen 	 */
61304e400768SDavid Christensen 	if (!rc)
61314e400768SDavid Christensen 		o->complete_cmd(sc, o, ECORE_F_CMD_HW_INIT);
61324e400768SDavid Christensen 
61334e400768SDavid Christensen 	return rc;
61344e400768SDavid Christensen }
61354e400768SDavid Christensen 
61364e400768SDavid Christensen /**
61374e400768SDavid Christensen  * ecore_func_reset_func - reset HW at function stage
61384e400768SDavid Christensen  *
61394e400768SDavid Christensen  * @sc:		device handle
61404e400768SDavid Christensen  * @drv:
61414e400768SDavid Christensen  *
61424e400768SDavid Christensen  * Reset HW at FW_MSG_CODE_DRV_UNLOAD_FUNCTION stage: reset only
61434e400768SDavid Christensen  * FUNCTION-only HW blocks.
61444e400768SDavid Christensen  */
ecore_func_reset_func(struct bxe_softc * sc,const struct ecore_func_sp_drv_ops * drv)61454e400768SDavid Christensen static inline void ecore_func_reset_func(struct bxe_softc *sc,
61464e400768SDavid Christensen 					const struct ecore_func_sp_drv_ops *drv)
61474e400768SDavid Christensen {
61484e400768SDavid Christensen 	drv->reset_hw_func(sc);
61494e400768SDavid Christensen }
61504e400768SDavid Christensen 
61514e400768SDavid Christensen /**
61524e400768SDavid Christensen  * ecore_func_reset_port - reser HW at port stage
61534e400768SDavid Christensen  *
61544e400768SDavid Christensen  * @sc:		device handle
61554e400768SDavid Christensen  * @drv:
61564e400768SDavid Christensen  *
61574e400768SDavid Christensen  * Reset HW at FW_MSG_CODE_DRV_UNLOAD_PORT stage: reset
61584e400768SDavid Christensen  * FUNCTION-only and PORT-only HW blocks.
61594e400768SDavid Christensen  *
61604e400768SDavid Christensen  *                 !!!IMPORTANT!!!
61614e400768SDavid Christensen  *
61624e400768SDavid Christensen  * It's important to call reset_port before reset_func() as the last thing
61634e400768SDavid Christensen  * reset_func does is pf_disable() thus disabling PGLUE_B, which
61644e400768SDavid Christensen  * makes impossible any DMAE transactions.
61654e400768SDavid Christensen  */
ecore_func_reset_port(struct bxe_softc * sc,const struct ecore_func_sp_drv_ops * drv)61664e400768SDavid Christensen static inline void ecore_func_reset_port(struct bxe_softc *sc,
61674e400768SDavid Christensen 					const struct ecore_func_sp_drv_ops *drv)
61684e400768SDavid Christensen {
61694e400768SDavid Christensen 	drv->reset_hw_port(sc);
61704e400768SDavid Christensen 	ecore_func_reset_func(sc, drv);
61714e400768SDavid Christensen }
61724e400768SDavid Christensen 
61734e400768SDavid Christensen /**
61744e400768SDavid Christensen  * ecore_func_reset_cmn - reser HW at common stage
61754e400768SDavid Christensen  *
61764e400768SDavid Christensen  * @sc:		device handle
61774e400768SDavid Christensen  * @drv:
61784e400768SDavid Christensen  *
61794e400768SDavid Christensen  * Reset HW at FW_MSG_CODE_DRV_UNLOAD_COMMON and
61804e400768SDavid Christensen  * FW_MSG_CODE_DRV_UNLOAD_COMMON_CHIP stages: reset COMMON,
61814e400768SDavid Christensen  * COMMON_CHIP, FUNCTION-only and PORT-only HW blocks.
61824e400768SDavid Christensen  */
ecore_func_reset_cmn(struct bxe_softc * sc,const struct ecore_func_sp_drv_ops * drv)61834e400768SDavid Christensen static inline void ecore_func_reset_cmn(struct bxe_softc *sc,
61844e400768SDavid Christensen 					const struct ecore_func_sp_drv_ops *drv)
61854e400768SDavid Christensen {
61864e400768SDavid Christensen 	ecore_func_reset_port(sc, drv);
61874e400768SDavid Christensen 	drv->reset_hw_cmn(sc);
61884e400768SDavid Christensen }
61894e400768SDavid Christensen 
ecore_func_hw_reset(struct bxe_softc * sc,struct ecore_func_state_params * params)61904e400768SDavid Christensen static inline int ecore_func_hw_reset(struct bxe_softc *sc,
61914e400768SDavid Christensen 				      struct ecore_func_state_params *params)
61924e400768SDavid Christensen {
61934e400768SDavid Christensen 	uint32_t reset_phase = params->params.hw_reset.reset_phase;
61944e400768SDavid Christensen 	struct ecore_func_sp_obj *o = params->f_obj;
61954e400768SDavid Christensen 	const struct ecore_func_sp_drv_ops *drv = o->drv;
61964e400768SDavid Christensen 
61974e400768SDavid Christensen 	ECORE_MSG(sc, "function %d  reset_phase %x\n", ECORE_ABS_FUNC_ID(sc),
61984e400768SDavid Christensen 		  reset_phase);
61994e400768SDavid Christensen 
62004e400768SDavid Christensen 	switch (reset_phase) {
62014e400768SDavid Christensen 	case FW_MSG_CODE_DRV_UNLOAD_COMMON:
62024e400768SDavid Christensen 		ecore_func_reset_cmn(sc, drv);
62034e400768SDavid Christensen 		break;
62044e400768SDavid Christensen 	case FW_MSG_CODE_DRV_UNLOAD_PORT:
62054e400768SDavid Christensen 		ecore_func_reset_port(sc, drv);
62064e400768SDavid Christensen 		break;
62074e400768SDavid Christensen 	case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
62084e400768SDavid Christensen 		ecore_func_reset_func(sc, drv);
62094e400768SDavid Christensen 		break;
62104e400768SDavid Christensen 	default:
62114e400768SDavid Christensen 		ECORE_ERR("Unknown reset_phase (0x%x) from MCP\n",
62124e400768SDavid Christensen 			  reset_phase);
62134e400768SDavid Christensen 		break;
62144e400768SDavid Christensen 	}
62154e400768SDavid Christensen 
62164e400768SDavid Christensen 	/* Complete the command immediately: no ramrods have been sent. */
62174e400768SDavid Christensen 	o->complete_cmd(sc, o, ECORE_F_CMD_HW_RESET);
62184e400768SDavid Christensen 
62194e400768SDavid Christensen 	return ECORE_SUCCESS;
62204e400768SDavid Christensen }
62214e400768SDavid Christensen 
ecore_func_send_start(struct bxe_softc * sc,struct ecore_func_state_params * params)62224e400768SDavid Christensen static inline int ecore_func_send_start(struct bxe_softc *sc,
62234e400768SDavid Christensen 					struct ecore_func_state_params *params)
62244e400768SDavid Christensen {
62254e400768SDavid Christensen 	struct ecore_func_sp_obj *o = params->f_obj;
62264e400768SDavid Christensen 	struct function_start_data *rdata =
62274e400768SDavid Christensen 		(struct function_start_data *)o->rdata;
62284e400768SDavid Christensen 	ecore_dma_addr_t data_mapping = o->rdata_mapping;
62294e400768SDavid Christensen 	struct ecore_func_start_params *start_params = &params->params.start;
62304e400768SDavid Christensen 
62314e400768SDavid Christensen 	ECORE_MEMSET(rdata, 0, sizeof(*rdata));
62324e400768SDavid Christensen 
62334e400768SDavid Christensen 	/* Fill the ramrod data with provided parameters */
62344e400768SDavid Christensen 	rdata->function_mode	= (uint8_t)start_params->mf_mode;
62354e400768SDavid Christensen 	rdata->sd_vlan_tag	= ECORE_CPU_TO_LE16(start_params->sd_vlan_tag);
62364e400768SDavid Christensen 	rdata->path_id		= ECORE_PATH_ID(sc);
62374e400768SDavid Christensen 	rdata->network_cos_mode	= start_params->network_cos_mode;
62384e400768SDavid Christensen 
62394ef8ebfdSDavid C Somayajulu 	rdata->vxlan_dst_port	= start_params->vxlan_dst_port;
62404ef8ebfdSDavid C Somayajulu 	rdata->geneve_dst_port	= start_params->geneve_dst_port;
62414ef8ebfdSDavid C Somayajulu 	rdata->inner_clss_l2gre	= start_params->inner_clss_l2gre;
62424ef8ebfdSDavid C Somayajulu 	rdata->inner_clss_l2geneve = start_params->inner_clss_l2geneve;
62434ef8ebfdSDavid C Somayajulu 	rdata->inner_clss_vxlan	= start_params->inner_clss_vxlan;
62444ef8ebfdSDavid C Somayajulu 	rdata->inner_rss	= start_params->inner_rss;
62454ef8ebfdSDavid C Somayajulu 
62464ef8ebfdSDavid C Somayajulu 	rdata->sd_accept_mf_clss_fail = start_params->class_fail;
62474ef8ebfdSDavid C Somayajulu 	if (start_params->class_fail_ethtype) {
62484ef8ebfdSDavid C Somayajulu 		rdata->sd_accept_mf_clss_fail_match_ethtype = 1;
62494ef8ebfdSDavid C Somayajulu 		rdata->sd_accept_mf_clss_fail_ethtype =
62504ef8ebfdSDavid C Somayajulu 			ECORE_CPU_TO_LE16(start_params->class_fail_ethtype);
62514ef8ebfdSDavid C Somayajulu 	}
62524ef8ebfdSDavid C Somayajulu 	rdata->sd_vlan_force_pri_flg = start_params->sd_vlan_force_pri;
62534ef8ebfdSDavid C Somayajulu 	rdata->sd_vlan_force_pri_val = start_params->sd_vlan_force_pri_val;
62544ef8ebfdSDavid C Somayajulu 
62554ef8ebfdSDavid C Somayajulu 	/** @@@TMP - until FW 7.10.7 (which will introduce an HSI change)
62564ef8ebfdSDavid C Somayajulu 	 * `sd_vlan_eth_type' will replace ethertype in SD mode even if
62574ef8ebfdSDavid C Somayajulu 	 * it's set to 0; This will probably break SD, so we're setting it
62584ef8ebfdSDavid C Somayajulu 	 * to ethertype 0x8100 for now.
62594e400768SDavid Christensen 	 */
62604ef8ebfdSDavid C Somayajulu 	if (start_params->sd_vlan_eth_type)
62614ef8ebfdSDavid C Somayajulu 		rdata->sd_vlan_eth_type =
62624ef8ebfdSDavid C Somayajulu 			ECORE_CPU_TO_LE16(start_params->sd_vlan_eth_type);
62634ef8ebfdSDavid C Somayajulu 	else
62644ef8ebfdSDavid C Somayajulu 		rdata->sd_vlan_eth_type =
62654ef8ebfdSDavid C Somayajulu 			ECORE_CPU_TO_LE16((uint16_t) 0x8100);
62664e400768SDavid Christensen 
62674ef8ebfdSDavid C Somayajulu 	rdata->no_added_tags = start_params->no_added_tags;
62684ef8ebfdSDavid C Somayajulu 
62694ef8ebfdSDavid C Somayajulu 	rdata->c2s_pri_tt_valid = start_params->c2s_pri_valid;
62704ef8ebfdSDavid C Somayajulu 	if (rdata->c2s_pri_tt_valid) {
62714ef8ebfdSDavid C Somayajulu 		memcpy(rdata->c2s_pri_trans_table.val,
62724ef8ebfdSDavid C Somayajulu 		       start_params->c2s_pri,
62734ef8ebfdSDavid C Somayajulu 		       MAX_VLAN_PRIORITIES);
62744ef8ebfdSDavid C Somayajulu 		rdata->c2s_pri_default = start_params->c2s_pri_default;
62754ef8ebfdSDavid C Somayajulu 	}
62764ef8ebfdSDavid C Somayajulu 
62774ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
62784ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
62794ef8ebfdSDavid C Somayajulu 	 *  and updating of the SPQ producer which involves a memory
62804ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
62814ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
62824ef8ebfdSDavid C Somayajulu 	 */
62834e400768SDavid Christensen 	return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0,
62844e400768SDavid Christensen 			     data_mapping, NONE_CONNECTION_TYPE);
62854e400768SDavid Christensen }
62864e400768SDavid Christensen 
ecore_func_send_switch_update(struct bxe_softc * sc,struct ecore_func_state_params * params)62874e400768SDavid Christensen static inline int ecore_func_send_switch_update(struct bxe_softc *sc,
62884e400768SDavid Christensen 					struct ecore_func_state_params *params)
62894e400768SDavid Christensen {
62904e400768SDavid Christensen 	struct ecore_func_sp_obj *o = params->f_obj;
62914e400768SDavid Christensen 	struct function_update_data *rdata =
62924e400768SDavid Christensen 		(struct function_update_data *)o->rdata;
62934e400768SDavid Christensen 	ecore_dma_addr_t data_mapping = o->rdata_mapping;
62944e400768SDavid Christensen 	struct ecore_func_switch_update_params *switch_update_params =
62954e400768SDavid Christensen 		&params->params.switch_update;
62964e400768SDavid Christensen 
62974e400768SDavid Christensen 	ECORE_MEMSET(rdata, 0, sizeof(*rdata));
62984e400768SDavid Christensen 
62994e400768SDavid Christensen 	/* Fill the ramrod data with provided parameters */
63004ef8ebfdSDavid C Somayajulu 	if (ECORE_TEST_BIT(ECORE_F_UPDATE_TX_SWITCH_SUSPEND_CHNG,
63014ef8ebfdSDavid C Somayajulu 			   &switch_update_params->changes)) {
63024e400768SDavid Christensen 	rdata->tx_switch_suspend_change_flg = 1;
63034ef8ebfdSDavid C Somayajulu 		rdata->tx_switch_suspend =
63044ef8ebfdSDavid C Somayajulu 			ECORE_TEST_BIT(ECORE_F_UPDATE_TX_SWITCH_SUSPEND,
63054ef8ebfdSDavid C Somayajulu 				       &switch_update_params->changes);
63064ef8ebfdSDavid C Somayajulu 	}
63074ef8ebfdSDavid C Somayajulu 
63084ef8ebfdSDavid C Somayajulu 	if (ECORE_TEST_BIT(ECORE_F_UPDATE_SD_VLAN_TAG_CHNG,
63094ef8ebfdSDavid C Somayajulu 			   &switch_update_params->changes)) {
63104ef8ebfdSDavid C Somayajulu 		rdata->sd_vlan_tag_change_flg = 1;
63114ef8ebfdSDavid C Somayajulu 		rdata->sd_vlan_tag =
63124ef8ebfdSDavid C Somayajulu 			ECORE_CPU_TO_LE16(switch_update_params->vlan);
63134ef8ebfdSDavid C Somayajulu 	}
63144ef8ebfdSDavid C Somayajulu 
63154ef8ebfdSDavid C Somayajulu 	if (ECORE_TEST_BIT(ECORE_F_UPDATE_SD_VLAN_ETH_TYPE_CHNG,
63164ef8ebfdSDavid C Somayajulu 			   &switch_update_params->changes)) {
63174ef8ebfdSDavid C Somayajulu 		rdata->sd_vlan_eth_type_change_flg = 1;
63184ef8ebfdSDavid C Somayajulu 		rdata->sd_vlan_eth_type =
63194ef8ebfdSDavid C Somayajulu 			ECORE_CPU_TO_LE16(switch_update_params->vlan_eth_type);
63204ef8ebfdSDavid C Somayajulu 	}
63214ef8ebfdSDavid C Somayajulu 
63224ef8ebfdSDavid C Somayajulu 	if (ECORE_TEST_BIT(ECORE_F_UPDATE_VLAN_FORCE_PRIO_CHNG,
63234ef8ebfdSDavid C Somayajulu 			   &switch_update_params->changes)) {
63244ef8ebfdSDavid C Somayajulu 		rdata->sd_vlan_force_pri_change_flg = 1;
63254ef8ebfdSDavid C Somayajulu 		if (ECORE_TEST_BIT(ECORE_F_UPDATE_VLAN_FORCE_PRIO_FLAG,
63264ef8ebfdSDavid C Somayajulu 				   &switch_update_params->changes))
63274ef8ebfdSDavid C Somayajulu 			rdata->sd_vlan_force_pri_flg = 1;
63284ef8ebfdSDavid C Somayajulu 		rdata->sd_vlan_force_pri_flg =
63294ef8ebfdSDavid C Somayajulu 			switch_update_params->vlan_force_prio;
63304ef8ebfdSDavid C Somayajulu 	}
63314ef8ebfdSDavid C Somayajulu 
63324ef8ebfdSDavid C Somayajulu 	if (ECORE_TEST_BIT(ECORE_F_UPDATE_TUNNEL_CFG_CHNG,
63334ef8ebfdSDavid C Somayajulu 			   &switch_update_params->changes)) {
63344ef8ebfdSDavid C Somayajulu 		rdata->update_tunn_cfg_flg = 1;
63354ef8ebfdSDavid C Somayajulu 		if (ECORE_TEST_BIT(ECORE_F_UPDATE_TUNNEL_INNER_CLSS_L2GRE,
63364ef8ebfdSDavid C Somayajulu 				   &switch_update_params->changes))
63374ef8ebfdSDavid C Somayajulu 			rdata->inner_clss_l2gre = 1;
63384ef8ebfdSDavid C Somayajulu 		if (ECORE_TEST_BIT(ECORE_F_UPDATE_TUNNEL_INNER_CLSS_VXLAN,
63394ef8ebfdSDavid C Somayajulu 				   &switch_update_params->changes))
63404ef8ebfdSDavid C Somayajulu 			rdata->inner_clss_vxlan = 1;
63414ef8ebfdSDavid C Somayajulu 		if (ECORE_TEST_BIT(ECORE_F_UPDATE_TUNNEL_INNER_CLSS_L2GENEVE,
63424ef8ebfdSDavid C Somayajulu 				   &switch_update_params->changes))
63434ef8ebfdSDavid C Somayajulu 			rdata->inner_clss_l2geneve = 1;
63444ef8ebfdSDavid C Somayajulu 		if (ECORE_TEST_BIT(ECORE_F_UPDATE_TUNNEL_INNER_RSS,
63454ef8ebfdSDavid C Somayajulu 				   &switch_update_params->changes))
63464ef8ebfdSDavid C Somayajulu 			rdata->inner_rss = 1;
63474ef8ebfdSDavid C Somayajulu 
63484ef8ebfdSDavid C Somayajulu 		rdata->vxlan_dst_port =
63494ef8ebfdSDavid C Somayajulu 			ECORE_CPU_TO_LE16(switch_update_params->vxlan_dst_port);
63504ef8ebfdSDavid C Somayajulu 		rdata->geneve_dst_port =
63514ef8ebfdSDavid C Somayajulu 			ECORE_CPU_TO_LE16(switch_update_params->geneve_dst_port);
63524ef8ebfdSDavid C Somayajulu 	}
63534ef8ebfdSDavid C Somayajulu 
63544e400768SDavid Christensen 	rdata->echo = SWITCH_UPDATE;
63554e400768SDavid Christensen 
63564ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
63574ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
63584ef8ebfdSDavid C Somayajulu 	 * and updating of the SPQ producer which involves a memory
63594ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
63604ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
63614ef8ebfdSDavid C Somayajulu 	 */
63624e400768SDavid Christensen 	return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
63634e400768SDavid Christensen 			     data_mapping, NONE_CONNECTION_TYPE);
63644e400768SDavid Christensen }
63654e400768SDavid Christensen 
ecore_func_send_afex_update(struct bxe_softc * sc,struct ecore_func_state_params * params)63664e400768SDavid Christensen static inline int ecore_func_send_afex_update(struct bxe_softc *sc,
63674e400768SDavid Christensen 					 struct ecore_func_state_params *params)
63684e400768SDavid Christensen {
63694e400768SDavid Christensen 	struct ecore_func_sp_obj *o = params->f_obj;
63704e400768SDavid Christensen 	struct function_update_data *rdata =
63714e400768SDavid Christensen 		(struct function_update_data *)o->afex_rdata;
63724e400768SDavid Christensen 	ecore_dma_addr_t data_mapping = o->afex_rdata_mapping;
63734e400768SDavid Christensen 	struct ecore_func_afex_update_params *afex_update_params =
63744e400768SDavid Christensen 		&params->params.afex_update;
63754e400768SDavid Christensen 
63764e400768SDavid Christensen 	ECORE_MEMSET(rdata, 0, sizeof(*rdata));
63774e400768SDavid Christensen 
63784e400768SDavid Christensen 	/* Fill the ramrod data with provided parameters */
63794e400768SDavid Christensen 	rdata->vif_id_change_flg = 1;
63804e400768SDavid Christensen 	rdata->vif_id = ECORE_CPU_TO_LE16(afex_update_params->vif_id);
63814e400768SDavid Christensen 	rdata->afex_default_vlan_change_flg = 1;
63824e400768SDavid Christensen 	rdata->afex_default_vlan =
63834e400768SDavid Christensen 		ECORE_CPU_TO_LE16(afex_update_params->afex_default_vlan);
63844e400768SDavid Christensen 	rdata->allowed_priorities_change_flg = 1;
63854e400768SDavid Christensen 	rdata->allowed_priorities = afex_update_params->allowed_priorities;
63864e400768SDavid Christensen 	rdata->echo = AFEX_UPDATE;
63874e400768SDavid Christensen 
63884ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
63894ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
63904e400768SDavid Christensen 	 *  and updating of the SPQ producer which involves a memory
63914ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
63924ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
63934e400768SDavid Christensen 	 */
63944e400768SDavid Christensen 	ECORE_MSG(sc,
63954e400768SDavid Christensen 		  "afex: sending func_update vif_id 0x%x dvlan 0x%x prio 0x%x\n",
63964e400768SDavid Christensen 		  rdata->vif_id,
63974e400768SDavid Christensen 		  rdata->afex_default_vlan, rdata->allowed_priorities);
63984e400768SDavid Christensen 
63994e400768SDavid Christensen 	return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
64004e400768SDavid Christensen 			     data_mapping, NONE_CONNECTION_TYPE);
64014e400768SDavid Christensen }
64024e400768SDavid Christensen 
64034e400768SDavid Christensen static
ecore_func_send_afex_viflists(struct bxe_softc * sc,struct ecore_func_state_params * params)64044e400768SDavid Christensen inline int ecore_func_send_afex_viflists(struct bxe_softc *sc,
64054e400768SDavid Christensen 					 struct ecore_func_state_params *params)
64064e400768SDavid Christensen {
64074e400768SDavid Christensen 	struct ecore_func_sp_obj *o = params->f_obj;
64084e400768SDavid Christensen 	struct afex_vif_list_ramrod_data *rdata =
64094e400768SDavid Christensen 		(struct afex_vif_list_ramrod_data *)o->afex_rdata;
64104e400768SDavid Christensen 	struct ecore_func_afex_viflists_params *afex_vif_params =
64114e400768SDavid Christensen 		&params->params.afex_viflists;
64124e400768SDavid Christensen 	uint64_t *p_rdata = (uint64_t *)rdata;
64134e400768SDavid Christensen 
64144e400768SDavid Christensen 	ECORE_MEMSET(rdata, 0, sizeof(*rdata));
64154e400768SDavid Christensen 
64164e400768SDavid Christensen 	/* Fill the ramrod data with provided parameters */
64174e400768SDavid Christensen 	rdata->vif_list_index = ECORE_CPU_TO_LE16(afex_vif_params->vif_list_index);
64184e400768SDavid Christensen 	rdata->func_bit_map          = afex_vif_params->func_bit_map;
64194e400768SDavid Christensen 	rdata->afex_vif_list_command = afex_vif_params->afex_vif_list_command;
64204e400768SDavid Christensen 	rdata->func_to_clear         = afex_vif_params->func_to_clear;
64214e400768SDavid Christensen 
64224e400768SDavid Christensen 	/* send in echo type of sub command */
64234e400768SDavid Christensen 	rdata->echo = afex_vif_params->afex_vif_list_command;
64244e400768SDavid Christensen 
64254e400768SDavid Christensen 	ECORE_MSG(sc, "afex: ramrod lists, cmd 0x%x index 0x%x func_bit_map 0x%x func_to_clr 0x%x\n",
64264e400768SDavid Christensen 		  rdata->afex_vif_list_command, rdata->vif_list_index,
64274e400768SDavid Christensen 		  rdata->func_bit_map, rdata->func_to_clear);
64284e400768SDavid Christensen 
64294ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
64304ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
64314ef8ebfdSDavid C Somayajulu 	 * and updating of the SPQ producer which involves a memory
64324ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
64334ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
64344ef8ebfdSDavid C Somayajulu 	 */
64354ef8ebfdSDavid C Somayajulu 
64364e400768SDavid Christensen 	/* this ramrod sends data directly and not through DMA mapping */
64374e400768SDavid Christensen 	return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_AFEX_VIF_LISTS, 0,
64384e400768SDavid Christensen 			     *p_rdata, NONE_CONNECTION_TYPE);
64394e400768SDavid Christensen }
64404e400768SDavid Christensen 
ecore_func_send_stop(struct bxe_softc * sc,struct ecore_func_state_params * params)64414e400768SDavid Christensen static inline int ecore_func_send_stop(struct bxe_softc *sc,
64424e400768SDavid Christensen 				       struct ecore_func_state_params *params)
64434e400768SDavid Christensen {
64444e400768SDavid Christensen 	return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0,
64454e400768SDavid Christensen 			     NONE_CONNECTION_TYPE);
64464e400768SDavid Christensen }
64474e400768SDavid Christensen 
ecore_func_send_tx_stop(struct bxe_softc * sc,struct ecore_func_state_params * params)64484e400768SDavid Christensen static inline int ecore_func_send_tx_stop(struct bxe_softc *sc,
64494e400768SDavid Christensen 				       struct ecore_func_state_params *params)
64504e400768SDavid Christensen {
64514e400768SDavid Christensen 	return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, 0, 0,
64524e400768SDavid Christensen 			     NONE_CONNECTION_TYPE);
64534e400768SDavid Christensen }
ecore_func_send_tx_start(struct bxe_softc * sc,struct ecore_func_state_params * params)64544e400768SDavid Christensen static inline int ecore_func_send_tx_start(struct bxe_softc *sc,
64554e400768SDavid Christensen 				       struct ecore_func_state_params *params)
64564e400768SDavid Christensen {
64574e400768SDavid Christensen 	struct ecore_func_sp_obj *o = params->f_obj;
64584e400768SDavid Christensen 	struct flow_control_configuration *rdata =
64594e400768SDavid Christensen 		(struct flow_control_configuration *)o->rdata;
64604e400768SDavid Christensen 	ecore_dma_addr_t data_mapping = o->rdata_mapping;
64614e400768SDavid Christensen 	struct ecore_func_tx_start_params *tx_start_params =
64624e400768SDavid Christensen 		&params->params.tx_start;
64634e400768SDavid Christensen 	int i;
64644e400768SDavid Christensen 
64654e400768SDavid Christensen 	ECORE_MEMSET(rdata, 0, sizeof(*rdata));
64664e400768SDavid Christensen 
64674e400768SDavid Christensen 	rdata->dcb_enabled = tx_start_params->dcb_enabled;
64684e400768SDavid Christensen 	rdata->dcb_version = tx_start_params->dcb_version;
64694e400768SDavid Christensen 	rdata->dont_add_pri_0 = tx_start_params->dont_add_pri_0;
64704e400768SDavid Christensen 
64714e400768SDavid Christensen 	for (i = 0; i < ARRAY_SIZE(rdata->traffic_type_to_priority_cos); i++)
64724e400768SDavid Christensen 		rdata->traffic_type_to_priority_cos[i] =
64734e400768SDavid Christensen 			tx_start_params->traffic_type_to_priority_cos[i];
64744e400768SDavid Christensen 
64754ef8ebfdSDavid C Somayajulu 	for (i = 0; i < MAX_TRAFFIC_TYPES; i++)
64764ef8ebfdSDavid C Somayajulu 		rdata->dcb_outer_pri[i] = tx_start_params->dcb_outer_pri[i];
64774ef8ebfdSDavid C Somayajulu 
64784ef8ebfdSDavid C Somayajulu 	/* No need for an explicit memory barrier here as long as we
64794ef8ebfdSDavid C Somayajulu 	 * ensure the ordering of writing to the SPQ element
64804ef8ebfdSDavid C Somayajulu 	 * and updating of the SPQ producer which involves a memory
64814ef8ebfdSDavid C Somayajulu 	 * read. If the memory read is removed we will have to put a
64824ef8ebfdSDavid C Somayajulu 	 * full memory barrier there (inside ecore_sp_post()).
64834ef8ebfdSDavid C Somayajulu 	 */
64844e400768SDavid Christensen 	return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0,
64854e400768SDavid Christensen 			     data_mapping, NONE_CONNECTION_TYPE);
64864e400768SDavid Christensen }
64874e400768SDavid Christensen 
ecore_func_send_set_timesync(struct bxe_softc * sc,struct ecore_func_state_params * params)64884ef8ebfdSDavid C Somayajulu static inline int ecore_func_send_set_timesync(struct bxe_softc *sc,
64894ef8ebfdSDavid C Somayajulu 					struct ecore_func_state_params *params)
64904ef8ebfdSDavid C Somayajulu {
64914ef8ebfdSDavid C Somayajulu 	struct ecore_func_sp_obj *o = params->f_obj;
64924ef8ebfdSDavid C Somayajulu 	struct set_timesync_ramrod_data *rdata =
64934ef8ebfdSDavid C Somayajulu 		(struct set_timesync_ramrod_data *)o->rdata;
64944ef8ebfdSDavid C Somayajulu 	ecore_dma_addr_t data_mapping = o->rdata_mapping;
64954ef8ebfdSDavid C Somayajulu 	struct ecore_func_set_timesync_params *set_timesync_params =
64964ef8ebfdSDavid C Somayajulu 		&params->params.set_timesync;
64974ef8ebfdSDavid C Somayajulu 
64984ef8ebfdSDavid C Somayajulu 	ECORE_MEMSET(rdata, 0, sizeof(*rdata));
64994ef8ebfdSDavid C Somayajulu 
65004ef8ebfdSDavid C Somayajulu 	/* Fill the ramrod data with provided parameters */
65014ef8ebfdSDavid C Somayajulu 	rdata->drift_adjust_cmd = set_timesync_params->drift_adjust_cmd;
65024ef8ebfdSDavid C Somayajulu 	rdata->offset_cmd = set_timesync_params->offset_cmd;
65034ef8ebfdSDavid C Somayajulu 	rdata->add_sub_drift_adjust_value =
65044ef8ebfdSDavid C Somayajulu 		set_timesync_params->add_sub_drift_adjust_value;
65054ef8ebfdSDavid C Somayajulu 	rdata->drift_adjust_value = set_timesync_params->drift_adjust_value;
65064ef8ebfdSDavid C Somayajulu 	rdata->drift_adjust_period = set_timesync_params->drift_adjust_period;
65074ef8ebfdSDavid C Somayajulu 	rdata->offset_delta.lo =
65084ef8ebfdSDavid C Somayajulu 		ECORE_CPU_TO_LE32(U64_LO(set_timesync_params->offset_delta));
65094ef8ebfdSDavid C Somayajulu 	rdata->offset_delta.hi =
65104ef8ebfdSDavid C Somayajulu 		ECORE_CPU_TO_LE32(U64_HI(set_timesync_params->offset_delta));
65114ef8ebfdSDavid C Somayajulu 
65124ef8ebfdSDavid C Somayajulu 	ECORE_MSG(sc, "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",
65134ef8ebfdSDavid C Somayajulu 	   rdata->drift_adjust_cmd, rdata->offset_cmd,
65144ef8ebfdSDavid C Somayajulu 	   rdata->add_sub_drift_adjust_value, rdata->drift_adjust_value,
65154ef8ebfdSDavid C Somayajulu 	   rdata->drift_adjust_period, rdata->offset_delta.lo,
65164ef8ebfdSDavid C Somayajulu 	   rdata->offset_delta.hi);
65174ef8ebfdSDavid C Somayajulu 
65184ef8ebfdSDavid C Somayajulu 	return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_SET_TIMESYNC, 0,
65194ef8ebfdSDavid C Somayajulu 			     data_mapping, NONE_CONNECTION_TYPE);
65204ef8ebfdSDavid C Somayajulu }
65214ef8ebfdSDavid C Somayajulu 
ecore_func_send_cmd(struct bxe_softc * sc,struct ecore_func_state_params * params)65224e400768SDavid Christensen static int ecore_func_send_cmd(struct bxe_softc *sc,
65234e400768SDavid Christensen 			       struct ecore_func_state_params *params)
65244e400768SDavid Christensen {
65254e400768SDavid Christensen 	switch (params->cmd) {
65264e400768SDavid Christensen 	case ECORE_F_CMD_HW_INIT:
65274e400768SDavid Christensen 		return ecore_func_hw_init(sc, params);
65284e400768SDavid Christensen 	case ECORE_F_CMD_START:
65294e400768SDavid Christensen 		return ecore_func_send_start(sc, params);
65304e400768SDavid Christensen 	case ECORE_F_CMD_STOP:
65314e400768SDavid Christensen 		return ecore_func_send_stop(sc, params);
65324e400768SDavid Christensen 	case ECORE_F_CMD_HW_RESET:
65334e400768SDavid Christensen 		return ecore_func_hw_reset(sc, params);
65344e400768SDavid Christensen 	case ECORE_F_CMD_AFEX_UPDATE:
65354e400768SDavid Christensen 		return ecore_func_send_afex_update(sc, params);
65364e400768SDavid Christensen 	case ECORE_F_CMD_AFEX_VIFLISTS:
65374e400768SDavid Christensen 		return ecore_func_send_afex_viflists(sc, params);
65384e400768SDavid Christensen 	case ECORE_F_CMD_TX_STOP:
65394e400768SDavid Christensen 		return ecore_func_send_tx_stop(sc, params);
65404e400768SDavid Christensen 	case ECORE_F_CMD_TX_START:
65414e400768SDavid Christensen 		return ecore_func_send_tx_start(sc, params);
65424e400768SDavid Christensen 	case ECORE_F_CMD_SWITCH_UPDATE:
65434e400768SDavid Christensen 		return ecore_func_send_switch_update(sc, params);
65444ef8ebfdSDavid C Somayajulu 	case ECORE_F_CMD_SET_TIMESYNC:
65454ef8ebfdSDavid C Somayajulu 		return ecore_func_send_set_timesync(sc, params);
65464e400768SDavid Christensen 	default:
65474e400768SDavid Christensen 		ECORE_ERR("Unknown command: %d\n", params->cmd);
65484e400768SDavid Christensen 		return ECORE_INVAL;
65494e400768SDavid Christensen 	}
65504e400768SDavid Christensen }
65514e400768SDavid Christensen 
ecore_init_func_obj(struct bxe_softc * sc,struct ecore_func_sp_obj * obj,void * rdata,ecore_dma_addr_t rdata_mapping,void * afex_rdata,ecore_dma_addr_t afex_rdata_mapping,struct ecore_func_sp_drv_ops * drv_iface)65524e400768SDavid Christensen void ecore_init_func_obj(struct bxe_softc *sc,
65534e400768SDavid Christensen 			 struct ecore_func_sp_obj *obj,
65544e400768SDavid Christensen 			 void *rdata, ecore_dma_addr_t rdata_mapping,
65554e400768SDavid Christensen 			 void *afex_rdata, ecore_dma_addr_t afex_rdata_mapping,
65564e400768SDavid Christensen 			 struct ecore_func_sp_drv_ops *drv_iface)
65574e400768SDavid Christensen {
65584e400768SDavid Christensen 	ECORE_MEMSET(obj, 0, sizeof(*obj));
65594e400768SDavid Christensen 
65604e400768SDavid Christensen 	ECORE_MUTEX_INIT(&obj->one_pending_mutex);
65614e400768SDavid Christensen 
65624e400768SDavid Christensen 	obj->rdata = rdata;
65634e400768SDavid Christensen 	obj->rdata_mapping = rdata_mapping;
65644e400768SDavid Christensen 	obj->afex_rdata = afex_rdata;
65654e400768SDavid Christensen 	obj->afex_rdata_mapping = afex_rdata_mapping;
65664e400768SDavid Christensen 	obj->send_cmd = ecore_func_send_cmd;
65674e400768SDavid Christensen 	obj->check_transition = ecore_func_chk_transition;
65684e400768SDavid Christensen 	obj->complete_cmd = ecore_func_comp_cmd;
65694e400768SDavid Christensen 	obj->wait_comp = ecore_func_wait_comp;
65704e400768SDavid Christensen 	obj->drv = drv_iface;
65714e400768SDavid Christensen }
65724e400768SDavid Christensen 
65734e400768SDavid Christensen /**
65744e400768SDavid Christensen  * ecore_func_state_change - perform Function state change transition
65754e400768SDavid Christensen  *
65764e400768SDavid Christensen  * @sc:		device handle
65774e400768SDavid Christensen  * @params:	parameters to perform the transaction
65784e400768SDavid Christensen  *
65794e400768SDavid Christensen  * returns 0 in case of successfully completed transition,
65804e400768SDavid Christensen  *         negative error code in case of failure, positive
65814e400768SDavid Christensen  *         (EBUSY) value if there is a completion to that is
65824e400768SDavid Christensen  *         still pending (possible only if RAMROD_COMP_WAIT is
65834e400768SDavid Christensen  *         not set in params->ramrod_flags for asynchronous
65844e400768SDavid Christensen  *         commands).
65854e400768SDavid Christensen  */
ecore_func_state_change(struct bxe_softc * sc,struct ecore_func_state_params * params)65864e400768SDavid Christensen int ecore_func_state_change(struct bxe_softc *sc,
65874e400768SDavid Christensen 			    struct ecore_func_state_params *params)
65884e400768SDavid Christensen {
65894e400768SDavid Christensen 	struct ecore_func_sp_obj *o = params->f_obj;
65904e400768SDavid Christensen 	int rc, cnt = 300;
65914e400768SDavid Christensen 	enum ecore_func_cmd cmd = params->cmd;
65924e400768SDavid Christensen 	unsigned long *pending = &o->pending;
65934e400768SDavid Christensen 
65944e400768SDavid Christensen 	ECORE_MUTEX_LOCK(&o->one_pending_mutex);
65954e400768SDavid Christensen 
65964e400768SDavid Christensen 	/* Check that the requested transition is legal */
65974e400768SDavid Christensen 	rc = o->check_transition(sc, o, params);
65984e400768SDavid Christensen 	if ((rc == ECORE_BUSY) &&
65994e400768SDavid Christensen 	    (ECORE_TEST_BIT(RAMROD_RETRY, &params->ramrod_flags))) {
66004e400768SDavid Christensen 		while ((rc == ECORE_BUSY) && (--cnt > 0)) {
66014e400768SDavid Christensen 			ECORE_MUTEX_UNLOCK(&o->one_pending_mutex);
66024e400768SDavid Christensen 			ECORE_MSLEEP(10);
66034e400768SDavid Christensen 			ECORE_MUTEX_LOCK(&o->one_pending_mutex);
66044e400768SDavid Christensen 			rc = o->check_transition(sc, o, params);
66054e400768SDavid Christensen 		}
66064e400768SDavid Christensen 		if (rc == ECORE_BUSY) {
66074e400768SDavid Christensen 			ECORE_MUTEX_UNLOCK(&o->one_pending_mutex);
66084e400768SDavid Christensen 			ECORE_ERR("timeout waiting for previous ramrod completion\n");
66094e400768SDavid Christensen 			return rc;
66104e400768SDavid Christensen 		}
66114e400768SDavid Christensen 	} else if (rc) {
66124e400768SDavid Christensen 		ECORE_MUTEX_UNLOCK(&o->one_pending_mutex);
66134e400768SDavid Christensen 		return rc;
66144e400768SDavid Christensen 	}
66154e400768SDavid Christensen 
66164e400768SDavid Christensen 	/* Set "pending" bit */
66174e400768SDavid Christensen 	ECORE_SET_BIT(cmd, pending);
66184e400768SDavid Christensen 
66194e400768SDavid Christensen 	/* Don't send a command if only driver cleanup was requested */
66204e400768SDavid Christensen 	if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
66214e400768SDavid Christensen 		ecore_func_state_change_comp(sc, o, cmd);
66224e400768SDavid Christensen 		ECORE_MUTEX_UNLOCK(&o->one_pending_mutex);
66234e400768SDavid Christensen 	} else {
66244e400768SDavid Christensen 		/* Send a ramrod */
66254e400768SDavid Christensen 		rc = o->send_cmd(sc, params);
66264e400768SDavid Christensen 
66274e400768SDavid Christensen 		ECORE_MUTEX_UNLOCK(&o->one_pending_mutex);
66284e400768SDavid Christensen 
66294e400768SDavid Christensen 		if (rc) {
66304e400768SDavid Christensen 			o->next_state = ECORE_F_STATE_MAX;
66314e400768SDavid Christensen 			ECORE_CLEAR_BIT(cmd, pending);
66324e400768SDavid Christensen 			ECORE_SMP_MB_AFTER_CLEAR_BIT();
66334e400768SDavid Christensen 			return rc;
66344e400768SDavid Christensen 		}
66354e400768SDavid Christensen 
66364e400768SDavid Christensen 		if (ECORE_TEST_BIT(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
66374e400768SDavid Christensen 			rc = o->wait_comp(sc, o, cmd);
66384e400768SDavid Christensen 			if (rc)
66394e400768SDavid Christensen 				return rc;
66404e400768SDavid Christensen 
66414e400768SDavid Christensen 			return ECORE_SUCCESS;
66424e400768SDavid Christensen 		}
66434e400768SDavid Christensen 	}
66444e400768SDavid Christensen 
66454e400768SDavid Christensen 	return ECORE_RET_PENDING(cmd, pending);
66464e400768SDavid Christensen }
6647