goto err_alloc_stats;
}
- mlxsw_sp_port->sample = kzalloc(sizeof(*mlxsw_sp_port->sample),
- GFP_KERNEL);
- if (!mlxsw_sp_port->sample) {
- err = -ENOMEM;
- goto err_alloc_sample;
- }
-
INIT_DELAYED_WORK(&mlxsw_sp_port->periodic_hw_stats.update_dw,
&update_stats_cache);
err_port_swid_set:
mlxsw_sp_port_module_unmap(mlxsw_sp_port);
err_port_module_map:
- kfree(mlxsw_sp_port->sample);
-err_alloc_sample:
free_percpu(mlxsw_sp_port->pcpu_stats);
err_alloc_stats:
free_netdev(dev);
mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, false);
mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT);
mlxsw_sp_port_module_unmap(mlxsw_sp_port);
- kfree(mlxsw_sp_port->sample);
free_percpu(mlxsw_sp_port->pcpu_stats);
WARN_ON_ONCE(!list_empty(&mlxsw_sp_port->vlans_list));
free_netdev(mlxsw_sp_port->dev);
{
struct mlxsw_sp *mlxsw_sp = priv;
struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
- struct psample_group *psample_group;
+ struct mlxsw_sp_port_sample *sample;
u32 size;
if (unlikely(!mlxsw_sp_port)) {
local_port);
goto out;
}
- if (unlikely(!mlxsw_sp_port->sample)) {
- dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: sample skb received on unsupported port\n",
- local_port);
- goto out;
- }
-
- size = mlxsw_sp_port->sample->truncate ?
- mlxsw_sp_port->sample->trunc_size : skb->len;
rcu_read_lock();
- psample_group = rcu_dereference(mlxsw_sp_port->sample->psample_group);
- if (!psample_group)
+ sample = rcu_dereference(mlxsw_sp_port->sample);
+ if (!sample)
goto out_unlock;
- psample_sample_packet(psample_group, skb, size,
- mlxsw_sp_port->dev->ifindex, 0,
- mlxsw_sp_port->sample->rate);
+ size = sample->truncate ? sample->trunc_size : skb->len;
+ psample_sample_packet(sample->psample_group, skb, size,
+ mlxsw_sp_port->dev->ifindex, 0, sample->rate);
out_unlock:
rcu_read_unlock();
out:
};
struct mlxsw_sp_port_sample {
- struct psample_group __rcu *psample_group;
+ struct psample_group *psample_group;
u32 trunc_size;
u32 rate;
bool truncate;
struct mlxsw_sp_port_xstats xstats;
struct delayed_work update_dw;
} periodic_hw_stats;
- struct mlxsw_sp_port_sample *sample;
+ struct mlxsw_sp_port_sample __rcu *sample;
struct list_head vlans_list;
struct mlxsw_sp_port_vlan *default_vlan;
struct mlxsw_sp_qdisc_state *qdisc;
struct mlxsw_sp_mall_mirror_entry mirror;
struct mlxsw_sp_port_sample sample;
};
+ struct rcu_head rcu;
};
static struct mlxsw_sp_mall_entry *
{
int err;
- if (!mlxsw_sp_port->sample)
- return -EOPNOTSUPP;
- if (rtnl_dereference(mlxsw_sp_port->sample->psample_group)) {
+ if (rtnl_dereference(mlxsw_sp_port->sample)) {
netdev_err(mlxsw_sp_port->dev, "sample already active\n");
return -EEXIST;
}
- rcu_assign_pointer(mlxsw_sp_port->sample->psample_group,
- mall_entry->sample.psample_group);
- mlxsw_sp_port->sample->truncate = mall_entry->sample.truncate;
- mlxsw_sp_port->sample->trunc_size = mall_entry->sample.trunc_size;
- mlxsw_sp_port->sample->rate = mall_entry->sample.rate;
+ rcu_assign_pointer(mlxsw_sp_port->sample, &mall_entry->sample);
err = mlxsw_sp_mall_port_sample_set(mlxsw_sp_port, true,
mall_entry->sample.rate);
return 0;
err_port_sample_set:
- RCU_INIT_POINTER(mlxsw_sp_port->sample->psample_group, NULL);
+ RCU_INIT_POINTER(mlxsw_sp_port->sample, NULL);
return err;
}
return;
mlxsw_sp_mall_port_sample_set(mlxsw_sp_port, false, 1);
- RCU_INIT_POINTER(mlxsw_sp_port->sample->psample_group, NULL);
+ RCU_INIT_POINTER(mlxsw_sp_port->sample, NULL);
}
static int
mlxsw_sp_mall_port_rule_del(mlxsw_sp_port, mall_entry);
list_del(&mall_entry->list);
- kfree(mall_entry);
+ kfree_rcu(mall_entry, rcu); /* sample RX packets may be in-flight */
}