1 // SPDX-License-Identifier: GPL-2.0 2 /* Forwarding and multicast database interface for the rtl8365mb switch family 3 * 4 * Copyright (C) 2022 Alvin Šipraga <alsi@bang-olufsen.dk> 5 */ 6 7 #include <linux/etherdevice.h> 8 9 #include "rtl8365mb_l2.h" 10 #include "rtl8365mb_table.h" 11 #include <linux/regmap.h> 12 13 #define RTL8365MB_L2_ENTRY_SIZE 6 14 15 #define RTL8365MB_L2_UC_D0_MAC5_MSK GENMASK(7, 0) 16 #define RTL8365MB_L2_UC_D0_MAC4_MSK GENMASK(15, 8) 17 #define RTL8365MB_L2_UC_D1_MAC3_MSK GENMASK(7, 0) 18 #define RTL8365MB_L2_UC_D1_MAC2_MSK GENMASK(15, 8) 19 #define RTL8365MB_L2_UC_D2_MAC1_MSK GENMASK(7, 0) 20 #define RTL8365MB_L2_UC_D2_MAC0_MSK GENMASK(15, 8) 21 #define RTL8365MB_L2_UC_D3_VID_MSK GENMASK(11, 0) 22 #define RTL8365MB_L2_UC_D3_IVL_MSK GENMASK(13, 13) 23 #define RTL8365MB_L2_UC_D3_PORT_EXT_MSK GENMASK(15, 15) 24 #define RTL8365MB_L2_UC_PORT_HI_MSK GENMASK(3, 3) 25 #define RTL8365MB_L2_UC_D4_EFID_MSK GENMASK(2, 0) 26 #define RTL8365MB_L2_UC_D4_FID_MSK GENMASK(6, 3) 27 #define RTL8365MB_L2_UC_D4_SA_PRI_MSK GENMASK(7, 7) 28 #define RTL8365MB_L2_UC_D4_PORT_MSK GENMASK(10, 8) 29 #define RTL8365MB_L2_UC_PORT_LO_MSK GENMASK(2, 0) 30 #define RTL8365MB_L2_UC_D4_AGE_MSK GENMASK(13, 11) 31 #define RTL8365MB_L2_UC_D4_AUTH_MSK GENMASK(14, 14) 32 #define RTL8365MB_L2_UC_D4_SA_BLOCK_MSK GENMASK(15, 15) 33 34 #define RTL8365MB_L2_UC_D5_DA_BLOCK_MSK GENMASK(0, 0) 35 #define RTL8365MB_L2_UC_D5_PRIORITY_MSK GENMASK(3, 1) 36 #define RTL8365MB_L2_UC_D5_FWD_PRI_MSK GENMASK(4, 4) 37 #define RTL8365MB_L2_UC_D5_STATIC_MSK GENMASK(5, 5) 38 39 #define RTL8365MB_L2_MC_D0_MAC5_MSK GENMASK(7, 0) 40 #define RTL8365MB_L2_MC_D0_MAC4_MSK GENMASK(15, 8) 41 #define RTL8365MB_L2_MC_D1_MAC3_MSK GENMASK(7, 0) 42 #define RTL8365MB_L2_MC_D1_MAC2_MSK GENMASK(15, 8) 43 #define RTL8365MB_L2_MC_D2_MAC1_MSK GENMASK(7, 0) 44 #define RTL8365MB_L2_MC_D2_MAC0_MSK GENMASK(15, 8) 45 #define RTL8365MB_L2_MC_D3_VID_MSK GENMASK(11, 0) 46 #define RTL8365MB_L2_MC_D3_IVL_MSK GENMASK(13, 13) 47 #define RTL8365MB_L2_MC_D3_MBR_HI1_MSK GENMASK(15, 14) 48 #define RTL8365MB_L2_MC_MBR_HI1_MSK GENMASK(9, 8) 49 50 #define RTL8365MB_L2_MC_D4_MBR_MSK GENMASK(7, 0) 51 #define RTL8365MB_L2_MC_MBR_LO_MSK GENMASK(7, 0) 52 #define RTL8365MB_L2_MC_D4_IGMPIDX_MSK GENMASK(15, 8) 53 54 #define RTL8365MB_L2_MC_D5_IGMP_ASIC_MSK GENMASK(0, 0) 55 #define RTL8365MB_L2_MC_D5_PRIORITY_MSK GENMASK(3, 1) 56 #define RTL8365MB_L2_MC_D5_FWD_PRI_MSK GENMASK(4, 4) 57 #define RTL8365MB_L2_MC_D5_STATIC_MSK GENMASK(5, 5) 58 #define RTL8365MB_L2_MC_D5_MBR_HI2_MSK GENMASK(7, 7) 59 #define RTL8365MB_L2_MC_MBR_HI2_MSK GENMASK(10, 10) 60 61 /* Port flush command registers - writing a 1 to the port's MASK bit will 62 * initiate the flush procedure. Completion is signalled when the corresponding 63 * BUSY bit is 0. 64 */ 65 #define RTL8365MB_L2_FLUSH_PORT_REG 0x0A36 66 #define RTL8365MB_L2_FLUSH_PORT_MSK_MSK GENMASK(7, 0) 67 #define RTL8365MB_L2_FLUSH_PORT_BUSY_MSK GENMASK(15, 8) 68 69 #define RTL8365MB_L2_FLUSH_PORT_EXT_REG 0x0A35 70 #define RTL8365MB_L2_FLUSH_PORT_EXT_MSK_MSK GENMASK(2, 0) 71 #define RTL8365MB_L2_FLUSH_PORT_EXT_BUSY_MSK GENMASK(5, 3) 72 73 #define RTL8365MB_L2_FLUSH_CTRL1_REG 0x0A37 74 #define RTL8365MB_L2_FLUSH_CTRL1_VID_MSK GENMASK(11, 0) 75 #define RTL8365MB_L2_FLUSH_CTRL1_FID_MSK GENMASK(15, 12) 76 77 #define RTL8365MB_L2_FLUSH_CTRL2_REG 0x0A38 78 #define RTL8365MB_L2_FLUSH_CTRL2_MODE_MSK GENMASK(1, 0) 79 #define RTL8365MB_L2_FLUSH_CTRL2_MODE_PORT 0 80 #define RTL8365MB_L2_FLUSH_CTRL2_MODE_PORT_VID 1 81 #define RTL8365MB_L2_FLUSH_CTRL2_MODE_PORT_FID 2 82 #define RTL8365MB_L2_FLUSH_CTRL2_TYPE_MSK GENMASK(2, 2) 83 #define RTL8365MB_L2_FLUSH_CTRL2_TYPE_DYNAMIC 0 84 #define RTL8365MB_L2_FLUSH_CTRL2_TYPE_BOTH 1 85 86 /* This flushes the entire LUT, reading it back it will turn 0 when the 87 * operation is complete 88 */ 89 #define RTL8365MB_L2_FLUSH_CTRL3_REG 0x0A39 90 #define RTL8365MB_L2_FLUSH_CTRL3_MSK GENMASK(0, 0) 91 92 struct rtl8365mb_l2_uc_key { 93 u8 mac_addr[ETH_ALEN]; 94 u16 vid; 95 u16 fid; 96 bool ivl; 97 u16 efid; 98 }; 99 100 struct rtl8365mb_l2_uc { 101 struct rtl8365mb_l2_uc_key key; 102 u8 port; 103 u8 age; 104 u8 priority; 105 106 bool sa_block; 107 bool da_block; 108 bool auth; 109 bool is_static; 110 bool sa_pri; 111 bool fwd_pri; 112 }; 113 114 struct rtl8365mb_l2_mc_key { 115 u8 mac_addr[ETH_ALEN]; 116 union { 117 u16 vid; /* IVL */ 118 u16 fid; /* SVL */ 119 }; 120 bool ivl; 121 }; 122 123 struct rtl8365mb_l2_mc { 124 struct rtl8365mb_l2_mc_key key; 125 u16 member; 126 u8 priority; 127 u8 igmpidx; 128 129 bool is_static; 130 bool fwd_pri; 131 bool igmp_asic; 132 }; 133 134 static void rtl8365mb_l2_data_to_uc(const u16 *data, struct rtl8365mb_l2_uc *uc) 135 { 136 u32 val; 137 138 uc->key.mac_addr[5] = FIELD_GET(RTL8365MB_L2_UC_D0_MAC5_MSK, data[0]); 139 uc->key.mac_addr[4] = FIELD_GET(RTL8365MB_L2_UC_D0_MAC4_MSK, data[0]); 140 uc->key.mac_addr[3] = FIELD_GET(RTL8365MB_L2_UC_D1_MAC3_MSK, data[1]); 141 uc->key.mac_addr[2] = FIELD_GET(RTL8365MB_L2_UC_D1_MAC2_MSK, data[1]); 142 uc->key.mac_addr[1] = FIELD_GET(RTL8365MB_L2_UC_D2_MAC1_MSK, data[2]); 143 uc->key.mac_addr[0] = FIELD_GET(RTL8365MB_L2_UC_D2_MAC0_MSK, data[2]); 144 uc->key.efid = FIELD_GET(RTL8365MB_L2_UC_D4_EFID_MSK, data[4]); 145 uc->key.vid = FIELD_GET(RTL8365MB_L2_UC_D3_VID_MSK, data[3]); 146 uc->key.ivl = FIELD_GET(RTL8365MB_L2_UC_D3_IVL_MSK, data[3]); 147 uc->key.fid = FIELD_GET(RTL8365MB_L2_UC_D4_FID_MSK, data[4]); 148 uc->age = FIELD_GET(RTL8365MB_L2_UC_D4_AGE_MSK, data[4]); 149 uc->auth = FIELD_GET(RTL8365MB_L2_UC_D4_AUTH_MSK, data[4]); 150 151 val = FIELD_GET(RTL8365MB_L2_UC_D4_PORT_MSK, data[4]); 152 uc->port = FIELD_PREP(RTL8365MB_L2_UC_PORT_LO_MSK, val); 153 val = FIELD_GET(RTL8365MB_L2_UC_D3_PORT_EXT_MSK, data[3]); 154 uc->port |= FIELD_PREP(RTL8365MB_L2_UC_PORT_HI_MSK, val); 155 156 uc->sa_pri = FIELD_GET(RTL8365MB_L2_UC_D4_SA_PRI_MSK, data[4]); 157 uc->fwd_pri = FIELD_GET(RTL8365MB_L2_UC_D5_FWD_PRI_MSK, data[5]); 158 uc->sa_block = FIELD_GET(RTL8365MB_L2_UC_D4_SA_BLOCK_MSK, data[4]); 159 uc->da_block = FIELD_GET(RTL8365MB_L2_UC_D5_DA_BLOCK_MSK, data[5]); 160 uc->priority = FIELD_GET(RTL8365MB_L2_UC_D5_PRIORITY_MSK, data[5]); 161 uc->is_static = FIELD_GET(RTL8365MB_L2_UC_D5_STATIC_MSK, data[5]); 162 } 163 164 static void rtl8365mb_l2_uc_to_data(const struct rtl8365mb_l2_uc *uc, u16 *data) 165 { 166 u32 val; 167 168 memset(data, 0, RTL8365MB_L2_ENTRY_SIZE * 2); 169 data[0] |= 170 FIELD_PREP(RTL8365MB_L2_UC_D0_MAC5_MSK, uc->key.mac_addr[5]); 171 data[0] |= 172 FIELD_PREP(RTL8365MB_L2_UC_D0_MAC4_MSK, uc->key.mac_addr[4]); 173 data[1] |= 174 FIELD_PREP(RTL8365MB_L2_UC_D1_MAC3_MSK, uc->key.mac_addr[3]); 175 data[1] |= 176 FIELD_PREP(RTL8365MB_L2_UC_D1_MAC2_MSK, uc->key.mac_addr[2]); 177 data[2] |= 178 FIELD_PREP(RTL8365MB_L2_UC_D2_MAC1_MSK, uc->key.mac_addr[1]); 179 data[2] |= 180 FIELD_PREP(RTL8365MB_L2_UC_D2_MAC0_MSK, uc->key.mac_addr[0]); 181 data[3] |= FIELD_PREP(RTL8365MB_L2_UC_D3_VID_MSK, uc->key.vid); 182 data[3] |= FIELD_PREP(RTL8365MB_L2_UC_D3_IVL_MSK, uc->key.ivl); 183 184 val = FIELD_GET(RTL8365MB_L2_UC_PORT_HI_MSK, uc->port); 185 data[3] |= FIELD_PREP(RTL8365MB_L2_UC_D3_PORT_EXT_MSK, val); 186 187 data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_FID_MSK, uc->key.fid); 188 data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_EFID_MSK, uc->key.efid); 189 data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_AGE_MSK, uc->age); 190 data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_AUTH_MSK, uc->auth); 191 192 val = FIELD_GET(RTL8365MB_L2_UC_PORT_LO_MSK, uc->port); 193 data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_PORT_MSK, val); 194 195 data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_SA_PRI_MSK, uc->sa_pri); 196 data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_SA_BLOCK_MSK, uc->sa_block); 197 data[5] |= FIELD_PREP(RTL8365MB_L2_UC_D5_FWD_PRI_MSK, uc->fwd_pri); 198 data[5] |= FIELD_PREP(RTL8365MB_L2_UC_D5_DA_BLOCK_MSK, uc->da_block); 199 data[5] |= FIELD_PREP(RTL8365MB_L2_UC_D5_PRIORITY_MSK, uc->priority); 200 data[5] |= FIELD_PREP(RTL8365MB_L2_UC_D5_STATIC_MSK, uc->is_static); 201 } 202 203 static void rtl8365mb_l2_data_to_mc(const u16 *data, struct rtl8365mb_l2_mc *mc) 204 { 205 u32 val; 206 207 mc->key.mac_addr[5] = FIELD_GET(RTL8365MB_L2_MC_D0_MAC5_MSK, data[0]); 208 mc->key.mac_addr[4] = FIELD_GET(RTL8365MB_L2_MC_D0_MAC4_MSK, data[0]); 209 mc->key.mac_addr[3] = FIELD_GET(RTL8365MB_L2_MC_D1_MAC3_MSK, data[1]); 210 mc->key.mac_addr[2] = FIELD_GET(RTL8365MB_L2_MC_D1_MAC2_MSK, data[1]); 211 mc->key.mac_addr[1] = FIELD_GET(RTL8365MB_L2_MC_D2_MAC1_MSK, data[2]); 212 mc->key.mac_addr[0] = FIELD_GET(RTL8365MB_L2_MC_D2_MAC0_MSK, data[2]); 213 /* key.vid,key.fid shares the same memory space */ 214 mc->key.vid = FIELD_GET(RTL8365MB_L2_MC_D3_VID_MSK, data[3]); 215 mc->key.ivl = FIELD_GET(RTL8365MB_L2_MC_D3_IVL_MSK, data[3]); 216 mc->priority = FIELD_GET(RTL8365MB_L2_MC_D5_PRIORITY_MSK, data[5]); 217 mc->fwd_pri = FIELD_GET(RTL8365MB_L2_MC_D5_FWD_PRI_MSK, data[5]); 218 mc->is_static = FIELD_GET(RTL8365MB_L2_MC_D5_STATIC_MSK, data[5]); 219 220 val = FIELD_GET(RTL8365MB_L2_MC_D4_MBR_MSK, data[4]); 221 mc->member = FIELD_PREP(RTL8365MB_L2_MC_MBR_LO_MSK, val); 222 val = FIELD_GET(RTL8365MB_L2_MC_D3_MBR_HI1_MSK, data[3]); 223 mc->member |= FIELD_PREP(RTL8365MB_L2_MC_MBR_HI1_MSK, val); 224 val = FIELD_GET(RTL8365MB_L2_MC_D5_MBR_HI2_MSK, data[5]); 225 mc->member |= FIELD_PREP(RTL8365MB_L2_MC_MBR_HI2_MSK, val); 226 227 mc->igmpidx = FIELD_GET(RTL8365MB_L2_MC_D4_IGMPIDX_MSK, data[4]); 228 mc->igmp_asic = FIELD_GET(RTL8365MB_L2_MC_D5_IGMP_ASIC_MSK, data[5]); 229 } 230 231 static void rtl8365mb_l2_mc_to_data(const struct rtl8365mb_l2_mc *mc, u16 *data) 232 { 233 u32 val; 234 235 memset(data, 0, RTL8365MB_L2_ENTRY_SIZE * 2); 236 data[0] |= FIELD_PREP(RTL8365MB_L2_MC_D0_MAC5_MSK, mc->key.mac_addr[5]); 237 data[0] |= FIELD_PREP(RTL8365MB_L2_MC_D0_MAC4_MSK, mc->key.mac_addr[4]); 238 data[1] |= FIELD_PREP(RTL8365MB_L2_MC_D1_MAC3_MSK, mc->key.mac_addr[3]); 239 data[1] |= FIELD_PREP(RTL8365MB_L2_MC_D1_MAC2_MSK, mc->key.mac_addr[2]); 240 data[2] |= FIELD_PREP(RTL8365MB_L2_MC_D2_MAC1_MSK, mc->key.mac_addr[1]); 241 data[2] |= FIELD_PREP(RTL8365MB_L2_MC_D2_MAC0_MSK, mc->key.mac_addr[0]); 242 data[3] |= FIELD_PREP(RTL8365MB_L2_MC_D3_VID_MSK, mc->key.vid); 243 data[3] |= FIELD_PREP(RTL8365MB_L2_MC_D3_IVL_MSK, mc->key.ivl); 244 245 val = FIELD_GET(RTL8365MB_L2_MC_MBR_HI1_MSK, mc->member); 246 data[3] |= FIELD_PREP(RTL8365MB_L2_MC_D3_MBR_HI1_MSK, val); 247 248 val = FIELD_GET(RTL8365MB_L2_MC_MBR_LO_MSK, mc->member); 249 data[4] |= FIELD_PREP(RTL8365MB_L2_MC_D4_MBR_MSK, val); 250 251 data[4] |= FIELD_PREP(RTL8365MB_L2_MC_D4_IGMPIDX_MSK, mc->igmpidx); 252 data[5] |= FIELD_PREP(RTL8365MB_L2_MC_D5_IGMP_ASIC_MSK, mc->igmp_asic); 253 data[5] |= FIELD_PREP(RTL8365MB_L2_MC_D5_PRIORITY_MSK, mc->priority); 254 data[5] |= FIELD_PREP(RTL8365MB_L2_MC_D5_FWD_PRI_MSK, mc->fwd_pri); 255 data[5] |= FIELD_PREP(RTL8365MB_L2_MC_D5_STATIC_MSK, mc->is_static); 256 257 val = FIELD_GET(RTL8365MB_L2_MC_MBR_HI2_MSK, mc->member); 258 data[5] |= FIELD_PREP(RTL8365MB_L2_MC_D5_MBR_HI2_MSK, val); 259 } 260 261 /* 262 * rtl8365mb_l2_get_next_uc() - get the next Unicast L2 entry 263 * @priv: realtek_priv pointer 264 * @addr: as input, the table index to start the walk 265 * as output, the found table index 266 * @port: restrict the walk on entries related to port 267 * @entry: returned L2 Unicast table entry 268 * 269 * This function gets the next unicast L2 table entry starting from @addr 270 * and checking exclusively entries related to @port. 271 * 272 * On success, it returns 0, updates @addr to the index of the found entry, 273 * and populates @entry. If the search reaches the end of the table and 274 * wraps around and @addr will be strictly lower than the input @addr. 275 * Callers must detect this wrap-around condition to prevent infinite loops. 276 * 277 * If the table contains no matching entries at all, it returns -ENOENT 278 * and leaves @addr and @entry unmodified. 279 * 280 * Return: Returns 0 on success, a negative error on failure. 281 **/ 282 int rtl8365mb_l2_get_next_uc(struct realtek_priv *priv, u16 *addr, int port, 283 struct realtek_fdb_entry *entry) 284 { 285 u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 }; 286 struct rtl8365mb_l2_uc uc; 287 int ret; 288 289 ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2, 290 RTL8365MB_TABLE_OP_READ, addr, 291 RTL8365MB_TABLE_L2_METHOD_ADDR_NEXT_UC_PORT, 292 port, data, RTL8365MB_L2_ENTRY_SIZE); 293 if (ret) 294 return ret; 295 296 rtl8365mb_l2_data_to_uc(data, &uc); 297 298 ether_addr_copy(entry->mac_addr, uc.key.mac_addr); 299 entry->vid = uc.key.vid; 300 entry->is_static = uc.is_static; 301 302 return 0; 303 } 304 305 int rtl8365mb_l2_add_uc(struct realtek_priv *priv, int port, 306 const unsigned char mac_addr[static ETH_ALEN], 307 u16 efid, u16 vid) 308 { 309 u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 }; 310 struct rtl8365mb_l2_uc uc = { 0 }; 311 u16 addr; 312 int ret; 313 314 memcpy(uc.key.mac_addr, mac_addr, ETH_ALEN); 315 uc.key.efid = efid; 316 uc.key.fid = 0; 317 uc.key.ivl = true; 318 uc.key.vid = vid; 319 320 uc.port = port; 321 /* Entries programmed by DSA (including those dynamically learned by 322 * the software bridge and injected into the CPU port via assisted 323 * learning) must be static. We do not let HW decrease age behind the 324 * OS's back. As a trade-off, these will show up as permanent to users. 325 */ 326 uc.is_static = true; 327 /* age greater than 0 adds/updates entries */ 328 uc.age = 1; 329 rtl8365mb_l2_uc_to_data(&uc, data); 330 331 /* add the new entry or update an existing one */ 332 ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2, 333 RTL8365MB_TABLE_OP_WRITE, &addr, 334 0, 0, 335 data, RTL8365MB_L2_ENTRY_SIZE); 336 337 /* Assume the missing new entry as the table is full */ 338 if (ret == -ENOENT) 339 return -ENOSPC; 340 341 /* addr will hold the table index, but it is not used here */ 342 return ret; 343 } 344 345 int rtl8365mb_l2_del_uc(struct realtek_priv *priv, int port, 346 const unsigned char mac_addr[static ETH_ALEN], 347 u16 efid, u16 vid) 348 { 349 u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 }; 350 struct rtl8365mb_l2_uc uc = { 0 }; 351 u16 addr; 352 int ret; 353 354 memcpy(uc.key.mac_addr, mac_addr, ETH_ALEN); 355 uc.key.efid = efid; 356 uc.key.fid = 0; 357 uc.key.ivl = true; 358 uc.key.vid = vid; 359 /* age 0 deletes the entry */ 360 uc.age = 0; 361 rtl8365mb_l2_uc_to_data(&uc, data); 362 363 /* it looks like the switch will always add/update the entry, 364 * even when age is 0 or uc.key did not match an existing entry, 365 * just to immediately drop it because age is zero. You can still 366 * get the added/updated address from @addr 367 */ 368 ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2, 369 RTL8365MB_TABLE_OP_WRITE, &addr, 370 0, 0, 371 data, RTL8365MB_L2_ENTRY_SIZE); 372 373 if (ret == -ENOENT) { 374 dev_dbg(priv->dev, "%s: %pM vid=%d efid=%d missing\n", 375 __func__, mac_addr, vid, efid); 376 /* Silently return success */ 377 return 0; 378 } 379 380 /* addr will hold the table index, but it is not used here */ 381 return ret; 382 } 383 384 int rtl8365mb_l2_flush(struct realtek_priv *priv, int port, u16 vid) 385 { 386 int mode = vid ? RTL8365MB_L2_FLUSH_CTRL2_MODE_PORT_VID : 387 RTL8365MB_L2_FLUSH_CTRL2_MODE_PORT; 388 u32 val, mask; 389 int ret; 390 391 mutex_lock(&priv->map_lock); 392 393 /* Configure flushing mode; only flush dynamic entries */ 394 ret = regmap_write(priv->map_nolock, RTL8365MB_L2_FLUSH_CTRL2_REG, 395 FIELD_PREP(RTL8365MB_L2_FLUSH_CTRL2_MODE_MSK, 396 mode) | 397 FIELD_PREP(RTL8365MB_L2_FLUSH_CTRL2_TYPE_MSK, 398 RTL8365MB_L2_FLUSH_CTRL2_TYPE_DYNAMIC)); 399 if (ret) 400 goto out; 401 402 ret = regmap_write(priv->map_nolock, RTL8365MB_L2_FLUSH_CTRL1_REG, 403 FIELD_PREP(RTL8365MB_L2_FLUSH_CTRL1_VID_MSK, vid)); 404 405 if (ret) 406 goto out; 407 /* Now issue the flush command and wait for its completion. There are 408 * two registers for this purpose, and which one to use depends on the 409 * port number. The _EXT register is for ports 8 or higher. 410 */ 411 if (port < 8) { 412 val = FIELD_PREP(RTL8365MB_L2_FLUSH_PORT_MSK_MSK, 413 BIT(port) & 0xFF); 414 ret = regmap_write(priv->map_nolock, 415 RTL8365MB_L2_FLUSH_PORT_REG, val); 416 if (ret) 417 goto out; 418 419 mask = FIELD_PREP(RTL8365MB_L2_FLUSH_PORT_BUSY_MSK, 420 BIT(port) & 0xFF); 421 ret = regmap_read_poll_timeout(priv->map_nolock, 422 RTL8365MB_L2_FLUSH_PORT_REG, 423 val, !(val & mask), 10, 10000); 424 if (ret) 425 goto out; 426 } else { 427 val = FIELD_PREP(RTL8365MB_L2_FLUSH_PORT_EXT_MSK_MSK, 428 BIT(port) >> 8); 429 ret = regmap_write(priv->map_nolock, 430 RTL8365MB_L2_FLUSH_PORT_EXT_REG, val); 431 if (ret) 432 goto out; 433 434 mask = FIELD_PREP(RTL8365MB_L2_FLUSH_PORT_EXT_BUSY_MSK, 435 BIT(port) >> 8); 436 ret = regmap_read_poll_timeout(priv->map_nolock, 437 RTL8365MB_L2_FLUSH_PORT_EXT_REG, 438 val, !(val & mask), 10, 10000); 439 if (ret) 440 goto out; 441 } 442 443 out: 444 mutex_unlock(&priv->map_lock); 445 446 return ret; 447 } 448 449 int rtl8365mb_l2_add_mc(struct realtek_priv *priv, int port, 450 const unsigned char mac_addr[static ETH_ALEN], 451 u16 vid) 452 { 453 u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 }; 454 struct rtl8365mb_l2_mc mc = { 0 }; 455 u16 addr; 456 int ret; 457 458 memcpy(mc.key.mac_addr, mac_addr, ETH_ALEN); 459 mc.key.vid = vid; 460 mc.key.ivl = true; 461 /* Already set the port and is_static, although not used in OP_READ, 462 * data will be ready for OP_WRITE if it is a new entry. 463 */ 464 mc.member |= BIT(port); 465 mc.is_static = 1; 466 rtl8365mb_l2_mc_to_data(&mc, data); 467 468 /* First look for an existing entry (to get existing port members) */ 469 ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2, 470 RTL8365MB_TABLE_OP_READ, &addr, 471 RTL8365MB_TABLE_L2_METHOD_MAC, 0, 472 data, RTL8365MB_L2_ENTRY_SIZE); 473 if (!ret) { 474 /* There is already an entry... */ 475 rtl8365mb_l2_data_to_mc(data, &mc); 476 dev_dbg(priv->dev, 477 "%s: found %pM addr=%d member=0x%x igmpidx=0x%x %s\n", 478 __func__, mac_addr, addr, mc.member, mc.igmpidx, 479 mc.is_static ? "static" : "dynamic"); 480 /* the port must be added as a member */ 481 mc.member |= BIT(port); 482 483 if (!mc.is_static) { 484 dev_dbg(priv->dev, 485 "%s: promoting addr=%d group to static\n", 486 __func__, addr); 487 mc.is_static = 1; 488 } 489 490 rtl8365mb_l2_mc_to_data(&mc, data); 491 } else if (ret == -ENOENT) { 492 /* New entry, no need to update data again as it already 493 * includes the member. 494 * 495 * Multicast hardware entries do not support EFID (bridge 496 * isolation). However, traffic isolation is still maintained 497 * because the hardware applies the port isolation masks 498 * (pmasks) configured in bridge_join after the L2 lookup. 499 * Entries from different bridges will collide on the same 500 * MAC+VID slot with an OR'ed member mask, but packets will 501 * only exit through ports allowed by the source port's pmask. 502 */ 503 } else { 504 return ret; 505 } 506 507 /* add the new entry or update an existing one */ 508 ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2, 509 RTL8365MB_TABLE_OP_WRITE, &addr, 510 0, 0, 511 data, RTL8365MB_L2_ENTRY_SIZE); 512 513 /* Assume the missing new entry as the table is full */ 514 if (ret == -ENOENT) 515 return -ENOSPC; 516 517 return ret; 518 } 519 520 int rtl8365mb_l2_del_mc(struct realtek_priv *priv, int port, 521 const unsigned char mac_addr[static ETH_ALEN], 522 u16 vid) 523 { 524 u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 }; 525 struct rtl8365mb_l2_mc mc = { 0 }; 526 u16 addr; 527 int ret; 528 529 memcpy(mc.key.mac_addr, mac_addr, ETH_ALEN); 530 mc.key.vid = vid; 531 mc.key.ivl = true; 532 rtl8365mb_l2_mc_to_data(&mc, data); 533 534 /* First look for an existing entry (to get existing port members) */ 535 ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2, 536 RTL8365MB_TABLE_OP_READ, &addr, 537 RTL8365MB_TABLE_L2_METHOD_MAC, 0, 538 data, RTL8365MB_L2_ENTRY_SIZE); 539 if (ret == -ENOENT) { 540 dev_dbg(priv->dev, "%s: %pM vid=%d missing\n", 541 __func__, mac_addr, vid); 542 /* Silently return success */ 543 return 0; 544 } 545 546 if (ret) 547 /* Return on any other error */ 548 return ret; 549 550 rtl8365mb_l2_data_to_mc(data, &mc); 551 dev_dbg(priv->dev, 552 "%s: found %pM addr=%d member=0x%x igmpidx=0x%x %s\n", 553 __func__, mac_addr, addr, mc.member, mc.igmpidx, 554 mc.is_static ? "static" : "dynamic"); 555 /* the port must be removed as a member */ 556 mc.member &= ~BIT(port); 557 if (!mc.member) { 558 /* Multicast entries do not have an age field. Clearing both 559 * the member portmask and is_static flags is the hardware 560 * signal to invalidate and reclaim the L2 table slot. 561 */ 562 mc.is_static = 0; 563 mc.igmpidx = 0; 564 mc.priority = 0; 565 mc.fwd_pri = 0; 566 mc.igmp_asic = 0; 567 } 568 rtl8365mb_l2_mc_to_data(&mc, data); 569 570 /* update the existing entry. */ 571 ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2, 572 RTL8365MB_TABLE_OP_WRITE, &addr, 573 0, 0, 574 data, RTL8365MB_L2_ENTRY_SIZE); 575 return ret; 576 } 577