Merge branch 'ocelot-felix-driver-cleanup'

Vladimir Oltean says:

====================
Ocelot/Felix driver cleanup

The cleanup mostly handles the statistics code path - some issues
regarding understandability became apparent after the series
"Fix trainwreck with Ocelot switch statistics counters":
https://lore.kernel.org/netdev/20230321010325.897817-1-vladimir.oltean@nxp.com/

There is also one patch which cleans up a misleading comment
in the DSA felix_setup().
====================

Link: https://lore.kernel.org/r/20230412124737.2243527-1-vladimir.oltean@nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2023-04-13 21:56:08 -07:00
commit fb4be9a4e7
5 changed files with 75 additions and 51 deletions

View File

@ -1550,11 +1550,6 @@ static int felix_connect_tag_protocol(struct dsa_switch *ds,
}
}
/* Hardware initialization done here so that we can allocate structures with
* devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing
* us to allocate structures twice (leak memory) and map PCI memory twice
* (which will not work).
*/
static int felix_setup(struct dsa_switch *ds)
{
struct ocelot *ocelot = ds->priv;

View File

@ -74,6 +74,15 @@ struct ocelot_multicast {
struct ocelot_pgid *pgid;
};
static inline void ocelot_reg_to_target_addr(struct ocelot *ocelot,
enum ocelot_reg reg,
enum ocelot_target *target,
u32 *addr)
{
*target = reg >> TARGET_OFFSET;
*addr = ocelot->map[*target][reg & REG_MASK];
}
int ocelot_bridge_num_find(struct ocelot *ocelot,
const struct net_device *bridge);

View File

@ -10,57 +10,60 @@
#include "ocelot.h"
int __ocelot_bulk_read_ix(struct ocelot *ocelot, u32 reg, u32 offset, void *buf,
int count)
int __ocelot_bulk_read_ix(struct ocelot *ocelot, enum ocelot_reg reg,
u32 offset, void *buf, int count)
{
u16 target = reg >> TARGET_OFFSET;
enum ocelot_target target;
u32 addr;
ocelot_reg_to_target_addr(ocelot, reg, &target, &addr);
WARN_ON(!target);
return regmap_bulk_read(ocelot->targets[target],
ocelot->map[target][reg & REG_MASK] + offset,
return regmap_bulk_read(ocelot->targets[target], addr + offset,
buf, count);
}
EXPORT_SYMBOL_GPL(__ocelot_bulk_read_ix);
u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset)
u32 __ocelot_read_ix(struct ocelot *ocelot, enum ocelot_reg reg, u32 offset)
{
u16 target = reg >> TARGET_OFFSET;
u32 val;
enum ocelot_target target;
u32 addr, val;
ocelot_reg_to_target_addr(ocelot, reg, &target, &addr);
WARN_ON(!target);
regmap_read(ocelot->targets[target],
ocelot->map[target][reg & REG_MASK] + offset, &val);
regmap_read(ocelot->targets[target], addr + offset, &val);
return val;
}
EXPORT_SYMBOL_GPL(__ocelot_read_ix);
void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset)
void __ocelot_write_ix(struct ocelot *ocelot, u32 val, enum ocelot_reg reg,
u32 offset)
{
u16 target = reg >> TARGET_OFFSET;
enum ocelot_target target;
u32 addr;
ocelot_reg_to_target_addr(ocelot, reg, &target, &addr);
WARN_ON(!target);
regmap_write(ocelot->targets[target],
ocelot->map[target][reg & REG_MASK] + offset, val);
regmap_write(ocelot->targets[target], addr + offset, val);
}
EXPORT_SYMBOL_GPL(__ocelot_write_ix);
void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
u32 offset)
void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask,
enum ocelot_reg reg, u32 offset)
{
u16 target = reg >> TARGET_OFFSET;
enum ocelot_target target;
u32 addr;
ocelot_reg_to_target_addr(ocelot, reg, &target, &addr);
WARN_ON(!target);
regmap_update_bits(ocelot->targets[target],
ocelot->map[target][reg & REG_MASK] + offset,
mask, val);
regmap_update_bits(ocelot->targets[target], addr + offset, mask, val);
}
EXPORT_SYMBOL_GPL(__ocelot_rmw_ix);
u32 ocelot_port_readl(struct ocelot_port *port, u32 reg)
u32 ocelot_port_readl(struct ocelot_port *port, enum ocelot_reg reg)
{
struct ocelot *ocelot = port->ocelot;
u16 target = reg >> TARGET_OFFSET;
@ -73,7 +76,7 @@ u32 ocelot_port_readl(struct ocelot_port *port, u32 reg)
}
EXPORT_SYMBOL_GPL(ocelot_port_readl);
void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg)
void ocelot_port_writel(struct ocelot_port *port, u32 val, enum ocelot_reg reg)
{
struct ocelot *ocelot = port->ocelot;
u16 target = reg >> TARGET_OFFSET;
@ -84,7 +87,8 @@ void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg)
}
EXPORT_SYMBOL_GPL(ocelot_port_writel);
void ocelot_port_rmwl(struct ocelot_port *port, u32 val, u32 mask, u32 reg)
void ocelot_port_rmwl(struct ocelot_port *port, u32 val, u32 mask,
enum ocelot_reg reg)
{
u32 cur = ocelot_port_readl(port, reg);

View File

@ -145,7 +145,7 @@ enum ocelot_stat {
};
struct ocelot_stat_layout {
u32 reg;
enum ocelot_reg reg;
char name[ETH_GSTRING_LEN];
};
@ -257,7 +257,7 @@ struct ocelot_stat_layout {
struct ocelot_stats_region {
struct list_head node;
u32 base;
enum ocelot_reg base;
enum ocelot_stat first_stat;
int count;
u32 *buf;
@ -395,7 +395,7 @@ static void ocelot_check_stats_work(struct work_struct *work)
void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data)
{
const struct ocelot_stat_layout *layout;
int i;
enum ocelot_stat i;
if (sset != ETH_SS_STATS)
return;
@ -442,7 +442,8 @@ out_unlock:
int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset)
{
const struct ocelot_stat_layout *layout;
int i, num_stats = 0;
enum ocelot_stat i;
int num_stats = 0;
if (sset != ETH_SS_STATS)
return -EOPNOTSUPP;
@ -461,8 +462,8 @@ static void ocelot_port_ethtool_stats_cb(struct ocelot *ocelot, int port,
void *priv)
{
const struct ocelot_stat_layout *layout;
enum ocelot_stat i;
u64 *data = priv;
int i;
layout = ocelot_get_stats_layout(ocelot);
@ -889,8 +890,8 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
{
struct ocelot_stats_region *region = NULL;
const struct ocelot_stat_layout *layout;
unsigned int last = 0;
int i;
enum ocelot_reg last = 0;
enum ocelot_stat i;
INIT_LIST_HEAD(&ocelot->stats_regions);
@ -900,6 +901,17 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
if (!layout[i].reg)
continue;
/* enum ocelot_stat must be kept sorted in the same order
* as the addresses behind layout[i].reg in order to have
* efficient bulking
*/
if (last) {
WARN(ocelot->map[SYS][last & REG_MASK] >= ocelot->map[SYS][layout[i].reg & REG_MASK],
"reg 0x%x had address 0x%x but reg 0x%x has address 0x%x, bulking broken!",
last, ocelot->map[SYS][last & REG_MASK],
layout[i].reg, ocelot->map[SYS][layout[i].reg & REG_MASK]);
}
if (region && ocelot->map[SYS][layout[i].reg & REG_MASK] ==
ocelot->map[SYS][last & REG_MASK] + 4) {
region->count++;
@ -909,12 +921,6 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
if (!region)
return -ENOMEM;
/* enum ocelot_stat must be kept sorted in the same
* order as layout[i].reg in order to have efficient
* bulking
*/
WARN_ON(last >= layout[i].reg);
region->base = layout[i].reg;
region->first_stat = i;
region->count = 1;
@ -925,6 +931,15 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
}
list_for_each_entry(region, &ocelot->stats_regions, node) {
enum ocelot_target target;
u32 addr;
ocelot_reg_to_target_addr(ocelot, region->base, &target,
&addr);
dev_dbg(ocelot->dev,
"region of %d contiguous counters starting with SYS:STAT:CNT[0x%03x]\n",
region->count, addr / 4);
region->buf = devm_kcalloc(ocelot->dev, region->count,
sizeof(*region->buf), GFP_KERNEL);
if (!region->buf)
@ -972,4 +987,3 @@ void ocelot_stats_deinit(struct ocelot *ocelot)
cancel_delayed_work(&ocelot->stats_work);
destroy_workqueue(ocelot->stats_queue);
}

View File

@ -940,15 +940,17 @@ struct ocelot_policer {
__ocelot_target_write_ix(ocelot, target, val, reg, 0)
/* I/O */
u32 ocelot_port_readl(struct ocelot_port *port, u32 reg);
void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg);
void ocelot_port_rmwl(struct ocelot_port *port, u32 val, u32 mask, u32 reg);
int __ocelot_bulk_read_ix(struct ocelot *ocelot, u32 reg, u32 offset, void *buf,
int count);
u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset);
void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset);
void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
u32 offset);
u32 ocelot_port_readl(struct ocelot_port *port, enum ocelot_reg reg);
void ocelot_port_writel(struct ocelot_port *port, u32 val, enum ocelot_reg reg);
void ocelot_port_rmwl(struct ocelot_port *port, u32 val, u32 mask,
enum ocelot_reg reg);
int __ocelot_bulk_read_ix(struct ocelot *ocelot, enum ocelot_reg reg,
u32 offset, void *buf, int count);
u32 __ocelot_read_ix(struct ocelot *ocelot, enum ocelot_reg reg, u32 offset);
void __ocelot_write_ix(struct ocelot *ocelot, u32 val, enum ocelot_reg reg,
u32 offset);
void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask,
enum ocelot_reg reg, u32 offset);
u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target,
u32 reg, u32 offset);
void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target,