summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/main.c
diff options
context:
space:
mode:
authorDan Williams2007-08-20 17:43:25 +0200
committerDavid S. Miller2007-10-11 01:50:34 +0200
commit954ee164f4f4598afc172c0ec3865d0352e55a0b (patch)
tree51aae73210d22c0a91282a52b5198cfa1ad068b4 /drivers/net/wireless/libertas/main.c
parent[PATCH] libertas: fix inadvertant removal of bits from commit 831441862956fff... (diff)
downloadkernel-qcow2-linux-954ee164f4f4598afc172c0ec3865d0352e55a0b.tar.gz
kernel-qcow2-linux-954ee164f4f4598afc172c0ec3865d0352e55a0b.tar.xz
kernel-qcow2-linux-954ee164f4f4598afc172c0ec3865d0352e55a0b.zip
[PATCH] libertas: reorganize and simplify init sequence
This patch moves all firmware load responsibility into the interface-specific code and gets rid of the firmware pointer in the generic card structure. It also removes 3 fairly unecessary callbacks: hw_register_dev, hw_unregister_dev, and hw_prog_firmware. It also makes the init sequence from interface probe functions more logical, as there are paired add/remove and start/stop calls into generic libertas code. Because the USB driver code uses the same TX URB callback for both firmware upload (where the generic libertas structure isn't initialized yet) and for normal operation (where it is), some bits of USB code have to deal with 'priv' being NULL. All USB firmware upload bits have been changed to not require 'priv' at all, but simply the USB card structure. Signed-off-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/main.c')
-rw-r--r--drivers/net/wireless/libertas/main.c405
1 files changed, 162 insertions, 243 deletions
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index ce1c18ee6280..6304bd97d399 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -791,7 +791,6 @@ static int libertas_thread(void *data)
} else
spin_unlock_irq(&adapter->driver_lock);
-
lbs_deb_thread(
"main-thread 222 (waking up): intcounter=%d currenttxskb=%p "
"dnld_sent=%d\n", adapter->intcounter,
@@ -926,7 +925,7 @@ static int libertas_thread(void *data)
* @param priv A pointer to wlan_private structure
* @return 0 or -1
*/
-static int wlan_setup_station_hw(wlan_private * priv)
+static int wlan_setup_firmware(wlan_private * priv)
{
int ret = -1;
wlan_adapter *adapter = priv->adapter;
@@ -934,14 +933,6 @@ static int wlan_setup_station_hw(wlan_private * priv)
lbs_deb_enter(LBS_DEB_FW);
- ret = priv->hw_prog_firmware(priv);
-
- if (ret) {
- lbs_deb_fw("bootloader in invalid state\n");
- ret = -1;
- goto done;
- }
-
/*
* Read MAC address from HW
*/
@@ -992,8 +983,6 @@ done:
return ret;
}
-static void command_timer_fn(unsigned long data);
-
/**
* This function handles the timeout of command sending.
* It will re-send the same command again.
@@ -1035,155 +1024,99 @@ static void command_timer_fn(unsigned long data)
return;
}
-static void libertas_free_adapter(wlan_private * priv)
+static int libertas_init_adapter(wlan_private * priv)
{
wlan_adapter *adapter = priv->adapter;
-
- if (!adapter) {
- lbs_deb_fw("why double free adapter?\n");
- return;
- }
-
- lbs_deb_fw("free command buffer\n");
- libertas_free_cmd_buffer(priv);
-
- lbs_deb_fw("free command_timer\n");
- del_timer(&adapter->command_timer);
-
- lbs_deb_fw("free scan results table\n");
- kfree(adapter->networks);
- adapter->networks = NULL;
-
- /* Free the adapter object itself */
- lbs_deb_fw("free adapter\n");
- kfree(adapter);
- priv->adapter = NULL;
-}
-
-static int wlan_allocate_adapter(wlan_private * priv)
-{
size_t bufsize;
- wlan_adapter *adapter = priv->adapter;
+ int i, ret = 0;
/* Allocate buffer to store the BSSID list */
bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
adapter->networks = kzalloc(bufsize, GFP_KERNEL);
if (!adapter->networks) {
lbs_pr_err("Out of memory allocating beacons\n");
- libertas_free_adapter(priv);
- return -ENOMEM;
+ ret = -1;
+ goto out;
}
- /* Allocate the command buffers */
- libertas_allocate_cmd_buffer(priv);
+ /* Initialize scan result lists */
+ INIT_LIST_HEAD(&adapter->network_free_list);
+ INIT_LIST_HEAD(&adapter->network_list);
+ for (i = 0; i < MAX_NETWORK_COUNT; i++) {
+ list_add_tail(&adapter->networks[i].list,
+ &adapter->network_free_list);
+ }
- memset(&adapter->libertas_ps_confirm_sleep, 0, sizeof(struct PS_CMD_ConfirmSleep));
adapter->libertas_ps_confirm_sleep.seqnum = cpu_to_le16(++adapter->seqnum);
adapter->libertas_ps_confirm_sleep.command =
cpu_to_le16(CMD_802_11_PS_MODE);
adapter->libertas_ps_confirm_sleep.size =
cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep));
- adapter->libertas_ps_confirm_sleep.result = 0;
adapter->libertas_ps_confirm_sleep.action =
cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
- return 0;
-}
-
-static void wlan_init_adapter(wlan_private * priv)
-{
- wlan_adapter *adapter = priv->adapter;
- int i;
-
- adapter->connect_status = LIBERTAS_DISCONNECTED;
memset(adapter->current_addr, 0xff, ETH_ALEN);
- /* 802.11 specific */
- adapter->secinfo.wep_enabled = 0;
- for (i = 0; i < sizeof(adapter->wep_keys) / sizeof(adapter->wep_keys[0]);
- i++)
- memset(&adapter->wep_keys[i], 0, sizeof(struct enc_key));
- adapter->wep_tx_keyidx = 0;
+ adapter->connect_status = LIBERTAS_DISCONNECTED;
adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
adapter->mode = IW_MODE_INFRA;
-
- adapter->pending_assoc_req = NULL;
- adapter->in_progress_assoc_req = NULL;
-
- /* Initialize scan result lists */
- INIT_LIST_HEAD(&adapter->network_free_list);
- INIT_LIST_HEAD(&adapter->network_list);
- for (i = 0; i < MAX_NETWORK_COUNT; i++) {
- list_add_tail(&adapter->networks[i].list,
- &adapter->network_free_list);
- }
-
- mutex_init(&adapter->lock);
-
- memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams));
adapter->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
-
- /* PnP and power profile */
- adapter->surpriseremoved = 0;
-
- adapter->currentpacketfilter =
- CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
-
+ adapter->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
adapter->radioon = RADIO_ON;
-
adapter->auto_rate = 1;
- adapter->cur_rate = 0;
-
- // set default capabilities
adapter->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
-
adapter->psmode = WLAN802_11POWERMODECAM;
-
adapter->psstate = PS_STATE_FULL_POWER;
- adapter->needtowakeup = 0;
- adapter->intcounter = 0;
-
- adapter->currenttxskb = NULL;
+ mutex_init(&adapter->lock);
memset(&adapter->tx_queue_ps, 0, NR_TX_QUEUE*sizeof(struct sk_buff*));
adapter->tx_queue_idx = 0;
spin_lock_init(&adapter->txqueue_lock);
- return;
-}
+ setup_timer(&adapter->command_timer, command_timer_fn,
+ (unsigned long)priv);
-static int libertas_init_fw(wlan_private * priv)
-{
- int ret = -1;
- wlan_adapter *adapter = priv->adapter;
+ INIT_LIST_HEAD(&adapter->cmdfreeq);
+ INIT_LIST_HEAD(&adapter->cmdpendingq);
- lbs_deb_enter(LBS_DEB_FW);
+ spin_lock_init(&adapter->driver_lock);
+ init_waitqueue_head(&adapter->cmd_pending);
+ adapter->nr_cmd_pending = 0;
- /* Allocate adapter structure */
- if ((ret = wlan_allocate_adapter(priv)) != 0)
- goto done;
+ /* Allocate the command buffers */
+ if (libertas_allocate_cmd_buffer(priv)) {
+ lbs_pr_err("Out of memory allocating command buffers\n");
+ ret = -1;
+ }
- /* init adapter structure */
- wlan_init_adapter(priv);
+out:
+ return ret;
+}
- /* init timer etc. */
- setup_timer(&adapter->command_timer, command_timer_fn,
- (unsigned long)priv);
+static void libertas_free_adapter(wlan_private * priv)
+{
+ wlan_adapter *adapter = priv->adapter;
- /* download fimrware etc. */
- if ((ret = wlan_setup_station_hw(priv)) != 0) {
- del_timer_sync(&adapter->command_timer);
- goto done;
+ if (!adapter) {
+ lbs_deb_fw("why double free adapter?\n");
+ return;
}
- /* init 802.11d */
- libertas_init_11d(priv);
+ lbs_deb_fw("free command buffer\n");
+ libertas_free_cmd_buffer(priv);
- ret = 0;
-done:
- lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
- return ret;
+ lbs_deb_fw("free command_timer\n");
+ del_timer(&adapter->command_timer);
+
+ lbs_deb_fw("free scan results table\n");
+ kfree(adapter->networks);
+ adapter->networks = NULL;
+
+ /* Free the adapter object itself */
+ lbs_deb_fw("free adapter\n");
+ kfree(adapter);
+ priv->adapter = NULL;
}
/**
@@ -1203,9 +1136,9 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev)
/* Allocate an Ethernet device and register it */
if (!(dev = alloc_etherdev(sizeof(wlan_private)))) {
lbs_pr_err("init ethX device failed\n");
- return NULL;
+ goto done;
}
- priv = dev->priv;
+ dmdev->driver_data = priv = dev->priv;
/* allocate buffer for wlan_adapter */
if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
@@ -1213,10 +1146,16 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev)
goto err_kzalloc;
}
+ if (libertas_init_adapter(priv)) {
+ lbs_pr_err("failed to initialize adapter structure.\n");
+ goto err_init_adapter;
+ }
+
priv->dev = dev;
priv->card = card;
priv->mesh_open = 0;
priv->infra_open = 0;
+ priv->hotplug_device = dmdev;
SET_MODULE_OWNER(dev);
@@ -1239,87 +1178,144 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev)
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;
priv->rtap_net_dev = NULL;
if (device_create_file(dmdev, &dev_attr_libertas_rtap))
- goto err_kzalloc;
+ goto err_init_adapter;
+
+ lbs_deb_thread("Starting main thread...\n");
+ init_waitqueue_head(&priv->waitq);
+ priv->main_thread = kthread_run(libertas_thread, dev, "libertas_main");
+ if (IS_ERR(priv->main_thread)) {
+ lbs_deb_thread("Error creating main thread.\n");
+ goto err_kthread_run;
+ }
+
+ priv->work_thread = create_singlethread_workqueue("libertas_worker");
+ INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker);
+ INIT_DELAYED_WORK(&priv->scan_work, libertas_scan_worker);
+ INIT_WORK(&priv->sync_channel, libertas_sync_channel);
+
goto done;
+err_kthread_run:
+ device_remove_file(dmdev, &dev_attr_libertas_rtap);
+
+err_init_adapter:
+ libertas_free_adapter(priv);
+
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)
+
+int libertas_remove_card(wlan_private *priv)
{
+ wlan_adapter *adapter = priv->adapter;
struct net_device *dev = priv->dev;
- int ret = -1;
+ union iwreq_data wrqu;
lbs_deb_enter(LBS_DEB_MAIN);
- lbs_deb_thread("Starting main thread...\n");
- init_waitqueue_head(&priv->waitq);
- priv->main_thread = kthread_run(libertas_thread, dev, "libertas_main");
- if (IS_ERR(priv->main_thread)) {
- lbs_deb_thread("Error creating main thread.\n");
- goto done;
- }
+ libertas_remove_rtap(priv);
- priv->work_thread = create_singlethread_workqueue("libertas_worker");
- INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker);
- INIT_DELAYED_WORK(&priv->scan_work, libertas_scan_worker);
+ dev = priv->dev;
+ device_remove_file(priv->hotplug_device, &dev_attr_libertas_rtap);
- INIT_WORK(&priv->sync_channel, libertas_sync_channel);
+ cancel_delayed_work(&priv->scan_work);
+ cancel_delayed_work(&priv->assoc_work);
+ destroy_workqueue(priv->work_thread);
- /*
- * Register the device. Fillup the private data structure with
- * relevant information from the card and request for the required
- * IRQ.
- */
- if (priv->hw_register_dev(priv) < 0) {
- lbs_pr_err("failed to register WLAN device\n");
- goto err_registerdev;
+ if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) {
+ adapter->psmode = WLAN802_11POWERMODECAM;
+ libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
}
- /* init FW and HW */
- if (libertas_init_fw(priv)) {
- lbs_pr_err("firmware init failed\n");
- goto err_registerdev;
- }
+ memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+
+ /* Stop the thread servicing the interrupts */
+ adapter->surpriseremoved = 1;
+ kthread_stop(priv->main_thread);
+
+ libertas_free_adapter(priv);
+
+ priv->dev = NULL;
+ free_netdev(dev);
+
+ lbs_deb_leave(LBS_DEB_MAIN);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(libertas_remove_card);
+
+
+int libertas_start_card(wlan_private *priv)
+{
+ struct net_device *dev = priv->dev;
+ int ret = -1;
+
+ lbs_deb_enter(LBS_DEB_MAIN);
+
+ /* poke the firmware */
+ ret = wlan_setup_firmware(priv);
+ if (ret)
+ goto done;
+
+ /* init 802.11d */
+ libertas_init_11d(priv);
if (register_netdev(dev)) {
lbs_pr_err("cannot register ethX device\n");
- goto err_init_fw;
+ goto done;
}
- lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
-
libertas_debugfs_init_one(priv, dev);
+ lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
+
ret = 0;
- goto done;
-err_init_fw:
- priv->hw_unregister_dev(priv);
-err_registerdev:
- destroy_workqueue(priv->work_thread);
- /* Stop the thread servicing the interrupts */
- wake_up_interruptible(&priv->waitq);
- kthread_stop(priv->main_thread);
done:
- lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+ lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
return ret;
}
-EXPORT_SYMBOL_GPL(libertas_activate_card);
+EXPORT_SYMBOL_GPL(libertas_start_card);
+
+
+int libertas_stop_card(wlan_private *priv)
+{
+ struct net_device *dev = priv->dev;
+ int ret = -1;
+ struct cmd_ctrl_node *cmdnode;
+ unsigned long flags;
+
+ lbs_deb_enter(LBS_DEB_MAIN);
+
+ netif_stop_queue(priv->dev);
+ netif_carrier_off(priv->dev);
+
+ libertas_debugfs_remove_one(priv);
+
+ /* Flush pending command nodes */
+ spin_lock_irqsave(&priv->adapter->driver_lock, flags);
+ list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) {
+ cmdnode->cmdwaitqwoken = 1;
+ wake_up_interruptible(&cmdnode->cmdwait_q);
+ }
+ spin_unlock_irqrestore(&priv->adapter->driver_lock, flags);
+
+ unregister_netdev(dev);
+
+ lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(libertas_stop_card);
/**
@@ -1389,89 +1385,12 @@ done:
}
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_HOST);
-
- spin_lock_irqsave(&priv->adapter->driver_lock, flags);
- list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) {
- cmdnode->cmdwaitqwoken = 1;
- wake_up_interruptible(&cmdnode->cmdwait_q);
- }
- spin_unlock_irqrestore(&priv->adapter->driver_lock, flags);
-}
-
-
-int libertas_remove_card(wlan_private *priv)
-{
- wlan_adapter *adapter;
- struct net_device *dev;
- union iwreq_data wrqu;
-
- lbs_deb_enter(LBS_DEB_NET);
-
- libertas_remove_rtap(priv);
- if (!priv)
- goto out;
-
- adapter = priv->adapter;
-
- if (!adapter)
- goto out;
-
- dev = priv->dev;
- device_remove_file(priv->hotplug_device, &dev_attr_libertas_rtap);
-
- netif_stop_queue(priv->dev);
- netif_carrier_off(priv->dev);
-
- wake_pending_cmdnodes(priv);
-
- unregister_netdev(dev);
-
- cancel_delayed_work(&priv->scan_work);
- cancel_delayed_work(&priv->assoc_work);
- destroy_workqueue(priv->work_thread);
-
- if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) {
- adapter->psmode = WLAN802_11POWERMODECAM;
- libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
- }
-
- memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-
- adapter->surpriseremoved = 1;
-
- /* Stop the thread servicing the interrupts */
- kthread_stop(priv->main_thread);
-
- libertas_debugfs_remove_one(priv);
-
- lbs_deb_net("free adapter\n");
- libertas_free_adapter(priv);
-
- lbs_deb_net("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);
+ lbs_deb_enter(LBS_DEB_MAIN);
if (!priv)
goto out;
@@ -1488,7 +1407,7 @@ void libertas_remove_mesh(wlan_private *priv)
free_netdev(mesh_dev);
out:
- lbs_deb_leave(LBS_DEB_NET);
+ lbs_deb_leave(LBS_DEB_MAIN);
}
EXPORT_SYMBOL_GPL(libertas_remove_mesh);