Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8c9983a2 authored by Vivien Didelot's avatar Vivien Didelot Committed by David S. Miller
Browse files

net: dsa: mv88e6xxx: factorize PHY access with PPU



Add a MV88E6XXX_FLAG_PPU flag to describe switch models with a PHY
Polling Unit. This allows to merge PPU specific PHY access code in the
share code.

Make the mv88e6xxx_ppu_disable and mv88e6xxx_phy_{read,write}_ppu
functions use unlocked register accesses in order to call them in
mv88e6xxx_phy_{read,write} in a locked context.

Since the PPU code is shared, also remove NET_DSA_MV88E6XXX_NEED_PPU.

Signed-off-by: default avatarVivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b5058d7a
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -13,15 +13,10 @@ config NET_DSA_MV88E6060
	  This enables support for the Marvell 88E6060 ethernet switch
	  chip.

config NET_DSA_MV88E6XXX_NEED_PPU
	bool
	default n

config NET_DSA_MV88E6131
	tristate "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support"
	depends on NET_DSA
	select NET_DSA_MV88E6XXX
	select NET_DSA_MV88E6XXX_NEED_PPU
	select NET_DSA_TAG_DSA
	---help---
	  This enables support for the Marvell 88E6085/6095/6095F/6131
+2 −37
Original line number Diff line number Diff line
@@ -132,8 +132,6 @@ static int mv88e6131_setup(struct dsa_switch *ds)
	if (ret < 0)
		return ret;

	mv88e6xxx_ppu_state_init(ps);

	ret = mv88e6xxx_switch_reset(ps, false);
	if (ret < 0)
		return ret;
@@ -145,46 +143,13 @@ static int mv88e6131_setup(struct dsa_switch *ds)
	return mv88e6xxx_setup_ports(ds);
}

static int mv88e6131_port_to_phy_addr(struct dsa_switch *ds, int port)
{
	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);

	if (port >= 0 && port < ps->info->num_ports)
		return port;

	return -EINVAL;
}

static int
mv88e6131_phy_read(struct dsa_switch *ds, int port, int regnum)
{
	int addr = mv88e6131_port_to_phy_addr(ds, port);

	if (addr < 0)
		return addr;

	return mv88e6xxx_phy_read_ppu(ds, addr, regnum);
}

static int
mv88e6131_phy_write(struct dsa_switch *ds,
			      int port, int regnum, u16 val)
{
	int addr = mv88e6131_port_to_phy_addr(ds, port);

	if (addr < 0)
		return addr;

	return mv88e6xxx_phy_write_ppu(ds, addr, regnum, val);
}

struct dsa_switch_driver mv88e6131_switch_driver = {
	.tag_protocol		= DSA_TAG_PROTO_DSA,
	.probe			= mv88e6131_drv_probe,
	.setup			= mv88e6131_setup,
	.set_addr		= mv88e6xxx_set_addr_direct,
	.phy_read		= mv88e6131_phy_read,
	.phy_write		= mv88e6131_phy_write,
	.phy_read		= mv88e6xxx_phy_read,
	.phy_write		= mv88e6xxx_phy_write,
	.get_strings		= mv88e6xxx_get_strings,
	.get_ethtool_stats	= mv88e6xxx_get_ethtool_stats,
	.get_sset_count		= mv88e6xxx_get_sset_count,
+25 −15
Original line number Diff line number Diff line
@@ -241,24 +241,23 @@ static int _mv88e6xxx_phy_write(struct mv88e6xxx_priv_state *ps, int addr,
	return 0;
}

#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
static int mv88e6xxx_ppu_disable(struct mv88e6xxx_priv_state *ps)
{
	int ret;
	unsigned long timeout;

	ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);
	ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);
	if (ret < 0)
		return ret;

	ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
	ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
				   ret & ~GLOBAL_CONTROL_PPU_ENABLE);
	if (ret)
		return ret;

	timeout = jiffies + 1 * HZ;
	while (time_before(jiffies, timeout)) {
		ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS);
		ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS);
		if (ret < 0)
			return ret;

