diff options
author | Brian Cavagnolo <brian@cozybit.com> | 2010-11-12 20:23:51 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-16 16:37:03 -0500 |
commit | 952a0e963fb02e50f4afbf502f7d468a8fe2b0fa (patch) | |
tree | e3d170f1e6e251557d8b684ed1e93789336f1c1d /drivers/net/wireless | |
parent | 0863ade8d6bde1d151f75720d999ff27f9fe3533 (diff) |
mwl8k: add API version checking for AP firmware
The AP firmware specifies an API version in the GET_HW_SPEC
command response. Currently, the driver only supports AP
firmware for the 8366, and only supports API v1. In the future,
if higher API version firmwares emerge (possibly for different
chips), different ops can be selected based on the reported API
version.
Signed-off-by: Brian Cavagnolo <brian@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/mwl8k.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index cbf72714e74d..e5b062c3bd56 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -101,6 +101,7 @@ struct mwl8k_device_info { | |||
101 | char *fw_image_sta; | 101 | char *fw_image_sta; |
102 | char *fw_image_ap; | 102 | char *fw_image_ap; |
103 | struct rxd_ops *ap_rxd_ops; | 103 | struct rxd_ops *ap_rxd_ops; |
104 | u32 fw_api_ap; | ||
104 | }; | 105 | }; |
105 | 106 | ||
106 | struct mwl8k_rx_queue { | 107 | struct mwl8k_rx_queue { |
@@ -1827,6 +1828,7 @@ struct mwl8k_cmd_get_hw_spec_ap { | |||
1827 | __le32 wcbbase1; | 1828 | __le32 wcbbase1; |
1828 | __le32 wcbbase2; | 1829 | __le32 wcbbase2; |
1829 | __le32 wcbbase3; | 1830 | __le32 wcbbase3; |
1831 | __le32 fw_api_version; | ||
1830 | } __packed; | 1832 | } __packed; |
1831 | 1833 | ||
1832 | static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) | 1834 | static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) |
@@ -1834,6 +1836,7 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) | |||
1834 | struct mwl8k_priv *priv = hw->priv; | 1836 | struct mwl8k_priv *priv = hw->priv; |
1835 | struct mwl8k_cmd_get_hw_spec_ap *cmd; | 1837 | struct mwl8k_cmd_get_hw_spec_ap *cmd; |
1836 | int rc; | 1838 | int rc; |
1839 | u32 api_version; | ||
1837 | 1840 | ||
1838 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 1841 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
1839 | if (cmd == NULL) | 1842 | if (cmd == NULL) |
@@ -1850,6 +1853,16 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) | |||
1850 | if (!rc) { | 1853 | if (!rc) { |
1851 | int off; | 1854 | int off; |
1852 | 1855 | ||
1856 | api_version = le32_to_cpu(cmd->fw_api_version); | ||
1857 | if (priv->device_info->fw_api_ap != api_version) { | ||
1858 | printk(KERN_ERR "%s: Unsupported fw API version for %s." | ||
1859 | " Expected %d got %d.\n", MWL8K_NAME, | ||
1860 | priv->device_info->part_name, | ||
1861 | priv->device_info->fw_api_ap, | ||
1862 | api_version); | ||
1863 | rc = -EINVAL; | ||
1864 | goto done; | ||
1865 | } | ||
1853 | SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); | 1866 | SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); |
1854 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); | 1867 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); |
1855 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); | 1868 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); |
@@ -1877,6 +1890,7 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) | |||
1877 | iowrite32(priv->txq[3].txd_dma, priv->sram + off); | 1890 | iowrite32(priv->txq[3].txd_dma, priv->sram + off); |
1878 | } | 1891 | } |
1879 | 1892 | ||
1893 | done: | ||
1880 | kfree(cmd); | 1894 | kfree(cmd); |
1881 | return rc; | 1895 | return rc; |
1882 | } | 1896 | } |
@@ -3939,6 +3953,10 @@ enum { | |||
3939 | MWL8366, | 3953 | MWL8366, |
3940 | }; | 3954 | }; |
3941 | 3955 | ||
3956 | #define MWL8K_8366_AP_FW_API 1 | ||
3957 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" | ||
3958 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) | ||
3959 | |||
3942 | static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { | 3960 | static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { |
3943 | [MWL8363] = { | 3961 | [MWL8363] = { |
3944 | .part_name = "88w8363", | 3962 | .part_name = "88w8363", |
@@ -3954,7 +3972,8 @@ static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { | |||
3954 | .part_name = "88w8366", | 3972 | .part_name = "88w8366", |
3955 | .helper_image = "mwl8k/helper_8366.fw", | 3973 | .helper_image = "mwl8k/helper_8366.fw", |
3956 | .fw_image_sta = "mwl8k/fmimage_8366.fw", | 3974 | .fw_image_sta = "mwl8k/fmimage_8366.fw", |
3957 | .fw_image_ap = "mwl8k/fmimage_8366_ap-1.fw", | 3975 | .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API), |
3976 | .fw_api_ap = MWL8K_8366_AP_FW_API, | ||
3958 | .ap_rxd_ops = &rxd_8366_ap_ops, | 3977 | .ap_rxd_ops = &rxd_8366_ap_ops, |
3959 | }, | 3978 | }, |
3960 | }; | 3979 | }; |
@@ -3965,7 +3984,7 @@ MODULE_FIRMWARE("mwl8k/helper_8687.fw"); | |||
3965 | MODULE_FIRMWARE("mwl8k/fmimage_8687.fw"); | 3984 | MODULE_FIRMWARE("mwl8k/fmimage_8687.fw"); |
3966 | MODULE_FIRMWARE("mwl8k/helper_8366.fw"); | 3985 | MODULE_FIRMWARE("mwl8k/helper_8366.fw"); |
3967 | MODULE_FIRMWARE("mwl8k/fmimage_8366.fw"); | 3986 | MODULE_FIRMWARE("mwl8k/fmimage_8366.fw"); |
3968 | MODULE_FIRMWARE("mwl8k/fmimage_8366_ap-1.fw"); | 3987 | MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API)); |
3969 | 3988 | ||
3970 | static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { | 3989 | static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { |
3971 | { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, }, | 3990 | { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, }, |