Skip to content

Commit

Permalink
mwifiex: add support for Marvell USB8797 chipset
Browse files Browse the repository at this point in the history
This patch supports Avastar 88W8797 chipset with USB interface.

The corresponding firmware image file is located at:
"mrvl/usb8797_uapsta.bin"

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Frank Huang <frankh@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Amitkumar Karwar authored and John W. Linville committed Apr 23, 2012
1 parent aee286c commit 4daffe3
Show file tree
Hide file tree
Showing 17 changed files with 1,399 additions and 71 deletions.
36 changes: 21 additions & 15 deletions drivers/net/wireless/mwifiex/11n_aggr.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,21 +233,27 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,

skb_push(skb_aggr, headroom);

/*
* Padding per MSDU will affect the length of next
* packet and hence the exact length of next packet
* is uncertain here.
*
* Also, aggregation of transmission buffer, while
* downloading the data to the card, wont gain much
* on the AMSDU packets as the AMSDU packets utilizes
* the transmission buffer space to the maximum
* (adapter->tx_buf_size).
*/
tx_param.next_pkt_len = 0;

ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
skb_aggr, &tx_param);
if (adapter->iface_type == MWIFIEX_USB) {
adapter->data_sent = true;
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA,
skb_aggr, NULL);
} else {
/*
* Padding per MSDU will affect the length of next
* packet and hence the exact length of next packet
* is uncertain here.
*
* Also, aggregation of transmission buffer, while
* downloading the data to the card, wont gain much
* on the AMSDU packets as the AMSDU packets utilizes
* the transmission buffer space to the maximum
* (adapter->tx_buf_size).
*/
tx_param.next_pkt_len = 0;

ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
skb_aggr, &tx_param);
}
switch (ret) {
case -EBUSY:
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
Expand Down
11 changes: 11 additions & 0 deletions drivers/net/wireless/mwifiex/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,14 @@ config MWIFIEX_PCIE

If you choose to build it as a module, it will be called
mwifiex_pcie.

config MWIFIEX_USB
tristate "Marvell WiFi-Ex Driver for USB8797"
depends on MWIFIEX && USB
select FW_LOADER
---help---
This adds support for wireless adapters based on Marvell
Avastar 88W8797 chipset with USB interface.

If you choose to build it as a module, it will be called
mwifiex_usb.
3 changes: 3 additions & 0 deletions drivers/net/wireless/mwifiex/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o

mwifiex_pcie-y += pcie.o
obj-$(CONFIG_MWIFIEX_PCIE) += mwifiex_pcie.o

mwifiex_usb-y += usb.o
obj-$(CONFIG_MWIFIEX_USB) += mwifiex_usb.o
63 changes: 52 additions & 11 deletions drivers/net/wireless/mwifiex/cmdevt.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
uint16_t cmd_size;
struct timeval tstamp;
unsigned long flags;
__le32 tmp;

if (!adapter || !cmd_node)
return -1;
Expand Down Expand Up @@ -178,15 +179,28 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size,
le16_to_cpu(host_cmd->seq_num));

skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN);

ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
cmd_node->cmd_skb, NULL);

skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN);
if (adapter->iface_type == MWIFIEX_USB) {
tmp = cpu_to_le32(MWIFIEX_USB_TYPE_CMD);
skb_push(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN);
memcpy(cmd_node->cmd_skb->data, &tmp, MWIFIEX_TYPE_LEN);
adapter->cmd_sent = true;
ret = adapter->if_ops.host_to_card(adapter,
MWIFIEX_USB_EP_CMD_EVENT,
cmd_node->cmd_skb, NULL);
skb_pull(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN);
if (ret == -EBUSY)
cmd_node->cmd_skb = NULL;
} else {
skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
cmd_node->cmd_skb, NULL);
skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN);
}

if (ret == -1) {
dev_err(adapter->dev, "DNLD_CMD: host to card failed\n");
if (adapter->iface_type == MWIFIEX_USB)
adapter->cmd_sent = false;
if (cmd_node->wait_q_enabled)
adapter->cmd_wait_q.status = -1;
mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
Expand Down Expand Up @@ -232,6 +246,9 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
struct mwifiex_opt_sleep_confirm *sleep_cfm_buf =
(struct mwifiex_opt_sleep_confirm *)
adapter->sleep_cfm->data;
struct sk_buff *sleep_cfm_tmp;
__le32 tmp;

priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);

sleep_cfm_buf->seq_num =
Expand All @@ -240,10 +257,28 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
priv->bss_type)));
adapter->seq_num++;

