| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522 |
- From 63874f7c2e46f192e43e6214d66236372e36396c Mon Sep 17 00:00:00 2001
- From: Luo Jie <[email protected]>
- Date: Sun, 9 Feb 2025 22:29:41 +0800
- Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE queue settings
- Configure unicast and multicast hardware queues for the PPE
- ports to enable packet forwarding between the ports.
- Each PPE port is assigned with a range of queues. The queue ID
- selection for a packet is decided by the queue base and queue
- offset that is configured based on the internal priority and
- the RSS hash value of the packet.
- Signed-off-by: Luo Jie <[email protected]>
- ---
- .../net/ethernet/qualcomm/ppe/ppe_config.c | 356 +++++++++++++++++-
- .../net/ethernet/qualcomm/ppe/ppe_config.h | 63 ++++
- drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 21 ++
- 3 files changed, 439 insertions(+), 1 deletion(-)
- --- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
- +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
- @@ -128,6 +128,34 @@ struct ppe_scheduler_port_config {
- unsigned int drr_node_id;
- };
-
- +/**
- + * struct ppe_port_schedule_resource - PPE port scheduler resource.
- + * @ucastq_start: Unicast queue start ID.
- + * @ucastq_end: Unicast queue end ID.
- + * @mcastq_start: Multicast queue start ID.
- + * @mcastq_end: Multicast queue end ID.
- + * @flow_id_start: Flow start ID.
- + * @flow_id_end: Flow end ID.
- + * @l0node_start: Scheduler node start ID for queue level.
- + * @l0node_end: Scheduler node end ID for queue level.
- + * @l1node_start: Scheduler node start ID for flow level.
- + * @l1node_end: Scheduler node end ID for flow level.
- + *
- + * PPE scheduler resource allocated among the PPE ports.
- + */
- +struct ppe_port_schedule_resource {
- + unsigned int ucastq_start;
- + unsigned int ucastq_end;
- + unsigned int mcastq_start;
- + unsigned int mcastq_end;
- + unsigned int flow_id_start;
- + unsigned int flow_id_end;
- + unsigned int l0node_start;
- + unsigned int l0node_end;
- + unsigned int l1node_start;
- + unsigned int l1node_end;
- +};
- +
- /* Assign the share buffer number 1550 to group 0 by default. */
- static const int ipq9574_ppe_bm_group_config = 1550;
-
- @@ -676,6 +704,111 @@ static const struct ppe_scheduler_port_c
- },
- };
-
- +/* The scheduler resource is applied to each PPE port, The resource
- + * includes the unicast & multicast queues, flow nodes and DRR nodes.
- + */
- +static const struct ppe_port_schedule_resource ppe_scheduler_res[] = {
- + { .ucastq_start = 0,
- + .ucastq_end = 63,
- + .mcastq_start = 256,
- + .mcastq_end = 271,
- + .flow_id_start = 0,
- + .flow_id_end = 0,
- + .l0node_start = 0,
- + .l0node_end = 7,
- + .l1node_start = 0,
- + .l1node_end = 0,
- + },
- + { .ucastq_start = 144,
- + .ucastq_end = 159,
- + .mcastq_start = 272,
- + .mcastq_end = 275,
- + .flow_id_start = 36,
- + .flow_id_end = 39,
- + .l0node_start = 48,
- + .l0node_end = 63,
- + .l1node_start = 8,
- + .l1node_end = 11,
- + },
- + { .ucastq_start = 160,
- + .ucastq_end = 175,
- + .mcastq_start = 276,
- + .mcastq_end = 279,
- + .flow_id_start = 40,
- + .flow_id_end = 43,
- + .l0node_start = 64,
- + .l0node_end = 79,
- + .l1node_start = 12,
- + .l1node_end = 15,
- + },
- + { .ucastq_start = 176,
- + .ucastq_end = 191,
- + .mcastq_start = 280,
- + .mcastq_end = 283,
- + .flow_id_start = 44,
- + .flow_id_end = 47,
- + .l0node_start = 80,
- + .l0node_end = 95,
- + .l1node_start = 16,
- + .l1node_end = 19,
- + },
- + { .ucastq_start = 192,
- + .ucastq_end = 207,
- + .mcastq_start = 284,
- + .mcastq_end = 287,
- + .flow_id_start = 48,
- + .flow_id_end = 51,
- + .l0node_start = 96,
- + .l0node_end = 111,
- + .l1node_start = 20,
- + .l1node_end = 23,
- + },
- + { .ucastq_start = 208,
- + .ucastq_end = 223,
- + .mcastq_start = 288,
- + .mcastq_end = 291,
- + .flow_id_start = 52,
- + .flow_id_end = 55,
- + .l0node_start = 112,
- + .l0node_end = 127,
- + .l1node_start = 24,
- + .l1node_end = 27,
- + },
- + { .ucastq_start = 224,
- + .ucastq_end = 239,
- + .mcastq_start = 292,
- + .mcastq_end = 295,
- + .flow_id_start = 56,
- + .flow_id_end = 59,
- + .l0node_start = 128,
- + .l0node_end = 143,
- + .l1node_start = 28,
- + .l1node_end = 31,
- + },
- + { .ucastq_start = 240,
- + .ucastq_end = 255,
- + .mcastq_start = 296,
- + .mcastq_end = 299,
- + .flow_id_start = 60,
- + .flow_id_end = 63,
- + .l0node_start = 144,
- + .l0node_end = 159,
- + .l1node_start = 32,
- + .l1node_end = 35,
- + },
- + { .ucastq_start = 64,
- + .ucastq_end = 143,
- + .mcastq_start = 0,
- + .mcastq_end = 0,
- + .flow_id_start = 1,
- + .flow_id_end = 35,
- + .l0node_start = 8,
- + .l0node_end = 47,
- + .l1node_start = 1,
- + .l1node_end = 7,
- + },
- +};
- +
- /* Set the PPE queue level scheduler configuration. */
- static int ppe_scheduler_l0_queue_map_set(struct ppe_device *ppe_dev,
- int node_id, int port,
- @@ -807,6 +940,149 @@ int ppe_queue_scheduler_set(struct ppe_d
- port, scheduler_cfg);
- }
-
- +/**
- + * ppe_queue_ucast_base_set - Set PPE unicast queue base ID and profile ID
- + * @ppe_dev: PPE device
- + * @queue_dst: PPE queue destination configuration
- + * @queue_base: PPE queue base ID
- + * @profile_id: Profile ID
- + *
- + * The PPE unicast queue base ID and profile ID are configured based on the
- + * destination port information that can be service code or CPU code or the
- + * destination port.
- + *
- + * Return: 0 on success, negative error code on failure.
- + */
- +int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev,
- + struct ppe_queue_ucast_dest queue_dst,
- + int queue_base, int profile_id)
- +{
- + int index, profile_size;
- + u32 val, reg;
- +
- + profile_size = queue_dst.src_profile << 8;
- + if (queue_dst.service_code_en)
- + index = PPE_QUEUE_BASE_SERVICE_CODE + profile_size +
- + queue_dst.service_code;
- + else if (queue_dst.cpu_code_en)
- + index = PPE_QUEUE_BASE_CPU_CODE + profile_size +
- + queue_dst.cpu_code;
- + else
- + index = profile_size + queue_dst.dest_port;
- +
- + val = FIELD_PREP(PPE_UCAST_QUEUE_MAP_TBL_PROFILE_ID, profile_id);
- + val |= FIELD_PREP(PPE_UCAST_QUEUE_MAP_TBL_QUEUE_ID, queue_base);
- + reg = PPE_UCAST_QUEUE_MAP_TBL_ADDR + index * PPE_UCAST_QUEUE_MAP_TBL_INC;
- +
- + return regmap_write(ppe_dev->regmap, reg, val);
- +}
- +
- +/**
- + * ppe_queue_ucast_offset_pri_set - Set PPE unicast queue offset based on priority
- + * @ppe_dev: PPE device
- + * @profile_id: Profile ID
- + * @priority: PPE internal priority to be used to set queue offset
- + * @queue_offset: Queue offset used for calculating the destination queue ID
- + *
- + * The PPE unicast queue offset is configured based on the PPE
- + * internal priority.
- + *
- + * Return: 0 on success, negative error code on failure.
- + */
- +int ppe_queue_ucast_offset_pri_set(struct ppe_device *ppe_dev,
- + int profile_id,
- + int priority,
- + int queue_offset)
- +{
- + u32 val, reg;
- + int index;
- +
- + index = (profile_id << 4) + priority;
- + val = FIELD_PREP(PPE_UCAST_PRIORITY_MAP_TBL_CLASS, queue_offset);
- + reg = PPE_UCAST_PRIORITY_MAP_TBL_ADDR + index * PPE_UCAST_PRIORITY_MAP_TBL_INC;
- +
- + return regmap_write(ppe_dev->regmap, reg, val);
- +}
- +
- +/**
- + * ppe_queue_ucast_offset_hash_set - Set PPE unicast queue offset based on hash
- + * @ppe_dev: PPE device
- + * @profile_id: Profile ID
- + * @rss_hash: Packet hash value to be used to set queue offset
- + * @queue_offset: Queue offset used for calculating the destination queue ID
- + *
- + * The PPE unicast queue offset is configured based on the RSS hash value.
- + *
- + * Return: 0 on success, negative error code on failure.
- + */
- +int ppe_queue_ucast_offset_hash_set(struct ppe_device *ppe_dev,
- + int profile_id,
- + int rss_hash,
- + int queue_offset)
- +{
- + u32 val, reg;
- + int index;
- +
- + index = (profile_id << 8) + rss_hash;
- + val = FIELD_PREP(PPE_UCAST_HASH_MAP_TBL_HASH, queue_offset);
- + reg = PPE_UCAST_HASH_MAP_TBL_ADDR + index * PPE_UCAST_HASH_MAP_TBL_INC;
- +
- + return regmap_write(ppe_dev->regmap, reg, val);
- +}
- +
- +/**
- + * ppe_port_resource_get - Get PPE resource per port
- + * @ppe_dev: PPE device
- + * @port: PPE port
- + * @type: Resource type
- + * @res_start: Resource start ID returned
- + * @res_end: Resource end ID returned
- + *
- + * PPE resource is assigned per PPE port, which is acquired for QoS scheduler.
- + *
- + * Return: 0 on success, negative error code on failure.
- + */
- +int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,
- + enum ppe_resource_type type,
- + int *res_start, int *res_end)
- +{
- + struct ppe_port_schedule_resource res;
- +
- + /* The reserved resource with the maximum port ID of PPE is
- + * also allowed to be acquired.
- + */
- + if (port > ppe_dev->num_ports)
- + return -EINVAL;
- +
- + res = ppe_scheduler_res[port];
- + switch (type) {
- + case PPE_RES_UCAST:
- + *res_start = res.ucastq_start;
- + *res_end = res.ucastq_end;
- + break;
- + case PPE_RES_MCAST:
- + *res_start = res.mcastq_start;
- + *res_end = res.mcastq_end;
- + break;
- + case PPE_RES_FLOW_ID:
- + *res_start = res.flow_id_start;
- + *res_end = res.flow_id_end;
- + break;
- + case PPE_RES_L0_NODE:
- + *res_start = res.l0node_start;
- + *res_end = res.l0node_end;
- + break;
- + case PPE_RES_L1_NODE:
- + *res_start = res.l1node_start;
- + *res_end = res.l1node_end;
- + break;
- + default:
- + return -EINVAL;
- + }
- +
- + return 0;
- +}
- +
- static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
- const struct ppe_bm_port_config port_cfg)
- {
- @@ -1140,6 +1416,80 @@ sch_config_fail:
- return ret;
- };
-
- +/* Configure PPE queue destination of each PPE port. */
- +static int ppe_queue_dest_init(struct ppe_device *ppe_dev)
- +{
- + int ret, port_id, index, q_base, q_offset, res_start, res_end, pri_max;
- + struct ppe_queue_ucast_dest queue_dst;
- +
- + for (port_id = 0; port_id < ppe_dev->num_ports; port_id++) {
- + memset(&queue_dst, 0, sizeof(queue_dst));
- +
- + ret = ppe_port_resource_get(ppe_dev, port_id, PPE_RES_UCAST,
- + &res_start, &res_end);
- + if (ret)
- + return ret;
- +
- + q_base = res_start;
- + queue_dst.dest_port = port_id;
- +
- + /* Configure queue base ID and profile ID that is same as
- + * physical port ID.
- + */
- + ret = ppe_queue_ucast_base_set(ppe_dev, queue_dst,
- + q_base, port_id);
- + if (ret)
- + return ret;
- +
- + /* Queue priority range supported by each PPE port */
- + ret = ppe_port_resource_get(ppe_dev, port_id, PPE_RES_L0_NODE,
- + &res_start, &res_end);
- + if (ret)
- + return ret;
- +
- + pri_max = res_end - res_start;
- +
- + /* Redirect ARP reply packet with the max priority on CPU port,
- + * which keeps the ARP reply directed to CPU (CPU code is 101)
- + * with highest priority queue of EDMA.
- + */
- + if (port_id == 0) {
- + memset(&queue_dst, 0, sizeof(queue_dst));
- +
- + queue_dst.cpu_code_en = true;
- + queue_dst.cpu_code = 101;
- + ret = ppe_queue_ucast_base_set(ppe_dev, queue_dst,
- + q_base + pri_max,
- + 0);
- + if (ret)
- + return ret;
- + }
- +
- + /* Initialize the queue offset of internal priority. */
- + for (index = 0; index < PPE_QUEUE_INTER_PRI_NUM; index++) {
- + q_offset = index > pri_max ? pri_max : index;
- +
- + ret = ppe_queue_ucast_offset_pri_set(ppe_dev, port_id,
- + index, q_offset);
- + if (ret)
- + return ret;
- + }
- +
- + /* Initialize the queue offset of RSS hash as 0 to avoid the
- + * random hardware value that will lead to the unexpected
- + * destination queue generated.
- + */
- + for (index = 0; index < PPE_QUEUE_HASH_NUM; index++) {
- + ret = ppe_queue_ucast_offset_hash_set(ppe_dev, port_id,
- + index, 0);
- + if (ret)
- + return ret;
- + }
- + }
- +
- + return 0;
- +}
- +
- int ppe_hw_config(struct ppe_device *ppe_dev)
- {
- int ret;
- @@ -1152,5 +1502,9 @@ int ppe_hw_config(struct ppe_device *ppe
- if (ret)
- return ret;
-
- - return ppe_config_scheduler(ppe_dev);
- + ret = ppe_config_scheduler(ppe_dev);
- + if (ret)
- + return ret;
- +
- + return ppe_queue_dest_init(ppe_dev);
- }
- --- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
- +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
- @@ -8,6 +8,16 @@
-
- #include "ppe.h"
-
- +/* There are different table index ranges for configuring queue base ID of
- + * the destination port, CPU code and service code.
- + */
- +#define PPE_QUEUE_BASE_DEST_PORT 0
- +#define PPE_QUEUE_BASE_CPU_CODE 1024
- +#define PPE_QUEUE_BASE_SERVICE_CODE 2048
- +
- +#define PPE_QUEUE_INTER_PRI_NUM 16
- +#define PPE_QUEUE_HASH_NUM 256
- +
- /**
- * enum ppe_scheduler_frame_mode - PPE scheduler frame mode.
- * @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG,
- @@ -42,8 +52,61 @@ struct ppe_scheduler_cfg {
- enum ppe_scheduler_frame_mode frame_mode;
- };
-
- +/**
- + * enum ppe_resource_type - PPE resource type.
- + * @PPE_RES_UCAST: Unicast queue resource.
- + * @PPE_RES_MCAST: Multicast queue resource.
- + * @PPE_RES_L0_NODE: Level 0 for queue based node resource.
- + * @PPE_RES_L1_NODE: Level 1 for flow based node resource.
- + * @PPE_RES_FLOW_ID: Flow based node resource.
- + */
- +enum ppe_resource_type {
- + PPE_RES_UCAST,
- + PPE_RES_MCAST,
- + PPE_RES_L0_NODE,
- + PPE_RES_L1_NODE,
- + PPE_RES_FLOW_ID,
- +};
- +
- +/**
- + * struct ppe_queue_ucast_dest - PPE unicast queue destination.
- + * @src_profile: Source profile.
- + * @service_code_en: Enable service code to map the queue base ID.
- + * @service_code: Service code.
- + * @cpu_code_en: Enable CPU code to map the queue base ID.
- + * @cpu_code: CPU code.
- + * @dest_port: destination port.
- + *
- + * PPE egress queue ID is decided by the service code if enabled, otherwise
- + * by the CPU code if enabled, or by destination port if both service code
- + * and CPU code are disabled.
- + */
- +struct ppe_queue_ucast_dest {
- + int src_profile;
- + bool service_code_en;
- + int service_code;
- + bool cpu_code_en;
- + int cpu_code;
- + int dest_port;
- +};
- +
- int ppe_hw_config(struct ppe_device *ppe_dev);
- int ppe_queue_scheduler_set(struct ppe_device *ppe_dev,
- int node_id, bool flow_level, int port,
- struct ppe_scheduler_cfg scheduler_cfg);
- +int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev,
- + struct ppe_queue_ucast_dest queue_dst,
- + int queue_base,
- + int profile_id);
- +int ppe_queue_ucast_offset_pri_set(struct ppe_device *ppe_dev,
- + int profile_id,
- + int priority,
- + int queue_offset);
- +int ppe_queue_ucast_offset_hash_set(struct ppe_device *ppe_dev,
- + int profile_id,
- + int rss_hash,
- + int queue_offset);
- +int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,
- + enum ppe_resource_type type,
- + int *res_start, int *res_end);
- #endif
- --- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
- +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
- @@ -164,6 +164,27 @@
- #define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \
- u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_PRE_ALLOC)
-
- +/* The queue base configurations based on destination port,
- + * service code or CPU code.
- + */
- +#define PPE_UCAST_QUEUE_MAP_TBL_ADDR 0x810000
- +#define PPE_UCAST_QUEUE_MAP_TBL_ENTRIES 3072
- +#define PPE_UCAST_QUEUE_MAP_TBL_INC 0x10
- +#define PPE_UCAST_QUEUE_MAP_TBL_PROFILE_ID GENMASK(3, 0)
- +#define PPE_UCAST_QUEUE_MAP_TBL_QUEUE_ID GENMASK(11, 4)
- +
- +/* The queue offset configurations based on RSS hash value. */
- +#define PPE_UCAST_HASH_MAP_TBL_ADDR 0x830000
- +#define PPE_UCAST_HASH_MAP_TBL_ENTRIES 4096
- +#define PPE_UCAST_HASH_MAP_TBL_INC 0x10
- +#define PPE_UCAST_HASH_MAP_TBL_HASH GENMASK(7, 0)
- +
- +/* The queue offset configurations based on PPE internal priority. */
- +#define PPE_UCAST_PRIORITY_MAP_TBL_ADDR 0x842000
- +#define PPE_UCAST_PRIORITY_MAP_TBL_ENTRIES 256
- +#define PPE_UCAST_PRIORITY_MAP_TBL_INC 0x10
- +#define PPE_UCAST_PRIORITY_MAP_TBL_CLASS GENMASK(3, 0)
- +
- /* PPE unicast queue (0-255) configurations. */
- #define PPE_AC_UNICAST_QUEUE_CFG_TBL_ADDR 0x848000
- #define PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES 256
|