net: ipa: allow arbitrary number of interconnects
authorAlex Elder <elder@linaro.org>
Fri, 15 Jan 2021 12:50:50 +0000 (06:50 -0600)
committerJakub Kicinski <kuba@kernel.org>
Mon, 18 Jan 2021 19:51:06 +0000 (11:51 -0800)
Currently we assume that the IPA hardware has exactly three
interconnects.  But that won't be guaranteed for all platforms,
so allow any number of interconnects to be specified in the
configuration data.

For each platform, define an array of interconnect data entries
(still associated with the IPA clock structure), and record the
number of entries initialized in that array.

Loop over all entries in this array when initializing, enabling,
disabling, or tearing down the set of interconnects.

With this change we no longer need the ipa_interconnect_id
enumerated type, so get rid of it.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ipa/ipa_clock.c
drivers/net/ipa/ipa_data-sc7180.c
drivers/net/ipa/ipa_data-sdm845.c
drivers/net/ipa/ipa_data.h

index fbe42106fc2a8d69dabbb15d6913f69b905821d9..354675a643db5193f97044ffd8230a182dd01bf3 100644 (file)
@@ -47,13 +47,15 @@ struct ipa_interconnect {
  * @count:             Clocking reference count
  * @mutex:             Protects clock enable/disable
  * @core:              IPA core clock
+ * @interconnect_count:        Number of elements in interconnect[]
  * @interconnect:      Interconnect array
  */
 struct ipa_clock {
        refcount_t count;
        struct mutex mutex; /* protects clock enable/disable */
        struct clk *core;
-       struct ipa_interconnect interconnect[IPA_INTERCONNECT_COUNT];
+       u32 interconnect_count;
+       struct ipa_interconnect *interconnect;
 };
 
 static int ipa_interconnect_init_one(struct device *dev,
@@ -90,31 +92,29 @@ static int ipa_interconnect_init(struct ipa_clock *clock, struct device *dev,
                                 const struct ipa_interconnect_data *data)
 {
        struct ipa_interconnect *interconnect;
+       u32 count;
        int ret;
 
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_MEMORY];
-       ret = ipa_interconnect_init_one(dev, interconnect, data++);
-       if (ret)
-               return ret;
-
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
-       ret = ipa_interconnect_init_one(dev, interconnect, data++);
-       if (ret)
-               goto err_memory_path_put;
-
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
-       ret = ipa_interconnect_init_one(dev, interconnect, data++);
-       if (ret)
-               goto err_imem_path_put;
+       count = clock->interconnect_count;
+       interconnect = kcalloc(count, sizeof(*interconnect), GFP_KERNEL);
+       if (!interconnect)
+               return -ENOMEM;
+       clock->interconnect = interconnect;
+
+       while (count--) {
+               ret = ipa_interconnect_init_one(dev, interconnect, data++);
+               if (ret)
+                       goto out_unwind;
+               interconnect++;
+       }
 
        return 0;
 
-err_imem_path_put:
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
-       ipa_interconnect_exit_one(interconnect);
-err_memory_path_put:
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_MEMORY];
-       ipa_interconnect_exit_one(interconnect);
+out_unwind:
+       while (interconnect-- > clock->interconnect)
+               ipa_interconnect_exit_one(interconnect);
+       kfree(clock->interconnect);
+       clock->interconnect = NULL;
 
        return ret;
 }
@@ -124,12 +124,11 @@ static void ipa_interconnect_exit(struct ipa_clock *clock)
 {
        struct ipa_interconnect *interconnect;
 
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_CONFIG];
-       ipa_interconnect_exit_one(interconnect);
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
-       ipa_interconnect_exit_one(interconnect);
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_MEMORY];
-       ipa_interconnect_exit_one(interconnect);
+       interconnect = clock->interconnect + clock->interconnect_count;
+       while (interconnect-- > clock->interconnect)
+               ipa_interconnect_exit_one(interconnect);
+       kfree(clock->interconnect);
+       clock->interconnect = NULL;
 }
 
 /* Currently we only use one bandwidth level, so just "enable" interconnects */
@@ -138,33 +137,23 @@ static int ipa_interconnect_enable(struct ipa *ipa)
        struct ipa_interconnect *interconnect;
        struct ipa_clock *clock = ipa->clock;
        int ret;
