mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-11-27 21:44:04 +02:00
ar71xx: add some code to detect DMA stuck conditions on ar7240
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@27975 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
5051a6677f
commit
db5c8f65ca
@ -589,6 +589,8 @@ void __init ar71xx_add_device_eth(unsigned int id)
|
|||||||
pdata->set_pll = id ? ar724x_set_pll_ge1
|
pdata->set_pll = id ? ar724x_set_pll_ge1
|
||||||
: ar724x_set_pll_ge0;
|
: ar724x_set_pll_ge0;
|
||||||
pdata->is_ar724x = 1;
|
pdata->is_ar724x = 1;
|
||||||
|
if (ar71xx_soc == AR71XX_SOC_AR7240)
|
||||||
|
pdata->is_ar7240 = 1;
|
||||||
|
|
||||||
if (!pdata->fifo_cfg1)
|
if (!pdata->fifo_cfg1)
|
||||||
pdata->fifo_cfg1 = 0x0010ffff;
|
pdata->fifo_cfg1 = 0x0010ffff;
|
||||||
|
@ -29,6 +29,7 @@ struct ag71xx_platform_data {
|
|||||||
|
|
||||||
u8 has_gbit:1;
|
u8 has_gbit:1;
|
||||||
u8 is_ar91xx:1;
|
u8 is_ar91xx:1;
|
||||||
|
u8 is_ar7240:1;
|
||||||
u8 is_ar724x:1;
|
u8 is_ar724x:1;
|
||||||
u8 has_ar8216:1;
|
u8 has_ar8216:1;
|
||||||
u8 has_ar7240_switch:1;
|
u8 has_ar7240_switch:1;
|
||||||
|
@ -236,6 +236,10 @@ static inline int ag71xx_desc_pktlen(struct ag71xx_desc *desc)
|
|||||||
#define AG71XX_REG_INT_ENABLE 0x0198
|
#define AG71XX_REG_INT_ENABLE 0x0198
|
||||||
#define AG71XX_REG_INT_STATUS 0x019c
|
#define AG71XX_REG_INT_STATUS 0x019c
|
||||||
|
|
||||||
|
#define AG71XX_REG_FIFO_DEPTH 0x01a8
|
||||||
|
#define AG71XX_REG_RX_SM 0x01b0
|
||||||
|
#define AG71XX_REG_TX_SM 0x01b4
|
||||||
|
|
||||||
#define MAC_CFG1_TXE BIT(0) /* Tx Enable */
|
#define MAC_CFG1_TXE BIT(0) /* Tx Enable */
|
||||||
#define MAC_CFG1_STX BIT(1) /* Synchronize Tx Enable */
|
#define MAC_CFG1_STX BIT(1) /* Synchronize Tx Enable */
|
||||||
#define MAC_CFG1_RXE BIT(2) /* Rx Enable */
|
#define MAC_CFG1_RXE BIT(2) /* Rx Enable */
|
||||||
|
@ -805,9 +805,33 @@ static void ag71xx_restart_work_func(struct work_struct *work)
|
|||||||
ag71xx_open(ag->dev);
|
ag71xx_open(ag->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ag71xx_check_dma_stuck(struct ag71xx *ag, unsigned long timestamp)
|
||||||
|
{
|
||||||
|
u32 rx_sm, tx_sm, rx_fd;
|
||||||
|
|
||||||
|
if (likely(time_before(jiffies, timestamp + HZ/10)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!netif_carrier_ok(ag->dev))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rx_sm = ag71xx_rr(ag, AG71XX_REG_RX_SM);
|
||||||
|
if ((rx_sm & 0x7) == 0x3 && ((rx_sm >> 4) & 0x7) == 0x6)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
tx_sm = ag71xx_rr(ag, AG71XX_REG_TX_SM);
|
||||||
|
rx_fd = ag71xx_rr(ag, AG71XX_REG_FIFO_DEPTH);
|
||||||
|
if (((tx_sm >> 4) & 0x7) == 0 && ((rx_sm & 0x7) == 0) &&
|
||||||
|
((rx_sm >> 4) & 0x7) == 0 && rx_fd == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int ag71xx_tx_packets(struct ag71xx *ag)
|
static int ag71xx_tx_packets(struct ag71xx *ag)
|
||||||
{
|
{
|
||||||
struct ag71xx_ring *ring = &ag->tx_ring;
|
struct ag71xx_ring *ring = &ag->tx_ring;
|
||||||
|
struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag);
|
||||||
int sent;
|
int sent;
|
||||||
|
|
||||||
DBG("%s: processing TX ring\n", ag->dev->name);
|
DBG("%s: processing TX ring\n", ag->dev->name);
|
||||||
@ -818,8 +842,12 @@ static int ag71xx_tx_packets(struct ag71xx *ag)
|
|||||||
struct ag71xx_desc *desc = ring->buf[i].desc;
|
struct ag71xx_desc *desc = ring->buf[i].desc;
|
||||||
struct sk_buff *skb = ring->buf[i].skb;
|
struct sk_buff *skb = ring->buf[i].skb;
|
||||||
|
|
||||||
if (!ag71xx_desc_empty(desc))
|
if (!ag71xx_desc_empty(desc)) {
|
||||||
|
if (pdata->is_ar7240 &&
|
||||||
|
ag71xx_check_dma_stuck(ag, ring->buf[i].timestamp))
|
||||||
|
schedule_work(&ag->restart_work);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS);
|
ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user