Browse Source

Fix issue #78 with patch from upstream commit d40a358136fdc19e6af13921867ed93444c08827

The rx ring buffer can stall on small packets on QCA953x and
QCA956x. Disabling the inline checksum engine fixes the stall.
The wr, rr functions cannot be used since this hidden register
is outside of the normal ag71xx register block.
RISCi_ATOM 5 years ago
parent
commit
9ce7a9d33a

+ 5 - 0
target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c

@@ -975,6 +975,9 @@ void __init ath79_register_eth(unsigned int id)
 			pdata->reset_bit = AR934X_RESET_GE0_MAC |
 					   AR934X_RESET_GE0_MDIO;
 			pdata->set_speed = ar934x_set_speed_ge0;
+
+			if (ath79_soc == ATH79_SOC_QCA9533)
+				pdata->disable_inline_checksum_engine = 1;
 		} else {
 			pdata->reset_bit = AR934X_RESET_GE1_MAC |
 					   AR934X_RESET_GE1_MDIO;
@@ -1076,6 +1079,8 @@ void __init ath79_register_eth(unsigned int id)
 				pdata->set_speed = qca956x_set_speed_sgmii;
 			else
 				pdata->set_speed = ar934x_set_speed_ge0;
+
+			pdata->disable_inline_checksum_engine = 1;
 		} else {
 			pdata->reset_bit = QCA955X_RESET_GE1_MAC |
 					   QCA955X_RESET_GE1_MDIO;

+ 1 - 0
target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h

@@ -37,6 +37,7 @@ struct ag71xx_platform_data {
 	u8		is_ar724x:1;
 	u8		has_ar8216:1;
 	u8		use_flow_control:1;
+	u8		disable_inline_checksum_engine:1;
 
 	struct ag71xx_switch_platform_data *switch_data;
 

+ 16 - 0
target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c

@@ -629,6 +629,22 @@ __ag71xx_link_adjust(struct ag71xx *ag, bool update)
 	ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2);
 	ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5);
 	ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl);
+
+	if (pdata->disable_inline_checksum_engine) {
+		/*
+		 * The rx ring buffer can stall on small packets on QCA953x and
+		 * QCA956x. Disabling the inline checksum engine fixes the stall.
+		 * The wr, rr functions cannot be used since this hidden register
+		 * is outside of the normal ag71xx register block.
+		 */
+		void __iomem *dam = ioremap_nocache(0xb90001bc, 0x4);
+		if (dam) {
+			__raw_writel(__raw_readl(dam) & ~BIT(27), dam);
+			(void)__raw_readl(dam);
+			iounmap(dam);
+		}
+	}
+
 	ag71xx_hw_start(ag);
 
 	netif_carrier_on(ag->dev);