iwlwifi: check the SCD conf from ALIVE response
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / pcie / trans.c
index dbeebef562d5ca0bca0c9b3ac391747ebfe02973..0703da892e59d03ad96177c7e5206ae211633f30 100644 (file)
@@ -216,7 +216,7 @@ static int iwl_rx_init(struct iwl_trans *trans)
        rxq->free_count = 0;
        spin_unlock_irqrestore(&rxq->lock, flags);
 
-       iwlagn_rx_replenish(trans);
+       iwl_rx_replenish(trans);
 
        iwl_trans_rx_hw_init(trans, rxq);
 
@@ -300,7 +300,7 @@ static void iwl_trans_pcie_queue_stuck_timer(unsigned long data)
        struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
        struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie);
        u32 scd_sram_addr = trans_pcie->scd_base_addr +
-               SCD_TX_STTS_MEM_LOWER_BOUND + (16 * txq->q.id);
+                               SCD_TX_STTS_QUEUE_OFFSET(txq->q.id);
        u8 buf[16];
        int i;
 
@@ -442,10 +442,10 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq,
        return 0;
 }
 
-/**
+/*
  * iwl_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
  */
-static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
+void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
@@ -492,10 +492,12 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
        iwl_tx_queue_unmap(trans, txq_id);
 
        /* De-alloc array of command/tx buffers */
-
        if (txq_id == trans_pcie->cmd_queue)
-               for (i = 0; i < txq->q.n_window; i++)
+               for (i = 0; i < txq->q.n_window; i++) {
                        kfree(txq->entries[i].cmd);
+                       kfree(txq->entries[i].copy_cmd);
+                       kfree(txq->entries[i].free_buf);
+               }
 
        /* De-alloc circular buffer of TFDs */
        if (txq->q.n_bd) {
@@ -675,13 +677,10 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans)
 static u16 iwl_pciexp_link_ctrl(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       int pos;
        u16 pci_lnk_ctl;
 
-       struct pci_dev *pci_dev = trans_pcie->pci_dev;
-
-       pos = pci_pcie_cap(pci_dev);
-       pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
+       pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL,
+                                 &pci_lnk_ctl);
        return pci_lnk_ctl;
 }
 
@@ -854,10 +853,8 @@ static int iwl_nic_init(struct iwl_trans *trans)
 
        iwl_op_mode_nic_config(trans->op_mode);
 
-#ifndef CONFIG_IWLWIFI_IDI
        /* Allocate the RX queue, or reset if it is already allocated */
        iwl_rx_init(trans);
-#endif
 
        /* Allocate or reset and init all Tx and Command queues */
        if (iwl_tx_init(trans))
@@ -896,6 +893,7 @@ static int iwl_set_hw_ready(struct iwl_trans *trans)
 static int iwl_prepare_card_hw(struct iwl_trans *trans)
 {
        int ret;
+       int t = 0;
 
        IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");
 
@@ -908,30 +906,25 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans)
        iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
                    CSR_HW_IF_CONFIG_REG_PREPARE);
 
-       ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG,
-                          ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
-                          CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
+       do {
+               ret = iwl_set_hw_ready(trans);
+               if (ret >= 0)
+                       return 0;
 
-       if (ret < 0)
-               return ret;
+               usleep_range(200, 1000);
+               t += 200;
+       } while (t < 150000);
 
-       /* HW should be ready by now, check again. */
-       ret = iwl_set_hw_ready(trans);
-       if (ret >= 0)
-               return 0;
        return ret;
 }
 
 /*
  * ucode
  */
-static int iwl_load_section(struct iwl_trans *trans, u8 section_num,
-                           const struct fw_desc *section)
+static int iwl_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr,
+                                  dma_addr_t phy_addr, u32 byte_cnt)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       dma_addr_t phy_addr = section->p_addr;
-       u32 byte_cnt = section->len;
-       u32 dst_addr = section->offset;
        int ret;
 
        trans_pcie->ucode_write_complete = false;
@@ -945,8 +938,8 @@ static int iwl_load_section(struct iwl_trans *trans, u8 section_num,
                           dst_addr);
 
        iwl_write_direct32(trans,
-               FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL),
-               phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);
+                          FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL),
+                          phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);
 
        iwl_write_direct32(trans,
                           FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL),
@@ -965,33 +958,64 @@ static int iwl_load_section(struct iwl_trans *trans, u8 section_num,
                           FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
                           FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
 
-       IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n",
-                    section_num);
        ret = wait_event_timeout(trans_pcie->ucode_write_waitq,
                                 trans_pcie->ucode_write_complete, 5 * HZ);
        if (!ret) {
-               IWL_ERR(trans, "Could not load the [%d] uCode section\n",
-                       section_num);
+               IWL_ERR(trans, "Failed to load firmware chunk!\n");
                return -ETIMEDOUT;
        }
 
        return 0;
 }
 
-static int iwl_load_given_ucode(struct iwl_trans *trans,
-                               const struct fw_img *image)
+static int iwl_load_section(struct iwl_trans *trans, u8 section_num,
+                           const struct fw_desc *section)
 {
+       u8 *v_addr;
+       dma_addr_t p_addr;
+       u32 offset;
        int ret = 0;
-               int i;
 
-               for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) {
-                       if (!image->sec[i].p_addr)
-                               break;
+       IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n",
+                    section_num);
+
+       v_addr = dma_alloc_coherent(trans->dev, PAGE_SIZE, &p_addr, GFP_KERNEL);
+       if (!v_addr)
+               return -ENOMEM;
+
+       for (offset = 0; offset < section->len; offset += PAGE_SIZE) {
+               u32 copy_size;
+
+               copy_size = min_t(u32, PAGE_SIZE, section->len - offset);
 
-                       ret = iwl_load_section(trans, i, &image->sec[i]);
-                       if (ret)
-                               return ret;
+               memcpy(v_addr, (u8 *)section->data + offset, copy_size);
+               ret = iwl_load_firmware_chunk(trans, section->offset + offset,
+                                             p_addr, copy_size);
+               if (ret) {
+                       IWL_ERR(trans,
+                               "Could not load the [%d] uCode section\n",
+                               section_num);
+                       break;
                }
+       }
+
+       dma_free_coherent(trans->dev, PAGE_SIZE, v_addr, p_addr);
+       return ret;
+}
+
+static int iwl_load_given_ucode(struct iwl_trans *trans,
+                               const struct fw_img *image)
+{
+       int i, ret = 0;
+
+       for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) {
+               if (!image->sec[i].data)
+                       break;
+
+               ret = iwl_load_section(trans, i, &image->sec[i]);
+               if (ret)
+                       return ret;
+       }
 
        /* Remove all resets to allow NIC to operate */
        iwl_write32(trans, CSR_RESET, 0);
@@ -1055,7 +1079,7 @@ static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask)
        iwl_write_prph(trans, SCD_TXFACT, mask);
 }
 
-static void iwl_tx_start(struct iwl_trans *trans)
+static void iwl_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        u32 a;
@@ -1068,6 +1092,10 @@ static void iwl_tx_start(struct iwl_trans *trans)
 
        trans_pcie->scd_base_addr =
                iwl_read_prph(trans, SCD_SRAM_BASE_ADDR);
+
+       WARN_ON(scd_base_addr != 0 &&
+               scd_base_addr != trans_pcie->scd_base_addr);
+
        a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND;
        /* reset conext data memory */
        for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND;
@@ -1113,10 +1141,10 @@ static void iwl_tx_start(struct iwl_trans *trans)
                            APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 }
 
