| .. | .. |
|---|
| 9 | 9 | #include "item.h" |
|---|
| 10 | 10 | #include "core_acl_flex_keys.h" |
|---|
| 11 | 11 | |
|---|
| 12 | +/* For the purpose of the driver, define an internal storage scratchpad |
|---|
| 13 | + * that will be used to store key/mask values. For each defined element type |
|---|
| 14 | + * define an internal storage geometry. |
|---|
| 15 | + * |
|---|
| 16 | + * When adding new elements, MLXSW_AFK_ELEMENT_STORAGE_SIZE must be increased |
|---|
| 17 | + * accordingly. |
|---|
| 18 | + */ |
|---|
| 19 | +static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = { |
|---|
| 20 | + MLXSW_AFK_ELEMENT_INFO_U32(SRC_SYS_PORT, 0x00, 16, 16), |
|---|
| 21 | + MLXSW_AFK_ELEMENT_INFO_BUF(DMAC_32_47, 0x04, 2), |
|---|
| 22 | + MLXSW_AFK_ELEMENT_INFO_BUF(DMAC_0_31, 0x06, 4), |
|---|
| 23 | + MLXSW_AFK_ELEMENT_INFO_BUF(SMAC_32_47, 0x0A, 2), |
|---|
| 24 | + MLXSW_AFK_ELEMENT_INFO_BUF(SMAC_0_31, 0x0C, 4), |
|---|
| 25 | + MLXSW_AFK_ELEMENT_INFO_U32(ETHERTYPE, 0x00, 0, 16), |
|---|
| 26 | + MLXSW_AFK_ELEMENT_INFO_U32(IP_PROTO, 0x10, 0, 8), |
|---|
| 27 | + MLXSW_AFK_ELEMENT_INFO_U32(VID, 0x10, 8, 12), |
|---|
| 28 | + MLXSW_AFK_ELEMENT_INFO_U32(PCP, 0x10, 20, 3), |
|---|
| 29 | + MLXSW_AFK_ELEMENT_INFO_U32(TCP_FLAGS, 0x10, 23, 9), |
|---|
| 30 | + MLXSW_AFK_ELEMENT_INFO_U32(DST_L4_PORT, 0x14, 0, 16), |
|---|
| 31 | + MLXSW_AFK_ELEMENT_INFO_U32(SRC_L4_PORT, 0x14, 16, 16), |
|---|
| 32 | + MLXSW_AFK_ELEMENT_INFO_U32(IP_TTL_, 0x18, 0, 8), |
|---|
| 33 | + MLXSW_AFK_ELEMENT_INFO_U32(IP_ECN, 0x18, 9, 2), |
|---|
| 34 | + MLXSW_AFK_ELEMENT_INFO_U32(IP_DSCP, 0x18, 11, 6), |
|---|
| 35 | + MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_8_10, 0x18, 17, 3), |
|---|
| 36 | + MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_0_7, 0x18, 20, 8), |
|---|
| 37 | + MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_96_127, 0x20, 4), |
|---|
| 38 | + MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_64_95, 0x24, 4), |
|---|
| 39 | + MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_32_63, 0x28, 4), |
|---|
| 40 | + MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_0_31, 0x2C, 4), |
|---|
| 41 | + MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_96_127, 0x30, 4), |
|---|
| 42 | + MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_64_95, 0x34, 4), |
|---|
| 43 | + MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_32_63, 0x38, 4), |
|---|
| 44 | + MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_0_31, 0x3C, 4), |
|---|
| 45 | +}; |
|---|
| 46 | + |
|---|
| 12 | 47 | struct mlxsw_afk { |
|---|
| 13 | 48 | struct list_head key_info_list; |
|---|
| 14 | 49 | unsigned int max_blocks; |
|---|
| .. | .. |
|---|
| 26 | 61 | const struct mlxsw_afk_block *block = &mlxsw_afk->blocks[i]; |
|---|
| 27 | 62 | |
|---|
| 28 | 63 | for (j = 0; j < block->instances_count; j++) { |
|---|
| 64 | + const struct mlxsw_afk_element_info *elinfo; |
|---|
| 29 | 65 | struct mlxsw_afk_element_inst *elinst; |
|---|
| 30 | 66 | |
|---|
| 31 | 67 | elinst = &block->instances[j]; |
|---|
| 32 | | - if (elinst->type != elinst->info->type || |
|---|
| 33 | | - elinst->item.size.bits != |
|---|
| 34 | | - elinst->info->item.size.bits) |
|---|
| 68 | + elinfo = &mlxsw_afk_element_infos[elinst->element]; |
|---|
| 69 | + if (elinst->type != elinfo->type || |
|---|
| 70 | + (!elinst->avoid_size_check && |
|---|
| 71 | + elinst->item.size.bits != |
|---|
| 72 | + elinfo->item.size.bits)) |
|---|
| 35 | 73 | return false; |
|---|
| 36 | 74 | } |
|---|
| 37 | 75 | } |
|---|
| .. | .. |
|---|
| 71 | 109 | * is index inside "blocks" |
|---|
| 72 | 110 | */ |
|---|
| 73 | 111 | struct mlxsw_afk_element_usage elusage; |
|---|
| 74 | | - const struct mlxsw_afk_block *blocks[0]; |
|---|
| 112 | + const struct mlxsw_afk_block *blocks[]; |
|---|
| 75 | 113 | }; |
|---|
| 76 | 114 | |
|---|
| 77 | 115 | static bool |
|---|
| .. | .. |
|---|
| 115 | 153 | struct mlxsw_afk_element_inst *elinst; |
|---|
| 116 | 154 | |
|---|
| 117 | 155 | elinst = &block->instances[j]; |
|---|
| 118 | | - if (elinst->info->element == element) { |
|---|
| 156 | + if (elinst->element == element) { |
|---|
| 119 | 157 | __set_bit(element, picker->hits[i].element); |
|---|
| 120 | 158 | picker->hits[i].total++; |
|---|
| 121 | 159 | } |
|---|
| .. | .. |
|---|
| 236 | 274 | struct mlxsw_afk_element_usage *elusage) |
|---|
| 237 | 275 | { |
|---|
| 238 | 276 | struct mlxsw_afk_key_info *key_info; |
|---|
| 239 | | - size_t alloc_size; |
|---|
| 240 | 277 | int err; |
|---|
| 241 | 278 | |
|---|
| 242 | | - alloc_size = sizeof(*key_info) + |
|---|
| 243 | | - sizeof(key_info->blocks[0]) * mlxsw_afk->max_blocks; |
|---|
| 244 | | - key_info = kzalloc(alloc_size, GFP_KERNEL); |
|---|
| 279 | + key_info = kzalloc(struct_size(key_info, blocks, mlxsw_afk->max_blocks), |
|---|
| 280 | + GFP_KERNEL); |
|---|
| 245 | 281 | if (!key_info) |
|---|
| 246 | 282 | return ERR_PTR(-ENOMEM); |
|---|
| 247 | 283 | err = mlxsw_afk_picker(mlxsw_afk, key_info, elusage); |
|---|
| .. | .. |
|---|
| 302 | 338 | struct mlxsw_afk_element_inst *elinst; |
|---|
| 303 | 339 | |
|---|
| 304 | 340 | elinst = &block->instances[i]; |
|---|
| 305 | | - if (elinst->info->element == element) |
|---|
| 341 | + if (elinst->element == element) |
|---|
| 306 | 342 | return elinst; |
|---|
| 307 | 343 | } |
|---|
| 308 | 344 | return NULL; |
|---|
| .. | .. |
|---|
| 387 | 423 | |
|---|
| 388 | 424 | static void mlxsw_sp_afk_encode_u32(const struct mlxsw_item *storage_item, |
|---|
| 389 | 425 | const struct mlxsw_item *output_item, |
|---|
| 390 | | - char *storage, char *output) |
|---|
| 426 | + char *storage, char *output, int diff) |
|---|
| 391 | 427 | { |
|---|
| 392 | 428 | u32 value; |
|---|
| 393 | 429 | |
|---|
| 394 | 430 | value = __mlxsw_item_get32(storage, storage_item, 0); |
|---|
| 395 | | - __mlxsw_item_set32(output, output_item, 0, value); |
|---|
| 431 | + __mlxsw_item_set32(output, output_item, 0, value + diff); |
|---|
| 396 | 432 | } |
|---|
| 397 | 433 | |
|---|
| 398 | 434 | static void mlxsw_sp_afk_encode_buf(const struct mlxsw_item *storage_item, |
|---|
| .. | .. |
|---|
| 408 | 444 | |
|---|
| 409 | 445 | static void |
|---|
| 410 | 446 | mlxsw_sp_afk_encode_one(const struct mlxsw_afk_element_inst *elinst, |
|---|
| 411 | | - char *output, char *storage) |
|---|
| 447 | + char *output, char *storage, int u32_diff) |
|---|
| 412 | 448 | { |
|---|
| 413 | | - const struct mlxsw_item *storage_item = &elinst->info->item; |
|---|
| 414 | 449 | const struct mlxsw_item *output_item = &elinst->item; |
|---|
| 450 | + const struct mlxsw_afk_element_info *elinfo; |
|---|
| 451 | + const struct mlxsw_item *storage_item; |
|---|
| 415 | 452 | |
|---|
| 453 | + elinfo = &mlxsw_afk_element_infos[elinst->element]; |
|---|
| 454 | + storage_item = &elinfo->item; |
|---|
| 416 | 455 | if (elinst->type == MLXSW_AFK_ELEMENT_TYPE_U32) |
|---|
| 417 | 456 | mlxsw_sp_afk_encode_u32(storage_item, output_item, |
|---|
| 418 | | - storage, output); |
|---|
| 457 | + storage, output, u32_diff); |
|---|
| 419 | 458 | else if (elinst->type == MLXSW_AFK_ELEMENT_TYPE_BUF) |
|---|
| 420 | 459 | mlxsw_sp_afk_encode_buf(storage_item, output_item, |
|---|
| 421 | 460 | storage, output); |
|---|
| .. | .. |
|---|
| 426 | 465 | void mlxsw_afk_encode(struct mlxsw_afk *mlxsw_afk, |
|---|
| 427 | 466 | struct mlxsw_afk_key_info *key_info, |
|---|
| 428 | 467 | struct mlxsw_afk_element_values *values, |
|---|
| 429 | | - char *key, char *mask, int block_start, int block_end) |
|---|
| 468 | + char *key, char *mask) |
|---|
| 430 | 469 | { |
|---|
| 470 | + unsigned int blocks_count = |
|---|
| 471 | + mlxsw_afk_key_info_blocks_count_get(key_info); |
|---|
| 431 | 472 | char block_mask[MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE]; |
|---|
| 432 | 473 | char block_key[MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE]; |
|---|
| 433 | 474 | const struct mlxsw_afk_element_inst *elinst; |
|---|
| 434 | 475 | enum mlxsw_afk_element element; |
|---|
| 435 | 476 | int block_index, i; |
|---|
| 436 | 477 | |
|---|
| 437 | | - for (i = block_start; i <= block_end; i++) { |
|---|
| 478 | + for (i = 0; i < blocks_count; i++) { |
|---|
| 438 | 479 | memset(block_key, 0, MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE); |
|---|
| 439 | 480 | memset(block_mask, 0, MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE); |
|---|
| 440 | 481 | |
|---|
| .. | .. |
|---|
| 446 | 487 | continue; |
|---|
| 447 | 488 | |
|---|
| 448 | 489 | mlxsw_sp_afk_encode_one(elinst, block_key, |
|---|
| 449 | | - values->storage.key); |
|---|
| 490 | + values->storage.key, |
|---|
| 491 | + elinst->u32_key_diff); |
|---|
| 450 | 492 | mlxsw_sp_afk_encode_one(elinst, block_mask, |
|---|
| 451 | | - values->storage.mask); |
|---|
| 493 | + values->storage.mask, 0); |
|---|
| 452 | 494 | } |
|---|
| 453 | 495 | |
|---|
| 454 | | - if (key) |
|---|
| 455 | | - mlxsw_afk->ops->encode_block(block_key, i, key); |
|---|
| 456 | | - if (mask) |
|---|
| 457 | | - mlxsw_afk->ops->encode_block(block_mask, i, mask); |
|---|
| 496 | + mlxsw_afk->ops->encode_block(key, i, block_key); |
|---|
| 497 | + mlxsw_afk->ops->encode_block(mask, i, block_mask); |
|---|
| 458 | 498 | } |
|---|
| 459 | 499 | } |
|---|
| 460 | 500 | EXPORT_SYMBOL(mlxsw_afk_encode); |
|---|
| 501 | + |
|---|
| 502 | +void mlxsw_afk_clear(struct mlxsw_afk *mlxsw_afk, char *key, |
|---|
| 503 | + int block_start, int block_end) |
|---|
| 504 | +{ |
|---|
| 505 | + int i; |
|---|
| 506 | + |
|---|
| 507 | + for (i = block_start; i <= block_end; i++) |
|---|
| 508 | + mlxsw_afk->ops->clear_block(key, i); |
|---|
| 509 | +} |
|---|
| 510 | +EXPORT_SYMBOL(mlxsw_afk_clear); |
|---|