aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-10-20 20:06:11 -0400
committerJeff Garzik <jeff@garzik.org>2006-10-21 14:08:24 -0400
commit470ea7eba4aaa517533f9b02ac9a104e77264548 (patch)
tree2726cf596e46f72e7ab54860a0589b2f858c5f21 /drivers
parent7347b03d25ad7d7f001373cf64f709457c6af618 (diff)
[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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sky2.c33
1 files changed, 12 insertions, 21 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 67ecd66f26d6..95efdb5bbbe1 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -699,16 +699,10 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
699 699
700} 700}
701 701
702/* Assign Ram Buffer allocation. 702/* Assign Ram Buffer allocation in units of 64bit (8 bytes) */
703 * start and end are in units of 4k bytes 703static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 end)
704 * ram registers are in units of 64bit words
705 */
706static void sky2_ramset(struct sky2_hw *hw, u16 q, u8 startk, u8 endk)
707{ 704{
708 u32 start, end; 705 pr_debug(PFX "q %d %#x %#x\n", q, start, end);
709
710 start = startk * 4096/8;
711 end = (endk * 4096/8) - 1;
712 706
713 sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); 707 sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
714 sky2_write32(hw, RB_ADDR(q, RB_START), start); 708 sky2_write32(hw, RB_ADDR(q, RB_START), start);
@@ -717,7 +711,7 @@ static void sky2_ramset(struct sky2_hw *hw, u16 q, u8 startk, u8 endk)
717 sky2_write32(hw, RB_ADDR(q, RB_RP), start); 711 sky2_write32(hw, RB_ADDR(q, RB_RP), start);
718 712
719 if (q == Q_R1 || q == Q_R2) { 713 if (q == Q_R1 || q == Q_R2) {
720 u32 space = (endk - startk) * 4096/8; 714 u32 space = end - start + 1;
721 u32 tp = space - space/4; 715 u32 tp = space - space/4;
722 716
723 /* On receive queue's set the thresholds 717 /* On receive queue's set the thresholds
@@ -1199,19 +1193,16 @@ static int sky2_up(struct net_device *dev)
1199 1193
1200 sky2_mac_init(hw, port); 1194 sky2_mac_init(hw, port);
1201 1195
1202 /* Determine available ram buffer space (in 4K blocks). 1196 /* Determine available ram buffer space in qwords. */
1203 * Note: not sure about the FE setting below yet 1197 ramsize = sky2_read8(hw, B2_E_0) * 4096/8;
1204 */
1205 if (hw->chip_id == CHIP_ID_YUKON_FE)
1206 ramsize = 4;
1207 else
1208 ramsize = sky2_read8(hw, B2_E_0);
1209 1198
1210 /* Give transmitter one third (rounded up) */ 1199 if (ramsize > 6*1024/8)
1211 rxspace = ramsize - (ramsize + 2) / 3; 1200 rxspace = ramsize - (ramsize + 2) / 3;
1201 else
1202 rxspace = ramsize / 2;
1212 1203
1213 sky2_ramset(hw, rxqaddr[port], 0, rxspace); 1204 sky2_ramset(hw, rxqaddr[port], 0, rxspace-1);
1214 sky2_ramset(hw, txqaddr[port], rxspace, ramsize); 1205 sky2_ramset(hw, txqaddr[port], rxspace, ramsize-1);
1215 1206
1216 /* Make sure SyncQ is disabled */ 1207 /* Make sure SyncQ is disabled */
1217 sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL), 1208 sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),