提交 cf6a64fd 编写于 作者: A Amitkumar Karwar 提交者: John W. Linville

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=85071Reported-by: NMarek Belisko <marek.belisko@gmail.com>
Tested-by: NMarek Belisko <marek.belisko@gmail.com>
Signed-off-by: NAvinash Patil <patila@marvell.com>
Signed-off-by: NCathy Luo <cluo@marvell.com>
Signed-off-by: NAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: NJohn W. Linville <linville@tuxdriver.com>
上级 041bfab5
......@@ -146,6 +146,8 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
atomic_dec(&adapter->rx_pending);
if (adapter->delay_main_work &&
(atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) {
if (adapter->if_ops.submit_rem_rx_urbs)
adapter->if_ops.submit_rem_rx_urbs(adapter);
adapter->delay_main_work = false;
queue_work(adapter->workqueue, &adapter->main_work);
}
......
......@@ -692,6 +692,7 @@ struct mwifiex_if_ops {
void (*fw_dump)(struct mwifiex_adapter *);
int (*clean_pcie_ring) (struct mwifiex_adapter *adapter);
void (*iface_work)(struct work_struct *work);
void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter);
};
struct mwifiex_adapter {
......
......@@ -222,7 +222,13 @@ static void mwifiex_usb_rx_complete(struct urb *urb)
else
size = MWIFIEX_RX_DATA_BUF_SIZE;
mwifiex_usb_submit_rx_urb(context, size);
if (card->rx_cmd_ep == context->ep) {
mwifiex_usb_submit_rx_urb(context, size);
} else {
context->skb = NULL;
if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING)
mwifiex_usb_submit_rx_urb(context, size);
}
return;
}
......@@ -978,6 +984,20 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
return 0;
}
static void mwifiex_usb_submit_rem_rx_urbs(struct mwifiex_adapter *adapter)
{
struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
int i;
struct urb_context *ctx;
for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
if (card->rx_data_list[i].skb)
continue;
ctx = &card->rx_data_list[i];
mwifiex_usb_submit_rx_urb(ctx, MWIFIEX_RX_DATA_BUF_SIZE);
}
}
static struct mwifiex_if_ops usb_ops = {
.register_dev = mwifiex_register_dev,
.unregister_dev = mwifiex_unregister_dev,
......@@ -989,6 +1009,7 @@ static struct mwifiex_if_ops usb_ops = {
.cmdrsp_complete = mwifiex_usb_cmd_event_complete,
.event_complete = mwifiex_usb_cmd_event_complete,
.host_to_card = mwifiex_usb_host_to_card,
.submit_rem_rx_urbs = mwifiex_usb_submit_rem_rx_urbs,
};
/* This function initializes the USB driver module.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册