>> >>>>>> >>>>>> Anyway, I don't buy the theory that this is caused by the firmware >>>>>> going out to lunch. The queues files in debugfs show the rx queue >>>>>> chugging along and all of the tx queues have read_ptr == write_ptr. >>>>>> Wireshark shows incoming broadcast traffic, too. I'd guess that the >>>>>> problem is more likely to be that the card is failing to wake up and >>>>>> notice pending data in the TIM. >>>> >>>> Well... I might have been unclear here (I never know how much detail I should share with the recipient :)). >>>> From your log it appears that the NIC is in power save. So we can't increment the write pointer of the Tx ring (add a packet for transmission). So we simply remember that we need to do so (increment the write pointer) and request a wakeup so that we will update the write pointer in the wakeup interrupt... which doesn't happen. >>>> No power save - no need for wakeup interrupt. >>> >>> I'm still unconvinced. One of the tx queues actually has a both >>> read_ptr and write_ptr incrementing once or twice per second even when >>> I can't ping the gateway. Can you point me at the right code or log >>> stuff to look at? >> >> drivers/net/wireless/iwlwifi/pcie/tx.c: >> static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, >> struct iwl_txq *txq) >> [snip] >> >> if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { >> IWL_DEBUG_INFO(trans, "Tx queue %d requesting wakeup, GP1 = 0x%x\n", >> txq_id, reg); >> iwl_set_bit(trans, CSR_GP_CNTRL, >> CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); >> txq->need_update = true; >> return; >> } >> [snip] >> } >> >> ISR - drivers/net/wireless/iwlwifi/pcie/tx.c: >> irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) >> { >> [snip] >> /* uCode wakes up after power-down sleep */ >> if (inta & CSR_INT_BIT_WAKEUP) { >> IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); >> iwl_pcie_rxq_check_wrptr(trans); >> iwl_pcie_txq_check_wrptrs(trans); >> >> isr_stats->wakeup++; >> >> handled |= CSR_INT_BIT_WAKEUP; >> } >> [snip] >> } >> >> drivers/net/wireless/iwlwifi/pcie/tx.c: >> void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans) >> { >> struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); >> int i; >> >> for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { >> struct iwl_txq *txq = &trans_pcie->txq[i]; >> >> spin_lock_bh(&txq->lock); >> if (trans_pcie->txq[i].need_update) { >> iwl_pcie_txq_inc_wr_ptr(trans, txq); >> trans_pcie->txq[i].need_update = false; >> } >> spin_unlock_bh(&txq->lock); >> } >> } >> >> Note that the CMD queue (9 or 4 depending on your configuration) - uses another mechanism that is safer but consumes more power. This queue is intended for commands and not for real Tx packets. > > If that's queue 4 in the debugfs tx_queues file, then I think that > that's the queue that keeps moving when the card is dead. I'll see if > I can improve the tx_queues file to show pending updates. > > Yay troubleshooting old hardware. > If you plan to spend some time hacking on the code, please take into account this code has been changed in 3.14 (mostly cleanups by Johannes and myself). Also note that long ago, I disabled shadow registers (you'll see ifs all over the code). Shadow registers makes the whole wakup thing much easier since it is handled internally in the HW. BUT we had tons of issues with it so we disabled it. Most of the issues should have gone away with the cmd_in_flight thing. So I would recommend you to give it a try with shadow register enabled. Just check the relevant iwl-XXXX.c file. -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html