skb_push(adapter->sleep_cfm, INTF_HEADER_LEN);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
adapter->sleep_cfm, NULL);
skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN);
if (adapter->iface_type == MWIFIEX_USB) {
sleep_cfm_tmp =
dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
+ MWIFIEX_TYPE_LEN);
skb_put(sleep_cfm_tmp, sizeof(struct mwifiex_opt_sleep_confirm)
+ MWIFIEX_TYPE_LEN);
tmp = cpu_to_le32(MWIFIEX_USB_TYPE_CMD);
memcpy(sleep_cfm_tmp->data, &tmp, MWIFIEX_TYPE_LEN);
memcpy(sleep_cfm_tmp->data + MWIFIEX_TYPE_LEN,
adapter->sleep_cfm->data,
sizeof(struct mwifiex_opt_sleep_confirm));
ret = adapter->if_ops.host_to_card(adapter,
MWIFIEX_USB_EP_CMD_EVENT,
sleep_cfm_tmp, NULL);
if (ret != -EBUSY)
dev_kfree_skb_any(sleep_cfm_tmp);
} else {
skb_push(adapter->sleep_cfm, INTF_HEADER_LEN);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
adapter->sleep_cfm, NULL);
skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN);
}

if (ret == -1) {
dev_err(adapter->dev, "SLEEP_CFM: failed\n");
Expand Down Expand Up @@ -343,7 +378,12 @@ int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter)
}
if (!cmd_array[i].resp_skb)
continue;
dev_kfree_skb_any(cmd_array[i].resp_skb);

if (adapter->iface_type == MWIFIEX_USB)
adapter->if_ops.cmdrsp_complete(adapter,
cmd_array[i].resp_skb);
else
dev_kfree_skb_any(cmd_array[i].resp_skb);
}
/* Release struct cmd_ctrl_node */
if (adapter->cmd_pool) {
Expand Down Expand Up @@ -1083,6 +1123,7 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter)
MWIFIEX_BSS_ROLE_ANY),
false);
}
EXPORT_SYMBOL_GPL(mwifiex_process_hs_config);

/*
* This function handles the command response of a sleep confirm command.
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/mwifiex/decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#define MWIFIEX_RATE_BITMAP_MCS127 159

#define MWIFIEX_RX_DATA_BUF_SIZE (4 * 1024)
#define MWIFIEX_RX_CMD_BUF_SIZE (2 * 1024)

#define MWIFIEX_RTS_MIN_VALUE (0)
#define MWIFIEX_RTS_MAX_VALUE (2347)
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/mwifiex/fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ enum KEY_TYPE_ID {
#define FIRMWARE_READY_SDIO 0xfedc
#define FIRMWARE_READY_PCIE 0xfedcba00

enum mwifiex_usb_ep {
MWIFIEX_USB_EP_CMD_EVENT = 1,
MWIFIEX_USB_EP_DATA = 2,
};

enum MWIFIEX_802_11_PRIVACY_FILTER {
MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL,
MWIFIEX_802_11_PRIV_FILTER_8021X_WEP
Expand Down
64 changes: 43 additions & 21 deletions drivers/net/wireless/mwifiex/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,10 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)

adapter->cmd_sent = false;

if (adapter->iface_type == MWIFIEX_PCIE)
adapter->data_sent = false;
else
if (adapter->iface_type == MWIFIEX_SDIO)
adapter->data_sent = true;
else
adapter->data_sent = false;

adapter->cmd_resp_received = false;
adapter->event_received = false;
Expand Down Expand Up @@ -379,7 +379,8 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter)

dev_dbg(adapter->dev, "info: free scan table\n");

adapter->if_ops.cleanup_if(adapter);
if (adapter->if_ops.cleanup_if)
adapter->if_ops.cleanup_if(adapter);

if (adapter->sleep_cfm)
dev_kfree_skb_any(adapter->sleep_cfm);
Expand Down Expand Up @@ -419,6 +420,8 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
spin_lock_init(&adapter->cmd_pending_q_lock);
spin_lock_init(&adapter->scan_pending_q_lock);

skb_queue_head_init(&adapter->usb_rx_data_q);

for (i = 0; i < adapter->priv_num; ++i) {
INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head);
adapter->bss_prio_tbl[i].bss_prio_cur = NULL;
Expand Down Expand Up @@ -574,6 +577,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
struct mwifiex_private *priv;
s32 i;
unsigned long flags;
struct sk_buff *skb;

/* mwifiex already shutdown */
if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY)
Expand Down Expand Up @@ -601,6 +605,18 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)

spin_lock_irqsave(&adapter->mwifiex_lock, flags);

if (adapter->if_ops.data_complete) {
while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) {
struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);

priv = adapter->priv[rx_info->bss_num];
if (priv)
priv->stats.rx_dropped++;

adapter->if_ops.data_complete(adapter, skb);
}
}

