diff options
author | Amitkumar Karwar <akarwar@marvell.com> | 2011-10-11 20:41:21 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-10-12 14:41:44 -0400 |
commit | d930faee141bd0a6a4873791996c5354c9a85ca7 (patch) | |
tree | c0ce085b87900d346cd3442cb1756aea060d416f | |
parent | ec205999d31bbb1208ab59c3b6d22c47cca74257 (diff) |
mwifiex: add support for Marvell pcie8766 chipset
This patch supports 88W8766P chipset with a PCIe interface.
The corresponding firmware image file is located at:
"mrvl/pcie8766_uapsta.bin"
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Ramesh Radhakrishnan <rramesh@marvell.com>
Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: Frank Huang <frankh@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/mwifiex/11n_aggr.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/Kconfig | 11 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/cmdevt.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/fw.h | 30 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/init.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 20 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/pcie.c | 1948 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/pcie.h | 148 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sdio.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sdio.h | 24 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_cmd.c | 64 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_cmdresp.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_tx.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/txrx.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/util.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.c | 4 |
18 files changed, 2284 insertions, 37 deletions
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 9e63d16365e3..079e5532e686 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c | |||
@@ -246,8 +246,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
246 | tx_param.next_pkt_len = 0; | 246 | tx_param.next_pkt_len = 0; |
247 | 247 | ||
248 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, | 248 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, |
249 | skb_aggr->data, | 249 | skb_aggr, &tx_param); |
250 | skb_aggr->len, &tx_param); | ||
251 | switch (ret) { | 250 | switch (ret) { |
252 | case -EBUSY: | 251 | case -EBUSY: |
253 | spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); | 252 | spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); |
diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig index 86962920cef3..8f2797aa0c60 100644 --- a/drivers/net/wireless/mwifiex/Kconfig +++ b/drivers/net/wireless/mwifiex/Kconfig | |||
@@ -19,3 +19,14 @@ config MWIFIEX_SDIO | |||
19 | 19 | ||
20 | If you choose to build it as a module, it will be called | 20 | If you choose to build it as a module, it will be called |
21 | mwifiex_sdio. | 21 | mwifiex_sdio. |
22 | |||
23 | config MWIFIEX_PCIE | ||
24 | tristate "Marvell WiFi-Ex Driver for PCIE 8766" | ||
25 | depends on MWIFIEX && PCI | ||
26 | select FW_LOADER | ||
27 | ---help--- | ||
28 | This adds support for wireless adapters based on Marvell | ||
29 | 8766 chipset with PCIe interface. | ||
30 | |||
31 | If you choose to build it as a module, it will be called | ||
32 | mwifiex_pcie. | ||
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile index 42cb733ea33a..b0257ad1bbed 100644 --- a/drivers/net/wireless/mwifiex/Makefile +++ b/drivers/net/wireless/mwifiex/Makefile | |||
@@ -39,3 +39,6 @@ obj-$(CONFIG_MWIFIEX) += mwifiex.o | |||
39 | 39 | ||
40 | mwifiex_sdio-y += sdio.o | 40 | mwifiex_sdio-y += sdio.o |
41 | obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o | 41 | obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o |
42 | |||
43 | mwifiex_pcie-y += pcie.o | ||
44 | obj-$(CONFIG_MWIFIEX_PCIE) += mwifiex_pcie.o | ||
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index d12e25d0c880..508de7f6d9c1 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -94,7 +94,7 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, | |||
94 | skb_trim(cmd_node->cmd_skb, 0); | 94 | skb_trim(cmd_node->cmd_skb, 0); |
95 | 95 | ||
96 | if (cmd_node->resp_skb) { | 96 | if (cmd_node->resp_skb) { |
97 | dev_kfree_skb_any(cmd_node->resp_skb); | 97 | adapter->if_ops.cmdrsp_complete(adapter, cmd_node->resp_skb); |
98 | cmd_node->resp_skb = NULL; | 98 | cmd_node->resp_skb = NULL; |
99 | } | 99 | } |
100 | } | 100 | } |
@@ -176,8 +176,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
176 | skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN); | 176 | skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN); |
177 | 177 | ||
178 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, | 178 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, |
179 | cmd_node->cmd_skb->data, | 179 | cmd_node->cmd_skb, NULL); |
180 | cmd_node->cmd_skb->len, NULL); | ||
181 | 180 | ||
182 | skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN); | 181 | skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN); |
183 | 182 | ||
@@ -238,8 +237,7 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) | |||
238 | 237 | ||
239 | skb_push(adapter->sleep_cfm, INTF_HEADER_LEN); | 238 | skb_push(adapter->sleep_cfm, INTF_HEADER_LEN); |
240 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, | 239 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, |
241 | adapter->sleep_cfm->data, | 240 | adapter->sleep_cfm, NULL); |
242 | adapter->sleep_cfm->len, NULL); | ||
243 | skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN); | 241 | skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN); |
244 | 242 | ||
245 | if (ret == -1) { | 243 | if (ret == -1) { |
@@ -402,8 +400,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) | |||
402 | 400 | ||
403 | adapter->event_cause = 0; | 401 | adapter->event_cause = 0; |
404 | adapter->event_skb = NULL; | 402 | adapter->event_skb = NULL; |
405 | 403 | adapter->if_ops.event_complete(adapter, skb); | |
406 | dev_kfree_skb_any(skb); | ||
407 | 404 | ||
408 | return ret; | 405 | return ret; |
409 | } | 406 | } |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index f23ec72ed4fe..71c61b7e74ee 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -84,7 +84,8 @@ enum KEY_TYPE_ID { | |||
84 | 84 | ||
85 | #define MAX_FIRMWARE_POLL_TRIES 100 | 85 | #define MAX_FIRMWARE_POLL_TRIES 100 |
86 | 86 | ||
87 | #define FIRMWARE_READY 0xfedc | 87 | #define FIRMWARE_READY_SDIO 0xfedc |
88 | #define FIRMWARE_READY_PCIE 0xfedcba00 | ||
88 | 89 | ||
89 | enum MWIFIEX_802_11_PRIVACY_FILTER { | 90 | enum MWIFIEX_802_11_PRIVACY_FILTER { |
90 | MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL, | 91 | MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL, |
@@ -221,7 +222,7 @@ enum MWIFIEX_802_11_WEP_STATUS { | |||
221 | #define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5 | 222 | #define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5 |
222 | #define HostCmd_CMD_CAU_REG_ACCESS 0x00ed | 223 | #define HostCmd_CMD_CAU_REG_ACCESS 0x00ed |
223 | #define HostCmd_CMD_SET_BSS_MODE 0x00f7 | 224 | #define HostCmd_CMD_SET_BSS_MODE 0x00f7 |
224 | 225 | #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa | |
225 | 226 | ||
226 | enum ENH_PS_MODES { | 227 | enum ENH_PS_MODES { |
227 | EN_PS = 1, | 228 | EN_PS = 1, |
@@ -1137,6 +1138,30 @@ struct host_cmd_ds_set_bss_mode { | |||
1137 | u8 con_type; | 1138 | u8 con_type; |
1138 | } __packed; | 1139 | } __packed; |
1139 | 1140 | ||
1141 | struct host_cmd_ds_pcie_details { | ||
1142 | /* TX buffer descriptor ring address */ | ||
1143 | u32 txbd_addr_lo; | ||
1144 | u32 txbd_addr_hi; | ||
1145 | /* TX buffer descriptor ring count */ | ||
1146 | u32 txbd_count; | ||
1147 | |||
1148 | /* RX buffer descriptor ring address */ | ||
1149 | u32 rxbd_addr_lo; | ||
1150 | u32 rxbd_addr_hi; | ||
1151 | /* RX buffer descriptor ring count */ | ||
1152 | u32 rxbd_count; | ||
1153 | |||
1154 | /* Event buffer descriptor ring address */ | ||
1155 | u32 evtbd_addr_lo; | ||
1156 | u32 evtbd_addr_hi; | ||
1157 | /* Event buffer descriptor ring count */ | ||
1158 | u32 evtbd_count; | ||
1159 | |||
1160 | /* Sleep cookie buffer physical address */ | ||
1161 | u32 sleep_cookie_addr_lo; | ||
1162 | u32 sleep_cookie_addr_hi; | ||
1163 | } __packed; | ||
1164 | |||
1140 | struct host_cmd_ds_command { | 1165 | struct host_cmd_ds_command { |
1141 | __le16 command; | 1166 | __le16 command; |
1142 | __le16 size; | 1167 | __le16 size; |
@@ -1184,6 +1209,7 @@ struct host_cmd_ds_command { | |||
1184 | struct host_cmd_ds_rf_reg_access rf_reg; | 1209 | struct host_cmd_ds_rf_reg_access rf_reg; |
1185 | struct host_cmd_ds_pmic_reg_access pmic_reg; | 1210 | struct host_cmd_ds_pmic_reg_access pmic_reg; |
1186 | struct host_cmd_ds_set_bss_mode bss_mode; | 1211 | struct host_cmd_ds_set_bss_mode bss_mode; |
1212 | struct host_cmd_ds_pcie_details pcie_host_spec; | ||
1187 | struct host_cmd_ds_802_11_eeprom_access eeprom; | 1213 | struct host_cmd_ds_802_11_eeprom_access eeprom; |
1188 | } params; | 1214 | } params; |
1189 | } __packed; | 1215 | } __packed; |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index e1076b46401e..0ce72fc91437 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -191,7 +191,12 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
191 | (adapter->sleep_cfm->data); | 191 | (adapter->sleep_cfm->data); |
192 | 192 | ||
193 | adapter->cmd_sent = false; | 193 | adapter->cmd_sent = false; |
194 | adapter->data_sent = true; | 194 | |
195 | if (adapter->iface_type == MWIFIEX_PCIE) | ||
196 | adapter->data_sent = false; | ||
197 | else | ||
198 | adapter->data_sent = true; | ||
199 | |||
195 | adapter->cmd_resp_received = false; | 200 | adapter->cmd_resp_received = false; |
196 | adapter->event_received = false; | 201 | adapter->event_received = false; |
197 | adapter->data_received = false; | 202 | adapter->data_received = false; |
@@ -581,11 +586,13 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
581 | int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, | 586 | int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, |
582 | struct mwifiex_fw_image *pmfw) | 587 | struct mwifiex_fw_image *pmfw) |
583 | { | 588 | { |
584 | int ret, winner; | 589 | int ret; |
585 | u32 poll_num = 1; | 590 | u32 poll_num = 1; |
586 | 591 | ||
592 | adapter->winner = 0; | ||
593 | |||
587 | /* Check if firmware is already running */ | 594 | /* Check if firmware is already running */ |
588 | ret = adapter->if_ops.check_fw_status(adapter, poll_num, &winner); | 595 | ret = adapter->if_ops.check_fw_status(adapter, poll_num); |
589 | if (!ret) { | 596 | if (!ret) { |
590 | dev_notice(adapter->dev, | 597 | dev_notice(adapter->dev, |
591 | "WLAN FW already running! Skip FW download\n"); | 598 | "WLAN FW already running! Skip FW download\n"); |
@@ -594,7 +601,7 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, | |||
594 | poll_num = MAX_FIRMWARE_POLL_TRIES; | 601 | poll_num = MAX_FIRMWARE_POLL_TRIES; |
595 | 602 | ||
596 | /* Check if we are the winner for downloading FW */ | 603 | /* Check if we are the winner for downloading FW */ |
597 | if (!winner) { | 604 | if (!adapter->winner) { |
598 | dev_notice(adapter->dev, | 605 | dev_notice(adapter->dev, |
599 | "Other interface already running!" | 606 | "Other interface already running!" |
600 | " Skip FW download\n"); | 607 | " Skip FW download\n"); |
@@ -612,7 +619,7 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, | |||
612 | 619 | ||
613 | poll_fw: | 620 | poll_fw: |
614 | /* Check if the firmware is downloaded successfully or not */ | 621 | /* Check if the firmware is downloaded successfully or not */ |
615 | ret = adapter->if_ops.check_fw_status(adapter, poll_num, NULL); | 622 | ret = adapter->if_ops.check_fw_status(adapter, poll_num); |
616 | if (ret) { | 623 | if (ret) { |
617 | dev_err(adapter->dev, "FW failed to be active in time\n"); | 624 | dev_err(adapter->dev, "FW failed to be active in time\n"); |
618 | return -1; | 625 | return -1; |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 277ea84a05f5..849144d9c94e 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -661,7 +661,7 @@ mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter) | |||
661 | */ | 661 | */ |
662 | int | 662 | int |
663 | mwifiex_add_card(void *card, struct semaphore *sem, | 663 | mwifiex_add_card(void *card, struct semaphore *sem, |
664 | struct mwifiex_if_ops *if_ops) | 664 | struct mwifiex_if_ops *if_ops, u8 iface_type) |
665 | { | 665 | { |
666 | struct mwifiex_adapter *adapter; | 666 | struct mwifiex_adapter *adapter; |
667 | char fmt[64]; | 667 | char fmt[64]; |
@@ -675,6 +675,8 @@ mwifiex_add_card(void *card, struct semaphore *sem, | |||
675 | goto err_init_sw; | 675 | goto err_init_sw; |
676 | } | 676 | } |
677 | 677 | ||
678 | adapter->iface_type = iface_type; | ||
679 | |||
678 | adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; | 680 | adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; |
679 | adapter->surprise_removed = false; | 681 | adapter->surprise_removed = false; |
680 | init_waitqueue_head(&adapter->init_wait_q); | 682 | init_waitqueue_head(&adapter->init_wait_q); |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 907ab746dc4b..ec45607c5f91 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "ioctl.h" | 37 | #include "ioctl.h" |
38 | #include "util.h" | 38 | #include "util.h" |
39 | #include "fw.h" | 39 | #include "fw.h" |
40 | #include "pcie.h" | ||
40 | 41 | ||
41 | extern const char driver_version[]; | 42 | extern const char driver_version[]; |
42 | 43 | ||
@@ -107,6 +108,8 @@ enum { | |||
107 | 108 | ||
108 | #define MAX_FREQUENCY_BAND_BG 2484 | 109 | #define MAX_FREQUENCY_BAND_BG 2484 |
109 | 110 | ||
111 | #define MWIFIEX_EVENT_HEADER_LEN 4 | ||
112 | |||
110 | struct mwifiex_dbg { | 113 | struct mwifiex_dbg { |
111 | u32 num_cmd_host_to_card_failure; | 114 | u32 num_cmd_host_to_card_failure; |
112 | u32 num_cmd_sleep_cfm_host_to_card_failure; | 115 | u32 num_cmd_sleep_cfm_host_to_card_failure; |
@@ -156,6 +159,11 @@ enum MWIFIEX_PS_STATE { | |||
156 | PS_STATE_SLEEP | 159 | PS_STATE_SLEEP |
157 | }; | 160 | }; |
158 | 161 | ||
162 | enum mwifiex_iface_type { | ||
163 | MWIFIEX_SDIO, | ||
164 | MWIFIEX_PCIE, | ||
165 | }; | ||
166 | |||
159 | struct mwifiex_add_ba_param { | 167 | struct mwifiex_add_ba_param { |
160 | u32 tx_win_size; | 168 | u32 tx_win_size; |
161 | u32 rx_win_size; | 169 | u32 rx_win_size; |
@@ -517,27 +525,31 @@ struct cmd_ctrl_node { | |||
517 | struct mwifiex_if_ops { | 525 | struct mwifiex_if_ops { |
518 | int (*init_if) (struct mwifiex_adapter *); | 526 | int (*init_if) (struct mwifiex_adapter *); |
519 | void (*cleanup_if) (struct mwifiex_adapter *); | 527 | void (*cleanup_if) (struct mwifiex_adapter *); |
520 | int (*check_fw_status) (struct mwifiex_adapter *, u32, int *); | 528 | int (*check_fw_status) (struct mwifiex_adapter *, u32); |
521 | int (*prog_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); | 529 | int (*prog_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); |
522 | int (*register_dev) (struct mwifiex_adapter *); | 530 | int (*register_dev) (struct mwifiex_adapter *); |
523 | void (*unregister_dev) (struct mwifiex_adapter *); | 531 | void (*unregister_dev) (struct mwifiex_adapter *); |
524 | int (*enable_int) (struct mwifiex_adapter *); | 532 | int (*enable_int) (struct mwifiex_adapter *); |
525 | int (*process_int_status) (struct mwifiex_adapter *); | 533 | int (*process_int_status) (struct mwifiex_adapter *); |
526 | int (*host_to_card) (struct mwifiex_adapter *, u8, | 534 | int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *, |
527 | u8 *payload, u32 pkt_len, | ||
528 | struct mwifiex_tx_param *); | 535 | struct mwifiex_tx_param *); |
529 | int (*wakeup) (struct mwifiex_adapter *); | 536 | int (*wakeup) (struct mwifiex_adapter *); |
530 | int (*wakeup_complete) (struct mwifiex_adapter *); | 537 | int (*wakeup_complete) (struct mwifiex_adapter *); |
531 | 538 | ||
539 | /* Interface specific functions */ | ||
532 | void (*update_mp_end_port) (struct mwifiex_adapter *, u16); | 540 | void (*update_mp_end_port) (struct mwifiex_adapter *, u16); |
533 | void (*cleanup_mpa_buf) (struct mwifiex_adapter *); | 541 | void (*cleanup_mpa_buf) (struct mwifiex_adapter *); |
542 | int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *); | ||
543 | int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *); | ||
534 | }; | 544 | }; |
535 | 545 | ||
536 | struct mwifiex_adapter { | 546 | struct mwifiex_adapter { |
547 | u8 iface_type; | ||
537 | struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; | 548 | struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; |
538 | u8 priv_num; | 549 | u8 priv_num; |
539 | const struct firmware *firmware; | 550 | const struct firmware *firmware; |
540 | char fw_name[32]; | 551 | char fw_name[32]; |
552 | int winner; | ||
541 | struct device *dev; | 553 | struct device *dev; |
542 | bool surprise_removed; | 554 | bool surprise_removed; |
543 | u32 fw_release_number; | 555 | u32 fw_release_number; |
@@ -872,7 +884,7 @@ struct mwifiex_private *mwifiex_bss_index_to_priv(struct mwifiex_adapter | |||
872 | *adapter, u8 bss_index); | 884 | *adapter, u8 bss_index); |
873 | int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, | 885 | int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, |
874 | u32 func_init_shutdown); | 886 | u32 func_init_shutdown); |
875 | int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *); | 887 | int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8); |
876 | int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *); | 888 | int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *); |
877 | 889 | ||
878 | void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version, | 890 | void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version, |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c new file mode 100644 index 000000000000..d34acf082d3a --- /dev/null +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -0,0 +1,1948 @@ | |||
1 | /* | ||
2 | * Marvell Wireless LAN device driver: PCIE specific handling | ||
3 | * | ||
4 | * Copyright (C) 2011, Marvell International Ltd. | ||
5 | * | ||
6 | * This software file (the "File") is distributed by Marvell International | ||
7 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
8 | * (the "License"). You may use, redistribute and/or modify this File in | ||
9 | * accordance with the terms and conditions of the License, a copy of which | ||
10 | * is available by writing to the Free Software Foundation, Inc., | ||
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
13 | * | ||
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
17 | * this warranty disclaimer. | ||
18 | */ | ||
19 | |||
20 | #include <linux/firmware.h> | ||
21 | |||
22 | #include "decl.h" | ||
23 | #include "ioctl.h" | ||
24 | #include "util.h" | ||
25 | #include "fw.h" | ||
26 | #include "main.h" | ||
27 | #include "wmm.h" | ||
28 | #include "11n.h" | ||
29 | #include "pcie.h" | ||
30 | |||
31 | #define PCIE_VERSION "1.0" | ||
32 | #define DRV_NAME "Marvell mwifiex PCIe" | ||
33 | |||
34 | static u8 user_rmmod; | ||
35 | |||
36 | static struct mwifiex_if_ops pcie_ops; | ||
37 | |||
38 | static struct semaphore add_remove_card_sem; | ||
39 | static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter); | ||
40 | static int mwifiex_pcie_resume(struct pci_dev *pdev); | ||
41 | |||
42 | /* | ||
43 | * This function is called after skb allocation to update | ||
44 | * "skb->cb" with physical address of data pointer. | ||
45 | */ | ||
46 | static phys_addr_t *mwifiex_update_sk_buff_pa(struct sk_buff *skb) | ||
47 | { | ||
48 | phys_addr_t *buf_pa = MWIFIEX_SKB_PACB(skb); | ||
49 | |||
50 | *buf_pa = (phys_addr_t)virt_to_phys(skb->data); | ||
51 | |||
52 | return buf_pa; | ||
53 | } | ||
54 | |||
55 | /* | ||
56 | * This function reads sleep cookie and checks if FW is ready | ||
57 | */ | ||
58 | static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter) | ||
59 | { | ||
60 | u32 *cookie_addr; | ||
61 | struct pcie_service_card *card = adapter->card; | ||
62 | |||
63 | if (card->sleep_cookie) { | ||
64 | cookie_addr = (u32 *)card->sleep_cookie->data; | ||
65 | dev_dbg(adapter->dev, "info: ACCESS_HW: sleep cookie=0x%x\n", | ||
66 | *cookie_addr); | ||
67 | if (*cookie_addr == FW_AWAKE_COOKIE) | ||
68 | return true; | ||
69 | } | ||
70 | |||
71 | return false; | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * This function probes an mwifiex device and registers it. It allocates | ||
76 | * the card structure, enables PCIE function number and initiates the | ||
77 | * device registration and initialization procedure by adding a logical | ||
78 | * interface. | ||
79 | */ | ||
80 | static int mwifiex_pcie_probe(struct pci_dev *pdev, | ||
81 | const struct pci_device_id *ent) | ||
82 | { | ||
83 | struct pcie_service_card *card; | ||
84 | |||
85 | pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n", | ||
86 | pdev->vendor, pdev->device, pdev->revision); | ||
87 | |||
88 | card = kzalloc(sizeof(struct pcie_service_card), GFP_KERNEL); | ||
89 | if (!card) { | ||
90 | pr_err("%s: failed to alloc memory\n", __func__); | ||
91 | return -ENOMEM; | ||
92 | } | ||
93 | |||
94 | card->dev = pdev; | ||
95 | |||
96 | if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops, | ||
97 | MWIFIEX_PCIE)) { | ||
98 | pr_err("%s failed\n", __func__); | ||
99 | kfree(card); | ||
100 | return -1; | ||
101 | } | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * This function removes the interface and frees up the card structure. | ||
108 | */ | ||
109 | static void mwifiex_pcie_remove(struct pci_dev *pdev) | ||
110 | { | ||
111 | struct pcie_service_card *card; | ||
112 | struct mwifiex_adapter *adapter; | ||
113 | int i; | ||
114 | |||
115 | card = pci_get_drvdata(pdev); | ||
116 | if (!card) | ||
117 | return; | ||
118 | |||
119 | adapter = card->adapter; | ||
120 | if (!adapter || !adapter->priv_num) | ||
121 | return; | ||
122 | |||
123 | if (user_rmmod) { | ||
124 | #ifdef CONFIG_PM | ||
125 | if (adapter->is_suspended) | ||
126 | mwifiex_pcie_resume(pdev); | ||
127 | #endif | ||
128 | |||
129 | for (i = 0; i < adapter->priv_num; i++) | ||
130 | if ((GET_BSS_ROLE(adapter->priv[i]) == | ||
131 | MWIFIEX_BSS_ROLE_STA) && | ||
132 | adapter->priv[i]->media_connected) | ||
133 | mwifiex_deauthenticate(adapter->priv[i], NULL); | ||
134 | |||
135 | mwifiex_disable_auto_ds(mwifiex_get_priv(adapter, | ||
136 | MWIFIEX_BSS_ROLE_ANY)); | ||
137 | |||
138 | mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, | ||
139 | MWIFIEX_BSS_ROLE_ANY), | ||
140 | MWIFIEX_FUNC_SHUTDOWN); | ||
141 | } | ||
142 | |||
143 | mwifiex_remove_card(card->adapter, &add_remove_card_sem); | ||
144 | kfree(card); | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * Kernel needs to suspend all functions separately. Therefore all | ||
149 | * registered functions must have drivers with suspend and resume | ||
150 | * methods. Failing that the kernel simply removes the whole card. | ||
151 | * | ||
152 | * If already not suspended, this function allocates and sends a host | ||
153 | * sleep activate request to the firmware and turns off the traffic. | ||
154 | */ | ||
155 | static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) | ||
156 | { | ||
157 | struct mwifiex_adapter *adapter; | ||
158 | struct pcie_service_card *card; | ||
159 | int hs_actived, i; | ||
160 | |||
161 | if (pdev) { | ||
162 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | ||
163 | if (!card || card->adapter) { | ||
164 | pr_err("Card or adapter structure is not valid\n"); | ||
165 | return 0; | ||
166 | } | ||
167 | } else { | ||
168 | pr_err("PCIE device is not specified\n"); | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | adapter = card->adapter; | ||
173 | |||
174 | hs_actived = mwifiex_enable_hs(adapter); | ||
175 | |||
176 | /* Indicate device suspended */ | ||
177 | adapter->is_suspended = true; | ||
178 | |||
179 | for (i = 0; i < adapter->priv_num; i++) | ||
180 | netif_carrier_off(adapter->priv[i]->netdev); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * Kernel needs to suspend all functions separately. Therefore all | ||
187 | * registered functions must have drivers with suspend and resume | ||
188 | * methods. Failing that the kernel simply removes the whole card. | ||
189 | * | ||
190 | * If already not resumed, this function turns on the traffic and | ||
191 | * sends a host sleep cancel request to the firmware. | ||
192 | */ | ||
193 | static int mwifiex_pcie_resume(struct pci_dev *pdev) | ||
194 | { | ||
195 | struct mwifiex_adapter *adapter; | ||
196 | struct pcie_service_card *card; | ||
197 | int i; | ||
198 | |||
199 | if (pdev) { | ||
200 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | ||
201 | if (!card || !card->adapter) { | ||
202 | pr_err("Card or adapter structure is not valid\n"); | ||
203 | return 0; | ||
204 | } | ||
205 | } else { | ||
206 | pr_err("PCIE device is not specified\n"); | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | adapter = card->adapter; | ||
211 | |||
212 | if (!adapter->is_suspended) { | ||
213 | dev_warn(adapter->dev, "Device already resumed\n"); | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | adapter->is_suspended = false; | ||
218 | |||
219 | for (i = 0; i < adapter->priv_num; i++) | ||
220 | if (adapter->priv[i]->media_connected) | ||
221 | netif_carrier_on(adapter->priv[i]->netdev); | ||
222 | |||
223 | mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), | ||
224 | MWIFIEX_ASYNC_CMD); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | #define PCIE_VENDOR_ID_MARVELL (0x11ab) | ||
230 | #define PCIE_DEVICE_ID_MARVELL_88W8766P (0x2b30) | ||
231 | |||
232 | static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = { | ||
233 | { | ||
234 | PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P, | ||
235 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
236 | }, | ||
237 | {}, | ||
238 | }; | ||
239 | |||
240 | MODULE_DEVICE_TABLE(pci, mwifiex_ids); | ||
241 | |||
242 | /* PCI Device Driver */ | ||
243 | static struct pci_driver __refdata mwifiex_pcie = { | ||
244 | .name = "mwifiex_pcie", | ||
245 | .id_table = mwifiex_ids, | ||
246 | .probe = mwifiex_pcie_probe, | ||
247 | .remove = mwifiex_pcie_remove, | ||
248 | #ifdef CONFIG_PM | ||
249 | /* Power Management Hooks */ | ||
250 | .suspend = mwifiex_pcie_suspend, | ||
251 | .resume = mwifiex_pcie_resume, | ||
252 | #endif | ||
253 | }; | ||
254 | |||
255 | /* | ||
256 | * This function writes data into PCIE card register. | ||
257 | */ | ||
258 | static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data) | ||
259 | { | ||
260 | struct pcie_service_card *card = adapter->card; | ||
261 | |||
262 | iowrite32(data, card->pci_mmap1 + reg); | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * This function reads data from PCIE card register. | ||
269 | */ | ||
270 | static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data) | ||
271 | { | ||
272 | struct pcie_service_card *card = adapter->card; | ||
273 | |||
274 | *data = ioread32(card->pci_mmap1 + reg); | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * This function wakes up the card. | ||
281 | * | ||
282 | * A host power up command is written to the card configuration | ||
283 | * register to wake up the card. | ||
284 | */ | ||
285 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | ||
286 | { | ||
287 | int i = 0; | ||
288 | |||
289 | while (mwifiex_pcie_ok_to_access_hw(adapter)) { | ||
290 | i++; | ||
291 | udelay(10); | ||
292 | /* 50ms max wait */ | ||
293 | if (i == 50000) | ||
294 | break; | ||
295 | } | ||
296 | |||
297 | dev_dbg(adapter->dev, "event: Wakeup device...\n"); | ||
298 | |||
299 | /* Enable interrupts or any chip access will wakeup device */ | ||
300 | if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK, HOST_INTR_MASK)) { | ||
301 | dev_warn(adapter->dev, "Enable host interrupt failed\n"); | ||
302 | return -1; | ||
303 | } | ||
304 | |||
305 | dev_dbg(adapter->dev, "PCIE wakeup: Setting PS_STATE_AWAKE\n"); | ||
306 | adapter->ps_state = PS_STATE_AWAKE; | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * This function is called after the card has woken up. | ||
313 | * | ||
314 | * The card configuration register is reset. | ||
315 | */ | ||
316 | static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter) | ||
317 | { | ||
318 | dev_dbg(adapter->dev, "cmd: Wakeup device completed\n"); | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | /* | ||
324 | * This function disables the host interrupt. | ||
325 | * | ||
326 | * The host interrupt mask is read, the disable bit is reset and | ||
327 | * written back to the card host interrupt mask register. | ||
328 | */ | ||
329 | static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter) | ||
330 | { | ||
331 | if (mwifiex_pcie_ok_to_access_hw(adapter)) { | ||
332 | if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK, | ||
333 | 0x00000000)) { | ||
334 | dev_warn(adapter->dev, "Disable host interrupt failed\n"); | ||
335 | return -1; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | /* | ||
343 | * This function enables the host interrupt. | ||
344 | * | ||
345 | * The host interrupt enable mask is written to the card | ||
346 | * host interrupt mask register. | ||
347 | */ | ||
348 | static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter) | ||
349 | { | ||
350 | if (mwifiex_pcie_ok_to_access_hw(adapter)) { | ||
351 | /* Simply write the mask to the register */ | ||
352 | if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK, | ||
353 | HOST_INTR_MASK)) { | ||
354 | dev_warn(adapter->dev, "Enable host interrupt failed\n"); | ||
355 | return -1; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | /* | ||
363 | * This function creates buffer descriptor ring for TX | ||
364 | */ | ||
365 | static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter) | ||
366 | { | ||
367 | struct pcie_service_card *card = adapter->card; | ||
368 | struct sk_buff *skb; | ||
369 | int i; | ||
370 | phys_addr_t *buf_pa; | ||
371 | |||
372 | /* | ||
373 | * driver maintaines the write pointer and firmware maintaines the read | ||
374 | * pointer. The write pointer starts at 0 (zero) while the read pointer | ||
375 | * starts at zero with rollover bit set | ||
376 | */ | ||
377 | card->txbd_wrptr = 0; | ||
378 | card->txbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND; | ||
379 | |||
380 | /* allocate shared memory for the BD ring and divide the same in to | ||
381 | several descriptors */ | ||
382 | card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) * | ||
383 | MWIFIEX_MAX_TXRX_BD; | ||
384 | dev_dbg(adapter->dev, "info: txbd_ring: Allocating %d bytes\n", | ||
385 | card->txbd_ring_size); | ||
386 | card->txbd_ring_vbase = kzalloc(card->txbd_ring_size, GFP_KERNEL); | ||
387 | if (!card->txbd_ring_vbase) { | ||
388 | dev_err(adapter->dev, "Unable to allocate buffer for txbd ring.\n"); | ||
389 | kfree(card->txbd_ring_vbase); | ||
390 | return -1; | ||
391 | } | ||
392 | card->txbd_ring_pbase = virt_to_phys(card->txbd_ring_vbase); | ||
393 | |||
394 | dev_dbg(adapter->dev, "info: txbd_ring - base: %p, pbase: %#x:%x," | ||
395 | "len: %x\n", card->txbd_ring_vbase, | ||
396 | (u32)card->txbd_ring_pbase, | ||
397 | (u32)((u64)card->txbd_ring_pbase >> 32), | ||
398 | card->txbd_ring_size); | ||
399 | |||
400 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { | ||
401 | card->txbd_ring[i] = (struct mwifiex_pcie_buf_desc *) | ||
402 | (card->txbd_ring_vbase + | ||
403 | (sizeof(struct mwifiex_pcie_buf_desc) * i)); | ||
404 | |||
405 | /* Allocate buffer here so that firmware can DMA data from it */ | ||
406 | skb = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE); | ||
407 | if (!skb) { | ||
408 | dev_err(adapter->dev, "Unable to allocate skb for TX ring.\n"); | ||
409 | kfree(card->txbd_ring_vbase); | ||
410 | return -ENOMEM; | ||
411 | } | ||
412 | buf_pa = mwifiex_update_sk_buff_pa(skb); | ||
413 | |||
414 | skb_put(skb, MWIFIEX_RX_DATA_BUF_SIZE); | ||
415 | dev_dbg(adapter->dev, "info: TX ring: add new skb base: %p, " | ||
416 | "buf_base: %p, buf_pbase: %#x:%x, " | ||
417 | "buf_len: %#x\n", skb, skb->data, | ||
418 | (u32)*buf_pa, (u32)(((u64)*buf_pa >> 32)), | ||
419 | skb->len); | ||
420 | |||
421 | card->tx_buf_list[i] = skb; | ||
422 | card->txbd_ring[i]->paddr = *buf_pa; | ||
423 | card->txbd_ring[i]->len = (u16)skb->len; | ||
424 | card->txbd_ring[i]->flags = 0; | ||
425 | } | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter) | ||
431 | { | ||
432 | struct pcie_service_card *card = adapter->card; | ||
433 | int i; | ||
434 | |||
435 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { | ||
436 | if (card->tx_buf_list[i]) | ||
437 | dev_kfree_skb_any(card->tx_buf_list[i]); | ||
438 | card->tx_buf_list[i] = NULL; | ||
439 | card->txbd_ring[i]->paddr = 0; | ||
440 | card->txbd_ring[i]->len = 0; | ||
441 | card->txbd_ring[i]->flags = 0; | ||
442 | card->txbd_ring[i] = NULL; | ||
443 | } | ||
444 | |||
445 | kfree(card->txbd_ring_vbase); | ||
446 | card->txbd_ring_size = 0; | ||
447 | card->txbd_wrptr = 0; | ||
448 | card->txbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND; | ||
449 | card->txbd_ring_vbase = NULL; | ||
450 | |||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | * This function creates buffer descriptor ring for RX | ||
456 | */ | ||
457 | static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) | ||
458 | { | ||
459 | struct pcie_service_card *card = adapter->card; | ||
460 | struct sk_buff *skb; | ||
461 | int i; | ||
462 | phys_addr_t *buf_pa; | ||
463 | |||
464 | /* | ||
465 | * driver maintaines the read pointer and firmware maintaines the write | ||
466 | * pointer. The write pointer starts at 0 (zero) while the read pointer | ||
467 | * starts at zero with rollover bit set | ||
468 | */ | ||
469 | card->rxbd_wrptr = 0; | ||
470 | card->rxbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND; | ||
471 | |||
472 | card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) * | ||
473 | MWIFIEX_MAX_TXRX_BD; | ||
474 | dev_dbg(adapter->dev, "info: rxbd_ring: Allocating %d bytes\n", | ||
475 | card->rxbd_ring_size); | ||
476 | card->rxbd_ring_vbase = kzalloc(card->rxbd_ring_size, GFP_KERNEL); | ||
477 | if (!card->rxbd_ring_vbase) { | ||
478 | dev_err(adapter->dev, "Unable to allocate buffer for " | ||
479 | "rxbd_ring.\n"); | ||
480 | return -1; | ||
481 | } | ||
482 | card->rxbd_ring_pbase = virt_to_phys(card->rxbd_ring_vbase); | ||
483 | |||
484 | dev_dbg(adapter->dev, "info: rxbd_ring - base: %p, pbase: %#x:%x," | ||
485 | "len: %#x\n", card->rxbd_ring_vbase, | ||
486 | (u32)card->rxbd_ring_pbase, | ||
487 | (u32)((u64)card->rxbd_ring_pbase >> 32), | ||
488 | card->rxbd_ring_size); | ||
489 | |||
490 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { | ||
491 | card->rxbd_ring[i] = (struct mwifiex_pcie_buf_desc *) | ||
492 | (card->rxbd_ring_vbase + | ||
493 | (sizeof(struct mwifiex_pcie_buf_desc) * i)); | ||
494 | |||
495 | /* Allocate skb here so that firmware can DMA data from it */ | ||
496 | skb = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE); | ||
497 | if (!skb) { | ||
498 | dev_err(adapter->dev, "Unable to allocate skb for RX ring.\n"); | ||
499 | kfree(card->rxbd_ring_vbase); | ||
500 | return -ENOMEM; | ||
501 | } | ||
502 | buf_pa = mwifiex_update_sk_buff_pa(skb); | ||
503 | skb_put(skb, MWIFIEX_RX_DATA_BUF_SIZE); | ||
504 | |||
505 | dev_dbg(adapter->dev, "info: RX ring: add new skb base: %p, " | ||
506 | "buf_base: %p, buf_pbase: %#x:%x, " | ||
507 | "buf_len: %#x\n", skb, skb->data, | ||
508 | (u32)*buf_pa, (u32)((u64)*buf_pa >> 32), | ||
509 | skb->len); | ||
510 | |||
511 | card->rx_buf_list[i] = skb; | ||
512 | card->rxbd_ring[i]->paddr = *buf_pa; | ||
513 | card->rxbd_ring[i]->len = (u16)skb->len; | ||
514 | card->rxbd_ring[i]->flags = 0; | ||
515 | } | ||
516 | |||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | /* | ||
521 | * This function deletes Buffer descriptor ring for RX | ||
522 | */ | ||
523 | static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter) | ||
524 | { | ||
525 | struct pcie_service_card *card = adapter->card; | ||
526 | int i; | ||
527 | |||
528 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { | ||
529 | if (card->rx_buf_list[i]) | ||
530 | dev_kfree_skb_any(card->rx_buf_list[i]); | ||
531 | card->rx_buf_list[i] = NULL; | ||
532 | card->rxbd_ring[i]->paddr = 0; | ||
533 | card->rxbd_ring[i]->len = 0; | ||
534 | card->rxbd_ring[i]->flags = 0; | ||
535 | card->rxbd_ring[i] = NULL; | ||
536 | } | ||
537 | |||
538 | kfree(card->rxbd_ring_vbase); | ||
539 | card->rxbd_ring_size = 0; | ||
540 | card->rxbd_wrptr = 0; | ||
541 | card->rxbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND; | ||
542 | card->rxbd_ring_vbase = NULL; | ||
543 | |||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | /* | ||
548 | * This function creates buffer descriptor ring for Events | ||
549 | */ | ||
550 | static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) | ||
551 | { | ||
552 | struct pcie_service_card *card = adapter->card; | ||
553 | struct sk_buff *skb; | ||
554 | int i; | ||
555 | phys_addr_t *buf_pa; | ||
556 | |||
557 | /* | ||
558 | * driver maintaines the read pointer and firmware maintaines the write | ||
559 | * pointer. The write pointer starts at 0 (zero) while the read pointer | ||
560 | * starts at zero with rollover bit set | ||
561 | */ | ||
562 | card->evtbd_wrptr = 0; | ||
563 | card->evtbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND; | ||
564 | |||
565 | card->evtbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) * | ||
566 | MWIFIEX_MAX_EVT_BD; | ||
567 | dev_dbg(adapter->dev, "info: evtbd_ring: Allocating %d bytes\n", | ||
568 | card->evtbd_ring_size); | ||
569 | card->evtbd_ring_vbase = kzalloc(card->evtbd_ring_size, GFP_KERNEL); | ||
570 | if (!card->evtbd_ring_vbase) { | ||
571 | dev_err(adapter->dev, "Unable to allocate buffer. " | ||
572 | "Terminating download\n"); | ||
573 | return -1; | ||
574 | } | ||
575 | card->evtbd_ring_pbase = virt_to_phys(card->evtbd_ring_vbase); | ||
576 | |||
577 | dev_dbg(adapter->dev, "info: CMDRSP/EVT bd_ring - base: %p, " | ||
578 | "pbase: %#x:%x, len: %#x\n", card->evtbd_ring_vbase, | ||
579 | (u32)card->evtbd_ring_pbase, | ||
580 | (u32)((u64)card->evtbd_ring_pbase >> 32), | ||
581 | card->evtbd_ring_size); | ||
582 | |||
583 | for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) { | ||
584 | card->evtbd_ring[i] = (struct mwifiex_pcie_buf_desc *) | ||
585 | (card->evtbd_ring_vbase + | ||
586 | (sizeof(struct mwifiex_pcie_buf_desc) * i)); | ||
587 | |||
588 | /* Allocate skb here so that firmware can DMA data from it */ | ||
589 | skb = dev_alloc_skb(MAX_EVENT_SIZE); | ||
590 | if (!skb) { | ||
591 | dev_err(adapter->dev, "Unable to allocate skb for EVENT buf.\n"); | ||
592 | kfree(card->evtbd_ring_vbase); | ||
593 | return -ENOMEM; | ||
594 | } | ||
595 | buf_pa = mwifiex_update_sk_buff_pa(skb); | ||
596 | skb_put(skb, MAX_EVENT_SIZE); | ||
597 | |||
598 | dev_dbg(adapter->dev, "info: Evt ring: add new skb. base: %p, " | ||
599 | "buf_base: %p, buf_pbase: %#x:%x, " | ||
600 | "buf_len: %#x\n", skb, skb->data, | ||
601 | (u32)*buf_pa, (u32)((u64)*buf_pa >> 32), | ||
602 | skb->len); | ||
603 | |||
604 | card->evt_buf_list[i] = skb; | ||
605 | card->evtbd_ring[i]->paddr = *buf_pa; | ||
606 | card->evtbd_ring[i]->len = (u16)skb->len; | ||
607 | card->evtbd_ring[i]->flags = 0; | ||
608 | } | ||
609 | |||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | /* | ||
614 | * This function deletes Buffer descriptor ring for Events | ||
615 | */ | ||
616 | static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter) | ||
617 | { | ||
618 | struct pcie_service_card *card = adapter->card; | ||
619 | int i; | ||
620 | |||
621 | for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) { | ||
622 | if (card->evt_buf_list[i]) | ||
623 | dev_kfree_skb_any(card->evt_buf_list[i]); | ||
624 | card->evt_buf_list[i] = NULL; | ||
625 | card->evtbd_ring[i]->paddr = 0; | ||
626 | card->evtbd_ring[i]->len = 0; | ||
627 | card->evtbd_ring[i]->flags = 0; | ||
628 | card->evtbd_ring[i] = NULL; | ||
629 | } | ||
630 | |||
631 | kfree(card->evtbd_ring_vbase); | ||
632 | card->evtbd_wrptr = 0; | ||
633 | card->evtbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND; | ||
634 | card->evtbd_ring_size = 0; | ||
635 | card->evtbd_ring_vbase = NULL; | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | /* | ||
641 | * This function allocates a buffer for CMDRSP | ||
642 | */ | ||
643 | static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter) | ||
644 | { | ||
645 | struct pcie_service_card *card = adapter->card; | ||
646 | struct sk_buff *skb; | ||
647 | |||
648 | /* Allocate memory for receiving command response data */ | ||
649 | skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE); | ||
650 | if (!skb) { | ||
651 | dev_err(adapter->dev, "Unable to allocate skb for command " | ||
652 | "response data.\n"); | ||
653 | return -ENOMEM; | ||
654 | } | ||
655 | mwifiex_update_sk_buff_pa(skb); | ||
656 | skb_put(skb, MWIFIEX_UPLD_SIZE); | ||
657 | card->cmdrsp_buf = skb; | ||
658 | |||
659 | skb = NULL; | ||
660 | /* Allocate memory for sending command to firmware */ | ||
661 | skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER); | ||
662 | if (!skb) { | ||
663 | dev_err(adapter->dev, "Unable to allocate skb for command " | ||
664 | "data.\n"); | ||
665 | return -ENOMEM; | ||
666 | } | ||
667 | mwifiex_update_sk_buff_pa(skb); | ||
668 | skb_put(skb, MWIFIEX_SIZE_OF_CMD_BUFFER); | ||
669 | card->cmd_buf = skb; | ||
670 | |||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | /* | ||
675 | * This function deletes a buffer for CMDRSP | ||
676 | */ | ||
677 | static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) | ||
678 | { | ||
679 | struct pcie_service_card *card; | ||
680 | |||
681 | if (!adapter) | ||
682 | return 0; | ||
683 | |||
684 | card = adapter->card; | ||
685 | |||
686 | if (card && card->cmdrsp_buf) | ||
687 | dev_kfree_skb_any(card->cmdrsp_buf); | ||
688 | |||
689 | if (card && card->cmd_buf) | ||
690 | dev_kfree_skb_any(card->cmd_buf); | ||
691 | |||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | /* | ||
696 | * This function allocates a buffer for sleep cookie | ||
697 | */ | ||
698 | static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter) | ||
699 | { | ||
700 | struct sk_buff *skb; | ||
701 | struct pcie_service_card *card = adapter->card; | ||
702 | |||
703 | /* Allocate memory for sleep cookie */ | ||
704 | skb = dev_alloc_skb(sizeof(u32)); | ||
705 | if (!skb) { | ||
706 | dev_err(adapter->dev, "Unable to allocate skb for sleep " | ||
707 | "cookie!\n"); | ||
708 | return -ENOMEM; | ||
709 | } | ||
710 | mwifiex_update_sk_buff_pa(skb); | ||
711 | skb_put(skb, sizeof(u32)); | ||
712 | |||
713 | /* Init val of Sleep Cookie */ | ||
714 | *(u32 *)skb->data = FW_AWAKE_COOKIE; | ||
715 | |||
716 | dev_dbg(adapter->dev, "alloc_scook: sleep cookie=0x%x\n", | ||
717 | *((u32 *)skb->data)); | ||
718 | |||
719 | /* Save the sleep cookie */ | ||
720 | card->sleep_cookie = skb; | ||
721 | |||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | /* | ||
726 | * This function deletes buffer for sleep cookie | ||
727 | */ | ||
728 | static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter) | ||
729 | { | ||
730 | struct pcie_service_card *card; | ||
731 | |||
732 | if (!adapter) | ||
733 | return 0; | ||
734 | |||
735 | card = adapter->card; | ||
736 | |||
737 | if (card && card->sleep_cookie) { | ||
738 | dev_kfree_skb_any(card->sleep_cookie); | ||
739 | card->sleep_cookie = NULL; | ||
740 | } | ||
741 | |||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | /* | ||
746 | * This function sends data buffer to device | ||
747 | */ | ||
748 | static int | ||
749 | mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb) | ||
750 | { | ||
751 | struct pcie_service_card *card = adapter->card; | ||
752 | u32 wrindx, rdptr; | ||
753 | phys_addr_t *buf_pa; | ||
754 | __le16 *tmp; | ||
755 | |||
756 | if (!mwifiex_pcie_ok_to_access_hw(adapter)) | ||
757 | mwifiex_pm_wakeup_card(adapter); | ||
758 | |||
759 | /* Read the TX ring read pointer set by firmware */ | ||
760 | if (mwifiex_read_reg(adapter, REG_TXBD_RDPTR, &rdptr)) { | ||
761 | dev_err(adapter->dev, "SEND DATA: failed to read " | ||
762 | "REG_TXBD_RDPTR\n"); | ||
763 | return -1; | ||
764 | } | ||
765 | |||
766 | wrindx = card->txbd_wrptr & MWIFIEX_TXBD_MASK; | ||
767 | |||
768 | dev_dbg(adapter->dev, "info: SEND DATA: <Rd: %#x, Wr: %#x>\n", rdptr, | ||
769 | card->txbd_wrptr); | ||
770 | if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) != | ||
771 | (rdptr & MWIFIEX_TXBD_MASK)) || | ||
772 | ((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) != | ||
773 | (rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) { | ||
774 | struct sk_buff *skb_data; | ||
775 | u8 *payload; | ||
776 | |||
777 | adapter->data_sent = true; | ||
778 | skb_data = card->tx_buf_list[wrindx]; | ||
779 | memcpy(skb_data->data, skb->data, skb->len); | ||
780 | payload = skb_data->data; | ||
781 | tmp = (__le16 *)&payload[0]; | ||
782 | *tmp = cpu_to_le16((u16)skb->len); | ||
783 | tmp = (__le16 *)&payload[2]; | ||
784 | *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA); | ||
785 | skb_put(skb_data, MWIFIEX_RX_DATA_BUF_SIZE - skb_data->len); | ||
786 | skb_trim(skb_data, skb->len); | ||
787 | buf_pa = MWIFIEX_SKB_PACB(skb_data); | ||
788 | card->txbd_ring[wrindx]->paddr = *buf_pa; | ||
789 | card->txbd_ring[wrindx]->len = (u16)skb_data->len; | ||
790 | card->txbd_ring[wrindx]->flags = MWIFIEX_BD_FLAG_FIRST_DESC | | ||
791 | MWIFIEX_BD_FLAG_LAST_DESC; | ||
792 | |||
793 | if ((++card->txbd_wrptr & MWIFIEX_TXBD_MASK) == | ||
794 | MWIFIEX_MAX_TXRX_BD) | ||
795 | card->txbd_wrptr = ((card->txbd_wrptr & | ||
796 | MWIFIEX_BD_FLAG_ROLLOVER_IND) ^ | ||
797 | MWIFIEX_BD_FLAG_ROLLOVER_IND); | ||
798 | |||
799 | /* Write the TX ring write pointer in to REG_TXBD_WRPTR */ | ||
800 | if (mwifiex_write_reg(adapter, REG_TXBD_WRPTR, | ||
801 | card->txbd_wrptr)) { | ||
802 | dev_err(adapter->dev, "SEND DATA: failed to write " | ||
803 | "REG_TXBD_WRPTR\n"); | ||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | /* Send the TX ready interrupt */ | ||
808 | if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, | ||
809 | CPU_INTR_DNLD_RDY)) { | ||
810 | dev_err(adapter->dev, "SEND DATA: failed to assert " | ||
811 | "door-bell interrupt.\n"); | ||
812 | return -1; | ||
813 | } | ||
814 | dev_dbg(adapter->dev, "info: SEND DATA: Updated <Rd: %#x, Wr: " | ||
815 | "%#x> and sent packet to firmware " | ||
816 | "successfully\n", rdptr, | ||
817 | card->txbd_wrptr); | ||
818 | } else { | ||
819 | dev_dbg(adapter->dev, "info: TX Ring full, can't send anymore " | ||
820 | "packets to firmware\n"); | ||
821 | adapter->data_sent = true; | ||
822 | /* Send the TX ready interrupt */ | ||
823 | if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, | ||
824 | CPU_INTR_DNLD_RDY)) | ||
825 | dev_err(adapter->dev, "SEND DATA: failed to assert " | ||
826 | "door-bell interrupt\n"); | ||
827 | return -EBUSY; | ||
828 | } | ||
829 | |||
830 | return 0; | ||
831 | } | ||
832 | |||
833 | /* | ||
834 | * This function handles received buffer ring and | ||
835 | * dispatches packets to upper | ||
836 | */ | ||
837 | static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) | ||
838 | { | ||
839 | struct pcie_service_card *card = adapter->card; | ||
840 | u32 wrptr, rd_index; | ||
841 | int ret = 0; | ||
842 | struct sk_buff *skb_tmp = NULL; | ||
843 | |||
844 | /* Read the RX ring Write pointer set by firmware */ | ||
845 | if (mwifiex_read_reg(adapter, REG_RXBD_WRPTR, &wrptr)) { | ||
846 | dev_err(adapter->dev, "RECV DATA: failed to read " | ||
847 | "REG_TXBD_RDPTR\n"); | ||
848 | ret = -1; | ||
849 | goto done; | ||
850 | } | ||
851 | |||
852 | while (((wrptr & MWIFIEX_RXBD_MASK) != | ||
853 | (card->rxbd_rdptr & MWIFIEX_RXBD_MASK)) || | ||
854 | ((wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) == | ||
855 | (card->rxbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) { | ||
856 | struct sk_buff *skb_data; | ||
857 | u16 rx_len; | ||
858 | |||
859 | rd_index = card->rxbd_rdptr & MWIFIEX_RXBD_MASK; | ||
860 | skb_data = card->rx_buf_list[rd_index]; | ||
861 | |||
862 | /* Get data length from interface header - | ||
863 | first byte is len, second byte is type */ | ||
864 | rx_len = *((u16 *)skb_data->data); | ||
865 | dev_dbg(adapter->dev, "info: RECV DATA: Rd=%#x, Wr=%#x, " | ||
866 | "Len=%d\n", card->rxbd_rdptr, wrptr, rx_len); | ||
867 | skb_tmp = dev_alloc_skb(rx_len); | ||
868 | if (!skb_tmp) { | ||
869 | dev_dbg(adapter->dev, "info: Failed to alloc skb " | ||
870 | "for RX\n"); | ||
871 | ret = -EBUSY; | ||
872 | goto done; | ||
873 | } | ||
874 | |||
875 | skb_put(skb_tmp, rx_len); | ||
876 | |||
877 | memcpy(skb_tmp->data, skb_data->data + INTF_HEADER_LEN, rx_len); | ||
878 | if ((++card->rxbd_rdptr & MWIFIEX_RXBD_MASK) == | ||
879 | MWIFIEX_MAX_TXRX_BD) { | ||
880 | card->rxbd_rdptr = ((card->rxbd_rdptr & | ||
881 | MWIFIEX_BD_FLAG_ROLLOVER_IND) ^ | ||
882 | MWIFIEX_BD_FLAG_ROLLOVER_IND); | ||
883 | } | ||
884 | dev_dbg(adapter->dev, "info: RECV DATA: <Rd: %#x, Wr: %#x>\n", | ||
885 | card->rxbd_rdptr, wrptr); | ||
886 | |||
887 | /* Write the RX ring read pointer in to REG_RXBD_RDPTR */ | ||
888 | if (mwifiex_write_reg(adapter, REG_RXBD_RDPTR, | ||
889 | card->rxbd_rdptr)) { | ||
890 | dev_err(adapter->dev, "RECV DATA: failed to " | ||
891 | "write REG_RXBD_RDPTR\n"); | ||
892 | ret = -1; | ||
893 | goto done; | ||
894 | } | ||
895 | |||
896 | /* Read the RX ring Write pointer set by firmware */ | ||
897 | if (mwifiex_read_reg(adapter, REG_RXBD_WRPTR, &wrptr)) { | ||
898 | dev_err(adapter->dev, "RECV DATA: failed to read " | ||
899 | "REG_TXBD_RDPTR\n"); | ||
900 | ret = -1; | ||
901 | goto done; | ||
902 | } | ||
903 | dev_dbg(adapter->dev, "info: RECV DATA: Received packet from " | ||
904 | "firmware successfully\n"); | ||
905 | mwifiex_handle_rx_packet(adapter, skb_tmp); | ||
906 | } | ||
907 | |||
908 | done: | ||
909 | if (ret && skb_tmp) | ||
910 | dev_kfree_skb_any(skb_tmp); | ||
911 | return ret; | ||
912 | } | ||
913 | |||
914 | /* | ||
915 | * This function downloads the boot command to device | ||
916 | */ | ||
917 | static int | ||
918 | mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | ||
919 | { | ||
920 | phys_addr_t *buf_pa = MWIFIEX_SKB_PACB(skb); | ||
921 | |||
922 | if (!(skb->data && skb->len && *buf_pa)) { | ||
923 | dev_err(adapter->dev, "Invalid parameter in %s <%p, %#x:%x, " | ||
924 | "%x>\n", __func__, skb->data, skb->len, | ||
925 | (u32)*buf_pa, (u32)((u64)*buf_pa >> 32)); | ||
926 | return -1; | ||
927 | } | ||
928 | |||
929 | /* Write the lower 32bits of the physical address to scratch | ||
930 | * register 0 */ | ||
931 | if (mwifiex_write_reg(adapter, PCIE_SCRATCH_0_REG, (u32)*buf_pa)) { | ||
932 | dev_err(adapter->dev, "%s: failed to write download command " | ||
933 | "to boot code.\n", __func__); | ||
934 | return -1; | ||
935 | } | ||
936 | |||
937 | /* Write the upper 32bits of the physical address to scratch | ||
938 | * register 1 */ | ||
939 | if (mwifiex_write_reg(adapter, PCIE_SCRATCH_1_REG, | ||
940 | (u32)((u64)*buf_pa >> 32))) { | ||
941 | dev_err(adapter->dev, "%s: failed to write download command " | ||
942 | "to boot code.\n", __func__); | ||
943 | return -1; | ||
944 | } | ||
945 | |||
946 | /* Write the command length to scratch register 2 */ | ||
947 | if (mwifiex_write_reg(adapter, PCIE_SCRATCH_2_REG, skb->len)) { | ||
948 | dev_err(adapter->dev, "%s: failed to write command length to " | ||
949 | "scratch register 2\n", __func__); | ||
950 | return -1; | ||
951 | } | ||
952 | |||
953 | /* Ring the door bell */ | ||
954 | if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, | ||
955 | CPU_INTR_DOOR_BELL)) { | ||
956 | dev_err(adapter->dev, "%s: failed to assert door-bell " | ||
957 | "interrupt.\n", __func__); | ||
958 | return -1; | ||
959 | } | ||
960 | |||
961 | return 0; | ||
962 | } | ||
963 | |||
964 | /* | ||
965 | * This function downloads commands to the device | ||
966 | */ | ||
967 | static int | ||
968 | mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | ||
969 | { | ||
970 | struct pcie_service_card *card = adapter->card; | ||
971 | int ret = 0; | ||
972 | phys_addr_t *cmd_buf_pa; | ||
973 | phys_addr_t *cmdrsp_buf_pa; | ||
974 | |||
975 | if (!(skb->data && skb->len)) { | ||
976 | dev_err(adapter->dev, "Invalid parameter in %s <%p, %#x>\n", | ||
977 | __func__, skb->data, skb->len); | ||
978 | return -1; | ||
979 | } | ||
980 | |||
981 | /* Make sure a command response buffer is available */ | ||
982 | if (!card->cmdrsp_buf) { | ||
983 | dev_err(adapter->dev, "No response buffer available, send " | ||
984 | "command failed\n"); | ||
985 | return -EBUSY; | ||
986 | } | ||
987 | |||
988 | /* Make sure a command buffer is available */ | ||
989 | if (!card->cmd_buf) { | ||
990 | dev_err(adapter->dev, "Command buffer not available\n"); | ||
991 | return -EBUSY; | ||
992 | } | ||
993 | |||
994 | adapter->cmd_sent = true; | ||
995 | /* Copy the given skb in to DMA accessable shared buffer */ | ||
996 | skb_put(card->cmd_buf, MWIFIEX_SIZE_OF_CMD_BUFFER - card->cmd_buf->len); | ||
997 | skb_trim(card->cmd_buf, skb->len); | ||
998 | memcpy(card->cmd_buf->data, skb->data, skb->len); | ||
999 | |||
1000 | /* To send a command, the driver will: | ||
1001 | 1. Write the 64bit physical address of the data buffer to | ||
1002 | SCRATCH1 + SCRATCH0 | ||
1003 | 2. Ring the door bell (i.e. set the door bell interrupt) | ||
1004 | |||
1005 | In response to door bell interrupt, the firmware will perform | ||
1006 | the DMA of the command packet (first header to obtain the total | ||
1007 | length and then rest of the command). | ||
1008 | */ | ||
1009 | |||
1010 | if (card->cmdrsp_buf) { | ||
1011 | cmdrsp_buf_pa = MWIFIEX_SKB_PACB(card->cmdrsp_buf); | ||
1012 | /* Write the lower 32bits of the cmdrsp buffer physical | ||
1013 | address */ | ||
1014 | if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_LO, | ||
1015 | (u32)*cmdrsp_buf_pa)) { | ||
1016 | dev_err(adapter->dev, "Failed to write download command to boot code.\n"); | ||
1017 | ret = -1; | ||
1018 | goto done; | ||
1019 | } | ||
1020 | /* Write the upper 32bits of the cmdrsp buffer physical | ||
1021 | address */ | ||
1022 | if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_HI, | ||
1023 | (u32)((u64)*cmdrsp_buf_pa >> 32))) { | ||
1024 | dev_err(adapter->dev, "Failed to write download command" | ||
1025 | " to boot code.\n"); | ||
1026 | ret = -1; | ||
1027 | goto done; | ||
1028 | } | ||
1029 | } | ||
1030 | |||
1031 | cmd_buf_pa = MWIFIEX_SKB_PACB(card->cmd_buf); | ||
1032 | /* Write the lower 32bits of the physical address to REG_CMD_ADDR_LO */ | ||
1033 | if (mwifiex_write_reg(adapter, REG_CMD_ADDR_LO, | ||
1034 | (u32)*cmd_buf_pa)) { | ||
1035 | dev_err(adapter->dev, "Failed to write download command " | ||
1036 | "to boot code.\n"); | ||
1037 | ret = -1; | ||
1038 | goto done; | ||
1039 | } | ||
1040 | /* Write the upper 32bits of the physical address to REG_CMD_ADDR_HI */ | ||
1041 | if (mwifiex_write_reg(adapter, REG_CMD_ADDR_HI, | ||
1042 | (u32)((u64)*cmd_buf_pa >> 32))) { | ||
1043 | dev_err(adapter->dev, "Failed to write download command " | ||
1044 | "to boot code.\n"); | ||
1045 | ret = -1; | ||
1046 | goto done; | ||
1047 | } | ||
1048 | |||
1049 | /* Write the command length to REG_CMD_SIZE */ | ||
1050 | if (mwifiex_write_reg(adapter, REG_CMD_SIZE, | ||
1051 | card->cmd_buf->len)) { | ||
1052 | dev_err(adapter->dev, "Failed to write command length to " | ||
1053 | "REG_CMD_SIZE\n"); | ||
1054 | ret = -1; | ||
1055 | goto done; | ||
1056 | } | ||
1057 | |||
1058 | /* Ring the door bell */ | ||
1059 | if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, | ||
1060 | CPU_INTR_DOOR_BELL)) { | ||
1061 | dev_err(adapter->dev, "Failed to assert door-bell " | ||
1062 | "interrupt.\n"); | ||
1063 | ret = -1; | ||
1064 | goto done; | ||
1065 | } | ||
1066 | |||
1067 | done: | ||
1068 | if (ret) | ||
1069 | adapter->cmd_sent = false; | ||
1070 | |||
1071 | return 0; | ||
1072 | } | ||
1073 | |||
1074 | /* | ||
1075 | * This function handles command complete interrupt | ||
1076 | */ | ||
1077 | static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) | ||
1078 | { | ||
1079 | struct pcie_service_card *card = adapter->card; | ||
1080 | int count = 0; | ||
1081 | |||
1082 | dev_dbg(adapter->dev, "info: Rx CMD Response\n"); | ||
1083 | |||
1084 | if (!adapter->curr_cmd) { | ||
1085 | skb_pull(card->cmdrsp_buf, INTF_HEADER_LEN); | ||
1086 | if (adapter->ps_state == PS_STATE_SLEEP_CFM) { | ||
1087 | mwifiex_process_sleep_confirm_resp(adapter, | ||
1088 | card->cmdrsp_buf->data, | ||
1089 | card->cmdrsp_buf->len); | ||
1090 | while (mwifiex_pcie_ok_to_access_hw(adapter) && | ||
1091 | (count++ < 10)) | ||
1092 | udelay(50); | ||
1093 | } else { | ||
1094 | dev_err(adapter->dev, "There is no command but " | ||
1095 | "got cmdrsp\n"); | ||
1096 | } | ||
1097 | memcpy(adapter->upld_buf, card->cmdrsp_buf->data, | ||
1098 | min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, | ||
1099 | card->cmdrsp_buf->len)); | ||
1100 | skb_push(card->cmdrsp_buf, INTF_HEADER_LEN); | ||
1101 | } else if (mwifiex_pcie_ok_to_access_hw(adapter)) { | ||
1102 | skb_pull(card->cmdrsp_buf, INTF_HEADER_LEN); | ||
1103 | adapter->curr_cmd->resp_skb = card->cmdrsp_buf; | ||
1104 | adapter->cmd_resp_received = true; | ||
1105 | /* Take the pointer and set it to CMD node and will | ||
1106 | return in the response complete callback */ | ||
1107 | card->cmdrsp_buf = NULL; | ||
1108 | |||
1109 | /* Clear the cmd-rsp buffer address in scratch registers. This | ||
1110 | will prevent firmware from writing to the same response | ||
1111 | buffer again. */ | ||
1112 | if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_LO, 0)) { | ||
1113 | dev_err(adapter->dev, "cmd_done: failed to clear " | ||
1114 | "cmd_rsp address.\n"); | ||
1115 | return -1; | ||
1116 | } | ||
1117 | /* Write the upper 32bits of the cmdrsp buffer physical | ||
1118 | address */ | ||
1119 | if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_HI, 0)) { | ||
1120 | dev_err(adapter->dev, "cmd_done: failed to clear " | ||
1121 | "cmd_rsp address.\n"); | ||
1122 | return -1; | ||
1123 | } | ||
1124 | } | ||
1125 | |||
1126 | return 0; | ||
1127 | } | ||
1128 | |||
1129 | /* | ||
1130 | * Command Response processing complete handler | ||
1131 | */ | ||
1132 | static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter, | ||
1133 | struct sk_buff *skb) | ||
1134 | { | ||
1135 | struct pcie_service_card *card = adapter->card; | ||
1136 | |||
1137 | if (skb) { | ||
1138 | card->cmdrsp_buf = skb; | ||
1139 | skb_push(card->cmdrsp_buf, INTF_HEADER_LEN); | ||
1140 | } | ||
1141 | |||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1145 | /* | ||
1146 | * This function handles firmware event ready interrupt | ||
1147 | */ | ||
1148 | static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter) | ||
1149 | { | ||
1150 | struct pcie_service_card *card = adapter->card; | ||
1151 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; | ||
1152 | u32 wrptr, event; | ||
1153 | |||
1154 | if (adapter->event_received) { | ||
1155 | dev_dbg(adapter->dev, "info: Event being processed, "\ | ||
1156 | "do not process this interrupt just yet\n"); | ||
1157 | return 0; | ||
1158 | } | ||
1159 | |||
1160 | if (rdptr >= MWIFIEX_MAX_EVT_BD) { | ||
1161 | dev_dbg(adapter->dev, "info: Invalid read pointer...\n"); | ||
1162 | return -1; | ||
1163 | } | ||
1164 | |||
1165 | /* Read the event ring write pointer set by firmware */ | ||
1166 | if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) { | ||
1167 | dev_err(adapter->dev, "EventReady: failed to read REG_EVTBD_WRPTR\n"); | ||
1168 | return -1; | ||
1169 | } | ||
1170 | |||
1171 | dev_dbg(adapter->dev, "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>", | ||
1172 | card->evtbd_rdptr, wrptr); | ||
1173 | if (((wrptr & MWIFIEX_EVTBD_MASK) != | ||
1174 | (card->evtbd_rdptr & MWIFIEX_EVTBD_MASK)) || | ||
1175 | ((wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) == | ||
1176 | (card->evtbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) { | ||
1177 | struct sk_buff *skb_cmd; | ||
1178 | __le16 data_len = 0; | ||
1179 | u16 evt_len; | ||
1180 | |||
1181 | dev_dbg(adapter->dev, "info: Read Index: %d\n", rdptr); | ||
1182 | skb_cmd = card->evt_buf_list[rdptr]; | ||
1183 | /* Take the pointer and set it to event pointer in adapter | ||
1184 | and will return back after event handling callback */ | ||
1185 | card->evt_buf_list[rdptr] = NULL; | ||
1186 | card->evtbd_ring[rdptr]->paddr = 0; | ||
1187 | card->evtbd_ring[rdptr]->len = 0; | ||
1188 | card->evtbd_ring[rdptr]->flags = 0; | ||
1189 | |||
1190 | event = *(u32 *) &skb_cmd->data[INTF_HEADER_LEN]; | ||
1191 | adapter->event_cause = event; | ||
1192 | /* The first 4bytes will be the event transfer header | ||
1193 | len is 2 bytes followed by type which is 2 bytes */ | ||
1194 | memcpy(&data_len, skb_cmd->data, sizeof(__le16)); | ||
1195 | evt_len = le16_to_cpu(data_len); | ||
1196 | |||
1197 | skb_pull(skb_cmd, INTF_HEADER_LEN); | ||
1198 | dev_dbg(adapter->dev, "info: Event length: %d\n", evt_len); | ||
1199 | |||
1200 | if ((evt_len > 0) && (evt_len < MAX_EVENT_SIZE)) | ||
1201 | memcpy(adapter->event_body, skb_cmd->data + | ||
1202 | MWIFIEX_EVENT_HEADER_LEN, evt_len - | ||
1203 | MWIFIEX_EVENT_HEADER_LEN); | ||
1204 | |||
1205 | adapter->event_received = true; | ||
1206 | adapter->event_skb = skb_cmd; | ||
1207 | |||
1208 | /* Do not update the event read pointer here, wait till the | ||
1209 | buffer is released. This is just to make things simpler, | ||
1210 | we need to find a better method of managing these buffers. | ||
1211 | */ | ||
1212 | } | ||
1213 | |||
1214 | return 0; | ||
1215 | } | ||
1216 | |||
1217 | /* | ||
1218 | * Event processing complete handler | ||
1219 | */ | ||
1220 | static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, | ||
1221 | struct sk_buff *skb) | ||
1222 | { | ||
1223 | struct pcie_service_card *card = adapter->card; | ||
1224 | int ret = 0; | ||
1225 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; | ||
1226 | u32 wrptr; | ||
1227 | phys_addr_t *buf_pa; | ||
1228 | |||
1229 | if (!skb) | ||
1230 | return 0; | ||
1231 | |||
1232 | if (rdptr >= MWIFIEX_MAX_EVT_BD) | ||
1233 | dev_err(adapter->dev, "event_complete: Invalid rdptr 0x%x\n", | ||
1234 | rdptr); | ||
1235 | |||
1236 | /* Read the event ring write pointer set by firmware */ | ||
1237 | if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) { | ||
1238 | dev_err(adapter->dev, "event_complete: failed to read REG_EVTBD_WRPTR\n"); | ||
1239 | ret = -1; | ||
1240 | goto done; | ||
1241 | } | ||
1242 | |||
1243 | if (!card->evt_buf_list[rdptr]) { | ||
1244 | skb_push(skb, INTF_HEADER_LEN); | ||
1245 | card->evt_buf_list[rdptr] = skb; | ||
1246 | buf_pa = MWIFIEX_SKB_PACB(skb); | ||
1247 | card->evtbd_ring[rdptr]->paddr = *buf_pa; | ||
1248 | card->evtbd_ring[rdptr]->len = (u16)skb->len; | ||
1249 | card->evtbd_ring[rdptr]->flags = 0; | ||
1250 | skb = NULL; | ||
1251 | } else { | ||
1252 | dev_dbg(adapter->dev, "info: ERROR: Buffer is still valid at " | ||
1253 | "index %d, <%p, %p>\n", rdptr, | ||
1254 | card->evt_buf_list[rdptr], skb); | ||
1255 | } | ||
1256 | |||
1257 | if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) { | ||
1258 | card->evtbd_rdptr = ((card->evtbd_rdptr & | ||
1259 | MWIFIEX_BD_FLAG_ROLLOVER_IND) ^ | ||
1260 | MWIFIEX_BD_FLAG_ROLLOVER_IND); | ||
1261 | } | ||
1262 | |||
1263 | dev_dbg(adapter->dev, "info: Updated <Rd: 0x%x, Wr: 0x%x>", | ||
1264 | card->evtbd_rdptr, wrptr); | ||
1265 | |||
1266 | /* Write the event ring read pointer in to REG_EVTBD_RDPTR */ | ||
1267 | if (mwifiex_write_reg(adapter, REG_EVTBD_RDPTR, card->evtbd_rdptr)) { | ||
1268 | dev_err(adapter->dev, "event_complete: failed to read REG_EVTBD_RDPTR\n"); | ||
1269 | ret = -1; | ||
1270 | goto done; | ||
1271 | } | ||
1272 | |||
1273 | done: | ||
1274 | /* Free the buffer for failure case */ | ||
1275 | if (ret && skb) | ||
1276 | dev_kfree_skb_any(skb); | ||
1277 | |||
1278 | dev_dbg(adapter->dev, "info: Check Events Again\n"); | ||
1279 | ret = mwifiex_pcie_process_event_ready(adapter); | ||
1280 | |||
1281 | return ret; | ||
1282 | } | ||
1283 | |||
1284 | /* | ||
1285 | * This function downloads the firmware to the card. | ||
1286 | * | ||
1287 | * Firmware is downloaded to the card in blocks. Every block download | ||
1288 | * is tested for CRC errors, and retried a number of times before | ||
1289 | * returning failure. | ||
1290 | */ | ||
1291 | static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | ||
1292 | struct mwifiex_fw_image *fw) | ||
1293 | { | ||
1294 | int ret; | ||
1295 | u8 *firmware = fw->fw_buf; | ||
1296 | u32 firmware_len = fw->fw_len; | ||
1297 | u32 offset = 0; | ||
1298 | struct sk_buff *skb; | ||
1299 | u32 txlen, tx_blocks = 0, tries, len; | ||
1300 | u32 block_retry_cnt = 0; | ||
1301 | |||
1302 | if (!adapter) { | ||
1303 | pr_err("adapter structure is not valid\n"); | ||
1304 | return -1; | ||
1305 | } | ||
1306 | |||
1307 | if (!firmware || !firmware_len) { | ||
1308 | dev_err(adapter->dev, "No firmware image found! " | ||
1309 | "Terminating download\n"); | ||
1310 | return -1; | ||
1311 | } | ||
1312 | |||
1313 | dev_dbg(adapter->dev, "info: Downloading FW image (%d bytes)\n", | ||
1314 | firmware_len); | ||
1315 | |||
1316 | if (mwifiex_pcie_disable_host_int(adapter)) { | ||
1317 | dev_err(adapter->dev, "%s: Disabling interrupts" | ||
1318 | " failed.\n", __func__); | ||
1319 | return -1; | ||
1320 | } | ||
1321 | |||
1322 | skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE); | ||
1323 | if (!skb) { | ||
1324 | ret = -ENOMEM; | ||
1325 | goto done; | ||
1326 | } | ||
1327 | mwifiex_update_sk_buff_pa(skb); | ||
1328 | |||
1329 | /* Perform firmware data transfer */ | ||
1330 | do { | ||
1331 | u32 ireg_intr = 0; | ||
1332 | |||
1333 | /* More data? */ | ||
1334 | if (offset >= firmware_len) | ||
1335 | break; | ||
1336 | |||
1337 | for (tries = 0; tries < MAX_POLL_TRIES; tries++) { | ||
1338 | ret = mwifiex_read_reg(adapter, PCIE_SCRATCH_2_REG, | ||
1339 | &len); | ||
1340 | if (ret) { | ||
1341 | dev_warn(adapter->dev, "Failed reading length from boot code\n"); | ||
1342 | goto done; | ||
1343 | } | ||
1344 | if (len) | ||
1345 | break; | ||
1346 | udelay(10); | ||
1347 | } | ||
1348 | |||
1349 | if (!len) { | ||
1350 | break; | ||
1351 | } else if (len > MWIFIEX_UPLD_SIZE) { | ||
1352 | pr_err("FW download failure @ %d, invalid length %d\n", | ||
1353 | offset, len); | ||
1354 | ret = -1; | ||
1355 | goto done; | ||
1356 | } | ||
1357 | |||
1358 | txlen = len; | ||
1359 | |||
1360 | if (len & BIT(0)) { | ||
1361 | block_retry_cnt++; | ||
1362 | if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) { | ||
1363 | pr_err("FW download failure @ %d, over max " | ||
1364 | "retry count\n", offset); | ||
1365 | ret = -1; | ||
1366 | goto done; | ||
1367 | } | ||
1368 | dev_err(adapter->dev, "FW CRC error indicated by the " | ||
1369 | "helper: len = 0x%04X, txlen = " | ||
1370 | "%d\n", len, txlen); | ||
1371 | len &= ~BIT(0); | ||
1372 | /* Setting this to 0 to resend from same offset */ | ||
1373 | txlen = 0; | ||
1374 | } else { | ||
1375 | block_retry_cnt = 0; | ||
1376 | /* Set blocksize to transfer - checking for | ||
1377 | last block */ | ||
1378 | if (firmware_len - offset < txlen) | ||
1379 | txlen = firmware_len - offset; | ||
1380 | |||
1381 | dev_dbg(adapter->dev, "."); | ||
1382 | |||
1383 | tx_blocks = | ||
1384 | (txlen + MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD - 1) / | ||
1385 | MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD; | ||
1386 | |||
1387 | /* Copy payload to buffer */ | ||
1388 | memmove(skb->data, &firmware[offset], txlen); | ||
1389 | } | ||
1390 | |||
1391 | skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len); | ||
1392 | skb_trim(skb, tx_blocks * MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD); | ||
1393 | |||
1394 | /* Send the boot command to device */ | ||
1395 | if (mwifiex_pcie_send_boot_cmd(adapter, skb)) { | ||
1396 | dev_err(adapter->dev, "Failed to send firmware download command\n"); | ||
1397 | ret = -1; | ||
1398 | goto done; | ||
1399 | } | ||
1400 | /* Wait for the command done interrupt */ | ||
1401 | do { | ||
1402 | if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS, | ||
1403 | &ireg_intr)) { | ||
1404 | dev_err(adapter->dev, "%s: Failed to read " | ||
1405 | "interrupt status during " | ||
1406 | "fw dnld.\n", __func__); | ||
1407 | ret = -1; | ||
1408 | goto done; | ||
1409 | } | ||
1410 | } while ((ireg_intr & CPU_INTR_DOOR_BELL) == | ||
1411 | CPU_INTR_DOOR_BELL); | ||
1412 | offset += txlen; | ||
1413 | } while (true); | ||
1414 | |||
1415 | dev_dbg(adapter->dev, "info:\nFW download over, size %d bytes\n", | ||
1416 | offset); | ||
1417 | |||
1418 | ret = 0; | ||
1419 | |||
1420 | done: | ||
1421 | dev_kfree_skb_any(skb); | ||
1422 | return ret; | ||
1423 | } | ||
1424 | |||
1425 | /* | ||
1426 | * This function checks the firmware status in card. | ||
1427 | * | ||
1428 | * The winner interface is also determined by this function. | ||
1429 | */ | ||
1430 | static int | ||
1431 | mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) | ||
1432 | { | ||
1433 | int ret = 0; | ||
1434 | u32 firmware_stat, winner_status; | ||
1435 | u32 tries; | ||
1436 | |||
1437 | /* Mask spurios interrupts */ | ||
1438 | if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK, | ||
1439 | HOST_INTR_MASK)) { | ||
1440 | dev_warn(adapter->dev, "Write register failed\n"); | ||
1441 | return -1; | ||
1442 | } | ||
1443 | |||
1444 | dev_dbg(adapter->dev, "Setting driver ready signature\n"); | ||
1445 | if (mwifiex_write_reg(adapter, REG_DRV_READY, FIRMWARE_READY_PCIE)) { | ||
1446 | dev_err(adapter->dev, "Failed to write driver ready signature\n"); | ||
1447 | return -1; | ||
1448 | } | ||
1449 | |||
1450 | /* Wait for firmware initialization event */ | ||
1451 | for (tries = 0; tries < poll_num; tries++) { | ||
1452 | if (mwifiex_read_reg(adapter, PCIE_SCRATCH_3_REG, | ||
1453 | &firmware_stat)) | ||
1454 | ret = -1; | ||
1455 | else | ||
1456 | ret = 0; | ||
1457 | if (ret) | ||
1458 | continue; | ||
1459 | if (firmware_stat == FIRMWARE_READY_PCIE) { | ||
1460 | ret = 0; | ||
1461 | break; | ||
1462 | } else { | ||
1463 | mdelay(100); | ||
1464 | ret = -1; | ||
1465 | } | ||
1466 | } | ||
1467 | |||
1468 | if (ret) { | ||
1469 | if (mwifiex_read_reg(adapter, PCIE_SCRATCH_3_REG, | ||
1470 | &winner_status)) | ||
1471 | ret = -1; | ||
1472 | else if (!winner_status) { | ||
1473 | dev_err(adapter->dev, "PCI-E is the winner\n"); | ||
1474 | adapter->winner = 1; | ||
1475 | ret = -1; | ||
1476 | } else { | ||
1477 | dev_err(adapter->dev, "PCI-E is not the winner <%#x, %d>, exit download\n", | ||
1478 | ret, adapter->winner); | ||
1479 | ret = 0; | ||
1480 | } | ||
1481 | } | ||
1482 | |||
1483 | return ret; | ||
1484 | } | ||
1485 | |||
1486 | /* | ||
1487 | * This function reads the interrupt status from card. | ||
1488 | */ | ||
1489 | static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) | ||
1490 | { | ||
1491 | u32 pcie_ireg; | ||
1492 | unsigned long flags; | ||
1493 | |||
1494 | if (!mwifiex_pcie_ok_to_access_hw(adapter)) | ||
1495 | return; | ||
1496 | |||
1497 | if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, &pcie_ireg)) { | ||
1498 | dev_warn(adapter->dev, "Read register failed\n"); | ||
1499 | return; | ||
1500 | } | ||
1501 | |||
1502 | if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) { | ||
1503 | |||
1504 | mwifiex_pcie_disable_host_int(adapter); | ||
1505 | |||
1506 | /* Clear the pending interrupts */ | ||
1507 | if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS, | ||
1508 | ~pcie_ireg)) { | ||
1509 | dev_warn(adapter->dev, "Write register failed\n"); | ||
1510 | return; | ||
1511 | } | ||
1512 | spin_lock_irqsave(&adapter->int_lock, flags); | ||
1513 | adapter->int_status |= pcie_ireg; | ||
1514 | spin_unlock_irqrestore(&adapter->int_lock, flags); | ||
1515 | |||
1516 | if (pcie_ireg & HOST_INTR_CMD_DONE) { | ||
1517 | if ((adapter->ps_state == PS_STATE_SLEEP_CFM) || | ||
1518 | (adapter->ps_state == PS_STATE_SLEEP)) { | ||
1519 | mwifiex_pcie_enable_host_int(adapter); | ||
1520 | if (mwifiex_write_reg(adapter, | ||
1521 | PCIE_CPU_INT_EVENT, | ||
1522 | CPU_INTR_SLEEP_CFM_DONE)) { | ||
1523 | dev_warn(adapter->dev, "Write register" | ||
1524 | " failed\n"); | ||
1525 | return; | ||
1526 | |||
1527 | } | ||
1528 | } | ||
1529 | } else if (!adapter->pps_uapsd_mode && | ||
1530 | adapter->ps_state == PS_STATE_SLEEP) { | ||
1531 | /* Potentially for PCIe we could get other | ||
1532 | * interrupts like shared. Don't change power | ||
1533 | * state until cookie is set */ | ||
1534 | if (mwifiex_pcie_ok_to_access_hw(adapter)) | ||
1535 | adapter->ps_state = PS_STATE_AWAKE; | ||
1536 | } | ||
1537 | } | ||
1538 | } | ||
1539 | |||
1540 | /* | ||
1541 | * Interrupt handler for PCIe root port | ||
1542 | * | ||
1543 | * This function reads the interrupt status from firmware and assigns | ||
1544 | * the main process in workqueue which will handle the interrupt. | ||
1545 | */ | ||
1546 | static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context) | ||
1547 | { | ||
1548 | struct pci_dev *pdev = (struct pci_dev *)context; | ||
1549 | struct pcie_service_card *card; | ||
1550 | struct mwifiex_adapter *adapter; | ||
1551 | |||
1552 | if (!pdev) { | ||
1553 | pr_debug("info: %s: pdev is NULL\n", (u8 *)pdev); | ||
1554 | goto exit; | ||
1555 | } | ||
1556 | |||
1557 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | ||
1558 | if (!card || !card->adapter) { | ||
1559 | pr_debug("info: %s: card=%p adapter=%p\n", __func__, card, | ||
1560 | card ? card->adapter : NULL); | ||
1561 | goto exit; | ||
1562 | } | ||
1563 | adapter = card->adapter; | ||
1564 | |||
1565 | if (adapter->surprise_removed) | ||
1566 | goto exit; | ||
1567 | |||
1568 | mwifiex_interrupt_status(adapter); | ||
1569 | queue_work(adapter->workqueue, &adapter->main_work); | ||
1570 | |||
1571 | exit: | ||
1572 | return IRQ_HANDLED; | ||
1573 | } | ||
1574 | |||
1575 | /* | ||
1576 | * This function checks the current interrupt status. | ||
1577 | * | ||
1578 | * The following interrupts are checked and handled by this function - | ||
1579 | * - Data sent | ||
1580 | * - Command sent | ||
1581 | * - Command received | ||
1582 | * - Packets received | ||
1583 | * - Events received | ||
1584 | * | ||
1585 | * In case of Rx packets received, the packets are uploaded from card to | ||
1586 | * host and processed accordingly. | ||
1587 | */ | ||
1588 | static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | ||
1589 | { | ||
1590 | int ret; | ||
1591 | u32 pcie_ireg = 0; | ||
1592 | unsigned long flags; | ||
1593 | |||
1594 | spin_lock_irqsave(&adapter->int_lock, flags); | ||
1595 | /* Clear out unused interrupts */ | ||
1596 | adapter->int_status &= HOST_INTR_MASK; | ||
1597 | spin_unlock_irqrestore(&adapter->int_lock, flags); | ||
1598 | |||
1599 | while (adapter->int_status & HOST_INTR_MASK) { | ||
1600 | if (adapter->int_status & HOST_INTR_DNLD_DONE) { | ||
1601 | adapter->int_status &= ~HOST_INTR_DNLD_DONE; | ||
1602 | if (adapter->data_sent) { | ||
1603 | dev_dbg(adapter->dev, "info: DATA sent Interrupt\n"); | ||
1604 | adapter->data_sent = false; | ||
1605 | } | ||
1606 | } | ||
1607 | if (adapter->int_status & HOST_INTR_UPLD_RDY) { | ||
1608 | adapter->int_status &= ~HOST_INTR_UPLD_RDY; | ||
1609 | dev_dbg(adapter->dev, "info: Rx DATA\n"); | ||
1610 | ret = mwifiex_pcie_process_recv_data(adapter); | ||
1611 | if (ret) | ||
1612 | return ret; | ||
1613 | } | ||
1614 | if (adapter->int_status & HOST_INTR_EVENT_RDY) { | ||
1615 | adapter->int_status &= ~HOST_INTR_EVENT_RDY; | ||
1616 | dev_dbg(adapter->dev, "info: Rx EVENT\n"); | ||
1617 | ret = mwifiex_pcie_process_event_ready(adapter); | ||
1618 | if (ret) | ||
1619 | return ret; | ||
1620 | } | ||
1621 | |||
1622 | if (adapter->int_status & HOST_INTR_CMD_DONE) { | ||
1623 | adapter->int_status &= ~HOST_INTR_CMD_DONE; | ||
1624 | if (adapter->cmd_sent) { | ||
1625 | dev_dbg(adapter->dev, "info: CMD sent Interrupt\n"); | ||
1626 | adapter->cmd_sent = false; | ||
1627 | } | ||
1628 | /* Handle command response */ | ||
1629 | ret = mwifiex_pcie_process_cmd_complete(adapter); | ||
1630 | if (ret) | ||
1631 | return ret; | ||
1632 | } | ||
1633 | |||
1634 | if (mwifiex_pcie_ok_to_access_hw(adapter)) { | ||
1635 | if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, | ||
1636 | &pcie_ireg)) { | ||
1637 | dev_warn(adapter->dev, "Read register failed\n"); | ||
1638 | return -1; | ||
1639 | } | ||
1640 | |||
1641 | if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) { | ||
1642 | if (mwifiex_write_reg(adapter, | ||
1643 | PCIE_HOST_INT_STATUS, ~pcie_ireg)) { | ||
1644 | dev_warn(adapter->dev, "Write register" | ||
1645 | " failed\n"); | ||
1646 | return -1; | ||
1647 | } | ||
1648 | adapter->int_status |= pcie_ireg; | ||
1649 | adapter->int_status &= HOST_INTR_MASK; | ||
1650 | } | ||
1651 | |||
1652 | } | ||
1653 | } | ||
1654 | dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n", | ||
1655 | adapter->cmd_sent, adapter->data_sent); | ||
1656 | mwifiex_pcie_enable_host_int(adapter); | ||
1657 | |||
1658 | return 0; | ||
1659 | } | ||
1660 | |||
1661 | /* | ||
1662 | * This function downloads data from driver to card. | ||
1663 | * | ||
1664 | * Both commands and data packets are transferred to the card by this | ||
1665 | * function. | ||
1666 | * | ||
1667 | * This function adds the PCIE specific header to the front of the buffer | ||
1668 | * before transferring. The header contains the length of the packet and | ||
1669 | * the type. The firmware handles the packets based upon this set type. | ||
1670 | */ | ||
1671 | static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type, | ||
1672 | struct sk_buff *skb, | ||
1673 | struct mwifiex_tx_param *tx_param) | ||
1674 | { | ||
1675 | if (!adapter || !skb) { | ||
1676 | dev_err(adapter->dev, "Invalid parameter in %s <%p, %p>\n", | ||
1677 | __func__, adapter, skb); | ||
1678 | return -1; | ||
1679 | } | ||
1680 | |||
1681 | if (type == MWIFIEX_TYPE_DATA) | ||
1682 | return mwifiex_pcie_send_data(adapter, skb); | ||
1683 | else if (type == MWIFIEX_TYPE_CMD) | ||
1684 | return mwifiex_pcie_send_cmd(adapter, skb); | ||
1685 | |||
1686 | return 0; | ||
1687 | } | ||
1688 | |||
1689 | /* | ||
1690 | * This function initializes the PCI-E host memory space, WCB rings, etc. | ||
1691 | * | ||
1692 | * The following initializations steps are followed - | ||
1693 | * - Allocate TXBD ring buffers | ||
1694 | * - Allocate RXBD ring buffers | ||
1695 | * - Allocate event BD ring buffers | ||
1696 | * - Allocate command response ring buffer | ||
1697 | * - Allocate sleep cookie buffer | ||
1698 | */ | ||
1699 | static int mwifiex_pcie_init(struct mwifiex_adapter *adapter) | ||
1700 | { | ||
1701 | struct pcie_service_card *card = adapter->card; | ||
1702 | int ret; | ||
1703 | struct pci_dev *pdev = card->dev; | ||
1704 | |||
1705 | pci_set_drvdata(pdev, card); | ||
1706 | |||
1707 | ret = pci_enable_device(pdev); | ||
1708 | if (ret) | ||
1709 | goto err_enable_dev; | ||
1710 | |||
1711 | pci_set_master(pdev); | ||
1712 | |||
1713 | dev_dbg(adapter->dev, "try set_consistent_dma_mask(32)\n"); | ||
1714 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
1715 | if (ret) { | ||
1716 | dev_err(adapter->dev, "set_dma_mask(32) failed\n"); | ||
1717 | goto err_set_dma_mask; | ||
1718 | } | ||
1719 | |||
1720 | ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
1721 | if (ret) { | ||
1722 | dev_err(adapter->dev, "set_consistent_dma_mask(64) failed\n"); | ||
1723 | goto err_set_dma_mask; | ||
1724 | } | ||
1725 | |||
1726 | ret = pci_request_region(pdev, 0, DRV_NAME); | ||
1727 | if (ret) { | ||
1728 | dev_err(adapter->dev, "req_reg(0) error\n"); | ||
1729 | goto err_req_region0; | ||
1730 | } | ||
1731 | card->pci_mmap = pci_iomap(pdev, 0, 0); | ||
1732 | if (!card->pci_mmap) { | ||
1733 | dev_err(adapter->dev, "iomap(0) error\n"); | ||
1734 | goto err_iomap0; | ||
1735 | } | ||
1736 | ret = pci_request_region(pdev, 2, DRV_NAME); | ||
1737 | if (ret) { | ||
1738 | dev_err(adapter->dev, "req_reg(2) error\n"); | ||
1739 | goto err_req_region2; | ||
1740 | } | ||
1741 | card->pci_mmap1 = pci_iomap(pdev, 2, 0); | ||
1742 | if (!card->pci_mmap1) { | ||
1743 | dev_err(adapter->dev, "iomap(2) error\n"); | ||
1744 | goto err_iomap2; | ||
1745 | } | ||
1746 | |||
1747 | dev_dbg(adapter->dev, "PCI memory map Virt0: %p PCI memory map Virt2: " | ||
1748 | "%p\n", card->pci_mmap, card->pci_mmap1); | ||
1749 | |||
1750 | card->cmdrsp_buf = NULL; | ||
1751 | ret = mwifiex_pcie_create_txbd_ring(adapter); | ||
1752 | if (ret) | ||
1753 | goto err_cre_txbd; | ||
1754 | ret = mwifiex_pcie_create_rxbd_ring(adapter); | ||
1755 | if (ret) | ||
1756 | goto err_cre_rxbd; | ||
1757 | ret = mwifiex_pcie_create_evtbd_ring(adapter); | ||
1758 | if (ret) | ||
1759 | goto err_cre_evtbd; | ||
1760 | ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter); | ||
1761 | if (ret) | ||
1762 | goto err_alloc_cmdbuf; | ||
1763 | ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter); | ||
1764 | if (ret) | ||
1765 | goto err_alloc_cookie; | ||
1766 | |||
1767 | return ret; | ||
1768 | |||
1769 | err_alloc_cookie: | ||
1770 | mwifiex_pcie_delete_cmdrsp_buf(adapter); | ||
1771 | err_alloc_cmdbuf: | ||
1772 | mwifiex_pcie_delete_evtbd_ring(adapter); | ||
1773 | err_cre_evtbd: | ||
1774 | mwifiex_pcie_delete_rxbd_ring(adapter); | ||
1775 | err_cre_rxbd: | ||
1776 | mwifiex_pcie_delete_txbd_ring(adapter); | ||
1777 | err_cre_txbd: | ||
1778 | pci_iounmap(pdev, card->pci_mmap1); | ||
1779 | err_iomap2: | ||
1780 | pci_release_region(pdev, 2); | ||
1781 | err_req_region2: | ||
1782 | pci_iounmap(pdev, card->pci_mmap); | ||
1783 | err_iomap0: | ||
1784 | pci_release_region(pdev, 0); | ||
1785 | err_req_region0: | ||
1786 | err_set_dma_mask: | ||
1787 | pci_disable_device(pdev); | ||
1788 | err_enable_dev: | ||
1789 | pci_set_drvdata(pdev, NULL); | ||
1790 | return ret; | ||
1791 | } | ||
1792 | |||
1793 | /* | ||
1794 | * This function cleans up the allocated card buffers. | ||
1795 | * | ||
1796 | * The following are freed by this function - | ||
1797 | * - TXBD ring buffers | ||
1798 | * - RXBD ring buffers | ||
1799 | * - Event BD ring buffers | ||
1800 | * - Command response ring buffer | ||
1801 | * - Sleep cookie buffer | ||
1802 | */ | ||
1803 | static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter) | ||
1804 | { | ||
1805 | struct pcie_service_card *card = adapter->card; | ||
1806 | struct pci_dev *pdev = card->dev; | ||
1807 | |||
1808 | mwifiex_pcie_delete_sleep_cookie_buf(adapter); | ||
1809 | mwifiex_pcie_delete_cmdrsp_buf(adapter); | ||
1810 | mwifiex_pcie_delete_evtbd_ring(adapter); | ||
1811 | mwifiex_pcie_delete_rxbd_ring(adapter); | ||
1812 | mwifiex_pcie_delete_txbd_ring(adapter); | ||
1813 | card->cmdrsp_buf = NULL; | ||
1814 | |||
1815 | dev_dbg(adapter->dev, "Clearing driver ready signature\n"); | ||
1816 | if (user_rmmod) { | ||
1817 | if (mwifiex_write_reg(adapter, REG_DRV_READY, 0x00000000)) | ||
1818 | dev_err(adapter->dev, "Failed to write driver not-ready signature\n"); | ||
1819 | } | ||
1820 | |||
1821 | if (pdev) { | ||
1822 | pci_iounmap(pdev, card->pci_mmap); | ||
1823 | pci_iounmap(pdev, card->pci_mmap1); | ||
1824 | |||
1825 | pci_release_regions(pdev); | ||
1826 | pci_disable_device(pdev); | ||
1827 | pci_set_drvdata(pdev, NULL); | ||
1828 | } | ||
1829 | } | ||
1830 | |||
1831 | /* | ||
1832 | * This function registers the PCIE device. | ||
1833 | * | ||
1834 | * PCIE IRQ is claimed, block size is set and driver data is initialized. | ||
1835 | */ | ||
1836 | static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | ||
1837 | { | ||
1838 | int ret; | ||
1839 | struct pcie_service_card *card = adapter->card; | ||
1840 | struct pci_dev *pdev = card->dev; | ||
1841 | |||
1842 | /* save adapter pointer in card */ | ||
1843 | card->adapter = adapter; | ||
1844 | |||
1845 | ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED, | ||
1846 | "MRVL_PCIE", pdev); | ||
1847 | if (ret) { | ||
1848 | pr_err("request_irq failed: ret=%d\n", ret); | ||
1849 | adapter->card = NULL; | ||
1850 | return -1; | ||
1851 | } | ||
1852 | |||
1853 | adapter->dev = &pdev->dev; | ||
1854 | strcpy(adapter->fw_name, PCIE8766_DEFAULT_FW_NAME); | ||
1855 | |||
1856 | return 0; | ||
1857 | } | ||
1858 | |||
1859 | /* | ||
1860 | * This function unregisters the PCIE device. | ||
1861 | * | ||
1862 | * The PCIE IRQ is released, the function is disabled and driver | ||
1863 | * data is set to null. | ||
1864 | */ | ||
1865 | static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter) | ||
1866 | { | ||
1867 | struct pcie_service_card *card = adapter->card; | ||
1868 | |||
1869 | if (card) { | ||
1870 | dev_dbg(adapter->dev, "%s(): calling free_irq()\n", __func__); | ||
1871 | free_irq(card->dev->irq, card->dev); | ||
1872 | } | ||
1873 | } | ||
1874 | |||
1875 | static struct mwifiex_if_ops pcie_ops = { | ||
1876 | .init_if = mwifiex_pcie_init, | ||
1877 | .cleanup_if = mwifiex_pcie_cleanup, | ||
1878 | .check_fw_status = mwifiex_check_fw_status, | ||
1879 | .prog_fw = mwifiex_prog_fw_w_helper, | ||
1880 | .register_dev = mwifiex_register_dev, | ||
1881 | .unregister_dev = mwifiex_unregister_dev, | ||
1882 | .enable_int = mwifiex_pcie_enable_host_int, | ||
1883 | .process_int_status = mwifiex_process_int_status, | ||
1884 | .host_to_card = mwifiex_pcie_host_to_card, | ||
1885 | .wakeup = mwifiex_pm_wakeup_card, | ||
1886 | .wakeup_complete = mwifiex_pm_wakeup_card_complete, | ||
1887 | |||
1888 | /* PCIE specific */ | ||
1889 | .cmdrsp_complete = mwifiex_pcie_cmdrsp_complete, | ||
1890 | .event_complete = mwifiex_pcie_event_complete, | ||
1891 | .update_mp_end_port = NULL, | ||
1892 | .cleanup_mpa_buf = NULL, | ||
1893 | }; | ||
1894 | |||
1895 | /* | ||
1896 | * This function initializes the PCIE driver module. | ||
1897 | * | ||
1898 | * This initiates the semaphore and registers the device with | ||
1899 | * PCIE bus. | ||
1900 | */ | ||
1901 | static int mwifiex_pcie_init_module(void) | ||
1902 | { | ||
1903 | int ret; | ||
1904 | |||
1905 | pr_debug("Marvell 8766 PCIe Driver\n"); | ||
1906 | |||
1907 | sema_init(&add_remove_card_sem, 1); | ||
1908 | |||
1909 | /* Clear the flag in case user removes the card. */ | ||
1910 | user_rmmod = 0; | ||
1911 | |||
1912 | ret = pci_register_driver(&mwifiex_pcie); | ||
1913 | if (ret) | ||
1914 | pr_err("Driver register failed!\n"); | ||
1915 | else | ||
1916 | pr_debug("info: Driver registered successfully!\n"); | ||
1917 | |||
1918 | return ret; | ||
1919 | } | ||
1920 | |||
1921 | /* | ||
1922 | * This function cleans up the PCIE driver. | ||
1923 | * | ||
1924 | * The following major steps are followed for cleanup - | ||
1925 | * - Resume the device if its suspended | ||
1926 | * - Disconnect the device if connected | ||
1927 | * - Shutdown the firmware | ||
1928 | * - Unregister the device from PCIE bus. | ||
1929 | */ | ||
1930 | static void mwifiex_pcie_cleanup_module(void) | ||
1931 | { | ||
1932 | if (!down_interruptible(&add_remove_card_sem)) | ||
1933 | up(&add_remove_card_sem); | ||
1934 | |||
1935 | /* Set the flag as user is removing this module. */ | ||
1936 | user_rmmod = 1; | ||
1937 | |||
1938 | pci_unregister_driver(&mwifiex_pcie); | ||
1939 | } | ||
1940 | |||
1941 | module_init(mwifiex_pcie_init_module); | ||
1942 | module_exit(mwifiex_pcie_cleanup_module); | ||
1943 | |||
1944 | MODULE_AUTHOR("Marvell International Ltd."); | ||
1945 | MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION); | ||
1946 | MODULE_VERSION(PCIE_VERSION); | ||
1947 | MODULE_LICENSE("GPL v2"); | ||
1948 | MODULE_FIRMWARE("mrvl/pcie8766_uapsta.bin"); | ||
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h new file mode 100644 index 000000000000..445ff21772e2 --- /dev/null +++ b/drivers/net/wireless/mwifiex/pcie.h | |||
@@ -0,0 +1,148 @@ | |||
1 | /* @file mwifiex_pcie.h | ||
2 | * | ||
3 | * @brief This file contains definitions for PCI-E interface. | ||
4 | * driver. | ||
5 | * | ||
6 | * Copyright (C) 2011, Marvell International Ltd. | ||
7 | * | ||
8 | * This software file (the "File") is distributed by Marvell International | ||
9 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
10 | * (the "License"). You may use, redistribute and/or modify this File in | ||
11 | * accordance with the terms and conditions of the License, a copy of which | ||
12 | * is available by writing to the Free Software Foundation, Inc., | ||
13 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
14 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
15 | * | ||
16 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
18 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
19 | * this warranty disclaimer. | ||
20 | */ | ||
21 | |||
22 | #ifndef _MWIFIEX_PCIE_H | ||
23 | #define _MWIFIEX_PCIE_H | ||
24 | |||
25 | #include <linux/pci.h> | ||
26 | #include <linux/pcieport_if.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | |||
29 | #include "main.h" | ||
30 | |||
31 | #define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin" | ||
32 | |||
33 | /* Constants for Buffer Descriptor (BD) rings */ | ||
34 | #define MWIFIEX_MAX_TXRX_BD 0x20 | ||
35 | #define MWIFIEX_TXBD_MASK 0x3F | ||
36 | #define MWIFIEX_RXBD_MASK 0x3F | ||
37 | |||
38 | #define MWIFIEX_MAX_EVT_BD 0x04 | ||
39 | #define MWIFIEX_EVTBD_MASK 0x07 | ||
40 | |||
41 | /* PCIE INTERNAL REGISTERS */ | ||
42 | #define PCIE_SCRATCH_0_REG 0xC10 | ||
43 | #define PCIE_SCRATCH_1_REG 0xC14 | ||
44 | #define PCIE_CPU_INT_EVENT 0xC18 | ||
45 | #define PCIE_CPU_INT_STATUS 0xC1C | ||
46 | #define PCIE_HOST_INT_STATUS 0xC30 | ||
47 | #define PCIE_HOST_INT_MASK 0xC34 | ||
48 | #define PCIE_HOST_INT_STATUS_MASK 0xC3C | ||
49 | #define PCIE_SCRATCH_2_REG 0xC40 | ||
50 | #define PCIE_SCRATCH_3_REG 0xC44 | ||
51 | #define PCIE_SCRATCH_4_REG 0xCC0 | ||
52 | #define PCIE_SCRATCH_5_REG 0xCC4 | ||
53 | #define PCIE_SCRATCH_6_REG 0xCC8 | ||
54 | #define PCIE_SCRATCH_7_REG 0xCCC | ||
55 | #define PCIE_SCRATCH_8_REG 0xCD0 | ||
56 | #define PCIE_SCRATCH_9_REG 0xCD4 | ||
57 | #define PCIE_SCRATCH_10_REG 0xCD8 | ||
58 | #define PCIE_SCRATCH_11_REG 0xCDC | ||
59 | #define PCIE_SCRATCH_12_REG 0xCE0 | ||
60 | |||
61 | #define CPU_INTR_DNLD_RDY BIT(0) | ||
62 | #define CPU_INTR_DOOR_BELL BIT(1) | ||
63 | #define CPU_INTR_SLEEP_CFM_DONE BIT(2) | ||
64 | #define CPU_INTR_RESET BIT(3) | ||
65 | |||
66 | #define HOST_INTR_DNLD_DONE BIT(0) | ||
67 | #define HOST_INTR_UPLD_RDY BIT(1) | ||
68 | #define HOST_INTR_CMD_DONE BIT(2) | ||
69 | #define HOST_INTR_EVENT_RDY BIT(3) | ||
70 | #define HOST_INTR_MASK (HOST_INTR_DNLD_DONE | \ | ||
71 | HOST_INTR_UPLD_RDY | \ | ||
72 | HOST_INTR_CMD_DONE | \ | ||
73 | HOST_INTR_EVENT_RDY) | ||
74 | |||
75 | #define MWIFIEX_BD_FLAG_ROLLOVER_IND BIT(7) | ||
76 | #define MWIFIEX_BD_FLAG_FIRST_DESC BIT(0) | ||
77 | #define MWIFIEX_BD_FLAG_LAST_DESC BIT(1) | ||
78 | #define REG_CMD_ADDR_LO PCIE_SCRATCH_0_REG | ||
79 | #define REG_CMD_ADDR_HI PCIE_SCRATCH_1_REG | ||
80 | #define REG_CMD_SIZE PCIE_SCRATCH_2_REG | ||
81 | |||
82 | #define REG_CMDRSP_ADDR_LO PCIE_SCRATCH_4_REG | ||
83 | #define REG_CMDRSP_ADDR_HI PCIE_SCRATCH_5_REG | ||
84 | |||
85 | /* TX buffer description read pointer */ | ||
86 | #define REG_TXBD_RDPTR PCIE_SCRATCH_6_REG | ||
87 | /* TX buffer description write pointer */ | ||
88 | #define REG_TXBD_WRPTR PCIE_SCRATCH_7_REG | ||
89 | /* RX buffer description read pointer */ | ||
90 | #define REG_RXBD_RDPTR PCIE_SCRATCH_8_REG | ||
91 | /* RX buffer description write pointer */ | ||
92 | #define REG_RXBD_WRPTR PCIE_SCRATCH_9_REG | ||
93 | /* Event buffer description read pointer */ | ||
94 | #define REG_EVTBD_RDPTR PCIE_SCRATCH_10_REG | ||
95 | /* Event buffer description write pointer */ | ||
96 | #define REG_EVTBD_WRPTR PCIE_SCRATCH_11_REG | ||
97 | /* Driver ready signature write pointer */ | ||
98 | #define REG_DRV_READY PCIE_SCRATCH_12_REG | ||
99 | |||
100 | /* Max retry number of command write */ | ||
101 | #define MAX_WRITE_IOMEM_RETRY 2 | ||
102 | /* Define PCIE block size for firmware download */ | ||
103 | #define MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD 256 | ||
104 | /* FW awake cookie after FW ready */ | ||
105 | #define FW_AWAKE_COOKIE (0xAA55AA55) | ||
106 | |||
107 | struct mwifiex_pcie_buf_desc { | ||
108 | u64 paddr; | ||
109 | u16 len; | ||
110 | u16 flags; | ||
111 | } __packed; | ||
112 | |||
113 | struct pcie_service_card { | ||
114 | struct pci_dev *dev; | ||
115 | struct mwifiex_adapter *adapter; | ||
116 | |||
117 | u32 txbd_wrptr; | ||
118 | u32 txbd_rdptr; | ||
119 | u32 txbd_ring_size; | ||
120 | u8 *txbd_ring_vbase; | ||
121 | phys_addr_t txbd_ring_pbase; | ||
122 | struct mwifiex_pcie_buf_desc *txbd_ring[MWIFIEX_MAX_TXRX_BD]; | ||
123 | struct sk_buff *tx_buf_list[MWIFIEX_MAX_TXRX_BD]; | ||
124 | |||
125 | u32 rxbd_wrptr; | ||
126 | u32 rxbd_rdptr; | ||
127 | u32 rxbd_ring_size; | ||
128 | u8 *rxbd_ring_vbase; | ||
129 | phys_addr_t rxbd_ring_pbase; | ||
130 | struct mwifiex_pcie_buf_desc *rxbd_ring[MWIFIEX_MAX_TXRX_BD]; | ||
131 | struct sk_buff *rx_buf_list[MWIFIEX_MAX_TXRX_BD]; | ||
132 | |||
133 | u32 evtbd_wrptr; | ||
134 | u32 evtbd_rdptr; | ||
135 | u32 evtbd_ring_size; | ||
136 | u8 *evtbd_ring_vbase; | ||
137 | phys_addr_t evtbd_ring_pbase; | ||
138 | struct mwifiex_pcie_buf_desc *evtbd_ring[MWIFIEX_MAX_EVT_BD]; | ||
139 | struct sk_buff *evt_buf_list[MWIFIEX_MAX_EVT_BD]; | ||
140 | |||
141 | struct sk_buff *cmd_buf; | ||
142 | struct sk_buff *cmdrsp_buf; | ||
143 | struct sk_buff *sleep_cookie; | ||
144 | void __iomem *pci_mmap; | ||
145 | void __iomem *pci_mmap1; | ||
146 | }; | ||
147 | |||
148 | #endif /* _MWIFIEX_PCIE_H */ | ||
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 82098ac483b8..283171bbcedf 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
@@ -89,7 +89,8 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) | |||
89 | return -EIO; | 89 | return -EIO; |
90 | } | 90 | } |
91 | 91 | ||
92 | if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops)) { | 92 | if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops, |
93 | MWIFIEX_SDIO)) { | ||
93 | pr_err("%s: add card failed\n", __func__); | 94 | pr_err("%s: add card failed\n", __func__); |
94 | kfree(card); | 95 | kfree(card); |
95 | sdio_claim_host(func); | 96 | sdio_claim_host(func); |
@@ -830,7 +831,7 @@ done: | |||
830 | * The winner interface is also determined by this function. | 831 | * The winner interface is also determined by this function. |
831 | */ | 832 | */ |
832 | static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, | 833 | static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, |
833 | u32 poll_num, int *winner) | 834 | u32 poll_num) |
834 | { | 835 | { |
835 | int ret = 0; | 836 | int ret = 0; |
836 | u16 firmware_stat; | 837 | u16 firmware_stat; |
@@ -842,7 +843,7 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, | |||
842 | ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat); | 843 | ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat); |
843 | if (ret) | 844 | if (ret) |
844 | continue; | 845 | continue; |
845 | if (firmware_stat == FIRMWARE_READY) { | 846 | if (firmware_stat == FIRMWARE_READY_SDIO) { |
846 | ret = 0; | 847 | ret = 0; |
847 | break; | 848 | break; |
848 | } else { | 849 | } else { |
@@ -851,15 +852,15 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, | |||
851 | } | 852 | } |
852 | } | 853 | } |
853 | 854 | ||
854 | if (winner && ret) { | 855 | if (ret) { |
855 | if (mwifiex_read_reg | 856 | if (mwifiex_read_reg |
856 | (adapter, CARD_FW_STATUS0_REG, &winner_status)) | 857 | (adapter, CARD_FW_STATUS0_REG, &winner_status)) |
857 | winner_status = 0; | 858 | winner_status = 0; |
858 | 859 | ||
859 | if (winner_status) | 860 | if (winner_status) |
860 | *winner = 0; | 861 | adapter->winner = 0; |
861 | else | 862 | else |
862 | *winner = 1; | 863 | adapter->winner = 1; |
863 | } | 864 | } |
864 | return ret; | 865 | return ret; |
865 | } | 866 | } |
@@ -1413,7 +1414,7 @@ tx_curr_single: | |||
1413 | * the type. The firmware handles the packets based upon this set type. | 1414 | * the type. The firmware handles the packets based upon this set type. |
1414 | */ | 1415 | */ |
1415 | static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, | 1416 | static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, |
1416 | u8 type, u8 *payload, u32 pkt_len, | 1417 | u8 type, struct sk_buff *skb, |
1417 | struct mwifiex_tx_param *tx_param) | 1418 | struct mwifiex_tx_param *tx_param) |
1418 | { | 1419 | { |
1419 | struct sdio_mmc_card *card = adapter->card; | 1420 | struct sdio_mmc_card *card = adapter->card; |
@@ -1421,6 +1422,8 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, | |||
1421 | u32 buf_block_len; | 1422 | u32 buf_block_len; |
1422 | u32 blk_size; | 1423 | u32 blk_size; |
1423 | u8 port = CTRL_PORT; | 1424 | u8 port = CTRL_PORT; |
1425 | u8 *payload = (u8 *)skb->data; | ||
1426 | u32 pkt_len = skb->len; | ||
1424 | 1427 | ||
1425 | /* Allocate buffer and copy payload */ | 1428 | /* Allocate buffer and copy payload */ |
1426 | blk_size = MWIFIEX_SDIO_BLOCK_SIZE; | 1429 | blk_size = MWIFIEX_SDIO_BLOCK_SIZE; |
@@ -1722,6 +1725,8 @@ static struct mwifiex_if_ops sdio_ops = { | |||
1722 | /* SDIO specific */ | 1725 | /* SDIO specific */ |
1723 | .update_mp_end_port = mwifiex_update_mp_end_port, | 1726 | .update_mp_end_port = mwifiex_update_mp_end_port, |
1724 | .cleanup_mpa_buf = mwifiex_cleanup_mpa_buf, | 1727 | .cleanup_mpa_buf = mwifiex_cleanup_mpa_buf, |
1728 | .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete, | ||
1729 | .event_complete = mwifiex_sdio_event_complete, | ||
1725 | }; | 1730 | }; |
1726 | 1731 | ||
1727 | /* | 1732 | /* |
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 524f78f4ee69..3f711801e58a 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h | |||
@@ -169,9 +169,6 @@ | |||
169 | /* Rx unit register */ | 169 | /* Rx unit register */ |
170 | #define CARD_RX_UNIT_REG 0x63 | 170 | #define CARD_RX_UNIT_REG 0x63 |
171 | 171 | ||
172 | /* Event header len w/o 4 bytes of interface header */ | ||
173 | #define MWIFIEX_EVENT_HEADER_LEN 4 | ||
174 | |||
175 | /* Max retry number of CMD53 write */ | 172 | /* Max retry number of CMD53 write */ |
176 | #define MAX_WRITE_IOMEM_RETRY 2 | 173 | #define MAX_WRITE_IOMEM_RETRY 2 |
177 | 174 | ||
@@ -304,4 +301,25 @@ struct sdio_mmc_card { | |||
304 | struct mwifiex_sdio_mpa_tx mpa_tx; | 301 | struct mwifiex_sdio_mpa_tx mpa_tx; |
305 | struct mwifiex_sdio_mpa_rx mpa_rx; | 302 | struct mwifiex_sdio_mpa_rx mpa_rx; |
306 | }; | 303 | }; |
304 | |||
305 | /* | ||
306 | * .cmdrsp_complete handler | ||
307 | */ | ||
308 | static inline int mwifiex_sdio_cmdrsp_complete(struct mwifiex_adapter *adapter, | ||
309 | struct sk_buff *skb) | ||
310 | { | ||
311 | dev_kfree_skb_any(skb); | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * .event_complete handler | ||
317 | */ | ||
318 | static inline int mwifiex_sdio_event_complete(struct mwifiex_adapter *adapter, | ||
319 | struct sk_buff *skb) | ||
320 | { | ||
321 | dev_kfree_skb_any(skb); | ||
322 | return 0; | ||
323 | } | ||
324 | |||
307 | #endif /* _MWIFIEX_SDIO_H */ | 325 | #endif /* _MWIFIEX_SDIO_H */ |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index c54ee287b878..ea6518d1c9e3 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -902,6 +902,59 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd, | |||
902 | } | 902 | } |
903 | 903 | ||
904 | /* | 904 | /* |
905 | * This function prepares command to set PCI-Express | ||
906 | * host buffer configuration | ||
907 | * | ||
908 | * Preparation includes - | ||
909 | * - Setting command ID, action and proper size | ||
910 | * - Setting host buffer configuration | ||
911 | * - Ensuring correct endian-ness | ||
912 | */ | ||
913 | static int | ||
914 | mwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv, | ||
915 | struct host_cmd_ds_command *cmd, u16 action) | ||
916 | { | ||
917 | struct host_cmd_ds_pcie_details *host_spec = | ||
918 | &cmd->params.pcie_host_spec; | ||
919 | struct pcie_service_card *card = priv->adapter->card; | ||
920 | phys_addr_t *buf_pa; | ||
921 | |||
922 | cmd->command = cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS); | ||
923 | cmd->size = cpu_to_le16(sizeof(struct | ||
924 | host_cmd_ds_pcie_details) + S_DS_GEN); | ||
925 | cmd->result = 0; | ||
926 | |||
927 | memset(host_spec, 0, sizeof(struct host_cmd_ds_pcie_details)); | ||
928 | |||
929 | if (action == HostCmd_ACT_GEN_SET) { | ||
930 | /* Send the ring base addresses and count to firmware */ | ||
931 | host_spec->txbd_addr_lo = (u32)(card->txbd_ring_pbase); | ||
932 | host_spec->txbd_addr_hi = | ||
933 | (u32)(((u64)card->txbd_ring_pbase)>>32); | ||
934 | host_spec->txbd_count = MWIFIEX_MAX_TXRX_BD; | ||
935 | host_spec->rxbd_addr_lo = (u32)(card->rxbd_ring_pbase); | ||
936 | host_spec->rxbd_addr_hi = | ||
937 | (u32)(((u64)card->rxbd_ring_pbase)>>32); | ||
938 | host_spec->rxbd_count = MWIFIEX_MAX_TXRX_BD; | ||
939 | host_spec->evtbd_addr_lo = | ||
940 | (u32)(card->evtbd_ring_pbase); | ||
941 | host_spec->evtbd_addr_hi = | ||
942 | (u32)(((u64)card->evtbd_ring_pbase)>>32); | ||
943 | host_spec->evtbd_count = MWIFIEX_MAX_EVT_BD; | ||
944 | if (card->sleep_cookie) { | ||
945 | buf_pa = MWIFIEX_SKB_PACB(card->sleep_cookie); | ||
946 | host_spec->sleep_cookie_addr_lo = (u32) *buf_pa; | ||
947 | host_spec->sleep_cookie_addr_hi = | ||
948 | (u32) (((u64)*buf_pa) >> 32); | ||
949 | dev_dbg(priv->adapter->dev, "sleep_cook_lo phy addr: " | ||
950 | "0x%x\n", host_spec->sleep_cookie_addr_lo); | ||
951 | } | ||
952 | } | ||
953 | |||
954 | return 0; | ||
955 | } | ||
956 | |||
957 | /* | ||
905 | * This function prepares the commands before sending them to the firmware. | 958 | * This function prepares the commands before sending them to the firmware. |
906 | * | 959 | * |
907 | * This is a generic function which calls specific command preparation | 960 | * This is a generic function which calls specific command preparation |
@@ -1079,6 +1132,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1079 | host_cmd_ds_set_bss_mode) + S_DS_GEN); | 1132 | host_cmd_ds_set_bss_mode) + S_DS_GEN); |
1080 | ret = 0; | 1133 | ret = 0; |
1081 | break; | 1134 | break; |
1135 | case HostCmd_CMD_PCIE_DESC_DETAILS: | ||
1136 | ret = mwifiex_cmd_pcie_host_spec(priv, cmd_ptr, cmd_action); | ||
1137 | break; | ||
1082 | default: | 1138 | default: |
1083 | dev_err(priv->adapter->dev, | 1139 | dev_err(priv->adapter->dev, |
1084 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); | 1140 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); |
@@ -1095,6 +1151,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1095 | * working state. | 1151 | * working state. |
1096 | * | 1152 | * |
1097 | * The following commands are issued sequentially - | 1153 | * The following commands are issued sequentially - |
1154 | * - Set PCI-Express host buffer configuration (PCIE only) | ||
1098 | * - Function init (for first interface only) | 1155 | * - Function init (for first interface only) |
1099 | * - Read MAC address (for first interface only) | 1156 | * - Read MAC address (for first interface only) |
1100 | * - Reconfigure Tx buffer size (for first interface only) | 1157 | * - Reconfigure Tx buffer size (for first interface only) |
@@ -1116,6 +1173,13 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
1116 | struct mwifiex_ds_11n_tx_cfg tx_cfg; | 1173 | struct mwifiex_ds_11n_tx_cfg tx_cfg; |
1117 | 1174 | ||
1118 | if (first_sta) { | 1175 | if (first_sta) { |
1176 | if (priv->adapter->iface_type == MWIFIEX_PCIE) { | ||
1177 | ret = mwifiex_send_cmd_async(priv, | ||
1178 | HostCmd_CMD_PCIE_DESC_DETAILS, | ||
1179 | HostCmd_ACT_GEN_SET, 0, NULL); | ||
1180 | if (ret) | ||
1181 | return -1; | ||
1182 | } | ||
1119 | 1183 | ||
1120 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_FUNC_INIT, | 1184 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_FUNC_INIT, |
1121 | HostCmd_ACT_GEN_SET, 0, NULL); | 1185 | HostCmd_ACT_GEN_SET, 0, NULL); |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 6804239d87bd..7a16b0c417af 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -952,6 +952,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
952 | case HostCmd_CMD_11N_CFG: | 952 | case HostCmd_CMD_11N_CFG: |
953 | ret = mwifiex_ret_11n_cfg(resp, data_buf); | 953 | ret = mwifiex_ret_11n_cfg(resp, data_buf); |
954 | break; | 954 | break; |
955 | case HostCmd_CMD_PCIE_DESC_DETAILS: | ||
956 | break; | ||
955 | default: | 957 | default: |
956 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 958 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
957 | resp->command); | 959 | resp->command); |
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 1822bfad8896..d97facd70e88 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c | |||
@@ -151,7 +151,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) | |||
151 | skb_push(skb, INTF_HEADER_LEN); | 151 | skb_push(skb, INTF_HEADER_LEN); |
152 | 152 | ||
153 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, | 153 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, |
154 | skb->data, skb->len, NULL); | 154 | skb, NULL); |
155 | switch (ret) { | 155 | switch (ret) { |
156 | case -EBUSY: | 156 | case -EBUSY: |
157 | adapter->data_sent = true; | 157 | adapter->data_sent = true; |
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 5d95c4b55a1f..4c3421eb6f40 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -78,7 +78,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, | |||
78 | (struct txpd *) (head_ptr + INTF_HEADER_LEN); | 78 | (struct txpd *) (head_ptr + INTF_HEADER_LEN); |
79 | 79 | ||
80 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, | 80 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, |
81 | skb->data, skb->len, tx_param); | 81 | skb, tx_param); |
82 | } | 82 | } |
83 | 83 | ||
84 | switch (ret) { | 84 | switch (ret) { |
diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h index 9506afc6c0e4..f6d36b9654a0 100644 --- a/drivers/net/wireless/mwifiex/util.h +++ b/drivers/net/wireless/mwifiex/util.h | |||
@@ -22,11 +22,16 @@ | |||
22 | 22 | ||
23 | static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb) | 23 | static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb) |
24 | { | 24 | { |
25 | return (struct mwifiex_rxinfo *)skb->cb; | 25 | return (struct mwifiex_rxinfo *)(skb->cb + sizeof(phys_addr_t)); |
26 | } | 26 | } |
27 | 27 | ||
28 | static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb) | 28 | static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb) |
29 | { | 29 | { |
30 | return (struct mwifiex_txinfo *)skb->cb; | 30 | return (struct mwifiex_txinfo *)(skb->cb + sizeof(phys_addr_t)); |
31 | } | ||
32 | |||
33 | static inline phys_addr_t *MWIFIEX_SKB_PACB(struct sk_buff *skb) | ||
34 | { | ||
35 | return (phys_addr_t *)skb->cb; | ||
31 | } | 36 | } |
32 | #endif /* !_MWIFIEX_UTIL_H_ */ | 37 | #endif /* !_MWIFIEX_UTIL_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index eda24474c1fc..6c239c3c8249 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -1125,8 +1125,8 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, | |||
1125 | tx_param.next_pkt_len = | 1125 | tx_param.next_pkt_len = |
1126 | ((skb_next) ? skb_next->len + | 1126 | ((skb_next) ? skb_next->len + |
1127 | sizeof(struct txpd) : 0); | 1127 | sizeof(struct txpd) : 0); |
1128 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, | 1128 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, skb, |
1129 | skb->data, skb->len, &tx_param); | 1129 | &tx_param); |
1130 | switch (ret) { | 1130 | switch (ret) { |
1131 | case -EBUSY: | 1131 | case -EBUSY: |
1132 | dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); | 1132 | dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); |