aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wimax')
-rw-r--r--drivers/net/wimax/i2400m/fw.c53
-rw-r--r--drivers/net/wimax/i2400m/i2400m.h21
-rw-r--r--drivers/net/wimax/i2400m/sdio.c11
-rw-r--r--drivers/net/wimax/i2400m/usb.c14
4 files changed, 64 insertions, 35 deletions
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c
index ecd0cfaefdc..675c6ce810c 100644
--- a/drivers/net/wimax/i2400m/fw.c
+++ b/drivers/net/wimax/i2400m/fw.c
@@ -483,7 +483,7 @@ ssize_t i2400m_dnload_bcf(struct i2400m *i2400m,
483 if (offset + section_size > bcf_len) { 483 if (offset + section_size > bcf_len) {
484 dev_err(dev, "fw %s: bad section #%zu, " 484 dev_err(dev, "fw %s: bad section #%zu, "
485 "end (@%zu) beyond EOF (@%zu)\n", 485 "end (@%zu) beyond EOF (@%zu)\n",
486 i2400m->bus_fw_name, section, 486 i2400m->fw_name, section,
487 offset + section_size, bcf_len); 487 offset + section_size, bcf_len);
488 ret = -EINVAL; 488 ret = -EINVAL;
489 goto error_section_beyond_eof; 489 goto error_section_beyond_eof;
@@ -493,7 +493,7 @@ ssize_t i2400m_dnload_bcf(struct i2400m *i2400m,
493 &ack, sizeof(ack), I2400M_BM_CMD_RAW); 493 &ack, sizeof(ack), I2400M_BM_CMD_RAW);
494 if (ret < 0) { 494 if (ret < 0) {
495 dev_err(dev, "fw %s: section #%zu (@%zu %zu B) " 495 dev_err(dev, "fw %s: section #%zu (@%zu %zu B) "
496 "failed %d\n", i2400m->bus_fw_name, section, 496 "failed %d\n", i2400m->fw_name, section,
497 offset, sizeof(*bh) + data_size, (int) ret); 497 offset, sizeof(*bh) + data_size, (int) ret);
498 goto error_send; 498 goto error_send;
499 } 499 }
@@ -874,7 +874,7 @@ int i2400m_dnload_init(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf)
874 if (result < 0) 874 if (result < 0)
875 dev_err(dev, "fw %s: non-signed download " 875 dev_err(dev, "fw %s: non-signed download "
876 "initialization failed: %d\n", 876 "initialization failed: %d\n",
877 i2400m->bus_fw_name, result); 877 i2400m->fw_name, result);
878 } else if (i2400m->sboot == 0 878 } else if (i2400m->sboot == 0
879 && (module_id & I2400M_BCF_MOD_ID_POKES)) { 879 && (module_id & I2400M_BCF_MOD_ID_POKES)) {
880 /* non-signed boot process with pokes, nothing to do */ 880 /* non-signed boot process with pokes, nothing to do */
@@ -886,7 +886,7 @@ int i2400m_dnload_init(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf)
886 if (result < 0) 886 if (result < 0)
887 dev_err(dev, "fw %s: signed boot download " 887 dev_err(dev, "fw %s: signed boot download "
888 "initialization failed: %d\n", 888 "initialization failed: %d\n",
889 i2400m->bus_fw_name, result); 889 i2400m->fw_name, result);
890 } 890 }
891 return result; 891 return result;
892} 892}
@@ -915,7 +915,7 @@ int i2400m_fw_check(struct i2400m *i2400m,
915 if (bcf_size < sizeof(*bcf)) { /* big enough header? */ 915 if (bcf_size < sizeof(*bcf)) { /* big enough header? */
916 dev_err(dev, "firmware %s too short: " 916 dev_err(dev, "firmware %s too short: "
917 "%zu B vs %zu (at least) expected\n", 917 "%zu B vs %zu (at least) expected\n",
918 i2400m->bus_fw_name, bcf_size, sizeof(*bcf)); 918 i2400m->fw_name, bcf_size, sizeof(*bcf));
919 goto error; 919 goto error;
920 } 920 }
921 921
@@ -931,7 +931,7 @@ int i2400m_fw_check(struct i2400m *i2400m,
931 if (bcf_size != size) { /* annoyingly paranoid */ 931 if (bcf_size != size) { /* annoyingly paranoid */
932 dev_err(dev, "firmware %s: bad size, got " 932 dev_err(dev, "firmware %s: bad size, got "
933 "%zu B vs %u expected\n", 933 "%zu B vs %u expected\n",
934 i2400m->bus_fw_name, bcf_size, size); 934 i2400m->fw_name, bcf_size, size);
935 goto error; 935 goto error;
936 } 936 }
937 937
@@ -943,7 +943,7 @@ int i2400m_fw_check(struct i2400m *i2400m,
943 943
944 if (module_type != 6) { /* built for the right hardware? */ 944 if (module_type != 6) { /* built for the right hardware? */
945 dev_err(dev, "bad fw %s: unexpected module type 0x%x; " 945 dev_err(dev, "bad fw %s: unexpected module type 0x%x; "
946 "aborting\n", i2400m->bus_fw_name, module_type); 946 "aborting\n", i2400m->fw_name, module_type);
947 goto error; 947 goto error;
948 } 948 }
949 949
@@ -951,10 +951,10 @@ int i2400m_fw_check(struct i2400m *i2400m,
951 result = 0; 951 result = 0;
952 if (module_vendor != 0x8086) 952 if (module_vendor != 0x8086)
953 dev_err(dev, "bad fw %s? unexpected vendor 0x%04x\n", 953 dev_err(dev, "bad fw %s? unexpected vendor 0x%04x\n",
954 i2400m->bus_fw_name, module_vendor); 954 i2400m->fw_name, module_vendor);
955 if (date < 0x20080300) 955 if (date < 0x20080300)
956 dev_err(dev, "bad fw %s? build date too old %08x\n", 956 dev_err(dev, "bad fw %s? build date too old %08x\n",
957 i2400m->bus_fw_name, date); 957 i2400m->fw_name, date);
958error: 958error:
959 return result; 959 return result;
960} 960}
@@ -1016,7 +1016,7 @@ hw_reboot:
1016 goto error_dev_rebooted; 1016 goto error_dev_rebooted;
1017 if (ret < 0) { 1017 if (ret < 0) {
1018 dev_err(dev, "fw %s: download failed: %d\n", 1018 dev_err(dev, "fw %s: download failed: %d\n",
1019 i2400m->bus_fw_name, ret); 1019 i2400m->fw_name, ret);
1020 goto error_dnload_bcf; 1020 goto error_dnload_bcf;
1021 } 1021 }
1022 1022
@@ -1026,12 +1026,12 @@ hw_reboot:
1026 if (ret < 0) { 1026 if (ret < 0) {
1027 dev_err(dev, "fw %s: " 1027 dev_err(dev, "fw %s: "
1028 "download finalization failed: %d\n", 1028 "download finalization failed: %d\n",
1029 i2400m->bus_fw_name, ret); 1029 i2400m->fw_name, ret);
1030 goto error_dnload_finalize; 1030 goto error_dnload_finalize;
1031 } 1031 }
1032 1032
1033 d_printf(2, dev, "fw %s successfully uploaded\n", 1033 d_printf(2, dev, "fw %s successfully uploaded\n",
1034 i2400m->bus_fw_name); 1034 i2400m->fw_name);
1035 i2400m->boot_mode = 0; 1035 i2400m->boot_mode = 0;
1036error_dnload_finalize: 1036error_dnload_finalize:
1037error_dnload_bcf: 1037error_dnload_bcf:
@@ -1067,28 +1067,41 @@ error_dev_rebooted:
1067 */ 1067 */
1068int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags) 1068int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags)
1069{ 1069{
1070 int ret = 0; 1070 int ret = 0, itr = 0;
1071 struct device *dev = i2400m_dev(i2400m); 1071 struct device *dev = i2400m_dev(i2400m);
1072 const struct firmware *fw; 1072 const struct firmware *fw;
1073 const struct i2400m_bcf_hdr *bcf; /* Firmware data */ 1073 const struct i2400m_bcf_hdr *bcf; /* Firmware data */
1074 const char *fw_name;
1074 1075
1075 d_fnstart(5, dev, "(i2400m %p)\n", i2400m); 1076 d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
1077
1076 /* Load firmware files to memory. */ 1078 /* Load firmware files to memory. */
1077 ret = request_firmware(&fw, i2400m->bus_fw_name, dev); 1079 itr = 0;
1078 if (ret) { 1080 while(1) {
1079 dev_err(dev, "fw %s: request failed: %d\n", 1081 fw_name = i2400m->bus_fw_names[itr];
1080 i2400m->bus_fw_name, ret); 1082 if (fw_name == NULL) {
1081 goto error_fw_req; 1083 dev_err(dev, "Could not find a usable firmware image\n");
1084 ret = -ENOENT;
1085 goto error_no_fw;
1086 }
1087 ret = request_firmware(&fw, fw_name, dev);
1088 if (ret == 0)
1089 break; /* got it */
1090 if (ret < 0)
1091 dev_err(dev, "fw %s: cannot load file: %d\n",
1092 fw_name, ret);
1093 itr++;
1082 } 1094 }
1083 bcf = (void *) fw->data;
1084 1095
1096 bcf = (void *) fw->data;
1097 i2400m->fw_name = fw_name;
1085 ret = i2400m_fw_check(i2400m, bcf, fw->size); 1098 ret = i2400m_fw_check(i2400m, bcf, fw->size);
1086 if (ret < 0) 1099 if (ret < 0)
1087 goto error_fw_bad; 1100 goto error_fw_bad;
1088 ret = i2400m_fw_dnload(i2400m, bcf, fw->size, flags); 1101 ret = i2400m_fw_dnload(i2400m, bcf, fw->size, flags);
1089error_fw_bad: 1102error_fw_bad:
1090 release_firmware(fw); 1103 release_firmware(fw);
1091error_fw_req: 1104error_no_fw:
1092 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret); 1105 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
1093 return ret; 1106 return ret;
1094} 1107}
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index f9e55397ee8..ad71ad1086e 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -156,10 +156,6 @@ enum {
156}; 156};
157 157
158 158
159/* Firmware version we request when pulling the fw image file */
160#define I2400M_FW_VERSION "1.4"
161
162
163/** 159/**
164 * i2400m_reset_type - methods to reset a device 160 * i2400m_reset_type - methods to reset a device
165 * 161 *
@@ -242,10 +238,14 @@ struct i2400m_reset_ctx;
242 * The caller to this function will check if the response is a 238 * The caller to this function will check if the response is a
243 * barker that indicates the device going into reset mode. 239 * barker that indicates the device going into reset mode.
244 * 240 *
245 * @bus_fw_name: [fill] name of the firmware image (in most cases, 241 * @bus_fw_names: [fill] a NULL-terminated array with the names of the
246 * they are all the same for a single release, except that they 242 * firmware images to try loading. This is made a list so we can
247 * have the type of the bus embedded in the name (eg: 243 * support backward compatibility of firmware releases (eg: if we
248 * i2400m-fw-X-VERSION.sbcf, where X is the bus name). 244 * can't find the default v1.4, we try v1.3). In general, the name
245 * should be i2400m-fw-X-VERSION.sbcf, where X is the bus name.
246 * The list is tried in order and the first one that loads is
247 * used. The fw loader will set i2400m->fw_name to point to the
248 * active firmware image.
249 * 249 *
250 * @bus_bm_mac_addr_impaired: [fill] Set to true if the device's MAC 250 * @bus_bm_mac_addr_impaired: [fill] Set to true if the device's MAC
251 * address provided in boot mode is kind of broken and needs to 251 * address provided in boot mode is kind of broken and needs to
@@ -364,6 +364,8 @@ struct i2400m_reset_ctx;
364 * These have to be in a separate directory, a child of 364 * These have to be in a separate directory, a child of
365 * (wimax_dev->debugfs_dentry) so they can be removed when the 365 * (wimax_dev->debugfs_dentry) so they can be removed when the
366 * module unloads, as we don't keep each dentry. 366 * module unloads, as we don't keep each dentry.
367 *
368 * @fw_name: name of the firmware image that is currently being used.
367 */ 369 */
368struct i2400m { 370struct i2400m {
369 struct wimax_dev wimax_dev; /* FIRST! See doc */ 371 struct wimax_dev wimax_dev; /* FIRST! See doc */
@@ -388,7 +390,7 @@ struct i2400m {
388 size_t, int flags); 390 size_t, int flags);
389 ssize_t (*bus_bm_wait_for_ack)(struct i2400m *, 391 ssize_t (*bus_bm_wait_for_ack)(struct i2400m *,
390 struct i2400m_bootrom_header *, size_t); 392 struct i2400m_bootrom_header *, size_t);
391 const char *bus_fw_name; 393 const char **bus_fw_names;
392 unsigned bus_bm_mac_addr_impaired:1; 394 unsigned bus_bm_mac_addr_impaired:1;
393 395
394 spinlock_t tx_lock; /* protect TX state */ 396 spinlock_t tx_lock; /* protect TX state */
@@ -421,6 +423,7 @@ struct i2400m {
421 struct sk_buff *wake_tx_skb; 423 struct sk_buff *wake_tx_skb;
422 424
423 struct dentry *debugfs_dentry; 425 struct dentry *debugfs_dentry;
426 const char *fw_name; /* name of the current firmware image */
424}; 427};
425 428
426 429
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
index 123a5f8db6a..5ac5e76701c 100644
--- a/drivers/net/wimax/i2400m/sdio.c
+++ b/drivers/net/wimax/i2400m/sdio.c
@@ -70,8 +70,13 @@
70static int ioe_timeout = 2; 70static int ioe_timeout = 2;
71module_param(ioe_timeout, int, 0); 71module_param(ioe_timeout, int, 0);
72 72
73/* Our firmware file name */ 73/* Our firmware file name list */
74#define I2400MS_FW_FILE_NAME "i2400m-fw-sdio-" I2400M_FW_VERSION ".sbcf" 74static const char *i2400ms_bus_fw_names[] = {
75#define I2400MS_FW_FILE_NAME "i2400m-fw-sdio-1.3.sbcf"
76 I2400MS_FW_FILE_NAME,
77 NULL
78};
79
75 80
76/* 81/*
77 * Enable the SDIO function 82 * Enable the SDIO function
@@ -401,7 +406,7 @@ int i2400ms_probe(struct sdio_func *func,
401 i2400m->bus_reset = i2400ms_bus_reset; 406 i2400m->bus_reset = i2400ms_bus_reset;
402 i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send; 407 i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send;
403 i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack; 408 i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack;
404 i2400m->bus_fw_name = I2400MS_FW_FILE_NAME; 409 i2400m->bus_fw_names = i2400ms_bus_fw_names;
405 i2400m->bus_bm_mac_addr_impaired = 1; 410 i2400m->bus_bm_mac_addr_impaired = 1;
406 411
407 result = i2400ms_enable_function(i2400ms->func); 412 result = i2400ms_enable_function(i2400ms->func);
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
index 7c28610da6f..ca4151a9e22 100644
--- a/drivers/net/wimax/i2400m/usb.c
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -73,7 +73,14 @@
73 73
74 74
75/* Our firmware file name */ 75/* Our firmware file name */
76#define I2400MU_FW_FILE_NAME "i2400m-fw-usb-" I2400M_FW_VERSION ".sbcf" 76static const char *i2400mu_bus_fw_names[] = {
77#define I2400MU_FW_FILE_NAME_v1_4 "i2400m-fw-usb-1.4.sbcf"
78 I2400MU_FW_FILE_NAME_v1_4,
79#define I2400MU_FW_FILE_NAME_v1_3 "i2400m-fw-usb-1.3.sbcf"
80 I2400MU_FW_FILE_NAME_v1_3,
81 NULL,
82};
83
77 84
78static 85static
79int i2400mu_bus_dev_start(struct i2400m *i2400m) 86int i2400mu_bus_dev_start(struct i2400m *i2400m)
@@ -394,7 +401,7 @@ int i2400mu_probe(struct usb_interface *iface,
394 i2400m->bus_reset = i2400mu_bus_reset; 401 i2400m->bus_reset = i2400mu_bus_reset;
395 i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send; 402 i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send;
396 i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack; 403 i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack;
397 i2400m->bus_fw_name = I2400MU_FW_FILE_NAME; 404 i2400m->bus_fw_names = i2400mu_bus_fw_names;
398 i2400m->bus_bm_mac_addr_impaired = 0; 405 i2400m->bus_bm_mac_addr_impaired = 0;
399 406
400#ifdef CONFIG_PM 407#ifdef CONFIG_PM
@@ -594,4 +601,5 @@ module_exit(i2400mu_driver_exit);
594MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>"); 601MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
595MODULE_DESCRIPTION("Intel 2400M WiMAX networking for USB"); 602MODULE_DESCRIPTION("Intel 2400M WiMAX networking for USB");
596MODULE_LICENSE("GPL"); 603MODULE_LICENSE("GPL");
597MODULE_FIRMWARE(I2400MU_FW_FILE_NAME); 604MODULE_FIRMWARE(I2400MU_FW_FILE_NAME_v1_4);
605MODULE_FIRMWARE(I2400MU_FW_FILE_NAME_v1_3);