Commit 02dc96ef authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Pull networking fixes from David Miller:

 1) Sanity check URB networking device parameters to avoid divide by
    zero, from Oliver Neukum.

 2) Disable global multicast filter in NCSI, otherwise LLDP and IPV6
    don't work properly. Longer term this needs a better fix tho. From
    Vijay Khemka.

 3) Small fixes to selftests (use ping when ping6 is not present, etc.)
    from David Ahern.

 4) Bring back rt_uses_gateway member of struct rtable, it's semantics
    were not well understood and trying to remove it broke things. From
    David Ahern.

 5) Move usbnet snaity checking, ignore endpoints with invalid
    wMaxPacketSize. From Bjørn Mork.

 6) Missing Kconfig deps for sja1105 driver, from Mao Wenan.

 7) Various small fixes to the mlx5 DR steering code, from Alaa Hleihel,
    Alex Vesker, and Yevgeny Kliteynik

 8) Missing CAP_NET_RAW checks in various places, from Ori Nimron.

 9) Fix crash when removing sch_cbs entry while offloading is enabled,
    from Vinicius Costa Gomes.

10) Signedness bug fixes, generally in looking at the result given by
    of_get_phy_mode() and friends. From Dan Crapenter.

11) Disable preemption around BPF_PROG_RUN() calls, from Eric Dumazet.

12) Don't create VRF ipv6 rules if ipv6 is disabled, from David Ahern.

13) Fix quantization code in tcp_bbr, from Kevin Yang.

* git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (127 commits)
  net: tap: clean up an indentation issue
  nfp: abm: fix memory leak in nfp_abm_u32_knode_replace
  tcp: better handle TCP_USER_TIMEOUT in SYN_SENT state
  sk_buff: drop all skb extensions on free and skb scrubbing
  tcp_bbr: fix quantization code to not raise cwnd if not probing bandwidth
  mlxsw: spectrum_flower: Fail in case user specifies multiple mirror actions
  Documentation: Clarify trap's description
  mlxsw: spectrum: Clear VLAN filters during port initialization
  net: ena: clean up indentation issue
  NFC: st95hf: clean up indentation issue
  net: phy: micrel: add Asym Pause workaround for KSZ9021
  net: socionext: ave: Avoid using netdev_err() before calling register_netdev()
  ptp: correctly disable flags on old ioctls
  lib: dimlib: fix help text typos
  net: dsa: microchip: Always set regmap stride to 1
  nfp: flower: fix memory leak in nfp_flower_spawn_vnic_reprs
  nfp: flower: prevent memory leak in nfp_flower_spawn_phy_reprs
  net/sched: Set default of CONFIG_NET_TC_SKB_EXT to N
  vrf: Do not attempt to create IPv6 mcast rule if IPv6 is disabled
  net: sched: sch_sfb: don't call qdisc_put() while holding tree lock
  ...
