summaryrefslogtreecommitdiffstats
path: root/drivers/net/benet/be_main.c
diff options
context:
space:
mode:
authorSathya Perla2009-08-10 05:43:51 +0200
committerDavid S. Miller2009-08-13 07:13:17 +0200
commit859b1e4ec86840b0d0980f82b626d687be682eb9 (patch)
tree8fda4f86d384eb1e61f3feea02639158214dd2d8 /drivers/net/benet/be_main.c
parentbe2net: fix bad queue traversal in be_rx_q_clean() (diff)
downloadkernel-qcow2-linux-859b1e4ec86840b0d0980f82b626d687be682eb9.tar.gz
kernel-qcow2-linux-859b1e4ec86840b0d0980f82b626d687be682eb9.tar.xz
kernel-qcow2-linux-859b1e4ec86840b0d0980f82b626d687be682eb9.zip
be2net: clear & notify residual events before destroying event queues
Any events rcvd after interrupts are disabled (in the driver unload path), must be cleared and notified before the event queues are destroyed Signed-off-by: Sathya Perla <sathyap@serverengines.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/benet/be_main.c')
-rw-r--r--drivers/net/benet/be_main.c85
1 files changed, 56 insertions, 29 deletions
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 9bbf447ee28f..2db879c03c6d 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -993,6 +993,56 @@ static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index)
kfree_skb(sent_skb);
}
+static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj)
+{
+ struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q);
+
+ if (!eqe->evt)
+ return NULL;
+
+ eqe->evt = le32_to_cpu(eqe->evt);
+ queue_tail_inc(&eq_obj->q);
+ return eqe;
+}
+
+static int event_handle(struct be_adapter *adapter,
+ struct be_eq_obj *eq_obj)
+{
+ struct be_eq_entry *eqe;
+ u16 num = 0;
+
+ while ((eqe = event_get(eq_obj)) != NULL) {
+ eqe->evt = 0;
+ num++;
+ }
+
+ /* Deal with any spurious interrupts that come
+ * without events
+ */
+ be_eq_notify(adapter, eq_obj->q.id, true, true, num);
+ if (num)
+ napi_schedule(&eq_obj->napi);
+
+ return num;
+}
+
+/* Just read and notify events without processing them.
+ * Used at the time of destroying event queues */
+static void be_eq_clean(struct be_adapter *adapter,
+ struct be_eq_obj *eq_obj)
+{
+ struct be_eq_entry *eqe;
+ u16 num = 0;
+
+ while ((eqe = event_get(eq_obj)) != NULL) {
+ eqe->evt = 0;
+ num++;
+ }
+
+ if (num)
+ be_eq_notify(adapter, eq_obj->q.id, false, true, num);
+}
+
static void be_rx_q_clean(struct be_adapter *adapter)
{
struct be_rx_page_info *page_info;
@@ -1114,6 +1164,9 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
be_cmd_q_destroy(adapter, q, QTYPE_CQ);
be_queue_free(adapter, q);
+ /* Clear any residual events */
+ be_eq_clean(adapter, &adapter->tx_eq);
+
q = &adapter->tx_eq.q;
if (q->created)
be_cmd_q_destroy(adapter, q, QTYPE_EQ);
@@ -1185,6 +1238,9 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)
be_cmd_q_destroy(adapter, q, QTYPE_CQ);
be_queue_free(adapter, q);
+ /* Clear any residual events */
+ be_eq_clean(adapter, &adapter->rx_eq);
+
q = &adapter->rx_eq.q;
if (q->created)
be_cmd_q_destroy(adapter, q, QTYPE_EQ);
@@ -1251,35 +1307,6 @@ rx_eq_free:
be_queue_free(adapter, eq);
return rc;
}
-static bool event_get(struct be_eq_obj *eq_obj, u16 *rid)
-{
- struct be_eq_entry *entry = queue_tail_node(&eq_obj->q);
- u32 evt = entry->evt;
-
- if (!evt)
- return false;
-
- evt = le32_to_cpu(evt);
- *rid = (evt >> EQ_ENTRY_RES_ID_SHIFT) & EQ_ENTRY_RES_ID_MASK;
- entry->evt = 0;
- queue_tail_inc(&eq_obj->q);
- return true;
-}
-
-static int event_handle(struct be_adapter *adapter, struct be_eq_obj *eq_obj)
-{
- u16 rid = 0, num = 0;
-
- while (event_get(eq_obj, &rid))
- num++;
-
- /* We can see an interrupt and no event */
- be_eq_notify(adapter, eq_obj->q.id, true, true, num);
- if (num)
- napi_schedule(&eq_obj->napi);
-
- return num;
-}
static irqreturn_t be_intx(int irq, void *dev)
{