Commit e49038d6 authored by David S. Miller's avatar David S. Miller

Merge branch 'qlcnic-next'

Rajesh Borundia says:

====================
qlcnic fixes

This series adds following fixes.

o While processing mailbox if driver gets a spurious mailbox
  interrupt it leads into premature completion of a next
  mailbox request. Added a guard against this by checking current
  state of mailbox and ignored spurious interrupt.
  Added a stats counter to record this condition.

v2:

o Added patch that removes usage of atomic_t as we are not implemeting
  atomicity by using atomic_t value.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b795a213 819bfe76
...@@ -566,6 +566,7 @@ struct qlcnic_adapter_stats { ...@@ -566,6 +566,7 @@ struct qlcnic_adapter_stats {
u64 tx_dma_map_error; u64 tx_dma_map_error;
u64 spurious_intr; u64 spurious_intr;
u64 mac_filter_limit_overrun; u64 mac_filter_limit_overrun;
u64 mbx_spurious_intr;
}; };
/* /*
...@@ -1099,7 +1100,7 @@ struct qlcnic_mailbox { ...@@ -1099,7 +1100,7 @@ struct qlcnic_mailbox {
unsigned long status; unsigned long status;
spinlock_t queue_lock; /* Mailbox queue lock */ spinlock_t queue_lock; /* Mailbox queue lock */
spinlock_t aen_lock; /* Mailbox response/AEN lock */ spinlock_t aen_lock; /* Mailbox response/AEN lock */
atomic_t rsp_status; u32 rsp_status;
u32 num_cmds; u32 num_cmds;
}; };
......
...@@ -491,7 +491,7 @@ irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter) ...@@ -491,7 +491,7 @@ irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
static inline void qlcnic_83xx_notify_mbx_response(struct qlcnic_mailbox *mbx) static inline void qlcnic_83xx_notify_mbx_response(struct qlcnic_mailbox *mbx)
{ {
atomic_set(&mbx->rsp_status, QLC_83XX_MBX_RESPONSE_ARRIVED); mbx->rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED;
complete(&mbx->completion); complete(&mbx->completion);
} }
...@@ -510,7 +510,7 @@ static void qlcnic_83xx_poll_process_aen(struct qlcnic_adapter *adapter) ...@@ -510,7 +510,7 @@ static void qlcnic_83xx_poll_process_aen(struct qlcnic_adapter *adapter)
if (event & QLCNIC_MBX_ASYNC_EVENT) { if (event & QLCNIC_MBX_ASYNC_EVENT) {
__qlcnic_83xx_process_aen(adapter); __qlcnic_83xx_process_aen(adapter);
} else { } else {
if (atomic_read(&mbx->rsp_status) != rsp_status) if (mbx->rsp_status != rsp_status)
qlcnic_83xx_notify_mbx_response(mbx); qlcnic_83xx_notify_mbx_response(mbx);
} }
out: out:
...@@ -1023,7 +1023,7 @@ static void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) ...@@ -1023,7 +1023,7 @@ static void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
if (event & QLCNIC_MBX_ASYNC_EVENT) { if (event & QLCNIC_MBX_ASYNC_EVENT) {
__qlcnic_83xx_process_aen(adapter); __qlcnic_83xx_process_aen(adapter);
} else { } else {
if (atomic_read(&mbx->rsp_status) != rsp_status) if (mbx->rsp_status != rsp_status)
qlcnic_83xx_notify_mbx_response(mbx); qlcnic_83xx_notify_mbx_response(mbx);
} }
} }
...@@ -2338,9 +2338,9 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter, ...@@ -2338,9 +2338,9 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
static irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data) static irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
{ {
u32 mask, resp, event, rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED;
struct qlcnic_adapter *adapter = data; struct qlcnic_adapter *adapter = data;
struct qlcnic_mailbox *mbx; struct qlcnic_mailbox *mbx;
u32 mask, resp, event;
unsigned long flags; unsigned long flags;
mbx = adapter->ahw->mailbox; mbx = adapter->ahw->mailbox;
...@@ -2350,10 +2350,14 @@ static irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data) ...@@ -2350,10 +2350,14 @@ static irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
goto out; goto out;
event = readl(QLCNIC_MBX_FW(adapter->ahw, 0)); event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
if (event & QLCNIC_MBX_ASYNC_EVENT) if (event & QLCNIC_MBX_ASYNC_EVENT) {
__qlcnic_83xx_process_aen(adapter); __qlcnic_83xx_process_aen(adapter);
else } else {
qlcnic_83xx_notify_mbx_response(mbx); if (mbx->rsp_status != rsp_status)
qlcnic_83xx_notify_mbx_response(mbx);
else
adapter->stats.mbx_spurious_intr++;
}
out: out:
mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK); mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
...@@ -4050,10 +4054,10 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work) ...@@ -4050,10 +4054,10 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
struct qlcnic_adapter *adapter = mbx->adapter; struct qlcnic_adapter *adapter = mbx->adapter;
const struct qlcnic_mbx_ops *mbx_ops = mbx->ops; const struct qlcnic_mbx_ops *mbx_ops = mbx->ops;
struct device *dev = &adapter->pdev->dev; struct device *dev = &adapter->pdev->dev;
atomic_t *rsp_status = &mbx->rsp_status;
struct list_head *head = &mbx->cmd_q; struct list_head *head = &mbx->cmd_q;
struct qlcnic_hardware_context *ahw; struct qlcnic_hardware_context *ahw;
struct qlcnic_cmd_args *cmd = NULL; struct qlcnic_cmd_args *cmd = NULL;
unsigned long flags;
ahw = adapter->ahw; ahw = adapter->ahw;
...@@ -4063,7 +4067,9 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work) ...@@ -4063,7 +4067,9 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
return; return;
} }
atomic_set(rsp_status, QLC_83XX_MBX_RESPONSE_WAIT); spin_lock_irqsave(&mbx->aen_lock, flags);
mbx->rsp_status = QLC_83XX_MBX_RESPONSE_WAIT;
spin_unlock_irqrestore(&mbx->aen_lock, flags);
spin_lock(&mbx->queue_lock); spin_lock(&mbx->queue_lock);
......
...@@ -59,7 +59,8 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = { ...@@ -59,7 +59,8 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
QLC_OFF(stats.mac_filter_limit_overrun)}, QLC_OFF(stats.mac_filter_limit_overrun)},
{"spurious intr", QLC_SIZEOF(stats.spurious_intr), {"spurious intr", QLC_SIZEOF(stats.spurious_intr),
QLC_OFF(stats.spurious_intr)}, QLC_OFF(stats.spurious_intr)},
{"mbx spurious intr", QLC_SIZEOF(stats.mbx_spurious_intr),
QLC_OFF(stats.mbx_spurious_intr)},
}; };
static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = { static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment