net: ipa: use a bitmap for defined endpoints
authorAlex Elder <elder@linaro.org>
Wed, 2 Nov 2022 22:11:35 +0000 (17:11 -0500)
committerDavid S. Miller <davem@davemloft.net>
Fri, 4 Nov 2022 10:16:53 +0000 (10:16 +0000)
IPA v5.0 supports more than 32 endpoints, so we will be unable to
represent endpoints defined in the configuration data with a 32-bit
value.  To prepare for that, convert the field in the IPA structure
representing defined endpoints to be a Linux bitmap.

Convert loops based on that field into for_each_set_bit() calls over
the new bitmap.  Note that the loop in ipa_endpoint_config() still
assumes there are 32 or fewer endpoints (when comparing against the
available endpoint bit mask); that assumption goes away in the next
patch.

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 a445955..261c726 100644 (file)
@@ -62,7 +62,7 @@ struct ipa_interrupt;
  * @zero_virt:         Virtual address of preallocated zero-filled memory
  * @zero_size:         Size (bytes) of preallocated zero-filled memory
  * @endpoint_count:    Number of endpoints represented by bit masks below
- * @defined:           Bit mask indicating endpoints defined in config data
+ * @defined:           Bitmap of endpoints defined in config data
  * @available:         Bit mask indicating endpoints hardware supports
  * @filter_map:                Bit mask indicating endpoints that support filtering
  * @set_up:            Bit mask indicating endpoints set up
@@ -117,9 +117,9 @@ struct ipa {
        void *zero_virt;
        size_t zero_size;
 
-       /* Bit masks indicating endpoint state */
+       /* Bitmaps indicating endpoint state */
        u32 endpoint_count;
-       u32 defined;                    /* Defined in configuration data */
+       unsigned long *defined;         /* Defined in configuration data */
        u32 available;                  /* Supported by hardware */
        u32 filter_map;
        u32 set_up;
index 32559ed..abc939c 100644 (file)
@@ -459,8 +459,8 @@ void ipa_endpoint_modem_pause_all(struct ipa *ipa, bool enable)
 /* Reset all modem endpoints to use the default exception endpoint */
 int ipa_endpoint_modem_exception_reset_all(struct ipa *ipa)
 {
-       u32 defined = ipa->defined;
        struct gsi_trans *trans;
+       u32 endpoint_id;
        u32 count;
 
        /* We need one command per modem TX endpoint, plus the commands
@@ -474,14 +474,11 @@ int ipa_endpoint_modem_exception_reset_all(struct ipa *ipa)
                return -EBUSY;
        }
 
-       while (defined) {
-               u32 endpoint_id = __ffs(defined);
+       for_each_set_bit(endpoint_id, ipa->defined, ipa->endpoint_count) {
                struct ipa_endpoint *endpoint;
                const struct ipa_reg *reg;
                u32 offset;
 
-               defined ^= BIT(endpoint_id);
-
                /* We only reset modem TX endpoints */
                endpoint = &ipa->endpoint[endpoint_id];
                if (!(endpoint->ee_id == GSI_EE_MODEM && endpoint->toward_ipa))
@@ -1823,16 +1820,11 @@ static void ipa_endpoint_teardown_one(struct ipa_endpoint *endpoint)
 
 void ipa_endpoint_setup(struct ipa *ipa)
 {
-       u32 defined = ipa->defined;
+       u32 endpoint_id;
 
        ipa->set_up = 0;
-       while (defined) {
-               u32 endpoint_id = __ffs(defined);
-
-               defined ^= BIT(endpoint_id);
-
+       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)
@@ -1853,10 +1845,10 @@ int ipa_endpoint_config(struct ipa *ipa)
 {
        struct device *dev = &ipa->pdev->dev;
        const struct ipa_reg *reg;
+       u32 endpoint_id;
        u32 tx_count;
        u32 rx_count;
        u32 rx_base;
-       u32 defined;
        u32 limit;
        u32 val;
 
@@ -1896,13 +1888,9 @@ int ipa_endpoint_config(struct ipa *ipa)
        /* Mark all supported RX and TX endpoints as available */
        ipa->available = GENMASK(limit - 1, rx_base) | GENMASK(tx_count - 1, 0);
 
-       defined = ipa->defined;
-       while (defined) {
-               u32 endpoint_id = __ffs(defined);
+       for_each_set_bit(endpoint_id, ipa->defined, ipa->endpoint_count) {
                struct ipa_endpoint *endpoint;
 
-               defined ^= BIT(endpoint_id);
-
                if (endpoint_id >= limit) {
                        dev_err(dev, "invalid endpoint id, %u > %u\n",
                                endpoint_id, limit - 1);
@@ -1954,27 +1942,26 @@ static void ipa_endpoint_init_one(struct ipa *ipa, enum ipa_endpoint_name name,
        endpoint->toward_ipa = data->toward_ipa;
        endpoint->config = data->endpoint.config;
 
-       ipa->defined |= BIT(endpoint->endpoint_id);
+       __set_bit(endpoint->endpoint_id, ipa->defined);
 }
 
 static void ipa_endpoint_exit_one(struct ipa_endpoint *endpoint)
 {
-       endpoint->ipa->defined &= ~BIT(endpoint->endpoint_id);
+       __clear_bit(endpoint->endpoint_id, endpoint->ipa->defined);
 
        memset(endpoint, 0, sizeof(*endpoint));
 }
 
 void ipa_endpoint_exit(struct ipa *ipa)
 {
-       u32 defined = ipa->defined;
+       u32 endpoint_id;
 
-       while (defined) {
-               u32 endpoint_id = __fls(defined);
+       for_each_set_bit(endpoint_id, ipa->defined, ipa->endpoint_count)
+               ipa_endpoint_exit_one(&ipa->endpoint[endpoint_id]);
 
-               defined ^= BIT(endpoint_id);
+       bitmap_free(ipa->defined);
+       ipa->defined = NULL;
 
-               ipa_endpoint_exit_one(&ipa->endpoint[endpoint_id]);
-       }
        memset(ipa->name_map, 0, sizeof(ipa->name_map));
        memset(ipa->channel_map, 0, sizeof(ipa->channel_map));
 }
@@ -1993,7 +1980,10 @@ u32 ipa_endpoint_init(struct ipa *ipa, u32 count,
        if (!ipa->endpoint_count)
                return 0;       /* Error */
 
-       ipa->defined = 0;
+       /* Initialize the defined endpoint bitmap */
+       ipa->defined = bitmap_zalloc(ipa->endpoint_count, GFP_KERNEL);
+       if (!ipa->defined)
+               return 0;       /* Error */
 
        filter_map = 0;
        for (name = 0; name < count; name++, data++) {