diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 90 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 35 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000-hw.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 45 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 46 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-fh.h | 65 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 48 |
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 | |||
825 | static 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 | */ | ||
839 | struct 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 | */ | ||
873 | struct 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 | */ |
899 | struct iwl4965_schedq_bc_tbl { | 841 | struct 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 | */ | ||
928 | struct 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 | ||
1634 | static 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 | |||
1647 | static 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 | ||
2297 | static struct iwl_lib_ops iwl4965_lib = { | 2276 | static 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 | */ |
93 | struct iwl5000_schedq_bc_tbl { | 93 | struct 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 | */ | ||
100 | struct 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 | ||
856 | static 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 | |||
869 | static 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 | ||
921 | static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | 899 | static 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 | ||
1451 | static struct iwl_lib_ops iwl5000_lib = { | 1428 | static 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 | } |
190 | EXPORT_SYMBOL(iwl_hw_detect); | 190 | EXPORT_SYMBOL(iwl_hw_detect); |
191 | 191 | ||
192 | /* Tell nic where to find the "keep warm" buffer */ | ||
193 | int 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); | ||
206 | out: | ||
207 | spin_unlock_irqrestore(&priv->lock, flags); | ||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | int 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 | */ | ||
227 | void 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 | |||
238 | int iwl_hw_nic_init(struct iwl_priv *priv) | 192 | int 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 { | |||
102 | struct iwl_lib_ops { | 102 | struct 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); | |||
197 | int iwl_set_hw_params(struct iwl_priv *priv); | 194 | int iwl_set_hw_params(struct iwl_priv *priv); |
198 | int iwl_init_drv(struct iwl_priv *priv); | 195 | int iwl_init_drv(struct iwl_priv *priv); |
199 | void iwl_uninit_drv(struct iwl_priv *priv); | 196 | void iwl_uninit_drv(struct iwl_priv *priv); |
200 | /* "keep warm" functions */ | ||
201 | int iwl_kw_init(struct iwl_priv *priv); | ||
202 | int iwl_kw_alloc(struct iwl_priv *priv); | ||
203 | void 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 | */ |
525 | struct iwl_hw_params { | 526 | struct 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) | |||
605 | struct iwl_priv; | 607 | struct iwl_priv; |
606 | 608 | ||
607 | 609 | ||
608 | /* Structures, enum, and defines specific to the 4965 */ | 610 | struct iwl_dma_ptr { |
609 | 611 | dma_addr_t dma; | |
610 | #define IWL_KW_SIZE 0x1000 /*4k */ | 612 | void *addr; |
611 | |||
612 | struct 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 | |||
429 | static 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 | */ | ||
443 | struct 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 | */ | ||
477 | struct 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 | ||
59 | static 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 | |||
69 | static 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 | |||
59 | static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) | 79 | static 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 | } |
523 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | 544 | EXPORT_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 | ||