Merge tag 'for-linus-20190706' of git://git.kernel.dk/linux-block
[linux/fpc-iii.git] / drivers / net / dsa / sja1105 / sja1105_dynamic_config.c
blobe73ab28bf63225770cef61056951f24ff73899cc
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
3 */
4 #include "sja1105.h"
6 #define SJA1105_SIZE_DYN_CMD 4
8 #define SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY \
9 SJA1105_SIZE_DYN_CMD
11 #define SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD \
12 (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_L2_LOOKUP_ENTRY)
14 #define SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD \
15 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY)
17 #define SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD \
18 (SJA1105_SIZE_DYN_CMD + 4 + SJA1105_SIZE_VLAN_LOOKUP_ENTRY)
20 #define SJA1105_SIZE_L2_FORWARDING_DYN_CMD \
21 (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_FORWARDING_ENTRY)
23 #define SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD \
24 (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY)
26 #define SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD \
27 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY)
29 #define SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD \
30 SJA1105_SIZE_DYN_CMD
32 #define SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD \
33 SJA1105_SIZE_DYN_CMD
35 #define SJA1105_MAX_DYN_CMD_SIZE \
36 SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD
38 static void
39 sja1105pqrs_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
40 enum packing_op op)
42 u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
43 const int size = SJA1105_SIZE_DYN_CMD;
45 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
46 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
47 sja1105_packing(p, &cmd->errors, 29, 29, size, op);
48 sja1105_packing(p, &cmd->valident, 27, 27, size, op);
49 /* Hack - The hardware takes the 'index' field within
50 * struct sja1105_l2_lookup_entry as the index on which this command
51 * will operate. However it will ignore everything else, so 'index'
52 * is logically part of command but physically part of entry.
53 * Populate the 'index' entry field from within the command callback,
54 * such that our API doesn't need to ask for a full-blown entry
55 * structure when e.g. a delete is requested.
57 sja1105_packing(buf, &cmd->index, 29, 20,
58 SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY, op);
59 /* TODO hostcmd */
62 static void
63 sja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
64 enum packing_op op)
66 u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
67 const int size = SJA1105_SIZE_DYN_CMD;
69 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
70 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
71 sja1105_packing(p, &cmd->errors, 29, 29, size, op);
72 sja1105_packing(p, &cmd->valident, 27, 27, size, op);
73 /* Hack - see comments above. */
74 sja1105_packing(buf, &cmd->index, 29, 20,
75 SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op);
78 static void
79 sja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
80 enum packing_op op)
82 u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
83 u64 mgmtroute = 1;
85 sja1105et_l2_lookup_cmd_packing(buf, cmd, op);
86 if (op == PACK)
87 sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
90 static size_t sja1105et_mgmt_route_entry_packing(void *buf, void *entry_ptr,
91 enum packing_op op)
93 struct sja1105_mgmt_entry *entry = entry_ptr;
94 const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
96 /* UM10944: To specify if a PTP egress timestamp shall be captured on
97 * each port upon transmission of the frame, the LSB of VLANID in the
98 * ENTRY field provided by the host must be set.
99 * Bit 1 of VLANID then specifies the register where the timestamp for
100 * this port is stored in.
102 sja1105_packing(buf, &entry->tsreg, 85, 85, size, op);
103 sja1105_packing(buf, &entry->takets, 84, 84, size, op);
104 sja1105_packing(buf, &entry->macaddr, 83, 36, size, op);
105 sja1105_packing(buf, &entry->destports, 35, 31, size, op);
106 sja1105_packing(buf, &entry->enfport, 30, 30, size, op);
107 return size;
110 /* In E/T, entry is at addresses 0x27-0x28. There is a 4 byte gap at 0x29,
111 * and command is at 0x2a. Similarly in P/Q/R/S there is a 1 register gap
112 * between entry (0x2d, 0x2e) and command (0x30).
114 static void
115 sja1105_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
116 enum packing_op op)
118 u8 *p = buf + SJA1105_SIZE_VLAN_LOOKUP_ENTRY + 4;
119 const int size = SJA1105_SIZE_DYN_CMD;
121 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
122 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
123 sja1105_packing(p, &cmd->valident, 27, 27, size, op);
124 /* Hack - see comments above, applied for 'vlanid' field of
125 * struct sja1105_vlan_lookup_entry.
127 sja1105_packing(buf, &cmd->index, 38, 27,
128 SJA1105_SIZE_VLAN_LOOKUP_ENTRY, op);
131 static void
132 sja1105_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
133 enum packing_op op)
135 u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY;
136 const int size = SJA1105_SIZE_DYN_CMD;
138 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
139 sja1105_packing(p, &cmd->errors, 30, 30, size, op);
140 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
141 sja1105_packing(p, &cmd->index, 4, 0, size, op);
144 static void
145 sja1105et_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
146 enum packing_op op)
148 const int size = SJA1105_SIZE_DYN_CMD;
149 /* Yup, user manual definitions are reversed */
150 u8 *reg1 = buf + 4;
152 sja1105_packing(reg1, &cmd->valid, 31, 31, size, op);
153 sja1105_packing(reg1, &cmd->index, 26, 24, size, op);
156 static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr,
157 enum packing_op op)
159 const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
160 struct sja1105_mac_config_entry *entry = entry_ptr;
161 /* Yup, user manual definitions are reversed */
162 u8 *reg1 = buf + 4;
163 u8 *reg2 = buf;
165 sja1105_packing(reg1, &entry->speed, 30, 29, size, op);
166 sja1105_packing(reg1, &entry->drpdtag, 23, 23, size, op);
167 sja1105_packing(reg1, &entry->drpuntag, 22, 22, size, op);
168 sja1105_packing(reg1, &entry->retag, 21, 21, size, op);
169 sja1105_packing(reg1, &entry->dyn_learn, 20, 20, size, op);
170 sja1105_packing(reg1, &entry->egress, 19, 19, size, op);
171 sja1105_packing(reg1, &entry->ingress, 18, 18, size, op);
172 sja1105_packing(reg1, &entry->ing_mirr, 17, 17, size, op);
173 sja1105_packing(reg1, &entry->egr_mirr, 16, 16, size, op);
174 sja1105_packing(reg1, &entry->vlanprio, 14, 12, size, op);
175 sja1105_packing(reg1, &entry->vlanid, 11, 0, size, op);
176 sja1105_packing(reg2, &entry->tp_delin, 31, 16, size, op);
177 sja1105_packing(reg2, &entry->tp_delout, 15, 0, size, op);
178 /* MAC configuration table entries which can't be reconfigured:
179 * top, base, enabled, ifg, maxage, drpnona664
181 /* Bogus return value, not used anywhere */
182 return 0;
185 static void
186 sja1105pqrs_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
187 enum packing_op op)
189 const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
190 u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
192 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
193 sja1105_packing(p, &cmd->errors, 30, 30, size, op);
194 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
195 sja1105_packing(p, &cmd->index, 2, 0, size, op);
198 static void
199 sja1105et_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
200 enum packing_op op)
202 sja1105_packing(buf, &cmd->valid, 31, 31,
203 SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
206 static size_t
207 sja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
208 enum packing_op op)
210 struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
212 sja1105_packing(buf, &entry->poly, 7, 0,
213 SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
214 /* Bogus return value, not used anywhere */
215 return 0;
218 static void
219 sja1105et_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
220 enum packing_op op)
222 const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
224 sja1105_packing(buf, &cmd->valid, 31, 31, size, op);
225 sja1105_packing(buf, &cmd->errors, 30, 30, size, op);
228 static size_t
229 sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
230 enum packing_op op)
232 struct sja1105_general_params_entry *entry = entry_ptr;
233 const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
235 sja1105_packing(buf, &entry->mirr_port, 2, 0, size, op);
236 /* Bogus return value, not used anywhere */
237 return 0;
240 #define OP_READ BIT(0)
241 #define OP_WRITE BIT(1)
242 #define OP_DEL BIT(2)
244 /* SJA1105E/T: First generation */
245 struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
246 [BLK_IDX_L2_LOOKUP] = {
247 .entry_packing = sja1105et_l2_lookup_entry_packing,
248 .cmd_packing = sja1105et_l2_lookup_cmd_packing,
249 .access = (OP_READ | OP_WRITE | OP_DEL),
250 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
251 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
252 .addr = 0x20,
254 [BLK_IDX_MGMT_ROUTE] = {
255 .entry_packing = sja1105et_mgmt_route_entry_packing,
256 .cmd_packing = sja1105et_mgmt_route_cmd_packing,
257 .access = (OP_READ | OP_WRITE),
258 .max_entry_count = SJA1105_NUM_PORTS,
259 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
260 .addr = 0x20,
262 [BLK_IDX_L2_POLICING] = {0},
263 [BLK_IDX_VLAN_LOOKUP] = {
264 .entry_packing = sja1105_vlan_lookup_entry_packing,
265 .cmd_packing = sja1105_vlan_lookup_cmd_packing,
266 .access = (OP_WRITE | OP_DEL),
267 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
268 .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
269 .addr = 0x27,
271 [BLK_IDX_L2_FORWARDING] = {
272 .entry_packing = sja1105_l2_forwarding_entry_packing,
273 .cmd_packing = sja1105_l2_forwarding_cmd_packing,
274 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
275 .access = OP_WRITE,
276 .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
277 .addr = 0x24,
279 [BLK_IDX_MAC_CONFIG] = {
280 .entry_packing = sja1105et_mac_config_entry_packing,
281 .cmd_packing = sja1105et_mac_config_cmd_packing,
282 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
283 .access = OP_WRITE,
284 .packed_size = SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD,
285 .addr = 0x36,
287 [BLK_IDX_L2_LOOKUP_PARAMS] = {
288 .entry_packing = sja1105et_l2_lookup_params_entry_packing,
289 .cmd_packing = sja1105et_l2_lookup_params_cmd_packing,
290 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
291 .access = OP_WRITE,
292 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
293 .addr = 0x38,
295 [BLK_IDX_L2_FORWARDING_PARAMS] = {0},
296 [BLK_IDX_GENERAL_PARAMS] = {
297 .entry_packing = sja1105et_general_params_entry_packing,
298 .cmd_packing = sja1105et_general_params_cmd_packing,
299 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
300 .access = OP_WRITE,
301 .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD,
302 .addr = 0x34,
304 [BLK_IDX_XMII_PARAMS] = {0},
307 /* SJA1105P/Q/R/S: Second generation: TODO */
308 struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = {
309 [BLK_IDX_L2_LOOKUP] = {
310 .entry_packing = sja1105pqrs_l2_lookup_entry_packing,
311 .cmd_packing = sja1105pqrs_l2_lookup_cmd_packing,
312 .access = (OP_READ | OP_WRITE | OP_DEL),
313 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
314 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
315 .addr = 0x24,
317 [BLK_IDX_L2_POLICING] = {0},
318 [BLK_IDX_VLAN_LOOKUP] = {
319 .entry_packing = sja1105_vlan_lookup_entry_packing,
320 .cmd_packing = sja1105_vlan_lookup_cmd_packing,
321 .access = (OP_READ | OP_WRITE | OP_DEL),
322 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
323 .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
324 .addr = 0x2D,
326 [BLK_IDX_L2_FORWARDING] = {
327 .entry_packing = sja1105_l2_forwarding_entry_packing,
328 .cmd_packing = sja1105_l2_forwarding_cmd_packing,
329 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
330 .access = OP_WRITE,
331 .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
332 .addr = 0x2A,
334 [BLK_IDX_MAC_CONFIG] = {
335 .entry_packing = sja1105pqrs_mac_config_entry_packing,
336 .cmd_packing = sja1105pqrs_mac_config_cmd_packing,
337 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
338 .access = (OP_READ | OP_WRITE),
339 .packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD,
340 .addr = 0x4B,
342 [BLK_IDX_L2_LOOKUP_PARAMS] = {
343 .entry_packing = sja1105et_l2_lookup_params_entry_packing,
344 .cmd_packing = sja1105et_l2_lookup_params_cmd_packing,
345 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
346 .access = (OP_READ | OP_WRITE),
347 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
348 .addr = 0x38,
350 [BLK_IDX_L2_FORWARDING_PARAMS] = {0},
351 [BLK_IDX_GENERAL_PARAMS] = {
352 .entry_packing = sja1105et_general_params_entry_packing,
353 .cmd_packing = sja1105et_general_params_cmd_packing,
354 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
355 .access = OP_WRITE,
356 .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD,
357 .addr = 0x34,
359 [BLK_IDX_XMII_PARAMS] = {0},
362 int sja1105_dynamic_config_read(struct sja1105_private *priv,
363 enum sja1105_blk_idx blk_idx,
364 int index, void *entry)
366 const struct sja1105_dynamic_table_ops *ops;
367 struct sja1105_dyn_cmd cmd = {0};
368 /* SPI payload buffer */
369 u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
370 int retries = 3;
371 int rc;
373 if (blk_idx >= BLK_IDX_MAX_DYN)
374 return -ERANGE;
376 ops = &priv->info->dyn_ops[blk_idx];
378 if (index >= ops->max_entry_count)
379 return -ERANGE;
380 if (!(ops->access & OP_READ))
381 return -EOPNOTSUPP;
382 if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
383 return -ERANGE;
384 if (!ops->cmd_packing)
385 return -EOPNOTSUPP;
386 if (!ops->entry_packing)
387 return -EOPNOTSUPP;
389 cmd.valid = true; /* Trigger action on table entry */
390 cmd.rdwrset = SPI_READ; /* Action is read */
391 cmd.index = index;
392 ops->cmd_packing(packed_buf, &cmd, PACK);
394 /* Send SPI write operation: read config table entry */
395 rc = sja1105_spi_send_packed_buf(priv, SPI_WRITE, ops->addr,
396 packed_buf, ops->packed_size);
397 if (rc < 0)
398 return rc;
400 /* Loop until we have confirmation that hardware has finished
401 * processing the command and has cleared the VALID field
403 do {
404 memset(packed_buf, 0, ops->packed_size);
406 /* Retrieve the read operation's result */
407 rc = sja1105_spi_send_packed_buf(priv, SPI_READ, ops->addr,
408 packed_buf, ops->packed_size);
409 if (rc < 0)
410 return rc;
412 cmd = (struct sja1105_dyn_cmd) {0};
413 ops->cmd_packing(packed_buf, &cmd, UNPACK);
414 /* UM10944: [valident] will always be found cleared
415 * during a read access with MGMTROUTE set.
416 * So don't error out in that case.
418 if (!cmd.valident && blk_idx != BLK_IDX_MGMT_ROUTE)
419 return -EINVAL;
420 cpu_relax();
421 } while (cmd.valid && --retries);
423 if (cmd.valid)
424 return -ETIMEDOUT;
426 /* Don't dereference possibly NULL pointer - maybe caller
427 * only wanted to see whether the entry existed or not.
429 if (entry)
430 ops->entry_packing(packed_buf, entry, UNPACK);
431 return 0;
434 int sja1105_dynamic_config_write(struct sja1105_private *priv,
435 enum sja1105_blk_idx blk_idx,
436 int index, void *entry, bool keep)
438 const struct sja1105_dynamic_table_ops *ops;
439 struct sja1105_dyn_cmd cmd = {0};
440 /* SPI payload buffer */
441 u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
442 int rc;
444 if (blk_idx >= BLK_IDX_MAX_DYN)
445 return -ERANGE;
447 ops = &priv->info->dyn_ops[blk_idx];
449 if (index >= ops->max_entry_count)
450 return -ERANGE;
451 if (!(ops->access & OP_WRITE))
452 return -EOPNOTSUPP;
453 if (!keep && !(ops->access & OP_DEL))
454 return -EOPNOTSUPP;
455 if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
456 return -ERANGE;
458 cmd.valident = keep; /* If false, deletes entry */
459 cmd.valid = true; /* Trigger action on table entry */
460 cmd.rdwrset = SPI_WRITE; /* Action is write */
461 cmd.index = index;
463 if (!ops->cmd_packing)
464 return -EOPNOTSUPP;
465 ops->cmd_packing(packed_buf, &cmd, PACK);
467 if (!ops->entry_packing)
468 return -EOPNOTSUPP;
469 /* Don't dereference potentially NULL pointer if just
470 * deleting a table entry is what was requested. For cases
471 * where 'index' field is physically part of entry structure,
472 * and needed here, we deal with that in the cmd_packing callback.
474 if (keep)
475 ops->entry_packing(packed_buf, entry, PACK);
477 /* Send SPI write operation: read config table entry */
478 rc = sja1105_spi_send_packed_buf(priv, SPI_WRITE, ops->addr,
479 packed_buf, ops->packed_size);
480 if (rc < 0)
481 return rc;
483 cmd = (struct sja1105_dyn_cmd) {0};
484 ops->cmd_packing(packed_buf, &cmd, UNPACK);
485 if (cmd.errors)
486 return -EINVAL;
488 return 0;
491 static u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly)
493 int i;
495 for (i = 0; i < 8; i++) {
496 if ((crc ^ byte) & (1 << 7)) {
497 crc <<= 1;
498 crc ^= poly;
499 } else {
500 crc <<= 1;
502 byte <<= 1;
504 return crc;
507 /* CRC8 algorithm with non-reversed input, non-reversed output,
508 * no input xor and no output xor. Code customized for receiving
509 * the SJA1105 E/T FDB keys (vlanid, macaddr) as input. CRC polynomial
510 * is also received as argument in the Koopman notation that the switch
511 * hardware stores it in.
513 u8 sja1105_fdb_hash(struct sja1105_private *priv, const u8 *addr, u16 vid)
515 struct sja1105_l2_lookup_params_entry *l2_lookup_params =
516 priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS].entries;
517 u64 poly_koopman = l2_lookup_params->poly;
518 /* Convert polynomial from Koopman to 'normal' notation */
519 u8 poly = (u8)(1 + (poly_koopman << 1));
520 u64 vlanid = l2_lookup_params->shared_learn ? 0 : vid;
521 u64 input = (vlanid << 48) | ether_addr_to_u64(addr);
522 u8 crc = 0; /* seed */
523 int i;
525 /* Mask the eight bytes starting from MSB one at a time */
526 for (i = 56; i >= 0; i -= 8) {
527 u8 byte = (input & (0xffull << i)) >> i;
529 crc = sja1105_crc8_add(crc, byte, poly);
531 return crc;