Commit fb4be9a4 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

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: default avatarJakub Kicinski <kuba@kernel.org>
parents c2865b11 a291399e
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -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;
+9 −0
Original line number Diff line number Diff line
@@ -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);

+27 −23
Original line number Diff line number Diff line
@@ -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);

+28 −14
Original line number Diff line number Diff line
@@ -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 @@ static void ocelot_port_stats_run(struct ocelot *ocelot, int port, void *priv,
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);
}
+11 −9
Original line number Diff line number Diff line
@@ -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 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,