msm_shared: Eliminate double copy of the intput string to uart driver.
The double copy allocates a buffer of 1K on stack and causes
stack overflow when the stack size is small.
Change-Id: I7531785577c03f6f1a0a4150cf1d41f70a96931a
diff --git a/platform/msm_shared/uart_dm.c b/platform/msm_shared/uart_dm.c
index 81e8f42..01bcbb6 100644
--- a/platform/msm_shared/uart_dm.c
+++ b/platform/msm_shared/uart_dm.c
@@ -1,17 +1,17 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
-
+/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@@ -60,20 +60,44 @@
* - While waiting Watchdog hasn't been taken into consideration.
*/
-#define PACK_CHARS_INTO_WORDS(a, cnt, word) { \
- word = 0; \
- for(int j=0; j < (int)cnt; j++) \
- { \
- word |= (a[j] & 0xff) \
- << (j * 8); \
- } \
- }
+#define NON_PRINTABLE_ASCII_CHAR 128
+
+static uint8_t pack_chars_into_words(uint8_t *buffer, uint8_t cnt, uint32_t *word)
+{
+ uint8_t num_chars_writtten = 0;
+
+ *word = 0;
+
+ for(int j=0; j < cnt; j++)
+ {
+ if (buffer[num_chars_writtten] == '\n')
+ {
+ /* replace '\n' by the NON_PRINTABLE_ASCII_CHAR and print '\r'.
+ * While printing the NON_PRINTABLE_ASCII_CHAR, we will print '\n'.
+ * Thus successfully replacing '\n' by '\r' '\n'.
+ */
+ *word |= ('\r' & 0xff) << (j * 8);
+ buffer[num_chars_writtten] = NON_PRINTABLE_ASCII_CHAR;
+ }
+ else
+ {
+ if (buffer[num_chars_writtten] == NON_PRINTABLE_ASCII_CHAR)
+ {
+ buffer[num_chars_writtten] = '\n';
+ }
+
+ *word |= (buffer[num_chars_writtten] & 0xff) << (j * 8);
+
+ num_chars_writtten++;
+ }
+ }
+
+ return num_chars_writtten;
+}
/* Static Function Prototype Declarations */
-static unsigned int msm_boot_uart_replace_lr_with_cr(char *data_in,
- int num_of_chars,
- char *data_out,
- int *num_of_chars_out);
+static unsigned int msm_boot_uart_calculate_num_chars_to_write(char *data_in,
+ uint32_t *num_of_chars);
static unsigned int msm_boot_uart_dm_init(uint32_t base);
static unsigned int msm_boot_uart_dm_read(uint32_t base,
unsigned int *data, int wait);
@@ -90,30 +114,27 @@
void udelay(unsigned usecs);
/*
- * Helper function to replace Line Feed char "\n" with
+ * Helper function to keep track of Line Feed char "\n" with
* Carriage Return "\r\n".
- * Currently keeping it simple than efficient
*/
static unsigned int
-msm_boot_uart_replace_lr_with_cr(char *data_in,
- int num_of_chars,
- char *data_out, int *num_of_chars_out)
+msm_boot_uart_calculate_num_chars_to_write(char *data_in,
+ uint32_t *num_of_chars)
{
int i = 0, j = 0;
- if ((data_in == NULL) || (data_out == NULL) || (num_of_chars < 0)) {
+ if ((data_in == NULL) || (*num_of_chars < 0)) {
return MSM_BOOT_UART_DM_E_INVAL;
}
- for (i = 0, j = 0; i < num_of_chars; i++, j++) {
+ for (i = 0, j = 0; i < *num_of_chars; i++, j++) {
if (data_in[i] == '\n') {
- data_out[j++] = '\r';
+ j++;
}
- data_out[j] = data_in[i];
}
- *num_of_chars_out = j;
+ *num_of_chars = j;
return MSM_BOOT_UART_DM_E_SUCCESS;
}
@@ -295,18 +316,15 @@
unsigned int tx_word = 0;
int i = 0;
char *tx_data = NULL;
- char new_data[1024];
+ uint8_t num_chars_written;
if ((data == NULL) || (num_of_chars <= 0)) {
return MSM_BOOT_UART_DM_E_INVAL;
}
- /* Replace line-feed (/n) with carriage-return + line-feed (/r/n) */
+ msm_boot_uart_calculate_num_chars_to_write(data, &num_of_chars);
- msm_boot_uart_replace_lr_with_cr(data, num_of_chars, new_data, &i);
-
- tx_data = new_data;
- num_of_chars = i;
+ tx_data = data;
/* Write to NO_CHARS_FOR_TX register number of characters
* to be transmitted. However, before writing TX_FIFO must
@@ -337,7 +355,7 @@
for (i = 0; i < (int)tx_word_count; i++) {
tx_char = (tx_char_left < 4) ? tx_char_left : 4;
- PACK_CHARS_INTO_WORDS(tx_data, tx_char, tx_word);
+ num_chars_written = pack_chars_into_words(tx_data, tx_char, &tx_word);
/* Wait till TX FIFO has space */
while (!(readl(MSM_BOOT_UART_DM_SR(base)) & MSM_BOOT_UART_DM_SR_TXRDY)) {
@@ -347,7 +365,7 @@
/* TX FIFO has space. Write the chars */
writel(tx_word, MSM_BOOT_UART_DM_TF(base, 0));
tx_char_left = num_of_chars - (i + 1) * 4;
- tx_data = tx_data + 4;
+ tx_data = tx_data + num_chars_written;
}
return MSM_BOOT_UART_DM_E_SUCCESS;