193f1cac5SPaul Winder /******************************************************************************
293f1cac5SPaul Winder
3*df36e06dSRobert Mustacchi Copyright (c) 2013-2018, Intel Corporation
493f1cac5SPaul Winder All rights reserved.
593f1cac5SPaul Winder
693f1cac5SPaul Winder Redistribution and use in source and binary forms, with or without
793f1cac5SPaul Winder modification, are permitted provided that the following conditions are met:
893f1cac5SPaul Winder
993f1cac5SPaul Winder 1. Redistributions of source code must retain the above copyright notice,
1093f1cac5SPaul Winder this list of conditions and the following disclaimer.
1193f1cac5SPaul Winder
1293f1cac5SPaul Winder 2. Redistributions in binary form must reproduce the above copyright
1393f1cac5SPaul Winder notice, this list of conditions and the following disclaimer in the
1493f1cac5SPaul Winder documentation and/or other materials provided with the distribution.
1593f1cac5SPaul Winder
1693f1cac5SPaul Winder 3. Neither the name of the Intel Corporation nor the names of its
1793f1cac5SPaul Winder contributors may be used to endorse or promote products derived from
1893f1cac5SPaul Winder this software without specific prior written permission.
1993f1cac5SPaul Winder
2093f1cac5SPaul Winder THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2193f1cac5SPaul Winder AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2293f1cac5SPaul Winder IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2393f1cac5SPaul Winder ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2493f1cac5SPaul Winder LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2593f1cac5SPaul Winder CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2693f1cac5SPaul Winder SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2793f1cac5SPaul Winder INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2893f1cac5SPaul Winder CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2993f1cac5SPaul Winder ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3093f1cac5SPaul Winder POSSIBILITY OF SUCH DAMAGE.
3193f1cac5SPaul Winder
3293f1cac5SPaul Winder ******************************************************************************/
3393f1cac5SPaul Winder /*$FreeBSD$*/
3493f1cac5SPaul Winder
3593f1cac5SPaul Winder #include "i40e_adminq.h"
3693f1cac5SPaul Winder #include "i40e_prototype.h"
3793f1cac5SPaul Winder #include "i40e_dcb.h"
3893f1cac5SPaul Winder
3993f1cac5SPaul Winder /**
4093f1cac5SPaul Winder * i40e_get_dcbx_status
4193f1cac5SPaul Winder * @hw: pointer to the hw struct
4293f1cac5SPaul Winder * @status: Embedded DCBX Engine Status
4393f1cac5SPaul Winder *
4493f1cac5SPaul Winder * Get the DCBX status from the Firmware
4593f1cac5SPaul Winder **/
i40e_get_dcbx_status(struct i40e_hw * hw,u16 * status)4693f1cac5SPaul Winder enum i40e_status_code i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
4793f1cac5SPaul Winder {
4893f1cac5SPaul Winder u32 reg;
4993f1cac5SPaul Winder
5093f1cac5SPaul Winder if (!status)
5193f1cac5SPaul Winder return I40E_ERR_PARAM;
5293f1cac5SPaul Winder
5393f1cac5SPaul Winder reg = rd32(hw, I40E_PRTDCB_GENS);
5493f1cac5SPaul Winder *status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >>
5593f1cac5SPaul Winder I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT);
5693f1cac5SPaul Winder
5793f1cac5SPaul Winder return I40E_SUCCESS;
5893f1cac5SPaul Winder }
5993f1cac5SPaul Winder
6093f1cac5SPaul Winder /**
6193f1cac5SPaul Winder * i40e_parse_ieee_etscfg_tlv
6293f1cac5SPaul Winder * @tlv: IEEE 802.1Qaz ETS CFG TLV
6393f1cac5SPaul Winder * @dcbcfg: Local store to update ETS CFG data
6493f1cac5SPaul Winder *
6593f1cac5SPaul Winder * Parses IEEE 802.1Qaz ETS CFG TLV
6693f1cac5SPaul Winder **/
i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)6793f1cac5SPaul Winder static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
6893f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
6993f1cac5SPaul Winder {
7093f1cac5SPaul Winder struct i40e_dcb_ets_config *etscfg;
7193f1cac5SPaul Winder u8 *buf = tlv->tlvinfo;
7293f1cac5SPaul Winder u16 offset = 0;
7393f1cac5SPaul Winder u8 priority;
7493f1cac5SPaul Winder int i;
7593f1cac5SPaul Winder
7693f1cac5SPaul Winder /* First Octet post subtype
7793f1cac5SPaul Winder * --------------------------
7893f1cac5SPaul Winder * |will-|CBS | Re- | Max |
7993f1cac5SPaul Winder * |ing | |served| TCs |
8093f1cac5SPaul Winder * --------------------------
8193f1cac5SPaul Winder * |1bit | 1bit|3 bits|3bits|
8293f1cac5SPaul Winder */
8393f1cac5SPaul Winder etscfg = &dcbcfg->etscfg;
8493f1cac5SPaul Winder etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >>
8593f1cac5SPaul Winder I40E_IEEE_ETS_WILLING_SHIFT);
8693f1cac5SPaul Winder etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >>
8793f1cac5SPaul Winder I40E_IEEE_ETS_CBS_SHIFT);
8893f1cac5SPaul Winder etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >>
8993f1cac5SPaul Winder I40E_IEEE_ETS_MAXTC_SHIFT);
9093f1cac5SPaul Winder
9193f1cac5SPaul Winder /* Move offset to Priority Assignment Table */
9293f1cac5SPaul Winder offset++;
9393f1cac5SPaul Winder
9493f1cac5SPaul Winder /* Priority Assignment Table (4 octets)
9593f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 |
9693f1cac5SPaul Winder * -----------------------------------------
9793f1cac5SPaul Winder * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
9893f1cac5SPaul Winder * -----------------------------------------
9993f1cac5SPaul Winder * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
10093f1cac5SPaul Winder * -----------------------------------------
10193f1cac5SPaul Winder */
10293f1cac5SPaul Winder for (i = 0; i < 4; i++) {
10393f1cac5SPaul Winder priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
10493f1cac5SPaul Winder I40E_IEEE_ETS_PRIO_1_SHIFT);
10593f1cac5SPaul Winder etscfg->prioritytable[i * 2] = priority;
10693f1cac5SPaul Winder priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
10793f1cac5SPaul Winder I40E_IEEE_ETS_PRIO_0_SHIFT);
10893f1cac5SPaul Winder etscfg->prioritytable[i * 2 + 1] = priority;
10993f1cac5SPaul Winder offset++;
11093f1cac5SPaul Winder }
11193f1cac5SPaul Winder
11293f1cac5SPaul Winder /* TC Bandwidth Table (8 octets)
11393f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
11493f1cac5SPaul Winder * ---------------------------------
11593f1cac5SPaul Winder * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
11693f1cac5SPaul Winder * ---------------------------------
11793f1cac5SPaul Winder */
11893f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
11993f1cac5SPaul Winder etscfg->tcbwtable[i] = buf[offset++];
12093f1cac5SPaul Winder
12193f1cac5SPaul Winder /* TSA Assignment Table (8 octets)
12293f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
12393f1cac5SPaul Winder * ---------------------------------
12493f1cac5SPaul Winder * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
12593f1cac5SPaul Winder * ---------------------------------
12693f1cac5SPaul Winder */
12793f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
12893f1cac5SPaul Winder etscfg->tsatable[i] = buf[offset++];
12993f1cac5SPaul Winder }
13093f1cac5SPaul Winder
13193f1cac5SPaul Winder /**
13293f1cac5SPaul Winder * i40e_parse_ieee_etsrec_tlv
13393f1cac5SPaul Winder * @tlv: IEEE 802.1Qaz ETS REC TLV
13493f1cac5SPaul Winder * @dcbcfg: Local store to update ETS REC data
13593f1cac5SPaul Winder *
13693f1cac5SPaul Winder * Parses IEEE 802.1Qaz ETS REC TLV
13793f1cac5SPaul Winder **/
i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)13893f1cac5SPaul Winder static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
13993f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
14093f1cac5SPaul Winder {
14193f1cac5SPaul Winder u8 *buf = tlv->tlvinfo;
14293f1cac5SPaul Winder u16 offset = 0;
14393f1cac5SPaul Winder u8 priority;
14493f1cac5SPaul Winder int i;
14593f1cac5SPaul Winder
14693f1cac5SPaul Winder /* Move offset to priority table */
14793f1cac5SPaul Winder offset++;
14893f1cac5SPaul Winder
14993f1cac5SPaul Winder /* Priority Assignment Table (4 octets)
15093f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 |
15193f1cac5SPaul Winder * -----------------------------------------
15293f1cac5SPaul Winder * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
15393f1cac5SPaul Winder * -----------------------------------------
15493f1cac5SPaul Winder * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
15593f1cac5SPaul Winder * -----------------------------------------
15693f1cac5SPaul Winder */
15793f1cac5SPaul Winder for (i = 0; i < 4; i++) {
15893f1cac5SPaul Winder priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
15993f1cac5SPaul Winder I40E_IEEE_ETS_PRIO_1_SHIFT);
16093f1cac5SPaul Winder dcbcfg->etsrec.prioritytable[i*2] = priority;
16193f1cac5SPaul Winder priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
16293f1cac5SPaul Winder I40E_IEEE_ETS_PRIO_0_SHIFT);
16393f1cac5SPaul Winder dcbcfg->etsrec.prioritytable[i*2 + 1] = priority;
16493f1cac5SPaul Winder offset++;
16593f1cac5SPaul Winder }
16693f1cac5SPaul Winder
16793f1cac5SPaul Winder /* TC Bandwidth Table (8 octets)
16893f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
16993f1cac5SPaul Winder * ---------------------------------
17093f1cac5SPaul Winder * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
17193f1cac5SPaul Winder * ---------------------------------
17293f1cac5SPaul Winder */
17393f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
17493f1cac5SPaul Winder dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
17593f1cac5SPaul Winder
17693f1cac5SPaul Winder /* TSA Assignment Table (8 octets)
17793f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
17893f1cac5SPaul Winder * ---------------------------------
17993f1cac5SPaul Winder * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
18093f1cac5SPaul Winder * ---------------------------------
18193f1cac5SPaul Winder */
18293f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
18393f1cac5SPaul Winder dcbcfg->etsrec.tsatable[i] = buf[offset++];
18493f1cac5SPaul Winder }
18593f1cac5SPaul Winder
18693f1cac5SPaul Winder /**
18793f1cac5SPaul Winder * i40e_parse_ieee_pfccfg_tlv
18893f1cac5SPaul Winder * @tlv: IEEE 802.1Qaz PFC CFG TLV
18993f1cac5SPaul Winder * @dcbcfg: Local store to update PFC CFG data
19093f1cac5SPaul Winder *
19193f1cac5SPaul Winder * Parses IEEE 802.1Qaz PFC CFG TLV
19293f1cac5SPaul Winder **/
i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)19393f1cac5SPaul Winder static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
19493f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
19593f1cac5SPaul Winder {
19693f1cac5SPaul Winder u8 *buf = tlv->tlvinfo;
19793f1cac5SPaul Winder
19893f1cac5SPaul Winder /* ----------------------------------------
19993f1cac5SPaul Winder * |will-|MBC | Re- | PFC | PFC Enable |
20093f1cac5SPaul Winder * |ing | |served| cap | |
20193f1cac5SPaul Winder * -----------------------------------------
20293f1cac5SPaul Winder * |1bit | 1bit|2 bits|4bits| 1 octet |
20393f1cac5SPaul Winder */
20493f1cac5SPaul Winder dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >>
20593f1cac5SPaul Winder I40E_IEEE_PFC_WILLING_SHIFT);
20693f1cac5SPaul Winder dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >>
20793f1cac5SPaul Winder I40E_IEEE_PFC_MBC_SHIFT);
20893f1cac5SPaul Winder dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >>
20993f1cac5SPaul Winder I40E_IEEE_PFC_CAP_SHIFT);
21093f1cac5SPaul Winder dcbcfg->pfc.pfcenable = buf[1];
21193f1cac5SPaul Winder }
21293f1cac5SPaul Winder
21393f1cac5SPaul Winder /**
21493f1cac5SPaul Winder * i40e_parse_ieee_app_tlv
21593f1cac5SPaul Winder * @tlv: IEEE 802.1Qaz APP TLV
21693f1cac5SPaul Winder * @dcbcfg: Local store to update APP PRIO data
21793f1cac5SPaul Winder *
21893f1cac5SPaul Winder * Parses IEEE 802.1Qaz APP PRIO TLV
21993f1cac5SPaul Winder **/
i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)22093f1cac5SPaul Winder static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
22193f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
22293f1cac5SPaul Winder {
22393f1cac5SPaul Winder u16 typelength;
22493f1cac5SPaul Winder u16 offset = 0;
22593f1cac5SPaul Winder u16 length;
22693f1cac5SPaul Winder int i = 0;
22793f1cac5SPaul Winder u8 *buf;
22893f1cac5SPaul Winder
22993f1cac5SPaul Winder typelength = I40E_NTOHS(tlv->typelength);
23093f1cac5SPaul Winder length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
23193f1cac5SPaul Winder I40E_LLDP_TLV_LEN_SHIFT);
23293f1cac5SPaul Winder buf = tlv->tlvinfo;
23393f1cac5SPaul Winder
23493f1cac5SPaul Winder /* The App priority table starts 5 octets after TLV header */
23593f1cac5SPaul Winder length -= (sizeof(tlv->ouisubtype) + 1);
23693f1cac5SPaul Winder
23793f1cac5SPaul Winder /* Move offset to App Priority Table */
23893f1cac5SPaul Winder offset++;
23993f1cac5SPaul Winder
24093f1cac5SPaul Winder /* Application Priority Table (3 octets)
24193f1cac5SPaul Winder * Octets:| 1 | 2 | 3 |
24293f1cac5SPaul Winder * -----------------------------------------
24393f1cac5SPaul Winder * |Priority|Rsrvd| Sel | Protocol ID |
24493f1cac5SPaul Winder * -----------------------------------------
24593f1cac5SPaul Winder * Bits:|23 21|20 19|18 16|15 0|
24693f1cac5SPaul Winder * -----------------------------------------
24793f1cac5SPaul Winder */
24893f1cac5SPaul Winder while (offset < length) {
24993f1cac5SPaul Winder dcbcfg->app[i].priority = (u8)((buf[offset] &
25093f1cac5SPaul Winder I40E_IEEE_APP_PRIO_MASK) >>
25193f1cac5SPaul Winder I40E_IEEE_APP_PRIO_SHIFT);
25293f1cac5SPaul Winder dcbcfg->app[i].selector = (u8)((buf[offset] &
25393f1cac5SPaul Winder I40E_IEEE_APP_SEL_MASK) >>
25493f1cac5SPaul Winder I40E_IEEE_APP_SEL_SHIFT);
25593f1cac5SPaul Winder dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
25693f1cac5SPaul Winder buf[offset + 2];
25793f1cac5SPaul Winder /* Move to next app */
25893f1cac5SPaul Winder offset += 3;
25993f1cac5SPaul Winder i++;
26093f1cac5SPaul Winder if (i >= I40E_DCBX_MAX_APPS)
26193f1cac5SPaul Winder break;
26293f1cac5SPaul Winder }
26393f1cac5SPaul Winder
26493f1cac5SPaul Winder dcbcfg->numapps = i;
26593f1cac5SPaul Winder }
26693f1cac5SPaul Winder
26793f1cac5SPaul Winder /**
26893f1cac5SPaul Winder * i40e_parse_ieee_etsrec_tlv
26993f1cac5SPaul Winder * @tlv: IEEE 802.1Qaz TLV
27093f1cac5SPaul Winder * @dcbcfg: Local store to update ETS REC data
27193f1cac5SPaul Winder *
27293f1cac5SPaul Winder * Get the TLV subtype and send it to parsing function
27393f1cac5SPaul Winder * based on the subtype value
27493f1cac5SPaul Winder **/
i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)27593f1cac5SPaul Winder static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
27693f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
27793f1cac5SPaul Winder {
27893f1cac5SPaul Winder u32 ouisubtype;
27993f1cac5SPaul Winder u8 subtype;
28093f1cac5SPaul Winder
28193f1cac5SPaul Winder ouisubtype = I40E_NTOHL(tlv->ouisubtype);
28293f1cac5SPaul Winder subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
28393f1cac5SPaul Winder I40E_LLDP_TLV_SUBTYPE_SHIFT);
28493f1cac5SPaul Winder switch (subtype) {
28593f1cac5SPaul Winder case I40E_IEEE_SUBTYPE_ETS_CFG:
28693f1cac5SPaul Winder i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
28793f1cac5SPaul Winder break;
28893f1cac5SPaul Winder case I40E_IEEE_SUBTYPE_ETS_REC:
28993f1cac5SPaul Winder i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
29093f1cac5SPaul Winder break;
29193f1cac5SPaul Winder case I40E_IEEE_SUBTYPE_PFC_CFG:
29293f1cac5SPaul Winder i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
29393f1cac5SPaul Winder break;
29493f1cac5SPaul Winder case I40E_IEEE_SUBTYPE_APP_PRI:
29593f1cac5SPaul Winder i40e_parse_ieee_app_tlv(tlv, dcbcfg);
29693f1cac5SPaul Winder break;
29793f1cac5SPaul Winder default:
29893f1cac5SPaul Winder break;
29993f1cac5SPaul Winder }
30093f1cac5SPaul Winder }
30193f1cac5SPaul Winder
30293f1cac5SPaul Winder /**
30393f1cac5SPaul Winder * i40e_parse_cee_pgcfg_tlv
30493f1cac5SPaul Winder * @tlv: CEE DCBX PG CFG TLV
30593f1cac5SPaul Winder * @dcbcfg: Local store to update ETS CFG data
30693f1cac5SPaul Winder *
30793f1cac5SPaul Winder * Parses CEE DCBX PG CFG TLV
30893f1cac5SPaul Winder **/
i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv * tlv,struct i40e_dcbx_config * dcbcfg)30993f1cac5SPaul Winder static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,
31093f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
31193f1cac5SPaul Winder {
31293f1cac5SPaul Winder struct i40e_dcb_ets_config *etscfg;
31393f1cac5SPaul Winder u8 *buf = tlv->tlvinfo;
31493f1cac5SPaul Winder u16 offset = 0;
31593f1cac5SPaul Winder u8 priority;
31693f1cac5SPaul Winder int i;
31793f1cac5SPaul Winder
31893f1cac5SPaul Winder etscfg = &dcbcfg->etscfg;
31993f1cac5SPaul Winder
32093f1cac5SPaul Winder if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
32193f1cac5SPaul Winder etscfg->willing = 1;
32293f1cac5SPaul Winder
32393f1cac5SPaul Winder etscfg->cbs = 0;
32493f1cac5SPaul Winder /* Priority Group Table (4 octets)
32593f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 |
32693f1cac5SPaul Winder * -----------------------------------------
32793f1cac5SPaul Winder * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
32893f1cac5SPaul Winder * -----------------------------------------
32993f1cac5SPaul Winder * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
33093f1cac5SPaul Winder * -----------------------------------------
33193f1cac5SPaul Winder */
33293f1cac5SPaul Winder for (i = 0; i < 4; i++) {
33393f1cac5SPaul Winder priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >>
33493f1cac5SPaul Winder I40E_CEE_PGID_PRIO_1_SHIFT);
33593f1cac5SPaul Winder etscfg->prioritytable[i * 2] = priority;
33693f1cac5SPaul Winder priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >>
33793f1cac5SPaul Winder I40E_CEE_PGID_PRIO_0_SHIFT);
33893f1cac5SPaul Winder etscfg->prioritytable[i * 2 + 1] = priority;
33993f1cac5SPaul Winder offset++;
34093f1cac5SPaul Winder }
34193f1cac5SPaul Winder
34293f1cac5SPaul Winder /* PG Percentage Table (8 octets)
34393f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
34493f1cac5SPaul Winder * ---------------------------------
34593f1cac5SPaul Winder * |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
34693f1cac5SPaul Winder * ---------------------------------
34793f1cac5SPaul Winder */
34893f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
34993f1cac5SPaul Winder etscfg->tcbwtable[i] = buf[offset++];
35093f1cac5SPaul Winder
35193f1cac5SPaul Winder /* Number of TCs supported (1 octet) */
35293f1cac5SPaul Winder etscfg->maxtcs = buf[offset];
35393f1cac5SPaul Winder }
35493f1cac5SPaul Winder
35593f1cac5SPaul Winder /**
35693f1cac5SPaul Winder * i40e_parse_cee_pfccfg_tlv
35793f1cac5SPaul Winder * @tlv: CEE DCBX PFC CFG TLV
35893f1cac5SPaul Winder * @dcbcfg: Local store to update PFC CFG data
35993f1cac5SPaul Winder *
36093f1cac5SPaul Winder * Parses CEE DCBX PFC CFG TLV
36193f1cac5SPaul Winder **/
i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv * tlv,struct i40e_dcbx_config * dcbcfg)36293f1cac5SPaul Winder static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,
36393f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
36493f1cac5SPaul Winder {
36593f1cac5SPaul Winder u8 *buf = tlv->tlvinfo;
36693f1cac5SPaul Winder
36793f1cac5SPaul Winder if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
36893f1cac5SPaul Winder dcbcfg->pfc.willing = 1;
36993f1cac5SPaul Winder
37093f1cac5SPaul Winder /* ------------------------
37193f1cac5SPaul Winder * | PFC Enable | PFC TCs |
37293f1cac5SPaul Winder * ------------------------
37393f1cac5SPaul Winder * | 1 octet | 1 octet |
37493f1cac5SPaul Winder */
37593f1cac5SPaul Winder dcbcfg->pfc.pfcenable = buf[0];
37693f1cac5SPaul Winder dcbcfg->pfc.pfccap = buf[1];
37793f1cac5SPaul Winder }
37893f1cac5SPaul Winder
37993f1cac5SPaul Winder /**
38093f1cac5SPaul Winder * i40e_parse_cee_app_tlv
38193f1cac5SPaul Winder * @tlv: CEE DCBX APP TLV
38293f1cac5SPaul Winder * @dcbcfg: Local store to update APP PRIO data
38393f1cac5SPaul Winder *
38493f1cac5SPaul Winder * Parses CEE DCBX APP PRIO TLV
38593f1cac5SPaul Winder **/
i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv * tlv,struct i40e_dcbx_config * dcbcfg)38693f1cac5SPaul Winder static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
38793f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
38893f1cac5SPaul Winder {
38993f1cac5SPaul Winder u16 length, typelength, offset = 0;
39093f1cac5SPaul Winder struct i40e_cee_app_prio *app;
39193f1cac5SPaul Winder u8 i;
39293f1cac5SPaul Winder
39393f1cac5SPaul Winder typelength = I40E_NTOHS(tlv->hdr.typelen);
39493f1cac5SPaul Winder length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
39593f1cac5SPaul Winder I40E_LLDP_TLV_LEN_SHIFT);
39693f1cac5SPaul Winder
39793f1cac5SPaul Winder dcbcfg->numapps = length / sizeof(*app);
39893f1cac5SPaul Winder if (!dcbcfg->numapps)
39993f1cac5SPaul Winder return;
40093f1cac5SPaul Winder if (dcbcfg->numapps > I40E_DCBX_MAX_APPS)
40193f1cac5SPaul Winder dcbcfg->numapps = I40E_DCBX_MAX_APPS;
40293f1cac5SPaul Winder
40393f1cac5SPaul Winder for (i = 0; i < dcbcfg->numapps; i++) {
40493f1cac5SPaul Winder u8 up, selector;
40593f1cac5SPaul Winder
40693f1cac5SPaul Winder app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);
40793f1cac5SPaul Winder for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {
40893f1cac5SPaul Winder if (app->prio_map & BIT(up))
40993f1cac5SPaul Winder break;
41093f1cac5SPaul Winder }
41193f1cac5SPaul Winder dcbcfg->app[i].priority = up;
41293f1cac5SPaul Winder
41393f1cac5SPaul Winder /* Get Selector from lower 2 bits, and convert to IEEE */
41493f1cac5SPaul Winder selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);
41593f1cac5SPaul Winder switch (selector) {
41693f1cac5SPaul Winder case I40E_CEE_APP_SEL_ETHTYPE:
41793f1cac5SPaul Winder dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
41893f1cac5SPaul Winder break;
41993f1cac5SPaul Winder case I40E_CEE_APP_SEL_TCPIP:
42093f1cac5SPaul Winder dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
42193f1cac5SPaul Winder break;
42293f1cac5SPaul Winder default:
42393f1cac5SPaul Winder /* Keep selector as it is for unknown types */
42493f1cac5SPaul Winder dcbcfg->app[i].selector = selector;
42593f1cac5SPaul Winder }
42693f1cac5SPaul Winder
42793f1cac5SPaul Winder dcbcfg->app[i].protocolid = I40E_NTOHS(app->protocol);
42893f1cac5SPaul Winder /* Move to next app */
42993f1cac5SPaul Winder offset += sizeof(*app);
43093f1cac5SPaul Winder }
43193f1cac5SPaul Winder }
43293f1cac5SPaul Winder
43393f1cac5SPaul Winder /**
43493f1cac5SPaul Winder * i40e_parse_cee_tlv
43593f1cac5SPaul Winder * @tlv: CEE DCBX TLV
43693f1cac5SPaul Winder * @dcbcfg: Local store to update DCBX config data
43793f1cac5SPaul Winder *
43893f1cac5SPaul Winder * Get the TLV subtype and send it to parsing function
43993f1cac5SPaul Winder * based on the subtype value
44093f1cac5SPaul Winder **/
i40e_parse_cee_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)44193f1cac5SPaul Winder static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,
44293f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
44393f1cac5SPaul Winder {
44493f1cac5SPaul Winder u16 len, tlvlen, sublen, typelength;
44593f1cac5SPaul Winder struct i40e_cee_feat_tlv *sub_tlv;
44693f1cac5SPaul Winder u8 subtype, feat_tlv_count = 0;
44793f1cac5SPaul Winder u32 ouisubtype;
44893f1cac5SPaul Winder
44993f1cac5SPaul Winder ouisubtype = I40E_NTOHL(tlv->ouisubtype);
45093f1cac5SPaul Winder subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
45193f1cac5SPaul Winder I40E_LLDP_TLV_SUBTYPE_SHIFT);
45293f1cac5SPaul Winder /* Return if not CEE DCBX */
45393f1cac5SPaul Winder if (subtype != I40E_CEE_DCBX_TYPE)
45493f1cac5SPaul Winder return;
45593f1cac5SPaul Winder
45693f1cac5SPaul Winder typelength = I40E_NTOHS(tlv->typelength);
45793f1cac5SPaul Winder tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
45893f1cac5SPaul Winder I40E_LLDP_TLV_LEN_SHIFT);
45993f1cac5SPaul Winder len = sizeof(tlv->typelength) + sizeof(ouisubtype) +
46093f1cac5SPaul Winder sizeof(struct i40e_cee_ctrl_tlv);
46193f1cac5SPaul Winder /* Return if no CEE DCBX Feature TLVs */
46293f1cac5SPaul Winder if (tlvlen <= len)
46393f1cac5SPaul Winder return;
46493f1cac5SPaul Winder
46593f1cac5SPaul Winder sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);
46693f1cac5SPaul Winder while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {
46793f1cac5SPaul Winder typelength = I40E_NTOHS(sub_tlv->hdr.typelen);
46893f1cac5SPaul Winder sublen = (u16)((typelength &
46993f1cac5SPaul Winder I40E_LLDP_TLV_LEN_MASK) >>
47093f1cac5SPaul Winder I40E_LLDP_TLV_LEN_SHIFT);
47193f1cac5SPaul Winder subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
47293f1cac5SPaul Winder I40E_LLDP_TLV_TYPE_SHIFT);
47393f1cac5SPaul Winder switch (subtype) {
47493f1cac5SPaul Winder case I40E_CEE_SUBTYPE_PG_CFG:
47593f1cac5SPaul Winder i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
47693f1cac5SPaul Winder break;
47793f1cac5SPaul Winder case I40E_CEE_SUBTYPE_PFC_CFG:
47893f1cac5SPaul Winder i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
47993f1cac5SPaul Winder break;
48093f1cac5SPaul Winder case I40E_CEE_SUBTYPE_APP_PRI:
48193f1cac5SPaul Winder i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);
48293f1cac5SPaul Winder break;
48393f1cac5SPaul Winder default:
48493f1cac5SPaul Winder return; /* Invalid Sub-type return */
48593f1cac5SPaul Winder }
48693f1cac5SPaul Winder feat_tlv_count++;
48793f1cac5SPaul Winder /* Move to next sub TLV */
48893f1cac5SPaul Winder sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +
48993f1cac5SPaul Winder sizeof(sub_tlv->hdr.typelen) +
49093f1cac5SPaul Winder sublen);
49193f1cac5SPaul Winder }
49293f1cac5SPaul Winder }
49393f1cac5SPaul Winder
49493f1cac5SPaul Winder /**
49593f1cac5SPaul Winder * i40e_parse_org_tlv
49693f1cac5SPaul Winder * @tlv: Organization specific TLV
49793f1cac5SPaul Winder * @dcbcfg: Local store to update ETS REC data
49893f1cac5SPaul Winder *
49993f1cac5SPaul Winder * Currently only IEEE 802.1Qaz TLV is supported, all others
50093f1cac5SPaul Winder * will be returned
50193f1cac5SPaul Winder **/
i40e_parse_org_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)50293f1cac5SPaul Winder static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
50393f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
50493f1cac5SPaul Winder {
50593f1cac5SPaul Winder u32 ouisubtype;
50693f1cac5SPaul Winder u32 oui;
50793f1cac5SPaul Winder
50893f1cac5SPaul Winder ouisubtype = I40E_NTOHL(tlv->ouisubtype);
50993f1cac5SPaul Winder oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >>
51093f1cac5SPaul Winder I40E_LLDP_TLV_OUI_SHIFT);
51193f1cac5SPaul Winder switch (oui) {
51293f1cac5SPaul Winder case I40E_IEEE_8021QAZ_OUI:
51393f1cac5SPaul Winder i40e_parse_ieee_tlv(tlv, dcbcfg);
51493f1cac5SPaul Winder break;
51593f1cac5SPaul Winder case I40E_CEE_DCBX_OUI:
51693f1cac5SPaul Winder i40e_parse_cee_tlv(tlv, dcbcfg);
51793f1cac5SPaul Winder break;
51893f1cac5SPaul Winder default:
51993f1cac5SPaul Winder break;
52093f1cac5SPaul Winder }
52193f1cac5SPaul Winder }
52293f1cac5SPaul Winder
52393f1cac5SPaul Winder /**
52493f1cac5SPaul Winder * i40e_lldp_to_dcb_config
52593f1cac5SPaul Winder * @lldpmib: LLDPDU to be parsed
52693f1cac5SPaul Winder * @dcbcfg: store for LLDPDU data
52793f1cac5SPaul Winder *
52893f1cac5SPaul Winder * Parse DCB configuration from the LLDPDU
52993f1cac5SPaul Winder **/
i40e_lldp_to_dcb_config(u8 * lldpmib,struct i40e_dcbx_config * dcbcfg)53093f1cac5SPaul Winder enum i40e_status_code i40e_lldp_to_dcb_config(u8 *lldpmib,
53193f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
53293f1cac5SPaul Winder {
53393f1cac5SPaul Winder enum i40e_status_code ret = I40E_SUCCESS;
53493f1cac5SPaul Winder struct i40e_lldp_org_tlv *tlv;
53593f1cac5SPaul Winder u16 type;
53693f1cac5SPaul Winder u16 length;
53793f1cac5SPaul Winder u16 typelength;
53893f1cac5SPaul Winder u16 offset = 0;
53993f1cac5SPaul Winder
54093f1cac5SPaul Winder if (!lldpmib || !dcbcfg)
54193f1cac5SPaul Winder return I40E_ERR_PARAM;
54293f1cac5SPaul Winder
54393f1cac5SPaul Winder /* set to the start of LLDPDU */
54493f1cac5SPaul Winder lldpmib += I40E_LLDP_MIB_HLEN;
54593f1cac5SPaul Winder tlv = (struct i40e_lldp_org_tlv *)lldpmib;
54693f1cac5SPaul Winder while (1) {
54793f1cac5SPaul Winder typelength = I40E_NTOHS(tlv->typelength);
54893f1cac5SPaul Winder type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
54993f1cac5SPaul Winder I40E_LLDP_TLV_TYPE_SHIFT);
55093f1cac5SPaul Winder length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
55193f1cac5SPaul Winder I40E_LLDP_TLV_LEN_SHIFT);
55293f1cac5SPaul Winder offset += sizeof(typelength) + length;
55393f1cac5SPaul Winder
55493f1cac5SPaul Winder /* END TLV or beyond LLDPDU size */
55593f1cac5SPaul Winder if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
55693f1cac5SPaul Winder break;
55793f1cac5SPaul Winder
55893f1cac5SPaul Winder switch (type) {
55993f1cac5SPaul Winder case I40E_TLV_TYPE_ORG:
56093f1cac5SPaul Winder i40e_parse_org_tlv(tlv, dcbcfg);
56193f1cac5SPaul Winder break;
56293f1cac5SPaul Winder default:
56393f1cac5SPaul Winder break;
56493f1cac5SPaul Winder }
56593f1cac5SPaul Winder
56693f1cac5SPaul Winder /* Move to next TLV */
56793f1cac5SPaul Winder tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
56893f1cac5SPaul Winder sizeof(tlv->typelength) +
56993f1cac5SPaul Winder length);
57093f1cac5SPaul Winder }
57193f1cac5SPaul Winder
57293f1cac5SPaul Winder return ret;
57393f1cac5SPaul Winder }
57493f1cac5SPaul Winder
57593f1cac5SPaul Winder /**
57693f1cac5SPaul Winder * i40e_aq_get_dcb_config
57793f1cac5SPaul Winder * @hw: pointer to the hw struct
57893f1cac5SPaul Winder * @mib_type: mib type for the query
57993f1cac5SPaul Winder * @bridgetype: bridge type for the query (remote)
58093f1cac5SPaul Winder * @dcbcfg: store for LLDPDU data
58193f1cac5SPaul Winder *
58293f1cac5SPaul Winder * Query DCB configuration from the Firmware
58393f1cac5SPaul Winder **/
i40e_aq_get_dcb_config(struct i40e_hw * hw,u8 mib_type,u8 bridgetype,struct i40e_dcbx_config * dcbcfg)58493f1cac5SPaul Winder enum i40e_status_code i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
58593f1cac5SPaul Winder u8 bridgetype,
58693f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
58793f1cac5SPaul Winder {
58893f1cac5SPaul Winder enum i40e_status_code ret = I40E_SUCCESS;
58993f1cac5SPaul Winder struct i40e_virt_mem mem;
59093f1cac5SPaul Winder u8 *lldpmib;
59193f1cac5SPaul Winder
59293f1cac5SPaul Winder /* Allocate the LLDPDU */
59393f1cac5SPaul Winder ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
59493f1cac5SPaul Winder if (ret)
59593f1cac5SPaul Winder return ret;
59693f1cac5SPaul Winder
59793f1cac5SPaul Winder lldpmib = (u8 *)mem.va;
59893f1cac5SPaul Winder ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
59993f1cac5SPaul Winder (void *)lldpmib, I40E_LLDPDU_SIZE,
60093f1cac5SPaul Winder NULL, NULL, NULL);
60193f1cac5SPaul Winder if (ret)
60293f1cac5SPaul Winder goto free_mem;
60393f1cac5SPaul Winder
60493f1cac5SPaul Winder /* Parse LLDP MIB to get dcb configuration */
60593f1cac5SPaul Winder ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
60693f1cac5SPaul Winder
60793f1cac5SPaul Winder free_mem:
60893f1cac5SPaul Winder i40e_free_virt_mem(hw, &mem);
60993f1cac5SPaul Winder return ret;
61093f1cac5SPaul Winder }
61193f1cac5SPaul Winder
61293f1cac5SPaul Winder /**
61393f1cac5SPaul Winder * i40e_cee_to_dcb_v1_config
61493f1cac5SPaul Winder * @cee_cfg: pointer to CEE v1 response configuration struct
61593f1cac5SPaul Winder * @dcbcfg: DCB configuration struct
61693f1cac5SPaul Winder *
61793f1cac5SPaul Winder * Convert CEE v1 configuration from firmware to DCB configuration
61893f1cac5SPaul Winder **/
i40e_cee_to_dcb_v1_config(struct i40e_aqc_get_cee_dcb_cfg_v1_resp * cee_cfg,struct i40e_dcbx_config * dcbcfg)61993f1cac5SPaul Winder static void i40e_cee_to_dcb_v1_config(
62093f1cac5SPaul Winder struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg,
62193f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
62293f1cac5SPaul Winder {
62393f1cac5SPaul Winder u16 status, tlv_status = LE16_TO_CPU(cee_cfg->tlv_status);
62493f1cac5SPaul Winder u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio);
62593f1cac5SPaul Winder u8 i, tc, err;
62693f1cac5SPaul Winder
62793f1cac5SPaul Winder /* CEE PG data to ETS config */
62893f1cac5SPaul Winder dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
62993f1cac5SPaul Winder
63093f1cac5SPaul Winder /* Note that the FW creates the oper_prio_tc nibbles reversed
63193f1cac5SPaul Winder * from those in the CEE Priority Group sub-TLV.
63293f1cac5SPaul Winder */
63393f1cac5SPaul Winder for (i = 0; i < 4; i++) {
63493f1cac5SPaul Winder tc = (u8)((cee_cfg->oper_prio_tc[i] &
63593f1cac5SPaul Winder I40E_CEE_PGID_PRIO_0_MASK) >>
63693f1cac5SPaul Winder I40E_CEE_PGID_PRIO_0_SHIFT);
63793f1cac5SPaul Winder dcbcfg->etscfg.prioritytable[i*2] = tc;
63893f1cac5SPaul Winder tc = (u8)((cee_cfg->oper_prio_tc[i] &
63993f1cac5SPaul Winder I40E_CEE_PGID_PRIO_1_MASK) >>
64093f1cac5SPaul Winder I40E_CEE_PGID_PRIO_1_SHIFT);
64193f1cac5SPaul Winder dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
64293f1cac5SPaul Winder }
64393f1cac5SPaul Winder
64493f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
64593f1cac5SPaul Winder dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
64693f1cac5SPaul Winder
64793f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
64893f1cac5SPaul Winder if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
64993f1cac5SPaul Winder /* Map it to next empty TC */
65093f1cac5SPaul Winder dcbcfg->etscfg.prioritytable[i] =
65193f1cac5SPaul Winder cee_cfg->oper_num_tc - 1;
65293f1cac5SPaul Winder dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
65393f1cac5SPaul Winder } else {
65493f1cac5SPaul Winder dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
65593f1cac5SPaul Winder }
65693f1cac5SPaul Winder }
65793f1cac5SPaul Winder
65893f1cac5SPaul Winder /* CEE PFC data to ETS config */
65993f1cac5SPaul Winder dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
66093f1cac5SPaul Winder dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
66193f1cac5SPaul Winder
66293f1cac5SPaul Winder status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >>
66393f1cac5SPaul Winder I40E_AQC_CEE_APP_STATUS_SHIFT;
66493f1cac5SPaul Winder err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
66593f1cac5SPaul Winder /* Add APPs if Error is False */
66693f1cac5SPaul Winder if (!err) {
66793f1cac5SPaul Winder /* CEE operating configuration supports FCoE/iSCSI/FIP only */
66893f1cac5SPaul Winder dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;
66993f1cac5SPaul Winder
67093f1cac5SPaul Winder /* FCoE APP */
67193f1cac5SPaul Winder dcbcfg->app[0].priority =
67293f1cac5SPaul Winder (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
67393f1cac5SPaul Winder I40E_AQC_CEE_APP_FCOE_SHIFT;
67493f1cac5SPaul Winder dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
67593f1cac5SPaul Winder dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
67693f1cac5SPaul Winder
67793f1cac5SPaul Winder /* iSCSI APP */
67893f1cac5SPaul Winder dcbcfg->app[1].priority =
67993f1cac5SPaul Winder (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
68093f1cac5SPaul Winder I40E_AQC_CEE_APP_ISCSI_SHIFT;
68193f1cac5SPaul Winder dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;
68293f1cac5SPaul Winder dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;
68393f1cac5SPaul Winder
68493f1cac5SPaul Winder /* FIP APP */
68593f1cac5SPaul Winder dcbcfg->app[2].priority =
68693f1cac5SPaul Winder (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
68793f1cac5SPaul Winder I40E_AQC_CEE_APP_FIP_SHIFT;
68893f1cac5SPaul Winder dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;
68993f1cac5SPaul Winder dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;
69093f1cac5SPaul Winder }
69193f1cac5SPaul Winder }
69293f1cac5SPaul Winder
69393f1cac5SPaul Winder /**
69493f1cac5SPaul Winder * i40e_cee_to_dcb_config
69593f1cac5SPaul Winder * @cee_cfg: pointer to CEE configuration struct
69693f1cac5SPaul Winder * @dcbcfg: DCB configuration struct
69793f1cac5SPaul Winder *
69893f1cac5SPaul Winder * Convert CEE configuration from firmware to DCB configuration
69993f1cac5SPaul Winder **/
i40e_cee_to_dcb_config(struct i40e_aqc_get_cee_dcb_cfg_resp * cee_cfg,struct i40e_dcbx_config * dcbcfg)70093f1cac5SPaul Winder static void i40e_cee_to_dcb_config(
70193f1cac5SPaul Winder struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg,
70293f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
70393f1cac5SPaul Winder {
70493f1cac5SPaul Winder u32 status, tlv_status = LE32_TO_CPU(cee_cfg->tlv_status);
70593f1cac5SPaul Winder u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio);
70693f1cac5SPaul Winder u8 i, tc, err, sync, oper;
70793f1cac5SPaul Winder
70893f1cac5SPaul Winder /* CEE PG data to ETS config */
70993f1cac5SPaul Winder dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
71093f1cac5SPaul Winder
71193f1cac5SPaul Winder /* Note that the FW creates the oper_prio_tc nibbles reversed
71293f1cac5SPaul Winder * from those in the CEE Priority Group sub-TLV.
71393f1cac5SPaul Winder */
71493f1cac5SPaul Winder for (i = 0; i < 4; i++) {
71593f1cac5SPaul Winder tc = (u8)((cee_cfg->oper_prio_tc[i] &
71693f1cac5SPaul Winder I40E_CEE_PGID_PRIO_0_MASK) >>
71793f1cac5SPaul Winder I40E_CEE_PGID_PRIO_0_SHIFT);
71893f1cac5SPaul Winder dcbcfg->etscfg.prioritytable[i*2] = tc;
71993f1cac5SPaul Winder tc = (u8)((cee_cfg->oper_prio_tc[i] &
72093f1cac5SPaul Winder I40E_CEE_PGID_PRIO_1_MASK) >>
72193f1cac5SPaul Winder I40E_CEE_PGID_PRIO_1_SHIFT);
72293f1cac5SPaul Winder dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
72393f1cac5SPaul Winder }
72493f1cac5SPaul Winder
72593f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
72693f1cac5SPaul Winder dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
72793f1cac5SPaul Winder
72893f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
72993f1cac5SPaul Winder if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
73093f1cac5SPaul Winder /* Map it to next empty TC */
73193f1cac5SPaul Winder dcbcfg->etscfg.prioritytable[i] =
73293f1cac5SPaul Winder cee_cfg->oper_num_tc - 1;
73393f1cac5SPaul Winder dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
73493f1cac5SPaul Winder } else {
73593f1cac5SPaul Winder dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
73693f1cac5SPaul Winder }
73793f1cac5SPaul Winder }
73893f1cac5SPaul Winder
73993f1cac5SPaul Winder /* CEE PFC data to ETS config */
74093f1cac5SPaul Winder dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
74193f1cac5SPaul Winder dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
74293f1cac5SPaul Winder
74393f1cac5SPaul Winder i = 0;
74493f1cac5SPaul Winder status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >>
74593f1cac5SPaul Winder I40E_AQC_CEE_FCOE_STATUS_SHIFT;
74693f1cac5SPaul Winder err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
74793f1cac5SPaul Winder sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
74893f1cac5SPaul Winder oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
74993f1cac5SPaul Winder /* Add FCoE APP if Error is False and Oper/Sync is True */
75093f1cac5SPaul Winder if (!err && sync && oper) {
75193f1cac5SPaul Winder /* FCoE APP */
75293f1cac5SPaul Winder dcbcfg->app[i].priority =
75393f1cac5SPaul Winder (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
75493f1cac5SPaul Winder I40E_AQC_CEE_APP_FCOE_SHIFT;
75593f1cac5SPaul Winder dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
75693f1cac5SPaul Winder dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;
75793f1cac5SPaul Winder i++;
75893f1cac5SPaul Winder }
75993f1cac5SPaul Winder
76093f1cac5SPaul Winder status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >>
76193f1cac5SPaul Winder I40E_AQC_CEE_ISCSI_STATUS_SHIFT;
76293f1cac5SPaul Winder err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
76393f1cac5SPaul Winder sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
76493f1cac5SPaul Winder oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
76593f1cac5SPaul Winder /* Add iSCSI APP if Error is False and Oper/Sync is True */
76693f1cac5SPaul Winder if (!err && sync && oper) {
76793f1cac5SPaul Winder /* iSCSI APP */
76893f1cac5SPaul Winder dcbcfg->app[i].priority =
76993f1cac5SPaul Winder (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
77093f1cac5SPaul Winder I40E_AQC_CEE_APP_ISCSI_SHIFT;
77193f1cac5SPaul Winder dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
77293f1cac5SPaul Winder dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;
77393f1cac5SPaul Winder i++;
77493f1cac5SPaul Winder }
77593f1cac5SPaul Winder
77693f1cac5SPaul Winder status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >>
77793f1cac5SPaul Winder I40E_AQC_CEE_FIP_STATUS_SHIFT;
77893f1cac5SPaul Winder err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
77993f1cac5SPaul Winder sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
78093f1cac5SPaul Winder oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
78193f1cac5SPaul Winder /* Add FIP APP if Error is False and Oper/Sync is True */
78293f1cac5SPaul Winder if (!err && sync && oper) {
78393f1cac5SPaul Winder /* FIP APP */
78493f1cac5SPaul Winder dcbcfg->app[i].priority =
78593f1cac5SPaul Winder (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
78693f1cac5SPaul Winder I40E_AQC_CEE_APP_FIP_SHIFT;
78793f1cac5SPaul Winder dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
78893f1cac5SPaul Winder dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;
78993f1cac5SPaul Winder i++;
79093f1cac5SPaul Winder }
79193f1cac5SPaul Winder dcbcfg->numapps = i;
79293f1cac5SPaul Winder }
79393f1cac5SPaul Winder
79493f1cac5SPaul Winder /**
79593f1cac5SPaul Winder * i40e_get_ieee_dcb_config
79693f1cac5SPaul Winder * @hw: pointer to the hw struct
79793f1cac5SPaul Winder *
79893f1cac5SPaul Winder * Get IEEE mode DCB configuration from the Firmware
79993f1cac5SPaul Winder **/
i40e_get_ieee_dcb_config(struct i40e_hw * hw)80093f1cac5SPaul Winder static enum i40e_status_code i40e_get_ieee_dcb_config(struct i40e_hw *hw)
80193f1cac5SPaul Winder {
80293f1cac5SPaul Winder enum i40e_status_code ret = I40E_SUCCESS;
80393f1cac5SPaul Winder
80493f1cac5SPaul Winder /* IEEE mode */
80593f1cac5SPaul Winder hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
80693f1cac5SPaul Winder /* Get Local DCB Config */
80793f1cac5SPaul Winder ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
80893f1cac5SPaul Winder &hw->local_dcbx_config);
80993f1cac5SPaul Winder if (ret)
81093f1cac5SPaul Winder goto out;
81193f1cac5SPaul Winder
81293f1cac5SPaul Winder /* Get Remote DCB Config */
81393f1cac5SPaul Winder ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
81493f1cac5SPaul Winder I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
81593f1cac5SPaul Winder &hw->remote_dcbx_config);
81693f1cac5SPaul Winder /* Don't treat ENOENT as an error for Remote MIBs */
81793f1cac5SPaul Winder if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
81893f1cac5SPaul Winder ret = I40E_SUCCESS;
81993f1cac5SPaul Winder
82093f1cac5SPaul Winder out:
82193f1cac5SPaul Winder return ret;
82293f1cac5SPaul Winder }
82393f1cac5SPaul Winder
82493f1cac5SPaul Winder /**
82593f1cac5SPaul Winder * i40e_get_dcb_config
82693f1cac5SPaul Winder * @hw: pointer to the hw struct
82793f1cac5SPaul Winder *
82893f1cac5SPaul Winder * Get DCB configuration from the Firmware
82993f1cac5SPaul Winder **/
i40e_get_dcb_config(struct i40e_hw * hw)83093f1cac5SPaul Winder enum i40e_status_code i40e_get_dcb_config(struct i40e_hw *hw)
83193f1cac5SPaul Winder {
83293f1cac5SPaul Winder enum i40e_status_code ret = I40E_SUCCESS;
83393f1cac5SPaul Winder struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg;
83493f1cac5SPaul Winder struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg;
83593f1cac5SPaul Winder
83693f1cac5SPaul Winder /* If Firmware version < v4.33 on X710/XL710, IEEE only */
83793f1cac5SPaul Winder if ((hw->mac.type == I40E_MAC_XL710) &&
83893f1cac5SPaul Winder (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
83993f1cac5SPaul Winder (hw->aq.fw_maj_ver < 4)))
84093f1cac5SPaul Winder return i40e_get_ieee_dcb_config(hw);
84193f1cac5SPaul Winder
84293f1cac5SPaul Winder /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */
84393f1cac5SPaul Winder if ((hw->mac.type == I40E_MAC_XL710) &&
84493f1cac5SPaul Winder ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) {
84593f1cac5SPaul Winder ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg,
84693f1cac5SPaul Winder sizeof(cee_v1_cfg), NULL);
84793f1cac5SPaul Winder if (ret == I40E_SUCCESS) {
84893f1cac5SPaul Winder /* CEE mode */
84993f1cac5SPaul Winder hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
85093f1cac5SPaul Winder hw->local_dcbx_config.tlv_status =
85193f1cac5SPaul Winder LE16_TO_CPU(cee_v1_cfg.tlv_status);
85293f1cac5SPaul Winder i40e_cee_to_dcb_v1_config(&cee_v1_cfg,
85393f1cac5SPaul Winder &hw->local_dcbx_config);
85493f1cac5SPaul Winder }
85593f1cac5SPaul Winder } else {
85693f1cac5SPaul Winder ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg,
85793f1cac5SPaul Winder sizeof(cee_cfg), NULL);
85893f1cac5SPaul Winder if (ret == I40E_SUCCESS) {
85993f1cac5SPaul Winder /* CEE mode */
86093f1cac5SPaul Winder hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
86193f1cac5SPaul Winder hw->local_dcbx_config.tlv_status =
86293f1cac5SPaul Winder LE32_TO_CPU(cee_cfg.tlv_status);
86393f1cac5SPaul Winder i40e_cee_to_dcb_config(&cee_cfg,
86493f1cac5SPaul Winder &hw->local_dcbx_config);
86593f1cac5SPaul Winder }
86693f1cac5SPaul Winder }
86793f1cac5SPaul Winder
86893f1cac5SPaul Winder /* CEE mode not enabled try querying IEEE data */
86993f1cac5SPaul Winder if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
87093f1cac5SPaul Winder return i40e_get_ieee_dcb_config(hw);
87193f1cac5SPaul Winder
87293f1cac5SPaul Winder if (ret != I40E_SUCCESS)
87393f1cac5SPaul Winder goto out;
87493f1cac5SPaul Winder
87593f1cac5SPaul Winder /* Get CEE DCB Desired Config */
87693f1cac5SPaul Winder ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
87793f1cac5SPaul Winder &hw->desired_dcbx_config);
87893f1cac5SPaul Winder if (ret)
87993f1cac5SPaul Winder goto out;
88093f1cac5SPaul Winder
88193f1cac5SPaul Winder /* Get Remote DCB Config */
88293f1cac5SPaul Winder ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
88393f1cac5SPaul Winder I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
88493f1cac5SPaul Winder &hw->remote_dcbx_config);
88593f1cac5SPaul Winder /* Don't treat ENOENT as an error for Remote MIBs */
88693f1cac5SPaul Winder if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
88793f1cac5SPaul Winder ret = I40E_SUCCESS;
88893f1cac5SPaul Winder
88993f1cac5SPaul Winder out:
89093f1cac5SPaul Winder return ret;
89193f1cac5SPaul Winder }
89293f1cac5SPaul Winder
89393f1cac5SPaul Winder /**
89493f1cac5SPaul Winder * i40e_init_dcb
89593f1cac5SPaul Winder * @hw: pointer to the hw struct
896*df36e06dSRobert Mustacchi * @enable_mib_change: enable mib change event
89793f1cac5SPaul Winder *
89893f1cac5SPaul Winder * Update DCB configuration from the Firmware
89993f1cac5SPaul Winder **/
i40e_init_dcb(struct i40e_hw * hw,bool enable_mib_change)900*df36e06dSRobert Mustacchi enum i40e_status_code i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change)
90193f1cac5SPaul Winder {
90293f1cac5SPaul Winder enum i40e_status_code ret = I40E_SUCCESS;
90393f1cac5SPaul Winder struct i40e_lldp_variables lldp_cfg;
90493f1cac5SPaul Winder u8 adminstatus = 0;
90593f1cac5SPaul Winder
90693f1cac5SPaul Winder if (!hw->func_caps.dcb)
907*df36e06dSRobert Mustacchi return I40E_NOT_SUPPORTED;
90893f1cac5SPaul Winder
90993f1cac5SPaul Winder /* Read LLDP NVM area */
910*df36e06dSRobert Mustacchi if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT) {
911*df36e06dSRobert Mustacchi u8 offset = 0;
912*df36e06dSRobert Mustacchi
913*df36e06dSRobert Mustacchi if (hw->mac.type == I40E_MAC_XL710)
914*df36e06dSRobert Mustacchi offset = I40E_LLDP_CURRENT_STATUS_XL710_OFFSET;
915*df36e06dSRobert Mustacchi else if (hw->mac.type == I40E_MAC_X722)
916*df36e06dSRobert Mustacchi offset = I40E_LLDP_CURRENT_STATUS_X722_OFFSET;
917*df36e06dSRobert Mustacchi else
918*df36e06dSRobert Mustacchi return I40E_NOT_SUPPORTED;
919*df36e06dSRobert Mustacchi
920*df36e06dSRobert Mustacchi ret = i40e_read_nvm_module_data(hw,
921*df36e06dSRobert Mustacchi I40E_SR_EMP_SR_SETTINGS_PTR,
922*df36e06dSRobert Mustacchi offset,
923*df36e06dSRobert Mustacchi I40E_LLDP_CURRENT_STATUS_OFFSET,
924*df36e06dSRobert Mustacchi I40E_LLDP_CURRENT_STATUS_SIZE,
925*df36e06dSRobert Mustacchi &lldp_cfg.adminstatus);
926*df36e06dSRobert Mustacchi } else {
927*df36e06dSRobert Mustacchi ret = i40e_read_lldp_cfg(hw, &lldp_cfg);
928*df36e06dSRobert Mustacchi }
92993f1cac5SPaul Winder if (ret)
930*df36e06dSRobert Mustacchi return I40E_ERR_NOT_READY;
93193f1cac5SPaul Winder
93293f1cac5SPaul Winder /* Get the LLDP AdminStatus for the current port */
93393f1cac5SPaul Winder adminstatus = lldp_cfg.adminstatus >> (hw->port * 4);
93493f1cac5SPaul Winder adminstatus &= 0xF;
93593f1cac5SPaul Winder
93693f1cac5SPaul Winder /* LLDP agent disabled */
93793f1cac5SPaul Winder if (!adminstatus) {
93893f1cac5SPaul Winder hw->dcbx_status = I40E_DCBX_STATUS_DISABLED;
939*df36e06dSRobert Mustacchi return I40E_ERR_NOT_READY;
94093f1cac5SPaul Winder }
94193f1cac5SPaul Winder
94293f1cac5SPaul Winder /* Get DCBX status */
94393f1cac5SPaul Winder ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
94493f1cac5SPaul Winder if (ret)
94593f1cac5SPaul Winder return ret;
94693f1cac5SPaul Winder
94793f1cac5SPaul Winder /* Check the DCBX Status */
948*df36e06dSRobert Mustacchi if (hw->dcbx_status == I40E_DCBX_STATUS_DONE ||
949*df36e06dSRobert Mustacchi hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) {
95093f1cac5SPaul Winder /* Get current DCBX configuration */
95193f1cac5SPaul Winder ret = i40e_get_dcb_config(hw);
95293f1cac5SPaul Winder if (ret)
95393f1cac5SPaul Winder return ret;
954*df36e06dSRobert Mustacchi } else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) {
955*df36e06dSRobert Mustacchi return I40E_ERR_NOT_READY;
95693f1cac5SPaul Winder }
95793f1cac5SPaul Winder
95893f1cac5SPaul Winder /* Configure the LLDP MIB change event */
959*df36e06dSRobert Mustacchi if (enable_mib_change)
960*df36e06dSRobert Mustacchi ret = i40e_aq_cfg_lldp_mib_change_event(hw, TRUE, NULL);
961*df36e06dSRobert Mustacchi
962*df36e06dSRobert Mustacchi return ret;
963*df36e06dSRobert Mustacchi }
964*df36e06dSRobert Mustacchi
965*df36e06dSRobert Mustacchi /**
966*df36e06dSRobert Mustacchi * i40e_get_fw_lldp_status
967*df36e06dSRobert Mustacchi * @hw: pointer to the hw struct
968*df36e06dSRobert Mustacchi * @lldp_status: pointer to the status enum
969*df36e06dSRobert Mustacchi *
970*df36e06dSRobert Mustacchi * Get status of FW Link Layer Discovery Protocol (LLDP) Agent.
971*df36e06dSRobert Mustacchi * Status of agent is reported via @lldp_status parameter.
972*df36e06dSRobert Mustacchi **/
973*df36e06dSRobert Mustacchi enum i40e_status_code
i40e_get_fw_lldp_status(struct i40e_hw * hw,enum i40e_get_fw_lldp_status_resp * lldp_status)974*df36e06dSRobert Mustacchi i40e_get_fw_lldp_status(struct i40e_hw *hw,
975*df36e06dSRobert Mustacchi enum i40e_get_fw_lldp_status_resp *lldp_status)
976*df36e06dSRobert Mustacchi {
977*df36e06dSRobert Mustacchi enum i40e_status_code ret;
978*df36e06dSRobert Mustacchi struct i40e_virt_mem mem;
979*df36e06dSRobert Mustacchi u8 *lldpmib;
980*df36e06dSRobert Mustacchi
981*df36e06dSRobert Mustacchi if (!lldp_status)
982*df36e06dSRobert Mustacchi return I40E_ERR_PARAM;
983*df36e06dSRobert Mustacchi
984*df36e06dSRobert Mustacchi /* Allocate buffer for the LLDPDU */
985*df36e06dSRobert Mustacchi ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
98693f1cac5SPaul Winder if (ret)
98793f1cac5SPaul Winder return ret;
98893f1cac5SPaul Winder
989*df36e06dSRobert Mustacchi lldpmib = (u8 *)mem.va;
990*df36e06dSRobert Mustacchi ret = i40e_aq_get_lldp_mib(hw, 0, 0, (void *)lldpmib,
991*df36e06dSRobert Mustacchi I40E_LLDPDU_SIZE, NULL, NULL, NULL);
992*df36e06dSRobert Mustacchi
993*df36e06dSRobert Mustacchi if (ret == I40E_SUCCESS) {
994*df36e06dSRobert Mustacchi *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
995*df36e06dSRobert Mustacchi } else if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) {
996*df36e06dSRobert Mustacchi /* MIB is not available yet but the agent is running */
997*df36e06dSRobert Mustacchi *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
998*df36e06dSRobert Mustacchi ret = I40E_SUCCESS;
999*df36e06dSRobert Mustacchi } else if (hw->aq.asq_last_status == I40E_AQ_RC_EPERM) {
1000*df36e06dSRobert Mustacchi *lldp_status = I40E_GET_FW_LLDP_STATUS_DISABLED;
1001*df36e06dSRobert Mustacchi ret = I40E_SUCCESS;
1002*df36e06dSRobert Mustacchi }
1003*df36e06dSRobert Mustacchi
1004*df36e06dSRobert Mustacchi i40e_free_virt_mem(hw, &mem);
100593f1cac5SPaul Winder return ret;
100693f1cac5SPaul Winder }
100793f1cac5SPaul Winder
1008*df36e06dSRobert Mustacchi
100993f1cac5SPaul Winder /**
101093f1cac5SPaul Winder * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format
101193f1cac5SPaul Winder * @tlv: Fill the ETS config data in IEEE format
101293f1cac5SPaul Winder * @dcbcfg: Local store which holds the DCB Config
101393f1cac5SPaul Winder *
101493f1cac5SPaul Winder * Prepare IEEE 802.1Qaz ETS CFG TLV
101593f1cac5SPaul Winder **/
i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)101693f1cac5SPaul Winder static void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv,
101793f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
101893f1cac5SPaul Winder {
101993f1cac5SPaul Winder u8 priority0, priority1, maxtcwilling = 0;
102093f1cac5SPaul Winder struct i40e_dcb_ets_config *etscfg;
102193f1cac5SPaul Winder u16 offset = 0, typelength, i;
102293f1cac5SPaul Winder u8 *buf = tlv->tlvinfo;
102393f1cac5SPaul Winder u32 ouisubtype;
102493f1cac5SPaul Winder
102593f1cac5SPaul Winder typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
102693f1cac5SPaul Winder I40E_IEEE_ETS_TLV_LENGTH);
102793f1cac5SPaul Winder tlv->typelength = I40E_HTONS(typelength);
102893f1cac5SPaul Winder
102993f1cac5SPaul Winder ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
103093f1cac5SPaul Winder I40E_IEEE_SUBTYPE_ETS_CFG);
103193f1cac5SPaul Winder tlv->ouisubtype = I40E_HTONL(ouisubtype);
103293f1cac5SPaul Winder
103393f1cac5SPaul Winder /* First Octet post subtype
103493f1cac5SPaul Winder * --------------------------
103593f1cac5SPaul Winder * |will-|CBS | Re- | Max |
103693f1cac5SPaul Winder * |ing | |served| TCs |
103793f1cac5SPaul Winder * --------------------------
103893f1cac5SPaul Winder * |1bit | 1bit|3 bits|3bits|
103993f1cac5SPaul Winder */
104093f1cac5SPaul Winder etscfg = &dcbcfg->etscfg;
104193f1cac5SPaul Winder if (etscfg->willing)
104293f1cac5SPaul Winder maxtcwilling = BIT(I40E_IEEE_ETS_WILLING_SHIFT);
104393f1cac5SPaul Winder maxtcwilling |= etscfg->maxtcs & I40E_IEEE_ETS_MAXTC_MASK;
104493f1cac5SPaul Winder buf[offset] = maxtcwilling;
104593f1cac5SPaul Winder
104693f1cac5SPaul Winder /* Move offset to Priority Assignment Table */
104793f1cac5SPaul Winder offset++;
104893f1cac5SPaul Winder
104993f1cac5SPaul Winder /* Priority Assignment Table (4 octets)
105093f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 |
105193f1cac5SPaul Winder * -----------------------------------------
105293f1cac5SPaul Winder * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
105393f1cac5SPaul Winder * -----------------------------------------
105493f1cac5SPaul Winder * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
105593f1cac5SPaul Winder * -----------------------------------------
105693f1cac5SPaul Winder */
105793f1cac5SPaul Winder for (i = 0; i < 4; i++) {
105893f1cac5SPaul Winder priority0 = etscfg->prioritytable[i * 2] & 0xF;
105993f1cac5SPaul Winder priority1 = etscfg->prioritytable[i * 2 + 1] & 0xF;
106093f1cac5SPaul Winder buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
106193f1cac5SPaul Winder priority1;
106293f1cac5SPaul Winder offset++;
106393f1cac5SPaul Winder }
106493f1cac5SPaul Winder
106593f1cac5SPaul Winder /* TC Bandwidth Table (8 octets)
106693f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
106793f1cac5SPaul Winder * ---------------------------------
106893f1cac5SPaul Winder * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
106993f1cac5SPaul Winder * ---------------------------------
107093f1cac5SPaul Winder */
107193f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
107293f1cac5SPaul Winder buf[offset++] = etscfg->tcbwtable[i];
107393f1cac5SPaul Winder
107493f1cac5SPaul Winder /* TSA Assignment Table (8 octets)
107593f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
107693f1cac5SPaul Winder * ---------------------------------
107793f1cac5SPaul Winder * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
107893f1cac5SPaul Winder * ---------------------------------
107993f1cac5SPaul Winder */
108093f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
108193f1cac5SPaul Winder buf[offset++] = etscfg->tsatable[i];
108293f1cac5SPaul Winder }
108393f1cac5SPaul Winder
108493f1cac5SPaul Winder /**
108593f1cac5SPaul Winder * i40e_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format
108693f1cac5SPaul Winder * @tlv: Fill ETS Recommended TLV in IEEE format
108793f1cac5SPaul Winder * @dcbcfg: Local store which holds the DCB Config
108893f1cac5SPaul Winder *
108993f1cac5SPaul Winder * Prepare IEEE 802.1Qaz ETS REC TLV
109093f1cac5SPaul Winder **/
i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)109193f1cac5SPaul Winder static void i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
109293f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
109393f1cac5SPaul Winder {
109493f1cac5SPaul Winder struct i40e_dcb_ets_config *etsrec;
109593f1cac5SPaul Winder u16 offset = 0, typelength, i;
109693f1cac5SPaul Winder u8 priority0, priority1;
109793f1cac5SPaul Winder u8 *buf = tlv->tlvinfo;
109893f1cac5SPaul Winder u32 ouisubtype;
109993f1cac5SPaul Winder
110093f1cac5SPaul Winder typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
110193f1cac5SPaul Winder I40E_IEEE_ETS_TLV_LENGTH);
110293f1cac5SPaul Winder tlv->typelength = I40E_HTONS(typelength);
110393f1cac5SPaul Winder
110493f1cac5SPaul Winder ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
110593f1cac5SPaul Winder I40E_IEEE_SUBTYPE_ETS_REC);
110693f1cac5SPaul Winder tlv->ouisubtype = I40E_HTONL(ouisubtype);
110793f1cac5SPaul Winder
110893f1cac5SPaul Winder etsrec = &dcbcfg->etsrec;
110993f1cac5SPaul Winder /* First Octet is reserved */
111093f1cac5SPaul Winder /* Move offset to Priority Assignment Table */
111193f1cac5SPaul Winder offset++;
111293f1cac5SPaul Winder
111393f1cac5SPaul Winder /* Priority Assignment Table (4 octets)
111493f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 |
111593f1cac5SPaul Winder * -----------------------------------------
111693f1cac5SPaul Winder * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
111793f1cac5SPaul Winder * -----------------------------------------
111893f1cac5SPaul Winder * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
111993f1cac5SPaul Winder * -----------------------------------------
112093f1cac5SPaul Winder */
112193f1cac5SPaul Winder for (i = 0; i < 4; i++) {
112293f1cac5SPaul Winder priority0 = etsrec->prioritytable[i * 2] & 0xF;
112393f1cac5SPaul Winder priority1 = etsrec->prioritytable[i * 2 + 1] & 0xF;
112493f1cac5SPaul Winder buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
112593f1cac5SPaul Winder priority1;
112693f1cac5SPaul Winder offset++;
112793f1cac5SPaul Winder }
112893f1cac5SPaul Winder
112993f1cac5SPaul Winder /* TC Bandwidth Table (8 octets)
113093f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
113193f1cac5SPaul Winder * ---------------------------------
113293f1cac5SPaul Winder * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
113393f1cac5SPaul Winder * ---------------------------------
113493f1cac5SPaul Winder */
113593f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
113693f1cac5SPaul Winder buf[offset++] = etsrec->tcbwtable[i];
113793f1cac5SPaul Winder
113893f1cac5SPaul Winder /* TSA Assignment Table (8 octets)
113993f1cac5SPaul Winder * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
114093f1cac5SPaul Winder * ---------------------------------
114193f1cac5SPaul Winder * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
114293f1cac5SPaul Winder * ---------------------------------
114393f1cac5SPaul Winder */
114493f1cac5SPaul Winder for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
114593f1cac5SPaul Winder buf[offset++] = etsrec->tsatable[i];
114693f1cac5SPaul Winder }
114793f1cac5SPaul Winder
114893f1cac5SPaul Winder /**
114993f1cac5SPaul Winder * i40e_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format
115093f1cac5SPaul Winder * @tlv: Fill PFC TLV in IEEE format
115193f1cac5SPaul Winder * @dcbcfg: Local store to get PFC CFG data
115293f1cac5SPaul Winder *
115393f1cac5SPaul Winder * Prepare IEEE 802.1Qaz PFC CFG TLV
115493f1cac5SPaul Winder **/
i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)115593f1cac5SPaul Winder static void i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv *tlv,
115693f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
115793f1cac5SPaul Winder {
115893f1cac5SPaul Winder u8 *buf = tlv->tlvinfo;
115993f1cac5SPaul Winder u32 ouisubtype;
116093f1cac5SPaul Winder u16 typelength;
116193f1cac5SPaul Winder
116293f1cac5SPaul Winder typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
116393f1cac5SPaul Winder I40E_IEEE_PFC_TLV_LENGTH);
116493f1cac5SPaul Winder tlv->typelength = I40E_HTONS(typelength);
116593f1cac5SPaul Winder
116693f1cac5SPaul Winder ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
116793f1cac5SPaul Winder I40E_IEEE_SUBTYPE_PFC_CFG);
116893f1cac5SPaul Winder tlv->ouisubtype = I40E_HTONL(ouisubtype);
116993f1cac5SPaul Winder
117093f1cac5SPaul Winder /* ----------------------------------------
117193f1cac5SPaul Winder * |will-|MBC | Re- | PFC | PFC Enable |
117293f1cac5SPaul Winder * |ing | |served| cap | |
117393f1cac5SPaul Winder * -----------------------------------------
117493f1cac5SPaul Winder * |1bit | 1bit|2 bits|4bits| 1 octet |
117593f1cac5SPaul Winder */
117693f1cac5SPaul Winder if (dcbcfg->pfc.willing)
117793f1cac5SPaul Winder buf[0] = BIT(I40E_IEEE_PFC_WILLING_SHIFT);
117893f1cac5SPaul Winder
117993f1cac5SPaul Winder if (dcbcfg->pfc.mbc)
118093f1cac5SPaul Winder buf[0] |= BIT(I40E_IEEE_PFC_MBC_SHIFT);
118193f1cac5SPaul Winder
118293f1cac5SPaul Winder buf[0] |= dcbcfg->pfc.pfccap & 0xF;
118393f1cac5SPaul Winder buf[1] = dcbcfg->pfc.pfcenable;
118493f1cac5SPaul Winder }
118593f1cac5SPaul Winder
118693f1cac5SPaul Winder /**
118793f1cac5SPaul Winder * i40e_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format
118893f1cac5SPaul Winder * @tlv: Fill APP TLV in IEEE format
118993f1cac5SPaul Winder * @dcbcfg: Local store to get APP CFG data
119093f1cac5SPaul Winder *
119193f1cac5SPaul Winder * Prepare IEEE 802.1Qaz APP CFG TLV
119293f1cac5SPaul Winder **/
i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)119393f1cac5SPaul Winder static void i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv *tlv,
119493f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
119593f1cac5SPaul Winder {
119693f1cac5SPaul Winder u16 typelength, length, offset = 0;
119793f1cac5SPaul Winder u8 priority, selector, i = 0;
119893f1cac5SPaul Winder u8 *buf = tlv->tlvinfo;
119993f1cac5SPaul Winder u32 ouisubtype;
120093f1cac5SPaul Winder
120193f1cac5SPaul Winder /* No APP TLVs then just return */
120293f1cac5SPaul Winder if (dcbcfg->numapps == 0)
120393f1cac5SPaul Winder return;
120493f1cac5SPaul Winder ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
120593f1cac5SPaul Winder I40E_IEEE_SUBTYPE_APP_PRI);
120693f1cac5SPaul Winder tlv->ouisubtype = I40E_HTONL(ouisubtype);
120793f1cac5SPaul Winder
120893f1cac5SPaul Winder /* Move offset to App Priority Table */
120993f1cac5SPaul Winder offset++;
121093f1cac5SPaul Winder /* Application Priority Table (3 octets)
121193f1cac5SPaul Winder * Octets:| 1 | 2 | 3 |
121293f1cac5SPaul Winder * -----------------------------------------
121393f1cac5SPaul Winder * |Priority|Rsrvd| Sel | Protocol ID |
121493f1cac5SPaul Winder * -----------------------------------------
121593f1cac5SPaul Winder * Bits:|23 21|20 19|18 16|15 0|
121693f1cac5SPaul Winder * -----------------------------------------
121793f1cac5SPaul Winder */
121893f1cac5SPaul Winder while (i < dcbcfg->numapps) {
121993f1cac5SPaul Winder priority = dcbcfg->app[i].priority & 0x7;
122093f1cac5SPaul Winder selector = dcbcfg->app[i].selector & 0x7;
122193f1cac5SPaul Winder buf[offset] = (priority << I40E_IEEE_APP_PRIO_SHIFT) | selector;
122293f1cac5SPaul Winder buf[offset + 1] = (dcbcfg->app[i].protocolid >> 0x8) & 0xFF;
122393f1cac5SPaul Winder buf[offset + 2] = dcbcfg->app[i].protocolid & 0xFF;
122493f1cac5SPaul Winder /* Move to next app */
122593f1cac5SPaul Winder offset += 3;
122693f1cac5SPaul Winder i++;
122793f1cac5SPaul Winder if (i >= I40E_DCBX_MAX_APPS)
122893f1cac5SPaul Winder break;
122993f1cac5SPaul Winder }
123093f1cac5SPaul Winder /* length includes size of ouisubtype + 1 reserved + 3*numapps */
123193f1cac5SPaul Winder length = sizeof(tlv->ouisubtype) + 1 + (i*3);
123293f1cac5SPaul Winder typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
123393f1cac5SPaul Winder (length & 0x1FF));
123493f1cac5SPaul Winder tlv->typelength = I40E_HTONS(typelength);
123593f1cac5SPaul Winder }
123693f1cac5SPaul Winder
123793f1cac5SPaul Winder /**
123893f1cac5SPaul Winder * i40e_add_dcb_tlv - Add all IEEE TLVs
123993f1cac5SPaul Winder * @tlv: pointer to org tlv
124093f1cac5SPaul Winder *
124193f1cac5SPaul Winder * add tlv information
124293f1cac5SPaul Winder **/
i40e_add_dcb_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg,u16 tlvid)124393f1cac5SPaul Winder static void i40e_add_dcb_tlv(struct i40e_lldp_org_tlv *tlv,
124493f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg,
124593f1cac5SPaul Winder u16 tlvid)
124693f1cac5SPaul Winder {
124793f1cac5SPaul Winder switch (tlvid) {
124893f1cac5SPaul Winder case I40E_IEEE_TLV_ID_ETS_CFG:
124993f1cac5SPaul Winder i40e_add_ieee_ets_tlv(tlv, dcbcfg);
125093f1cac5SPaul Winder break;
125193f1cac5SPaul Winder case I40E_IEEE_TLV_ID_ETS_REC:
125293f1cac5SPaul Winder i40e_add_ieee_etsrec_tlv(tlv, dcbcfg);
125393f1cac5SPaul Winder break;
125493f1cac5SPaul Winder case I40E_IEEE_TLV_ID_PFC_CFG:
125593f1cac5SPaul Winder i40e_add_ieee_pfc_tlv(tlv, dcbcfg);
125693f1cac5SPaul Winder break;
125793f1cac5SPaul Winder case I40E_IEEE_TLV_ID_APP_PRI:
125893f1cac5SPaul Winder i40e_add_ieee_app_pri_tlv(tlv, dcbcfg);
125993f1cac5SPaul Winder break;
126093f1cac5SPaul Winder default:
126193f1cac5SPaul Winder break;
126293f1cac5SPaul Winder }
126393f1cac5SPaul Winder }
126493f1cac5SPaul Winder
126593f1cac5SPaul Winder /**
126693f1cac5SPaul Winder * i40e_set_dcb_config - Set the local LLDP MIB to FW
126793f1cac5SPaul Winder * @hw: pointer to the hw struct
126893f1cac5SPaul Winder *
126993f1cac5SPaul Winder * Set DCB configuration to the Firmware
127093f1cac5SPaul Winder **/
i40e_set_dcb_config(struct i40e_hw * hw)127193f1cac5SPaul Winder enum i40e_status_code i40e_set_dcb_config(struct i40e_hw *hw)
127293f1cac5SPaul Winder {
127393f1cac5SPaul Winder enum i40e_status_code ret = I40E_SUCCESS;
127493f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg;
127593f1cac5SPaul Winder struct i40e_virt_mem mem;
127693f1cac5SPaul Winder u8 mib_type, *lldpmib;
127793f1cac5SPaul Winder u16 miblen;
127893f1cac5SPaul Winder
127993f1cac5SPaul Winder /* update the hw local config */
128093f1cac5SPaul Winder dcbcfg = &hw->local_dcbx_config;
128193f1cac5SPaul Winder /* Allocate the LLDPDU */
128293f1cac5SPaul Winder ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
128393f1cac5SPaul Winder if (ret)
128493f1cac5SPaul Winder return ret;
128593f1cac5SPaul Winder
128693f1cac5SPaul Winder mib_type = SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB;
128793f1cac5SPaul Winder if (dcbcfg->app_mode == I40E_DCBX_APPS_NON_WILLING) {
128893f1cac5SPaul Winder mib_type |= SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS <<
128993f1cac5SPaul Winder SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT;
129093f1cac5SPaul Winder }
129193f1cac5SPaul Winder lldpmib = (u8 *)mem.va;
129293f1cac5SPaul Winder ret = i40e_dcb_config_to_lldp(lldpmib, &miblen, dcbcfg);
129393f1cac5SPaul Winder ret = i40e_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, NULL);
129493f1cac5SPaul Winder
129593f1cac5SPaul Winder i40e_free_virt_mem(hw, &mem);
129693f1cac5SPaul Winder return ret;
129793f1cac5SPaul Winder }
129893f1cac5SPaul Winder
129993f1cac5SPaul Winder /**
130093f1cac5SPaul Winder * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format
1301*df36e06dSRobert Mustacchi * @lldpmib: pointer to mib to be output
1302*df36e06dSRobert Mustacchi * @miblen: pointer to u16 for length of lldpmib
130393f1cac5SPaul Winder * @dcbcfg: store for LLDPDU data
130493f1cac5SPaul Winder *
130593f1cac5SPaul Winder * send DCB configuration to FW
130693f1cac5SPaul Winder **/
i40e_dcb_config_to_lldp(u8 * lldpmib,u16 * miblen,struct i40e_dcbx_config * dcbcfg)130793f1cac5SPaul Winder enum i40e_status_code i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen,
130893f1cac5SPaul Winder struct i40e_dcbx_config *dcbcfg)
130993f1cac5SPaul Winder {
131093f1cac5SPaul Winder u16 length, offset = 0, tlvid = I40E_TLV_ID_START;
131193f1cac5SPaul Winder enum i40e_status_code ret = I40E_SUCCESS;
131293f1cac5SPaul Winder struct i40e_lldp_org_tlv *tlv;
131393f1cac5SPaul Winder u16 typelength;
131493f1cac5SPaul Winder
131593f1cac5SPaul Winder tlv = (struct i40e_lldp_org_tlv *)lldpmib;
131693f1cac5SPaul Winder while (1) {
131793f1cac5SPaul Winder i40e_add_dcb_tlv(tlv, dcbcfg, tlvid++);
131893f1cac5SPaul Winder typelength = I40E_NTOHS(tlv->typelength);
131993f1cac5SPaul Winder length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
132093f1cac5SPaul Winder I40E_LLDP_TLV_LEN_SHIFT);
132193f1cac5SPaul Winder if (length)
132293f1cac5SPaul Winder offset += length + 2;
132393f1cac5SPaul Winder /* END TLV or beyond LLDPDU size */
132493f1cac5SPaul Winder if ((tlvid >= I40E_TLV_ID_END_OF_LLDPPDU) ||
132593f1cac5SPaul Winder (offset > I40E_LLDPDU_SIZE))
132693f1cac5SPaul Winder break;
132793f1cac5SPaul Winder /* Move to next TLV */
132893f1cac5SPaul Winder if (length)
132993f1cac5SPaul Winder tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
133093f1cac5SPaul Winder sizeof(tlv->typelength) + length);
133193f1cac5SPaul Winder }
133293f1cac5SPaul Winder *miblen = offset;
133393f1cac5SPaul Winder return ret;
133493f1cac5SPaul Winder }
133593f1cac5SPaul Winder
133693f1cac5SPaul Winder
133793f1cac5SPaul Winder /**
133893f1cac5SPaul Winder * _i40e_read_lldp_cfg - generic read of LLDP Configuration data from NVM
133993f1cac5SPaul Winder * @hw: pointer to the HW structure
134093f1cac5SPaul Winder * @lldp_cfg: pointer to hold lldp configuration variables
134193f1cac5SPaul Winder * @module: address of the module pointer
134293f1cac5SPaul Winder * @word_offset: offset of LLDP configuration
134393f1cac5SPaul Winder *
134493f1cac5SPaul Winder * Reads the LLDP configuration data from NVM using passed addresses
134593f1cac5SPaul Winder **/
_i40e_read_lldp_cfg(struct i40e_hw * hw,struct i40e_lldp_variables * lldp_cfg,u8 module,u32 word_offset)134693f1cac5SPaul Winder static enum i40e_status_code _i40e_read_lldp_cfg(struct i40e_hw *hw,
134793f1cac5SPaul Winder struct i40e_lldp_variables *lldp_cfg,
134893f1cac5SPaul Winder u8 module, u32 word_offset)
134993f1cac5SPaul Winder {
135093f1cac5SPaul Winder u32 address, offset = (2 * word_offset);
135193f1cac5SPaul Winder enum i40e_status_code ret;
135293f1cac5SPaul Winder __le16 raw_mem;
135393f1cac5SPaul Winder u16 mem;
135493f1cac5SPaul Winder
135593f1cac5SPaul Winder ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
135693f1cac5SPaul Winder if (ret != I40E_SUCCESS)
135793f1cac5SPaul Winder return ret;
135893f1cac5SPaul Winder
135993f1cac5SPaul Winder ret = i40e_aq_read_nvm(hw, 0x0, module * 2, sizeof(raw_mem), &raw_mem,
136093f1cac5SPaul Winder TRUE, NULL);
136193f1cac5SPaul Winder i40e_release_nvm(hw);
136293f1cac5SPaul Winder if (ret != I40E_SUCCESS)
136393f1cac5SPaul Winder return ret;
136493f1cac5SPaul Winder
136593f1cac5SPaul Winder mem = LE16_TO_CPU(raw_mem);
136693f1cac5SPaul Winder /* Check if this pointer needs to be read in word size or 4K sector
136793f1cac5SPaul Winder * units.
136893f1cac5SPaul Winder */
136993f1cac5SPaul Winder if (mem & I40E_PTR_TYPE)
137093f1cac5SPaul Winder address = (0x7FFF & mem) * 4096;
137193f1cac5SPaul Winder else
137293f1cac5SPaul Winder address = (0x7FFF & mem) * 2;
137393f1cac5SPaul Winder
137493f1cac5SPaul Winder ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
137593f1cac5SPaul Winder if (ret != I40E_SUCCESS)
137693f1cac5SPaul Winder goto err_lldp_cfg;
137793f1cac5SPaul Winder
137893f1cac5SPaul Winder ret = i40e_aq_read_nvm(hw, module, offset, sizeof(raw_mem), &raw_mem,
137993f1cac5SPaul Winder TRUE, NULL);
138093f1cac5SPaul Winder i40e_release_nvm(hw);
138193f1cac5SPaul Winder if (ret != I40E_SUCCESS)
138293f1cac5SPaul Winder return ret;
138393f1cac5SPaul Winder
138493f1cac5SPaul Winder mem = LE16_TO_CPU(raw_mem);
138593f1cac5SPaul Winder offset = mem + word_offset;
138693f1cac5SPaul Winder offset *= 2;
138793f1cac5SPaul Winder
138893f1cac5SPaul Winder ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
138993f1cac5SPaul Winder if (ret != I40E_SUCCESS)
139093f1cac5SPaul Winder goto err_lldp_cfg;
139193f1cac5SPaul Winder
139293f1cac5SPaul Winder ret = i40e_aq_read_nvm(hw, 0, address + offset,
139393f1cac5SPaul Winder sizeof(struct i40e_lldp_variables), lldp_cfg,
139493f1cac5SPaul Winder TRUE, NULL);
139593f1cac5SPaul Winder i40e_release_nvm(hw);
139693f1cac5SPaul Winder
139793f1cac5SPaul Winder err_lldp_cfg:
139893f1cac5SPaul Winder return ret;
139993f1cac5SPaul Winder }
140093f1cac5SPaul Winder
140193f1cac5SPaul Winder /**
140293f1cac5SPaul Winder * i40e_read_lldp_cfg - read LLDP Configuration data from NVM
140393f1cac5SPaul Winder * @hw: pointer to the HW structure
140493f1cac5SPaul Winder * @lldp_cfg: pointer to hold lldp configuration variables
140593f1cac5SPaul Winder *
140693f1cac5SPaul Winder * Reads the LLDP configuration data from NVM
140793f1cac5SPaul Winder **/
i40e_read_lldp_cfg(struct i40e_hw * hw,struct i40e_lldp_variables * lldp_cfg)140893f1cac5SPaul Winder enum i40e_status_code i40e_read_lldp_cfg(struct i40e_hw *hw,
140993f1cac5SPaul Winder struct i40e_lldp_variables *lldp_cfg)
141093f1cac5SPaul Winder {
141193f1cac5SPaul Winder enum i40e_status_code ret = I40E_SUCCESS;
141293f1cac5SPaul Winder u32 mem;
141393f1cac5SPaul Winder
141493f1cac5SPaul Winder if (!lldp_cfg)
141593f1cac5SPaul Winder return I40E_ERR_PARAM;
141693f1cac5SPaul Winder
141793f1cac5SPaul Winder ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
141893f1cac5SPaul Winder if (ret != I40E_SUCCESS)
141993f1cac5SPaul Winder return ret;
142093f1cac5SPaul Winder
142193f1cac5SPaul Winder ret = i40e_aq_read_nvm(hw, I40E_SR_NVM_CONTROL_WORD, 0, sizeof(mem),
142293f1cac5SPaul Winder &mem, TRUE, NULL);
142393f1cac5SPaul Winder i40e_release_nvm(hw);
142493f1cac5SPaul Winder if (ret != I40E_SUCCESS)
142593f1cac5SPaul Winder return ret;
142693f1cac5SPaul Winder
142793f1cac5SPaul Winder /* Read a bit that holds information whether we are running flat or
142893f1cac5SPaul Winder * structured NVM image. Flat image has LLDP configuration in shadow
142993f1cac5SPaul Winder * ram, so there is a need to pass different addresses for both cases.
143093f1cac5SPaul Winder */
143193f1cac5SPaul Winder if (mem & I40E_SR_NVM_MAP_STRUCTURE_TYPE) {
143293f1cac5SPaul Winder /* Flat NVM case */
143393f1cac5SPaul Winder ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_SR_EMP_MODULE_PTR,
143493f1cac5SPaul Winder I40E_SR_LLDP_CFG_PTR);
143593f1cac5SPaul Winder } else {
143693f1cac5SPaul Winder /* Good old structured NVM image */
143793f1cac5SPaul Winder ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_EMP_MODULE_PTR,
143893f1cac5SPaul Winder I40E_NVM_LLDP_CFG_PTR);
143993f1cac5SPaul Winder }
144093f1cac5SPaul Winder
144193f1cac5SPaul Winder return ret;
144293f1cac5SPaul Winder }
1443