aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/libertas/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/main.c')
-rw-r--r--drivers/net/wireless/libertas/main.c278
1 files changed, 276 insertions, 2 deletions
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 03217f5537a..7e417eacbc7 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -794,6 +794,280 @@ static int libertas_thread(void *data)
}
/**
+ * @brief This function downloads firmware image, gets
+ * HW spec from firmware and set basic parameters to
+ * firmware.
+ *
+ * @param priv A pointer to wlan_private structure
+ * @return 0 or -1
+ */
+static int wlan_setup_station_hw(wlan_private * priv)
+{
+ int ret = -1;
+ wlan_adapter *adapter = priv->adapter;
+
+ 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
+ */
+ memset(adapter->current_addr, 0xff, ETH_ALEN);
+
+ ret = libertas_prepare_and_send_command(priv, CMD_GET_HW_SPEC,
+ 0, CMD_OPTION_WAITFORRSP, 0, NULL);
+
+ if (ret) {
+ ret = -1;
+ goto done;
+ }
+
+ libertas_set_mac_packet_filter(priv);
+
+ /* Get the supported Data rates */
+ ret = libertas_prepare_and_send_command(priv, CMD_802_11_DATA_RATE,
+ CMD_ACT_GET_TX_RATE,
+ CMD_OPTION_WAITFORRSP, 0, NULL);
+
+ if (ret) {
+ ret = -1;
+ goto done;
+ }
+
+ ret = 0;
+done:
+ lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
+ 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.
+ */
+static void command_timer_fn(unsigned long data)
+{
+ wlan_private *priv = (wlan_private *)data;
+ wlan_adapter *adapter = priv->adapter;
+ struct cmd_ctrl_node *ptempnode;
+ struct cmd_ds_command *cmd;
+ unsigned long flags;
+
+ ptempnode = adapter->cur_cmd;
+ if (ptempnode == NULL) {
+ lbs_deb_fw("ptempnode empty\n");
+ return;
+ }
+
+ cmd = (struct cmd_ds_command *)ptempnode->bufvirtualaddr;
+ if (!cmd) {
+ lbs_deb_fw("cmd is NULL\n");
+ return;
+ }
+
+ lbs_deb_fw("command_timer_fn fired, cmd %x\n", cmd->command);
+
+ if (!adapter->fw_ready)
+ return;
+
+ spin_lock_irqsave(&adapter->driver_lock, flags);
+ adapter->cur_cmd = NULL;
+ spin_unlock_irqrestore(&adapter->driver_lock, flags);
+
+ lbs_deb_fw("re-sending same command because of timeout\n");
+ libertas_queue_cmd(adapter, ptempnode, 0);
+
+ wake_up_interruptible(&priv->waitq);
+
+ return;
+}
+
+static int wlan_allocate_adapter(wlan_private * priv)
+{
+ size_t bufsize;
+ wlan_adapter *adapter = priv->adapter;
+
+ /* 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;
+ }
+
+ /* Allocate the command buffers */
+ libertas_allocate_cmd_buffer(priv);
+
+ 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->scanprobes = 0;
+
+ adapter->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
+ adapter->data_avg_factor = DEFAULT_DATA_AVG_FACTOR;
+
+ /* ATIM params */
+ adapter->atimwindow = 0;
+
+ adapter->connect_status = LIBERTAS_DISCONNECTED;
+ memset(adapter->current_addr, 0xff, ETH_ALEN);
+
+ /* scan type */
+ adapter->scantype = CMD_SCAN_TYPE_ACTIVE;
+
+ /* scan mode */
+ adapter->scanmode = CMD_BSS_TYPE_ANY;
+
+ /* 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->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);
+
+ adapter->prescan = 1;
+
+ 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->radioon = RADIO_ON;
+ adapter->txantenna = RF_ANTENNA_2;
+ adapter->rxantenna = RF_ANTENNA_AUTO;
+
+ adapter->auto_rate = 1;
+ adapter->cur_rate = 0;
+ adapter->adhoc_grate_enabled = 0;
+
+ adapter->beaconperiod = MRVDRV_BEACON_INTERVAL;
+
+ // set default capabilities
+ adapter->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
+
+ adapter->psmode = WLAN802_11POWERMODECAM;
+ adapter->multipledtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;
+
+ adapter->listeninterval = MRVDRV_DEFAULT_LISTEN_INTERVAL;
+
+ adapter->psstate = PS_STATE_FULL_POWER;
+ adapter->needtowakeup = 0;
+ adapter->locallisteninterval = 0; /* default value in firmware will be used */
+
+ adapter->intcounter = 0;
+
+ adapter->currenttxskb = NULL;
+ adapter->pkttxctrl = 0;
+
+ 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;
+}
+
+void libertas_free_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 libertas_init_fw(wlan_private * priv)
+{
+ int ret = -1;
+ wlan_adapter *adapter = priv->adapter;
+
+ lbs_deb_enter(LBS_DEB_FW);
+
+ /* Allocate adapter structure */
+ if ((ret = wlan_allocate_adapter(priv)) != 0)
+ goto done;
+
+ /* init adapter structure */
+ wlan_init_adapter(priv);
+
+ /* init timer etc. */
+ setup_timer(&adapter->command_timer, command_timer_fn,
+ (unsigned long)priv);
+
+ /* download fimrware etc. */
+ if ((ret = wlan_setup_station_hw(priv)) != 0) {
+ del_timer_sync(&adapter->command_timer);
+ goto done;
+ }
+
+ /* init 802.11d */
+ libertas_init_11d(priv);
+
+ ret = 0;
+done:
+ lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
+ return ret;
+}
+
+/**
* @brief This function adds the card. it will probe the
* card, allocate the wlan_priv and initialize the device.
*
@@ -863,7 +1137,7 @@ done:
}
EXPORT_SYMBOL_GPL(libertas_add_card);
-int libertas_activate_card(wlan_private *priv, char *fw_name)
+int libertas_activate_card(wlan_private *priv)
{
struct net_device *dev = priv->dev;
int ret = -1;
@@ -894,7 +1168,7 @@ int libertas_activate_card(wlan_private *priv, char *fw_name)
}
/* init FW and HW */
- if (fw_name && libertas_init_fw(priv, fw_name)) {
+ if (libertas_init_fw(priv)) {
lbs_pr_err("firmware init failed\n");
goto err_registerdev;
}