octeontx2-af: Support for VTAG strip and capture
[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 void rvu_npc_set_pkind(struct rvu *rvu, int pkind, struct rvu_pfvf *pfvf)
21 {
22         int blkaddr;
23         u64 val = 0;
24
25         blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
26         if (blkaddr < 0)
27                 return;
28
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);
32 }
33
34 int rvu_npc_get_pkind(struct rvu *rvu, u16 pf)
35 {
36         struct npc_pkind *pkind = &rvu->hw->pkind;
37         u32 map;
38         int i;
39
40         for (i = 0; i < pkind->rsrc.max; i++) {
41                 map = pkind->pfchan_map[i];
42                 if (((map >> 16) & 0x3F) == pf)
43                         return i;
44         }
45         return -1;
46 }
47
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)
51 {
52         struct npc_kpu_action0 action0 = {0};
53         struct npc_kpu_action1 action1 = {0};
54         u64 reg;
55
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;
61
62         if (pkind)
63                 reg = NPC_AF_PKINDX_ACTION1(entry);
64         else
65                 reg = NPC_AF_KPUX_ENTRYX_ACTION1(kpu, entry);
66
67         rvu_write64(rvu, blkaddr, reg, *(u64 *)&action1);
68
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;
81
82         if (pkind)
83                 reg = NPC_AF_PKINDX_ACTION0(entry);
84         else
85                 reg = NPC_AF_KPUX_ENTRYX_ACTION0(kpu, entry);
86
87         rvu_write64(rvu, blkaddr, reg, *(u64 *)&action0);
88 }
89
90 static void npc_config_kpucam(struct rvu *rvu, int blkaddr,
91                               struct npc_kpu_profile_cam *kpucam,
92                               int kpu, int entry)
93 {
94         struct npc_kpu_cam cam0 = {0};
95         struct npc_kpu_cam cam1 = {0};
96
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;
101
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;
106
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);
111 }
112
113 static inline u64 enable_mask(int count)
114 {
115         return (((count) < 64) ? ~(BIT_ULL(count) - 1) : (0x00ULL));
116 }
117
118 static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu,
119                                     struct npc_kpu_profile *profile)
120 {
121         int entry, num_entries, max_entries;
122
123         if (profile->cam_entries != profile->action_entries) {
124                 dev_err(rvu->dev,
125                         "KPU%d: CAM and action entries [%d != %d] not equal\n",
126                         kpu, profile->cam_entries, profile->action_entries);
127         }
128
129         max_entries = rvu_read64(rvu, blkaddr, NPC_AF_CONST1) & 0xFFF;
130
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);
136
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],
141                                      kpu, entry, false);
142
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));
151         }
152
153         /* Enable this KPU */
154         rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(kpu), 0x01);
155 }
156
157 static void npc_parser_profile_init(struct rvu *rvu, int blkaddr)
158 {
159         struct rvu_hwinfo *hw = rvu->hw;
160         int num_pkinds, num_kpus, idx;
161         struct npc_pkind *pkind;
162
163         /* Get HW limits */
164         hw->npc_kpus = (rvu_read64(rvu, blkaddr, NPC_AF_CONST) >> 8) & 0x1F;
165
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);
173         }
174
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.
178          */
179         pkind = &hw->pkind;
180         num_pkinds = ARRAY_SIZE(ikpu_action_entries);
181         num_pkinds = min_t(int, pkind->rsrc.max, num_pkinds);
182
183         for (idx = 0; idx < num_pkinds; idx++)
184                 npc_config_kpuaction(rvu, blkaddr,
185                                      &ikpu_action_entries[idx], 0, idx, true);
186
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);
190
191         for (idx = 0; idx < num_kpus; idx++)
192                 npc_program_kpu_profile(rvu, blkaddr,
193                                         idx, &npc_kpu_profiles[idx]);
194 }
195
196 int rvu_npc_init(struct rvu *rvu)
197 {
198         struct npc_pkind *pkind = &rvu->hw->pkind;
199         int blkaddr, err;
200
201         blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
202         if (blkaddr < 0) {
203                 dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__);
204                 return -ENODEV;
205         }
206
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);
211         if (err)
212                 return err;
213
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)
218                 return -ENOMEM;
219
220         /* Configure KPU profile */
221         npc_parser_profile_init(rvu, blkaddr);
222
223         return 0;
224 }
225
226 void rvu_npc_freemem(struct rvu *rvu)
227 {
228         struct npc_pkind *pkind = &rvu->hw->pkind;
229
230         kfree(pkind->rsrc.bmap);
231 }