root/drivers/net/ethernet/ti/cpsw_ale.c

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

DEFINITIONS

This source file includes following definitions.
  1. cpsw_ale_get_field
  2. cpsw_ale_set_field
  3. DEFINE_ALE_FIELD
  4. cpsw_ale_set_addr
  5. cpsw_ale_read
  6. cpsw_ale_write
  7. cpsw_ale_match_addr
  8. cpsw_ale_match_vlan
  9. cpsw_ale_match_free
  10. cpsw_ale_find_ageable
  11. cpsw_ale_flush_mcast
  12. cpsw_ale_flush_multicast
  13. cpsw_ale_set_vlan_entry_type
  14. cpsw_ale_add_ucast
  15. cpsw_ale_del_ucast
  16. cpsw_ale_add_mcast
  17. cpsw_ale_del_mcast
  18. cpsw_ale_set_vlan_mcast
  19. cpsw_ale_add_vlan
  20. cpsw_ale_del_vlan
  21. cpsw_ale_set_allmulti
  22. cpsw_ale_control_set
  23. cpsw_ale_control_get
  24. cpsw_ale_timer
  25. cpsw_ale_start
  26. cpsw_ale_stop
  27. cpsw_ale_create
  28. cpsw_ale_dump

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Texas Instruments N-Port Ethernet Switch Address Lookup Engine
   4  *
   5  * Copyright (C) 2012 Texas Instruments
   6  *
   7  */
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/platform_device.h>
  11 #include <linux/seq_file.h>
  12 #include <linux/slab.h>
  13 #include <linux/err.h>
  14 #include <linux/io.h>
  15 #include <linux/stat.h>
  16 #include <linux/sysfs.h>
  17 #include <linux/etherdevice.h>
  18 
  19 #include "cpsw_ale.h"
  20 
  21 #define BITMASK(bits)           (BIT(bits) - 1)
  22 
  23 #define ALE_VERSION_MAJOR(rev, mask) (((rev) >> 8) & (mask))
  24 #define ALE_VERSION_MINOR(rev)  (rev & 0xff)
  25 #define ALE_VERSION_1R3         0x0103
  26 #define ALE_VERSION_1R4         0x0104
  27 
  28 /* ALE Registers */
  29 #define ALE_IDVER               0x00
  30 #define ALE_STATUS              0x04
  31 #define ALE_CONTROL             0x08
  32 #define ALE_PRESCALE            0x10
  33 #define ALE_UNKNOWNVLAN         0x18
  34 #define ALE_TABLE_CONTROL       0x20
  35 #define ALE_TABLE               0x34
  36 #define ALE_PORTCTL             0x40
  37 
  38 /* ALE NetCP NU switch specific Registers */
  39 #define ALE_UNKNOWNVLAN_MEMBER                  0x90
  40 #define ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD       0x94
  41 #define ALE_UNKNOWNVLAN_REG_MCAST_FLOOD         0x98
  42 #define ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS      0x9C
  43 #define ALE_VLAN_MASK_MUX(reg)                  (0xc0 + (0x4 * (reg)))
  44 
  45 #define ALE_TABLE_WRITE         BIT(31)
  46 
  47 #define ALE_TYPE_FREE                   0
  48 #define ALE_TYPE_ADDR                   1
  49 #define ALE_TYPE_VLAN                   2
  50 #define ALE_TYPE_VLAN_ADDR              3
  51 
  52 #define ALE_UCAST_PERSISTANT            0
  53 #define ALE_UCAST_UNTOUCHED             1
  54 #define ALE_UCAST_OUI                   2
  55 #define ALE_UCAST_TOUCHED               3
  56 
  57 #define ALE_TABLE_SIZE_MULTIPLIER       1024
  58 #define ALE_STATUS_SIZE_MASK            0x1f
  59 #define ALE_TABLE_SIZE_DEFAULT          64
  60 
  61 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
  62 {
  63         int idx;
  64 
  65         idx    = start / 32;
  66         start -= idx * 32;
  67         idx    = 2 - idx; /* flip */
  68         return (ale_entry[idx] >> start) & BITMASK(bits);
  69 }
  70 
  71 static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
  72                                       u32 value)
  73 {
  74         int idx;
  75 
  76         value &= BITMASK(bits);
  77         idx    = start / 32;
  78         start -= idx * 32;
  79         idx    = 2 - idx; /* flip */
  80         ale_entry[idx] &= ~(BITMASK(bits) << start);
  81         ale_entry[idx] |=  (value << start);
  82 }
  83 
  84 #define DEFINE_ALE_FIELD(name, start, bits)                             \
  85 static inline int cpsw_ale_get_##name(u32 *ale_entry)                   \
  86 {                                                                       \
  87         return cpsw_ale_get_field(ale_entry, start, bits);              \
  88 }                                                                       \
  89 static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value)       \
  90 {                                                                       \
  91         cpsw_ale_set_field(ale_entry, start, bits, value);              \
  92 }
  93 
  94 #define DEFINE_ALE_FIELD1(name, start)                                  \
  95 static inline int cpsw_ale_get_##name(u32 *ale_entry, u32 bits)         \
  96 {                                                                       \
  97         return cpsw_ale_get_field(ale_entry, start, bits);              \
  98 }                                                                       \
  99 static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value,       \
 100                 u32 bits)                                               \
 101 {                                                                       \
 102         cpsw_ale_set_field(ale_entry, start, bits, value);              \
 103 }
 104 
 105 DEFINE_ALE_FIELD(entry_type,            60,     2)
 106 DEFINE_ALE_FIELD(vlan_id,               48,     12)
 107 DEFINE_ALE_FIELD(mcast_state,           62,     2)
 108 DEFINE_ALE_FIELD1(port_mask,            66)
 109 DEFINE_ALE_FIELD(super,                 65,     1)
 110 DEFINE_ALE_FIELD(ucast_type,            62,     2)
 111 DEFINE_ALE_FIELD1(port_num,             66)
 112 DEFINE_ALE_FIELD(blocked,               65,     1)
 113 DEFINE_ALE_FIELD(secure,                64,     1)
 114 DEFINE_ALE_FIELD1(vlan_untag_force,     24)
 115 DEFINE_ALE_FIELD1(vlan_reg_mcast,       16)
 116 DEFINE_ALE_FIELD1(vlan_unreg_mcast,     8)
 117 DEFINE_ALE_FIELD1(vlan_member_list,     0)
 118 DEFINE_ALE_FIELD(mcast,                 40,     1)
 119 /* ALE NetCP nu switch specific */
 120 DEFINE_ALE_FIELD(vlan_unreg_mcast_idx,  20,     3)
 121 DEFINE_ALE_FIELD(vlan_reg_mcast_idx,    44,     3)
 122 
 123 /* The MAC address field in the ALE entry cannot be macroized as above */
 124 static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
 125 {
 126         int i;
 127 
 128         for (i = 0; i < 6; i++)
 129                 addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
 130 }
 131 
 132 static inline void cpsw_ale_set_addr(u32 *ale_entry, const u8 *addr)
 133 {
 134         int i;
 135 
 136         for (i = 0; i < 6; i++)
 137                 cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);
 138 }
 139 
 140 static int cpsw_ale_read(struct cpsw_ale *ale, int idx, u32 *ale_entry)
 141 {
 142         int i;
 143 
 144         WARN_ON(idx > ale->params.ale_entries);
 145 
 146         writel_relaxed(idx, ale->params.ale_regs + ALE_TABLE_CONTROL);
 147 
 148         for (i = 0; i < ALE_ENTRY_WORDS; i++)
 149                 ale_entry[i] = readl_relaxed(ale->params.ale_regs +
 150                                              ALE_TABLE + 4 * i);
 151 
 152         return idx;
 153 }
 154 
 155 static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
 156 {
 157         int i;
 158 
 159         WARN_ON(idx > ale->params.ale_entries);
 160 
 161         for (i = 0; i < ALE_ENTRY_WORDS; i++)
 162                 writel_relaxed(ale_entry[i], ale->params.ale_regs +
 163                                ALE_TABLE + 4 * i);
 164 
 165         writel_relaxed(idx | ALE_TABLE_WRITE, ale->params.ale_regs +
 166                        ALE_TABLE_CONTROL);
 167 
 168         return idx;
 169 }
 170 
 171 static int cpsw_ale_match_addr(struct cpsw_ale *ale, const u8 *addr, u16 vid)
 172 {
 173         u32 ale_entry[ALE_ENTRY_WORDS];
 174         int type, idx;
 175 
 176         for (idx = 0; idx < ale->params.ale_entries; idx++) {
 177                 u8 entry_addr[6];
 178 
 179                 cpsw_ale_read(ale, idx, ale_entry);
 180                 type = cpsw_ale_get_entry_type(ale_entry);
 181                 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
 182                         continue;
 183                 if (cpsw_ale_get_vlan_id(ale_entry) != vid)
 184                         continue;
 185                 cpsw_ale_get_addr(ale_entry, entry_addr);
 186                 if (ether_addr_equal(entry_addr, addr))
 187                         return idx;
 188         }
 189         return -ENOENT;
 190 }
 191 
 192 static int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
 193 {
 194         u32 ale_entry[ALE_ENTRY_WORDS];
 195         int type, idx;
 196 
 197         for (idx = 0; idx < ale->params.ale_entries; idx++) {
 198                 cpsw_ale_read(ale, idx, ale_entry);
 199                 type = cpsw_ale_get_entry_type(ale_entry);
 200                 if (type != ALE_TYPE_VLAN)
 201                         continue;
 202                 if (cpsw_ale_get_vlan_id(ale_entry) == vid)
 203                         return idx;
 204         }
 205         return -ENOENT;
 206 }
 207 
 208 static int cpsw_ale_match_free(struct cpsw_ale *ale)
 209 {
 210         u32 ale_entry[ALE_ENTRY_WORDS];
 211         int type, idx;
 212 
 213         for (idx = 0; idx < ale->params.ale_entries; idx++) {
 214                 cpsw_ale_read(ale, idx, ale_entry);
 215                 type = cpsw_ale_get_entry_type(ale_entry);
 216                 if (type == ALE_TYPE_FREE)
 217                         return idx;
 218         }
 219         return -ENOENT;
 220 }
 221 
 222 static int cpsw_ale_find_ageable(struct cpsw_ale *ale)
 223 {
 224         u32 ale_entry[ALE_ENTRY_WORDS];
 225         int type, idx;
 226 
 227         for (idx = 0; idx < ale->params.ale_entries; idx++) {
 228                 cpsw_ale_read(ale, idx, ale_entry);
 229                 type = cpsw_ale_get_entry_type(ale_entry);
 230                 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
 231                         continue;
 232                 if (cpsw_ale_get_mcast(ale_entry))
 233                         continue;
 234                 type = cpsw_ale_get_ucast_type(ale_entry);
 235                 if (type != ALE_UCAST_PERSISTANT &&
 236                     type != ALE_UCAST_OUI)
 237                         return idx;
 238         }
 239         return -ENOENT;
 240 }
 241 
 242 static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
 243                                  int port_mask)
 244 {
 245         int mask;
 246 
 247         mask = cpsw_ale_get_port_mask(ale_entry,
 248                                       ale->port_mask_bits);
 249         if ((mask & port_mask) == 0)
 250                 return; /* ports dont intersect, not interested */
 251         mask &= ~port_mask;
 252 
 253         /* free if only remaining port is host port */
 254         if (mask)
 255                 cpsw_ale_set_port_mask(ale_entry, mask,
 256                                        ale->port_mask_bits);
 257         else
 258                 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 259 }
 260 
 261 int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid)
 262 {
 263         u32 ale_entry[ALE_ENTRY_WORDS];
 264         int ret, idx;
 265 
 266         for (idx = 0; idx < ale->params.ale_entries; idx++) {
 267                 cpsw_ale_read(ale, idx, ale_entry);
 268                 ret = cpsw_ale_get_entry_type(ale_entry);
 269                 if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)
 270                         continue;
 271 
 272                 /* if vid passed is -1 then remove all multicast entry from
 273                  * the table irrespective of vlan id, if a valid vlan id is
 274                  * passed then remove only multicast added to that vlan id.
 275                  * if vlan id doesn't match then move on to next entry.
 276                  */
 277                 if (vid != -1 && cpsw_ale_get_vlan_id(ale_entry) != vid)
 278                         continue;
 279 
 280                 if (cpsw_ale_get_mcast(ale_entry)) {
 281                         u8 addr[6];
 282 
 283                         if (cpsw_ale_get_super(ale_entry))
 284                                 continue;
 285 
 286                         cpsw_ale_get_addr(ale_entry, addr);
 287                         if (!is_broadcast_ether_addr(addr))
 288                                 cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
 289                 }
 290 
 291                 cpsw_ale_write(ale, idx, ale_entry);
 292         }
 293         return 0;
 294 }
 295 
 296 static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
 297                                                 int flags, u16 vid)
 298 {
 299         if (flags & ALE_VLAN) {
 300                 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
 301                 cpsw_ale_set_vlan_id(ale_entry, vid);
 302         } else {
 303                 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
 304         }
 305 }
 306 
 307 int cpsw_ale_add_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
 308                        int flags, u16 vid)
 309 {
 310         u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 311         int idx;
 312 
 313         cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
 314 
 315         cpsw_ale_set_addr(ale_entry, addr);
 316         cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
 317         cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
 318         cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
 319         cpsw_ale_set_port_num(ale_entry, port, ale->port_num_bits);
 320 
 321         idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
 322         if (idx < 0)
 323                 idx = cpsw_ale_match_free(ale);
 324         if (idx < 0)
 325                 idx = cpsw_ale_find_ageable(ale);
 326         if (idx < 0)
 327                 return -ENOMEM;
 328 
 329         cpsw_ale_write(ale, idx, ale_entry);
 330         return 0;
 331 }
 332 
 333 int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
 334                        int flags, u16 vid)
 335 {
 336         u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 337         int idx;
 338 
 339         idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
 340         if (idx < 0)
 341                 return -ENOENT;
 342 
 343         cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 344         cpsw_ale_write(ale, idx, ale_entry);
 345         return 0;
 346 }
 347 
 348 int cpsw_ale_add_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
 349                        int flags, u16 vid, int mcast_state)
 350 {
 351         u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 352         int idx, mask;
 353 
 354         idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
 355         if (idx >= 0)
 356                 cpsw_ale_read(ale, idx, ale_entry);
 357 
 358         cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
 359 
 360         cpsw_ale_set_addr(ale_entry, addr);
 361         cpsw_ale_set_super(ale_entry, (flags & ALE_SUPER) ? 1 : 0);
 362         cpsw_ale_set_mcast_state(ale_entry, mcast_state);
 363 
 364         mask = cpsw_ale_get_port_mask(ale_entry,
 365                                       ale->port_mask_bits);
 366         port_mask |= mask;
 367         cpsw_ale_set_port_mask(ale_entry, port_mask,
 368                                ale->port_mask_bits);
 369 
 370         if (idx < 0)
 371                 idx = cpsw_ale_match_free(ale);
 372         if (idx < 0)
 373                 idx = cpsw_ale_find_ageable(ale);
 374         if (idx < 0)
 375                 return -ENOMEM;
 376 
 377         cpsw_ale_write(ale, idx, ale_entry);
 378         return 0;
 379 }
 380 
 381 int cpsw_ale_del_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
 382                        int flags, u16 vid)
 383 {
 384         u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 385         int idx;
 386 
 387         idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
 388         if (idx < 0)
 389                 return -ENOENT;
 390 
 391         cpsw_ale_read(ale, idx, ale_entry);
 392 
 393         if (port_mask)
 394                 cpsw_ale_set_port_mask(ale_entry, port_mask,
 395                                        ale->port_mask_bits);
 396         else
 397                 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 398 
 399         cpsw_ale_write(ale, idx, ale_entry);
 400         return 0;
 401 }
 402 
 403 /* ALE NetCP NU switch specific vlan functions */
 404 static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
 405                                     int reg_mcast, int unreg_mcast)
 406 {
 407         int idx;
 408 
 409         /* Set VLAN registered multicast flood mask */
 410         idx = cpsw_ale_get_vlan_reg_mcast_idx(ale_entry);
 411         writel(reg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
 412 
 413         /* Set VLAN unregistered multicast flood mask */
 414         idx = cpsw_ale_get_vlan_unreg_mcast_idx(ale_entry);
 415         writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
 416 }
 417 
 418 int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
 419                       int reg_mcast, int unreg_mcast)
 420 {
 421         u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 422         int idx;
 423 
 424         idx = cpsw_ale_match_vlan(ale, vid);
 425         if (idx >= 0)
 426                 cpsw_ale_read(ale, idx, ale_entry);
 427 
 428         cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
 429         cpsw_ale_set_vlan_id(ale_entry, vid);
 430 
 431         cpsw_ale_set_vlan_untag_force(ale_entry, untag, ale->vlan_field_bits);
 432         if (!ale->params.nu_switch_ale) {
 433                 cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast,
 434                                             ale->vlan_field_bits);
 435                 cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
 436                                               ale->vlan_field_bits);
 437         } else {
 438                 cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast, unreg_mcast);
 439         }
 440         cpsw_ale_set_vlan_member_list(ale_entry, port, ale->vlan_field_bits);
 441 
 442         if (idx < 0)
 443                 idx = cpsw_ale_match_free(ale);
 444         if (idx < 0)
 445                 idx = cpsw_ale_find_ageable(ale);
 446         if (idx < 0)
 447                 return -ENOMEM;
 448 
 449         cpsw_ale_write(ale, idx, ale_entry);
 450         return 0;
 451 }
 452 
 453 int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
 454 {
 455         u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 456         int idx;
 457 
 458         idx = cpsw_ale_match_vlan(ale, vid);
 459         if (idx < 0)
 460                 return -ENOENT;
 461 
 462         cpsw_ale_read(ale, idx, ale_entry);
 463 
 464         if (port_mask)
 465                 cpsw_ale_set_vlan_member_list(ale_entry, port_mask,
 466                                               ale->vlan_field_bits);
 467         else
 468                 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 469 
 470         cpsw_ale_write(ale, idx, ale_entry);
 471         return 0;
 472 }
 473 
 474 void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti, int port)
 475 {
 476         u32 ale_entry[ALE_ENTRY_WORDS];
 477         int unreg_mcast = 0;
 478         int type, idx;
 479 
 480         for (idx = 0; idx < ale->params.ale_entries; idx++) {
 481                 int vlan_members;
 482 
 483                 cpsw_ale_read(ale, idx, ale_entry);
 484                 type = cpsw_ale_get_entry_type(ale_entry);
 485                 if (type != ALE_TYPE_VLAN)
 486                         continue;
 487                 vlan_members =
 488                         cpsw_ale_get_vlan_member_list(ale_entry,
 489                                                       ale->vlan_field_bits);
 490 
 491                 if (port != -1 && !(vlan_members & BIT(port)))
 492                         continue;
 493 
 494                 unreg_mcast =
 495                         cpsw_ale_get_vlan_unreg_mcast(ale_entry,
 496                                                       ale->vlan_field_bits);
 497                 if (allmulti)
 498                         unreg_mcast |= ALE_PORT_HOST;
 499                 else
 500                         unreg_mcast &= ~ALE_PORT_HOST;
 501                 cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
 502                                               ale->vlan_field_bits);
 503                 cpsw_ale_write(ale, idx, ale_entry);
 504         }
 505 }
 506 
 507 struct ale_control_info {
 508         const char      *name;
 509         int             offset, port_offset;
 510         int             shift, port_shift;
 511         int             bits;
 512 };
 513 
 514 static struct ale_control_info ale_controls[ALE_NUM_CONTROLS] = {
 515         [ALE_ENABLE]            = {
 516                 .name           = "enable",
 517                 .offset         = ALE_CONTROL,
 518                 .port_offset    = 0,
 519                 .shift          = 31,
 520                 .port_shift     = 0,
 521                 .bits           = 1,
 522         },
 523         [ALE_CLEAR]             = {
 524                 .name           = "clear",
 525                 .offset         = ALE_CONTROL,
 526                 .port_offset    = 0,
 527                 .shift          = 30,
 528                 .port_shift     = 0,
 529                 .bits           = 1,
 530         },
 531         [ALE_AGEOUT]            = {
 532                 .name           = "ageout",
 533                 .offset         = ALE_CONTROL,
 534                 .port_offset    = 0,
 535                 .shift          = 29,
 536                 .port_shift     = 0,
 537                 .bits           = 1,
 538         },
 539         [ALE_P0_UNI_FLOOD]      = {
 540                 .name           = "port0_unicast_flood",
 541                 .offset         = ALE_CONTROL,
 542                 .port_offset    = 0,
 543                 .shift          = 8,
 544                 .port_shift     = 0,
 545                 .bits           = 1,
 546         },
 547         [ALE_VLAN_NOLEARN]      = {
 548                 .name           = "vlan_nolearn",
 549                 .offset         = ALE_CONTROL,
 550                 .port_offset    = 0,
 551                 .shift          = 7,
 552                 .port_shift     = 0,
 553                 .bits           = 1,
 554         },
 555         [ALE_NO_PORT_VLAN]      = {
 556                 .name           = "no_port_vlan",
 557                 .offset         = ALE_CONTROL,
 558                 .port_offset    = 0,
 559                 .shift          = 6,
 560                 .port_shift     = 0,
 561                 .bits           = 1,
 562         },
 563         [ALE_OUI_DENY]          = {
 564                 .name           = "oui_deny",
 565                 .offset         = ALE_CONTROL,
 566                 .port_offset    = 0,
 567                 .shift          = 5,
 568                 .port_shift     = 0,
 569                 .bits           = 1,
 570         },
 571         [ALE_BYPASS]            = {
 572                 .name           = "bypass",
 573                 .offset         = ALE_CONTROL,
 574                 .port_offset    = 0,
 575                 .shift          = 4,
 576                 .port_shift     = 0,
 577                 .bits           = 1,
 578         },
 579         [ALE_RATE_LIMIT_TX]     = {
 580                 .name           = "rate_limit_tx",
 581                 .offset         = ALE_CONTROL,
 582                 .port_offset    = 0,
 583                 .shift          = 3,
 584                 .port_shift     = 0,
 585                 .bits           = 1,
 586         },
 587         [ALE_VLAN_AWARE]        = {
 588                 .name           = "vlan_aware",
 589                 .offset         = ALE_CONTROL,
 590                 .port_offset    = 0,
 591                 .shift          = 2,
 592                 .port_shift     = 0,
 593                 .bits           = 1,
 594         },
 595         [ALE_AUTH_ENABLE]       = {
 596                 .name           = "auth_enable",
 597                 .offset         = ALE_CONTROL,
 598                 .port_offset    = 0,
 599                 .shift          = 1,
 600                 .port_shift     = 0,
 601                 .bits           = 1,
 602         },
 603         [ALE_RATE_LIMIT]        = {
 604                 .name           = "rate_limit",
 605                 .offset         = ALE_CONTROL,
 606                 .port_offset    = 0,
 607                 .shift          = 0,
 608                 .port_shift     = 0,
 609                 .bits           = 1,
 610         },
 611         [ALE_PORT_STATE]        = {
 612                 .name           = "port_state",
 613                 .offset         = ALE_PORTCTL,
 614                 .port_offset    = 4,
 615                 .shift          = 0,
 616                 .port_shift     = 0,
 617                 .bits           = 2,
 618         },
 619         [ALE_PORT_DROP_UNTAGGED] = {
 620                 .name           = "drop_untagged",
 621                 .offset         = ALE_PORTCTL,
 622                 .port_offset    = 4,
 623                 .shift          = 2,
 624                 .port_shift     = 0,
 625                 .bits           = 1,
 626         },
 627         [ALE_PORT_DROP_UNKNOWN_VLAN] = {
 628                 .name           = "drop_unknown",
 629                 .offset         = ALE_PORTCTL,
 630                 .port_offset    = 4,
 631                 .shift          = 3,
 632                 .port_shift     = 0,
 633                 .bits           = 1,
 634         },
 635         [ALE_PORT_NOLEARN]      = {
 636                 .name           = "nolearn",
 637                 .offset         = ALE_PORTCTL,
 638                 .port_offset    = 4,
 639                 .shift          = 4,
 640                 .port_shift     = 0,
 641                 .bits           = 1,
 642         },
 643         [ALE_PORT_NO_SA_UPDATE] = {
 644                 .name           = "no_source_update",
 645                 .offset         = ALE_PORTCTL,
 646                 .port_offset    = 4,
 647                 .shift          = 5,
 648                 .port_shift     = 0,
 649                 .bits           = 1,
 650         },
 651         [ALE_PORT_MCAST_LIMIT]  = {
 652                 .name           = "mcast_limit",
 653                 .offset         = ALE_PORTCTL,
 654                 .port_offset    = 4,
 655                 .shift          = 16,
 656                 .port_shift     = 0,
 657                 .bits           = 8,
 658         },
 659         [ALE_PORT_BCAST_LIMIT]  = {
 660                 .name           = "bcast_limit",
 661                 .offset         = ALE_PORTCTL,
 662                 .port_offset    = 4,
 663                 .shift          = 24,
 664                 .port_shift     = 0,
 665                 .bits           = 8,
 666         },
 667         [ALE_PORT_UNKNOWN_VLAN_MEMBER] = {
 668                 .name           = "unknown_vlan_member",
 669                 .offset         = ALE_UNKNOWNVLAN,
 670                 .port_offset    = 0,
 671                 .shift          = 0,
 672                 .port_shift     = 0,
 673                 .bits           = 6,
 674         },
 675         [ALE_PORT_UNKNOWN_MCAST_FLOOD] = {
 676                 .name           = "unknown_mcast_flood",
 677                 .offset         = ALE_UNKNOWNVLAN,
 678                 .port_offset    = 0,
 679                 .shift          = 8,
 680                 .port_shift     = 0,
 681                 .bits           = 6,
 682         },
 683         [ALE_PORT_UNKNOWN_REG_MCAST_FLOOD] = {
 684                 .name           = "unknown_reg_flood",
 685                 .offset         = ALE_UNKNOWNVLAN,
 686                 .port_offset    = 0,
 687                 .shift          = 16,
 688                 .port_shift     = 0,
 689                 .bits           = 6,
 690         },
 691         [ALE_PORT_UNTAGGED_EGRESS] = {
 692                 .name           = "untagged_egress",
 693                 .offset         = ALE_UNKNOWNVLAN,
 694                 .port_offset    = 0,
 695                 .shift          = 24,
 696                 .port_shift     = 0,
 697                 .bits           = 6,
 698         },
 699 };
 700 
 701 int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,
 702                          int value)
 703 {
 704         const struct ale_control_info *info;
 705         int offset, shift;
 706         u32 tmp, mask;
 707 
 708         if (control < 0 || control >= ARRAY_SIZE(ale_controls))
 709                 return -EINVAL;
 710 
 711         info = &ale_controls[control];
 712         if (info->port_offset == 0 && info->port_shift == 0)
 713                 port = 0; /* global, port is a dont care */
 714 
 715         if (port < 0 || port >= ale->params.ale_ports)
 716                 return -EINVAL;
 717 
 718         mask = BITMASK(info->bits);
 719         if (value & ~mask)
 720                 return -EINVAL;
 721 
 722         offset = info->offset + (port * info->port_offset);
 723         shift  = info->shift  + (port * info->port_shift);
 724 
 725         tmp = readl_relaxed(ale->params.ale_regs + offset);
 726         tmp = (tmp & ~(mask << shift)) | (value << shift);
 727         writel_relaxed(tmp, ale->params.ale_regs + offset);
 728 
 729         return 0;
 730 }
 731 
 732 int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control)
 733 {
 734         const struct ale_control_info *info;
 735         int offset, shift;
 736         u32 tmp;
 737 
 738         if (control < 0 || control >= ARRAY_SIZE(ale_controls))
 739                 return -EINVAL;
 740 
 741         info = &ale_controls[control];
 742         if (info->port_offset == 0 && info->port_shift == 0)
 743                 port = 0; /* global, port is a dont care */
 744 
 745         if (port < 0 || port >= ale->params.ale_ports)
 746                 return -EINVAL;
 747 
 748         offset = info->offset + (port * info->port_offset);
 749         shift  = info->shift  + (port * info->port_shift);
 750 
 751         tmp = readl_relaxed(ale->params.ale_regs + offset) >> shift;
 752         return tmp & BITMASK(info->bits);
 753 }
 754 
 755 static void cpsw_ale_timer(struct timer_list *t)
 756 {
 757         struct cpsw_ale *ale = from_timer(ale, t, timer);
 758 
 759         cpsw_ale_control_set(ale, 0, ALE_AGEOUT, 1);
 760 
 761         if (ale->ageout) {
 762                 ale->timer.expires = jiffies + ale->ageout;
 763                 add_timer(&ale->timer);
 764         }
 765 }
 766 
 767 void cpsw_ale_start(struct cpsw_ale *ale)
 768 {
 769         cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1);
 770         cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
 771 
 772         timer_setup(&ale->timer, cpsw_ale_timer, 0);
 773         if (ale->ageout) {
 774                 ale->timer.expires = jiffies + ale->ageout;
 775                 add_timer(&ale->timer);
 776         }
 777 }
 778 
 779 void cpsw_ale_stop(struct cpsw_ale *ale)
 780 {
 781         del_timer_sync(&ale->timer);
 782         cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
 783         cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0);
 784 }
 785 
 786 struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)
 787 {
 788         struct cpsw_ale *ale;
 789         u32 rev, ale_entries;
 790 
 791         ale = devm_kzalloc(params->dev, sizeof(*ale), GFP_KERNEL);
 792         if (!ale)
 793                 return NULL;
 794 
 795         ale->params = *params;
 796         ale->ageout = ale->params.ale_ageout * HZ;
 797 
 798         rev = readl_relaxed(ale->params.ale_regs + ALE_IDVER);
 799         if (!ale->params.major_ver_mask)
 800                 ale->params.major_ver_mask = 0xff;
 801         ale->version =
 802                 (ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask) << 8) |
 803                  ALE_VERSION_MINOR(rev);
 804         dev_info(ale->params.dev, "initialized cpsw ale version %d.%d\n",
 805                  ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask),
 806                  ALE_VERSION_MINOR(rev));
 807 
 808         if (!ale->params.ale_entries) {
 809                 ale_entries =
 810                         readl_relaxed(ale->params.ale_regs + ALE_STATUS) &
 811                         ALE_STATUS_SIZE_MASK;
 812                 /* ALE available on newer NetCP switches has introduced
 813                  * a register, ALE_STATUS, to indicate the size of ALE
 814                  * table which shows the size as a multiple of 1024 entries.
 815                  * For these, params.ale_entries will be set to zero. So
 816                  * read the register and update the value of ale_entries.
 817                  * ALE table on NetCP lite, is much smaller and is indicated
 818                  * by a value of zero in ALE_STATUS. So use a default value
 819                  * of ALE_TABLE_SIZE_DEFAULT for this. Caller is expected
 820                  * to set the value of ale_entries for all other versions
 821                  * of ALE.
 822                  */
 823                 if (!ale_entries)
 824                         ale_entries = ALE_TABLE_SIZE_DEFAULT;
 825                 else
 826                         ale_entries *= ALE_TABLE_SIZE_MULTIPLIER;
 827                 ale->params.ale_entries = ale_entries;
 828         }
 829         dev_info(ale->params.dev,
 830                  "ALE Table size %ld\n", ale->params.ale_entries);
 831 
 832         /* set default bits for existing h/w */
 833         ale->port_mask_bits = ale->params.ale_ports;
 834         ale->port_num_bits = order_base_2(ale->params.ale_ports);
 835         ale->vlan_field_bits = ale->params.ale_ports;
 836 
 837         /* Set defaults override for ALE on NetCP NU switch and for version
 838          * 1R3
 839          */
 840         if (ale->params.nu_switch_ale) {
 841                 /* Separate registers for unknown vlan configuration.
 842                  * Also there are N bits, where N is number of ale
 843                  * ports and shift value should be 0
 844                  */
 845                 ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].bits =
 846                                         ale->params.ale_ports;
 847                 ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].offset =
 848                                         ALE_UNKNOWNVLAN_MEMBER;
 849                 ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].bits =
 850                                         ale->params.ale_ports;
 851                 ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].shift = 0;
 852                 ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].offset =
 853                                         ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD;
 854                 ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].bits =
 855                                         ale->params.ale_ports;
 856                 ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].shift = 0;
 857                 ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].offset =
 858                                         ALE_UNKNOWNVLAN_REG_MCAST_FLOOD;
 859                 ale_controls[ALE_PORT_UNTAGGED_EGRESS].bits =
 860                                         ale->params.ale_ports;
 861                 ale_controls[ALE_PORT_UNTAGGED_EGRESS].shift = 0;
 862                 ale_controls[ALE_PORT_UNTAGGED_EGRESS].offset =
 863                                         ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS;
 864         }
 865 
 866         cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
 867         return ale;
 868 }
 869 
 870 void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
 871 {
 872         int i;
 873 
 874         for (i = 0; i < ale->params.ale_entries; i++) {
 875                 cpsw_ale_read(ale, i, data);
 876                 data += ALE_ENTRY_WORDS;
 877         }
 878 }

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