aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2009-10-22 14:20:59 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-11-06 16:54:37 -0500
commit54bc3a0d7a0c9a13da31183609c42cf7786138e1 (patch)
tree1e6e62d890d05d2dde478fa6b241d83de3ba63d8 /drivers/net/wireless/mwl8k.c
parent788838ebe8a4caca93a91982c7bbf393edf24c08 (diff)
mwl8k: allow for different receive descriptor formats
As the receive descriptor format is determined by the firmware running on the hardware and not by the hardware itself, and as these descriptor formats vary a bit between different firmware releases, abstract out the receive descriptor init/refill/process methods, and allow choosing between different formats at run time depending on the chip and firmware we're running on. Signed-off-by: Lennert Buytenhek <buytenh@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r--drivers/net/wireless/mwl8k.c180
1 files changed, 119 insertions, 61 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 49ae31b8b621..c9a4c1e1987f 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -80,10 +80,18 @@
80#define MWL8K_RX_QUEUES 1 80#define MWL8K_RX_QUEUES 1
81#define MWL8K_TX_QUEUES 4 81#define MWL8K_TX_QUEUES 4
82 82
83struct rxd_ops {
84 int rxd_size;
85 void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr);
86 void (*rxd_refill)(void *rxd, dma_addr_t addr, int len);
87 int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status);
88};
89
83struct mwl8k_device_info { 90struct mwl8k_device_info {
84 char *part_name; 91 char *part_name;
85 char *helper_image; 92 char *helper_image;
86 char *fw_image; 93 char *fw_image;
94 struct rxd_ops *rxd_ops;
87}; 95};
88 96
89struct mwl8k_rx_queue { 97struct mwl8k_rx_queue {
@@ -95,7 +103,7 @@ struct mwl8k_rx_queue {
95 /* refill descs here */ 103 /* refill descs here */
96 int tail; 104 int tail;
97 105
98 struct mwl8k_rx_desc *rxd; 106 void *rxd;
99 dma_addr_t rxd_dma; 107 dma_addr_t rxd_dma;
100 struct { 108 struct {
101 struct sk_buff *skb; 109 struct sk_buff *skb;
@@ -134,6 +142,7 @@ struct mwl8k_priv {
134 142
135 struct mwl8k_device_info *device_info; 143 struct mwl8k_device_info *device_info;
136 bool ap_fw; 144 bool ap_fw;
145 struct rxd_ops *rxd_ops;
137 146
138 /* firmware files and meta data */ 147 /* firmware files and meta data */
139 struct mwl8k_firmware fw; 148 struct mwl8k_firmware fw;
@@ -744,9 +753,7 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb)
744/* 753/*
745 * Packet reception. 754 * Packet reception.
746 */ 755 */
747#define MWL8K_RX_CTRL_OWNED_BY_HOST 0x02 756struct mwl8k_rxd_8687 {
748
749struct mwl8k_rx_desc {
750 __le16 pkt_len; 757 __le16 pkt_len;
751 __u8 link_quality; 758 __u8 link_quality;
752 __u8 noise_level; 759 __u8 noise_level;
@@ -763,16 +770,79 @@ struct mwl8k_rx_desc {
763 __u8 pad2[2]; 770 __u8 pad2[2];
764} __attribute__((packed)); 771} __attribute__((packed));
765 772
773#define MWL8K_8687_RATE_INFO_SHORTPRE 0x8000
774#define MWL8K_8687_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3)
775#define MWL8K_8687_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f)
776#define MWL8K_8687_RATE_INFO_40MHZ 0x0004
777#define MWL8K_8687_RATE_INFO_SHORTGI 0x0002
778#define MWL8K_8687_RATE_INFO_MCS_FORMAT 0x0001
779
780#define MWL8K_8687_RX_CTRL_OWNED_BY_HOST 0x02
781
782static void mwl8k_rxd_8687_init(void *_rxd, dma_addr_t next_dma_addr)
783{
784 struct mwl8k_rxd_8687 *rxd = _rxd;
785
786 rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr);
787 rxd->rx_ctrl = MWL8K_8687_RX_CTRL_OWNED_BY_HOST;
788}
789
790static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len)
791{
792 struct mwl8k_rxd_8687 *rxd = _rxd;
793
794 rxd->pkt_len = cpu_to_le16(len);
795 rxd->pkt_phys_addr = cpu_to_le32(addr);
796 wmb();
797 rxd->rx_ctrl = 0;
798}
799
800static int
801mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status)
802{
803 struct mwl8k_rxd_8687 *rxd = _rxd;
804 u16 rate_info;
805
806 if (!(rxd->rx_ctrl & MWL8K_8687_RX_CTRL_OWNED_BY_HOST))
807 return -1;
808 rmb();
809
810 rate_info = le16_to_cpu(rxd->rate_info);
811
812 memset(status, 0, sizeof(*status));
813
814 status->signal = -rxd->rssi;
815 status->noise = -rxd->noise_level;
816 status->qual = rxd->link_quality;
817 status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info);
818 status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info);
819
820 if (rate_info & MWL8K_8687_RATE_INFO_SHORTPRE)
821 status->flag |= RX_FLAG_SHORTPRE;
822 if (rate_info & MWL8K_8687_RATE_INFO_40MHZ)
823 status->flag |= RX_FLAG_40MHZ;
824 if (rate_info & MWL8K_8687_RATE_INFO_SHORTGI)
825 status->flag |= RX_FLAG_SHORT_GI;
826 if (rate_info & MWL8K_8687_RATE_INFO_MCS_FORMAT)
827 status->flag |= RX_FLAG_HT;
828
829 status->band = IEEE80211_BAND_2GHZ;
830 status->freq = ieee80211_channel_to_frequency(rxd->channel);
831
832 return le16_to_cpu(rxd->pkt_len);
833}
834
835static struct rxd_ops rxd_8687_ops = {
836 .rxd_size = sizeof(struct mwl8k_rxd_8687),
837 .rxd_init = mwl8k_rxd_8687_init,
838 .rxd_refill = mwl8k_rxd_8687_refill,
839 .rxd_process = mwl8k_rxd_8687_process,
840};
841
842
766#define MWL8K_RX_DESCS 256 843#define MWL8K_RX_DESCS 256
767#define MWL8K_RX_MAXSZ 3800 844#define MWL8K_RX_MAXSZ 3800
768 845
769#define RATE_INFO_SHORTPRE 0x8000
770#define RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3)
771#define RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f)
772#define RATE_INFO_40MHZ 0x0004
773#define RATE_INFO_SHORTGI 0x0002
774#define RATE_INFO_MCS_FORMAT 0x0001
775
776static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index) 846static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
777{ 847{
778 struct mwl8k_priv *priv = hw->priv; 848 struct mwl8k_priv *priv = hw->priv;
@@ -784,7 +854,7 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
784 rxq->head = 0; 854 rxq->head = 0;
785 rxq->tail = 0; 855 rxq->tail = 0;
786 856
787 size = MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc); 857 size = MWL8K_RX_DESCS * priv->rxd_ops->rxd_size;
788 858
789 rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma); 859 rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma);
790 if (rxq->rxd == NULL) { 860 if (rxq->rxd == NULL) {
@@ -804,15 +874,20 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
804 memset(rxq->buf, 0, MWL8K_RX_DESCS * sizeof(*rxq->buf)); 874 memset(rxq->buf, 0, MWL8K_RX_DESCS * sizeof(*rxq->buf));
805 875
806 for (i = 0; i < MWL8K_RX_DESCS; i++) { 876 for (i = 0; i < MWL8K_RX_DESCS; i++) {
807 struct mwl8k_rx_desc *rx_desc; 877 int desc_size;
878 void *rxd;
808 int nexti; 879 int nexti;
880 dma_addr_t next_dma_addr;
881
882 desc_size = priv->rxd_ops->rxd_size;
883 rxd = rxq->rxd + (i * priv->rxd_ops->rxd_size);
809 884
810 rx_desc = rxq->rxd + i; 885 nexti = i + 1;
811 nexti = (i + 1) % MWL8K_RX_DESCS; 886 if (nexti == MWL8K_RX_DESCS)
887 nexti = 0;
888 next_dma_addr = rxq->rxd_dma + (nexti * desc_size);
812 889
813 rx_desc->next_rxd_phys_addr = 890 priv->rxd_ops->rxd_init(rxd, next_dma_addr);
814 cpu_to_le32(rxq->rxd_dma + nexti * sizeof(*rx_desc));
815 rx_desc->rx_ctrl = MWL8K_RX_CTRL_OWNED_BY_HOST;
816 } 891 }
817 892
818 return 0; 893 return 0;
@@ -829,25 +904,24 @@ static int rxq_refill(struct ieee80211_hw *hw, int index, int limit)
829 struct sk_buff *skb; 904 struct sk_buff *skb;
830 dma_addr_t addr; 905 dma_addr_t addr;
831 int rx; 906 int rx;
907 void *rxd;
832 908
833 skb = dev_alloc_skb(MWL8K_RX_MAXSZ); 909 skb = dev_alloc_skb(MWL8K_RX_MAXSZ);
834 if (skb == NULL) 910 if (skb == NULL)
835 break; 911 break;
836 912
837 rxq->rxd_count++;
838
839 rx = rxq->tail;
840 rxq->tail = (rx + 1) % MWL8K_RX_DESCS;
841
842 addr = pci_map_single(priv->pdev, skb->data, 913 addr = pci_map_single(priv->pdev, skb->data,
843 MWL8K_RX_MAXSZ, DMA_FROM_DEVICE); 914 MWL8K_RX_MAXSZ, DMA_FROM_DEVICE);
844 915
845 rxq->rxd[rx].pkt_len = cpu_to_le16(MWL8K_RX_MAXSZ); 916 rxq->rxd_count++;
846 rxq->rxd[rx].pkt_phys_addr = cpu_to_le32(addr); 917 rx = rxq->tail++;
918 if (rxq->tail == MWL8K_RX_DESCS)
919 rxq->tail = 0;
847 rxq->buf[rx].skb = skb; 920 rxq->buf[rx].skb = skb;
848 pci_unmap_addr_set(&rxq->buf[rx], dma, addr); 921 pci_unmap_addr_set(&rxq->buf[rx], dma, addr);
849 wmb(); 922
850 rxq->rxd[rx].rx_ctrl = 0; 923 rxd = rxq->rxd + (rx * priv->rxd_ops->rxd_size);
924 priv->rxd_ops->rxd_refill(rxd, addr, MWL8K_RX_MAXSZ);
851 925
852 refilled++; 926 refilled++;
853 } 927 }
@@ -878,7 +952,7 @@ static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index)
878 rxq->buf = NULL; 952 rxq->buf = NULL;
879 953
880 pci_free_consistent(priv->pdev, 954 pci_free_consistent(priv->pdev,
881 MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc), 955 MWL8K_RX_DESCS * priv->rxd_ops->rxd_size,
882 rxq->rxd, rxq->rxd_dma); 956 rxq->rxd, rxq->rxd_dma);
883 rxq->rxd = NULL; 957 rxq->rxd = NULL;
884} 958}
@@ -922,20 +996,21 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
922 996
923 processed = 0; 997 processed = 0;
924 while (rxq->rxd_count && limit--) { 998 while (rxq->rxd_count && limit--) {
925 struct mwl8k_rx_desc *rx_desc;
926 struct sk_buff *skb; 999 struct sk_buff *skb;
1000 void *rxd;
1001 int pkt_len;
927 struct ieee80211_rx_status status; 1002 struct ieee80211_rx_status status;
928 struct ieee80211_hdr *wh;
929 u16 rate_info;
930
931 rx_desc = rxq->rxd + rxq->head;
932 if (!(rx_desc->rx_ctrl & MWL8K_RX_CTRL_OWNED_BY_HOST))
933 break;
934 rmb();
935 1003
936 skb = rxq->buf[rxq->head].skb; 1004 skb = rxq->buf[rxq->head].skb;
937 if (skb == NULL) 1005 if (skb == NULL)
938 break; 1006 break;
1007
1008 rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size);
1009
1010 pkt_len = priv->rxd_ops->rxd_process(rxd, &status);
1011 if (pkt_len < 0)
1012 break;
1013
939 rxq->buf[rxq->head].skb = NULL; 1014 rxq->buf[rxq->head].skb = NULL;
940 1015
941 pci_unmap_single(priv->pdev, 1016 pci_unmap_single(priv->pdev,
@@ -943,42 +1018,23 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
943 MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); 1018 MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
944 pci_unmap_addr_set(&rxq->buf[rxq->head], dma, 0); 1019 pci_unmap_addr_set(&rxq->buf[rxq->head], dma, 0);
945 1020
946 rxq->head = (rxq->head + 1) % MWL8K_RX_DESCS; 1021 rxq->head++;
1022 if (rxq->head == MWL8K_RX_DESCS)
1023 rxq->head = 0;
1024
947 rxq->rxd_count--; 1025 rxq->rxd_count--;
948 1026
949 skb_put(skb, le16_to_cpu(rx_desc->pkt_len)); 1027 skb_put(skb, pkt_len);
950 mwl8k_remove_dma_header(skb); 1028 mwl8k_remove_dma_header(skb);
951 1029
952 wh = (struct ieee80211_hdr *)skb->data;
953
954 /* 1030 /*
955 * Check for a pending join operation. Save a 1031 * Check for a pending join operation. Save a
956 * copy of the beacon and schedule a tasklet to 1032 * copy of the beacon and schedule a tasklet to
957 * send a FINALIZE_JOIN command to the firmware. 1033 * send a FINALIZE_JOIN command to the firmware.
958 */ 1034 */
959 if (mwl8k_capture_bssid(priv, wh)) 1035 if (mwl8k_capture_bssid(priv, (void *)skb->data))
960 mwl8k_save_beacon(hw, skb); 1036 mwl8k_save_beacon(hw, skb);
961 1037
962 rate_info = le16_to_cpu(rx_desc->rate_info);
963
964 memset(&status, 0, sizeof(status));
965 status.mactime = 0;
966 status.signal = -rx_desc->rssi;
967 status.noise = -rx_desc->noise_level;
968 status.qual = rx_desc->link_quality;
969 status.antenna = RATE_INFO_ANTSELECT(rate_info);
970 status.rate_idx = RATE_INFO_RATEID(rate_info);
971 status.flag = 0;
972 if (rate_info & RATE_INFO_SHORTPRE)
973 status.flag |= RX_FLAG_SHORTPRE;
974 if (rate_info & RATE_INFO_40MHZ)
975 status.flag |= RX_FLAG_40MHZ;
976 if (rate_info & RATE_INFO_SHORTGI)
977 status.flag |= RX_FLAG_SHORT_GI;
978 if (rate_info & RATE_INFO_MCS_FORMAT)
979 status.flag |= RX_FLAG_HT;
980 status.band = IEEE80211_BAND_2GHZ;
981 status.freq = ieee80211_channel_to_frequency(rx_desc->channel);
982 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); 1038 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
983 ieee80211_rx_irqsafe(hw, skb); 1039 ieee80211_rx_irqsafe(hw, skb);
984 1040
@@ -2959,6 +3015,7 @@ static struct mwl8k_device_info di_8687 = {
2959 .part_name = "88w8687", 3015 .part_name = "88w8687",
2960 .helper_image = "mwl8k/helper_8687.fw", 3016 .helper_image = "mwl8k/helper_8687.fw",
2961 .fw_image = "mwl8k/fmimage_8687.fw", 3017 .fw_image = "mwl8k/fmimage_8687.fw",
3018 .rxd_ops = &rxd_8687_ops,
2962}; 3019};
2963 3020
2964static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { 3021static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
@@ -3014,6 +3071,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
3014 priv->hw = hw; 3071 priv->hw = hw;
3015 priv->pdev = pdev; 3072 priv->pdev = pdev;
3016 priv->device_info = (void *)id->driver_data; 3073 priv->device_info = (void *)id->driver_data;
3074 priv->rxd_ops = priv->device_info->rxd_ops;
3017 priv->sniffer_enabled = false; 3075 priv->sniffer_enabled = false;
3018 priv->wmm_enabled = false; 3076 priv->wmm_enabled = false;
3019 priv->pending_tx_pkts = 0; 3077 priv->pending_tx_pkts = 0;