diff options
Diffstat (limited to 'drivers/staging/most/aim-network/networking.c')
-rw-r--r-- | drivers/staging/most/aim-network/networking.c | 172 |
1 files changed, 48 insertions, 124 deletions
diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index ce1764cba5f0..a2e37511341a 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -22,7 +22,6 @@ #include <linux/wait.h> #include <linux/kobject.h> #include "mostcore.h" -#include "networking.h" #define MEP_HDR_LEN 8 #define MDP_HDR_LEN 16 @@ -65,12 +64,10 @@ struct net_dev_channel { struct net_dev_context { struct most_interface *iface; - bool channels_opened; bool is_mamac; struct net_device *dev; struct net_dev_channel rx; struct net_dev_channel tx; - struct completion mac_compl; struct list_head list; }; @@ -157,14 +154,12 @@ static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo) static int most_nd_set_mac_address(struct net_device *dev, void *p) { - struct net_dev_context *nd = dev->ml_priv; + struct net_dev_context *nd = netdev_priv(dev); int err = eth_mac_addr(dev, p); if (err) return err; - BUG_ON(nd->dev != dev); - nd->is_mamac = (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 && dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0); @@ -178,18 +173,15 @@ static int most_nd_set_mac_address(struct net_device *dev, void *p) return 0; } +static void on_netinfo(struct most_interface *iface, + unsigned char link_stat, unsigned char *mac_addr); + static int most_nd_open(struct net_device *dev) { - struct net_dev_context *nd = dev->ml_priv; - long ret; + struct net_dev_context *nd = netdev_priv(dev); netdev_info(dev, "open net device\n"); - BUG_ON(nd->dev != dev); - - if (nd->channels_opened) - return -EFAULT; - BUG_ON(!nd->tx.linked || !nd->rx.linked); if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) { @@ -203,46 +195,28 @@ static int most_nd_open(struct net_device *dev) return -EBUSY; } - if (!is_valid_ether_addr(dev->dev_addr)) { - nd->iface->request_netinfo(nd->iface, nd->tx.ch_id); - ret = wait_for_completion_interruptible_timeout( - &nd->mac_compl, msecs_to_jiffies(5000)); - if (!ret) { - netdev_err(dev, "mac timeout\n"); - ret = -EBUSY; - goto err; - } - - if (ret < 0) { - netdev_warn(dev, "mac waiting interrupted\n"); - goto err; - } - } - - nd->channels_opened = true; + netif_carrier_off(dev); + if (is_valid_ether_addr(dev->dev_addr)) + netif_dormant_off(dev); + else + netif_dormant_on(dev); netif_wake_queue(dev); + if (nd->iface->request_netinfo) + nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, on_netinfo); return 0; - -err: - most_stop_channel(nd->iface, nd->tx.ch_id, &aim); - most_stop_channel(nd->iface, nd->rx.ch_id, &aim); - return ret; } static int most_nd_stop(struct net_device *dev) { - struct net_dev_context *nd = dev->ml_priv; + struct net_dev_context *nd = netdev_priv(dev); netdev_info(dev, "stop net device\n"); - BUG_ON(nd->dev != dev); netif_stop_queue(dev); - - if (nd->channels_opened) { - most_stop_channel(nd->iface, nd->rx.ch_id, &aim); - most_stop_channel(nd->iface, nd->tx.ch_id, &aim); - nd->channels_opened = false; - } + if (nd->iface->request_netinfo) + nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL); + most_stop_channel(nd->iface, nd->rx.ch_id, &aim); + most_stop_channel(nd->iface, nd->tx.ch_id, &aim); return 0; } @@ -250,12 +224,10 @@ static int most_nd_stop(struct net_device *dev) static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_dev_context *nd = dev->ml_priv; + struct net_dev_context *nd = netdev_priv(dev); struct mbo *mbo; int ret; - BUG_ON(nd->dev != dev); - mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim); if (!mbo) { @@ -296,26 +268,14 @@ static void most_nd_setup(struct net_device *dev) dev->netdev_ops = &most_nd_ops; } -static void most_net_rm_netdev_safe(struct net_dev_context *nd) -{ - if (!nd->dev) - return; - - pr_info("remove net device %p\n", nd->dev); - - unregister_netdev(nd->dev); - free_netdev(nd->dev); - nd->dev = NULL; -} - static struct net_dev_context *get_net_dev_context( struct most_interface *iface) { - struct net_dev_context *nd, *tmp; + struct net_dev_context *nd; unsigned long flags; spin_lock_irqsave(&list_lock, flags); - list_for_each_entry_safe(nd, tmp, &net_devices, list) { + list_for_each_entry(nd, &net_devices, list) { if (nd->iface == iface) { spin_unlock_irqrestore(&list_lock, flags); return nd; @@ -342,12 +302,16 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, nd = get_net_dev_context(iface); if (!nd) { - nd = kzalloc(sizeof(*nd), GFP_KERNEL); - if (!nd) + struct net_device *dev; + + dev = alloc_netdev(sizeof(struct net_dev_context), "meth%d", + NET_NAME_UNKNOWN, most_nd_setup); + if (!dev) return -ENOMEM; - init_completion(&nd->mac_compl); + nd = netdev_priv(dev); nd->iface = iface; + nd->dev = dev; spin_lock_irqsave(&list_lock, flags); list_add(&nd->list, &net_devices); @@ -360,31 +324,13 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, return -EINVAL; } - if (nd->tx.linked || nd->rx.linked) { - struct net_device *dev = - alloc_netdev(0, "meth%d", NET_NAME_UNKNOWN, - most_nd_setup); - - if (!dev) { - pr_err("no memory for net_device\n"); - return -ENOMEM; - } - - nd->dev = dev; - ch->ch_id = channel_idx; - ch->linked = true; - - dev->ml_priv = nd; - if (register_netdev(dev)) { - pr_err("registering net device failed\n"); - ch->linked = false; - free_netdev(dev); - return -EINVAL; - } - } - ch->ch_id = channel_idx; ch->linked = true; + if (nd->tx.linked && nd->rx.linked && register_netdev(nd->dev)) { + pr_err("register_netdev() failed\n"); + ch->linked = false; + return -EINVAL; + } return 0; } @@ -407,19 +353,19 @@ static int aim_disconnect_channel(struct most_interface *iface, else return -EINVAL; - ch->linked = false; - /* * do not call most_stop_channel() here, because channels are * going to be closed in ndo_stop() after unregister_netdev() */ - most_net_rm_netdev_safe(nd); + if (nd->rx.linked && nd->tx.linked) + unregister_netdev(nd->dev); + ch->linked = false; if (!nd->rx.linked && !nd->tx.linked) { spin_lock_irqsave(&list_lock, flags); list_del(&nd->list); spin_unlock_irqrestore(&list_lock, flags); - kfree(nd); + free_netdev(nd->dev); } return 0; @@ -431,10 +377,7 @@ static int aim_resume_tx_channel(struct most_interface *iface, struct net_dev_context *nd; nd = get_net_dev_context(iface); - if (!nd || !nd->channels_opened || nd->tx.ch_id != channel_idx) - return 0; - - if (!nd->dev) + if (!nd || nd->tx.ch_id != channel_idx) return 0; netif_wake_queue(nd->dev); @@ -452,14 +395,10 @@ static int aim_rx_data(struct mbo *mbo) unsigned int skb_len; nd = get_net_dev_context(mbo->ifp); - if (!nd || !nd->channels_opened || nd->rx.ch_id != mbo->hdm_channel_id) + if (!nd || nd->rx.ch_id != mbo->hdm_channel_id) return -EIO; dev = nd->dev; - if (!dev) { - pr_err_once("drop packet: missing net_device\n"); - return -EIO; - } if (nd->is_mamac) { if (!PMS_IS_MAMAC(buf, len)) @@ -531,35 +470,18 @@ static int __init most_net_init(void) static void __exit most_net_exit(void) { - struct net_dev_context *nd, *tmp; - unsigned long flags; - - spin_lock_irqsave(&list_lock, flags); - list_for_each_entry_safe(nd, tmp, &net_devices, list) { - list_del(&nd->list); - spin_unlock_irqrestore(&list_lock, flags); - /* - * do not call most_stop_channel() here, because channels are - * going to be closed in ndo_stop() after unregister_netdev() - */ - most_net_rm_netdev_safe(nd); - kfree(nd); - spin_lock_irqsave(&list_lock, flags); - } - spin_unlock_irqrestore(&list_lock, flags); - - most_deregister_aim(&aim); pr_info("most_net_exit()\n"); + most_deregister_aim(&aim); } /** - * most_deliver_netinfo - callback for HDM to be informed about HW's MAC + * on_netinfo - callback for HDM to be informed about HW's MAC * @param iface - most interface instance * @param link_stat - link status * @param mac_addr - MAC address */ -void most_deliver_netinfo(struct most_interface *iface, - unsigned char link_stat, unsigned char *mac_addr) +static void on_netinfo(struct most_interface *iface, + unsigned char link_stat, unsigned char *mac_addr) { struct net_dev_context *nd; struct net_device *dev; @@ -570,22 +492,24 @@ void most_deliver_netinfo(struct most_interface *iface, return; dev = nd->dev; - if (!dev) - return; + + if (link_stat) + netif_carrier_on(dev); + else + netif_carrier_off(dev); if (m && is_valid_ether_addr(m)) { if (!is_valid_ether_addr(dev->dev_addr)) { netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n", m[0], m[1], m[2], m[3], m[4], m[5]); ether_addr_copy(dev->dev_addr, m); - complete(&nd->mac_compl); + netif_dormant_off(dev); } else if (!ether_addr_equal(dev->dev_addr, m)) { netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n", m[0], m[1], m[2], m[3], m[4], m[5]); } } } -EXPORT_SYMBOL(most_deliver_netinfo); module_init(most_net_init); module_exit(most_net_exit); |