0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/bitfield.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/irqdomain.h>
0013
0014 #include "chip.h"
0015 #include "global1.h"
0016
0017
0018
0019 static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
0020 struct mv88e6xxx_vtu_entry *entry)
0021 {
0022 u16 val;
0023 int err;
0024
0025 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
0026 if (err)
0027 return err;
0028
0029 entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
0030 entry->policy = !!(val & MV88E6352_G1_VTU_FID_VID_POLICY);
0031 return 0;
0032 }
0033
0034 static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
0035 struct mv88e6xxx_vtu_entry *entry)
0036 {
0037 u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
0038
0039 if (entry->policy)
0040 val |= MV88E6352_G1_VTU_FID_VID_POLICY;
0041
0042 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
0043 }
0044
0045
0046
0047 static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip, u8 *sid)
0048 {
0049 u16 val;
0050 int err;
0051
0052 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
0053 if (err)
0054 return err;
0055
0056 *sid = val & MV88E6352_G1_VTU_SID_MASK;
0057
0058 return 0;
0059 }
0060
0061 static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip, u8 sid)
0062 {
0063 u16 val = sid & MV88E6352_G1_VTU_SID_MASK;
0064
0065 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
0066 }
0067
0068
0069
0070 static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
0071 {
0072 int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY);
0073
0074 return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0);
0075 }
0076
0077 static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
0078 {
0079 int err;
0080
0081 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
0082 MV88E6XXX_G1_VTU_OP_BUSY | op);
0083 if (err)
0084 return err;
0085
0086 return mv88e6xxx_g1_vtu_op_wait(chip);
0087 }
0088
0089
0090
0091 static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
0092 bool *valid, u16 *vid)
0093 {
0094 u16 val;
0095 int err;
0096
0097 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
0098 if (err)
0099 return err;
0100
0101 if (vid) {
0102 *vid = val & 0xfff;
0103
0104 if (val & MV88E6390_G1_VTU_VID_PAGE)
0105 *vid |= 0x1000;
0106 }
0107
0108 if (valid)
0109 *valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
0110
0111 return 0;
0112 }
0113
0114 static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
0115 bool valid, u16 vid)
0116 {
0117 u16 val = vid & 0xfff;
0118
0119 if (vid & 0x1000)
0120 val |= MV88E6390_G1_VTU_VID_PAGE;
0121
0122 if (valid)
0123 val |= MV88E6XXX_G1_VTU_VID_VALID;
0124
0125 return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
0126 }
0127
0128
0129
0130
0131
0132 static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
0133 u16 *regs)
0134 {
0135 int i;
0136
0137
0138 for (i = 0; i < 3; ++i) {
0139 u16 *reg = ®s[i];
0140 int err;
0141
0142 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
0143 if (err)
0144 return err;
0145 }
0146
0147 return 0;
0148 }
0149
0150 static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
0151 u8 *member, u8 *state)
0152 {
0153 u16 regs[3];
0154 int err;
0155 int i;
0156
0157 err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
0158 if (err)
0159 return err;
0160
0161
0162 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
0163 unsigned int member_offset = (i % 4) * 4;
0164 unsigned int state_offset = member_offset + 2;
0165
0166 if (member)
0167 member[i] = (regs[i / 4] >> member_offset) & 0x3;
0168
0169 if (state)
0170 state[i] = (regs[i / 4] >> state_offset) & 0x3;
0171 }
0172
0173 return 0;
0174 }
0175
0176 static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
0177 u8 *member, u8 *state)
0178 {
0179 u16 regs[3] = { 0 };
0180 int i;
0181
0182
0183 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
0184 unsigned int member_offset = (i % 4) * 4;
0185 unsigned int state_offset = member_offset + 2;
0186
0187 if (member)
0188 regs[i / 4] |= (member[i] & 0x3) << member_offset;
0189
0190 if (state)
0191 regs[i / 4] |= (state[i] & 0x3) << state_offset;
0192 }
0193
0194
0195 for (i = 0; i < 3; ++i) {
0196 u16 reg = regs[i];
0197 int err;
0198
0199 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
0200 if (err)
0201 return err;
0202 }
0203
0204 return 0;
0205 }
0206
0207 static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
0208 {
0209 u16 regs[2];
0210 int i;
0211
0212
0213 for (i = 0; i < 2; ++i) {
0214 u16 *reg = ®s[i];
0215 int err;
0216
0217 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
0218 if (err)
0219 return err;
0220 }
0221
0222
0223 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
0224 unsigned int offset = (i % 8) * 2;
0225
0226 data[i] = (regs[i / 8] >> offset) & 0x3;
0227 }
0228
0229 return 0;
0230 }
0231
0232 static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
0233 {
0234 u16 regs[2] = { 0 };
0235 int i;
0236
0237
0238 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
0239 unsigned int offset = (i % 8) * 2;
0240
0241 regs[i / 8] |= (data[i] & 0x3) << offset;
0242 }
0243
0244
0245 for (i = 0; i < 2; ++i) {
0246 u16 reg = regs[i];
0247 int err;
0248
0249 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
0250 if (err)
0251 return err;
0252 }
0253
0254 return 0;
0255 }
0256
0257
0258
0259 int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
0260 struct mv88e6xxx_vtu_entry *entry)
0261 {
0262 int err;
0263
0264 err = mv88e6xxx_g1_vtu_op_wait(chip);
0265 if (err)
0266 return err;
0267
0268
0269
0270
0271
0272
0273
0274
0275 if (!entry->valid) {
0276 err = mv88e6xxx_g1_vtu_vid_write(chip, false, entry->vid);
0277 if (err)
0278 return err;
0279 }
0280
0281 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
0282 if (err)
0283 return err;
0284
0285 return mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, &entry->vid);
0286 }
0287
0288 int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
0289 struct mv88e6xxx_vtu_entry *entry)
0290 {
0291 u16 val;
0292 int err;
0293
0294 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
0295 if (err)
0296 return err;
0297
0298 if (entry->valid) {
0299 err = mv88e6185_g1_vtu_data_read(chip, entry->member, entry->state);
0300 if (err)
0301 return err;
0302
0303
0304
0305
0306 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
0307 if (err)
0308 return err;
0309
0310 entry->fid = val & 0x000f;
0311 entry->fid |= (val & 0x0f00) >> 4;
0312 entry->fid &= mv88e6xxx_num_databases(chip) - 1;
0313 }
0314
0315 return 0;
0316 }
0317
0318 int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
0319 struct mv88e6xxx_vtu_entry *entry)
0320 {
0321 int err;
0322
0323
0324 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
0325 if (err)
0326 return err;
0327
0328 if (entry->valid) {
0329 err = mv88e6185_g1_vtu_data_read(chip, entry->member, NULL);
0330 if (err)
0331 return err;
0332
0333 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
0334 if (err)
0335 return err;
0336
0337 err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
0338 if (err)
0339 return err;
0340 }
0341
0342 return 0;
0343 }
0344
0345 int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
0346 struct mv88e6xxx_vtu_entry *entry)
0347 {
0348 int err;
0349
0350
0351 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
0352 if (err)
0353 return err;
0354
0355 if (entry->valid) {
0356 err = mv88e6390_g1_vtu_data_read(chip, entry->member);
0357 if (err)
0358 return err;
0359
0360 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
0361 if (err)
0362 return err;
0363
0364 err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
0365 if (err)
0366 return err;
0367 }
0368
0369 return 0;
0370 }
0371
0372 int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
0373 struct mv88e6xxx_vtu_entry *entry)
0374 {
0375 u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
0376 int err;
0377
0378 err = mv88e6xxx_g1_vtu_op_wait(chip);
0379 if (err)
0380 return err;
0381
0382 err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid);
0383 if (err)
0384 return err;
0385
0386 if (entry->valid) {
0387 err = mv88e6185_g1_vtu_data_write(chip, entry->member, entry->state);
0388 if (err)
0389 return err;
0390
0391
0392
0393
0394
0395
0396
0397
0398 op |= entry->fid & 0x000f;
0399 op |= (entry->fid & 0x00f0) << 4;
0400 }
0401
0402 return mv88e6xxx_g1_vtu_op(chip, op);
0403 }
0404
0405 int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
0406 struct mv88e6xxx_vtu_entry *entry)
0407 {
0408 int err;
0409
0410 err = mv88e6xxx_g1_vtu_op_wait(chip);
0411 if (err)
0412 return err;
0413
0414 err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid);
0415 if (err)
0416 return err;
0417
0418 if (entry->valid) {
0419
0420 err = mv88e6185_g1_vtu_data_write(chip, entry->member, NULL);
0421 if (err)
0422 return err;
0423
0424 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
0425 if (err)
0426 return err;
0427
0428 err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
0429 if (err)
0430 return err;
0431 }
0432
0433
0434 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
0435 }
0436
0437 int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
0438 struct mv88e6xxx_vtu_entry *entry)
0439 {
0440 int err;
0441
0442 err = mv88e6xxx_g1_vtu_op_wait(chip);
0443 if (err)
0444 return err;
0445
0446 err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid);
0447 if (err)
0448 return err;
0449
0450 if (entry->valid) {
0451
0452 err = mv88e6390_g1_vtu_data_write(chip, entry->member);
0453 if (err)
0454 return err;
0455
0456 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
0457 if (err)
0458 return err;
0459
0460 err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
0461 if (err)
0462 return err;
0463 }
0464
0465
0466 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
0467 }
0468
0469 int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
0470 {
0471 int err;
0472
0473 err = mv88e6xxx_g1_vtu_op_wait(chip);
0474 if (err)
0475 return err;
0476
0477 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
0478 }
0479
0480
0481
0482 int mv88e6xxx_g1_stu_getnext(struct mv88e6xxx_chip *chip,
0483 struct mv88e6xxx_stu_entry *entry)
0484 {
0485 int err;
0486
0487 err = mv88e6xxx_g1_vtu_op_wait(chip);
0488 if (err)
0489 return err;
0490
0491
0492
0493
0494
0495
0496
0497
0498 if (!entry->valid) {
0499 err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
0500 if (err)
0501 return err;
0502 }
0503
0504 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
0505 if (err)
0506 return err;
0507
0508 err = mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, NULL);
0509 if (err)
0510 return err;
0511
0512 if (entry->valid) {
0513 err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
0514 if (err)
0515 return err;
0516 }
0517
0518 return 0;
0519 }
0520
0521 int mv88e6352_g1_stu_getnext(struct mv88e6xxx_chip *chip,
0522 struct mv88e6xxx_stu_entry *entry)
0523 {
0524 int err;
0525
0526 err = mv88e6xxx_g1_stu_getnext(chip, entry);
0527 if (err)
0528 return err;
0529
0530 if (!entry->valid)
0531 return 0;
0532
0533 return mv88e6185_g1_vtu_data_read(chip, NULL, entry->state);
0534 }
0535
0536 int mv88e6390_g1_stu_getnext(struct mv88e6xxx_chip *chip,
0537 struct mv88e6xxx_stu_entry *entry)
0538 {
0539 int err;
0540
0541 err = mv88e6xxx_g1_stu_getnext(chip, entry);
0542 if (err)
0543 return err;
0544
0545 if (!entry->valid)
0546 return 0;
0547
0548 return mv88e6390_g1_vtu_data_read(chip, entry->state);
0549 }
0550
0551 int mv88e6352_g1_stu_loadpurge(struct mv88e6xxx_chip *chip,
0552 struct mv88e6xxx_stu_entry *entry)
0553 {
0554 int err;
0555
0556 err = mv88e6xxx_g1_vtu_op_wait(chip);
0557 if (err)
0558 return err;
0559
0560 err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0);
0561 if (err)
0562 return err;
0563
0564 err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
0565 if (err)
0566 return err;
0567
0568 if (entry->valid) {
0569 err = mv88e6185_g1_vtu_data_write(chip, NULL, entry->state);
0570 if (err)
0571 return err;
0572 }
0573
0574
0575 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
0576 }
0577
0578 int mv88e6390_g1_stu_loadpurge(struct mv88e6xxx_chip *chip,
0579 struct mv88e6xxx_stu_entry *entry)
0580 {
0581 int err;
0582
0583 err = mv88e6xxx_g1_vtu_op_wait(chip);
0584 if (err)
0585 return err;
0586
0587 err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0);
0588 if (err)
0589 return err;
0590
0591 err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
0592 if (err)
0593 return err;
0594
0595 if (entry->valid) {
0596 err = mv88e6390_g1_vtu_data_write(chip, entry->state);
0597 if (err)
0598 return err;
0599 }
0600
0601
0602 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
0603 }
0604
0605
0606
0607 static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
0608 {
0609 struct mv88e6xxx_chip *chip = dev_id;
0610 u16 val, vid;
0611 int spid;
0612 int err;
0613
0614 mv88e6xxx_reg_lock(chip);
0615
0616 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
0617 if (err)
0618 goto out;
0619
0620 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
0621 if (err)
0622 goto out;
0623
0624 err = mv88e6xxx_g1_vtu_vid_read(chip, NULL, &vid);
0625 if (err)
0626 goto out;
0627
0628 spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
0629
0630 if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
0631 dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
0632 vid, spid);
0633 chip->ports[spid].vtu_member_violation++;
0634 }
0635
0636 if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
0637 dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
0638 vid, spid);
0639 chip->ports[spid].vtu_miss_violation++;
0640 }
0641
0642 mv88e6xxx_reg_unlock(chip);
0643
0644 return IRQ_HANDLED;
0645
0646 out:
0647 mv88e6xxx_reg_unlock(chip);
0648
0649 dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
0650 err);
0651
0652 return IRQ_HANDLED;
0653 }
0654
0655 int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
0656 {
0657 int err;
0658
0659 chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
0660 MV88E6XXX_G1_STS_IRQ_VTU_PROB);
0661 if (chip->vtu_prob_irq < 0)
0662 return chip->vtu_prob_irq;
0663
0664 snprintf(chip->vtu_prob_irq_name, sizeof(chip->vtu_prob_irq_name),
0665 "mv88e6xxx-%s-g1-vtu-prob", dev_name(chip->dev));
0666
0667 err = request_threaded_irq(chip->vtu_prob_irq, NULL,
0668 mv88e6xxx_g1_vtu_prob_irq_thread_fn,
0669 IRQF_ONESHOT, chip->vtu_prob_irq_name,
0670 chip);
0671 if (err)
0672 irq_dispose_mapping(chip->vtu_prob_irq);
0673
0674 return err;
0675 }
0676
0677 void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
0678 {
0679 free_irq(chip->vtu_prob_irq, chip);
0680 irq_dispose_mapping(chip->vtu_prob_irq);
0681 }