net/ice/base: update boost TCAM for DVM
Add code to update boost TCAM entries to enable DVM. This requires enabled DVM entries, and disabling SVM entries. Signed-off-by: Dan Nowlin <dan.nowlin@intel.com> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com> Acked-by: Qiming Yang <qiming.yang@intel.com>
This commit is contained in:
parent
c2b328a4ed
commit
f977165db0
@ -7,9 +7,17 @@
|
||||
#include "ice_protocol_type.h"
|
||||
#include "ice_flow.h"
|
||||
|
||||
/* For supporting double VLAN mode, it is necessary to enable or disable certain
|
||||
* boost tcam entries. The metadata labels names that match the following
|
||||
* prefixes will be saved to allow enabling double VLAN mode.
|
||||
*/
|
||||
#define ICE_DVM_PRE "BOOST_MAC_VLAN_DVM" /* enable these entries */
|
||||
#define ICE_SVM_PRE "BOOST_MAC_VLAN_SVM" /* disable these entries */
|
||||
|
||||
/* To support tunneling entries by PF, the package will append the PF number to
|
||||
* the label; for example TNL_VXLAN_PF0, TNL_VXLAN_PF1, TNL_VXLAN_PF2, etc.
|
||||
*/
|
||||
#define ICE_TNL_PRE "TNL_"
|
||||
static const struct ice_tunnel_type_scan tnls[] = {
|
||||
{ TNL_VXLAN, "TNL_VXLAN_PF" },
|
||||
{ TNL_GENEVE, "TNL_GENEVE_PF" },
|
||||
@ -531,6 +539,57 @@ ice_enum_labels(struct ice_seg *ice_seg, u32 type, struct ice_pkg_enum *state,
|
||||
return label->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_add_tunnel_hint
|
||||
* @hw: pointer to the HW structure
|
||||
* @label_name: label text
|
||||
* @val: value of the tunnel port boost entry
|
||||
*/
|
||||
static void ice_add_tunnel_hint(struct ice_hw *hw, char *label_name, u16 val)
|
||||
{
|
||||
if (hw->tnl.count < ICE_TUNNEL_MAX_ENTRIES) {
|
||||
u16 i;
|
||||
|
||||
for (i = 0; tnls[i].type != TNL_LAST; i++) {
|
||||
size_t len = strlen(tnls[i].label_prefix);
|
||||
|
||||
/* Look for matching label start, before continuing */
|
||||
if (strncmp(label_name, tnls[i].label_prefix, len))
|
||||
continue;
|
||||
|
||||
/* Make sure this label matches our PF. Note that the PF
|
||||
* character ('0' - '7') will be located where our
|
||||
* prefix string's null terminator is located.
|
||||
*/
|
||||
if ((label_name[len] - '0') == hw->pf_id) {
|
||||
hw->tnl.tbl[hw->tnl.count].type = tnls[i].type;
|
||||
hw->tnl.tbl[hw->tnl.count].valid = false;
|
||||
hw->tnl.tbl[hw->tnl.count].in_use = false;
|
||||
hw->tnl.tbl[hw->tnl.count].marked = false;
|
||||
hw->tnl.tbl[hw->tnl.count].boost_addr = val;
|
||||
hw->tnl.tbl[hw->tnl.count].port = 0;
|
||||
hw->tnl.count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_add_dvm_hint
|
||||
* @hw: pointer to the HW structure
|
||||
* @val: value of the boost entry
|
||||
* @enable: true if entry needs to be enabled, or false if needs to be disabled
|
||||
*/
|
||||
static void ice_add_dvm_hint(struct ice_hw *hw, u16 val, bool enable)
|
||||
{
|
||||
if (hw->dvm_upd.count < ICE_DVM_MAX_ENTRIES) {
|
||||
hw->dvm_upd.tbl[hw->dvm_upd.count].boost_addr = val;
|
||||
hw->dvm_upd.tbl[hw->dvm_upd.count].enable = enable;
|
||||
hw->dvm_upd.count++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_init_pkg_hints
|
||||
* @hw: pointer to the HW structure
|
||||
@ -557,40 +616,34 @@ static void ice_init_pkg_hints(struct ice_hw *hw, struct ice_seg *ice_seg)
|
||||
label_name = ice_enum_labels(ice_seg, ICE_SID_LBL_RXPARSER_TMEM, &state,
|
||||
&val);
|
||||
|
||||
while (label_name && hw->tnl.count < ICE_TUNNEL_MAX_ENTRIES) {
|
||||
for (i = 0; tnls[i].type != TNL_LAST; i++) {
|
||||
size_t len = strlen(tnls[i].label_prefix);
|
||||
while (label_name) {
|
||||
if (!strncmp(label_name, ICE_TNL_PRE, strlen(ICE_TNL_PRE)))
|
||||
/* check for a tunnel entry */
|
||||
ice_add_tunnel_hint(hw, label_name, val);
|
||||
|
||||
/* Look for matching label start, before continuing */
|
||||
if (strncmp(label_name, tnls[i].label_prefix, len))
|
||||
continue;
|
||||
/* check for a dvm mode entry */
|
||||
else if (!strncmp(label_name, ICE_DVM_PRE, strlen(ICE_DVM_PRE)))
|
||||
ice_add_dvm_hint(hw, val, true);
|
||||
|
||||
/* Make sure this label matches our PF. Note that the PF
|
||||
* character ('0' - '7') will be located where our
|
||||
* prefix string's null terminator is located.
|
||||
*/
|
||||
if ((label_name[len] - '0') == hw->pf_id) {
|
||||
hw->tnl.tbl[hw->tnl.count].type = tnls[i].type;
|
||||
hw->tnl.tbl[hw->tnl.count].valid = false;
|
||||
hw->tnl.tbl[hw->tnl.count].in_use = false;
|
||||
hw->tnl.tbl[hw->tnl.count].marked = false;
|
||||
hw->tnl.tbl[hw->tnl.count].boost_addr = val;
|
||||
hw->tnl.tbl[hw->tnl.count].port = 0;
|
||||
hw->tnl.count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* check for a svm mode entry */
|
||||
else if (!strncmp(label_name, ICE_SVM_PRE, strlen(ICE_SVM_PRE)))
|
||||
ice_add_dvm_hint(hw, val, false);
|
||||
|
||||
label_name = ice_enum_labels(NULL, 0, &state, &val);
|
||||
}
|
||||
|
||||
/* Cache the appropriate boost TCAM entry pointers */
|
||||
/* Cache the appropriate boost TCAM entry pointers for tunnels */
|
||||
for (i = 0; i < hw->tnl.count; i++) {
|
||||
ice_find_boost_entry(ice_seg, hw->tnl.tbl[i].boost_addr,
|
||||
&hw->tnl.tbl[i].boost_entry);
|
||||
if (hw->tnl.tbl[i].boost_entry)
|
||||
hw->tnl.tbl[i].valid = true;
|
||||
}
|
||||
|
||||
/* Cache the appropriate boost TCAM entry pointers for DVM and SVM */
|
||||
for (i = 0; i < hw->dvm_upd.count; i++)
|
||||
ice_find_boost_entry(ice_seg, hw->dvm_upd.tbl[i].boost_addr,
|
||||
&hw->dvm_upd.tbl[i].boost_entry);
|
||||
}
|
||||
|
||||
/* Key creation */
|
||||
@ -994,6 +1047,36 @@ ice_find_seg_in_pkg(struct ice_hw *hw, u32 seg_type,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_update_pkg_no_lock
|
||||
* @hw: pointer to the hardware structure
|
||||
* @bufs: pointer to an array of buffers
|
||||
* @count: the number of buffers in the array
|
||||
*/
|
||||
static enum ice_status
|
||||
ice_update_pkg_no_lock(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
|
||||
{
|
||||
enum ice_status status = ICE_SUCCESS;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
struct ice_buf_hdr *bh = (struct ice_buf_hdr *)(bufs + i);
|
||||
bool last = ((i + 1) == count);
|
||||
u32 offset, info;
|
||||
|
||||
status = ice_aq_update_pkg(hw, bh, LE16_TO_CPU(bh->data_end),
|
||||
last, &offset, &info, NULL);
|
||||
|
||||
if (status) {
|
||||
ice_debug(hw, ICE_DBG_PKG, "Update pkg failed: err %d off %d inf %d\n",
|
||||
status, offset, info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_update_pkg
|
||||
* @hw: pointer to the hardware structure
|
||||
@ -1006,25 +1089,12 @@ enum ice_status
|
||||
ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
|
||||
{
|
||||
enum ice_status status;
|
||||
u32 offset, info, i;
|
||||
|
||||
status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
struct ice_buf_hdr *bh = (struct ice_buf_hdr *)(bufs + i);
|
||||
bool last = ((i + 1) == count);
|
||||
|
||||
status = ice_aq_update_pkg(hw, bh, LE16_TO_CPU(bh->data_end),
|
||||
last, &offset, &info, NULL);
|
||||
|
||||
if (status) {
|
||||
ice_debug(hw, ICE_DBG_PKG, "Update pkg failed: err %d off %d inf %d\n",
|
||||
status, offset, info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
status = ice_update_pkg_no_lock(hw, bufs, count);
|
||||
|
||||
ice_release_change_lock(hw);
|
||||
|
||||
@ -2202,6 +2272,93 @@ ice_get_open_tunnel_port(struct ice_hw *hw, enum ice_tunnel_type type,
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_upd_dvm_boost_entry
|
||||
* @hw: pointer to the HW structure
|
||||
* @entry: pointer to double vlan boost entry info
|
||||
*/
|
||||
static enum ice_status
|
||||
ice_upd_dvm_boost_entry(struct ice_hw *hw, struct ice_dvm_entry *entry)
|
||||
{
|
||||
struct ice_boost_tcam_section *sect_rx, *sect_tx;
|
||||
enum ice_status status = ICE_ERR_MAX_LIMIT;
|
||||
struct ice_buf_build *bld;
|
||||
u8 val, dc, nm;
|
||||
|
||||
bld = ice_pkg_buf_alloc(hw);
|
||||
if (!bld)
|
||||
return ICE_ERR_NO_MEMORY;
|
||||
|
||||
/* allocate 2 sections, one for Rx parser, one for Tx parser */
|
||||
if (ice_pkg_buf_reserve_section(bld, 2))
|
||||
goto ice_upd_dvm_boost_entry_err;
|
||||
|
||||
sect_rx = (struct ice_boost_tcam_section *)
|
||||
ice_pkg_buf_alloc_section(bld, ICE_SID_RXPARSER_BOOST_TCAM,
|
||||
ice_struct_size(sect_rx, tcam, 1));
|
||||
if (!sect_rx)
|
||||
goto ice_upd_dvm_boost_entry_err;
|
||||
sect_rx->count = CPU_TO_LE16(1);
|
||||
|
||||
sect_tx = (struct ice_boost_tcam_section *)
|
||||
ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM,
|
||||
ice_struct_size(sect_tx, tcam, 1));
|
||||
if (!sect_tx)
|
||||
goto ice_upd_dvm_boost_entry_err;
|
||||
sect_tx->count = CPU_TO_LE16(1);
|
||||
|
||||
/* copy original boost entry to update package buffer */
|
||||
ice_memcpy(sect_rx->tcam, entry->boost_entry, sizeof(*sect_rx->tcam),
|
||||
ICE_NONDMA_TO_NONDMA);
|
||||
|
||||
/* re-write the don't care and never match bits accordingly */
|
||||
if (entry->enable) {
|
||||
/* all bits are don't care */
|
||||
val = 0x00;
|
||||
dc = 0xFF;
|
||||
nm = 0x00;
|
||||
} else {
|
||||
/* disable, one never match bit, the rest are don't care */
|
||||
val = 0x00;
|
||||
dc = 0xF7;
|
||||
nm = 0x08;
|
||||
}
|
||||
|
||||
ice_set_key((u8 *)§_rx->tcam[0].key, sizeof(sect_rx->tcam[0].key),
|
||||
&val, NULL, &dc, &nm, 0, sizeof(u8));
|
||||
|
||||
/* exact copy of entry to Tx section entry */
|
||||
ice_memcpy(sect_tx->tcam, sect_rx->tcam, sizeof(*sect_tx->tcam),
|
||||
ICE_NONDMA_TO_NONDMA);
|
||||
|
||||
status = ice_update_pkg_no_lock(hw, ice_pkg_buf(bld), 1);
|
||||
|
||||
ice_upd_dvm_boost_entry_err:
|
||||
ice_pkg_buf_free(hw, bld);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_set_dvm_boost_entries
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Enable double vlan by updating the appropriate boost tcam entries.
|
||||
*/
|
||||
enum ice_status ice_set_dvm_boost_entries(struct ice_hw *hw)
|
||||
{
|
||||
enum ice_status status;
|
||||
u16 i;
|
||||
|
||||
for (i = 0; i < hw->dvm_upd.count; i++) {
|
||||
status = ice_upd_dvm_boost_entry(hw, &hw->dvm_upd.tbl[i]);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return ICE_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_create_tunnel
|
||||
* @hw: pointer to the HW structure
|
||||
|
@ -49,6 +49,7 @@ ice_get_open_tunnel_port(struct ice_hw *hw, enum ice_tunnel_type type,
|
||||
u16 *port);
|
||||
enum ice_status
|
||||
ice_create_tunnel(struct ice_hw *hw, enum ice_tunnel_type type, u16 port);
|
||||
enum ice_status ice_set_dvm_boost_entries(struct ice_hw *hw);
|
||||
enum ice_status ice_destroy_tunnel(struct ice_hw *hw, u16 port, bool all);
|
||||
bool ice_tunnel_port_in_use(struct ice_hw *hw, u16 port, u16 *index);
|
||||
bool
|
||||
|
@ -675,6 +675,19 @@ struct ice_tunnel_table {
|
||||
u16 count;
|
||||
};
|
||||
|
||||
struct ice_dvm_entry {
|
||||
u16 boost_addr;
|
||||
u16 enable;
|
||||
struct ice_boost_tcam_entry *boost_entry;
|
||||
};
|
||||
|
||||
#define ICE_DVM_MAX_ENTRIES 48
|
||||
|
||||
struct ice_dvm_table {
|
||||
struct ice_dvm_entry tbl[ICE_DVM_MAX_ENTRIES];
|
||||
u16 count;
|
||||
};
|
||||
|
||||
struct ice_pkg_es {
|
||||
__le16 count;
|
||||
__le16 offset;
|
||||
|
@ -992,6 +992,8 @@ struct ice_hw {
|
||||
/* tunneling info */
|
||||
struct ice_lock tnl_lock;
|
||||
struct ice_tunnel_table tnl;
|
||||
/* dvm boost update information */
|
||||
struct ice_dvm_table dvm_upd;
|
||||
|
||||
struct ice_acl_tbl *acl_tbl;
|
||||
struct ice_fd_hw_prof **acl_prof;
|
||||
|
@ -312,6 +312,13 @@ static enum ice_status ice_set_dvm(struct ice_hw *hw)
|
||||
return status;
|
||||
}
|
||||
|
||||
status = ice_set_dvm_boost_entries(hw);
|
||||
if (status) {
|
||||
ice_debug(hw, ICE_DBG_INIT, "Failed to set boost TCAM entries for double VLAN mode, status %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
return ICE_SUCCESS;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user