/** Poll for completed and received packets * * @v netdev Network device */ static void b44_poll(struct net_device *netdev) { struct b44_private *bp = netdev_priv(netdev); u32 istat; /* Interrupt status */ istat = br32(bp, B44_ISTAT); istat &= IMASK_DEF; /* only the events we care about */ if (!istat) return; if (istat & ISTAT_TX) b44_tx_complete(bp); if (istat & ISTAT_RX) b44_process_rx_packets(bp); if (istat & ISTAT_ERRORS) { DBG("b44 error istat=0x%08x\n", istat); /* Reset B44 core partially to avoid long waits */ b44_irq(bp->netdev, 0); b44_halt(bp); b44_init_tx_ring(bp); b44_init_rx_ring(bp); b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY); } /* Acknowledge interrupt */ bw32(bp, B44_ISTAT, 0); bflush(bp, B44_ISTAT, 1); }
static int b44_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) { struct b44 *bp = netdev_priv(dev); spin_lock_irq(&bp->lock); if (epause->autoneg) bp->flags |= B44_FLAG_PAUSE_AUTO; else bp->flags &= ~B44_FLAG_PAUSE_AUTO; if (epause->rx_pause) bp->flags |= B44_FLAG_RX_PAUSE; else bp->flags &= ~B44_FLAG_RX_PAUSE; if (epause->tx_pause) bp->flags |= B44_FLAG_TX_PAUSE; else bp->flags &= ~B44_FLAG_TX_PAUSE; if (bp->flags & B44_FLAG_PAUSE_AUTO) { b44_halt(bp); b44_init_rings(bp); b44_init_hw(bp); } else { __b44_set_flow_ctrl(bp, bp->flags); } spin_unlock_irq(&bp->lock); b44_enable_ints(bp); return 0; }
static int b44_change_mtu(struct net_device *dev, int new_mtu) { struct b44 *bp = netdev_priv(dev); if (new_mtu < B44_MIN_MTU || new_mtu > B44_MAX_MTU) return -EINVAL; if (!netif_running(dev)) { /* We'll just catch it later when the * device is up'd. */ dev->mtu = new_mtu; return 0; } spin_lock_irq(&bp->lock); b44_halt(bp); dev->mtu = new_mtu; b44_init_rings(bp); b44_init_hw(bp); spin_unlock_irq(&bp->lock); b44_enable_ints(bp); return 0; }
static int b44_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { struct b44 *bp = netdev_priv(dev); if ((ering->rx_pending > B44_RX_RING_SIZE - 1) || (ering->rx_mini_pending != 0) || (ering->rx_jumbo_pending != 0) || (ering->tx_pending > B44_TX_RING_SIZE - 1)) return -EINVAL; spin_lock_irq(&bp->lock); bp->rx_pending = ering->rx_pending; bp->tx_pending = ering->tx_pending; b44_halt(bp); b44_init_rings(bp); b44_init_hw(bp); netif_wake_queue(bp->dev); spin_unlock_irq(&bp->lock); b44_enable_ints(bp); return 0; }
static int b44_close(struct net_device *dev) { struct b44 *bp = netdev_priv(dev); netif_stop_queue(dev); del_timer_sync(&bp->timer); spin_lock_irq(&bp->lock); #if 0 b44_dump_state(bp); #endif b44_halt(bp); b44_free_rings(bp); bp->flags &= ~B44_FLAG_INIT_COMPLETE; netif_carrier_off(bp->dev); spin_unlock_irq(&bp->lock); free_irq(dev->irq, dev); b44_free_consistent(bp); return 0; }
static int b44_poll(struct net_device *netdev, int *budget) { struct b44 *bp = netdev_priv(netdev); int done; spin_lock_irq(&bp->lock); if (bp->istat & (ISTAT_TX | ISTAT_TO)) { /* spin_lock(&bp->tx_lock); */ b44_tx(bp); /* spin_unlock(&bp->tx_lock); */ } spin_unlock_irq(&bp->lock); done = 1; if (bp->istat & ISTAT_RX) { int orig_budget = *budget; int work_done; if (orig_budget > netdev->quota) orig_budget = netdev->quota; work_done = b44_rx(bp, orig_budget); *budget -= work_done; netdev->quota -= work_done; if (work_done >= orig_budget) done = 0; } if (bp->istat & ISTAT_ERRORS) { spin_lock_irq(&bp->lock); b44_halt(bp); b44_init_rings(bp); b44_init_hw(bp); netif_wake_queue(bp->dev); spin_unlock_irq(&bp->lock); done = 1; } if (done) { netif_rx_complete(netdev); b44_enable_ints(bp); } return (done ? 0 : 1); }
static void b44_tx_timeout(struct net_device *dev) { struct b44 *bp = netdev_priv(dev); printk(KERN_ERR PFX "%s: transmit timed out, resetting\n", dev->name); spin_lock_irq(&bp->lock); b44_halt(bp); b44_init_rings(bp); b44_init_hw(bp); spin_unlock_irq(&bp->lock); b44_enable_ints(bp); netif_wake_queue(dev); }
static int b44_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); struct b44 *bp = dev->priv; if (!netif_running(dev)) return 0; del_timer_sync(&bp->timer); spin_lock_irq(&bp->lock); b44_halt(bp); netif_carrier_off(bp->dev); netif_device_detach(bp->dev); b44_free_rings(bp); spin_unlock_irq(&bp->lock); return 0; }