* Re: [PATCH net-next 2/2] net: exit busy loop when another process is runnable
From: Peter Zijlstra @ 2016-04-14 0:55 UTC (permalink / raw)
To: Jason Wang
Cc: Eliezer Tamir, Eric Dumazet, Ingo Molnar, Mike Galbraith, davem,
netdev, linux-kernel, mst, Ingo Molnar jacob.e.keller@intel.com
In-Reply-To: <54056459.4060100@redhat.com>
On Tue, Sep 02, 2014 at 02:31:53PM +0800, Jason Wang wrote:
> Yes, but current code can not do this. In most of the cases, the new
> woke up process have no chance to run if another process is busy loop in
> the same cpu.
That sounds weird; a process that slept will have an effective vruntime
deficit vs one that has been running for a while.
^ permalink raw reply
* [PATCH net-next 7/8] dsa: mv88e6xxx: Use the name table to determine number of ports
From: Andrew Lunn @ 2016-04-13 23:59 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460591998-20598-1-git-send-email-andrew@lunn.ch>
Extend the ID to name table to also include the number of ports.
Saves a few switch statements and it is likely other entries will be
added to the table later.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6123.c | 30 +++++++++---------------------
drivers/net/dsa/mv88e6131.c | 25 +++++--------------------
drivers/net/dsa/mv88e6171.c | 10 ++++------
drivers/net/dsa/mv88e6352.c | 26 ++++++++++++--------------
drivers/net/dsa/mv88e6xxx.c | 35 +++++++++++++++++++++--------------
drivers/net/dsa/mv88e6xxx.h | 1 +
6 files changed, 52 insertions(+), 75 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index b4dd7ef039da..ac2e6609367d 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -20,15 +20,15 @@
#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)" },
+ { PORT_SWITCH_ID_6123, "Marvell 88E6123", 3 },
+ { PORT_SWITCH_ID_6123_A1, "Marvell 88E6123 (A1)", 3 },
+ { PORT_SWITCH_ID_6123_A2, "Marvell 88E6123 (A2)", 3 },
+ { PORT_SWITCH_ID_6161, "Marvell 88E6161", 6 },
+ { PORT_SWITCH_ID_6161_A1, "Marvell 88E6161 (A1)", 6 },
+ { PORT_SWITCH_ID_6161_A2, "Marvell 88E6161 (A2)", 6 },
+ { PORT_SWITCH_ID_6165, "Marvell 88E6165", 6 },
+ { PORT_SWITCH_ID_6165_A1, "Marvell 88E6165 (A1)", 6 },
+ { PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)", 6 },
};
static char *mv88e6123_drv_probe(struct device *dsa_dev,
@@ -88,18 +88,6 @@ static int mv88e6123_setup(struct dsa_switch *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(ps, false);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 1659d4dc93c0..969f67c77835 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -20,11 +20,11 @@
#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" },
+ { PORT_SWITCH_ID_6085, "Marvell 88E6085", 10 },
+ { PORT_SWITCH_ID_6095, "Marvell 88E6095/88E6095F", 11 },
+ { PORT_SWITCH_ID_6131, "Marvell 88E6131", 8 },
+ { PORT_SWITCH_ID_6131_B2, "Marvell 88E6131 (B2)", 8 },
+ { PORT_SWITCH_ID_6185, "Marvell 88E6185", 10 },
};
static char *mv88e6131_drv_probe(struct device *dsa_dev,
@@ -112,21 +112,6 @@ static int mv88e6131_setup(struct dsa_switch *ds)
mv88e6xxx_ppu_state_init(ps);
- 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(ps, false);
if (ret < 0)
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 0b934b3008ca..8044927590a4 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -20,10 +20,10 @@
#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" },
+ { PORT_SWITCH_ID_6171, "Marvell 88E6171", 7 },
+ { PORT_SWITCH_ID_6175, "Marvell 88E6175", 7 },
+ { PORT_SWITCH_ID_6350, "Marvell 88E6350", 7 },
+ { PORT_SWITCH_ID_6351, "Marvell 88E6351", 7 },
};
static char *mv88e6171_drv_probe(struct device *dsa_dev,
@@ -85,8 +85,6 @@ static int mv88e6171_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;
- ps->num_ports = 7;
-
ret = mv88e6xxx_switch_reset(ps, true);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index b745a1f36a1f..e5541cd66e86 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -24,18 +24,18 @@
#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)" },
+ { PORT_SWITCH_ID_6172, "Marvell 88E6172", 7 },
+ { PORT_SWITCH_ID_6176, "Marvell 88E6176", 7 },
+ { PORT_SWITCH_ID_6240, "Marvell 88E6240", 7 },
+ { PORT_SWITCH_ID_6320, "Marvell 88E6320", 7 },
+ { PORT_SWITCH_ID_6320_A1, "Marvell 88E6320 (A1)", 7 },
+ { PORT_SWITCH_ID_6320_A2, "Marvell 88e6320 (A2)", 7 },
+ { PORT_SWITCH_ID_6321, "Marvell 88E6321", 7 },
+ { PORT_SWITCH_ID_6321_A1, "Marvell 88E6321 (A1)", 7 },
+ { PORT_SWITCH_ID_6321_A2, "Marvell 88e6321 (A2)", 7 },
+ { PORT_SWITCH_ID_6352, "Marvell 88E6352", 7 },
+ { PORT_SWITCH_ID_6352_A0, "Marvell 88E6352 (A0)", 7 },
+ { PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)", 7 },
};
static char *mv88e6352_drv_probe(struct device *dsa_dev,
@@ -95,8 +95,6 @@ static int mv88e6352_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;
- ps->num_ports = 7;
-
mutex_init(&ps->eeprom_mutex);
ret = mv88e6xxx_switch_reset(ps, true);
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index b8db7ed12005..9bf20c6d8aac 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3206,23 +3206,23 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
EXPORT_SYMBOL_GPL(mv88e6xxx_get_temp_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 int mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
+ const struct mv88e6xxx_switch_id *table,
+ unsigned int num)
{
int i, ret;
if (!bus)
- return NULL;
+ return -EINVAL;
ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
if (ret < 0)
- return NULL;
+ return ret;
/* Look up the exact switch ID */
for (i = 0; i < num; ++i)
if (table[i].id == ret)
- return table[i].name;
+ return i;
/* Look up only the product number */
for (i = 0; i < num; ++i) {
@@ -3231,11 +3231,11 @@ static char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
"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;
+ return i;
}
}
- return NULL;
+ return -ENODEV;
}
char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
@@ -3245,13 +3245,14 @@ char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
{
struct mv88e6xxx_priv_state *ps;
struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
- char *name;
+ char *name = NULL;
+ int entry;
if (!bus)
return NULL;
- name = mv88e6xxx_lookup_name(bus, sw_addr, table, num);
- if (name) {
+ entry = mv88e6xxx_lookup_name(bus, sw_addr, table, num);
+ if (entry >= 0) {
ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
if (!ps)
return NULL;
@@ -3260,6 +3261,9 @@ char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
if (!ps->bus)
return NULL;
ps->sw_addr = sw_addr;
+
+ name = table[entry].name;
+ ps->num_ports = table[entry].num_ports;
}
return name;
}
@@ -3273,6 +3277,7 @@ int mv88e6xxx_probe(struct mdio_device *mdiodev, struct dsa_switch_driver *ops,
struct mv88e6xxx_priv_state *ps;
struct dsa_switch *ds;
const char *name;
+ int entry;
int err;
ds = devm_kzalloc(dev, sizeof(*ds) + sizeof(*ps), GFP_KERNEL);
@@ -3290,11 +3295,13 @@ int mv88e6xxx_probe(struct mdio_device *mdiodev, struct dsa_switch_driver *ops,
ds->drv = ops;
- name = mv88e6xxx_lookup_name(ps->bus, ps->sw_addr, table, table_size);
- if (!name) {
+ entry = mv88e6xxx_lookup_name(ps->bus, ps->sw_addr, table, table_size);
+ if (entry < 0) {
dev_err(dev, "Failed to find switch");
- return -ENODEV;
+ return entry;
}
+ name = table[entry].name;
+ ps->num_ports = table[entry].num_ports;
ps->reset = devm_gpiod_get(&mdiodev->dev, "reset", GPIOD_ASIS);
err = PTR_ERR(ps->reset);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 3f7a432c9050..1621e400ef5b 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -371,6 +371,7 @@
struct mv88e6xxx_switch_id {
u16 id;
char *name;
+ int num_ports;
};
struct mv88e6xxx_atu_entry {
--
2.7.0
^ permalink raw reply related
* [PATCH net-next 1/8] dsa: mv88e6xxx: Prepare for turning this into a library module
From: Andrew Lunn @ 2016-04-13 23:59 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460591998-20598-1-git-send-email-andrew@lunn.ch>
Export all the functions so that we can later turn the module into a
library module.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 9985a0cf31f1..9b568f39aaf0 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -120,6 +120,7 @@ int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_reg_read);
static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
int reg, u16 val)
@@ -177,6 +178,7 @@ int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_reg_write);
int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
{
@@ -186,6 +188,7 @@ int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_set_addr_direct);
int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
{
@@ -211,6 +214,7 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_set_addr_indirect);
static int _mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
{
@@ -336,6 +340,7 @@ void mv88e6xxx_ppu_state_init(struct dsa_switch *ds)
ps->ppu_timer.data = (unsigned long)ps;
ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_ppu_state_init);
int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
{
@@ -349,6 +354,7 @@ int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_read_ppu);
int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
int regnum, u16 val)
@@ -363,6 +369,7 @@ int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_write_ppu);
#endif
static bool mv88e6xxx_6065_family(struct dsa_switch *ds)
@@ -587,6 +594,7 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
out:
mutex_unlock(&ps->smi_mutex);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_adjust_link);
static int _mv88e6xxx_stats_wait(struct dsa_switch *ds)
{
@@ -783,6 +791,7 @@ void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
}
}
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_strings);
int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
{
@@ -796,6 +805,7 @@ int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
}
return j;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_sset_count);
void
mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
@@ -823,11 +833,13 @@ mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
mutex_unlock(&ps->smi_mutex);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_ethtool_stats);
int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
{
return 32 * sizeof(u16);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_regs_len);
void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
struct ethtool_regs *regs, void *_p)
@@ -847,6 +859,7 @@ void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
p[i] = ret;
}
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_regs);
static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset,
u16 mask)
@@ -890,12 +903,14 @@ int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
return mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
GLOBAL2_EEPROM_OP_LOAD);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_eeprom_load_wait);
int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
{
return mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
GLOBAL2_EEPROM_OP_BUSY);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_eeprom_busy_wait);
static int _mv88e6xxx_atu_wait(struct dsa_switch *ds)
{
@@ -962,6 +977,7 @@ out:
mutex_unlock(&ps->smi_mutex);
return reg;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_eee);
int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
struct phy_device *phydev, struct ethtool_eee *e)
@@ -988,6 +1004,7 @@ out:
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_set_eee);
static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 fid, u16 cmd)
{
@@ -1216,6 +1233,7 @@ void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
set_bit(port, ps->port_state_update_mask);
schedule_work(&ps->bridge_work);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_stp_state_set);
static int _mv88e6xxx_port_pvid(struct dsa_switch *ds, int port, u16 *new,
u16 *old)
@@ -1456,6 +1474,7 @@ unlock:
return err;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_vlan_dump);
static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds,
struct mv88e6xxx_vtu_stu_entry *entry)
@@ -1864,6 +1883,7 @@ unlock:
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_vlan_filtering);
int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan,
@@ -1884,6 +1904,7 @@ int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
*/
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_vlan_prepare);
static int _mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid,
bool untagged)
@@ -1924,6 +1945,7 @@ void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
mutex_unlock(&ps->smi_mutex);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_vlan_add);
static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
{
@@ -1990,6 +2012,7 @@ unlock:
return err;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_vlan_del);
static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds,
const unsigned char *addr)
@@ -2079,6 +2102,7 @@ int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
*/
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_fdb_prepare);
void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_fdb *fdb,
@@ -2094,6 +2118,7 @@ void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
netdev_err(ds->ports[port], "failed to load MAC address\n");
mutex_unlock(&ps->smi_mutex);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_fdb_add);
int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_fdb *fdb)
@@ -2108,6 +2133,7 @@ int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_fdb_del);
static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid,
struct mv88e6xxx_atu_entry *entry)
@@ -2241,6 +2267,7 @@ unlock:
return err;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_fdb_dump);
int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
struct net_device *bridge)
@@ -2283,6 +2310,7 @@ unlock:
return err;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_bridge_join);
void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
{
@@ -2308,6 +2336,7 @@ void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
mutex_unlock(&ps->smi_mutex);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_bridge_leave);
static void mv88e6xxx_bridge_work(struct work_struct *work)
{
@@ -2659,6 +2688,7 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
}
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_setup_ports);
int mv88e6xxx_setup_common(struct dsa_switch *ds)
{
@@ -2673,6 +2703,7 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_setup_common);
int mv88e6xxx_setup_global(struct dsa_switch *ds)
{
@@ -2793,6 +2824,7 @@ unlock:
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_setup_global);
int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
{
@@ -2842,6 +2874,7 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_switch_reset);
int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg)
{
@@ -2854,6 +2887,7 @@ int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg)
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_page_read);
int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
int reg, int val)
@@ -2867,6 +2901,7 @@ int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_page_write);
static int mv88e6xxx_port_to_phy_addr(struct dsa_switch *ds, int port)
{
@@ -2892,6 +2927,7 @@ mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
mutex_unlock(&ps->smi_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_read);
int
mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
@@ -2908,6 +2944,7 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
mutex_unlock(&ps->smi_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_write);
int
mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum)
@@ -2924,6 +2961,7 @@ mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum)
mutex_unlock(&ps->smi_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_read_indirect);
int
mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
@@ -2941,6 +2979,7 @@ mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
mutex_unlock(&ps->smi_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_write_indirect);
#ifdef CONFIG_NET_DSA_HWMON
@@ -3012,6 +3051,7 @@ int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
return mv88e61xx_get_temp(ds, temp);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_temp);
int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)
{
@@ -3031,6 +3071,7 @@ int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_temp_limit);
int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)
{
@@ -3047,6 +3088,7 @@ int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)
return mv88e6xxx_phy_page_write(ds, phy, 6, 26,
(ret & 0xe0ff) | (temp << 8));
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_set_temp_limit);
int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
{
@@ -3066,6 +3108,7 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_temp_alarm);
#endif /* CONFIG_NET_DSA_HWMON */
static char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
@@ -3125,6 +3168,7 @@ char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
}
return name;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_drv_probe);
static int __init mv88e6xxx_init(void)
{
--
2.7.0
^ permalink raw reply related
* [PATCH net-next] gre: eliminate holes in ip_tunnel
From: Stephen Hemminger @ 2016-04-14 0:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev
The structure can be packed denser by doing minor rearrangement
of existing elements.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
--- a/include/net/ip_tunnels.h 2016-04-11 13:42:06.654666930 -0700
+++ b/include/net/ip_tunnels.h 2016-04-13 16:47:59.821692189 -0700
@@ -105,24 +105,23 @@ struct ip_tunnel {
struct net_device *dev;
struct net *net; /* netns for packet i/o */
- int err_count; /* Number of arrived ICMP errors */
unsigned long err_time; /* Time when the last ICMP error
* arrived */
+ int err_count; /* Number of arrived ICMP errors */
/* These four fields used only by GRE */
u32 i_seqno; /* The last seen seqno */
u32 o_seqno; /* The last output seqno */
int tun_hlen; /* Precalculated header length */
- int mlink;
struct dst_cache dst_cache;
struct ip_tunnel_parm parms;
+ int mlink;
int encap_hlen; /* Encap header length (FOU,GUE) */
- struct ip_tunnel_encap encap;
-
int hlen; /* tun_hlen + encap_hlen */
+ struct ip_tunnel_encap encap;
/* for SIT */
#ifdef CONFIG_IPV6_SIT_6RD
^ permalink raw reply
* [PATCH net-next 2/8] dsa: mv88e6xxx: Add macro for registering the drivers
From: Andrew Lunn @ 2016-04-13 23:59 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460591998-20598-1-git-send-email-andrew@lunn.ch>
The macro cuts down on boilerplate. The switch driver needs to both
register itself as an MDIO driver and register itself as a switch
driver. This second registration is needed to retain backwards
compatibility with the old binding.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx.h | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 5d27decc85cb..afb9ebdfc595 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -561,6 +561,26 @@ extern struct dsa_switch_driver mv88e6171_switch_driver;
return __ret; \
})
-
+/**
+ * mv88e6xxx_module_driver() - Helper macro for registering mv88e6xxx drivers
+ *
+ * Helper macro for mv88e6xxx drivers which do not do anything special
+ * in module init/exit. Each module may only use this macro once, and
+ * calling it replaces module_init() and module_exit().
+ */
+#define mv88e6xxx_module_driver(_mdio_driver, _switch_driver) \
+static int __init mv88e6xxx_module_init(void) \
+{ \
+ register_switch_driver(&_switch_driver); \
+ return mdio_driver_register(&_mdio_driver); \
+} \
+module_init(mv88e6xxx_module_init); \
+ \
+static void __exit mv88e6xxx_module_exit(void) \
+{ \
+ mdio_driver_unregister(&_mdio_driver); \
+ unregister_switch_driver(&_switch_driver); \
+} \
+module_exit(mv88e6xxx_module_exit)
#endif
--
2.7.0
^ permalink raw reply related
* [PATCH net-next 3/8] dsa: Add mdio device support to Marvell switches
From: Andrew Lunn @ 2016-04-13 23:59 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460591998-20598-1-git-send-email-andrew@lunn.ch>
Allow Marvell switches to be mdio devices. Currently they just probe
and allocate there private structure. Later patches will make them
register with the DSA framework.
At the same time, make them separate modules, and make mv88e6xxx a
library module.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
v2: s/Copywrite/Copyright
---
.../devicetree/bindings/net/dsa/marvell.txt | 29 ++++++++++
drivers/net/dsa/Makefile | 19 ++----
drivers/net/dsa/mv88e6123.c | 30 +++++++++-
drivers/net/dsa/mv88e6131.c | 31 ++++++++--
drivers/net/dsa/mv88e6171.c | 31 ++++++++--
drivers/net/dsa/mv88e6352.c | 33 +++++++++--
drivers/net/dsa/mv88e6xxx.c | 67 +++++++++++++---------
drivers/net/dsa/mv88e6xxx.h | 5 ++
8 files changed, 186 insertions(+), 59 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/dsa/marvell.txt
diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt
new file mode 100644
index 000000000000..51b7cd9408f2
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt
@@ -0,0 +1,29 @@
+Marvell DSA Switch Device Tree Bindings
+---------------------------------------
+
+WARNING: This binding is currently unstable. Do not program it into a
+FLASH never to be changed again. Once this binding is stable, this
+warning will be removed.
+
+If you need a stable binding, use the old dsa.txt binding.
+
+Marvell Switches are MDIO devices. The following properties should be
+placed as a child node of an mdio device.
+
+Required properties:
+- compatible : Should be one of "marvell,mv88e6123",
+ "marvell,mv88e6131", "marvell,mv88e6171",
+ "marvell,mv88e6352" or "marvell,mv88e6060"
+- reg : Address on the MII bus for the switch.
+
+Example:
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ switch0: switch@1 {
+ reg = <0>;
+ compatible = "marvell,mv88e6131";
+ };
+ };
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index a6e09939be65..3e1f36120e02 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -1,16 +1,7 @@
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
-obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx_drv.o
-mv88e6xxx_drv-y += mv88e6xxx.o
-ifdef CONFIG_NET_DSA_MV88E6123
-mv88e6xxx_drv-y += mv88e6123.o
-endif
-ifdef CONFIG_NET_DSA_MV88E6131
-mv88e6xxx_drv-y += mv88e6131.o
-endif
-ifdef CONFIG_NET_DSA_MV88E6352
-mv88e6xxx_drv-y += mv88e6352.o
-endif
-ifdef CONFIG_NET_DSA_MV88E6171
-mv88e6xxx_drv-y += mv88e6171.o
-endif
+obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o
+obj-$(CONFIG_NET_DSA_MV88E6131) += mv88e6123.o
+obj-$(CONFIG_NET_DSA_MV88E6131) += mv88e6131.o
+obj-$(CONFIG_NET_DSA_MV88E6352) += mv88e6352.o
+obj-$(CONFIG_NET_DSA_MV88E6171) += mv88e6171.o
obj-$(CONFIG_NET_DSA_BCM_SF2) += bcm_sf2.o
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index c34283d929c4..7ef0e3c7b703 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -1,6 +1,7 @@
/*
* net/dsa/mv88e6123_61_65.c - Marvell 88e6123/6161/6165 switch chip support
* Copyright (c) 2008-2009 Marvell Semiconductor
+ * Copyright (c) 2015 Andrew Lunn <andrew@lunn.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -11,6 +12,7 @@
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/list.h>
+#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
@@ -123,6 +125,28 @@ struct dsa_switch_driver mv88e6123_switch_driver = {
.get_regs = mv88e6xxx_get_regs,
};
-MODULE_ALIAS("platform:mv88e6123");
-MODULE_ALIAS("platform:mv88e6161");
-MODULE_ALIAS("platform:mv88e6165");
+static int mv88e6123_probe(struct mdio_device *mdiodev)
+{
+ return mv88e6xxx_probe(mdiodev, &mv88e6123_switch_driver,
+ mv88e6123_table, ARRAY_SIZE(mv88e6123_table));
+}
+
+static const struct of_device_id mv88e6123_of_match[] = {
+ { .compatible = "marvell,mv88e6123" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mv88e6123_of_match);
+
+static struct mdio_driver mv88e6123_driver = {
+ .probe = mv88e6123_probe,
+ .remove = mv88e6xxx_remove,
+ .mdiodrv.driver = {
+ .name = "mv88e6123",
+ .of_match_table = mv88e6123_of_match,
+ },
+};
+
+mv88e6xxx_module_driver(mv88e6123_driver, mv88e6123_switch_driver);
+
+MODULE_DESCRIPTION("Driver for Marvell 6123 family ethernet switch chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index f5d75fce1e96..25f35937787e 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -1,6 +1,7 @@
/*
* net/dsa/mv88e6131.c - Marvell 88e6095/6095f/6131 switch chip support
* Copyright (c) 2008-2009 Marvell Semiconductor
+ * Copyright (c) 2015 Andrew Lunn <andrew@lunn.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -11,6 +12,7 @@
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/list.h>
+#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
@@ -186,7 +188,28 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
.port_fdb_dump = mv88e6xxx_port_fdb_dump,
};
-MODULE_ALIAS("platform:mv88e6085");
-MODULE_ALIAS("platform:mv88e6095");
-MODULE_ALIAS("platform:mv88e6095f");
-MODULE_ALIAS("platform:mv88e6131");
+static int mv88e6131_probe(struct mdio_device *mdiodev)
+{
+ return mv88e6xxx_probe(mdiodev, &mv88e6131_switch_driver,
+ mv88e6131_table, ARRAY_SIZE(mv88e6131_table));
+}
+
+static const struct of_device_id mv88e6131_of_match[] = {
+ { .compatible = "marvell,mv88e6131" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mv88e6131_of_match);
+
+static struct mdio_driver mv88e6131_driver = {
+ .probe = mv88e6131_probe,
+ .remove = mv88e6xxx_remove,
+ .mdiodrv.driver = {
+ .name = "mv88e6131",
+ .of_match_table = mv88e6131_of_match,
+ },
+};
+
+mv88e6xxx_module_driver(mv88e6131_driver, mv88e6131_switch_driver);
+
+MODULE_DESCRIPTION("Driver for Marvell 6131 family ethernet switch chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index f5622506cdfa..abf2a9bbbec5 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -1,6 +1,7 @@
/* net/dsa/mv88e6171.c - Marvell 88e6171 switch chip support
* Copyright (c) 2008-2009 Marvell Semiconductor
* Copyright (c) 2014 Claudio Leite <leitec@staticky.com>
+ * Copyright (c) 2015 Andrew Lunn <andrew@lunn.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -11,6 +12,7 @@
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/list.h>
+#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
@@ -121,7 +123,28 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
.port_fdb_dump = mv88e6xxx_port_fdb_dump,
};
-MODULE_ALIAS("platform:mv88e6171");
-MODULE_ALIAS("platform:mv88e6175");
-MODULE_ALIAS("platform:mv88e6350");
-MODULE_ALIAS("platform:mv88e6351");
+static int mv88e6171_probe(struct mdio_device *mdiodev)
+{
+ return mv88e6xxx_probe(mdiodev, &mv88e6171_switch_driver,
+ mv88e6171_table, ARRAY_SIZE(mv88e6171_table));
+}
+
+static const struct of_device_id mv88e6171_of_match[] = {
+ { .compatible = "marvell,mv88e6171" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mv88e6171_of_match);
+
+static struct mdio_driver mv88e6171_driver = {
+ .probe = mv88e6171_probe,
+ .remove = mv88e6xxx_remove,
+ .mdiodrv.driver = {
+ .name = "mv88e6171",
+ .of_match_table = mv88e6171_of_match,
+ },
+};
+
+mv88e6xxx_module_driver(mv88e6171_driver, mv88e6171_switch_driver);
+
+MODULE_DESCRIPTION("Driver for Marvell 6171 family ethernet switch chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index e54ee27db129..22d42fb51991 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -2,6 +2,7 @@
* net/dsa/mv88e6352.c - Marvell 88e6352 switch chip support
*
* Copyright (c) 2014 Guenter Roeck
+ * Copyright (c) 2015 Andrew Lunn <andrew@lunn.ch>
*
* Derived from mv88e6123_61_65.c
* Copyright (c) 2008-2009 Marvell Semiconductor
@@ -15,9 +16,9 @@
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/list.h>
+#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/netdevice.h>
-#include <linux/platform_device.h>
#include <linux/phy.h>
#include <net/dsa.h>
#include "mv88e6xxx.h"
@@ -342,8 +343,28 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
.port_fdb_dump = mv88e6xxx_port_fdb_dump,
};
-MODULE_ALIAS("platform:mv88e6172");
-MODULE_ALIAS("platform:mv88e6176");
-MODULE_ALIAS("platform:mv88e6320");
-MODULE_ALIAS("platform:mv88e6321");
-MODULE_ALIAS("platform:mv88e6352");
+static int mv88e6352_probe(struct mdio_device *mdiodev)
+{
+ return mv88e6xxx_probe(mdiodev, &mv88e6352_switch_driver,
+ mv88e6352_table, ARRAY_SIZE(mv88e6352_table));
+}
+
+static const struct of_device_id mv88e6352_of_match[] = {
+ { .compatible = "marvell,mv88e6352" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mv88e6352_of_match);
+
+static struct mdio_driver mv88e6352_driver = {
+ .probe = mv88e6352_probe,
+ .remove = mv88e6xxx_remove,
+ .mdiodrv.driver = {
+ .name = "mv88e6352",
+ .of_match_table = mv88e6352_of_match,
+ },
+};
+
+mv88e6xxx_module_driver(mv88e6352_driver, mv88e6352_switch_driver);
+
+MODULE_DESCRIPTION("Driver for Marvell 6352 family ethernet switch chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 9b568f39aaf0..9e906e0459c7 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3170,40 +3170,51 @@ char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
}
EXPORT_SYMBOL_GPL(mv88e6xxx_drv_probe);
-static int __init mv88e6xxx_init(void)
+int mv88e6xxx_probe(struct mdio_device *mdiodev, struct dsa_switch_driver *ops,
+ const struct mv88e6xxx_switch_id *table,
+ unsigned int table_size)
{
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
- register_switch_driver(&mv88e6131_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123)
- register_switch_driver(&mv88e6123_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6352)
- register_switch_driver(&mv88e6352_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
- register_switch_driver(&mv88e6171_switch_driver);
-#endif
+ struct device *dev = &mdiodev->dev;
+ struct mv88e6xxx_priv_state *ps;
+ struct dsa_switch *ds;
+ const char *name;
+
+ ds = devm_kzalloc(dev, sizeof(*ds) + sizeof(*ps), GFP_KERNEL);
+ if (!ds)
+ return -ENOMEM;
+
+ ps = (struct mv88e6xxx_priv_state *)(ds + 1);
+ ds->priv = ps;
+ ps->ds = ds;
+ ps->bus = mdiodev->bus;
+ ps->sw_addr = mdiodev->addr;
+
+ get_device(&ps->bus->dev);
+
+ ds->drv = ops;
+
+ name = mv88e6xxx_lookup_name(ps->bus, ps->sw_addr, table, table_size);
+ if (!name) {
+ dev_err(dev, "Failed to find switch");
+ return -ENODEV;
+ }
+
+ dev_set_drvdata(dev, ds);
+
return 0;
}
-module_init(mv88e6xxx_init);
+EXPORT_SYMBOL_GPL(mv88e6xxx_probe);
-static void __exit mv88e6xxx_cleanup(void)
+void mv88e6xxx_remove(struct mdio_device *mdiodev)
{
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
- unregister_switch_driver(&mv88e6171_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6352)
- unregister_switch_driver(&mv88e6352_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123)
- unregister_switch_driver(&mv88e6123_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
- unregister_switch_driver(&mv88e6131_switch_driver);
-#endif
+ struct device *dev = &mdiodev->dev;
+ struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+ devm_kfree(dev, ds);
+ put_device(&ps->bus->dev);
}
-module_exit(mv88e6xxx_cleanup);
+EXPORT_SYMBOL_GPL(mv88e6xxx_remove);
MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index afb9ebdfc595..3bdc0fdf692f 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -536,6 +536,11 @@ int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg);
int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
int reg, int val);
+int mv88e6xxx_probe(struct mdio_device *mdiodev, struct dsa_switch_driver *ops,
+ const struct mv88e6xxx_switch_id *table,
+ unsigned int table_size);
+void mv88e6xxx_remove(struct mdio_device *mdiodev);
+
extern struct dsa_switch_driver mv88e6131_switch_driver;
extern struct dsa_switch_driver mv88e6123_switch_driver;
--
2.7.0
^ permalink raw reply related
* [PATCH net-next 6/8] dsa: mv88e6xxx: Replace ds with ps where possible
From: Andrew Lunn @ 2016-04-13 23:59 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460591998-20598-1-git-send-email-andrew@lunn.ch>
The dsa_switch structure ds is actually needed in very few places,
mostly during setup of the switch. The private structure ps is however
needed nearly everywhere. Pass ps, not ds internally.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6123.c | 11 +-
drivers/net/dsa/mv88e6131.c | 19 +-
drivers/net/dsa/mv88e6171.c | 11 +-
drivers/net/dsa/mv88e6352.c | 22 +-
drivers/net/dsa/mv88e6xxx.c | 938 ++++++++++++++++++++++----------------------
drivers/net/dsa/mv88e6xxx.h | 14 +-
6 files changed, 510 insertions(+), 505 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 450dad5af568..b4dd7ef039da 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -42,6 +42,7 @@ static char *mv88e6123_drv_probe(struct device *dsa_dev,
static int mv88e6123_setup_global(struct dsa_switch *ds)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
u32 upstream_port = dsa_upstream_port(ds);
int ret;
u32 reg;
@@ -54,7 +55,7 @@ static int mv88e6123_setup_global(struct dsa_switch *ds)
* external PHYs to poll), don't discard packets with
* excessive collisions, and mask all interrupt sources.
*/
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL, 0x0000);
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, 0x0000);
if (ret)
return ret;
@@ -65,14 +66,14 @@ static int mv88e6123_setup_global(struct dsa_switch *ds)
reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
if (ret)
return ret;
/* Disable remote management for now, and set the switch's
* DSA device number.
*/
- return mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL_2,
+ return mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
ds->index & 0x1f);
}
@@ -83,7 +84,7 @@ static int mv88e6123_setup(struct dsa_switch *ds)
ps->ds = ds;
- ret = mv88e6xxx_setup_common(ds);
+ ret = mv88e6xxx_setup_common(ps);
if (ret < 0)
return ret;
@@ -99,7 +100,7 @@ static int mv88e6123_setup(struct dsa_switch *ds)
return -ENODEV;
}
- ret = mv88e6xxx_switch_reset(ds, false);
+ ret = mv88e6xxx_switch_reset(ps, false);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index e1e2410a660c..1659d4dc93c0 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -38,6 +38,7 @@ static char *mv88e6131_drv_probe(struct device *dsa_dev,
static int mv88e6131_setup_global(struct dsa_switch *ds)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
u32 upstream_port = dsa_upstream_port(ds);
int ret;
u32 reg;
@@ -51,14 +52,14 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
* to arbitrate between packet queues, set the maximum frame
* size to 1632, and mask all interrupt sources.
*/
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL,
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
GLOBAL_CONTROL_PPU_ENABLE |
GLOBAL_CONTROL_MAX_FRAME_1632);
if (ret)
return ret;
/* Set the VLAN ethertype to 0x8100. */
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CORE_TAG_TYPE, 0x8100);
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CORE_TAG_TYPE, 0x8100);
if (ret)
return ret;
@@ -69,7 +70,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
GLOBAL_MONITOR_CONTROL_ARP_DISABLED;
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
if (ret)
return ret;
@@ -78,11 +79,11 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
* DSA device number.
*/
if (ds->dst->pd->nr_chips > 1)
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL_2,
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
GLOBAL_CONTROL_2_MULTIPLE_CASCADE |
(ds->index & 0x1f));
else
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL_2,
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
GLOBAL_CONTROL_2_NO_CASCADE |
(ds->index & 0x1f));
if (ret)
@@ -91,7 +92,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
/* Force the priority of IGMP/MLD snoop frames and ARP frames
* to the highest setting.
*/
- return mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE,
+ return mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE,
GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP |
7 << GLOBAL2_PRIO_OVERRIDE_SNOOP_SHIFT |
GLOBAL2_PRIO_OVERRIDE_FORCE_ARP |
@@ -105,11 +106,11 @@ static int mv88e6131_setup(struct dsa_switch *ds)
ps->ds = ds;
- ret = mv88e6xxx_setup_common(ds);
+ ret = mv88e6xxx_setup_common(ps);
if (ret < 0)
return ret;
- mv88e6xxx_ppu_state_init(ds);
+ mv88e6xxx_ppu_state_init(ps);
switch (ps->id) {
case PORT_SWITCH_ID_6085:
@@ -127,7 +128,7 @@ static int mv88e6131_setup(struct dsa_switch *ds)
return -ENODEV;
}
- ret = mv88e6xxx_switch_reset(ds, false);
+ ret = mv88e6xxx_switch_reset(ps, false);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index e3998be13515..0b934b3008ca 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -37,6 +37,7 @@ static char *mv88e6171_drv_probe(struct device *dsa_dev,
static int mv88e6171_setup_global(struct dsa_switch *ds)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
u32 upstream_port = dsa_upstream_port(ds);
int ret;
u32 reg;
@@ -48,7 +49,7 @@ static int mv88e6171_setup_global(struct dsa_switch *ds)
/* Discard packets with excessive collisions, mask all
* interrupt sources, enable PPU.
*/
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL,
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
GLOBAL_CONTROL_PPU_ENABLE |
GLOBAL_CONTROL_DISCARD_EXCESS);
if (ret)
@@ -62,14 +63,14 @@ static int mv88e6171_setup_global(struct dsa_switch *ds)
upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT;
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
if (ret)
return ret;
/* Disable remote management for now, and set the switch's
* DSA device number.
*/
- return mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL_2,
+ return mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
ds->index & 0x1f);
}
@@ -80,13 +81,13 @@ static int mv88e6171_setup(struct dsa_switch *ds)
ps->ds = ds;
- ret = mv88e6xxx_setup_common(ds);
+ ret = mv88e6xxx_setup_common(ps);
if (ret < 0)
return ret;
ps->num_ports = 7;
- ret = mv88e6xxx_switch_reset(ds, true);
+ ret = mv88e6xxx_switch_reset(ps, true);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index baeb594b63cc..b745a1f36a1f 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -49,6 +49,7 @@ static char *mv88e6352_drv_probe(struct device *dsa_dev,
static int mv88e6352_setup_global(struct dsa_switch *ds)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
u32 upstream_port = dsa_upstream_port(ds);
int ret;
u32 reg;
@@ -60,7 +61,7 @@ static int mv88e6352_setup_global(struct dsa_switch *ds)
/* Discard packets with excessive collisions,
* mask all interrupt sources, enable PPU (bit 14, undocumented).
*/
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL,
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
GLOBAL_CONTROL_PPU_ENABLE |
GLOBAL_CONTROL_DISCARD_EXCESS);
if (ret)
@@ -73,14 +74,14 @@ static int mv88e6352_setup_global(struct dsa_switch *ds)
reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
if (ret)
return ret;
/* Disable remote management for now, and set the switch's
* DSA device number.
*/
- return mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x1c, ds->index & 0x1f);
+ return mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x1c, ds->index & 0x1f);
}
static int mv88e6352_setup(struct dsa_switch *ds)
@@ -90,7 +91,7 @@ static int mv88e6352_setup(struct dsa_switch *ds)
ps->ds = ds;
- ret = mv88e6xxx_setup_common(ds);
+ ret = mv88e6xxx_setup_common(ps);
if (ret < 0)
return ret;
@@ -98,7 +99,7 @@ static int mv88e6352_setup(struct dsa_switch *ds)
mutex_init(&ps->eeprom_mutex);
- ret = mv88e6xxx_switch_reset(ds, true);
+ ret = mv88e6xxx_switch_reset(ps, true);
if (ret < 0)
return ret;
@@ -116,7 +117,7 @@ static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr)
mutex_lock(&ps->eeprom_mutex);
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
GLOBAL2_EEPROM_OP_READ |
(addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
if (ret < 0)
@@ -126,7 +127,7 @@ static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr)
if (ret < 0)
goto error;
- ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_EEPROM_DATA);
+ ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA);
error:
mutex_unlock(&ps->eeprom_mutex);
return ret;
@@ -197,9 +198,10 @@ static int mv88e6352_get_eeprom(struct dsa_switch *ds,
static int mv88e6352_eeprom_is_readonly(struct dsa_switch *ds)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
- ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP);
+ ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP);
if (ret < 0)
return ret;
@@ -217,11 +219,11 @@ static int mv88e6352_write_eeprom_word(struct dsa_switch *ds, int addr,
mutex_lock(&ps->eeprom_mutex);
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data);
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data);
if (ret < 0)
goto error;
- ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
GLOBAL2_EEPROM_OP_WRITE |
(addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
if (ret < 0)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 93110460e0c3..b8db7ed12005 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -25,12 +25,10 @@
#include <net/switchdev.h>
#include "mv88e6xxx.h"
-static void assert_smi_lock(struct dsa_switch *ds)
+static void assert_smi_lock(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
if (unlikely(!mutex_is_locked(&ps->smi_mutex))) {
- dev_err(ds->master_dev, "SMI lock not held!\n");
+ dev_err(ps->dev, "SMI lock not held!\n");
dump_stack();
}
}
@@ -92,30 +90,29 @@ static int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr,
return ret & 0xffff;
}
-static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
+static int _mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps,
+ int addr, int reg)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
- assert_smi_lock(ds);
+ assert_smi_lock(ps);
ret = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, addr, reg);
if (ret < 0)
return ret;
- dev_dbg(ds->master_dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
+ dev_dbg(ps->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
addr, reg, ret);
return ret;
}
-int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
+int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_reg_read(ds, addr, reg);
+ ret = _mv88e6xxx_reg_read(ps, addr, reg);
mutex_unlock(&ps->smi_mutex);
return ret;
@@ -154,26 +151,24 @@ static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
return 0;
}
-static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg,
- u16 val)
+static int _mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
+ int reg, u16 val)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ assert_smi_lock(ps);
- assert_smi_lock(ds);
-
- dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
+ dev_dbg(ps->dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
addr, reg, val);
return __mv88e6xxx_reg_write(ps->bus, ps->sw_addr, addr, reg, val);
}
-int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
+int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
+ int reg, u16 val)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_reg_write(ds, addr, reg, val);
+ ret = _mv88e6xxx_reg_write(ps, addr, reg, val);
mutex_unlock(&ps->smi_mutex);
return ret;
@@ -182,25 +177,27 @@ EXPORT_SYMBOL_GPL(mv88e6xxx_reg_write);
int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int err;
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MAC_01,
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_01,
(addr[0] << 8) | addr[1]);
if (err)
return err;
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MAC_23,
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_23,
(addr[2] << 8) | addr[3]);
if (err)
return err;
- return mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MAC_45,
+ return mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_45,
(addr[4] << 8) | addr[5]);
}
EXPORT_SYMBOL_GPL(mv88e6xxx_set_addr_direct);
int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret, err;
int i;
@@ -208,7 +205,7 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
int j;
/* Write the MAC address byte. */
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SWITCH_MAC,
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SWITCH_MAC,
GLOBAL2_SWITCH_MAC_BUSY |
(i << 8) | addr[i]);
if (err)
@@ -216,13 +213,11 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
/* Wait for the write to complete. */
for (j = 0; j < 16; j++) {
- ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2,
+ ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2,
GLOBAL2_SWITCH_MAC);
if (ret < 0)
return ret;
- if (ret < 0)
- return ret;
if ((ret & GLOBAL2_SWITCH_MAC_BUSY) == 0)
break;
}
@@ -234,39 +229,40 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
}
EXPORT_SYMBOL_GPL(mv88e6xxx_set_addr_indirect);
-static int _mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
+static int _mv88e6xxx_phy_read(struct mv88e6xxx_priv_state *ps, int addr,
+ int regnum)
{
if (addr >= 0)
- return _mv88e6xxx_reg_read(ds, addr, regnum);
+ return _mv88e6xxx_reg_read(ps, addr, regnum);
return 0xffff;
}
-static int _mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum,
- u16 val)
+static int _mv88e6xxx_phy_write(struct mv88e6xxx_priv_state *ps, int addr,
+ int regnum, u16 val)
{
if (addr >= 0)
- return _mv88e6xxx_reg_write(ds, addr, regnum, val);
+ return _mv88e6xxx_reg_write(ps, addr, regnum, val);
return 0;
}
#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
-static int mv88e6xxx_ppu_disable(struct dsa_switch *ds)
+static int mv88e6xxx_ppu_disable(struct mv88e6xxx_priv_state *ps)
{
int ret;
unsigned long timeout;
- ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_CONTROL);
+ ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);
if (ret < 0)
return ret;
- ret = mv88e6xxx_reg_write(ds, 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(ds, REG_GLOBAL, GLOBAL_STATUS);
+ ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS);
if (ret < 0)
return ret;
@@ -279,23 +275,23 @@ static int mv88e6xxx_ppu_disable(struct dsa_switch *ds)
return -ETIMEDOUT;
}
-static int mv88e6xxx_ppu_enable(struct dsa_switch *ds)
+static int mv88e6xxx_ppu_enable(struct mv88e6xxx_priv_state *ps)
{
int ret, err;
unsigned long timeout;
- ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_CONTROL);
+ ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);
if (ret < 0)
return ret;
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL,
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
ret | GLOBAL_CONTROL_PPU_ENABLE);
if (err)
return err;
timeout = jiffies + 1 * HZ;
while (time_before(jiffies, timeout)) {
- ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATUS);
+ ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS);
if (ret < 0)
return ret;
@@ -314,9 +310,7 @@ static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
if (mutex_trylock(&ps->ppu_mutex)) {
- struct dsa_switch *ds = ps->ds;
-
- if (mv88e6xxx_ppu_enable(ds) == 0)
+ if (mv88e6xxx_ppu_enable(ps) == 0)
ps->ppu_disabled = 0;
mutex_unlock(&ps->ppu_mutex);
}
@@ -329,9 +323,8 @@ static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps)
schedule_work(&ps->ppu_work);
}
-static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds)
+static int mv88e6xxx_ppu_access_get(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
mutex_lock(&ps->ppu_mutex);
@@ -342,7 +335,7 @@ static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds)
* it.
*/
if (!ps->ppu_disabled) {
- ret = mv88e6xxx_ppu_disable(ds);
+ ret = mv88e6xxx_ppu_disable(ps);
if (ret < 0) {
mutex_unlock(&ps->ppu_mutex);
return ret;
@@ -356,19 +349,15 @@ static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds)
return ret;
}
-static void mv88e6xxx_ppu_access_put(struct dsa_switch *ds)
+static void mv88e6xxx_ppu_access_put(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
/* Schedule a timer to re-enable the PHY polling unit. */
mod_timer(&ps->ppu_timer, jiffies + msecs_to_jiffies(10));
mutex_unlock(&ps->ppu_mutex);
}
-void mv88e6xxx_ppu_state_init(struct dsa_switch *ds)
+void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
mutex_init(&ps->ppu_mutex);
INIT_WORK(&ps->ppu_work, mv88e6xxx_ppu_reenable_work);
init_timer(&ps->ppu_timer);
@@ -379,12 +368,13 @@ EXPORT_SYMBOL_GPL(mv88e6xxx_ppu_state_init);
int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
- ret = mv88e6xxx_ppu_access_get(ds);
+ ret = mv88e6xxx_ppu_access_get(ps);
if (ret >= 0) {
- ret = mv88e6xxx_reg_read(ds, addr, regnum);
- mv88e6xxx_ppu_access_put(ds);
+ ret = mv88e6xxx_reg_read(ps, addr, regnum);
+ mv88e6xxx_ppu_access_put(ps);
}
return ret;
@@ -394,12 +384,13 @@ EXPORT_SYMBOL_GPL(mv88e6xxx_phy_read_ppu);
int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
int regnum, u16 val)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
- ret = mv88e6xxx_ppu_access_get(ds);
+ ret = mv88e6xxx_ppu_access_get(ps);
if (ret >= 0) {
- ret = mv88e6xxx_reg_write(ds, addr, regnum, val);
- mv88e6xxx_ppu_access_put(ds);
+ ret = mv88e6xxx_reg_write(ps, addr, regnum, val);
+ mv88e6xxx_ppu_access_put(ps);
}
return ret;
@@ -407,10 +398,8 @@ int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
EXPORT_SYMBOL_GPL(mv88e6xxx_phy_write_ppu);
#endif
-static bool mv88e6xxx_6065_family(struct dsa_switch *ds)
+static bool mv88e6xxx_6065_family(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
switch (ps->id) {
case PORT_SWITCH_ID_6031:
case PORT_SWITCH_ID_6061:
@@ -421,10 +410,8 @@ static bool mv88e6xxx_6065_family(struct dsa_switch *ds)
return false;
}
-static bool mv88e6xxx_6095_family(struct dsa_switch *ds)
+static bool mv88e6xxx_6095_family(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
switch (ps->id) {
case PORT_SWITCH_ID_6092:
case PORT_SWITCH_ID_6095:
@@ -433,10 +420,8 @@ static bool mv88e6xxx_6095_family(struct dsa_switch *ds)
return false;
}
-static bool mv88e6xxx_6097_family(struct dsa_switch *ds)
+static bool mv88e6xxx_6097_family(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
switch (ps->id) {
case PORT_SWITCH_ID_6046:
case PORT_SWITCH_ID_6085:
@@ -447,10 +432,8 @@ static bool mv88e6xxx_6097_family(struct dsa_switch *ds)
return false;
}
-static bool mv88e6xxx_6165_family(struct dsa_switch *ds)
+static bool mv88e6xxx_6165_family(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
switch (ps->id) {
case PORT_SWITCH_ID_6123:
case PORT_SWITCH_ID_6161:
@@ -460,10 +443,8 @@ static bool mv88e6xxx_6165_family(struct dsa_switch *ds)
return false;
}
-static bool mv88e6xxx_6185_family(struct dsa_switch *ds)
+static bool mv88e6xxx_6185_family(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
switch (ps->id) {
case PORT_SWITCH_ID_6121:
case PORT_SWITCH_ID_6122:
@@ -478,10 +459,8 @@ static bool mv88e6xxx_6185_family(struct dsa_switch *ds)
return false;
}
-static bool mv88e6xxx_6320_family(struct dsa_switch *ds)
+static bool mv88e6xxx_6320_family(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
switch (ps->id) {
case PORT_SWITCH_ID_6320:
case PORT_SWITCH_ID_6321:
@@ -490,10 +469,8 @@ static bool mv88e6xxx_6320_family(struct dsa_switch *ds)
return false;
}
-static bool mv88e6xxx_6351_family(struct dsa_switch *ds)
+static bool mv88e6xxx_6351_family(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
switch (ps->id) {
case PORT_SWITCH_ID_6171:
case PORT_SWITCH_ID_6175:
@@ -504,10 +481,8 @@ static bool mv88e6xxx_6351_family(struct dsa_switch *ds)
return false;
}
-static bool mv88e6xxx_6352_family(struct dsa_switch *ds)
+static bool mv88e6xxx_6352_family(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
switch (ps->id) {
case PORT_SWITCH_ID_6172:
case PORT_SWITCH_ID_6176:
@@ -518,10 +493,8 @@ static bool mv88e6xxx_6352_family(struct dsa_switch *ds)
return false;
}
-static unsigned int mv88e6xxx_num_databases(struct dsa_switch *ds)
+static unsigned int mv88e6xxx_num_databases(struct mv88e6xxx_priv_state *ps)
{
- 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;
@@ -531,32 +504,32 @@ static unsigned int mv88e6xxx_num_databases(struct dsa_switch *ds)
return 64;
/* The following devices have 8-bit identifiers for 256 databases */
- if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds))
+ if (mv88e6xxx_6095_family(ps) || mv88e6xxx_6185_family(ps))
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))
+ if (mv88e6xxx_6097_family(ps) || mv88e6xxx_6165_family(ps) ||
+ mv88e6xxx_6351_family(ps) || mv88e6xxx_6352_family(ps))
return 4096;
return 0;
}
-static bool mv88e6xxx_has_fid_reg(struct dsa_switch *ds)
+static bool mv88e6xxx_has_fid_reg(struct mv88e6xxx_priv_state *ps)
{
/* Does the device have dedicated FID registers for ATU and VTU ops? */
- if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) ||
- mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds))
+ if (mv88e6xxx_6097_family(ps) || mv88e6xxx_6165_family(ps) ||
+ mv88e6xxx_6351_family(ps) || mv88e6xxx_6352_family(ps))
return true;
return false;
}
-static bool mv88e6xxx_has_stu(struct dsa_switch *ds)
+static bool mv88e6xxx_has_stu(struct mv88e6xxx_priv_state *ps)
{
/* Does the device have STU and dedicated SID registers for VTU ops? */
- if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) ||
- mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds))
+ if (mv88e6xxx_6097_family(ps) || mv88e6xxx_6165_family(ps) ||
+ mv88e6xxx_6351_family(ps) || mv88e6xxx_6352_family(ps))
return true;
return false;
@@ -578,7 +551,7 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL);
+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_PCS_CTRL);
if (ret < 0)
goto out;
@@ -592,7 +565,7 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
if (phydev->link)
reg |= PORT_PCS_CTRL_LINK_UP;
- if (mv88e6xxx_6065_family(ds) && phydev->speed > SPEED_100)
+ if (mv88e6xxx_6065_family(ps) && phydev->speed > SPEED_100)
goto out;
switch (phydev->speed) {
@@ -614,7 +587,7 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
if (phydev->duplex == DUPLEX_FULL)
reg |= PORT_PCS_CTRL_DUPLEX_FULL;
- if ((mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds)) &&
+ if ((mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps)) &&
(port >= ps->num_ports - 2)) {
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
@@ -624,20 +597,20 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
reg |= (PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
PORT_PCS_CTRL_RGMII_DELAY_TXCLK);
}
- _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_PCS_CTRL, reg);
+ _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_PCS_CTRL, reg);
out:
mutex_unlock(&ps->smi_mutex);
}
EXPORT_SYMBOL_GPL(mv88e6xxx_adjust_link);
-static int _mv88e6xxx_stats_wait(struct dsa_switch *ds)
+static int _mv88e6xxx_stats_wait(struct mv88e6xxx_priv_state *ps)
{
int ret;
int i;
for (i = 0; i < 10; i++) {
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATS_OP);
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATS_OP);
if ((ret & GLOBAL_STATS_OP_BUSY) == 0)
return 0;
}
@@ -645,52 +618,54 @@ static int _mv88e6xxx_stats_wait(struct dsa_switch *ds)
return -ETIMEDOUT;
}
-static int _mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port)
+static int _mv88e6xxx_stats_snapshot(struct mv88e6xxx_priv_state *ps,
+ int port)
{
int ret;
- if (mv88e6xxx_6320_family(ds) || mv88e6xxx_6352_family(ds))
+ if (mv88e6xxx_6320_family(ps) || mv88e6xxx_6352_family(ps))
port = (port + 1) << 5;
/* Snapshot the hardware statistics counters for this port. */
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_STATS_OP,
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_STATS_OP,
GLOBAL_STATS_OP_CAPTURE_PORT |
GLOBAL_STATS_OP_HIST_RX_TX | port);
if (ret < 0)
return ret;
/* Wait for the snapshotting to complete. */
- ret = _mv88e6xxx_stats_wait(ds);
+ ret = _mv88e6xxx_stats_wait(ps);
if (ret < 0)
return ret;
return 0;
}
-static void _mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val)
+static void _mv88e6xxx_stats_read(struct mv88e6xxx_priv_state *ps,
+ int stat, u32 *val)
{
u32 _val;
int ret;
*val = 0;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_STATS_OP,
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_STATS_OP,
GLOBAL_STATS_OP_READ_CAPTURED |
GLOBAL_STATS_OP_HIST_RX_TX | stat);
if (ret < 0)
return;
- ret = _mv88e6xxx_stats_wait(ds);
+ ret = _mv88e6xxx_stats_wait(ps);
if (ret < 0)
return;
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATS_COUNTER_32);
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATS_COUNTER_32);
if (ret < 0)
return;
_val = ret << 16;
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATS_COUNTER_01);
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATS_COUNTER_01);
if (ret < 0)
return;
@@ -759,26 +734,26 @@ static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
{ "out_management", 4, 0x1f | GLOBAL_STATS_OP_BANK_1, BANK1, },
};
-static bool mv88e6xxx_has_stat(struct dsa_switch *ds,
+static bool mv88e6xxx_has_stat(struct mv88e6xxx_priv_state *ps,
struct mv88e6xxx_hw_stat *stat)
{
switch (stat->type) {
case BANK0:
return true;
case BANK1:
- return mv88e6xxx_6320_family(ds);
+ return mv88e6xxx_6320_family(ps);
case PORT:
- return mv88e6xxx_6095_family(ds) ||
- mv88e6xxx_6185_family(ds) ||
- mv88e6xxx_6097_family(ds) ||
- mv88e6xxx_6165_family(ds) ||
- mv88e6xxx_6351_family(ds) ||
- mv88e6xxx_6352_family(ds);
+ return mv88e6xxx_6095_family(ps) ||
+ mv88e6xxx_6185_family(ps) ||
+ mv88e6xxx_6097_family(ps) ||
+ mv88e6xxx_6165_family(ps) ||
+ mv88e6xxx_6351_family(ps) ||
+ mv88e6xxx_6352_family(ps);
}
return false;
}
-static uint64_t _mv88e6xxx_get_ethtool_stat(struct dsa_switch *ds,
+static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_priv_state *ps,
struct mv88e6xxx_hw_stat *s,
int port)
{
@@ -789,13 +764,13 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct dsa_switch *ds,
switch (s->type) {
case PORT:
- ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), s->reg);
+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), s->reg);
if (ret < 0)
return UINT64_MAX;
low = ret;
if (s->sizeof_stat == 4) {
- ret = _mv88e6xxx_reg_read(ds, REG_PORT(port),
+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(port),
s->reg + 1);
if (ret < 0)
return UINT64_MAX;
@@ -804,9 +779,9 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct dsa_switch *ds,
break;
case BANK0:
case BANK1:
- _mv88e6xxx_stats_read(ds, s->reg, &low);
+ _mv88e6xxx_stats_read(ps, s->reg, &low);
if (s->sizeof_stat == 8)
- _mv88e6xxx_stats_read(ds, s->reg + 1, &high);
+ _mv88e6xxx_stats_read(ps, s->reg + 1, &high);
}
value = (((u64)high) << 16) | low;
return value;
@@ -814,12 +789,13 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct dsa_switch *ds,
void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
struct mv88e6xxx_hw_stat *stat;
int i, j;
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
- if (mv88e6xxx_has_stat(ds, stat)) {
+ if (mv88e6xxx_has_stat(ps, stat)) {
memcpy(data + j * ETH_GSTRING_LEN, stat->string,
ETH_GSTRING_LEN);
j++;
@@ -830,12 +806,13 @@ EXPORT_SYMBOL_GPL(mv88e6xxx_get_strings);
int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
struct mv88e6xxx_hw_stat *stat;
int i, j;
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
- if (mv88e6xxx_has_stat(ds, stat))
+ if (mv88e6xxx_has_stat(ps, stat))
j++;
}
return j;
@@ -853,15 +830,15 @@ mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_stats_snapshot(ds, port);
+ ret = _mv88e6xxx_stats_snapshot(ps, port);
if (ret < 0) {
mutex_unlock(&ps->smi_mutex);
return;
}
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
- if (mv88e6xxx_has_stat(ds, stat)) {
- data[j] = _mv88e6xxx_get_ethtool_stat(ds, stat, port);
+ if (mv88e6xxx_has_stat(ps, stat)) {
+ data[j] = _mv88e6xxx_get_ethtool_stat(ps, stat, port);
j++;
}
}
@@ -879,6 +856,7 @@ EXPORT_SYMBOL_GPL(mv88e6xxx_get_regs_len);
void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
struct ethtool_regs *regs, void *_p)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
u16 *p = _p;
int i;
@@ -889,14 +867,14 @@ void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
for (i = 0; i < 32; i++) {
int ret;
- ret = mv88e6xxx_reg_read(ds, REG_PORT(port), i);
+ ret = mv88e6xxx_reg_read(ps, REG_PORT(port), i);
if (ret >= 0)
p[i] = ret;
}
}
EXPORT_SYMBOL_GPL(mv88e6xxx_get_regs);
-static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset,
+static int _mv88e6xxx_wait(struct mv88e6xxx_priv_state *ps, int reg, int offset,
u16 mask)
{
unsigned long timeout = jiffies + HZ / 10;
@@ -904,7 +882,7 @@ static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset,
while (time_before(jiffies, timeout)) {
int ret;
- ret = _mv88e6xxx_reg_read(ds, reg, offset);
+ ret = _mv88e6xxx_reg_read(ps, reg, offset);
if (ret < 0)
return ret;
if (!(ret & mask))
@@ -915,76 +893,82 @@ static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset,
return -ETIMEDOUT;
}
-static int mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
+static int mv88e6xxx_wait(struct mv88e6xxx_priv_state *ps, int reg,
+ int offset, u16 mask)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_wait(ds, reg, offset, mask);
+ ret = _mv88e6xxx_wait(ps, reg, offset, mask);
mutex_unlock(&ps->smi_mutex);
return ret;
}
-static int _mv88e6xxx_phy_wait(struct dsa_switch *ds)
+static int _mv88e6xxx_phy_wait(struct mv88e6xxx_priv_state *ps)
{
- return _mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_SMI_OP,
+ return _mv88e6xxx_wait(ps, REG_GLOBAL2, GLOBAL2_SMI_OP,
GLOBAL2_SMI_OP_BUSY);
}
int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
{
- return mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+ return mv88e6xxx_wait(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
GLOBAL2_EEPROM_OP_LOAD);
}
EXPORT_SYMBOL_GPL(mv88e6xxx_eeprom_load_wait);
int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
{
- return mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+ return mv88e6xxx_wait(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
GLOBAL2_EEPROM_OP_BUSY);
}
EXPORT_SYMBOL_GPL(mv88e6xxx_eeprom_busy_wait);
-static int _mv88e6xxx_atu_wait(struct dsa_switch *ds)
+static int _mv88e6xxx_atu_wait(struct mv88e6xxx_priv_state *ps)
{
- return _mv88e6xxx_wait(ds, REG_GLOBAL, GLOBAL_ATU_OP,
+ return _mv88e6xxx_wait(ps, REG_GLOBAL, GLOBAL_ATU_OP,
GLOBAL_ATU_OP_BUSY);
}
-static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr,
- int regnum)
+static int _mv88e6xxx_phy_read_indirect(struct mv88e6xxx_priv_state *ps,
+ int addr, int regnum)
{
int ret;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SMI_OP,
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SMI_OP,
GLOBAL2_SMI_OP_22_READ | (addr << 5) |
regnum);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_phy_wait(ds);
+ ret = _mv88e6xxx_phy_wait(ps);
if (ret < 0)
return ret;
- return _mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_SMI_DATA);
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_SMI_DATA);
+
+ return ret;
}
-static int _mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr,
- int regnum, u16 val)
+static int _mv88e6xxx_phy_write_indirect(struct mv88e6xxx_priv_state *ps,
+ int addr, int regnum, u16 val)
{
int ret;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SMI_DATA, val);
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SMI_DATA, val);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SMI_OP,
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SMI_OP,
GLOBAL2_SMI_OP_22_WRITE | (addr << 5) |
regnum);
- return _mv88e6xxx_phy_wait(ds);
+ return _mv88e6xxx_phy_wait(ps);
}
int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
@@ -994,14 +978,14 @@ int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
mutex_lock(&ps->smi_mutex);
- reg = _mv88e6xxx_phy_read_indirect(ds, port, 16);
+ reg = _mv88e6xxx_phy_read_indirect(ps, port, 16);
if (reg < 0)
goto out;
e->eee_enabled = !!(reg & 0x0200);
e->tx_lpi_enabled = !!(reg & 0x0100);
- reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_STATUS);
+ reg = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_STATUS);
if (reg < 0)
goto out;
@@ -1023,7 +1007,7 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_phy_read_indirect(ds, port, 16);
+ ret = _mv88e6xxx_phy_read_indirect(ps, port, 16);
if (ret < 0)
goto out;
@@ -1033,7 +1017,7 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
if (e->tx_lpi_enabled)
reg |= 0x0100;
- ret = _mv88e6xxx_phy_write_indirect(ds, port, 16, reg);
+ ret = _mv88e6xxx_phy_write_indirect(ps, port, 16, reg);
out:
mutex_unlock(&ps->smi_mutex);
@@ -1041,21 +1025,21 @@ out:
}
EXPORT_SYMBOL_GPL(mv88e6xxx_set_eee);
-static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 fid, u16 cmd)
+static int _mv88e6xxx_atu_cmd(struct mv88e6xxx_priv_state *ps, u16 fid, u16 cmd)
{
int ret;
- if (mv88e6xxx_has_fid_reg(ds)) {
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid);
+ if (mv88e6xxx_has_fid_reg(ps)) {
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_FID, fid);
if (ret < 0)
return ret;
- } else if (mv88e6xxx_num_databases(ds) == 256) {
+ } else if (mv88e6xxx_num_databases(ps) == 256) {
/* ATU DBNum[7:4] are located in ATU Control 15:12 */
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL);
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL,
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL,
(ret & 0xfff) |
((fid << 8) & 0xf000));
if (ret < 0)
@@ -1065,14 +1049,14 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 fid, u16 cmd)
cmd |= fid & 0xf;
}
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_OP, cmd);
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_OP, cmd);
if (ret < 0)
return ret;
- return _mv88e6xxx_atu_wait(ds);
+ return _mv88e6xxx_atu_wait(ps);
}
-static int _mv88e6xxx_atu_data_write(struct dsa_switch *ds,
+static int _mv88e6xxx_atu_data_write(struct mv88e6xxx_priv_state *ps,
struct mv88e6xxx_atu_entry *entry)
{
u16 data = entry->state & GLOBAL_ATU_DATA_STATE_MASK;
@@ -1092,21 +1076,21 @@ static int _mv88e6xxx_atu_data_write(struct dsa_switch *ds,
data |= (entry->portv_trunkid << shift) & mask;
}
- return _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, data);
+ return _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_DATA, data);
}
-static int _mv88e6xxx_atu_flush_move(struct dsa_switch *ds,
+static int _mv88e6xxx_atu_flush_move(struct mv88e6xxx_priv_state *ps,
struct mv88e6xxx_atu_entry *entry,
bool static_too)
{
int op;
int err;
- err = _mv88e6xxx_atu_wait(ds);
+ err = _mv88e6xxx_atu_wait(ps);
if (err)
return err;
- err = _mv88e6xxx_atu_data_write(ds, entry);
+ err = _mv88e6xxx_atu_data_write(ps, entry);
if (err)
return err;
@@ -1118,21 +1102,22 @@ static int _mv88e6xxx_atu_flush_move(struct dsa_switch *ds,
GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC;
}
- return _mv88e6xxx_atu_cmd(ds, entry->fid, op);
+ return _mv88e6xxx_atu_cmd(ps, entry->fid, op);
}
-static int _mv88e6xxx_atu_flush(struct dsa_switch *ds, u16 fid, bool static_too)
+static int _mv88e6xxx_atu_flush(struct mv88e6xxx_priv_state *ps,
+ u16 fid, bool static_too)
{
struct mv88e6xxx_atu_entry entry = {
.fid = fid,
.state = 0, /* EntryState bits must be 0 */
};
- return _mv88e6xxx_atu_flush_move(ds, &entry, static_too);
+ return _mv88e6xxx_atu_flush_move(ps, &entry, static_too);
}
-static int _mv88e6xxx_atu_move(struct dsa_switch *ds, u16 fid, int from_port,
- int to_port, bool static_too)
+static int _mv88e6xxx_atu_move(struct mv88e6xxx_priv_state *ps, u16 fid,
+ int from_port, int to_port, bool static_too)
{
struct mv88e6xxx_atu_entry entry = {
.trunk = false,
@@ -1146,14 +1131,14 @@ static int _mv88e6xxx_atu_move(struct dsa_switch *ds, u16 fid, int from_port,
entry.portv_trunkid = (to_port & 0x0f) << 4;
entry.portv_trunkid |= from_port & 0x0f;
- return _mv88e6xxx_atu_flush_move(ds, &entry, static_too);
+ return _mv88e6xxx_atu_flush_move(ps, &entry, static_too);
}
-static int _mv88e6xxx_atu_remove(struct dsa_switch *ds, u16 fid, int port,
- bool static_too)
+static int _mv88e6xxx_atu_remove(struct mv88e6xxx_priv_state *ps, u16 fid,
+ int port, bool static_too)
{
/* Destination port 0xF means remove the entries */
- return _mv88e6xxx_atu_move(ds, fid, port, 0x0f, static_too);
+ return _mv88e6xxx_atu_move(ps, fid, port, 0x0f, static_too);
}
static const char * const mv88e6xxx_port_state_names[] = {
@@ -1163,12 +1148,14 @@ static const char * const mv88e6xxx_port_state_names[] = {
[PORT_CONTROL_STATE_FORWARDING] = "Forwarding",
};
-static int _mv88e6xxx_port_state(struct dsa_switch *ds, int port, u8 state)
+static int _mv88e6xxx_port_state(struct mv88e6xxx_priv_state *ps, int port,
+ u8 state)
{
+ struct dsa_switch *ds = ps->ds;
int reg, ret = 0;
u8 oldstate;
- reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL);
+ reg = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL);
if (reg < 0)
return reg;
@@ -1183,13 +1170,13 @@ static int _mv88e6xxx_port_state(struct dsa_switch *ds, int port, u8 state)
oldstate == PORT_CONTROL_STATE_FORWARDING)
&& (state == PORT_CONTROL_STATE_DISABLED ||
state == PORT_CONTROL_STATE_BLOCKING)) {
- ret = _mv88e6xxx_atu_remove(ds, 0, port, false);
+ ret = _mv88e6xxx_atu_remove(ps, 0, port, false);
if (ret)
return ret;
}
reg = (reg & ~PORT_CONTROL_STATE_MASK) | state;
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL,
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL,
reg);
if (ret)
return ret;
@@ -1202,11 +1189,12 @@ static int _mv88e6xxx_port_state(struct dsa_switch *ds, int port, u8 state)
return ret;
}
-static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port)
+static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_priv_state *ps,
+ 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;
+ struct dsa_switch *ds = ps->ds;
u16 output_ports = 0;
int reg;
int i;
@@ -1229,14 +1217,14 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port)
/* prevent frames from going back out of the port they came in on */
output_ports &= ~BIT(port);
- reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN);
+ reg = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_BASE_VLAN);
if (reg < 0)
return reg;
reg &= ~mask;
reg |= output_ports & mask;
- return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN, reg);
+ return _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_BASE_VLAN, reg);
}
void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
@@ -1270,13 +1258,14 @@ void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
}
EXPORT_SYMBOL_GPL(mv88e6xxx_port_stp_state_set);
-static int _mv88e6xxx_port_pvid(struct dsa_switch *ds, int port, u16 *new,
- u16 *old)
+static int _mv88e6xxx_port_pvid(struct mv88e6xxx_priv_state *ps, int port,
+ u16 *new, u16 *old)
{
+ struct dsa_switch *ds = ps->ds;
u16 pvid;
int ret;
- ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_DEFAULT_VLAN);
+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_DEFAULT_VLAN);
if (ret < 0)
return ret;
@@ -1286,7 +1275,7 @@ static int _mv88e6xxx_port_pvid(struct dsa_switch *ds, int port, u16 *new,
ret &= ~PORT_DEFAULT_VLAN_MASK;
ret |= *new & PORT_DEFAULT_VLAN_MASK;
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_DEFAULT_VLAN, ret);
if (ret < 0)
return ret;
@@ -1301,55 +1290,56 @@ static int _mv88e6xxx_port_pvid(struct dsa_switch *ds, int port, u16 *new,
return 0;
}
-static int _mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid)
+static int _mv88e6xxx_port_pvid_get(struct mv88e6xxx_priv_state *ps,
+ int port, u16 *pvid)
{
- return _mv88e6xxx_port_pvid(ds, port, NULL, pvid);
+ return _mv88e6xxx_port_pvid(ps, port, NULL, pvid);
}
-static int _mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 pvid)
+static int _mv88e6xxx_port_pvid_set(struct mv88e6xxx_priv_state *ps,
+ int port, u16 pvid)
{
- return _mv88e6xxx_port_pvid(ds, port, &pvid, NULL);
+ return _mv88e6xxx_port_pvid(ps, port, &pvid, NULL);
}
-static int _mv88e6xxx_vtu_wait(struct dsa_switch *ds)
+static int _mv88e6xxx_vtu_wait(struct mv88e6xxx_priv_state *ps)
{
- return _mv88e6xxx_wait(ds, REG_GLOBAL, GLOBAL_VTU_OP,
+ return _mv88e6xxx_wait(ps, REG_GLOBAL, GLOBAL_VTU_OP,
GLOBAL_VTU_OP_BUSY);
}
-static int _mv88e6xxx_vtu_cmd(struct dsa_switch *ds, u16 op)
+static int _mv88e6xxx_vtu_cmd(struct mv88e6xxx_priv_state *ps, u16 op)
{
int ret;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_OP, op);
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_OP, op);
if (ret < 0)
return ret;
- return _mv88e6xxx_vtu_wait(ds);
+ return _mv88e6xxx_vtu_wait(ps);
}
-static int _mv88e6xxx_vtu_stu_flush(struct dsa_switch *ds)
+static int _mv88e6xxx_vtu_stu_flush(struct mv88e6xxx_priv_state *ps)
{
int ret;
- ret = _mv88e6xxx_vtu_wait(ds);
+ ret = _mv88e6xxx_vtu_wait(ps);
if (ret < 0)
return ret;
- return _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_FLUSH_ALL);
+ return _mv88e6xxx_vtu_cmd(ps, GLOBAL_VTU_OP_FLUSH_ALL);
}
-static int _mv88e6xxx_vtu_stu_data_read(struct dsa_switch *ds,
+static int _mv88e6xxx_vtu_stu_data_read(struct mv88e6xxx_priv_state *ps,
struct mv88e6xxx_vtu_stu_entry *entry,
unsigned int nibble_offset)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
u16 regs[3];
int i;
int ret;
for (i = 0; i < 3; ++i) {
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL,
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL,
GLOBAL_VTU_DATA_0_3 + i);
if (ret < 0)
return ret;
@@ -1367,11 +1357,10 @@ static int _mv88e6xxx_vtu_stu_data_read(struct dsa_switch *ds,
return 0;
}
-static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds,
+static int _mv88e6xxx_vtu_stu_data_write(struct mv88e6xxx_priv_state *ps,
struct mv88e6xxx_vtu_stu_entry *entry,
unsigned int nibble_offset)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
u16 regs[3] = { 0 };
int i;
int ret;
@@ -1384,7 +1373,7 @@ static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds,
}
for (i = 0; i < 3; ++i) {
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL,
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL,
GLOBAL_VTU_DATA_0_3 + i, regs[i]);
if (ret < 0)
return ret;
@@ -1393,27 +1382,27 @@ static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds,
return 0;
}
-static int _mv88e6xxx_vtu_vid_write(struct dsa_switch *ds, u16 vid)
+static int _mv88e6xxx_vtu_vid_write(struct mv88e6xxx_priv_state *ps, u16 vid)
{
- return _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_VID,
+ return _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_VID,
vid & GLOBAL_VTU_VID_MASK);
}
-static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds,
+static int _mv88e6xxx_vtu_getnext(struct mv88e6xxx_priv_state *ps,
struct mv88e6xxx_vtu_stu_entry *entry)
{
struct mv88e6xxx_vtu_stu_entry next = { 0 };
int ret;
- ret = _mv88e6xxx_vtu_wait(ds);
+ ret = _mv88e6xxx_vtu_wait(ps);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_VTU_GET_NEXT);
+ ret = _mv88e6xxx_vtu_cmd(ps, GLOBAL_VTU_OP_VTU_GET_NEXT);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_VTU_VID);
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_VID);
if (ret < 0)
return ret;
@@ -1421,22 +1410,22 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds,
next.valid = !!(ret & GLOBAL_VTU_VID_VALID);
if (next.valid) {
- ret = _mv88e6xxx_vtu_stu_data_read(ds, &next, 0);
+ ret = _mv88e6xxx_vtu_stu_data_read(ps, &next, 0);
if (ret < 0)
return ret;
- if (mv88e6xxx_has_fid_reg(ds)) {
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL,
+ if (mv88e6xxx_has_fid_reg(ps)) {
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL,
GLOBAL_VTU_FID);
if (ret < 0)
return ret;
next.fid = ret & GLOBAL_VTU_FID_MASK;
- } else if (mv88e6xxx_num_databases(ds) == 256) {
+ } else if (mv88e6xxx_num_databases(ps) == 256) {
/* VTU DBNum[7:4] are located in VTU Operation 11:8, and
* VTU DBNum[3:0] are located in VTU Operation 3:0
*/
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL,
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL,
GLOBAL_VTU_OP);
if (ret < 0)
return ret;
@@ -1445,8 +1434,8 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds,
next.fid |= ret & 0xf;
}
- if (mv88e6xxx_has_stu(ds)) {
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL,
+ if (mv88e6xxx_has_stu(ps)) {
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL,
GLOBAL_VTU_SID);
if (ret < 0)
return ret;
@@ -1470,16 +1459,16 @@ int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
mutex_lock(&ps->smi_mutex);
- err = _mv88e6xxx_port_pvid_get(ds, port, &pvid);
+ err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);
if (err)
goto unlock;
- err = _mv88e6xxx_vtu_vid_write(ds, GLOBAL_VTU_VID_MASK);
+ err = _mv88e6xxx_vtu_vid_write(ps, GLOBAL_VTU_VID_MASK);
if (err)
goto unlock;
do {
- err = _mv88e6xxx_vtu_getnext(ds, &next);
+ err = _mv88e6xxx_vtu_getnext(ps, &next);
if (err)
break;
@@ -1511,14 +1500,14 @@ unlock:
}
EXPORT_SYMBOL_GPL(mv88e6xxx_port_vlan_dump);
-static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds,
+static int _mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_priv_state *ps,
struct mv88e6xxx_vtu_stu_entry *entry)
{
u16 op = GLOBAL_VTU_OP_VTU_LOAD_PURGE;
u16 reg = 0;
int ret;
- ret = _mv88e6xxx_vtu_wait(ds);
+ ret = _mv88e6xxx_vtu_wait(ps);
if (ret < 0)
return ret;
@@ -1526,23 +1515,23 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds,
goto loadpurge;
/* Write port member tags */
- ret = _mv88e6xxx_vtu_stu_data_write(ds, entry, 0);
+ ret = _mv88e6xxx_vtu_stu_data_write(ps, entry, 0);
if (ret < 0)
return ret;
- if (mv88e6xxx_has_stu(ds)) {
+ if (mv88e6xxx_has_stu(ps)) {
reg = entry->sid & GLOBAL_VTU_SID_MASK;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_SID, reg);
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_SID, reg);
if (ret < 0)
return ret;
}
- if (mv88e6xxx_has_fid_reg(ds)) {
+ if (mv88e6xxx_has_fid_reg(ps)) {
reg = entry->fid & GLOBAL_VTU_FID_MASK;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_FID, reg);
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_FID, reg);
if (ret < 0)
return ret;
- } else if (mv88e6xxx_num_databases(ds) == 256) {
+ } else if (mv88e6xxx_num_databases(ps) == 256) {
/* VTU DBNum[7:4] are located in VTU Operation 11:8, and
* VTU DBNum[3:0] are located in VTU Operation 3:0
*/
@@ -1553,46 +1542,46 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds,
reg = GLOBAL_VTU_VID_VALID;
loadpurge:
reg |= entry->vid & GLOBAL_VTU_VID_MASK;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_VID, reg);
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_VID, reg);
if (ret < 0)
return ret;
- return _mv88e6xxx_vtu_cmd(ds, op);
+ return _mv88e6xxx_vtu_cmd(ps, op);
}
-static int _mv88e6xxx_stu_getnext(struct dsa_switch *ds, u8 sid,
+static int _mv88e6xxx_stu_getnext(struct mv88e6xxx_priv_state *ps, u8 sid,
struct mv88e6xxx_vtu_stu_entry *entry)
{
struct mv88e6xxx_vtu_stu_entry next = { 0 };
int ret;
- ret = _mv88e6xxx_vtu_wait(ds);
+ ret = _mv88e6xxx_vtu_wait(ps);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_SID,
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_SID,
sid & GLOBAL_VTU_SID_MASK);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_STU_GET_NEXT);
+ ret = _mv88e6xxx_vtu_cmd(ps, GLOBAL_VTU_OP_STU_GET_NEXT);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_VTU_SID);
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_SID);
if (ret < 0)
return ret;
next.sid = ret & GLOBAL_VTU_SID_MASK;
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_VTU_VID);
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_VID);
if (ret < 0)
return ret;
next.valid = !!(ret & GLOBAL_VTU_VID_VALID);
if (next.valid) {
- ret = _mv88e6xxx_vtu_stu_data_read(ds, &next, 2);
+ ret = _mv88e6xxx_vtu_stu_data_read(ps, &next, 2);
if (ret < 0)
return ret;
}
@@ -1601,13 +1590,13 @@ static int _mv88e6xxx_stu_getnext(struct dsa_switch *ds, u8 sid,
return 0;
}
-static int _mv88e6xxx_stu_loadpurge(struct dsa_switch *ds,
+static int _mv88e6xxx_stu_loadpurge(struct mv88e6xxx_priv_state *ps,
struct mv88e6xxx_vtu_stu_entry *entry)
{
u16 reg = 0;
int ret;
- ret = _mv88e6xxx_vtu_wait(ds);
+ ret = _mv88e6xxx_vtu_wait(ps);
if (ret < 0)
return ret;
@@ -1615,40 +1604,41 @@ static int _mv88e6xxx_stu_loadpurge(struct dsa_switch *ds,
goto loadpurge;
/* Write port states */
- ret = _mv88e6xxx_vtu_stu_data_write(ds, entry, 2);
+ ret = _mv88e6xxx_vtu_stu_data_write(ps, entry, 2);
if (ret < 0)
return ret;
reg = GLOBAL_VTU_VID_VALID;
loadpurge:
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_VID, reg);
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_VID, reg);
if (ret < 0)
return ret;
reg = entry->sid & GLOBAL_VTU_SID_MASK;
- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_SID, reg);
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_SID, reg);
if (ret < 0)
return ret;
- return _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_STU_LOAD_PURGE);
+ return _mv88e6xxx_vtu_cmd(ps, GLOBAL_VTU_OP_STU_LOAD_PURGE);
}
-static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new,
- u16 *old)
+static int _mv88e6xxx_port_fid(struct mv88e6xxx_priv_state *ps, int port,
+ u16 *new, u16 *old)
{
+ struct dsa_switch *ds = ps->ds;
u16 upper_mask;
u16 fid;
int ret;
- if (mv88e6xxx_num_databases(ds) == 4096)
+ if (mv88e6xxx_num_databases(ps) == 4096)
upper_mask = 0xff;
- else if (mv88e6xxx_num_databases(ds) == 256)
+ else if (mv88e6xxx_num_databases(ps) == 256)
upper_mask = 0xf;
else
return -EOPNOTSUPP;
/* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */
- ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN);
+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_BASE_VLAN);
if (ret < 0)
return ret;
@@ -1658,14 +1648,14 @@ static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new,
ret &= ~PORT_BASE_VLAN_FID_3_0_MASK;
ret |= (*new << 12) & PORT_BASE_VLAN_FID_3_0_MASK;
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN,
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_BASE_VLAN,
ret);
if (ret < 0)
return ret;
}
/* Port's default FID bits 11:4 are located in reg 0x05, offset 0 */
- ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL_1);
+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL_1);
if (ret < 0)
return ret;
@@ -1675,7 +1665,7 @@ static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new,
ret &= ~upper_mask;
ret |= (*new >> 4) & upper_mask;
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_1,
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_1,
ret);
if (ret < 0)
return ret;
@@ -1689,19 +1679,20 @@ static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new,
return 0;
}
-static int _mv88e6xxx_port_fid_get(struct dsa_switch *ds, int port, u16 *fid)
+static int _mv88e6xxx_port_fid_get(struct mv88e6xxx_priv_state *ps,
+ int port, u16 *fid)
{
- return _mv88e6xxx_port_fid(ds, port, NULL, fid);
+ return _mv88e6xxx_port_fid(ps, port, NULL, fid);
}
-static int _mv88e6xxx_port_fid_set(struct dsa_switch *ds, int port, u16 fid)
+static int _mv88e6xxx_port_fid_set(struct mv88e6xxx_priv_state *ps,
+ int port, u16 fid)
{
- return _mv88e6xxx_port_fid(ds, port, &fid, NULL);
+ return _mv88e6xxx_port_fid(ps, port, &fid, NULL);
}
-static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
+static int _mv88e6xxx_fid_new(struct mv88e6xxx_priv_state *ps, u16 *fid)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
struct mv88e6xxx_vtu_stu_entry vlan;
int i, err;
@@ -1710,7 +1701,7 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
/* Set every FID bit used by the (un)bridged ports */
for (i = 0; i < ps->num_ports; ++i) {
- err = _mv88e6xxx_port_fid_get(ds, i, fid);
+ err = _mv88e6xxx_port_fid_get(ps, i, fid);
if (err)
return err;
@@ -1718,12 +1709,12 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
}
/* Set every FID bit used by the VLAN entries */
- err = _mv88e6xxx_vtu_vid_write(ds, GLOBAL_VTU_VID_MASK);
+ err = _mv88e6xxx_vtu_vid_write(ps, GLOBAL_VTU_VID_MASK);
if (err)
return err;
do {
- err = _mv88e6xxx_vtu_getnext(ds, &vlan);
+ err = _mv88e6xxx_vtu_getnext(ps, &vlan);
if (err)
return err;
@@ -1737,24 +1728,24 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
* databases are not needed. Return the next positive available.
*/
*fid = find_next_zero_bit(fid_bitmap, MV88E6XXX_N_FID, 1);
- if (unlikely(*fid >= mv88e6xxx_num_databases(ds)))
+ if (unlikely(*fid >= mv88e6xxx_num_databases(ps)))
return -ENOSPC;
/* Clear the database */
- return _mv88e6xxx_atu_flush(ds, *fid, true);
+ return _mv88e6xxx_atu_flush(ps, *fid, true);
}
-static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid,
+static int _mv88e6xxx_vtu_new(struct mv88e6xxx_priv_state *ps, u16 vid,
struct mv88e6xxx_vtu_stu_entry *entry)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ struct dsa_switch *ds = ps->ds;
struct mv88e6xxx_vtu_stu_entry vlan = {
.valid = true,
.vid = vid,
};
int i, err;
- err = _mv88e6xxx_fid_new(ds, &vlan.fid);
+ err = _mv88e6xxx_fid_new(ps, &vlan.fid);
if (err)
return err;
@@ -1764,8 +1755,8 @@ static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid,
? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED
: GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
- if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) ||
- mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) {
+ if (mv88e6xxx_6097_family(ps) || mv88e6xxx_6165_family(ps) ||
+ mv88e6xxx_6351_family(ps) || mv88e6xxx_6352_family(ps)) {
struct mv88e6xxx_vtu_stu_entry vstp;
/* Adding a VTU entry requires a valid STU entry. As VSTP is not
@@ -1773,7 +1764,7 @@ static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid,
* entries. Thus, validate the SID 0.
*/
vlan.sid = 0;
- err = _mv88e6xxx_stu_getnext(ds, GLOBAL_VTU_SID_MASK, &vstp);
+ err = _mv88e6xxx_stu_getnext(ps, GLOBAL_VTU_SID_MASK, &vstp);
if (err)
return err;
@@ -1782,7 +1773,7 @@ static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid,
vstp.valid = true;
vstp.sid = vlan.sid;
- err = _mv88e6xxx_stu_loadpurge(ds, &vstp);
+ err = _mv88e6xxx_stu_loadpurge(ps, &vstp);
if (err)
return err;
}
@@ -1792,7 +1783,7 @@ static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid,
return 0;
}
-static int _mv88e6xxx_vtu_get(struct dsa_switch *ds, u16 vid,
+static int _mv88e6xxx_vtu_get(struct mv88e6xxx_priv_state *ps, u16 vid,
struct mv88e6xxx_vtu_stu_entry *entry, bool creat)
{
int err;
@@ -1800,11 +1791,11 @@ static int _mv88e6xxx_vtu_get(struct dsa_switch *ds, u16 vid,
if (!vid)
return -EINVAL;
- err = _mv88e6xxx_vtu_vid_write(ds, vid - 1);
+ err = _mv88e6xxx_vtu_vid_write(ps, vid - 1);
if (err)
return err;
- err = _mv88e6xxx_vtu_getnext(ds, entry);
+ err = _mv88e6xxx_vtu_getnext(ps, entry);
if (err)
return err;
@@ -1815,7 +1806,7 @@ static int _mv88e6xxx_vtu_get(struct dsa_switch *ds, u16 vid,
* -EOPNOTSUPP to inform bridge about an eventual software VLAN.
*/
- err = _mv88e6xxx_vtu_new(ds, vid, entry);
+ err = _mv88e6xxx_vtu_new(ps, vid, entry);
}
return err;
@@ -1833,12 +1824,12 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
mutex_lock(&ps->smi_mutex);
- err = _mv88e6xxx_vtu_vid_write(ds, vid_begin - 1);
+ err = _mv88e6xxx_vtu_vid_write(ps, vid_begin - 1);
if (err)
goto unlock;
do {
- err = _mv88e6xxx_vtu_getnext(ds, &vlan);
+ err = _mv88e6xxx_vtu_getnext(ps, &vlan);
if (err)
goto unlock;
@@ -1892,7 +1883,7 @@ int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL_2);
+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL_2);
if (ret < 0)
goto unlock;
@@ -1902,7 +1893,7 @@ int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
ret &= ~PORT_CONTROL_2_8021Q_MASK;
ret |= new & PORT_CONTROL_2_8021Q_MASK;
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_2,
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_2,
ret);
if (ret < 0)
goto unlock;
@@ -1941,13 +1932,13 @@ int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
}
EXPORT_SYMBOL_GPL(mv88e6xxx_port_vlan_prepare);
-static int _mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid,
- bool untagged)
+static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_priv_state *ps, int port,
+ u16 vid, bool untagged)
{
struct mv88e6xxx_vtu_stu_entry vlan;
int err;
- err = _mv88e6xxx_vtu_get(ds, vid, &vlan, true);
+ err = _mv88e6xxx_vtu_get(ps, vid, &vlan, true);
if (err)
return err;
@@ -1955,7 +1946,7 @@ static int _mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid,
GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED :
GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED;
- return _mv88e6xxx_vtu_loadpurge(ds, &vlan);
+ return _mv88e6xxx_vtu_loadpurge(ps, &vlan);
}
void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
@@ -1970,11 +1961,11 @@ void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
mutex_lock(&ps->smi_mutex);
for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid)
- if (_mv88e6xxx_port_vlan_add(ds, port, vid, untagged))
+ if (_mv88e6xxx_port_vlan_add(ps, port, vid, untagged))
netdev_err(ds->ports[port], "failed to add VLAN %d%c\n",
vid, untagged ? 'u' : 't');
- if (pvid && _mv88e6xxx_port_pvid_set(ds, port, vlan->vid_end))
+ if (pvid && _mv88e6xxx_port_pvid_set(ps, port, vlan->vid_end))
netdev_err(ds->ports[port], "failed to set PVID %d\n",
vlan->vid_end);
@@ -1982,13 +1973,14 @@ void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
}
EXPORT_SYMBOL_GPL(mv88e6xxx_port_vlan_add);
-static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
+static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_priv_state *ps,
+ int port, u16 vid)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ struct dsa_switch *ds = ps->ds;
struct mv88e6xxx_vtu_stu_entry vlan;
int i, err;
- err = _mv88e6xxx_vtu_get(ds, vid, &vlan, false);
+ err = _mv88e6xxx_vtu_get(ps, vid, &vlan, false);
if (err)
return err;
@@ -2010,11 +2002,11 @@ static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
}
}
- err = _mv88e6xxx_vtu_loadpurge(ds, &vlan);
+ err = _mv88e6xxx_vtu_loadpurge(ps, &vlan);
if (err)
return err;
- return _mv88e6xxx_atu_remove(ds, vlan.fid, port, false);
+ return _mv88e6xxx_atu_remove(ps, vlan.fid, port, false);
}
int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
@@ -2026,17 +2018,17 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
mutex_lock(&ps->smi_mutex);
- err = _mv88e6xxx_port_pvid_get(ds, port, &pvid);
+ err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);
if (err)
goto unlock;
for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
- err = _mv88e6xxx_port_vlan_del(ds, port, vid);
+ err = _mv88e6xxx_port_vlan_del(ps, port, vid);
if (err)
goto unlock;
if (vid == pvid) {
- err = _mv88e6xxx_port_pvid_set(ds, port, 0);
+ err = _mv88e6xxx_port_pvid_set(ps, port, 0);
if (err)
goto unlock;
}
@@ -2049,14 +2041,14 @@ unlock:
}
EXPORT_SYMBOL_GPL(mv88e6xxx_port_vlan_del);
-static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds,
+static int _mv88e6xxx_atu_mac_write(struct mv88e6xxx_priv_state *ps,
const unsigned char *addr)
{
int i, ret;
for (i = 0; i < 3; i++) {
ret = _mv88e6xxx_reg_write(
- ds, REG_GLOBAL, GLOBAL_ATU_MAC_01 + i,
+ ps, REG_GLOBAL, GLOBAL_ATU_MAC_01 + i,
(addr[i * 2] << 8) | addr[i * 2 + 1]);
if (ret < 0)
return ret;
@@ -2065,12 +2057,13 @@ static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds,
return 0;
}
-static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, unsigned char *addr)
+static int _mv88e6xxx_atu_mac_read(struct mv88e6xxx_priv_state *ps,
+ unsigned char *addr)
{
int i, ret;
for (i = 0; i < 3; i++) {
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL,
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL,
GLOBAL_ATU_MAC_01 + i);
if (ret < 0)
return ret;
@@ -2081,27 +2074,27 @@ static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, unsigned char *addr)
return 0;
}
-static int _mv88e6xxx_atu_load(struct dsa_switch *ds,
+static int _mv88e6xxx_atu_load(struct mv88e6xxx_priv_state *ps,
struct mv88e6xxx_atu_entry *entry)
{
int ret;
- ret = _mv88e6xxx_atu_wait(ds);
+ ret = _mv88e6xxx_atu_wait(ps);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_atu_mac_write(ds, entry->mac);
+ ret = _mv88e6xxx_atu_mac_write(ps, entry->mac);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_atu_data_write(ds, entry);
+ ret = _mv88e6xxx_atu_data_write(ps, entry);
if (ret < 0)
return ret;
- return _mv88e6xxx_atu_cmd(ds, entry->fid, GLOBAL_ATU_OP_LOAD_DB);
+ return _mv88e6xxx_atu_cmd(ps, entry->fid, GLOBAL_ATU_OP_LOAD_DB);
}
-static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port,
+static int _mv88e6xxx_port_fdb_load(struct mv88e6xxx_priv_state *ps, int port,
const unsigned char *addr, u16 vid,
u8 state)
{
@@ -2111,9 +2104,9 @@ static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port,
/* Null VLAN ID corresponds to the port private database */
if (vid == 0)
- err = _mv88e6xxx_port_fid_get(ds, port, &vlan.fid);
+ err = _mv88e6xxx_port_fid_get(ps, port, &vlan.fid);
else
- err = _mv88e6xxx_vtu_get(ds, vid, &vlan, false);
+ err = _mv88e6xxx_vtu_get(ps, vid, &vlan, false);
if (err)
return err;
@@ -2125,7 +2118,7 @@ static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port,
entry.portv_trunkid = BIT(port);
}
- return _mv88e6xxx_atu_load(ds, &entry);
+ return _mv88e6xxx_atu_load(ps, &entry);
}
int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
@@ -2149,7 +2142,7 @@ void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
mutex_lock(&ps->smi_mutex);
- if (_mv88e6xxx_port_fdb_load(ds, port, fdb->addr, fdb->vid, state))
+ if (_mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid, state))
netdev_err(ds->ports[port], "failed to load MAC address\n");
mutex_unlock(&ps->smi_mutex);
}
@@ -2162,7 +2155,7 @@ int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
int ret;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_port_fdb_load(ds, port, fdb->addr, fdb->vid,
+ ret = _mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid,
GLOBAL_ATU_DATA_STATE_UNUSED);
mutex_unlock(&ps->smi_mutex);
@@ -2170,7 +2163,7 @@ int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
}
EXPORT_SYMBOL_GPL(mv88e6xxx_port_fdb_del);
-static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid,
+static int _mv88e6xxx_atu_getnext(struct mv88e6xxx_priv_state *ps, u16 fid,
struct mv88e6xxx_atu_entry *entry)
{
struct mv88e6xxx_atu_entry next = { 0 };
@@ -2178,19 +2171,19 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid,
next.fid = fid;
- ret = _mv88e6xxx_atu_wait(ds);
+ ret = _mv88e6xxx_atu_wait(ps);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB);
+ ret = _mv88e6xxx_atu_cmd(ps, fid, GLOBAL_ATU_OP_GET_NEXT_DB);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_atu_mac_read(ds, next.mac);
+ ret = _mv88e6xxx_atu_mac_read(ps, next.mac);
if (ret < 0)
return ret;
- ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA);
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_ATU_DATA);
if (ret < 0)
return ret;
@@ -2215,8 +2208,8 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid,
return 0;
}
-static int _mv88e6xxx_port_fdb_dump_one(struct dsa_switch *ds, u16 fid, u16 vid,
- int port,
+static int _mv88e6xxx_port_fdb_dump_one(struct mv88e6xxx_priv_state *ps,
+ u16 fid, u16 vid, int port,
struct switchdev_obj_port_fdb *fdb,
int (*cb)(struct switchdev_obj *obj))
{
@@ -2225,12 +2218,12 @@ static int _mv88e6xxx_port_fdb_dump_one(struct dsa_switch *ds, u16 fid, u16 vid,
};
int err;
- err = _mv88e6xxx_atu_mac_write(ds, addr.mac);
+ err = _mv88e6xxx_atu_mac_write(ps, addr.mac);
if (err)
return err;
do {
- err = _mv88e6xxx_atu_getnext(ds, fid, &addr);
+ err = _mv88e6xxx_atu_getnext(ps, fid, &addr);
if (err)
break;
@@ -2270,28 +2263,28 @@ int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
mutex_lock(&ps->smi_mutex);
/* Dump port's default Filtering Information Database (VLAN ID 0) */
- err = _mv88e6xxx_port_fid_get(ds, port, &fid);
+ err = _mv88e6xxx_port_fid_get(ps, port, &fid);
if (err)
goto unlock;
- err = _mv88e6xxx_port_fdb_dump_one(ds, fid, 0, port, fdb, cb);
+ err = _mv88e6xxx_port_fdb_dump_one(ps, fid, 0, port, fdb, cb);
if (err)
goto unlock;
/* Dump VLANs' Filtering Information Databases */
- err = _mv88e6xxx_vtu_vid_write(ds, vlan.vid);
+ err = _mv88e6xxx_vtu_vid_write(ps, vlan.vid);
if (err)
goto unlock;
do {
- err = _mv88e6xxx_vtu_getnext(ds, &vlan);
+ err = _mv88e6xxx_vtu_getnext(ps, &vlan);
if (err)
break;
if (!vlan.valid)
break;
- err = _mv88e6xxx_port_fdb_dump_one(ds, vlan.fid, vlan.vid, port,
+ err = _mv88e6xxx_port_fdb_dump_one(ps, vlan.fid, vlan.vid, port,
fdb, cb);
if (err)
break;
@@ -2319,13 +2312,13 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
break;
if (i < ps->num_ports)
- err = _mv88e6xxx_port_fid_get(ds, i, &fid);
+ err = _mv88e6xxx_port_fid_get(ps, i, &fid);
else
- err = _mv88e6xxx_fid_new(ds, &fid);
+ err = _mv88e6xxx_fid_new(ps, &fid);
if (err)
goto unlock;
- err = _mv88e6xxx_port_fid_set(ds, port, fid);
+ err = _mv88e6xxx_port_fid_set(ps, port, fid);
if (err)
goto unlock;
@@ -2334,7 +2327,7 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
for (i = 0; i < ps->num_ports; ++i) {
if (ps->ports[i].bridge_dev == bridge) {
- err = _mv88e6xxx_port_based_vlan_map(ds, i);
+ err = _mv88e6xxx_port_based_vlan_map(ps, i);
if (err)
break;
}
@@ -2357,8 +2350,8 @@ void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
mutex_lock(&ps->smi_mutex);
/* Give the port a fresh Filtering Information Database */
- if (_mv88e6xxx_fid_new(ds, &fid) ||
- _mv88e6xxx_port_fid_set(ds, port, fid))
+ if (_mv88e6xxx_fid_new(ps, &fid) ||
+ _mv88e6xxx_port_fid_set(ps, port, fid))
netdev_warn(ds->ports[port], "failed to assign a new FID\n");
/* Unassign the bridge and remap each port's VLANTable */
@@ -2366,7 +2359,7 @@ void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
for (i = 0; i < ps->num_ports; ++i)
if (i == port || ps->ports[i].bridge_dev == bridge)
- if (_mv88e6xxx_port_based_vlan_map(ds, i))
+ if (_mv88e6xxx_port_based_vlan_map(ps, i))
netdev_warn(ds->ports[i], "failed to remap\n");
mutex_unlock(&ps->smi_mutex);
@@ -2386,57 +2379,58 @@ static void mv88e6xxx_bridge_work(struct work_struct *work)
for (port = 0; port < ps->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",
+ _mv88e6xxx_port_state(ps, port, ps->ports[port].state))
+ netdev_warn(ds->ports[port],
+ "failed to update state to %s\n",
mv88e6xxx_port_state_names[ps->ports[port].state]);
mutex_unlock(&ps->smi_mutex);
}
-static int _mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
- int reg, int val)
+static int _mv88e6xxx_phy_page_write(struct mv88e6xxx_priv_state *ps,
+ int port, int page, int reg, int val)
{
int ret;
- ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page);
+ ret = _mv88e6xxx_phy_write_indirect(ps, port, 0x16, page);
if (ret < 0)
goto restore_page_0;
- ret = _mv88e6xxx_phy_write_indirect(ds, port, reg, val);
+ ret = _mv88e6xxx_phy_write_indirect(ps, port, reg, val);
restore_page_0:
- _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0);
+ _mv88e6xxx_phy_write_indirect(ps, port, 0x16, 0x0);
return ret;
}
-static int _mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page,
- int reg)
+static int _mv88e6xxx_phy_page_read(struct mv88e6xxx_priv_state *ps,
+ int port, int page, int reg)
{
int ret;
- ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page);
+ ret = _mv88e6xxx_phy_write_indirect(ps, port, 0x16, page);
if (ret < 0)
goto restore_page_0;
- ret = _mv88e6xxx_phy_read_indirect(ds, port, reg);
+ ret = _mv88e6xxx_phy_read_indirect(ps, port, reg);
restore_page_0:
- _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0);
+ _mv88e6xxx_phy_write_indirect(ps, port, 0x16, 0x0);
return ret;
}
-static int mv88e6xxx_power_on_serdes(struct dsa_switch *ds)
+static int mv88e6xxx_power_on_serdes(struct mv88e6xxx_priv_state *ps)
{
int ret;
- ret = _mv88e6xxx_phy_page_read(ds, REG_FIBER_SERDES, PAGE_FIBER_SERDES,
+ ret = _mv88e6xxx_phy_page_read(ps, REG_FIBER_SERDES, PAGE_FIBER_SERDES,
MII_BMCR);
if (ret < 0)
return ret;
if (ret & BMCR_PDOWN) {
ret &= ~BMCR_PDOWN;
- ret = _mv88e6xxx_phy_page_write(ds, REG_FIBER_SERDES,
+ ret = _mv88e6xxx_phy_page_write(ps, REG_FIBER_SERDES,
PAGE_FIBER_SERDES, MII_BMCR,
ret);
}
@@ -2452,24 +2446,24 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
mutex_lock(&ps->smi_mutex);
- if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
- mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
- mv88e6xxx_6185_family(ds) || mv88e6xxx_6095_family(ds) ||
- mv88e6xxx_6065_family(ds) || mv88e6xxx_6320_family(ds)) {
+ if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
+ mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
+ mv88e6xxx_6185_family(ps) || mv88e6xxx_6095_family(ps) ||
+ mv88e6xxx_6065_family(ps) || mv88e6xxx_6320_family(ps)) {
/* MAC Forcing register: don't force link, speed,
* duplex or flow control state to any particular
* values on physical ports, but force the CPU port
* and all DSA ports to their maximum bandwidth and
* full duplex.
*/
- reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL);
+ reg = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_PCS_CTRL);
if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
reg &= ~PORT_PCS_CTRL_UNFORCED;
reg |= PORT_PCS_CTRL_FORCE_LINK |
PORT_PCS_CTRL_LINK_UP |
PORT_PCS_CTRL_DUPLEX_FULL |
PORT_PCS_CTRL_FORCE_DUPLEX;
- if (mv88e6xxx_6065_family(ds))
+ if (mv88e6xxx_6065_family(ps))
reg |= PORT_PCS_CTRL_100;
else
reg |= PORT_PCS_CTRL_1000;
@@ -2477,7 +2471,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
reg |= PORT_PCS_CTRL_UNFORCED;
}
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_PCS_CTRL, reg);
if (ret)
goto abort;
@@ -2498,19 +2492,19 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
* forwarding of unknown unicasts and multicasts.
*/
reg = 0;
- if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
- mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
- mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds) ||
- mv88e6xxx_6185_family(ds) || mv88e6xxx_6320_family(ds))
+ if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
+ mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
+ mv88e6xxx_6095_family(ps) || mv88e6xxx_6065_family(ps) ||
+ mv88e6xxx_6185_family(ps) || mv88e6xxx_6320_family(ps))
reg = PORT_CONTROL_IGMP_MLD_SNOOP |
PORT_CONTROL_USE_TAG | PORT_CONTROL_USE_IP |
PORT_CONTROL_STATE_FORWARDING;
if (dsa_is_cpu_port(ds, port)) {
- if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds))
+ if (mv88e6xxx_6095_family(ps) || mv88e6xxx_6185_family(ps))
reg |= PORT_CONTROL_DSA_TAG;
- if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
- mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
- mv88e6xxx_6320_family(ds)) {
+ if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
+ mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
+ mv88e6xxx_6320_family(ps)) {
if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA)
reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA;
else
@@ -2519,20 +2513,20 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
PORT_CONTROL_FORWARD_UNKNOWN_MC;
}
- if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
- mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
- mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds) ||
- mv88e6xxx_6185_family(ds) || mv88e6xxx_6320_family(ds)) {
+ if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
+ mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
+ mv88e6xxx_6095_family(ps) || mv88e6xxx_6065_family(ps) ||
+ mv88e6xxx_6185_family(ps) || mv88e6xxx_6320_family(ps)) {
if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA)
reg |= PORT_CONTROL_EGRESS_ADD_TAG;
}
}
if (dsa_is_dsa_port(ds, port)) {
- if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds))
+ if (mv88e6xxx_6095_family(ps) || mv88e6xxx_6185_family(ps))
reg |= PORT_CONTROL_DSA_TAG;
- if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
- mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
- mv88e6xxx_6320_family(ds)) {
+ if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
+ mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
+ mv88e6xxx_6320_family(ps)) {
reg |= PORT_CONTROL_FRAME_MODE_DSA;
}
@@ -2541,7 +2535,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
PORT_CONTROL_FORWARD_UNKNOWN_MC;
}
if (reg) {
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_CONTROL, reg);
if (ret)
goto abort;
@@ -2550,15 +2544,15 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
/* If this port is connected to a SerDes, make sure the SerDes is not
* powered down.
*/
- if (mv88e6xxx_6352_family(ds)) {
- ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_STATUS);
+ if (mv88e6xxx_6352_family(ps)) {
+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_STATUS);
if (ret < 0)
goto abort;
ret &= PORT_STATUS_CMODE_MASK;
if ((ret == PORT_STATUS_CMODE_100BASE_X) ||
(ret == PORT_STATUS_CMODE_1000BASE_X) ||
(ret == PORT_STATUS_CMODE_SGMII)) {
- ret = mv88e6xxx_power_on_serdes(ds);
+ ret = mv88e6xxx_power_on_serdes(ps);
if (ret < 0)
goto abort;
}
@@ -2571,17 +2565,17 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
* copy of all transmitted/received frames on this port to the CPU.
*/
reg = 0;
- if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
- mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
- mv88e6xxx_6095_family(ds) || mv88e6xxx_6320_family(ds) ||
- mv88e6xxx_6185_family(ds))
+ if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
+ mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
+ mv88e6xxx_6095_family(ps) || mv88e6xxx_6320_family(ps) ||
+ mv88e6xxx_6185_family(ps))
reg = PORT_CONTROL_2_MAP_DA;
- if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
- mv88e6xxx_6165_family(ds) || mv88e6xxx_6320_family(ds))
+ if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
+ mv88e6xxx_6165_family(ps) || mv88e6xxx_6320_family(ps))
reg |= PORT_CONTROL_2_JUMBO_10240;
- if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds)) {
+ if (mv88e6xxx_6095_family(ps) || mv88e6xxx_6185_family(ps)) {
/* Set the upstream port this port should use */
reg |= dsa_upstream_port(ds);
/* enable forwarding of unknown multicast addresses to
@@ -2594,7 +2588,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
reg |= PORT_CONTROL_2_8021Q_DISABLED;
if (reg) {
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_CONTROL_2, reg);
if (ret)
goto abort;
@@ -2610,24 +2604,24 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
reg = PORT_ASSOC_VECTOR_LOCKED_PORT;
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_ASSOC_VECTOR, reg);
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_ASSOC_VECTOR, reg);
if (ret)
goto abort;
/* Egress rate control 2: disable egress rate control. */
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_RATE_CONTROL_2,
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_RATE_CONTROL_2,
0x0000);
if (ret)
goto abort;
- if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
- mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
- mv88e6xxx_6320_family(ds)) {
+ if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
+ mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
+ mv88e6xxx_6320_family(ps)) {
/* Do not limit the period of time that this port can
* be paused for by the remote end or the period of
* time that this port can pause the remote end.
*/
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_PAUSE_CTRL, 0x0000);
if (ret)
goto abort;
@@ -2636,12 +2630,12 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
* address database entries that this port is allowed
* to use.
*/
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_ATU_CONTROL, 0x0000);
/* Priority Override: disable DA, SA and VTU priority
* override.
*/
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_PRI_OVERRIDE, 0x0000);
if (ret)
goto abort;
@@ -2649,14 +2643,14 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
/* Port Ethertype: use the Ethertype DSA Ethertype
* value.
*/
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_ETH_TYPE, ETH_P_EDSA);
if (ret)
goto abort;
/* Tag Remap: use an identity 802.1p prio -> switch
* prio mapping.
*/
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_TAG_REGMAP_0123, 0x3210);
if (ret)
goto abort;
@@ -2664,18 +2658,18 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
/* Tag Remap 2: use an identity 802.1p prio -> switch
* prio mapping.
*/
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_TAG_REGMAP_4567, 0x7654);
if (ret)
goto abort;
}
- if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
- mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
- mv88e6xxx_6185_family(ds) || mv88e6xxx_6095_family(ds) ||
- mv88e6xxx_6320_family(ds)) {
+ if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
+ mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
+ mv88e6xxx_6185_family(ps) || mv88e6xxx_6095_family(ps) ||
+ mv88e6xxx_6320_family(ps)) {
/* Rate Control: disable ingress rate limiting. */
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_RATE_CONTROL, 0x0001);
if (ret)
goto abort;
@@ -2684,7 +2678,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
/* Port Control 1: disable trunking, disable sending
* learning messages to this port.
*/
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_1, 0x0000);
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_1, 0x0000);
if (ret)
goto abort;
@@ -2692,18 +2686,18 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
* database, and allow bidirectional communication between the
* CPU and DSA port(s), and the other ports.
*/
- ret = _mv88e6xxx_port_fid_set(ds, port, port + 1);
+ ret = _mv88e6xxx_port_fid_set(ps, port, port + 1);
if (ret)
goto abort;
- ret = _mv88e6xxx_port_based_vlan_map(ds, port);
+ ret = _mv88e6xxx_port_based_vlan_map(ps, port);
if (ret)
goto abort;
/* Default VLAN ID and priority: don't set a default VLAN
* ID, and set the default packet priority to zero.
*/
- ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_DEFAULT_VLAN,
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_DEFAULT_VLAN,
0x0000);
abort:
mutex_unlock(&ps->smi_mutex);
@@ -2725,11 +2719,8 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
}
EXPORT_SYMBOL_GPL(mv88e6xxx_setup_ports);
-int mv88e6xxx_setup_common(struct dsa_switch *ds)
+int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
- ps->ds = ds;
mutex_init(&ps->smi_mutex);
ps->id = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, REG_PORT(0),
@@ -2751,46 +2742,46 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
* enable address learn messages to be sent to all message
* ports.
*/
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL,
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL,
0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL);
if (err)
return err;
/* Configure the IP ToS mapping registers. */
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000);
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000);
if (err)
return err;
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000);
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000);
if (err)
return err;
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555);
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555);
if (err)
return err;
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555);
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555);
if (err)
return err;
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa);
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa);
if (err)
return err;
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa);
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa);
if (err)
return err;
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff);
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff);
if (err)
return err;
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff);
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff);
if (err)
return err;
/* Configure the IEEE 802.1p priority mapping register. */
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41);
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41);
if (err)
return err;
/* Send all frames with destination addresses matching
* 01:80:c2:00:00:0x to the CPU port.
*/
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff);
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff);
if (err)
return err;
@@ -2799,7 +2790,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
* highest, and send all special multicast frames to the CPU
* port at the highest priority.
*/
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SWITCH_MGMT,
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SWITCH_MGMT,
0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 |
GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI);
if (err)
@@ -2814,17 +2805,17 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
nexthop = ds->pd->rtable[i] & 0x1f;
err = mv88e6xxx_reg_write(
- ds, REG_GLOBAL2,
+ ps, REG_GLOBAL2,
GLOBAL2_DEVICE_MAPPING,
GLOBAL2_DEVICE_MAPPING_UPDATE |
(i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) | nexthop);
- if (err)
- return err;
+ if (err)
+ return err;
}
/* Clear all trunk masks. */
for (i = 0; i < 8; i++) {
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_TRUNK_MASK,
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_TRUNK_MASK,
0x8000 |
(i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |
((1 << ps->num_ports) - 1));
@@ -2835,7 +2826,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
/* Clear all trunk mappings. */
for (i = 0; i < 16; i++) {
err = mv88e6xxx_reg_write(
- ds, REG_GLOBAL2,
+ ps, REG_GLOBAL2,
GLOBAL2_TRUNK_MAPPING,
GLOBAL2_TRUNK_MAPPING_UPDATE |
(i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT));
@@ -2843,13 +2834,13 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
return err;
}
- if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
- mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
- mv88e6xxx_6320_family(ds)) {
+ if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
+ mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
+ mv88e6xxx_6320_family(ps)) {
/* Send all frames with destination addresses matching
* 01:80:c2:00:00:2x to the CPU port.
*/
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL2,
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL2,
GLOBAL2_MGMT_EN_2X, 0xffff);
if (err)
return err;
@@ -2857,14 +2848,14 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
/* Initialise cross-chip port VLAN table to reset
* defaults.
*/
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL2,
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL2,
GLOBAL2_PVT_ADDR, 0x9000);
if (err)
return err;
/* Clear the priority override table. */
for (i = 0; i < 16; i++) {
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL2,
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL2,
GLOBAL2_PRIO_OVERRIDE,
0x8000 | (i << 8));
if (err)
@@ -2872,16 +2863,16 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
}
}
- if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
- mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
- mv88e6xxx_6185_family(ds) || mv88e6xxx_6095_family(ds) ||
- mv88e6xxx_6320_family(ds)) {
+ if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
+ mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
+ mv88e6xxx_6185_family(ps) || mv88e6xxx_6095_family(ps) ||
+ mv88e6xxx_6320_family(ps)) {
/* Disable ingress rate limiting by resetting all
* ingress rate limit registers to their initial
* state.
*/
for (i = 0; i < ps->num_ports; i++) {
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL2,
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL2,
GLOBAL2_INGRESS_OP,
0x9000 | (i << 8));
if (err)
@@ -2890,24 +2881,24 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
}
/* Clear the statistics counters for all ports */
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_STATS_OP,
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_STATS_OP,
GLOBAL_STATS_OP_FLUSH_ALL);
if (err)
return err;
/* Wait for the flush to complete. */
mutex_lock(&ps->smi_mutex);
- err = _mv88e6xxx_stats_wait(ds);
+ err = _mv88e6xxx_stats_wait(ps);
if (err < 0)
goto unlock;
/* Clear all ATU entries */
- err = _mv88e6xxx_atu_flush(ds, 0, true);
+ err = _mv88e6xxx_atu_flush(ps, 0, true);
if (err < 0)
goto unlock;
/* Clear all the VTU and STU entries */
- err = _mv88e6xxx_vtu_stu_flush(ds);
+ err = _mv88e6xxx_vtu_stu_flush(ps);
unlock:
mutex_unlock(&ps->smi_mutex);
@@ -2915,9 +2906,8 @@ unlock:
}
EXPORT_SYMBOL_GPL(mv88e6xxx_setup_global);
-int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
+int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
struct gpio_desc *gpiod = ps->reset;
unsigned long timeout;
@@ -2926,11 +2916,11 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
/* Set all ports to the disabled state. */
for (i = 0; i < ps->num_ports; i++) {
- ret = mv88e6xxx_reg_read(ds, REG_PORT(i), PORT_CONTROL);
+ ret = mv88e6xxx_reg_read(ps, REG_PORT(i), PORT_CONTROL);
if (ret < 0)
return ret;
- err = mv88e6xxx_reg_write(ds, REG_PORT(i), PORT_CONTROL,
+ err = mv88e6xxx_reg_write(ps, REG_PORT(i), PORT_CONTROL,
ret & 0xfffc);
if (err)
return err;
@@ -2952,16 +2942,16 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
* through global registers 0x18 and 0x19.
*/
if (ppu_active)
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x04, 0xc000);
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc000);
else
- err = mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x04, 0xc400);
+ err = mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc400);
if (err)
return err;
/* Wait up to one second for reset to complete. */
timeout = jiffies + 1 * HZ;
while (time_before(jiffies, timeout)) {
- ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x00);
+ ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, 0x00);
if (ret < 0)
return ret;
@@ -2982,7 +2972,7 @@ int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg)
int ret;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_phy_page_read(ds, port, page, reg);
+ ret = _mv88e6xxx_phy_page_read(ps, port, page, reg);
mutex_unlock(&ps->smi_mutex);
return ret;
@@ -2996,17 +2986,16 @@ int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
int ret;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_phy_page_write(ds, port, page, reg, val);
+ ret = _mv88e6xxx_phy_page_write(ps, port, page, reg, val);
mutex_unlock(&ps->smi_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(mv88e6xxx_phy_page_write);
-static int mv88e6xxx_port_to_phy_addr(struct dsa_switch *ds, int port)
+static int mv88e6xxx_port_to_phy_addr(struct mv88e6xxx_priv_state *ps,
+ int port)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
if (port >= 0 && port < ps->num_ports)
return port;
return -EINVAL;
@@ -3016,14 +3005,14 @@ int
mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int addr = mv88e6xxx_port_to_phy_addr(ds, port);
+ int addr = mv88e6xxx_port_to_phy_addr(ps, port);
int ret;
if (addr < 0)
- return addr;
+ return 0xffff;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_phy_read(ds, addr, regnum);
+ ret = _mv88e6xxx_phy_read(ps, addr, regnum);
mutex_unlock(&ps->smi_mutex);
return ret;
}
@@ -3033,14 +3022,14 @@ int
mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int addr = mv88e6xxx_port_to_phy_addr(ds, port);
+ int addr = mv88e6xxx_port_to_phy_addr(ps, port);
int ret;
if (addr < 0)
- return addr;
+ return 0xffff;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_phy_write(ds, addr, regnum, val);
+ ret = _mv88e6xxx_phy_write(ps, addr, regnum, val);
mutex_unlock(&ps->smi_mutex);
return ret;
}
@@ -3050,14 +3039,14 @@ int
mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int addr = mv88e6xxx_port_to_phy_addr(ds, port);
+ int addr = mv88e6xxx_port_to_phy_addr(ps, port);
int ret;
if (addr < 0)
- return addr;
+ return 0xffff;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_phy_read_indirect(ds, addr, regnum);
+ ret = _mv88e6xxx_phy_read_indirect(ps, addr, regnum);
mutex_unlock(&ps->smi_mutex);
return ret;
}
@@ -3068,14 +3057,14 @@ mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
u16 val)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int addr = mv88e6xxx_port_to_phy_addr(ds, port);
+ int addr = mv88e6xxx_port_to_phy_addr(ps, port);
int ret;
if (addr < 0)
return addr;
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_phy_write_indirect(ds, addr, regnum, val);
+ ret = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val);
mutex_unlock(&ps->smi_mutex);
return ret;
}
@@ -3093,44 +3082,45 @@ static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp)
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x6);
+ ret = _mv88e6xxx_phy_write(ps, 0x0, 0x16, 0x6);
if (ret < 0)
goto error;
/* Enable temperature sensor */
- ret = _mv88e6xxx_phy_read(ds, 0x0, 0x1a);
+ ret = _mv88e6xxx_phy_read(ps, 0x0, 0x1a);
if (ret < 0)
goto error;
- ret = _mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret | (1 << 5));
+ ret = _mv88e6xxx_phy_write(ps, 0x0, 0x1a, ret | (1 << 5));
if (ret < 0)
goto error;
/* Wait for temperature to stabilize */
usleep_range(10000, 12000);
- val = _mv88e6xxx_phy_read(ds, 0x0, 0x1a);
+ val = _mv88e6xxx_phy_read(ps, 0x0, 0x1a);
if (val < 0) {
ret = val;
goto error;
}
/* Disable temperature sensor */
- ret = _mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret & ~(1 << 5));
+ ret = _mv88e6xxx_phy_write(ps, 0x0, 0x1a, ret & ~(1 << 5));
if (ret < 0)
goto error;
*temp = ((val & 0x1f) - 5) * 5;
error:
- _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x0);
+ _mv88e6xxx_phy_write(ps, 0x0, 0x16, 0x0);
mutex_unlock(&ps->smi_mutex);
return ret;
}
static int mv88e63xx_get_temp(struct dsa_switch *ds, int *temp)
{
- int phy = mv88e6xxx_6320_family(ds) ? 3 : 0;
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
int ret;
*temp = 0;
@@ -3146,7 +3136,9 @@ static int mv88e63xx_get_temp(struct dsa_switch *ds, int *temp)
int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
{
- if (mv88e6xxx_6320_family(ds) || mv88e6xxx_6352_family(ds))
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+ if (mv88e6xxx_6320_family(ps) || mv88e6xxx_6352_family(ps))
return mv88e63xx_get_temp(ds, temp);
return mv88e61xx_get_temp(ds, temp);
@@ -3155,10 +3147,11 @@ EXPORT_SYMBOL_GPL(mv88e6xxx_get_temp);
int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)
{
- int phy = mv88e6xxx_6320_family(ds) ? 3 : 0;
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
int ret;
- if (!mv88e6xxx_6320_family(ds) && !mv88e6xxx_6352_family(ds))
+ if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps))
return -EOPNOTSUPP;
*temp = 0;
@@ -3175,10 +3168,11 @@ EXPORT_SYMBOL_GPL(mv88e6xxx_get_temp_limit);
int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)
{
- int phy = mv88e6xxx_6320_family(ds) ? 3 : 0;
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
int ret;
- if (!mv88e6xxx_6320_family(ds) && !mv88e6xxx_6352_family(ds))
+ if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps))
return -EOPNOTSUPP;
ret = mv88e6xxx_phy_page_read(ds, phy, 6, 26);
@@ -3192,10 +3186,11 @@ EXPORT_SYMBOL_GPL(mv88e6xxx_set_temp_limit);
int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
{
- int phy = mv88e6xxx_6320_family(ds) ? 3 : 0;
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
int ret;
- if (!mv88e6xxx_6320_family(ds) && !mv88e6xxx_6352_family(ds))
+ if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps))
return -EOPNOTSUPP;
*alarm = false;
@@ -3286,6 +3281,7 @@ int mv88e6xxx_probe(struct mdio_device *mdiodev, struct dsa_switch_driver *ops,
ps = (struct mv88e6xxx_priv_state *)(ds + 1);
ds->priv = ps;
+ ps->dev = dev;
ps->ds = ds;
ps->bus = mdiodev->bus;
ps->sw_addr = mdiodev->addr;
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 6d1b6207144d..3f7a432c9050 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -401,6 +401,9 @@ struct mv88e6xxx_priv_state {
/* The dsa_switch this private structure is related to */
struct dsa_switch *ds;
+ /* The device this structure is associated to */
+ struct device *dev;
+
/* When using multi-chip addressing, this mutex protects
* access to the indirect access registers. (In single-chip
* mode, this mutex is effectively useless.)
@@ -468,17 +471,18 @@ struct mv88e6xxx_hw_stat {
enum stat_type type;
};
-int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);
+int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, 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);
int mv88e6xxx_setup_ports(struct dsa_switch *ds);
-int mv88e6xxx_setup_common(struct dsa_switch *ds);
+int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps);
int mv88e6xxx_setup_global(struct dsa_switch *ds);
-int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg);
-int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val);
+int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg);
+int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
+ int reg, u16 val);
int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr);
int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr);
int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum);
@@ -486,7 +490,7 @@ 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 dsa_switch *ds);
+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);
--
2.7.0
^ permalink raw reply related
* [PATCH net-next 8/8] dsa: mv88e6131: Don't special case a single device
From: Andrew Lunn @ 2016-04-13 23:59 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460591998-20598-1-git-send-email-andrew@lunn.ch>
When multiple switches are interconnected in a tree, a routing table
is used for directing packets out the correct port towards a remote
destination. This works equally well for a single switch, since the
routing table is empty. So don't special case for a single switch.
This makes the mv88e6131 behave like the other drivers.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6131.c | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 969f67c77835..c7ee11f73be6 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -74,18 +74,12 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
if (ret)
return ret;
- /* Disable cascade port functionality unless this device
- * is used in a cascade configuration, and set the switch's
- * DSA device number.
+ /* Set the switch's DSA device number and enable the use of
+ * the routing table.
*/
- if (ds->dst->pd->nr_chips > 1)
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
- GLOBAL_CONTROL_2_MULTIPLE_CASCADE |
- (ds->index & 0x1f));
- else
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
- GLOBAL_CONTROL_2_NO_CASCADE |
- (ds->index & 0x1f));
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
+ GLOBAL_CONTROL_2_MULTIPLE_CASCADE |
+ (ds->index & 0x1f));
if (ret)
return ret;
--
2.7.0
^ permalink raw reply related
* [PATCH net-next 5/8] dsa: mv88e6xxx: Kill the REG_READ and REG_WRITE macros
From: Andrew Lunn @ 2016-04-13 23:59 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460591998-20598-1-git-send-email-andrew@lunn.ch>
These macros hide a ds variable and a return statement on error, which
can lead to locking issues. Kill them off.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6123.c | 13 ++-
drivers/net/dsa/mv88e6131.c | 41 ++++----
drivers/net/dsa/mv88e6171.c | 16 +--
drivers/net/dsa/mv88e6352.c | 15 +--
drivers/net/dsa/mv88e6xxx.c | 232 +++++++++++++++++++++++++++++++-------------
drivers/net/dsa/mv88e6xxx.h | 19 ----
6 files changed, 217 insertions(+), 119 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 7ef0e3c7b703..450dad5af568 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -54,7 +54,9 @@ static int mv88e6123_setup_global(struct dsa_switch *ds)
* external PHYs to poll), don't discard packets with
* excessive collisions, and mask all interrupt sources.
*/
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, 0x0000);
+ ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL, 0x0000);
+ if (ret)
+ return ret;
/* Configure the upstream port, and configure the upstream
* port as the port to which ingress and egress monitor frames
@@ -63,14 +65,15 @@ static int mv88e6123_setup_global(struct dsa_switch *ds)
reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
- REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ if (ret)
+ return ret;
/* Disable remote management for now, and set the switch's
* DSA device number.
*/
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, ds->index & 0x1f);
-
- return 0;
+ return mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL_2,
+ ds->index & 0x1f);
}
static int mv88e6123_setup(struct dsa_switch *ds)
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 25f35937787e..e1e2410a660c 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -51,11 +51,16 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
* to arbitrate between packet queues, set the maximum frame
* size to 1632, and mask all interrupt sources.
*/
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL,
- GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_MAX_FRAME_1632);
+ ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL,
+ GLOBAL_CONTROL_PPU_ENABLE |
+ GLOBAL_CONTROL_MAX_FRAME_1632);
+ if (ret)
+ return ret;
/* Set the VLAN ethertype to 0x8100. */
- REG_WRITE(REG_GLOBAL, GLOBAL_CORE_TAG_TYPE, 0x8100);
+ ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CORE_TAG_TYPE, 0x8100);
+ if (ret)
+ return ret;
/* Disable ARP mirroring, and configure the upstream port as
* the port to which ingress and egress monitor frames are to
@@ -64,31 +69,33 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
GLOBAL_MONITOR_CONTROL_ARP_DISABLED;
- REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ if (ret)
+ return ret;
/* Disable cascade port functionality unless this device
* is used in a cascade configuration, and set the switch's
* DSA device number.
*/
if (ds->dst->pd->nr_chips > 1)
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2,
- GLOBAL_CONTROL_2_MULTIPLE_CASCADE |
- (ds->index & 0x1f));
+ ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL_2,
+ GLOBAL_CONTROL_2_MULTIPLE_CASCADE |
+ (ds->index & 0x1f));
else
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2,
- GLOBAL_CONTROL_2_NO_CASCADE |
- (ds->index & 0x1f));
+ ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL_2,
+ GLOBAL_CONTROL_2_NO_CASCADE |
+ (ds->index & 0x1f));
+ if (ret)
+ return ret;
/* Force the priority of IGMP/MLD snoop frames and ARP frames
* to the highest setting.
*/
- REG_WRITE(REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE,
- GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP |
- 7 << GLOBAL2_PRIO_OVERRIDE_SNOOP_SHIFT |
- GLOBAL2_PRIO_OVERRIDE_FORCE_ARP |
- 7 << GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT);
-
- return 0;
+ return mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE,
+ GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP |
+ 7 << GLOBAL2_PRIO_OVERRIDE_SNOOP_SHIFT |
+ GLOBAL2_PRIO_OVERRIDE_FORCE_ARP |
+ 7 << GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT);
}
static int mv88e6131_setup(struct dsa_switch *ds)
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index abf2a9bbbec5..e3998be13515 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -48,8 +48,11 @@ static int mv88e6171_setup_global(struct dsa_switch *ds)
/* Discard packets with excessive collisions, mask all
* interrupt sources, enable PPU.
*/
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL,
- GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_DISCARD_EXCESS);
+ ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL,
+ GLOBAL_CONTROL_PPU_ENABLE |
+ GLOBAL_CONTROL_DISCARD_EXCESS);
+ if (ret)
+ return ret;
/* Configure the upstream port, and configure the upstream
* port as the port to which ingress and egress monitor frames
@@ -59,14 +62,15 @@ static int mv88e6171_setup_global(struct dsa_switch *ds)
upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT;
- REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ if (ret)
+ return ret;
/* Disable remote management for now, and set the switch's
* DSA device number.
*/
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, ds->index & 0x1f);
-
- return 0;
+ return mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL_2,
+ ds->index & 0x1f);
}
static int mv88e6171_setup(struct dsa_switch *ds)
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 22d42fb51991..baeb594b63cc 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -60,8 +60,11 @@ static int mv88e6352_setup_global(struct dsa_switch *ds)
/* Discard packets with excessive collisions,
* mask all interrupt sources, enable PPU (bit 14, undocumented).
*/
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL,
- GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_DISCARD_EXCESS);
+ ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL,
+ GLOBAL_CONTROL_PPU_ENABLE |
+ GLOBAL_CONTROL_DISCARD_EXCESS);
+ if (ret)
+ return ret;
/* Configure the upstream port, and configure the upstream
* port as the port to which ingress and egress monitor frames
@@ -70,14 +73,14 @@ static int mv88e6352_setup_global(struct dsa_switch *ds)
reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
- REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ if (ret)
+ return ret;
/* Disable remote management for now, and set the switch's
* DSA device number.
*/
- REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f);
-
- return 0;
+ return mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x1c, ds->index & 0x1f);
}
static int mv88e6352_setup(struct dsa_switch *ds)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index ef29a94da975..93110460e0c3 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -182,29 +182,47 @@ EXPORT_SYMBOL_GPL(mv88e6xxx_reg_write);
int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
{
- REG_WRITE(REG_GLOBAL, GLOBAL_MAC_01, (addr[0] << 8) | addr[1]);
- REG_WRITE(REG_GLOBAL, GLOBAL_MAC_23, (addr[2] << 8) | addr[3]);
- REG_WRITE(REG_GLOBAL, GLOBAL_MAC_45, (addr[4] << 8) | addr[5]);
+ int err;
- return 0;
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MAC_01,
+ (addr[0] << 8) | addr[1]);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MAC_23,
+ (addr[2] << 8) | addr[3]);
+ if (err)
+ return err;
+
+ return mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MAC_45,
+ (addr[4] << 8) | addr[5]);
}
EXPORT_SYMBOL_GPL(mv88e6xxx_set_addr_direct);
int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
{
+ int ret, err;
int i;
- int ret;
for (i = 0; i < 6; i++) {
int j;
/* Write the MAC address byte. */
- REG_WRITE(REG_GLOBAL2, GLOBAL2_SWITCH_MAC,
- GLOBAL2_SWITCH_MAC_BUSY | (i << 8) | addr[i]);
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SWITCH_MAC,
+ GLOBAL2_SWITCH_MAC_BUSY |
+ (i << 8) | addr[i]);
+ if (err)
+ return err;
/* Wait for the write to complete. */
for (j = 0; j < 16; j++) {
- ret = REG_READ(REG_GLOBAL2, GLOBAL2_SWITCH_MAC);
+ ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2,
+ GLOBAL2_SWITCH_MAC);
+ if (ret < 0)
+ return ret;
+
+ if (ret < 0)
+ return ret;
if ((ret & GLOBAL2_SWITCH_MAC_BUSY) == 0)
break;
}
@@ -237,13 +255,21 @@ static int mv88e6xxx_ppu_disable(struct dsa_switch *ds)
int ret;
unsigned long timeout;
- ret = REG_READ(REG_GLOBAL, GLOBAL_CONTROL);
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL,
- ret & ~GLOBAL_CONTROL_PPU_ENABLE);
+ ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_CONTROL);
+ if (ret < 0)
+ return ret;
+
+ ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL,
+ ret & ~GLOBAL_CONTROL_PPU_ENABLE);
+ if (ret)
+ return ret;
timeout = jiffies + 1 * HZ;
while (time_before(jiffies, timeout)) {
- ret = REG_READ(REG_GLOBAL, GLOBAL_STATUS);
+ ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATUS);
+ if (ret < 0)
+ return ret;
+
usleep_range(1000, 2000);
if ((ret & GLOBAL_STATUS_PPU_MASK) !=
GLOBAL_STATUS_PPU_POLLING)
@@ -255,15 +281,24 @@ static int mv88e6xxx_ppu_disable(struct dsa_switch *ds)
static int mv88e6xxx_ppu_enable(struct dsa_switch *ds)
{
- int ret;
+ int ret, err;
unsigned long timeout;
- ret = REG_READ(REG_GLOBAL, GLOBAL_CONTROL);
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, ret | GLOBAL_CONTROL_PPU_ENABLE);
+ ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_CONTROL);
+ if (ret < 0)
+ return ret;
+
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL,
+ ret | GLOBAL_CONTROL_PPU_ENABLE);
+ if (err)
+ return err;
timeout = jiffies + 1 * HZ;
while (time_before(jiffies, timeout)) {
- ret = REG_READ(REG_GLOBAL, GLOBAL_STATUS);
+ ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATUS);
+ if (ret < 0)
+ return ret;
+
usleep_range(1000, 2000);
if ((ret & GLOBAL_STATUS_PPU_MASK) ==
GLOBAL_STATUS_PPU_POLLING)
@@ -2697,7 +2732,8 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
ps->ds = ds;
mutex_init(&ps->smi_mutex);
- ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0;
+ ps->id = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, REG_PORT(0),
+ PORT_SWITCH_ID) & 0xfff0;
INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
@@ -2708,42 +2744,66 @@ EXPORT_SYMBOL_GPL(mv88e6xxx_setup_common);
int mv88e6xxx_setup_global(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
+ int err;
int i;
/* Set the default address aging time to 5 minutes, and
* enable address learn messages to be sent to all message
* ports.
*/
- REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL,
- 0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL);
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL,
+ 0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL);
+ if (err)
+ return err;
/* Configure the IP ToS mapping registers. */
- REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000);
- REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000);
- REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555);
- REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555);
- REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa);
- REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa);
- REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff);
- REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff);
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000);
+ if (err)
+ return err;
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000);
+ if (err)
+ return err;
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555);
+ if (err)
+ return err;
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555);
+ if (err)
+ return err;
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa);
+ if (err)
+ return err;
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa);
+ if (err)
+ return err;
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff);
+ if (err)
+ return err;
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff);
+ if (err)
+ return err;
/* Configure the IEEE 802.1p priority mapping register. */
- REG_WRITE(REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41);
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41);
+ if (err)
+ return err;
/* Send all frames with destination addresses matching
* 01:80:c2:00:00:0x to the CPU port.
*/
- REG_WRITE(REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff);
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff);
+ if (err)
+ return err;
/* Ignore removed tag data on doubly tagged packets, disable
* flow control messages, force flow control priority to the
* highest, and send all special multicast frames to the CPU
* port at the highest priority.
*/
- REG_WRITE(REG_GLOBAL2, GLOBAL2_SWITCH_MGMT,
- 0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 |
- GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI);
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SWITCH_MGMT,
+ 0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 |
+ GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI);
+ if (err)
+ return err;
/* Program the DSA routing table. */
for (i = 0; i < 32; i++) {
@@ -2753,23 +2813,35 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
i != ds->index && i < ds->dst->pd->nr_chips)
nexthop = ds->pd->rtable[i] & 0x1f;
- REG_WRITE(REG_GLOBAL2, GLOBAL2_DEVICE_MAPPING,
- GLOBAL2_DEVICE_MAPPING_UPDATE |
- (i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) |
- nexthop);
+ err = mv88e6xxx_reg_write(
+ ds, REG_GLOBAL2,
+ GLOBAL2_DEVICE_MAPPING,
+ GLOBAL2_DEVICE_MAPPING_UPDATE |
+ (i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) | nexthop);
+ if (err)
+ return err;
}
/* Clear all trunk masks. */
- for (i = 0; i < 8; i++)
- REG_WRITE(REG_GLOBAL2, GLOBAL2_TRUNK_MASK,
- 0x8000 | (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |
- ((1 << ps->num_ports) - 1));
+ for (i = 0; i < 8; i++) {
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_TRUNK_MASK,
+ 0x8000 |
+ (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |
+ ((1 << ps->num_ports) - 1));
+ if (err)
+ return err;
+ }
/* Clear all trunk mappings. */
- for (i = 0; i < 16; i++)
- REG_WRITE(REG_GLOBAL2, GLOBAL2_TRUNK_MAPPING,
- GLOBAL2_TRUNK_MAPPING_UPDATE |
- (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT));
+ for (i = 0; i < 16; i++) {
+ err = mv88e6xxx_reg_write(
+ ds, REG_GLOBAL2,
+ GLOBAL2_TRUNK_MAPPING,
+ GLOBAL2_TRUNK_MAPPING_UPDATE |
+ (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT));
+ if (err)
+ return err;
+ }
if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
@@ -2777,17 +2849,27 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
/* Send all frames with destination addresses matching
* 01:80:c2:00:00:2x to the CPU port.
*/
- REG_WRITE(REG_GLOBAL2, GLOBAL2_MGMT_EN_2X, 0xffff);
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL2,
+ GLOBAL2_MGMT_EN_2X, 0xffff);
+ if (err)
+ return err;
/* Initialise cross-chip port VLAN table to reset
* defaults.
*/
- REG_WRITE(REG_GLOBAL2, GLOBAL2_PVT_ADDR, 0x9000);
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL2,
+ GLOBAL2_PVT_ADDR, 0x9000);
+ if (err)
+ return err;
/* Clear the priority override table. */
- for (i = 0; i < 16; i++)
- REG_WRITE(REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE,
- 0x8000 | (i << 8));
+ for (i = 0; i < 16; i++) {
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL2,
+ GLOBAL2_PRIO_OVERRIDE,
+ 0x8000 | (i << 8));
+ if (err)
+ return err;
+ }
}
if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
@@ -2798,31 +2880,38 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
* ingress rate limit registers to their initial
* state.
*/
- for (i = 0; i < ps->num_ports; i++)
- REG_WRITE(REG_GLOBAL2, GLOBAL2_INGRESS_OP,
- 0x9000 | (i << 8));
+ for (i = 0; i < ps->num_ports; i++) {
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL2,
+ GLOBAL2_INGRESS_OP,
+ 0x9000 | (i << 8));
+ if (err)
+ return err;
+ }
}
/* Clear the statistics counters for all ports */
- REG_WRITE(REG_GLOBAL, GLOBAL_STATS_OP, GLOBAL_STATS_OP_FLUSH_ALL);
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_STATS_OP,
+ GLOBAL_STATS_OP_FLUSH_ALL);
+ if (err)
+ return err;
/* Wait for the flush to complete. */
mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_stats_wait(ds);
- if (ret < 0)
+ err = _mv88e6xxx_stats_wait(ds);
+ if (err < 0)
goto unlock;
/* Clear all ATU entries */
- ret = _mv88e6xxx_atu_flush(ds, 0, true);
- if (ret < 0)
+ err = _mv88e6xxx_atu_flush(ds, 0, true);
+ if (err < 0)
goto unlock;
/* Clear all the VTU and STU entries */
- ret = _mv88e6xxx_vtu_stu_flush(ds);
+ err = _mv88e6xxx_vtu_stu_flush(ds);
unlock:
mutex_unlock(&ps->smi_mutex);
- return ret;
+ return err;
}
EXPORT_SYMBOL_GPL(mv88e6xxx_setup_global);
@@ -2832,13 +2921,19 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
struct gpio_desc *gpiod = ps->reset;
unsigned long timeout;
- int ret;
+ int ret, err;
int i;
/* Set all ports to the disabled state. */
for (i = 0; i < ps->num_ports; i++) {
- ret = REG_READ(REG_PORT(i), PORT_CONTROL);
- REG_WRITE(REG_PORT(i), PORT_CONTROL, ret & 0xfffc);
+ ret = mv88e6xxx_reg_read(ds, REG_PORT(i), PORT_CONTROL);
+ if (ret < 0)
+ return ret;
+
+ err = mv88e6xxx_reg_write(ds, REG_PORT(i), PORT_CONTROL,
+ ret & 0xfffc);
+ if (err)
+ return err;
}
/* Wait for transmit queues to drain. */
@@ -2857,14 +2952,19 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
* through global registers 0x18 and 0x19.
*/
if (ppu_active)
- REG_WRITE(REG_GLOBAL, 0x04, 0xc000);
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x04, 0xc000);
else
- REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
+ err = mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x04, 0xc400);
+ if (err)
+ return err;
/* Wait up to one second for reset to complete. */
timeout = jiffies + 1 * HZ;
while (time_before(jiffies, timeout)) {
- ret = REG_READ(REG_GLOBAL, 0x00);
+ ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x00);
+ if (ret < 0)
+ return ret;
+
if ((ret & is_reset) == is_reset)
break;
usleep_range(1000, 2000);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 739d3ff1bddf..6d1b6207144d 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -554,25 +554,6 @@ extern struct dsa_switch_driver mv88e6123_switch_driver;
extern struct dsa_switch_driver mv88e6352_switch_driver;
extern struct dsa_switch_driver mv88e6171_switch_driver;
-#define REG_READ(addr, reg) \
- ({ \
- int __ret; \
- \
- __ret = mv88e6xxx_reg_read(ds, addr, reg); \
- if (__ret < 0) \
- return __ret; \
- __ret; \
- })
-
-#define REG_WRITE(addr, reg, val) \
- ({ \
- int __ret; \
- \
- __ret = mv88e6xxx_reg_write(ds, addr, reg, val); \
- if (__ret < 0) \
- return __ret; \
- })
-
/**
* mv88e6xxx_module_driver() - Helper macro for registering mv88e6xxx drivers
*
--
2.7.0
^ permalink raw reply related
* [PATCH net-next 4/8] dsa: Move gpio reset into switch driver
From: Andrew Lunn @ 2016-04-13 23:59 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
In-Reply-To: <1460591998-20598-1-git-send-email-andrew@lunn.ch>
Resetting the switch is something the driver does, not the framework.
So move the parsing of this property into the driver.
There are no in kernel users of this property, so moving it does not
break anything. There is a board which will make use of this property
making its way into the kernel.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
Documentation/devicetree/bindings/net/dsa/dsa.txt | 2 --
Documentation/devicetree/bindings/net/dsa/marvell.txt | 10 ++++++++++
drivers/net/dsa/mv88e6xxx.c | 14 +++++++++++++-
drivers/net/dsa/mv88e6xxx.h | 7 +++++++
include/net/dsa.h | 8 --------
net/dsa/dsa.c | 16 ----------------
6 files changed, 30 insertions(+), 27 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.txt b/Documentation/devicetree/bindings/net/dsa/dsa.txt
index 5fdbbcdf8c4b..9f4807f90c31 100644
--- a/Documentation/devicetree/bindings/net/dsa/dsa.txt
+++ b/Documentation/devicetree/bindings/net/dsa/dsa.txt
@@ -31,8 +31,6 @@ A switch child node has the following optional property:
switch. Must be set if the switch can not detect
the presence and/or size of a connected EEPROM,
otherwise optional.
-- reset-gpios : phandle and specifier to a gpio line connected to
- reset pin of the switch chip.
A switch may have multiple "port" children nodes
diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt
index 51b7cd9408f2..301416e94513 100644
--- a/Documentation/devicetree/bindings/net/dsa/marvell.txt
+++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt
@@ -10,12 +10,20 @@ If you need a stable binding, use the old dsa.txt binding.
Marvell Switches are MDIO devices. The following properties should be
placed as a child node of an mdio device.
+The properties described here are those specific to Marvell devices.
+Additional required and optional properties can be found in dsa2.txt.
+
Required properties:
- compatible : Should be one of "marvell,mv88e6123",
"marvell,mv88e6131", "marvell,mv88e6171",
"marvell,mv88e6352" or "marvell,mv88e6060"
- reg : Address on the MII bus for the switch.
+Optional properties:
+
+- reset-gpios : Should be a gpio specifier for a reset line
+
+Optional Properties
Example:
mdio {
@@ -25,5 +33,7 @@ Example:
switch0: switch@1 {
reg = <0>;
compatible = "marvell,mv88e6131";
+
+ reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
};
};
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 9e906e0459c7..ef29a94da975 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2830,7 +2830,7 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
- struct gpio_desc *gpiod = ds->pd->reset;
+ struct gpio_desc *gpiod = ps->reset;
unsigned long timeout;
int ret;
int i;
@@ -3178,6 +3178,7 @@ int mv88e6xxx_probe(struct mdio_device *mdiodev, struct dsa_switch_driver *ops,
struct mv88e6xxx_priv_state *ps;
struct dsa_switch *ds;
const char *name;
+ int err;
ds = devm_kzalloc(dev, sizeof(*ds) + sizeof(*ps), GFP_KERNEL);
if (!ds)
@@ -3199,6 +3200,17 @@ int mv88e6xxx_probe(struct mdio_device *mdiodev, struct dsa_switch_driver *ops,
return -ENODEV;
}
+ ps->reset = devm_gpiod_get(&mdiodev->dev, "reset", GPIOD_ASIS);
+ err = PTR_ERR(ps->reset);
+ if (err) {
+ if (err == -ENOENT) {
+ /* Optional, so not an error */
+ ps->reset = NULL;
+ } else {
+ return err;
+ }
+ }
+
dev_set_drvdata(dev, ds);
return 0;
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 3bdc0fdf692f..739d3ff1bddf 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -12,6 +12,7 @@
#define __MV88E6XXX_H
#include <linux/if_vlan.h>
+#include <linux/gpio/consumer.h>
#ifndef UINT64_MAX
#define UINT64_MAX (u64)(~((u64)0))
@@ -446,6 +447,12 @@ struct mv88e6xxx_priv_state {
DECLARE_BITMAP(port_state_update_mask, DSA_MAX_PORTS);
struct work_struct bridge_work;
+
+ /* A switch may have a GPIO line tied to its reset pin. Parse
+ * this from the device tree, and use it before performing
+ * switch soft reset.
+ */
+ struct gpio_desc *reset;
};
enum stat_type {
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 689ebd3542ba..b54a2ed1002c 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -16,7 +16,6 @@
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/phy.h>
#include <linux/phy_fixed.h>
#include <linux/ethtool.h>
@@ -65,13 +64,6 @@ struct dsa_chip_data {
* NULL if there is only one switch chip.
*/
s8 *rtable;
-
- /*
- * A switch may have a GPIO line tied to its reset pin. Parse
- * this from the device tree, and use it before performing
- * switch soft reset.
- */
- struct gpio_desc *reset;
};
struct dsa_platform_data {
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 60ea98481806..1e2238e71ea7 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -660,9 +660,6 @@ static int dsa_of_probe(struct device *dev)
const char *port_name;
int chip_index, port_index;
const unsigned int *sw_addr, *port_reg;
- int gpio;
- enum of_gpio_flags of_flags;
- unsigned long flags;
u32 eeprom_len;
int ret;
@@ -741,19 +738,6 @@ static int dsa_of_probe(struct device *dev)
put_device(cd->host_dev);
cd->host_dev = &mdio_bus_switch->dev;
}
- gpio = of_get_named_gpio_flags(child, "reset-gpios", 0,
- &of_flags);
- if (gpio_is_valid(gpio)) {
- flags = (of_flags == OF_GPIO_ACTIVE_LOW ?
- GPIOF_ACTIVE_LOW : 0);
- ret = devm_gpio_request_one(dev, gpio, flags,
- "switch_reset");
- if (ret)
- goto out_free_chip;
-
- cd->reset = gpio_to_desc(gpio);
- gpiod_direction_output(cd->reset, 0);
- }
for_each_available_child_of_node(child, port) {
port_reg = of_get_property(port, "reg", NULL);
--
2.7.0
^ permalink raw reply related
* [PATCH net-next 0/8] DSA refactoring: set 2
From: Andrew Lunn @ 2016-04-13 23:59 UTC (permalink / raw)
To: David Miller; +Cc: Florian Fainelli, netdev, Vivien Didelot, Andrew Lunn
More preparatory patches for the DSA probe refactoring.
The first three patches turn the Marvell drivers into individual
modules, and a shared library module. They also become real Linux
devices, with probe functions. However, at the moment, this is just
stub code to be filled out with later patches.
With the drivers becoming real devices, it becomes easier to interact
with device tree properties. One such driver property is a GPIO line
used for resetting the switch. This is only used in Marvell devices,
so move it out of the core code into the Marvell shared code. This
changes the existing binding, but no in tree device tree actually uses
it.
The REG_READ and REG_WRITE macros have caused problems in the past,
since they contain a return statement, messing up locking code. They
also assume a ds variable is available. Kill them off.
With the addition of the drivers becoming devices, the order in which
data structures are created is changing. Previously, the DSA framework
would create the dsa_switch structure and pass it to the setup()
method, which would then allocate the driver private structure. Now
the drivers probe as devices, they allocate there private structure
first, and will only get a dsa_switch structure later. Future changes
to have the device export its own MDIO bus rather than have the
framework do it, requires at some of the driver functions operate
using only the private structure. Perform a mass internal API change
to pass the private structure internally, and only pass the dsa_switch
structure for the public APIs.
Each driver maintains a table of IDs to name strings. Extending this
table with the number of ports a switch has. It is likely this will
get further extended with number of VLANs, address databases etc.
The mv88e6131 driver does something different for a single switch vs a
collection of switches. All other drivers don't special case a single
switch. There is no need to do this, so remove the special case. This
will help later with unifying this code into the shared library.
So nothing too interesting here, that will come later...
Andrew Lunn (8):
dsa: mv88e6xxx: Prepare for turning this into a library module
dsa: mv88e6xxx: Add macro for registering the drivers
dsa: Add mdio device support to Marvell switches
dsa: Move gpio reset into switch driver
dsa: mv88e6xxx: Kill the REG_READ and REG_WRITE macros
dsa: mv88e6xxx: Replace ds with ps where possible
dsa: mv88e6xxx: Use the name table to determine number of ports
dsa: mv88e6131: Don't special case a single device
Documentation/devicetree/bindings/net/dsa/dsa.txt | 2 -
.../devicetree/bindings/net/dsa/marvell.txt | 39 +
drivers/net/dsa/Makefile | 19 +-
drivers/net/dsa/mv88e6123.c | 78 +-
drivers/net/dsa/mv88e6131.c | 112 +-
drivers/net/dsa/mv88e6171.c | 62 +-
drivers/net/dsa/mv88e6352.c | 90 +-
drivers/net/dsa/mv88e6xxx.c | 1240 +++++++++++---------
drivers/net/dsa/mv88e6xxx.h | 66 +-
include/net/dsa.h | 8 -
net/dsa/dsa.c | 16 -
11 files changed, 1000 insertions(+), 732 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/dsa/marvell.txt
--
2.7.0
^ permalink raw reply
* [PATCH 1/1] hv_netvsc: Implement support for VF drivers on Hyper-V
From: K. Y. Srinivasan @ 2016-04-13 23:58 UTC (permalink / raw)
To: davem, netdev, linux-kernel, devel, olaf, apw, jasowang
Support VF drivers on Hyper-V. On Hyper-V, each VF instance presented to
the guest has an associated synthetic interface that shares the MAC address
with the VF instance. Typically these are bonded together to support
live migration. By default, the host delivers all the incoming packets
on the synthetic interface. Once the VF is up, we need to explicitly switch
the data path on the host to divert traffic onto the VF interface. Even after
switching the data path, broadcast and multicast packets are always delivered
on the synthetic interface and these will have to be injected back onto the
VF interface (if VF is up).
This patch implements the necessary support in netvsc to support Linux
VF drivers.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
drivers/net/hyperv/hyperv_net.h | 14 ++
drivers/net/hyperv/netvsc.c | 29 ++++
drivers/net/hyperv/netvsc_drv.c | 309 +++++++++++++++++++++++++++++++++++----
3 files changed, 326 insertions(+), 26 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 8b3bd8e..6700a4d 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -202,6 +202,8 @@ int rndis_filter_receive(struct hv_device *dev,
int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac);
+void netvsc_switch_datapath(struct netvsc_device *nv_dev, bool vf);
+
#define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF)
#define NVSP_PROTOCOL_VERSION_1 2
@@ -641,6 +643,12 @@ struct netvsc_reconfig {
u32 event;
};
+struct garp_wrk {
+ struct work_struct dwrk;
+ struct net_device *netdev;
+ struct netvsc_device *netvsc_dev;
+};
+
/* The context of the netvsc device */
struct net_device_context {
/* point back to our device context */
@@ -656,6 +664,7 @@ struct net_device_context {
struct work_struct work;
u32 msg_enable; /* debug level */
+ struct garp_wrk gwrk;
struct netvsc_stats __percpu *tx_stats;
struct netvsc_stats __percpu *rx_stats;
@@ -730,6 +739,11 @@ struct netvsc_device {
u32 vf_alloc;
/* Serial number of the VF to team with */
u32 vf_serial;
+ atomic_t open_cnt;
+ /* State to manage the associated VF interface. */
+ bool vf_inject;
+ struct net_device *vf_netdev;
+ atomic_t vf_use_cnt;
};
/* NdisInitialize message */
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index ec313fc..eddce3c 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -33,6 +33,30 @@
#include "hyperv_net.h"
+/*
+ * Switch the data path from the synthetic interface to the VF
+ * interface.
+ */
+void netvsc_switch_datapath(struct netvsc_device *nv_dev, bool vf)
+{
+ struct nvsp_message *init_pkt = &nv_dev->channel_init_pkt;
+ struct hv_device *dev = nv_dev->dev;
+
+ memset(init_pkt, 0, sizeof(struct nvsp_message));
+ init_pkt->hdr.msg_type = NVSP_MSG4_TYPE_SWITCH_DATA_PATH;
+ if (vf)
+ init_pkt->msg.v4_msg.active_dp.active_datapath =
+ NVSP_DATAPATH_VF;
+ else
+ init_pkt->msg.v4_msg.active_dp.active_datapath =
+ NVSP_DATAPATH_SYNTHETIC;
+
+ vmbus_sendpacket(dev->channel, init_pkt,
+ sizeof(struct nvsp_message),
+ (unsigned long)init_pkt,
+ VM_PKT_DATA_INBAND, 0);
+}
+
static struct netvsc_device *alloc_net_device(struct hv_device *device)
{
@@ -52,11 +76,16 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
init_waitqueue_head(&net_device->wait_drain);
net_device->start_remove = false;
net_device->destroy = false;
+ atomic_set(&net_device->open_cnt, 0);
+ atomic_set(&net_device->vf_use_cnt, 0);
net_device->dev = device;
net_device->ndev = ndev;
net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT;
net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT;
+ net_device->vf_netdev = NULL;
+ net_device->vf_inject = false;
+
hv_set_drvdata(device, net_device);
return net_device;
}
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index b8121eb..5669589 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -610,42 +610,24 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
schedule_delayed_work(&ndev_ctx->dwork, 0);
}
-/*
- * netvsc_recv_callback - Callback when we receive a packet from the
- * "wire" on the specified device.
- */
-int netvsc_recv_callback(struct hv_device *device_obj,
+
+static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net,
struct hv_netvsc_packet *packet,
- void **data,
struct ndis_tcp_ip_checksum_info *csum_info,
- struct vmbus_channel *channel,
- u16 vlan_tci)
+ void *data, u16 vlan_tci)
{
- struct net_device *net;
- struct net_device_context *net_device_ctx;
struct sk_buff *skb;
- struct netvsc_stats *rx_stats;
- net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev;
- if (!net || net->reg_state != NETREG_REGISTERED) {
- return NVSP_STAT_FAIL;
- }
- net_device_ctx = netdev_priv(net);
- rx_stats = this_cpu_ptr(net_device_ctx->rx_stats);
-
- /* Allocate a skb - TODO direct I/O to pages? */
skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen);
- if (unlikely(!skb)) {
- ++net->stats.rx_dropped;
- return NVSP_STAT_FAIL;
- }
+ if (!skb)
+ return skb;
/*
* Copy to skb. This copy is needed here since the memory pointed by
* hv_netvsc_packet cannot be deallocated
*/
- memcpy(skb_put(skb, packet->total_data_buflen), *data,
- packet->total_data_buflen);
+ memcpy(skb_put(skb, packet->total_data_buflen), data,
+ packet->total_data_buflen);
skb->protocol = eth_type_trans(skb, net);
if (csum_info) {
@@ -663,6 +645,75 @@ int netvsc_recv_callback(struct hv_device *device_obj,
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
vlan_tci);
+ return skb;
+}
+
+/*
+ * netvsc_recv_callback - Callback when we receive a packet from the
+ * "wire" on the specified device.
+ */
+int netvsc_recv_callback(struct hv_device *device_obj,
+ struct hv_netvsc_packet *packet,
+ void **data,
+ struct ndis_tcp_ip_checksum_info *csum_info,
+ struct vmbus_channel *channel,
+ u16 vlan_tci)
+{
+ struct net_device *net;
+ struct net_device_context *net_device_ctx;
+ struct sk_buff *skb;
+ struct sk_buff *vf_skb;
+ struct netvsc_stats *rx_stats;
+ struct netvsc_device *netvsc_dev = hv_get_drvdata(device_obj);
+ u32 bytes_recvd = packet->total_data_buflen;
+ int ret = 0;
+
+ net = netvsc_dev->ndev;
+ if (!net || net->reg_state != NETREG_REGISTERED)
+ return NVSP_STAT_FAIL;
+
+ if (READ_ONCE(netvsc_dev->vf_inject)) {
+ atomic_inc(&netvsc_dev->vf_use_cnt);
+ if (READ_ONCE(netvsc_dev->vf_inject)) {
+ /*
+ * We raced; just move on.
+ */
+ atomic_dec(&netvsc_dev->vf_use_cnt);
+ goto vf_injection_done;
+ }
+
+ /*
+ * Inject this packet into the VF inerface.
+ * On Hyper-V, multicast and brodcast packets
+ * are only delivered on the synthetic interface
+ * (after subjecting these to policy filters on
+ * the host). Deliver these via the VF interface
+ * in the guest.
+ */
+ vf_skb = netvsc_alloc_recv_skb(netvsc_dev->vf_netdev, packet,
+ csum_info, *data, vlan_tci);
+ if (vf_skb != NULL) {
+ ++netvsc_dev->vf_netdev->stats.rx_packets;
+ netvsc_dev->vf_netdev->stats.rx_bytes += bytes_recvd;
+ netif_receive_skb(vf_skb);
+ } else {
+ ++net->stats.rx_dropped;
+ ret = NVSP_STAT_FAIL;
+ }
+ atomic_dec(&netvsc_dev->vf_use_cnt);
+ return ret;
+ }
+
+vf_injection_done:
+ net_device_ctx = netdev_priv(net);
+ rx_stats = this_cpu_ptr(net_device_ctx->rx_stats);
+
+ /* Allocate a skb - TODO direct I/O to pages? */
+ skb = netvsc_alloc_recv_skb(net, packet, csum_info, *data, vlan_tci);
+ if (unlikely(!skb)) {
+ ++net->stats.rx_dropped;
+ return NVSP_STAT_FAIL;
+ }
skb_record_rx_queue(skb, channel->
offermsg.offer.sub_channel_index);
@@ -1102,6 +1153,172 @@ static void netvsc_free_netdev(struct net_device *netdev)
free_netdev(netdev);
}
+static void netvsc_notify_peers(struct work_struct *wrk)
+{
+ struct garp_wrk *gwrk;
+
+ gwrk = container_of(wrk, struct garp_wrk, dwrk);
+
+ netdev_notify_peers(gwrk->netdev);
+
+ atomic_dec(&gwrk->netvsc_dev->vf_use_cnt);
+}
+
+static struct netvsc_device *get_netvsc_device(char *mac)
+{
+ struct net_device *dev;
+ struct net_device_context *netvsc_ctx = NULL;
+ int rtnl_locked;
+
+ rtnl_locked = rtnl_trylock();
+
+ for_each_netdev(&init_net, dev) {
+ if (memcmp(dev->dev_addr, mac, ETH_ALEN) == 0) {
+ if (dev->netdev_ops != &device_ops)
+ continue;
+ netvsc_ctx = netdev_priv(dev);
+ break;
+ }
+ }
+ if (rtnl_locked)
+ rtnl_unlock();
+
+ if (netvsc_ctx == NULL)
+ return NULL;
+
+ return hv_get_drvdata(netvsc_ctx->device_ctx);
+}
+
+static int netvsc_register_vf(struct net_device *vf_netdev)
+{
+ struct netvsc_device *netvsc_dev;
+ const struct ethtool_ops *eth_ops = vf_netdev->ethtool_ops;
+
+ if (eth_ops == NULL || eth_ops == ðtool_ops)
+ return NOTIFY_DONE;
+
+ /*
+ * We will use the MAC address to locate the synthetic interface to
+ * associate with the VF interface. If we don't find a matching
+ * synthetic interface, move on.
+ */
+ netvsc_dev = get_netvsc_device(vf_netdev->dev_addr);
+ if (netvsc_dev == NULL)
+ return NOTIFY_DONE;
+
+ pr_info("VF registering: %s\n", vf_netdev->name);
+ /*
+ * Take a reference on the module.
+ */
+ try_module_get(THIS_MODULE);
+ netvsc_dev->vf_netdev = vf_netdev;
+ return NOTIFY_OK;
+}
+
+
+static int netvsc_vf_up(struct net_device *vf_netdev)
+{
+ struct netvsc_device *netvsc_dev;
+ const struct ethtool_ops *eth_ops = vf_netdev->ethtool_ops;
+ struct net_device_context *net_device_ctx;
+
+ if (eth_ops == ðtool_ops)
+ return NOTIFY_DONE;
+
+ netvsc_dev = get_netvsc_device(vf_netdev->dev_addr);
+
+ if ((netvsc_dev == NULL) || (netvsc_dev->vf_netdev == NULL))
+ return NOTIFY_DONE;
+
+ pr_info("VF up: %s\n", vf_netdev->name);
+ net_device_ctx = netdev_priv(netvsc_dev->ndev);
+ netvsc_dev->vf_inject = true;
+
+ /*
+ * Open the device before switching data path.
+ */
+ rndis_filter_open(net_device_ctx->device_ctx);
+
+ /*
+ * notify the host to switch the data path.
+ */
+ netvsc_switch_datapath(netvsc_dev, true);
+ pr_info("Data path switched to VF: %s\n", vf_netdev->name);
+
+ netif_carrier_off(netvsc_dev->ndev);
+
+ /*
+ * Now notify peers. We are scheduling work to
+ * notify peers; take a reference to prevent
+ * the VF interface from vanishing.
+ */
+ atomic_inc(&netvsc_dev->vf_use_cnt);
+ net_device_ctx->gwrk.netdev = vf_netdev;
+ net_device_ctx->gwrk.netvsc_dev = netvsc_dev;
+ schedule_work(&net_device_ctx->gwrk.dwrk);
+
+ return NOTIFY_OK;
+}
+
+
+static int netvsc_vf_down(struct net_device *vf_netdev)
+{
+ struct netvsc_device *netvsc_dev;
+ struct net_device_context *net_device_ctx;
+ const struct ethtool_ops *eth_ops = vf_netdev->ethtool_ops;
+
+ if (eth_ops == ðtool_ops)
+ return NOTIFY_DONE;
+
+ netvsc_dev = get_netvsc_device(vf_netdev->dev_addr);
+
+ if ((netvsc_dev == NULL) || (netvsc_dev->vf_netdev == NULL))
+ return NOTIFY_DONE;
+
+ pr_info("VF down: %s\n", vf_netdev->name);
+ net_device_ctx = netdev_priv(netvsc_dev->ndev);
+ netvsc_dev->vf_inject = false;
+ /*
+ * Wait for currently active users to
+ * drain out.
+ */
+
+ while (atomic_read(&netvsc_dev->vf_use_cnt) != 0)
+ udelay(50);
+ netvsc_switch_datapath(netvsc_dev, false);
+ pr_info("Data path switched from VF: %s\n", vf_netdev->name);
+ rndis_filter_close(net_device_ctx->device_ctx);
+ netif_carrier_on(netvsc_dev->ndev);
+ /*
+ * Notify peers.
+ */
+ atomic_inc(&netvsc_dev->vf_use_cnt);
+ net_device_ctx->gwrk.netdev = netvsc_dev->ndev;
+ net_device_ctx->gwrk.netvsc_dev = netvsc_dev;
+ schedule_work(&net_device_ctx->gwrk.dwrk);
+
+ return NOTIFY_OK;
+}
+
+
+static int netvsc_unregister_vf(struct net_device *vf_netdev)
+{
+ struct netvsc_device *netvsc_dev;
+ const struct ethtool_ops *eth_ops = vf_netdev->ethtool_ops;
+
+ if (eth_ops == ðtool_ops)
+ return NOTIFY_DONE;
+
+ netvsc_dev = get_netvsc_device(vf_netdev->dev_addr);
+ if (netvsc_dev == NULL)
+ return NOTIFY_DONE;
+ pr_info("VF unregistering: %s\n", vf_netdev->name);
+
+ netvsc_dev->vf_netdev = NULL;
+ module_put(THIS_MODULE);
+ return NOTIFY_OK;
+}
+
static int netvsc_probe(struct hv_device *dev,
const struct hv_vmbus_device_id *dev_id)
{
@@ -1140,6 +1357,7 @@ static int netvsc_probe(struct hv_device *dev,
hv_set_drvdata(dev, net);
INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
INIT_WORK(&net_device_ctx->work, do_set_multicast);
+ INIT_WORK(&net_device_ctx->gwrk.dwrk, netvsc_notify_peers);
spin_lock_init(&net_device_ctx->lock);
INIT_LIST_HEAD(&net_device_ctx->reconfig_events);
@@ -1235,19 +1453,58 @@ static struct hv_driver netvsc_drv = {
.remove = netvsc_remove,
};
+
+/*
+ * On Hyper-V, every VF interface is matched with a corresponding
+ * synthetic interface. The synthetic interface is presented first
+ * to the guest. When the corresponding VF instance is registered,
+ * we will take care of switching the data path.
+ */
+static int netvsc_netdev_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
+
+ switch (event) {
+ case NETDEV_REGISTER:
+ return netvsc_register_vf(event_dev);
+ case NETDEV_UNREGISTER:
+ return netvsc_unregister_vf(event_dev);
+ case NETDEV_UP:
+ return netvsc_vf_up(event_dev);
+ case NETDEV_DOWN:
+ return netvsc_vf_down(event_dev);
+ default:
+ return NOTIFY_DONE;
+ }
+}
+
+static struct notifier_block netvsc_netdev_notifier = {
+ .notifier_call = netvsc_netdev_event,
+};
+
static void __exit netvsc_drv_exit(void)
{
+ unregister_netdevice_notifier(&netvsc_netdev_notifier);
vmbus_driver_unregister(&netvsc_drv);
}
static int __init netvsc_drv_init(void)
{
+ int ret;
+
if (ring_size < RING_SIZE_MIN) {
ring_size = RING_SIZE_MIN;
pr_info("Increased ring_size to %d (min allowed)\n",
ring_size);
}
- return vmbus_driver_register(&netvsc_drv);
+ ret = vmbus_driver_register(&netvsc_drv);
+
+ if (ret)
+ return ret;
+
+ register_netdevice_notifier(&netvsc_netdev_notifier);
+ return 0;
}
MODULE_LICENSE("GPL");
--
1.7.4.1
^ permalink raw reply related
* [PATCH 1/3] netfilter: arp_tables: register table in initns
From: Pablo Neira Ayuso @ 2016-04-13 22:54 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1460588094-3933-1-git-send-email-pablo@netfilter.org>
From: Florian Westphal <fw@strlen.de>
arptables is broken since we didn't register the table anymore --
even 'arptables -L' fails.
Fixes: b9e69e127397187b ("netfilter: xtables: don't hook tables by default")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/ipv4/netfilter/arptable_filter.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index dd8c80d..8f8713b 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -81,6 +81,12 @@ static int __init arptable_filter_init(void)
return ret;
}
+ ret = arptable_filter_table_init(&init_net);
+ if (ret) {
+ unregister_pernet_subsys(&arptable_filter_net_ops);
+ kfree(arpfilter_ops);
+ }
+
return ret;
}
--
2.1.4
^ permalink raw reply related
* [PATCH 0/3] Netfilter fixes for net
From: Pablo Neira Ayuso @ 2016-04-13 22:54 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
Hi David,
The following patchset contains Netfilter fixes for your net tree. More
specifically, they are:
1) Fix missing filter table per-netns registration in arptables, from
Florian Westphal.
2) Resolve out of bound access when parsing TCP options in
nf_conntrack_tcp, patch from Jozsef Kadlecsik.
3) Prefer NFPROTO_BRIDGE extensions over NFPROTO_UNSPEC in ebtables,
this resolves conflict between xt_limit and ebt_limit, from Phil Sutter.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
Thanks!
----------------------------------------------------------------
The following changes since commit 0a1a37b6d62e6864a77a82e925217c720f91f963:
net: add the AF_KCM entries to family name tables (2016-04-06 16:59:01 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git HEAD
for you to fetch changes up to bcf4934288402be3464110109a4dae3bd6fb3e93:
netfilter: ebtables: Fix extension lookup with identical name (2016-04-13 01:16:57 +0200)
----------------------------------------------------------------
Florian Westphal (1):
netfilter: arp_tables: register table in initns
Jozsef Kadlecsik (1):
netfilter: nf_conntrack_tcp: Fix stack out of bounds when parsing TCP options
Phil Sutter (1):
netfilter: ebtables: Fix extension lookup with identical name
net/bridge/netfilter/ebtables.c | 6 +++++-
net/ipv4/netfilter/arptable_filter.c | 6 ++++++
net/netfilter/nf_conntrack_proto_tcp.c | 4 ++++
3 files changed, 15 insertions(+), 1 deletion(-)
^ permalink raw reply
* [PATCH 3/3] netfilter: ebtables: Fix extension lookup with identical name
From: Pablo Neira Ayuso @ 2016-04-13 22:54 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1460588094-3933-1-git-send-email-pablo@netfilter.org>
From: Phil Sutter <phil@nwl.cc>
If a requested extension exists as module and is not loaded,
ebt_check_match() might accidentally use an NFPROTO_UNSPEC one with same
name and fail.
Reproduced with limit match: Given xt_limit and ebt_limit both built as
module, the following would fail:
modprobe xt_limit
ebtables -I INPUT --limit 1/s -j ACCEPT
The fix is to make ebt_check_match() distrust a found NFPROTO_UNSPEC
extension and retry after requesting an appropriate module.
Cc: Florian Westphal <fw@strlen.de>
Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/bridge/netfilter/ebtables.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 8570bc7..5a61f35 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -370,7 +370,11 @@ ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par,
left - sizeof(struct ebt_entry_match) < m->match_size)
return -EINVAL;
- match = xt_request_find_match(NFPROTO_BRIDGE, m->u.name, 0);
+ match = xt_find_match(NFPROTO_BRIDGE, m->u.name, 0);
+ if (IS_ERR(match) || match->family != NFPROTO_BRIDGE) {
+ request_module("ebt_%s", m->u.name);
+ match = xt_find_match(NFPROTO_BRIDGE, m->u.name, 0);
+ }
if (IS_ERR(match))
return PTR_ERR(match);
m->u.match = match;
--
2.1.4
^ permalink raw reply related
* [PATCH 2/3] netfilter: nf_conntrack_tcp: Fix stack out of bounds when parsing TCP options
From: Pablo Neira Ayuso @ 2016-04-13 22:54 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1460588094-3933-1-git-send-email-pablo@netfilter.org>
From: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Baozeng Ding reported a KASAN stack out of bounds issue - it uncovered that
the TCP option parsing routines in netfilter TCP connection tracking could
read one byte out of the buffer of the TCP options. Therefore in the patch
we check that the available data length is large enough to parse both TCP
option code and size.
Reported-by: Baozeng Ding <sploving1@gmail.com>
Tested-by: Baozeng Ding <sploving1@gmail.com>
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_conntrack_proto_tcp.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 278f3b9..7cc1d9c 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -410,6 +410,8 @@ static void tcp_options(const struct sk_buff *skb,
length--;
continue;
default:
+ if (length < 2)
+ return;
opsize=*ptr++;
if (opsize < 2) /* "silly options" */
return;
@@ -470,6 +472,8 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff,
length--;
continue;
default:
+ if (length < 2)
+ return;
opsize = *ptr++;
if (opsize < 2) /* "silly options" */
return;
--
2.1.4
^ permalink raw reply related
* Re: [PATCH 0/3] crypto: af_alg - add TLS type encryption
From: Tadeusz Struk @ 2016-04-13 22:46 UTC (permalink / raw)
To: Fridolin Pokorny
Cc: Tom Herbert, Herbert Xu, linux-crypto, LKML, David S. Miller,
Linux Kernel Network Developers, davejwatson, nmav,
fridolin.pokorny
In-Reply-To: <570CD852.7060003@redhat.com>
Hi Fridolin,
On 04/12/2016 04:13 AM, Fridolin Pokorny wrote:
> we were experimenting with this. We have a prove of concept of a kernel
> TLS type socket, so called AF_KTLS, which is based on Dave Watson's
> RFC5288 patch. It handles both TLS and DTLS, unfortunately it is not
> ready now to be proposed here. There are still issues which should be
> solved (but mostly user space API design) [1]. If you are interested, we
> could combine efforts.
>
> Regards,
> Fridolin Pokorny
>
> [1] https://github.com/fridex/af_ktls
I had a quick look and it looks like is limited only to gcm(aes).
I would be more interested to have a generic interface that could do generic algorithm
suits like aes-cbc-hmac-sha1 also.
This also seems to work in a synchronous (send one and wait) mode, which is a not good
solution for HW accelerators, which I'm trying to enable.
Thanks,
--
TS
^ permalink raw reply
* [PATCH iproute2] ss: take care of unknown min_rtt
From: Eric Dumazet @ 2016-04-13 22:18 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
From: Eric Dumazet <edumazet@google.com>
Kernel sets info->tcpi_min_rtt to ~0U when no RTT sample was ever
taken for the session, thus min_rtt is unknown.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
misc/ss.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/misc/ss.c b/misc/ss.c
index 38cf331..51ff5ac 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -2018,7 +2018,8 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
s.segs_out = info->tcpi_segs_out;
s.segs_in = info->tcpi_segs_in;
s.not_sent = info->tcpi_notsent_bytes;
- s.min_rtt = (double) info->tcpi_min_rtt / 1000;
+ if (info->tcpi_min_rtt && info->tcpi_min_rtt != ~0U)
+ s.min_rtt = (double) info->tcpi_min_rtt / 1000;
tcp_stats_print(&s);
free(s.dctcp);
}
^ permalink raw reply related
* Re: [PATCH 1/2] [v4] net: emac: emac gigabit ethernet controller driver
From: Florian Fainelli @ 2016-04-13 22:16 UTC (permalink / raw)
To: Timur Tabi, netdev, linux-kernel, devicetree, linux-arm-msm,
sdharia, Shanker Donthineni, Greg Kroah-Hartman, vikrams, cov,
gavidov, Rob Herring, andrew, bjorn.andersson, Mark Langsdorf,
Jon Masters, Andy Gross, David S. Miller
In-Reply-To: <1460570393-19838-1-git-send-email-timur@codeaurora.org>
On 13/04/16 10:59, Timur Tabi wrote:
> From: Gilad Avidov <gavidov@codeaurora.org>
>
> Add supports for ethernet controller HW on Qualcomm Technologies, Inc. SoC.
> This driver supports the following features:
> 1) Checksum offload.
> 2) Runtime power management support.
> 3) Interrupt coalescing support.
> 4) SGMII phy.
> 5) SGMII direct connection without external phy.
I think you should shoot for more simple for an initial submission:
- no offload
- no timestamping
get that accepted, and then add features one by one, it sure is more
work, but it helps with the review, and makes you work off a solid base.
You will see below, but a pet peeve of mine is authors reimplementing
code that exists in PHYLIB.
[snip]
> diff --git a/Documentation/devicetree/bindings/net/qcom-emac.txt b/Documentation/devicetree/bindings/net/qcom-emac.txt
> new file mode 100644
> index 0000000..df5e7c0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/qcom-emac.txt
> @@ -0,0 +1,65 @@
> +Qualcomm EMAC Gigabit Ethernet Controller
> +
> +Required properties:
> +- compatible : Should be "qcom,emac".
> +- reg : Offset and length of the register regions for the device
> +- reg-names : Register region names referenced in 'reg' above.
> + Required register resource entries are:
> + "base" : EMAC controller base register block.
> + "csr" : EMAC wrapper register block.
> + Optional register resource entries are:
> + "ptp" : EMAC PTP (1588) register block.
> + Required if 'qcom,emac-tstamp-en' is present.
> + "sgmii" : EMAC SGMII PHY register block.
> +- interrupts : Interrupt numbers used by this controller
> +- interrupt-names : Interrupt resource names referenced in 'interrupts' above.
> + Required interrupt resource entries are:
> + "emac_core0" : EMAC core0 interrupt.
> + "sgmii_irq" : EMAC SGMII interrupt.
> +- phy-addr : Specifies phy address on MDIO bus.
> + Required if the optional property "qcom,no-external-phy"
> + is not specified.
This is not the standard way to represent an Ethernet PHY hanging off a
MDIO bus see ethernet.txt and phy.txt in D/dt/bindings/net/
> +
> +Optional properties:
> +- qcom,emac-tstamp-en : Enables the PTP (1588) timestamping feature.
> + Include this only if PTP (1588) timestamping
> + feature is needed. If included, "ptp" register
> + base should be specified.
If the "ptp" register range is not specified, then PTP gets disabled, so
is a boolean really required here, considering that this looks like a
policy decision more than anything.
> +- mac-address : The 6-byte MAC address. If present, it is the
> + default MAC address.
This property is pretty much mandatory
> +- qcom,no-external-phy : Indicates there is no external PHY connected to
> + EMAC. Include this only if the EMAC is directly
> + connected to the peer end without EPHY.
How is the internal PHY accessed, is it responding on the MDIO bus at a
particular address? If so, standard MDIO scanning/probing works, and you
can have your PHY driver flag this device has internal. Worst case, you
can do what BCMGENET does, and have a special "phy-mode" value set to
"internal" when this knowledge needs to exist prior to MDIO bus scanning
(e.g: to power on the PHY).
> +Example:
> + emac0: qcom,emac@feb20000 {
> + compatible = "qcom,fsm9900-emac";
> + reg-names = "base", "csr", "ptp", "sgmii";
> + reg = <0xfeb20000 0x10000>,
> + <0xfeb36000 0x1000>,
> + <0xfeb3c000 0x4000>,
> + <0xfeb38000 0x400>;
> + #address-cells = <0>;
> + interrupt-parent = <&emac0>;
> + #interrupt-cells = <1>;
> + interrupts = <0 1>;
> + interrupt-map-mask = <0xffffffff>;
> + interrupt-map = <0 &intc 0 76 0
> + 1 &intc 0 80 0>;
> + interrupt-names = "emac_core0", "sgmii_irq";
> + qcom,emac-tstamp-en;
> + phy-addr = <0>;
> +
> + pinctrl-names = "default";
> + pinctrl-0 = <&mdio_pins_a>;
> + };
> +
> + tlmm: pinctrl@fd510000 {
> + compatible = "qcom,fsm9900-pinctrl";
> +
> + mdio_pins_a: mdio {
> + state {
> + pins = "gpio123", "gpio124";
> + function = "mdio";
> + };
> + };
> + };
> diff --git a/drivers/net/ethernet/qualcomm/Kconfig b/drivers/net/ethernet/qualcomm/Kconfig
> index a76e380..85b599f 100644
> --- a/drivers/net/ethernet/qualcomm/Kconfig
> +++ b/drivers/net/ethernet/qualcomm/Kconfig
> @@ -24,4 +24,15 @@ config QCA7000
> To compile this driver as a module, choose M here. The module
> will be called qcaspi.
>
> +config QCOM_EMAC
> + tristate "Qualcomm Technologies, Inc. EMAC Gigabit Ethernet support"
> + select CRC32
> + ---help---
> + This driver supports the Qualcomm Technologies, Inc. Gigabit
> + Ethernet Media Access Controller (EMAC). The controller
> + supports IEEE 802.3-2002, half-duplex mode at 10/100 Mb/s,
> + full-duplex mode at 10/100/1000Mb/s, Wake On LAN (WOL) for
> + low power, Receive-Side Scaling (RSS), and IEEE 1588-2008
> + Precision Clock Synchronization Protocol.
> +
> endif # NET_VENDOR_QUALCOMM
[snip]
> +/* Config MAC modes */
> +void emac_mac_mode_config(struct emac_adapter *adpt)
> +{
> + u32 mac;
> +
> + mac = readl(adpt->base + EMAC_MAC_CTRL);
> +
> + if (test_bit(EMAC_STATUS_VLANSTRIP_EN, &adpt->status))
> + mac |= VLAN_STRIP;
> + else
> + mac &= ~VLAN_STRIP;
> +
> + if (test_bit(EMAC_STATUS_PROMISC_EN, &adpt->status))
> + mac |= PROM_MODE;
> + else
> + mac &= ~PROM_MODE;
> +
> + if (test_bit(EMAC_STATUS_MULTIALL_EN, &adpt->status))
> + mac |= MULTI_ALL;
> + else
> + mac &= ~MULTI_ALL;
> +
> + if (test_bit(EMAC_STATUS_LOOPBACK_EN, &adpt->status))
> + mac |= MAC_LP_EN;
> + else
> + mac &= ~MAC_LP_EN;
Do you need to maintain these flags when most, if not all of them
already exist in dev->flags or dev->features?
[snip]
> + /* setup link speed */
> + mac &= ~SPEED_BMSK;
> + switch (phy->link_speed) {
> + case EMAC_LINK_SPEED_1GB_FULL:
> + mac |= ((emac_mac_speed_1000 << SPEED_SHFT) & SPEED_BMSK);
> + csr1 |= FREQ_MODE;
> + break;
> + default:
> + mac |= ((emac_mac_speed_10_100 << SPEED_SHFT) & SPEED_BMSK);
> + csr1 &= ~FREQ_MODE;
> + break;
> + }
If you implement the driver using PHYLIB, which you should in order to
support arbitrary or internal PHYs, then this function gets invoked
whenever there is a link parameter change (auto-neg, forcing,
duplex/speed/no link etc.).
[snip]
> + napi_enable(&adpt->rx_q.napi);
> +
> + /* enable mac irq */
> + writel(~DIS_INT, adpt->base + EMAC_INT_STATUS);
> + writel(adpt->irq.mask, adpt->base + EMAC_INT_MASK);
> +
> + netif_start_queue(netdev);
Starting the TX queue is typically the last ting you want to do, to
avoid a transient state where the TX queue is enabled, and the link is
not (which is okay if your driver is properly implemented and reflects
carrier changes anyway).
> + clear_bit(EMAC_STATUS_DOWN, &adpt->status);
> +
> + /* check link status */
> + set_bit(EMAC_STATUS_TASK_LSC_REQ, &adpt->status);
> + adpt->link_chk_timeout = jiffies + EMAC_TRY_LINK_TIMEOUT;
> + mod_timer(&adpt->timers, jiffies);
Please implement a PHYLIB driver and use phy_start() here.
> +
> + return 0;
> +}
> +
> +/* Bring down the interface/HW */
> +void emac_mac_down(struct emac_adapter *adpt, bool reset)
> +{
> + struct net_device *netdev = adpt->netdev;
> + struct emac_phy *phy = &adpt->phy;
> + unsigned long flags;
> +
> + set_bit(EMAC_STATUS_DOWN, &adpt->status);
Do you need to maintain that? Would not netif_running() tell you what
you want if you reflect the carrier state properly?
> +
> + netif_stop_queue(netdev);
> + netif_carrier_off(netdev);
phy_stop() would take care of the latter.
[snip]
> +/* Process transmit event */
> +void emac_mac_tx_process(struct emac_adapter *adpt, struct emac_tx_queue *tx_q)
> +{
> + struct emac_buffer *tpbuf;
> + u32 hw_consume_idx;
> + u32 pkts_compl = 0, bytes_compl = 0;
> + u32 reg = readl_relaxed(adpt->base + tx_q->consume_reg);
> +
> + hw_consume_idx = (reg & tx_q->consume_mask) >> tx_q->consume_shift;
> +
> + while (tx_q->tpd.consume_idx != hw_consume_idx) {
> + tpbuf = GET_TPD_BUFFER(tx_q, tx_q->tpd.consume_idx);
> + if (tpbuf->dma_addr) {
> + dma_unmap_single(adpt->netdev->dev.parent,
> + tpbuf->dma_addr, tpbuf->length,
> + DMA_TO_DEVICE);
> + tpbuf->dma_addr = 0;
> + }
> +
> + if (tpbuf->skb) {
> + pkts_compl++;
> + bytes_compl += tpbuf->skb->len;
> + dev_kfree_skb_irq(tpbuf->skb);
> + tpbuf->skb = NULL;
> + }
> +
> + if (++tx_q->tpd.consume_idx == tx_q->tpd.count)
> + tx_q->tpd.consume_idx = 0;
> + }
> +
> + if (pkts_compl || bytes_compl)
> + netdev_completed_queue(adpt->netdev, pkts_compl, bytes_compl);
The condition can be eliminated.
[snip]
> + if (skb_network_offset(skb) != ETH_HLEN)
> + TPD_TYP_SET(&tpd, 1);
> +
> + emac_tx_fill_tpd(adpt, tx_q, skb, &tpd);
> +
> + netdev_sent_queue(adpt->netdev, skb->len);
> +
> + /* update produce idx */
> + prod_idx = (tx_q->tpd.produce_idx << tx_q->produce_shift) &
> + tx_q->produce_mask;
> + emac_reg_update32(adpt->base + tx_q->produce_reg,
> + tx_q->produce_mask, prod_idx);
Since you have a producer index, you should consider checking
skb->xmit_more to know whether you can update the register now, or
later, which could save some expensive operation and batch TX.
[snip]
> diff --git a/drivers/net/ethernet/qualcomm/emac/emac-phy.c b/drivers/net/ethernet/qualcomm/emac/emac-phy.c
> new file mode 100644
> index 0000000..7d18de3
> --- /dev/null
> +++ b/drivers/net/ethernet/qualcomm/emac/emac-phy.c
This file is really really ugly, and duplicates a lot of functionality
provided by PHYLIB, you really need to implement a PHYLIB MDIO driver
and eventually a small PHY driver for your internal PHY if it needs some
baby sitting.
[snip]
> diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
> new file mode 100644
> index 0000000..ce328f5
> --- /dev/null
> +++ b/drivers/net/ethernet/qualcomm/emac/emac.c
> @@ -0,0 +1,1206 @@
> +/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +/* Qualcomm Technologies, Inc. EMAC Gigabit Ethernet Driver
> + * The EMAC driver supports following features:
> + * 1) Receive Side Scaling (RSS).
> + * 2) Checksum offload.
> + * 3) Multiple PHY support on MDIO bus.
> + * 4) Runtime power management support.
> + * 5) Interrupt coalescing support.
> + * 6) SGMII phy.
> + * 7) SGMII direct connection (without external phy).
> + */
> +
> +#include <linux/if_ether.h>
> +#include <linux/if_vlan.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_net.h>
> +#include <linux/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include "emac.h"
> +#include "emac-mac.h"
> +#include "emac-phy.h"
> +#include "emac-sgmii.h"
> +
> +#define DRV_VERSION "1.3.0.0"
> +
> +static int debug = -1;
> +module_param(debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
ethtool -s <iface> msglvl provides you with that already.
> +
> +static int emac_irq_use_extended;
> +module_param(emac_irq_use_extended, int, S_IRUGO | S_IWUSR | S_IWGRP);
What is that module parameter used for?
> +
> +const char emac_drv_name[] = "qcom-emac";
> +const char emac_drv_description[] =
> + "Qualcomm Technologies, Inc. EMAC Ethernet Driver";
> +const char emac_drv_version[] = DRV_VERSION;
Static all other the place?
[snip]
> +
> +/* NAPI */
> +static int emac_napi_rtx(struct napi_struct *napi, int budget)
> +{
> + struct emac_rx_queue *rx_q = container_of(napi, struct emac_rx_queue,
> + napi);
> + struct emac_adapter *adpt = netdev_priv(rx_q->netdev);
> + struct emac_irq *irq = rx_q->irq;
> +
> + int work_done = 0;
> +
> + /* Keep link state information with original netdev */
> + if (!netif_carrier_ok(adpt->netdev))
> + goto quit_polling;
I do not think this is a condition that could occur?
> +
> + emac_mac_rx_process(adpt, rx_q, &work_done, budget);
> +
> + if (work_done < budget) {
> +quit_polling:
> + napi_complete(napi);
> +
> + irq->mask |= rx_q->intr;
> + writel(irq->mask, adpt->base + EMAC_INT_MASK);
> + }
> +
> + return work_done;
> +}
> +
> +/* Transmit the packet */
> +static int emac_start_xmit(struct sk_buff *skb, struct net_device *netdev)
> +{
> + struct emac_adapter *adpt = netdev_priv(netdev);
> +
> + return emac_mac_tx_buf_send(adpt, &adpt->tx_q, skb);
I would inline emac_mac_tx_buf_send()'s body here to make it much easier
to read and audit...
> +}
> +
> +irqreturn_t emac_isr(int _irq, void *data)
> +{
> + struct emac_irq *irq = data;
> + struct emac_adapter *adpt = container_of(irq, struct emac_adapter, irq);
> + struct emac_rx_queue *rx_q = &adpt->rx_q;
> +
> + int max_ints = 1;
> + u32 isr, status;
> +
> + /* disable the interrupt */
> + writel(0, adpt->base + EMAC_INT_MASK);
> +
> + do {
With max_ints = 1, this is essentially the same as no loop, so just
inline it to reduce the indentation.
> + isr = readl_relaxed(adpt->base + EMAC_INT_STATUS);
> + status = isr & irq->mask;
> +
> + if (status == 0)
> + break;
> +
> + if (status & ISR_ERROR) {
> + netif_warn(adpt, intr, adpt->netdev,
> + "warning: error irq status 0x%lx\n",
> + status & ISR_ERROR);
> + /* reset MAC */
> + set_bit(EMAC_STATUS_TASK_REINIT_REQ, &adpt->status);
> + emac_work_thread_reschedule(adpt);
> + }
> +
> + /* Schedule the napi for receive queue with interrupt
> + * status bit set
> + */
> + if ((status & rx_q->intr)) {
> + if (napi_schedule_prep(&rx_q->napi)) {
> + irq->mask &= ~rx_q->intr;
> + __napi_schedule(&rx_q->napi);
> + }
> + }
> +
> + if (status & TX_PKT_INT)
> + emac_mac_tx_process(adpt, &adpt->tx_q);
You should consider using a NAPI instance for reclaiming TX buffers as well.
> +
> + if (status & ISR_OVER)
> + netif_warn(adpt, intr, adpt->netdev,
> + "warning: TX/RX overflow status 0x%lx\n",
> + status & ISR_OVER);
This should be ratelimited presumably
> +
> + /* link event */
> + if (status & (ISR_GPHY_LINK | SW_MAN_INT)) {
> + emac_lsc_schedule_check(adpt);
> + break;
> + }
> + } while (--max_ints > 0);
> +
> + /* enable the interrupt */
> + writel(irq->mask, adpt->base + EMAC_INT_MASK);
> +
> + return IRQ_HANDLED;
> +}
> +
> +/* Configure VLAN tag strip/insert feature */
> +static int emac_set_features(struct net_device *netdev,
> + netdev_features_t features)
> +{
> + struct emac_adapter *adpt = netdev_priv(netdev);
> +
> + netdev_features_t changed = features ^ netdev->features;
> +
> + if (!(changed & (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX)))
> + return 0;
> +
> + netdev->features = features;
> + if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
> + set_bit(EMAC_STATUS_VLANSTRIP_EN, &adpt->status);
> + else
> + clear_bit(EMAC_STATUS_VLANSTRIP_EN, &adpt->status);
What about TX vlan offload?
[snip]
> +
> +/* Called when the network interface is made active */
> +static int emac_open(struct net_device *netdev)
> +{
> + struct emac_adapter *adpt = netdev_priv(netdev);
> + int ret;
> +
> + netif_carrier_off(netdev);
That seems unnecessary here because your close/down function does that,
and with PHYLIB you would get it set correctly anyway.
[snip]
> +/* PHY related IOCTLs */
> +static int emac_mii_ioctl(struct net_device *netdev,
> + struct ifreq *ifr, int cmd)
> +{
> + struct emac_adapter *adpt = netdev_priv(netdev);
> + struct emac_phy *phy = &adpt->phy;
> + struct mii_ioctl_data *data = if_mii(ifr);
> +
> + switch (cmd) {
> + case SIOCGMIIPHY:
> + data->phy_id = phy->addr;
> + return 0;
> +
> + case SIOCGMIIREG:
> + if (!capable(CAP_NET_ADMIN))
> + return -EPERM;
> +
> + if (data->reg_num & ~(0x1F))
> + return -EFAULT;
> +
> + if (data->phy_id >= PHY_MAX_ADDR)
> + return -EFAULT;
> +
> + if (phy->external && data->phy_id != phy->addr)
> + return -EFAULT;
> +
> + return emac_phy_read(adpt, data->phy_id, data->reg_num,
> + &data->val_out);
> +
> + case SIOCSMIIREG:
> + if (!capable(CAP_NET_ADMIN))
> + return -EPERM;
> +
> + if (data->reg_num & ~(0x1F))
> + return -EFAULT;
> +
> + if (data->phy_id >= PHY_MAX_ADDR)
> + return -EFAULT;
> +
> + if (phy->external && data->phy_id != phy->addr)
> + return -EFAULT;
> +
> + return emac_phy_write(adpt, data->phy_id, data->reg_num,
> + data->val_in);
> + default:
> + return -EFAULT;
> + }
All of that can be eliminated with a PHYLIB implementation too.
[snip]
> +/* Provide network statistics info for the interface */
> +struct rtnl_link_stats64 *emac_get_stats64(struct net_device *netdev,
> + struct rtnl_link_stats64 *net_stats)
> +{
> + struct emac_adapter *adpt = netdev_priv(netdev);
> + struct emac_stats *stats = &adpt->stats;
> + u16 addr = REG_MAC_RX_STATUS_BIN;
> + u64 *stats_itr = &adpt->stats.rx_ok;
> + u32 val;
> +
> + while (addr <= REG_MAC_RX_STATUS_END) {
> + val = readl_relaxed(adpt->base + addr);
> + *stats_itr += val;
> + ++stats_itr;
> + addr += sizeof(u32);
> + }
There is no reader locking here, what happens if two applications read
the statistics at the same time?
[snip]
> +/* Get the resources */
> +static int emac_probe_resources(struct platform_device *pdev,
> + struct emac_adapter *adpt)
> +{
> + struct net_device *netdev = adpt->netdev;
> + struct device_node *node = pdev->dev.of_node;
> + struct resource *res;
> + const void *maddr;
> + int ret = 0;
> + int i;
> +
> + /* get time stamp enable flag */
> + adpt->timestamp_en = of_property_read_bool(node, "qcom,emac-tstamp-en");
> +
> + /* get mac address */
> + maddr = of_get_mac_address(node);
> + if (!maddr)
> + return -ENODEV;
No, generate a random one, continue, but warn,
> +
> + memcpy(adpt->mac_perm_addr, maddr, netdev->addr_len);
> +
> + ret = platform_get_irq_byname(pdev, EMAC_MAC_IRQ_RES);
> + if (ret < 0) {
> + netdev_err(adpt->netdev,
> + "error: missing %s resource\n", EMAC_MAC_IRQ_RES);
> + return ret;
> + }
> + adpt->irq.irq = ret;
> +
> + ret = emac_clks_get(pdev, adpt);
> + if (ret)
> + return ret;
> +
> + /* get register addresses */
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base");
> + if (!res) {
> + netdev_err(adpt->netdev, "error: missing 'base' resource\n");
> + ret = -ENXIO;
> + goto err_reg_res;
> + }
> +
> + adpt->base = devm_ioremap_resource(&pdev->dev, res);
> + if (!adpt->base) {
> + ret = -ENOMEM;
> + goto err_reg_res;
> + }
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr");
> + if (!res) {
> + netdev_err(adpt->netdev, "error: missing 'csr' resource\n");
> + ret = -ENXIO;
> + goto err_reg_res;
> + }
No need to check that, devm_ioremap_resource() does it too.
> +
> + adpt->csr = devm_ioremap_resource(&pdev->dev, res);
> + if (!adpt->csr) {
> + ret = -ENOMEM;
> + goto err_reg_res;
> + }
> +
> + netdev->base_addr = (unsigned long)adpt->base;
> + return 0;
> +
> +err_reg_res:
> + for (i = 0; i < EMAC_CLK_CNT; i++) {
> + if (adpt->clk[i]) {
> + clk_put(adpt->clk[i]);
> + adpt->clk[i] = NULL;
> + }
> + }
> +
> + return ret;
> +}
> +
> +/* Release resources */
> +static void emac_release_resources(struct emac_adapter *adpt)
> +{
> + int i;
> +
> + for (i = 0; i < EMAC_CLK_CNT; i++)
> + if (adpt->clk[i]) {
> + clk_put(adpt->clk[i]);
> + adpt->clk[i] = NULL;
> + }
> +}
> +
> +/* Probe function */
> +static int emac_probe(struct platform_device *pdev)
> +{
> + struct net_device *netdev;
> + struct emac_adapter *adpt;
> + struct emac_phy *phy;
> + int ret = 0;
> + u32 hw_ver;
> + u32 extended_irq_mask = emac_irq_use_extended ? IMR_EXTENDED_MASK :
> + IMR_NORMAL_MASK;
> +
> + netdev = alloc_etherdev(sizeof(struct emac_adapter));
> + if (!netdev)
> + return -ENOMEM;
There are references to multiple queues in the code, so why not
alloc_etherdev_mq() here with the correct number of queues?
> +
> + dev_set_drvdata(&pdev->dev, netdev);
> + SET_NETDEV_DEV(netdev, &pdev->dev);
> +
> + adpt = netdev_priv(netdev);
> + adpt->netdev = netdev;
> + phy = &adpt->phy;
> + adpt->msg_enable = netif_msg_init(debug, EMAC_MSG_DEFAULT);
> +
> + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
Really, is not that supposed to run on ARM64 servers?
--
Florian
^ permalink raw reply
* Re: [PATCH v2 net-next 0/7] DSA refactoring: set 1
From: David Miller @ 2016-04-13 22:15 UTC (permalink / raw)
To: andrew; +Cc: f.fainelli, netdev, vivien.didelot
In-Reply-To: <1460508045-20254-1-git-send-email-andrew@lunn.ch>
From: Andrew Lunn <andrew@lunn.ch>
Date: Wed, 13 Apr 2016 02:40:38 +0200
> There has been a long running effort to refractor DSA probing to make
> the switches true linux devices. Here are a small collection of
> patches moving in this direction. Most have been seen before.
>
> We take a little step forward by passing the dsa device point to the
> driver, thus allowing it to perform resource allocations using the
> normal mechanisms. This device structure will later be replaced by the
> devices own device structure.
>
> Future patches will add a true driver probe function, so we rename the
> current probe function, cleaning up the namespace.
>
> phys_port_mask continually confuses me, thinking it is about PHYs. But
> it is actually about ports enabled to the outside world. So rename it to
> enabled_port_mask.
>
> Lots more patches yet to follow, this is just doing some ground work.
>
> v2:
> enabled_port_mask instread of user_port_masks
> Added Tested-by's and Reviewed-by.
Series applied, thanks.
^ permalink raw reply
* [PATCH] sctp: simplify sk_receive_queue locking
From: Marcelo Ricardo Leitner @ 2016-04-13 22:12 UTC (permalink / raw)
To: netdev; +Cc: linux-sctp, Vlad Yasevich, Neil Horman
SCTP already serializes access to rcvbuf through its sock lock:
sctp_recvmsg takes it right in the start and release at the end, while
rx path will also take the lock before doing any socket processing. On
sctp_rcv() it will check if there is an user using the socket and, if
there is, it will queue incoming packets to the backlog. The backlog
processing will do the same. Even timers will do such check and
re-schedule if an user is using the socket.
Simplifying this will allow us to remove sctp_skb_list_tail and get ride
of some expensive lockings. The lists that it is used on are also
mangled with functions like __skb_queue_tail and __skb_unlink in the
same context, like on sctp_ulpq_tail_event() and sctp_clear_pd().
sctp_close() will also purge those while using only the sock lock.
Therefore the lockings performed by sctp_skb_list_tail() are not
necessary. This patch removes this function and replaces its calls with
just skb_queue_splice_tail_init() instead.
The biggest gain is at sctp_ulpq_tail_event(), because the events always
contain a list, even if it's queueing a single skb and this was
triggering expensive calls to spin_lock_irqsave/_irqrestore for every
data chunk received.
As SCTP will deliver each data chunk on a corresponding recvmsg, the
more effective the change will be.
Before this patch, with chunks with 30 bytes:
netperf -t SCTP_STREAM -H 192.168.1.2 -cC -l 60 -- -m 30 -S 400000
400000 -s 400000 400000
on a 10Gbit link with 1500 MTU:
SCTP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.1.1 () port 0 AF_INET
Recv Send Send Utilization Service Demand
Socket Socket Message Elapsed Send Recv Send Recv
Size Size Size Time Throughput local remote local remote
bytes bytes bytes secs. 10^6bits/s % S % S us/KB us/KB
425984 425984 30 60.00 137.45 7.34 7.36 52.504 52.608
With it:
SCTP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.1.1 () port 0 AF_INET
Recv Send Send Utilization Service Demand
Socket Socket Message Elapsed Send Recv Send Recv
Size Size Size Time Throughput local remote local remote
bytes bytes bytes secs. 10^6bits/s % S % S us/KB us/KB
425984 425984 30 60.00 179.10 7.97 6.70 43.740 36.788
Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
---
Tested doing single and multi-threaded recvmsg()s on a socket flooded
with chunks, varying sizes across tests, all good.
netperf as above also good.
sctp_test too.
include/net/sctp/sctp.h | 15 ---------------
net/sctp/socket.c | 4 +---
net/sctp/ulpqueue.c | 5 +++--
3 files changed, 4 insertions(+), 20 deletions(-)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 03fb33efcae21d54192204629ff4ced2e36e7d4d..978d5f67d5a700aaa6d15d31c7eff62b430b589a 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -359,21 +359,6 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp);
#define sctp_skb_for_each(pos, head, tmp) \
skb_queue_walk_safe(head, pos, tmp)
-/* A helper to append an entire skb list (list) to another (head). */
-static inline void sctp_skb_list_tail(struct sk_buff_head *list,
- struct sk_buff_head *head)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&head->lock, flags);
- spin_lock(&list->lock);
-
- skb_queue_splice_tail_init(list, head);
-
- spin_unlock(&list->lock);
- spin_unlock_irqrestore(&head->lock, flags);
-}
-
/**
* sctp_list_dequeue - remove from the head of the queue
* @list: list to dequeue from
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 36697f85ce48be39f41ddedd9f53369c7f9e28d8..bf265a4bba6e85a31cb9779511c2af9eac077710 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6766,13 +6766,11 @@ struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
* However, this function was correct in any case. 8)
*/
if (flags & MSG_PEEK) {
- spin_lock_bh(&sk->sk_receive_queue.lock);
skb = skb_peek(&sk->sk_receive_queue);
if (skb)
atomic_inc(&skb->users);
- spin_unlock_bh(&sk->sk_receive_queue.lock);
} else {
- skb = skb_dequeue(&sk->sk_receive_queue);
+ skb = __skb_dequeue(&sk->sk_receive_queue);
}
if (skb)
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 72e5b3e41cddf9d79371de8ab01484e4601b97b6..ec12a8920e5fd7a0f26d19f1695bc2feeae41518 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -141,7 +141,8 @@ int sctp_clear_pd(struct sock *sk, struct sctp_association *asoc)
*/
if (!skb_queue_empty(&sp->pd_lobby)) {
struct list_head *list;
- sctp_skb_list_tail(&sp->pd_lobby, &sk->sk_receive_queue);
+ skb_queue_splice_tail_init(&sp->pd_lobby,
+ &sk->sk_receive_queue);
list = (struct list_head *)&sctp_sk(sk)->pd_lobby;
INIT_LIST_HEAD(list);
return 1;
@@ -252,7 +253,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
* collected on a list.
*/
if (skb_list)
- sctp_skb_list_tail(skb_list, queue);
+ skb_queue_splice_tail_init(skb_list, queue);
else
__skb_queue_tail(queue, skb);
--
2.5.0
^ permalink raw reply related
* Re: pull-request: mac80211-next 2016-04-13
From: David Miller @ 2016-04-13 22:01 UTC (permalink / raw)
To: johannes; +Cc: netdev, linux-wireless
In-Reply-To: <1460576192-24712-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes@sipsolutions.net>
Date: Wed, 13 Apr 2016 21:36:31 +0200
> For a while now I've wanted to remove enum ieee80211_band, and in
> order to synchronize more easily with Kalle that's (apart from a
> documentation change I already had pending) all in this pull.
>
> Let me know if there's any problem.
Pulled, thanks Johannes.
^ permalink raw reply
* Re: pull-request: wireless-drivers 2016-04-13
From: David Miller @ 2016-04-13 21:56 UTC (permalink / raw)
To: kvalo-sgV2jX0FEOL9JmXXK+q4OQ
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <87d1pts6zq.fsf-HodKDYzPHsUD5k0oWYwrnHL1okKdlPRT@public.gmane.org>
From: Kalle Valo <kvalo-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Date: Wed, 13 Apr 2016 21:23:21 +0300
> few very small fixes for 4.6. All but one are either build fixes or
> memory leaks. More info in the signed tag below.
>
> Please let me know if there are any problems.
Pulled, thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH for-next V1 1/2] net/mlx5: Fix mlx5 ifc cmd_hca_cap bad offsets
From: Saeed Mahameed @ 2016-04-13 21:54 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Saeed Mahameed, David S. Miller, Doug Ledford, Linux Netdev List,
linux-rdma, Linus Torvalds, Or Gerlitz, Matan Barak,
Leon Romanovsky, Tal Alon, Tariq Toukan
In-Reply-To: <20160413174820.GC28411@obsidianresearch.com>
On Wed, Apr 13, 2016 at 8:48 PM, Jason Gunthorpe
<jgunthorpe@obsidianresearch.com> wrote:
> On Wed, Apr 13, 2016 at 07:11:03PM +0300, Saeed Mahameed wrote:
>
>> Fixes: b0844444590e ("net/mlx5_core: Introduce access function to read internal timer ")
>> Fixes: b4ff3a36d3e4 ("net/mlx5: Use offset based reserved field names in the IFC header file")
>
> Are you sure those are right? b doesn't have the
> reserved_at names.
>
Yes, as stated in the commit message, change b0844444590e replaced two
reserved fields with 3 fields with a different size than the original
two, which broke all the offsets of the fields that came after.
>
> You know, the reserved_XXX just need to have unique unchanging
> numbers, it doesn't matter what the numbers are - but you have to stop
> changing them :( That is the key to avoiding conflicts when
> backporting/merging/etc.
>
> I guess the big rename has already landed, but simply stopping the
> practice of renumbing the reserved fields would have been enough.
>
This was a mistake which had to be fixed, the offset numbering was
wrong from day one of introducing those offsets, I prefer to do it
now, once and forever.
But i totally agree, we will do our best to keep this file clean as
much as possible.
Thanks for your concern.
Saeed.
^ permalink raw reply
* Re: [PATCH net-next 1/1] tipc: remove remnants of old broadcast code
From: David Miller @ 2016-04-13 21:50 UTC (permalink / raw)
To: jon.maloy
Cc: netdev, paul.gortmaker, parthasarathy.bhuvaragan, richard.alpe,
ying.xue, maloy, tipc-discussion
In-Reply-To: <1460562347-26436-1-git-send-email-jon.maloy@ericsson.com>
From: Jon Maloy <jon.maloy@ericsson.com>
Date: Wed, 13 Apr 2016 11:45:47 -0400
> We remove a couple of leftover fields in struct tipc_bearer. Those
> were used by the old broadcast implementation, and are not needed
> any longer. There is no functional changes in this commit.
>
> Acked-by: Ying Xue <ying.xue@windriver.com>
> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Applied, thank you.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox