]> git.itanic.dy.fi Git - linux-stable/commitdiff
net: ipa: use a bitmap for available endpoints
authorAlex Elder <elder@linaro.org>
Wed, 2 Nov 2022 22:11:36 +0000 (17:11 -0500)
committerDavid S. Miller <davem@davemloft.net>
Fri, 4 Nov 2022 10:16:53 +0000 (10:16 +0000)
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>
drivers/net/ipa/ipa.h
drivers/net/ipa/ipa_endpoint.c
drivers/net/ipa/ipa_interrupt.c

index 261c7263f9e31dcbc4c648462cddb57edfcaeb75..c603575e2a58ba32a7f6a3feaccc7ce1438aef7a 100644 (file)
@@ -61,9 +61,10 @@ struct ipa_interrupt;
  * @zero_addr:         DMA address of preallocated zero-filled memory
  * @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
+ * @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
- * @available:         Bit mask indicating endpoints hardware supports
+ * @available:         Bitmap of endpoints supported by hardware
  * @filter_map:                Bit mask indicating endpoints that support filtering
  * @set_up:            Bit mask indicating endpoints set up
  * @enabled:           Bit mask indicating endpoints enabled
@@ -119,8 +120,9 @@ struct ipa {
 
        /* Bitmaps indicating endpoint state */
        u32 endpoint_count;
+       u32 available_count;
        unsigned long *defined;         /* Defined in configuration data */
-       u32 available;                  /* Supported by hardware */
+       unsigned long *available;       /* Supported by hardware */
        u32 filter_map;
        u32 set_up;
        u32 enabled;
index abc939c272b5a65a73b38e323686518215d81337..a7932e8d0b2bf228f1fee8ff8e64170b917782d0 100644 (file)
@@ -351,19 +351,17 @@ ipa_endpoint_program_delay(struct ipa_endpoint *endpoint, bool enable)
 static bool ipa_endpoint_aggr_active(struct ipa_endpoint *endpoint)
 {
        u32 endpoint_id = endpoint->endpoint_id;
-       u32 mask = BIT(endpoint_id % 32);
        struct ipa *ipa = endpoint->ipa;
        u32 unit = endpoint_id / 32;
        const struct ipa_reg *reg;
        u32 val;
 
-       /* This works until we actually have more than 32 endpoints */
-       WARN_ON(!(mask & ipa->available));
+       WARN_ON(!test_bit(endpoint_id, ipa->available));
 
        reg = ipa_reg(ipa, STATE_AGGR_ACTIVE);
        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)
@@ -374,8 +372,7 @@ static void ipa_endpoint_force_close(struct ipa_endpoint *endpoint)
        u32 unit = endpoint_id / 32;
        const struct ipa_reg *reg;
 
-       /* This works until we actually have more than 32 endpoints */
-       WARN_ON(!(mask & ipa->available));
+       WARN_ON(!test_bit(endpoint_id, ipa->available));
 
        reg = ipa_reg(ipa, AGGR_FORCE_CLOSE);
        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;
 }
 
+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)
 {
        struct device *dev = &ipa->pdev->dev;
@@ -1863,7 +1867,13 @@ int ipa_endpoint_config(struct ipa *ipa)
         * assume the configuration is valid.
         */
        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;
        }
 
@@ -1885,8 +1895,15 @@ int ipa_endpoint_config(struct ipa *ipa)
                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 */
-       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) {
                struct ipa_endpoint *endpoint;
@@ -1894,13 +1911,13 @@ int ipa_endpoint_config(struct ipa *ipa)
                if (endpoint_id >= limit) {
                        dev_err(dev, "invalid endpoint id, %u > %u\n",
                                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",
                                endpoint_id);
-                       return -EINVAL;
+                       goto err_free_bitmap;
                }
 
                /* 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);
-               return -EINVAL;
+               goto err_free_bitmap;
        }
 
        return 0;
-}
 
-void ipa_endpoint_deconfig(struct ipa *ipa)
-{
-       ipa->available = 0;     /* Nothing more to do */
+err_free_bitmap:
+       ipa_endpoint_deconfig(ipa);
+
+       return -EINVAL;
 }
 
 static void ipa_endpoint_init_one(struct ipa *ipa, enum ipa_endpoint_name name,
index a62bc667bda0ea9468375e9225b720d653fcb2f5..a49f66efacb8750a50f8467007d002897fac2bb0 100644 (file)
@@ -132,14 +132,13 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
                                          u32 endpoint_id, bool enable)
 {
        struct ipa *ipa = interrupt->ipa;
-       u32 mask = BIT(endpoint_id % 32);
        u32 unit = endpoint_id / 32;
        const struct ipa_reg *reg;
        u32 offset;
+       u32 mask;
        u32 val;
 
-       /* This works until we actually have more than 32 endpoints */
-       WARN_ON(!(mask & ipa->available));
+       WARN_ON(!test_bit(endpoint_id, ipa->available));
 
        /* IPA version 3.0 does not support TX_SUSPEND interrupt control */
        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);
        offset = ipa_reg_n_offset(reg, unit);
        val = ioread32(ipa->reg_virt + offset);
+
+       mask = BIT(endpoint_id);
        if (enable)
                val |= mask;
        else
                val &= ~mask;
+
        iowrite32(val, ipa->reg_virt + offset);
 }