aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2008-11-07 12:58:40 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-11-21 11:07:23 -0500
commit4ddbb7d060061e584cb2137f4c7e41e502a560b4 (patch)
treecb6a78a622df2660411786e73c2bbd33b187d173 /drivers/net/wireless
parent8d86422a83d79e3d3241cf0f269fca0c2640bcee (diff)
iwlwifi: revamp tx scheduler byte count tables handling
This moves byte count tables to tx domain removing completely ambivalent shared data. Changes handling of allocation byte count tables and keep warm consistent memory Moves general tx scheduler definitions from iwl-4956-hw.h to iwl-fh.h Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-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 94ae1a84f786..fb0fd773960f 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 017e5ea58de6..c43cf2f072cd 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 8f9edc79e254..c6595e8b4405 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 e81000cdcbc5..ee3613db3132 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 c1ed02e206bb..a9000f14e704 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 ec474db4d107..8bd4d087d4e2 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 1dca9d36f8c2..1ae7a11e80d4 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 55590a55198d..c36096069bfd 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 153754277e07..2c5f919dd847 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 7d8b4e2d5094..725f62fce7a5 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