8a88dc5ff000240df9bf153c2d6c76daf7517a62
[openwrt/openwrt.git] / target / linux / mediatek / files-5.10 / drivers / net / phy / rtk / rtl8367c / trunk.c
1 /*
2 * Copyright (C) 2013 Realtek Semiconductor Corp.
3 * All Rights Reserved.
4 *
5 * Unless you and Realtek execute a separate written software license
6 * agreement governing use of this software, this software is licensed
7 * to you under the terms of the GNU General Public License version 2,
8 * available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
9 *
10 * $Revision: 76306 $
11 * $Date: 2017-03-08 15:13:58 +0800 (週三, 08 三月 2017) $
12 *
13 * Purpose : RTK switch high-level API for RTL8367/RTL8367C
14 * Feature : Here is a list of all functions and variables in Trunk module.
15 *
16 */
17
18 #include <rtk_switch.h>
19 #include <rtk_error.h>
20 #include <trunk.h>
21 #include <string.h>
22
23 #include <rtl8367c_asicdrv.h>
24 #include <rtl8367c_asicdrv_trunking.h>
25
26 /* Function Name:
27 * rtk_trunk_port_set
28 * Description:
29 * Set trunking group available port mask
30 * Input:
31 * trk_gid - trunk group id
32 * pTrunk_member_portmask - Logic trunking member port mask
33 * Output:
34 * None
35 * Return:
36 * RT_ERR_OK - OK
37 * RT_ERR_FAILED - Failed
38 * RT_ERR_SMI - SMI access error
39 * RT_ERR_LA_TRUNK_ID - Invalid trunking group
40 * RT_ERR_PORT_MASK - Invalid portmask.
41 * Note:
42 * The API can set port trunking group port mask. Each port trunking group has max 4 ports.
43 * If enabled port mask has less than 2 ports available setting, then this trunking group function is disabled.
44 */
45 rtk_api_ret_t rtk_trunk_port_set(rtk_trunk_group_t trk_gid, rtk_portmask_t *pTrunk_member_portmask)
46 {
47 rtk_api_ret_t retVal;
48 rtk_uint32 pmsk;
49 rtk_uint32 regValue, type, tmp;
50
51
52 if((retVal = rtl8367c_setAsicReg(0x13C2, 0x0249)) != RT_ERR_OK)
53 return retVal;
54
55 if((retVal = rtl8367c_getAsicReg(0x1300, &regValue)) != RT_ERR_OK)
56 return retVal;
57
58 if((retVal = rtl8367c_setAsicReg(0x13C2, 0x0000)) != RT_ERR_OK)
59 return retVal;
60
61 switch (regValue)
62 {
63 case 0x0276:
64 case 0x0597:
65 case 0x6367:
66 type = 0;
67 break;
68 case 0x0652:
69 case 0x6368:
70 type = 1;
71 break;
72 case 0x0801:
73 case 0x6511:
74 type = 2;
75 break;
76 default:
77 return RT_ERR_FAILED;
78 }
79
80 /* Check initialization state */
81 RTK_CHK_INIT_STATE();
82
83 /* Check Trunk Group Valid */
84 RTK_CHK_TRUNK_GROUP_VALID(trk_gid);
85
86 if(NULL == pTrunk_member_portmask)
87 return RT_ERR_NULL_POINTER;
88
89 RTK_CHK_PORTMASK_VALID(pTrunk_member_portmask);
90
91 if((retVal = rtk_switch_portmask_L2P_get(pTrunk_member_portmask, &pmsk)) != RT_ERR_OK)
92 return retVal;
93
94 if((type == 0) || (type == 1))
95 {
96 if ((pmsk | RTL8367C_PORT_TRUNK_GROUP_MASK_MASK(trk_gid)) != (rtk_uint32)RTL8367C_PORT_TRUNK_GROUP_MASK_MASK(trk_gid))
97 return RT_ERR_PORT_MASK;
98
99 pmsk = (pmsk & RTL8367C_PORT_TRUNK_GROUP_MASK_MASK(trk_gid)) >> RTL8367C_PORT_TRUNK_GROUP_MASK_OFFSET(trk_gid);
100 }
101 else if(type == 2)
102 {
103 tmp = 0;
104
105 if(pmsk & 0x2)
106 tmp |= 1;
107 if(pmsk & 0x8)
108 tmp |=2;
109 if(pmsk & 0x80)
110 tmp |=8;
111
112 pmsk = tmp;
113 }
114
115 if ((retVal = rtl8367c_setAsicTrunkingGroup(trk_gid, pmsk)) != RT_ERR_OK)
116 return retVal;
117
118 return RT_ERR_OK;
119 }
120
121 /* Function Name:
122 * rtk_trunk_port_get
123 * Description:
124 * Get trunking group available port mask
125 * Input:
126 * trk_gid - trunk group id
127 * Output:
128 * pTrunk_member_portmask - Logic trunking member port mask
129 * Return:
130 * RT_ERR_OK - OK
131 * RT_ERR_FAILED - Failed
132 * RT_ERR_SMI - SMI access error
133 * RT_ERR_LA_TRUNK_ID - Invalid trunking group
134 * Note:
135 * The API can get 2 port trunking group.
136 */
137 rtk_api_ret_t rtk_trunk_port_get(rtk_trunk_group_t trk_gid, rtk_portmask_t *pTrunk_member_portmask)
138 {
139 rtk_api_ret_t retVal;
140 rtk_uint32 pmsk;
141
142 /* Check initialization state */
143 RTK_CHK_INIT_STATE();
144
145 /* Check Trunk Group Valid */
146 RTK_CHK_TRUNK_GROUP_VALID(trk_gid);
147
148 if ((retVal = rtl8367c_getAsicTrunkingGroup(trk_gid, &pmsk)) != RT_ERR_OK)
149 return retVal;
150
151 pmsk = pmsk << RTL8367C_PORT_TRUNK_GROUP_MASK_OFFSET(trk_gid);
152
153 if((retVal = rtk_switch_portmask_P2L_get(pmsk, pTrunk_member_portmask)) != RT_ERR_OK)
154 return retVal;
155
156 return RT_ERR_OK;
157 }
158
159 /* Function Name:
160 * rtk_trunk_distributionAlgorithm_set
161 * Description:
162 * Set port trunking hash select sources
163 * Input:
164 * trk_gid - trunk group id
165 * algo_bitmask - Bitmask of the distribution algorithm
166 * Output:
167 * None
168 * Return:
169 * RT_ERR_OK - OK
170 * RT_ERR_FAILED - Failed
171 * RT_ERR_SMI - SMI access error
172 * RT_ERR_LA_TRUNK_ID - Invalid trunking group
173 * RT_ERR_LA_HASHMASK - Hash algorithm selection error.
174 * RT_ERR_PORT_MASK - Invalid portmask.
175 * Note:
176 * The API can set port trunking hash algorithm sources.
177 * 7 bits mask for link aggregation group0 hash parameter selection {DIP, SIP, DMAC, SMAC, SPA}
178 * - 0b0000001: SPA
179 * - 0b0000010: SMAC
180 * - 0b0000100: DMAC
181 * - 0b0001000: SIP
182 * - 0b0010000: DIP
183 * - 0b0100000: TCP/UDP Source Port
184 * - 0b1000000: TCP/UDP Destination Port
185 * Example:
186 * - 0b0000011: SMAC & SPA
187 * - Note that it could be an arbitrary combination or independent set
188 */
189 rtk_api_ret_t rtk_trunk_distributionAlgorithm_set(rtk_trunk_group_t trk_gid, rtk_uint32 algo_bitmask)
190 {
191 rtk_api_ret_t retVal;
192
193 /* Check initialization state */
194 RTK_CHK_INIT_STATE();
195
196 if (trk_gid != RTK_WHOLE_SYSTEM)
197 return RT_ERR_LA_TRUNK_ID;
198
199 if (algo_bitmask >= 128)
200 return RT_ERR_LA_HASHMASK;
201
202 if ((retVal = rtl8367c_setAsicTrunkingHashSelect(algo_bitmask)) != RT_ERR_OK)
203 return retVal;
204
205 return RT_ERR_OK;
206 }
207
208 /* Function Name:
209 * rtk_trunk_distributionAlgorithm_get
210 * Description:
211 * Get port trunking hash select sources
212 * Input:
213 * trk_gid - trunk group id
214 * Output:
215 * pAlgo_bitmask - Bitmask of the distribution algorithm
216 * Return:
217 * RT_ERR_OK - OK
218 * RT_ERR_FAILED - Failed
219 * RT_ERR_SMI - SMI access error
220 * RT_ERR_LA_TRUNK_ID - Invalid trunking group
221 * Note:
222 * The API can get port trunking hash algorithm sources.
223 */
224 rtk_api_ret_t rtk_trunk_distributionAlgorithm_get(rtk_trunk_group_t trk_gid, rtk_uint32 *pAlgo_bitmask)
225 {
226 rtk_api_ret_t retVal;
227
228 /* Check initialization state */
229 RTK_CHK_INIT_STATE();
230
231 if (trk_gid != RTK_WHOLE_SYSTEM)
232 return RT_ERR_LA_TRUNK_ID;
233
234 if(NULL == pAlgo_bitmask)
235 return RT_ERR_NULL_POINTER;
236
237 if ((retVal = rtl8367c_getAsicTrunkingHashSelect((rtk_uint32 *)pAlgo_bitmask)) != RT_ERR_OK)
238 return retVal;
239
240 return RT_ERR_OK;
241 }
242
243 /* Function Name:
244 * rtk_trunk_trafficSeparate_set
245 * Description:
246 * Set the traffic separation setting of a trunk group from the specified device.
247 * Input:
248 * trk_gid - trunk group id
249 * separateType - traffic separation setting
250 * Output:
251 * None
252 * Return:
253 * RT_ERR_OK
254 * RT_ERR_FAILED
255 * RT_ERR_UNIT_ID - invalid unit id
256 * RT_ERR_LA_TRUNK_ID - invalid trunk ID
257 * RT_ERR_LA_HASHMASK - invalid hash mask
258 * Note:
259 * SEPARATE_NONE: disable traffic separation
260 * SEPARATE_FLOOD: trunk MSB link up port is dedicated to TX flooding (L2 lookup miss) traffic
261 */
262 rtk_api_ret_t rtk_trunk_trafficSeparate_set(rtk_trunk_group_t trk_gid, rtk_trunk_separateType_t separateType)
263 {
264 rtk_api_ret_t retVal;
265 rtk_uint32 enabled;
266
267 /* Check initialization state */
268 RTK_CHK_INIT_STATE();
269
270 if (trk_gid != RTK_WHOLE_SYSTEM)
271 return RT_ERR_LA_TRUNK_ID;
272
273 if(separateType >= SEPARATE_END)
274 return RT_ERR_INPUT;
275
276 enabled = (separateType == SEPARATE_FLOOD) ? ENABLED : DISABLED;
277 if ((retVal = rtl8367c_setAsicTrunkingFlood(enabled)) != RT_ERR_OK)
278 return retVal;
279
280 return RT_ERR_OK;
281 }
282
283 /* Function Name:
284 * rtk_trunk_trafficSeparate_get
285 * Description:
286 * Get the traffic separation setting of a trunk group from the specified device.
287 * Input:
288 * trk_gid - trunk group id
289 * Output:
290 * pSeparateType - pointer separated traffic type
291 * Return:
292 * RT_ERR_OK
293 * RT_ERR_FAILED
294 * RT_ERR_UNIT_ID - invalid unit id
295 * RT_ERR_LA_TRUNK_ID - invalid trunk ID
296 * RT_ERR_NULL_POINTER - input parameter may be null pointer
297 * Note:
298 * SEPARATE_NONE: disable traffic separation
299 * SEPARATE_FLOOD: trunk MSB link up port is dedicated to TX flooding (L2 lookup miss) traffic
300 */
301 rtk_api_ret_t rtk_trunk_trafficSeparate_get(rtk_trunk_group_t trk_gid, rtk_trunk_separateType_t *pSeparateType)
302 {
303 rtk_api_ret_t retVal;
304 rtk_uint32 enabled;
305
306 /* Check initialization state */
307 RTK_CHK_INIT_STATE();
308
309 if (trk_gid != RTK_WHOLE_SYSTEM)
310 return RT_ERR_LA_TRUNK_ID;
311
312 if(NULL == pSeparateType)
313 return RT_ERR_NULL_POINTER;
314
315 if ((retVal = rtl8367c_getAsicTrunkingFlood(&enabled)) != RT_ERR_OK)
316 return retVal;
317
318 *pSeparateType = (enabled == ENABLED) ? SEPARATE_FLOOD : SEPARATE_NONE;
319 return RT_ERR_OK;
320 }
321
322 /* Function Name:
323 * rtk_trunk_mode_set
324 * Description:
325 * Set the trunk mode to the specified device.
326 * Input:
327 * mode - trunk mode
328 * Output:
329 * None
330 * Return:
331 * RT_ERR_OK
332 * RT_ERR_FAILED
333 * RT_ERR_INPUT - invalid input parameter
334 * Note:
335 * The enum of the trunk mode as following
336 * - TRUNK_MODE_NORMAL
337 * - TRUNK_MODE_DUMB
338 */
339 rtk_api_ret_t rtk_trunk_mode_set(rtk_trunk_mode_t mode)
340 {
341 rtk_api_ret_t retVal;
342
343 /* Check initialization state */
344 RTK_CHK_INIT_STATE();
345
346 if(mode >= TRUNK_MODE_END)
347 return RT_ERR_INPUT;
348
349 if ((retVal = rtl8367c_setAsicTrunkingMode((rtk_uint32)mode)) != RT_ERR_OK)
350 return retVal;
351
352 return RT_ERR_OK;
353 }
354
355 /* Function Name:
356 * rtk_trunk_mode_get
357 * Description:
358 * Get the trunk mode from the specified device.
359 * Input:
360 * None
361 * Output:
362 * pMode - pointer buffer of trunk mode
363 * Return:
364 * RT_ERR_OK
365 * RT_ERR_FAILED
366 * RT_ERR_NULL_POINTER - input parameter may be null pointer
367 * Note:
368 * The enum of the trunk mode as following
369 * - TRUNK_MODE_NORMAL
370 * - TRUNK_MODE_DUMB
371 */
372 rtk_api_ret_t rtk_trunk_mode_get(rtk_trunk_mode_t *pMode)
373 {
374 rtk_api_ret_t retVal;
375
376 /* Check initialization state */
377 RTK_CHK_INIT_STATE();
378
379 if(NULL == pMode)
380 return RT_ERR_NULL_POINTER;
381
382 if ((retVal = rtl8367c_getAsicTrunkingMode((rtk_uint32 *)pMode)) != RT_ERR_OK)
383 return retVal;
384
385 return RT_ERR_OK;
386 }
387
388 /* Function Name:
389 * rtk_trunk_trafficPause_set
390 * Description:
391 * Set the traffic pause setting of a trunk group.
392 * Input:
393 * trk_gid - trunk group id
394 * enable - traffic pause state
395 * Output:
396 * None
397 * Return:
398 * RT_ERR_OK
399 * RT_ERR_FAILED
400 * RT_ERR_LA_TRUNK_ID - invalid trunk ID
401 * Note:
402 * None.
403 */
404 rtk_api_ret_t rtk_trunk_trafficPause_set(rtk_trunk_group_t trk_gid, rtk_enable_t enable)
405 {
406 rtk_api_ret_t retVal;
407
408 /* Check initialization state */
409 RTK_CHK_INIT_STATE();
410
411 /* Check Trunk Group Valid */
412 RTK_CHK_TRUNK_GROUP_VALID(trk_gid);
413
414 if(enable >= RTK_ENABLE_END)
415 return RT_ERR_INPUT;
416
417 if ((retVal = rtl8367c_setAsicTrunkingFc((rtk_uint32)trk_gid, (rtk_uint32)enable)) != RT_ERR_OK)
418 return retVal;
419
420 return RT_ERR_OK;
421 }
422
423 /* Function Name:
424 * rtk_trunk_trafficPause_get
425 * Description:
426 * Get the traffic pause setting of a trunk group.
427 * Input:
428 * trk_gid - trunk group id
429 * Output:
430 * pEnable - pointer of traffic pause state.
431 * Return:
432 * RT_ERR_OK
433 * RT_ERR_FAILED
434 * RT_ERR_LA_TRUNK_ID - invalid trunk ID
435 * RT_ERR_NULL_POINTER - input parameter may be null pointer
436 * Note:
437 * None.
438 */
439 rtk_api_ret_t rtk_trunk_trafficPause_get(rtk_trunk_group_t trk_gid, rtk_enable_t *pEnable)
440 {
441 rtk_api_ret_t retVal;
442
443 /* Check initialization state */
444 RTK_CHK_INIT_STATE();
445
446 /* Check Trunk Group Valid */
447 RTK_CHK_TRUNK_GROUP_VALID(trk_gid);
448
449 if(NULL == pEnable)
450 return RT_ERR_NULL_POINTER;
451
452 if ((retVal = rtl8367c_getAsicTrunkingFc((rtk_uint32)trk_gid, (rtk_uint32 *)pEnable)) != RT_ERR_OK)
453 return retVal;
454
455 return RT_ERR_OK;
456 }
457
458 /* Function Name:
459 * rtk_trunk_hashMappingTable_set
460 * Description:
461 * Set hash value to port array in the trunk group id from the specified device.
462 * Input:
463 * trk_gid - trunk group id
464 * pHash2Port_array - ports associate with the hash value
465 * Output:
466 * None
467 * Return:
468 * RT_ERR_OK
469 * RT_ERR_FAILED
470 * RT_ERR_UNIT_ID - invalid unit id
471 * RT_ERR_LA_TRUNK_ID - invalid trunk ID
472 * RT_ERR_NULL_POINTER - input parameter may be null pointer
473 * RT_ERR_LA_TRUNK_NOT_EXIST - the trunk doesn't exist
474 * RT_ERR_LA_NOT_MEMBER_PORT - the port is not a member port of the trunk
475 * RT_ERR_LA_CPUPORT - CPU port can not be aggregated port
476 * Note:
477 * Trunk group 0 & 1 shares the same hash mapping table.
478 * Trunk group 2 uses a independent table.
479 */
480 rtk_api_ret_t rtk_trunk_hashMappingTable_set(rtk_trunk_group_t trk_gid, rtk_trunk_hashVal2Port_t *pHash2Port_array)
481 {
482 rtk_api_ret_t retVal;
483 rtk_uint32 hashValue;
484
485 /* Check initialization state */
486 RTK_CHK_INIT_STATE();
487
488 /* Check Trunk Group Valid */
489 RTK_CHK_TRUNK_GROUP_VALID(trk_gid);
490
491 if(NULL == pHash2Port_array)
492 return RT_ERR_NULL_POINTER;
493
494 if(trk_gid <= TRUNK_GROUP1)
495 {
496 for(hashValue = 0; hashValue < RTK_MAX_NUM_OF_TRUNK_HASH_VAL; hashValue++)
497 {
498 if ((retVal = rtl8367c_setAsicTrunkingHashTable(hashValue, pHash2Port_array->value[hashValue])) != RT_ERR_OK)
499 return retVal;
500 }
501 }
502 else
503 {
504 for(hashValue = 0; hashValue < RTK_MAX_NUM_OF_TRUNK_HASH_VAL; hashValue++)
505 {
506 if ((retVal = rtl8367c_setAsicTrunkingHashTable1(hashValue, pHash2Port_array->value[hashValue])) != RT_ERR_OK)
507 return retVal;
508 }
509 }
510
511 return RT_ERR_OK;
512 }
513
514 /* Function Name:
515 * rtk_trunk_hashMappingTable_get
516 * Description:
517 * Get hash value to port array in the trunk group id from the specified device.
518 * Input:
519 * trk_gid - trunk group id
520 * Output:
521 * pHash2Port_array - pointer buffer of ports associate with the hash value
522 * Return:
523 * RT_ERR_OK
524 * RT_ERR_FAILED
525 * RT_ERR_UNIT_ID - invalid unit id
526 * RT_ERR_LA_TRUNK_ID - invalid trunk ID
527 * RT_ERR_NULL_POINTER - input parameter may be null pointer
528 * Note:
529 * Trunk group 0 & 1 shares the same hash mapping table.
530 * Trunk group 2 uses a independent table.
531 */
532 rtk_api_ret_t rtk_trunk_hashMappingTable_get(rtk_trunk_group_t trk_gid, rtk_trunk_hashVal2Port_t *pHash2Port_array)
533 {
534 rtk_api_ret_t retVal;
535 rtk_uint32 hashValue;
536 rtk_uint32 hashPort;
537
538 /* Check initialization state */
539 RTK_CHK_INIT_STATE();
540
541 /* Check Trunk Group Valid */
542 RTK_CHK_TRUNK_GROUP_VALID(trk_gid);
543
544 if(NULL == pHash2Port_array)
545 return RT_ERR_NULL_POINTER;
546
547 if(trk_gid <= TRUNK_GROUP1)
548 {
549 for(hashValue = 0; hashValue < RTK_MAX_NUM_OF_TRUNK_HASH_VAL; hashValue++)
550 {
551 if ((retVal = rtl8367c_getAsicTrunkingHashTable(hashValue, &hashPort)) != RT_ERR_OK)
552 return retVal;
553
554 pHash2Port_array->value[hashValue] = hashPort;
555 }
556 }
557 else
558 {
559 for(hashValue = 0; hashValue < RTK_MAX_NUM_OF_TRUNK_HASH_VAL; hashValue++)
560 {
561 if ((retVal = rtl8367c_getAsicTrunkingHashTable1(hashValue, &hashPort)) != RT_ERR_OK)
562 return retVal;
563
564 pHash2Port_array->value[hashValue] = hashPort;
565 }
566 }
567
568 return RT_ERR_OK;
569 }
570
571 /* Function Name:
572 * rtk_trunk_portQueueEmpty_get
573 * Description:
574 * Get the port mask which all queues are empty.
575 * Input:
576 * None.
577 * Output:
578 * pEmpty_portmask - pointer empty port mask
579 * Return:
580 * RT_ERR_OK
581 * RT_ERR_FAILED
582 * RT_ERR_NULL_POINTER - input parameter may be null pointer
583 * Note:
584 * None.
585 */
586 rtk_api_ret_t rtk_trunk_portQueueEmpty_get(rtk_portmask_t *pEmpty_portmask)
587 {
588 rtk_api_ret_t retVal;
589 rtk_uint32 pmask;
590
591 /* Check initialization state */
592 RTK_CHK_INIT_STATE();
593
594 if(NULL == pEmpty_portmask)
595 return RT_ERR_NULL_POINTER;
596
597 if ((retVal = rtl8367c_getAsicQeueuEmptyStatus(&pmask)) != RT_ERR_OK)
598 return retVal;
599
600 if ((retVal = rtk_switch_portmask_P2L_get(pmask, pEmpty_portmask)) != RT_ERR_OK)
601 return retVal;
602
603 return RT_ERR_OK;
604 }
605