@@ -361,35 +360,33 @@ void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps)
	ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
}

int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
static int mv88e6xxx_phy_read_ppu(struct mv88e6xxx_priv_state *ps, int addr,
				  int regnum)
{
	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
	int ret;

	ret = mv88e6xxx_ppu_access_get(ps);
	if (ret >= 0) {
		ret = mv88e6xxx_reg_read(ps, addr, regnum);
		ret = _mv88e6xxx_reg_read(ps, addr, regnum);
		mv88e6xxx_ppu_access_put(ps);
	}

	return ret;
}

int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
static int mv88e6xxx_phy_write_ppu(struct mv88e6xxx_priv_state *ps, int addr,
				   int regnum, u16 val)
{
	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
	int ret;

	ret = mv88e6xxx_ppu_access_get(ps);
	if (ret >= 0) {
		ret = mv88e6xxx_reg_write(ps, addr, regnum, val);
		ret = _mv88e6xxx_reg_write(ps, addr, regnum, val);
		mv88e6xxx_ppu_access_put(ps);
	}

	return ret;
}
#endif

static bool mv88e6xxx_6065_family(struct mv88e6xxx_priv_state *ps)
{
@@ -2599,6 +2596,9 @@ int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)

	INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);

	if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
		mv88e6xxx_ppu_state_init(ps);

	return 0;
}

@@ -2884,7 +2884,12 @@ mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
		return 0xffff;

	mutex_lock(&ps->smi_mutex);

	if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
		ret = mv88e6xxx_phy_read_ppu(ps, addr, regnum);
	else
		ret = _mv88e6xxx_phy_read(ps, addr, regnum);

	mutex_unlock(&ps->smi_mutex);
	return ret;
}
@@ -2900,7 +2905,12 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
		return 0xffff;

	mutex_lock(&ps->smi_mutex);

	if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
		ret = mv88e6xxx_phy_write_ppu(ps, addr, regnum, val);
	else
		ret = _mv88e6xxx_phy_write(ps, addr, regnum, val);

	mutex_unlock(&ps->smi_mutex);
	return ret;
}
+16 −9
Original line number Diff line number Diff line
@@ -350,13 +350,26 @@ enum mv88e6xxx_family {
	MV88E6XXX_FAMILY_6352,	/* 6172 6176 6240 6352 */
};

#define MV88E6XXX_FLAGS_FAMILY_6095	0
enum mv88e6xxx_cap {
	/* PHY Polling Unit.
	 * See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
	 */
	MV88E6XXX_CAP_PPU,
};

/* Bitmask of capabilities */
#define MV88E6XXX_FLAG_PPU		BIT(MV88E6XXX_CAP_PPU)

#define MV88E6XXX_FLAGS_FAMILY_6097	0
#define MV88E6XXX_FLAGS_FAMILY_6095	\
	MV88E6XXX_FLAG_PPU

#define MV88E6XXX_FLAGS_FAMILY_6097	\
	MV88E6XXX_FLAG_PPU

#define MV88E6XXX_FLAGS_FAMILY_6165	0

#define MV88E6XXX_FLAGS_FAMILY_6185	0
#define MV88E6XXX_FLAGS_FAMILY_6185	\
	MV88E6XXX_FLAG_PPU

#define MV88E6XXX_FLAGS_FAMILY_6320	0

@@ -418,7 +431,6 @@ struct mv88e6xxx_priv_state {
	struct mii_bus *bus;
	int sw_addr;

#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
	/* Handles automatic disabling and re-enabling of the PHY
	 * polling unit.
	 */
@@ -426,7 +438,6 @@ struct mv88e6xxx_priv_state {
	int			ppu_disabled;
	struct work_struct	ppu_work;
	struct timer_list	ppu_timer;
#endif

	/* This mutex serialises access to the statistics unit.
	 * Hold this mutex over snapshot + dump sequences.
@@ -489,10 +500,6 @@ int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val);
int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum);
int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
				 u16 val);
void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps);
int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum);
int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
			    int regnum, u16 val);
void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data);
void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
				 uint64_t *data);