X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=drivers%2Fnet%2Fqede%2Fbase%2Fecore_dcbx.c;h=8175619ae65dc0c030846a472d21162b73d6c457;hb=6b3e017e5d25f15da73f7700f7f2ac553ef1a2e9;hp=6a966cb9178c9702eff3bbd705680035c015e3f7;hpb=8b25d1ad5d2264bdfc2818c7bda74ee2697df6db;p=deb_dpdk.git diff --git a/drivers/net/qede/base/ecore_dcbx.c b/drivers/net/qede/base/ecore_dcbx.c index 6a966cb9..8175619a 100644 --- a/drivers/net/qede/base/ecore_dcbx.c +++ b/drivers/net/qede/base/ecore_dcbx.c @@ -15,7 +15,6 @@ #include "ecore_iro.h" #define ECORE_DCBX_MAX_MIB_READ_TRY (100) -#define ECORE_MAX_PFC_PRIORITIES 8 #define ECORE_ETH_TYPE_DEFAULT (0) #define ECORE_DCBX_INVALID_PRIORITY 0xFF @@ -24,7 +23,7 @@ * the traffic class corresponding to the priority. */ #define ECORE_DCBX_PRIO2TC(prio_tc_tbl, prio) \ - ((u32)(pri_tc_tbl >> ((7 - prio) * 4)) & 0x7) + ((u32)(prio_tc_tbl >> ((7 - prio) * 4)) & 0x7) static bool ecore_dcbx_app_ethtype(u32 app_info_bitmap) { @@ -38,6 +37,18 @@ static bool ecore_dcbx_app_port(u32 app_info_bitmap) DCBX_APP_SF_PORT) ? true : false; } +static bool ecore_dcbx_ieee_app_port(u32 app_info_bitmap, u8 type) +{ + u8 mfw_val = ECORE_MFW_GET_FIELD(app_info_bitmap, DCBX_APP_SF_IEEE); + + /* Old MFW */ + if (mfw_val == DCBX_APP_SF_IEEE_RESERVED) + return ecore_dcbx_app_port(app_info_bitmap); + + return (mfw_val == type || mfw_val == DCBX_APP_SF_IEEE_TCP_UDP_PORT) ? + true : false; +} + static bool ecore_dcbx_default_tlv(u32 app_info_bitmap, u16 proto_id) { return (ecore_dcbx_app_ethtype(app_info_bitmap) && @@ -62,6 +73,12 @@ static bool ecore_dcbx_ieee(u32 dcbx_cfg_bitmap) DCBX_CONFIG_VERSION_IEEE) ? true : false; } +static bool ecore_dcbx_local(u32 dcbx_cfg_bitmap) +{ + return (ECORE_MFW_GET_FIELD(dcbx_cfg_bitmap, DCBX_CONFIG_VERSION) == + DCBX_CONFIG_VERSION_STATIC) ? true : false; +} + /* @@@TBD A0 Eagle workaround */ void ecore_dcbx_eagle_workaround(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, bool set_to_pfc) @@ -83,8 +100,8 @@ ecore_dcbx_dp_protocol(struct ecore_hwfn *p_hwfn, { struct ecore_hw_info *p_info = &p_hwfn->hw_info; enum dcbx_protocol_type id; - bool enable, update; - u8 prio, tc, size; + u8 prio, tc, size, update; + bool enable; const char *name; /* @DPDK */ int i; @@ -102,8 +119,10 @@ ecore_dcbx_dp_protocol(struct ecore_hwfn *p_hwfn, prio = p_data->arr[id].priority; DP_INFO(p_hwfn, - "%s info: update %d, enable %d, prio %d, tc %d, num_tc %d\n", - name, update, enable, prio, tc, p_info->num_tc); + "%s info: update %d, enable %d, prio %d, tc %d," + " num_active_tc %d dscp_enable = %d dscp_val = %d\n", + name, update, enable, prio, tc, p_info->num_active_tc, + p_data->arr[id].dscp_enable, p_data->arr[id].dscp_val); } } @@ -112,28 +131,42 @@ ecore_dcbx_set_pf_tcs(struct ecore_hw_info *p_info, u8 tc, enum ecore_pci_personality personality) { /* QM reconf data */ - if (p_info->personality == personality) { - if (personality == ECORE_PCI_ETH) - p_info->non_offload_tc = tc; - else - p_info->offload_tc = tc; - } + if (p_info->personality == personality) + p_info->offload_tc = tc; } void ecore_dcbx_set_params(struct ecore_dcbx_results *p_data, - struct ecore_hw_info *p_info, + struct ecore_hwfn *p_hwfn, bool enable, bool update, u8 prio, u8 tc, enum dcbx_protocol_type type, enum ecore_pci_personality personality) { + struct ecore_dcbx_dscp_params *dscp = &p_hwfn->p_dcbx_info->get.dscp; + /* PF update ramrod data */ - p_data->arr[type].update = update; p_data->arr[type].enable = enable; p_data->arr[type].priority = prio; p_data->arr[type].tc = tc; + p_data->arr[type].dscp_enable = dscp->enabled; + if (p_data->arr[type].dscp_enable) { + u8 i; + + for (i = 0; i < ECORE_DCBX_DSCP_SIZE; i++) + if (prio == dscp->dscp_pri_map[i]) { + p_data->arr[type].dscp_val = i; + break; + } + } + + if (enable && p_data->arr[type].dscp_enable) + p_data->arr[type].update = UPDATE_DCB_DSCP; + else if (enable) + p_data->arr[type].update = UPDATE_DCB; + else + p_data->arr[type].update = DONT_UPDATE_DCB_DHCP; - ecore_dcbx_set_pf_tcs(p_info, tc, personality); + ecore_dcbx_set_pf_tcs(&p_hwfn->hw_info, tc, personality); } /* Update app protocol data and hw_info fields with the TLV info */ @@ -143,7 +176,6 @@ ecore_dcbx_update_app_info(struct ecore_dcbx_results *p_data, bool enable, bool update, u8 prio, u8 tc, enum dcbx_protocol_type type) { - struct ecore_hw_info *p_info = &p_hwfn->hw_info; enum ecore_pci_personality personality; enum dcbx_protocol_type id; const char *name; /* @DPDK */ @@ -161,7 +193,7 @@ ecore_dcbx_update_app_info(struct ecore_dcbx_results *p_data, personality = ecore_dcbx_app_update[i].personality; name = ecore_dcbx_app_update[i].name; - ecore_dcbx_set_params(p_data, p_info, enable, update, + ecore_dcbx_set_params(p_data, p_hwfn, enable, update, prio, tc, type, personality); } } @@ -197,7 +229,8 @@ ecore_dcbx_get_app_priority(u8 pri_bitmap, u8 *priority) static bool ecore_dcbx_get_app_protocol_type(struct ecore_hwfn *p_hwfn, - u32 app_prio_bitmap, u16 id, int *type) + u32 app_prio_bitmap, u16 id, + enum dcbx_protocol_type *type, bool ieee) { bool status = false; @@ -205,7 +238,11 @@ ecore_dcbx_get_app_protocol_type(struct ecore_hwfn *p_hwfn, *type = DCBX_PROTOCOL_ETH; status = true; } else { - DP_ERR(p_hwfn, "Unsupported protocol %d\n", id); + *type = DCBX_MAX_PROTOCOL_TYPE; + DP_ERR(p_hwfn, + "No action required, App TLV id = 0x%x" + " app_prio_bitmap = 0x%x\n", + id, app_prio_bitmap); } return status; @@ -218,16 +255,18 @@ static enum _ecore_status_t ecore_dcbx_process_tlv(struct ecore_hwfn *p_hwfn, struct ecore_dcbx_results *p_data, struct dcbx_app_priority_entry *p_tbl, u32 pri_tc_tbl, - int count, bool dcbx_enabled) + int count, u8 dcbx_version) { enum _ecore_status_t rc = ECORE_SUCCESS; u8 tc, priority, priority_map; - int i, type = -1; + enum dcbx_protocol_type type; + bool enable, ieee; u16 protocol_id; - bool enable; + int i; DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "Num APP entries = %d\n", count); + ieee = (dcbx_version == DCBX_CONFIG_VERSION_IEEE); /* Parse APP TLV */ for (i = 0; i < count; i++) { protocol_id = ECORE_MFW_GET_FIELD(p_tbl[i].entry, @@ -242,7 +281,8 @@ ecore_dcbx_process_tlv(struct ecore_hwfn *p_hwfn, tc = ECORE_DCBX_PRIO2TC(pri_tc_tbl, priority); if (ecore_dcbx_get_app_protocol_type(p_hwfn, p_tbl[i].entry, - protocol_id, &type)) { + protocol_id, &type, + ieee)) { /* ETH always have the enable bit reset, as it gets * vlan information per packet. For other protocols, * should be set according to the dcbx_enabled @@ -267,7 +307,7 @@ ecore_dcbx_process_tlv(struct ecore_hwfn *p_hwfn, if (p_data->arr[type].update) continue; - enable = (type == DCBX_PROTOCOL_ETH) ? false : dcbx_enabled; + enable = (type == DCBX_PROTOCOL_ETH) ? false : !!dcbx_version; ecore_dcbx_update_app_info(p_data, p_hwfn, enable, true, priority, tc, type); } @@ -288,14 +328,11 @@ ecore_dcbx_process_mib_info(struct ecore_hwfn *p_hwfn) struct dcbx_ets_feature *p_ets; struct ecore_hw_info *p_info; u32 pri_tc_tbl, flags; - bool dcbx_enabled; + u8 dcbx_version; int num_entries; - /* If DCBx version is non zero, then negotiation was - * successfuly performed - */ flags = p_hwfn->p_dcbx_info->operational.flags; - dcbx_enabled = ECORE_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION) != 0; + dcbx_version = ECORE_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION); p_app = &p_hwfn->p_dcbx_info->operational.features.app; p_tbl = p_app->app_pri_tbl; @@ -307,13 +344,14 @@ ecore_dcbx_process_mib_info(struct ecore_hwfn *p_hwfn) num_entries = ECORE_MFW_GET_FIELD(p_app->flags, DCBX_APP_NUM_ENTRIES); rc = ecore_dcbx_process_tlv(p_hwfn, &data, p_tbl, pri_tc_tbl, - num_entries, dcbx_enabled); + num_entries, dcbx_version); if (rc != ECORE_SUCCESS) return rc; - p_info->num_tc = ECORE_MFW_GET_FIELD(p_ets->flags, DCBX_ETS_MAX_TCS); + p_info->num_active_tc = ECORE_MFW_GET_FIELD(p_ets->flags, + DCBX_ETS_MAX_TCS); data.pf_id = p_hwfn->rel_pf_id; - data.dcbx_enabled = dcbx_enabled; + data.dcbx_enabled = !!dcbx_version; ecore_dcbx_dp_protocol(p_hwfn, &data); @@ -348,14 +386,16 @@ ecore_dcbx_copy_mib(struct ecore_hwfn *p_hwfn, read_count++; DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, - "mib type = %d, try count = %d prefix seq num = %d suffix seq num = %d\n", + "mib type = %d, try count = %d prefix seq num =" + " %d suffix seq num = %d\n", type, read_count, prefix_seq_num, suffix_seq_num); } while ((prefix_seq_num != suffix_seq_num) && (read_count < ECORE_DCBX_MAX_MIB_READ_TRY)); if (read_count >= ECORE_DCBX_MAX_MIB_READ_TRY) { DP_ERR(p_hwfn, - "MIB read err, mib type = %d, try count = %d prefix seq num = %d suffix seq num = %d\n", + "MIB read err, mib type = %d, try count =" + " %d prefix seq num = %d suffix seq num = %d\n", type, read_count, prefix_seq_num, suffix_seq_num); rc = ECORE_IO; } @@ -384,36 +424,92 @@ static void ecore_dcbx_get_app_data(struct ecore_hwfn *p_hwfn, struct dcbx_app_priority_feature *p_app, struct dcbx_app_priority_entry *p_tbl, - struct ecore_dcbx_params *p_params) + struct ecore_dcbx_params *p_params, bool ieee) { + struct ecore_app_entry *entry; + u8 pri_map; int i; p_params->app_willing = ECORE_MFW_GET_FIELD(p_app->flags, DCBX_APP_WILLING); p_params->app_valid = ECORE_MFW_GET_FIELD(p_app->flags, DCBX_APP_ENABLED); + p_params->app_error = ECORE_MFW_GET_FIELD(p_app->flags, DCBX_APP_ERROR); p_params->num_app_entries = ECORE_MFW_GET_FIELD(p_app->flags, - DCBX_APP_ENABLED); - for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) - p_params->app_bitmap[i] = p_tbl[i].entry; + DCBX_APP_NUM_ENTRIES); + for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) { + entry = &p_params->app_entry[i]; + if (ieee) { + u8 sf_ieee; + u32 val; + + sf_ieee = ECORE_MFW_GET_FIELD(p_tbl[i].entry, + DCBX_APP_SF_IEEE); + switch (sf_ieee) { + case DCBX_APP_SF_IEEE_RESERVED: + /* Old MFW */ + val = ECORE_MFW_GET_FIELD(p_tbl[i].entry, + DCBX_APP_SF); + entry->sf_ieee = val ? + ECORE_DCBX_SF_IEEE_TCP_UDP_PORT : + ECORE_DCBX_SF_IEEE_ETHTYPE; + break; + case DCBX_APP_SF_IEEE_ETHTYPE: + entry->sf_ieee = ECORE_DCBX_SF_IEEE_ETHTYPE; + break; + case DCBX_APP_SF_IEEE_TCP_PORT: + entry->sf_ieee = ECORE_DCBX_SF_IEEE_TCP_PORT; + break; + case DCBX_APP_SF_IEEE_UDP_PORT: + entry->sf_ieee = ECORE_DCBX_SF_IEEE_UDP_PORT; + break; + case DCBX_APP_SF_IEEE_TCP_UDP_PORT: + entry->sf_ieee = + ECORE_DCBX_SF_IEEE_TCP_UDP_PORT; + break; + } + } else { + entry->ethtype = !(ECORE_MFW_GET_FIELD(p_tbl[i].entry, + DCBX_APP_SF)); + } + + pri_map = ECORE_MFW_GET_FIELD(p_tbl[i].entry, DCBX_APP_PRI_MAP); + ecore_dcbx_get_app_priority(pri_map, &entry->prio); + entry->proto_id = ECORE_MFW_GET_FIELD(p_tbl[i].entry, + DCBX_APP_PROTOCOL_ID); + ecore_dcbx_get_app_protocol_type(p_hwfn, p_tbl[i].entry, + entry->proto_id, + &entry->proto_type, ieee); + } DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, - "APP params: willing %d, valid %d\n", - p_params->app_willing, p_params->app_valid); + "APP params: willing %d, valid %d error = %d\n", + p_params->app_willing, p_params->app_valid, + p_params->app_error); } static void ecore_dcbx_get_pfc_data(struct ecore_hwfn *p_hwfn, u32 pfc, struct ecore_dcbx_params *p_params) { - p_params->pfc_willing = ECORE_MFW_GET_FIELD(pfc, DCBX_PFC_WILLING); - p_params->max_pfc_tc = ECORE_MFW_GET_FIELD(pfc, DCBX_PFC_CAPS); - p_params->pfc_enabled = ECORE_MFW_GET_FIELD(pfc, DCBX_PFC_ENABLED); - p_params->pfc_bitmap = pfc; + u8 pfc_map; + + p_params->pfc.willing = ECORE_MFW_GET_FIELD(pfc, DCBX_PFC_WILLING); + p_params->pfc.max_tc = ECORE_MFW_GET_FIELD(pfc, DCBX_PFC_CAPS); + p_params->pfc.enabled = ECORE_MFW_GET_FIELD(pfc, DCBX_PFC_ENABLED); + pfc_map = ECORE_MFW_GET_FIELD(pfc, DCBX_PFC_PRI_EN_BITMAP); + p_params->pfc.prio[0] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_0); + p_params->pfc.prio[1] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_1); + p_params->pfc.prio[2] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_2); + p_params->pfc.prio[3] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_3); + p_params->pfc.prio[4] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_4); + p_params->pfc.prio[5] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_5); + p_params->pfc.prio[6] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_6); + p_params->pfc.prio[7] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_7); DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "PFC params: willing %d, pfc_bitmap %d\n", - p_params->pfc_willing, p_params->pfc_bitmap); + p_params->pfc.willing, pfc_map); } static void @@ -421,28 +517,34 @@ ecore_dcbx_get_ets_data(struct ecore_hwfn *p_hwfn, struct dcbx_ets_feature *p_ets, struct ecore_dcbx_params *p_params) { + u32 bw_map[2], tsa_map[2], pri_map; int i; p_params->ets_willing = ECORE_MFW_GET_FIELD(p_ets->flags, DCBX_ETS_WILLING); p_params->ets_enabled = ECORE_MFW_GET_FIELD(p_ets->flags, DCBX_ETS_ENABLED); + p_params->ets_cbs = ECORE_MFW_GET_FIELD(p_ets->flags, DCBX_ETS_CBS); p_params->max_ets_tc = ECORE_MFW_GET_FIELD(p_ets->flags, DCBX_ETS_MAX_TCS); - p_params->ets_pri_tc_tbl[0] = p_ets->pri_tc_tbl[0]; - DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, - "ETS params: willing %d, pri_tc_tbl_0 %x max_ets_tc %d\n", - p_params->ets_willing, p_params->ets_pri_tc_tbl[0], - p_params->max_ets_tc); + "ETS params: willing %d, ets_cbs %d pri_tc_tbl_0 %x" + " max_ets_tc %d\n", + p_params->ets_willing, p_params->ets_cbs, + p_ets->pri_tc_tbl[0], p_params->max_ets_tc); /* 8 bit tsa and bw data corresponding to each of the 8 TC's are * encoded in a type u32 array of size 2. */ - for (i = 0; i < 2; i++) { - p_params->ets_tc_tsa_tbl[i] = p_ets->tc_tsa_tbl[i]; - p_params->ets_tc_bw_tbl[i] = p_ets->tc_bw_tbl[i]; - + bw_map[0] = OSAL_BE32_TO_CPU(p_ets->tc_bw_tbl[0]); + bw_map[1] = OSAL_BE32_TO_CPU(p_ets->tc_bw_tbl[1]); + tsa_map[0] = OSAL_BE32_TO_CPU(p_ets->tc_tsa_tbl[0]); + tsa_map[1] = OSAL_BE32_TO_CPU(p_ets->tc_tsa_tbl[1]); + pri_map = OSAL_BE32_TO_CPU(p_ets->pri_tc_tbl[0]); + for (i = 0; i < ECORE_MAX_PFC_PRIORITIES; i++) { + p_params->ets_tc_bw_tbl[i] = ((u8 *)bw_map)[i]; + p_params->ets_tc_tsa_tbl[i] = ((u8 *)tsa_map)[i]; + p_params->ets_pri_tc_tbl[i] = ECORE_DCBX_PRIO2TC(pri_map, i); DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "elem %d bw_tbl %x tsa_tbl %x\n", i, p_params->ets_tc_bw_tbl[i], @@ -455,9 +557,10 @@ ecore_dcbx_get_common_params(struct ecore_hwfn *p_hwfn, struct dcbx_app_priority_feature *p_app, struct dcbx_app_priority_entry *p_tbl, struct dcbx_ets_feature *p_ets, - u32 pfc, struct ecore_dcbx_params *p_params) + u32 pfc, struct ecore_dcbx_params *p_params, + bool ieee) { - ecore_dcbx_get_app_data(p_hwfn, p_app, p_tbl, p_params); + ecore_dcbx_get_app_data(p_hwfn, p_app, p_tbl, p_params, ieee); ecore_dcbx_get_ets_data(p_hwfn, p_ets, p_params); ecore_dcbx_get_pfc_data(p_hwfn, pfc, p_params); @@ -483,7 +586,8 @@ ecore_dcbx_get_local_params(struct ecore_hwfn *p_hwfn, p_ets = &p_hwfn->p_dcbx_info->local_admin.features.ets; pfc = p_hwfn->p_dcbx_info->local_admin.features.pfc; - ecore_dcbx_get_common_params(p_hwfn, p_app, p_tbl, p_ets, pfc, p_data); + ecore_dcbx_get_common_params(p_hwfn, p_app, p_tbl, p_ets, pfc, p_data, + false); p_local->valid = true; return ECORE_SUCCESS; @@ -508,7 +612,8 @@ ecore_dcbx_get_remote_params(struct ecore_hwfn *p_hwfn, p_ets = &p_hwfn->p_dcbx_info->remote.features.ets; pfc = p_hwfn->p_dcbx_info->remote.features.pfc; - ecore_dcbx_get_common_params(p_hwfn, p_app, p_tbl, p_ets, pfc, p_data); + ecore_dcbx_get_common_params(p_hwfn, p_app, p_tbl, p_ets, pfc, p_data, + false); p_remote->valid = true; return ECORE_SUCCESS; @@ -551,12 +656,15 @@ ecore_dcbx_get_operational_params(struct ecore_hwfn *p_hwfn, p_operational->ieee = ecore_dcbx_ieee(flags); p_operational->cee = ecore_dcbx_cee(flags); + p_operational->local = ecore_dcbx_local(flags); DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, - "Version support: ieee %d, cee %d\n", - p_operational->ieee, p_operational->cee); + "Version support: ieee %d, cee %d, static %d\n", + p_operational->ieee, p_operational->cee, + p_operational->local); - ecore_dcbx_get_common_params(p_hwfn, p_app, p_tbl, p_ets, pfc, p_data); + ecore_dcbx_get_common_params(p_hwfn, p_app, p_tbl, p_ets, pfc, p_data, + p_operational->ieee); ecore_dcbx_get_priority_info(p_hwfn, &p_operational->app_prio, p_results); err = ECORE_MFW_GET_FIELD(p_app->flags, DCBX_APP_ERROR); @@ -567,6 +675,35 @@ ecore_dcbx_get_operational_params(struct ecore_hwfn *p_hwfn, return rc; } +static enum _ecore_status_t +ecore_dcbx_get_dscp_params(struct ecore_hwfn *p_hwfn, + struct ecore_ptt *p_ptt, + struct ecore_dcbx_get *params) +{ + struct ecore_dcbx_dscp_params *p_dscp; + struct dcb_dscp_map *p_dscp_map; + int i, j, entry; + u32 pri_map; + + p_dscp = ¶ms->dscp; + p_dscp_map = &p_hwfn->p_dcbx_info->dscp_map; + p_dscp->enabled = ECORE_MFW_GET_FIELD(p_dscp_map->flags, + DCB_DSCP_ENABLE); + /* MFW encodes 64 dscp entries into 8 element array of u32 entries, + * where each entry holds the 4bit priority map for 8 dscp entries. + */ + for (i = 0, entry = 0; i < ECORE_DCBX_DSCP_SIZE / 8; i++) { + pri_map = OSAL_BE32_TO_CPU(p_dscp_map->dscp_pri_map[i]); + DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "elem %d pri_map 0x%x\n", + entry, pri_map); + for (j = 0; j < ECORE_DCBX_DSCP_SIZE / 8; j++, entry++) + p_dscp->dscp_pri_map[entry] = (u32)(pri_map >> + (j * 4)) & 0xf; + } + + return ECORE_SUCCESS; +} + static enum _ecore_status_t ecore_dcbx_get_local_lldp_params(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, @@ -668,6 +805,7 @@ ecore_dcbx_read_remote_lldp_mib(struct ecore_hwfn *p_hwfn, enum _ecore_status_t rc = ECORE_SUCCESS; struct ecore_dcbx_mib_meta_data data; + OSAL_MEM_ZERO(&data, sizeof(data)); data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port, lldp_status_params); data.lldp_remote = p_hwfn->p_dcbx_info->lldp_remote; @@ -685,6 +823,7 @@ ecore_dcbx_read_operational_mib(struct ecore_hwfn *p_hwfn, struct ecore_dcbx_mib_meta_data data; enum _ecore_status_t rc = ECORE_SUCCESS; + OSAL_MEM_ZERO(&data, sizeof(data)); data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port, operational_dcbx_mib); data.mib = &p_hwfn->p_dcbx_info->operational; @@ -702,6 +841,7 @@ ecore_dcbx_read_remote_mib(struct ecore_hwfn *p_hwfn, struct ecore_dcbx_mib_meta_data data; enum _ecore_status_t rc = ECORE_SUCCESS; + OSAL_MEM_ZERO(&data, sizeof(data)); data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port, remote_dcbx_mib); data.mib = &p_hwfn->p_dcbx_info->remote; @@ -727,6 +867,18 @@ ecore_dcbx_read_local_mib(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt) return rc; } +static void +ecore_dcbx_read_dscp_mib(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt) +{ + struct ecore_dcbx_mib_meta_data data; + + data.addr = p_hwfn->mcp_info->port_addr + + offsetof(struct public_port, dcb_dscp_map); + data.dscp_map = &p_hwfn->p_dcbx_info->dscp_map; + data.size = sizeof(struct dcb_dscp_map); + ecore_memcpy_from(p_hwfn, p_ptt, data.dscp_map, data.addr, data.size); +} + static enum _ecore_status_t ecore_dcbx_read_mib(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, enum ecore_mib_read_type type) @@ -735,6 +887,7 @@ static enum _ecore_status_t ecore_dcbx_read_mib(struct ecore_hwfn *p_hwfn, switch (type) { case ECORE_DCBX_OPERATIONAL_MIB: + ecore_dcbx_read_dscp_mib(p_hwfn, p_ptt); rc = ecore_dcbx_read_operational_mib(p_hwfn, p_ptt, type); break; case ECORE_DCBX_REMOTE_MIB: @@ -773,6 +926,9 @@ ecore_dcbx_mib_update_event(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, return rc; if (type == ECORE_DCBX_OPERATIONAL_MIB) { + ecore_dcbx_get_dscp_params(p_hwfn, p_ptt, + &p_hwfn->p_dcbx_info->get); + rc = ecore_dcbx_process_mib_info(p_hwfn); if (!rc) { bool enabled; @@ -793,6 +949,14 @@ ecore_dcbx_mib_update_event(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, } } ecore_dcbx_get_params(p_hwfn, p_ptt, type); + + /* Update the DSCP to TC mapping bit if required */ + if ((type == ECORE_DCBX_OPERATIONAL_MIB) && + p_hwfn->p_dcbx_info->dscp_nig_update) { + ecore_wr(p_hwfn, p_ptt, NIG_REG_DSCP_TO_TC_MAP_ENABLE, 0x1); + p_hwfn->p_dcbx_info->dscp_nig_update = false; + } + OSAL_DCBX_AEN(p_hwfn, type); return rc; @@ -826,6 +990,8 @@ static void ecore_dcbx_update_protocol_data(struct protocol_dcb_data *p_data, p_data->dcb_enable_flag = p_src->arr[type].enable; p_data->dcb_priority = p_src->arr[type].priority; p_data->dcb_tc = p_src->arr[type].tc; + p_data->dscp_enable_flag = p_src->arr[type].dscp_enable; + p_data->dscp_val = p_src->arr[type].dscp_val; } /* Set pf update ramrod command params */ @@ -833,7 +999,7 @@ void ecore_dcbx_set_pf_update_params(struct ecore_dcbx_results *p_src, struct pf_update_ramrod_data *p_dest) { struct protocol_dcb_data *p_dcb_data; - bool update_flag; + bool update_flag = false; p_dest->pf_id = p_src->pf_id; @@ -885,3 +1051,302 @@ enum _ecore_status_t ecore_dcbx_query_params(struct ecore_hwfn *p_hwfn, return rc; } + +static void +ecore_dcbx_set_pfc_data(struct ecore_hwfn *p_hwfn, + u32 *pfc, struct ecore_dcbx_params *p_params) +{ + u8 pfc_map = 0; + int i; + + if (p_params->pfc.willing) + *pfc |= DCBX_PFC_WILLING_MASK; + else + *pfc &= ~DCBX_PFC_WILLING_MASK; + + if (p_params->pfc.enabled) + *pfc |= DCBX_PFC_ENABLED_MASK; + else + *pfc &= ~DCBX_PFC_ENABLED_MASK; + + *pfc &= ~DCBX_PFC_CAPS_MASK; + *pfc |= (u32)p_params->pfc.max_tc << DCBX_PFC_CAPS_SHIFT; + + for (i = 0; i < ECORE_MAX_PFC_PRIORITIES; i++) + if (p_params->pfc.prio[i]) + pfc_map |= (0x1 << i); + + *pfc |= (pfc_map << DCBX_PFC_PRI_EN_BITMAP_SHIFT); + + DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "pfc = 0x%x\n", *pfc); +} + +static void +ecore_dcbx_set_ets_data(struct ecore_hwfn *p_hwfn, + struct dcbx_ets_feature *p_ets, + struct ecore_dcbx_params *p_params) +{ + u8 *bw_map, *tsa_map; + int i; + + if (p_params->ets_willing) + p_ets->flags |= DCBX_ETS_WILLING_MASK; + else + p_ets->flags &= ~DCBX_ETS_WILLING_MASK; + + if (p_params->ets_cbs) + p_ets->flags |= DCBX_ETS_CBS_MASK; + else + p_ets->flags &= ~DCBX_ETS_CBS_MASK; + + if (p_params->ets_enabled) + p_ets->flags |= DCBX_ETS_ENABLED_MASK; + else + p_ets->flags &= ~DCBX_ETS_ENABLED_MASK; + + p_ets->flags &= ~DCBX_ETS_MAX_TCS_MASK; + p_ets->flags |= (u32)p_params->max_ets_tc << DCBX_ETS_MAX_TCS_SHIFT; + + bw_map = (u8 *)&p_ets->tc_bw_tbl[0]; + tsa_map = (u8 *)&p_ets->tc_tsa_tbl[0]; + p_ets->pri_tc_tbl[0] = 0; + for (i = 0; i < ECORE_MAX_PFC_PRIORITIES; i++) { + bw_map[i] = p_params->ets_tc_bw_tbl[i]; + tsa_map[i] = p_params->ets_tc_tsa_tbl[i]; + p_ets->pri_tc_tbl[0] |= (((u32)p_params->ets_pri_tc_tbl[i]) << + ((7 - i) * 4)); + } + p_ets->pri_tc_tbl[0] = OSAL_CPU_TO_BE32(p_ets->pri_tc_tbl[0]); + for (i = 0; i < 2; i++) { + p_ets->tc_bw_tbl[i] = OSAL_CPU_TO_BE32(p_ets->tc_bw_tbl[i]); + p_ets->tc_tsa_tbl[i] = OSAL_CPU_TO_BE32(p_ets->tc_tsa_tbl[i]); + } +} + +static void +ecore_dcbx_set_app_data(struct ecore_hwfn *p_hwfn, + struct dcbx_app_priority_feature *p_app, + struct ecore_dcbx_params *p_params, bool ieee) +{ + u32 *entry; + int i; + + if (p_params->app_willing) + p_app->flags |= DCBX_APP_WILLING_MASK; + else + p_app->flags &= ~DCBX_APP_WILLING_MASK; + + if (p_params->app_valid) + p_app->flags |= DCBX_APP_ENABLED_MASK; + else + p_app->flags &= ~DCBX_APP_ENABLED_MASK; + + p_app->flags &= ~DCBX_APP_NUM_ENTRIES_MASK; + p_app->flags |= (u32)p_params->num_app_entries << + DCBX_APP_NUM_ENTRIES_SHIFT; + + for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) { + entry = &p_app->app_pri_tbl[i].entry; + if (ieee) { + *entry &= ~DCBX_APP_SF_IEEE_MASK; + switch (p_params->app_entry[i].sf_ieee) { + case ECORE_DCBX_SF_IEEE_ETHTYPE: + *entry |= ((u32)DCBX_APP_SF_IEEE_ETHTYPE << + DCBX_APP_SF_IEEE_SHIFT); + break; + case ECORE_DCBX_SF_IEEE_TCP_PORT: + *entry |= ((u32)DCBX_APP_SF_IEEE_TCP_PORT << + DCBX_APP_SF_IEEE_SHIFT); + break; + case ECORE_DCBX_SF_IEEE_UDP_PORT: + *entry |= ((u32)DCBX_APP_SF_IEEE_UDP_PORT << + DCBX_APP_SF_IEEE_SHIFT); + break; + case ECORE_DCBX_SF_IEEE_TCP_UDP_PORT: + *entry |= (u32)DCBX_APP_SF_IEEE_TCP_UDP_PORT << + DCBX_APP_SF_IEEE_SHIFT; + break; + } + } else { + *entry &= ~DCBX_APP_SF_MASK; + if (p_params->app_entry[i].ethtype) + *entry |= ((u32)DCBX_APP_SF_ETHTYPE << + DCBX_APP_SF_SHIFT); + else + *entry |= ((u32)DCBX_APP_SF_PORT << + DCBX_APP_SF_SHIFT); + } + *entry &= ~DCBX_APP_PROTOCOL_ID_MASK; + *entry |= ((u32)p_params->app_entry[i].proto_id << + DCBX_APP_PROTOCOL_ID_SHIFT); + *entry &= ~DCBX_APP_PRI_MAP_MASK; + *entry |= ((u32)(p_params->app_entry[i].prio) << + DCBX_APP_PRI_MAP_SHIFT); + } +} + +static enum _ecore_status_t +ecore_dcbx_set_local_params(struct ecore_hwfn *p_hwfn, + struct dcbx_local_params *local_admin, + struct ecore_dcbx_set *params) +{ + bool ieee = false; + + local_admin->flags = 0; + OSAL_MEMCPY(&local_admin->features, + &p_hwfn->p_dcbx_info->operational.features, + sizeof(struct dcbx_features)); + + if (params->enabled) { + local_admin->config = params->ver_num; + ieee = !!(params->ver_num & DCBX_CONFIG_VERSION_IEEE); + } else { + local_admin->config = DCBX_CONFIG_VERSION_DISABLED; + } + + if (params->override_flags & ECORE_DCBX_OVERRIDE_PFC_CFG) + ecore_dcbx_set_pfc_data(p_hwfn, &local_admin->features.pfc, + ¶ms->config.params); + + if (params->override_flags & ECORE_DCBX_OVERRIDE_ETS_CFG) + ecore_dcbx_set_ets_data(p_hwfn, &local_admin->features.ets, + ¶ms->config.params); + + if (params->override_flags & ECORE_DCBX_OVERRIDE_APP_CFG) + ecore_dcbx_set_app_data(p_hwfn, &local_admin->features.app, + ¶ms->config.params, ieee); + + return ECORE_SUCCESS; +} + +static enum _ecore_status_t +ecore_dcbx_set_dscp_params(struct ecore_hwfn *p_hwfn, + struct dcb_dscp_map *p_dscp_map, + struct ecore_dcbx_set *p_params) +{ + int entry, i, j; + u32 val; + + OSAL_MEMCPY(p_dscp_map, &p_hwfn->p_dcbx_info->dscp_map, + sizeof(*p_dscp_map)); + + if (p_params->dscp.enabled) + p_dscp_map->flags |= DCB_DSCP_ENABLE_MASK; + else + p_dscp_map->flags &= ~DCB_DSCP_ENABLE_MASK; + + for (i = 0, entry = 0; i < 8; i++) { + val = 0; + for (j = 0; j < 8; j++, entry++) + val |= (((u32)p_params->dscp.dscp_pri_map[entry]) << + (j * 4)); + + p_dscp_map->dscp_pri_map[i] = OSAL_CPU_TO_BE32(val); + } + + p_hwfn->p_dcbx_info->dscp_nig_update = true; + + return ECORE_SUCCESS; +} + +enum _ecore_status_t ecore_dcbx_config_params(struct ecore_hwfn *p_hwfn, + struct ecore_ptt *p_ptt, + struct ecore_dcbx_set *params, + bool hw_commit) +{ + enum _ecore_status_t rc = ECORE_SUCCESS; + struct ecore_dcbx_mib_meta_data data; + struct dcbx_local_params local_admin; + struct dcb_dscp_map dscp_map; + u32 resp = 0, param = 0; + + if (!hw_commit) { + OSAL_MEMCPY(&p_hwfn->p_dcbx_info->set, params, + sizeof(struct ecore_dcbx_set)); + return ECORE_SUCCESS; + } + + /* clear set-parmas cache */ + OSAL_MEMSET(&p_hwfn->p_dcbx_info->set, 0, + sizeof(struct ecore_dcbx_set)); + + OSAL_MEMSET(&local_admin, 0, sizeof(local_admin)); + ecore_dcbx_set_local_params(p_hwfn, &local_admin, params); + + data.addr = p_hwfn->mcp_info->port_addr + + offsetof(struct public_port, local_admin_dcbx_mib); + data.local_admin = &local_admin; + data.size = sizeof(struct dcbx_local_params); + ecore_memcpy_to(p_hwfn, p_ptt, data.addr, data.local_admin, data.size); + + if (params->override_flags & ECORE_DCBX_OVERRIDE_DSCP_CFG) { + OSAL_MEMSET(&dscp_map, 0, sizeof(dscp_map)); + ecore_dcbx_set_dscp_params(p_hwfn, &dscp_map, params); + + data.addr = p_hwfn->mcp_info->port_addr + + offsetof(struct public_port, dcb_dscp_map); + data.dscp_map = &dscp_map; + data.size = sizeof(struct dcb_dscp_map); + ecore_memcpy_to(p_hwfn, p_ptt, data.addr, data.dscp_map, + data.size); + } + + rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_DCBX, + 1 << DRV_MB_PARAM_LLDP_SEND_SHIFT, &resp, ¶m); + if (rc != ECORE_SUCCESS) { + DP_NOTICE(p_hwfn, false, + "Failed to send DCBX update request\n"); + return rc; + } + + return rc; +} + +enum _ecore_status_t ecore_dcbx_get_config_params(struct ecore_hwfn *p_hwfn, + struct ecore_dcbx_set *params) +{ + struct ecore_dcbx_get *dcbx_info; + int rc; + + if (p_hwfn->p_dcbx_info->set.config.valid) { + OSAL_MEMCPY(params, &p_hwfn->p_dcbx_info->set, + sizeof(struct ecore_dcbx_set)); + return ECORE_SUCCESS; + } + + dcbx_info = OSAL_ALLOC(p_hwfn->p_dev, GFP_KERNEL, + sizeof(struct ecore_dcbx_get)); + if (!dcbx_info) { + DP_ERR(p_hwfn, "Failed to allocate struct ecore_dcbx_info\n"); + return ECORE_NOMEM; + } + + rc = ecore_dcbx_query_params(p_hwfn, dcbx_info, + ECORE_DCBX_OPERATIONAL_MIB); + if (rc) { + OSAL_FREE(p_hwfn->p_dev, dcbx_info); + return rc; + } + p_hwfn->p_dcbx_info->set.override_flags = 0; + + p_hwfn->p_dcbx_info->set.ver_num = DCBX_CONFIG_VERSION_DISABLED; + if (dcbx_info->operational.cee) + p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_CEE; + if (dcbx_info->operational.ieee) + p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_IEEE; + if (dcbx_info->operational.local) + p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_STATIC; + + p_hwfn->p_dcbx_info->set.enabled = dcbx_info->operational.enabled; + OSAL_MEMCPY(&p_hwfn->p_dcbx_info->set.config.params, + &dcbx_info->operational.params, + sizeof(struct ecore_dcbx_admin_params)); + p_hwfn->p_dcbx_info->set.config.valid = true; + + OSAL_MEMCPY(params, &p_hwfn->p_dcbx_info->set, + sizeof(struct ecore_dcbx_set)); + + OSAL_FREE(p_hwfn->p_dev, dcbx_info); + + return ECORE_SUCCESS; +}