diff options
author | Jeff Garzik <jeff@garzik.org> | 2007-06-12 22:27:30 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-06-12 22:27:30 -0400 |
commit | 12b90de64f38226e1e095c55b533f0f4d4f0f572 (patch) | |
tree | 9955197d842511064a1eff6db815fe56cd8f0eb3 /drivers/net/wireless/libertas/main.c | |
parent | 6f8a7c66e2dc8080950d28edc0259f37739aead9 (diff) | |
parent | 717c9339202a42ae7bec7d3c4b84deecdcae9f81 (diff) | |
download | kernel_samsung_crespo-12b90de64f38226e1e095c55b533f0f4d4f0f572.zip kernel_samsung_crespo-12b90de64f38226e1e095c55b533f0f4d4f0f572.tar.gz kernel_samsung_crespo-12b90de64f38226e1e095c55b533f0f4d4f0f572.tar.bz2 |
Merge branch 'libertas' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into upstream-fixes
Diffstat (limited to 'drivers/net/wireless/libertas/main.c')
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 673 |
1 files changed, 294 insertions, 379 deletions
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index b9b25ce..ec9be0c 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -4,6 +4,7 @@ * thread etc.. */ +#include <linux/moduleparam.h> #include <linux/delay.h> #include <linux/freezer.h> #include <linux/etherdevice.h> @@ -11,26 +12,28 @@ #include <linux/if_arp.h> #include <net/iw_handler.h> +#include <net/ieee80211.h> #include "host.h" -#include "sbi.h" #include "decl.h" #include "dev.h" -#include "fw.h" #include "wext.h" #include "debugfs.h" #include "assoc.h" -#define DRIVER_RELEASE_VERSION "320.p0" +#define DRIVER_RELEASE_VERSION "322.p0" const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION #ifdef DEBUG "-dbg" #endif ""; -#ifdef ENABLE_PM -static struct pm_dev *wlan_pm_dev = NULL; -#endif + +/* Module parameters */ +unsigned int libertas_debug = 0; +module_param(libertas_debug, int, 0644); +EXPORT_SYMBOL_GPL(libertas_debug); + #define WLAN_TX_PWR_DEFAULT 20 /*100mW */ #define WLAN_TX_PWR_US_DEFAULT 20 /*100mW */ @@ -146,14 +149,6 @@ static struct region_cfp_table region_cfp_table[] = { }; /** - * the rates supported by the card - */ -u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES] = - { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12, - 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00 -}; - -/** * the rates supported */ u8 libertas_supported_rates[G_SUPPORTED_RATES] = @@ -173,23 +168,11 @@ u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES] = u8 libertas_adhoc_rates_b[4] = { 0x82, 0x84, 0x8b, 0x96 }; /** - * the global variable of a pointer to wlan_private - * structure variable - */ -static wlan_private *wlanpriv = NULL; - -#define MAX_DEVS 5 -static struct net_device *libertas_devs[MAX_DEVS]; -static int libertas_found = 0; - -/** * the table to keep region code */ u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE] = { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 }; -static u8 *default_fw_name = "usb8388.bin"; - /** * Attributes exported through sysfs */ @@ -207,7 +190,7 @@ static ssize_t libertas_mpp_get(struct device * dev, cmd_act_mesh_get_mpp, cmd_option_waitforrsp, 0, (void *)&mesh_access); - return snprintf(buf, 3, "%d\n", mesh_access.data[0]); + return snprintf(buf, 3, "%d\n", le32_to_cpu(mesh_access.data[0])); } /** @@ -216,10 +199,12 @@ static ssize_t libertas_mpp_get(struct device * dev, 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; - + uint32_t datum; memset(&mesh_access, 0, sizeof(mesh_access)); - sscanf(buf, "%d", &(mesh_access.data[0])); + sscanf(buf, "%d", &datum); + mesh_access.data[0] = cpu_to_le32(datum); + libertas_prepare_and_send_command((to_net_dev(dev))->priv, cmd_mesh_access, cmd_act_mesh_set_mpp, @@ -231,8 +216,7 @@ static ssize_t libertas_mpp_set(struct device * dev, * libertas_mpp attribute to be exported per mshX interface * through sysfs (/sys/class/net/mshX/libertas-mpp) */ -static DEVICE_ATTR(libertas_mpp, 0644, libertas_mpp_get, - libertas_mpp_set ); +static DEVICE_ATTR(libertas_mpp, 0644, libertas_mpp_get, libertas_mpp_set ); /** * @brief Check if the device can be open and wait if necessary. @@ -245,7 +229,8 @@ static DEVICE_ATTR(libertas_mpp, 0644, libertas_mpp_get, * function to work around the issue. * */ -static int pre_open_check(struct net_device *dev) { +static int pre_open_check(struct net_device *dev) +{ wlan_private *priv = (wlan_private *) dev->priv; wlan_adapter *adapter = priv->adapter; int i = 0; @@ -255,8 +240,7 @@ static int pre_open_check(struct net_device *dev) { msleep_interruptible(100); } if (!adapter->fw_ready) { - lbs_pr_info("FW not ready, pre_open_check() return failure\n"); - LEAVE(); + lbs_pr_err("firmware not ready\n"); return -1; } @@ -274,17 +258,19 @@ static int wlan_dev_open(struct net_device *dev) wlan_private *priv = (wlan_private *) dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); - + lbs_deb_enter(LBS_DEB_NET); priv->open = 1; if (adapter->connect_status == libertas_connected) { - netif_carrier_on(priv->wlan_dev.netdev); - } else - netif_carrier_off(priv->wlan_dev.netdev); + netif_carrier_on(priv->dev); + netif_carrier_on(priv->mesh_dev); + } else { + netif_carrier_off(priv->dev); + netif_carrier_off(priv->mesh_dev); + } - LEAVE(); + lbs_deb_leave(LBS_DEB_NET); return 0; } /** @@ -297,12 +283,12 @@ 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); + netif_wake_queue(priv->mesh_dev); if (priv->infra_open == 0) - return wlan_dev_open(priv->wlan_dev.netdev) ; + return wlan_dev_open(priv->dev) ; return 0; } @@ -319,9 +305,9 @@ static int wlan_open(struct net_device *dev) if(pre_open_check(dev) == -1) return -1; priv->infra_open = 1 ; - netif_wake_queue(priv->wlan_dev.netdev); + netif_wake_queue(priv->dev); if (priv->open == 0) - return wlan_dev_open(priv->wlan_dev.netdev) ; + return wlan_dev_open(priv->dev) ; return 0; } @@ -329,12 +315,12 @@ static int wlan_dev_close(struct net_device *dev) { wlan_private *priv = dev->priv; - ENTER(); + lbs_deb_enter(LBS_DEB_NET); - netif_carrier_off(priv->wlan_dev.netdev); + netif_carrier_off(priv->dev); priv->open = 0; - LEAVE(); + lbs_deb_leave(LBS_DEB_NET); return 0; } @@ -351,7 +337,7 @@ static int mesh_close(struct net_device *dev) priv->mesh_open = 0; netif_stop_queue(priv->mesh_dev); if (priv->infra_open == 0) - return wlan_dev_close( ((wlan_private *) dev->priv)->wlan_dev.netdev) ; + return wlan_dev_close(dev); else return 0; } @@ -362,147 +348,38 @@ 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); + netif_stop_queue(dev); priv->infra_open = 0; if (priv->mesh_open == 0) - return wlan_dev_close( ((wlan_private *) dev->priv)->wlan_dev.netdev) ; + return wlan_dev_close(dev); else return 0; } -#ifdef ENABLE_PM - -/** - * @brief This function is a callback function. it is called by - * kernel to enter or exit power saving mode. - * - * @param pmdev A pointer to pm_dev - * @param pmreq pm_request_t - * @param pmdata A pointer to pmdata - * @return 0 or -1 - */ -static int wlan_pm_callback(struct pm_dev *pmdev, pm_request_t pmreq, - void *pmdata) -{ - wlan_private *priv = wlanpriv; - wlan_adapter *adapter = priv->adapter; - struct net_device *dev = priv->wlan_dev.netdev; - - lbs_pr_debug(1, "WPRM_PM_CALLBACK: pmreq = %d.\n", pmreq); - - switch (pmreq) { - case PM_SUSPEND: - lbs_pr_debug(1, "WPRM_PM_CALLBACK: enter PM_SUSPEND.\n"); - - /* in associated mode */ - if (adapter->connect_status == libertas_connected) { - if ((adapter->psstate != PS_STATE_SLEEP) - ) { - lbs_pr_debug(1, - "wlan_pm_callback: can't enter sleep mode\n"); - return -1; - } else { - - /* - * Detach the network interface - * if the network is running - */ - if (netif_running(dev)) { - netif_device_detach(dev); - lbs_pr_debug(1, - "netif_device_detach().\n"); - } - libertas_sbi_suspend(priv); - } - break; - } - - /* in non associated mode */ - - /* - * Detach the network interface - * if the network is running - */ - if (netif_running(dev)) - netif_device_detach(dev); - - /* - * Storing and restoring of the regs be taken care - * at the driver rest will be done at wlan driver - * this makes driver independent of the card - */ - - libertas_sbi_suspend(priv); - - break; - - case PM_RESUME: - /* in associated mode */ - if (adapter->connect_status == libertas_connected) { - { - /* - * Bring the inteface up first - * This case should not happen still ... - */ - libertas_sbi_resume(priv); - - /* - * Attach the network interface - * if the network is running - */ - if (netif_running(dev)) { - netif_device_attach(dev); - lbs_pr_debug(1, - "after netif_device_attach().\n"); - } - lbs_pr_debug(1, - "After netif attach, in associated mode.\n"); - } - break; - } - - /* in non associated mode */ - - /* - * Bring the inteface up first - * This case should not happen still ... - */ - - libertas_sbi_resume(priv); - - if (netif_running(dev)) - netif_device_attach(dev); - - lbs_pr_debug(1, "after netif attach, in NON associated mode.\n"); - break; - } - - return 0; -} -#endif /* ENABLE_PM */ - static int wlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { int ret = 0; wlan_private *priv = dev->priv; - ENTER(); + lbs_deb_enter(LBS_DEB_NET); - if (priv->wlan_dev.dnld_sent || priv->adapter->TxLockFlag) { + if (priv->dnld_sent || priv->adapter->TxLockFlag) { priv->stats.tx_dropped++; goto done; } - netif_stop_queue(priv->wlan_dev.netdev); + netif_stop_queue(priv->dev); + netif_stop_queue(priv->mesh_dev); if (libertas_process_tx(priv, skb) == 0) dev->trans_start = jiffies; done: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); return ret; } @@ -513,33 +390,43 @@ done: static int mesh_pre_start_xmit(struct sk_buff *skb, struct net_device *dev) { wlan_private *priv = dev->priv; - ENTER(); + int ret; + + lbs_deb_enter(LBS_DEB_MESH); + SET_MESH_FRAME(skb); - LEAVE(); - return wlan_hard_start_xmit(skb, priv->wlan_dev.netdev); + ret = wlan_hard_start_xmit(skb, priv->dev); + lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); + return ret; } /** * @brief Mark non-mesh packets and handover them to wlan_hard_start_xmit * */ -static int wlan_pre_start_xmit(struct sk_buff *skb, struct net_device *dev) { - ENTER(); +static int wlan_pre_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int ret; + + lbs_deb_enter(LBS_DEB_NET); + UNSET_MESH_FRAME(skb); - LEAVE(); - return wlan_hard_start_xmit(skb, dev); + + ret = wlan_hard_start_xmit(skb, dev); + lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); + return ret; } static void wlan_tx_timeout(struct net_device *dev) { wlan_private *priv = (wlan_private *) dev->priv; - ENTER(); + lbs_deb_enter(LBS_DEB_TX); - lbs_pr_err("tx watch dog timeout!\n"); + lbs_pr_err("tx watch dog timeout\n"); - priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED; + priv->dnld_sent = DNLD_RES_RECEIVED; dev->trans_start = jiffies; if (priv->adapter->currenttxskb) { @@ -550,10 +437,12 @@ static void wlan_tx_timeout(struct net_device *dev) libertas_send_tx_feedback(priv); } else wake_up_interruptible(&priv->mainthread.waitq); - } else if (priv->adapter->connect_status == libertas_connected) - netif_wake_queue(priv->wlan_dev.netdev); + } else if (priv->adapter->connect_status == libertas_connected) { + netif_wake_queue(priv->dev); + netif_wake_queue(priv->mesh_dev); + } - LEAVE(); + lbs_deb_leave(LBS_DEB_TX); } /** @@ -576,7 +465,10 @@ static int wlan_set_mac_address(struct net_device *dev, void *addr) wlan_adapter *adapter = priv->adapter; struct sockaddr *phwaddr = addr; - ENTER(); + lbs_deb_enter(LBS_DEB_NET); + + /* In case it was called from the mesh device */ + dev = priv->dev ; memset(adapter->current_addr, 0, ETH_ALEN); @@ -591,17 +483,18 @@ static int wlan_set_mac_address(struct net_device *dev, void *addr) cmd_option_waitforrsp, 0, NULL); if (ret) { - lbs_pr_debug(1, "set mac address failed.\n"); + lbs_deb_net("set MAC address failed\n"); ret = -1; goto done; } 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: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); return ret; } @@ -626,12 +519,12 @@ static void wlan_set_multicast_list(struct net_device *dev) wlan_adapter *adapter = priv->adapter; int oldpacketfilter; - ENTER(); + lbs_deb_enter(LBS_DEB_NET); oldpacketfilter = adapter->currentpacketfilter; if (dev->flags & IFF_PROMISC) { - lbs_pr_debug(1, "enable Promiscuous mode\n"); + lbs_deb_net("enable promiscuous mode\n"); adapter->currentpacketfilter |= cmd_act_mac_promiscuous_enable; adapter->currentpacketfilter &= @@ -644,7 +537,7 @@ static void wlan_set_multicast_list(struct net_device *dev) if (dev->flags & IFF_ALLMULTI || dev->mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) { - lbs_pr_debug(1, "Enabling All Multicast!\n"); + lbs_deb_net( "enabling all multicast\n"); adapter->currentpacketfilter |= cmd_act_mac_all_multicast_enable; adapter->currentpacketfilter &= @@ -654,8 +547,8 @@ static void wlan_set_multicast_list(struct net_device *dev) ~cmd_act_mac_all_multicast_enable; if (!dev->mc_count) { - lbs_pr_debug(1, "No multicast addresses - " - "disabling multicast!\n"); + lbs_deb_net("no multicast addresses, " + "disabling multicast\n"); adapter->currentpacketfilter &= ~cmd_act_mac_multicast_enable; } else { @@ -667,12 +560,12 @@ static void wlan_set_multicast_list(struct net_device *dev) adapter->nr_of_multicastmacaddr = wlan_copy_multicast_address(adapter, dev); - lbs_pr_debug(1, "Multicast addresses: %d\n", + lbs_deb_net("multicast addresses: %d\n", dev->mc_count); for (i = 0; i < dev->mc_count; i++) { - lbs_pr_debug(1, "Multicast address %d:" - "%x %x %x %x %x %x\n", i, + lbs_deb_net("Multicast address %d:" + MAC_FMT "\n", i, adapter->multicastlist[i][0], adapter->multicastlist[i][1], adapter->multicastlist[i][2], @@ -680,7 +573,7 @@ static void wlan_set_multicast_list(struct net_device *dev) adapter->multicastlist[i][4], adapter->multicastlist[i][5]); } - /* set multicast addresses to firmware */ + /* send multicast addresses to firmware */ libertas_prepare_and_send_command(priv, cmd_mac_multicast_adr, cmd_act_set, 0, 0, @@ -693,13 +586,13 @@ static void wlan_set_multicast_list(struct net_device *dev) libertas_set_mac_packet_filter(priv); } - LEAVE(); + lbs_deb_leave(LBS_DEB_NET); } /** - * @brief This function hanldes the major job in WLAN driver. - * it handles the event generated by firmware, rx data received - * from firmware and tx data sent from kernel. + * @brief This function handles the major jobs in the WLAN driver. + * It handles all events generated by firmware, RX data received + * from firmware and TX data sent from kernel. * * @param data A pointer to wlan_thread structure * @return 0 @@ -712,26 +605,26 @@ static int wlan_service_main_thread(void *data) wait_queue_t wait; u8 ireg = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_THREAD); wlan_activate_thread(thread); init_waitqueue_entry(&wait, current); for (;;) { - lbs_pr_debug(1, "main-thread 111: intcounter=%d " + lbs_deb_thread( "main-thread 111: intcounter=%d " "currenttxskb=%p dnld_sent=%d\n", adapter->intcounter, - adapter->currenttxskb, priv->wlan_dev.dnld_sent); + adapter->currenttxskb, priv->dnld_sent); add_wait_queue(&thread->waitq, &wait); set_current_state(TASK_INTERRUPTIBLE); spin_lock_irq(&adapter->driver_lock); if ((adapter->psstate == PS_STATE_SLEEP) || (!adapter->intcounter - && (priv->wlan_dev.dnld_sent || adapter->cur_cmd || + && (priv->dnld_sent || adapter->cur_cmd || list_empty(&adapter->cmdpendingq)))) { - lbs_pr_debug(1, + lbs_deb_thread( "main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n", adapter->connect_status, adapter->intcounter, adapter->psmode, adapter->psstate); @@ -741,23 +634,23 @@ static int wlan_service_main_thread(void *data) spin_unlock_irq(&adapter->driver_lock); - lbs_pr_debug(1, + lbs_deb_thread( "main-thread 222 (waking up): intcounter=%d currenttxskb=%p " "dnld_sent=%d\n", adapter->intcounter, - adapter->currenttxskb, priv->wlan_dev.dnld_sent); + adapter->currenttxskb, priv->dnld_sent); set_current_state(TASK_RUNNING); remove_wait_queue(&thread->waitq, &wait); try_to_freeze(); - lbs_pr_debug(1, "main-thread 333: intcounter=%d currenttxskb=%p " + lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p " "dnld_sent=%d\n", adapter->intcounter, - adapter->currenttxskb, priv->wlan_dev.dnld_sent); + adapter->currenttxskb, priv->dnld_sent); if (kthread_should_stop() || adapter->surpriseremoved) { - lbs_pr_debug(1, + lbs_deb_thread( "main-thread: break from main thread: surpriseremoved=0x%x\n", adapter->surpriseremoved); break; @@ -768,10 +661,10 @@ static int wlan_service_main_thread(void *data) if (adapter->intcounter) { u8 int_status; adapter->intcounter = 0; - int_status = libertas_sbi_get_int_status(priv, &ireg); + int_status = priv->hw_get_int_status(priv, &ireg); if (int_status) { - lbs_pr_debug(1, + lbs_deb_thread( "main-thread: reading HOST_INT_STATUS_REG failed\n"); spin_unlock_irq(&adapter->driver_lock); continue; @@ -779,14 +672,14 @@ static int wlan_service_main_thread(void *data) adapter->hisregcpy |= ireg; } - lbs_pr_debug(1, "main-thread 444: intcounter=%d currenttxskb=%p " + lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p " "dnld_sent=%d\n", adapter->intcounter, - adapter->currenttxskb, priv->wlan_dev.dnld_sent); + adapter->currenttxskb, priv->dnld_sent); /* command response? */ if (adapter->hisregcpy & his_cmdupldrdy) { - lbs_pr_debug(1, "main-thread: cmd response ready.\n"); + lbs_deb_thread("main-thread: cmd response ready\n"); adapter->hisregcpy &= ~his_cmdupldrdy; spin_unlock_irq(&adapter->driver_lock); @@ -796,13 +689,13 @@ static int wlan_service_main_thread(void *data) /* Any Card Event */ if (adapter->hisregcpy & his_cardevent) { - lbs_pr_debug(1, "main-thread: Card Event Activity.\n"); + lbs_deb_thread("main-thread: Card Event Activity\n"); adapter->hisregcpy &= ~his_cardevent; - if (libertas_sbi_read_event_cause(priv)) { + if (priv->hw_read_event_cause(priv)) { lbs_pr_alert( - "main-thread: libertas_sbi_read_event_cause failed.\n"); + "main-thread: hw_read_event_cause failed\n"); spin_unlock_irq(&adapter->driver_lock); continue; } @@ -813,15 +706,15 @@ static int wlan_service_main_thread(void *data) /* Check if we need to confirm Sleep Request received previously */ if (adapter->psstate == PS_STATE_PRE_SLEEP) { - if (!priv->wlan_dev.dnld_sent && !adapter->cur_cmd) { + if (!priv->dnld_sent && !adapter->cur_cmd) { if (adapter->connect_status == libertas_connected) { - lbs_pr_debug(1, + lbs_deb_thread( "main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p " "dnld_sent=%d cur_cmd=%p, confirm now\n", adapter->intcounter, adapter->currenttxskb, - priv->wlan_dev.dnld_sent, + priv->dnld_sent, adapter->cur_cmd); libertas_ps_confirm_sleep(priv, @@ -847,7 +740,7 @@ static int wlan_service_main_thread(void *data) continue; /* Execute the next command */ - if (!priv->wlan_dev.dnld_sent && !priv->adapter->cur_cmd) + if (!priv->dnld_sent && !priv->adapter->cur_cmd) libertas_execute_next_command(priv); /* Wake-up command waiters which can't sleep in @@ -864,7 +757,7 @@ static int wlan_service_main_thread(void *data) wake_up_all(&adapter->cmd_pending); wlan_deactivate_thread(thread); - LEAVE(); + lbs_deb_leave(LBS_DEB_THREAD); return 0; } @@ -875,49 +768,32 @@ static int wlan_service_main_thread(void *data) * @param card A pointer to card * @return A pointer to wlan_private structure */ -wlan_private *wlan_add_card(void *card) +wlan_private *libertas_add_card(void *card, struct device *dmdev) { struct net_device *dev = NULL; - struct net_device *mesh_dev = NULL; wlan_private *priv = NULL; - ENTER(); + lbs_deb_enter(LBS_DEB_NET); /* Allocate an Ethernet device and register it */ if (!(dev = alloc_etherdev(sizeof(wlan_private)))) { - lbs_pr_alert( "Init ethernet device failed!\n"); + lbs_pr_err("init ethX device failed\n"); return NULL; } - priv = dev->priv; /* allocate buffer for wlan_adapter */ - if (!(priv->adapter = kmalloc(sizeof(wlan_adapter), GFP_KERNEL))) { - lbs_pr_alert( "Allocate buffer for wlan_adapter failed!\n"); - goto err_kmalloc; + if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) { + lbs_pr_err("allocate buffer for wlan_adapter failed\n"); + goto err_kzalloc; } - /* Allocate a virtual mesh device */ - if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) { - lbs_pr_debug(1, "Init ethernet 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)); - - priv->wlan_dev.netdev = dev; - priv->wlan_dev.card = card; + priv->dev = dev; + priv->card = card; priv->mesh_open = 0; priv->infra_open = 0; - priv->mesh_dev = mesh_dev; - wlanpriv = priv; SET_MODULE_OWNER(dev); - SET_MODULE_OWNER(mesh_dev); /* Setup the OS Interface to our functions */ dev->open = wlan_open; @@ -925,116 +801,171 @@ 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, wlanpriv->wlan_dev.netdev->dev_addr, - sizeof(wlanpriv->wlan_dev.netdev->dev_addr)); - -#define WLAN_WATCHDOG_TIMEOUT (5 * HZ) - dev->tx_timeout = wlan_tx_timeout; dev->get_stats = wlan_get_stats; - dev->watchdog_timeo = WLAN_WATCHDOG_TIMEOUT; + dev->watchdog_timeo = 5 * HZ; 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; dev->flags |= IFF_BROADCAST | IFF_MULTICAST; dev->set_multicast_list = wlan_set_multicast_list; + SET_NETDEV_DEV(dev, dmdev); + INIT_LIST_HEAD(&priv->adapter->cmdfreeq); INIT_LIST_HEAD(&priv->adapter->cmdpendingq); spin_lock_init(&priv->adapter->driver_lock); init_waitqueue_head(&priv->adapter->cmd_pending); priv->adapter->nr_cmd_pending = 0; + goto done; - lbs_pr_debug(1, "Starting kthread...\n"); +err_kzalloc: + free_netdev(dev); + priv = NULL; +done: + lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv); + return priv; +} +EXPORT_SYMBOL_GPL(libertas_add_card); + +int libertas_activate_card(wlan_private *priv, char *fw_name) +{ + struct net_device *dev = priv->dev; + int ret = -1; + + lbs_deb_enter(LBS_DEB_MAIN); + + lbs_deb_thread("Starting kthread...\n"); priv->mainthread.priv = priv; wlan_create_thread(wlan_service_main_thread, &priv->mainthread, "wlan_main_service"); priv->assoc_thread = create_singlethread_workqueue("libertas_assoc"); - INIT_DELAYED_WORK(&priv->assoc_work, wlan_association_worker); + INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker); /* * Register the device. Fillup the private data structure with * relevant information from the card and request for the required * IRQ. */ - if (libertas_sbi_register_dev(priv) < 0) { - lbs_pr_info("failed to register wlan device!\n"); + if (priv->hw_register_dev(priv) < 0) { + lbs_pr_err("failed to register WLAN device\n"); goto err_registerdev; } /* init FW and HW */ - if (libertas_init_fw(priv)) { - lbs_pr_debug(1, "Firmware Init failed\n"); + if (fw_name && libertas_init_fw(priv, fw_name)) { + lbs_pr_err("firmware init failed\n"); goto err_registerdev; } if (register_netdev(dev)) { - lbs_pr_err("Cannot register network device!\n"); + lbs_pr_err("cannot register ethX device\n"); goto err_init_fw; } - /* Register virtual mesh interface */ - if (register_netdev(mesh_dev)) { - lbs_pr_info("Cannot register mesh virtual interface!\n"); - goto err_init_fw; - } - - lbs_pr_info("%s: Marvell Wlan 802.11 adapter ", dev->name); + lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); libertas_debugfs_init_one(priv, dev); - if (libertas_found == MAX_DEVS) - goto err_init_fw; - libertas_devs[libertas_found] = dev; - libertas_found++; -#ifdef ENABLE_PM - if (!(wlan_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, wlan_pm_callback))) - lbs_pr_alert( "failed to register PM callback\n"); -#endif - if (device_create_file(&(mesh_dev->dev), &dev_attr_libertas_mpp)) - goto err_create_file; + ret = 0; + goto done; - LEAVE(); - return priv; - -err_create_file: - device_remove_file(&(mesh_dev->dev), &dev_attr_libertas_mpp); err_init_fw: - libertas_sbi_unregister_dev(priv); + priv->hw_unregister_dev(priv); err_registerdev: destroy_workqueue(priv->assoc_thread); /* Stop the thread servicing the interrupts */ wake_up_interruptible(&priv->mainthread.waitq); wlan_terminate_thread(&priv->mainthread); - kfree(priv->adapter); -err_kmalloc: - free_netdev(dev); +done: + lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); + return ret; +} +EXPORT_SYMBOL_GPL(libertas_activate_card); + + +/** + * @brief This function adds mshX interface + * + * @param priv A pointer to the wlan_private structure + * @return 0 if successful, -X otherwise + */ +int libertas_add_mesh(wlan_private *priv, struct device *dev) +{ + 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->set_mac_address = wlan_set_mac_address; + mesh_dev->ethtool_ops = &libertas_ethtool_ops; + memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, + sizeof(priv->dev->dev_addr)); + + SET_NETDEV_DEV(priv->mesh_dev, dev); + +#ifdef WIRELESS_EXT + mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_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); - wlanpriv = NULL; - LEAVE(); - return NULL; +done: + lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); + return ret; } +EXPORT_SYMBOL_GPL(libertas_add_mesh); static void wake_pending_cmdnodes(wlan_private *priv) { struct cmd_ctrl_node *cmdnode; unsigned long flags; + lbs_deb_enter(LBS_DEB_CMD); + spin_lock_irqsave(&priv->adapter->driver_lock, flags); list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) { cmdnode->cmdwaitqwoken = 1; @@ -1044,40 +975,29 @@ static void wake_pending_cmdnodes(wlan_private *priv) } -int wlan_remove_card(void *card) +int libertas_remove_card(wlan_private *priv) { - 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; - ENTER(); + lbs_deb_enter(LBS_DEB_NET); - if (!priv) { - LEAVE(); - return 0; - } + if (!priv) + goto out; adapter = priv->adapter; - if (!adapter) { - LEAVE(); - return 0; - } + if (!adapter) + goto out; - dev = priv->wlan_dev.netdev; - mesh_dev = priv->mesh_dev; + dev = priv->dev; - netif_stop_queue(mesh_dev); - netif_stop_queue(priv->wlan_dev.netdev); - netif_carrier_off(priv->wlan_dev.netdev); + netif_stop_queue(priv->dev); + netif_carrier_off(priv->dev); 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); @@ -1090,11 +1010,7 @@ int wlan_remove_card(void *card) memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN); wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); - -#ifdef ENABLE_PM - pm_unregister(wlan_pm_dev); -#endif + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); adapter->surpriseremoved = 1; @@ -1103,28 +1019,45 @@ int wlan_remove_card(void *card) libertas_debugfs_remove_one(priv); - lbs_pr_debug(1, "Free adapter\n"); + lbs_deb_net("free adapter\n"); libertas_free_adapter(priv); - for (i = 0; i<libertas_found; i++) { - if (libertas_devs[i]==priv->wlan_dev.netdev) { - libertas_devs[i] = libertas_devs[--libertas_found]; - libertas_devs[libertas_found] = NULL ; - break ; - } - } + lbs_deb_net("unregister finish\n"); - lbs_pr_debug(1, "Unregister finish\n"); + priv->dev = NULL; + free_netdev(dev); + +out: + lbs_deb_leave(LBS_DEB_NET); + return 0; +} +EXPORT_SYMBOL_GPL(libertas_remove_card); + + +void libertas_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); + netif_carrier_off(priv->mesh_dev); + + device_remove_file(&(mesh_dev->dev), &dev_attr_libertas_mpp); + unregister_netdev(mesh_dev); - priv->wlan_dev.netdev = NULL; priv->mesh_dev = NULL ; free_netdev(mesh_dev); - free_netdev(dev); - wlanpriv = NULL; - LEAVE(); - return 0; +out: + lbs_deb_leave(LBS_DEB_NET); } +EXPORT_SYMBOL_GPL(libertas_remove_mesh); /** * @brief This function finds the CFP in @@ -1139,33 +1072,34 @@ struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, int *c { int i, end; - ENTER(); + lbs_deb_enter(LBS_DEB_MAIN); end = sizeof(region_cfp_table)/sizeof(struct region_cfp_table); for (i = 0; i < end ; i++) { - lbs_pr_debug(1, "region_cfp_table[i].region=%d\n", + lbs_deb_main("region_cfp_table[i].region=%d\n", region_cfp_table[i].region); if (region_cfp_table[i].region == region) { *cfp_no = region_cfp_table[i].cfp_no_BG; - LEAVE(); + lbs_deb_leave(LBS_DEB_MAIN); return region_cfp_table[i].cfp_BG; } } - LEAVE(); + lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL"); return NULL; } int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band) { wlan_adapter *adapter = priv->adapter; + int ret = 0; int i = 0; struct chan_freq_power *cfp; int cfp_no; - ENTER(); + lbs_deb_enter(LBS_DEB_MAIN); memset(adapter->region_channel, 0, sizeof(adapter->region_channel)); @@ -1175,17 +1109,19 @@ int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band) adapter->region_channel[i].nrcfp = cfp_no; adapter->region_channel[i].CFP = cfp; } else { - lbs_pr_debug(1, "wrong region code %#x in band B-G\n", + lbs_deb_main("wrong region code %#x in band B/G\n", region); - return -1; + ret = -1; + goto out; } adapter->region_channel[i].valid = 1; adapter->region_channel[i].region = region; adapter->region_channel[i].band = band; i++; } - LEAVE(); - return 0; +out: + lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); + return ret; } /** @@ -1200,9 +1136,9 @@ void libertas_interrupt(struct net_device *dev) { wlan_private *priv = dev->priv; - ENTER(); + lbs_deb_enter(LBS_DEB_THREAD); - lbs_pr_debug(1, "libertas_interrupt: intcounter=%d\n", + lbs_deb_thread("libertas_interrupt: intcounter=%d\n", priv->adapter->intcounter); priv->adapter->intcounter++; @@ -1210,56 +1146,35 @@ void libertas_interrupt(struct net_device *dev) if (priv->adapter->psstate == PS_STATE_SLEEP) { priv->adapter->psstate = PS_STATE_AWAKE; netif_wake_queue(dev); + netif_wake_queue(priv->mesh_dev); } wake_up_interruptible(&priv->mainthread.waitq); - LEAVE(); + lbs_deb_leave(LBS_DEB_THREAD); } +EXPORT_SYMBOL_GPL(libertas_interrupt); -static int wlan_init_module(void) +static int libertas_init_module(void) { - int ret = 0; - - ENTER(); - - if (libertas_fw_name == NULL) { - libertas_fw_name = default_fw_name; - } - + lbs_deb_enter(LBS_DEB_MAIN); libertas_debugfs_init(); - - if (libertas_sbi_register()) { - ret = -1; - libertas_debugfs_remove(); - goto done; - } - -done: - LEAVE(); - return ret; + lbs_deb_leave(LBS_DEB_MAIN); + return 0; } -static void wlan_cleanup_module(void) +static void libertas_exit_module(void) { - int i; - - ENTER(); - - for (i = 0; i<libertas_found; i++) { - wlan_private *priv = libertas_devs[i]->priv; - reset_device(priv); - } + lbs_deb_enter(LBS_DEB_MAIN); - libertas_sbi_unregister(); libertas_debugfs_remove(); - LEAVE(); + lbs_deb_leave(LBS_DEB_MAIN); } -module_init(wlan_init_module); -module_exit(wlan_cleanup_module); +module_init(libertas_init_module); +module_exit(libertas_exit_module); -MODULE_DESCRIPTION("M-WLAN Driver"); +MODULE_DESCRIPTION("Libertas WLAN Driver Library"); MODULE_AUTHOR("Marvell International Ltd."); MODULE_LICENSE("GPL"); |