aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/b43/b43.h32
-rw-r--r--drivers/net/wireless/b43/main.c154
-rw-r--r--drivers/net/wireless/b43/main.h7
3 files changed, 149 insertions, 44 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index a53c378e7484..9e0da212f8ce 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -655,10 +655,39 @@ struct b43_wl {
655 struct work_struct txpower_adjust_work; 655 struct work_struct txpower_adjust_work;
656}; 656};
657 657
658/* The type of the firmware file. */
659enum b43_firmware_file_type {
660 B43_FWTYPE_PROPRIETARY,
661 B43_FWTYPE_OPENSOURCE,
662 B43_NR_FWTYPES,
663};
664
665/* Context data for fetching firmware. */
666struct b43_request_fw_context {
667 /* The device we are requesting the fw for. */
668 struct b43_wldev *dev;
669 /* The type of firmware to request. */
670 enum b43_firmware_file_type req_type;
671 /* Error messages for each firmware type. */
672 char errors[B43_NR_FWTYPES][128];
673 /* Temporary buffer for storing the firmware name. */
674 char fwname[64];
675 /* A fatal error occured while requesting. Firmware reqest
676 * can not continue, as any other reqest will also fail. */
677 int fatal_failure;
678};
679
658/* In-memory representation of a cached microcode file. */ 680/* In-memory representation of a cached microcode file. */
659struct b43_firmware_file { 681struct b43_firmware_file {
660 const char *filename; 682 const char *filename;
661 const struct firmware *data; 683 const struct firmware *data;
684 /* Type of the firmware file name. Note that this does only indicate
685 * the type by the firmware name. NOT the file contents.
686 * If you want to check for proprietary vs opensource, use (struct b43_firmware)->opensource
687 * instead! The (struct b43_firmware)->opensource flag is derived from the actual firmware
688 * binary code, not just the filename.
689 */
690 enum b43_firmware_file_type type;
662}; 691};
663 692
664/* Pointers to the firmware data and meta information about it. */ 693/* Pointers to the firmware data and meta information about it. */
@@ -677,7 +706,8 @@ struct b43_firmware {
677 /* Firmware patchlevel */ 706 /* Firmware patchlevel */
678 u16 patch; 707 u16 patch;
679 708
680 /* Set to true, if we are using an opensource firmware. */ 709 /* Set to true, if we are using an opensource firmware.
710 * Use this to check for proprietary vs opensource. */
681 bool opensource; 711 bool opensource;
682 /* Set to true, if the core needs a PCM firmware, but 712 /* Set to true, if the core needs a PCM firmware, but
683 * we failed to load one. This is always false for 713 * we failed to load one. This is always false for
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 675a73a98072..cbb3d45f6fc9 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1934,7 +1934,7 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
1934 return ret; 1934 return ret;
1935} 1935}
1936 1936
1937static void do_release_fw(struct b43_firmware_file *fw) 1937void b43_do_release_fw(struct b43_firmware_file *fw)
1938{ 1938{
1939 release_firmware(fw->data); 1939 release_firmware(fw->data);
1940 fw->data = NULL; 1940 fw->data = NULL;
@@ -1943,10 +1943,10 @@ static void do_release_fw(struct b43_firmware_file *fw)
1943 1943
1944static void b43_release_firmware(struct b43_wldev *dev) 1944static void b43_release_firmware(struct b43_wldev *dev)
1945{ 1945{
1946 do_release_fw(&dev->fw.ucode); 1946 b43_do_release_fw(&dev->fw.ucode);
1947 do_release_fw(&dev->fw.pcm); 1947 b43_do_release_fw(&dev->fw.pcm);
1948 do_release_fw(&dev->fw.initvals); 1948 b43_do_release_fw(&dev->fw.initvals);
1949 do_release_fw(&dev->fw.initvals_band); 1949 b43_do_release_fw(&dev->fw.initvals_band);
1950} 1950}
1951 1951
1952static void b43_print_fw_helptext(struct b43_wl *wl, bool error) 1952static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
@@ -1963,12 +1963,10 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
1963 b43warn(wl, text); 1963 b43warn(wl, text);
1964} 1964}
1965 1965
1966static int do_request_fw(struct b43_wldev *dev, 1966int b43_do_request_fw(struct b43_request_fw_context *ctx,
1967 const char *name, 1967 const char *name,
1968 struct b43_firmware_file *fw, 1968 struct b43_firmware_file *fw)
1969 bool silent)
1970{ 1969{
1971 char path[sizeof(modparam_fwpostfix) + 32];
1972 const struct firmware *blob; 1970 const struct firmware *blob;
1973 struct b43_fw_header *hdr; 1971 struct b43_fw_header *hdr;
1974 u32 size; 1972 u32 size;
@@ -1976,29 +1974,49 @@ static int do_request_fw(struct b43_wldev *dev,
1976 1974
1977 if (!name) { 1975 if (!name) {
1978 /* Don't fetch anything. Free possibly cached firmware. */ 1976 /* Don't fetch anything. Free possibly cached firmware. */
1979 do_release_fw(fw); 1977 /* FIXME: We should probably keep it anyway, to save some headache
1978 * on suspend/resume with multiband devices. */
1979 b43_do_release_fw(fw);
1980 return 0; 1980 return 0;
1981 } 1981 }
1982 if (fw->filename) { 1982 if (fw->filename) {
1983 if (strcmp(fw->filename, name) == 0) 1983 if ((fw->type == ctx->req_type) &&
1984 (strcmp(fw->filename, name) == 0))
1984 return 0; /* Already have this fw. */ 1985 return 0; /* Already have this fw. */
1985 /* Free the cached firmware first. */ 1986 /* Free the cached firmware first. */
1986 do_release_fw(fw); 1987 /* FIXME: We should probably do this later after we successfully
1988 * got the new fw. This could reduce headache with multiband devices.
1989 * We could also redesign this to cache the firmware for all possible
1990 * bands all the time. */
1991 b43_do_release_fw(fw);
1992 }
1993
1994 switch (ctx->req_type) {
1995 case B43_FWTYPE_PROPRIETARY:
1996 snprintf(ctx->fwname, sizeof(ctx->fwname),
1997 "b43%s/%s.fw",
1998 modparam_fwpostfix, name);
1999 break;
2000 case B43_FWTYPE_OPENSOURCE:
2001 snprintf(ctx->fwname, sizeof(ctx->fwname),
2002 "b43-open%s/%s.fw",
2003 modparam_fwpostfix, name);
2004 break;
2005 default:
2006 B43_WARN_ON(1);
2007 return -ENOSYS;
1987 } 2008 }
1988 2009 err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
1989 snprintf(path, ARRAY_SIZE(path),
1990 "b43%s/%s.fw",
1991 modparam_fwpostfix, name);
1992 err = request_firmware(&blob, path, dev->dev->dev);
1993 if (err == -ENOENT) { 2010 if (err == -ENOENT) {
1994 if (!silent) { 2011 snprintf(ctx->errors[ctx->req_type],
1995 b43err(dev->wl, "Firmware file \"%s\" not found\n", 2012 sizeof(ctx->errors[ctx->req_type]),
1996 path); 2013 "Firmware file \"%s\" not found\n", ctx->fwname);
1997 }
1998 return err; 2014 return err;
1999 } else if (err) { 2015 } else if (err) {
2000 b43err(dev->wl, "Firmware file \"%s\" request failed (err=%d)\n", 2016 snprintf(ctx->errors[ctx->req_type],
2001 path, err); 2017 sizeof(ctx->errors[ctx->req_type]),
2018 "Firmware file \"%s\" request failed (err=%d)\n",
2019 ctx->fwname, err);
2002 return err; 2020 return err;
2003 } 2021 }
2004 if (blob->size < sizeof(struct b43_fw_header)) 2022 if (blob->size < sizeof(struct b43_fw_header))
@@ -2021,20 +2039,24 @@ static int do_request_fw(struct b43_wldev *dev,
2021 2039
2022 fw->data = blob; 2040 fw->data = blob;
2023 fw->filename = name; 2041 fw->filename = name;
2042 fw->type = ctx->req_type;
2024 2043
2025 return 0; 2044 return 0;
2026 2045
2027err_format: 2046err_format:
2028 b43err(dev->wl, "Firmware file \"%s\" format error.\n", path); 2047 snprintf(ctx->errors[ctx->req_type],
2048 sizeof(ctx->errors[ctx->req_type]),
2049 "Firmware file \"%s\" format error.\n", ctx->fwname);
2029 release_firmware(blob); 2050 release_firmware(blob);
2030 2051
2031 return -EPROTO; 2052 return -EPROTO;
2032} 2053}
2033 2054
2034static int b43_request_firmware(struct b43_wldev *dev) 2055static int b43_try_request_fw(struct b43_request_fw_context *ctx)
2035{ 2056{
2036 struct b43_firmware *fw = &dev->fw; 2057 struct b43_wldev *dev = ctx->dev;
2037 const u8 rev = dev->dev->id.revision; 2058 struct b43_firmware *fw = &ctx->dev->fw;
2059 const u8 rev = ctx->dev->dev->id.revision;
2038 const char *filename; 2060 const char *filename;
2039 u32 tmshigh; 2061 u32 tmshigh;
2040 int err; 2062 int err;
@@ -2049,7 +2071,7 @@ static int b43_request_firmware(struct b43_wldev *dev)
2049 filename = "ucode13"; 2071 filename = "ucode13";
2050 else 2072 else
2051 goto err_no_ucode; 2073 goto err_no_ucode;
2052 err = do_request_fw(dev, filename, &fw->ucode, 0); 2074 err = b43_do_request_fw(ctx, filename, &fw->ucode);
2053 if (err) 2075 if (err)
2054 goto err_load; 2076 goto err_load;
2055 2077
@@ -2061,7 +2083,7 @@ static int b43_request_firmware(struct b43_wldev *dev)
2061 else 2083 else
2062 goto err_no_pcm; 2084 goto err_no_pcm;
2063 fw->pcm_request_failed = 0; 2085 fw->pcm_request_failed = 0;
2064 err = do_request_fw(dev, filename, &fw->pcm, 1); 2086 err = b43_do_request_fw(ctx, filename, &fw->pcm);
2065 if (err == -ENOENT) { 2087 if (err == -ENOENT) {
2066 /* We did not find a PCM file? Not fatal, but 2088 /* We did not find a PCM file? Not fatal, but
2067 * core rev <= 10 must do without hwcrypto then. */ 2089 * core rev <= 10 must do without hwcrypto then. */
@@ -2097,7 +2119,7 @@ static int b43_request_firmware(struct b43_wldev *dev)
2097 default: 2119 default:
2098 goto err_no_initvals; 2120 goto err_no_initvals;
2099 } 2121 }
2100 err = do_request_fw(dev, filename, &fw->initvals, 0); 2122 err = b43_do_request_fw(ctx, filename, &fw->initvals);
2101 if (err) 2123 if (err)
2102 goto err_load; 2124 goto err_load;
2103 2125
@@ -2131,30 +2153,34 @@ static int b43_request_firmware(struct b43_wldev *dev)
2131 default: 2153 default:
2132 goto err_no_initvals; 2154 goto err_no_initvals;
2133 } 2155 }
2134 err = do_request_fw(dev, filename, &fw->initvals_band, 0); 2156 err = b43_do_request_fw(ctx, filename, &fw->initvals_band);
2135 if (err) 2157 if (err)
2136 goto err_load; 2158 goto err_load;
2137 2159
2138 return 0; 2160 return 0;
2139 2161
2140err_load:
2141 b43_print_fw_helptext(dev->wl, 1);
2142 goto error;
2143
2144err_no_ucode: 2162err_no_ucode:
2145 err = -ENODEV; 2163 err = ctx->fatal_failure = -EOPNOTSUPP;
2146 b43err(dev->wl, "No microcode available for core rev %u\n", rev); 2164 b43err(dev->wl, "The driver does not know which firmware (ucode) "
2165 "is required for your device (wl-core rev %u)\n", rev);
2147 goto error; 2166 goto error;
2148 2167
2149err_no_pcm: 2168err_no_pcm:
2150 err = -ENODEV; 2169 err = ctx->fatal_failure = -EOPNOTSUPP;
2151 b43err(dev->wl, "No PCM available for core rev %u\n", rev); 2170 b43err(dev->wl, "The driver does not know which firmware (PCM) "
2171 "is required for your device (wl-core rev %u)\n", rev);
2152 goto error; 2172 goto error;
2153 2173
2154err_no_initvals: 2174err_no_initvals:
2155 err = -ENODEV; 2175 err = ctx->fatal_failure = -EOPNOTSUPP;
2156 b43err(dev->wl, "No Initial Values firmware file for PHY %u, " 2176 b43err(dev->wl, "The driver does not know which firmware (initvals) "
2157 "core rev %u\n", dev->phy.type, rev); 2177 "is required for your device (wl-core rev %u)\n", rev);
2178 goto error;
2179
2180err_load:
2181 /* We failed to load this firmware image. The error message
2182 * already is in ctx->errors. Return and let our caller decide
2183 * what to do. */
2158 goto error; 2184 goto error;
2159 2185
2160error: 2186error:
@@ -2162,6 +2188,48 @@ error:
2162 return err; 2188 return err;
2163} 2189}
2164 2190
2191static int b43_request_firmware(struct b43_wldev *dev)
2192{
2193 struct b43_request_fw_context *ctx;
2194 unsigned int i;
2195 int err;
2196 const char *errmsg;
2197
2198 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
2199 if (!ctx)
2200 return -ENOMEM;
2201 ctx->dev = dev;
2202
2203 ctx->req_type = B43_FWTYPE_PROPRIETARY;
2204 err = b43_try_request_fw(ctx);
2205 if (!err)
2206 goto out; /* Successfully loaded it. */
2207 err = ctx->fatal_failure;
2208 if (err)
2209 goto out;
2210
2211 ctx->req_type = B43_FWTYPE_OPENSOURCE;
2212 err = b43_try_request_fw(ctx);
2213 if (!err)
2214 goto out; /* Successfully loaded it. */
2215 err = ctx->fatal_failure;
2216 if (err)
2217 goto out;
2218
2219 /* Could not find a usable firmware. Print the errors. */
2220 for (i = 0; i < B43_NR_FWTYPES; i++) {
2221 errmsg = ctx->errors[i];
2222 if (strlen(errmsg))
2223 b43err(dev->wl, errmsg);
2224 }
2225 b43_print_fw_helptext(dev->wl, 1);
2226 err = -ENOENT;
2227
2228out:
2229 kfree(ctx);
2230 return err;
2231}
2232
2165static int b43_upload_microcode(struct b43_wldev *dev) 2233static int b43_upload_microcode(struct b43_wldev *dev)
2166{ 2234{
2167 const size_t hdr_len = sizeof(struct b43_fw_header); 2235 const size_t hdr_len = sizeof(struct b43_fw_header);
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index f871a252cb55..e6d90f377d9b 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -121,4 +121,11 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags);
121void b43_mac_suspend(struct b43_wldev *dev); 121void b43_mac_suspend(struct b43_wldev *dev);
122void b43_mac_enable(struct b43_wldev *dev); 122void b43_mac_enable(struct b43_wldev *dev);
123 123
124
125struct b43_request_fw_context;
126int b43_do_request_fw(struct b43_request_fw_context *ctx,
127 const char *name,
128 struct b43_firmware_file *fw);
129void b43_do_release_fw(struct b43_firmware_file *fw);
130
124#endif /* B43_MAIN_H_ */ 131#endif /* B43_MAIN_H_ */