diff options
Diffstat (limited to 'drivers/staging/ath6kl/os/linux')
-rw-r--r-- | drivers/staging/ath6kl/os/linux/ar6000_drv.c | 56 | ||||
-rw-r--r-- | drivers/staging/ath6kl/os/linux/cfg80211.c | 211 | ||||
-rw-r--r-- | drivers/staging/ath6kl/os/linux/include/ar6000_drv.h | 19 | ||||
-rw-r--r-- | drivers/staging/ath6kl/os/linux/include/cfg80211.h | 11 | ||||
-rw-r--r-- | drivers/staging/ath6kl/os/linux/include/config_linux.h | 2 | ||||
-rw-r--r-- | drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h | 2 | ||||
-rw-r--r-- | drivers/staging/ath6kl/os/linux/include/osapi_linux.h | 1 |
7 files changed, 261 insertions, 41 deletions
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_drv.c b/drivers/staging/ath6kl/os/linux/ar6000_drv.c index 48dd9e363596..499b7a90e941 100644 --- a/drivers/staging/ath6kl/os/linux/ar6000_drv.c +++ b/drivers/staging/ath6kl/os/linux/ar6000_drv.c @@ -954,9 +954,13 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, const char *filename; const struct firmware *fw_entry; u32 fw_entry_size; + u8 **buf; + size_t *buf_len; switch (file) { case AR6K_OTP_FILE: + buf = &ar->fw_otp; + buf_len = &ar->fw_otp_len; if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { filename = AR6003_REV1_OTP_FILE; } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { @@ -970,6 +974,8 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, break; case AR6K_FIRMWARE_FILE: + buf = &ar->fw; + buf_len = &ar->fw_len; if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { filename = AR6003_REV1_FIRMWARE_FILE; } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { @@ -1028,6 +1034,8 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, break; case AR6K_PATCH_FILE: + buf = &ar->fw_patch; + buf_len = &ar->fw_patch_len; if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { filename = AR6003_REV1_PATCH_FILE; } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { @@ -1041,6 +1049,8 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, break; case AR6K_BOARD_DATA_FILE: + buf = &ar->fw_data; + buf_len = &ar->fw_data_len; if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { filename = AR6003_REV1_BOARD_DATA_FILE; } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { @@ -1057,23 +1067,29 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown file type: %d\n", file)); return A_ERROR; } - if ((A_REQUEST_FIRMWARE(&fw_entry, filename, ((struct device *)ar->osDevInfo.pOSDevice))) != 0) - { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to get %s\n", filename)); - return A_ENOENT; + + if (*buf == NULL) { + if ((A_REQUEST_FIRMWARE(&fw_entry, filename, ((struct device *)ar->osDevInfo.pOSDevice))) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to get %s\n", filename)); + return A_ENOENT; + } + + *buf = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL); + *buf_len = fw_entry->size; + A_RELEASE_FIRMWARE(fw_entry); } #ifdef SOFTMAC_FILE_USED - if (file==AR6K_BOARD_DATA_FILE && fw_entry->data) { - ar6000_softmac_update(ar, (u8 *)fw_entry->data, fw_entry->size); + if (file==AR6K_BOARD_DATA_FILE && *buf_len) { + ar6000_softmac_update(ar, *buf, *buf_len); } #endif - fw_entry_size = fw_entry->size; + fw_entry_size = *buf_len; /* Load extended board data for AR6003 */ - if ((file==AR6K_BOARD_DATA_FILE) && (fw_entry->data)) { + if ((file==AR6K_BOARD_DATA_FILE) && *buf) { u32 board_ext_address; u32 board_ext_data_size; u32 board_data_size; @@ -1089,14 +1105,13 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board extended Data download address: 0x%x\n", board_ext_address)); /* check whether the target has allocated memory for extended board data and file contains extended board data */ - if ((board_ext_address) && (fw_entry->size == (board_data_size + board_ext_data_size))) { + if ((board_ext_address) && (*buf_len == (board_data_size + board_ext_data_size))) { u32 param; - status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (u8 *)(fw_entry->data + board_data_size), board_ext_data_size); + status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (u8 *)(*buf + board_data_size), board_ext_data_size); if (status) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); - A_RELEASE_FIRMWARE(fw_entry); return A_ERROR; } @@ -1110,17 +1125,16 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, } if (compressed) { - status = BMIFastDownload(ar->arHifDevice, address, (u8 *)fw_entry->data, fw_entry_size); + status = BMIFastDownload(ar->arHifDevice, address, *buf, fw_entry_size); } else { - status = BMIWriteMemory(ar->arHifDevice, address, (u8 *)fw_entry->data, fw_entry_size); + status = BMIWriteMemory(ar->arHifDevice, address, *buf, fw_entry_size); } if (status) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); - A_RELEASE_FIRMWARE(fw_entry); return A_ERROR; } - A_RELEASE_FIRMWARE(fw_entry); + return 0; } @@ -2088,6 +2102,11 @@ ar6000_destroy(struct net_device *dev, unsigned int unregister) ar6000_remove_ap_interface(); #endif /*CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + kfree(ar->fw_otp); + kfree(ar->fw); + kfree(ar->fw_patch); + kfree(ar->fw_data); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("-ar6000_destroy \n")); } @@ -4114,6 +4133,13 @@ ar6000_ready_event(void *devt, u8 *datap, u8 phyCap, u32 sw_ver, u32 abi_ver) ar->arVersion.wlan_ver = sw_ver; ar->arVersion.abi_ver = abi_ver; + snprintf(ar->wdev->wiphy->fw_version, sizeof(ar->wdev->wiphy->fw_version), + "%u:%u:%u:%u", + (ar->arVersion.wlan_ver & 0xf0000000) >> 28, + (ar->arVersion.wlan_ver & 0x0f000000) >> 24, + (ar->arVersion.wlan_ver & 0x00ff0000) >> 16, + (ar->arVersion.wlan_ver & 0x0000ffff)); + /* Indicate to the waiting thread that the ready event was received */ ar->arWmiReady = true; wake_up(&arEvent); diff --git a/drivers/staging/ath6kl/os/linux/cfg80211.c b/drivers/staging/ath6kl/os/linux/cfg80211.c index d3a774dbb7e8..5fdda4aa2fee 100644 --- a/drivers/staging/ath6kl/os/linux/cfg80211.c +++ b/drivers/staging/ath6kl/os/linux/cfg80211.c @@ -24,6 +24,7 @@ #include <linux/wireless.h> #include <linux/ieee80211.h> #include <net/cfg80211.h> +#include <net/netlink.h> #include "ar6000_drv.h" @@ -867,26 +868,31 @@ ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status) AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: status %d\n", __func__, status)); - if(ar->scan_request) - { - /* Translate data to cfg80211 mgmt format */ - if (ar->arWmi) - wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy); + if (!ar->scan_request) + return; + + if ((status == A_ECANCELED) || (status == A_EBUSY)) { + cfg80211_scan_done(ar->scan_request, true); + goto out; + } - cfg80211_scan_done(ar->scan_request, - ((status & A_ECANCELED) || (status & A_EBUSY)) ? true : false); + /* Translate data to cfg80211 mgmt format */ + wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy); - if(ar->scan_request->n_ssids && - ar->scan_request->ssids[0].ssid_len) { + cfg80211_scan_done(ar->scan_request, false); + + if(ar->scan_request->n_ssids && + ar->scan_request->ssids[0].ssid_len) { u8 i; for (i = 0; i < ar->scan_request->n_ssids; i++) { - wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG, - 0, NULL); + wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG, + 0, NULL); } - } - ar->scan_request = NULL; } + +out: + ar->scan_request = NULL; } static int @@ -1453,6 +1459,159 @@ ar6k_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) return 0; } +#ifdef CONFIG_NL80211_TESTMODE +enum ar6k_testmode_attr { + __AR6K_TM_ATTR_INVALID = 0, + AR6K_TM_ATTR_CMD = 1, + AR6K_TM_ATTR_DATA = 2, + + /* keep last */ + __AR6K_TM_ATTR_AFTER_LAST, + AR6K_TM_ATTR_MAX = __AR6K_TM_ATTR_AFTER_LAST - 1 +}; + +enum ar6k_testmode_cmd { + AR6K_TM_CMD_TCMD = 0, + AR6K_TM_CMD_RX_REPORT = 1, +}; + +#define AR6K_TM_DATA_MAX_LEN 5000 + +static const struct nla_policy ar6k_testmode_policy[AR6K_TM_ATTR_MAX + 1] = { + [AR6K_TM_ATTR_CMD] = { .type = NLA_U32 }, + [AR6K_TM_ATTR_DATA] = { .type = NLA_BINARY, + .len = AR6K_TM_DATA_MAX_LEN }, +}; + +void ar6000_testmode_rx_report_event(struct ar6_softc *ar, void *buf, + int buf_len) +{ + if (down_interruptible(&ar->arSem)) + return; + + kfree(ar->tcmd_rx_report); + + ar->tcmd_rx_report = kmemdup(buf, buf_len, GFP_KERNEL); + ar->tcmd_rx_report_len = buf_len; + + up(&ar->arSem); + + wake_up(&arEvent); +} + +static int ar6000_testmode_rx_report(struct ar6_softc *ar, void *buf, + int buf_len, struct sk_buff *skb) +{ + int ret = 0; + long left; + + if (down_interruptible(&ar->arSem)) + return -ERESTARTSYS; + + if (ar->arWmiReady == false) { + ret = -EIO; + goto out; + } + + if (ar->bIsDestroyProgress) { + ret = -EBUSY; + goto out; + } + + WARN_ON(ar->tcmd_rx_report != NULL); + WARN_ON(ar->tcmd_rx_report_len > 0); + + if (wmi_test_cmd(ar->arWmi, buf, buf_len) < 0) { + up(&ar->arSem); + return -EIO; + } + + left = wait_event_interruptible_timeout(arEvent, + ar->tcmd_rx_report != NULL, + wmitimeout * HZ); + + if (left == 0) { + ret = -ETIMEDOUT; + goto out; + } else if (left < 0) { + ret = left; + goto out; + } + + if (ar->tcmd_rx_report == NULL || ar->tcmd_rx_report_len == 0) { + ret = -EINVAL; + goto out; + } + + NLA_PUT(skb, AR6K_TM_ATTR_DATA, ar->tcmd_rx_report_len, + ar->tcmd_rx_report); + + kfree(ar->tcmd_rx_report); + ar->tcmd_rx_report = NULL; + +out: + up(&ar->arSem); + + return ret; + +nla_put_failure: + ret = -ENOBUFS; + goto out; +} + +static int ar6k_testmode_cmd(struct wiphy *wiphy, void *data, int len) +{ + struct ar6_softc *ar = wiphy_priv(wiphy); + struct nlattr *tb[AR6K_TM_ATTR_MAX + 1]; + int err, buf_len, reply_len; + struct sk_buff *skb; + void *buf; + + err = nla_parse(tb, AR6K_TM_ATTR_MAX, data, len, + ar6k_testmode_policy); + if (err) + return err; + + if (!tb[AR6K_TM_ATTR_CMD]) + return -EINVAL; + + switch (nla_get_u32(tb[AR6K_TM_ATTR_CMD])) { + case AR6K_TM_CMD_TCMD: + if (!tb[AR6K_TM_ATTR_DATA]) + return -EINVAL; + + buf = nla_data(tb[AR6K_TM_ATTR_DATA]); + buf_len = nla_len(tb[AR6K_TM_ATTR_DATA]); + + wmi_test_cmd(ar->arWmi, buf, buf_len); + + return 0; + + break; + case AR6K_TM_CMD_RX_REPORT: + if (!tb[AR6K_TM_ATTR_DATA]) + return -EINVAL; + + buf = nla_data(tb[AR6K_TM_ATTR_DATA]); + buf_len = nla_len(tb[AR6K_TM_ATTR_DATA]); + + reply_len = nla_total_size(AR6K_TM_DATA_MAX_LEN); + skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len); + if (!skb) + return -ENOMEM; + + err = ar6000_testmode_rx_report(ar, buf, buf_len, skb); + if (err < 0) { + kfree_skb(skb); + return err; + } + + return cfg80211_testmode_reply(skb); + default: + return -EOPNOTSUPP; + } +} +#endif static const u32 cipher_suites[] = { @@ -1607,6 +1766,28 @@ static int ar6k_get_station(struct wiphy *wiphy, struct net_device *dev, return 0; } +static int ar6k_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + struct ar6_softc *ar = ar6k_priv(netdev); + return wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid, pmksa->pmkid, true); +} + +static int ar6k_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + struct ar6_softc *ar = ar6k_priv(netdev); + return wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid, pmksa->pmkid, false); +} + +static int ar6k_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) +{ + struct ar6_softc *ar = ar6k_priv(netdev); + if (ar->arConnected) + return wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, false); + return 0; +} + static struct cfg80211_ops ar6k_cfg80211_ops = { .change_virtual_intf = ar6k_cfg80211_change_iface, @@ -1628,6 +1809,10 @@ cfg80211_ops ar6k_cfg80211_ops = { .join_ibss = ar6k_cfg80211_join_ibss, .leave_ibss = ar6k_cfg80211_leave_ibss, .get_station = ar6k_get_station, + .set_pmksa = ar6k_set_pmksa, + .del_pmksa = ar6k_del_pmksa, + .flush_pmksa = ar6k_flush_pmksa, + CFG80211_TESTMODE_CMD(ar6k_testmode_cmd) }; struct wireless_dev * diff --git a/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h b/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h index 11dc39c6987a..80cef77738fb 100644 --- a/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h +++ b/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h @@ -545,15 +545,9 @@ struct ar6_softc { s8 arMaxRetries; u8 arPhyCapability; #ifdef CONFIG_HOST_TCMD_SUPPORT - u8 tcmdRxReport; - u32 tcmdRxTotalPkt; - s32 tcmdRxRssi; - u32 tcmdPm; u32 arTargetMode; - u32 tcmdRxcrcErrPkt; - u32 tcmdRxsecErrPkt; - u16 tcmdRateCnt[TCMD_MAX_RATES]; - u16 tcmdRateCntShortGuard[TCMD_MAX_RATES]; + void *tcmd_rx_report; + int tcmd_rx_report_len; #endif AR6000_WLAN_STATE arWlanState; struct ar_node_mapping arNodeMap[MAX_NODE_NUM]; @@ -650,6 +644,15 @@ struct ar6_softc { void *arApDev; #endif u8 arAutoAuthStage; + + u8 *fw_otp; + size_t fw_otp_len; + u8 *fw; + size_t fw_len; + u8 *fw_patch; + size_t fw_patch_len; + u8 *fw_data; + size_t fw_data_len; }; #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT diff --git a/drivers/staging/ath6kl/os/linux/include/cfg80211.h b/drivers/staging/ath6kl/os/linux/include/cfg80211.h index 1a6ae97c6b08..d5253207b198 100644 --- a/drivers/staging/ath6kl/os/linux/include/cfg80211.h +++ b/drivers/staging/ath6kl/os/linux/include/cfg80211.h @@ -41,6 +41,17 @@ void ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason, void ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast); +#ifdef CONFIG_NL80211_TESTMODE +void ar6000_testmode_rx_report_event(struct ar6_softc *ar, void *buf, + int buf_len); +#else +static inline void ar6000_testmode_rx_report_event(struct ar6_softc *ar, + void *buf, int buf_len) +{ +} +#endif + + #endif /* _AR6K_CFG80211_H_ */ diff --git a/drivers/staging/ath6kl/os/linux/include/config_linux.h b/drivers/staging/ath6kl/os/linux/include/config_linux.h index d4030e26b20c..dbbe1a00b92c 100644 --- a/drivers/staging/ath6kl/os/linux/include/config_linux.h +++ b/drivers/staging/ath6kl/os/linux/include/config_linux.h @@ -28,8 +28,6 @@ extern "C" { #endif -#include <linux/version.h> - /* * Host side Test Command support */ diff --git a/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h b/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h index 769a48014313..e6e96de3fc6b 100644 --- a/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h +++ b/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h @@ -24,8 +24,6 @@ #ifndef _IEEE80211_IOCTL_H_ #define _IEEE80211_IOCTL_H_ -#include <linux/version.h> - #ifdef __cplusplus extern "C" { #endif diff --git a/drivers/staging/ath6kl/os/linux/include/osapi_linux.h b/drivers/staging/ath6kl/os/linux/include/osapi_linux.h index 07078b49583f..41f437307727 100644 --- a/drivers/staging/ath6kl/os/linux/include/osapi_linux.h +++ b/drivers/staging/ath6kl/os/linux/include/osapi_linux.h @@ -29,7 +29,6 @@ #ifdef __KERNEL__ -#include <linux/version.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/string.h> |