static int __exit ar2313_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); rx_tasklet_cleanup(dev); ar2313_init_cleanup(dev); unregister_netdev(dev); kfree(dev); return 0; }
static int ar2313_init(struct net_device *dev) { struct ar2313_private *sp = dev->priv; int ecode = 0; /* * Allocate descriptors */ if (ar2313_allocate_descriptors(dev)) { printk("%s: %s: ar2313_allocate_descriptors failed\n", dev->name, __FUNCTION__); ecode = -EAGAIN; goto init_error; } /* * Get the memory for the skb rings. */ if (sp->rx_skb == NULL) { sp->rx_skb = kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES, GFP_KERNEL); if (!(sp->rx_skb)) { printk("%s: %s: rx_skb kmalloc failed\n", dev->name, __FUNCTION__); ecode = -EAGAIN; goto init_error; } } memset(sp->rx_skb, 0, sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES); if (sp->tx_skb == NULL) { sp->tx_skb = kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES, GFP_KERNEL); if (!(sp->tx_skb)) { printk("%s: %s: tx_skb kmalloc failed\n", dev->name, __FUNCTION__); ecode = -EAGAIN; goto init_error; } } memset(sp->tx_skb, 0, sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES); /* * Set tx_csm before we start receiving interrupts, otherwise * the interrupt handler might think it is supposed to process * tx ints before we are up and running, which may cause a null * pointer access in the int handler. */ sp->rx_skbprd = 0; sp->cur_rx = 0; sp->tx_prd = 0; sp->tx_csm = 0; /* * Zero the stats before starting the interface */ memset(&sp->stats, 0, sizeof(sp->stats)); /* * We load the ring here as there seem to be no way to tell the * firmware to wipe the ring without re-initializing it. */ ar2313_load_rx_ring(dev, RX_RING_SIZE); /* * Init hardware */ ar2313_reset_reg(dev); setupADM(dev); /* * Get the IRQ */ ecode = request_irq(dev->irq, &ar2313_interrupt, IRQF_SHARED | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, dev->name, dev); if (ecode) { printk(KERN_WARNING "%s: %s: Requested IRQ %d is busy\n", dev->name, __FUNCTION__, dev->irq); goto init_error; } tasklet_enable(&sp->rx_tasklet); return 0; init_error: ar2313_init_cleanup(dev); return ecode; }
int __init ar2313_probe(struct platform_device *pdev) { struct net_device *dev; struct ar2313_private *sp; struct resource *res; unsigned long ar_eth_base; char buf[64]; dev = alloc_etherdev(sizeof(struct ar2313_private)); if (dev == NULL) { printk(KERN_ERR "ar2313: Unable to allocate net_device structure!\n"); return -ENOMEM; } platform_set_drvdata(pdev, dev); sp = netdev_priv(dev); sp->dev = dev; sp->cfg = pdev->dev.platform_data; sprintf(buf, "eth%d_membase", pdev->id); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, buf); if (!res) return -ENODEV; sp->link = 0; ar_eth_base = res->start; sp->phy = sp->cfg->phy; sprintf(buf, "eth%d_irq", pdev->id); dev->irq = platform_get_irq_byname(pdev, buf); spin_lock_init(&sp->lock); /* initialize func pointers */ dev->open = &ar2313_open; dev->stop = &ar2313_close; dev->hard_start_xmit = &ar2313_start_xmit; dev->set_multicast_list = &ar2313_multicast_list; #ifdef TX_TIMEOUT dev->tx_timeout = ar2313_tx_timeout; dev->watchdog_timeo = AR2313_TX_TIMEOUT; #endif dev->do_ioctl = &ar2313_ioctl; // SAMEER: do we need this? dev->features |= NETIF_F_HIGHDMA; tasklet_init(&sp->rx_tasklet, rx_tasklet_func, (unsigned long) dev); tasklet_disable(&sp->rx_tasklet); sp->eth_regs = ioremap_nocache(virt_to_phys(ar_eth_base), sizeof(*sp->eth_regs)); if (!sp->eth_regs) { printk("Can't remap eth registers\n"); return (-ENXIO); } /* * When there's only one MAC, PHY regs are typically on ENET0, * even though the MAC might be on ENET1. * Needto remap PHY regs separately in this case */ if (virt_to_phys(ar_eth_base) == virt_to_phys(sp->phy_regs)) sp->phy_regs = sp->eth_regs; else { sp->phy_regs = ioremap_nocache(virt_to_phys(sp->cfg->phy_base), sizeof(*sp->phy_regs)); if (!sp->phy_regs) { printk("Can't remap phy registers\n"); return (-ENXIO); } } sp->dma_regs = ioremap_nocache(virt_to_phys(ar_eth_base + 0x1000), sizeof(*sp->dma_regs)); dev->base_addr = (unsigned int) sp->dma_regs; if (!sp->dma_regs) { printk("Can't remap DMA registers\n"); return (-ENXIO); } sp->int_regs = ioremap_nocache(virt_to_phys(sp->cfg->reset_base), 4); if (!sp->int_regs) { printk("Can't remap INTERRUPT registers\n"); return (-ENXIO); } strncpy(sp->name, "Atheros AR231x", sizeof(sp->name) - 1); sp->name[sizeof(sp->name) - 1] = '\0'; memcpy(dev->dev_addr, sp->cfg->macaddr, 6); sp->board_idx = BOARD_IDX_STATIC; if (ar2313_init(dev)) { /* * ar2313_init() calls ar2313_init_cleanup() on error. */ kfree(dev); return -ENODEV; } if (register_netdev(dev)) { printk("%s: register_netdev failed\n", __func__); return -1; } printk("%s: %s: %02x:%02x:%02x:%02x:%02x:%02x, irq %d\n", dev->name, sp->name, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], dev->irq); sp->mii_bus.priv = dev; sp->mii_bus.read = mdiobus_read; sp->mii_bus.write = mdiobus_write; sp->mii_bus.reset = mdiobus_reset; sp->mii_bus.name = "ar2313_eth_mii"; sp->mii_bus.id = 0; sp->mii_bus.irq = kmalloc(sizeof(int), GFP_KERNEL); *sp->mii_bus.irq = PHY_POLL; mdiobus_register(&sp->mii_bus); if (mdiobus_probe(dev) != 0) { printk(KERN_ERR "ar2313: mdiobus_probe failed"); rx_tasklet_cleanup(dev); ar2313_init_cleanup(dev); unregister_netdev(dev); kfree(dev); } else { /* start link poll timer */ ar2313_setup_timer(dev); } return 0; }