root/drivers/net/dsa/mv88e6xxx/global1_vtu.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mv88e6xxx_g1_vtu_fid_read
  2. mv88e6xxx_g1_vtu_fid_write
  3. mv88e6xxx_g1_vtu_sid_read
  4. mv88e6xxx_g1_vtu_sid_write
  5. mv88e6xxx_g1_vtu_op_wait
  6. mv88e6xxx_g1_vtu_op
  7. mv88e6xxx_g1_vtu_vid_read
  8. mv88e6xxx_g1_vtu_vid_write
  9. mv88e6185_g1_vtu_data_read
  10. mv88e6185_g1_vtu_data_write
  11. mv88e6390_g1_vtu_data_read
  12. mv88e6390_g1_vtu_data_write
  13. mv88e6xxx_g1_vtu_stu_getnext
  14. mv88e6xxx_g1_vtu_stu_get
  15. mv88e6xxx_g1_vtu_getnext
  16. mv88e6250_g1_vtu_getnext
  17. mv88e6185_g1_vtu_getnext
  18. mv88e6352_g1_vtu_getnext
  19. mv88e6390_g1_vtu_getnext
  20. mv88e6250_g1_vtu_loadpurge
  21. mv88e6185_g1_vtu_loadpurge
  22. mv88e6352_g1_vtu_loadpurge
  23. mv88e6390_g1_vtu_loadpurge
  24. mv88e6xxx_g1_vtu_flush
  25. mv88e6xxx_g1_vtu_prob_irq_thread_fn
  26. mv88e6xxx_g1_vtu_prob_irq_setup
  27. mv88e6xxx_g1_vtu_prob_irq_free

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support
   4  *
   5  * Copyright (c) 2008 Marvell Semiconductor
   6  * Copyright (c) 2015 CMC Electronics, Inc.
   7  * Copyright (c) 2017 Savoir-faire Linux, Inc.
   8  */
   9 
  10 #include <linux/bitfield.h>
  11 #include <linux/interrupt.h>
  12 #include <linux/irqdomain.h>
  13 
  14 #include "chip.h"
  15 #include "global1.h"
  16 
  17 /* Offset 0x02: VTU FID Register */
  18 
  19 static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
  20                                      struct mv88e6xxx_vtu_entry *entry)
  21 {
  22         u16 val;
  23         int err;
  24 
  25         err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
  26         if (err)
  27                 return err;
  28 
  29         entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
  30 
  31         return 0;
  32 }
  33 
  34 static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
  35                                       struct mv88e6xxx_vtu_entry *entry)
  36 {
  37         u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
  38 
  39         return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
  40 }
  41 
  42 /* Offset 0x03: VTU SID Register */
  43 
  44 static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip,
  45                                      struct mv88e6xxx_vtu_entry *entry)
  46 {
  47         u16 val;
  48         int err;
  49 
  50         err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
  51         if (err)
  52                 return err;
  53 
  54         entry->sid = val & MV88E6352_G1_VTU_SID_MASK;
  55 
  56         return 0;
  57 }
  58 
  59 static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip,
  60                                       struct mv88e6xxx_vtu_entry *entry)
  61 {
  62         u16 val = entry->sid & MV88E6352_G1_VTU_SID_MASK;
  63 
  64         return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
  65 }
  66 
  67 /* Offset 0x05: VTU Operation Register */
  68 
  69 static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
  70 {
  71         int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY);
  72 
  73         return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0);
  74 }
  75 
  76 static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
  77 {
  78         int err;
  79 
  80         err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
  81                                  MV88E6XXX_G1_VTU_OP_BUSY | op);
  82         if (err)
  83                 return err;
  84 
  85         return mv88e6xxx_g1_vtu_op_wait(chip);
  86 }
  87 
  88 /* Offset 0x06: VTU VID Register */
  89 
  90 static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
  91                                      struct mv88e6xxx_vtu_entry *entry)
  92 {
  93         u16 val;
  94         int err;
  95 
  96         err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
  97         if (err)
  98                 return err;
  99 
 100         entry->vid = val & 0xfff;
 101 
 102         if (val & MV88E6390_G1_VTU_VID_PAGE)
 103                 entry->vid |= 0x1000;
 104 
 105         entry->valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
 106 
 107         return 0;
 108 }
 109 
 110 static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
 111                                       struct mv88e6xxx_vtu_entry *entry)
 112 {
 113         u16 val = entry->vid & 0xfff;
 114 
 115         if (entry->vid & 0x1000)
 116                 val |= MV88E6390_G1_VTU_VID_PAGE;
 117 
 118         if (entry->valid)
 119                 val |= MV88E6XXX_G1_VTU_VID_VALID;
 120 
 121         return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
 122 }
 123 
 124 /* Offset 0x07: VTU/STU Data Register 1
 125  * Offset 0x08: VTU/STU Data Register 2
 126  * Offset 0x09: VTU/STU Data Register 3
 127  */
 128 
 129 static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
 130                                       struct mv88e6xxx_vtu_entry *entry)
 131 {
 132         u16 regs[3];
 133         int i;
 134 
 135         /* Read all 3 VTU/STU Data registers */
 136         for (i = 0; i < 3; ++i) {
 137                 u16 *reg = &regs[i];
 138                 int err;
 139 
 140                 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
 141                 if (err)
 142                         return err;
 143         }
 144 
 145         /* Extract MemberTag and PortState data */
 146         for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
 147                 unsigned int member_offset = (i % 4) * 4;
 148                 unsigned int state_offset = member_offset + 2;
 149 
 150                 entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
 151                 entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
 152         }
 153 
 154         return 0;
 155 }
 156 
 157 static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
 158                                        struct mv88e6xxx_vtu_entry *entry)
 159 {
 160         u16 regs[3] = { 0 };
 161         int i;
 162 
 163         /* Insert MemberTag and PortState data */
 164         for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
 165                 unsigned int member_offset = (i % 4) * 4;
 166                 unsigned int state_offset = member_offset + 2;
 167 
 168                 regs[i / 4] |= (entry->member[i] & 0x3) << member_offset;
 169                 regs[i / 4] |= (entry->state[i] & 0x3) << state_offset;
 170         }
 171 
 172         /* Write all 3 VTU/STU Data registers */
 173         for (i = 0; i < 3; ++i) {
 174                 u16 reg = regs[i];
 175                 int err;
 176 
 177                 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
 178                 if (err)
 179                         return err;
 180         }
 181 
 182         return 0;
 183 }
 184 
 185 static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
 186 {
 187         u16 regs[2];
 188         int i;
 189 
 190         /* Read the 2 VTU/STU Data registers */
 191         for (i = 0; i < 2; ++i) {
 192                 u16 *reg = &regs[i];
 193                 int err;
 194 
 195                 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
 196                 if (err)
 197                         return err;
 198         }
 199 
 200         /* Extract data */
 201         for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
 202                 unsigned int offset = (i % 8) * 2;
 203 
 204                 data[i] = (regs[i / 8] >> offset) & 0x3;
 205         }
 206 
 207         return 0;
 208 }
 209 
 210 static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
 211 {
 212         u16 regs[2] = { 0 };
 213         int i;
 214 
 215         /* Insert data */
 216         for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
 217                 unsigned int offset = (i % 8) * 2;
 218 
 219                 regs[i / 8] |= (data[i] & 0x3) << offset;
 220         }
 221 
 222         /* Write the 2 VTU/STU Data registers */
 223         for (i = 0; i < 2; ++i) {
 224                 u16 reg = regs[i];
 225                 int err;
 226 
 227                 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
 228                 if (err)
 229                         return err;
 230         }
 231 
 232         return 0;
 233 }
 234 
 235 /* VLAN Translation Unit Operations */
 236 
 237 static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip *chip,
 238                                         struct mv88e6xxx_vtu_entry *entry)
 239 {
 240         int err;
 241 
 242         err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
 243         if (err)
 244                 return err;
 245 
 246         err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
 247         if (err)
 248                 return err;
 249 
 250         err = mv88e6xxx_g1_vtu_sid_read(chip, entry);
 251         if (err)
 252                 return err;
 253 
 254         return mv88e6xxx_g1_vtu_vid_read(chip, entry);
 255 }
 256 
 257 static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip *chip,
 258                                     struct mv88e6xxx_vtu_entry *vtu)
 259 {
 260         struct mv88e6xxx_vtu_entry stu;
 261         int err;
 262 
 263         err = mv88e6xxx_g1_vtu_sid_read(chip, vtu);
 264         if (err)
 265                 return err;
 266 
 267         stu.sid = vtu->sid - 1;
 268 
 269         err = mv88e6xxx_g1_vtu_stu_getnext(chip, &stu);
 270         if (err)
 271                 return err;
 272 
 273         if (stu.sid != vtu->sid || !stu.valid)
 274                 return -EINVAL;
 275 
 276         return 0;
 277 }
 278 
 279 static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
 280                                     struct mv88e6xxx_vtu_entry *entry)
 281 {
 282         int err;
 283 
 284         err = mv88e6xxx_g1_vtu_op_wait(chip);
 285         if (err)
 286                 return err;
 287 
 288         /* To get the next higher active VID, the VTU GetNext operation can be
 289          * started again without setting the VID registers since it already
 290          * contains the last VID.
 291          *
 292          * To save a few hardware accesses and abstract this to the caller,
 293          * write the VID only once, when the entry is given as invalid.
 294          */
 295         if (!entry->valid) {
 296                 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
 297                 if (err)
 298                         return err;
 299         }
 300 
 301         err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
 302         if (err)
 303                 return err;
 304 
 305         return mv88e6xxx_g1_vtu_vid_read(chip, entry);
 306 }
 307 
 308 int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
 309                              struct mv88e6xxx_vtu_entry *entry)
 310 {
 311         u16 val;
 312         int err;
 313 
 314         err = mv88e6xxx_g1_vtu_getnext(chip, entry);
 315         if (err)
 316                 return err;
 317 
 318         if (entry->valid) {
 319                 err = mv88e6185_g1_vtu_data_read(chip, entry);
 320                 if (err)
 321                         return err;
 322 
 323                 /* VTU DBNum[3:0] are located in VTU Operation 3:0
 324                  * VTU DBNum[5:4] are located in VTU Operation 9:8
 325                  */
 326                 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
 327                 if (err)
 328                         return err;
 329 
 330                 entry->fid = val & 0x000f;
 331                 entry->fid |= (val & 0x0300) >> 4;
 332         }
 333 
 334         return 0;
 335 }
 336 
 337 int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
 338                              struct mv88e6xxx_vtu_entry *entry)
 339 {
 340         u16 val;
 341         int err;
 342 
 343         err = mv88e6xxx_g1_vtu_getnext(chip, entry);
 344         if (err)
 345                 return err;
 346 
 347         if (entry->valid) {
 348                 err = mv88e6185_g1_vtu_data_read(chip, entry);
 349                 if (err)
 350                         return err;
 351 
 352                 /* VTU DBNum[3:0] are located in VTU Operation 3:0
 353                  * VTU DBNum[7:4] are located in VTU Operation 11:8
 354                  */
 355                 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
 356                 if (err)
 357                         return err;
 358 
 359                 entry->fid = val & 0x000f;
 360                 entry->fid |= (val & 0x0f00) >> 4;
 361         }
 362 
 363         return 0;
 364 }
 365 
 366 int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
 367                              struct mv88e6xxx_vtu_entry *entry)
 368 {
 369         int err;
 370 
 371         /* Fetch VLAN MemberTag data from the VTU */
 372         err = mv88e6xxx_g1_vtu_getnext(chip, entry);
 373         if (err)
 374                 return err;
 375 
 376         if (entry->valid) {
 377                 /* Fetch (and mask) VLAN PortState data from the STU */
 378                 err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
 379                 if (err)
 380                         return err;
 381 
 382                 err = mv88e6185_g1_vtu_data_read(chip, entry);
 383                 if (err)
 384                         return err;
 385 
 386                 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
 387                 if (err)
 388                         return err;
 389         }
 390 
 391         return 0;
 392 }
 393 
 394 int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
 395                              struct mv88e6xxx_vtu_entry *entry)
 396 {
 397         int err;
 398 
 399         /* Fetch VLAN MemberTag data from the VTU */
 400         err = mv88e6xxx_g1_vtu_getnext(chip, entry);
 401         if (err)
 402                 return err;
 403 
 404         if (entry->valid) {
 405                 err = mv88e6390_g1_vtu_data_read(chip, entry->member);
 406                 if (err)
 407                         return err;
 408 
 409                 /* Fetch VLAN PortState data from the STU */
 410                 err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
 411                 if (err)
 412                         return err;
 413 
 414                 err = mv88e6390_g1_vtu_data_read(chip, entry->state);
 415                 if (err)
 416                         return err;
 417 
 418                 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
 419                 if (err)
 420                         return err;
 421         }
 422 
 423         return 0;
 424 }
 425 
 426 int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
 427                                struct mv88e6xxx_vtu_entry *entry)
 428 {
 429         u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
 430         int err;
 431 
 432         err = mv88e6xxx_g1_vtu_op_wait(chip);
 433         if (err)
 434                 return err;
 435 
 436         err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
 437         if (err)
 438                 return err;
 439 
 440         if (entry->valid) {
 441                 err = mv88e6185_g1_vtu_data_write(chip, entry);
 442                 if (err)
 443                         return err;
 444 
 445                 /* VTU DBNum[3:0] are located in VTU Operation 3:0
 446                  * VTU DBNum[5:4] are located in VTU Operation 9:8
 447                  */
 448                 op |= entry->fid & 0x000f;
 449                 op |= (entry->fid & 0x0030) << 4;
 450         }
 451 
 452         return mv88e6xxx_g1_vtu_op(chip, op);
 453 }
 454 
 455 int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
 456                                struct mv88e6xxx_vtu_entry *entry)
 457 {
 458         u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
 459         int err;
 460 
 461         err = mv88e6xxx_g1_vtu_op_wait(chip);
 462         if (err)
 463                 return err;
 464 
 465         err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
 466         if (err)
 467                 return err;
 468 
 469         if (entry->valid) {
 470                 err = mv88e6185_g1_vtu_data_write(chip, entry);
 471                 if (err)
 472                         return err;
 473 
 474                 /* VTU DBNum[3:0] are located in VTU Operation 3:0
 475                  * VTU DBNum[7:4] are located in VTU Operation 11:8
 476                  */
 477                 op |= entry->fid & 0x000f;
 478                 op |= (entry->fid & 0x00f0) << 4;
 479         }
 480 
 481         return mv88e6xxx_g1_vtu_op(chip, op);
 482 }
 483 
 484 int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
 485                                struct mv88e6xxx_vtu_entry *entry)
 486 {
 487         int err;
 488 
 489         err = mv88e6xxx_g1_vtu_op_wait(chip);
 490         if (err)
 491                 return err;
 492 
 493         err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
 494         if (err)
 495                 return err;
 496 
 497         if (entry->valid) {
 498                 /* Write MemberTag and PortState data */
 499                 err = mv88e6185_g1_vtu_data_write(chip, entry);
 500                 if (err)
 501                         return err;
 502 
 503                 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
 504                 if (err)
 505                         return err;
 506 
 507                 /* Load STU entry */
 508                 err = mv88e6xxx_g1_vtu_op(chip,
 509                                           MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
 510                 if (err)
 511                         return err;
 512 
 513                 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
 514                 if (err)
 515                         return err;
 516         }
 517 
 518         /* Load/Purge VTU entry */
 519         return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
 520 }
 521 
 522 int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
 523                                struct mv88e6xxx_vtu_entry *entry)
 524 {
 525         int err;
 526 
 527         err = mv88e6xxx_g1_vtu_op_wait(chip);
 528         if (err)
 529                 return err;
 530 
 531         err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
 532         if (err)
 533                 return err;
 534 
 535         if (entry->valid) {
 536                 /* Write PortState data */
 537                 err = mv88e6390_g1_vtu_data_write(chip, entry->state);
 538                 if (err)
 539                         return err;
 540 
 541                 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
 542                 if (err)
 543                         return err;
 544 
 545                 /* Load STU entry */
 546                 err = mv88e6xxx_g1_vtu_op(chip,
 547                                           MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
 548                 if (err)
 549                         return err;
 550 
 551                 /* Write MemberTag data */
 552                 err = mv88e6390_g1_vtu_data_write(chip, entry->member);
 553                 if (err)
 554                         return err;
 555 
 556                 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
 557                 if (err)
 558                         return err;
 559         }
 560 
 561         /* Load/Purge VTU entry */
 562         return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
 563 }
 564 
 565 int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
 566 {
 567         int err;
 568 
 569         err = mv88e6xxx_g1_vtu_op_wait(chip);
 570         if (err)
 571                 return err;
 572 
 573         return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
 574 }
 575 
 576 static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
 577 {
 578         struct mv88e6xxx_chip *chip = dev_id;
 579         struct mv88e6xxx_vtu_entry entry;
 580         int spid;
 581         int err;
 582         u16 val;
 583 
 584         mv88e6xxx_reg_lock(chip);
 585 
 586         err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
 587         if (err)
 588                 goto out;
 589 
 590         err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
 591         if (err)
 592                 goto out;
 593 
 594         err = mv88e6xxx_g1_vtu_vid_read(chip, &entry);
 595         if (err)
 596                 goto out;
 597 
 598         spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
 599 
 600         if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
 601                 dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
 602                                     entry.vid, spid);
 603                 chip->ports[spid].vtu_member_violation++;
 604         }
 605 
 606         if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
 607                 dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
 608                                     entry.vid, spid);
 609                 chip->ports[spid].vtu_miss_violation++;
 610         }
 611 
 612         mv88e6xxx_reg_unlock(chip);
 613 
 614         return IRQ_HANDLED;
 615 
 616 out:
 617         mv88e6xxx_reg_unlock(chip);
 618 
 619         dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
 620                 err);
 621 
 622         return IRQ_HANDLED;
 623 }
 624 
 625 int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
 626 {
 627         int err;
 628 
 629         chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
 630                                               MV88E6XXX_G1_STS_IRQ_VTU_PROB);
 631         if (chip->vtu_prob_irq < 0)
 632                 return chip->vtu_prob_irq;
 633 
 634         err = request_threaded_irq(chip->vtu_prob_irq, NULL,
 635                                    mv88e6xxx_g1_vtu_prob_irq_thread_fn,
 636                                    IRQF_ONESHOT, "mv88e6xxx-g1-vtu-prob",
 637                                    chip);
 638         if (err)
 639                 irq_dispose_mapping(chip->vtu_prob_irq);
 640 
 641         return err;
 642 }
 643 
 644 void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
 645 {
 646         free_irq(chip->vtu_prob_irq, chip);
 647         irq_dispose_mapping(chip->vtu_prob_irq);
 648 }

/* [<][>][^][v][top][bottom][index][help] */