aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-03-01 16:24:54 -0500
committerDavid S. Miller <davem@davemloft.net>2016-03-01 16:24:54 -0500
commitec1606c0906de35dbc6f21aea75c2b950104cae5 (patch)
tree923ad677a36f4dae005e1f52c1973456fe2b23a9
parent7f66ee41566d00f80ed15c0cec0b237f7af8ac0f (diff)
parent214cdb998739428b09d80b4b152faa7d1e6ad156 (diff)
Merge branch 'mv88e6xxx-vlan-filtering'
Vivien Didelot says: ==================== net: dsa: mv88e6xxx: implement VLAN filtering This patchset fixes hardware bridging for non 802.1Q aware systems. The mv88e6xxx DSA driver currently depends on CONFIG_VLAN_8021Q and CONFIG_BRIDGE_VLAN_FILTERING enabled for correct bridging between switch ports. Patch 1/9 adds support for the VLAN filtering switchdev attribute in DSA. Patchs 2/9 and 3/9 add helper functions for the following patches. Patchs 4/9 to 6/9 assign dynamic address databases to VLANs, ports, and bridge groups (the lowest available FID is cleared and assigned), and thus restore support for per-port FDB operations. Patchs 7/9 to 9/9 refine ports isolation and setup 802.1Q on user demand. With this patchset, ports get correctly bridged and the driver behaves as expected, with or without 802.1Q support. With CONFIG_VLAN_8021Q enabled, setting a default PVID to the bridge correctly propagates the corresponding VLAN, in addition to the hardware bridging: # echo 42 > /sys/class/net/<bridge>/bridge/default_pvid But considering CONFIG_BRIDGE_VLAN_FILTERING enabled, the hardware VLAN filtering is enabled on all bridge members only when the user requests it: # echo 1 > /sys/class/net/<bridge>/bridge/vlan_filtering ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/dsa/mv88e6171.c1
-rw-r--r--drivers/net/dsa/mv88e6352.c1
-rw-r--r--drivers/net/dsa/mv88e6xxx.c441
-rw-r--r--drivers/net/dsa/mv88e6xxx.h6
-rw-r--r--include/net/dsa.h2
-rw-r--r--net/dsa/slave.c21
6 files changed, 370 insertions, 102 deletions
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index dd1ebaf48077..d72ccbdf53ec 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -106,6 +106,7 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
106 .port_join_bridge = mv88e6xxx_port_bridge_join, 106 .port_join_bridge = mv88e6xxx_port_bridge_join,
107 .port_leave_bridge = mv88e6xxx_port_bridge_leave, 107 .port_leave_bridge = mv88e6xxx_port_bridge_leave,
108 .port_stp_update = mv88e6xxx_port_stp_update, 108 .port_stp_update = mv88e6xxx_port_stp_update,
109 .port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
109 .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, 110 .port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
110 .port_vlan_add = mv88e6xxx_port_vlan_add, 111 .port_vlan_add = mv88e6xxx_port_vlan_add,
111 .port_vlan_del = mv88e6xxx_port_vlan_del, 112 .port_vlan_del = mv88e6xxx_port_vlan_del,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index bbca36ac4f77..a41fa5043d77 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -327,6 +327,7 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
327 .port_join_bridge = mv88e6xxx_port_bridge_join, 327 .port_join_bridge = mv88e6xxx_port_bridge_join,
328 .port_leave_bridge = mv88e6xxx_port_bridge_leave, 328 .port_leave_bridge = mv88e6xxx_port_bridge_leave,
329 .port_stp_update = mv88e6xxx_port_stp_update, 329 .port_stp_update = mv88e6xxx_port_stp_update,
330 .port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
330 .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, 331 .port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
331 .port_vlan_add = mv88e6xxx_port_vlan_add, 332 .port_vlan_add = mv88e6xxx_port_vlan_add,
332 .port_vlan_del = mv88e6xxx_port_vlan_del, 333 .port_vlan_del = mv88e6xxx_port_vlan_del,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index d98dc635b00b..d11c9d58cf10 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1087,12 +1087,32 @@ abort:
1087 return ret; 1087 return ret;
1088} 1088}
1089 1089
1090static int _mv88e6xxx_port_vlan_map_set(struct dsa_switch *ds, int port, 1090static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port)
1091 u16 output_ports)
1092{ 1091{
1093 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 1092 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1093 struct net_device *bridge = ps->ports[port].bridge_dev;
1094 const u16 mask = (1 << ps->num_ports) - 1; 1094 const u16 mask = (1 << ps->num_ports) - 1;
1095 u16 output_ports = 0;
1095 int reg; 1096 int reg;
1097 int i;
1098
1099 /* allow CPU port or DSA link(s) to send frames to every port */
1100 if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
1101 output_ports = mask;
1102 } else {
1103 for (i = 0; i < ps->num_ports; ++i) {
1104 /* allow sending frames to every group member */
1105 if (bridge && ps->ports[i].bridge_dev == bridge)
1106 output_ports |= BIT(i);
1107
1108 /* allow sending frames to CPU port and DSA link(s) */
1109 if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
1110 output_ports |= BIT(i);
1111 }
1112 }
1113
1114 /* prevent frames from going back out of the port they came in on */
1115 output_ports &= ~BIT(port);
1096 1116
1097 reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN); 1117 reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN);
1098 if (reg < 0) 1118 if (reg < 0)
@@ -1458,16 +1478,122 @@ loadpurge:
1458 return _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_STU_LOAD_PURGE); 1478 return _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_STU_LOAD_PURGE);
1459} 1479}
1460 1480
1461static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid, 1481static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new,
1462 struct mv88e6xxx_vtu_stu_entry *entry) 1482 u16 *old)
1483{
1484 u16 fid;
1485 int ret;
1486
1487 /* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */
1488 ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN);
1489 if (ret < 0)
1490 return ret;
1491
1492 fid = (ret & PORT_BASE_VLAN_FID_3_0_MASK) >> 12;
1493
1494 if (new) {
1495 ret &= ~PORT_BASE_VLAN_FID_3_0_MASK;
1496 ret |= (*new << 12) & PORT_BASE_VLAN_FID_3_0_MASK;
1497
1498 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN,
1499 ret);
1500 if (ret < 0)
1501 return ret;
1502 }
1503
1504 /* Port's default FID bits 11:4 are located in reg 0x05, offset 0 */
1505 ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL_1);
1506 if (ret < 0)
1507 return ret;
1508
1509 fid |= (ret & PORT_CONTROL_1_FID_11_4_MASK) << 4;
1510
1511 if (new) {
1512 ret &= ~PORT_CONTROL_1_FID_11_4_MASK;
1513 ret |= (*new >> 4) & PORT_CONTROL_1_FID_11_4_MASK;
1514
1515 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_1,
1516 ret);
1517 if (ret < 0)
1518 return ret;
1519
1520 netdev_dbg(ds->ports[port], "FID %d (was %d)\n", *new, fid);
1521 }
1522
1523 if (old)
1524 *old = fid;
1525
1526 return 0;
1527}
1528
1529static int _mv88e6xxx_port_fid_get(struct dsa_switch *ds, int port, u16 *fid)
1530{
1531 return _mv88e6xxx_port_fid(ds, port, NULL, fid);
1532}
1533
1534static int _mv88e6xxx_port_fid_set(struct dsa_switch *ds, int port, u16 fid)
1535{
1536 return _mv88e6xxx_port_fid(ds, port, &fid, NULL);
1537}
1538
1539static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
1540{
1541 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1542 DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
1543 struct mv88e6xxx_vtu_stu_entry vlan;
1544 int i, err;
1545
1546 bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
1547
1548 /* Set every FID bit used by the (un)bridged ports */
1549 for (i = 0; i < ps->num_ports; ++i) {
1550 err = _mv88e6xxx_port_fid_get(ds, i, fid);
1551 if (err)
1552 return err;
1553
1554 set_bit(*fid, fid_bitmap);
1555 }
1556
1557 /* Set every FID bit used by the VLAN entries */
1558 err = _mv88e6xxx_vtu_vid_write(ds, GLOBAL_VTU_VID_MASK);
1559 if (err)
1560 return err;
1561
1562 do {
1563 err = _mv88e6xxx_vtu_getnext(ds, &vlan);
1564 if (err)
1565 return err;
1566
1567 if (!vlan.valid)
1568 break;
1569
1570 set_bit(vlan.fid, fid_bitmap);
1571 } while (vlan.vid < GLOBAL_VTU_VID_MASK);
1572
1573 /* The reset value 0x000 is used to indicate that multiple address
1574 * databases are not needed. Return the next positive available.
1575 */
1576 *fid = find_next_zero_bit(fid_bitmap, MV88E6XXX_N_FID, 1);
1577 if (unlikely(*fid == MV88E6XXX_N_FID))
1578 return -ENOSPC;
1579
1580 /* Clear the database */
1581 return _mv88e6xxx_atu_flush(ds, *fid, true);
1582}
1583
1584static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid,
1585 struct mv88e6xxx_vtu_stu_entry *entry)
1463{ 1586{
1464 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 1587 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1465 struct mv88e6xxx_vtu_stu_entry vlan = { 1588 struct mv88e6xxx_vtu_stu_entry vlan = {
1466 .valid = true, 1589 .valid = true,
1467 .vid = vid, 1590 .vid = vid,
1468 .fid = vid, /* We use one FID per VLAN */
1469 }; 1591 };
1470 int i; 1592 int i, err;
1593
1594 err = _mv88e6xxx_fid_new(ds, &vlan.fid);
1595 if (err)
1596 return err;
1471 1597
1472 /* exclude all ports except the CPU and DSA ports */ 1598 /* exclude all ports except the CPU and DSA ports */
1473 for (i = 0; i < ps->num_ports; ++i) 1599 for (i = 0; i < ps->num_ports; ++i)
@@ -1478,7 +1604,6 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid,
1478 if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || 1604 if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) ||
1479 mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) { 1605 mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) {
1480 struct mv88e6xxx_vtu_stu_entry vstp; 1606 struct mv88e6xxx_vtu_stu_entry vstp;
1481 int err;
1482 1607
1483 /* Adding a VTU entry requires a valid STU entry. As VSTP is not 1608 /* Adding a VTU entry requires a valid STU entry. As VSTP is not
1484 * implemented, only one STU entry is needed to cover all VTU 1609 * implemented, only one STU entry is needed to cover all VTU
@@ -1498,17 +1623,41 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid,
1498 if (err) 1623 if (err)
1499 return err; 1624 return err;
1500 } 1625 }
1501
1502 /* Clear all MAC addresses from the new database */
1503 err = _mv88e6xxx_atu_flush(ds, vlan.fid, true);
1504 if (err)
1505 return err;
1506 } 1626 }
1507 1627
1508 *entry = vlan; 1628 *entry = vlan;
1509 return 0; 1629 return 0;
1510} 1630}
1511 1631
1632static int _mv88e6xxx_vtu_get(struct dsa_switch *ds, u16 vid,
1633 struct mv88e6xxx_vtu_stu_entry *entry, bool creat)
1634{
1635 int err;
1636
1637 if (!vid)
1638 return -EINVAL;
1639
1640 err = _mv88e6xxx_vtu_vid_write(ds, vid - 1);
1641 if (err)
1642 return err;
1643
1644 err = _mv88e6xxx_vtu_getnext(ds, entry);
1645 if (err)
1646 return err;
1647
1648 if (entry->vid != vid || !entry->valid) {
1649 if (!creat)
1650 return -EOPNOTSUPP;
1651 /* -ENOENT would've been more appropriate, but switchdev expects
1652 * -EOPNOTSUPP to inform bridge about an eventual software VLAN.
1653 */
1654
1655 err = _mv88e6xxx_vtu_new(ds, vid, entry);
1656 }
1657
1658 return err;
1659}
1660
1512static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, 1661static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
1513 u16 vid_begin, u16 vid_end) 1662 u16 vid_begin, u16 vid_end)
1514{ 1663{
@@ -1563,16 +1712,51 @@ unlock:
1563 return err; 1712 return err;
1564} 1713}
1565 1714
1715static const char * const mv88e6xxx_port_8021q_mode_names[] = {
1716 [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled",
1717 [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback",
1718 [PORT_CONTROL_2_8021Q_CHECK] = "Check",
1719 [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
1720};
1721
1722int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
1723 bool vlan_filtering)
1724{
1725 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1726 u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE :
1727 PORT_CONTROL_2_8021Q_DISABLED;
1728 int ret;
1729
1730 mutex_lock(&ps->smi_mutex);
1731
1732 ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL_2);
1733 if (ret < 0)
1734 goto unlock;
1735
1736 old = ret & PORT_CONTROL_2_8021Q_MASK;
1737
1738 ret &= ~PORT_CONTROL_2_8021Q_MASK;
1739 ret |= new & PORT_CONTROL_2_8021Q_MASK;
1740
1741 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_2, ret);
1742 if (ret < 0)
1743 goto unlock;
1744
1745 netdev_dbg(ds->ports[port], "802.1Q Mode: %s (was %s)\n",
1746 mv88e6xxx_port_8021q_mode_names[new],
1747 mv88e6xxx_port_8021q_mode_names[old]);
1748unlock:
1749 mutex_unlock(&ps->smi_mutex);
1750
1751 return ret;
1752}
1753
1566int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, 1754int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
1567 const struct switchdev_obj_port_vlan *vlan, 1755 const struct switchdev_obj_port_vlan *vlan,
1568 struct switchdev_trans *trans) 1756 struct switchdev_trans *trans)
1569{ 1757{
1570 int err; 1758 int err;
1571 1759
1572 /* We reserve a few VLANs to isolate unbridged ports */
1573 if (vlan->vid_end >= 4000)
1574 return -EOPNOTSUPP;
1575
1576 /* If the requested port doesn't belong to the same bridge as the VLAN 1760 /* If the requested port doesn't belong to the same bridge as the VLAN
1577 * members, do not support it (yet) and fallback to software VLAN. 1761 * members, do not support it (yet) and fallback to software VLAN.
1578 */ 1762 */
@@ -1593,20 +1777,10 @@ static int _mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid,
1593 struct mv88e6xxx_vtu_stu_entry vlan; 1777 struct mv88e6xxx_vtu_stu_entry vlan;
1594 int err; 1778 int err;
1595 1779
1596 err = _mv88e6xxx_vtu_vid_write(ds, vid - 1); 1780 err = _mv88e6xxx_vtu_get(ds, vid, &vlan, true);
1597 if (err)
1598 return err;
1599
1600 err = _mv88e6xxx_vtu_getnext(ds, &vlan);
1601 if (err) 1781 if (err)
1602 return err; 1782 return err;
1603 1783
1604 if (vlan.vid != vid || !vlan.valid) {
1605 err = _mv88e6xxx_vlan_init(ds, vid, &vlan);
1606 if (err)
1607 return err;
1608 }
1609
1610 vlan.data[port] = untagged ? 1784 vlan.data[port] = untagged ?
1611 GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED : 1785 GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED :
1612 GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED; 1786 GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED;
@@ -1647,16 +1821,12 @@ static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
1647 struct mv88e6xxx_vtu_stu_entry vlan; 1821 struct mv88e6xxx_vtu_stu_entry vlan;
1648 int i, err; 1822 int i, err;
1649 1823
1650 err = _mv88e6xxx_vtu_vid_write(ds, vid - 1); 1824 err = _mv88e6xxx_vtu_get(ds, vid, &vlan, false);
1651 if (err) 1825 if (err)
1652 return err; 1826 return err;
1653 1827
1654 err = _mv88e6xxx_vtu_getnext(ds, &vlan); 1828 /* Tell switchdev if this VLAN is handled in software */
1655 if (err) 1829 if (vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
1656 return err;
1657
1658 if (vlan.vid != vid || !vlan.valid ||
1659 vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
1660 return -EOPNOTSUPP; 1830 return -EOPNOTSUPP;
1661 1831
1662 vlan.data[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER; 1832 vlan.data[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
@@ -1684,7 +1854,6 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
1684 const struct switchdev_obj_port_vlan *vlan) 1854 const struct switchdev_obj_port_vlan *vlan)
1685{ 1855{
1686 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 1856 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1687 const u16 defpvid = 4000 + ds->index * DSA_MAX_PORTS + port;
1688 u16 pvid, vid; 1857 u16 pvid, vid;
1689 int err = 0; 1858 int err = 0;
1690 1859
@@ -1700,8 +1869,7 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
1700 goto unlock; 1869 goto unlock;
1701 1870
1702 if (vid == pvid) { 1871 if (vid == pvid) {
1703 /* restore reserved VLAN ID */ 1872 err = _mv88e6xxx_port_pvid_set(ds, port, 0);
1704 err = _mv88e6xxx_port_pvid_set(ds, port, defpvid);
1705 if (err) 1873 if (err)
1706 goto unlock; 1874 goto unlock;
1707 } 1875 }
@@ -1774,8 +1942,18 @@ static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port,
1774 u8 state) 1942 u8 state)
1775{ 1943{
1776 struct mv88e6xxx_atu_entry entry = { 0 }; 1944 struct mv88e6xxx_atu_entry entry = { 0 };
1945 struct mv88e6xxx_vtu_stu_entry vlan;
1946 int err;
1777 1947
1778 entry.fid = vid; /* We use one FID per VLAN */ 1948 /* Null VLAN ID corresponds to the port private database */
1949 if (vid == 0)
1950 err = _mv88e6xxx_port_fid_get(ds, port, &vlan.fid);
1951 else
1952 err = _mv88e6xxx_vtu_get(ds, vid, &vlan, false);
1953 if (err)
1954 return err;
1955
1956 entry.fid = vlan.fid;
1779 entry.state = state; 1957 entry.state = state;
1780 ether_addr_copy(entry.mac, addr); 1958 ether_addr_copy(entry.mac, addr);
1781 if (state != GLOBAL_ATU_DATA_STATE_UNUSED) { 1959 if (state != GLOBAL_ATU_DATA_STATE_UNUSED) {
@@ -1790,10 +1968,6 @@ int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
1790 const struct switchdev_obj_port_fdb *fdb, 1968 const struct switchdev_obj_port_fdb *fdb,
1791 struct switchdev_trans *trans) 1969 struct switchdev_trans *trans)
1792{ 1970{
1793 /* We don't use per-port FDB */
1794 if (fdb->vid == 0)
1795 return -EOPNOTSUPP;
1796
1797 /* We don't need any dynamic resource from the kernel (yet), 1971 /* We don't need any dynamic resource from the kernel (yet),
1798 * so skip the prepare phase. 1972 * so skip the prepare phase.
1799 */ 1973 */
@@ -1880,6 +2054,47 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid,
1880 return 0; 2054 return 0;
1881} 2055}
1882 2056
2057static int _mv88e6xxx_port_fdb_dump_one(struct dsa_switch *ds, u16 fid, u16 vid,
2058 int port,
2059 struct switchdev_obj_port_fdb *fdb,
2060 int (*cb)(struct switchdev_obj *obj))
2061{
2062 struct mv88e6xxx_atu_entry addr = {
2063 .mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
2064 };
2065 int err;
2066
2067 err = _mv88e6xxx_atu_mac_write(ds, addr.mac);
2068 if (err)
2069 return err;
2070
2071 do {
2072 err = _mv88e6xxx_atu_getnext(ds, fid, &addr);
2073 if (err)
2074 break;
2075
2076 if (addr.state == GLOBAL_ATU_DATA_STATE_UNUSED)
2077 break;
2078
2079 if (!addr.trunk && addr.portv_trunkid & BIT(port)) {
2080 bool is_static = addr.state ==
2081 (is_multicast_ether_addr(addr.mac) ?
2082 GLOBAL_ATU_DATA_STATE_MC_STATIC :
2083 GLOBAL_ATU_DATA_STATE_UC_STATIC);
2084
2085 fdb->vid = vid;
2086 ether_addr_copy(fdb->addr, addr.mac);
2087 fdb->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
2088
2089 err = cb(&fdb->obj);
2090 if (err)
2091 break;
2092 }
2093 } while (!is_broadcast_ether_addr(addr.mac));
2094
2095 return err;
2096}
2097
1883int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, 2098int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
1884 struct switchdev_obj_port_fdb *fdb, 2099 struct switchdev_obj_port_fdb *fdb,
1885 int (*cb)(struct switchdev_obj *obj)) 2100 int (*cb)(struct switchdev_obj *obj))
@@ -1888,55 +2103,37 @@ int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
1888 struct mv88e6xxx_vtu_stu_entry vlan = { 2103 struct mv88e6xxx_vtu_stu_entry vlan = {
1889 .vid = GLOBAL_VTU_VID_MASK, /* all ones */ 2104 .vid = GLOBAL_VTU_VID_MASK, /* all ones */
1890 }; 2105 };
2106 u16 fid;
1891 int err; 2107 int err;
1892 2108
1893 mutex_lock(&ps->smi_mutex); 2109 mutex_lock(&ps->smi_mutex);
1894 2110
2111 /* Dump port's default Filtering Information Database (VLAN ID 0) */
2112 err = _mv88e6xxx_port_fid_get(ds, port, &fid);
2113 if (err)
2114 goto unlock;
2115
2116 err = _mv88e6xxx_port_fdb_dump_one(ds, fid, 0, port, fdb, cb);
2117 if (err)
2118 goto unlock;
2119
2120 /* Dump VLANs' Filtering Information Databases */
1895 err = _mv88e6xxx_vtu_vid_write(ds, vlan.vid); 2121 err = _mv88e6xxx_vtu_vid_write(ds, vlan.vid);
1896 if (err) 2122 if (err)
1897 goto unlock; 2123 goto unlock;
1898 2124
1899 do { 2125 do {
1900 struct mv88e6xxx_atu_entry addr = {
1901 .mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
1902 };
1903
1904 err = _mv88e6xxx_vtu_getnext(ds, &vlan); 2126 err = _mv88e6xxx_vtu_getnext(ds, &vlan);
1905 if (err) 2127 if (err)
1906 goto unlock; 2128 break;
1907 2129
1908 if (!vlan.valid) 2130 if (!vlan.valid)
1909 break; 2131 break;
1910 2132
1911 err = _mv88e6xxx_atu_mac_write(ds, addr.mac); 2133 err = _mv88e6xxx_port_fdb_dump_one(ds, vlan.fid, vlan.vid, port,
2134 fdb, cb);
1912 if (err) 2135 if (err)
1913 goto unlock; 2136 break;
1914
1915 do {
1916 err = _mv88e6xxx_atu_getnext(ds, vlan.fid, &addr);
1917 if (err)
1918 goto unlock;
1919
1920 if (addr.state == GLOBAL_ATU_DATA_STATE_UNUSED)
1921 break;
1922
1923 if (!addr.trunk && addr.portv_trunkid & BIT(port)) {
1924 bool is_static = addr.state ==
1925 (is_multicast_ether_addr(addr.mac) ?
1926 GLOBAL_ATU_DATA_STATE_MC_STATIC :
1927 GLOBAL_ATU_DATA_STATE_UC_STATIC);
1928
1929 fdb->vid = vlan.vid;
1930 ether_addr_copy(fdb->addr, addr.mac);
1931 fdb->ndm_state = is_static ? NUD_NOARP :
1932 NUD_REACHABLE;
1933
1934 err = cb(&fdb->obj);
1935 if (err)
1936 goto unlock;
1937 }
1938 } while (!is_broadcast_ether_addr(addr.mac));
1939
1940 } while (vlan.vid < GLOBAL_VTU_VID_MASK); 2137 } while (vlan.vid < GLOBAL_VTU_VID_MASK);
1941 2138
1942unlock: 2139unlock:
@@ -1949,32 +2146,76 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
1949 struct net_device *bridge) 2146 struct net_device *bridge)
1950{ 2147{
1951 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 2148 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2149 u16 fid;
2150 int i, err;
2151
2152 mutex_lock(&ps->smi_mutex);
2153
2154 /* Get or create the bridge FID and assign it to the port */
2155 for (i = 0; i < ps->num_ports; ++i)
2156 if (ps->ports[i].bridge_dev == bridge)
2157 break;
2158
2159 if (i < ps->num_ports)
2160 err = _mv88e6xxx_port_fid_get(ds, i, &fid);
2161 else
2162 err = _mv88e6xxx_fid_new(ds, &fid);
2163 if (err)
2164 goto unlock;
2165
2166 err = _mv88e6xxx_port_fid_set(ds, port, fid);
2167 if (err)
2168 goto unlock;
1952 2169
2170 /* Assign the bridge and remap each port's VLANTable */
1953 ps->ports[port].bridge_dev = bridge; 2171 ps->ports[port].bridge_dev = bridge;
1954 2172
1955 return 0; 2173 for (i = 0; i < ps->num_ports; ++i) {
2174 if (ps->ports[i].bridge_dev == bridge) {
2175 err = _mv88e6xxx_port_based_vlan_map(ds, i);
2176 if (err)
2177 break;
2178 }
2179 }
2180
2181unlock:
2182 mutex_unlock(&ps->smi_mutex);
2183
2184 return err;
1956} 2185}
1957 2186
1958int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port) 2187int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
1959{ 2188{
1960 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 2189 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2190 struct net_device *bridge = ps->ports[port].bridge_dev;
2191 u16 fid;
2192 int i, err;
1961 2193
1962 ps->ports[port].bridge_dev = NULL; 2194 mutex_lock(&ps->smi_mutex);
1963 2195
1964 return 0; 2196 /* Give the port a fresh Filtering Information Database */
1965} 2197 err = _mv88e6xxx_fid_new(ds, &fid);
2198 if (err)
2199 goto unlock;
1966 2200
1967static int mv88e6xxx_setup_port_default_vlan(struct dsa_switch *ds, int port) 2201 err = _mv88e6xxx_port_fid_set(ds, port, fid);
1968{ 2202 if (err)
1969 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 2203 goto unlock;
1970 const u16 pvid = 4000 + ds->index * DSA_MAX_PORTS + port;
1971 int err;
1972 2204
1973 mutex_lock(&ps->smi_mutex); 2205 /* Unassign the bridge and remap each port's VLANTable */
1974 err = _mv88e6xxx_port_vlan_add(ds, port, pvid, true); 2206 ps->ports[port].bridge_dev = NULL;
1975 if (!err) 2207
1976 err = _mv88e6xxx_port_pvid_set(ds, port, pvid); 2208 for (i = 0; i < ps->num_ports; ++i) {
2209 if (i == port || ps->ports[i].bridge_dev == bridge) {
2210 err = _mv88e6xxx_port_based_vlan_map(ds, i);
2211 if (err)
2212 break;
2213 }
2214 }
2215
2216unlock:
1977 mutex_unlock(&ps->smi_mutex); 2217 mutex_unlock(&ps->smi_mutex);
2218
1978 return err; 2219 return err;
1979} 2220}
1980 2221
@@ -2098,7 +2339,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
2098 } 2339 }
2099 2340
2100 /* Port Control 2: don't force a good FCS, set the maximum frame size to 2341 /* Port Control 2: don't force a good FCS, set the maximum frame size to
2101 * 10240 bytes, enable secure 802.1q tags, don't discard tagged or 2342 * 10240 bytes, disable 802.1q tags checking, don't discard tagged or
2102 * untagged frames on this port, do a destination address lookup on all 2343 * untagged frames on this port, do a destination address lookup on all
2103 * received packets as usual, disable ARP mirroring and don't send a 2344 * received packets as usual, disable ARP mirroring and don't send a
2104 * copy of all transmitted/received frames on this port to the CPU. 2345 * copy of all transmitted/received frames on this port to the CPU.
@@ -2123,7 +2364,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
2123 reg |= PORT_CONTROL_2_FORWARD_UNKNOWN; 2364 reg |= PORT_CONTROL_2_FORWARD_UNKNOWN;
2124 } 2365 }
2125 2366
2126 reg |= PORT_CONTROL_2_8021Q_SECURE; 2367 reg |= PORT_CONTROL_2_8021Q_DISABLED;
2127 2368
2128 if (reg) { 2369 if (reg) {
2129 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 2370 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
@@ -2220,12 +2461,15 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
2220 if (ret) 2461 if (ret)
2221 goto abort; 2462 goto abort;
2222 2463
2223 /* Port based VLAN map: do not give each port its own address 2464 /* Port based VLAN map: give each port its own address
2224 * database, and allow every port to egress frames on all other ports. 2465 * database, and allow bidirectional communication between the
2466 * CPU and DSA port(s), and the other ports.
2225 */ 2467 */
2226 reg = BIT(ps->num_ports) - 1; /* all ports */ 2468 ret = _mv88e6xxx_port_fid_set(ds, port, port + 1);
2227 reg &= ~BIT(port); /* except itself */ 2469 if (ret)
2228 ret = _mv88e6xxx_port_vlan_map_set(ds, port, reg); 2470 goto abort;
2471
2472 ret = _mv88e6xxx_port_based_vlan_map(ds, port);
2229 if (ret) 2473 if (ret)
2230 goto abort; 2474 goto abort;
2231 2475
@@ -2249,13 +2493,6 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
2249 ret = mv88e6xxx_setup_port(ds, i); 2493 ret = mv88e6xxx_setup_port(ds, i);
2250 if (ret < 0) 2494 if (ret < 0)
2251 return ret; 2495 return ret;
2252
2253 if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
2254 continue;
2255
2256 ret = mv88e6xxx_setup_port_default_vlan(ds, i);
2257 if (ret < 0)
2258 return ret;
2259 } 2496 }
2260 return 0; 2497 return 0;
2261} 2498}
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 6a30bda63a2f..d7b088dd8e16 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -133,7 +133,9 @@
133#define PORT_CONTROL_STATE_LEARNING 0x02 133#define PORT_CONTROL_STATE_LEARNING 0x02
134#define PORT_CONTROL_STATE_FORWARDING 0x03 134#define PORT_CONTROL_STATE_FORWARDING 0x03
135#define PORT_CONTROL_1 0x05 135#define PORT_CONTROL_1 0x05
136#define PORT_CONTROL_1_FID_11_4_MASK (0xff << 0)
136#define PORT_BASE_VLAN 0x06 137#define PORT_BASE_VLAN 0x06
138#define PORT_BASE_VLAN_FID_3_0_MASK (0xf << 12)
137#define PORT_DEFAULT_VLAN 0x07 139#define PORT_DEFAULT_VLAN 0x07
138#define PORT_DEFAULT_VLAN_MASK 0xfff 140#define PORT_DEFAULT_VLAN_MASK 0xfff
139#define PORT_CONTROL_2 0x08 141#define PORT_CONTROL_2 0x08
@@ -355,6 +357,8 @@
355#define GLOBAL2_QOS_WEIGHT 0x1c 357#define GLOBAL2_QOS_WEIGHT 0x1c
356#define GLOBAL2_MISC 0x1d 358#define GLOBAL2_MISC 0x1d
357 359
360#define MV88E6XXX_N_FID 4096
361
358struct mv88e6xxx_switch_id { 362struct mv88e6xxx_switch_id {
359 u16 id; 363 u16 id;
360 char *name; 364 char *name;
@@ -486,6 +490,8 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
486 struct net_device *bridge); 490 struct net_device *bridge);
487int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port); 491int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port);
488int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state); 492int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state);
493int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
494 bool vlan_filtering);
489int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, 495int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
490 const struct switchdev_obj_port_vlan *vlan, 496 const struct switchdev_obj_port_vlan *vlan,
491 struct switchdev_trans *trans); 497 struct switchdev_trans *trans);
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 3dd54867174a..26c0a3fa009a 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -305,6 +305,8 @@ struct dsa_switch_driver {
305 /* 305 /*
306 * VLAN support 306 * VLAN support
307 */ 307 */
308 int (*port_vlan_filtering)(struct dsa_switch *ds, int port,
309 bool vlan_filtering);
308 int (*port_vlan_prepare)(struct dsa_switch *ds, int port, 310 int (*port_vlan_prepare)(struct dsa_switch *ds, int port,
309 const struct switchdev_obj_port_vlan *vlan, 311 const struct switchdev_obj_port_vlan *vlan,
310 struct switchdev_trans *trans); 312 struct switchdev_trans *trans);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index cde29239b60d..27bf03d11670 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -317,6 +317,24 @@ static int dsa_slave_stp_update(struct net_device *dev, u8 state)
317 return ret; 317 return ret;
318} 318}
319 319
320static int dsa_slave_vlan_filtering(struct net_device *dev,
321 const struct switchdev_attr *attr,
322 struct switchdev_trans *trans)
323{
324 struct dsa_slave_priv *p = netdev_priv(dev);
325 struct dsa_switch *ds = p->parent;
326
327 /* bridge skips -EOPNOTSUPP, so skip the prepare phase */
328 if (switchdev_trans_ph_prepare(trans))
329 return 0;
330
331 if (ds->drv->port_vlan_filtering)
332 return ds->drv->port_vlan_filtering(ds, p->port,
333 attr->u.vlan_filtering);
334
335 return 0;
336}
337
320static int dsa_slave_port_attr_set(struct net_device *dev, 338static int dsa_slave_port_attr_set(struct net_device *dev,
321 const struct switchdev_attr *attr, 339 const struct switchdev_attr *attr,
322 struct switchdev_trans *trans) 340 struct switchdev_trans *trans)
@@ -333,6 +351,9 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
333 ret = ds->drv->port_stp_update(ds, p->port, 351 ret = ds->drv->port_stp_update(ds, p->port,
334 attr->u.stp_state); 352 attr->u.stp_state);
335 break; 353 break;
354 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
355 ret = dsa_slave_vlan_filtering(dev, attr, trans);
356 break;
336 default: 357 default:
337 ret = -EOPNOTSUPP; 358 ret = -EOPNOTSUPP;
338 break; 359 break;