-
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_MEMORY];
-       ret = icc_set_bw(interconnect->path, interconnect->average_bandwidth,
-                        interconnect->peak_bandwidth);
-       if (ret)
-               return ret;
-
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
-       ret = icc_set_bw(interconnect->path, interconnect->average_bandwidth,
-                        interconnect->peak_bandwidth);
-       if (ret)
-               goto err_memory_path_disable;
-
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_CONFIG];
-       ret = icc_set_bw(interconnect->path, interconnect->average_bandwidth,
-                        interconnect->peak_bandwidth);
-       if (ret)
-               goto err_imem_path_disable;
+       u32 i;
+
+       interconnect = clock->interconnect;
+       for (i = 0; i < clock->interconnect_count; i++) {
+               ret = icc_set_bw(interconnect->path,
+                                interconnect->average_bandwidth,
+                                interconnect->peak_bandwidth);
+               if (ret)
+                       goto out_unwind;
+               interconnect++;
+       }
 
        return 0;
 
-err_imem_path_disable:
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
-       (void)icc_set_bw(interconnect->path, 0, 0);
-err_memory_path_disable:
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_MEMORY];
-       (void)icc_set_bw(interconnect->path, 0, 0);
+out_unwind:
+       while (interconnect-- > clock->interconnect)
+               (void)icc_set_bw(interconnect->path, 0, 0);
 
        return ret;
 }
@@ -175,22 +164,17 @@ static void ipa_interconnect_disable(struct ipa *ipa)
        struct ipa_interconnect *interconnect;
        struct ipa_clock *clock = ipa->clock;
        int result = 0;
+       u32 count;
        int ret;
 
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_MEMORY];
-       ret = icc_set_bw(interconnect->path, 0, 0);
-       if (ret)
-               result = ret;
-
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
-       ret = icc_set_bw(interconnect->path, 0, 0);
-       if (ret && !result)
-               result = ret;
-
-       interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
-       ret = icc_set_bw(interconnect->path, 0, 0);
-       if (ret && !result)
-               result = ret;
+       count = clock->interconnect_count;
+       interconnect = clock->interconnect + count;
+       while (count--) {
+               interconnect--;
+               ret = icc_set_bw(interconnect->path, 0, 0);
+               if (ret && !result)
+                       result = ret;
+       }
 
        if (result)
                dev_err(&ipa->pdev->dev,
@@ -314,8 +298,9 @@ ipa_clock_init(struct device *dev, const struct ipa_clock_data *data)
                goto err_clk_put;
        }
        clock->core = clk;
+       clock->interconnect_count = data->interconnect_count;
 
-       ret = ipa_interconnect_init(clock, dev, data->interconnect);
+       ret = ipa_interconnect_init(clock, dev, data->interconnect_data);
        if (ret)
                goto err_kfree;
 
index 1936ecb4c1104b7381649f22aea4dd39954c0769..997b51ceb7d7661d321aea4fc06d693f767bb44f 100644 (file)
@@ -309,27 +309,30 @@ static struct ipa_mem_data ipa_mem_data = {
        .smem_size      = 0x00002000,
 };
 
+/* Interconnect bandwidths are in 1000 byte/second units */
+static struct ipa_interconnect_data ipa_interconnect_data[] = {
+       {
+               .name                   = "memory",
+               .peak_bandwidth         = 465000,       /* 465 MBps */
+               .average_bandwidth      = 80000,        /* 80 MBps */
+       },
+       /* Average bandwidth is unused for the next two interconnects */
+       {
+               .name                   = "imem",
+               .peak_bandwidth         = 68570,        /* 68.570 MBps */
+               .average_bandwidth      = 0,            /* unused */
+       },
+       {
+               .name                   = "config",
+               .peak_bandwidth         = 30000,        /* 30 MBps */
+               .average_bandwidth      = 0,            /* unused */
+       },
+};
+
 static struct ipa_clock_data ipa_clock_data = {
        .core_clock_rate        = 100 * 1000 * 1000,    /* Hz */
-       /* Interconnect bandwidths are in 1000 byte/second units */
-       .interconnect = {
-               [IPA_INTERCONNECT_MEMORY] = {
-                       .name                   = "memory",
-                       .peak_bandwidth         = 465000,       /* 465 MBps */
-                       .average_bandwidth      = 80000,        /* 80 MBps */
-               },
-               /* Average bandwidth unused for the next two interconnects */
-               [IPA_INTERCONNECT_IMEM] = {
-                       .name                   = "imem",
-                       .peak_bandwidth         = 68570,        /* 68.57 MBps */
-                       .average_bandwidth      = 0,            /* unused */
-               },
-               [IPA_INTERCONNECT_CONFIG] = {
-                       .name                   = "config",
-                       .peak_bandwidth         = 30000,        /* 30 MBps */
-                       .average_bandwidth      = 0,            /* unused */
-               },
-       },
+       .interconnect_count     = ARRAY_SIZE(ipa_interconnect_data),
+       .interconnect_data      = ipa_interconnect_data,
 };
 
 /* Configuration data for the SC7180 SoC. */
