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

Merge branch 'am65-cpsw-rx-dscp-prio-map'

Roger Quadros says:

====================
net: ethernet: ti: am65-cpsw: enable DSCP to priority map for RX

Configure default DSCP to User Priority mapping registers as per:
https://datatracker.ietf.org/doc/html/rfc8325#section-4.3
and
https://datatracker.ietf.org/doc/html/rfc8622#section-11

Also update Priority to Thread maping to be compliant with
IEEE802.1Q-2014. Priority Code Point (PCP) 2 is higher priority than
PCP 0 (Best Effort). PCP 1 (Background) is lower priority than
PCP 0 (Best Effort).

---
Changes in v4:
- Updated default DSCP to User Priority mapping as per
https://datatracker.ietf.org/doc/html/rfc8325#section-4.3
and
https://datatracker.ietf.org/doc/html/rfc8622#section-11
- Link to v3: https://lore.kernel.org/r/20241109-am65-cpsw-multi-rx-dscp-v3-0-1cfb76928490@kernel.org

Changes in v3:
- Added Reviewed-by tag to patch 1
- Added macros for DSCP PRI field size and DSCP PRI per register
- Drop unnecessary readl() in am65_cpsw_port_set_dscp_map()
- Link to v2: https://lore.kernel.org/r/20241107-am65-cpsw-multi-rx-dscp-v2-0-9e9cd1920035@kernel.org

Changes in v2:
- Updated references to more recent standard IEEE802.1Q-2014.
- Dropped reference to web link which might change in the future.
- Typo fix in commit log.
- Link to v1: https://lore.kernel.org/r/20241105-am65-cpsw-multi-rx-dscp-v1-0-38db85333c88@kernel.org
====================

Signed-off-by: Roger Quadros <rogerq@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

