Merge bb8f86f40e ("net: export a helper for adding up queue stats") into android16-6.12-lts

Steps on the way to 6.12.29

Change-Id: I176bb12ce2ae5614c558f22d50d03f8588b0d28a
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2025-05-30 13:12:24 +00:00
12 changed files with 340 additions and 199 deletions

View File

@@ -373,15 +373,17 @@ static void b53_enable_vlan(struct b53_device *dev, int port, bool enable,
b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5, &vc5);
}
vc1 &= ~VC1_RX_MCST_FWD_EN;
if (enable) {
vc0 |= VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID;
vc1 |= VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN;
vc1 |= VC1_RX_MCST_UNTAG_EN;
vc4 &= ~VC4_ING_VID_CHECK_MASK;
if (enable_filtering) {
vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S;
vc5 |= VC5_DROP_VTABLE_MISS;
} else {
vc4 |= VC4_ING_VID_VIO_FWD << VC4_ING_VID_CHECK_S;
vc4 |= VC4_NO_ING_VID_CHK << VC4_ING_VID_CHECK_S;
vc5 &= ~VC5_DROP_VTABLE_MISS;
}
@@ -393,7 +395,7 @@ static void b53_enable_vlan(struct b53_device *dev, int port, bool enable,
} else {
vc0 &= ~(VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID);
vc1 &= ~(VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN);
vc1 &= ~VC1_RX_MCST_UNTAG_EN;
vc4 &= ~VC4_ING_VID_CHECK_MASK;
vc5 &= ~VC5_DROP_VTABLE_MISS;
@@ -576,6 +578,18 @@ static void b53_eee_enable_set(struct dsa_switch *ds, int port, bool enable)
b53_write16(dev, B53_EEE_PAGE, B53_EEE_EN_CTRL, reg);
}
int b53_setup_port(struct dsa_switch *ds, int port)
{
struct b53_device *dev = ds->priv;
b53_port_set_ucast_flood(dev, port, true);
b53_port_set_mcast_flood(dev, port, true);
b53_port_set_learning(dev, port, false);
return 0;
}
EXPORT_SYMBOL(b53_setup_port);
int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
{
struct b53_device *dev = ds->priv;
@@ -588,10 +602,6 @@ int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
b53_port_set_ucast_flood(dev, port, true);
b53_port_set_mcast_flood(dev, port, true);
b53_port_set_learning(dev, port, false);
if (dev->ops->irq_enable)
ret = dev->ops->irq_enable(dev, port);
if (ret)
@@ -722,10 +732,6 @@ static void b53_enable_cpu_port(struct b53_device *dev, int port)
b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), port_ctrl);
b53_brcm_hdr_setup(dev->ds, port);
b53_port_set_ucast_flood(dev, port, true);
b53_port_set_mcast_flood(dev, port, true);
b53_port_set_learning(dev, port, false);
}
static void b53_enable_mib(struct b53_device *dev)
@@ -761,6 +767,22 @@ static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port)
return dev->tag_protocol == DSA_TAG_PROTO_NONE && dsa_is_cpu_port(ds, port);
}
static bool b53_vlan_port_may_join_untagged(struct dsa_switch *ds, int port)
{
struct b53_device *dev = ds->priv;
struct dsa_port *dp;
if (!dev->vlan_filtering)
return true;
dp = dsa_to_port(ds, port);
if (dsa_port_is_cpu(dp))
return true;
return dp->bridge == NULL;
}
int b53_configure_vlan(struct dsa_switch *ds)
{
struct b53_device *dev = ds->priv;
@@ -779,7 +801,7 @@ int b53_configure_vlan(struct dsa_switch *ds)
b53_do_vlan_op(dev, VTA_CMD_CLEAR);
}
b53_enable_vlan(dev, -1, dev->vlan_enabled, ds->vlan_filtering);
b53_enable_vlan(dev, -1, dev->vlan_enabled, dev->vlan_filtering);
/* Create an untagged VLAN entry for the default PVID in case
* CONFIG_VLAN_8021Q is disabled and there are no calls to
@@ -787,26 +809,39 @@ int b53_configure_vlan(struct dsa_switch *ds)
* entry. Do this only when the tagging protocol is not
* DSA_TAG_PROTO_NONE
*/
v = &dev->vlans[def_vid];
b53_for_each_port(dev, i) {
v = &dev->vlans[def_vid];
v->members |= BIT(i);
if (!b53_vlan_port_needs_forced_tagged(ds, i))
v->untag = v->members;
b53_write16(dev, B53_VLAN_PAGE,
B53_VLAN_PORT_DEF_TAG(i), def_vid);
}
/* Upon initial call we have not set-up any VLANs, but upon
* system resume, we need to restore all VLAN entries.
*/
for (vid = def_vid; vid < dev->num_vlans; vid++) {
v = &dev->vlans[vid];
if (!v->members)
if (!b53_vlan_port_may_join_untagged(ds, i))
continue;
b53_set_vlan_entry(dev, vid, v);
b53_fast_age_vlan(dev, vid);
vl.members |= BIT(i);
if (!b53_vlan_port_needs_forced_tagged(ds, i))
vl.untag = vl.members;
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(i),
def_vid);
}
b53_set_vlan_entry(dev, def_vid, &vl);
if (dev->vlan_filtering) {
/* Upon initial call we have not set-up any VLANs, but upon
* system resume, we need to restore all VLAN entries.
*/
for (vid = def_vid + 1; vid < dev->num_vlans; vid++) {
v = &dev->vlans[vid];
if (!v->members)
continue;
b53_set_vlan_entry(dev, vid, v);
b53_fast_age_vlan(dev, vid);
}
b53_for_each_port(dev, i) {
if (!dsa_is_cpu_port(ds, i))
b53_write16(dev, B53_VLAN_PAGE,
B53_VLAN_PORT_DEF_TAG(i),
dev->ports[i].pvid);
}
}
return 0;
@@ -1126,7 +1161,9 @@ EXPORT_SYMBOL(b53_setup_devlink_resources);
static int b53_setup(struct dsa_switch *ds)
{
struct b53_device *dev = ds->priv;
struct b53_vlan *vl;
unsigned int port;
u16 pvid;
int ret;
/* Request bridge PVID untagged when DSA_TAG_PROTO_NONE is set
@@ -1134,12 +1171,26 @@ static int b53_setup(struct dsa_switch *ds)
*/
ds->untag_bridge_pvid = dev->tag_protocol == DSA_TAG_PROTO_NONE;
/* The switch does not tell us the original VLAN for untagged
* packets, so keep the CPU port always tagged.
*/
ds->untag_vlan_aware_bridge_pvid = true;
ret = b53_reset_switch(dev);
if (ret) {
dev_err(ds->dev, "failed to reset switch\n");
return ret;
}
/* setup default vlan for filtering mode */
pvid = b53_default_pvid(dev);
vl = &dev->vlans[pvid];
b53_for_each_port(dev, port) {
vl->members |= BIT(port);
if (!b53_vlan_port_needs_forced_tagged(ds, port))
vl->untag |= BIT(port);
}
b53_reset_mib(dev);
ret = b53_apply_config(dev);
@@ -1493,7 +1544,10 @@ int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
{
struct b53_device *dev = ds->priv;
b53_enable_vlan(dev, port, dev->vlan_enabled, vlan_filtering);
if (dev->vlan_filtering != vlan_filtering) {
dev->vlan_filtering = vlan_filtering;
b53_apply_config(dev);
}
return 0;
}
@@ -1518,7 +1572,7 @@ static int b53_vlan_prepare(struct dsa_switch *ds, int port,
if (vlan->vid >= dev->num_vlans)
return -ERANGE;
b53_enable_vlan(dev, port, true, ds->vlan_filtering);
b53_enable_vlan(dev, port, true, dev->vlan_filtering);
return 0;
}
@@ -1531,18 +1585,29 @@ int b53_vlan_add(struct dsa_switch *ds, int port,
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
struct b53_vlan *vl;
u16 old_pvid, new_pvid;
int err;
err = b53_vlan_prepare(ds, port, vlan);
if (err)
return err;
if (vlan->vid == 0)
return 0;
old_pvid = dev->ports[port].pvid;
if (pvid)
new_pvid = vlan->vid;
else if (!pvid && vlan->vid == old_pvid)
new_pvid = b53_default_pvid(dev);
else
new_pvid = old_pvid;
dev->ports[port].pvid = new_pvid;
vl = &dev->vlans[vlan->vid];
b53_get_vlan_entry(dev, vlan->vid, vl);
if (vlan->vid == 0 && vlan->vid == b53_default_pvid(dev))
untagged = true;
if (dsa_is_cpu_port(ds, port))
untagged = false;
vl->members |= BIT(port);
if (untagged && !b53_vlan_port_needs_forced_tagged(ds, port))
@@ -1550,13 +1615,16 @@ int b53_vlan_add(struct dsa_switch *ds, int port,
else
vl->untag &= ~BIT(port);
if (!dev->vlan_filtering)
return 0;
b53_set_vlan_entry(dev, vlan->vid, vl);
b53_fast_age_vlan(dev, vlan->vid);
if (pvid && !dsa_is_cpu_port(ds, port)) {
if (!dsa_is_cpu_port(ds, port) && new_pvid != old_pvid) {
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port),
vlan->vid);
b53_fast_age_vlan(dev, vlan->vid);
new_pvid);
b53_fast_age_vlan(dev, old_pvid);
}
return 0;
@@ -1571,20 +1639,25 @@ int b53_vlan_del(struct dsa_switch *ds, int port,
struct b53_vlan *vl;
u16 pvid;
b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), &pvid);
if (vlan->vid == 0)
return 0;
pvid = dev->ports[port].pvid;
vl = &dev->vlans[vlan->vid];
b53_get_vlan_entry(dev, vlan->vid, vl);
vl->members &= ~BIT(port);
if (pvid == vlan->vid)
pvid = b53_default_pvid(dev);
dev->ports[port].pvid = pvid;
if (untagged && !b53_vlan_port_needs_forced_tagged(ds, port))
vl->untag &= ~(BIT(port));
if (!dev->vlan_filtering)
return 0;
b53_set_vlan_entry(dev, vlan->vid, vl);
b53_fast_age_vlan(dev, vlan->vid);
@@ -1917,8 +1990,9 @@ int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge,
bool *tx_fwd_offload, struct netlink_ext_ack *extack)
{
struct b53_device *dev = ds->priv;
struct b53_vlan *vl;
s8 cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
u16 pvlan, reg;
u16 pvlan, reg, pvid;
unsigned int i;
/* On 7278, port 7 which connects to the ASP should only receive
@@ -1927,15 +2001,29 @@ int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge,
if (dev->chip_id == BCM7278_DEVICE_ID && port == 7)
return -EINVAL;
/* Make this port leave the all VLANs join since we will have proper
* VLAN entries from now on
*/
if (is58xx(dev)) {
b53_read16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN, &reg);
reg &= ~BIT(port);
if ((reg & BIT(cpu_port)) == BIT(cpu_port))
reg &= ~BIT(cpu_port);
b53_write16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN, reg);
pvid = b53_default_pvid(dev);
vl = &dev->vlans[pvid];
if (dev->vlan_filtering) {
/* Make this port leave the all VLANs join since we will have
* proper VLAN entries from now on
*/
if (is58xx(dev)) {
b53_read16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN,
&reg);
reg &= ~BIT(port);
if ((reg & BIT(cpu_port)) == BIT(cpu_port))
reg &= ~BIT(cpu_port);
b53_write16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN,
reg);
}
b53_get_vlan_entry(dev, pvid, vl);
vl->members &= ~BIT(port);
if (vl->members == BIT(cpu_port))
vl->members &= ~BIT(cpu_port);
vl->untag = vl->members;
b53_set_vlan_entry(dev, pvid, vl);
}
b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), &pvlan);
@@ -1968,7 +2056,7 @@ EXPORT_SYMBOL(b53_br_join);
void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge)
{
struct b53_device *dev = ds->priv;
struct b53_vlan *vl = &dev->vlans[0];
struct b53_vlan *vl;
s8 cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
unsigned int i;
u16 pvlan, reg, pvid;
@@ -1994,15 +2082,18 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge)
dev->ports[port].vlan_ctl_mask = pvlan;
pvid = b53_default_pvid(dev);
vl = &dev->vlans[pvid];
if (dev->vlan_filtering) {
/* Make this port join all VLANs without VLAN entries */
if (is58xx(dev)) {
b53_read16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN, &reg);
reg |= BIT(port);
if (!(reg & BIT(cpu_port)))
reg |= BIT(cpu_port);
b53_write16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN, reg);
}
/* Make this port join all VLANs without VLAN entries */
if (is58xx(dev)) {
b53_read16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN, &reg);
reg |= BIT(port);
if (!(reg & BIT(cpu_port)))
reg |= BIT(cpu_port);
b53_write16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN, reg);
} else {
b53_get_vlan_entry(dev, pvid, vl);
vl->members |= BIT(port) | BIT(cpu_port);
vl->untag |= BIT(port) | BIT(cpu_port);
@@ -2307,6 +2398,7 @@ static const struct dsa_switch_ops b53_switch_ops = {
.phy_read = b53_phy_read16,
.phy_write = b53_phy_write16,
.phylink_get_caps = b53_phylink_get_caps,
.port_setup = b53_setup_port,
.port_enable = b53_enable_port,
.port_disable = b53_disable_port,
.get_mac_eee = b53_get_mac_eee,
@@ -2751,6 +2843,7 @@ struct b53_device *b53_switch_alloc(struct device *base,
ds->ops = &b53_switch_ops;
ds->phylink_mac_ops = &b53_phylink_mac_ops;
dev->vlan_enabled = true;
dev->vlan_filtering = false;
/* Let DSA handle the case were multiple bridges span the same switch
* device and different VLAN awareness settings are requested, which
* would be breaking filtering semantics for any of the other bridge

View File

@@ -95,6 +95,7 @@ struct b53_pcs {
struct b53_port {
u16 vlan_ctl_mask;
u16 pvid;
struct ethtool_keee eee;
};
@@ -146,6 +147,7 @@ struct b53_device {
unsigned int num_vlans;
struct b53_vlan *vlans;
bool vlan_enabled;
bool vlan_filtering;
unsigned int num_ports;
struct b53_port *ports;
@@ -380,6 +382,7 @@ enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port,
enum dsa_tag_protocol mprot);
void b53_mirror_del(struct dsa_switch *ds, int port,
struct dsa_mall_mirror_tc_entry *mirror);
int b53_setup_port(struct dsa_switch *ds, int port);
int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
void b53_disable_port(struct dsa_switch *ds, int port);
void b53_brcm_hdr_setup(struct dsa_switch *ds, int port);

View File

@@ -1230,6 +1230,7 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
.resume = bcm_sf2_sw_resume,
.get_wol = bcm_sf2_sw_get_wol,
.set_wol = bcm_sf2_sw_set_wol,
.port_setup = b53_setup_port,
.port_enable = bcm_sf2_port_setup,
.port_disable = bcm_sf2_port_disable,
.get_mac_eee = b53_get_mac_eee,

View File

@@ -700,8 +700,10 @@ enum {
/* PUL User Registers */
#define FBNIC_CSR_START_PUL_USER 0x31000 /* CSR section delimiter */
#define FBNIC_PUL_OB_TLP_HDR_AW_CFG 0x3103d /* 0xc40f4 */
#define FBNIC_PUL_OB_TLP_HDR_AW_CFG_FLUSH CSR_BIT(19)
#define FBNIC_PUL_OB_TLP_HDR_AW_CFG_BME CSR_BIT(18)
#define FBNIC_PUL_OB_TLP_HDR_AR_CFG 0x3103e /* 0xc40f8 */
#define FBNIC_PUL_OB_TLP_HDR_AR_CFG_FLUSH CSR_BIT(19)
#define FBNIC_PUL_OB_TLP_HDR_AR_CFG_BME CSR_BIT(18)
#define FBNIC_CSR_END_PUL_USER 0x31080 /* CSR section delimiter */

View File

@@ -17,11 +17,29 @@ static void __fbnic_mbx_wr_desc(struct fbnic_dev *fbd, int mbx_idx,
{
u32 desc_offset = FBNIC_IPC_MBX(mbx_idx, desc_idx);
/* Write the upper 32b and then the lower 32b. Doing this the
* FW can then read lower, upper, lower to verify that the state
* of the descriptor wasn't changed mid-transaction.
*/
fw_wr32(fbd, desc_offset + 1, upper_32_bits(desc));
fw_wrfl(fbd);
fw_wr32(fbd, desc_offset, lower_32_bits(desc));
}
static void __fbnic_mbx_invalidate_desc(struct fbnic_dev *fbd, int mbx_idx,
int desc_idx, u32 desc)
{
u32 desc_offset = FBNIC_IPC_MBX(mbx_idx, desc_idx);
/* For initialization we write the lower 32b of the descriptor first.
* This way we can set the state to mark it invalid before we clear the
* upper 32b.
*/
fw_wr32(fbd, desc_offset, desc);
fw_wrfl(fbd);
fw_wr32(fbd, desc_offset + 1, 0);
}
static u64 __fbnic_mbx_rd_desc(struct fbnic_dev *fbd, int mbx_idx, int desc_idx)
{
u32 desc_offset = FBNIC_IPC_MBX(mbx_idx, desc_idx);
@@ -33,29 +51,41 @@ static u64 __fbnic_mbx_rd_desc(struct fbnic_dev *fbd, int mbx_idx, int desc_idx)
return desc;
}
static void fbnic_mbx_init_desc_ring(struct fbnic_dev *fbd, int mbx_idx)
static void fbnic_mbx_reset_desc_ring(struct fbnic_dev *fbd, int mbx_idx)
{
int desc_idx;
/* Disable DMA transactions from the device,
* and flush any transactions triggered during cleaning
*/
switch (mbx_idx) {
case FBNIC_IPC_MBX_RX_IDX:
wr32(fbd, FBNIC_PUL_OB_TLP_HDR_AW_CFG,
FBNIC_PUL_OB_TLP_HDR_AW_CFG_FLUSH);
break;
case FBNIC_IPC_MBX_TX_IDX:
wr32(fbd, FBNIC_PUL_OB_TLP_HDR_AR_CFG,
FBNIC_PUL_OB_TLP_HDR_AR_CFG_FLUSH);
break;
}
wrfl(fbd);
/* Initialize first descriptor to all 0s. Doing this gives us a
* solid stop for the firmware to hit when it is done looping
* through the ring.
*/
__fbnic_mbx_wr_desc(fbd, mbx_idx, 0, 0);
fw_wrfl(fbd);
__fbnic_mbx_invalidate_desc(fbd, mbx_idx, 0, 0);
/* We then fill the rest of the ring starting at the end and moving
* back toward descriptor 0 with skip descriptors that have no
* length nor address, and tell the firmware that they can skip
* them and just move past them to the one we initialized to 0.
*/
for (desc_idx = FBNIC_IPC_MBX_DESC_LEN; --desc_idx;) {
__fbnic_mbx_wr_desc(fbd, mbx_idx, desc_idx,
FBNIC_IPC_MBX_DESC_FW_CMPL |
FBNIC_IPC_MBX_DESC_HOST_CMPL);
fw_wrfl(fbd);
}
for (desc_idx = FBNIC_IPC_MBX_DESC_LEN; --desc_idx;)
__fbnic_mbx_invalidate_desc(fbd, mbx_idx, desc_idx,
FBNIC_IPC_MBX_DESC_FW_CMPL |
FBNIC_IPC_MBX_DESC_HOST_CMPL);
}
void fbnic_mbx_init(struct fbnic_dev *fbd)
@@ -76,7 +106,7 @@ void fbnic_mbx_init(struct fbnic_dev *fbd)
wr32(fbd, FBNIC_INTR_CLEAR(0), 1u << FBNIC_FW_MSIX_ENTRY);
for (i = 0; i < FBNIC_IPC_MBX_INDICES; i++)
fbnic_mbx_init_desc_ring(fbd, i);
fbnic_mbx_reset_desc_ring(fbd, i);
}
static int fbnic_mbx_map_msg(struct fbnic_dev *fbd, int mbx_idx,
@@ -141,7 +171,7 @@ static void fbnic_mbx_clean_desc_ring(struct fbnic_dev *fbd, int mbx_idx)
{
int i;
fbnic_mbx_init_desc_ring(fbd, mbx_idx);
fbnic_mbx_reset_desc_ring(fbd, mbx_idx);
for (i = FBNIC_IPC_MBX_DESC_LEN; i--;)
fbnic_mbx_unmap_and_free_msg(fbd, mbx_idx, i);
@@ -265,67 +295,41 @@ static int fbnic_fw_xmit_simple_msg(struct fbnic_dev *fbd, u32 msg_type)
return err;
}
/**
* fbnic_fw_xmit_cap_msg - Allocate and populate a FW capabilities message
* @fbd: FBNIC device structure
*
* Return: NULL on failure to allocate, error pointer on error, or pointer
* to new TLV test message.
*
* Sends a single TLV header indicating the host wants the firmware to
* confirm the capabilities and version.
**/
static int fbnic_fw_xmit_cap_msg(struct fbnic_dev *fbd)
{
int err = fbnic_fw_xmit_simple_msg(fbd, FBNIC_TLV_MSG_ID_HOST_CAP_REQ);
/* Return 0 if we are not calling this on ASIC */
return (err == -EOPNOTSUPP) ? 0 : err;
}
static void fbnic_mbx_postinit_desc_ring(struct fbnic_dev *fbd, int mbx_idx)
static void fbnic_mbx_init_desc_ring(struct fbnic_dev *fbd, int mbx_idx)
{
struct fbnic_fw_mbx *mbx = &fbd->mbx[mbx_idx];
/* This is a one time init, so just exit if it is completed */
if (mbx->ready)
return;
mbx->ready = true;
switch (mbx_idx) {
case FBNIC_IPC_MBX_RX_IDX:
/* Enable DMA writes from the device */
wr32(fbd, FBNIC_PUL_OB_TLP_HDR_AW_CFG,
FBNIC_PUL_OB_TLP_HDR_AW_CFG_BME);
/* Make sure we have a page for the FW to write to */
fbnic_mbx_alloc_rx_msgs(fbd);
break;
case FBNIC_IPC_MBX_TX_IDX:
/* Force version to 1 if we successfully requested an update
* from the firmware. This should be overwritten once we get
* the actual version from the firmware in the capabilities
* request message.
*/
if (!fbnic_fw_xmit_cap_msg(fbd) &&
!fbd->fw_cap.running.mgmt.version)
fbd->fw_cap.running.mgmt.version = 1;
/* Enable DMA reads from the device */
wr32(fbd, FBNIC_PUL_OB_TLP_HDR_AR_CFG,
FBNIC_PUL_OB_TLP_HDR_AR_CFG_BME);
break;
}
}
static void fbnic_mbx_postinit(struct fbnic_dev *fbd)
static bool fbnic_mbx_event(struct fbnic_dev *fbd)
{
int i;
/* We only need to do this on the first interrupt following init.
/* We only need to do this on the first interrupt following reset.
* this primes the mailbox so that we will have cleared all the
* skip descriptors.
*/
if (!(rd32(fbd, FBNIC_INTR_STATUS(0)) & (1u << FBNIC_FW_MSIX_ENTRY)))
return;
return false;
wr32(fbd, FBNIC_INTR_CLEAR(0), 1u << FBNIC_FW_MSIX_ENTRY);
for (i = 0; i < FBNIC_IPC_MBX_INDICES; i++)
fbnic_mbx_postinit_desc_ring(fbd, i);
return true;
}
/**
@@ -726,7 +730,7 @@ next_page:
void fbnic_mbx_poll(struct fbnic_dev *fbd)
{
fbnic_mbx_postinit(fbd);
fbnic_mbx_event(fbd);
fbnic_mbx_process_tx_msgs(fbd);
fbnic_mbx_process_rx_msgs(fbd);
@@ -734,60 +738,80 @@ void fbnic_mbx_poll(struct fbnic_dev *fbd)
int fbnic_mbx_poll_tx_ready(struct fbnic_dev *fbd)
{
struct fbnic_fw_mbx *tx_mbx;
int attempts = 50;
unsigned long timeout = jiffies + 10 * HZ + 1;
int err, i;
/* Immediate fail if BAR4 isn't there */
if (!fbnic_fw_present(fbd))
return -ENODEV;
do {
if (!time_is_after_jiffies(timeout))
return -ETIMEDOUT;
tx_mbx = &fbd->mbx[FBNIC_IPC_MBX_TX_IDX];
while (!tx_mbx->ready && --attempts) {
/* Force the firmware to trigger an interrupt response to
* avoid the mailbox getting stuck closed if the interrupt
* is reset.
*/
fbnic_mbx_init_desc_ring(fbd, FBNIC_IPC_MBX_TX_IDX);
fbnic_mbx_reset_desc_ring(fbd, FBNIC_IPC_MBX_TX_IDX);
msleep(200);
/* Immediate fail if BAR4 went away */
if (!fbnic_fw_present(fbd))
return -ENODEV;
fbnic_mbx_poll(fbd);
}
msleep(20);
} while (!fbnic_mbx_event(fbd));
return attempts ? 0 : -ETIMEDOUT;
/* FW has shown signs of life. Enable DMA and start Tx/Rx */
for (i = 0; i < FBNIC_IPC_MBX_INDICES; i++)
fbnic_mbx_init_desc_ring(fbd, i);
/* Request an update from the firmware. This should overwrite
* mgmt.version once we get the actual version from the firmware
* in the capabilities request message.
*/
err = fbnic_fw_xmit_simple_msg(fbd, FBNIC_TLV_MSG_ID_HOST_CAP_REQ);
if (err)
goto clean_mbx;
/* Use "1" to indicate we entered the state waiting for a response */
fbd->fw_cap.running.mgmt.version = 1;
return 0;
clean_mbx:
/* Cleanup Rx buffers and disable mailbox */
fbnic_mbx_clean(fbd);
return err;
}
void fbnic_mbx_flush_tx(struct fbnic_dev *fbd)
{
unsigned long timeout = jiffies + 10 * HZ + 1;
struct fbnic_fw_mbx *tx_mbx;
int attempts = 50;
u8 count = 0;
/* Nothing to do if there is no mailbox */
if (!fbnic_fw_present(fbd))
return;
u8 tail;
/* Record current Rx stats */
tx_mbx = &fbd->mbx[FBNIC_IPC_MBX_TX_IDX];
/* Nothing to do if mailbox never got to ready */
if (!tx_mbx->ready)
return;
spin_lock_irq(&fbd->fw_tx_lock);
/* Clear ready to prevent any further attempts to transmit */
tx_mbx->ready = false;
/* Read tail to determine the last tail state for the ring */
tail = tx_mbx->tail;
spin_unlock_irq(&fbd->fw_tx_lock);
/* Give firmware time to process packet,
* we will wait up to 10 seconds which is 50 waits of 200ms.
* we will wait up to 10 seconds which is 500 waits of 20ms.
*/
do {
u8 head = tx_mbx->head;
if (head == tx_mbx->tail)
/* Tx ring is empty once head == tail */
if (head == tail)
break;
msleep(200);
msleep(20);
fbnic_mbx_process_tx_msgs(fbd);
count += (tx_mbx->head - head) % FBNIC_IPC_MBX_DESC_LEN;
} while (count < FBNIC_IPC_MBX_DESC_LEN && --attempts);
} while (time_is_after_jiffies(timeout));
}
void fbnic_get_fw_ver_commit_str(struct fbnic_dev *fbd, char *fw_version,

View File

@@ -79,12 +79,6 @@ static void fbnic_mac_init_axi(struct fbnic_dev *fbd)
fbnic_init_readrq(fbd, FBNIC_QM_RNI_RBP_CTL, cls, readrq);
fbnic_init_mps(fbd, FBNIC_QM_RNI_RDE_CTL, cls, mps);
fbnic_init_mps(fbd, FBNIC_QM_RNI_RCM_CTL, cls, mps);
/* Enable XALI AR/AW outbound */
wr32(fbd, FBNIC_PUL_OB_TLP_HDR_AW_CFG,
FBNIC_PUL_OB_TLP_HDR_AW_CFG_BME);
wr32(fbd, FBNIC_PUL_OB_TLP_HDR_AR_CFG,
FBNIC_PUL_OB_TLP_HDR_AR_CFG_BME);
}
static void fbnic_mac_init_qm(struct fbnic_dev *fbd)

View File

@@ -82,9 +82,6 @@ struct z_erofs_pcluster {
/* L: whether partial decompression or not */
bool partial;
/* L: indicate several pageofs_outs or not */
bool multibases;
/* L: whether extra buffer allocations are best-effort */
bool besteffort;
@@ -1073,8 +1070,6 @@ static int z_erofs_scan_folio(struct z_erofs_decompress_frontend *f,
break;
erofs_onlinefolio_split(folio);
if (f->pcl->pageofs_out != (map->m_la & ~PAGE_MASK))
f->pcl->multibases = true;
if (f->pcl->length < offset + end - map->m_la) {
f->pcl->length = offset + end - map->m_la;
f->pcl->pageofs_out = map->m_la & ~PAGE_MASK;
@@ -1120,7 +1115,6 @@ struct z_erofs_decompress_backend {
struct page *onstack_pages[Z_EROFS_ONSTACK_PAGES];
struct super_block *sb;
struct z_erofs_pcluster *pcl;
/* pages with the longest decompressed length for deduplication */
struct page **decompressed_pages;
/* pages to keep the compressed data */
@@ -1129,6 +1123,8 @@ struct z_erofs_decompress_backend {
struct list_head decompressed_secondary_bvecs;
struct page **pagepool;
unsigned int onstack_used, nr_pages;
/* indicate if temporary copies should be preserved for later use */
bool keepxcpy;
};
struct z_erofs_bvec_item {
@@ -1139,18 +1135,20 @@ struct z_erofs_bvec_item {
static void z_erofs_do_decompressed_bvec(struct z_erofs_decompress_backend *be,
struct z_erofs_bvec *bvec)
{
int poff = bvec->offset + be->pcl->pageofs_out;
struct z_erofs_bvec_item *item;
unsigned int pgnr;
struct page **page;
if (!((bvec->offset + be->pcl->pageofs_out) & ~PAGE_MASK) &&
(bvec->end == PAGE_SIZE ||
bvec->offset + bvec->end == be->pcl->length)) {
pgnr = (bvec->offset + be->pcl->pageofs_out) >> PAGE_SHIFT;
DBG_BUGON(pgnr >= be->nr_pages);
if (!be->decompressed_pages[pgnr]) {
be->decompressed_pages[pgnr] = bvec->page;
if (!(poff & ~PAGE_MASK) && (bvec->end == PAGE_SIZE ||
bvec->offset + bvec->end == be->pcl->length)) {
DBG_BUGON((poff >> PAGE_SHIFT) >= be->nr_pages);
page = be->decompressed_pages + (poff >> PAGE_SHIFT);
if (!*page) {
*page = bvec->page;
return;
}
} else {
be->keepxcpy = true;
}
/* (cold path) one pcluster is requested multiple times */
@@ -1316,7 +1314,7 @@ static int z_erofs_decompress_pcluster(struct z_erofs_decompress_backend *be,
.alg = pcl->algorithmformat,
.inplace_io = overlapped,
.partial_decoding = pcl->partial,
.fillgaps = pcl->multibases,
.fillgaps = be->keepxcpy,
.gfp = pcl->besteffort ? GFP_KERNEL :
GFP_NOWAIT | __GFP_NORETRY
}, be->pagepool);
@@ -1370,7 +1368,6 @@ static int z_erofs_decompress_pcluster(struct z_erofs_decompress_backend *be,
pcl->length = 0;
pcl->partial = true;
pcl->multibases = false;
pcl->besteffort = false;
pcl->bvset.nextpage = NULL;
pcl->vcnt = 0;

View File

@@ -92,6 +92,12 @@ struct netdev_stat_ops {
struct netdev_queue_stats_tx *tx);
};
void netdev_stat_queue_sum(struct net_device *netdev,
int rx_start, int rx_end,
struct netdev_queue_stats_rx *rx_sum,
int tx_start, int tx_end,
struct netdev_queue_stats_tx *tx_sum);
/**
* struct netdev_queue_mgmt_ops - netdev ops for queue management
*

View File

@@ -2534,6 +2534,7 @@ int skb_do_redirect(struct sk_buff *skb)
goto out_drop;
skb->dev = dev;
dev_sw_netstats_rx_add(dev, skb->len);
skb_scrub_packet(skb, false);
return -EAGAIN;
}
return flags & BPF_F_NEIGH ?

View File

@@ -616,25 +616,66 @@ netdev_nl_stats_by_queue(struct net_device *netdev, struct sk_buff *rsp,
return 0;
}
/**
* netdev_stat_queue_sum() - add up queue stats from range of queues
* @netdev: net_device
* @rx_start: index of the first Rx queue to query
* @rx_end: index after the last Rx queue (first *not* to query)
* @rx_sum: output Rx stats, should be already initialized
* @tx_start: index of the first Tx queue to query
* @tx_end: index after the last Tx queue (first *not* to query)
* @tx_sum: output Tx stats, should be already initialized
*
* Add stats from [start, end) range of queue IDs to *x_sum structs.
* The sum structs must be already initialized. Usually this
* helper is invoked from the .get_base_stats callbacks of drivers
* to account for stats of disabled queues. In that case the ranges
* are usually [netdev->real_num_*x_queues, netdev->num_*x_queues).
*/
void netdev_stat_queue_sum(struct net_device *netdev,
int rx_start, int rx_end,
struct netdev_queue_stats_rx *rx_sum,
int tx_start, int tx_end,
struct netdev_queue_stats_tx *tx_sum)
{
const struct netdev_stat_ops *ops;
struct netdev_queue_stats_rx rx;
struct netdev_queue_stats_tx tx;
int i;
ops = netdev->stat_ops;
for (i = rx_start; i < rx_end; i++) {
memset(&rx, 0xff, sizeof(rx));
if (ops->get_queue_stats_rx)
ops->get_queue_stats_rx(netdev, i, &rx);
netdev_nl_stats_add(rx_sum, &rx, sizeof(rx));
}
for (i = tx_start; i < tx_end; i++) {
memset(&tx, 0xff, sizeof(tx));
if (ops->get_queue_stats_tx)
ops->get_queue_stats_tx(netdev, i, &tx);
netdev_nl_stats_add(tx_sum, &tx, sizeof(tx));
}
}
EXPORT_SYMBOL(netdev_stat_queue_sum);
static int
netdev_nl_stats_by_netdev(struct net_device *netdev, struct sk_buff *rsp,
const struct genl_info *info)
{
struct netdev_queue_stats_rx rx_sum, rx;
struct netdev_queue_stats_tx tx_sum, tx;
const struct netdev_stat_ops *ops;
struct netdev_queue_stats_rx rx_sum;
struct netdev_queue_stats_tx tx_sum;
void *hdr;
int i;
ops = netdev->stat_ops;
/* Netdev can't guarantee any complete counters */
if (!ops->get_base_stats)
if (!netdev->stat_ops->get_base_stats)
return 0;
memset(&rx_sum, 0xff, sizeof(rx_sum));
memset(&tx_sum, 0xff, sizeof(tx_sum));
ops->get_base_stats(netdev, &rx_sum, &tx_sum);
netdev->stat_ops->get_base_stats(netdev, &rx_sum, &tx_sum);
/* The op was there, but nothing reported, don't bother */
if (!memchr_inv(&rx_sum, 0xff, sizeof(rx_sum)) &&
@@ -647,18 +688,8 @@ netdev_nl_stats_by_netdev(struct net_device *netdev, struct sk_buff *rsp,
if (nla_put_u32(rsp, NETDEV_A_QSTATS_IFINDEX, netdev->ifindex))
goto nla_put_failure;
for (i = 0; i < netdev->real_num_rx_queues; i++) {
memset(&rx, 0xff, sizeof(rx));
if (ops->get_queue_stats_rx)
ops->get_queue_stats_rx(netdev, i, &rx);
netdev_nl_stats_add(&rx_sum, &rx, sizeof(rx));
}
for (i = 0; i < netdev->real_num_tx_queues; i++) {
memset(&tx, 0xff, sizeof(tx));
if (ops->get_queue_stats_tx)
ops->get_queue_stats_tx(netdev, i, &tx);
netdev_nl_stats_add(&tx_sum, &tx, sizeof(tx));
}
netdev_stat_queue_sum(netdev, 0, netdev->real_num_rx_queues, &rx_sum,
0, netdev->real_num_tx_queues, &tx_sum);
if (netdev_nl_stats_write_rx(rsp, &rx_sum) ||
netdev_nl_stats_write_tx(rsp, &tx_sum))

View File

@@ -64,7 +64,7 @@ struct hbucket {
#define ahash_sizeof_regions(htable_bits) \
(ahash_numof_locks(htable_bits) * sizeof(struct ip_set_region))
#define ahash_region(n, htable_bits) \
((n) % ahash_numof_locks(htable_bits))
((n) / jhash_size(HTABLE_REGION_BITS))
#define ahash_bucket_start(h, htable_bits) \
((htable_bits) < HTABLE_REGION_BITS ? 0 \
: (h) * jhash_size(HTABLE_REGION_BITS))

View File

@@ -119,13 +119,12 @@ __mtu_check_toobig_v6(const struct sk_buff *skb, u32 mtu)
return false;
}
/* Get route to daddr, update *saddr, optionally bind route to saddr */
/* Get route to daddr, optionally bind route to saddr */
static struct rtable *do_output_route4(struct net *net, __be32 daddr,
int rt_mode, __be32 *saddr)
int rt_mode, __be32 *ret_saddr)
{
struct flowi4 fl4;
struct rtable *rt;
bool loop = false;
memset(&fl4, 0, sizeof(fl4));
fl4.daddr = daddr;
@@ -135,23 +134,17 @@ static struct rtable *do_output_route4(struct net *net, __be32 daddr,
retry:
rt = ip_route_output_key(net, &fl4);
if (IS_ERR(rt)) {
/* Invalid saddr ? */
if (PTR_ERR(rt) == -EINVAL && *saddr &&
rt_mode & IP_VS_RT_MODE_CONNECT && !loop) {
*saddr = 0;
flowi4_update_output(&fl4, 0, daddr, 0);
goto retry;
}
IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", &daddr);
return NULL;
} else if (!*saddr && rt_mode & IP_VS_RT_MODE_CONNECT && fl4.saddr) {
}
if (rt_mode & IP_VS_RT_MODE_CONNECT && fl4.saddr) {
ip_rt_put(rt);
*saddr = fl4.saddr;
flowi4_update_output(&fl4, 0, daddr, fl4.saddr);
loop = true;
rt_mode = 0;
goto retry;
}
*saddr = fl4.saddr;
if (ret_saddr)
*ret_saddr = fl4.saddr;
return rt;
}
@@ -344,19 +337,15 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
if (ret_saddr)
*ret_saddr = dest_dst->dst_saddr.ip;
} else {
__be32 saddr = htonl(INADDR_ANY);
noref = 0;
/* For such unconfigured boxes avoid many route lookups
* for performance reasons because we do not remember saddr
*/
rt_mode &= ~IP_VS_RT_MODE_CONNECT;
rt = do_output_route4(net, daddr, rt_mode, &saddr);
rt = do_output_route4(net, daddr, rt_mode, ret_saddr);
if (!rt)
goto err_unreach;
if (ret_saddr)
*ret_saddr = saddr;
}
local = (rt->rt_flags & RTCF_LOCAL) ? 1 : 0;