index 3b556b5a6340658ceb180fdf7b917d33061feeeb..88c9c3562ab792d5f3e130e3d9bd643253b44713 100644 (file)
@@ -329,27 +329,30 @@ static struct ipa_mem_data ipa_mem_data = {
        .smem_size      = 0x00002000,
 };
 
+/* Interconnect bandwidths are in 1000 byte/second units */
+static struct ipa_interconnect_data ipa_interconnect_data[] = {
+       {
+               .name                   = "memory",
+               .peak_bandwidth         = 600000,       /* 600 MBps */
+               .average_bandwidth      = 80000,        /* 80 MBps */
+       },
+       /* Average bandwidth is unused for the next two interconnects */
+       {
+               .name                   = "imem",
+               .peak_bandwidth         = 350000,       /* 350 MBps */
+               .average_bandwidth      = 0,            /* unused */
+       },
+       {
+               .name                   = "config",
+               .peak_bandwidth         = 40000,        /* 40 MBps */
+               .average_bandwidth      = 0,            /* unused */
+       },
+};
+
 static struct ipa_clock_data ipa_clock_data = {
        .core_clock_rate        = 75 * 1000 * 1000,     /* Hz */
-       /* Interconnect bandwidths are in 1000 byte/second units */
-       .interconnect = {
-               [IPA_INTERCONNECT_MEMORY] = {
-                       .name                   = "memory",
-                       .peak_bandwidth         = 600000,       /* 600 MBps */
-                       .average_bandwidth      = 80000,        /* 80 MBps */
-               },
-               /* Average bandwidth unused for the next two interconnects */
-               [IPA_INTERCONNECT_IMEM] = {
-                       .name                   = "imem",
-                       .peak_bandwidth         = 350000,       /* 350 MBps */
-                       .average_bandwidth      = 0,            /* unused */
-               },
-               [IPA_INTERCONNECT_CONFIG] = {
-                       .name                   = "config",
-                       .peak_bandwidth         = 40000,        /* 40 MBps */
-                       .average_bandwidth      = 0,            /* unused */
-               },
-       },
+       .interconnect_count     = ARRAY_SIZE(ipa_interconnect_data),
+       .interconnect_data      = ipa_interconnect_data,
 };
 
 /* Configuration data for the SDM845 SoC. */
index d8ea6266dc6a1fe26b595db7089f7f8753ab2dbd..b476fc373f7fe1771931050ba0e7357f3858a5e1 100644 (file)
@@ -258,14 +258,6 @@ struct ipa_mem_data {
        u32 smem_size;
 };
 
-/** enum ipa_interconnect_id - IPA interconnect identifier */
-enum ipa_interconnect_id {
-       IPA_INTERCONNECT_MEMORY,
-       IPA_INTERCONNECT_IMEM,
-       IPA_INTERCONNECT_CONFIG,
-       IPA_INTERCONNECT_COUNT,         /* Last; not an interconnect */
-};
-
 /**
  * struct ipa_interconnect_data - description of IPA interconnect bandwidths
  * @name:              Interconnect name (matches interconnect-name in DT)
@@ -281,11 +273,13 @@ struct ipa_interconnect_data {
 /**
  * struct ipa_clock_data - description of IPA clock and interconnect rates
  * @core_clock_rate:   Core clock rate (Hz)
- * @interconnect:      Array of interconnect bandwidth parameters
+ * @interconnect_count:        Number of entries in the interconnect_data array
+ * @interconnect_data: IPA interconnect configuration data
  */
 struct ipa_clock_data {
        u32 core_clock_rate;
-       struct ipa_interconnect_data interconnect[IPA_INTERCONNECT_COUNT];
+       u32 interconnect_count;         /* # entries in interconnect_data[] */
+       const struct ipa_interconnect_data *interconnect_data;
 };
 
 /**