/* Free adapter structure */
mwifiex_free_adapter(adapter);

Expand Down Expand Up @@ -630,24 +646,28 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
int ret;
u32 poll_num = 1;

adapter->winner = 0;
if (adapter->if_ops.check_fw_status) {
adapter->winner = 0;

/* Check if firmware is already running */
ret = adapter->if_ops.check_fw_status(adapter, poll_num);
if (!ret) {
dev_notice(adapter->dev,
"WLAN FW already running! Skip FW download\n");
goto done;
}
poll_num = MAX_FIRMWARE_POLL_TRIES;

/* Check if we are the winner for downloading FW */
if (!adapter->winner) {
dev_notice(adapter->dev,
"Other intf already running! Skip FW download\n");
poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
goto poll_fw;
/* check if firmware is already running */
ret = adapter->if_ops.check_fw_status(adapter, poll_num);
if (!ret) {
dev_notice(adapter->dev,
"WLAN FW already running! Skip FW dnld\n");
goto done;
}

poll_num = MAX_FIRMWARE_POLL_TRIES;

/* check if we are the winner for downloading FW */
if (!adapter->winner) {
dev_notice(adapter->dev,
"FW already running! Skip FW dnld\n");
poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
goto poll_fw;
}
}

if (pmfw) {
/* Download firmware with helper */
ret = adapter->if_ops.prog_fw(adapter, pmfw);
Expand All @@ -666,6 +686,8 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
}
done:
/* re-enable host interrupt for mwifiex after fw dnld is successful */
adapter->if_ops.enable_int(adapter);
if (adapter->if_ops.enable_int)
adapter->if_ops.enable_int(adapter);

return ret;
}
26 changes: 20 additions & 6 deletions drivers/net/wireless/mwifiex/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops));

/* card specific initialization has been deferred until now .. */
if (adapter->if_ops.init_if(adapter))
goto error;
if (adapter->if_ops.init_if)
if (adapter->if_ops.init_if(adapter))
goto error;

adapter->priv_num = 0;

Expand Down Expand Up @@ -140,6 +141,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
{
int ret = 0;
unsigned long flags;
struct sk_buff *skb;

spin_lock_irqsave(&adapter->main_proc_lock, flags);

Expand All @@ -161,7 +163,8 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
if (adapter->int_status) {
if (adapter->hs_activated)
mwifiex_process_hs_config(adapter);
adapter->if_ops.process_int_status(adapter);
if (adapter->if_ops.process_int_status)
adapter->if_ops.process_int_status(adapter);
}

/* Need to wake up the card ? */
Expand All @@ -174,6 +177,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
adapter->if_ops.wakeup(adapter);
continue;
}

if (IS_CARD_RX_RCVD(adapter)) {
adapter->pm_wakeup_fw_try = false;
if (adapter->ps_state == PS_STATE_SLEEP)
Expand All @@ -194,6 +198,11 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
}
}

/* Check Rx data for USB */
if (adapter->iface_type == MWIFIEX_USB)
while ((skb = skb_dequeue(&adapter->usb_rx_data_q)))
mwifiex_handle_rx_packet(adapter, skb);

/* Check for Cmd Resp */
if (adapter->cmd_resp_received) {
adapter->cmd_resp_received = false;
Expand Down Expand Up @@ -317,7 +326,10 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
fw.fw_buf = (u8 *) adapter->firmware->data;
fw.fw_len = adapter->firmware->size;

ret = mwifiex_dnld_fw(adapter, &fw);
if (adapter->if_ops.dnld_fw)
ret = adapter->if_ops.dnld_fw(adapter, &fw);
else
ret = mwifiex_dnld_fw(adapter, &fw);
if (ret == -1)
goto done;

Expand Down Expand Up @@ -731,7 +743,8 @@ mwifiex_add_card(void *card, struct semaphore *sem,

err_init_fw:
pr_debug("info: %s: unregister device\n", __func__);
adapter->if_ops.unregister_dev(adapter);
if (adapter->if_ops.unregister_dev)
adapter->if_ops.unregister_dev(adapter);
err_registerdev:
adapter->surprise_removed = true;
mwifiex_terminate_workqueue(adapter);
Expand Down Expand Up @@ -836,7 +849,8 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)

/* Unregister device */
dev_dbg(adapter->dev, "info: unregister device\n");
adapter->if_ops.unregister_dev(adapter);
if (adapter->if_ops.unregister_dev)
adapter->if_ops.unregister_dev(adapter);
/* Free adapter structure */
dev_dbg(adapter->dev, "info: free adapter\n");
mwifiex_free_adapter(adapter);
Expand Down
Loading

0 comments on commit 4daffe3

Please sign in to comment.