aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwmc3200wifi/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/rx.c')
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index 38d950b0f24b..c8a31be16885 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -344,10 +344,15 @@ static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id)
344 u8 id_hash = IWM_RX_ID_GET_HASH(id); 344 u8 id_hash = IWM_RX_ID_GET_HASH(id);
345 struct iwm_rx_packet *packet; 345 struct iwm_rx_packet *packet;
346 346
347 spin_lock(&iwm->packet_lock[id_hash]);
347 list_for_each_entry(packet, &iwm->rx_packets[id_hash], node) 348 list_for_each_entry(packet, &iwm->rx_packets[id_hash], node)
348 if (packet->id == id) 349 if (packet->id == id) {
350 list_del(&packet->node);
351 spin_unlock(&iwm->packet_lock[id_hash]);
349 return packet; 352 return packet;
353 }
350 354
355 spin_unlock(&iwm->packet_lock[id_hash]);
351 return NULL; 356 return NULL;
352} 357}
353 358
@@ -385,18 +390,22 @@ void iwm_rx_free(struct iwm_priv *iwm)
385 struct iwm_rx_packet *packet, *np; 390 struct iwm_rx_packet *packet, *np;
386 int i; 391 int i;
387 392
393 spin_lock(&iwm->ticket_lock);
388 list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) { 394 list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) {
389 list_del(&ticket->node); 395 list_del(&ticket->node);
390 iwm_rx_ticket_node_free(ticket); 396 iwm_rx_ticket_node_free(ticket);
391 } 397 }
398 spin_unlock(&iwm->ticket_lock);
392 399
393 for (i = 0; i < IWM_RX_ID_HASH; i++) { 400 for (i = 0; i < IWM_RX_ID_HASH; i++) {
401 spin_lock(&iwm->packet_lock[i]);
394 list_for_each_entry_safe(packet, np, &iwm->rx_packets[i], 402 list_for_each_entry_safe(packet, np, &iwm->rx_packets[i],
395 node) { 403 node) {
396 list_del(&packet->node); 404 list_del(&packet->node);
397 kfree_skb(packet->skb); 405 kfree_skb(packet->skb);
398 kfree(packet); 406 kfree(packet);
399 } 407 }
408 spin_unlock(&iwm->packet_lock[i]);
400 } 409 }
401} 410}
402 411
@@ -424,7 +433,9 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf,
424 ticket->action == IWM_RX_TICKET_RELEASE ? 433 ticket->action == IWM_RX_TICKET_RELEASE ?
425 "RELEASE" : "DROP", 434 "RELEASE" : "DROP",
426 ticket->id); 435 ticket->id);
436 spin_lock(&iwm->ticket_lock);
427 list_add_tail(&ticket_node->node, &iwm->rx_tickets); 437 list_add_tail(&ticket_node->node, &iwm->rx_tickets);
438 spin_unlock(&iwm->ticket_lock);
428 439
429 /* 440 /*
430 * We received an Rx ticket, most likely there's 441 * We received an Rx ticket, most likely there's
@@ -457,6 +468,7 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf,
457 struct iwm_rx_packet *packet; 468 struct iwm_rx_packet *packet;
458 u16 id, buf_offset; 469 u16 id, buf_offset;
459 u32 packet_size; 470 u32 packet_size;
471 u8 id_hash;
460 472
461 IWM_DBG_RX(iwm, DBG, "\n"); 473 IWM_DBG_RX(iwm, DBG, "\n");
462 474
@@ -474,7 +486,10 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf,
474 if (IS_ERR(packet)) 486 if (IS_ERR(packet))
475 return PTR_ERR(packet); 487 return PTR_ERR(packet);
476 488
477 list_add_tail(&packet->node, &iwm->rx_packets[IWM_RX_ID_GET_HASH(id)]); 489 id_hash = IWM_RX_ID_GET_HASH(id);
490 spin_lock(&iwm->packet_lock[id_hash]);
491 list_add_tail(&packet->node, &iwm->rx_packets[id_hash]);
492 spin_unlock(&iwm->packet_lock[id_hash]);
478 493
479 /* We might (unlikely) have received the packet _after_ the ticket */ 494 /* We might (unlikely) have received the packet _after_ the ticket */
480 queue_work(iwm->rx_wq, &iwm->rx_worker); 495 queue_work(iwm->rx_wq, &iwm->rx_worker);
@@ -1664,6 +1679,7 @@ void iwm_rx_worker(struct work_struct *work)
1664 * We stop whenever a ticket is missing its packet, as we're 1679 * We stop whenever a ticket is missing its packet, as we're
1665 * supposed to send the packets in order. 1680 * supposed to send the packets in order.
1666 */ 1681 */
1682 spin_lock(&iwm->ticket_lock);
1667 list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) { 1683 list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) {
1668 struct iwm_rx_packet *packet = 1684 struct iwm_rx_packet *packet =
1669 iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id)); 1685 iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id));
@@ -1672,12 +1688,12 @@ void iwm_rx_worker(struct work_struct *work)
1672 IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d " 1688 IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d "
1673 "to be handled first\n", 1689 "to be handled first\n",
1674 le16_to_cpu(ticket->ticket->id)); 1690 le16_to_cpu(ticket->ticket->id));
1675 return; 1691 break;
1676 } 1692 }
1677 1693
1678 list_del(&ticket->node); 1694 list_del(&ticket->node);
1679 list_del(&packet->node);
1680 iwm_rx_process_packet(iwm, packet, ticket); 1695 iwm_rx_process_packet(iwm, packet, ticket);
1681 } 1696 }
1697 spin_unlock(&iwm->ticket_lock);
1682} 1698}
1683 1699