Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-dsa-b53-fix-bcm5325-support'

Álvaro Fernández Rojas says:

====================
net: dsa: b53: fix BCM5325 support

These patches get the BCM5325 switch working with b53.

The existing brcm legacy tag only works with BCM63xx switches.
We need to add a new legacy tag for BCM5325 and BCM5365 switches, which
require including the FCS and length.

I'm not really sure that everything here is correct since I don't work for
Broadcom and all this is based on the public datasheet available for the
BCM5325 and my own experiments with a Huawei HG556a (BCM6358).

Both sets of patches have been merged due to the change requested by Jonas
about BRCM_HDR register access depending on legacy tags.
====================

Link: https://patch.msgid.link/20250614080000.1884236-1-noltari@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+415 -96
+1
drivers/net/dsa/b53/Kconfig
··· 5 5 select NET_DSA_TAG_NONE 6 6 select NET_DSA_TAG_BRCM 7 7 select NET_DSA_TAG_BRCM_LEGACY 8 + select NET_DSA_TAG_BRCM_LEGACY_FCS 8 9 select NET_DSA_TAG_BRCM_PREPEND 9 10 help 10 11 This driver adds support for Broadcom managed switch chips. It supports
+224 -58
drivers/net/dsa/b53/b53_common.c
··· 361 361 362 362 b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); 363 363 364 - /* Include IMP port in dumb forwarding mode 365 - */ 366 - b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, &mgmt); 367 - mgmt |= B53_MII_DUMB_FWDG_EN; 368 - b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt); 364 + if (!is5325(dev)) { 365 + /* Include IMP port in dumb forwarding mode */ 366 + b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, &mgmt); 367 + mgmt |= B53_MII_DUMB_FWDG_EN; 368 + b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt); 369 369 370 - /* Look at B53_UC_FWD_EN and B53_MC_FWD_EN to decide whether 371 - * frames should be flooded or not. 372 - */ 373 - b53_read8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, &mgmt); 374 - mgmt |= B53_UC_FWD_EN | B53_MC_FWD_EN | B53_IPMC_FWD_EN; 375 - b53_write8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, mgmt); 370 + /* Look at B53_UC_FWD_EN and B53_MC_FWD_EN to decide whether 371 + * frames should be flooded or not. 372 + */ 373 + b53_read8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, &mgmt); 374 + mgmt |= B53_UC_FWD_EN | B53_MC_FWD_EN | B53_IPMC_FWD_EN; 375 + b53_write8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, mgmt); 376 + } else { 377 + b53_read8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, &mgmt); 378 + mgmt |= B53_IP_MCAST_25; 379 + b53_write8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, mgmt); 380 + } 376 381 } 377 382 378 383 static void b53_enable_vlan(struct b53_device *dev, int port, bool enable, ··· 492 487 { 493 488 unsigned int i; 494 489 490 + if (is5325(dev)) 491 + return 0; 492 + 495 493 b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL, 496 494 FAST_AGE_DONE | FAST_AGE_DYNAMIC | mask); 497 495 ··· 519 511 520 512 static int b53_fast_age_port(struct b53_device *dev, int port) 521 513 { 514 + if (is5325(dev)) 515 + return 0; 516 + 522 517 b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_PORT_CTRL, port); 523 518 524 519 return b53_flush_arl(dev, FAST_AGE_PORT); ··· 529 518 530 519 static int b53_fast_age_vlan(struct b53_device *dev, u16 vid) 531 520 { 521 + if (is5325(dev)) 522 + return 0; 523 + 532 524 b53_write16(dev, B53_CTRL_PAGE, B53_FAST_AGE_VID_CTRL, vid); 533 525 534 526 return b53_flush_arl(dev, FAST_AGE_VLAN); ··· 542 528 struct b53_device *dev = ds->priv; 543 529 unsigned int i; 544 530 u16 pvlan; 531 + 532 + /* BCM5325 CPU port is at 8 */ 533 + if ((is5325(dev) || is5365(dev)) && cpu_port == B53_CPU_PORT_25) 534 + cpu_port = B53_CPU_PORT; 545 535 546 536 /* Enable the IMP port to be in the same VLAN as the other ports 547 537 * on a per-port basis such that we only have Port i and IMP in ··· 564 546 { 565 547 u16 uc; 566 548 567 - b53_read16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, &uc); 568 - if (unicast) 569 - uc |= BIT(port); 570 - else 571 - uc &= ~BIT(port); 572 - b53_write16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, uc); 549 + if (is5325(dev)) { 550 + if (port == B53_CPU_PORT_25) 551 + port = B53_CPU_PORT; 552 + 553 + b53_read16(dev, B53_IEEE_PAGE, B53_IEEE_UCAST_DLF, &uc); 554 + if (unicast) 555 + uc |= BIT(port) | B53_IEEE_UCAST_DROP_EN; 556 + else 557 + uc &= ~BIT(port); 558 + b53_write16(dev, B53_IEEE_PAGE, B53_IEEE_UCAST_DLF, uc); 559 + } else { 560 + b53_read16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, &uc); 561 + if (unicast) 562 + uc |= BIT(port); 563 + else 564 + uc &= ~BIT(port); 565 + b53_write16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, uc); 566 + } 573 567 } 574 568 575 569 static void b53_port_set_mcast_flood(struct b53_device *dev, int port, ··· 589 559 { 590 560 u16 mc; 591 561 592 - b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, &mc); 593 - if (multicast) 594 - mc |= BIT(port); 595 - else 596 - mc &= ~BIT(port); 597 - b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, mc); 562 + if (is5325(dev)) { 563 + if (port == B53_CPU_PORT_25) 564 + port = B53_CPU_PORT; 598 565 599 - b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, &mc); 600 - if (multicast) 601 - mc |= BIT(port); 602 - else 603 - mc &= ~BIT(port); 604 - b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, mc); 566 + b53_read16(dev, B53_IEEE_PAGE, B53_IEEE_MCAST_DLF, &mc); 567 + if (multicast) 568 + mc |= BIT(port) | B53_IEEE_MCAST_DROP_EN; 569 + else 570 + mc &= ~BIT(port); 571 + b53_write16(dev, B53_IEEE_PAGE, B53_IEEE_MCAST_DLF, mc); 572 + } else { 573 + b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, &mc); 574 + if (multicast) 575 + mc |= BIT(port); 576 + else 577 + mc &= ~BIT(port); 578 + b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, mc); 579 + 580 + b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, &mc); 581 + if (multicast) 582 + mc |= BIT(port); 583 + else 584 + mc &= ~BIT(port); 585 + b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, mc); 586 + } 605 587 } 606 588 607 589 static void b53_port_set_learning(struct b53_device *dev, int port, 608 590 bool learning) 609 591 { 610 592 u16 reg; 593 + 594 + if (is5325(dev)) 595 + return; 611 596 612 597 b53_read16(dev, B53_CTRL_PAGE, B53_DIS_LEARNING, &reg); 613 598 if (learning) ··· 659 614 */ 660 615 if (dsa_is_user_port(ds, port)) 661 616 b53_set_eap_mode(dev, port, EAP_MODE_SIMPLIFIED); 617 + 618 + if (is5325(dev) && 619 + in_range(port, 1, 4)) { 620 + u8 reg; 621 + 622 + b53_read8(dev, B53_CTRL_PAGE, B53_PD_MODE_CTRL_25, &reg); 623 + reg &= ~PD_MODE_POWER_DOWN_PORT(0); 624 + if (dsa_is_unused_port(ds, port)) 625 + reg |= PD_MODE_POWER_DOWN_PORT(port); 626 + else 627 + reg &= ~PD_MODE_POWER_DOWN_PORT(port); 628 + b53_write8(dev, B53_CTRL_PAGE, B53_PD_MODE_CTRL_25, reg); 629 + } 662 630 663 631 return 0; 664 632 } ··· 770 712 else if (port == 5) 771 713 hdr_ctl |= GC_FRM_MGMT_PORT_M; 772 714 b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, hdr_ctl); 715 + 716 + /* B53_BRCM_HDR not present on devices with legacy tags */ 717 + if (dev->tag_protocol == DSA_TAG_PROTO_BRCM_LEGACY || 718 + dev->tag_protocol == DSA_TAG_PROTO_BRCM_LEGACY_FCS) 719 + return; 773 720 774 721 /* Enable Broadcom tags for IMP port */ 775 722 b53_read8(dev, B53_MGMT_PAGE, B53_BRCM_HDR, &hdr_ctl); ··· 1320 1257 if (port == dev->imp_port) { 1321 1258 off = B53_PORT_OVERRIDE_CTRL; 1322 1259 val = PORT_OVERRIDE_EN; 1260 + } else if (is5325(dev)) { 1261 + return; 1323 1262 } else { 1324 1263 off = B53_GMII_PORT_OVERRIDE_CTRL(port); 1325 1264 val = GMII_PO_EN; ··· 1346 1281 if (port == dev->imp_port) { 1347 1282 off = B53_PORT_OVERRIDE_CTRL; 1348 1283 val = PORT_OVERRIDE_EN; 1284 + } else if (is5325(dev)) { 1285 + return; 1349 1286 } else { 1350 1287 off = B53_GMII_PORT_OVERRIDE_CTRL(port); 1351 1288 val = GMII_PO_EN; ··· 1378 1311 return; 1379 1312 } 1380 1313 1381 - if (rx_pause) 1382 - reg |= PORT_OVERRIDE_RX_FLOW; 1383 - if (tx_pause) 1384 - reg |= PORT_OVERRIDE_TX_FLOW; 1314 + if (rx_pause) { 1315 + if (is5325(dev)) 1316 + reg |= PORT_OVERRIDE_LP_FLOW_25; 1317 + else 1318 + reg |= PORT_OVERRIDE_RX_FLOW; 1319 + } 1320 + 1321 + if (tx_pause) { 1322 + if (is5325(dev)) 1323 + reg |= PORT_OVERRIDE_LP_FLOW_25; 1324 + else 1325 + reg |= PORT_OVERRIDE_TX_FLOW; 1326 + } 1385 1327 1386 1328 b53_write8(dev, B53_CTRL_PAGE, off, reg); 1387 1329 } ··· 1840 1764 return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT; 1841 1765 } 1842 1766 1767 + static int b53_arl_read_25(struct b53_device *dev, u64 mac, 1768 + u16 vid, struct b53_arl_entry *ent, u8 *idx) 1769 + { 1770 + DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES); 1771 + unsigned int i; 1772 + int ret; 1773 + 1774 + ret = b53_arl_op_wait(dev); 1775 + if (ret) 1776 + return ret; 1777 + 1778 + bitmap_zero(free_bins, dev->num_arl_bins); 1779 + 1780 + /* Read the bins */ 1781 + for (i = 0; i < dev->num_arl_bins; i++) { 1782 + u64 mac_vid; 1783 + 1784 + b53_read64(dev, B53_ARLIO_PAGE, 1785 + B53_ARLTBL_MAC_VID_ENTRY(i), &mac_vid); 1786 + 1787 + b53_arl_to_entry_25(ent, mac_vid); 1788 + 1789 + if (!(mac_vid & ARLTBL_VALID_25)) { 1790 + set_bit(i, free_bins); 1791 + continue; 1792 + } 1793 + if ((mac_vid & ARLTBL_MAC_MASK) != mac) 1794 + continue; 1795 + if (dev->vlan_enabled && 1796 + ((mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25) != vid) 1797 + continue; 1798 + *idx = i; 1799 + return 0; 1800 + } 1801 + 1802 + *idx = find_first_bit(free_bins, dev->num_arl_bins); 1803 + return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT; 1804 + } 1805 + 1843 1806 static int b53_arl_op(struct b53_device *dev, int op, int port, 1844 1807 const unsigned char *addr, u16 vid, bool is_valid) 1845 1808 { ··· 1893 1778 1894 1779 /* Perform a read for the given MAC and VID */ 1895 1780 b53_write48(dev, B53_ARLIO_PAGE, B53_MAC_ADDR_IDX, mac); 1896 - b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid); 1781 + if (!is5325m(dev)) 1782 + b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid); 1897 1783 1898 1784 /* Issue a read operation for this MAC */ 1899 1785 ret = b53_arl_rw_op(dev, 1); 1900 1786 if (ret) 1901 1787 return ret; 1902 1788 1903 - ret = b53_arl_read(dev, mac, vid, &ent, &idx); 1789 + if (is5325(dev) || is5365(dev)) 1790 + ret = b53_arl_read_25(dev, mac, vid, &ent, &idx); 1791 + else 1792 + ret = b53_arl_read(dev, mac, vid, &ent, &idx); 1904 1793 1905 1794 /* If this is a read, just finish now */ 1906 1795 if (op) ··· 1948 1829 ent.is_static = true; 1949 1830 ent.is_age = false; 1950 1831 memcpy(ent.mac, addr, ETH_ALEN); 1951 - b53_arl_from_entry(&mac_vid, &fwd_entry, &ent); 1832 + if (is5325(dev) || is5365(dev)) 1833 + b53_arl_from_entry_25(&mac_vid, &ent); 1834 + else 1835 + b53_arl_from_entry(&mac_vid, &fwd_entry, &ent); 1952 1836 1953 1837 b53_write64(dev, B53_ARLIO_PAGE, 1954 1838 B53_ARLTBL_MAC_VID_ENTRY(idx), mac_vid); 1955 - b53_write32(dev, B53_ARLIO_PAGE, 1956 - B53_ARLTBL_DATA_ENTRY(idx), fwd_entry); 1839 + 1840 + if (!is5325(dev) && !is5365(dev)) 1841 + b53_write32(dev, B53_ARLIO_PAGE, 1842 + B53_ARLTBL_DATA_ENTRY(idx), fwd_entry); 1957 1843 1958 1844 return b53_arl_rw_op(dev, 0); 1959 1845 } ··· 1969 1845 { 1970 1846 struct b53_device *priv = ds->priv; 1971 1847 int ret; 1972 - 1973 - /* 5325 and 5365 require some more massaging, but could 1974 - * be supported eventually 1975 - */ 1976 - if (is5325(priv) || is5365(priv)) 1977 - return -EOPNOTSUPP; 1978 1848 1979 1849 mutex_lock(&priv->arl_mutex); 1980 1850 ret = b53_arl_op(priv, 0, port, addr, vid, true); ··· 1996 1878 static int b53_arl_search_wait(struct b53_device *dev) 1997 1879 { 1998 1880 unsigned int timeout = 1000; 1999 - u8 reg; 1881 + u8 reg, offset; 1882 + 1883 + if (is5325(dev) || is5365(dev)) 1884 + offset = B53_ARL_SRCH_CTL_25; 1885 + else 1886 + offset = B53_ARL_SRCH_CTL; 2000 1887 2001 1888 do { 2002 - b53_read8(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, &reg); 1889 + b53_read8(dev, B53_ARLIO_PAGE, offset, &reg); 2003 1890 if (!(reg & ARL_SRCH_STDN)) 2004 1891 return 0; 2005 1892 ··· 2021 1898 struct b53_arl_entry *ent) 2022 1899 { 2023 1900 u64 mac_vid; 2024 - u32 fwd_entry; 2025 1901 2026 - b53_read64(dev, B53_ARLIO_PAGE, 2027 - B53_ARL_SRCH_RSTL_MACVID(idx), &mac_vid); 2028 - b53_read32(dev, B53_ARLIO_PAGE, 2029 - B53_ARL_SRCH_RSTL(idx), &fwd_entry); 2030 - b53_arl_to_entry(ent, mac_vid, fwd_entry); 1902 + if (is5325(dev)) { 1903 + b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25, 1904 + &mac_vid); 1905 + b53_arl_to_entry_25(ent, mac_vid); 1906 + } else if (is5365(dev)) { 1907 + b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65, 1908 + &mac_vid); 1909 + b53_arl_to_entry_25(ent, mac_vid); 1910 + } else { 1911 + u32 fwd_entry; 1912 + 1913 + b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_MACVID(idx), 1914 + &mac_vid); 1915 + b53_read32(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL(idx), 1916 + &fwd_entry); 1917 + b53_arl_to_entry(ent, mac_vid, fwd_entry); 1918 + } 2031 1919 } 2032 1920 2033 1921 static int b53_fdb_copy(int port, const struct b53_arl_entry *ent, ··· 2059 1925 struct b53_device *priv = ds->priv; 2060 1926 struct b53_arl_entry results[2]; 2061 1927 unsigned int count = 0; 1928 + u8 offset; 2062 1929 int ret; 2063 1930 u8 reg; 2064 1931 2065 1932 mutex_lock(&priv->arl_mutex); 2066 1933 1934 + if (is5325(priv) || is5365(priv)) 1935 + offset = B53_ARL_SRCH_CTL_25; 1936 + else 1937 + offset = B53_ARL_SRCH_CTL; 1938 + 2067 1939 /* Start search operation */ 2068 1940 reg = ARL_SRCH_STDN; 2069 - b53_write8(priv, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, reg); 1941 + b53_write8(priv, offset, B53_ARL_SRCH_CTL, reg); 2070 1942 2071 1943 do { 2072 1944 ret = b53_arl_search_wait(priv); ··· 2305 2165 struct switchdev_brport_flags flags, 2306 2166 struct netlink_ext_ack *extack) 2307 2167 { 2308 - if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD | BR_LEARNING)) 2168 + struct b53_device *dev = ds->priv; 2169 + unsigned long mask = (BR_FLOOD | BR_MCAST_FLOOD); 2170 + 2171 + if (!is5325(dev)) 2172 + mask |= BR_LEARNING; 2173 + 2174 + if (flags.mask & ~mask) 2309 2175 return -EINVAL; 2310 2176 2311 2177 return 0; ··· 2387 2241 goto out; 2388 2242 } 2389 2243 2390 - /* Older models require a different 6 byte tag */ 2391 - if (is5325(dev) || is5365(dev) || is63xx(dev)) { 2244 + /* Older models require different 6 byte tags */ 2245 + if (is5325(dev) || is5365(dev)) { 2246 + dev->tag_protocol = DSA_TAG_PROTO_BRCM_LEGACY_FCS; 2247 + goto out; 2248 + } else if (is63xx(dev)) { 2392 2249 dev->tag_protocol = DSA_TAG_PROTO_BRCM_LEGACY; 2393 2250 goto out; 2394 2251 } ··· 2979 2830 } 2980 2831 } 2981 2832 2833 + if (is5325e(dev)) 2834 + dev->num_arl_buckets = 512; 2835 + 2982 2836 dev->num_ports = fls(dev->enabled_ports); 2983 2837 2984 2838 dev->ds->num_ports = min_t(unsigned int, dev->num_ports, DSA_MAX_PORTS); ··· 3083 2931 b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, 0xf); 3084 2932 b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, &tmp); 3085 2933 3086 - if (tmp == 0xf) 2934 + if (tmp == 0xf) { 2935 + u32 phy_id; 2936 + int val; 2937 + 3087 2938 dev->chip_id = BCM5325_DEVICE_ID; 3088 - else 2939 + 2940 + val = b53_phy_read16(dev->ds, 0, MII_PHYSID1); 2941 + phy_id = (val & 0xffff) << 16; 2942 + val = b53_phy_read16(dev->ds, 0, MII_PHYSID2); 2943 + phy_id |= (val & 0xfff0); 2944 + 2945 + if (phy_id == 0x00406330) 2946 + dev->variant_id = B53_VARIANT_5325M; 2947 + else if (phy_id == 0x0143bc30) 2948 + dev->variant_id = B53_VARIANT_5325E; 2949 + } else { 3089 2950 dev->chip_id = BCM5365_DEVICE_ID; 2951 + } 3090 2952 break; 3091 2953 case BCM5389_DEVICE_ID: 3092 2954 case BCM5395_DEVICE_ID:
+48
drivers/net/dsa/b53/b53_priv.h
··· 84 84 BCM53134_DEVICE_ID = 0x5075, 85 85 }; 86 86 87 + enum b53_variant_id { 88 + B53_VARIANT_NONE = 0, 89 + B53_VARIANT_5325E, 90 + B53_VARIANT_5325M, 91 + }; 92 + 87 93 struct b53_pcs { 88 94 struct phylink_pcs pcs; 89 95 struct b53_device *dev; ··· 124 118 125 119 /* chip specific data */ 126 120 u32 chip_id; 121 + enum b53_variant_id variant_id; 127 122 u8 core_rev; 128 123 u8 vta_regs[3]; 129 124 u8 duplex_reg; ··· 170 163 static inline int is5325(struct b53_device *dev) 171 164 { 172 165 return dev->chip_id == BCM5325_DEVICE_ID; 166 + } 167 + 168 + static inline int is5325e(struct b53_device *dev) 169 + { 170 + return is5325(dev) && 171 + dev->variant_id == B53_VARIANT_5325E; 172 + } 173 + 174 + static inline int is5325m(struct b53_device *dev) 175 + { 176 + return is5325(dev) && 177 + dev->variant_id == B53_VARIANT_5325M; 173 178 } 174 179 175 180 static inline int is5365(struct b53_device *dev) ··· 317 298 ent->vid = mac_vid >> ARLTBL_VID_S; 318 299 } 319 300 301 + static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent, 302 + u64 mac_vid) 303 + { 304 + memset(ent, 0, sizeof(*ent)); 305 + ent->port = (mac_vid >> ARLTBL_DATA_PORT_ID_S_25) & 306 + ARLTBL_DATA_PORT_ID_MASK_25; 307 + ent->is_valid = !!(mac_vid & ARLTBL_VALID_25); 308 + ent->is_age = !!(mac_vid & ARLTBL_AGE_25); 309 + ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); 310 + u64_to_ether_addr(mac_vid, ent->mac); 311 + ent->vid = mac_vid >> ARLTBL_VID_S_65; 312 + } 313 + 320 314 static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry, 321 315 const struct b53_arl_entry *ent) 322 316 { ··· 342 310 *fwd_entry |= ARLTBL_STATIC; 343 311 if (ent->is_age) 344 312 *fwd_entry |= ARLTBL_AGE; 313 + } 314 + 315 + static inline void b53_arl_from_entry_25(u64 *mac_vid, 316 + const struct b53_arl_entry *ent) 317 + { 318 + *mac_vid = ether_addr_to_u64(ent->mac); 319 + *mac_vid |= (u64)(ent->port & ARLTBL_DATA_PORT_ID_MASK_25) << 320 + ARLTBL_DATA_PORT_ID_S_25; 321 + *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK_25) << 322 + ARLTBL_VID_S_65; 323 + if (ent->is_valid) 324 + *mac_vid |= ARLTBL_VALID_25; 325 + if (ent->is_static) 326 + *mac_vid |= ARLTBL_STATIC_25; 327 + if (ent->is_age) 328 + *mac_vid |= ARLTBL_AGE_25; 345 329 } 346 330 347 331 #ifdef CONFIG_BCM47XX
+23 -4
drivers/net/dsa/b53/b53_regs.h
··· 29 29 #define B53_ARLIO_PAGE 0x05 /* ARL Access */ 30 30 #define B53_FRAMEBUF_PAGE 0x06 /* Management frame access */ 31 31 #define B53_MEM_ACCESS_PAGE 0x08 /* Memory access */ 32 + #define B53_IEEE_PAGE 0x0a /* IEEE 802.1X */ 32 33 33 34 /* PHY Registers */ 34 35 #define B53_PORT_MII_PAGE(i) (0x10 + (i)) /* Port i MII Registers */ ··· 96 95 #define PORT_OVERRIDE_SPEED_10M (0 << PORT_OVERRIDE_SPEED_S) 97 96 #define PORT_OVERRIDE_SPEED_100M (1 << PORT_OVERRIDE_SPEED_S) 98 97 #define PORT_OVERRIDE_SPEED_1000M (2 << PORT_OVERRIDE_SPEED_S) 98 + #define PORT_OVERRIDE_LP_FLOW_25 BIT(3) /* BCM5325 only */ 99 99 #define PORT_OVERRIDE_RV_MII_25 BIT(4) /* BCM5325 only */ 100 100 #define PORT_OVERRIDE_RX_FLOW BIT(4) 101 101 #define PORT_OVERRIDE_TX_FLOW BIT(5) 102 102 #define PORT_OVERRIDE_SPEED_2000M BIT(6) /* BCM5301X only, requires setting 1000M */ 103 103 #define PORT_OVERRIDE_EN BIT(7) /* Use the register contents */ 104 104 105 - /* Power-down mode control */ 105 + /* Power-down mode control (8 bit) */ 106 106 #define B53_PD_MODE_CTRL_25 0x0f 107 + #define PD_MODE_PORT_MASK 0x1f 108 + /* Bit 0 also powers down the switch. */ 109 + #define PD_MODE_POWER_DOWN_PORT(i) BIT(i) 107 110 108 111 /* IP Multicast control (8 bit) */ 109 112 #define B53_IP_MULTICAST_CTRL 0x21 113 + #define B53_IP_MCAST_25 BIT(0) 110 114 #define B53_IPMC_FWD_EN BIT(1) 111 115 #define B53_UC_FWD_EN BIT(6) 112 116 #define B53_MC_FWD_EN BIT(7) ··· 330 324 #define ARLTBL_VID_MASK 0xfff 331 325 #define ARLTBL_DATA_PORT_ID_S_25 48 332 326 #define ARLTBL_DATA_PORT_ID_MASK_25 0xf 333 - #define ARLTBL_AGE_25 BIT(61) 334 - #define ARLTBL_STATIC_25 BIT(62) 335 - #define ARLTBL_VALID_25 BIT(63) 327 + #define ARLTBL_VID_S_65 53 328 + #define ARLTBL_AGE_25 BIT_ULL(61) 329 + #define ARLTBL_STATIC_25 BIT_ULL(62) 330 + #define ARLTBL_VALID_25 BIT_ULL(63) 336 331 337 332 /* ARL Table Data Entry N Registers (32 bit) */ 338 333 #define B53_ARLTBL_DATA_ENTRY(n) ((0x10 * (n)) + 0x18) ··· 371 364 372 365 #define B53_ARL_SRCH_RSTL_MACVID(x) (B53_ARL_SRCH_RSTL_0_MACVID + ((x) * 0x10)) 373 366 #define B53_ARL_SRCH_RSTL(x) (B53_ARL_SRCH_RSTL_0 + ((x) * 0x10)) 367 + 368 + /************************************************************************* 369 + * IEEE 802.1X Registers 370 + *************************************************************************/ 371 + 372 + /* Multicast DLF Drop Control register (16 bit) */ 373 + #define B53_IEEE_MCAST_DLF 0x94 374 + #define B53_IEEE_MCAST_DROP_EN BIT(11) 375 + 376 + /* Unicast DLF Drop Control register (16 bit) */ 377 + #define B53_IEEE_UCAST_DLF 0x96 378 + #define B53_IEEE_UCAST_DROP_EN BIT(11) 374 379 375 380 /************************************************************************* 376 381 * Port VLAN Registers
+2
include/net/dsa.h
··· 54 54 #define DSA_TAG_PROTO_RZN1_A5PSW_VALUE 26 55 55 #define DSA_TAG_PROTO_LAN937X_VALUE 27 56 56 #define DSA_TAG_PROTO_VSC73XX_8021Q_VALUE 28 57 + #define DSA_TAG_PROTO_BRCM_LEGACY_FCS_VALUE 29 57 58 58 59 enum dsa_tag_protocol { 59 60 DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, 60 61 DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE, 61 62 DSA_TAG_PROTO_BRCM_LEGACY = DSA_TAG_PROTO_BRCM_LEGACY_VALUE, 63 + DSA_TAG_PROTO_BRCM_LEGACY_FCS = DSA_TAG_PROTO_BRCM_LEGACY_FCS_VALUE, 62 64 DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE, 63 65 DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE, 64 66 DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE,
+14 -2
net/dsa/Kconfig
··· 42 42 Broadcom switches which place the tag after the MAC source address. 43 43 44 44 config NET_DSA_TAG_BRCM_LEGACY 45 - tristate "Tag driver for Broadcom legacy switches using in-frame headers" 45 + tristate "Tag driver for BCM63xx legacy switches using in-frame headers" 46 46 select NET_DSA_TAG_BRCM_COMMON 47 47 help 48 48 Say Y if you want to enable support for tagging frames for the 49 - Broadcom legacy switches which place the tag after the MAC source 49 + BCM63xx legacy switches which place the tag after the MAC source 50 50 address. 51 + This tag is used in BCM63xx legacy switches which work without the 52 + original FCS and length before the tag insertion. 53 + 54 + config NET_DSA_TAG_BRCM_LEGACY_FCS 55 + tristate "Tag driver for BCM53xx legacy switches using in-frame headers" 56 + select NET_DSA_TAG_BRCM_COMMON 57 + help 58 + Say Y if you want to enable support for tagging frames for the 59 + BCM53xx legacy switches which place the tag after the MAC source 60 + address. 61 + This tag is used in BCM53xx legacy switches which expect original 62 + FCS and length before the tag insertion to be present. 51 63 52 64 config NET_DSA_TAG_BRCM_PREPEND 53 65 tristate "Tag driver for Broadcom switches using prepended headers"
+103 -32
net/dsa/tag_brcm.c
··· 15 15 16 16 #define BRCM_NAME "brcm" 17 17 #define BRCM_LEGACY_NAME "brcm-legacy" 18 + #define BRCM_LEGACY_FCS_NAME "brcm-legacy-fcs" 18 19 #define BRCM_PREPEND_NAME "brcm-prepend" 19 20 20 21 /* Legacy Broadcom tag (6 bytes) */ ··· 33 32 #define BRCM_LEG_MULTICAST (1 << 5) 34 33 #define BRCM_LEG_EGRESS (2 << 5) 35 34 #define BRCM_LEG_INGRESS (3 << 5) 35 + #define BRCM_LEG_LEN_HI(x) (((x) >> 8) & 0x7) 36 + 37 + /* 4th byte in the tag */ 38 + #define BRCM_LEG_LEN_LO(x) ((x) & 0xff) 36 39 37 40 /* 6th byte in the tag */ 38 41 #define BRCM_LEG_PORT_ID (0xf) ··· 217 212 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM, BRCM_NAME); 218 213 #endif 219 214 215 + #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) || \ 216 + IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS) 217 + static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb, 218 + struct net_device *dev) 219 + { 220 + int len = BRCM_LEG_TAG_LEN; 221 + int source_port; 222 + u8 *brcm_tag; 223 + 224 + if (unlikely(!pskb_may_pull(skb, BRCM_LEG_TAG_LEN + VLAN_HLEN))) 225 + return NULL; 226 + 227 + brcm_tag = dsa_etype_header_pos_rx(skb); 228 + 229 + source_port = brcm_tag[5] & BRCM_LEG_PORT_ID; 230 + 231 + skb->dev = dsa_conduit_find_user(dev, 0, source_port); 232 + if (!skb->dev) 233 + return NULL; 234 + 235 + /* VLAN tag is added by BCM63xx internal switch */ 236 + if (netdev_uses_dsa(skb->dev)) 237 + len += VLAN_HLEN; 238 + 239 + /* Remove Broadcom tag and update checksum */ 240 + skb_pull_rcsum(skb, len); 241 + 242 + dsa_default_offload_fwd_mark(skb); 243 + 244 + dsa_strip_etype_header(skb, len); 245 + 246 + return skb; 247 + } 248 + #endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY || CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS */ 249 + 220 250 #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) 221 251 static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb, 222 252 struct net_device *dev) ··· 290 250 return skb; 291 251 } 292 252 293 - static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb, 294 - struct net_device *dev) 295 - { 296 - int len = BRCM_LEG_TAG_LEN; 297 - int source_port; 298 - u8 *brcm_tag; 299 - 300 - if (unlikely(!pskb_may_pull(skb, BRCM_LEG_TAG_LEN + VLAN_HLEN))) 301 - return NULL; 302 - 303 - brcm_tag = dsa_etype_header_pos_rx(skb); 304 - 305 - source_port = brcm_tag[5] & BRCM_LEG_PORT_ID; 306 - 307 - skb->dev = dsa_conduit_find_user(dev, 0, source_port); 308 - if (!skb->dev) 309 - return NULL; 310 - 311 - /* VLAN tag is added by BCM63xx internal switch */ 312 - if (netdev_uses_dsa(skb->dev)) 313 - len += VLAN_HLEN; 314 - 315 - /* Remove Broadcom tag and update checksum */ 316 - skb_pull_rcsum(skb, len); 317 - 318 - dsa_default_offload_fwd_mark(skb); 319 - 320 - dsa_strip_etype_header(skb, len); 321 - 322 - return skb; 323 - } 324 - 325 253 static const struct dsa_device_ops brcm_legacy_netdev_ops = { 326 254 .name = BRCM_LEGACY_NAME, 327 255 .proto = DSA_TAG_PROTO_BRCM_LEGACY, ··· 301 293 DSA_TAG_DRIVER(brcm_legacy_netdev_ops); 302 294 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY, BRCM_LEGACY_NAME); 303 295 #endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY */ 296 + 297 + #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS) 298 + static struct sk_buff *brcm_leg_fcs_tag_xmit(struct sk_buff *skb, 299 + struct net_device *dev) 300 + { 301 + struct dsa_port *dp = dsa_user_to_port(dev); 302 + unsigned int fcs_len; 303 + __le32 fcs_val; 304 + u8 *brcm_tag; 305 + 306 + /* The Ethernet switch we are interfaced with needs packets to be at 307 + * least 64 bytes (including FCS) otherwise they will be discarded when 308 + * they enter the switch port logic. When Broadcom tags are enabled, we 309 + * need to make sure that packets are at least 70 bytes (including FCS 310 + * and tag) because the length verification is done after the Broadcom 311 + * tag is stripped off the ingress packet. 312 + * 313 + * Let dsa_user_xmit() free the SKB. 314 + */ 315 + if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false)) 316 + return NULL; 317 + 318 + fcs_len = skb->len; 319 + fcs_val = cpu_to_le32(crc32_le(~0, skb->data, fcs_len) ^ ~0); 320 + 321 + skb_push(skb, BRCM_LEG_TAG_LEN); 322 + 323 + dsa_alloc_etype_header(skb, BRCM_LEG_TAG_LEN); 324 + 325 + brcm_tag = skb->data + 2 * ETH_ALEN; 326 + 327 + /* Broadcom tag type */ 328 + brcm_tag[0] = BRCM_LEG_TYPE_HI; 329 + brcm_tag[1] = BRCM_LEG_TYPE_LO; 330 + 331 + /* Broadcom tag value */ 332 + brcm_tag[2] = BRCM_LEG_EGRESS | BRCM_LEG_LEN_HI(fcs_len); 333 + brcm_tag[3] = BRCM_LEG_LEN_LO(fcs_len); 334 + brcm_tag[4] = 0; 335 + brcm_tag[5] = dp->index & BRCM_LEG_PORT_ID; 336 + 337 + /* Original FCS value */ 338 + if (__skb_pad(skb, ETH_FCS_LEN, false)) 339 + return NULL; 340 + skb_put_data(skb, &fcs_val, ETH_FCS_LEN); 341 + 342 + return skb; 343 + } 344 + 345 + static const struct dsa_device_ops brcm_legacy_fcs_netdev_ops = { 346 + .name = BRCM_LEGACY_FCS_NAME, 347 + .proto = DSA_TAG_PROTO_BRCM_LEGACY_FCS, 348 + .xmit = brcm_leg_fcs_tag_xmit, 349 + .rcv = brcm_leg_tag_rcv, 350 + .needed_headroom = BRCM_LEG_TAG_LEN, 351 + }; 352 + 353 + DSA_TAG_DRIVER(brcm_legacy_fcs_netdev_ops); 354 + MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY_FCS, BRCM_LEGACY_FCS_NAME); 355 + #endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS */ 304 356 305 357 #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) 306 358 static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb, ··· 395 327 #endif 396 328 #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) 397 329 &DSA_TAG_DRIVER_NAME(brcm_legacy_netdev_ops), 330 + #endif 331 + #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS) 332 + &DSA_TAG_DRIVER_NAME(brcm_legacy_fcs_netdev_ops), 398 333 #endif 399 334 #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) 400 335 &DSA_TAG_DRIVER_NAME(brcm_prepend_netdev_ops),