Lines Matching +full:ipa +full:- +full:reg

1 // SPDX-License-Identifier: GPL-2.0
3 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
4 * Copyright (C) 2018-2023 Linaro Ltd.
15 #include <linux/dma-mapping.h>
17 #include "ipa.h"
28 * DOC: IPA Filter and Route Tables
30 * The IPA has tables defined in its local (IPA-resident) memory that define
32 * endian 64-bit "slot" that holds the address of a rule definition. (The
38 * by all IPA hardware (IPA v4.2 doesn't support hashed tables).
41 * an object (such as a route or filter table) in IPA-resident memory must
42 * 128-byte aligned. An object in system memory (such as a route or filter
43 * rule) must be at an 8-byte aligned address. We currently only place
46 * A rule consists of a contiguous block of 32-bit values terminated with
52 * not all TX endpoints support filtering. The first 64-bit slot in a
55 * address of a filter rule in the memory following the bitmap. Until IPA
56 * v5.0, the low-order bit (bit 0) in this bitmap represents a special
61 * removed starting at IPA v5.0. For IPA v5.0+, the endpoint bitmap
62 * position defines the endpoint ID--i.e. if bit 1 is set in the endpoint
63 * bitmap, endpoint 1 has a filter rule. Older versions of IPA represent
75 * endpoints they "own" directly. Currently the AP does not use the IPA
79 * bitmap as defined prior to IPA v5.0.
81 * IPA Filter Table
82 * ----------------------
84 * |--------------------|
86 * |--------------------|
88 * |--------------------|
90 * |--------------------|
92 * |--------------------|
94 * ----------------------
100 * though the AP currently does not use the IPA routing functionality.
102 * IPA Route Table
103 * ----------------------
105 * |--------------------|
107 * |--------------------|
109 * |--------------------|
111 * |--------------------|
113 * |--------------------|
115 * |--------------------|
117 * |--------------------|
119 * ----------------------
122 /* Filter or route rules consist of a set of 32-bit values followed by a
123 * 32-bit all-zero rule list terminator. The "zero rule" is simply an
124 * all-zero rule followed by the list terminator.
141 * It is a 64-bit block of zeroed memory. Code in ipa_table_init() in ipa_table_validate_build()
148 ipa_table_mem(struct ipa *ipa, bool filter, bool hashed, bool ipv6) in ipa_table_mem() argument
161 return ipa_mem_find(ipa, mem_id); in ipa_table_mem()
164 bool ipa_filtered_valid(struct ipa *ipa, u64 filtered) in ipa_filtered_valid() argument
166 struct device *dev = &ipa->pdev->dev; in ipa_filtered_valid()
176 if (count > ipa->filter_count) { in ipa_filtered_valid()
178 count, ipa->filter_count); in ipa_filtered_valid()
187 static dma_addr_t ipa_table_addr(struct ipa *ipa, bool filter_mask, u16 count) in ipa_table_addr() argument
194 WARN_ON(count > max_t(u32, ipa->filter_count, ipa->route_count)); in ipa_table_addr()
199 return ipa->table_addr + skip * sizeof(*ipa->table_virt); in ipa_table_addr()
205 struct ipa *ipa = container_of(trans->gsi, struct ipa, gsi); in ipa_table_reset_add() local
212 mem = ipa_table_mem(ipa, filter, hashed, ipv6); in ipa_table_reset_add()
213 if (!mem || !mem->size) in ipa_table_reset_add()
219 offset = mem->offset + first * sizeof(__le64); in ipa_table_reset_add()
221 addr = ipa_table_addr(ipa, false, count); in ipa_table_reset_add()
228 * for the IPv4 and IPv6 non-hashed and hashed filter tables.
231 ipa_filter_reset_table(struct ipa *ipa, bool hashed, bool ipv6, bool modem) in ipa_filter_reset_table() argument
233 u64 ep_mask = ipa->filtered; in ipa_filter_reset_table()
237 trans = ipa_cmd_trans_alloc(ipa, hweight64(ep_mask)); in ipa_filter_reset_table()
239 dev_err(&ipa->pdev->dev, in ipa_filter_reset_table()
242 return -EBUSY; in ipa_filter_reset_table()
252 endpoint = &ipa->endpoint[endpoint_id]; in ipa_filter_reset_table()
253 if (endpoint->ee_id != ee_id) in ipa_filter_reset_table()
268 static int ipa_filter_reset(struct ipa *ipa, bool modem) in ipa_filter_reset() argument
272 ret = ipa_filter_reset_table(ipa, false, false, modem); in ipa_filter_reset()
276 ret = ipa_filter_reset_table(ipa, false, true, modem); in ipa_filter_reset()
277 if (ret || !ipa_table_hash_support(ipa)) in ipa_filter_reset()
280 ret = ipa_filter_reset_table(ipa, true, false, modem); in ipa_filter_reset()
284 return ipa_filter_reset_table(ipa, true, true, modem); in ipa_filter_reset()
289 * won't exceed the per-transaction command limit.
291 static int ipa_route_reset(struct ipa *ipa, bool modem) in ipa_route_reset() argument
293 bool hash_support = ipa_table_hash_support(ipa); in ipa_route_reset()
294 u32 modem_route_count = ipa->modem_route_count; in ipa_route_reset()
299 trans = ipa_cmd_trans_alloc(ipa, hash_support ? 4 : 2); in ipa_route_reset()
301 dev_err(&ipa->pdev->dev, in ipa_route_reset()
304 return -EBUSY; in ipa_route_reset()
312 count = ipa->route_count - modem_route_count; in ipa_route_reset()
328 void ipa_table_reset(struct ipa *ipa, bool modem) in ipa_table_reset() argument
330 struct device *dev = &ipa->pdev->dev; in ipa_table_reset()
337 ret = ipa_filter_reset(ipa, modem); in ipa_table_reset()
342 ret = ipa_route_reset(ipa, modem); in ipa_table_reset()
348 int ipa_table_hash_flush(struct ipa *ipa) in ipa_table_hash_flush() argument
351 const struct reg *reg; in ipa_table_hash_flush() local
354 if (!ipa_table_hash_support(ipa)) in ipa_table_hash_flush()
357 trans = ipa_cmd_trans_alloc(ipa, 1); in ipa_table_hash_flush()
359 dev_err(&ipa->pdev->dev, "no transaction for hash flush\n"); in ipa_table_hash_flush()
360 return -EBUSY; in ipa_table_hash_flush()
363 if (ipa->version < IPA_VERSION_5_0) { in ipa_table_hash_flush()
364 reg = ipa_reg(ipa, FILT_ROUT_HASH_FLUSH); in ipa_table_hash_flush()
366 val = reg_bit(reg, IPV6_ROUTER_HASH); in ipa_table_hash_flush()
367 val |= reg_bit(reg, IPV6_FILTER_HASH); in ipa_table_hash_flush()
368 val |= reg_bit(reg, IPV4_ROUTER_HASH); in ipa_table_hash_flush()
369 val |= reg_bit(reg, IPV4_FILTER_HASH); in ipa_table_hash_flush()
371 reg = ipa_reg(ipa, FILT_ROUT_CACHE_FLUSH); in ipa_table_hash_flush()
373 /* IPA v5.0+ uses a unified cache (both IPv4 and IPv6) */ in ipa_table_hash_flush()
374 val = reg_bit(reg, ROUTER_CACHE); in ipa_table_hash_flush()
375 val |= reg_bit(reg, FILTER_CACHE); in ipa_table_hash_flush()
378 ipa_cmd_register_write_add(trans, reg_offset(reg), val, val, false); in ipa_table_hash_flush()
387 struct ipa *ipa = container_of(trans->gsi, struct ipa, gsi); in ipa_table_init_add() local
406 /* The non-hashed region will exist (see ipa_table_mem_valid()) */ in ipa_table_init_add()
407 mem = ipa_table_mem(ipa, filter, false, ipv6); in ipa_table_init_add()
408 hash_mem = ipa_table_mem(ipa, filter, true, ipv6); in ipa_table_init_add()
409 hash_offset = hash_mem ? hash_mem->offset : 0; in ipa_table_init_add()
416 * table is either the same as the non-hashed one, or zero. in ipa_table_init_add()
418 count = 1 + hweight64(ipa->filtered); in ipa_table_init_add()
419 hash_count = hash_mem && hash_mem->size ? count : 0; in ipa_table_init_add()
424 count = mem->size / sizeof(__le64); in ipa_table_init_add()
425 hash_count = hash_mem ? hash_mem->size / sizeof(__le64) : 0; in ipa_table_init_add()
430 addr = ipa_table_addr(ipa, filter, count); in ipa_table_init_add()
431 hash_addr = ipa_table_addr(ipa, filter, hash_count); in ipa_table_init_add()
433 ipa_cmd_table_init_add(trans, opcode, size, mem->offset, addr, in ipa_table_init_add()
439 zero_offset = mem->offset + size; in ipa_table_init_add()
440 zero_size = mem->size - size; in ipa_table_init_add()
442 ipa->zero_addr, true); in ipa_table_init_add()
448 zero_size = hash_mem->size - hash_size; in ipa_table_init_add()
450 ipa->zero_addr, true); in ipa_table_init_add()
453 int ipa_table_setup(struct ipa *ipa) in ipa_table_setup() argument
458 * - IPv4: in ipa_table_setup()
459 * - One for route table initialization (non-hashed and hashed) in ipa_table_setup()
460 * - One for filter table initialization (non-hashed and hashed) in ipa_table_setup()
461 * - One to zero unused entries in the non-hashed filter table in ipa_table_setup()
462 * - One to zero unused entries in the hashed filter table in ipa_table_setup()
463 * - IPv6: in ipa_table_setup()
464 * - One for route table initialization (non-hashed and hashed) in ipa_table_setup()
465 * - One for filter table initialization (non-hashed and hashed) in ipa_table_setup()
466 * - One to zero unused entries in the non-hashed filter table in ipa_table_setup()
467 * - One to zero unused entries in the hashed filter table in ipa_table_setup()
470 trans = ipa_cmd_trans_alloc(ipa, 8); in ipa_table_setup()
472 dev_err(&ipa->pdev->dev, "no transaction for table setup\n"); in ipa_table_setup()
473 return -EBUSY; in ipa_table_setup()
487 * ipa_filter_tuple_zero() - Zero an endpoint's hashed filter tuple
495 u32 endpoint_id = endpoint->endpoint_id; in ipa_filter_tuple_zero()
496 struct ipa *ipa = endpoint->ipa; in ipa_filter_tuple_zero() local
497 const struct reg *reg; in ipa_filter_tuple_zero() local
501 if (ipa->version < IPA_VERSION_5_0) { in ipa_filter_tuple_zero()
502 reg = ipa_reg(ipa, ENDP_FILTER_ROUTER_HSH_CFG); in ipa_filter_tuple_zero()
504 offset = reg_n_offset(reg, endpoint_id); in ipa_filter_tuple_zero()
505 val = ioread32(endpoint->ipa->reg_virt + offset); in ipa_filter_tuple_zero()
507 /* Zero all filter-related fields, preserving the rest */ in ipa_filter_tuple_zero()
508 val &= ~reg_fmask(reg, FILTER_HASH_MSK_ALL); in ipa_filter_tuple_zero()
510 /* IPA v5.0 separates filter and router cache configuration */ in ipa_filter_tuple_zero()
511 reg = ipa_reg(ipa, ENDP_FILTER_CACHE_CFG); in ipa_filter_tuple_zero()
512 offset = reg_n_offset(reg, endpoint_id); in ipa_filter_tuple_zero()
514 /* Zero all filter-related fields */ in ipa_filter_tuple_zero()
518 iowrite32(val, endpoint->ipa->reg_virt + offset); in ipa_filter_tuple_zero()
522 static void ipa_filter_config(struct ipa *ipa, bool modem) in ipa_filter_config() argument
525 u64 ep_mask = ipa->filtered; in ipa_filter_config()
527 if (!ipa_table_hash_support(ipa)) in ipa_filter_config()
536 endpoint = &ipa->endpoint[endpoint_id]; in ipa_filter_config()
537 if (endpoint->ee_id == ee_id) in ipa_filter_config()
542 static bool ipa_route_id_modem(struct ipa *ipa, u32 route_id) in ipa_route_id_modem() argument
544 return route_id < ipa->modem_route_count; in ipa_route_id_modem()
548 * ipa_route_tuple_zero() - Zero a hashed route table entry tuple
549 * @ipa: IPA pointer
554 static void ipa_route_tuple_zero(struct ipa *ipa, u32 route_id) in ipa_route_tuple_zero() argument
556 const struct reg *reg; in ipa_route_tuple_zero() local
560 if (ipa->version < IPA_VERSION_5_0) { in ipa_route_tuple_zero()
561 reg = ipa_reg(ipa, ENDP_FILTER_ROUTER_HSH_CFG); in ipa_route_tuple_zero()
562 offset = reg_n_offset(reg, route_id); in ipa_route_tuple_zero()
564 val = ioread32(ipa->reg_virt + offset); in ipa_route_tuple_zero()
566 /* Zero all route-related fields, preserving the rest */ in ipa_route_tuple_zero()
567 val &= ~reg_fmask(reg, ROUTER_HASH_MSK_ALL); in ipa_route_tuple_zero()
569 /* IPA v5.0 separates filter and router cache configuration */ in ipa_route_tuple_zero()
570 reg = ipa_reg(ipa, ENDP_ROUTER_CACHE_CFG); in ipa_route_tuple_zero()
571 offset = reg_n_offset(reg, route_id); in ipa_route_tuple_zero()
573 /* Zero all route-related fields */ in ipa_route_tuple_zero()
577 iowrite32(val, ipa->reg_virt + offset); in ipa_route_tuple_zero()
581 static void ipa_route_config(struct ipa *ipa, bool modem) in ipa_route_config() argument
585 if (!ipa_table_hash_support(ipa)) in ipa_route_config()
588 for (route_id = 0; route_id < ipa->route_count; route_id++) in ipa_route_config()
589 if (ipa_route_id_modem(ipa, route_id) == modem) in ipa_route_config()
590 ipa_route_tuple_zero(ipa, route_id); in ipa_route_config()
594 void ipa_table_config(struct ipa *ipa) in ipa_table_config() argument
596 ipa_filter_config(ipa, false); in ipa_table_config()
597 ipa_filter_config(ipa, true); in ipa_table_config()
598 ipa_route_config(ipa, false); in ipa_table_config()
599 ipa_route_config(ipa, true); in ipa_table_config()
602 /* Verify the sizes of all IPA table filter or routing table memory regions
605 bool ipa_table_mem_valid(struct ipa *ipa, bool filter) in ipa_table_mem_valid() argument
607 bool hash_support = ipa_table_hash_support(ipa); in ipa_table_mem_valid()
613 /* IPv4 and IPv6 non-hashed tables are expected to be defined and in ipa_table_mem_valid()
617 mem_ipv4 = ipa_table_mem(ipa, filter, false, false); in ipa_table_mem_valid()
621 mem_ipv6 = ipa_table_mem(ipa, filter, false, true); in ipa_table_mem_valid()
625 if (mem_ipv4->size != mem_ipv6->size) in ipa_table_mem_valid()
629 count = mem_ipv4->size / sizeof(__le64); in ipa_table_mem_valid()
633 ipa->filter_count = count - 1; /* Filter map in first entry */ in ipa_table_mem_valid()
635 ipa->route_count = count; in ipa_table_mem_valid()
638 if (!ipa_cmd_table_init_valid(ipa, mem_ipv4, !filter)) in ipa_table_mem_valid()
646 if (count < 1 + hweight64(ipa->filtered)) in ipa_table_mem_valid()
652 if (count < ipa->modem_route_count + 1) in ipa_table_mem_valid()
657 * and have the same size as non-hashed tables. If hashing is not in ipa_table_mem_valid()
661 mem_hashed = ipa_table_mem(ipa, filter, true, false); in ipa_table_mem_valid()
663 if (!mem_hashed || mem_hashed->size != mem_ipv4->size) in ipa_table_mem_valid()
666 if (mem_hashed && mem_hashed->size) in ipa_table_mem_valid()
671 mem_hashed = ipa_table_mem(ipa, filter, true, true); in ipa_table_mem_valid()
673 if (!mem_hashed || mem_hashed->size != mem_ipv6->size) in ipa_table_mem_valid()
676 if (mem_hashed && mem_hashed->size) in ipa_table_mem_valid()
684 * route table data. This is used when initializing or resetting the IPA
696 * routing there is also a 64-bit "zero rule" that means no routing, and
700 * +-------------------+
701 * --> | zero rule |
702 * / |-------------------|
704 * |\ |-------------------|
705 * | ---- zero rule address | \
706 * |\ |-------------------| |
707 * | ---- zero rule address | | Max IPA filter count
708 * | |-------------------| > or IPA route count,
710 * \ |-------------------| |
711 * ---- zero rule address | /
712 * +-------------------+
714 int ipa_table_init(struct ipa *ipa) in ipa_table_init() argument
716 struct device *dev = &ipa->pdev->dev; in ipa_table_init()
725 count = max_t(u32, ipa->filter_count, ipa->route_count); in ipa_table_init()
727 /* The IPA hardware requires route and filter table rules to be in ipa_table_init()
728 * aligned on a 128-byte boundary. We put the "zero rule" at the in ipa_table_init()
730 * by dma_alloc_coherent() is guaranteed to be a power-of-2 number in ipa_table_init()
736 return -ENOMEM; in ipa_table_init()
738 ipa->table_virt = virt; in ipa_table_init()
739 ipa->table_addr = addr; in ipa_table_init()
746 * it left one position. Prior to IPA v5.0, bit 0 repesents global in ipa_table_init()
747 * filtering, which is possible but not used. IPA v5.0+ eliminated in ipa_table_init()
750 if (ipa->version < IPA_VERSION_5_0) in ipa_table_init()
751 *virt++ = cpu_to_le64(ipa->filtered << 1); in ipa_table_init()
753 *virt++ = cpu_to_le64(ipa->filtered); in ipa_table_init()
757 while (count--) in ipa_table_init()
763 void ipa_table_exit(struct ipa *ipa) in ipa_table_exit() argument
765 u32 count = max_t(u32, 1 + ipa->filter_count, ipa->route_count); in ipa_table_exit()
766 struct device *dev = &ipa->pdev->dev; in ipa_table_exit()
771 dma_free_coherent(dev, size, ipa->table_virt, ipa->table_addr); in ipa_table_exit()
772 ipa->table_addr = 0; in ipa_table_exit()
773 ipa->table_virt = NULL; in ipa_table_exit()