aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorSathya Perla <sathyap@serverengines.com>2009-08-09 23:43:51 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-13 01:13:17 -0400
commit859b1e4ec86840b0d0980f82b626d687be682eb9 (patch)
tree8fda4f86d384eb1e61f3feea02639158214dd2d8 /drivers/net
parentcdab23b7017693c00dd69fa28bcdf5b0434b3838 (diff)
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')
-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)
993 kfree_skb(sent_skb); 993 kfree_skb(sent_skb);
994} 994}
995 995
996static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj)
997{
998 struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q);
999
1000 if (!eqe->evt)
1001 return NULL;
1002
1003 eqe->evt = le32_to_cpu(eqe->evt);
1004 queue_tail_inc(&eq_obj->q);
1005 return eqe;
1006}
1007
1008static int event_handle(struct be_adapter *adapter,
1009 struct be_eq_obj *eq_obj)
1010{
1011 struct be_eq_entry *eqe;
1012 u16 num = 0;
1013
1014 while ((eqe = event_get(eq_obj)) != NULL) {
1015 eqe->evt = 0;
1016 num++;
1017 }
1018
1019 /* Deal with any spurious interrupts that come
1020 * without events
1021 */
1022 be_eq_notify(adapter, eq_obj->q.id, true, true, num);
1023 if (num)
1024 napi_schedule(&eq_obj->napi);
1025
1026 return num;
1027}
1028
1029/* Just read and notify events without processing them.
1030 * Used at the time of destroying event queues */
1031static void be_eq_clean(struct be_adapter *adapter,
1032 struct be_eq_obj *eq_obj)
1033{
1034 struct be_eq_entry *eqe;
1035 u16 num = 0;
1036
1037 while ((eqe = event_get(eq_obj)) != NULL) {
1038 eqe->evt = 0;
1039 num++;
1040 }
1041
1042 if (num)
1043 be_eq_notify(adapter, eq_obj->q.id, false, true, num);
1044}
1045
996static void be_rx_q_clean(struct be_adapter *adapter) 1046static void be_rx_q_clean(struct be_adapter *adapter)
997{ 1047{
998 struct be_rx_page_info *page_info; 1048 struct be_rx_page_info *page_info;
@@ -1114,6 +1164,9 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
1114 be_cmd_q_destroy(adapter, q, QTYPE_CQ); 1164 be_cmd_q_destroy(adapter, q, QTYPE_CQ);
1115 be_queue_free(adapter, q); 1165 be_queue_free(adapter, q);
1116 1166
1167 /* Clear any residual events */
1168 be_eq_clean(adapter, &adapter->tx_eq);
1169
1117 q = &adapter->tx_eq.q; 1170 q = &adapter->tx_eq.q;
1118 if (q->created) 1171 if (q->created)
1119 be_cmd_q_destroy(adapter, q, QTYPE_EQ); 1172 be_cmd_q_destroy(adapter, q, QTYPE_EQ);
@@ -1185,6 +1238,9 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)
1185 be_cmd_q_destroy(adapter, q, QTYPE_CQ); 1238 be_cmd_q_destroy(adapter, q, QTYPE_CQ);
1186 be_queue_free(adapter, q); 1239 be_queue_free(adapter, q);
1187 1240
1241 /* Clear any residual events */
1242 be_eq_clean(adapter, &adapter->rx_eq);
1243
1188 q = &adapter->rx_eq.q; 1244 q = &adapter->rx_eq.q;
1189 if (q->created) 1245 if (q->created)
1190 be_cmd_q_destroy(adapter, q, QTYPE_EQ); 1246 be_cmd_q_destroy(adapter, q, QTYPE_EQ);
@@ -1251,35 +1307,6 @@ rx_eq_free:
1251 be_queue_free(adapter, eq); 1307 be_queue_free(adapter, eq);
1252 return rc; 1308 return rc;
1253} 1309}
1254static bool event_get(struct be_eq_obj *eq_obj, u16 *rid)
1255{
1256 struct be_eq_entry *entry = queue_tail_node(&eq_obj->q);
1257 u32 evt = entry->evt;
1258
1259 if (!evt)
1260 return false;
1261
1262 evt = le32_to_cpu(evt);
1263 *rid = (evt >> EQ_ENTRY_RES_ID_SHIFT) & EQ_ENTRY_RES_ID_MASK;
1264 entry->evt = 0;
1265 queue_tail_inc(&eq_obj->q);
1266 return true;
1267}
1268
1269static int event_handle(struct be_adapter *adapter, struct be_eq_obj *eq_obj)
1270{
1271 u16 rid = 0, num = 0;
1272
1273 while (event_get(eq_obj, &rid))
1274 num++;
1275
1276 /* We can see an interrupt and no event */
1277 be_eq_notify(adapter, eq_obj->q.id, true, true, num);
1278 if (num)
1279 napi_schedule(&eq_obj->napi);
1280
1281 return num;
1282}
1283 1310
1284static irqreturn_t be_intx(int irq, void *dev) 1311static irqreturn_t be_intx(int irq, void *dev)
1285{ 1312{