aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-hw.h90
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c35
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000-hw.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c45
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c46
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fh.h65
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c48
10 files changed, 129 insertions, 244 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index 94ae1a84f78..fb0fd773960 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -819,64 +819,6 @@ enum {
819#define IWL49_NUM_QUEUES 16 819#define IWL49_NUM_QUEUES 16
820#define IWL49_NUM_AMPDU_QUEUES 8 820#define IWL49_NUM_AMPDU_QUEUES 8
821 821
822#define IWL_TX_DMA_MASK (DMA_BIT_MASK(36) & ~0x3)
823#define IWL_NUM_OF_TBS 20
824
825static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
826{
827 return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
828}
829/**
830 * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
831 *
832 * This structure contains dma address and length of transmission address
833 *
834 * @lo: low [31:0] portion of the dma address of TX buffer
835 * every even is unaligned on 16 bit boundary
836 * @hi_n_len 0-3 [35:32] portion of dma
837 * 4-16 length of the tx buffer
838 */
839struct iwl_tfd_tb {
840 __le32 lo;
841 __le16 hi_n_len;
842} __attribute__((packed));
843
844/**
845 * struct iwl_tfd
846 *
847 * Transmit Frame Descriptor (TFD)
848 *
849 * @ __reserved1[3] reserved
850 * @ num_tbs 0-5 number of active tbs
851 * 6-7 padding (not used)
852 * @ tbs[20] transmit frame buffer descriptors
853 * @ __pad padding
854 *
855 * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
856 * Both driver and device share these circular buffers, each of which must be
857 * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes
858 *
859 * Driver must indicate the physical address of the base of each
860 * circular buffer via the FH_MEM_CBBC_QUEUE registers.
861 *
862 * Each TFD contains pointer/size information for up to 20 data buffers
863 * in host DRAM. These buffers collectively contain the (one) frame described
864 * by the TFD. Each buffer must be a single contiguous block of memory within
865 * itself, but buffers may be scattered in host DRAM. Each buffer has max size
866 * of (4K - 4). The concatenates all of a TFD's buffers into a single
867 * Tx frame, up to 8 KBytes in size.
868 *
869 * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
870 *
871 * Bit fields in the control dword (val0):
872 */
873struct iwl_tfd {
874 u8 __reserved1[3];
875 u8 num_tbs;
876 struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS];
877 __le32 __pad;
878} __attribute__ ((packed));
879
880 822
881/** 823/**
882 * struct iwl4965_schedq_bc_tbl 824 * struct iwl4965_schedq_bc_tbl
@@ -896,37 +838,9 @@ struct iwl_tfd {
896 * padding puts each byte count table on a 1024-byte boundary; 838 * padding puts each byte count table on a 1024-byte boundary;
897 * 4965 assumes tables are separated by 1024 bytes. 839 * 4965 assumes tables are separated by 1024 bytes.
898 */ 840 */
899struct iwl4965_schedq_bc_tbl { 841struct iwl4965_scd_bc_tbl {
900 __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; 842 __le16 tfd_offset[TFD_QUEUE_BC_SIZE];
901 u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)]; 843 u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)];
902} __attribute__ ((packed)); 844} __attribute__ ((packed));
903 845
904 846#endif /* !__iwl_4965_hw_h__ */
905/**
906 * struct iwl4965_shared - handshake area for Tx and Rx
907 *
908 * For convenience in allocating memory, this structure combines 2 areas of
909 * DRAM which must be shared between driver and 4965. These do not need to
910 * be combined, if better allocation would result from keeping them separate:
911 *
912 * 1) The Tx byte count tables occupy 1024 bytes each (16 KBytes total for
913 * 16 queues). Driver uses SCD_DRAM_BASE_ADDR to tell 4965 where to find
914 * the first of these tables. 4965 assumes tables are 1024 bytes apart.
915 *
916 * 2) The Rx status (val0 and val1) occupies only 8 bytes. Driver uses
917 * FH_RSCSR_CHNL0_STTS_WPTR_REG to tell 4965 where to find this area.
918 * Driver reads val0 to determine the latest Receive Buffer Descriptor (RBD)
919 * that has been filled by the 4965.
920 *
921 * Bit fields val0:
922 * 31-12: Not used
923 * 11- 0: Index of last filled Rx buffer descriptor (4965 writes, driver reads)
924 *
925 * Bit fields val1:
926 * 31- 0: Not used
927 */
928struct iwl4965_shared {
929 struct iwl4965_schedq_bc_tbl queues_bc_tbls[IWL49_NUM_QUEUES];
930} __attribute__ ((packed));
931
932#endif /* __iwl4965_4965_hw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 017e5ea58de..c43cf2f072c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -715,8 +715,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
715 715
716 /* Tel 4965 where to find Tx byte count tables */ 716 /* Tel 4965 where to find Tx byte count tables */
717 iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR, 717 iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
718 (priv->shared_phys + 718 priv->scd_bc_tbls.dma >> 10);
719 offsetof(struct iwl4965_shared, queues_bc_tbls)) >> 10);
720 719
721 /* Disable chain mode for all queues */ 720 /* Disable chain mode for all queues */
722 iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0); 721 iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
@@ -804,6 +803,8 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
804 } 803 }
805 804
806 priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; 805 priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
806 priv->hw_params.scd_bc_tbls_size =
807 IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl);
807 priv->hw_params.max_stations = IWL4965_STATION_COUNT; 808 priv->hw_params.max_stations = IWL4965_STATION_COUNT;
808 priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; 809 priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
809 priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; 810 priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
@@ -1631,28 +1632,6 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1631} 1632}
1632#endif 1633#endif
1633 1634
1634static int iwl4965_alloc_shared_mem(struct iwl_priv *priv)
1635{
1636 priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
1637 sizeof(struct iwl4965_shared),
1638 &priv->shared_phys);
1639 if (!priv->shared_virt)
1640 return -ENOMEM;
1641
1642 memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared));
1643
1644 return 0;
1645}
1646
1647static void iwl4965_free_shared_mem(struct iwl_priv *priv)
1648{
1649 if (priv->shared_virt)
1650 pci_free_consistent(priv->pci_dev,
1651 sizeof(struct iwl4965_shared),
1652 priv->shared_virt,
1653 priv->shared_phys);
1654}
1655
1656/** 1635/**
1657 * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array 1636 * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
1658 */ 1637 */
@@ -1660,7 +1639,7 @@ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
1660 struct iwl_tx_queue *txq, 1639 struct iwl_tx_queue *txq,
1661 u16 byte_cnt) 1640 u16 byte_cnt)
1662{ 1641{
1663 struct iwl4965_shared *shared_data = priv->shared_virt; 1642 struct iwl4965_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
1664 int txq_id = txq->q.id; 1643 int txq_id = txq->q.id;
1665 int write_ptr = txq->q.write_ptr; 1644 int write_ptr = txq->q.write_ptr;
1666 int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; 1645 int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
@@ -1670,11 +1649,11 @@ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
1670 1649
1671 bc_ent = cpu_to_le16(len & 0xFFF); 1650 bc_ent = cpu_to_le16(len & 0xFFF);
1672 /* Set up byte count within first 256 entries */ 1651 /* Set up byte count within first 256 entries */
1673 shared_data->queues_bc_tbls[txq_id].tfd_offset[write_ptr] = bc_ent; 1652 scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
1674 1653
1675 /* If within first 64 entries, duplicate at end */ 1654 /* If within first 64 entries, duplicate at end */
1676 if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) 1655 if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
1677 shared_data->queues_bc_tbls[txq_id]. 1656 scd_bc_tbl[txq_id].
1678 tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; 1657 tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
1679} 1658}
1680 1659
@@ -2296,8 +2275,6 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
2296 2275
2297static struct iwl_lib_ops iwl4965_lib = { 2276static struct iwl_lib_ops iwl4965_lib = {
2298 .set_hw_params = iwl4965_hw_set_hw_params, 2277 .set_hw_params = iwl4965_hw_set_hw_params,
2299 .alloc_shared_mem = iwl4965_alloc_shared_mem,
2300 .free_shared_mem = iwl4965_free_shared_mem,
2301 .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, 2278 .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
2302 .txq_set_sched = iwl4965_txq_set_sched, 2279 .txq_set_sched = iwl4965_txq_set_sched,
2303 .txq_agg_enable = iwl4965_txq_agg_enable, 2280 .txq_agg_enable = iwl4965_txq_agg_enable,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index 8f9edc79e25..c6595e8b440 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -90,16 +90,10 @@
90 * @tfd_offset 0-12 - tx command byte count 90 * @tfd_offset 0-12 - tx command byte count
91 * 12-16 - station index 91 * 12-16 - station index
92 */ 92 */
93struct iwl5000_schedq_bc_tbl { 93struct iwl5000_scd_bc_tbl {
94 __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; 94 __le16 tfd_offset[TFD_QUEUE_BC_SIZE];
95} __attribute__ ((packed)); 95} __attribute__ ((packed));
96 96
97/**
98 * struct iwl5000_shared
99 */
100struct iwl5000_shared {
101 struct iwl5000_schedq_bc_tbl queues_bc_tbls[IWL50_NUM_QUEUES];
102} __attribute__ ((packed));
103 97
104#endif /* __iwl_5000_hw_h__ */ 98#endif /* __iwl_5000_hw_h__ */
105 99
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index e81000cdcbc..ee3613db313 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -721,11 +721,9 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
721 iwl_write_targ_mem(priv, a, 0); 721 iwl_write_targ_mem(priv, a, 0);
722 722
723 iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, 723 iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR,
724 (priv->shared_phys + 724 priv->scd_bc_tbls.dma >> 10);
725 offsetof(struct iwl5000_shared, queues_bc_tbls)) >> 10);
726 iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, 725 iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL,
727 IWL50_SCD_QUEUECHAIN_SEL_ALL( 726 IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num));
728 priv->hw_params.max_txq_num));
729 iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); 727 iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0);
730 728
731 /* initiate the queues */ 729 /* initiate the queues */
@@ -788,6 +786,8 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
788 } 786 }
789 787
790 priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; 788 priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
789 priv->hw_params.scd_bc_tbls_size =
790 IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl);
791 priv->hw_params.max_stations = IWL5000_STATION_COUNT; 791 priv->hw_params.max_stations = IWL5000_STATION_COUNT;
792 priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; 792 priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
793 priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; 793 priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE;
@@ -853,28 +853,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
853 return 0; 853 return 0;
854} 854}
855 855
856static int iwl5000_alloc_shared_mem(struct iwl_priv *priv)
857{
858 priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
859 sizeof(struct iwl5000_shared),
860 &priv->shared_phys);
861 if (!priv->shared_virt)
862 return -ENOMEM;
863
864 memset(priv->shared_virt, 0, sizeof(struct iwl5000_shared));
865
866 return 0;
867}
868
869static void iwl5000_free_shared_mem(struct iwl_priv *priv)
870{
871 if (priv->shared_virt)
872 pci_free_consistent(priv->pci_dev,
873 sizeof(struct iwl5000_shared),
874 priv->shared_virt,
875 priv->shared_phys);
876}
877
878/** 856/**
879 * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array 857 * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
880 */ 858 */
@@ -882,7 +860,7 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
882 struct iwl_tx_queue *txq, 860 struct iwl_tx_queue *txq,
883 u16 byte_cnt) 861 u16 byte_cnt)
884{ 862{
885 struct iwl5000_shared *shared_data = priv->shared_virt; 863 struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
886 int write_ptr = txq->q.write_ptr; 864 int write_ptr = txq->q.write_ptr;
887 int txq_id = txq->q.id; 865 int txq_id = txq->q.id;
888 u8 sec_ctl = 0; 866 u8 sec_ctl = 0;
@@ -911,17 +889,17 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
911 889
912 bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); 890 bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
913 891
914 shared_data->queues_bc_tbls[txq_id].tfd_offset[write_ptr] = bc_ent; 892 scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
915 893
916 if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) 894 if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
917 shared_data->queues_bc_tbls[txq_id]. 895 scd_bc_tbl[txq_id].
918 tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; 896 tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
919} 897}
920 898
921static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, 899static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
922 struct iwl_tx_queue *txq) 900 struct iwl_tx_queue *txq)
923{ 901{
924 struct iwl5000_shared *shared_data = priv->shared_virt; 902 struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
925 int txq_id = txq->q.id; 903 int txq_id = txq->q.id;
926 int read_ptr = txq->q.read_ptr; 904 int read_ptr = txq->q.read_ptr;
927 u8 sta_id = 0; 905 u8 sta_id = 0;
@@ -933,11 +911,10 @@ static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
933 sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; 911 sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
934 912
935 bc_ent = cpu_to_le16(1 | (sta_id << 12)); 913 bc_ent = cpu_to_le16(1 | (sta_id << 12));
936 shared_data->queues_bc_tbls[txq_id]. 914 scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
937 tfd_offset[read_ptr] = bc_ent;
938 915
939 if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) 916 if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
940 shared_data->queues_bc_tbls[txq_id]. 917 scd_bc_tbl[txq_id].
941 tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; 918 tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
942} 919}
943 920
@@ -1450,8 +1427,6 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
1450 1427
1451static struct iwl_lib_ops iwl5000_lib = { 1428static struct iwl_lib_ops iwl5000_lib = {
1452 .set_hw_params = iwl5000_hw_set_hw_params, 1429 .set_hw_params = iwl5000_hw_set_hw_params,
1453 .alloc_shared_mem = iwl5000_alloc_shared_mem,
1454 .free_shared_mem = iwl5000_free_shared_mem,
1455 .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, 1430 .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
1456 .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, 1431 .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
1457 .txq_set_sched = iwl5000_txq_set_sched, 1432 .txq_set_sched = iwl5000_txq_set_sched,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index c1ed02e206b..a9000f14e70 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2196,8 +2196,6 @@ static void __iwl_down(struct iwl_priv *priv)
2196 priv->cfg->ops->lib->apm_ops.stop(priv); 2196 priv->cfg->ops->lib->apm_ops.stop(priv);
2197 else 2197 else
2198 priv->cfg->ops->lib->apm_ops.reset(priv); 2198 priv->cfg->ops->lib->apm_ops.reset(priv);
2199 priv->cfg->ops->lib->free_shared_mem(priv);
2200
2201 exit: 2199 exit:
2202 memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); 2200 memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
2203 2201
@@ -2250,12 +2248,6 @@ static int __iwl_up(struct iwl_priv *priv)
2250 2248
2251 iwl_write32(priv, CSR_INT, 0xFFFFFFFF); 2249 iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
2252 2250
2253 ret = priv->cfg->ops->lib->alloc_shared_mem(priv);
2254 if (ret) {
2255 IWL_ERROR("Unable to allocate shared memory\n");
2256 return ret;
2257 }
2258
2259 ret = iwl_hw_nic_init(priv); 2251 ret = iwl_hw_nic_init(priv);
2260 if (ret) { 2252 if (ret) {
2261 IWL_ERROR("Unable to init nic\n"); 2253 IWL_ERROR("Unable to init nic\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index ec474db4d10..8bd4d087d4e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -189,52 +189,6 @@ void iwl_hw_detect(struct iwl_priv *priv)
189} 189}
190EXPORT_SYMBOL(iwl_hw_detect); 190EXPORT_SYMBOL(iwl_hw_detect);
191 191
192/* Tell nic where to find the "keep warm" buffer */
193int iwl_kw_init(struct iwl_priv *priv)
194{
195 unsigned long flags;
196 int ret;
197
198 spin_lock_irqsave(&priv->lock, flags);
199 ret = iwl_grab_nic_access(priv);
200 if (ret)
201 goto out;
202
203 iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG,
204 priv->kw.dma_addr >> 4);
205 iwl_release_nic_access(priv);
206out:
207 spin_unlock_irqrestore(&priv->lock, flags);
208 return ret;
209}
210
211int iwl_kw_alloc(struct iwl_priv *priv)
212{
213 struct pci_dev *dev = priv->pci_dev;
214 struct iwl_kw *kw = &priv->kw;
215
216 kw->size = IWL_KW_SIZE;
217 kw->v_addr = pci_alloc_consistent(dev, kw->size, &kw->dma_addr);
218 if (!kw->v_addr)
219 return -ENOMEM;
220
221 return 0;
222}
223
224/**
225 * iwl_kw_free - Free the "keep warm" buffer
226 */
227void iwl_kw_free(struct iwl_priv *priv)
228{
229 struct pci_dev *dev = priv->pci_dev;
230 struct iwl_kw *kw = &priv->kw;
231
232 if (kw->v_addr) {
233 pci_free_consistent(dev, kw->size, kw->v_addr, kw->dma_addr);
234 memset(kw, 0, sizeof(*kw));
235 }
236}
237
238int iwl_hw_nic_init(struct iwl_priv *priv) 192int iwl_hw_nic_init(struct iwl_priv *priv)
239{ 193{
240 unsigned long flags; 194 unsigned long flags;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 1dca9d36f8c..1ae7a11e80d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -102,9 +102,6 @@ struct iwl_hcmd_utils_ops {
102struct iwl_lib_ops { 102struct iwl_lib_ops {
103 /* set hw dependent parameters */ 103 /* set hw dependent parameters */
104 int (*set_hw_params)(struct iwl_priv *priv); 104 int (*set_hw_params)(struct iwl_priv *priv);
105 /* ucode shared memory */
106 int (*alloc_shared_mem)(struct iwl_priv *priv);
107 void (*free_shared_mem)(struct iwl_priv *priv);
108 /* Handling TX */ 105 /* Handling TX */
109 void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv, 106 void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv,
110 struct iwl_tx_queue *txq, 107 struct iwl_tx_queue *txq,
@@ -197,10 +194,6 @@ int iwl_setup_mac(struct iwl_priv *priv);
197int iwl_set_hw_params(struct iwl_priv *priv); 194int iwl_set_hw_params(struct iwl_priv *priv);
198int iwl_init_drv(struct iwl_priv *priv); 195int iwl_init_drv(struct iwl_priv *priv);
199void iwl_uninit_drv(struct iwl_priv *priv); 196void iwl_uninit_drv(struct iwl_priv *priv);
200/* "keep warm" functions */
201int iwl_kw_init(struct iwl_priv *priv);
202int iwl_kw_alloc(struct iwl_priv *priv);
203void iwl_kw_free(struct iwl_priv *priv);
204 197
205/***************************************************** 198/*****************************************************
206* RX 199* RX
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 55590a55198..c36096069bf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -507,6 +507,7 @@ struct iwl_sensitivity_ranges {
507/** 507/**
508 * struct iwl_hw_params 508 * struct iwl_hw_params
509 * @max_txq_num: Max # Tx queues supported 509 * @max_txq_num: Max # Tx queues supported
510 * @scd_bc_tbls_size: size of scheduler byte count tables
510 * @tx/rx_chains_num: Number of TX/RX chains 511 * @tx/rx_chains_num: Number of TX/RX chains
511 * @valid_tx/rx_ant: usable antennas 512 * @valid_tx/rx_ant: usable antennas
512 * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) 513 * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
@@ -524,6 +525,7 @@ struct iwl_sensitivity_ranges {
524 */ 525 */
525struct iwl_hw_params { 526struct iwl_hw_params {
526 u16 max_txq_num; 527 u16 max_txq_num;
528 u16 scd_bc_tbls_size;
527 u8 tx_chains_num; 529 u8 tx_chains_num;
528 u8 rx_chains_num; 530 u8 rx_chains_num;
529 u8 valid_tx_ant; 531 u8 valid_tx_ant;
@@ -605,13 +607,9 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
605struct iwl_priv; 607struct iwl_priv;
606 608
607 609
608/* Structures, enum, and defines specific to the 4965 */ 610struct iwl_dma_ptr {
609 611 dma_addr_t dma;
610#define IWL_KW_SIZE 0x1000 /*4k */ 612 void *addr;
611
612struct iwl_kw {
613 dma_addr_t dma_addr;
614 void *v_addr;
615 size_t size; 613 size_t size;
616}; 614};
617 615
@@ -907,7 +905,9 @@ struct iwl_priv {
907 struct iwl_rx_queue rxq; 905 struct iwl_rx_queue rxq;
908 struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES]; 906 struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES];
909 unsigned long txq_ctx_active_msk; 907 unsigned long txq_ctx_active_msk;
910 struct iwl_kw kw; /* keep warm address */ 908 struct iwl_dma_ptr kw; /* keep warm address */
909 struct iwl_dma_ptr scd_bc_tbls;
910
911 u32 scd_base_addr; /* scheduler sram base address */ 911 u32 scd_base_addr; /* scheduler sram base address */
912 912
913 unsigned long status; 913 unsigned long status;
@@ -967,10 +967,7 @@ struct iwl_priv {
967 struct ieee80211_vif *vif; 967 struct ieee80211_vif *vif;
968 968
969 struct iwl_hw_params hw_params; 969 struct iwl_hw_params hw_params;
970 /* driver/uCode shared Tx Byte Counts */ 970
971 void *shared_virt;
972 /* Physical Pointer to Tx Byte Counts */
973 dma_addr_t shared_phys;
974 971
975 /* Current association information needed to configure the 972 /* Current association information needed to configure the
976 * hardware */ 973 * hardware */
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index 153754277e0..2c5f919dd84 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -420,4 +420,69 @@ struct iwl_rb_status {
420 __le16 finished_fr_nam; 420 __le16 finished_fr_nam;
421} __attribute__ ((packed)); 421} __attribute__ ((packed));
422 422
423
424
425#define IWL_TX_DMA_MASK DMA_BIT_MASK(36)
426
427#define IWL_NUM_OF_TBS 20
428
429static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
430{
431 return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
432}
433/**
434 * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
435 *
436 * This structure contains dma address and length of transmission address
437 *
438 * @lo: low [31:0] portion of the dma address of TX buffer
439 * every even is unaligned on 16 bit boundary
440 * @hi_n_len 0-3 [35:32] portion of dma
441 * 4-16 length of the tx buffer
442 */
443struct iwl_tfd_tb {
444 __le32 lo;
445 __le16 hi_n_len;
446} __attribute__((packed));
447
448/**
449 * struct iwl_tfd
450 *
451 * Transmit Frame Descriptor (TFD)
452 *
453 * @ __reserved1[3] reserved
454 * @ num_tbs 0-5 number of active tbs
455 * 6-7 padding (not used)
456 * @ tbs[20] transmit frame buffer descriptors
457 * @ __pad padding
458 *
459 * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
460 * Both driver and device share these circular buffers, each of which must be
461 * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes
462 *
463 * Driver must indicate the physical address of the base of each
464 * circular buffer via the FH_MEM_CBBC_QUEUE registers.
465 *
466 * Each TFD contains pointer/size information for up to 20 data buffers
467 * in host DRAM. These buffers collectively contain the (one) frame described
468 * by the TFD. Each buffer must be a single contiguous block of memory within
469 * itself, but buffers may be scattered in host DRAM. Each buffer has max size
470 * of (4K - 4). The concatenates all of a TFD's buffers into a single
471 * Tx frame, up to 8 KBytes in size.
472 *
473 * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
474 *
475 * Bit fields in the control dword (val0):
476 */
477struct iwl_tfd {
478 u8 __reserved1[3];
479 u8 num_tbs;
480 struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS];
481 __le32 __pad;
482} __attribute__ ((packed));
483
484
485/* Keep Warm Size */
486#define IWL_KW_SIZE 0x1000 /*4k */
487
423#endif /* !__iwl_fh_h__ */ 488#endif /* !__iwl_fh_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 7d8b4e2d509..725f62fce7a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -56,6 +56,26 @@ static const u16 default_tid_to_tx_fifo[] = {
56 IWL_TX_FIFO_AC3 56 IWL_TX_FIFO_AC3
57}; 57};
58 58
59static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv,
60 struct iwl_dma_ptr *ptr, size_t size)
61{
62 ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma);
63 if (!ptr->addr)
64 return -ENOMEM;
65 ptr->size = size;
66 return 0;
67}
68
69static inline void iwl_free_dma_ptr(struct iwl_priv *priv,
70 struct iwl_dma_ptr *ptr)
71{
72 if (unlikely(!ptr->addr))
73 return;
74
75 pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma);
76 memset(ptr, 0, sizeof(*ptr));
77}
78
59static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) 79static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
60{ 80{
61 struct iwl_tfd_tb *tb = &tfd->tbs[idx]; 81 struct iwl_tfd_tb *tb = &tfd->tbs[idx];
@@ -517,8 +537,9 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
517 else 537 else
518 iwl_tx_queue_free(priv, txq_id); 538 iwl_tx_queue_free(priv, txq_id);
519 539
520 /* Keep-warm buffer */ 540 iwl_free_dma_ptr(priv, &priv->kw);
521 iwl_kw_free(priv); 541
542 iwl_free_dma_ptr(priv, &priv->scd_bc_tbls);
522} 543}
523EXPORT_SYMBOL(iwl_hw_txq_ctx_free); 544EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
524 545
@@ -535,13 +556,17 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
535 int txq_id, slots_num; 556 int txq_id, slots_num;
536 unsigned long flags; 557 unsigned long flags;
537 558
538 iwl_kw_free(priv);
539
540 /* Free all tx/cmd queues and keep-warm buffer */ 559 /* Free all tx/cmd queues and keep-warm buffer */
541 iwl_hw_txq_ctx_free(priv); 560 iwl_hw_txq_ctx_free(priv);
542 561
562 ret = iwl_alloc_dma_ptr(priv, &priv->scd_bc_tbls,
563 priv->hw_params.scd_bc_tbls_size);
564 if (ret) {
565 IWL_ERROR("Scheduler BC Table allocation failed\n");
566 goto error_bc_tbls;
567 }
543 /* Alloc keep-warm buffer */ 568 /* Alloc keep-warm buffer */
544 ret = iwl_kw_alloc(priv); 569 ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
545 if (ret) { 570 if (ret) {
546 IWL_ERROR("Keep Warm allocation failed\n"); 571 IWL_ERROR("Keep Warm allocation failed\n");
547 goto error_kw; 572 goto error_kw;
@@ -556,16 +581,13 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
556 /* Turn off all Tx DMA fifos */ 581 /* Turn off all Tx DMA fifos */
557 priv->cfg->ops->lib->txq_set_sched(priv, 0); 582 priv->cfg->ops->lib->txq_set_sched(priv, 0);
558 583
584 /* Tell NIC where to find the "keep warm" buffer */
585 iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
586
559 iwl_release_nic_access(priv); 587 iwl_release_nic_access(priv);
560 spin_unlock_irqrestore(&priv->lock, flags); 588 spin_unlock_irqrestore(&priv->lock, flags);
561 589
562 590
563 /* Tell nic where to find the keep-warm buffer */
564 ret = iwl_kw_init(priv);
565 if (ret) {
566 IWL_ERROR("kw_init failed\n");
567 goto error_reset;
568 }
569 591
570 /* Alloc and init all Tx queues, including the command queue (#4) */ 592 /* Alloc and init all Tx queues, including the command queue (#4) */
571 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { 593 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
@@ -584,8 +606,10 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
584 error: 606 error:
585 iwl_hw_txq_ctx_free(priv); 607 iwl_hw_txq_ctx_free(priv);
586 error_reset: 608 error_reset:
587 iwl_kw_free(priv); 609 iwl_free_dma_ptr(priv, &priv->kw);
588 error_kw: 610 error_kw:
611 iwl_free_dma_ptr(priv, &priv->scd_bc_tbls);
612 error_bc_tbls:
589 return ret; 613 return ret;
590} 614}
591 615