parents edf445ad faeacb6d
...@@ -18,7 +18,7 @@ static int dr_rule_append_to_miss_list(struct mlx5dr_ste *new_last_ste, ...@@ -18,7 +18,7 @@ static int dr_rule_append_to_miss_list(struct mlx5dr_ste *new_last_ste,
struct mlx5dr_ste *last_ste; struct mlx5dr_ste *last_ste;
/* The new entry will be inserted after the last */ /* The new entry will be inserted after the last */
last_ste = list_entry(miss_list->prev, struct mlx5dr_ste, miss_list_node); last_ste = list_last_entry(miss_list, struct mlx5dr_ste, miss_list_node);
WARN_ON(!last_ste); WARN_ON(!last_ste);
ste_info_last = kzalloc(sizeof(*ste_info_last), GFP_KERNEL); ste_info_last = kzalloc(sizeof(*ste_info_last), GFP_KERNEL);
......
...@@ -429,12 +429,9 @@ static void dr_ste_remove_middle_ste(struct mlx5dr_ste *ste, ...@@ -429,12 +429,9 @@ static void dr_ste_remove_middle_ste(struct mlx5dr_ste *ste,
struct mlx5dr_ste *prev_ste; struct mlx5dr_ste *prev_ste;
u64 miss_addr; u64 miss_addr;
prev_ste = list_entry(mlx5dr_ste_get_miss_list(ste)->prev, struct mlx5dr_ste, prev_ste = list_prev_entry(ste, miss_list_node);
miss_list_node); if (WARN_ON(!prev_ste))
if (!prev_ste) {
WARN_ON(true);
return; return;
}
miss_addr = mlx5dr_ste_get_miss_addr(ste->hw_ste); miss_addr = mlx5dr_ste_get_miss_addr(ste->hw_ste);
mlx5dr_ste_set_miss_addr(prev_ste->hw_ste, miss_addr); mlx5dr_ste_set_miss_addr(prev_ste->hw_ste, miss_addr);
...@@ -461,8 +458,8 @@ void mlx5dr_ste_free(struct mlx5dr_ste *ste, ...@@ -461,8 +458,8 @@ void mlx5dr_ste_free(struct mlx5dr_ste *ste,
struct mlx5dr_ste_htbl *stats_tbl; struct mlx5dr_ste_htbl *stats_tbl;
LIST_HEAD(send_ste_list); LIST_HEAD(send_ste_list);
first_ste = list_entry(mlx5dr_ste_get_miss_list(ste)->next, first_ste = list_first_entry(mlx5dr_ste_get_miss_list(ste),
struct mlx5dr_ste, miss_list_node); struct mlx5dr_ste, miss_list_node);
stats_tbl = first_ste->htbl; stats_tbl = first_ste->htbl;
/* Two options: /* Two options:
...@@ -479,8 +476,7 @@ void mlx5dr_ste_free(struct mlx5dr_ste *ste, ...@@ -479,8 +476,7 @@ void mlx5dr_ste_free(struct mlx5dr_ste *ste,
if (last_ste == first_ste) if (last_ste == first_ste)
next_ste = NULL; next_ste = NULL;
else else
next_ste = list_entry(ste->miss_list_node.next, next_ste = list_next_entry(ste, miss_list_node);
struct mlx5dr_ste, miss_list_node);
if (!next_ste) { if (!next_ste) {
/* One and only entry in the list */ /* One and only entry in the list */
...@@ -841,6 +837,8 @@ static void dr_ste_copy_mask_misc(char *mask, struct mlx5dr_match_misc *spec) ...@@ -841,6 +837,8 @@ static void dr_ste_copy_mask_misc(char *mask, struct mlx5dr_match_misc *spec)
spec->source_sqn = MLX5_GET(fte_match_set_misc, mask, source_sqn); spec->source_sqn = MLX5_GET(fte_match_set_misc, mask, source_sqn);
spec->source_port = MLX5_GET(fte_match_set_misc, mask, source_port); spec->source_port = MLX5_GET(fte_match_set_misc, mask, source_port);
spec->source_eswitch_owner_vhca_id = MLX5_GET(fte_match_set_misc, mask,
source_eswitch_owner_vhca_id);
spec->outer_second_prio = MLX5_GET(fte_match_set_misc, mask, outer_second_prio); spec->outer_second_prio = MLX5_GET(fte_match_set_misc, mask, outer_second_prio);
spec->outer_second_cfi = MLX5_GET(fte_match_set_misc, mask, outer_second_cfi); spec->outer_second_cfi = MLX5_GET(fte_match_set_misc, mask, outer_second_cfi);
...@@ -2254,11 +2252,18 @@ static int dr_ste_build_src_gvmi_qpn_bit_mask(struct mlx5dr_match_param *value, ...@@ -2254,11 +2252,18 @@ static int dr_ste_build_src_gvmi_qpn_bit_mask(struct mlx5dr_match_param *value,
{ {
struct mlx5dr_match_misc *misc_mask = &value->misc; struct mlx5dr_match_misc *misc_mask = &value->misc;
if (misc_mask->source_port != 0xffff) /* Partial misc source_port is not supported */
if (misc_mask->source_port && misc_mask->source_port != 0xffff)
return -EINVAL;
/* Partial misc source_eswitch_owner_vhca_id is not supported */
if (misc_mask->source_eswitch_owner_vhca_id &&
misc_mask->source_eswitch_owner_vhca_id != 0xffff)
return -EINVAL; return -EINVAL;
DR_STE_SET_MASK(src_gvmi_qp, bit_mask, source_gvmi, misc_mask, source_port); DR_STE_SET_MASK(src_gvmi_qp, bit_mask, source_gvmi, misc_mask, source_port);
DR_STE_SET_MASK(src_gvmi_qp, bit_mask, source_qp, misc_mask, source_sqn); DR_STE_SET_MASK(src_gvmi_qp, bit_mask, source_qp, misc_mask, source_sqn);
misc_mask->source_eswitch_owner_vhca_id = 0;
return 0; return 0;
} }
...@@ -2270,17 +2275,33 @@ static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, ...@@ -2270,17 +2275,33 @@ static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
struct mlx5dr_match_misc *misc = &value->misc; struct mlx5dr_match_misc *misc = &value->misc;
struct mlx5dr_cmd_vport_cap *vport_cap; struct mlx5dr_cmd_vport_cap *vport_cap;
struct mlx5dr_domain *dmn = sb->dmn;
struct mlx5dr_cmd_caps *caps;
u8 *tag = hw_ste->tag; u8 *tag = hw_ste->tag;
DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn); DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn);
vport_cap = mlx5dr_get_vport_cap(sb->caps, misc->source_port); if (sb->vhca_id_valid) {
/* Find port GVMI based on the eswitch_owner_vhca_id */
if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi)
caps = &dmn->info.caps;
else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id ==
dmn->peer_dmn->info.caps.gvmi))
caps = &dmn->peer_dmn->info.caps;
else
return -EINVAL;
} else {
caps = &dmn->info.caps;
}
vport_cap = mlx5dr_get_vport_cap(caps, misc->source_port);
if (!vport_cap) if (!vport_cap)
return -EINVAL; return -EINVAL;
if (vport_cap->vport_gvmi) if (vport_cap->vport_gvmi)
MLX5_SET(ste_src_gvmi_qp, tag, source_gvmi, vport_cap->vport_gvmi); MLX5_SET(ste_src_gvmi_qp, tag, source_gvmi, vport_cap->vport_gvmi);
misc->source_eswitch_owner_vhca_id = 0;
misc->source_port = 0; misc->source_port = 0;
return 0; return 0;
...@@ -2288,17 +2309,20 @@ static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, ...@@ -2288,17 +2309,20 @@ static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
int mlx5dr_ste_build_src_gvmi_qpn(struct mlx5dr_ste_build *sb, int mlx5dr_ste_build_src_gvmi_qpn(struct mlx5dr_ste_build *sb,
struct mlx5dr_match_param *mask, struct mlx5dr_match_param *mask,
struct mlx5dr_cmd_caps *caps, struct mlx5dr_domain *dmn,
bool inner, bool rx) bool inner, bool rx)
{ {
int ret; int ret;
/* Set vhca_id_valid before we reset source_eswitch_owner_vhca_id */
sb->vhca_id_valid = mask->misc.source_eswitch_owner_vhca_id;
ret = dr_ste_build_src_gvmi_qpn_bit_mask(mask, sb->bit_mask); ret = dr_ste_build_src_gvmi_qpn_bit_mask(mask, sb->bit_mask);
if (ret) if (ret)
return ret; return ret;
sb->rx = rx; sb->rx = rx;
sb->caps = caps; sb->dmn = dmn;
sb->inner = inner; sb->inner = inner;
sb->lu_type = MLX5DR_STE_LU_TYPE_SRC_GVMI_AND_QP; sb->lu_type = MLX5DR_STE_LU_TYPE_SRC_GVMI_AND_QP;
sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
......
...@@ -180,6 +180,8 @@ void mlx5dr_send_fill_and_append_ste_send_info(struct mlx5dr_ste *ste, u16 size, ...@@ -180,6 +180,8 @@ void mlx5dr_send_fill_and_append_ste_send_info(struct mlx5dr_ste *ste, u16 size,
struct mlx5dr_ste_build { struct mlx5dr_ste_build {
u8 inner:1; u8 inner:1;
u8 rx:1; u8 rx:1;
u8 vhca_id_valid:1;
struct mlx5dr_domain *dmn;
struct mlx5dr_cmd_caps *caps; struct mlx5dr_cmd_caps *caps;
u8 lu_type; u8 lu_type;
u16 byte_mask; u16 byte_mask;
...@@ -331,7 +333,7 @@ void mlx5dr_ste_build_register_1(struct mlx5dr_ste_build *sb, ...@@ -331,7 +333,7 @@ void mlx5dr_ste_build_register_1(struct mlx5dr_ste_build *sb,
bool inner, bool rx); bool inner, bool rx);
int mlx5dr_ste_build_src_gvmi_qpn(struct mlx5dr_ste_build *sb, int mlx5dr_ste_build_src_gvmi_qpn(struct mlx5dr_ste_build *sb,
struct mlx5dr_match_param *mask, struct mlx5dr_match_param *mask,
struct mlx5dr_cmd_caps *caps, struct mlx5dr_domain *dmn,
bool inner, bool rx); bool inner, bool rx);
void mlx5dr_ste_build_empty_always_hit(struct mlx5dr_ste_build *sb, bool rx); void mlx5dr_ste_build_empty_always_hit(struct mlx5dr_ste_build *sb, bool rx);
...@@ -453,7 +455,7 @@ struct mlx5dr_match_misc { ...@@ -453,7 +455,7 @@ struct mlx5dr_match_misc {
u32 gre_c_present:1; u32 gre_c_present:1;
/* Source port.;0xffff determines wire port */ /* Source port.;0xffff determines wire port */
u32 source_port:16; u32 source_port:16;
u32 reserved_auto2:16; u32 source_eswitch_owner_vhca_id:16;
/* VLAN ID of first VLAN tag the inner header of the incoming packet. /* VLAN ID of first VLAN tag the inner header of the incoming packet.
* Valid only when inner_second_cvlan_tag ==1 or inner_second_svlan_tag ==1 * Valid only when inner_second_cvlan_tag ==1 or inner_second_svlan_tag ==1
*/ */
...@@ -745,7 +747,6 @@ struct mlx5dr_action { ...@@ -745,7 +747,6 @@ struct mlx5dr_action {
struct { struct {
struct mlx5dr_domain *dmn; struct mlx5dr_domain *dmn;
struct mlx5dr_cmd_vport_cap *caps; struct mlx5dr_cmd_vport_cap *caps;
u32 num;
} vport; } vport;
struct { struct {
u32 vlan_hdr; /* tpid_pcp_dei_vid */ u32 vlan_hdr; /* tpid_pcp_dei_vid */
......
...@@ -3771,6 +3771,14 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, ...@@ -3771,6 +3771,14 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
goto err_port_qdiscs_init; goto err_port_qdiscs_init;
} }
err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, 0, VLAN_N_VID - 1, false,
false);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to clear VLAN filter\n",
mlxsw_sp_port->local_port);
goto err_port_vlan_clear;
}
err = mlxsw_sp_port_nve_init(mlxsw_sp_port); err = mlxsw_sp_port_nve_init(mlxsw_sp_port);
if (err) { if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize NVE\n", dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize NVE\n",
...@@ -3818,6 +3826,7 @@ err_port_vlan_create: ...@@ -3818,6 +3826,7 @@ err_port_vlan_create:
err_port_pvid_set: err_port_pvid_set:
mlxsw_sp_port_nve_fini(mlxsw_sp_port); mlxsw_sp_port_nve_fini(mlxsw_sp_port);
err_port_nve_init: err_port_nve_init:
err_port_vlan_clear:
mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port); mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port);
err_port_qdiscs_init: err_port_qdiscs_init:
mlxsw_sp_port_fids_fini(mlxsw_sp_port); mlxsw_sp_port_fids_fini(mlxsw_sp_port);
......
...@@ -21,6 +21,7 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, ...@@ -21,6 +21,7 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
const struct flow_action_entry *act; const struct flow_action_entry *act;
int mirror_act_count = 0;
int err, i; int err, i;
if (!flow_action_has_entries(flow_action)) if (!flow_action_has_entries(flow_action))
...@@ -105,6 +106,11 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, ...@@ -105,6 +106,11 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
case FLOW_ACTION_MIRRED: { case FLOW_ACTION_MIRRED: {
struct net_device *out_dev = act->dev; struct net_device *out_dev = act->dev;
if (mirror_act_count++) {
NL_SET_ERR_MSG_MOD(extack, "Multiple mirror actions per rule are not supported");
return -EOPNOTSUPP;
}
err = mlxsw_sp_acl_rulei_act_mirror(mlxsw_sp, rulei, err = mlxsw_sp_acl_rulei_act_mirror(mlxsw_sp, rulei,
block, out_dev, block, out_dev,
extack); extack);
......
...@@ -176,8 +176,10 @@ nfp_abm_u32_knode_replace(struct nfp_abm_link *alink, ...@@ -176,8 +176,10 @@ nfp_abm_u32_knode_replace(struct nfp_abm_link *alink,
u8 mask, val; u8 mask, val;
int err; int err;
if (!nfp_abm_u32_check_knode(alink->abm, knode, proto, extack)) if (!nfp_abm_u32_check_knode(alink->abm, knode, proto, extack)) {
err = -EOPNOTSUPP;
goto err_delete; goto err_delete;
}
tos_off = proto == htons(ETH_P_IP) ? 16 : 20; tos_off = proto == htons(ETH_P_IP) ? 16 : 20;
...@@ -198,14 +200,18 @@ nfp_abm_u32_knode_replace(struct nfp_abm_link *alink, ...@@ -198,14 +200,18 @@ nfp_abm_u32_knode_replace(struct nfp_abm_link *alink,
if ((iter->val & cmask) == (val & cmask) && if ((iter->val & cmask) == (val & cmask) &&
iter->band != knode->res->classid) { iter->band != knode->res->classid) {
NL_SET_ERR_MSG_MOD(extack, "conflict with already offloaded filter"); NL_SET_ERR_MSG_MOD(extack, "conflict with already offloaded filter");
err = -EOPNOTSUPP;
goto err_delete; goto err_delete;
} }
} }
if (!match) { if (!match) {
match = kzalloc(sizeof(*match), GFP_KERNEL); match = kzalloc(sizeof(*match), GFP_KERNEL);
if (!match) if (!match) {
return -ENOMEM; err = -ENOMEM;
goto err_delete;
}
list_add(&match->list, &alink->dscp_map); list_add(&match->list, &alink->dscp_map);
} }
match->handle = knode->handle; match->handle = knode->handle;
...@@ -221,7 +227,7 @@ nfp_abm_u32_knode_replace(struct nfp_abm_link *alink, ...@@ -221,7 +227,7 @@ nfp_abm_u32_knode_replace(struct nfp_abm_link *alink,
err_delete: err_delete:
nfp_abm_u32_knode_delete(alink, knode); nfp_abm_u32_knode_delete(alink, knode);
return -EOPNOTSUPP; return err;
} }
static int nfp_abm_setup_tc_block_cb(enum tc_setup_type type, static int nfp_abm_setup_tc_block_cb(enum tc_setup_type type,
......
...@@ -400,6 +400,7 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app, ...@@ -400,6 +400,7 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
repr_priv = kzalloc(sizeof(*repr_priv), GFP_KERNEL); repr_priv = kzalloc(sizeof(*repr_priv), GFP_KERNEL);
if (!repr_priv) { if (!repr_priv) {
err = -ENOMEM; err = -ENOMEM;
nfp_repr_free(repr);
goto err_reprs_clean; goto err_reprs_clean;
} }
...@@ -413,6 +414,7 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app, ...@@ -413,6 +414,7 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
port = nfp_port_alloc(app, port_type, repr); port = nfp_port_alloc(app, port_type, repr);
if (IS_ERR(port)) { if (IS_ERR(port)) {
err = PTR_ERR(port); err = PTR_ERR(port);
kfree(repr_priv);
nfp_repr_free(repr); nfp_repr_free(repr);
goto err_reprs_clean; goto err_reprs_clean;
} }
...@@ -433,6 +435,7 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app, ...@@ -433,6 +435,7 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
err = nfp_repr_init(app, repr, err = nfp_repr_init(app, repr,
port_id, port, priv->nn->dp.netdev); port_id, port, priv->nn->dp.netdev);
if (err) { if (err) {
kfree(repr_priv);
nfp_port_free(port); nfp_port_free(port);
nfp_repr_free(repr); nfp_repr_free(repr);
goto err_reprs_clean; goto err_reprs_clean;
...@@ -515,6 +518,7 @@ nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv) ...@@ -515,6 +518,7 @@ nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)
repr_priv = kzalloc(sizeof(*repr_priv), GFP_KERNEL); repr_priv = kzalloc(sizeof(*repr_priv), GFP_KERNEL);
if (!repr_priv) { if (!repr_priv) {
err = -ENOMEM; err = -ENOMEM;
nfp_repr_free(repr);
goto err_reprs_clean; goto err_reprs_clean;
} }
...@@ -525,11 +529,13 @@ nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv) ...@@ -525,11 +529,13 @@ nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)
port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT, repr); port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT, repr);
if (IS_ERR(port)) { if (IS_ERR(port)) {
err = PTR_ERR(port); err = PTR_ERR(port);
kfree(repr_priv);
nfp_repr_free(repr); nfp_repr_free(repr);
goto err_reprs_clean; goto err_reprs_clean;
} }
err = nfp_port_init_phy_port(app->pf, app, port, i); err = nfp_port_init_phy_port(app->pf, app, port, i);
if (err) { if (err) {
kfree(repr_priv);
nfp_port_free(port); nfp_port_free(port);
nfp_repr_free(repr); nfp_repr_free(repr);
goto err_reprs_clean; goto err_reprs_clean;
...@@ -542,6 +548,7 @@ nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv) ...@@ -542,6 +548,7 @@ nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)
err = nfp_repr_init(app, repr, err = nfp_repr_init(app, repr,
cmsg_port_id, port, priv->nn->dp.netdev); cmsg_port_id, port, priv->nn->dp.netdev);
if (err) { if (err) {
kfree(repr_priv);
nfp_port_free(port); nfp_port_free(port);
nfp_repr_free(repr); nfp_repr_free(repr);
goto err_reprs_clean; goto err_reprs_clean;
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* drivers/net/ethernet/netx-eth.c
*
* Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/platform_device.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/mii.h>
#include <asm/io.h>
#include <mach/hardware.h>
#include <mach/netx-regs.h>
#include <mach/pfifo.h>
#include <mach/xc.h>
#include <linux/platform_data/eth-netx.h>
/* XC Fifo Offsets */
#define EMPTY_PTR_FIFO(xcno) (0 + ((xcno) << 3)) /* Index of the empty pointer FIFO */
#define IND_FIFO_PORT_HI(xcno) (1 + ((xcno) << 3)) /* Index of the FIFO where received */
/* Data packages are indicated by XC */
#define IND_FIFO_PORT_LO(xcno) (2 + ((xcno) << 3)) /* Index of the FIFO where received */
/* Data packages are indicated by XC */
#define REQ_FIFO_PORT_HI(xcno) (3 + ((xcno) << 3)) /* Index of the FIFO where Data packages */
/* have to be indicated by ARM which */
/* shall be sent */
#define REQ_FIFO_PORT_LO(xcno) (4 + ((xcno) << 3)) /* Index of the FIFO where Data packages */
/* have to be indicated by ARM which shall */
/* be sent */
#define CON_FIFO_PORT_HI(xcno) (5 + ((xcno) << 3)) /* Index of the FIFO where sent Data packages */
/* are confirmed */
#define CON_FIFO_PORT_LO(xcno) (6 + ((xcno) << 3)) /* Index of the FIFO where sent Data */
/* packages are confirmed */
#define PFIFO_MASK(xcno) (0x7f << (xcno*8))
#define FIFO_PTR_FRAMELEN_SHIFT 0
#define FIFO_PTR_FRAMELEN_MASK (0x7ff << 0)
#define FIFO_PTR_FRAMELEN(len) (((len) << 0) & FIFO_PTR_FRAMELEN_MASK)
#define FIFO_PTR_TIMETRIG (1<<11)
#define FIFO_PTR_MULTI_REQ
#define FIFO_PTR_ORIGIN (1<<14)
#define FIFO_PTR_VLAN (1<<15)
#define FIFO_PTR_FRAMENO_SHIFT 16
#define FIFO_PTR_FRAMENO_MASK (0x3f << 16)
#define FIFO_PTR_FRAMENO(no) (((no) << 16) & FIFO_PTR_FRAMENO_MASK)
#define FIFO_PTR_SEGMENT_SHIFT 22
#define FIFO_PTR_SEGMENT_MASK (0xf << 22)
#define FIFO_PTR_SEGMENT(seg) (((seg) & 0xf) << 22)
#define FIFO_PTR_ERROR_SHIFT 28
#define FIFO_PTR_ERROR_MASK (0xf << 28)
#define ISR_LINK_STATUS_CHANGE (1<<4)
#define ISR_IND_LO (1<<3)
#define ISR_CON_LO (1<<2)
#define ISR_IND_HI (1<<1)
#define ISR_CON_HI (1<<0)
#define ETH_MAC_LOCAL_CONFIG 0x1560
#define ETH_MAC_4321 0x1564
#define ETH_MAC_65 0x1568
#define MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT 16
#define MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK (0xf<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT)
#define MAC_TRAFFIC_CLASS_ARRANGEMENT(x) (((x)<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT) & MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK)
#define LOCAL_CONFIG_LINK_STATUS_IRQ_EN (1<<24)
#define LOCAL_CONFIG_CON_LO_IRQ_EN (1<<23)
#define LOCAL_CONFIG_CON_HI_IRQ_EN (1<<22)
#define LOCAL_CONFIG_IND_LO_IRQ_EN (1<<21)
#define LOCAL_CONFIG_IND_HI_IRQ_EN (1<<20)
#define CARDNAME "netx-eth"
/* LSB must be zero */
#define INTERNAL_PHY_ADR 0x1c
struct netx_eth_priv {
void __iomem *sram_base, *xpec_base, *xmac_base;
int id;
struct mii_if_info mii;
u32 msg_enable;
struct xc *xc;
spinlock_t lock;
};
static void netx_eth_set_multicast_list(struct net_device *ndev)
{
/* implement me */
}
static int
netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
struct netx_eth_priv *priv = netdev_priv(ndev);
unsigned char *buf = skb->data;
unsigned int len = skb->len;
spin_lock_irq(&priv->lock);
memcpy_toio(priv->sram_base + 1560, (void *)buf, len);
if (len < 60) {
memset_io(priv->sram_base + 1560 + len, 0, 60 - len);
len = 60;
}
pfifo_push(REQ_FIFO_PORT_LO(priv->id),
FIFO_PTR_SEGMENT(priv->id) |
FIFO_PTR_FRAMENO(1) |
FIFO_PTR_FRAMELEN(len));
ndev->stats.tx_packets++;
ndev->stats.tx_bytes += skb->len;
netif_stop_queue(ndev);
spin_unlock_irq(&priv->lock);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
static void netx_eth_receive(struct net_device *ndev)
{
struct netx_eth_priv *priv = netdev_priv(ndev);
unsigned int val, frameno, seg, len;
unsigned char *data;
struct sk_buff *skb;
val = pfifo_pop(IND_FIFO_PORT_LO(priv->id));
frameno = (val & FIFO_PTR_FRAMENO_MASK) >> FIFO_PTR_FRAMENO_SHIFT;
seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT;
len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT;
skb = netdev_alloc_skb(ndev, len);