Merge tag 'mips-fixes_5.14_1' of git://git.kernel.org/pub/scm/linux/kernel/git/mips...
[linux-2.6-microblaze.git] / drivers / net / ethernet / marvell / octeontx2 / af / rvu_switch.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell OcteonTx2 RVU Admin Function driver
3  *
4  * Copyright (C) 2021 Marvell.
5  */
6
7 #include <linux/bitfield.h>
8 #include "rvu.h"
9
10 static int rvu_switch_install_rx_rule(struct rvu *rvu, u16 pcifunc,
11                                       u16 chan_mask)
12 {
13         struct npc_install_flow_req req = { 0 };
14         struct npc_install_flow_rsp rsp = { 0 };
15         struct rvu_pfvf *pfvf;
16
17         pfvf = rvu_get_pfvf(rvu, pcifunc);
18         /* If the pcifunc is not initialized then nothing to do.
19          * This same function will be called again via rvu_switch_update_rules
20          * after pcifunc is initialized.
21          */
22         if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))
23                 return 0;
24
25         ether_addr_copy(req.packet.dmac, pfvf->mac_addr);
26         eth_broadcast_addr((u8 *)&req.mask.dmac);
27         req.hdr.pcifunc = 0; /* AF is requester */
28         req.vf = pcifunc;
29         req.features = BIT_ULL(NPC_DMAC);
30         req.channel = pfvf->rx_chan_base;
31         req.chan_mask = chan_mask;
32         req.intf = pfvf->nix_rx_intf;
33         req.op = NIX_RX_ACTION_DEFAULT;
34         req.default_rule = 1;
35
36         return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
37 }
38
39 static int rvu_switch_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry)
40 {
41         struct npc_install_flow_req req = { 0 };
42         struct npc_install_flow_rsp rsp = { 0 };
43         struct rvu_pfvf *pfvf;
44         u8 lbkid;
45
46         pfvf = rvu_get_pfvf(rvu, pcifunc);
47         /* If the pcifunc is not initialized then nothing to do.
48          * This same function will be called again via rvu_switch_update_rules
49          * after pcifunc is initialized.
50          */
51         if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))
52                 return 0;
53
54         lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1;
55         ether_addr_copy(req.packet.dmac, pfvf->mac_addr);
56         eth_broadcast_addr((u8 *)&req.mask.dmac);
57         req.hdr.pcifunc = 0; /* AF is requester */
58         req.vf = pcifunc;
59         req.entry = entry;
60         req.features = BIT_ULL(NPC_DMAC);
61         req.intf = pfvf->nix_tx_intf;
62         req.op = NIX_TX_ACTIONOP_UCAST_CHAN;
63         req.index = (lbkid << 8) | RVU_SWITCH_LBK_CHAN;
64         req.set_cntr = 1;
65
66         return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
67 }
68
69 static int rvu_switch_install_rules(struct rvu *rvu)
70 {
71         struct rvu_switch *rswitch = &rvu->rswitch;
72         u16 start = rswitch->start_entry;
73         struct rvu_hwinfo *hw = rvu->hw;
74         u16 pcifunc, entry = 0;
75         int pf, vf, numvfs;
76         int err;
77
78         for (pf = 1; pf < hw->total_pfs; pf++) {
79                 if (!is_pf_cgxmapped(rvu, pf))
80                         continue;
81
82                 pcifunc = pf << 10;
83                 /* rvu_get_nix_blkaddr sets up the corresponding NIX block
84                  * address and NIX RX and TX interfaces for a pcifunc.
85                  * Generally it is called during attach call of a pcifunc but it
86                  * is called here since we are pre-installing rules before
87                  * nixlfs are attached
88                  */
89                 rvu_get_nix_blkaddr(rvu, pcifunc);
90
91                 /* MCAM RX rule for a PF/VF already exists as default unicast
92                  * rules installed by AF. Hence change the channel in those
93                  * rules to ignore channel so that packets with the required
94                  * DMAC received from LBK(by other PF/VFs in system) or from
95                  * external world (from wire) are accepted.
96                  */
97                 err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);
98                 if (err) {
99                         dev_err(rvu->dev, "RX rule for PF%d failed(%d)\n",
100                                 pf, err);
101                         return err;
102                 }
103
104                 err = rvu_switch_install_tx_rule(rvu, pcifunc, start + entry);
105                 if (err) {
106                         dev_err(rvu->dev, "TX rule for PF%d failed(%d)\n",
107                                 pf, err);
108                         return err;
109                 }
110
111                 rswitch->entry2pcifunc[entry++] = pcifunc;
112
113                 rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
114                 for (vf = 0; vf < numvfs; vf++) {
115                         pcifunc = pf << 10 | ((vf + 1) & 0x3FF);
116                         rvu_get_nix_blkaddr(rvu, pcifunc);
117
118                         err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);
119                         if (err) {
120                                 dev_err(rvu->dev,
121                                         "RX rule for PF%dVF%d failed(%d)\n",
122                                         pf, vf, err);
123                                 return err;
124                         }
125
126                         err = rvu_switch_install_tx_rule(rvu, pcifunc,
127                                                          start + entry);
128                         if (err) {
129                                 dev_err(rvu->dev,
130                                         "TX rule for PF%dVF%d failed(%d)\n",
131                                         pf, vf, err);
132                                 return err;
133                         }
134
135                         rswitch->entry2pcifunc[entry++] = pcifunc;
136                 }
137         }
138
139         return 0;
140 }
141
142 void rvu_switch_enable(struct rvu *rvu)
143 {
144         struct npc_mcam_alloc_entry_req alloc_req = { 0 };
145         struct npc_mcam_alloc_entry_rsp alloc_rsp = { 0 };
146         struct npc_delete_flow_req uninstall_req = { 0 };
147         struct npc_mcam_free_entry_req free_req = { 0 };
148         struct rvu_switch *rswitch = &rvu->rswitch;
149         struct msg_rsp rsp;
150         int ret;
151
152         alloc_req.contig = true;
153         alloc_req.count = rvu->cgx_mapped_pfs + rvu->cgx_mapped_vfs;
154         ret = rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &alloc_req,
155                                                     &alloc_rsp);
156         if (ret) {
157                 dev_err(rvu->dev,
158                         "Unable to allocate MCAM entries\n");
159                 goto exit;
160         }
161
162         if (alloc_rsp.count != alloc_req.count) {
163                 dev_err(rvu->dev,
164                         "Unable to allocate %d MCAM entries, got %d\n",
165                         alloc_req.count, alloc_rsp.count);
166                 goto free_entries;
167         }
168
169         rswitch->entry2pcifunc = kcalloc(alloc_req.count, sizeof(u16),
170                                          GFP_KERNEL);
171         if (!rswitch->entry2pcifunc)
172                 goto free_entries;
173
174         rswitch->used_entries = alloc_rsp.count;
175         rswitch->start_entry = alloc_rsp.entry;
176
177         ret = rvu_switch_install_rules(rvu);
178         if (ret)
179                 goto uninstall_rules;
180
181         return;
182
183 uninstall_rules:
184         uninstall_req.start = rswitch->start_entry;
185         uninstall_req.end =  rswitch->start_entry + rswitch->used_entries - 1;
186         rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &rsp);
187         kfree(rswitch->entry2pcifunc);
188 free_entries:
189         free_req.all = 1;
190         rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);
191 exit:
192         return;
193 }
194
195 void rvu_switch_disable(struct rvu *rvu)
196 {
197         struct npc_delete_flow_req uninstall_req = { 0 };
198         struct npc_mcam_free_entry_req free_req = { 0 };
199         struct rvu_switch *rswitch = &rvu->rswitch;
200         struct rvu_hwinfo *hw = rvu->hw;
201         int pf, vf, numvfs;
202         struct msg_rsp rsp;
203         u16 pcifunc;
204         int err;
205
206         if (!rswitch->used_entries)
207                 return;
208
209         for (pf = 1; pf < hw->total_pfs; pf++) {
210                 if (!is_pf_cgxmapped(rvu, pf))
211                         continue;
212
213                 pcifunc = pf << 10;
214                 err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF);
215                 if (err)
216                         dev_err(rvu->dev,
217                                 "Reverting RX rule for PF%d failed(%d)\n",
218                                 pf, err);
219
220                 rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
221                 for (vf = 0; vf < numvfs; vf++) {
222                         pcifunc = pf << 10 | ((vf + 1) & 0x3FF);
223                         err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF);
224                         if (err)
225                                 dev_err(rvu->dev,
226                                         "Reverting RX rule for PF%dVF%d failed(%d)\n",
227                                         pf, vf, err);
228                 }
229         }
230
231         uninstall_req.start = rswitch->start_entry;
232         uninstall_req.end =  rswitch->start_entry + rswitch->used_entries - 1;
233         free_req.all = 1;
234         rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &rsp);
235         rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);
236         rswitch->used_entries = 0;
237         kfree(rswitch->entry2pcifunc);
238 }
239
240 void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc)
241 {
242         struct rvu_switch *rswitch = &rvu->rswitch;
243         u32 max = rswitch->used_entries;
244         u16 entry;
245
246         if (!rswitch->used_entries)
247                 return;
248
249         for (entry = 0; entry < max; entry++) {
250                 if (rswitch->entry2pcifunc[entry] == pcifunc)
251                         break;
252         }
253
254         if (entry >= max)
255                 return;
256
257         rvu_switch_install_tx_rule(rvu, pcifunc, rswitch->start_entry + entry);
258         rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);
259 }