aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2009-01-23 15:21:51 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:01:30 -0500
commit1a9f509368ceb24fc66be961be15c69966f5eb5d (patch)
treec038db8330a52ad757ef630cbe8738e1f5afc1ca
parent2f47690ed42a85820783dee7f16ae47edadf8fad (diff)
b43: Automatically probe for opensource firmware
First probe for proprietary firmware and then probe for opensource firmware. This way around it's a win-win situation. 1) If proprietary fw is available, it will work. 2) If opensource firmware is available, but no proprietary (Distros can only ship open fw) it might work. 3) If both open and proprietary are available, it will work, because it selects the proprietary. We currently don't prefer the open fw in this case, because it doesn't work on all devices. It would introduce a regression otherwise. The remaining FIXMEs in this patch are harmless, because they only matter on multiband devices, which are not implemented yet anyway. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-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_ */