static void cpsw_ndo_tx_timeout(struct net_device *ndev) { struct cpsw_priv *priv = netdev_priv(ndev); cpsw_err(priv, tx_err, "transmit timeout, restarting dma\n"); priv->stats.tx_errors++; cpsw_intr_disable(priv); cpdma_ctlr_int_ctrl(priv->dma, false); cpdma_chan_stop(priv->txch); cpdma_chan_start(priv->txch); cpdma_ctlr_int_ctrl(priv->dma, true); cpsw_intr_enable(priv); cpdma_ctlr_eoi(priv->dma); }
int cpdma_ctlr_start(struct cpdma_ctlr *ctlr) { unsigned long flags; int i; spin_lock_irqsave(&ctlr->lock, flags); if (ctlr->state != CPDMA_STATE_IDLE) { spin_unlock_irqrestore(&ctlr->lock, flags); return -EBUSY; } if (ctlr->params.has_soft_reset) { unsigned timeout = 10 * 100; dma_reg_write(ctlr, CPDMA_SOFTRESET, 1); while (timeout) { if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0) break; udelay(10); timeout--; } WARN_ON(!timeout); } for (i = 0; i < ctlr->num_chan; i++) { __raw_writel(0, ctlr->params.txhdp + 4 * i); __raw_writel(0, ctlr->params.rxhdp + 4 * i); __raw_writel(0, ctlr->params.txcp + 4 * i); __raw_writel(0, ctlr->params.rxcp + 4 * i); } dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); dma_reg_write(ctlr, CPDMA_TXCONTROL, 1); dma_reg_write(ctlr, CPDMA_RXCONTROL, 1); ctlr->state = CPDMA_STATE_ACTIVE; for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { if (ctlr->channels[i]) cpdma_chan_start(ctlr->channels[i]); } spin_unlock_irqrestore(&ctlr->lock, flags); return 0; }
int cpdma_ctlr_start(struct cpdma_ctlr *ctlr) { rtdm_lockctx_t context; int i; rtdm_lock_get_irqsave(&ctlr->lock, context); if (ctlr->state != CPDMA_STATE_IDLE) { rtdm_lock_put_irqrestore(&ctlr->lock, context); return -EBUSY; } if (ctlr->params.has_soft_reset) { unsigned long timeout = jiffies + HZ/10; dma_reg_write(ctlr, CPDMA_SOFTRESET, 1); while (time_before(jiffies, timeout)) { if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0) break; } WARN_ON(!time_before(jiffies, timeout)); } for (i = 0; i < ctlr->num_chan; i++) { __raw_writel(0, ctlr->params.txhdp + 4 * i); __raw_writel(0, ctlr->params.rxhdp + 4 * i); __raw_writel(0, ctlr->params.txcp + 4 * i); __raw_writel(0, ctlr->params.rxcp + 4 * i); } dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); dma_reg_write(ctlr, CPDMA_TXCONTROL, 1); dma_reg_write(ctlr, CPDMA_RXCONTROL, 1); ctlr->state = CPDMA_STATE_ACTIVE; for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { if (ctlr->channels[i]) cpdma_chan_start(ctlr->channels[i]); } rtdm_lock_put_irqrestore(&ctlr->lock, context); return 0; }