Commit 88de7672 authored by Alex Elder's avatar Alex Elder Committed by David S. Miller

net: ipa: use a bitmap for available endpoints

Similar to the previous patch, replace the 32-bit unsigned used to
track endpoints supported by hardware with a Linux bitmap, to allow
an arbitrary number of endpoints to be represented.

Move ipa_endpoint_deconfig() above ipa_endpoint_config() and use
it in the error path of the latter function.
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9a9f5129
...@@ -61,9 +61,10 @@ struct ipa_interrupt; ...@@ -61,9 +61,10 @@ struct ipa_interrupt;
* @zero_addr: DMA address of preallocated zero-filled memory * @zero_addr: DMA address of preallocated zero-filled memory
* @zero_virt: Virtual address of preallocated zero-filled memory * @zero_virt: Virtual address of preallocated zero-filled memory
* @zero_size: Size (bytes) of preallocated zero-filled memory * @zero_size: Size (bytes) of preallocated zero-filled memory
* @endpoint_count: Number of endpoints represented by bit masks below * @endpoint_count: Number of defined bits in most bitmaps below
* @available_count: Number of defined bits in the available bitmap
* @defined: Bitmap of endpoints defined in config data * @defined: Bitmap of endpoints defined in config data
* @available: Bit mask indicating endpoints hardware supports * @available: Bitmap of endpoints supported by hardware
* @filter_map: Bit mask indicating endpoints that support filtering * @filter_map: Bit mask indicating endpoints that support filtering
* @set_up: Bit mask indicating endpoints set up * @set_up: Bit mask indicating endpoints set up
* @enabled: Bit mask indicating endpoints enabled * @enabled: Bit mask indicating endpoints enabled
...@@ -119,8 +120,9 @@ struct ipa { ...@@ -119,8 +120,9 @@ struct ipa {
/* Bitmaps indicating endpoint state */ /* Bitmaps indicating endpoint state */
u32 endpoint_count; u32 endpoint_count;
u32 available_count;
unsigned long *defined; /* Defined in configuration data */ unsigned long *defined; /* Defined in configuration data */
u32 available; /* Supported by hardware */ unsigned long *available; /* Supported by hardware */
u32 filter_map; u32 filter_map;
u32 set_up; u32 set_up;
u32 enabled; u32 enabled;
......
...@@ -351,19 +351,17 @@ ipa_endpoint_program_delay(struct ipa_endpoint *endpoint, bool enable) ...@@ -351,19 +351,17 @@ ipa_endpoint_program_delay(struct ipa_endpoint *endpoint, bool enable)
static bool ipa_endpoint_aggr_active(struct ipa_endpoint *endpoint) static bool ipa_endpoint_aggr_active(struct ipa_endpoint *endpoint)
{ {
u32 endpoint_id = endpoint->endpoint_id; u32 endpoint_id = endpoint->endpoint_id;
u32 mask = BIT(endpoint_id % 32);
struct ipa *ipa = endpoint->ipa; struct ipa *ipa = endpoint->ipa;
u32 unit = endpoint_id / 32; u32 unit = endpoint_id / 32;
const struct ipa_reg *reg; const struct ipa_reg *reg;
u32 val; u32 val;
/* This works until we actually have more than 32 endpoints */ WARN_ON(!test_bit(endpoint_id, ipa->available));
WARN_ON(!(mask & ipa->available));
reg = ipa_reg(ipa, STATE_AGGR_ACTIVE); reg = ipa_reg(ipa, STATE_AGGR_ACTIVE);
val = ioread32(ipa->reg_virt + ipa_reg_n_offset(reg, unit)); val = ioread32(ipa->reg_virt + ipa_reg_n_offset(reg, unit));
return !!(val & mask); return !!(val & BIT(endpoint_id % 32));
} }
static void ipa_endpoint_force_close(struct ipa_endpoint *endpoint) static void ipa_endpoint_force_close(struct ipa_endpoint *endpoint)
...@@ -374,8 +372,7 @@ static void ipa_endpoint_force_close(struct ipa_endpoint *endpoint) ...@@ -374,8 +372,7 @@ static void ipa_endpoint_force_close(struct ipa_endpoint *endpoint)
u32 unit = endpoint_id / 32; u32 unit = endpoint_id / 32;
const struct ipa_reg *reg; const struct ipa_reg *reg;
/* This works until we actually have more than 32 endpoints */ WARN_ON(!test_bit(endpoint_id, ipa->available));
WARN_ON(!(mask & ipa->available));
reg = ipa_reg(ipa, AGGR_FORCE_CLOSE); reg = ipa_reg(ipa, AGGR_FORCE_CLOSE);
iowrite32(mask, ipa->reg_virt + ipa_reg_n_offset(reg, unit)); iowrite32(mask, ipa->reg_virt + ipa_reg_n_offset(reg, unit));
...@@ -1841,6 +1838,13 @@ void ipa_endpoint_teardown(struct ipa *ipa) ...@@ -1841,6 +1838,13 @@ void ipa_endpoint_teardown(struct ipa *ipa)
ipa->set_up = 0; ipa->set_up = 0;
} }
void ipa_endpoint_deconfig(struct ipa *ipa)
{
ipa->available_count = 0;
bitmap_free(ipa->available);
ipa->available = NULL;
}
int ipa_endpoint_config(struct ipa *ipa) int ipa_endpoint_config(struct ipa *ipa)
{ {
struct device *dev = &ipa->pdev->dev; struct device *dev = &ipa->pdev->dev;
...@@ -1863,7 +1867,13 @@ int ipa_endpoint_config(struct ipa *ipa) ...@@ -1863,7 +1867,13 @@ int ipa_endpoint_config(struct ipa *ipa)
* assume the configuration is valid. * assume the configuration is valid.
*/ */
if (ipa->version < IPA_VERSION_3_5) { if (ipa->version < IPA_VERSION_3_5) {
ipa->available = ~0; ipa->available = bitmap_zalloc(IPA_ENDPOINT_MAX, GFP_KERNEL);
if (!ipa->available)
return -ENOMEM;
ipa->available_count = IPA_ENDPOINT_MAX;
bitmap_set(ipa->available, 0, IPA_ENDPOINT_MAX);
return 0; return 0;
} }
...@@ -1885,8 +1895,15 @@ int ipa_endpoint_config(struct ipa *ipa) ...@@ -1885,8 +1895,15 @@ int ipa_endpoint_config(struct ipa *ipa)
return -EINVAL; return -EINVAL;
} }
/* Allocate and initialize the available endpoint bitmap */
ipa->available = bitmap_zalloc(limit, GFP_KERNEL);
if (!ipa->available)
return -ENOMEM;
ipa->available_count = limit;
/* Mark all supported RX and TX endpoints as available */ /* Mark all supported RX and TX endpoints as available */
ipa->available = GENMASK(limit - 1, rx_base) | GENMASK(tx_count - 1, 0); bitmap_set(ipa->available, 0, tx_count);
bitmap_set(ipa->available, rx_base, rx_count);
for_each_set_bit(endpoint_id, ipa->defined, ipa->endpoint_count) { for_each_set_bit(endpoint_id, ipa->defined, ipa->endpoint_count) {
struct ipa_endpoint *endpoint; struct ipa_endpoint *endpoint;
...@@ -1894,13 +1911,13 @@ int ipa_endpoint_config(struct ipa *ipa) ...@@ -1894,13 +1911,13 @@ int ipa_endpoint_config(struct ipa *ipa)
if (endpoint_id >= limit) { if (endpoint_id >= limit) {
dev_err(dev, "invalid endpoint id, %u > %u\n", dev_err(dev, "invalid endpoint id, %u > %u\n",
endpoint_id, limit - 1); endpoint_id, limit - 1);
return -EINVAL; goto err_free_bitmap;
} }
if (!(BIT(endpoint_id) & ipa->available)) { if (!test_bit(endpoint_id, ipa->available)) {
dev_err(dev, "unavailable endpoint id %u\n", dev_err(dev, "unavailable endpoint id %u\n",
endpoint_id); endpoint_id);
return -EINVAL; goto err_free_bitmap;
} }
/* Make sure it's pointing in the right direction */ /* Make sure it's pointing in the right direction */
...@@ -1913,15 +1930,15 @@ int ipa_endpoint_config(struct ipa *ipa) ...@@ -1913,15 +1930,15 @@ int ipa_endpoint_config(struct ipa *ipa)
} }
dev_err(dev, "endpoint id %u wrong direction\n", endpoint_id); dev_err(dev, "endpoint id %u wrong direction\n", endpoint_id);
return -EINVAL; goto err_free_bitmap;
} }
return 0; return 0;
}
void ipa_endpoint_deconfig(struct ipa *ipa) err_free_bitmap:
{ ipa_endpoint_deconfig(ipa);
ipa->available = 0; /* Nothing more to do */
return -EINVAL;
} }
static void ipa_endpoint_init_one(struct ipa *ipa, enum ipa_endpoint_name name, static void ipa_endpoint_init_one(struct ipa *ipa, enum ipa_endpoint_name name,
......
...@@ -132,14 +132,13 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt, ...@@ -132,14 +132,13 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
u32 endpoint_id, bool enable) u32 endpoint_id, bool enable)
{ {
struct ipa *ipa = interrupt->ipa; struct ipa *ipa = interrupt->ipa;
u32 mask = BIT(endpoint_id % 32);
u32 unit = endpoint_id / 32; u32 unit = endpoint_id / 32;
const struct ipa_reg *reg; const struct ipa_reg *reg;
u32 offset; u32 offset;
u32 mask;
u32 val; u32 val;
/* This works until we actually have more than 32 endpoints */ WARN_ON(!test_bit(endpoint_id, ipa->available));
WARN_ON(!(mask & ipa->available));
/* IPA version 3.0 does not support TX_SUSPEND interrupt control */ /* IPA version 3.0 does not support TX_SUSPEND interrupt control */
if (ipa->version == IPA_VERSION_3_0) if (ipa->version == IPA_VERSION_3_0)
...@@ -148,10 +147,13 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt, ...@@ -148,10 +147,13 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
reg = ipa_reg(ipa, IRQ_SUSPEND_EN); reg = ipa_reg(ipa, IRQ_SUSPEND_EN);
offset = ipa_reg_n_offset(reg, unit); offset = ipa_reg_n_offset(reg, unit);
val = ioread32(ipa->reg_virt + offset); val = ioread32(ipa->reg_virt + offset);
mask = BIT(endpoint_id);
if (enable) if (enable)
val |= mask; val |= mask;
else else
val &= ~mask; val &= ~mask;
iowrite32(val, ipa->reg_virt + offset); iowrite32(val, ipa->reg_virt + offset);
} }
......
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