Merge branch 'for-next-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/nab...
[deliverable/linux.git] / drivers / net / wireless / intel / iwlwifi / pcie / internal.h
index 73c95594eabe2c530d503fa51aedce05f0ffb8a9..dadafbdef9d946199b8be927a2478fea079150b1 100644 (file)
@@ -2,6 +2,7 @@
  *
  * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 Intel Deutschland GmbH
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
 #define RX_NUM_QUEUES 1
 #define RX_POST_REQ_ALLOC 2
 #define RX_CLAIM_REQ_ALLOC 8
-#define RX_POOL_SIZE ((RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC) * RX_NUM_QUEUES)
-#define RX_LOW_WATERMARK 8
+#define RX_PENDING_WATERMARK 16
 
 struct iwl_host_cmd;
 
 /*This file includes the declaration that are internal to the
  * trans_pcie layer */
 
+/**
+ * struct iwl_rx_mem_buffer
+ * @page_dma: bus address of rxb page
+ * @page: driver's pointer to the rxb page
+ * @vid: index of this rxb in the global table
+ */
 struct iwl_rx_mem_buffer {
        dma_addr_t page_dma;
        struct page *page;
+       u16 vid;
        struct list_head list;
 };
 
@@ -90,8 +97,12 @@ struct isr_statistics {
 
 /**
  * struct iwl_rxq - Rx queue
- * @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
+ * @id: queue index
+ * @bd: driver's pointer to buffer of receive buffer descriptors (rbd).
+ *     Address size is 32 bit in pre-9000 devices and 64 bit in 9000 devices.
  * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
+ * @ubd: driver's pointer to buffer of used receive buffer descriptors (rbd)
+ * @ubd_dma: physical address of buffer of used receive buffer descriptors (rbd)
  * @read: Shared index to newest available Rx buffer
  * @write: Shared index to oldest written Rx packet
  * @free_count: Number of pre-allocated buffers in rx_free
@@ -103,32 +114,34 @@ struct isr_statistics {
  * @rb_stts: driver's pointer to receive buffer status
  * @rb_stts_dma: bus address of receive buffer status
  * @lock:
- * @pool: initial pool of iwl_rx_mem_buffer for the queue
- * @queue: actual rx queue
+ * @queue: actual rx queue. Not used for multi-rx queue.
  *
  * NOTE:  rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
  */
 struct iwl_rxq {
-       __le32 *bd;
+       int id;
+       void *bd;
        dma_addr_t bd_dma;
+       __le32 *used_bd;
+       dma_addr_t used_bd_dma;
        u32 read;
        u32 write;
        u32 free_count;
        u32 used_count;
        u32 write_actual;
+       u32 queue_size;
        struct list_head rx_free;
        struct list_head rx_used;
        bool need_update;
        struct iwl_rb_status *rb_stts;
        dma_addr_t rb_stts_dma;
        spinlock_t lock;
-       struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE];
+       struct napi_struct napi;
        struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
 };
 
 /**
  * struct iwl_rb_allocator - Rx allocator
- * @pool: initial pool of allocator
  * @req_pending: number of requests the allcator had not processed yet
  * @req_ready: number of requests honored and ready for claiming
  * @rbd_allocated: RBDs with pages allocated and ready to be handled to
@@ -140,7 +153,6 @@ struct iwl_rxq {
  * @rx_alloc: work struct for background calls
  */
 struct iwl_rb_allocator {
-       struct iwl_rx_mem_buffer pool[RX_POOL_SIZE];
        atomic_t req_pending;
        atomic_t req_ready;
        struct list_head rbd_allocated;
@@ -280,6 +292,7 @@ struct iwl_txq {
        bool ampdu;
        bool block;
        unsigned long wd_timeout;
+       struct sk_buff_head overflow_q;
 };
 
 static inline dma_addr_t
@@ -297,6 +310,8 @@ struct iwl_tso_hdr_page {
 /**
  * struct iwl_trans_pcie - PCIe transport specific data
  * @rxq: all the RX queue data
+ * @rx_pool: initial pool of iwl_rx_mem_buffer for all the queues
+ * @global_table: table mapping received VID from hw to rxb
  * @rba: allocator for RX replenishing
  * @drv - pointer to iwl_drv
  * @trans: pointer to the generic transport area
@@ -321,15 +336,24 @@ struct iwl_tso_hdr_page {
  * @fw_mon_phys: physical address of the buffer for the firmware monitor
  * @fw_mon_page: points to the first page of the buffer for the firmware monitor
  * @fw_mon_size: size of the buffer for the firmware monitor
+ * @msix_entries: array of MSI-X entries
+ * @msix_enabled: true if managed to enable MSI-X
+ * @allocated_vector: the number of interrupt vector allocated by the OS
+ * @default_irq_num: default irq for non rx interrupt
+ * @fh_init_mask: initial unmasked fh causes
+ * @hw_init_mask: initial unmasked hw causes
+ * @fh_mask: current unmasked fh causes
+ * @hw_mask: current unmasked hw causes
  */
 struct iwl_trans_pcie {
-       struct iwl_rxq rxq;
+       struct iwl_rxq *rxq;
+       struct iwl_rx_mem_buffer rx_pool[RX_POOL_SIZE];
+       struct iwl_rx_mem_buffer *global_table[MQ_RX_TABLE_SIZE];
        struct iwl_rb_allocator rba;
        struct iwl_trans *trans;
        struct iwl_drv *drv;
 
        struct net_device napi_dev;
-       struct napi_struct napi;
 
        struct __percpu iwl_tso_hdr_page *tso_hdr_page;
 
@@ -359,6 +383,7 @@ struct iwl_trans_pcie {
        bool ucode_write_complete;
        wait_queue_head_t ucode_write_waitq;
        wait_queue_head_t wait_command_queue;
+       wait_queue_head_t d0i3_waitq;
 
        u8 cmd_queue;
        u8 cmd_fifo;
@@ -385,6 +410,15 @@ struct iwl_trans_pcie {
        dma_addr_t fw_mon_phys;
        struct page *fw_mon_page;
        u32 fw_mon_size;
+
+       struct msix_entry msix_entries[IWL_MAX_RX_HW_QUEUES];
+       bool msix_enabled;
+       u32 allocated_vector;
+       u32 default_irq_num;
+       u32 fh_init_mask;
+       u32 hw_init_mask;
+       u32 fh_mask;
+       u32 hw_mask;
 };
 
 static inline struct iwl_trans_pcie *
@@ -413,7 +447,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans);
 * RX
 ******************************************************/
 int iwl_pcie_rx_init(struct iwl_trans *trans);
+irqreturn_t iwl_pcie_msix_isr(int irq, void *data);
 irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id);
+irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id);
+irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id);
 int iwl_pcie_rx_stop(struct iwl_trans *trans);
 void iwl_pcie_rx_free(struct iwl_trans *trans);
 
