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:
@@ -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 &= ~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 &= ~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 |= 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 |= 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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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 ?
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user