static int hieth_platdev_remove_port(struct platform_device *pdev, int port) { struct net_device *ndev; struct hieth_netdev_local *ld; ndev = hieth_devs_save[port]; if (!ndev) goto _ndev_exit; ld = netdev_priv(ndev); unregister_netdev(ndev); hieth_destroy_skb_buffers(ld); phy_disconnect(ld->phy); ld->phy = NULL; iounmap((void *)ld->iobase); local_lock_exit(); hieth_devs_save[port] = NULL; free_netdev(ndev); _ndev_exit: return 0; }
void hieth_mdio_exit(struct hieth_mdio_local *ld) { local_lock_exit(ld); }
static int hieth_platdev_probe_port(struct platform_device *pdev, int port) { int ret = -1; struct net_device *netdev = NULL; struct hieth_netdev_local *ld; if ((UP_PORT != port) && (DOWN_PORT != port)) { hieth_error("port error!"); ret = -ENODEV; goto _error_exit; } netdev = alloc_etherdev(sizeof(*ld)); if (netdev == NULL) { hieth_error("alloc_etherdev fail!"); ret = -ENOMEM; goto _error_alloc_etherdev; } SET_NETDEV_DEV(netdev, &pdev->dev); netdev->irq = CONFIG_HIETH_IRQNUM; netdev->watchdog_timeo = 3*HZ; netdev->netdev_ops = &hieth_netdev_ops; netdev->ethtool_ops = &hieth_ethtools_ops; /* init hieth_global somethings... */ hieth_devs_save[port] = netdev; /* init hieth_local_driver */ ld = netdev_priv(netdev); memset(ld, 0, sizeof(*ld)); local_lock_init(ld); ld->iobase = (unsigned long)ioremap_nocache(CONFIG_HIETH_IOBASE, \ CONFIG_HIETH_IOSIZE); if (!ld->iobase) { hieth_error("ioremap_nocache err, base=0x%.8x, size=0x%.8x\n", CONFIG_HIETH_IOBASE, CONFIG_HIETH_IOSIZE); ret = -EFAULT; goto _error_ioremap_nocache; } ld->iobase_phys = CONFIG_HIETH_IOBASE; ld->port = port; ld->dev = &(pdev->dev); /* reset and init port */ hieth_port_reset(ld, ld->port); hieth_port_init(ld, ld->port); ld->depth.hw_xmitq = CONFIG_HIETH_HWQ_XMIT_DEPTH; memset(ld->phy_name, 0, sizeof(ld->phy_name)); snprintf(ld->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, \ HIETH_MIIBUS_NAME, UD_PHY_NAME(CONFIG_HIETH_PHYID)); ld->phy = phy_connect(netdev, ld->phy_name, hieth_adjust_link, 0, \ UD_BIT_NAME(CONFIG_HIETH_MII_RMII_MODE) ? \ PHY_INTERFACE_MODE_MII : PHY_INTERFACE_MODE_MII); if (IS_ERR(ld->phy)) { hieth_error("connect to phy_device %s failed!", ld->phy_name); ld->phy = NULL; goto _error_phy_connect; } skb_queue_head_init(&ld->rx_head); skb_queue_head_init(&ld->rx_hw); skb_queue_head_init(&ld->tx_hw); ld->tx_hw_cnt = 0; ret = hieth_init_skb_buffers(ld); if (ret) { hieth_error("hieth_init_skb_buffers failed!"); goto _error_init_skb_buffers; } ret = register_netdev(netdev); if (ret) { hieth_error("register_netdev %s failed!", netdev->name); goto _error_register_netdev; } return ret; _error_register_netdev: hieth_destroy_skb_buffers(ld); _error_init_skb_buffers: phy_disconnect(ld->phy); ld->phy = NULL; _error_phy_connect: iounmap((void *)ld->iobase); _error_ioremap_nocache: local_lock_exit(); hieth_devs_save[port] = NULL; free_netdev(netdev); _error_alloc_etherdev: _error_exit: return ret; }