diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/benet/be_main.c | 85 |
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 | ||
996 | static 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 | |||
1008 | static 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 */ | ||
1031 | static 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 | |||
996 | static void be_rx_q_clean(struct be_adapter *adapter) | 1046 | static 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 | } |
1254 | static 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 | |||
1269 | static 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 | ||
1284 | static irqreturn_t be_intx(int irq, void *dev) | 1311 | static irqreturn_t be_intx(int irq, void *dev) |
1285 | { | 1312 | { |