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: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9a9f512974
commit
88de767240
|
@ -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 {
|
||||||
|
|
||||||
/* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue