net: ipa: introduce ipa_resource.c
authorAlex Elder <elder@linaro.org>
Fri, 26 Mar 2021 15:11:11 +0000 (10:11 -0500)
committerDavid S. Miller <davem@davemloft.net>
Fri, 26 Mar 2021 22:02:38 +0000 (15:02 -0700)
Separate the IPA resource-related code into a new source file,
"ipa_resource.c", and matching header file "ipa_resource.h".

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ipa/Makefile
drivers/net/ipa/ipa_main.c
drivers/net/ipa/ipa_reg.h
drivers/net/ipa/ipa_resource.c [new file with mode: 0644]
drivers/net/ipa/ipa_resource.h [new file with mode: 0644]

index afe5df1..14a7d84 100644 (file)
@@ -7,6 +7,6 @@ ipa-y                   :=      ipa_main.o ipa_clock.o ipa_reg.o ipa_mem.o \
                                ipa_table.o ipa_interrupt.o gsi.o gsi_trans.o \
                                ipa_gsi.o ipa_smp2p.o ipa_uc.o \
                                ipa_endpoint.o ipa_cmd.o ipa_modem.o \
-                               ipa_qmi.o ipa_qmi_msg.o
+                               ipa_resource.o ipa_qmi.o ipa_qmi_msg.o
 
 ipa-y                  +=      ipa_data-sdm845.o ipa_data-sc7180.o
index f071e90..e180291 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- * Copyright (C) 2018-2020 Linaro Ltd.
+ * Copyright (C) 2018-2021 Linaro Ltd.
  */
 
 #include <linux/types.h>
@@ -22,6 +22,7 @@
 #include "ipa_clock.h"
 #include "ipa_data.h"
 #include "ipa_endpoint.h"
+#include "ipa_resource.h"
 #include "ipa_cmd.h"
 #include "ipa_reg.h"
 #include "ipa_mem.h"
@@ -452,151 +453,6 @@ static void ipa_hardware_deconfig(struct ipa *ipa)
        ipa_hardware_dcd_deconfig(ipa);
 }
 
-#ifdef IPA_VALIDATION
-
-static bool ipa_resource_limits_valid(struct ipa *ipa,
-                                     const struct ipa_resource_data *data)
-{
-       u32 group_count;
-       u32 i;
-       u32 j;
-
-       /* We program at most 6 source or destination resource group limits */
-       BUILD_BUG_ON(IPA_RESOURCE_GROUP_SRC_MAX > 6);
-
-       group_count = ipa_resource_group_src_count(ipa->version);
-       if (!group_count || group_count > IPA_RESOURCE_GROUP_SRC_MAX)
-               return false;
-
-       /* Return an error if a non-zero resource limit is specified
-        * for a resource group not supported by hardware.
-        */
-       for (i = 0; i < data->resource_src_count; i++) {
-               const struct ipa_resource_src *resource;
-
-               resource = &data->resource_src[i];
-               for (j = group_count; j < IPA_RESOURCE_GROUP_SRC_MAX; j++)
-                       if (resource->limits[j].min || resource->limits[j].max)
-                               return false;
-       }
-
-       group_count = ipa_resource_group_dst_count(ipa->version);
-       if (!group_count || group_count > IPA_RESOURCE_GROUP_DST_MAX)
-               return false;
-
-       for (i = 0; i < data->resource_dst_count; i++) {
-               const struct ipa_resource_dst *resource;
-
-               resource = &data->resource_dst[i];
-               for (j = group_count; j < IPA_RESOURCE_GROUP_DST_MAX; j++)
-                       if (resource->limits[j].min || resource->limits[j].max)
-                               return false;
-       }
-
-       return true;
-}
-
-#else /* !IPA_VALIDATION */
-
-static bool ipa_resource_limits_valid(struct ipa *ipa,
-                                     const struct ipa_resource_data *data)
-{
-       return true;
-}
-
-#endif /* !IPA_VALIDATION */
-
-static void
-ipa_resource_config_common(struct ipa *ipa, u32 offset,
-                          const struct ipa_resource_limits *xlimits,
-                          const struct ipa_resource_limits *ylimits)
-{
-       u32 val;
-
-       val = u32_encode_bits(xlimits->min, X_MIN_LIM_FMASK);
-       val |= u32_encode_bits(xlimits->max, X_MAX_LIM_FMASK);
-       if (ylimits) {
-               val |= u32_encode_bits(ylimits->min, Y_MIN_LIM_FMASK);
-               val |= u32_encode_bits(ylimits->max, Y_MAX_LIM_FMASK);
-       }
-
-       iowrite32(val, ipa->reg_virt + offset);
-}
-
-static void ipa_resource_config_src(struct ipa *ipa,
-                                   const struct ipa_resource_src *resource)
-{
-       u32 group_count = ipa_resource_group_src_count(ipa->version);
-       const struct ipa_resource_limits *ylimits;
-       u32 offset;
-
-       offset = IPA_REG_SRC_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type);
-       ylimits = group_count == 1 ? NULL : &resource->limits[1];
-       ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits);
-
-       if (group_count < 2)
-               return;
-
-       offset = IPA_REG_SRC_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type);
-       ylimits = group_count == 3 ? NULL : &resource->limits[3];
-       ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits);
-
-       if (group_count < 4)
-               return;
-
-       offset = IPA_REG_SRC_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource->type);
-       ylimits = group_count == 5 ? NULL : &resource->limits[5];
-       ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits);
-}
-
-static void ipa_resource_config_dst(struct ipa *ipa,
-                                   const struct ipa_resource_dst *resource)
-{
-       u32 group_count = ipa_resource_group_dst_count(ipa->version);
-       const struct ipa_resource_limits *ylimits;
-       u32 offset;
-
-       offset = IPA_REG_DST_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type);
-       ylimits = group_count == 1 ? NULL : &resource->limits[1];
-       ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits);
-
-       if (group_count < 2)
-               return;
-
-       offset = IPA_REG_DST_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type);
-       ylimits = group_count == 3 ? NULL : &resource->limits[3];
-       ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits);
-
-       if (group_count < 4)
-               return;
-
-       offset = IPA_REG_DST_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource->type);
-       ylimits = group_count == 5 ? NULL : &resource->limits[5];
-       ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits);
-}
-
-static int
-ipa_resource_config(struct ipa *ipa, const struct ipa_resource_data *data)
-{
-       u32 i;
-
-       if (!ipa_resource_limits_valid(ipa, data))
-               return -EINVAL;
-
-       for (i = 0; i < data->resource_src_count; i++)
-               ipa_resource_config_src(ipa, &data->resource_src[i]);
-
-       for (i = 0; i < data->resource_dst_count; i++)
-               ipa_resource_config_dst(ipa, &data->resource_dst[i]);
-
-       return 0;
-}
-
-static void ipa_resource_deconfig(struct ipa *ipa)
-{
-       /* Nothing to do */
-}
-
 /**
  * ipa_config() - Configure IPA hardware
  * @ipa:       IPA pointer
index 8820e08..9c798ce 100644 (file)
@@ -346,48 +346,6 @@ enum ipa_pulse_gran {
        IPA_GRAN_655350_US                      = 0x7,
 };
 
-/* # IPA source resource groups available based on version */
-static inline u32 ipa_resource_group_src_count(enum ipa_version version)
-{
-       switch (version) {
-       case IPA_VERSION_3_5_1:
-       case IPA_VERSION_4_0:
-       case IPA_VERSION_4_1:
-               return 4;
-
-       case IPA_VERSION_4_2:
-               return 1;
-
-       case IPA_VERSION_4_5:
-               return 5;
-
-       default:
-               return 0;
-       }
-}
-
-/* # IPA destination resource groups available based on version */
-static inline u32 ipa_resource_group_dst_count(enum ipa_version version)
-{
-       switch (version) {
-       case IPA_VERSION_3_5_1:
-               return 3;
-
-       case IPA_VERSION_4_0:
-       case IPA_VERSION_4_1:
-               return 4;
-
-       case IPA_VERSION_4_2:
-               return 1;
-
-       case IPA_VERSION_4_5:
-               return 5;
-
-       default:
-               return 0;
-       }
-}
-
 /* Not all of the following are present (depends on IPA version) */
 #define IPA_REG_SRC_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(rt) \
                                        (0x00000400 + 0x0020 * (rt))
diff --git a/drivers/net/ipa/ipa_resource.c b/drivers/net/ipa/ipa_resource.c
new file mode 100644 (file)
index 0000000..2f0f2dc
--- /dev/null
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2018-2021 Linaro Ltd.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include "ipa.h"
+#include "ipa_data.h"
+#include "ipa_reg.h"
+#include "ipa_resource.h"
+
+/**
+ * DOC: IPA Resources
+ *
+ * The IPA manages a set of resources internally for various purposes.
+ * A given IPA version has a fixed number of resource types, and a fixed
+ * total number of resources of each type.  "Source" resource types
+ * are separate from "destination" resource types.
+ *
+ * Each version of IPA also has some number of resource groups.  Each
+ * endpoint is assigned to a resource group, and all endpoints in the
+ * same group share pools of each type of resource.  A subset of the
+ * total resources of each type is assigned for use by each group.
+ */
+
+/* # IPA source resource groups available based on version */
+static u32 ipa_resource_group_src_count(enum ipa_version version)
+{
+       switch (version) {
+       case IPA_VERSION_3_5_1:
+       case IPA_VERSION_4_0:
+       case IPA_VERSION_4_1:
+               return 4;
+
+       case IPA_VERSION_4_2:
+               return 1;
+
+       case IPA_VERSION_4_5:
+               return 5;
+
+       default:
+               return 0;
+       }
+}
+
+/* # IPA destination resource groups available based on version */
+static u32 ipa_resource_group_dst_count(enum ipa_version version)
+{
+       switch (version) {
+       case IPA_VERSION_3_5_1:
+               return 3;
+
+       case IPA_VERSION_4_0:
+       case IPA_VERSION_4_1:
+               return 4;
+
+       case IPA_VERSION_4_2:
+               return 1;
+
+       case IPA_VERSION_4_5:
+               return 5;
+
+       default:
+               return 0;
+       }
+}
+
+static bool ipa_resource_limits_valid(struct ipa *ipa,
+                                     const struct ipa_resource_data *data)
+{
+#ifdef IPA_VALIDATION
+       u32 group_count;
+       u32 i;
+       u32 j;
+
+       /* We program at most 6 source or destination resource group limits */
+       BUILD_BUG_ON(IPA_RESOURCE_GROUP_SRC_MAX > 6);
+
+       group_count = ipa_resource_group_src_count(ipa->version);
+       if (!group_count || group_count > IPA_RESOURCE_GROUP_SRC_MAX)
+               return false;
+
+       /* Return an error if a non-zero resource limit is specified
+        * for a resource group not supported by hardware.
+        */
+       for (i = 0; i < data->resource_src_count; i++) {
+               const struct ipa_resource_src *resource;
+
+               resource = &data->resource_src[i];
+               for (j = group_count; j < IPA_RESOURCE_GROUP_SRC_MAX; j++)
+                       if (resource->limits[j].min || resource->limits[j].max)
+                               return false;
+       }
+
+       group_count = ipa_resource_group_dst_count(ipa->version);
+       if (!group_count || group_count > IPA_RESOURCE_GROUP_DST_MAX)
+               return false;
+
+       for (i = 0; i < data->resource_dst_count; i++) {
+               const struct ipa_resource_dst *resource;
+
+               resource = &data->resource_dst[i];
+               for (j = group_count; j < IPA_RESOURCE_GROUP_DST_MAX; j++)
+                       if (resource->limits[j].min || resource->limits[j].max)
+                               return false;
+       }
+#endif /* !IPA_VALIDATION */
+       return true;
+}
+
+static void
+ipa_resource_config_common(struct ipa *ipa, u32 offset,
+                          const struct ipa_resource_limits *xlimits,
+                          const struct ipa_resource_limits *ylimits)
+{
+       u32 val;
+
+       val = u32_encode_bits(xlimits->min, X_MIN_LIM_FMASK);
+       val |= u32_encode_bits(xlimits->max, X_MAX_LIM_FMASK);
+       if (ylimits) {
+               val |= u32_encode_bits(ylimits->min, Y_MIN_LIM_FMASK);
+               val |= u32_encode_bits(ylimits->max, Y_MAX_LIM_FMASK);
+       }
+
+       iowrite32(val, ipa->reg_virt + offset);
+}
+
+static void ipa_resource_config_src(struct ipa *ipa,
+                                   const struct ipa_resource_src *resource)
+{
+       u32 group_count = ipa_resource_group_src_count(ipa->version);
+       const struct ipa_resource_limits *ylimits;
+       u32 offset;
+
+       offset = IPA_REG_SRC_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type);
+       ylimits = group_count == 1 ? NULL : &resource->limits[1];
+       ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits);
+
+       if (group_count < 2)
+               return;
+
+       offset = IPA_REG_SRC_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type);
+       ylimits = group_count == 3 ? NULL : &resource->limits[3];
+       ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits);
+
+       if (group_count < 4)
+               return;
+
+       offset = IPA_REG_SRC_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource->type);
+       ylimits = group_count == 5 ? NULL : &resource->limits[5];
+       ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits);
+}
+
+static void ipa_resource_config_dst(struct ipa *ipa,
+                                   const struct ipa_resource_dst *resource)
+{
+       u32 group_count = ipa_resource_group_dst_count(ipa->version);
+       const struct ipa_resource_limits *ylimits;
+       u32 offset;
+
+       offset = IPA_REG_DST_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type);
+       ylimits = group_count == 1 ? NULL : &resource->limits[1];
+       ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits);
+
+       if (group_count < 2)
+               return;
+
+       offset = IPA_REG_DST_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type);
+       ylimits = group_count == 3 ? NULL : &resource->limits[3];
+       ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits);
+
+       if (group_count < 4)
+               return;
+
+       offset = IPA_REG_DST_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource->type);
+       ylimits = group_count == 5 ? NULL : &resource->limits[5];
+       ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits);
+}
+
+/* Configure resources */
+int ipa_resource_config(struct ipa *ipa, const struct ipa_resource_data *data)
+{
+       u32 i;
+
+       if (!ipa_resource_limits_valid(ipa, data))
+               return -EINVAL;
+
+       for (i = 0; i < data->resource_src_count; i++)
+               ipa_resource_config_src(ipa, &data->resource_src[i]);
+
+       for (i = 0; i < data->resource_dst_count; i++)
+               ipa_resource_config_dst(ipa, &data->resource_dst[i]);
+
+       return 0;
+}
+
+/* Inverse of ipa_resource_config() */
+void ipa_resource_deconfig(struct ipa *ipa)
+{
+       /* Nothing to do */
+}
diff --git a/drivers/net/ipa/ipa_resource.h b/drivers/net/ipa/ipa_resource.h
new file mode 100644 (file)
index 0000000..9f74036
--- /dev/null
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2019-2021 Linaro Ltd.
+ */
+#ifndef _IPA_RESOURCE_H_
+#define _IPA_RESOURCE_H_
+
+struct ipa;
+struct ipa_resource_data;
+
+/**
+ * ipa_resource_config() - Configure resources
+ * @ipa:       IPA pointer
+ * @data:      IPA resource configuration data
+ *
+ * Return:     true if all regions are valid, false otherwise
+ */
+int ipa_resource_config(struct ipa *ipa, const struct ipa_resource_data *data);
+
+/**
+ * ipa_resource_deconfig() - Inverse of ipa_resource_config()
+ * @ipa:       IPA pointer
+ */
+void ipa_resource_deconfig(struct ipa *ipa);
+
+#endif /* _IPA_RESOURCE_H_ */