Lines Matching +full:ipa +full:- +full:ap +full:- +full:to +full:- +full:modem

1 // SPDX-License-Identifier: GPL-2.0
3 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
4 * Copyright (C) 2018-2022 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
51 * Each filter rule is associated with an AP or modem TX endpoint, though
52 * not all TX endpoints support filtering. The first 64-bit slot in a
54 * the table. The low-order bit (bit 0) in this bitmap represents a
55 * special global filter, which applies to all traffic. This is not
57 * entry (i.e. slot containing a system address referring to a rule) for
59 * for endpoint 2, and so on. Space is set aside in IPA local memory to
63 * The AP initializes all entries in a filter table to refer to a "zero"
64 * entry. Once initialized the modem and AP update the entries for
65 * endpoints they "own" directly. Currently the AP does not use the
66 * IPA filtering functionality.
68 * IPA Filter Table
69 * ----------------------
71 * |--------------------|
72 * 1st endpoint | 0x000123456789abc0 | DMA address for modem endpoint 2 rule
73 * |--------------------|
74 * 2nd endpoint | 0x000123456789abf0 | DMA address for AP endpoint 5 rule
75 * |--------------------|
77 * |--------------------|
79 * |--------------------|
81 * ----------------------
83 * The set of available route rules is divided about equally between the AP
84 * and modem. The AP initializes all entries in a route table to refer to
85 * a "zero entry". Once initialized, the modem and AP are responsible for
87 * though the AP currently does not use the IPA routing functionality.
89 * IPA Route Table
90 * ----------------------
91 * 1st modem route | 0x0001234500001100 | DMA address for first route rule
92 * |--------------------|
93 * 2nd modem route | 0x0001234500001140 | DMA address for second route rule
94 * |--------------------|
96 * |--------------------|
97 * Last modem route| 0x0001234500002280 | DMA address for Nth route rule
98 * |--------------------|
99 * 1st AP route | 0x0001234500001100 | DMA address for route rule (N+1)
100 * |--------------------|
101 * 2nd AP route | 0x0001234500001140 | DMA address for next route rule
102 * |--------------------|
104 * |--------------------|
105 * Last AP route | 0x0001234500002280 | DMA address for last route rule
106 * ----------------------
109 /* Assignment of route table entries to the modem and AP */
113 (IPA_ROUTE_COUNT_MAX - IPA_ROUTE_MODEM_COUNT)
115 /* Filter or route rules consist of a set of 32-bit values followed by a
116 * 32-bit all-zero rule list terminator. The "zero rule" is simply an
117 * all-zero rule followed by the list terminator.
125 * to filter or route rules. But the size of a table entry in ipa_table_validate_build()
126 * is 64 bits regardless of what the size of an AP DMA address in ipa_table_validate_build()
128 * code in ipa_table_init() uses a pointer to __le64 to in ipa_table_validate_build()
133 /* A "zero rule" is used to represent no filtering or no routing. in ipa_table_validate_build()
134 * It is a 64-bit block of zeroed memory. Code in ipa_table_init() in ipa_table_validate_build()
135 * assumes that it can be written using a pointer to __le64. in ipa_table_validate_build()
141 /* The modem must be allotted at least one route table entry */ in ipa_table_validate_build()
149 ipa_table_valid_one(struct ipa *ipa, enum ipa_mem_id mem_id, bool route) in ipa_table_valid_one() argument
151 const struct ipa_mem *mem = ipa_mem_find(ipa, mem_id); in ipa_table_valid_one()
152 struct device *dev = &ipa->pdev->dev; in ipa_table_valid_one()
160 if (!ipa_cmd_table_valid(ipa, mem, route)) in ipa_table_valid_one()
163 /* mem->size >= size is sufficient, but we'll demand more */ in ipa_table_valid_one()
164 if (mem->size == size) in ipa_table_valid_one()
168 if (ipa_table_hash_support(ipa) && !mem->size) in ipa_table_valid_one()
172 route ? "route" : "filter", mem_id, mem->size, size); in ipa_table_valid_one()
178 bool ipa_table_valid(struct ipa *ipa) in ipa_table_valid() argument
182 valid = ipa_table_valid_one(ipa, IPA_MEM_V4_FILTER, false); in ipa_table_valid()
183 valid = valid && ipa_table_valid_one(ipa, IPA_MEM_V6_FILTER, false); in ipa_table_valid()
184 valid = valid && ipa_table_valid_one(ipa, IPA_MEM_V4_ROUTE, true); in ipa_table_valid()
185 valid = valid && ipa_table_valid_one(ipa, IPA_MEM_V6_ROUTE, true); in ipa_table_valid()
187 if (!ipa_table_hash_support(ipa)) in ipa_table_valid()
190 valid = valid && ipa_table_valid_one(ipa, IPA_MEM_V4_FILTER_HASHED, in ipa_table_valid()
192 valid = valid && ipa_table_valid_one(ipa, IPA_MEM_V6_FILTER_HASHED, in ipa_table_valid()
194 valid = valid && ipa_table_valid_one(ipa, IPA_MEM_V4_ROUTE_HASHED, in ipa_table_valid()
196 valid = valid && ipa_table_valid_one(ipa, IPA_MEM_V6_ROUTE_HASHED, in ipa_table_valid()
202 bool ipa_filter_map_valid(struct ipa *ipa, u32 filter_map) in ipa_filter_map_valid() argument
204 struct device *dev = &ipa->pdev->dev; in ipa_filter_map_valid()
225 static dma_addr_t ipa_table_addr(struct ipa *ipa, bool filter_mask, u16 count) in ipa_table_addr() argument
237 return ipa->table_addr + skip * sizeof(*ipa->table_virt); in ipa_table_addr()
243 struct ipa *ipa = container_of(trans->gsi, struct ipa, gsi); in ipa_table_reset_add() local
244 const struct ipa_mem *mem = ipa_mem_find(ipa, mem_id); in ipa_table_reset_add()
249 /* Nothing to do if the table memory region is empty */ in ipa_table_reset_add()
250 if (!mem->size) in ipa_table_reset_add()
256 offset = mem->offset + first * sizeof(__le64); in ipa_table_reset_add()
258 addr = ipa_table_addr(ipa, false, count); in ipa_table_reset_add()
263 /* Reset entries in a single filter table belonging to either the AP or
264 * modem to refer to the zero entry. The memory region supplied will be
265 * for the IPv4 and IPv6 non-hashed and hashed filter tables.
268 ipa_filter_reset_table(struct ipa *ipa, enum ipa_mem_id mem_id, bool modem) in ipa_filter_reset_table() argument
270 u32 ep_mask = ipa->filter_map; in ipa_filter_reset_table()
275 trans = ipa_cmd_trans_alloc(ipa, count); in ipa_filter_reset_table()
277 dev_err(&ipa->pdev->dev, in ipa_filter_reset_table()
279 modem ? "modem" : "AP"); in ipa_filter_reset_table()
280 return -EBUSY; in ipa_filter_reset_table()
283 ee_id = modem ? GSI_EE_MODEM : GSI_EE_AP; in ipa_filter_reset_table()
290 endpoint = &ipa->endpoint[endpoint_id]; in ipa_filter_reset_table()
291 if (endpoint->ee_id != ee_id) in ipa_filter_reset_table()
302 /* Theoretically, each filter table could have more filter slots to
306 static int ipa_filter_reset(struct ipa *ipa, bool modem) in ipa_filter_reset() argument
310 ret = ipa_filter_reset_table(ipa, IPA_MEM_V4_FILTER, modem); in ipa_filter_reset()
314 ret = ipa_filter_reset_table(ipa, IPA_MEM_V4_FILTER_HASHED, modem); in ipa_filter_reset()
318 ret = ipa_filter_reset_table(ipa, IPA_MEM_V6_FILTER, modem); in ipa_filter_reset()
321 ret = ipa_filter_reset_table(ipa, IPA_MEM_V6_FILTER_HASHED, modem); in ipa_filter_reset()
326 /* The AP routes and modem routes are each contiguous within the
328 * won't exceed the per-transaction command limit.
330 static int ipa_route_reset(struct ipa *ipa, bool modem) in ipa_route_reset() argument
336 trans = ipa_cmd_trans_alloc(ipa, 4); in ipa_route_reset()
338 dev_err(&ipa->pdev->dev, in ipa_route_reset()
340 modem ? "modem" : "AP"); in ipa_route_reset()
341 return -EBUSY; in ipa_route_reset()
344 if (modem) { in ipa_route_reset()
365 void ipa_table_reset(struct ipa *ipa, bool modem) in ipa_table_reset() argument
367 struct device *dev = &ipa->pdev->dev; in ipa_table_reset()
371 ee_name = modem ? "modem" : "AP"; in ipa_table_reset()
374 ret = ipa_filter_reset(ipa, modem); in ipa_table_reset()
379 ret = ipa_route_reset(ipa, modem); in ipa_table_reset()
385 int ipa_table_hash_flush(struct ipa *ipa) in ipa_table_hash_flush() argument
392 if (!ipa_table_hash_support(ipa)) in ipa_table_hash_flush()
395 trans = ipa_cmd_trans_alloc(ipa, 1); in ipa_table_hash_flush()
397 dev_err(&ipa->pdev->dev, "no transaction for hash flush\n"); in ipa_table_hash_flush()
398 return -EBUSY; in ipa_table_hash_flush()
401 reg = ipa_reg(ipa, FILT_ROUT_HASH_FLUSH); in ipa_table_hash_flush()
421 struct ipa *ipa = container_of(trans->gsi, struct ipa, gsi); in ipa_table_init_add() local
422 const struct ipa_mem *hash_mem = ipa_mem_find(ipa, hash_mem_id); in ipa_table_init_add()
423 const struct ipa_mem *mem = ipa_mem_find(ipa, mem_id); in ipa_table_init_add()
433 /* Compute the number of table entries to initialize */ in ipa_table_init_add()
437 * to hold the bitmap itself. The size of the hashed filter in ipa_table_init_add()
438 * table is either the same as the non-hashed one, or zero. in ipa_table_init_add()
440 count = 1 + hweight32(ipa->filter_map); in ipa_table_init_add()
441 hash_count = hash_mem->size ? count : 0; in ipa_table_init_add()
446 count = mem->size / sizeof(__le64); in ipa_table_init_add()
447 hash_count = hash_mem->size / sizeof(__le64); in ipa_table_init_add()
452 addr = ipa_table_addr(ipa, filter, count); in ipa_table_init_add()
453 hash_addr = ipa_table_addr(ipa, filter, hash_count); in ipa_table_init_add()
455 ipa_cmd_table_init_add(trans, opcode, size, mem->offset, addr, in ipa_table_init_add()
456 hash_size, hash_mem->offset, hash_addr); in ipa_table_init_add()
461 zero_offset = mem->offset + size; in ipa_table_init_add()
462 zero_size = mem->size - size; in ipa_table_init_add()
464 ipa->zero_addr, true); in ipa_table_init_add()
469 zero_offset = hash_mem->offset + hash_size; in ipa_table_init_add()
470 zero_size = hash_mem->size - hash_size; in ipa_table_init_add()
472 ipa->zero_addr, true); in ipa_table_init_add()
475 int ipa_table_setup(struct ipa *ipa) in ipa_table_setup() argument
480 * - IPv4: in ipa_table_setup()
481 * - One for route table initialization (non-hashed and hashed) in ipa_table_setup()
482 * - One for filter table initialization (non-hashed and hashed) in ipa_table_setup()
483 * - One to zero unused entries in the non-hashed filter table in ipa_table_setup()
484 * - One to zero unused entries in the hashed filter table in ipa_table_setup()
485 * - IPv6: in ipa_table_setup()
486 * - One for route table initialization (non-hashed and hashed) in ipa_table_setup()
487 * - One for filter table initialization (non-hashed and hashed) in ipa_table_setup()
488 * - One to zero unused entries in the non-hashed filter table in ipa_table_setup()
489 * - One to zero unused entries in the hashed filter table in ipa_table_setup()
492 trans = ipa_cmd_trans_alloc(ipa, 8); in ipa_table_setup()
494 dev_err(&ipa->pdev->dev, "no transaction for table setup\n"); in ipa_table_setup()
495 return -EBUSY; in ipa_table_setup()
516 * ipa_filter_tuple_zero() - Zero an endpoint's hashed filter tuple
519 * Endpoint must be for the AP (not modem) and support filtering. Updates
524 u32 endpoint_id = endpoint->endpoint_id; in ipa_filter_tuple_zero()
525 struct ipa *ipa = endpoint->ipa; in ipa_filter_tuple_zero() local
530 reg = ipa_reg(ipa, ENDP_FILTER_ROUTER_HSH_CFG); in ipa_filter_tuple_zero()
533 val = ioread32(endpoint->ipa->reg_virt + offset); in ipa_filter_tuple_zero()
535 /* Zero all filter-related fields, preserving the rest */ in ipa_filter_tuple_zero()
538 iowrite32(val, endpoint->ipa->reg_virt + offset); in ipa_filter_tuple_zero()
542 static void ipa_filter_config(struct ipa *ipa, bool modem) in ipa_filter_config() argument
544 enum gsi_ee_id ee_id = modem ? GSI_EE_MODEM : GSI_EE_AP; in ipa_filter_config()
545 u32 ep_mask = ipa->filter_map; in ipa_filter_config()
547 if (!ipa_table_hash_support(ipa)) in ipa_filter_config()
556 endpoint = &ipa->endpoint[endpoint_id]; in ipa_filter_config()
557 if (endpoint->ee_id == ee_id) in ipa_filter_config()
565 route_id <= IPA_ROUTE_MODEM_MIN + IPA_ROUTE_MODEM_COUNT - 1; in ipa_route_id_modem()
569 * ipa_route_tuple_zero() - Zero a hashed route table entry tuple
570 * @ipa: IPA pointer
575 static void ipa_route_tuple_zero(struct ipa *ipa, u32 route_id) in ipa_route_tuple_zero() argument
581 reg = ipa_reg(ipa, ENDP_FILTER_ROUTER_HSH_CFG); in ipa_route_tuple_zero()
584 val = ioread32(ipa->reg_virt + offset); in ipa_route_tuple_zero()
586 /* Zero all route-related fields, preserving the rest */ in ipa_route_tuple_zero()
589 iowrite32(val, ipa->reg_virt + offset); in ipa_route_tuple_zero()
593 static void ipa_route_config(struct ipa *ipa, bool modem) in ipa_route_config() argument
597 if (!ipa_table_hash_support(ipa)) in ipa_route_config()
601 if (ipa_route_id_modem(route_id) == modem) in ipa_route_config()
602 ipa_route_tuple_zero(ipa, route_id); in ipa_route_config()
606 void ipa_table_config(struct ipa *ipa) in ipa_table_config() argument
608 ipa_filter_config(ipa, false); in ipa_table_config()
609 ipa_filter_config(ipa, true); in ipa_table_config()
610 ipa_route_config(ipa, false); in ipa_table_config()
611 ipa_route_config(ipa, true); in ipa_table_config()
616 * route table data. This is used when initializing or resetting the IPA
620 * endpoints contain entries in the table. In addition to that first entry,
625 * reset) its entries are made to refer to the zero rule.
628 * routing there is also a 64-bit "zero rule" that means no routing, and
629 * when a route table is initialized or reset, its entries are made to refer
630 * to the zero rule. The zero rule is shared for route and filter tables.
632 * Note that the IPA hardware requires a filter or route rule address to be
638 * +-------------------+
639 * --> | zero rule |
640 * / |-------------------|
642 * |\ |-------------------|
643 * | ---- zero rule address | \
644 * |\ |-------------------| |
645 * | ---- zero rule address | | IPA_FILTER_COUNT_MAX
646 * | |-------------------| > or IPA_ROUTE_COUNT_MAX,
648 * \ |-------------------| |
649 * ---- zero rule address | /
650 * +-------------------+
652 int ipa_table_init(struct ipa *ipa) in ipa_table_init() argument
655 struct device *dev = &ipa->pdev->dev; in ipa_table_init()
663 /* The IPA hardware requires route and filter table rules to be in ipa_table_init()
664 * aligned on a 128-byte boundary. We put the "zero rule" at the in ipa_table_init()
666 * by dma_alloc_coherent() is guaranteed to be a power-of-2 number in ipa_table_init()
672 return -ENOMEM; in ipa_table_init()
674 ipa->table_virt = virt; in ipa_table_init()
675 ipa->table_addr = addr; in ipa_table_init()
681 * must be converted to the hardware representation by shifting in ipa_table_init()
685 *virt++ = cpu_to_le64((u64)ipa->filter_map << 1); in ipa_table_init()
689 while (count--) in ipa_table_init()
695 void ipa_table_exit(struct ipa *ipa) in ipa_table_exit() argument
698 struct device *dev = &ipa->pdev->dev; in ipa_table_exit()
703 dma_free_coherent(dev, size, ipa->table_virt, ipa->table_addr); in ipa_table_exit()
704 ipa->table_addr = 0; in ipa_table_exit()
705 ipa->table_virt = NULL; in ipa_table_exit()