From 78523daa86cf0b02c4d2f73b962c04ad565e9140 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Fri, 25 May 2007 11:49:19 -0400 Subject: [PATCH] [PATCH] libertas: single out mesh code This patches adds the two functions wlan_add_mesh() and wlan_remove_mesh(), which are responsible for the mshX interface. In a CF driver with a non- mesh-aware firmware you can omit the calls to this functions. Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmdresp.c | 4 +- drivers/net/wireless/libertas/decl.h | 2 + drivers/net/wireless/libertas/if_usb.c | 7 +- drivers/net/wireless/libertas/main.c | 136 ++++++++++++++++++++++---------- drivers/net/wireless/libertas/rx.c | 2 +- 5 files changed, 104 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 9509b8e..c8fce7b 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -220,7 +220,9 @@ static int wlan_ret_get_hw_spec(wlan_private * priv, } memcpy(priv->wlan_dev.netdev->dev_addr, adapter->current_addr, ETH_ALEN); - memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN); + if (priv->mesh_dev) + memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, + ETH_ALEN); if (libertas_set_regiontable(priv, adapter->regioncode, 0)) { ret = -1; diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index dfe2764..9eed599 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -79,5 +79,7 @@ extern struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, int *cfp_no); wlan_private *wlan_add_card(void *card); int wlan_remove_card(void *card); +int wlan_add_mesh(wlan_private *priv); +void wlan_remove_mesh(wlan_private *priv); #endif /* _WLAN_DECL_H_ */ diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 208d257..c1a662b 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -99,7 +99,7 @@ static int if_usb_probe(struct usb_interface *intf, struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; - wlan_private *pwlanpriv; + wlan_private *priv; struct usb_card_rec *usb_cardp; int i; @@ -187,7 +187,9 @@ static int if_usb_probe(struct usb_interface *intf, * about keeping pwlanpriv around since it will be set on our * usb device data in -> add() -> libertas_sbi_register_dev(). */ - if (!(pwlanpriv = wlan_add_card(usb_cardp))) + if (!(priv = wlan_add_card(usb_cardp))) + goto dealloc; + if (wlan_add_mesh(priv)) goto dealloc; usb_get_dev(udev); @@ -228,6 +230,7 @@ static void if_usb_disconnect(struct usb_interface *intf) /* card is removed and we can call wlan_remove_card */ lbs_deb_usbd(&cardp->udev->dev, "call remove card\n"); + wlan_remove_mesh(priv); wlan_remove_card(cardp); /* Unlink and free urb */ diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 6fcb2bd..abba7ec4 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -208,7 +208,6 @@ static ssize_t libertas_mpp_set(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) { struct cmd_ds_mesh_access mesh_access; - memset(&mesh_access, 0, sizeof(mesh_access)); sscanf(buf, "%d", &(mesh_access.data[0])); libertas_prepare_and_send_command((to_net_dev(dev))->priv, @@ -287,7 +286,7 @@ static int mesh_open(struct net_device *dev) { wlan_private *priv = (wlan_private *) dev->priv ; - if(pre_open_check(dev) == -1) + if (pre_open_check(dev) == -1) return -1; priv->mesh_open = 1 ; netif_start_queue(priv->mesh_dev); @@ -352,7 +351,8 @@ static int mesh_close(struct net_device *dev) * @param dev A pointer to net_device structure * @return 0 */ -static int wlan_close(struct net_device *dev) { +static int wlan_close(struct net_device *dev) +{ wlan_private *priv = (wlan_private *) dev->priv; netif_stop_queue(priv->wlan_dev.netdev); @@ -487,7 +487,8 @@ static int wlan_set_mac_address(struct net_device *dev, void *addr) lbs_dbg_hex("adapter->macaddr:", adapter->current_addr, ETH_ALEN); memcpy(dev->dev_addr, adapter->current_addr, ETH_ALEN); - memcpy(((wlan_private *) dev->priv)->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN); + if (priv->mesh_dev) + memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN); done: lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); @@ -767,7 +768,6 @@ static int wlan_service_main_thread(void *data) wlan_private *wlan_add_card(void *card) { struct net_device *dev = NULL; - struct net_device *mesh_dev = NULL; wlan_private *priv = NULL; lbs_deb_enter(LBS_DEB_NET); @@ -786,15 +786,6 @@ wlan_private *wlan_add_card(void *card) goto err_kmalloc; } - /* Allocate a virtual mesh device */ - if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) { - lbs_deb_mesh("init mshX device failed\n"); - return NULL; - } - - /* Both intervaces share the priv structure */ - mesh_dev->priv = priv; - /* init wlan_adapter */ memset(priv->adapter, 0, sizeof(wlan_adapter)); @@ -802,10 +793,8 @@ wlan_private *wlan_add_card(void *card) priv->wlan_dev.card = card; priv->mesh_open = 0; priv->infra_open = 0; - priv->mesh_dev = mesh_dev; SET_MODULE_OWNER(dev); - SET_MODULE_OWNER(mesh_dev); /* Setup the OS Interface to our functions */ dev->open = wlan_open; @@ -813,12 +802,6 @@ wlan_private *wlan_add_card(void *card) dev->stop = wlan_close; dev->do_ioctl = libertas_do_ioctl; dev->set_mac_address = wlan_set_mac_address; - mesh_dev->open = mesh_open; - mesh_dev->hard_start_xmit = mesh_pre_start_xmit; - mesh_dev->stop = mesh_close; - mesh_dev->do_ioctl = libertas_do_ioctl; - memcpy(mesh_dev->dev_addr, priv->wlan_dev.netdev->dev_addr, - sizeof(priv->wlan_dev.netdev->dev_addr)); #define WLAN_WATCHDOG_TIMEOUT (5 * HZ) @@ -826,12 +809,9 @@ wlan_private *wlan_add_card(void *card) dev->get_stats = wlan_get_stats; dev->watchdog_timeo = WLAN_WATCHDOG_TIMEOUT; dev->ethtool_ops = &libertas_ethtool_ops; - mesh_dev->get_stats = wlan_get_stats; - mesh_dev->ethtool_ops = &libertas_ethtool_ops; #ifdef WIRELESS_EXT dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def; - mesh_dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def; #endif #define NETIF_F_DYNALLOC 16 dev->features |= NETIF_F_DYNALLOC; @@ -875,12 +855,6 @@ wlan_private *wlan_add_card(void *card) goto err_init_fw; } - /* Register virtual mesh interface */ - if (register_netdev(mesh_dev)) { - lbs_pr_err("cannot register mshX virtual interface\n"); - goto err_init_fw; - } - lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); libertas_debugfs_init_one(priv, dev); @@ -889,14 +863,10 @@ wlan_private *wlan_add_card(void *card) goto err_init_fw; libertas_devs[libertas_found] = dev; libertas_found++; - if (device_create_file(&(mesh_dev->dev), &dev_attr_libertas_mpp)) - goto err_create_file; lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv); return priv; -err_create_file: - device_remove_file(&(mesh_dev->dev), &dev_attr_libertas_mpp); err_init_fw: libertas_sbi_unregister_dev(priv); err_registerdev: @@ -907,12 +877,76 @@ err_registerdev: kfree(priv->adapter); err_kmalloc: free_netdev(dev); - free_netdev(mesh_dev); lbs_deb_leave_args(LBS_DEB_NET, "priv NULL"); return NULL; } +/** + * @brief This function adds mshX interface + * + * @param priv A pointer to the wlan_private structure + * @return 0 if successful, -X otherwise + */ +int wlan_add_mesh(wlan_private *priv) +{ + struct net_device *mesh_dev = NULL; + int ret = 0; + + lbs_deb_enter(LBS_DEB_MESH); + + /* Allocate a virtual mesh device */ + if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) { + lbs_deb_mesh("init mshX device failed\n"); + ret = -ENOMEM; + goto done; + } + mesh_dev->priv = priv; + priv->mesh_dev = mesh_dev; + + SET_MODULE_OWNER(mesh_dev); + + mesh_dev->open = mesh_open; + mesh_dev->hard_start_xmit = mesh_pre_start_xmit; + mesh_dev->stop = mesh_close; + mesh_dev->do_ioctl = libertas_do_ioctl; + mesh_dev->get_stats = wlan_get_stats; + mesh_dev->ethtool_ops = &libertas_ethtool_ops; + memcpy(mesh_dev->dev_addr, priv->wlan_dev.netdev->dev_addr, + sizeof(priv->wlan_dev.netdev->dev_addr)); + +#ifdef WIRELESS_EXT + mesh_dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def; +#endif +#define NETIF_F_DYNALLOC 16 + + /* Register virtual mesh interface */ + ret = register_netdev(mesh_dev); + if (ret) { + lbs_pr_err("cannot register mshX virtual interface\n"); + goto err_free; + } + + ret = device_create_file(&(mesh_dev->dev), &dev_attr_libertas_mpp); + if (ret) + goto err_unregister; + + /* Everything successful */ + ret = 0; + goto done; + + +err_unregister: + unregister_netdev(mesh_dev); + +err_free: + free_netdev(mesh_dev); + +done: + lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); + return ret; +} + static void wake_pending_cmdnodes(wlan_private *priv) { struct cmd_ctrl_node *cmdnode; @@ -934,7 +968,6 @@ int wlan_remove_card(void *card) wlan_private *priv = libertas_sbi_get_priv(card); wlan_adapter *adapter; struct net_device *dev; - struct net_device *mesh_dev; union iwreq_data wrqu; int i; @@ -949,16 +982,12 @@ int wlan_remove_card(void *card) goto out; dev = priv->wlan_dev.netdev; - mesh_dev = priv->mesh_dev; - netif_stop_queue(mesh_dev); netif_stop_queue(priv->wlan_dev.netdev); netif_carrier_off(priv->wlan_dev.netdev); wake_pending_cmdnodes(priv); - device_remove_file(&(mesh_dev->dev), &dev_attr_libertas_mpp); - unregister_netdev(mesh_dev); unregister_netdev(dev); cancel_delayed_work(&priv->assoc_work); @@ -994,8 +1023,6 @@ int wlan_remove_card(void *card) lbs_deb_net("unregister finish\n"); priv->wlan_dev.netdev = NULL; - priv->mesh_dev = NULL ; - free_netdev(mesh_dev); free_netdev(dev); out: @@ -1003,6 +1030,29 @@ out: return 0; } +void wlan_remove_mesh(wlan_private *priv) +{ + struct net_device *mesh_dev; + + lbs_deb_enter(LBS_DEB_NET); + + if (!priv) + goto out; + + mesh_dev = priv->mesh_dev; + + netif_stop_queue(mesh_dev); + + device_remove_file(&(mesh_dev->dev), &dev_attr_libertas_mpp); + unregister_netdev(mesh_dev); + + priv->mesh_dev = NULL ; + free_netdev(mesh_dev); + +out: + lbs_deb_leave(LBS_DEB_NET); +} + /** * @brief This function finds the CFP in * region_cfp_table based on region and band parameter. diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 371cbf17..a0779dc 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -140,7 +140,7 @@ void libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb) { lbs_deb_rx("skb->data %p\n", skb->data); - if(IS_MESH_FRAME(skb)) + if (priv->mesh_dev && IS_MESH_FRAME(skb)) skb->dev = priv->mesh_dev; else skb->dev = priv->wlan_dev.netdev; -- 2.7.4