+122 -14
+100
drivers/net/ethernet/ti/am65-cpsw-nuss.c
··· 71 71 #define AM65_CPSW_PORT_REG_RX_PRI_MAP 0x020 72 72 #define AM65_CPSW_PORT_REG_RX_MAXLEN 0x024 73 73 74 + #define AM65_CPSW_PORTN_REG_CTL 0x004 75 + #define AM65_CPSW_PORTN_REG_DSCP_MAP 0x120 74 76 #define AM65_CPSW_PORTN_REG_SA_L 0x308 75 77 #define AM65_CPSW_PORTN_REG_SA_H 0x30c 76 78 #define AM65_CPSW_PORTN_REG_TS_CTL 0x310 ··· 95 93 96 94 /* AM65_CPSW_PORT_REG_PRI_CTL */ 97 95 #define AM65_CPSW_PORT_REG_PRI_CTL_RX_PTYPE_RROBIN BIT(8) 96 + 97 + /* AM65_CPSW_PN_REG_CTL */ 98 + #define AM65_CPSW_PN_REG_CTL_DSCP_IPV4_EN BIT(1) 99 + #define AM65_CPSW_PN_REG_CTL_DSCP_IPV6_EN BIT(2) 98 100 99 101 /* AM65_CPSW_PN_TS_CTL register fields */ 100 102 #define AM65_CPSW_PN_TS_CTL_TX_ANX_F_EN BIT(4) ··· 180 174 181 175 writel(mac_hi, slave->port_base + AM65_CPSW_PORTN_REG_SA_H); 182 176 writel(mac_lo, slave->port_base + AM65_CPSW_PORTN_REG_SA_L); 177 + } 178 + 179 + #define AM65_CPSW_DSCP_MAX GENMASK(5, 0) 180 + #define AM65_CPSW_PRI_MAX GENMASK(2, 0) 181 + #define AM65_CPSW_DSCP_PRI_PER_REG 8 182 + #define AM65_CPSW_DSCP_PRI_SIZE 4 /* in bits */ 183 + static int am65_cpsw_port_set_dscp_map(struct am65_cpsw_port *slave, u8 dscp, u8 pri) 184 + { 185 + int reg_ofs; 186 + int bit_ofs; 187 + u32 val; 188 + 189 + if (dscp > AM65_CPSW_DSCP_MAX) 190 + return -EINVAL; 191 + 192 + if (pri > AM65_CPSW_PRI_MAX) 193 + return -EINVAL; 194 + 195 + /* 32-bit register offset to this dscp */ 196 + reg_ofs = (dscp / AM65_CPSW_DSCP_PRI_PER_REG) * 4; 197 + /* bit field offset to this dscp */ 198 + bit_ofs = AM65_CPSW_DSCP_PRI_SIZE * (dscp % AM65_CPSW_DSCP_PRI_PER_REG); 199 + 200 + val = readl(slave->port_base + AM65_CPSW_PORTN_REG_DSCP_MAP + reg_ofs); 201 + val &= ~(AM65_CPSW_PRI_MAX << bit_ofs); /* clear */ 202 + val |= pri << bit_ofs; /* set */ 203 + writel(val, slave->port_base + AM65_CPSW_PORTN_REG_DSCP_MAP + reg_ofs); 204 + 205 + return 0; 206 + } 207 + 208 + static void am65_cpsw_port_enable_dscp_map(struct am65_cpsw_port *slave) 209 + { 210 + int dscp, pri; 211 + u32 val; 212 + 213 + /* Default DSCP to User Priority mapping as per: 214 + * https://datatracker.ietf.org/doc/html/rfc8325#section-4.3 215 + * and 216 + * https://datatracker.ietf.org/doc/html/rfc8622#section-11 217 + */ 218 + for (dscp = 0; dscp <= AM65_CPSW_DSCP_MAX; dscp++) { 219 + switch (dscp) { 220 + case 56: /* CS7 */ 221 + case 48: /* CS6 */ 222 + pri = 7; 223 + break; 224 + case 46: /* EF */ 225 + case 44: /* VA */ 226 + pri = 6; 227 + break; 228 + case 40: /* CS5 */ 229 + pri = 5; 230 + break; 231 + case 34: /* AF41 */ 232 + case 36: /* AF42 */ 233 + case 38: /* AF43 */ 234 + case 32: /* CS4 */ 235 + case 26: /* AF31 */ 236 + case 28: /* AF32 */ 237 + case 30: /* AF33 */ 238 + case 24: /* CS3 */ 239 + pri = 4; 240 + break; 241 + case 18: /* AF21 */ 242 + case 20: /* AF22 */ 243 + case 22: /* AF23 */ 244 + pri = 3; 245 + break; 246 + case 16: /* CS2 */ 247 + case 10: /* AF11 */ 248 + case 12: /* AF12 */ 249 + case 14: /* AF13 */ 250 + case 0: /* DF */ 251 + pri = 0; 252 + break; 253 + case 8: /* CS1 */ 254 + case 1: /* LE */ 255 + pri = 1; 256 + break; 257 + default: 258 + pri = 0; 259 + break; 260 + } 261 + 262 + am65_cpsw_port_set_dscp_map(slave, dscp, pri); 263 + } 264 + 265 + /* enable port IPV4 and IPV6 DSCP for this port */ 266 + val = readl(slave->port_base + AM65_CPSW_PORTN_REG_CTL); 267 + val |= AM65_CPSW_PN_REG_CTL_DSCP_IPV4_EN | 268 + AM65_CPSW_PN_REG_CTL_DSCP_IPV6_EN; 269 + writel(val, slave->port_base + AM65_CPSW_PORTN_REG_CTL); 183 270 } 184 271 185 272 static void am65_cpsw_sl_ctl_reset(struct am65_cpsw_port *port) ··· 1015 916 common->usage_count++; 1016 917 1017 918 am65_cpsw_port_set_sl_mac(port, ndev->dev_addr); 919 + am65_cpsw_port_enable_dscp_map(port); 1018 920 1019 921 if (common->is_emac_mode) 1020 922 am65_cpsw_init_port_emac_ale(port);
+22 -14
drivers/net/ethernet/ti/cpsw_ale.c
··· 1704 1704 void cpsw_ale_classifier_setup_default(struct cpsw_ale *ale, int num_rx_ch) 1705 1705 { 1706 1706 int pri, idx; 1707 - /* IEEE802.1D-2004, Standard for Local and metropolitan area networks 1708 - * Table G-2 - Traffic type acronyms 1709 - * Table G-3 - Defining traffic types 1710 - * User priority values 1 and 2 effectively communicate a lower 1711 - * priority than 0. In the below table 0 is assigned to higher priority 1712 - * thread than 1 and 2 wherever possible. 1713 - * The below table maps which thread the user priority needs to be 1707 + 1708 + /* Reference: 1709 + * IEEE802.1Q-2014, Standard for Local and metropolitan area networks 1710 + * Table I-2 - Traffic type acronyms 1711 + * Table I-3 - Defining traffic types 1712 + * Section I.4 Traffic types and priority values, states: 1713 + * "0 is thus used both for default priority and for Best Effort, and 1714 + * Background is associated with a priority value of 1. This means 1715 + * that the value 1 effectively communicates a lower priority than 0." 1716 + * 1717 + * In the table below, Priority Code Point (PCP) 0 is assigned 1718 + * to a higher priority thread than PCP 1 wherever possible. 1719 + * The table maps which thread the PCP traffic needs to be 1714 1720 * sent to for a given number of threads (RX channels). Upper threads 1715 1721 * have higher priority. 1716 1722 * e.g. if number of threads is 8 then user priority 0 will map to 1717 - * pri_thread_map[8-1][0] i.e. thread 2 1723 + * pri_thread_map[8-1][0] i.e. thread 1 1718 1724 */ 1719 - int pri_thread_map[8][8] = { { 0, 0, 0, 0, 0, 0, 0, 0, }, 1725 + 1726 + int pri_thread_map[8][8] = { /* BK,BE,EE,CA,VI,VO,IC,NC */ 1727 + { 0, 0, 0, 0, 0, 0, 0, 0, }, 1720 1728 { 0, 0, 0, 0, 1, 1, 1, 1, }, 1721 1729 { 0, 0, 0, 0, 1, 1, 2, 2, }, 1722 - { 1, 0, 0, 1, 2, 2, 3, 3, }, 1723 - { 1, 0, 0, 1, 2, 3, 4, 4, }, 1724 - { 1, 0, 0, 2, 3, 4, 5, 5, }, 1725 - { 1, 0, 0, 2, 3, 4, 5, 6, }, 1726 - { 2, 0, 1, 3, 4, 5, 6, 7, } }; 1730 + { 0, 0, 1, 1, 2, 2, 3, 3, }, 1731 + { 0, 0, 1, 1, 2, 2, 3, 4, }, 1732 + { 1, 0, 2, 2, 3, 3, 4, 5, }, 1733 + { 1, 0, 2, 3, 4, 4, 5, 6, }, 1734 + { 1, 0, 2, 3, 4, 5, 6, 7 } }; 1727 1735 1728 1736 cpsw_ale_policer_reset(ale); 1729 1737