aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorPavan Savoy <pavan_savoy@ti.com>2011-02-04 03:23:13 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-04 15:41:21 -0500
commitef04d121f030329aae0c2d3ec22beea0c5cbcfd3 (patch)
tree891fe4bd9a903b553d058ad08d787fbb07d64565 /drivers/misc
parent6710fcff66ef0330cdc458557271ee86026745d0 (diff)
drivers:misc: ti-st: firmware download optimization
To fasten the process of firmware download, the chip allows disabling of the command complete event generation from host. In these cases, only few very essential commands would have the command complete events and hence the wait associated with them. So now the driver would wait for a command complete event, only when it comes across a wait event during firmware parsing. This would also mean we need to skip not just the change baud rate command but also the wait for it. Signed-off-by: Pavan Savoy <pavan_savoy@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/ti-st/st_core.c18
-rw-r--r--drivers/misc/ti-st/st_kim.c80
2 files changed, 91 insertions, 7 deletions
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index f7bb96f3a424..dd2c879faff6 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -52,6 +52,24 @@ static void remove_channel_from_table(struct st_data_s *st_gdata,
52 st_gdata->list[proto->chnl_id] = NULL; 52 st_gdata->list[proto->chnl_id] = NULL;
53} 53}
54 54
55/*
56 * called from KIM during firmware download.
57 *
58 * This is a wrapper function to tty->ops->write_room.
59 * It returns number of free space available in
60 * uart tx buffer.
61 */
62int st_get_uart_wr_room(struct st_data_s *st_gdata)
63{
64 struct tty_struct *tty;
65 if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
66 pr_err("tty unavailable to perform write");
67 return -1;
68 }
69 tty = st_gdata->tty;
70 return tty->ops->write_room(tty);
71}
72
55/* can be called in from 73/* can be called in from
56 * -- KIM (during fw download) 74 * -- KIM (during fw download)
57 * -- ST Core (during st_write) 75 * -- ST Core (during st_write)
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index ccc46a7b0abb..2c096ccd53b0 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -232,6 +232,26 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
232 return 0; 232 return 0;
233} 233}
234 234
235void skip_change_remote_baud(unsigned char **ptr, long *len)
236{
237 unsigned char *nxt_action, *cur_action;
238 cur_action = *ptr;
239
240 nxt_action = cur_action + sizeof(struct bts_action) +
241 ((struct bts_action *) cur_action)->size;
242
243 if (((struct bts_action *) nxt_action)->type != ACTION_WAIT_EVENT) {
244 pr_err("invalid action after change remote baud command");
245 } else {
246 *ptr = *ptr + sizeof(struct bts_action) +
247 ((struct bts_action *)nxt_action)->size;
248 *len = *len - (sizeof(struct bts_action) +
249 ((struct bts_action *)nxt_action)->size);
250 /* warn user on not commenting these in firmware */
251 pr_warn("skipping the wait event of change remote baud");
252 }
253}
254
235/** 255/**
236 * download_firmware - 256 * download_firmware -
237 * internal function which parses through the .bts firmware 257 * internal function which parses through the .bts firmware
@@ -244,6 +264,9 @@ static long download_firmware(struct kim_data_s *kim_gdata)
244 unsigned char *ptr = NULL; 264 unsigned char *ptr = NULL;
245 unsigned char *action_ptr = NULL; 265 unsigned char *action_ptr = NULL;
246 unsigned char bts_scr_name[30] = { 0 }; /* 30 char long bts scr name? */ 266 unsigned char bts_scr_name[30] = { 0 }; /* 30 char long bts scr name? */
267 int wr_room_space;
268 int cmd_size;
269 unsigned long timeout;
247 270
248 err = read_local_version(kim_gdata, bts_scr_name); 271 err = read_local_version(kim_gdata, bts_scr_name);
249 if (err != 0) { 272 if (err != 0) {
@@ -280,13 +303,43 @@ static long download_firmware(struct kim_data_s *kim_gdata)
280 0xFF36)) { 303 0xFF36)) {
281 /* ignore remote change 304 /* ignore remote change
282 * baud rate HCI VS command */ 305 * baud rate HCI VS command */
283 pr_err 306 pr_warn("change remote baud"
284 (" change remote baud"
285 " rate command in firmware"); 307 " rate command in firmware");
308 skip_change_remote_baud(&ptr, &len);
286 break; 309 break;
287 } 310 }
311 /*
312 * Make sure we have enough free space in uart
313 * tx buffer to write current firmware command
314 */
315 cmd_size = ((struct bts_action *)ptr)->size;
316 timeout = jiffies + msecs_to_jiffies(CMD_WR_TIME);
317 do {
318 wr_room_space =
319 st_get_uart_wr_room(kim_gdata->core_data);
320 if (wr_room_space < 0) {
321 pr_err("Unable to get free "
322 "space info from uart tx buffer");
323 release_firmware(kim_gdata->fw_entry);
324 return wr_room_space;
325 }
326 mdelay(1); /* wait 1ms before checking room */
327 } while ((wr_room_space < cmd_size) &&
328 time_before(jiffies, timeout));
329
330 /* Timeout happened ? */
331 if (time_after_eq(jiffies, timeout)) {
332 pr_err("Timeout while waiting for free "
333 "free space in uart tx buffer");
334 release_firmware(kim_gdata->fw_entry);
335 return -ETIMEDOUT;
336 }
288 337
289 INIT_COMPLETION(kim_gdata->kim_rcvd); 338 /*
339 * Free space found in uart buffer, call st_int_write
340 * to send current firmware command to the uart tx
341 * buffer.
342 */
290 err = st_int_write(kim_gdata->core_data, 343 err = st_int_write(kim_gdata->core_data,
291 ((struct bts_action_send *)action_ptr)->data, 344 ((struct bts_action_send *)action_ptr)->data,
292 ((struct bts_action *)ptr)->size); 345 ((struct bts_action *)ptr)->size);
@@ -294,15 +347,28 @@ static long download_firmware(struct kim_data_s *kim_gdata)
294 release_firmware(kim_gdata->fw_entry); 347 release_firmware(kim_gdata->fw_entry);
295 return err; 348 return err;
296 } 349 }
350 /*
351 * Check number of bytes written to the uart tx buffer
352 * and requested command write size
353 */
354 if (err != cmd_size) {
355 pr_err("Number of bytes written to uart "
356 "tx buffer are not matching with "
357 "requested cmd write size");
358 release_firmware(kim_gdata->fw_entry);
359 return -EIO;
360 }
361 break;
362 case ACTION_WAIT_EVENT: /* wait */
297 if (!wait_for_completion_timeout 363 if (!wait_for_completion_timeout
298 (&kim_gdata->kim_rcvd, 364 (&kim_gdata->kim_rcvd,
299 msecs_to_jiffies(CMD_RESP_TIME))) { 365 msecs_to_jiffies(CMD_RESP_TIME))) {
300 pr_err 366 pr_err("response timeout during fw download ");
301 (" response timeout during fw download ");
302 /* timed out */ 367 /* timed out */
303 release_firmware(kim_gdata->fw_entry); 368 release_firmware(kim_gdata->fw_entry);
304 return -ETIMEDOUT; 369 return -ETIMEDOUT;
305 } 370 }
371 INIT_COMPLETION(kim_gdata->kim_rcvd);
306 break; 372 break;
307 case ACTION_DELAY: /* sleep */ 373 case ACTION_DELAY: /* sleep */
308 pr_info("sleep command in scr"); 374 pr_info("sleep command in scr");