octeontx2-af: Config NPC KPU engines with parser profile
[muen/linux.git] / drivers / net / ethernet / marvell / octeontx2 / af / rvu_npc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell OcteonTx2 RVU Admin Function driver
3  *
4  * Copyright (C) 2018 Marvell International Ltd.
5  *
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.
9  */
10
11 #include <linux/module.h>
12 #include <linux/pci.h>
13
14 #include "rvu_struct.h"
15 #include "rvu_reg.h"
16 #include "rvu.h"
17 #include "npc.h"
18 #include "npc_profile.h"
19
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)
23 {
24         struct npc_kpu_action0 action0 = {0};
25         struct npc_kpu_action1 action1 = {0};
26         u64 reg;
27
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;
33
34         if (pkind)
35                 reg = NPC_AF_PKINDX_ACTION1(entry);
36         else
37                 reg = NPC_AF_KPUX_ENTRYX_ACTION1(kpu, entry);
38
39         rvu_write64(rvu, blkaddr, reg, *(u64 *)&action1);
40
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;
53
54         if (pkind)
55                 reg = NPC_AF_PKINDX_ACTION0(entry);
56         else
57                 reg = NPC_AF_KPUX_ENTRYX_ACTION0(kpu, entry);
58
59         rvu_write64(rvu, blkaddr, reg, *(u64 *)&action0);
60 }
61
62 static void npc_config_kpucam(struct rvu *rvu, int blkaddr,
63                               struct npc_kpu_profile_cam *kpucam,
64                               int kpu, int entry)
65 {
66         struct npc_kpu_cam cam0 = {0};
67         struct npc_kpu_cam cam1 = {0};
68
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;
73
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;
78
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);
83 }
84
85 static inline u64 enable_mask(int count)
86 {
87         return (((count) < 64) ? ~(BIT_ULL(count) - 1) : (0x00ULL));
88 }
89
90 static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu,
91                                     struct npc_kpu_profile *profile)
92 {
93         int entry, num_entries, max_entries;
94
95         if (profile->cam_entries != profile->action_entries) {
96                 dev_err(rvu->dev,
97                         "KPU%d: CAM and action entries [%d != %d] not equal\n",
98                         kpu, profile->cam_entries, profile->action_entries);
99         }
100
101         max_entries = rvu_read64(rvu, blkaddr, NPC_AF_CONST1) & 0xFFF;
102
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);
108
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],
113                                      kpu, entry, false);
114
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));
123         }
124
125         /* Enable this KPU */
126         rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(kpu), 0x01);
127 }
128
129 static void npc_parser_profile_init(struct rvu *rvu, int blkaddr)
130 {
131         struct rvu_hwinfo *hw = rvu->hw;
132         int num_pkinds, num_kpus, idx;
133         struct npc_pkind *pkind;
134
135         /* Get HW limits */
136         hw->npc_kpus = (rvu_read64(rvu, blkaddr, NPC_AF_CONST) >> 8) & 0x1F;
137
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);
145         }
146
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.
150          */
151         pkind = &hw->pkind;
152         num_pkinds = ARRAY_SIZE(ikpu_action_entries);
153         num_pkinds = min_t(int, pkind->rsrc.max, num_pkinds);
154
155         for (idx = 0; idx < num_pkinds; idx++)
156                 npc_config_kpuaction(rvu, blkaddr,
157                                      &ikpu_action_entries[idx], 0, idx, true);
158
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);
162
163         for (idx = 0; idx < num_kpus; idx++)
164                 npc_program_kpu_profile(rvu, blkaddr,
165                                         idx, &npc_kpu_profiles[idx]);
166 }
167
168 int rvu_npc_init(struct rvu *rvu)
169 {
170         struct npc_pkind *pkind = &rvu->hw->pkind;
171         int blkaddr, err;
172
173         blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
174         if (blkaddr < 0) {
175                 dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__);
176                 return -ENODEV;
177         }
178
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);
183         if (err)
184                 return err;
185
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)
190                 return -ENOMEM;
191
192         /* Configure KPU profile */
193         npc_parser_profile_init(rvu, blkaddr);
194
195         return 0;
196 }
197
198 void rvu_npc_freemem(struct rvu *rvu)
199 {
200         struct npc_pkind *pkind = &rvu->hw->pkind;
201
202         kfree(pkind->rsrc.bmap);
203 }