static int __exit ag71xx_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); if (dev) { struct ag71xx *ag = netdev_priv(dev); ag71xx_phy_disconnect(ag); unregister_netdev(dev); free_irq(dev->irq, dev); iounmap(ag->mii_ctrl); iounmap(ag->mac_base2); iounmap(ag->mac_base); kfree(dev); platform_set_drvdata(pdev, NULL); } return 0; }
static int __init ag71xx_probe(struct platform_device *pdev) { struct net_device *dev; struct resource *res; struct ag71xx *ag; struct ag71xx_platform_data *pdata; int err; pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "no platform data specified\n"); err = -ENXIO; goto err_out; } if (pdata->mii_bus_dev == NULL) { dev_err(&pdev->dev, "no MII bus device specified\n"); err = -EINVAL; goto err_out; } dev = alloc_etherdev(sizeof(*ag)); if (!dev) { dev_err(&pdev->dev, "alloc_etherdev failed\n"); err = -ENOMEM; goto err_out; } SET_NETDEV_DEV(dev, &pdev->dev); ag = netdev_priv(dev); ag->pdev = pdev; ag->dev = dev; ag->msg_enable = netif_msg_init(ag71xx_msg_level, AG71XX_DEFAULT_MSG_ENABLE); spin_lock_init(&ag->lock); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac_base"); if (!res) { dev_err(&pdev->dev, "no mac_base resource found\n"); err = -ENXIO; goto err_out; } ag->mac_base = ioremap_nocache(res->start, res->end - res->start + 1); if (!ag->mac_base) { dev_err(&pdev->dev, "unable to ioremap mac_base\n"); err = -ENOMEM; goto err_free_dev; } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mii_ctrl"); if (!res) { dev_err(&pdev->dev, "no mii_ctrl resource found\n"); err = -ENXIO; goto err_unmap_base; } ag->mii_ctrl = ioremap_nocache(res->start, res->end - res->start + 1); if (!ag->mii_ctrl) { dev_err(&pdev->dev, "unable to ioremap mii_ctrl\n"); err = -ENOMEM; goto err_unmap_base; } dev->irq = platform_get_irq(pdev, 0); err = request_irq(dev->irq, ag71xx_interrupt, IRQF_DISABLED | IRQF_SAMPLE_RANDOM, dev->name, dev); if (err) { dev_err(&pdev->dev, "unable to request IRQ %d\n", dev->irq); goto err_unmap_mii_ctrl; } dev->base_addr = (unsigned long)ag->mac_base; dev->netdev_ops = &ag71xx_netdev_ops; dev->ethtool_ops = &ag71xx_ethtool_ops; INIT_WORK(&ag->restart_work, ag71xx_restart_work_func); init_timer(&ag->oom_timer); ag->oom_timer.data = (unsigned long) dev; ag->oom_timer.function = ag71xx_oom_timer_handler; memcpy(dev->dev_addr, pdata->mac_addr, ETH_ALEN); netif_napi_add(dev, &ag->napi, ag71xx_poll, AG71XX_NAPI_WEIGHT); err = register_netdev(dev); if (err) { dev_err(&pdev->dev, "unable to register net device\n"); goto err_free_irq; } printk(KERN_INFO "%s: Atheros AG71xx at 0x%08lx, irq %d\n", dev->name, dev->base_addr, dev->irq); ag71xx_dump_regs(ag); ag71xx_hw_init(ag); ag71xx_dump_regs(ag); err = ag71xx_phy_connect(ag); if (err) goto err_unregister_netdev; err = ag71xx_debugfs_init(ag); if (err) goto err_phy_disconnect; platform_set_drvdata(pdev, dev); return 0; err_phy_disconnect: ag71xx_phy_disconnect(ag); err_unregister_netdev: unregister_netdev(dev); err_free_irq: free_irq(dev->irq, dev); err_unmap_mii_ctrl: iounmap(ag->mii_ctrl); err_unmap_base: iounmap(ag->mac_base); err_free_dev: kfree(dev); err_out: platform_set_drvdata(pdev, NULL); return err; }