Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] sky2: 88E803X transmit lockup

The reason sky2 driver was locking up on transmit on the Yukon-FE chipset
is that it was misconfiguring the internal RAM buffer so the transmitter
and receiver were sharing the same space.

The code assumed there was 16K of RAM on Yukon-FE (taken from vendor driver
sk98lin which is even more f*cked up on this). Then it assigned based on that.
The giveaway was that the registers would only hold 9bits so both RX/TX
had 0..1ff for space. It is a wonder it worked at all!

This patch addresses this, and fixes an easily reproducible hang on Transmit.
Only the Yukon-FE chip is Marvell 88E803X (10/100 only) are affected.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>

authored by

Stephen Hemminger and committed by
Jeff Garzik
470ea7eb 7347b03d

+12 -21
+12 -21
drivers/net/sky2.c
··· 699 699 700 700 } 701 701 702 - /* Assign Ram Buffer allocation. 703 - * start and end are in units of 4k bytes 704 - * ram registers are in units of 64bit words 705 - */ 706 - static void sky2_ramset(struct sky2_hw *hw, u16 q, u8 startk, u8 endk) 702 + /* Assign Ram Buffer allocation in units of 64bit (8 bytes) */ 703 + static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 end) 707 704 { 708 - u32 start, end; 709 - 710 - start = startk * 4096/8; 711 - end = (endk * 4096/8) - 1; 705 + pr_debug(PFX "q %d %#x %#x\n", q, start, end); 712 706 713 707 sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); 714 708 sky2_write32(hw, RB_ADDR(q, RB_START), start); ··· 711 717 sky2_write32(hw, RB_ADDR(q, RB_RP), start); 712 718 713 719 if (q == Q_R1 || q == Q_R2) { 714 - u32 space = (endk - startk) * 4096/8; 720 + u32 space = end - start + 1; 715 721 u32 tp = space - space/4; 716 722 717 723 /* On receive queue's set the thresholds ··· 1193 1199 1194 1200 sky2_mac_init(hw, port); 1195 1201 1196 - /* Determine available ram buffer space (in 4K blocks). 1197 - * Note: not sure about the FE setting below yet 1198 - */ 1199 - if (hw->chip_id == CHIP_ID_YUKON_FE) 1200 - ramsize = 4; 1202 + /* Determine available ram buffer space in qwords. */ 1203 + ramsize = sky2_read8(hw, B2_E_0) * 4096/8; 1204 + 1205 + if (ramsize > 6*1024/8) 1206 + rxspace = ramsize - (ramsize + 2) / 3; 1201 1207 else 1202 - ramsize = sky2_read8(hw, B2_E_0); 1208 + rxspace = ramsize / 2; 1203 1209 1204 - /* Give transmitter one third (rounded up) */ 1205 - rxspace = ramsize - (ramsize + 2) / 3; 1206 - 1207 - sky2_ramset(hw, rxqaddr[port], 0, rxspace); 1208 - sky2_ramset(hw, txqaddr[port], rxspace, ramsize); 1210 + sky2_ramset(hw, rxqaddr[port], 0, rxspace-1); 1211 + sky2_ramset(hw, txqaddr[port], rxspace, ramsize-1); 1209 1212 1210 1213 /* Make sure SyncQ is disabled */ 1211 1214 sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),