提交 ccd37cff 编写于 作者: D David S. Miller

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 48ace4ef

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: NDavid S. Miller <davem@davemloft.net>
......@@ -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,
unsigned int num)
static const struct mv88e6xxx_info *
mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info *table,
unsigned int num)
{
int i, ret;
if (!bus)
return NULL;
ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
if (ret < 0)
return NULL;
int i;
/* 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,
int sw_addr, void **priv,
const struct mv88e6xxx_switch_id *table,
unsigned int num)
const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
int sw_addr, void **priv,
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) {
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->sw_addr = sw_addr;
}
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;
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,10 +447,10 @@ 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,
int sw_addr, void **priv,
const struct mv88e6xxx_switch_id *table,
unsigned int num);
const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
int sw_addr, void **priv,
const struct mv88e6xxx_info *table,
unsigned int num);
int mv88e6xxx_setup_ports(struct dsa_switch *ds);
int mv88e6xxx_setup_common(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;
/*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册