aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVivien Didelot <vivien.didelot@savoirfairelinux.com>2017-05-01 14:05:11 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-01 15:03:09 -0400
commitbd00e053ae29d3215a9085b5c0add7298bbc417c (patch)
treece7e6950d255419e441765d3c5c1c66507cf861d
parent3cf3c8469f70d18f8bbcdf8361e62812ebc571cd (diff)
net: dsa: mv88e6xxx: split VTU entry data member
VLAN aware Marvell chips can program 802.1Q VLAN membership as well as 802.1s per VLAN Spanning Tree state using the same 3 VTU Data registers. Some chips such as 88E6185 use different Data registers offsets for ports state and membership, and program them in a single operation. Other chips such as 88E6352 use the same register layout but program them in distinct operations (an indirect table is used for 802.1s.) Newer chips such as 88E6390 use the same offsets for both state and membership in distinct operations, thus require multiple data accesses. To correctly abstract this, split the "data" structure member of mv88e6xxx_vtu_entry in two "state" and "member" members, before adding VTU support for newer chips. Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c21
-rw-r--r--drivers/net/dsa/mv88e6xxx/mv88e6xxx.h3
2 files changed, 13 insertions, 11 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index e45ddf3e90e8..f025d3c22dba 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1312,7 +1312,7 @@ static int _mv88e6xxx_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
1312 unsigned int shift = (i % 4) * 4 + nibble_offset; 1312 unsigned int shift = (i % 4) * 4 + nibble_offset;
1313 u16 reg = regs[i / 4]; 1313 u16 reg = regs[i / 4];
1314 1314
1315 entry->data[i] = (reg >> shift) & GLOBAL_VTU_STU_DATA_MASK; 1315 entry->state[i] = (reg >> shift) & GLOBAL_VTU_STU_DATA_MASK;
1316 } 1316 }
1317 1317
1318 return 0; 1318 return 0;
@@ -1339,7 +1339,7 @@ static int _mv88e6xxx_vtu_stu_data_write(struct mv88e6xxx_chip *chip,
1339 1339
1340 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { 1340 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
1341 unsigned int shift = (i % 4) * 4 + nibble_offset; 1341 unsigned int shift = (i % 4) * 4 + nibble_offset;
1342 u8 data = entry->data[i]; 1342 u8 data = entry->state[i];
1343 1343
1344 regs[i / 4] |= (data & GLOBAL_VTU_STU_DATA_MASK) << shift; 1344 regs[i / 4] |= (data & GLOBAL_VTU_STU_DATA_MASK) << shift;
1345 } 1345 }
@@ -1461,7 +1461,7 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
1461 if (!next.valid) 1461 if (!next.valid)
1462 break; 1462 break;
1463 1463
1464 if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) 1464 if (next.member[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
1465 continue; 1465 continue;
1466 1466
1467 /* reinit and dump this VLAN obj */ 1467 /* reinit and dump this VLAN obj */
@@ -1469,7 +1469,7 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
1469 vlan->vid_end = next.vid; 1469 vlan->vid_end = next.vid;
1470 vlan->flags = 0; 1470 vlan->flags = 0;
1471 1471
1472 if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED) 1472 if (next.member[port] == GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED)
1473 vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED; 1473 vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
1474 1474
1475 if (next.vid == pvid) 1475 if (next.vid == pvid)
@@ -1669,7 +1669,8 @@ static int _mv88e6xxx_vtu_new(struct mv88e6xxx_chip *chip, u16 vid,
1669 1669
1670 /* exclude all ports except the CPU and DSA ports */ 1670 /* exclude all ports except the CPU and DSA ports */
1671 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) 1671 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
1672 vlan.data[i] = dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i) 1672 vlan.member[i] = dsa_is_cpu_port(ds, i) ||
1673 dsa_is_dsa_port(ds, i)
1673 ? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED 1674 ? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED
1674 : GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER; 1675 : GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
1675 1676
@@ -1765,7 +1766,7 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
1765 if (!ds->ports[port].netdev) 1766 if (!ds->ports[port].netdev)
1766 continue; 1767 continue;
1767 1768
1768 if (vlan.data[i] == 1769 if (vlan.member[i] ==
1769 GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) 1770 GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
1770 continue; 1771 continue;
1771 1772
@@ -1844,7 +1845,7 @@ static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port,
1844 if (err) 1845 if (err)
1845 return err; 1846 return err;
1846 1847
1847 vlan.data[port] = untagged ? 1848 vlan.member[port] = untagged ?
1848 GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED : 1849 GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED :
1849 GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED; 1850 GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED;
1850 1851
@@ -1890,10 +1891,10 @@ static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,
1890 return err; 1891 return err;
1891 1892
1892 /* Tell switchdev if this VLAN is handled in software */ 1893 /* Tell switchdev if this VLAN is handled in software */
1893 if (vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) 1894 if (vlan.member[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
1894 return -EOPNOTSUPP; 1895 return -EOPNOTSUPP;
1895 1896
1896 vlan.data[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER; 1897 vlan.member[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
1897 1898
1898 /* keep the VLAN unless all ports are excluded */ 1899 /* keep the VLAN unless all ports are excluded */
1899 vlan.valid = false; 1900 vlan.valid = false;
@@ -1901,7 +1902,7 @@ static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,
1901 if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)) 1902 if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
1902 continue; 1903 continue;
1903 1904
1904 if (vlan.data[i] != GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) { 1905 if (vlan.member[i] != GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
1905 vlan.valid = true; 1906 vlan.valid = true;
1906 break; 1907 break;
1907 } 1908 }
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index 5695ca206620..8638892a7e18 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -704,7 +704,8 @@ struct mv88e6xxx_vtu_entry {
704 u16 fid; 704 u16 fid;
705 u8 sid; 705 u8 sid;
706 bool valid; 706 bool valid;
707 u8 data[DSA_MAX_PORTS]; 707 u8 member[DSA_MAX_PORTS];
708 u8 state[DSA_MAX_PORTS];
708}; 709};
709 710
710struct mv88e6xxx_bus_ops; 711struct mv88e6xxx_bus_ops;