i2400m_tx_setup() is never called in atomic context. The call chains ending up at i2400m_tx_setup() are: [1] i2400m_tx_setup() <- __i2400m_dev_start() <- __i2400m_dev_reset_handle() [2] i2400m_tx_setup() <- __i2400m_dev_start() <- i2400m_dev_start() <- i2400m_setup() <- i2400mu_probe() [3] i2400m_tx_setup() <- __i2400m_dev_start() <- i2400m_post_reset() <- i2400mu_post_reset()
__i2400m_dev_reset_handle() is only set as a parameter of INIT_WORK() in i2400m_init(). i2400mu_probe() is only set as ".probe" in struct usb_driver. i2400mu_post_reset() is only set as ".post_reset" in struct usb_driver. These functions are not called in atomic context. Despite never getting called from atomic context, i2400m_tx_setup() calls kmalloc() with GFP_ATOMIC, which does not sleep for allocation. GFP_ATOMIC is not necessary and can be replaced with GFP_KERNEL, which can sleep and improve the possibility of sucessful allocation. This is found by a static analysis tool named DCNS written by myself. And I also manually check it. Signed-off-by: Jia-Ju Bai <baijiaju1...@gmail.com> --- drivers/net/wimax/i2400m/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wimax/i2400m/tx.c b/drivers/net/wimax/i2400m/tx.c index f20886a..cfbc187 100644 --- a/drivers/net/wimax/i2400m/tx.c +++ b/drivers/net/wimax/i2400m/tx.c @@ -973,7 +973,7 @@ int i2400m_tx_setup(struct i2400m *i2400m) * the WS was scheduled on another CPU */ INIT_WORK(&i2400m->wake_tx_ws, i2400m_wake_tx_work); - tx_buf = kmalloc(I2400M_TX_BUF_SIZE, GFP_ATOMIC); + tx_buf = kmalloc(I2400M_TX_BUF_SIZE, GFP_KERNEL); if (tx_buf == NULL) { result = -ENOMEM; goto error_kmalloc; -- 1.9.1