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

net: ipa: use a bitmap for set-up endpoints

Replace the 32-bit unsigned used to track endpoints that have
completed setup with a Linux bitmap, to allow an arbitrary number
of endpoints to be represented.

Rework the error handling in ipa_endpoint_init() so the defined
endpoint bitmap is freed if an error occurs early.  Once endpoints
have been initialized, ipa_endpoint_exit() is used to recover if
the set of filtered endpoints is invalid.
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0f97fbd4
...@@ -66,7 +66,7 @@ struct ipa_interrupt; ...@@ -66,7 +66,7 @@ struct ipa_interrupt;
* @defined: Bitmap of endpoints defined in config data * @defined: Bitmap of endpoints defined in config data
* @available: Bitmap of endpoints supported by hardware * @available: Bitmap of endpoints supported by hardware
* @filtered: Bitmap of endpoints that support filtering * @filtered: Bitmap of endpoints that support filtering
* @set_up: Bit mask indicating endpoints set up * @set_up: Bitmap of endpoints that are set up for use
* @enabled: Bit mask indicating endpoints enabled * @enabled: Bit mask indicating endpoints enabled
* @modem_tx_count: Number of defined modem TX endoints * @modem_tx_count: Number of defined modem TX endoints
* @endpoint: Array of endpoint information * @endpoint: Array of endpoint information
...@@ -124,7 +124,7 @@ struct ipa { ...@@ -124,7 +124,7 @@ struct ipa {
unsigned long *defined; /* Defined in configuration data */ unsigned long *defined; /* Defined in configuration data */
unsigned long *available; /* Supported by hardware */ unsigned long *available; /* Supported by hardware */
u64 filtered; /* Support filtering (AP and modem) */ u64 filtered; /* Support filtering (AP and modem) */
u32 set_up; unsigned long *set_up;
u32 enabled; u32 enabled;
u32 modem_tx_count; u32 modem_tx_count;
......
...@@ -1802,12 +1802,12 @@ static void ipa_endpoint_setup_one(struct ipa_endpoint *endpoint) ...@@ -1802,12 +1802,12 @@ static void ipa_endpoint_setup_one(struct ipa_endpoint *endpoint)
ipa_endpoint_program(endpoint); ipa_endpoint_program(endpoint);
endpoint->ipa->set_up |= BIT(endpoint->endpoint_id); __set_bit(endpoint->endpoint_id, endpoint->ipa->set_up);
} }
static void ipa_endpoint_teardown_one(struct ipa_endpoint *endpoint) static void ipa_endpoint_teardown_one(struct ipa_endpoint *endpoint)
{ {
endpoint->ipa->set_up &= ~BIT(endpoint->endpoint_id); __clear_bit(endpoint->endpoint_id, endpoint->ipa->set_up);
if (!endpoint->toward_ipa) if (!endpoint->toward_ipa)
cancel_delayed_work_sync(&endpoint->replenish_work); cancel_delayed_work_sync(&endpoint->replenish_work);
...@@ -1819,23 +1819,16 @@ void ipa_endpoint_setup(struct ipa *ipa) ...@@ -1819,23 +1819,16 @@ void ipa_endpoint_setup(struct ipa *ipa)
{ {
u32 endpoint_id; u32 endpoint_id;
ipa->set_up = 0;
for_each_set_bit(endpoint_id, ipa->defined, ipa->endpoint_count) for_each_set_bit(endpoint_id, ipa->defined, ipa->endpoint_count)
ipa_endpoint_setup_one(&ipa->endpoint[endpoint_id]); ipa_endpoint_setup_one(&ipa->endpoint[endpoint_id]);
} }
void ipa_endpoint_teardown(struct ipa *ipa) void ipa_endpoint_teardown(struct ipa *ipa)
{ {
u32 set_up = ipa->set_up; u32 endpoint_id;
while (set_up) {
u32 endpoint_id = __fls(set_up);
set_up ^= BIT(endpoint_id);
for_each_set_bit(endpoint_id, ipa->set_up, ipa->endpoint_count)
ipa_endpoint_teardown_one(&ipa->endpoint[endpoint_id]); ipa_endpoint_teardown_one(&ipa->endpoint[endpoint_id]);
}
ipa->set_up = 0;
} }
void ipa_endpoint_deconfig(struct ipa *ipa) void ipa_endpoint_deconfig(struct ipa *ipa)
...@@ -1978,6 +1971,8 @@ void ipa_endpoint_exit(struct ipa *ipa) ...@@ -1978,6 +1971,8 @@ void ipa_endpoint_exit(struct ipa *ipa)
for_each_set_bit(endpoint_id, ipa->defined, ipa->endpoint_count) for_each_set_bit(endpoint_id, ipa->defined, ipa->endpoint_count)
ipa_endpoint_exit_one(&ipa->endpoint[endpoint_id]); ipa_endpoint_exit_one(&ipa->endpoint[endpoint_id]);
bitmap_free(ipa->set_up);
ipa->set_up = NULL;
bitmap_free(ipa->defined); bitmap_free(ipa->defined);
ipa->defined = NULL; ipa->defined = NULL;
...@@ -1999,11 +1994,15 @@ int ipa_endpoint_init(struct ipa *ipa, u32 count, ...@@ -1999,11 +1994,15 @@ int ipa_endpoint_init(struct ipa *ipa, u32 count,
if (!ipa->endpoint_count) if (!ipa->endpoint_count)
return -EINVAL; return -EINVAL;
/* Initialize the defined endpoint bitmap */ /* Initialize endpoint state bitmaps */
ipa->defined = bitmap_zalloc(ipa->endpoint_count, GFP_KERNEL); ipa->defined = bitmap_zalloc(ipa->endpoint_count, GFP_KERNEL);
if (!ipa->defined) if (!ipa->defined)
return -ENOMEM; return -ENOMEM;
ipa->set_up = bitmap_zalloc(ipa->endpoint_count, GFP_KERNEL);
if (!ipa->set_up)
goto err_free_defined;
filtered = 0; filtered = 0;
for (name = 0; name < count; name++, data++) { for (name = 0; name < count; name++, data++) {
if (ipa_gsi_endpoint_data_empty(data)) if (ipa_gsi_endpoint_data_empty(data))
...@@ -2017,15 +2016,20 @@ int ipa_endpoint_init(struct ipa *ipa, u32 count, ...@@ -2017,15 +2016,20 @@ int ipa_endpoint_init(struct ipa *ipa, u32 count,
ipa->modem_tx_count++; ipa->modem_tx_count++;
} }
if (!ipa_filtered_valid(ipa, filtered)) /* Make sure the set of filtered endpoints is valid */
goto err_endpoint_exit; if (!ipa_filtered_valid(ipa, filtered)) {
ipa_endpoint_exit(ipa);
return -EINVAL;
}
ipa->filtered = filtered; ipa->filtered = filtered;
return 0; return 0;
err_endpoint_exit: err_free_defined:
ipa_endpoint_exit(ipa); bitmap_free(ipa->defined);
ipa->defined = NULL;
return -EINVAL; return -ENOMEM;
} }
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