staging: csr: remove func_enter macro
[linux-2.6.git] / drivers / staging / csr / firmware.c
blob881acc90e53222fb3ad55da17ff8ed1d64079bd3
1 /*
2 * ---------------------------------------------------------------------------
3 * FILE: firmware.c
5 * PURPOSE:
6 * Implements the f/w related HIP core lib API.
7 * It is part of the porting exercise in Linux.
9 * Also, it contains example code for reading the loader and f/w files
10 * from the userspace and starting the SME in Linux.
12 * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd.
14 * Refer to LICENSE.txt included with this source code for details on
15 * the license terms.
17 * ---------------------------------------------------------------------------
19 #include <linux/kmod.h>
20 #include <linux/vmalloc.h>
21 #include <linux/firmware.h>
22 #include <asm/uaccess.h>
23 #include "csr_wifi_hip_unifi.h"
24 #include "csr_wifi_hip_unifi_udi.h"
25 #include "unifiio.h"
26 #include "unifi_priv.h"
29 * ---------------------------------------------------------------------------
31 * F/W download. Part of the HIP core API
33 * ---------------------------------------------------------------------------
38 * ---------------------------------------------------------------------------
39 * unifi_fw_read_start
41 * Returns a structure to be passed in unifi_fw_read().
42 * This structure is an OS specific description of the f/w file.
43 * In the linux implementation it is a buffer with the f/w and its' length.
44 * The HIP driver calls this functions to request for the loader or
45 * the firmware file.
46 * The structure pointer can be freed when unifi_fw_read_stop() is called.
48 * Arguments:
49 * ospriv Pointer to driver context.
50 * is_fw Type of firmware to retrieve
51 * info Versions information. Can be used to determine
52 * the appropriate f/w file to load.
54 * Returns:
55 * O on success, non-zero otherwise.
57 * ---------------------------------------------------------------------------
59 void*
60 unifi_fw_read_start(void *ospriv, s8 is_fw, const card_info_t *info)
62 unifi_priv_t *priv = (unifi_priv_t*)ospriv;
63 CSR_UNUSED(info);
65 if (is_fw == UNIFI_FW_STA) {
66 /* F/w may have been released after a previous successful download. */
67 if (priv->fw_sta.dl_data == NULL) {
68 unifi_trace(priv, UDBG2, "Attempt reload of sta f/w\n");
69 uf_request_firmware_files(priv, UNIFI_FW_STA);
71 /* Set up callback struct for readfunc() */
72 if (priv->fw_sta.dl_data != NULL) {
73 func_exit();
74 return &priv->fw_sta;
77 } else {
78 unifi_error(priv, "downloading firmware... unknown request: %d\n", is_fw);
81 func_exit();
82 return NULL;
83 } /* unifi_fw_read_start() */
88 * ---------------------------------------------------------------------------
89 * unifi_fw_read_stop
91 * Called when the HIP driver has finished using the loader or
92 * the firmware file.
93 * The firmware buffer may be released now.
95 * Arguments:
96 * ospriv Pointer to driver context.
97 * dlpriv The pointer returned by unifi_fw_read_start()
99 * ---------------------------------------------------------------------------
101 void
102 unifi_fw_read_stop(void *ospriv, void *dlpriv)
104 unifi_priv_t *priv = (unifi_priv_t*)ospriv;
105 struct dlpriv *dl_struct = (struct dlpriv *)dlpriv;
107 if (dl_struct != NULL) {
108 if (dl_struct->dl_data != NULL) {
109 unifi_trace(priv, UDBG2, "Release f/w buffer %p, %d bytes\n",
110 dl_struct->dl_data, dl_struct->dl_len);
112 uf_release_firmware(priv, dl_struct);
115 func_exit();
116 } /* unifi_fw_read_stop() */
120 * ---------------------------------------------------------------------------
121 * unifi_fw_open_buffer
123 * Returns a handle for a buffer dynamically allocated by the driver,
124 * e.g. into which a firmware file may have been converted from another format
125 * which is the case with some production test images.
127 * The handle may then be used by unifi_fw_read() to access the contents of
128 * the buffer.
130 * Arguments:
131 * ospriv Pointer to driver context.
132 * fwbuf Buffer containing firmware image
133 * len Length of buffer in bytes
135 * Returns
136 * Handle for buffer, or NULL on error
137 * ---------------------------------------------------------------------------
139 void *
140 unifi_fw_open_buffer(void *ospriv, void *fwbuf, u32 len)
142 unifi_priv_t *priv = (unifi_priv_t*)ospriv;
144 if (fwbuf == NULL) {
145 func_exit();
146 return NULL;
148 priv->fw_conv.dl_data = fwbuf;
149 priv->fw_conv.dl_len = len;
150 priv->fw_conv.fw_desc = NULL; /* No OS f/w resource is associated */
152 func_exit();
153 return &priv->fw_conv;
157 * ---------------------------------------------------------------------------
158 * unifi_fw_close_buffer
160 * Releases any handle for a buffer dynamically allocated by the driver,
161 * e.g. into which a firmware file may have been converted from another format
162 * which is the case with some production test images.
165 * Arguments:
166 * ospriv Pointer to driver context.
167 * fwbuf Buffer containing firmware image
169 * Returns
170 * Handle for buffer, or NULL on error
171 * ---------------------------------------------------------------------------
173 void unifi_fw_close_buffer(void *ospriv, void *fwbuf)
178 * ---------------------------------------------------------------------------
179 * unifi_fw_read
181 * The HIP driver calls this function to ask for a part of the loader or
182 * the firmware file.
184 * Arguments:
185 * ospriv Pointer to driver context.
186 * arg The pointer returned by unifi_fw_read_start().
187 * offset The offset in the file to return from.
188 * buf A buffer to store the requested data.
189 * len The size of the buf and the size of the requested data.
191 * Returns
192 * The number of bytes read from the firmware image, or -ve on error
193 * ---------------------------------------------------------------------------
196 unifi_fw_read(void *ospriv, void *arg, u32 offset, void *buf, u32 len)
198 const struct dlpriv *dlpriv = arg;
200 if (offset >= dlpriv->dl_len) {
201 /* at end of file */
202 return 0;
205 if ((offset + len) > dlpriv->dl_len) {
206 /* attempt to read past end of file */
207 return -1;
210 memcpy(buf, dlpriv->dl_data+offset, len);
212 return len;
214 } /* unifi_fw_read() */
219 #define UNIFIHELPER_INIT_MODE_SMEUSER 2
220 #define UNIFIHELPER_INIT_MODE_NATIVE 1
223 * ---------------------------------------------------------------------------
224 * uf_run_unifihelper
226 * Ask userspace to send us firmware for download by running
227 * '/usr/sbin/unififw'.
228 * The same script starts the SME userspace application.
229 * Derived from net_run_sbin_hotplug().
231 * Arguments:
232 * priv Pointer to OS private struct.
234 * Returns:
235 * None.
236 * ---------------------------------------------------------------------------
239 uf_run_unifihelper(unifi_priv_t *priv)
241 #ifdef CONFIG_HOTPLUG
243 #ifdef ANDROID_BUILD
244 char *prog = "/system/bin/unififw";
245 #else
246 char *prog = "/usr/sbin/unififw";
247 #endif /* ANDROID_BUILD */
249 char *argv[6], *envp[4];
250 char inst_str[8];
251 char init_mode[8];
252 int i, r;
254 #if (defined CSR_SME_USERSPACE) && (!defined CSR_SUPPORT_WEXT)
255 unifi_trace(priv, UDBG1, "SME userspace build: run unifi_helper manually\n");
256 return 0;
257 #endif
259 unifi_trace(priv, UDBG1, "starting %s\n", prog);
261 snprintf(inst_str, 8, "%d", priv->instance);
262 #if (defined CSR_SME_USERSPACE)
263 snprintf(init_mode, 8, "%d", UNIFIHELPER_INIT_MODE_SMEUSER);
264 #else
265 snprintf(init_mode, 8, "%d", UNIFIHELPER_INIT_MODE_NATIVE);
266 #endif /* CSR_SME_USERSPACE */
268 i = 0;
269 argv[i++] = prog;
270 argv[i++] = inst_str;
271 argv[i++] = init_mode;
272 argv[i++] = 0;
273 argv[i] = 0;
274 /* Don't add more args without making argv bigger */
276 /* minimal command environment */
277 i = 0;
278 envp[i++] = "HOME=/";
279 envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
280 envp[i] = 0;
281 /* Don't add more without making envp bigger */
283 unifi_trace(priv, UDBG2, "running %s %s %s\n", argv[0], argv[1], argv[2]);
285 r = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
287 return r;
288 #else
289 unifi_trace(priv, UDBG1, "Can't automatically download firmware because kernel does not have HOTPLUG\n");
290 return -1;
291 #endif
292 } /* uf_run_unifihelper() */
294 #ifdef CSR_WIFI_SPLIT_PATCH
295 static u8 is_ap_mode(unifi_priv_t *priv)
297 if (priv == NULL || priv->interfacePriv[0] == NULL)
299 return FALSE;
302 /* Test for mode requiring AP patch */
303 return(CSR_WIFI_HIP_IS_AP_FW(priv->interfacePriv[0]->interfaceMode));
305 #endif
308 * ---------------------------------------------------------------------------
309 * uf_request_firmware_files
311 * Get the firmware files from userspace.
313 * Arguments:
314 * priv Pointer to OS private struct.
315 * is_fw type of firmware to load (UNIFI_FW_STA/LOADER)
317 * Returns:
318 * None.
319 * ---------------------------------------------------------------------------
321 int uf_request_firmware_files(unifi_priv_t *priv, int is_fw)
323 /* uses the default method to get the firmware */
324 const struct firmware *fw_entry;
325 int postfix;
326 #define UNIFI_MAX_FW_PATH_LEN 32
327 char fw_name[UNIFI_MAX_FW_PATH_LEN];
328 int r;
330 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
331 if (priv->mib_data.length) {
332 vfree(priv->mib_data.data);
333 priv->mib_data.data = NULL;
334 priv->mib_data.length = 0;
336 #endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT*/
338 postfix = priv->instance;
340 if (is_fw == UNIFI_FW_STA) {
341 /* Free kernel buffer and reload */
342 uf_release_firmware(priv, &priv->fw_sta);
343 #ifdef CSR_WIFI_SPLIT_PATCH
344 scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s",
345 postfix, (is_ap_mode(priv) ? "ap.xbv" : "staonly.xbv") );
346 #else
347 scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s",
348 postfix, "sta.xbv" );
349 #endif
350 r = request_firmware(&fw_entry, fw_name, priv->unifi_device);
351 if (r == 0) {
352 priv->fw_sta.dl_data = fw_entry->data;
353 priv->fw_sta.dl_len = fw_entry->size;
354 priv->fw_sta.fw_desc = (void *)fw_entry;
355 } else {
356 unifi_trace(priv, UDBG2, "Firmware file not available\n");
360 return 0;
362 } /* uf_request_firmware_files() */
365 * ---------------------------------------------------------------------------
366 * uf_release_firmware_files
368 * Release all buffers used to store firmware files
370 * Arguments:
371 * priv Pointer to OS private struct.
373 * Returns:
374 * None.
375 * ---------------------------------------------------------------------------
377 int uf_release_firmware_files(unifi_priv_t *priv)
379 uf_release_firmware(priv, &priv->fw_sta);
381 return 0;
385 * ---------------------------------------------------------------------------
386 * uf_release_firmware
388 * Release specific buffer used to store firmware
390 * Arguments:
391 * priv Pointer to OS private struct.
392 * to_free Pointer to specific buffer to release
394 * Returns:
395 * None.
396 * ---------------------------------------------------------------------------
398 int uf_release_firmware(unifi_priv_t *priv, struct dlpriv *to_free)
400 if (to_free != NULL) {
401 release_firmware((const struct firmware *)to_free->fw_desc);
402 to_free->fw_desc = NULL;
403 to_free->dl_data = NULL;
404 to_free->dl_len = 0;
406 return 0;