-static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans)
+static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
 {
        iwl_reset_ict(trans);
-       iwl_tx_start(trans);
+       iwl_tx_start(trans, scd_addr);
 }
 
 /**
@@ -1184,9 +1212,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
         */
        if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) {
                iwl_trans_tx_stop(trans);
-#ifndef CONFIG_IWLWIFI_IDI
                iwl_trans_rx_stop(trans);
-#endif
+
                /* Power-down device's busmaster DMA clocks */
                iwl_write_prph(trans, APMG_CLK_DIS_REG,
                               APMG_CLK_VAL_DMA_CLK_RQT);
@@ -1223,6 +1250,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
        clear_bit(STATUS_INT_ENABLED, &trans_pcie->status);
        clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
        clear_bit(STATUS_TPOWER_PMI, &trans_pcie->status);
+       clear_bit(STATUS_RFKILL, &trans_pcie->status);
 }
 
 static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans)
@@ -1363,11 +1391,13 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
        dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
                                   DMA_BIDIRECTIONAL);
 
-       trace_iwlwifi_dev_tx(trans->dev,
+       trace_iwlwifi_dev_tx(trans->dev, skb,
                             &txq->tfds[txq->q.write_ptr],
                             sizeof(struct iwl_tfd),
                             &dev_cmd->hdr, firstlen,
                             skb->data + hdr_len, secondlen);
+       trace_iwlwifi_dev_tx_data(trans->dev, skb,
+                                 skb->data + hdr_len, secondlen);
 
        /* start timer if queue currently empty */
        if (txq->need_update && q->read_ptr == q->write_ptr &&
@@ -1457,14 +1487,16 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
        bool hw_rfkill;
        unsigned long flags;
 
+       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       iwl_disable_interrupts(trans);
+       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+
        iwl_apm_stop(trans);
 
        spin_lock_irqsave(&trans_pcie->irq_lock, flags);
        iwl_disable_interrupts(trans);
        spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
-       iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
-
        if (!op_mode_leaving) {
                /*
                 * Even if we stop the HW, we still want the RF kill
@@ -1490,14 +1522,13 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
        struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
        /* n_bd is usually 256 => n_bd - 1 = 0xff */
        int tfd_num = ssn & (txq->q.n_bd - 1);
-       int freed = 0;
 
        spin_lock(&txq->lock);
 
        if (txq->q.read_ptr != tfd_num) {
                IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n",
                                   txq_id, txq->q.read_ptr, tfd_num, ssn);
-               freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
+               iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
                if (iwl_queue_space(&txq->q) > txq->q.low_mark)
                        iwl_wake_queue(trans, txq);
        }
@@ -1552,9 +1583,8 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
        iwl_trans_pcie_tx_free(trans);
-#ifndef CONFIG_IWLWIFI_IDI
        iwl_trans_pcie_rx_free(trans);
-#endif
+
        if (trans_pcie->irq_requested == true) {
                free_irq(trans_pcie->irq, trans);
                iwl_free_isr_ict(trans);
@@ -1772,7 +1802,7 @@ void iwl_dump_csr(struct iwl_trans *trans)
 #define DEBUGFS_ADD_FILE(name, parent, mode) do {                      \
        if (!debugfs_create_file(#name, mode, parent, trans,            \
                                 &iwl_dbgfs_##name##_ops))              \
-               return -ENOMEM;                                         \
+               goto err;                                               \
 } while (0)
 
 /* file operation */
@@ -2036,6 +2066,10 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
        DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR);
        DEBUGFS_ADD_FILE(fw_restart, dir, S_IWUSR);
        return 0;
+
+err:
+       IWL_ERR(trans, "failed to create the trans debugfs entry\n");
+       return -ENOMEM;
 }
 #else
 static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
@@ -2177,7 +2211,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
        }
 
        /* Initialize the wait queue for commands */
-       init_waitqueue_head(&trans->wait_command_queue);
+       init_waitqueue_head(&trans_pcie->wait_command_queue);
        spin_lock_init(&trans->reg_lock);
 
        snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
This page took 0.047124 seconds and 5 git commands to generate.