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: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
b5058d7a30
Коммит
8c9983a224
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 & ~GLOBAL_CONTROL_PPU_ENABLE);
|
||||
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,
|
||||
int regnum, u16 val)
|
||||
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);
|
||||
ret = _mv88e6xxx_phy_read(ps, addr, regnum);
|
||||
|
||||
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);
|
||||
ret = _mv88e6xxx_phy_write(ps, addr, regnum, val);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
#define MV88E6XXX_FLAGS_FAMILY_6097 0
|
||||
/* Bitmask of capabilities */
|
||||
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
|
||||
|
||||
#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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче