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:
commit
fb4be9a4e7
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue