@@ -427,6 +427,57 @@ void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze)
427
427
mutex_unlock (& p -> mib .cnt_mutex );
428
428
}
429
429
430
+ int ksz9477_errata_monitor (struct ksz_device * dev , int port ,
431
+ u64 tx_late_col )
432
+ {
433
+ u32 pmavbc ;
434
+ u8 status ;
435
+ u16 pqm ;
436
+ int ret ;
437
+
438
+ ret = ksz_pread8 (dev , port , REG_PORT_STATUS_0 , & status );
439
+ if (ret )
440
+ return ret ;
441
+ if (!(FIELD_GET (PORT_INTF_SPEED_MASK , status ) == PORT_INTF_SPEED_NONE ) &&
442
+ !(status & PORT_INTF_FULL_DUPLEX )) {
443
+ /* Errata DS80000754 recommends monitoring potential faults in
444
+ * half-duplex mode. The switch might not be able to communicate anymore
445
+ * in these states.
446
+ * If you see this message, please read the errata-sheet for more information:
447
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9477S-Errata-DS80000754.pdf
448
+ * To workaround this issue, half-duplex mode should be avoided.
449
+ * A software reset could be implemented to recover from this state.
450
+ */
451
+ dev_warn_once (dev -> dev ,
452
+ "Half-duplex detected on port %d, transmission halt may occur\n" ,
453
+ port );
454
+ if (tx_late_col != 0 ) {
455
+ /* Transmission halt with late collisions */
456
+ dev_crit_once (dev -> dev ,
457
+ "TX late collisions detected, transmission may be halted on port %d\n" ,
458
+ port );
459
+ }
460
+ ret = ksz_read8 (dev , REG_SW_LUE_CTRL_0 , & status );
461
+ if (ret )
462
+ return ret ;
463
+ if (status & SW_VLAN_ENABLE ) {
464
+ ret = ksz_pread16 (dev , port , REG_PORT_QM_TX_CNT_0__4 , & pqm );
465
+ if (ret )
466
+ return ret ;
467
+ ret = ksz_read32 (dev , REG_PMAVBC , & pmavbc );
468
+ if (ret )
469
+ return ret ;
470
+ if ((FIELD_GET (PMAVBC_MASK , pmavbc ) <= PMAVBC_MIN ) ||
471
+ (FIELD_GET (PORT_QM_TX_CNT_M , pqm ) >= PORT_QM_TX_CNT_MAX )) {
472
+ /* Transmission halt with Half-Duplex and VLAN */
473
+ dev_crit_once (dev -> dev ,
474
+ "resources out of limits, transmission may be halted\n" );
475
+ }
476
+ }
477
+ }
478
+ return ret ;
479
+ }
480
+
430
481
void ksz9477_port_init_cnt (struct ksz_device * dev , int port )
431
482
{
432
483
struct ksz_port_mib * mib = & dev -> ports [port ].mib ;
@@ -1297,6 +1348,10 @@ int ksz9477_setup(struct dsa_switch *ds)
1297
1348
/* Enable REG_SW_MTU__2 reg by setting SW_JUMBO_PACKET */
1298
1349
ksz_cfg (dev , REG_SW_MAC_CTRL_1 , SW_JUMBO_PACKET , true);
1299
1350
1351
+ /* Use collision based back pressure mode. */
1352
+ ksz_cfg (dev , REG_SW_MAC_CTRL_1 , SW_BACK_PRESSURE ,
1353
+ SW_BACK_PRESSURE_COLLISION );
1354
+
1300
1355
/* Now we can configure default MTU value */
1301
1356
ret = regmap_update_bits (ksz_regmap_16 (dev ), REG_SW_MTU__2 , REG_SW_MTU_MASK ,
1302
1357
VLAN_ETH_FRAME_LEN + ETH_FCS_LEN );
0 commit comments