New upstream version 18.08
[deb_dpdk.git] / drivers / net / nfp / nfpcore / nfp-common / nfp_cppat.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Netronome Systems, Inc.
3  * All rights reserved.
4  */
5
6 #ifndef __NFP_CPPAT_H__
7 #define __NFP_CPPAT_H__
8
9 #include "nfp_platform.h"
10 #include "nfp_resid.h"
11
12 /* This file contains helpers for creating CPP commands
13  *
14  * All magic NFP-6xxx IMB 'mode' numbers here are from:
15  * Databook (1 August 2013)
16  * - System Overview and Connectivity
17  * -- Internal Connectivity
18  * --- Distributed Switch Fabric - Command Push/Pull (DSF-CPP) Bus
19  * ---- CPP addressing
20  * ----- Table 3.6. CPP Address Translation Mode Commands
21  */
22
23 #define _NIC_NFP6000_MU_LOCALITY_DIRECT 2
24
25 static inline int
26 _nfp6000_decode_basic(uint64_t addr, int *dest_island, int cpp_tgt, int mode,
27                       int addr40, int isld1, int isld0);
28
29 static uint64_t
30 _nic_mask64(int msb, int lsb, int at0)
31 {
32         uint64_t v;
33         int w = msb - lsb + 1;
34
35         if (w == 64)
36                 return ~(uint64_t)0;
37
38         if ((lsb + w) > 64)
39                 return 0;
40
41         v = (UINT64_C(1) << w) - 1;
42
43         if (at0)
44                 return v;
45
46         return v << lsb;
47 }
48
49 /* For VQDR, we may not modify the Channel bits, which might overlap
50  * with the Index bit. When it does, we need to ensure that isld0 == isld1.
51  */
52 static inline int
53 _nfp6000_encode_basic(uint64_t *addr, int dest_island, int cpp_tgt, int mode,
54                       int addr40, int isld1, int isld0)
55 {
56         uint64_t _u64;
57         int iid_lsb, idx_lsb;
58         int i, v = 0;
59         int isld[2];
60
61         isld[0] = isld0;
62         isld[1] = isld1;
63
64         switch (cpp_tgt) {
65         case NFP6000_CPPTGT_MU:
66                 /* This function doesn't handle MU */
67                 return NFP_ERRNO(EINVAL);
68         case NFP6000_CPPTGT_CTXPB:
69                 /* This function doesn't handle CTXPB */
70                 return NFP_ERRNO(EINVAL);
71         default:
72                 break;
73         }
74
75         switch (mode) {
76         case 0:
77                 if (cpp_tgt == NFP6000_CPPTGT_VQDR && !addr40) {
78                         /*
79                          * In this specific mode we'd rather not modify the
80                          * address but we can verify if the existing contents
81                          * will point to a valid island.
82                          */
83                         i = _nfp6000_decode_basic(*addr, &v, cpp_tgt, mode,
84                                                   addr40, isld1,
85                                                   isld0);
86                         if (i != 0)
87                                 /* Full Island ID and channel bits overlap */
88                                 return i;
89
90                         /*
91                          * If dest_island is invalid, the current address won't
92                          * go where expected.
93                          */
94                         if (dest_island != -1 && dest_island != v)
95                                 return NFP_ERRNO(EINVAL);
96
97                         /* If dest_island was -1, we don't care */
98                         return 0;
99                 }
100
101                 iid_lsb = (addr40) ? 34 : 26;
102
103                 /* <39:34> or <31:26> */
104                 _u64 = _nic_mask64((iid_lsb + 5), iid_lsb, 0);
105                 *addr &= ~_u64;
106                 *addr |= (((uint64_t)dest_island) << iid_lsb) & _u64;
107                 return 0;
108         case 1:
109                 if (cpp_tgt == NFP6000_CPPTGT_VQDR && !addr40) {
110                         i = _nfp6000_decode_basic(*addr, &v, cpp_tgt, mode,
111                                                   addr40, isld1, isld0);
112                         if (i != 0)
113                                 /* Full Island ID and channel bits overlap */
114                                 return i;
115
116                         /*
117                          * If dest_island is invalid, the current address won't
118                          * go where expected.
119                          */
120                         if (dest_island != -1 && dest_island != v)
121                                 return NFP_ERRNO(EINVAL);
122
123                         /* If dest_island was -1, we don't care */
124                         return 0;
125                 }
126
127                 idx_lsb = (addr40) ? 39 : 31;
128                 if (dest_island == isld0) {
129                         /* Only need to clear the Index bit */
130                         *addr &= ~_nic_mask64(idx_lsb, idx_lsb, 0);
131                         return 0;
132                 }
133
134                 if (dest_island == isld1) {
135                         /* Only need to set the Index bit */
136                         *addr |= (UINT64_C(1) << idx_lsb);
137                         return 0;
138                 }
139
140                 return NFP_ERRNO(ENODEV);
141         case 2:
142                 if (cpp_tgt == NFP6000_CPPTGT_VQDR && !addr40) {
143                         /* iid<0> = addr<30> = channel<0> */
144                         /* channel<1> = addr<31> = Index */
145
146                         /*
147                          * Special case where we allow channel bits to be set
148                          * before hand and with them select an island.
149                          * So we need to confirm that it's at least plausible.
150                          */
151                         i = _nfp6000_decode_basic(*addr, &v, cpp_tgt, mode,
152                                                   addr40, isld1, isld0);
153                         if (i != 0)
154                                 /* Full Island ID and channel bits overlap */
155                                 return i;
156
157                         /*
158                          * If dest_island is invalid, the current address won't
159                          * go where expected.
160                          */
161                         if (dest_island != -1 && dest_island != v)
162                                 return NFP_ERRNO(EINVAL);
163
164                         /* If dest_island was -1, we don't care */
165                         return 0;
166                 }
167
168                 /*
169                  * Make sure we compare against isldN values by clearing the
170                  * LSB. This is what the silicon does.
171                  **/
172                 isld[0] &= ~1;
173                 isld[1] &= ~1;
174
175                 idx_lsb = (addr40) ? 39 : 31;
176                 iid_lsb = idx_lsb - 1;
177
178                 /*
179                  * Try each option, take first one that fits. Not sure if we
180                  * would want to do some smarter searching and prefer 0 or non-0
181                  * island IDs.
182                  */
183
184                 for (i = 0; i < 2; i++) {
185                         for (v = 0; v < 2; v++) {
186                                 if (dest_island != (isld[i] | v))
187                                         continue;
188                                 *addr &= ~_nic_mask64(idx_lsb, iid_lsb, 0);
189                                 *addr |= (((uint64_t)i) << idx_lsb);
190                                 *addr |= (((uint64_t)v) << iid_lsb);
191                                 return 0;
192                         }
193                 }
194
195                 return NFP_ERRNO(ENODEV);
196         case 3:
197                 if (cpp_tgt == NFP6000_CPPTGT_VQDR && !addr40) {
198                         /*
199                          * iid<0> = addr<29> = data
200                          * iid<1> = addr<30> = channel<0>
201                          * channel<1> = addr<31> = Index
202                          */
203                         i = _nfp6000_decode_basic(*addr, &v, cpp_tgt, mode,
204                                                   addr40, isld1, isld0);
205                         if (i != 0)
206                                 /* Full Island ID and channel bits overlap */
207                                 return i;
208
209                         if (dest_island != -1 && dest_island != v)
210                                 return NFP_ERRNO(EINVAL);
211
212                         /* If dest_island was -1, we don't care */
213                         return 0;
214                 }
215
216                 isld[0] &= ~3;
217                 isld[1] &= ~3;
218
219                 idx_lsb = (addr40) ? 39 : 31;
220                 iid_lsb = idx_lsb - 2;
221
222                 for (i = 0; i < 2; i++) {
223                         for (v = 0; v < 4; v++) {
224                                 if (dest_island != (isld[i] | v))
225                                         continue;
226                                 *addr &= ~_nic_mask64(idx_lsb, iid_lsb, 0);
227                                 *addr |= (((uint64_t)i) << idx_lsb);
228                                 *addr |= (((uint64_t)v) << iid_lsb);
229                                 return 0;
230                         }
231                 }
232                 return NFP_ERRNO(ENODEV);
233         default:
234                 break;
235         }
236
237         return NFP_ERRNO(EINVAL);
238 }
239
240 static inline int
241 _nfp6000_decode_basic(uint64_t addr, int *dest_island, int cpp_tgt, int mode,
242                       int addr40, int isld1, int isld0)
243 {
244         int iid_lsb, idx_lsb;
245
246         switch (cpp_tgt) {
247         case NFP6000_CPPTGT_MU:
248                 /* This function doesn't handle MU */
249                 return NFP_ERRNO(EINVAL);
250         case NFP6000_CPPTGT_CTXPB:
251                 /* This function doesn't handle CTXPB */
252                 return NFP_ERRNO(EINVAL);
253         default:
254                 break;
255         }
256
257         switch (mode) {
258         case 0:
259                 /*
260                  * For VQDR, in this mode for 32-bit addressing it would be
261                  * islands 0, 16, 32 and 48 depending on channel and upper
262                  * address bits. Since those are not all valid islands, most
263                  * decode cases would result in bad island IDs, but we do them
264                  * anyway since this is decoding an address that is already
265                  * assumed to be used as-is to get to sram.
266                  */
267                 iid_lsb = (addr40) ? 34 : 26;
268                 *dest_island = (int)(addr >> iid_lsb) & 0x3F;
269                 return 0;
270         case 1:
271                 /*
272                  * For VQDR 32-bit, this would decode as:
273                  *      Channel 0: island#0
274                  *      Channel 1: island#0
275                  *      Channel 2: island#1
276                  *      Channel 3: island#1
277                  *
278                  * That would be valid as long as both islands have VQDR.
279                  * Let's allow this.
280                  */
281
282                 idx_lsb = (addr40) ? 39 : 31;
283                 if (addr & _nic_mask64(idx_lsb, idx_lsb, 0))
284                         *dest_island = isld1;
285                 else
286                         *dest_island = isld0;
287
288                 return 0;
289         case 2:
290                 /*
291                  * For VQDR 32-bit:
292                  *      Channel 0: (island#0 | 0)
293                  *      Channel 1: (island#0 | 1)
294                  *      Channel 2: (island#1 | 0)
295                  *      Channel 3: (island#1 | 1)
296                  *
297                  * Make sure we compare against isldN values by clearing the
298                  * LSB. This is what the silicon does.
299                  */
300                 isld0 &= ~1;
301                 isld1 &= ~1;
302
303                 idx_lsb = (addr40) ? 39 : 31;
304                 iid_lsb = idx_lsb - 1;
305
306                 if (addr & _nic_mask64(idx_lsb, idx_lsb, 0))
307                         *dest_island = isld1 | (int)((addr >> iid_lsb) & 1);
308                 else
309                         *dest_island = isld0 | (int)((addr >> iid_lsb) & 1);
310
311                 return 0;
312         case 3:
313                 /*
314                  * In this mode the data address starts to affect the island ID
315                  * so rather not allow it. In some really specific case one
316                  * could use this to send the upper half of the VQDR channel to
317                  * another MU, but this is getting very specific. However, as
318                  * above for mode 0, this is the decoder and the caller should
319                  * validate the resulting IID. This blindly does what the
320                  * silicon would do.
321                  */
322
323                 isld0 &= ~3;
324                 isld1 &= ~3;
325
326                 idx_lsb = (addr40) ? 39 : 31;
327                 iid_lsb = idx_lsb - 2;
328
329                 if (addr & _nic_mask64(idx_lsb, idx_lsb, 0))
330                         *dest_island = isld1 | (int)((addr >> iid_lsb) & 3);
331                 else
332                         *dest_island = isld0 | (int)((addr >> iid_lsb) & 3);
333
334                 return 0;
335         default:
336                 break;
337         }
338
339         return NFP_ERRNO(EINVAL);
340 }
341
342 static inline int
343 _nfp6000_cppat_mu_locality_lsb(int mode, int addr40)
344 {
345         switch (mode) {
346         case 0:
347         case 1:
348         case 2:
349         case 3:
350                 return (addr40) ? 38 : 30;
351         default:
352                 break;
353         }
354         return NFP_ERRNO(EINVAL);
355 }
356
357 static inline int
358 _nfp6000_encode_mu(uint64_t *addr, int dest_island, int mode, int addr40,
359                    int isld1, int isld0)
360 {
361         uint64_t _u64;
362         int iid_lsb, idx_lsb, locality_lsb;
363         int i, v;
364         int isld[2];
365         int da;
366
367         isld[0] = isld0;
368         isld[1] = isld1;
369         locality_lsb = _nfp6000_cppat_mu_locality_lsb(mode, addr40);
370
371         if (((*addr >> locality_lsb) & 3) == _NIC_NFP6000_MU_LOCALITY_DIRECT)
372                 da = 1;
373         else
374                 da = 0;
375
376         switch (mode) {
377         case 0:
378                 iid_lsb = (addr40) ? 32 : 24;
379                 _u64 = _nic_mask64((iid_lsb + 5), iid_lsb, 0);
380                 *addr &= ~_u64;
381                 *addr |= (((uint64_t)dest_island) << iid_lsb) & _u64;
382                 return 0;
383         case 1:
384                 if (da) {
385                         iid_lsb = (addr40) ? 32 : 24;
386                         _u64 = _nic_mask64((iid_lsb + 5), iid_lsb, 0);
387                         *addr &= ~_u64;
388                         *addr |= (((uint64_t)dest_island) << iid_lsb) & _u64;
389                         return 0;
390                 }
391
392                 idx_lsb = (addr40) ? 37 : 29;
393                 if (dest_island == isld0) {
394                         *addr &= ~_nic_mask64(idx_lsb, idx_lsb, 0);
395                         return 0;
396                 }
397
398                 if (dest_island == isld1) {
399                         *addr |= (UINT64_C(1) << idx_lsb);
400                         return 0;
401                 }
402
403                 return NFP_ERRNO(ENODEV);
404         case 2:
405                 if (da) {
406                         iid_lsb = (addr40) ? 32 : 24;
407                         _u64 = _nic_mask64((iid_lsb + 5), iid_lsb, 0);
408                         *addr &= ~_u64;
409                         *addr |= (((uint64_t)dest_island) << iid_lsb) & _u64;
410                         return 0;
411                 }
412
413                 /*
414                  * Make sure we compare against isldN values by clearing the
415                  * LSB. This is what the silicon does.
416                  */
417                 isld[0] &= ~1;
418                 isld[1] &= ~1;
419
420                 idx_lsb = (addr40) ? 37 : 29;
421                 iid_lsb = idx_lsb - 1;
422
423                 /*
424                  * Try each option, take first one that fits. Not sure if we
425                  * would want to do some smarter searching and prefer 0 or
426                  * non-0 island IDs.
427                  */
428
429                 for (i = 0; i < 2; i++) {
430                         for (v = 0; v < 2; v++) {
431                                 if (dest_island != (isld[i] | v))
432                                         continue;
433                                 *addr &= ~_nic_mask64(idx_lsb, iid_lsb, 0);
434                                 *addr |= (((uint64_t)i) << idx_lsb);
435                                 *addr |= (((uint64_t)v) << iid_lsb);
436                                 return 0;
437                         }
438                 }
439                 return NFP_ERRNO(ENODEV);
440         case 3:
441                 /*
442                  * Only the EMU will use 40 bit addressing. Silently set the
443                  * direct locality bit for everyone else. The SDK toolchain
444                  * uses dest_island <= 0 to test for atypical address encodings
445                  * to support access to local-island CTM with a 32-but address
446                  * (high-locality is effectively ignored and just used for
447                  * routing to island #0).
448                  */
449                 if (dest_island > 0 &&
450                     (dest_island < 24 || dest_island > 26)) {
451                         *addr |= ((uint64_t)_NIC_NFP6000_MU_LOCALITY_DIRECT)
452                                  << locality_lsb;
453                         da = 1;
454                 }
455
456                 if (da) {
457                         iid_lsb = (addr40) ? 32 : 24;
458                         _u64 = _nic_mask64((iid_lsb + 5), iid_lsb, 0);
459                         *addr &= ~_u64;
460                         *addr |= (((uint64_t)dest_island) << iid_lsb) & _u64;
461                         return 0;
462                 }
463
464                 isld[0] &= ~3;
465                 isld[1] &= ~3;
466
467                 idx_lsb = (addr40) ? 37 : 29;
468                 iid_lsb = idx_lsb - 2;
469
470                 for (i = 0; i < 2; i++) {
471                         for (v = 0; v < 4; v++) {
472                                 if (dest_island != (isld[i] | v))
473                                         continue;
474                                 *addr &= ~_nic_mask64(idx_lsb, iid_lsb, 0);
475                                 *addr |= (((uint64_t)i) << idx_lsb);
476                                 *addr |= (((uint64_t)v) << iid_lsb);
477                                 return 0;
478                         }
479                 }
480
481                 return NFP_ERRNO(ENODEV);
482         default:
483                 break;
484         }
485
486         return NFP_ERRNO(EINVAL);
487 }
488
489 static inline int
490 _nfp6000_decode_mu(uint64_t addr, int *dest_island, int mode, int addr40,
491                    int isld1, int isld0)
492 {
493         int iid_lsb, idx_lsb, locality_lsb;
494         int da;
495
496         locality_lsb = _nfp6000_cppat_mu_locality_lsb(mode, addr40);
497
498         if (((addr >> locality_lsb) & 3) == _NIC_NFP6000_MU_LOCALITY_DIRECT)
499                 da = 1;
500         else
501                 da = 0;
502
503         switch (mode) {
504         case 0:
505                 iid_lsb = (addr40) ? 32 : 24;
506                 *dest_island = (int)(addr >> iid_lsb) & 0x3F;
507                 return 0;
508         case 1:
509                 if (da) {
510                         iid_lsb = (addr40) ? 32 : 24;
511                         *dest_island = (int)(addr >> iid_lsb) & 0x3F;
512                         return 0;
513                 }
514
515                 idx_lsb = (addr40) ? 37 : 29;
516
517                 if (addr & _nic_mask64(idx_lsb, idx_lsb, 0))
518                         *dest_island = isld1;
519                 else
520                         *dest_island = isld0;
521
522                 return 0;
523         case 2:
524                 if (da) {
525                         iid_lsb = (addr40) ? 32 : 24;
526                         *dest_island = (int)(addr >> iid_lsb) & 0x3F;
527                         return 0;
528                 }
529                 /*
530                  * Make sure we compare against isldN values by clearing the
531                  * LSB. This is what the silicon does.
532                  */
533                 isld0 &= ~1;
534                 isld1 &= ~1;
535
536                 idx_lsb = (addr40) ? 37 : 29;
537                 iid_lsb = idx_lsb - 1;
538
539                 if (addr & _nic_mask64(idx_lsb, idx_lsb, 0))
540                         *dest_island = isld1 | (int)((addr >> iid_lsb) & 1);
541                 else
542                         *dest_island = isld0 | (int)((addr >> iid_lsb) & 1);
543
544                 return 0;
545         case 3:
546                 if (da) {
547                         iid_lsb = (addr40) ? 32 : 24;
548                         *dest_island = (int)(addr >> iid_lsb) & 0x3F;
549                         return 0;
550                 }
551
552                 isld0 &= ~3;
553                 isld1 &= ~3;
554
555                 idx_lsb = (addr40) ? 37 : 29;
556                 iid_lsb = idx_lsb - 2;
557
558                 if (addr & _nic_mask64(idx_lsb, idx_lsb, 0))
559                         *dest_island = isld1 | (int)((addr >> iid_lsb) & 3);
560                 else
561                         *dest_island = isld0 | (int)((addr >> iid_lsb) & 3);
562
563                 return 0;
564         default:
565                 break;
566         }
567
568         return NFP_ERRNO(EINVAL);
569 }
570
571 static inline int
572 _nfp6000_cppat_addr_encode(uint64_t *addr, int dest_island, int cpp_tgt,
573                            int mode, int addr40, int isld1, int isld0)
574 {
575         switch (cpp_tgt) {
576         case NFP6000_CPPTGT_NBI:
577         case NFP6000_CPPTGT_VQDR:
578         case NFP6000_CPPTGT_ILA:
579         case NFP6000_CPPTGT_PCIE:
580         case NFP6000_CPPTGT_ARM:
581         case NFP6000_CPPTGT_CRYPTO:
582         case NFP6000_CPPTGT_CLS:
583                 return _nfp6000_encode_basic(addr, dest_island, cpp_tgt, mode,
584                                              addr40, isld1, isld0);
585
586         case NFP6000_CPPTGT_MU:
587                 return _nfp6000_encode_mu(addr, dest_island, mode, addr40,
588                                           isld1, isld0);
589
590         case NFP6000_CPPTGT_CTXPB:
591                 if (mode != 1 || addr40 != 0)
592                         return NFP_ERRNO(EINVAL);
593
594                 *addr &= ~_nic_mask64(29, 24, 0);
595                 *addr |= (((uint64_t)dest_island) << 24) &
596                           _nic_mask64(29, 24, 0);
597                 return 0;
598         default:
599                 break;
600         }
601
602         return NFP_ERRNO(EINVAL);
603 }
604
605 static inline int
606 _nfp6000_cppat_addr_decode(uint64_t addr, int *dest_island, int cpp_tgt,
607                            int mode, int addr40, int isld1, int isld0)
608 {
609         switch (cpp_tgt) {
610         case NFP6000_CPPTGT_NBI:
611         case NFP6000_CPPTGT_VQDR:
612         case NFP6000_CPPTGT_ILA:
613         case NFP6000_CPPTGT_PCIE:
614         case NFP6000_CPPTGT_ARM:
615         case NFP6000_CPPTGT_CRYPTO:
616         case NFP6000_CPPTGT_CLS:
617                 return _nfp6000_decode_basic(addr, dest_island, cpp_tgt, mode,
618                                              addr40, isld1, isld0);
619
620         case NFP6000_CPPTGT_MU:
621                 return _nfp6000_decode_mu(addr, dest_island, mode, addr40,
622                                           isld1, isld0);
623
624         case NFP6000_CPPTGT_CTXPB:
625                 if (mode != 1 || addr40 != 0)
626                         return -EINVAL;
627                 *dest_island = (int)(addr >> 24) & 0x3F;
628                 return 0;
629         default:
630                 break;
631         }
632
633         return -EINVAL;
634 }
635
636 static inline int
637 _nfp6000_cppat_addr_iid_clear(uint64_t *addr, int cpp_tgt, int mode, int addr40)
638 {
639         int iid_lsb, locality_lsb, da;
640
641         switch (cpp_tgt) {
642         case NFP6000_CPPTGT_NBI:
643         case NFP6000_CPPTGT_VQDR:
644         case NFP6000_CPPTGT_ILA:
645         case NFP6000_CPPTGT_PCIE:
646         case NFP6000_CPPTGT_ARM:
647         case NFP6000_CPPTGT_CRYPTO:
648         case NFP6000_CPPTGT_CLS:
649                 switch (mode) {
650                 case 0:
651                         iid_lsb = (addr40) ? 34 : 26;
652                         *addr &= ~(UINT64_C(0x3F) << iid_lsb);
653                         return 0;
654                 case 1:
655                         iid_lsb = (addr40) ? 39 : 31;
656                         *addr &= ~_nic_mask64(iid_lsb, iid_lsb, 0);
657                         return 0;
658                 case 2:
659                         iid_lsb = (addr40) ? 38 : 30;
660                         *addr &= ~_nic_mask64(iid_lsb + 1, iid_lsb, 0);
661                         return 0;
662                 case 3:
663                         iid_lsb = (addr40) ? 37 : 29;
664                         *addr &= ~_nic_mask64(iid_lsb + 2, iid_lsb, 0);
665                         return 0;
666                 default:
667                         break;
668                 }
669         case NFP6000_CPPTGT_MU:
670                 locality_lsb = _nfp6000_cppat_mu_locality_lsb(mode, addr40);
671                 da = (((*addr >> locality_lsb) & 3) ==
672                       _NIC_NFP6000_MU_LOCALITY_DIRECT);
673                 switch (mode) {
674                 case 0:
675                         iid_lsb = (addr40) ? 32 : 24;
676                         *addr &= ~(UINT64_C(0x3F) << iid_lsb);
677                         return 0;
678                 case 1:
679                         if (da) {
680                                 iid_lsb = (addr40) ? 32 : 24;
681                                 *addr &= ~(UINT64_C(0x3F) << iid_lsb);
682                                 return 0;
683                         }
684                         iid_lsb = (addr40) ? 37 : 29;
685                         *addr &= ~_nic_mask64(iid_lsb, iid_lsb, 0);
686                         return 0;
687                 case 2:
688                         if (da) {
689                                 iid_lsb = (addr40) ? 32 : 24;
690                                 *addr &= ~(UINT64_C(0x3F) << iid_lsb);
691                                 return 0;
692                         }
693
694                         iid_lsb = (addr40) ? 36 : 28;
695                         *addr &= ~_nic_mask64(iid_lsb + 1, iid_lsb, 0);
696                         return 0;
697                 case 3:
698                         if (da) {
699                                 iid_lsb = (addr40) ? 32 : 24;
700                                 *addr &= ~(UINT64_C(0x3F) << iid_lsb);
701                                 return 0;
702                         }
703
704                         iid_lsb = (addr40) ? 35 : 27;
705                         *addr &= ~_nic_mask64(iid_lsb + 2, iid_lsb, 0);
706                         return 0;
707                 default:
708                         break;
709                 }
710         case NFP6000_CPPTGT_CTXPB:
711                 if (mode != 1 || addr40 != 0)
712                         return 0;
713                 *addr &= ~(UINT64_C(0x3F) << 24);
714                 return 0;
715         default:
716                 break;
717         }
718
719         return NFP_ERRNO(EINVAL);
720 }
721
722 #endif /* __NFP_CPPAT_H__ */