Merge branch 'sja1105-fixes'
Vladimir Oltean says: ==================== Fixes for SJA1105 DSA driver This series contains some minor fixes in the sja1105 driver: - improved error handling in the probe path - rejecting an invalid phy-mode specified in the device tree - register access fix for SJA1105P/Q/R/S for the virtual links through the dynamic reconfiguration interface - handling 2 bridge VLANs where the second is supposed to overwrite the first - making sure that the lack of a pvid results in the actual dropping of untagged traffic ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
93c5d741d1
|
@ -167,9 +167,10 @@ enum sja1105_hostcmd {
|
|||
SJA1105_HOSTCMD_INVALIDATE = 4,
|
||||
};
|
||||
|
||||
/* Command and entry overlap */
|
||||
static void
|
||||
sja1105_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
|
||||
enum packing_op op)
|
||||
sja1105et_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
|
||||
enum packing_op op)
|
||||
{
|
||||
const int size = SJA1105_SIZE_DYN_CMD;
|
||||
|
||||
|
@ -179,6 +180,20 @@ sja1105_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
|
|||
sja1105_packing(buf, &cmd->index, 9, 0, size, op);
|
||||
}
|
||||
|
||||
/* Command and entry are separate */
|
||||
static void
|
||||
sja1105pqrs_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
|
||||
enum packing_op op)
|
||||
{
|
||||
u8 *p = buf + SJA1105_SIZE_VL_LOOKUP_ENTRY;
|
||||
const int size = SJA1105_SIZE_DYN_CMD;
|
||||
|
||||
sja1105_packing(p, &cmd->valid, 31, 31, size, op);
|
||||
sja1105_packing(p, &cmd->errors, 30, 30, size, op);
|
||||
sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
|
||||
sja1105_packing(p, &cmd->index, 9, 0, size, op);
|
||||
}
|
||||
|
||||
static size_t sja1105et_vl_lookup_entry_packing(void *buf, void *entry_ptr,
|
||||
enum packing_op op)
|
||||
{
|
||||
|
@ -641,7 +656,7 @@ static size_t sja1105pqrs_cbs_entry_packing(void *buf, void *entry_ptr,
|
|||
const struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
|
||||
[BLK_IDX_VL_LOOKUP] = {
|
||||
.entry_packing = sja1105et_vl_lookup_entry_packing,
|
||||
.cmd_packing = sja1105_vl_lookup_cmd_packing,
|
||||
.cmd_packing = sja1105et_vl_lookup_cmd_packing,
|
||||
.access = OP_WRITE,
|
||||
.max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
|
||||
.packed_size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD,
|
||||
|
@ -725,7 +740,7 @@ const struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
|
|||
const struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = {
|
||||
[BLK_IDX_VL_LOOKUP] = {
|
||||
.entry_packing = sja1105_vl_lookup_entry_packing,
|
||||
.cmd_packing = sja1105_vl_lookup_cmd_packing,
|
||||
.cmd_packing = sja1105pqrs_vl_lookup_cmd_packing,
|
||||
.access = (OP_READ | OP_WRITE),
|
||||
.max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
|
||||
.packed_size = SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "sja1105_tas.h"
|
||||
|
||||
#define SJA1105_UNKNOWN_MULTICAST 0x010000000000ull
|
||||
#define SJA1105_DEFAULT_VLAN (VLAN_N_VID - 1)
|
||||
|
||||
static const struct dsa_switch_ops sja1105_switch_ops;
|
||||
|
||||
|
@ -207,6 +208,7 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv,
|
|||
default:
|
||||
dev_err(dev, "Unsupported PHY mode %s!\n",
|
||||
phy_modes(ports[i].phy_mode));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Even though the SerDes port is able to drive SGMII autoneg
|
||||
|
@ -321,6 +323,13 @@ static int sja1105_init_l2_lookup_params(struct sja1105_private *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Set up a default VLAN for untagged traffic injected from the CPU
|
||||
* using management routes (e.g. STP, PTP) as opposed to tag_8021q.
|
||||
* All DT-defined ports are members of this VLAN, and there are no
|
||||
* restrictions on forwarding (since the CPU selects the destination).
|
||||
* Frames from this VLAN will always be transmitted as untagged, and
|
||||
* neither the bridge nor the 8021q module cannot create this VLAN ID.
|
||||
*/
|
||||
static int sja1105_init_static_vlan(struct sja1105_private *priv)
|
||||
{
|
||||
struct sja1105_table *table;
|
||||
|
@ -330,17 +339,13 @@ static int sja1105_init_static_vlan(struct sja1105_private *priv)
|
|||
.vmemb_port = 0,
|
||||
.vlan_bc = 0,
|
||||
.tag_port = 0,
|
||||
.vlanid = 1,
|
||||
.vlanid = SJA1105_DEFAULT_VLAN,
|
||||
};
|
||||
struct dsa_switch *ds = priv->ds;
|
||||
int port;
|
||||
|
||||
table = &priv->static_config.tables[BLK_IDX_VLAN_LOOKUP];
|
||||
|
||||
/* The static VLAN table will only contain the initial pvid of 1.
|
||||
* All other VLANs are to be configured through dynamic entries,
|
||||
* and kept in the static configuration table as backing memory.
|
||||
*/
|
||||
if (table->entry_count) {
|
||||
kfree(table->entries);
|
||||
table->entry_count = 0;
|
||||
|
@ -353,9 +358,6 @@ static int sja1105_init_static_vlan(struct sja1105_private *priv)
|
|||
|
||||
table->entry_count = 1;
|
||||
|
||||
/* VLAN 1: all DT-defined ports are members; no restrictions on
|
||||
* forwarding; always transmit as untagged.
|
||||
*/
|
||||
for (port = 0; port < ds->num_ports; port++) {
|
||||
struct sja1105_bridge_vlan *v;
|
||||
|
||||
|
@ -366,15 +368,12 @@ static int sja1105_init_static_vlan(struct sja1105_private *priv)
|
|||
pvid.vlan_bc |= BIT(port);
|
||||
pvid.tag_port &= ~BIT(port);
|
||||
|
||||
/* Let traffic that don't need dsa_8021q (e.g. STP, PTP) be
|
||||
* transmitted as untagged.
|
||||
*/
|
||||
v = kzalloc(sizeof(*v), GFP_KERNEL);
|
||||
if (!v)
|
||||
return -ENOMEM;
|
||||
|
||||
v->port = port;
|
||||
v->vid = 1;
|
||||
v->vid = SJA1105_DEFAULT_VLAN;
|
||||
v->untagged = true;
|
||||
if (dsa_is_cpu_port(ds, port))
|
||||
v->pvid = true;
|
||||
|
@ -2817,11 +2816,22 @@ static int sja1105_vlan_add_one(struct dsa_switch *ds, int port, u16 vid,
|
|||
bool pvid = flags & BRIDGE_VLAN_INFO_PVID;
|
||||
struct sja1105_bridge_vlan *v;
|
||||
|
||||
list_for_each_entry(v, vlan_list, list)
|
||||
if (v->port == port && v->vid == vid &&
|
||||
v->untagged == untagged && v->pvid == pvid)
|
||||
list_for_each_entry(v, vlan_list, list) {
|
||||
if (v->port == port && v->vid == vid) {
|
||||
/* Already added */
|
||||
return 0;
|
||||
if (v->untagged == untagged && v->pvid == pvid)
|
||||
/* Nothing changed */
|
||||
return 0;
|
||||
|
||||
/* It's the same VLAN, but some of the flags changed
|
||||
* and the user did not bother to delete it first.
|
||||
* Update it and trigger sja1105_build_vlan_table.
|
||||
*/
|
||||
v->untagged = untagged;
|
||||
v->pvid = pvid;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
v = kzalloc(sizeof(*v), GFP_KERNEL);
|
||||
if (!v) {
|
||||
|
@ -2976,13 +2986,13 @@ static int sja1105_setup(struct dsa_switch *ds)
|
|||
rc = sja1105_static_config_load(priv, ports);
|
||||
if (rc < 0) {
|
||||
dev_err(ds->dev, "Failed to load static config: %d\n", rc);
|
||||
return rc;
|
||||
goto out_ptp_clock_unregister;
|
||||
}
|
||||
/* Configure the CGU (PHY link modes and speeds) */
|
||||
rc = sja1105_clocking_setup(priv);
|
||||
if (rc < 0) {
|
||||
dev_err(ds->dev, "Failed to configure MII clocking: %d\n", rc);
|
||||
return rc;
|
||||
goto out_static_config_free;
|
||||
}
|
||||
/* On SJA1105, VLAN filtering per se is always enabled in hardware.
|
||||
* The only thing we can do to disable it is lie about what the 802.1Q
|
||||
|
@ -3003,7 +3013,7 @@ static int sja1105_setup(struct dsa_switch *ds)
|
|||
|
||||
rc = sja1105_devlink_setup(ds);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
goto out_static_config_free;
|
||||
|
||||
/* The DSA/switchdev model brings up switch ports in standalone mode by
|
||||
* default, and that means vlan_filtering is 0 since they're not under
|
||||
|
@ -3012,6 +3022,17 @@ static int sja1105_setup(struct dsa_switch *ds)
|
|||
rtnl_lock();
|
||||
rc = sja1105_setup_8021q_tagging(ds, true);
|
||||
rtnl_unlock();
|
||||
if (rc)
|
||||
goto out_devlink_teardown;
|
||||
|
||||
return 0;
|
||||
|
||||
out_devlink_teardown:
|
||||
sja1105_devlink_teardown(ds);
|
||||
out_ptp_clock_unregister:
|
||||
sja1105_ptp_clock_unregister(ds);
|
||||
out_static_config_free:
|
||||
sja1105_static_config_free(&priv->static_config);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -3646,8 +3667,10 @@ static int sja1105_probe(struct spi_device *spi)
|
|||
priv->cbs = devm_kcalloc(dev, priv->info->num_cbs_shapers,
|
||||
sizeof(struct sja1105_cbs_entry),
|
||||
GFP_KERNEL);
|
||||
if (!priv->cbs)
|
||||
return -ENOMEM;
|
||||
if (!priv->cbs) {
|
||||
rc = -ENOMEM;
|
||||
goto out_unregister_switch;
|
||||
}
|
||||
}
|
||||
|
||||
/* Connections between dsa_port and sja1105_port */
|
||||
|
@ -3672,7 +3695,7 @@ static int sja1105_probe(struct spi_device *spi)
|
|||
dev_err(ds->dev,
|
||||
"failed to create deferred xmit thread: %d\n",
|
||||
rc);
|
||||
goto out;
|
||||
goto out_destroy_workers;
|
||||
}
|
||||
skb_queue_head_init(&sp->xmit_queue);
|
||||
sp->xmit_tpid = ETH_P_SJA1105;
|
||||
|
@ -3682,7 +3705,8 @@ static int sja1105_probe(struct spi_device *spi)
|
|||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
|
||||
out_destroy_workers:
|
||||
while (port-- > 0) {
|
||||
struct sja1105_port *sp = &priv->ports[port];
|
||||
|
||||
|
@ -3691,6 +3715,10 @@ out:
|
|||
|
||||
kthread_destroy_worker(sp->xmit_worker);
|
||||
}
|
||||
|
||||
out_unregister_switch:
|
||||
dsa_unregister_switch(ds);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче