/* Transmit buffers */
struct sk_buff *tx_skb[TX_RING_SIZE];
+ dma_addr_t tx_addr;
unsigned int valid_txskb[TX_RING_SIZE];
unsigned int cur_tx;
unsigned int dma_tx;
/* Receive buffers */
struct sk_buff *rx_skb[RX_RING_SIZE];
+ dma_addr_t rx_addr;
unsigned int irq_rxskb[RX_RING_SIZE];
int pkt_len[RX_RING_SIZE];
unsigned int cur_rx;
static int nuport_mac_start_tx_dma(struct nuport_mac_priv *priv,
struct sk_buff *skb)
{
- dma_addr_t p;
u32 reg;
unsigned int timeout = 2048;
if (!timeout)
return -EBUSY;
- p = dma_map_single(&priv->pdev->dev, skb->data,
+ priv->tx_addr = dma_map_single(&priv->pdev->dev, skb->data,
skb->len, DMA_TO_DEVICE);
+ if (!priv->tx_addr)
+ return -ENOMEM;
/* enable enhanced mode */
nuport_mac_writel(TX_DMA_ENH_ENABLE, TX_DMA_ENH);
- nuport_mac_writel(p, TX_BUFFER_ADDR);
+ nuport_mac_writel(priv->tx_addr, TX_BUFFER_ADDR);
nuport_mac_writel((skb->len) - 1, TX_PKT_BYTES);
wmb();
reg = TX_DMA_ENABLE | TX_DMA_START_FRAME | TX_DMA_END_FRAME;
static int nuport_mac_start_rx_dma(struct nuport_mac_priv *priv,
struct sk_buff *skb)
{
- dma_addr_t p;
u32 reg;
unsigned int timeout = 2048;
if (!timeout)
return -EBUSY;
- p = dma_map_single(&priv->pdev->dev, skb->data,
+ priv->rx_addr = dma_map_single(&priv->pdev->dev, skb->data,
RX_ALLOC_SIZE, DMA_FROM_DEVICE);
+ if (!priv->rx_addr)
+ return -ENOMEM;
- nuport_mac_writel(p, RX_BUFFER_ADDR);
+ nuport_mac_writel(priv->rx_addr, RX_BUFFER_ADDR);
wmb();
nuport_mac_writel(RX_DMA_ENABLE, RX_START_DMA);
struct nuport_mac_priv *priv = netdev_priv(dev);
u32 reg;
u8 phy_addr;
+ unsigned long flags;
+ irqreturn_t ret = IRQ_HANDLED;
+ spin_lock_irqsave(&priv->lock, flags);
reg = nuport_mac_readl(LINK_INT_CSR);
phy_addr = (reg >> LINK_PHY_ADDR_SHIFT) & (PHY_MAX_ADDR - 1);
if (phy_addr != priv->phydev->addr) {
netdev_err(dev, "spurious PHY irq (phy: %d)\n", phy_addr);
- return IRQ_NONE;
+ ret = IRQ_NONE;
+ goto out;
}
priv->phydev->link = (reg & LINK_UP);
nuport_mac_adjust_link(dev);
- return IRQ_HANDLED;
+out:
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return ret;
}
static irqreturn_t nuport_mac_tx_interrupt(int irq, void *dev_id)
skb = priv->tx_skb[priv->dma_tx];
priv->tx_skb[priv->dma_tx] = NULL;
priv->valid_txskb[priv->dma_tx] = 0;
+ dma_unmap_single(&priv->pdev->dev, priv->rx_addr, skb->len,
+ DMA_TO_DEVICE);
dev_kfree_skb_irq(skb);
priv->dma_tx++;
status = get_unaligned((u32 *) (skb->data + len));
skb->dev = dev;
+ dma_unmap_single(&priv->pdev->dev, priv->rx_addr, skb->len,
+ DMA_FROM_DEVICE);
+
/* packet filter failed */
if (!(status & (1 << 30))) {
dev_kfree_skb_irq(skb);
phydev->supported &= PHY_BASIC_FEATURES;
phydev->advertising = phydev->supported;
priv->phydev = phydev;
- priv->old_link = 0;
- priv->old_duplex = -1;
+ priv->old_link = 1;
+ priv->old_duplex = DUPLEX_FULL;
dev_info(&priv->pdev->dev, "attached PHY driver [%s] "
"(mii_bus:phy_addr=%d)\n",