1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> 3 */ 4 #include "sja1105.h" 5 6 /* In the dynamic configuration interface, the switch exposes a register-like 7 * view of some of the static configuration tables. 8 * Many times the field organization of the dynamic tables is abbreviated (not 9 * all fields are dynamically reconfigurable) and different from the static 10 * ones, but the key reason for having it is that we can spare a switch reset 11 * for settings that can be changed dynamically. 12 * 13 * This file creates a per-switch-family abstraction called 14 * struct sja1105_dynamic_table_ops and two operations that work with it: 15 * - sja1105_dynamic_config_write 16 * - sja1105_dynamic_config_read 17 * 18 * Compared to the struct sja1105_table_ops from sja1105_static_config.c, 19 * the dynamic accessors work with a compound buffer: 20 * 21 * packed_buf 22 * 23 * | 24 * V 25 * +-----------------------------------------+------------------+ 26 * | ENTRY BUFFER | COMMAND BUFFER | 27 * +-----------------------------------------+------------------+ 28 * 29 * <----------------------- packed_size ------------------------> 30 * 31 * The ENTRY BUFFER may or may not have the same layout, or size, as its static 32 * configuration table entry counterpart. When it does, the same packing 33 * function is reused (bar exceptional cases - see 34 * sja1105pqrs_dyn_l2_lookup_entry_packing). 35 * 36 * The reason for the COMMAND BUFFER being at the end is to be able to send 37 * a dynamic write command through a single SPI burst. By the time the switch 38 * reacts to the command, the ENTRY BUFFER is already populated with the data 39 * sent by the core. 40 * 41 * The COMMAND BUFFER is always SJA1105_SIZE_DYN_CMD bytes (one 32-bit word) in 42 * size. 43 * 44 * Sometimes the ENTRY BUFFER does not really exist (when the number of fields 45 * that can be reconfigured is small), then the switch repurposes some of the 46 * unused 32 bits of the COMMAND BUFFER to hold ENTRY data. 47 * 48 * The key members of struct sja1105_dynamic_table_ops are: 49 * - .entry_packing: A function that deals with packing an ENTRY structure 50 * into an SPI buffer, or retrieving an ENTRY structure 51 * from one. 52 * The @packed_buf pointer it's given does always point to 53 * the ENTRY portion of the buffer. 54 * - .cmd_packing: A function that deals with packing/unpacking the COMMAND 55 * structure to/from the SPI buffer. 56 * It is given the same @packed_buf pointer as .entry_packing, 57 * so most of the time, the @packed_buf points *behind* the 58 * COMMAND offset inside the buffer. 59 * To access the COMMAND portion of the buffer, the function 60 * knows its correct offset. 61 * Giving both functions the same pointer is handy because in 62 * extreme cases (see sja1105pqrs_dyn_l2_lookup_entry_packing) 63 * the .entry_packing is able to jump to the COMMAND portion, 64 * or vice-versa (sja1105pqrs_l2_lookup_cmd_packing). 65 * - .access: A bitmap of: 66 * OP_READ: Set if the hardware manual marks the ENTRY portion of the 67 * dynamic configuration table buffer as R (readable) after 68 * an SPI read command (the switch will populate the buffer). 69 * OP_WRITE: Set if the manual marks the ENTRY portion of the dynamic 70 * table buffer as W (writable) after an SPI write command 71 * (the switch will read the fields provided in the buffer). 72 * OP_DEL: Set if the manual says the VALIDENT bit is supported in the 73 * COMMAND portion of this dynamic config buffer (i.e. the 74 * specified entry can be invalidated through a SPI write 75 * command). 76 * OP_SEARCH: Set if the manual says that the index of an entry can 77 * be retrieved in the COMMAND portion of the buffer based 78 * on its ENTRY portion, as a result of a SPI write command. 79 * Only the TCAM-based FDB table on SJA1105 P/Q/R/S supports 80 * this. 81 * - .max_entry_count: The number of entries, counting from zero, that can be 82 * reconfigured through the dynamic interface. If a static 83 * table can be reconfigured at all dynamically, this 84 * number always matches the maximum number of supported 85 * static entries. 86 * - .packed_size: The length in bytes of the compound ENTRY + COMMAND BUFFER. 87 * Note that sometimes the compound buffer may contain holes in 88 * it (see sja1105_vlan_lookup_cmd_packing). The @packed_buf is 89 * contiguous however, so @packed_size includes any unused 90 * bytes. 91 * - .addr: The base SPI address at which the buffer must be written to the 92 * switch's memory. When looking at the hardware manual, this must 93 * always match the lowest documented address for the ENTRY, and not 94 * that of the COMMAND, since the other 32-bit words will follow along 95 * at the correct addresses. 96 */ 97 98 #define SJA1105_SIZE_DYN_CMD 4 99 100 #define SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD \ 101 SJA1105_SIZE_DYN_CMD 102 103 #define SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD \ 104 (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_VL_LOOKUP_ENTRY) 105 106 #define SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY \ 107 SJA1105_SIZE_DYN_CMD 108 109 #define SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD \ 110 (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_L2_LOOKUP_ENTRY) 111 112 #define SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD \ 113 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY) 114 115 #define SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD \ 116 (SJA1105_SIZE_DYN_CMD + 4 + SJA1105_SIZE_VLAN_LOOKUP_ENTRY) 117 118 #define SJA1105_SIZE_L2_FORWARDING_DYN_CMD \ 119 (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_FORWARDING_ENTRY) 120 121 #define SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD \ 122 (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY) 123 124 #define SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD \ 125 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY) 126 127 #define SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD \ 128 SJA1105_SIZE_DYN_CMD 129 130 #define SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_DYN_CMD \ 131 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY) 132 133 #define SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD \ 134 SJA1105_SIZE_DYN_CMD 135 136 #define SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD \ 137 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY) 138 139 #define SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD \ 140 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY) 141 142 #define SJA1105_SIZE_RETAGGING_DYN_CMD \ 143 (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_RETAGGING_ENTRY) 144 145 #define SJA1105ET_SIZE_CBS_DYN_CMD \ 146 (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_CBS_ENTRY) 147 148 #define SJA1105PQRS_SIZE_CBS_DYN_CMD \ 149 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_CBS_ENTRY) 150 151 #define SJA1105_MAX_DYN_CMD_SIZE \ 152 SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD 153 154 struct sja1105_dyn_cmd { 155 bool search; 156 u64 valid; 157 u64 rdwrset; 158 u64 errors; 159 u64 valident; 160 u64 index; 161 }; 162 163 enum sja1105_hostcmd { 164 SJA1105_HOSTCMD_SEARCH = 1, 165 SJA1105_HOSTCMD_READ = 2, 166 SJA1105_HOSTCMD_WRITE = 3, 167 SJA1105_HOSTCMD_INVALIDATE = 4, 168 }; 169 170 /* Command and entry overlap */ 171 static void 172 sja1105et_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 173 enum packing_op op) 174 { 175 const int size = SJA1105_SIZE_DYN_CMD; 176 177 sja1105_packing(buf, &cmd->valid, 31, 31, size, op); 178 sja1105_packing(buf, &cmd->errors, 30, 30, size, op); 179 sja1105_packing(buf, &cmd->rdwrset, 29, 29, size, op); 180 sja1105_packing(buf, &cmd->index, 9, 0, size, op); 181 } 182 183 /* Command and entry are separate */ 184 static void 185 sja1105pqrs_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 186 enum packing_op op) 187 { 188 u8 *p = buf + SJA1105_SIZE_VL_LOOKUP_ENTRY; 189 const int size = SJA1105_SIZE_DYN_CMD; 190 191 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 192 sja1105_packing(p, &cmd->errors, 30, 30, size, op); 193 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op); 194 sja1105_packing(p, &cmd->index, 9, 0, size, op); 195 } 196 197 static size_t sja1105et_vl_lookup_entry_packing(void *buf, void *entry_ptr, 198 enum packing_op op) 199 { 200 struct sja1105_vl_lookup_entry *entry = entry_ptr; 201 const int size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD; 202 203 sja1105_packing(buf, &entry->egrmirr, 21, 17, size, op); 204 sja1105_packing(buf, &entry->ingrmirr, 16, 16, size, op); 205 return size; 206 } 207 208 static void 209 sja1105pqrs_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 210 enum packing_op op) 211 { 212 u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 213 const int size = SJA1105_SIZE_DYN_CMD; 214 u64 hostcmd; 215 216 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 217 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 218 sja1105_packing(p, &cmd->errors, 29, 29, size, op); 219 sja1105_packing(p, &cmd->valident, 27, 27, size, op); 220 221 /* VALIDENT is supposed to indicate "keep or not", but in SJA1105 E/T, 222 * using it to delete a management route was unsupported. UM10944 223 * said about it: 224 * 225 * In case of a write access with the MGMTROUTE flag set, 226 * the flag will be ignored. It will always be found cleared 227 * for read accesses with the MGMTROUTE flag set. 228 * 229 * SJA1105 P/Q/R/S keeps the same behavior w.r.t. VALIDENT, but there 230 * is now another flag called HOSTCMD which does more stuff (quoting 231 * from UM11040): 232 * 233 * A write request is accepted only when HOSTCMD is set to write host 234 * or invalid. A read request is accepted only when HOSTCMD is set to 235 * search host or read host. 236 * 237 * So it is possible to translate a RDWRSET/VALIDENT combination into 238 * HOSTCMD so that we keep the dynamic command API in place, and 239 * at the same time achieve compatibility with the management route 240 * command structure. 241 */ 242 if (cmd->rdwrset == SPI_READ) { 243 if (cmd->search) 244 hostcmd = SJA1105_HOSTCMD_SEARCH; 245 else 246 hostcmd = SJA1105_HOSTCMD_READ; 247 } else { 248 /* SPI_WRITE */ 249 if (cmd->valident) 250 hostcmd = SJA1105_HOSTCMD_WRITE; 251 else 252 hostcmd = SJA1105_HOSTCMD_INVALIDATE; 253 } 254 sja1105_packing(p, &hostcmd, 25, 23, size, op); 255 256 /* Hack - The hardware takes the 'index' field within 257 * struct sja1105_l2_lookup_entry as the index on which this command 258 * will operate. However it will ignore everything else, so 'index' 259 * is logically part of command but physically part of entry. 260 * Populate the 'index' entry field from within the command callback, 261 * such that our API doesn't need to ask for a full-blown entry 262 * structure when e.g. a delete is requested. 263 */ 264 sja1105_packing(buf, &cmd->index, 15, 6, 265 SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY, op); 266 } 267 268 /* The switch is so retarded that it makes our command/entry abstraction 269 * crumble apart. 270 * 271 * On P/Q/R/S, the switch tries to say whether a FDB entry 272 * is statically programmed or dynamically learned via a flag called LOCKEDS. 273 * The hardware manual says about this fiels: 274 * 275 * On write will specify the format of ENTRY. 276 * On read the flag will be found cleared at times the VALID flag is found 277 * set. The flag will also be found cleared in response to a read having the 278 * MGMTROUTE flag set. In response to a read with the MGMTROUTE flag 279 * cleared, the flag be set if the most recent access operated on an entry 280 * that was either loaded by configuration or through dynamic reconfiguration 281 * (as opposed to automatically learned entries). 282 * 283 * The trouble with this flag is that it's part of the *command* to access the 284 * dynamic interface, and not part of the *entry* retrieved from it. 285 * Otherwise said, for a sja1105_dynamic_config_read, LOCKEDS is supposed to be 286 * an output from the switch into the command buffer, and for a 287 * sja1105_dynamic_config_write, the switch treats LOCKEDS as an input 288 * (hence we can write either static, or automatically learned entries, from 289 * the core). 290 * But the manual contradicts itself in the last phrase where it says that on 291 * read, LOCKEDS will be set to 1 for all FDB entries written through the 292 * dynamic interface (therefore, the value of LOCKEDS from the 293 * sja1105_dynamic_config_write is not really used for anything, it'll store a 294 * 1 anyway). 295 * This means you can't really write a FDB entry with LOCKEDS=0 (automatically 296 * learned) into the switch, which kind of makes sense. 297 * As for reading through the dynamic interface, it doesn't make too much sense 298 * to put LOCKEDS into the command, since the switch will inevitably have to 299 * ignore it (otherwise a command would be like "read the FDB entry 123, but 300 * only if it's dynamically learned" <- well how am I supposed to know?) and 301 * just use it as an output buffer for its findings. But guess what... that's 302 * what the entry buffer is for! 303 * Unfortunately, what really breaks this abstraction is the fact that it 304 * wasn't designed having the fact in mind that the switch can output 305 * entry-related data as writeback through the command buffer. 306 * However, whether a FDB entry is statically or dynamically learned *is* part 307 * of the entry and not the command data, no matter what the switch thinks. 308 * In order to do that, we'll need to wrap around the 309 * sja1105pqrs_l2_lookup_entry_packing from sja1105_static_config.c, and take 310 * a peek outside of the caller-supplied @buf (the entry buffer), to reach the 311 * command buffer. 312 */ 313 static size_t 314 sja1105pqrs_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr, 315 enum packing_op op) 316 { 317 struct sja1105_l2_lookup_entry *entry = entry_ptr; 318 u8 *cmd = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 319 const int size = SJA1105_SIZE_DYN_CMD; 320 321 sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op); 322 323 return sja1105pqrs_l2_lookup_entry_packing(buf, entry_ptr, op); 324 } 325 326 static void 327 sja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 328 enum packing_op op) 329 { 330 u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY; 331 const int size = SJA1105_SIZE_DYN_CMD; 332 333 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 334 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 335 sja1105_packing(p, &cmd->errors, 29, 29, size, op); 336 sja1105_packing(p, &cmd->valident, 27, 27, size, op); 337 /* Hack - see comments above. */ 338 sja1105_packing(buf, &cmd->index, 29, 20, 339 SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op); 340 } 341 342 static size_t sja1105et_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr, 343 enum packing_op op) 344 { 345 struct sja1105_l2_lookup_entry *entry = entry_ptr; 346 u8 *cmd = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY; 347 const int size = SJA1105_SIZE_DYN_CMD; 348 349 sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op); 350 351 return sja1105et_l2_lookup_entry_packing(buf, entry_ptr, op); 352 } 353 354 static void 355 sja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 356 enum packing_op op) 357 { 358 u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY; 359 u64 mgmtroute = 1; 360 361 sja1105et_l2_lookup_cmd_packing(buf, cmd, op); 362 if (op == PACK) 363 sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD); 364 } 365 366 static size_t sja1105et_mgmt_route_entry_packing(void *buf, void *entry_ptr, 367 enum packing_op op) 368 { 369 struct sja1105_mgmt_entry *entry = entry_ptr; 370 const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY; 371 372 /* UM10944: To specify if a PTP egress timestamp shall be captured on 373 * each port upon transmission of the frame, the LSB of VLANID in the 374 * ENTRY field provided by the host must be set. 375 * Bit 1 of VLANID then specifies the register where the timestamp for 376 * this port is stored in. 377 */ 378 sja1105_packing(buf, &entry->tsreg, 85, 85, size, op); 379 sja1105_packing(buf, &entry->takets, 84, 84, size, op); 380 sja1105_packing(buf, &entry->macaddr, 83, 36, size, op); 381 sja1105_packing(buf, &entry->destports, 35, 31, size, op); 382 sja1105_packing(buf, &entry->enfport, 30, 30, size, op); 383 return size; 384 } 385 386 static void 387 sja1105pqrs_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 388 enum packing_op op) 389 { 390 u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 391 u64 mgmtroute = 1; 392 393 sja1105pqrs_l2_lookup_cmd_packing(buf, cmd, op); 394 if (op == PACK) 395 sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD); 396 } 397 398 static size_t sja1105pqrs_mgmt_route_entry_packing(void *buf, void *entry_ptr, 399 enum packing_op op) 400 { 401 const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 402 struct sja1105_mgmt_entry *entry = entry_ptr; 403 404 /* In P/Q/R/S, enfport got renamed to mgmtvalid, but its purpose 405 * is the same (driver uses it to confirm that frame was sent). 406 * So just keep the name from E/T. 407 */ 408 sja1105_packing(buf, &entry->tsreg, 71, 71, size, op); 409 sja1105_packing(buf, &entry->takets, 70, 70, size, op); 410 sja1105_packing(buf, &entry->macaddr, 69, 22, size, op); 411 sja1105_packing(buf, &entry->destports, 21, 17, size, op); 412 sja1105_packing(buf, &entry->enfport, 16, 16, size, op); 413 return size; 414 } 415 416 /* In E/T, entry is at addresses 0x27-0x28. There is a 4 byte gap at 0x29, 417 * and command is at 0x2a. Similarly in P/Q/R/S there is a 1 register gap 418 * between entry (0x2d, 0x2e) and command (0x30). 419 */ 420 static void 421 sja1105_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 422 enum packing_op op) 423 { 424 u8 *p = buf + SJA1105_SIZE_VLAN_LOOKUP_ENTRY + 4; 425 const int size = SJA1105_SIZE_DYN_CMD; 426 427 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 428 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 429 sja1105_packing(p, &cmd->valident, 27, 27, size, op); 430 /* Hack - see comments above, applied for 'vlanid' field of 431 * struct sja1105_vlan_lookup_entry. 432 */ 433 sja1105_packing(buf, &cmd->index, 38, 27, 434 SJA1105_SIZE_VLAN_LOOKUP_ENTRY, op); 435 } 436 437 static void 438 sja1105_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 439 enum packing_op op) 440 { 441 u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY; 442 const int size = SJA1105_SIZE_DYN_CMD; 443 444 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 445 sja1105_packing(p, &cmd->errors, 30, 30, size, op); 446 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op); 447 sja1105_packing(p, &cmd->index, 4, 0, size, op); 448 } 449 450 static void 451 sja1105et_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 452 enum packing_op op) 453 { 454 const int size = SJA1105_SIZE_DYN_CMD; 455 /* Yup, user manual definitions are reversed */ 456 u8 *reg1 = buf + 4; 457 458 sja1105_packing(reg1, &cmd->valid, 31, 31, size, op); 459 sja1105_packing(reg1, &cmd->index, 26, 24, size, op); 460 } 461 462 static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr, 463 enum packing_op op) 464 { 465 const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY; 466 struct sja1105_mac_config_entry *entry = entry_ptr; 467 /* Yup, user manual definitions are reversed */ 468 u8 *reg1 = buf + 4; 469 u8 *reg2 = buf; 470 471 sja1105_packing(reg1, &entry->speed, 30, 29, size, op); 472 sja1105_packing(reg1, &entry->drpdtag, 23, 23, size, op); 473 sja1105_packing(reg1, &entry->drpuntag, 22, 22, size, op); 474 sja1105_packing(reg1, &entry->retag, 21, 21, size, op); 475 sja1105_packing(reg1, &entry->dyn_learn, 20, 20, size, op); 476 sja1105_packing(reg1, &entry->egress, 19, 19, size, op); 477 sja1105_packing(reg1, &entry->ingress, 18, 18, size, op); 478 sja1105_packing(reg1, &entry->ing_mirr, 17, 17, size, op); 479 sja1105_packing(reg1, &entry->egr_mirr, 16, 16, size, op); 480 sja1105_packing(reg1, &entry->vlanprio, 14, 12, size, op); 481 sja1105_packing(reg1, &entry->vlanid, 11, 0, size, op); 482 sja1105_packing(reg2, &entry->tp_delin, 31, 16, size, op); 483 sja1105_packing(reg2, &entry->tp_delout, 15, 0, size, op); 484 /* MAC configuration table entries which can't be reconfigured: 485 * top, base, enabled, ifg, maxage, drpnona664 486 */ 487 /* Bogus return value, not used anywhere */ 488 return 0; 489 } 490 491 static void 492 sja1105pqrs_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 493 enum packing_op op) 494 { 495 const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY; 496 u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY; 497 498 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 499 sja1105_packing(p, &cmd->errors, 30, 30, size, op); 500 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op); 501 sja1105_packing(p, &cmd->index, 2, 0, size, op); 502 } 503 504 static void 505 sja1105et_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 506 enum packing_op op) 507 { 508 sja1105_packing(buf, &cmd->valid, 31, 31, 509 SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op); 510 } 511 512 static size_t 513 sja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr, 514 enum packing_op op) 515 { 516 struct sja1105_l2_lookup_params_entry *entry = entry_ptr; 517 518 sja1105_packing(buf, &entry->poly, 7, 0, 519 SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op); 520 /* Bogus return value, not used anywhere */ 521 return 0; 522 } 523 524 static void 525 sja1105pqrs_l2_lookup_params_cmd_packing(void *buf, 526 struct sja1105_dyn_cmd *cmd, 527 enum packing_op op) 528 { 529 u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY; 530 const int size = SJA1105_SIZE_DYN_CMD; 531 532 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 533 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 534 } 535 536 static void 537 sja1105et_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 538 enum packing_op op) 539 { 540 const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD; 541 542 sja1105_packing(buf, &cmd->valid, 31, 31, size, op); 543 sja1105_packing(buf, &cmd->errors, 30, 30, size, op); 544 } 545 546 static size_t 547 sja1105et_general_params_entry_packing(void *buf, void *entry_ptr, 548 enum packing_op op) 549 { 550 struct sja1105_general_params_entry *entry = entry_ptr; 551 const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD; 552 553 sja1105_packing(buf, &entry->mirr_port, 2, 0, size, op); 554 /* Bogus return value, not used anywhere */ 555 return 0; 556 } 557 558 static void 559 sja1105pqrs_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 560 enum packing_op op) 561 { 562 u8 *p = buf + SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY; 563 const int size = SJA1105_SIZE_DYN_CMD; 564 565 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 566 sja1105_packing(p, &cmd->errors, 30, 30, size, op); 567 sja1105_packing(p, &cmd->rdwrset, 28, 28, size, op); 568 } 569 570 static void 571 sja1105pqrs_avb_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 572 enum packing_op op) 573 { 574 u8 *p = buf + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY; 575 const int size = SJA1105_SIZE_DYN_CMD; 576 577 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 578 sja1105_packing(p, &cmd->errors, 30, 30, size, op); 579 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op); 580 } 581 582 static void 583 sja1105_retagging_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 584 enum packing_op op) 585 { 586 u8 *p = buf + SJA1105_SIZE_RETAGGING_ENTRY; 587 const int size = SJA1105_SIZE_DYN_CMD; 588 589 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 590 sja1105_packing(p, &cmd->errors, 30, 30, size, op); 591 sja1105_packing(p, &cmd->valident, 29, 29, size, op); 592 sja1105_packing(p, &cmd->rdwrset, 28, 28, size, op); 593 sja1105_packing(p, &cmd->index, 5, 0, size, op); 594 } 595 596 static void sja1105et_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 597 enum packing_op op) 598 { 599 u8 *p = buf + SJA1105ET_SIZE_CBS_ENTRY; 600 const int size = SJA1105_SIZE_DYN_CMD; 601 602 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 603 sja1105_packing(p, &cmd->index, 19, 16, size, op); 604 } 605 606 static size_t sja1105et_cbs_entry_packing(void *buf, void *entry_ptr, 607 enum packing_op op) 608 { 609 const size_t size = SJA1105ET_SIZE_CBS_ENTRY; 610 struct sja1105_cbs_entry *entry = entry_ptr; 611 u8 *cmd = buf + size; 612 u32 *p = buf; 613 614 sja1105_packing(cmd, &entry->port, 5, 3, SJA1105_SIZE_DYN_CMD, op); 615 sja1105_packing(cmd, &entry->prio, 2, 0, SJA1105_SIZE_DYN_CMD, op); 616 sja1105_packing(p + 3, &entry->credit_lo, 31, 0, size, op); 617 sja1105_packing(p + 2, &entry->credit_hi, 31, 0, size, op); 618 sja1105_packing(p + 1, &entry->send_slope, 31, 0, size, op); 619 sja1105_packing(p + 0, &entry->idle_slope, 31, 0, size, op); 620 return size; 621 } 622 623 static void sja1105pqrs_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 624 enum packing_op op) 625 { 626 u8 *p = buf + SJA1105PQRS_SIZE_CBS_ENTRY; 627 const int size = SJA1105_SIZE_DYN_CMD; 628 629 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 630 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 631 sja1105_packing(p, &cmd->errors, 29, 29, size, op); 632 sja1105_packing(p, &cmd->index, 3, 0, size, op); 633 } 634 635 static size_t sja1105pqrs_cbs_entry_packing(void *buf, void *entry_ptr, 636 enum packing_op op) 637 { 638 const size_t size = SJA1105PQRS_SIZE_CBS_ENTRY; 639 struct sja1105_cbs_entry *entry = entry_ptr; 640 641 sja1105_packing(buf, &entry->port, 159, 157, size, op); 642 sja1105_packing(buf, &entry->prio, 156, 154, size, op); 643 sja1105_packing(buf, &entry->credit_lo, 153, 122, size, op); 644 sja1105_packing(buf, &entry->credit_hi, 121, 90, size, op); 645 sja1105_packing(buf, &entry->send_slope, 89, 58, size, op); 646 sja1105_packing(buf, &entry->idle_slope, 57, 26, size, op); 647 return size; 648 } 649 650 #define OP_READ BIT(0) 651 #define OP_WRITE BIT(1) 652 #define OP_DEL BIT(2) 653 #define OP_SEARCH BIT(3) 654 655 /* SJA1105E/T: First generation */ 656 const struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = { 657 [BLK_IDX_VL_LOOKUP] = { 658 .entry_packing = sja1105et_vl_lookup_entry_packing, 659 .cmd_packing = sja1105et_vl_lookup_cmd_packing, 660 .access = OP_WRITE, 661 .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT, 662 .packed_size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD, 663 .addr = 0x35, 664 }, 665 [BLK_IDX_L2_LOOKUP] = { 666 .entry_packing = sja1105et_dyn_l2_lookup_entry_packing, 667 .cmd_packing = sja1105et_l2_lookup_cmd_packing, 668 .access = (OP_READ | OP_WRITE | OP_DEL), 669 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT, 670 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD, 671 .addr = 0x20, 672 }, 673 [BLK_IDX_MGMT_ROUTE] = { 674 .entry_packing = sja1105et_mgmt_route_entry_packing, 675 .cmd_packing = sja1105et_mgmt_route_cmd_packing, 676 .access = (OP_READ | OP_WRITE), 677 .max_entry_count = SJA1105_NUM_PORTS, 678 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD, 679 .addr = 0x20, 680 }, 681 [BLK_IDX_VLAN_LOOKUP] = { 682 .entry_packing = sja1105_vlan_lookup_entry_packing, 683 .cmd_packing = sja1105_vlan_lookup_cmd_packing, 684 .access = (OP_WRITE | OP_DEL), 685 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT, 686 .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD, 687 .addr = 0x27, 688 }, 689 [BLK_IDX_L2_FORWARDING] = { 690 .entry_packing = sja1105_l2_forwarding_entry_packing, 691 .cmd_packing = sja1105_l2_forwarding_cmd_packing, 692 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT, 693 .access = OP_WRITE, 694 .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD, 695 .addr = 0x24, 696 }, 697 [BLK_IDX_MAC_CONFIG] = { 698 .entry_packing = sja1105et_mac_config_entry_packing, 699 .cmd_packing = sja1105et_mac_config_cmd_packing, 700 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT, 701 .access = OP_WRITE, 702 .packed_size = SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD, 703 .addr = 0x36, 704 }, 705 [BLK_IDX_L2_LOOKUP_PARAMS] = { 706 .entry_packing = sja1105et_l2_lookup_params_entry_packing, 707 .cmd_packing = sja1105et_l2_lookup_params_cmd_packing, 708 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT, 709 .access = OP_WRITE, 710 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, 711 .addr = 0x38, 712 }, 713 [BLK_IDX_GENERAL_PARAMS] = { 714 .entry_packing = sja1105et_general_params_entry_packing, 715 .cmd_packing = sja1105et_general_params_cmd_packing, 716 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, 717 .access = OP_WRITE, 718 .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD, 719 .addr = 0x34, 720 }, 721 [BLK_IDX_RETAGGING] = { 722 .entry_packing = sja1105_retagging_entry_packing, 723 .cmd_packing = sja1105_retagging_cmd_packing, 724 .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, 725 .access = (OP_WRITE | OP_DEL), 726 .packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD, 727 .addr = 0x31, 728 }, 729 [BLK_IDX_CBS] = { 730 .entry_packing = sja1105et_cbs_entry_packing, 731 .cmd_packing = sja1105et_cbs_cmd_packing, 732 .max_entry_count = SJA1105ET_MAX_CBS_COUNT, 733 .access = OP_WRITE, 734 .packed_size = SJA1105ET_SIZE_CBS_DYN_CMD, 735 .addr = 0x2c, 736 }, 737 }; 738 739 /* SJA1105P/Q/R/S: Second generation */ 740 const struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = { 741 [BLK_IDX_VL_LOOKUP] = { 742 .entry_packing = sja1105_vl_lookup_entry_packing, 743 .cmd_packing = sja1105pqrs_vl_lookup_cmd_packing, 744 .access = (OP_READ | OP_WRITE), 745 .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT, 746 .packed_size = SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD, 747 .addr = 0x47, 748 }, 749 [BLK_IDX_L2_LOOKUP] = { 750 .entry_packing = sja1105pqrs_dyn_l2_lookup_entry_packing, 751 .cmd_packing = sja1105pqrs_l2_lookup_cmd_packing, 752 .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH), 753 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT, 754 .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD, 755 .addr = 0x24, 756 }, 757 [BLK_IDX_MGMT_ROUTE] = { 758 .entry_packing = sja1105pqrs_mgmt_route_entry_packing, 759 .cmd_packing = sja1105pqrs_mgmt_route_cmd_packing, 760 .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH), 761 .max_entry_count = SJA1105_NUM_PORTS, 762 .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD, 763 .addr = 0x24, 764 }, 765 [BLK_IDX_VLAN_LOOKUP] = { 766 .entry_packing = sja1105_vlan_lookup_entry_packing, 767 .cmd_packing = sja1105_vlan_lookup_cmd_packing, 768 .access = (OP_READ | OP_WRITE | OP_DEL), 769 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT, 770 .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD, 771 .addr = 0x2D, 772 }, 773 [BLK_IDX_L2_FORWARDING] = { 774 .entry_packing = sja1105_l2_forwarding_entry_packing, 775 .cmd_packing = sja1105_l2_forwarding_cmd_packing, 776 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT, 777 .access = OP_WRITE, 778 .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD, 779 .addr = 0x2A, 780 }, 781 [BLK_IDX_MAC_CONFIG] = { 782 .entry_packing = sja1105pqrs_mac_config_entry_packing, 783 .cmd_packing = sja1105pqrs_mac_config_cmd_packing, 784 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT, 785 .access = (OP_READ | OP_WRITE), 786 .packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD, 787 .addr = 0x4B, 788 }, 789 [BLK_IDX_L2_LOOKUP_PARAMS] = { 790 .entry_packing = sja1105pqrs_l2_lookup_params_entry_packing, 791 .cmd_packing = sja1105pqrs_l2_lookup_params_cmd_packing, 792 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT, 793 .access = (OP_READ | OP_WRITE), 794 .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, 795 .addr = 0x54, 796 }, 797 [BLK_IDX_AVB_PARAMS] = { 798 .entry_packing = sja1105pqrs_avb_params_entry_packing, 799 .cmd_packing = sja1105pqrs_avb_params_cmd_packing, 800 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT, 801 .access = (OP_READ | OP_WRITE), 802 .packed_size = SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD, 803 .addr = 0x8003, 804 }, 805 [BLK_IDX_GENERAL_PARAMS] = { 806 .entry_packing = sja1105pqrs_general_params_entry_packing, 807 .cmd_packing = sja1105pqrs_general_params_cmd_packing, 808 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, 809 .access = (OP_READ | OP_WRITE), 810 .packed_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD, 811 .addr = 0x3B, 812 }, 813 [BLK_IDX_RETAGGING] = { 814 .entry_packing = sja1105_retagging_entry_packing, 815 .cmd_packing = sja1105_retagging_cmd_packing, 816 .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, 817 .access = (OP_READ | OP_WRITE | OP_DEL), 818 .packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD, 819 .addr = 0x38, 820 }, 821 [BLK_IDX_CBS] = { 822 .entry_packing = sja1105pqrs_cbs_entry_packing, 823 .cmd_packing = sja1105pqrs_cbs_cmd_packing, 824 .max_entry_count = SJA1105PQRS_MAX_CBS_COUNT, 825 .access = OP_WRITE, 826 .packed_size = SJA1105PQRS_SIZE_CBS_DYN_CMD, 827 .addr = 0x32, 828 }, 829 }; 830 831 /* Provides read access to the settings through the dynamic interface 832 * of the switch. 833 * @blk_idx is used as key to select from the sja1105_dynamic_table_ops. 834 * The selection is limited by the hardware in respect to which 835 * configuration blocks can be read through the dynamic interface. 836 * @index is used to retrieve a particular table entry. If negative, 837 * (and if the @blk_idx supports the searching operation) a search 838 * is performed by the @entry parameter. 839 * @entry Type-casted to an unpacked structure that holds a table entry 840 * of the type specified in @blk_idx. 841 * Usually an output argument. If @index is negative, then this 842 * argument is used as input/output: it should be pre-populated 843 * with the element to search for. Entries which support the 844 * search operation will have an "index" field (not the @index 845 * argument to this function) and that is where the found index 846 * will be returned (or left unmodified - thus negative - if not 847 * found). 848 */ 849 int sja1105_dynamic_config_read(struct sja1105_private *priv, 850 enum sja1105_blk_idx blk_idx, 851 int index, void *entry) 852 { 853 const struct sja1105_dynamic_table_ops *ops; 854 struct sja1105_dyn_cmd cmd = {0}; 855 /* SPI payload buffer */ 856 u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0}; 857 int retries = 3; 858 int rc; 859 860 if (blk_idx >= BLK_IDX_MAX_DYN) 861 return -ERANGE; 862 863 ops = &priv->info->dyn_ops[blk_idx]; 864 865 if (index >= 0 && index >= ops->max_entry_count) 866 return -ERANGE; 867 if (index < 0 && !(ops->access & OP_SEARCH)) 868 return -EOPNOTSUPP; 869 if (!(ops->access & OP_READ)) 870 return -EOPNOTSUPP; 871 if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE) 872 return -ERANGE; 873 if (!ops->cmd_packing) 874 return -EOPNOTSUPP; 875 if (!ops->entry_packing) 876 return -EOPNOTSUPP; 877 878 cmd.valid = true; /* Trigger action on table entry */ 879 cmd.rdwrset = SPI_READ; /* Action is read */ 880 if (index < 0) { 881 /* Avoid copying a signed negative number to an u64 */ 882 cmd.index = 0; 883 cmd.search = true; 884 } else { 885 cmd.index = index; 886 cmd.search = false; 887 } 888 cmd.valident = true; 889 ops->cmd_packing(packed_buf, &cmd, PACK); 890 891 if (cmd.search) 892 ops->entry_packing(packed_buf, entry, PACK); 893 894 /* Send SPI write operation: read config table entry */ 895 rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf, 896 ops->packed_size); 897 if (rc < 0) 898 return rc; 899 900 /* Loop until we have confirmation that hardware has finished 901 * processing the command and has cleared the VALID field 902 */ 903 do { 904 memset(packed_buf, 0, ops->packed_size); 905 906 /* Retrieve the read operation's result */ 907 rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf, 908 ops->packed_size); 909 if (rc < 0) 910 return rc; 911 912 cmd = (struct sja1105_dyn_cmd) {0}; 913 ops->cmd_packing(packed_buf, &cmd, UNPACK); 914 /* UM10944: [valident] will always be found cleared 915 * during a read access with MGMTROUTE set. 916 * So don't error out in that case. 917 */ 918 if (!cmd.valident && blk_idx != BLK_IDX_MGMT_ROUTE) 919 return -ENOENT; 920 cpu_relax(); 921 } while (cmd.valid && --retries); 922 923 if (cmd.valid) 924 return -ETIMEDOUT; 925 926 /* Don't dereference possibly NULL pointer - maybe caller 927 * only wanted to see whether the entry existed or not. 928 */ 929 if (entry) 930 ops->entry_packing(packed_buf, entry, UNPACK); 931 return 0; 932 } 933 934 int sja1105_dynamic_config_write(struct sja1105_private *priv, 935 enum sja1105_blk_idx blk_idx, 936 int index, void *entry, bool keep) 937 { 938 const struct sja1105_dynamic_table_ops *ops; 939 struct sja1105_dyn_cmd cmd = {0}; 940 /* SPI payload buffer */ 941 u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0}; 942 int rc; 943 944 if (blk_idx >= BLK_IDX_MAX_DYN) 945 return -ERANGE; 946 947 ops = &priv->info->dyn_ops[blk_idx]; 948 949 if (index >= ops->max_entry_count) 950 return -ERANGE; 951 if (index < 0) 952 return -ERANGE; 953 if (!(ops->access & OP_WRITE)) 954 return -EOPNOTSUPP; 955 if (!keep && !(ops->access & OP_DEL)) 956 return -EOPNOTSUPP; 957 if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE) 958 return -ERANGE; 959 960 cmd.valident = keep; /* If false, deletes entry */ 961 cmd.valid = true; /* Trigger action on table entry */ 962 cmd.rdwrset = SPI_WRITE; /* Action is write */ 963 cmd.index = index; 964 965 if (!ops->cmd_packing) 966 return -EOPNOTSUPP; 967 ops->cmd_packing(packed_buf, &cmd, PACK); 968 969 if (!ops->entry_packing) 970 return -EOPNOTSUPP; 971 /* Don't dereference potentially NULL pointer if just 972 * deleting a table entry is what was requested. For cases 973 * where 'index' field is physically part of entry structure, 974 * and needed here, we deal with that in the cmd_packing callback. 975 */ 976 if (keep) 977 ops->entry_packing(packed_buf, entry, PACK); 978 979 /* Send SPI write operation: read config table entry */ 980 rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf, 981 ops->packed_size); 982 if (rc < 0) 983 return rc; 984 985 cmd = (struct sja1105_dyn_cmd) {0}; 986 ops->cmd_packing(packed_buf, &cmd, UNPACK); 987 if (cmd.errors) 988 return -EINVAL; 989 990 return 0; 991 } 992 993 static u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly) 994 { 995 int i; 996 997 for (i = 0; i < 8; i++) { 998 if ((crc ^ byte) & (1 << 7)) { 999 crc <<= 1; 1000 crc ^= poly; 1001 } else { 1002 crc <<= 1; 1003 } 1004 byte <<= 1; 1005 } 1006 return crc; 1007 } 1008 1009 /* CRC8 algorithm with non-reversed input, non-reversed output, 1010 * no input xor and no output xor. Code customized for receiving 1011 * the SJA1105 E/T FDB keys (vlanid, macaddr) as input. CRC polynomial 1012 * is also received as argument in the Koopman notation that the switch 1013 * hardware stores it in. 1014 */ 1015 u8 sja1105et_fdb_hash(struct sja1105_private *priv, const u8 *addr, u16 vid) 1016 { 1017 struct sja1105_l2_lookup_params_entry *l2_lookup_params = 1018 priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS].entries; 1019 u64 poly_koopman = l2_lookup_params->poly; 1020 /* Convert polynomial from Koopman to 'normal' notation */ 1021 u8 poly = (u8)(1 + (poly_koopman << 1)); 1022 u64 vlanid = l2_lookup_params->shared_learn ? 0 : vid; 1023 u64 input = (vlanid << 48) | ether_addr_to_u64(addr); 1024 u8 crc = 0; /* seed */ 1025 int i; 1026 1027 /* Mask the eight bytes starting from MSB one at a time */ 1028 for (i = 56; i >= 0; i -= 8) { 1029 u8 byte = (input & (0xffull << i)) >> i; 1030 1031 crc = sja1105_crc8_add(crc, byte, poly); 1032 } 1033 return crc; 1034 } 1035