@@ -468,15 +505,24 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans);
 ******************************************************/
 static inline void iwl_disable_interrupts(struct iwl_trans *trans)
 {
-       clear_bit(STATUS_INT_ENABLED, &trans->status);
-
-       /* disable interrupts from uCode/NIC to host */
-       iwl_write32(trans, CSR_INT_MASK, 0x00000000);
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
-       /* acknowledge/clear/reset any interrupts still pending
-        * from uCode or flow handler (Rx/Tx DMA) */
-       iwl_write32(trans, CSR_INT, 0xffffffff);
-       iwl_write32(trans, CSR_FH_INT_STATUS, 0xffffffff);
+       clear_bit(STATUS_INT_ENABLED, &trans->status);
+       if (!trans_pcie->msix_enabled) {
+               /* disable interrupts from uCode/NIC to host */
+               iwl_write32(trans, CSR_INT_MASK, 0x00000000);
+
+               /* acknowledge/clear/reset any interrupts still pending
+                * from uCode or flow handler (Rx/Tx DMA) */
+               iwl_write32(trans, CSR_INT, 0xffffffff);
+               iwl_write32(trans, CSR_FH_INT_STATUS, 0xffffffff);
+       } else {
+               /* disable all the interrupt we might use */
+               iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD,
+                           trans_pcie->fh_init_mask);
+               iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD,
+                           trans_pcie->hw_init_mask);
+       }
        IWL_DEBUG_ISR(trans, "Disabled interrupts\n");
 }
 
@@ -486,8 +532,37 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans)
 
        IWL_DEBUG_ISR(trans, "Enabling interrupts\n");
        set_bit(STATUS_INT_ENABLED, &trans->status);
-       trans_pcie->inta_mask = CSR_INI_SET_MASK;
-       iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
+       if (!trans_pcie->msix_enabled) {
+               trans_pcie->inta_mask = CSR_INI_SET_MASK;
+               iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
+       } else {
+               /*
+                * fh/hw_mask keeps all the unmasked causes.
+                * Unlike msi, in msix cause is enabled when it is unset.
+                */
+               trans_pcie->hw_mask = trans_pcie->hw_init_mask;
+               trans_pcie->fh_mask = trans_pcie->fh_init_mask;
+               iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD,
+                           ~trans_pcie->fh_mask);
+               iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD,
+                           ~trans_pcie->hw_mask);
+       }
+}
+
+static inline void iwl_enable_hw_int_msk_msix(struct iwl_trans *trans, u32 msk)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD, ~msk);
+       trans_pcie->hw_mask = msk;
+}
+
+static inline void iwl_enable_fh_int_msk_msix(struct iwl_trans *trans, u32 msk)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, ~msk);
+       trans_pcie->fh_mask = msk;
 }
 
 static inline void iwl_enable_fw_load_int(struct iwl_trans *trans)
@@ -495,8 +570,15 @@ static inline void iwl_enable_fw_load_int(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
        IWL_DEBUG_ISR(trans, "Enabling FW load interrupt\n");
-       trans_pcie->inta_mask = CSR_INT_BIT_FH_TX;
-       iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
+       if (!trans_pcie->msix_enabled) {
+               trans_pcie->inta_mask = CSR_INT_BIT_FH_TX;
+               iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
+       } else {
+               iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD,
+                           trans_pcie->hw_init_mask);
+               iwl_enable_fh_int_msk_msix(trans,
+                                          MSIX_FH_INT_CAUSES_D2S_CH0_NUM);
+       }
 }
 
 static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
@@ -504,8 +586,15 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
        IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
-       trans_pcie->inta_mask = CSR_INT_BIT_RF_KILL;
-       iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
+       if (!trans_pcie->msix_enabled) {
+               trans_pcie->inta_mask = CSR_INT_BIT_RF_KILL;
+               iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
+       } else {
+               iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD,
+                           trans_pcie->fh_init_mask);
+               iwl_enable_hw_int_msk_msix(trans,
+                                          MSIX_HW_INT_CAUSES_REG_RF_KILL);
+       }
 }
 
 static inline void iwl_wake_queue(struct iwl_trans *trans,
@@ -588,4 +677,7 @@ static inline int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)
 }
 #endif
 
+int iwl_pci_fw_exit_d0i3(struct iwl_trans *trans);
+int iwl_pci_fw_enter_d0i3(struct iwl_trans *trans);
+
 #endif /* __iwl_trans_int_pcie_h__ */
This page took 0.029944 seconds and 5 git commands to generate.