From d2d8d2f89672ec1a4bac47382e7da7185a530932 Mon Sep 17 00:00:00 2001 From: xiaojin Date: Thu, 19 Apr 2012 08:49:38 +0800 Subject: [PATCH] n_gsm.c: Enhancement of gsm_mux TX/RX buf allocate BZ: 28510 In LEX platform, we found huge kmalloc fail if repeated gsmld open and close that trigged by stmd(userspace) or modem reset. LEX memory size is 512M, only the half of Medfield. Enhancement: 1. gsm_mux buf/txframe allocation moved to gsmld_config, according to mtu/mru of cfg 2. if encoding ==0, txframe allocate one mtu; otherwise allocate double mtu 3. if allocation size less than PAGE, use kmalloc; otherwise use vmalloc This patch is part of the solution to TX/RX buffer allocate fail. We also need to change mtu/mru in STMD, it should matched to N1 of AT+CMUX. N1(Maximum Frame Size) of modem is 1509 now. Signed-off-by: xiaojin Change-Id: I928f9943bce17c065e070750ccf6648d577b17ff Reviewed-on: http://android.intel.com:8080/43942 Reviewed-by: Stoltz-douchet, OlivierX Reviewed-by: Pillet, VincentX Reviewed-by: Xiao, Jin Reviewed-by: Roulliere, Pierre Reviewed-by: Liu, Chuansheng Reviewed-by: Predon, Frederic Reviewed-by: Lebsir, SamiX Tested-by: Lebsir, SamiX Reviewed-by: buildbot Tested-by: buildbot --- drivers/tty/n_gsm.c | 78 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 13 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 034c349..38a4dde 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2114,6 +2114,35 @@ int gsm_activate_mux(struct gsm_mux *gsm) EXPORT_SYMBOL_GPL(gsm_activate_mux); /** + * gsm_mux_malloc - + * @size: bytes to allocate + * + * Dedicated for gsm_mux buf/txframe malloc + */ +unsigned char *gsm_mux_buf_malloc(unsigned int size) +{ + if (size <= PAGE_SIZE) + return kmalloc(size, GFP_KERNEL); + else + return vmalloc(size); +} + +/** + * gsm_mux_buf_free - + * @size: bytes to free + * @add: addr to free + * + * Dedicated for gsm_mux buf/txframe free + */ +void gsm_mux_buf_free(unsigned int size, void *addr) +{ + if (size <= PAGE_SIZE) + kfree(addr); + else + vfree(addr); +} + +/** * gsm_free_mux - free up a mux * @mux: mux to free * @@ -2121,8 +2150,14 @@ EXPORT_SYMBOL_GPL(gsm_activate_mux); */ void gsm_free_mux(struct gsm_mux *gsm) { - kfree(gsm->txframe); - kfree(gsm->buf); + if (gsm->buf != NULL) + gsm_mux_buf_free(gsm->mru + 1, gsm->buf); + if (gsm->txframe != NULL) { + if (gsm->encoding == 0) + gsm_mux_buf_free(gsm->mtu + 1, gsm->txframe); + else + gsm_mux_buf_free(2 * gsm->mtu + 2, gsm->txframe); + } kfree(gsm); } EXPORT_SYMBOL_GPL(gsm_free_mux); @@ -2162,17 +2197,6 @@ struct gsm_mux *gsm_alloc_mux(void) struct gsm_mux *gsm = kzalloc(sizeof(struct gsm_mux), GFP_KERNEL); if (gsm == NULL) return NULL; - gsm->buf = kmalloc(MAX_MRU + 1, GFP_KERNEL); - if (gsm->buf == NULL) { - kfree(gsm); - return NULL; - } - gsm->txframe = kmalloc(2 * MAX_MRU + 2, GFP_KERNEL); - if (gsm->txframe == NULL) { - kfree(gsm->buf); - kfree(gsm); - return NULL; - } spin_lock_init(&gsm->lock); kref_init(&gsm->ref); INIT_LIST_HEAD(&gsm->tx_list); @@ -2549,6 +2573,34 @@ static int gsmld_config(struct tty_struct *tty, struct gsm_mux *gsm, need_restart = 1; /* + * gsm_mux.buf allocate dynamically + * according to ldisc configuration + */ + if (gsm->buf != NULL) + gsm_mux_buf_free(gsm->mru + 1, gsm->buf); + gsm->buf = gsm_mux_buf_malloc(c->mru + 1); + if (gsm->buf == NULL) + return -ENOMEM; + /* + * gsm_mux.txframe allocate dynamically + * according to ldisc configuration + */ + if (gsm->txframe != NULL) { + if (gsm->encoding == 0) + gsm_mux_buf_free(gsm->mtu + 1, gsm->txframe); + else + gsm_mux_buf_free(2 * gsm->mtu + 2, gsm->txframe); + } + if (c->encapsulation == 0) + gsm->txframe = gsm_mux_buf_malloc(c->mtu + 1); + else + gsm->txframe = gsm_mux_buf_malloc(2 * c->mtu + 2); + if (gsm->txframe == NULL) { + gsm_mux_buf_free(c->mru + 1, gsm->buf); + return -ENOMEM; + } + + /* * Close down what is needed, restart and initiate the new * configuration */ -- 2.7.4