diff options
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/rx.c')
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/rx.c | 24 |
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 | ||