]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/benet/be_main.c
be2net:Creating/destroying queues regardless of netif_running() in suspend/resume...
[net-next-2.6.git] / drivers / net / benet / be_main.c
index 9bbf447ee28f6712fb97a52969bb3eb8a03a0442..45507d88e6a135d2106e3e2101038011f4e8dea9 100644 (file)
@@ -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)
 {
@@ -1945,9 +1972,9 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
        if (netif_running(netdev)) {
                rtnl_lock();
                be_close(netdev);
-               be_clear(adapter);
                rtnl_unlock();
        }
+       be_clear(adapter);
 
        pci_save_state(pdev);
        pci_disable_device(pdev);
@@ -1970,9 +1997,9 @@ static int be_resume(struct pci_dev *pdev)
        pci_set_power_state(pdev, 0);
        pci_restore_state(pdev);
 
+       be_setup(adapter);
        if (netif_running(netdev)) {
                rtnl_lock();
-               be_setup(adapter);
                be_open(netdev);
                rtnl_unlock();
        }