aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2012-06-25 10:46:40 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-07-10 12:10:12 -0400
commit4a1ccce852882c174d2392d2d8db1d65f48d4a10 (patch)
tree0dcf0b3644a48ac643450688ea0a1529d3296498 /drivers/net
parent01b3c0e4df483affb076405f129aa45bc2cde499 (diff)
wlcore/wl12xx/wl18xx: check min FW version
Refuse to boot if the FW version is too old. The minimum version is set per chip, with the option of setting it per PG in the future. When boot fails because of an old FW, display a helpful message. Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c9
-rw-r--r--drivers/net/wireless/ti/wl12xx/wl12xx.h14
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c4
-rw-r--r--drivers/net/wireless/ti/wl18xx/wl18xx.h7
-rw-r--r--drivers/net/wireless/ti/wlcore/boot.c51
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h15
6 files changed, 100 insertions, 0 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 47ba2e0017f4..1c56d1db0712 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -646,6 +646,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
646 /* read data preparation is only needed by wl127x */ 646 /* read data preparation is only needed by wl127x */
647 wl->ops->prepare_read = wl127x_prepare_read; 647 wl->ops->prepare_read = wl127x_prepare_read;
648 648
649 wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER,
650 WL127X_MAJOR_VER, WL127X_SUBTYPE_VER,
651 WL127X_MINOR_VER);
649 break; 652 break;
650 653
651 case CHIP_ID_1271_PG20: 654 case CHIP_ID_1271_PG20:
@@ -663,6 +666,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
663 /* read data preparation is only needed by wl127x */ 666 /* read data preparation is only needed by wl127x */
664 wl->ops->prepare_read = wl127x_prepare_read; 667 wl->ops->prepare_read = wl127x_prepare_read;
665 668
669 wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER,
670 WL127X_MAJOR_VER, WL127X_SUBTYPE_VER,
671 WL127X_MINOR_VER);
666 break; 672 break;
667 673
668 case CHIP_ID_1283_PG20: 674 case CHIP_ID_1283_PG20:
@@ -676,6 +682,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
676 wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | 682 wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN |
677 WLCORE_QUIRK_TKIP_HEADER_SPACE; 683 WLCORE_QUIRK_TKIP_HEADER_SPACE;
678 684
685 wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER, WL128X_IFTYPE_VER,
686 WL128X_MAJOR_VER, WL128X_SUBTYPE_VER,
687 WL128X_MINOR_VER);
679 break; 688 break;
680 case CHIP_ID_1283_PG10: 689 case CHIP_ID_1283_PG10:
681 default: 690 default:
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
index de1132410876..26990fb4edea 100644
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -24,6 +24,20 @@
24 24
25#include "conf.h" 25#include "conf.h"
26 26
27/* minimum FW required for driver for wl127x */
28#define WL127X_CHIP_VER 6
29#define WL127X_IFTYPE_VER 3
30#define WL127X_MAJOR_VER 10
31#define WL127X_SUBTYPE_VER 2
32#define WL127X_MINOR_VER 115
33
34/* minimum FW required for driver for wl128x */
35#define WL128X_CHIP_VER 7
36#define WL128X_IFTYPE_VER 3
37#define WL128X_MAJOR_VER 10
38#define WL128X_SUBTYPE_VER 2
39#define WL128X_MINOR_VER 115
40
27struct wl127x_rx_mem_pool_addr { 41struct wl127x_rx_mem_pool_addr {
28 u32 addr; 42 u32 addr;
29 u32 addr_extra; 43 u32 addr_extra;
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 16847eccfe80..341e878a974b 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -611,6 +611,10 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
611 WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | 611 WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN |
612 WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN | 612 WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN |
613 WLCORE_QUIRK_TX_PAD_LAST_FRAME; 613 WLCORE_QUIRK_TX_PAD_LAST_FRAME;
614
615 wlcore_set_min_fw_ver(wl, WL18XX_CHIP_VER, WL18XX_IFTYPE_VER,
616 WL18XX_MAJOR_VER, WL18XX_SUBTYPE_VER,
617 WL18XX_MINOR_VER);
614 break; 618 break;
615 case CHIP_ID_185x_PG10: 619 case CHIP_ID_185x_PG10:
616 wl1271_warning("chip id 0x%x (185x PG10) is deprecated", 620 wl1271_warning("chip id 0x%x (185x PG10) is deprecated",
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index bc67a4750615..6452396fa1d4 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -24,6 +24,13 @@
24 24
25#include "conf.h" 25#include "conf.h"
26 26
27/* minimum FW required for driver */
28#define WL18XX_CHIP_VER 8
29#define WL18XX_IFTYPE_VER 2
30#define WL18XX_MAJOR_VER 0
31#define WL18XX_SUBTYPE_VER 0
32#define WL18XX_MINOR_VER 100
33
27#define WL18XX_CMD_MAX_SIZE 740 34#define WL18XX_CMD_MAX_SIZE 740
28 35
29struct wl18xx_priv { 36struct wl18xx_priv {
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c
index 8965960b841a..61113291a890 100644
--- a/drivers/net/wireless/ti/wlcore/boot.c
+++ b/drivers/net/wireless/ti/wlcore/boot.c
@@ -81,6 +81,53 @@ out:
81 return ret; 81 return ret;
82} 82}
83 83
84static int wlcore_validate_fw_ver(struct wl1271 *wl)
85{
86 unsigned int *fw_ver = wl->chip.fw_ver;
87 unsigned int *min_ver = wl->min_fw_ver;
88
89 /* the chip must be exactly equal */
90 if (min_ver[FW_VER_CHIP] != fw_ver[FW_VER_CHIP])
91 goto fail;
92
93 /* always check the next digit if all previous ones are equal */
94
95 if (min_ver[FW_VER_IF_TYPE] < fw_ver[FW_VER_IF_TYPE])
96 goto out;
97 else if (min_ver[FW_VER_IF_TYPE] > fw_ver[FW_VER_IF_TYPE])
98 goto fail;
99
100 if (min_ver[FW_VER_MAJOR] < fw_ver[FW_VER_MAJOR])
101 goto out;
102 else if (min_ver[FW_VER_MAJOR] > fw_ver[FW_VER_MAJOR])
103 goto fail;
104
105 if (min_ver[FW_VER_SUBTYPE] < fw_ver[FW_VER_SUBTYPE])
106 goto out;
107 else if (min_ver[FW_VER_SUBTYPE] > fw_ver[FW_VER_SUBTYPE])
108 goto fail;
109
110 if (min_ver[FW_VER_MINOR] < fw_ver[FW_VER_MINOR])
111 goto out;
112 else if (min_ver[FW_VER_MINOR] > fw_ver[FW_VER_MINOR])
113 goto fail;
114
115out:
116 return 0;
117
118fail:
119 wl1271_error("Your WiFi FW version (%u.%u.%u.%u.%u) is outdated.\n"
120 "Please use at least FW %u.%u.%u.%u.%u.\n"
121 "You can get more information at:\n"
122 "http://wireless.kernel.org/en/users/Drivers/wl12xx",
123 fw_ver[FW_VER_CHIP], fw_ver[FW_VER_IF_TYPE],
124 fw_ver[FW_VER_MAJOR], fw_ver[FW_VER_SUBTYPE],
125 fw_ver[FW_VER_MINOR], min_ver[FW_VER_CHIP],
126 min_ver[FW_VER_IF_TYPE], min_ver[FW_VER_MAJOR],
127 min_ver[FW_VER_SUBTYPE], min_ver[FW_VER_MINOR]);
128 return -EINVAL;
129}
130
84static int wlcore_boot_static_data(struct wl1271 *wl) 131static int wlcore_boot_static_data(struct wl1271 *wl)
85{ 132{
86 struct wl1271_static_data *static_data; 133 struct wl1271_static_data *static_data;
@@ -101,6 +148,10 @@ static int wlcore_boot_static_data(struct wl1271 *wl)
101 if (ret < 0) 148 if (ret < 0)
102 goto out_free; 149 goto out_free;
103 150
151 ret = wlcore_validate_fw_ver(wl);
152 if (ret < 0)
153 goto out_free;
154
104 ret = wlcore_handle_static_data(wl, static_data); 155 ret = wlcore_handle_static_data(wl, static_data);
105 if (ret < 0) 156 if (ret < 0)
106 goto out_free; 157 goto out_free;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 216bdb0f2756..942cef13d8f4 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -390,6 +390,9 @@ struct wl1271 {
390 390
391 /* sleep auth value currently configured to FW */ 391 /* sleep auth value currently configured to FW */
392 int sleep_auth; 392 int sleep_auth;
393
394 /* the minimum FW version required for the driver to work */
395 unsigned int min_fw_ver[NUM_FW_VER];
393}; 396};
394 397
395int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); 398int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
@@ -408,6 +411,18 @@ wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band,
408 memcpy(&wl->ht_cap[band], ht_cap, sizeof(*ht_cap)); 411 memcpy(&wl->ht_cap[band], ht_cap, sizeof(*ht_cap));
409} 412}
410 413
414static inline void
415wlcore_set_min_fw_ver(struct wl1271 *wl, unsigned int chip,
416 unsigned int iftype, unsigned int major,
417 unsigned int subtype, unsigned int minor)
418{
419 wl->min_fw_ver[FW_VER_CHIP] = chip;
420 wl->min_fw_ver[FW_VER_IF_TYPE] = iftype;
421 wl->min_fw_ver[FW_VER_MAJOR] = major;
422 wl->min_fw_ver[FW_VER_SUBTYPE] = subtype;
423 wl->min_fw_ver[FW_VER_MINOR] = minor;
424}
425
411/* Firmware image load chunk size */ 426/* Firmware image load chunk size */
412#define CHUNK_SIZE 16384 427#define CHUNK_SIZE 16384
413 428