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 void rvu_npc_set_pkind(struct rvu *rvu, int pkind, struct rvu_pfvf *pfvf)
25 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
29 /* Config CPI base for the PKIND */
30 val = pkind | 1ULL << 62;
31 rvu_write64(rvu, blkaddr, NPC_AF_PKINDX_CPI_DEFX(pkind, 0), val);
34 int rvu_npc_get_pkind(struct rvu *rvu, u16 pf)
36 struct npc_pkind *pkind = &rvu->hw->pkind;
40 for (i = 0; i < pkind->rsrc.max; i++) {
41 map = pkind->pfchan_map[i];
42 if (((map >> 16) & 0x3F) == pf)
48 static void npc_config_kpuaction(struct rvu *rvu, int blkaddr,
49 struct npc_kpu_profile_action *kpuaction,
50 int kpu, int entry, bool pkind)
52 struct npc_kpu_action0 action0 = {0};
53 struct npc_kpu_action1 action1 = {0};
56 action1.errlev = kpuaction->errlev;
57 action1.errcode = kpuaction->errcode;
58 action1.dp0_offset = kpuaction->dp0_offset;
59 action1.dp1_offset = kpuaction->dp1_offset;
60 action1.dp2_offset = kpuaction->dp2_offset;
63 reg = NPC_AF_PKINDX_ACTION1(entry);
65 reg = NPC_AF_KPUX_ENTRYX_ACTION1(kpu, entry);
67 rvu_write64(rvu, blkaddr, reg, *(u64 *)&action1);
69 action0.byp_count = kpuaction->bypass_count;
70 action0.capture_ena = kpuaction->cap_ena;
71 action0.parse_done = kpuaction->parse_done;
72 action0.next_state = kpuaction->next_state;
73 action0.capture_lid = kpuaction->lid;
74 action0.capture_ltype = kpuaction->ltype;
75 action0.capture_flags = kpuaction->flags;
76 action0.ptr_advance = kpuaction->ptr_advance;
77 action0.var_len_offset = kpuaction->offset;
78 action0.var_len_mask = kpuaction->mask;
79 action0.var_len_right = kpuaction->right;
80 action0.var_len_shift = kpuaction->shift;
83 reg = NPC_AF_PKINDX_ACTION0(entry);
85 reg = NPC_AF_KPUX_ENTRYX_ACTION0(kpu, entry);
87 rvu_write64(rvu, blkaddr, reg, *(u64 *)&action0);
90 static void npc_config_kpucam(struct rvu *rvu, int blkaddr,
91 struct npc_kpu_profile_cam *kpucam,
94 struct npc_kpu_cam cam0 = {0};
95 struct npc_kpu_cam cam1 = {0};
97 cam1.state = kpucam->state & kpucam->state_mask;
98 cam1.dp0_data = kpucam->dp0 & kpucam->dp0_mask;
99 cam1.dp1_data = kpucam->dp1 & kpucam->dp1_mask;
100 cam1.dp2_data = kpucam->dp2 & kpucam->dp2_mask;
102 cam0.state = ~kpucam->state & kpucam->state_mask;
103 cam0.dp0_data = ~kpucam->dp0 & kpucam->dp0_mask;
104 cam0.dp1_data = ~kpucam->dp1 & kpucam->dp1_mask;
105 cam0.dp2_data = ~kpucam->dp2 & kpucam->dp2_mask;
107 rvu_write64(rvu, blkaddr,
108 NPC_AF_KPUX_ENTRYX_CAMX(kpu, entry, 0), *(u64 *)&cam0);
109 rvu_write64(rvu, blkaddr,
110 NPC_AF_KPUX_ENTRYX_CAMX(kpu, entry, 1), *(u64 *)&cam1);
113 static inline u64 enable_mask(int count)
115 return (((count) < 64) ? ~(BIT_ULL(count) - 1) : (0x00ULL));
118 static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu,
119 struct npc_kpu_profile *profile)
121 int entry, num_entries, max_entries;
123 if (profile->cam_entries != profile->action_entries) {
125 "KPU%d: CAM and action entries [%d != %d] not equal\n",
126 kpu, profile->cam_entries, profile->action_entries);
129 max_entries = rvu_read64(rvu, blkaddr, NPC_AF_CONST1) & 0xFFF;
131 /* Program CAM match entries for previous KPU extracted data */
132 num_entries = min_t(int, profile->cam_entries, max_entries);
133 for (entry = 0; entry < num_entries; entry++)
134 npc_config_kpucam(rvu, blkaddr,
135 &profile->cam[entry], kpu, entry);
137 /* Program this KPU's actions */
138 num_entries = min_t(int, profile->action_entries, max_entries);
139 for (entry = 0; entry < num_entries; entry++)
140 npc_config_kpuaction(rvu, blkaddr, &profile->action[entry],
143 /* Enable all programmed entries */
144 num_entries = min_t(int, profile->action_entries, profile->cam_entries);
145 rvu_write64(rvu, blkaddr,
146 NPC_AF_KPUX_ENTRY_DISX(kpu, 0), enable_mask(num_entries));
147 if (num_entries > 64) {
148 rvu_write64(rvu, blkaddr,
149 NPC_AF_KPUX_ENTRY_DISX(kpu, 1),
150 enable_mask(num_entries - 64));
153 /* Enable this KPU */
154 rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(kpu), 0x01);
157 static void npc_parser_profile_init(struct rvu *rvu, int blkaddr)
159 struct rvu_hwinfo *hw = rvu->hw;
160 int num_pkinds, num_kpus, idx;
161 struct npc_pkind *pkind;
164 hw->npc_kpus = (rvu_read64(rvu, blkaddr, NPC_AF_CONST) >> 8) & 0x1F;
166 /* Disable all KPUs and their entries */
167 for (idx = 0; idx < hw->npc_kpus; idx++) {
168 rvu_write64(rvu, blkaddr,
169 NPC_AF_KPUX_ENTRY_DISX(idx, 0), ~0ULL);
170 rvu_write64(rvu, blkaddr,
171 NPC_AF_KPUX_ENTRY_DISX(idx, 1), ~0ULL);
172 rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(idx), 0x00);
175 /* First program IKPU profile i.e PKIND configs.
176 * Check HW max count to avoid configuring junk or
177 * writing to unsupported CSR addresses.
180 num_pkinds = ARRAY_SIZE(ikpu_action_entries);
181 num_pkinds = min_t(int, pkind->rsrc.max, num_pkinds);
183 for (idx = 0; idx < num_pkinds; idx++)
184 npc_config_kpuaction(rvu, blkaddr,
185 &ikpu_action_entries[idx], 0, idx, true);
187 /* Program KPU CAM and Action profiles */
188 num_kpus = ARRAY_SIZE(npc_kpu_profiles);
189 num_kpus = min_t(int, hw->npc_kpus, num_kpus);
191 for (idx = 0; idx < num_kpus; idx++)
192 npc_program_kpu_profile(rvu, blkaddr,
193 idx, &npc_kpu_profiles[idx]);
196 int rvu_npc_init(struct rvu *rvu)
198 struct npc_pkind *pkind = &rvu->hw->pkind;
201 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
203 dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__);
207 /* Allocate resource bimap for pkind*/
208 pkind->rsrc.max = (rvu_read64(rvu, blkaddr,
209 NPC_AF_CONST1) >> 12) & 0xFF;
210 err = rvu_alloc_bitmap(&pkind->rsrc);
214 /* Allocate mem for pkind to PF and channel mapping info */
215 pkind->pfchan_map = devm_kcalloc(rvu->dev, pkind->rsrc.max,
216 sizeof(u32), GFP_KERNEL);
217 if (!pkind->pfchan_map)
220 /* Configure KPU profile */
221 npc_parser_profile_init(rvu, blkaddr);
223 /* Config Outer L2, IPv4's NPC layer info */
224 rvu_write64(rvu, blkaddr, NPC_AF_PCK_DEF_OL2,
225 (NPC_LID_LA << 8) | (NPC_LT_LA_ETHER << 4) | 0x0F);
226 rvu_write64(rvu, blkaddr, NPC_AF_PCK_DEF_OIP4,
227 (NPC_LID_LC << 8) | (NPC_LT_LC_IP << 4) | 0x0F);
229 /* Enable below for Rx pkts.
230 * - Outer IPv4 header checksum validation.
231 * - Detect outer L2 broadcast address and set NPC_RESULT_S[L2M].
233 rvu_write64(rvu, blkaddr, NPC_AF_PCK_CFG,
234 rvu_read64(rvu, blkaddr, NPC_AF_PCK_CFG) |
235 BIT_ULL(6) | BIT_ULL(2));
240 void rvu_npc_freemem(struct rvu *rvu)
242 struct npc_pkind *pkind = &rvu->hw->pkind;
244 kfree(pkind->rsrc.bmap);