aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/skge.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-10-16 15:15:49 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-16 21:10:28 -0400
commit7fb7ac241162dc51ec0f7644d4a97b2855213c32 (patch)
treef16d164d20f4335a0f9fffd768b57cc18d68f932 /drivers/net/skge.c
parent298e1a9ebe37662f2145c07b678ebd09b86c020a (diff)
skge: fix ram buffer size calculation
This fixes problems with transmit hangs on older fiber based SysKonnect boards. Adjust ram buffer sizing calculation to make it correct on all boards and make it like the code in sky2 driver. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r--drivers/net/skge.c51
1 files changed, 24 insertions, 27 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 2aae9fe38c5a..e593585f8bf7 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -2403,32 +2403,31 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
2403 return err; 2403 return err;
2404} 2404}
2405 2405
2406static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len) 2406/* Assign Ram Buffer allocation to queue */
2407static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, u32 space)
2407{ 2408{
2408 u32 end; 2409 u32 end;
2409 2410
2410 start /= 8; 2411 /* convert from K bytes to qwords used for hw register */
2411 len /= 8; 2412 start *= 1024/8;
2412 end = start + len - 1; 2413 space *= 1024/8;
2414 end = start + space - 1;
2413 2415
2414 skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); 2416 skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
2415 skge_write32(hw, RB_ADDR(q, RB_START), start); 2417 skge_write32(hw, RB_ADDR(q, RB_START), start);
2418 skge_write32(hw, RB_ADDR(q, RB_END), end);
2416 skge_write32(hw, RB_ADDR(q, RB_WP), start); 2419 skge_write32(hw, RB_ADDR(q, RB_WP), start);
2417 skge_write32(hw, RB_ADDR(q, RB_RP), start); 2420 skge_write32(hw, RB_ADDR(q, RB_RP), start);
2418 skge_write32(hw, RB_ADDR(q, RB_END), end);
2419 2421
2420 if (q == Q_R1 || q == Q_R2) { 2422 if (q == Q_R1 || q == Q_R2) {
2423 u32 tp = space - space/4;
2424
2421 /* Set thresholds on receive queue's */ 2425 /* Set thresholds on receive queue's */
2422 skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), 2426 skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
2423 start + (2*len)/3); 2427 skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
2424 skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), 2428 } else if (hw->chip_id != CHIP_ID_GENESIS)
2425 start + (len/3)); 2429 /* Genesis Tx Fifo is too small for normal store/forward */
2426 } else {
2427 /* Enable store & forward on Tx queue's because
2428 * Tx FIFO is only 4K on Genesis and 1K on Yukon
2429 */
2430 skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD); 2430 skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD);
2431 }
2432 2431
2433 skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD); 2432 skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD);
2434} 2433}
@@ -2456,7 +2455,7 @@ static int skge_up(struct net_device *dev)
2456 struct skge_port *skge = netdev_priv(dev); 2455 struct skge_port *skge = netdev_priv(dev);
2457 struct skge_hw *hw = skge->hw; 2456 struct skge_hw *hw = skge->hw;
2458 int port = skge->port; 2457 int port = skge->port;
2459 u32 chunk, ram_addr; 2458 u32 ramaddr, ramsize, rxspace;
2460 size_t rx_size, tx_size; 2459 size_t rx_size, tx_size;
2461 int err; 2460 int err;
2462 2461
@@ -2511,14 +2510,15 @@ static int skge_up(struct net_device *dev)
2511 spin_unlock_bh(&hw->phy_lock); 2510 spin_unlock_bh(&hw->phy_lock);
2512 2511
2513 /* Configure RAMbuffers */ 2512 /* Configure RAMbuffers */
2514 chunk = hw->ram_size / ((hw->ports + 1)*2); 2513 ramsize = (hw->ram_size - hw->ram_offset) / hw->ports;
2515 ram_addr = hw->ram_offset + 2 * chunk * port; 2514 ramaddr = hw->ram_offset + port * ramsize;
2515 rxspace = 8 + (2*(ramsize - 16))/3;
2516 2516
2517 skge_ramset(hw, rxqaddr[port], ram_addr, chunk); 2517 skge_ramset(hw, rxqaddr[port], ramaddr, rxspace);
2518 skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean); 2518 skge_ramset(hw, txqaddr[port], ramaddr + rxspace, ramsize - rxspace);
2519 2519
2520 skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean);
2520 BUG_ON(skge->tx_ring.to_use != skge->tx_ring.to_clean); 2521 BUG_ON(skge->tx_ring.to_use != skge->tx_ring.to_clean);
2521 skge_ramset(hw, txqaddr[port], ram_addr+chunk, chunk);
2522 skge_qset(skge, txqaddr[port], skge->tx_ring.to_use); 2522 skge_qset(skge, txqaddr[port], skge->tx_ring.to_use);
2523 2523
2524 /* Start receiver BMU */ 2524 /* Start receiver BMU */
@@ -3450,15 +3450,12 @@ static int skge_reset(struct skge_hw *hw)
3450 if (hw->chip_id == CHIP_ID_GENESIS) { 3450 if (hw->chip_id == CHIP_ID_GENESIS) {
3451 if (t8 == 3) { 3451 if (t8 == 3) {
3452 /* special case: 4 x 64k x 36, offset = 0x80000 */ 3452 /* special case: 4 x 64k x 36, offset = 0x80000 */
3453 hw->ram_size = 0x100000; 3453 hw->ram_size = 1024;
3454 hw->ram_offset = 0x80000; 3454 hw->ram_offset = 512;
3455 } else 3455 } else
3456 hw->ram_size = t8 * 512; 3456 hw->ram_size = t8 * 512;
3457 } 3457 } else /* Yukon */
3458 else if (t8 == 0) 3458 hw->ram_size = t8 ? t8 * 4 : 128;
3459 hw->ram_size = 0x20000;
3460 else
3461 hw->ram_size = t8 * 4096;
3462 3459
3463 hw->intr_mask = IS_HW_ERR; 3460 hw->intr_mask = IS_HW_ERR;
3464 3461