forked from Minki/linux
Merge branch 'dsa-mv88e6xxx-switch-factorization'
Vivien Didelot says:
====================
net: dsa: mv88e6xxx: factorize switch info
This patchset factorizes the mv88e6xxx code by sharing a new extendable
info structure to store static data such as switch family, product
number, number of ports, number of databases and the name.
The next step is to add a "flags" bitmap member to the info structure in
order to simplify the shared code with a feature-based logic instead of
checking their family/ID.
This is a step forward having a single mv88e6xxx driver supporting many
similar devices, like any usual Linux driver.
Changes v3 -> v4:
- constify probed name in DSA
- rebase patchset above conflicting commit 48ace4e
Changes v2 -> v3:
- update commit messages and add Andrew's tags
- keep the info lookup code in a separated function
- split the single switch ID reading in probe in a new commit
Changes v1 -> v2:
- define PORT_SWITCH_ID_PROD_NUM_* values
- use plain struct mv88e6xxx_info
- remove non used yet ps->rev
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ccd37cffe3
@ -135,9 +135,9 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds)
|
||||
return BCM_SF2_STATS_SIZE;
|
||||
}
|
||||
|
||||
static char *bcm_sf2_sw_drv_probe(struct device *dsa_dev,
|
||||
struct device *host_dev,
|
||||
int sw_addr, void **_priv)
|
||||
static const char *bcm_sf2_sw_drv_probe(struct device *dsa_dev,
|
||||
struct device *host_dev, int sw_addr,
|
||||
void **_priv)
|
||||
{
|
||||
struct bcm_sf2_priv *priv;
|
||||
|
||||
|
@ -51,7 +51,7 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
|
||||
return __ret; \
|
||||
})
|
||||
|
||||
static char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr)
|
||||
static const char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -69,13 +69,13 @@ static char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *mv88e6060_drv_probe(struct device *dsa_dev,
|
||||
struct device *host_dev,
|
||||
int sw_addr, void **_priv)
|
||||
static const char *mv88e6060_drv_probe(struct device *dsa_dev,
|
||||
struct device *host_dev, int sw_addr,
|
||||
void **_priv)
|
||||
{
|
||||
struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
|
||||
struct mv88e6060_priv *priv;
|
||||
char *name;
|
||||
const char *name;
|
||||
|
||||
name = mv88e6060_get_name(bus, sw_addr);
|
||||
if (name) {
|
||||
|
@ -17,21 +17,31 @@
|
||||
#include <net/dsa.h>
|
||||
#include "mv88e6xxx.h"
|
||||
|
||||
static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
|
||||
{ PORT_SWITCH_ID_6123, "Marvell 88E6123" },
|
||||
{ PORT_SWITCH_ID_6123_A1, "Marvell 88E6123 (A1)" },
|
||||
{ PORT_SWITCH_ID_6123_A2, "Marvell 88E6123 (A2)" },
|
||||
{ PORT_SWITCH_ID_6161, "Marvell 88E6161" },
|
||||
{ PORT_SWITCH_ID_6161_A1, "Marvell 88E6161 (A1)" },
|
||||
{ PORT_SWITCH_ID_6161_A2, "Marvell 88E6161 (A2)" },
|
||||
{ PORT_SWITCH_ID_6165, "Marvell 88E6165" },
|
||||
{ PORT_SWITCH_ID_6165_A1, "Marvell 88E6165 (A1)" },
|
||||
{ PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" },
|
||||
static const struct mv88e6xxx_info mv88e6123_table[] = {
|
||||
{
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6123,
|
||||
.family = MV88E6XXX_FAMILY_6165,
|
||||
.name = "Marvell 88E6123",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 3,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6161,
|
||||
.family = MV88E6XXX_FAMILY_6165,
|
||||
.name = "Marvell 88E6161",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 6,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6165,
|
||||
.family = MV88E6XXX_FAMILY_6165,
|
||||
.name = "Marvell 88E6165",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 6,
|
||||
}
|
||||
};
|
||||
|
||||
static char *mv88e6123_drv_probe(struct device *dsa_dev,
|
||||
struct device *host_dev,
|
||||
int sw_addr, void **priv)
|
||||
static const char *mv88e6123_drv_probe(struct device *dsa_dev,
|
||||
struct device *host_dev, int sw_addr,
|
||||
void **priv)
|
||||
{
|
||||
return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
|
||||
mv88e6123_table,
|
||||
@ -76,27 +86,12 @@ static int mv88e6123_setup_global(struct dsa_switch *ds)
|
||||
|
||||
static int mv88e6123_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
int ret;
|
||||
|
||||
ps->ds = ds;
|
||||
|
||||
ret = mv88e6xxx_setup_common(ds);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (ps->id) {
|
||||
case PORT_SWITCH_ID_6123:
|
||||
ps->num_ports = 3;
|
||||
break;
|
||||
case PORT_SWITCH_ID_6161:
|
||||
case PORT_SWITCH_ID_6165:
|
||||
ps->num_ports = 6;
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = mv88e6xxx_switch_reset(ds, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -17,17 +17,37 @@
|
||||
#include <net/dsa.h>
|
||||
#include "mv88e6xxx.h"
|
||||
|
||||
static const struct mv88e6xxx_switch_id mv88e6131_table[] = {
|
||||
{ PORT_SWITCH_ID_6085, "Marvell 88E6085" },
|
||||
{ PORT_SWITCH_ID_6095, "Marvell 88E6095/88E6095F" },
|
||||
{ PORT_SWITCH_ID_6131, "Marvell 88E6131" },
|
||||
{ PORT_SWITCH_ID_6131_B2, "Marvell 88E6131 (B2)" },
|
||||
{ PORT_SWITCH_ID_6185, "Marvell 88E6185" },
|
||||
static const struct mv88e6xxx_info mv88e6131_table[] = {
|
||||
{
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6095,
|
||||
.family = MV88E6XXX_FAMILY_6095,
|
||||
.name = "Marvell 88E6095/88E6095F",
|
||||
.num_databases = 256,
|
||||
.num_ports = 11,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6085,
|
||||
.family = MV88E6XXX_FAMILY_6097,
|
||||
.name = "Marvell 88E6085",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 10,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6131,
|
||||
.family = MV88E6XXX_FAMILY_6185,
|
||||
.name = "Marvell 88E6131",
|
||||
.num_databases = 256,
|
||||
.num_ports = 8,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6185,
|
||||
.family = MV88E6XXX_FAMILY_6185,
|
||||
.name = "Marvell 88E6185",
|
||||
.num_databases = 256,
|
||||
.num_ports = 10,
|
||||
}
|
||||
};
|
||||
|
||||
static char *mv88e6131_drv_probe(struct device *dsa_dev,
|
||||
struct device *host_dev,
|
||||
int sw_addr, void **priv)
|
||||
static const char *mv88e6131_drv_probe(struct device *dsa_dev,
|
||||
struct device *host_dev, int sw_addr,
|
||||
void **priv)
|
||||
{
|
||||
return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
|
||||
mv88e6131_table,
|
||||
@ -98,33 +118,14 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
|
||||
|
||||
static int mv88e6131_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
int ret;
|
||||
|
||||
ps->ds = ds;
|
||||
|
||||
ret = mv88e6xxx_setup_common(ds);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mv88e6xxx_ppu_state_init(ds);
|
||||
|
||||
switch (ps->id) {
|
||||
case PORT_SWITCH_ID_6085:
|
||||
case PORT_SWITCH_ID_6185:
|
||||
ps->num_ports = 10;
|
||||
break;
|
||||
case PORT_SWITCH_ID_6095:
|
||||
ps->num_ports = 11;
|
||||
break;
|
||||
case PORT_SWITCH_ID_6131:
|
||||
case PORT_SWITCH_ID_6131_B2:
|
||||
ps->num_ports = 8;
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = mv88e6xxx_switch_reset(ds, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -140,7 +141,7 @@ 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->num_ports)
|
||||
if (port >= 0 && port < ps->info->num_ports)
|
||||
return port;
|
||||
|
||||
return -EINVAL;
|
||||
|
@ -17,16 +17,37 @@
|
||||
#include <net/dsa.h>
|
||||
#include "mv88e6xxx.h"
|
||||
|
||||
static const struct mv88e6xxx_switch_id mv88e6171_table[] = {
|
||||
{ PORT_SWITCH_ID_6171, "Marvell 88E6171" },
|
||||
{ PORT_SWITCH_ID_6175, "Marvell 88E6175" },
|
||||
{ PORT_SWITCH_ID_6350, "Marvell 88E6350" },
|
||||
{ PORT_SWITCH_ID_6351, "Marvell 88E6351" },
|
||||
static const struct mv88e6xxx_info mv88e6171_table[] = {
|
||||
{
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6171,
|
||||
.family = MV88E6XXX_FAMILY_6351,
|
||||
.name = "Marvell 88E6171",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 7,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6175,
|
||||
.family = MV88E6XXX_FAMILY_6351,
|
||||
.name = "Marvell 88E6175",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 7,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6350,
|
||||
.family = MV88E6XXX_FAMILY_6351,
|
||||
.name = "Marvell 88E6350",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 7,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6351,
|
||||
.family = MV88E6XXX_FAMILY_6351,
|
||||
.name = "Marvell 88E6351",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 7,
|
||||
}
|
||||
};
|
||||
|
||||
static char *mv88e6171_drv_probe(struct device *dsa_dev,
|
||||
struct device *host_dev,
|
||||
int sw_addr, void **priv)
|
||||
static const char *mv88e6171_drv_probe(struct device *dsa_dev,
|
||||
struct device *host_dev, int sw_addr,
|
||||
void **priv)
|
||||
{
|
||||
return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
|
||||
mv88e6171_table,
|
||||
@ -73,17 +94,12 @@ static int mv88e6171_setup_global(struct dsa_switch *ds)
|
||||
|
||||
static int mv88e6171_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
int ret;
|
||||
|
||||
ps->ds = ds;
|
||||
|
||||
ret = mv88e6xxx_setup_common(ds);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ps->num_ports = 7;
|
||||
|
||||
ret = mv88e6xxx_switch_reset(ds, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -22,24 +22,49 @@
|
||||
#include <net/dsa.h>
|
||||
#include "mv88e6xxx.h"
|
||||
|
||||
static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
|
||||
{ PORT_SWITCH_ID_6172, "Marvell 88E6172" },
|
||||
{ PORT_SWITCH_ID_6176, "Marvell 88E6176" },
|
||||
{ PORT_SWITCH_ID_6240, "Marvell 88E6240" },
|
||||
{ PORT_SWITCH_ID_6320, "Marvell 88E6320" },
|
||||
{ PORT_SWITCH_ID_6320_A1, "Marvell 88E6320 (A1)" },
|
||||
{ PORT_SWITCH_ID_6320_A2, "Marvell 88e6320 (A2)" },
|
||||
{ PORT_SWITCH_ID_6321, "Marvell 88E6321" },
|
||||
{ PORT_SWITCH_ID_6321_A1, "Marvell 88E6321 (A1)" },
|
||||
{ PORT_SWITCH_ID_6321_A2, "Marvell 88e6321 (A2)" },
|
||||
{ PORT_SWITCH_ID_6352, "Marvell 88E6352" },
|
||||
{ PORT_SWITCH_ID_6352_A0, "Marvell 88E6352 (A0)" },
|
||||
{ PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" },
|
||||
static const struct mv88e6xxx_info mv88e6352_table[] = {
|
||||
{
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6320,
|
||||
.family = MV88E6XXX_FAMILY_6320,
|
||||
.name = "Marvell 88E6320",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 7,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6321,
|
||||
.family = MV88E6XXX_FAMILY_6320,
|
||||
.name = "Marvell 88E6321",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 7,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6172,
|
||||
.family = MV88E6XXX_FAMILY_6352,
|
||||
.name = "Marvell 88E6172",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 7,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6176,
|
||||
.family = MV88E6XXX_FAMILY_6352,
|
||||
.name = "Marvell 88E6176",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 7,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6240,
|
||||
.family = MV88E6XXX_FAMILY_6352,
|
||||
.name = "Marvell 88E6240",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 7,
|
||||
}, {
|
||||
.prod_num = PORT_SWITCH_ID_PROD_NUM_6352,
|
||||
.family = MV88E6XXX_FAMILY_6352,
|
||||
.name = "Marvell 88E6352",
|
||||
.num_databases = 4096,
|
||||
.num_ports = 7,
|
||||
}
|
||||
};
|
||||
|
||||
static char *mv88e6352_drv_probe(struct device *dsa_dev,
|
||||
struct device *host_dev,
|
||||
int sw_addr, void **priv)
|
||||
static const char *mv88e6352_drv_probe(struct device *dsa_dev,
|
||||
struct device *host_dev, int sw_addr,
|
||||
void **priv)
|
||||
{
|
||||
return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
|
||||
mv88e6352_table,
|
||||
@ -87,14 +112,10 @@ static int mv88e6352_setup(struct dsa_switch *ds)
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
int ret;
|
||||
|
||||
ps->ds = ds;
|
||||
|
||||
ret = mv88e6xxx_setup_common(ds);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ps->num_ports = 7;
|
||||
|
||||
mutex_init(&ps->eeprom_mutex);
|
||||
|
||||
ret = mv88e6xxx_switch_reset(ds, true);
|
||||
|
@ -402,135 +402,63 @@ static bool mv88e6xxx_6065_family(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
||||
switch (ps->id) {
|
||||
case PORT_SWITCH_ID_6031:
|
||||
case PORT_SWITCH_ID_6061:
|
||||
case PORT_SWITCH_ID_6035:
|
||||
case PORT_SWITCH_ID_6065:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return ps->info->family == MV88E6XXX_FAMILY_6065;
|
||||
}
|
||||
|
||||
static bool mv88e6xxx_6095_family(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
||||
switch (ps->id) {
|
||||
case PORT_SWITCH_ID_6092:
|
||||
case PORT_SWITCH_ID_6095:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return ps->info->family == MV88E6XXX_FAMILY_6095;
|
||||
}
|
||||
|
||||
static bool mv88e6xxx_6097_family(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
||||
switch (ps->id) {
|
||||
case PORT_SWITCH_ID_6046:
|
||||
case PORT_SWITCH_ID_6085:
|
||||
case PORT_SWITCH_ID_6096:
|
||||
case PORT_SWITCH_ID_6097:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return ps->info->family == MV88E6XXX_FAMILY_6097;
|
||||
}
|
||||
|
||||
static bool mv88e6xxx_6165_family(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
||||
switch (ps->id) {
|
||||
case PORT_SWITCH_ID_6123:
|
||||
case PORT_SWITCH_ID_6161:
|
||||
case PORT_SWITCH_ID_6165:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return ps->info->family == MV88E6XXX_FAMILY_6165;
|
||||
}
|
||||
|
||||
static bool mv88e6xxx_6185_family(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
||||
switch (ps->id) {
|
||||
case PORT_SWITCH_ID_6121:
|
||||
case PORT_SWITCH_ID_6122:
|
||||
case PORT_SWITCH_ID_6152:
|
||||
case PORT_SWITCH_ID_6155:
|
||||
case PORT_SWITCH_ID_6182:
|
||||
case PORT_SWITCH_ID_6185:
|
||||
case PORT_SWITCH_ID_6108:
|
||||
case PORT_SWITCH_ID_6131:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return ps->info->family == MV88E6XXX_FAMILY_6185;
|
||||
}
|
||||
|
||||
static bool mv88e6xxx_6320_family(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
||||
switch (ps->id) {
|
||||
case PORT_SWITCH_ID_6320:
|
||||
case PORT_SWITCH_ID_6321:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return ps->info->family == MV88E6XXX_FAMILY_6320;
|
||||
}
|
||||
|
||||
static bool mv88e6xxx_6351_family(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
||||
switch (ps->id) {
|
||||
case PORT_SWITCH_ID_6171:
|
||||
case PORT_SWITCH_ID_6175:
|
||||
case PORT_SWITCH_ID_6350:
|
||||
case PORT_SWITCH_ID_6351:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return ps->info->family == MV88E6XXX_FAMILY_6351;
|
||||
}
|
||||
|
||||
static bool mv88e6xxx_6352_family(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
||||
switch (ps->id) {
|
||||
case PORT_SWITCH_ID_6172:
|
||||
case PORT_SWITCH_ID_6176:
|
||||
case PORT_SWITCH_ID_6240:
|
||||
case PORT_SWITCH_ID_6352:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return ps->info->family == MV88E6XXX_FAMILY_6352;
|
||||
}
|
||||
|
||||
static unsigned int mv88e6xxx_num_databases(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
||||
/* The following devices have 4-bit identifiers for 16 databases */
|
||||
if (ps->id == PORT_SWITCH_ID_6061)
|
||||
return 16;
|
||||
|
||||
/* The following devices have 6-bit identifiers for 64 databases */
|
||||
if (ps->id == PORT_SWITCH_ID_6065)
|
||||
return 64;
|
||||
|
||||
/* The following devices have 8-bit identifiers for 256 databases */
|
||||
if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds))
|
||||
return 256;
|
||||
|
||||
/* The following devices have 12-bit identifiers for 4096 databases */
|
||||
if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) ||
|
||||
mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds))
|
||||
return 4096;
|
||||
|
||||
return 0;
|
||||
return ps->info->num_databases;
|
||||
}
|
||||
|
||||
static bool mv88e6xxx_has_fid_reg(struct dsa_switch *ds)
|
||||
@ -606,7 +534,7 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
|
||||
reg |= PORT_PCS_CTRL_DUPLEX_FULL;
|
||||
|
||||
if ((mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds)) &&
|
||||
(port >= ps->num_ports - 2)) {
|
||||
(port >= ps->info->num_ports - 2)) {
|
||||
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
|
||||
reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
|
||||
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
|
||||
@ -1187,7 +1115,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
struct net_device *bridge = ps->ports[port].bridge_dev;
|
||||
const u16 mask = (1 << ps->num_ports) - 1;
|
||||
const u16 mask = (1 << ps->info->num_ports) - 1;
|
||||
u16 output_ports = 0;
|
||||
int reg;
|
||||
int i;
|
||||
@ -1196,7 +1124,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port)
|
||||
if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
|
||||
output_ports = mask;
|
||||
} else {
|
||||
for (i = 0; i < ps->num_ports; ++i) {
|
||||
for (i = 0; i < ps->info->num_ports; ++i) {
|
||||
/* allow sending frames to every group member */
|
||||
if (bridge && ps->ports[i].bridge_dev == bridge)
|
||||
output_ports |= BIT(i);
|
||||
@ -1337,7 +1265,7 @@ static int _mv88e6xxx_vtu_stu_data_read(struct dsa_switch *ds,
|
||||
regs[i] = ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ps->num_ports; ++i) {
|
||||
for (i = 0; i < ps->info->num_ports; ++i) {
|
||||
unsigned int shift = (i % 4) * 4 + nibble_offset;
|
||||
u16 reg = regs[i / 4];
|
||||
|
||||
@ -1356,7 +1284,7 @@ static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds,
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < ps->num_ports; ++i) {
|
||||
for (i = 0; i < ps->info->num_ports; ++i) {
|
||||
unsigned int shift = (i % 4) * 4 + nibble_offset;
|
||||
u8 data = entry->data[i];
|
||||
|
||||
@ -1688,7 +1616,7 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
|
||||
bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
|
||||
|
||||
/* Set every FID bit used by the (un)bridged ports */
|
||||
for (i = 0; i < ps->num_ports; ++i) {
|
||||
for (i = 0; i < ps->info->num_ports; ++i) {
|
||||
err = _mv88e6xxx_port_fid_get(ds, i, fid);
|
||||
if (err)
|
||||
return err;
|
||||
@ -1738,7 +1666,7 @@ static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid,
|
||||
return err;
|
||||
|
||||
/* exclude all ports except the CPU and DSA ports */
|
||||
for (i = 0; i < ps->num_ports; ++i)
|
||||
for (i = 0; i < ps->info->num_ports; ++i)
|
||||
vlan.data[i] = dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)
|
||||
? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED
|
||||
: GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
|
||||
@ -1827,7 +1755,7 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
|
||||
if (vlan.vid > vid_end)
|
||||
break;
|
||||
|
||||
for (i = 0; i < ps->num_ports; ++i) {
|
||||
for (i = 0; i < ps->info->num_ports; ++i) {
|
||||
if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i))
|
||||
continue;
|
||||
|
||||
@ -1976,7 +1904,7 @@ static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
|
||||
|
||||
/* keep the VLAN unless all ports are excluded */
|
||||
vlan.valid = false;
|
||||
for (i = 0; i < ps->num_ports; ++i) {
|
||||
for (i = 0; i < ps->info->num_ports; ++i) {
|
||||
if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
|
||||
continue;
|
||||
|
||||
@ -2285,11 +2213,11 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
|
||||
mutex_lock(&ps->smi_mutex);
|
||||
|
||||
/* Get or create the bridge FID and assign it to the port */
|
||||
for (i = 0; i < ps->num_ports; ++i)
|
||||
for (i = 0; i < ps->info->num_ports; ++i)
|
||||
if (ps->ports[i].bridge_dev == bridge)
|
||||
break;
|
||||
|
||||
if (i < ps->num_ports)
|
||||
if (i < ps->info->num_ports)
|
||||
err = _mv88e6xxx_port_fid_get(ds, i, &fid);
|
||||
else
|
||||
err = _mv88e6xxx_fid_new(ds, &fid);
|
||||
@ -2303,7 +2231,7 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
|
||||
/* Assign the bridge and remap each port's VLANTable */
|
||||
ps->ports[port].bridge_dev = bridge;
|
||||
|
||||
for (i = 0; i < ps->num_ports; ++i) {
|
||||
for (i = 0; i < ps->info->num_ports; ++i) {
|
||||
if (ps->ports[i].bridge_dev == bridge) {
|
||||
err = _mv88e6xxx_port_based_vlan_map(ds, i);
|
||||
if (err)
|
||||
@ -2334,7 +2262,7 @@ void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
|
||||
/* Unassign the bridge and remap each port's VLANTable */
|
||||
ps->ports[port].bridge_dev = NULL;
|
||||
|
||||
for (i = 0; i < ps->num_ports; ++i)
|
||||
for (i = 0; i < ps->info->num_ports; ++i)
|
||||
if (i == port || ps->ports[i].bridge_dev == bridge)
|
||||
if (_mv88e6xxx_port_based_vlan_map(ds, i))
|
||||
netdev_warn(ds->ports[i], "failed to remap\n");
|
||||
@ -2353,7 +2281,7 @@ static void mv88e6xxx_bridge_work(struct work_struct *work)
|
||||
|
||||
mutex_lock(&ps->smi_mutex);
|
||||
|
||||
for (port = 0; port < ps->num_ports; ++port)
|
||||
for (port = 0; port < ps->info->num_ports; ++port)
|
||||
if (test_and_clear_bit(port, ps->port_state_update_mask) &&
|
||||
_mv88e6xxx_port_state(ds, port, ps->ports[port].state))
|
||||
netdev_warn(ds->ports[port], "failed to update state to %s\n",
|
||||
@ -2685,7 +2613,7 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ps->num_ports; i++) {
|
||||
for (i = 0; i < ps->info->num_ports; i++) {
|
||||
ret = mv88e6xxx_setup_port(ds, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -2700,10 +2628,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
|
||||
ps->ds = ds;
|
||||
mutex_init(&ps->smi_mutex);
|
||||
|
||||
ps->id = mv88e6xxx_reg_read(ds, REG_PORT(0), PORT_SWITCH_ID) & 0xfff0;
|
||||
if (ps->id < 0)
|
||||
return ps->id;
|
||||
|
||||
INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
|
||||
|
||||
return 0;
|
||||
@ -2796,7 +2720,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
|
||||
err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_TRUNK_MASK,
|
||||
0x8000 |
|
||||
(i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |
|
||||
((1 << ps->num_ports) - 1));
|
||||
((1 << ps->info->num_ports) - 1));
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
@ -2849,7 +2773,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
|
||||
* ingress rate limit registers to their initial
|
||||
* state.
|
||||
*/
|
||||
for (i = 0; i < ps->num_ports; i++) {
|
||||
for (i = 0; i < ps->info->num_ports; i++) {
|
||||
err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2,
|
||||
GLOBAL2_INGRESS_OP,
|
||||
0x9000 | (i << 8));
|
||||
@ -2894,7 +2818,7 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
|
||||
mutex_lock(&ps->smi_mutex);
|
||||
|
||||
/* Set all ports to the disabled state. */
|
||||
for (i = 0; i < ps->num_ports; i++) {
|
||||
for (i = 0; i < ps->info->num_ports; i++) {
|
||||
ret = _mv88e6xxx_reg_read(ds, REG_PORT(i), PORT_CONTROL);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
@ -2977,7 +2901,7 @@ static int mv88e6xxx_port_to_phy_addr(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
||||
if (port >= 0 && port < ps->num_ports)
|
||||
if (port >= 0 && port < ps->info->num_ports)
|
||||
return port;
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -3173,61 +3097,60 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
|
||||
}
|
||||
#endif /* CONFIG_NET_DSA_HWMON */
|
||||
|
||||
static char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
|
||||
const struct mv88e6xxx_switch_id *table,
|
||||
static const struct mv88e6xxx_info *
|
||||
mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info *table,
|
||||
unsigned int num)
|
||||
{
|
||||
int i, ret;
|
||||
int i;
|
||||
|
||||
if (!bus)
|
||||
return NULL;
|
||||
|
||||
ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
|
||||
/* Look up the exact switch ID */
|
||||
for (i = 0; i < num; ++i)
|
||||
if (table[i].id == ret)
|
||||
return table[i].name;
|
||||
|
||||
/* Look up only the product number */
|
||||
for (i = 0; i < num; ++i) {
|
||||
if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) {
|
||||
dev_warn(&bus->dev,
|
||||
"unknown revision %d, using base switch 0x%x\n",
|
||||
ret & PORT_SWITCH_ID_REV_MASK,
|
||||
ret & PORT_SWITCH_ID_PROD_NUM_MASK);
|
||||
return table[i].name;
|
||||
}
|
||||
}
|
||||
if (table[i].prod_num == prod_num)
|
||||
return &table[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
|
||||
const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
|
||||
int sw_addr, void **priv,
|
||||
const struct mv88e6xxx_switch_id *table,
|
||||
const struct mv88e6xxx_info *table,
|
||||
unsigned int num)
|
||||
{
|
||||
const struct mv88e6xxx_info *info;
|
||||
struct mv88e6xxx_priv_state *ps;
|
||||
struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
|
||||
char *name;
|
||||
struct mii_bus *bus;
|
||||
const char *name;
|
||||
int id, prod_num, rev;
|
||||
|
||||
bus = dsa_host_dev_to_mii_bus(host_dev);
|
||||
if (!bus)
|
||||
return NULL;
|
||||
|
||||
name = mv88e6xxx_lookup_name(bus, sw_addr, table, num);
|
||||
if (name) {
|
||||
id = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
|
||||
if (id < 0)
|
||||
return NULL;
|
||||
|
||||
prod_num = (id & 0xfff0) >> 4;
|
||||
rev = id & 0x000f;
|
||||
|
||||
info = mv88e6xxx_lookup_info(prod_num, table, num);
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
name = info->name;
|
||||
|
||||
ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
|
||||
if (!ps)
|
||||
return NULL;
|
||||
*priv = ps;
|
||||
ps->bus = dsa_host_dev_to_mii_bus(host_dev);
|
||||
if (!ps->bus)
|
||||
return NULL;
|
||||
|
||||
ps->bus = bus;
|
||||
ps->sw_addr = sw_addr;
|
||||
}
|
||||
ps->info = info;
|
||||
|
||||
*priv = ps;
|
||||
|
||||
dev_info(&ps->bus->dev, "switch 0x%x probed: %s, revision %u\n",
|
||||
prod_num, name, rev);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -68,52 +68,23 @@
|
||||
#define PORT_PCS_CTRL_UNFORCED 0x03
|
||||
#define PORT_PAUSE_CTRL 0x02
|
||||
#define PORT_SWITCH_ID 0x03
|
||||
#define PORT_SWITCH_ID_PROD_NUM_MASK 0xfff0
|
||||
#define PORT_SWITCH_ID_REV_MASK 0x000f
|
||||
#define PORT_SWITCH_ID_6031 0x0310
|
||||
#define PORT_SWITCH_ID_6035 0x0350
|
||||
#define PORT_SWITCH_ID_6046 0x0480
|
||||
#define PORT_SWITCH_ID_6061 0x0610
|
||||
#define PORT_SWITCH_ID_6065 0x0650
|
||||
#define PORT_SWITCH_ID_6085 0x04a0
|
||||
#define PORT_SWITCH_ID_6092 0x0970
|
||||
#define PORT_SWITCH_ID_6095 0x0950
|
||||
#define PORT_SWITCH_ID_6096 0x0980
|
||||
#define PORT_SWITCH_ID_6097 0x0990
|
||||
#define PORT_SWITCH_ID_6108 0x1070
|
||||
#define PORT_SWITCH_ID_6121 0x1040
|
||||
#define PORT_SWITCH_ID_6122 0x1050
|
||||
#define PORT_SWITCH_ID_6123 0x1210
|
||||
#define PORT_SWITCH_ID_6123_A1 0x1212
|
||||
#define PORT_SWITCH_ID_6123_A2 0x1213
|
||||
#define PORT_SWITCH_ID_6131 0x1060
|
||||
#define PORT_SWITCH_ID_6131_B2 0x1066
|
||||
#define PORT_SWITCH_ID_6152 0x1a40
|
||||
#define PORT_SWITCH_ID_6155 0x1a50
|
||||
#define PORT_SWITCH_ID_6161 0x1610
|
||||
#define PORT_SWITCH_ID_6161_A1 0x1612
|
||||
#define PORT_SWITCH_ID_6161_A2 0x1613
|
||||
#define PORT_SWITCH_ID_6165 0x1650
|
||||
#define PORT_SWITCH_ID_6165_A1 0x1652
|
||||
#define PORT_SWITCH_ID_6165_A2 0x1653
|
||||
#define PORT_SWITCH_ID_6171 0x1710
|
||||
#define PORT_SWITCH_ID_6172 0x1720
|
||||
#define PORT_SWITCH_ID_6175 0x1750
|
||||
#define PORT_SWITCH_ID_6176 0x1760
|
||||
#define PORT_SWITCH_ID_6182 0x1a60
|
||||
#define PORT_SWITCH_ID_6185 0x1a70
|
||||
#define PORT_SWITCH_ID_6240 0x2400
|
||||
#define PORT_SWITCH_ID_6320 0x1150
|
||||
#define PORT_SWITCH_ID_6320_A1 0x1151
|
||||
#define PORT_SWITCH_ID_6320_A2 0x1152
|
||||
#define PORT_SWITCH_ID_6321 0x3100
|
||||
#define PORT_SWITCH_ID_6321_A1 0x3101
|
||||
#define PORT_SWITCH_ID_6321_A2 0x3102
|
||||
#define PORT_SWITCH_ID_6350 0x3710
|
||||
#define PORT_SWITCH_ID_6351 0x3750
|
||||
#define PORT_SWITCH_ID_6352 0x3520
|
||||
#define PORT_SWITCH_ID_6352_A0 0x3521
|
||||
#define PORT_SWITCH_ID_6352_A1 0x3522
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6085 0x04a
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6095 0x095
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6131 0x106
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6320 0x115
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6123 0x121
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6161 0x161
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6165 0x165
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6171 0x171
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6172 0x172
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6175 0x175
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6176 0x176
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6185 0x1a7
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6240 0x240
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6321 0x310
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6352 0x352
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6350 0x371
|
||||
#define PORT_SWITCH_ID_PROD_NUM_6351 0x375
|
||||
#define PORT_CONTROL 0x04
|
||||
#define PORT_CONTROL_USE_CORE_TAG BIT(15)
|
||||
#define PORT_CONTROL_DROP_ON_LOCK BIT(14)
|
||||
@ -367,9 +338,24 @@
|
||||
|
||||
#define MV88E6XXX_N_FID 4096
|
||||
|
||||
struct mv88e6xxx_switch_id {
|
||||
u16 id;
|
||||
char *name;
|
||||
enum mv88e6xxx_family {
|
||||
MV88E6XXX_FAMILY_NONE,
|
||||
MV88E6XXX_FAMILY_6065, /* 6031 6035 6061 6065 */
|
||||
MV88E6XXX_FAMILY_6095, /* 6092 6095 */
|
||||
MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */
|
||||
MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */
|
||||
MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */
|
||||
MV88E6XXX_FAMILY_6320, /* 6320 6321 */
|
||||
MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
|
||||
MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */
|
||||
};
|
||||
|
||||
struct mv88e6xxx_info {
|
||||
enum mv88e6xxx_family family;
|
||||
u16 prod_num;
|
||||
const char *name;
|
||||
unsigned int num_databases;
|
||||
unsigned int num_ports;
|
||||
};
|
||||
|
||||
struct mv88e6xxx_atu_entry {
|
||||
@ -397,6 +383,8 @@ struct mv88e6xxx_priv_port {
|
||||
};
|
||||
|
||||
struct mv88e6xxx_priv_state {
|
||||
const struct mv88e6xxx_info *info;
|
||||
|
||||
/* The dsa_switch this private structure is related to */
|
||||
struct dsa_switch *ds;
|
||||
|
||||
@ -438,9 +426,6 @@ struct mv88e6xxx_priv_state {
|
||||
*/
|
||||
struct mutex eeprom_mutex;
|
||||
|
||||
int id; /* switch product id */
|
||||
int num_ports; /* number of switch ports */
|
||||
|
||||
struct mv88e6xxx_priv_port ports[DSA_MAX_PORTS];
|
||||
|
||||
DECLARE_BITMAP(port_state_update_mask, DSA_MAX_PORTS);
|
||||
@ -462,9 +447,9 @@ struct mv88e6xxx_hw_stat {
|
||||
};
|
||||
|
||||
int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);
|
||||
char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
|
||||
const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
|
||||
int sw_addr, void **priv,
|
||||
const struct mv88e6xxx_switch_id *table,
|
||||
const struct mv88e6xxx_info *table,
|
||||
unsigned int num);
|
||||
|
||||
int mv88e6xxx_setup_ports(struct dsa_switch *ds);
|
||||
|
@ -217,8 +217,9 @@ struct dsa_switch_driver {
|
||||
/*
|
||||
* Probing and setup.
|
||||
*/
|
||||
char *(*probe)(struct device *dsa_dev, struct device *host_dev,
|
||||
int sw_addr, void **priv);
|
||||
const char *(*probe)(struct device *dsa_dev,
|
||||
struct device *host_dev, int sw_addr,
|
||||
void **priv);
|
||||
int (*setup)(struct dsa_switch *ds);
|
||||
int (*set_addr)(struct dsa_switch *ds, u8 *addr);
|
||||
u32 (*get_phy_flags)(struct dsa_switch *ds, int port);
|
||||
|
@ -52,11 +52,11 @@ EXPORT_SYMBOL_GPL(unregister_switch_driver);
|
||||
|
||||
static struct dsa_switch_driver *
|
||||
dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr,
|
||||
char **_name, void **priv)
|
||||
const char **_name, void **priv)
|
||||
{
|
||||
struct dsa_switch_driver *ret;
|
||||
struct list_head *list;
|
||||
char *name;
|
||||
const char *name;
|
||||
|
||||
ret = NULL;
|
||||
name = NULL;
|
||||
@ -383,7 +383,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
|
||||
struct dsa_switch_driver *drv;
|
||||
struct dsa_switch *ds;
|
||||
int ret;
|
||||
char *name;
|
||||
const char *name;
|
||||
void *priv;
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user