net: ipa: use a bitmap for set-up endpoints
authorAlex Elder <elder@linaro.org>
Wed, 2 Nov 2022 22:11:38 +0000 (17:11 -0500)
committerDavid S. Miller <davem@davemloft.net>
Fri, 4 Nov 2022 10:16:53 +0000 (10:16 +0000)
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: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ipa/ipa.h
drivers/net/ipa/ipa_endpoint.c

index 557101c..f14d1bd 100644 (file)
@@ -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;
index 0381187..3fe20b4 100644 (file)
@@ -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,23 +1819,16 @@ 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;
 }