static void iwl_rx_handle(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rx_queue *rxq = &trans_pcie->rxq; u32 r, i; u8 fill_rx = 0; u32 count = 8; int total_empty; /* */ r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; i = rxq->read; /* */ if (i == r) IWL_DEBUG_RX(trans, "r = %d, i = %d\n", r, i); /* */ total_empty = r - rxq->write_actual; if (total_empty < 0) total_empty += RX_QUEUE_SIZE; if (total_empty > (RX_QUEUE_SIZE / 2)) fill_rx = 1; while (i != r) { struct iwl_rx_mem_buffer *rxb; rxb = rxq->queue[i]; rxq->queue[i] = NULL; IWL_DEBUG_RX(trans, "rxbuf: r = %d, i = %d (%p)\n", rxb); iwl_rx_handle_rxbuf(trans, rxb); i = (i + 1) & RX_QUEUE_MASK; /* */ if (fill_rx) { count++; if (count >= 8) { rxq->read = i; iwlagn_rx_replenish_now(trans); count = 0; } } } /* */ rxq->read = i; if (fill_rx) iwlagn_rx_replenish_now(trans); else iwlagn_rx_queue_restock(trans); }
/** * iwl_rx_handle - Main entry function for receiving responses from uCode * * Uses the priv->rx_handlers callback function array to invoke * the appropriate handlers, including command responses, * frame-received notifications, and other notifications. */ static void iwl_rx_handle(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rx_queue *rxq = &trans_pcie->rxq; u32 r, i; u8 fill_rx = 0; u32 count = 8; int total_empty; /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; i = rxq->read; /* Rx interrupt, but nothing sent from uCode */ if (i == r) IWL_DEBUG_RX(trans, "r = %d, i = %d\n", r, i); /* calculate total frames need to be restock after handling RX */ total_empty = r - rxq->write_actual; if (total_empty < 0) total_empty += RX_QUEUE_SIZE; if (total_empty > (RX_QUEUE_SIZE / 2)) fill_rx = 1; while (i != r) { struct iwl_rx_mem_buffer *rxb; rxb = rxq->queue[i]; rxq->queue[i] = NULL; IWL_DEBUG_RX(trans, "rxbuf: r = %d, i = %d (%p)\n", rxb); iwl_rx_handle_rxbuf(trans, rxb); i = (i + 1) & RX_QUEUE_MASK; /* If there are a lot of unused frames, * restock the Rx queue so ucode wont assert. */ if (fill_rx) { count++; if (count >= 8) { rxq->read = i; iwlagn_rx_replenish_now(trans); count = 0; } } } /* Backtrack one entry */ rxq->read = i; if (fill_rx) iwlagn_rx_replenish_now(trans); else iwlagn_rx_queue_restock(trans); }
/** * iwl_rx_handle - Main entry function for receiving responses from uCode * * Uses the priv->rx_handlers callback function array to invoke * the appropriate handlers, including command responses, * frame-received notifications, and other notifications. */ static void iwl_rx_handle(struct iwl_trans *trans) { struct iwl_rx_mem_buffer *rxb; struct iwl_rx_packet *pkt; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rx_queue *rxq = &trans_pcie->rxq; struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; struct iwl_device_cmd *cmd; u32 r, i; int reclaim; unsigned long flags; u8 fill_rx = 0; u32 count = 8; int total_empty; int index, cmd_index; /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; i = rxq->read; /* Rx interrupt, but nothing sent from uCode */ if (i == r) IWL_DEBUG_RX(trans, "r = %d, i = %d\n", r, i); /* calculate total frames need to be restock after handling RX */ total_empty = r - rxq->write_actual; if (total_empty < 0) total_empty += RX_QUEUE_SIZE; if (total_empty > (RX_QUEUE_SIZE / 2)) fill_rx = 1; while (i != r) { int len, err; u16 sequence; rxb = rxq->queue[i]; /* If an RXB doesn't have a Rx queue slot associated with it, * then a bug has been introduced in the queue refilling * routines -- catch it here */ if (WARN_ON(rxb == NULL)) { i = (i + 1) & RX_QUEUE_MASK; continue; } rxq->queue[i] = NULL; dma_unmap_page(bus(trans)->dev, rxb->page_dma, PAGE_SIZE << hw_params(trans).rx_page_order, DMA_FROM_DEVICE); pkt = rxb_addr(rxb); IWL_DEBUG_RX(trans, "r = %d, i = %d, %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; len += sizeof(u32); /* account for status word */ trace_iwlwifi_dev_rx(priv(trans), pkt, len); /* Reclaim a command buffer only if this packet is a response * to a (driver-originated) command. * If the packet (e.g. Rx frame) originated from uCode, * there is no command buffer to reclaim. * Ucode should set SEQ_RX_FRAME bit if ucode-originated, * but apparently a few don't get set; catch them here. */ reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) && (pkt->hdr.cmd != REPLY_RX_PHY_CMD) && (pkt->hdr.cmd != REPLY_RX) && (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) && (pkt->hdr.cmd != REPLY_COMPRESSED_BA) && (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && (pkt->hdr.cmd != REPLY_TX); sequence = le16_to_cpu(pkt->hdr.sequence); index = SEQ_TO_INDEX(sequence); cmd_index = get_cmd_index(&txq->q, index); if (reclaim) cmd = txq->cmd[cmd_index]; else cmd = NULL; /* warn if this is cmd response / notification and the uCode * didn't set the SEQ_RX_FRAME for a frame that is * uCode-originated * If you saw this code after the second half of 2012, then * please remove it */ WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false && (!(pkt->hdr.sequence & SEQ_RX_FRAME)), "reclaim is false, SEQ_RX_FRAME unset: %s\n", get_cmd_string(pkt->hdr.cmd)); err = iwl_rx_dispatch(priv(trans), rxb, cmd); /* * XXX: After here, we should always check rxb->page * against NULL before touching it or its virtual * memory (pkt). Because some rx_handler might have * already taken or freed the pages. */ if (reclaim) { /* Invoke any callbacks, transfer the buffer to caller, * and fire off the (possibly) blocking * iwl_trans_send_cmd() * as we reclaim the driver command queue */ if (rxb->page) iwl_tx_cmd_complete(trans, rxb, err); else IWL_WARN(trans, "Claim null rxb?\n"); } /* Reuse the page if possible. For notification packets and * SKBs that fail to Rx correctly, add them back into the * rx_free list for reuse later. */ spin_lock_irqsave(&rxq->lock, flags); if (rxb->page != NULL) { rxb->page_dma = dma_map_page(bus(trans)->dev, rxb->page, 0, PAGE_SIZE << hw_params(trans).rx_page_order, DMA_FROM_DEVICE); list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; } else list_add_tail(&rxb->list, &rxq->rx_used); spin_unlock_irqrestore(&rxq->lock, flags); i = (i + 1) & RX_QUEUE_MASK; /* If there are a lot of unused frames, * restock the Rx queue so ucode wont assert. */ if (fill_rx) { count++; if (count >= 8) { rxq->read = i; iwlagn_rx_replenish_now(trans); count = 0; } } } /* Backtrack one entry */ rxq->read = i; if (fill_rx) iwlagn_rx_replenish_now(trans); else iwlagn_rx_queue_restock(trans); }