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; }
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; }