Skip to content

Commit

Permalink
be2net: clear & notify residual events before destroying event queues
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sathya Perla authored and David S. Miller committed Aug 13, 2009
1 parent cdab23b commit 859b1e4
Showing 1 changed file with 56 additions and 29 deletions.
85 changes: 56 additions & 29 deletions drivers/net/benet/be_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1251,35 +1307,6 @@ static int be_rx_queues_create(struct be_adapter *adapter)
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)
{
Expand Down

0 comments on commit 859b1e4

Please sign in to comment.