aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2014-11-05 06:34:29 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-11-11 16:31:12 -0500
commitcf6a64fd603ae0f7391f7589b0f3568d4e79605c (patch)
tree0995759fefa625fb07b44ebe5c318f70eaff4fc1
parent041bfab5bbb6ec721c743f487e3e22b87f666996 (diff)
mwifiex: fix out of memory issue observed for USB chipsets
On some platforms, system goes out of memory during heavy Rx traffic with our USB chipsets. In case of SDIO/PCIe, after receiving 50 packets in Rx queue we stop processing interrupts till packets pending fall below low threshold i.e 20. We don't have similar logic for USB, so if host platform is slow, we would hit a case where firmware keeps on pushing packets at high speed than driver/kernel can process. We will stop submitting URBs for Rx data when pending packet count reaches high threshold and restart them when enough packets are consumed to solve the problem. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=85071 Reported-by: Marek Belisko <marek.belisko@gmail.com> Tested-by: Marek Belisko <marek.belisko@gmail.com> Signed-off-by: Avinash Patil <patila@marvell.com> Signed-off-by: Cathy Luo <cluo@marvell.com> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/mwifiex/main.c2
-rw-r--r--drivers/net/wireless/mwifiex/main.h1
-rw-r--r--drivers/net/wireless/mwifiex/usb.c23
3 files changed, 25 insertions, 1 deletions
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index cb23ca3653b5..2a5a59bec124 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -146,6 +146,8 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
146 atomic_dec(&adapter->rx_pending); 146 atomic_dec(&adapter->rx_pending);
147 if (adapter->delay_main_work && 147 if (adapter->delay_main_work &&
148 (atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) { 148 (atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) {
149 if (adapter->if_ops.submit_rem_rx_urbs)
150 adapter->if_ops.submit_rem_rx_urbs(adapter);
149 adapter->delay_main_work = false; 151 adapter->delay_main_work = false;
150 queue_work(adapter->workqueue, &adapter->main_work); 152 queue_work(adapter->workqueue, &adapter->main_work);
151 } 153 }
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 4ef3c7a8f9fb..eced41ef1967 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -692,6 +692,7 @@ struct mwifiex_if_ops {
692 void (*fw_dump)(struct mwifiex_adapter *); 692 void (*fw_dump)(struct mwifiex_adapter *);
693 int (*clean_pcie_ring) (struct mwifiex_adapter *adapter); 693 int (*clean_pcie_ring) (struct mwifiex_adapter *adapter);
694 void (*iface_work)(struct work_struct *work); 694 void (*iface_work)(struct work_struct *work);
695 void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter);
695}; 696};
696 697
697struct mwifiex_adapter { 698struct mwifiex_adapter {
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index 08e9ec065275..6cc8519c0f40 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -222,7 +222,13 @@ setup_for_next:
222 else 222 else
223 size = MWIFIEX_RX_DATA_BUF_SIZE; 223 size = MWIFIEX_RX_DATA_BUF_SIZE;
224 224
225 mwifiex_usb_submit_rx_urb(context, size); 225 if (card->rx_cmd_ep == context->ep) {
226 mwifiex_usb_submit_rx_urb(context, size);
227 } else {
228 context->skb = NULL;
229 if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING)
230 mwifiex_usb_submit_rx_urb(context, size);
231 }
226 232
227 return; 233 return;
228} 234}
@@ -978,6 +984,20 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
978 return 0; 984 return 0;
979} 985}
980 986
987static void mwifiex_usb_submit_rem_rx_urbs(struct mwifiex_adapter *adapter)
988{
989 struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
990 int i;
991 struct urb_context *ctx;
992
993 for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
994 if (card->rx_data_list[i].skb)
995 continue;
996 ctx = &card->rx_data_list[i];
997 mwifiex_usb_submit_rx_urb(ctx, MWIFIEX_RX_DATA_BUF_SIZE);
998 }
999}
1000
981static struct mwifiex_if_ops usb_ops = { 1001static struct mwifiex_if_ops usb_ops = {
982 .register_dev = mwifiex_register_dev, 1002 .register_dev = mwifiex_register_dev,
983 .unregister_dev = mwifiex_unregister_dev, 1003 .unregister_dev = mwifiex_unregister_dev,
@@ -989,6 +1009,7 @@ static struct mwifiex_if_ops usb_ops = {
989 .cmdrsp_complete = mwifiex_usb_cmd_event_complete, 1009 .cmdrsp_complete = mwifiex_usb_cmd_event_complete,
990 .event_complete = mwifiex_usb_cmd_event_complete, 1010 .event_complete = mwifiex_usb_cmd_event_complete,
991 .host_to_card = mwifiex_usb_host_to_card, 1011 .host_to_card = mwifiex_usb_host_to_card,
1012 .submit_rem_rx_urbs = mwifiex_usb_submit_rem_rx_urbs,
992}; 1013};
993 1014
994/* This function initializes the USB driver module. 1015/* This function initializes the USB driver module.