Merge branch 'mlxsw-fixes'
Ido Schimmel says: ==================== mlxsw: Various fixes This patchset contains small fixes in mlxsw and one fix in the bridge driver. Patches #1-#4 perform small adjustments in PCI and FID code following recent tests that were performed on the Spectrum-2 ASIC. Patch #5 fixes the bridge driver to mark FDB entries that were added by user as such. Otherwise, these entries will be ignored by underlying switch drivers. Patch #6 fixes a long standing issue in mlxsw where the driver incorrectly programmed static FDB entries as both static and sticky. Patches #7-#8 add test cases for above mentioned bugs. Please consider patches #1, #2 and #4 for stable. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
efa8c819a6
|
@ -604,29 +604,31 @@ static void mlxsw_pci_cq_tasklet(unsigned long data)
|
|||
u16 wqe_counter = mlxsw_pci_cqe_wqe_counter_get(cqe);
|
||||
u8 sendq = mlxsw_pci_cqe_sr_get(q->u.cq.v, cqe);
|
||||
u8 dqn = mlxsw_pci_cqe_dqn_get(q->u.cq.v, cqe);
|
||||
char ncqe[MLXSW_PCI_CQE_SIZE_MAX];
|
||||
|
||||
memcpy(ncqe, cqe, q->elem_size);
|
||||
mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
|
||||
|
||||
if (sendq) {
|
||||
struct mlxsw_pci_queue *sdq;
|
||||
|
||||
sdq = mlxsw_pci_sdq_get(mlxsw_pci, dqn);
|
||||
mlxsw_pci_cqe_sdq_handle(mlxsw_pci, sdq,
|
||||
wqe_counter, cqe);
|
||||
wqe_counter, ncqe);
|
||||
q->u.cq.comp_sdq_count++;
|
||||
} else {
|
||||
struct mlxsw_pci_queue *rdq;
|
||||
|
||||
rdq = mlxsw_pci_rdq_get(mlxsw_pci, dqn);
|
||||
mlxsw_pci_cqe_rdq_handle(mlxsw_pci, rdq,
|
||||
wqe_counter, q->u.cq.v, cqe);
|
||||
wqe_counter, q->u.cq.v, ncqe);
|
||||
q->u.cq.comp_rdq_count++;
|
||||
}
|
||||
if (++items == credits)
|
||||
break;
|
||||
}
|
||||
if (items) {
|
||||
mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
|
||||
if (items)
|
||||
mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q);
|
||||
}
|
||||
}
|
||||
|
||||
static u16 mlxsw_pci_cq_elem_count(const struct mlxsw_pci_queue *q)
|
||||
|
@ -1365,10 +1367,10 @@ static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
|
|||
u32 val = mlxsw_pci_read32(mlxsw_pci, FW_READY);
|
||||
|
||||
if ((val & MLXSW_PCI_FW_READY_MASK) == MLXSW_PCI_FW_READY_MAGIC)
|
||||
break;
|
||||
return 0;
|
||||
cond_resched();
|
||||
} while (time_before(jiffies, end));
|
||||
return 0;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static int mlxsw_pci_alloc_irq_vectors(struct mlxsw_pci *mlxsw_pci)
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#define MLXSW_PCI_SW_RESET 0xF0010
|
||||
#define MLXSW_PCI_SW_RESET_RST_BIT BIT(0)
|
||||
#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 5000
|
||||
#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 13000
|
||||
#define MLXSW_PCI_SW_RESET_WAIT_MSECS 100
|
||||
#define MLXSW_PCI_FW_READY 0xA1844
|
||||
#define MLXSW_PCI_FW_READY_MASK 0xFFFF
|
||||
|
@ -53,6 +53,7 @@
|
|||
#define MLXSW_PCI_WQE_SIZE 32 /* 32 bytes per element */
|
||||
#define MLXSW_PCI_CQE01_SIZE 16 /* 16 bytes per element */
|
||||
#define MLXSW_PCI_CQE2_SIZE 32 /* 32 bytes per element */
|
||||
#define MLXSW_PCI_CQE_SIZE_MAX MLXSW_PCI_CQE2_SIZE
|
||||
#define MLXSW_PCI_EQE_SIZE 16 /* 16 bytes per element */
|
||||
#define MLXSW_PCI_WQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE)
|
||||
#define MLXSW_PCI_CQE01_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE01_SIZE)
|
||||
|
|
|
@ -997,8 +997,8 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
|
|||
static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = {
|
||||
.type = MLXSW_SP_FID_TYPE_DUMMY,
|
||||
.fid_size = sizeof(struct mlxsw_sp_fid),
|
||||
.start_index = MLXSW_SP_RFID_BASE - 1,
|
||||
.end_index = MLXSW_SP_RFID_BASE - 1,
|
||||
.start_index = VLAN_N_VID - 1,
|
||||
.end_index = VLAN_N_VID - 1,
|
||||
.ops = &mlxsw_sp_fid_dummy_ops,
|
||||
};
|
||||
|
||||
|
|
|
@ -1233,7 +1233,7 @@ mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
|
|||
static enum mlxsw_reg_sfd_rec_policy mlxsw_sp_sfd_rec_policy(bool dynamic)
|
||||
{
|
||||
return dynamic ? MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS :
|
||||
MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY;
|
||||
MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_MLAG;
|
||||
}
|
||||
|
||||
static enum mlxsw_reg_sfd_op mlxsw_sp_sfd_op(bool adding)
|
||||
|
@ -1290,7 +1290,7 @@ static int mlxsw_sp_port_fdb_tunnel_uc_op(struct mlxsw_sp *mlxsw_sp,
|
|||
static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
|
||||
const char *mac, u16 fid, bool adding,
|
||||
enum mlxsw_reg_sfd_rec_action action,
|
||||
bool dynamic)
|
||||
enum mlxsw_reg_sfd_rec_policy policy)
|
||||
{
|
||||
char *sfd_pl;
|
||||
u8 num_rec;
|
||||
|
@ -1301,8 +1301,7 @@ static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
|
|||
return -ENOMEM;
|
||||
|
||||
mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
|
||||
mlxsw_reg_sfd_uc_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic),
|
||||
mac, fid, action, local_port);
|
||||
mlxsw_reg_sfd_uc_pack(sfd_pl, 0, policy, mac, fid, action, local_port);
|
||||
num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
|
||||
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
|
||||
if (err)
|
||||
|
@ -1321,7 +1320,8 @@ static int mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
|
|||
bool dynamic)
|
||||
{
|
||||
return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid, adding,
|
||||
MLXSW_REG_SFD_REC_ACTION_NOP, dynamic);
|
||||
MLXSW_REG_SFD_REC_ACTION_NOP,
|
||||
mlxsw_sp_sfd_rec_policy(dynamic));
|
||||
}
|
||||
|
||||
int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
|
||||
|
@ -1329,7 +1329,7 @@ int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
|
|||
{
|
||||
return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, 0, mac, fid, adding,
|
||||
MLXSW_REG_SFD_REC_ACTION_FORWARD_IP_ROUTER,
|
||||
false);
|
||||
MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id,
|
||||
|
|
|
@ -1128,6 +1128,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
|
|||
err = -ENOMEM;
|
||||
goto err_unlock;
|
||||
}
|
||||
if (swdev_notify)
|
||||
fdb->added_by_user = 1;
|
||||
fdb->added_by_external_learn = 1;
|
||||
fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
|
||||
} else {
|
||||
|
@ -1147,6 +1149,9 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
|
|||
modified = true;
|
||||
}
|
||||
|
||||
if (swdev_notify)
|
||||
fdb->added_by_user = 1;
|
||||
|
||||
if (modified)
|
||||
fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ ALL_TESTS="
|
|||
lag_unlink_slaves_test
|
||||
lag_dev_deletion_test
|
||||
vlan_interface_uppers_test
|
||||
bridge_extern_learn_test
|
||||
devlink_reload_test
|
||||
"
|
||||
NUM_NETIFS=2
|
||||
|
@ -541,6 +542,25 @@ vlan_interface_uppers_test()
|
|||
ip link del dev br0
|
||||
}
|
||||
|
||||
bridge_extern_learn_test()
|
||||
{
|
||||
# Test that externally learned entries added from user space are
|
||||
# marked as offloaded
|
||||
RET=0
|
||||
|
||||
ip link add name br0 type bridge
|
||||
ip link set dev $swp1 master br0
|
||||
|
||||
bridge fdb add de:ad:be:ef:13:37 dev $swp1 master extern_learn
|
||||
|
||||
bridge fdb show brport $swp1 | grep de:ad:be:ef:13:37 | grep -q offload
|
||||
check_err $? "fdb entry not marked as offloaded when should"
|
||||
|
||||
log_test "externally learned fdb entry"
|
||||
|
||||
ip link del dev br0
|
||||
}
|
||||
|
||||
devlink_reload_test()
|
||||
{
|
||||
# Test that after executing all the above configuration tests, a
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
ALL_TESTS="ping_ipv4 ping_ipv6 learning flooding vlan_deletion"
|
||||
ALL_TESTS="ping_ipv4 ping_ipv6 learning flooding vlan_deletion extern_learn"
|
||||
NUM_NETIFS=4
|
||||
CHECK_TC="yes"
|
||||
source lib.sh
|
||||
|
@ -109,6 +109,38 @@ vlan_deletion()
|
|||
ping_ipv6
|
||||
}
|
||||
|
||||
extern_learn()
|
||||
{
|
||||
local mac=de:ad:be:ef:13:37
|
||||
local ageing_time
|
||||
|
||||
# Test that externally learned FDB entries can roam, but not age out
|
||||
RET=0
|
||||
|
||||
bridge fdb add de:ad:be:ef:13:37 dev $swp1 master extern_learn vlan 1
|
||||
|
||||
bridge fdb show brport $swp1 | grep -q de:ad:be:ef:13:37
|
||||
check_err $? "Did not find FDB entry when should"
|
||||
|
||||
# Wait for 10 seconds after the ageing time to make sure the FDB entry
|
||||
# was not aged out
|
||||
ageing_time=$(bridge_ageing_time_get br0)
|
||||
sleep $((ageing_time + 10))
|
||||
|
||||
bridge fdb show brport $swp1 | grep -q de:ad:be:ef:13:37
|
||||
check_err $? "FDB entry was aged out when should not"
|
||||
|
||||
$MZ $h2 -c 1 -p 64 -a $mac -t ip -q
|
||||
|
||||
bridge fdb show brport $swp2 | grep -q de:ad:be:ef:13:37
|
||||
check_err $? "FDB entry did not roam when should"
|
||||
|
||||
log_test "Externally learned FDB entry - ageing & roaming"
|
||||
|
||||
bridge fdb del de:ad:be:ef:13:37 dev $swp2 master vlan 1 &> /dev/null
|
||||
bridge fdb del de:ad:be:ef:13:37 dev $swp1 master vlan 1 &> /dev/null
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
setup_prepare
|
||||
|
|
Loading…
Reference in New Issue