@@ -82,6 +82,10 @@ static const u8 ksz_supported_apptrust[] = {
8282 IEEE_8021QAZ_APP_SEL_DSCP ,
8383};
8484
85+ static const u8 ksz8_port2_supported_apptrust [] = {
86+ DCB_APP_SEL_PCP ,
87+ };
88+
8589static const char * const ksz_supported_apptrust_variants [] = {
8690 "empty" , "dscp" , "pcp" , "dscp pcp"
8791};
@@ -181,6 +185,49 @@ int ksz_port_get_default_prio(struct dsa_switch *ds, int port)
181185 return (data & mask ) >> shift ;
182186}
183187
188+ /**
189+ * ksz88x3_port_set_default_prio_quirks - Quirks for default priority
190+ * @dev: Pointer to the KSZ switch device structure
191+ * @port: Port number for which to set the default priority
192+ * @prio: Priority value to set
193+ *
194+ * This function implements quirks for setting the default priority on KSZ88x3
195+ * devices. On Port 2, no other priority providers are working
196+ * except of PCP. So, configuring default priority on Port 2 is not possible.
197+ * On Port 1, it is not possible to configure port priority if PCP
198+ * apptrust on Port 2 is disabled. Since we disable multiple queues on the
199+ * switch to disable PCP on Port 2, we need to ensure that the default priority
200+ * configuration on Port 1 is in agreement with the configuration on Port 2.
201+ *
202+ * Return: 0 on success, or a negative error code on failure
203+ */
204+ static int ksz88x3_port_set_default_prio_quirks (struct ksz_device * dev , int port ,
205+ u8 prio )
206+ {
207+ if (!prio )
208+ return 0 ;
209+
210+ if (port == KSZ_PORT_2 ) {
211+ dev_err (dev -> dev , "Port priority configuration is not working on Port 2\n" );
212+ return - EINVAL ;
213+ } else if (port == KSZ_PORT_1 ) {
214+ u8 port2_data ;
215+ int ret ;
216+
217+ ret = ksz_pread8 (dev , KSZ_PORT_2 , KSZ8_REG_PORT_1_CTRL_0 ,
218+ & port2_data );
219+ if (ret )
220+ return ret ;
221+
222+ if (!(port2_data & KSZ8_PORT_802_1P_ENABLE )) {
223+ dev_err (dev -> dev , "Not possible to configur port priority on Port 1 if PCP apptrust on Port 2 is disabled\n" );
224+ return - EINVAL ;
225+ }
226+ }
227+
228+ return 0 ;
229+ }
230+
184231/**
185232 * ksz_port_set_default_prio - Sets the default priority for a port on a KSZ
186233 * switch
@@ -196,12 +243,18 @@ int ksz_port_get_default_prio(struct dsa_switch *ds, int port)
196243int ksz_port_set_default_prio (struct dsa_switch * ds , int port , u8 prio )
197244{
198245 struct ksz_device * dev = ds -> priv ;
199- int reg , shift ;
246+ int reg , shift , ret ;
200247 u8 mask ;
201248
202249 if (prio >= dev -> info -> num_ipvs )
203250 return - EINVAL ;
204251
252+ if (ksz_is_ksz88x3 (dev )) {
253+ ret = ksz88x3_port_set_default_prio_quirks (dev , port , prio );
254+ if (ret )
255+ return ret ;
256+ }
257+
205258 ksz_get_default_port_prio_reg (dev , & reg , & mask , & shift );
206259
207260 return ksz_prmw8 (dev , port , reg , mask , (prio << shift ) & mask );
@@ -408,6 +461,155 @@ static int ksz_port_set_apptrust_validate(struct ksz_device *dev, int port,
408461 return - EINVAL ;
409462}
410463
464+ /**
465+ * ksz88x3_port1_apptrust_quirk - Quirk for apptrust configuration on Port 1
466+ * of KSZ88x3 devices
467+ * @dev: Pointer to the KSZ switch device structure
468+ * @port: Port number for which to set the apptrust selectors
469+ * @reg: Register address for the apptrust configuration
470+ * @port1_data: Data to set for the apptrust configuration
471+ *
472+ * This function implements a quirk for apptrust configuration on Port 1 of
473+ * KSZ88x3 devices. It ensures that apptrust configuration on Port 1 is not
474+ * possible if PCP apptrust on Port 2 is disabled. This is because the Port 2
475+ * seems to be permanently hardwired to PCP classification, so we need to
476+ * do Port 1 configuration always in agreement with Port 2 configuration.
477+ *
478+ * Return: 0 on success, or a negative error code on failure
479+ */
480+ static int ksz88x3_port1_apptrust_quirk (struct ksz_device * dev , int port ,
481+ int reg , u8 port1_data )
482+ {
483+ u8 port2_data ;
484+ int ret ;
485+
486+ /* If no apptrust is requested for Port 1, no need to care about Port 2
487+ * configuration.
488+ */
489+ if (!(port1_data & (KSZ8_PORT_802_1P_ENABLE | KSZ8_PORT_DIFFSERV_ENABLE )))
490+ return 0 ;
491+
492+ /* We got request to enable any apptrust on Port 1. To make it possible,
493+ * we need to enable multiple queues on the switch. If we enable
494+ * multiqueue support, PCP classification on Port 2 will be
495+ * automatically activated by HW.
496+ */
497+ ret = ksz_pread8 (dev , KSZ_PORT_2 , reg , & port2_data );
498+ if (ret )
499+ return ret ;
500+
501+ /* If KSZ8_PORT_802_1P_ENABLE bit is set on Port 2, the driver showed
502+ * the interest in PCP classification on Port 2. In this case,
503+ * multiqueue support is enabled and we can enable any apptrust on
504+ * Port 1.
505+ * If KSZ8_PORT_802_1P_ENABLE bit is not set on Port 2, the PCP
506+ * classification on Port 2 is still active, but the driver disabled
507+ * multiqueue support and made frame prioritization inactive for
508+ * all ports. In this case, we can't enable any apptrust on Port 1.
509+ */
510+ if (!(port2_data & KSZ8_PORT_802_1P_ENABLE )) {
511+ dev_err (dev -> dev , "Not possible to enable any apptrust on Port 1 if PCP apptrust on Port 2 is disabled\n" );
512+ return - EINVAL ;
513+ }
514+
515+ return 0 ;
516+ }
517+
518+ /**
519+ * ksz88x3_port2_apptrust_quirk - Quirk for apptrust configuration on Port 2
520+ * of KSZ88x3 devices
521+ * @dev: Pointer to the KSZ switch device structure
522+ * @port: Port number for which to set the apptrust selectors
523+ * @reg: Register address for the apptrust configuration
524+ * @port2_data: Data to set for the apptrust configuration
525+ *
526+ * This function implements a quirk for apptrust configuration on Port 2 of
527+ * KSZ88x3 devices. It ensures that DSCP apptrust is not working on Port 2 and
528+ * that it is not possible to disable PCP on Port 2. The only way to disable PCP
529+ * on Port 2 is to disable multiple queues on the switch.
530+ *
531+ * Return: 0 on success, or a negative error code on failure
532+ */
533+ static int ksz88x3_port2_apptrust_quirk (struct ksz_device * dev , int port ,
534+ int reg , u8 port2_data )
535+ {
536+ struct dsa_switch * ds = dev -> ds ;
537+ u8 port1_data ;
538+ int ret ;
539+
540+ /* First validate Port 2 configuration. DiffServ/DSCP is not working
541+ * on this port.
542+ */
543+ if (port2_data & KSZ8_PORT_DIFFSERV_ENABLE ) {
544+ dev_err (dev -> dev , "DSCP apptrust is not working on Port 2\n" );
545+ return - EINVAL ;
546+ }
547+
548+ /* If PCP support is requested, we need to enable all queues on the
549+ * switch to make PCP priority working on Port 2.
550+ */
551+ if (port2_data & KSZ8_PORT_802_1P_ENABLE )
552+ return ksz8_all_queues_split (dev , dev -> info -> num_tx_queues );
553+
554+ /* We got request to disable PCP priority on Port 2.
555+ * Now, we need to compare Port 2 configuration with Port 1
556+ * configuration.
557+ */
558+ ret = ksz_pread8 (dev , KSZ_PORT_1 , reg , & port1_data );
559+ if (ret )
560+ return ret ;
561+
562+ /* If Port 1 has any apptrust enabled, we can't disable multiple queues
563+ * on the switch, so we can't disable PCP on Port 2.
564+ */
565+ if (port1_data & (KSZ8_PORT_802_1P_ENABLE | KSZ8_PORT_DIFFSERV_ENABLE )) {
566+ dev_err (dev -> dev , "Not possible to disable PCP on Port 2 if any apptrust is enabled on Port 1\n" );
567+ return - EINVAL ;
568+ }
569+
570+ /* Now we need to ensure that default priority on Port 1 is set to 0
571+ * otherwise we can't disable multiqueue support on the switch.
572+ */
573+ ret = ksz_port_get_default_prio (ds , KSZ_PORT_1 );
574+ if (ret < 0 ) {
575+ return ret ;
576+ } else if (ret ) {
577+ dev_err (dev -> dev , "Not possible to disable PCP on Port 2 if non zero default priority is set on Port 1\n" );
578+ return - EINVAL ;
579+ }
580+
581+ /* Port 1 has no apptrust or default priority set and we got request to
582+ * disable PCP on Port 2. We can disable multiqueue support to disable
583+ * PCP on Port 2.
584+ */
585+ return ksz8_all_queues_split (dev , 1 );
586+ }
587+
588+ /**
589+ * ksz88x3_port_apptrust_quirk - Quirk for apptrust configuration on KSZ88x3
590+ * devices
591+ * @dev: Pointer to the KSZ switch device structure
592+ * @port: Port number for which to set the apptrust selectors
593+ * @reg: Register address for the apptrust configuration
594+ * @data: Data to set for the apptrust configuration
595+ *
596+ * This function implements a quirk for apptrust configuration on KSZ88x3
597+ * devices. It ensures that apptrust configuration on Port 1 and
598+ * Port 2 is done in agreement with each other.
599+ *
600+ * Return: 0 on success, or a negative error code on failure
601+ */
602+ static int ksz88x3_port_apptrust_quirk (struct ksz_device * dev , int port ,
603+ int reg , u8 data )
604+ {
605+ if (port == KSZ_PORT_1 )
606+ return ksz88x3_port1_apptrust_quirk (dev , port , reg , data );
607+ else if (port == KSZ_PORT_2 )
608+ return ksz88x3_port2_apptrust_quirk (dev , port , reg , data );
609+
610+ return 0 ;
611+ }
612+
411613/**
412614 * ksz_port_set_apptrust - Sets the apptrust selectors for a port on a KSZ
413615 * switch
@@ -448,6 +650,12 @@ int ksz_port_set_apptrust(struct dsa_switch *ds, int port,
448650 }
449651 }
450652
653+ if (ksz_is_ksz88x3 (dev )) {
654+ ret = ksz88x3_port_apptrust_quirk (dev , port , reg , data );
655+ if (ret )
656+ return ret ;
657+ }
658+
451659 return ksz_prmw8 (dev , port , reg , mask , data );
452660}
453661
@@ -502,7 +710,9 @@ int ksz_port_get_apptrust(struct dsa_switch *ds, int port, u8 *sel, int *nsel)
502710 */
503711int ksz_dcb_init_port (struct ksz_device * dev , int port )
504712{
713+ const u8 * sel ;
505714 int ret , ipv ;
715+ int sel_len ;
506716
507717 if (is_ksz8 (dev )) {
508718 ipv = ieee8021q_tt_to_tc (IEEE8021Q_TT_BE ,
@@ -518,8 +728,18 @@ int ksz_dcb_init_port(struct ksz_device *dev, int port)
518728 if (ret )
519729 return ret ;
520730
521- return ksz_port_set_apptrust (dev -> ds , port , ksz_supported_apptrust ,
522- ARRAY_SIZE (ksz_supported_apptrust ));
731+ if (ksz_is_ksz88x3 (dev ) && port == KSZ_PORT_2 ) {
732+ /* KSZ88x3 devices do not support DSCP classification on
733+ * "Port 2.
734+ */
735+ sel = ksz8_port2_supported_apptrust ;
736+ sel_len = ARRAY_SIZE (ksz8_port2_supported_apptrust );
737+ } else {
738+ sel = ksz_supported_apptrust ;
739+ sel_len = ARRAY_SIZE (ksz_supported_apptrust );
740+ }
741+
742+ return ksz_port_set_apptrust (dev -> ds , port , sel , sel_len );
523743}
524744
525745/**
0 commit comments