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, ®_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(®_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 ®_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(®_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(®_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(®_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, ¶ms->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, ¶ms->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 ¶ms->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 = ¶ms->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 ¶ms->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 ¶ms->update_flags);
51624e400768SDavid Christensen data->inner_vlan_removal_change_flg =
51634e400768SDavid Christensen ECORE_TEST_BIT(ECORE_Q_UPDATE_IN_VLAN_REM_CHNG,
51644e400768SDavid Christensen ¶ms->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 ¶ms->update_flags);
51704e400768SDavid Christensen data->outer_vlan_removal_change_flg =
51714e400768SDavid Christensen ECORE_TEST_BIT(ECORE_Q_UPDATE_OUT_VLAN_REM_CHNG,
51724e400768SDavid Christensen ¶ms->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 ¶ms->update_flags);
51804e400768SDavid Christensen data->anti_spoofing_change_flg =
51814e400768SDavid Christensen ECORE_TEST_BIT(ECORE_Q_UPDATE_ANTI_SPOOF_CHNG,
51824e400768SDavid Christensen ¶ms->update_flags);
51834e400768SDavid Christensen
51844e400768SDavid Christensen /* Activate/Deactivate */
51854e400768SDavid Christensen data->activate_flg =
51864e400768SDavid Christensen ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE, ¶ms->update_flags);
51874e400768SDavid Christensen data->activate_change_flg =
51884e400768SDavid Christensen ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE_CHNG,
51894e400768SDavid Christensen ¶ms->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 ¶ms->update_flags);
51954e400768SDavid Christensen data->default_vlan_change_flg =
51964e400768SDavid Christensen ECORE_TEST_BIT(ECORE_Q_UPDATE_DEF_VLAN_EN_CHNG,
51974e400768SDavid Christensen ¶ms->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 ¶ms->update_flags);
52034e400768SDavid Christensen data->silent_vlan_removal_flg =
52044e400768SDavid Christensen ECORE_TEST_BIT(ECORE_Q_UPDATE_SILENT_VLAN_REM,
52054e400768SDavid Christensen ¶ms->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 ¶ms->update_flags);
52134e400768SDavid Christensen data->tx_switching_change_flg =
52144e400768SDavid Christensen ECORE_TEST_BIT(ECORE_Q_UPDATE_TX_SWITCHING_CHNG,
52154e400768SDavid Christensen ¶ms->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 ¶ms->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 ¶ms->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 ¶ms->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 = ¶ms->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 = ¶ms->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 ¶ms->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 ¶ms->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, ¶ms->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 ¶ms->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 ¶ms->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, ¶ms->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 = ¶ms->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 ¶ms->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 ¶ms->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 ¶ms->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 ¶ms->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 ¶ms->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, ¶ms->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, ¶ms->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, ¶ms->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