Commit 19aaf72c authored by Alex Elder's avatar Alex Elder Committed by David S. Miller

net: ipa: DMA addresses are nicely aligned

A recent patch avoided doing 64-bit modulo operations by checking
the alignment of some DMA allocations using only the lower 32 bits
of the address.

David Laight pointed out (after the fix was committed) that DMA
allocations might already satisfy the alignment requirements.  And
he was right.

Remove the alignment checks that occur after DMA allocation requests,
and update comments to explain why the constraint is satisfied.  The
only place IPA_TABLE_ALIGN was used was to check the alignment; it is
therefore no longer needed, so get rid of it.

Add comments where GSI_RING_ELEMENT_SIZE and the tre_count and
event_count channel data fields are defined to make explicit they
are required to be powers of 2.

Revise a comment in gsi_trans_pool_init_dma(), taking into account
that dma_alloc_coherent() guarantees its result is aligned to a page
size (or order thereof).

Don't bother printing an error if a DMA allocation fails.
Suggested-by: default avatarDavid Laight <David.Laight@ACULAB.COM>
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 782d767a
...@@ -1444,18 +1444,13 @@ static int gsi_ring_alloc(struct gsi *gsi, struct gsi_ring *ring, u32 count) ...@@ -1444,18 +1444,13 @@ static int gsi_ring_alloc(struct gsi *gsi, struct gsi_ring *ring, u32 count)
dma_addr_t addr; dma_addr_t addr;
/* Hardware requires a 2^n ring size, with alignment equal to size. /* Hardware requires a 2^n ring size, with alignment equal to size.
* The size is a power of 2, so we can check alignment using just * The DMA address returned by dma_alloc_coherent() is guaranteed to
* the bottom 32 bits for a DMA address of any size. * be a power-of-2 number of pages, which satisfies the requirement.
*/ */
ring->virt = dma_alloc_coherent(dev, size, &addr, GFP_KERNEL); ring->virt = dma_alloc_coherent(dev, size, &addr, GFP_KERNEL);
if (ring->virt && lower_32_bits(addr) % size) { if (!ring->virt)
dma_free_coherent(dev, size, ring->virt, addr);
dev_err(dev, "unable to alloc 0x%x-aligned ring buffer\n",
size);
return -EINVAL; /* Not a good error value, but distinct */
} else if (!ring->virt) {
return -ENOMEM; return -ENOMEM;
}
ring->addr = addr; ring->addr = addr;
ring->count = count; ring->count = count;
......
...@@ -14,7 +14,7 @@ struct gsi_trans; ...@@ -14,7 +14,7 @@ struct gsi_trans;
struct gsi_ring; struct gsi_ring;
struct gsi_channel; struct gsi_channel;
#define GSI_RING_ELEMENT_SIZE 16 /* bytes */ #define GSI_RING_ELEMENT_SIZE 16 /* bytes; must be a power of 2 */
/* Return the entry that follows one provided in a transaction pool */ /* Return the entry that follows one provided in a transaction pool */
void *gsi_trans_pool_next(struct gsi_trans_pool *pool, void *element); void *gsi_trans_pool_next(struct gsi_trans_pool *pool, void *element);
......
...@@ -153,11 +153,10 @@ int gsi_trans_pool_init_dma(struct device *dev, struct gsi_trans_pool *pool, ...@@ -153,11 +153,10 @@ int gsi_trans_pool_init_dma(struct device *dev, struct gsi_trans_pool *pool,
size = __roundup_pow_of_two(size); size = __roundup_pow_of_two(size);
total_size = (count + max_alloc - 1) * size; total_size = (count + max_alloc - 1) * size;
/* The allocator will give us a power-of-2 number of pages. But we /* The allocator will give us a power-of-2 number of pages
* can't guarantee that, so request it. That way we won't waste any * sufficient to satisfy our request. Round up our requested
* memory that would be available beyond the required space. * size to avoid any unused space in the allocation. This way
* * gsi_trans_pool_exit_dma() can assume the total allocated
* Note that gsi_trans_pool_exit_dma() assumes the total allocated
* size is exactly (count * size). * size is exactly (count * size).
*/ */
total_size = get_order(total_size) << PAGE_SHIFT; total_size = get_order(total_size) << PAGE_SHIFT;
......
...@@ -90,8 +90,8 @@ struct ipa_qsb_data { ...@@ -90,8 +90,8 @@ struct ipa_qsb_data {
* that can be included in a single transaction. * that can be included in a single transaction.
*/ */
struct gsi_channel_data { struct gsi_channel_data {
u16 tre_count; u16 tre_count; /* must be a power of 2 */
u16 event_count; u16 event_count; /* must be a power of 2 */
u8 tlv_count; u8 tlv_count;
}; };
......
...@@ -96,9 +96,6 @@ ...@@ -96,9 +96,6 @@
* ---------------------- * ----------------------
*/ */
/* IPA hardware constrains filter and route tables alignment */
#define IPA_TABLE_ALIGN 128 /* Minimum table alignment */
/* Assignment of route table entries to the modem and AP */ /* Assignment of route table entries to the modem and AP */
#define IPA_ROUTE_MODEM_MIN 0 #define IPA_ROUTE_MODEM_MIN 0
#define IPA_ROUTE_MODEM_COUNT 8 #define IPA_ROUTE_MODEM_COUNT 8
...@@ -652,26 +649,17 @@ int ipa_table_init(struct ipa *ipa) ...@@ -652,26 +649,17 @@ int ipa_table_init(struct ipa *ipa)
ipa_table_validate_build(); ipa_table_validate_build();
/* The IPA hardware requires route and filter table rules to be
* aligned on a 128-byte boundary. We put the "zero rule" at the
* base of the table area allocated here. The DMA address returned
* by dma_alloc_coherent() is guaranteed to be a power-of-2 number
* of pages, which satisfies the rule alignment requirement.
*/
size = IPA_ZERO_RULE_SIZE + (1 + count) * IPA_TABLE_ENTRY_SIZE; size = IPA_ZERO_RULE_SIZE + (1 + count) * IPA_TABLE_ENTRY_SIZE;
virt = dma_alloc_coherent(dev, size, &addr, GFP_KERNEL); virt = dma_alloc_coherent(dev, size, &addr, GFP_KERNEL);
if (!virt) if (!virt)
return -ENOMEM; return -ENOMEM;
/* We put the "zero rule" at the base of our table area. The IPA
* hardware requires route and filter table rules to be aligned
* on a 128-byte boundary. As long as the alignment constraint
* is a power of 2, we can check alignment using just the bottom
* 32 bits for a DMA address of any size.
*/
BUILD_BUG_ON(!is_power_of_2(IPA_TABLE_ALIGN));
if (lower_32_bits(addr) % IPA_TABLE_ALIGN) {
dev_err(dev, "table address %pad not %u-byte aligned\n",
&addr, IPA_TABLE_ALIGN);
dma_free_coherent(dev, size, virt, addr);
return -ERANGE;
}
ipa->table_virt = virt; ipa->table_virt = virt;
ipa->table_addr = addr; ipa->table_addr = addr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment