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

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
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ struct ipa_interrupt;
 * @defined:		Bitmap of endpoints defined in config data
 * @available:		Bitmap of endpoints supported by hardware
 * @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
 * @modem_tx_count:	Number of defined modem TX endoints
 * @endpoint:		Array of endpoint information
@@ -124,7 +124,7 @@ struct ipa {
	unsigned long *defined;		/* Defined in configuration data */
	unsigned long *available;	/* Supported by hardware */
	u64 filtered;			/* Support filtering (AP and modem) */
	u32 set_up;
	unsigned long *set_up;
	u32 enabled;

	u32 modem_tx_count;
+21 −17
Original line number Diff line number Diff line
@@ -1802,12 +1802,12 @@ static void ipa_endpoint_setup_one(struct ipa_endpoint *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)
{
	endpoint->ipa->set_up &= ~BIT(endpoint->endpoint_id);
	__clear_bit(endpoint->endpoint_id, endpoint->ipa->set_up);

	if (!endpoint->toward_ipa)
		cancel_delayed_work_sync(&endpoint->replenish_work);
@@ -1819,24 +1819,17 @@ void ipa_endpoint_setup(struct ipa *ipa)
{
	u32 endpoint_id;

	ipa->set_up = 0;
	for_each_set_bit(endpoint_id, ipa->defined, ipa->endpoint_count)
		ipa_endpoint_setup_one(&ipa->endpoint[endpoint_id]);
}

void ipa_endpoint_teardown(struct ipa *ipa)
{
	u32 set_up = ipa->set_up;

	while (set_up) {
		u32 endpoint_id = __fls(set_up);

		set_up ^= BIT(endpoint_id);
	u32 endpoint_id;

	for_each_set_bit(endpoint_id, ipa->set_up, ipa->endpoint_count)
		ipa_endpoint_teardown_one(&ipa->endpoint[endpoint_id]);
}
	ipa->set_up = 0;
}

void ipa_endpoint_deconfig(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)
		ipa_endpoint_exit_one(&ipa->endpoint[endpoint_id]);

	bitmap_free(ipa->set_up);
	ipa->set_up = NULL;
	bitmap_free(ipa->defined);
	ipa->defined = NULL;

@@ -1999,11 +1994,15 @@ int ipa_endpoint_init(struct ipa *ipa, u32 count,
	if (!ipa->endpoint_count)
		return -EINVAL;

	/* Initialize the defined endpoint bitmap */
	/* Initialize endpoint state bitmaps */
	ipa->defined = bitmap_zalloc(ipa->endpoint_count, GFP_KERNEL);
	if (!ipa->defined)
		return -ENOMEM;

	ipa->set_up = bitmap_zalloc(ipa->endpoint_count, GFP_KERNEL);
	if (!ipa->set_up)
		goto err_free_defined;

	filtered = 0;
	for (name = 0; name < count; name++, data++) {
		if (ipa_gsi_endpoint_data_empty(data))
@@ -2017,15 +2016,20 @@ int ipa_endpoint_init(struct ipa *ipa, u32 count,
			ipa->modem_tx_count++;
	}

	if (!ipa_filtered_valid(ipa, filtered))
		goto err_endpoint_exit;
	/* Make sure the set of filtered endpoints is valid */
	if (!ipa_filtered_valid(ipa, filtered)) {
		ipa_endpoint_exit(ipa);

		return -EINVAL;
	}

	ipa->filtered = filtered;

	return 0;

err_endpoint_exit:
	ipa_endpoint_exit(ipa);
err_free_defined:
	bitmap_free(ipa->defined);
	ipa->defined = NULL;

	return -EINVAL;
	return -ENOMEM;
}