1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell OcteonTx2 RVU Admin Function driver
4 * Copyright (C) 2018 Marvell International Ltd.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/module.h>
12 #include <linux/pci.h>
14 #include "rvu_struct.h"
18 #include "npc_profile.h"
20 static void npc_config_kpuaction(struct rvu *rvu, int blkaddr,
21 struct npc_kpu_profile_action *kpuaction,
22 int kpu, int entry, bool pkind)
24 struct npc_kpu_action0 action0 = {0};
25 struct npc_kpu_action1 action1 = {0};
28 action1.errlev = kpuaction->errlev;
29 action1.errcode = kpuaction->errcode;
30 action1.dp0_offset = kpuaction->dp0_offset;
31 action1.dp1_offset = kpuaction->dp1_offset;
32 action1.dp2_offset = kpuaction->dp2_offset;
35 reg = NPC_AF_PKINDX_ACTION1(entry);
37 reg = NPC_AF_KPUX_ENTRYX_ACTION1(kpu, entry);
39 rvu_write64(rvu, blkaddr, reg, *(u64 *)&action1);
41 action0.byp_count = kpuaction->bypass_count;
42 action0.capture_ena = kpuaction->cap_ena;
43 action0.parse_done = kpuaction->parse_done;
44 action0.next_state = kpuaction->next_state;
45 action0.capture_lid = kpuaction->lid;
46 action0.capture_ltype = kpuaction->ltype;
47 action0.capture_flags = kpuaction->flags;
48 action0.ptr_advance = kpuaction->ptr_advance;
49 action0.var_len_offset = kpuaction->offset;
50 action0.var_len_mask = kpuaction->mask;
51 action0.var_len_right = kpuaction->right;
52 action0.var_len_shift = kpuaction->shift;
55 reg = NPC_AF_PKINDX_ACTION0(entry);
57 reg = NPC_AF_KPUX_ENTRYX_ACTION0(kpu, entry);
59 rvu_write64(rvu, blkaddr, reg, *(u64 *)&action0);
62 static void npc_config_kpucam(struct rvu *rvu, int blkaddr,
63 struct npc_kpu_profile_cam *kpucam,
66 struct npc_kpu_cam cam0 = {0};
67 struct npc_kpu_cam cam1 = {0};
69 cam1.state = kpucam->state & kpucam->state_mask;
70 cam1.dp0_data = kpucam->dp0 & kpucam->dp0_mask;
71 cam1.dp1_data = kpucam->dp1 & kpucam->dp1_mask;
72 cam1.dp2_data = kpucam->dp2 & kpucam->dp2_mask;
74 cam0.state = ~kpucam->state & kpucam->state_mask;
75 cam0.dp0_data = ~kpucam->dp0 & kpucam->dp0_mask;
76 cam0.dp1_data = ~kpucam->dp1 & kpucam->dp1_mask;
77 cam0.dp2_data = ~kpucam->dp2 & kpucam->dp2_mask;
79 rvu_write64(rvu, blkaddr,
80 NPC_AF_KPUX_ENTRYX_CAMX(kpu, entry, 0), *(u64 *)&cam0);
81 rvu_write64(rvu, blkaddr,
82 NPC_AF_KPUX_ENTRYX_CAMX(kpu, entry, 1), *(u64 *)&cam1);
85 static inline u64 enable_mask(int count)
87 return (((count) < 64) ? ~(BIT_ULL(count) - 1) : (0x00ULL));
90 static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu,
91 struct npc_kpu_profile *profile)
93 int entry, num_entries, max_entries;
95 if (profile->cam_entries != profile->action_entries) {
97 "KPU%d: CAM and action entries [%d != %d] not equal\n",
98 kpu, profile->cam_entries, profile->action_entries);
101 max_entries = rvu_read64(rvu, blkaddr, NPC_AF_CONST1) & 0xFFF;
103 /* Program CAM match entries for previous KPU extracted data */
104 num_entries = min_t(int, profile->cam_entries, max_entries);
105 for (entry = 0; entry < num_entries; entry++)
106 npc_config_kpucam(rvu, blkaddr,
107 &profile->cam[entry], kpu, entry);
109 /* Program this KPU's actions */
110 num_entries = min_t(int, profile->action_entries, max_entries);
111 for (entry = 0; entry < num_entries; entry++)
112 npc_config_kpuaction(rvu, blkaddr, &profile->action[entry],
115 /* Enable all programmed entries */
116 num_entries = min_t(int, profile->action_entries, profile->cam_entries);
117 rvu_write64(rvu, blkaddr,
118 NPC_AF_KPUX_ENTRY_DISX(kpu, 0), enable_mask(num_entries));
119 if (num_entries > 64) {
120 rvu_write64(rvu, blkaddr,
121 NPC_AF_KPUX_ENTRY_DISX(kpu, 1),
122 enable_mask(num_entries - 64));
125 /* Enable this KPU */
126 rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(kpu), 0x01);
129 static void npc_parser_profile_init(struct rvu *rvu, int blkaddr)
131 struct rvu_hwinfo *hw = rvu->hw;
132 int num_pkinds, num_kpus, idx;
133 struct npc_pkind *pkind;
136 hw->npc_kpus = (rvu_read64(rvu, blkaddr, NPC_AF_CONST) >> 8) & 0x1F;
138 /* Disable all KPUs and their entries */
139 for (idx = 0; idx < hw->npc_kpus; idx++) {
140 rvu_write64(rvu, blkaddr,
141 NPC_AF_KPUX_ENTRY_DISX(idx, 0), ~0ULL);
142 rvu_write64(rvu, blkaddr,
143 NPC_AF_KPUX_ENTRY_DISX(idx, 1), ~0ULL);
144 rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(idx), 0x00);
147 /* First program IKPU profile i.e PKIND configs.
148 * Check HW max count to avoid configuring junk or
149 * writing to unsupported CSR addresses.
152 num_pkinds = ARRAY_SIZE(ikpu_action_entries);
153 num_pkinds = min_t(int, pkind->rsrc.max, num_pkinds);
155 for (idx = 0; idx < num_pkinds; idx++)
156 npc_config_kpuaction(rvu, blkaddr,
157 &ikpu_action_entries[idx], 0, idx, true);
159 /* Program KPU CAM and Action profiles */
160 num_kpus = ARRAY_SIZE(npc_kpu_profiles);
161 num_kpus = min_t(int, hw->npc_kpus, num_kpus);
163 for (idx = 0; idx < num_kpus; idx++)
164 npc_program_kpu_profile(rvu, blkaddr,
165 idx, &npc_kpu_profiles[idx]);
168 int rvu_npc_init(struct rvu *rvu)
170 struct npc_pkind *pkind = &rvu->hw->pkind;
173 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
175 dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__);
179 /* Allocate resource bimap for pkind*/
180 pkind->rsrc.max = (rvu_read64(rvu, blkaddr,
181 NPC_AF_CONST1) >> 12) & 0xFF;
182 err = rvu_alloc_bitmap(&pkind->rsrc);
186 /* Allocate mem for pkind to PF and channel mapping info */
187 pkind->pfchan_map = devm_kcalloc(rvu->dev, pkind->rsrc.max,
188 sizeof(u32), GFP_KERNEL);
189 if (!pkind->pfchan_map)
192 /* Configure KPU profile */
193 npc_parser_profile_init(rvu, blkaddr);
198 void rvu_npc_freemem(struct rvu *rvu)
200 struct npc_pkind *pkind = &rvu->hw->pkind;
202 kfree(pkind->rsrc.bmap);