aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2009-12-28 15:09:11 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-12-28 15:09:11 -0500
commitea1e4b842049fcc4741096538114871a74859314 (patch)
treec2336ab480ac0fd62e0dc41b391d99c97158dc9c /drivers/net/wireless/mwl8k.c
parentb6ce5c33001b1dc83e6a1a6f30c5dccccea651b6 (diff)
parent92c6f8d849178582fc527aaf1e51dd37a74767d3 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r--drivers/net/wireless/mwl8k.c327
1 files changed, 163 insertions, 164 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 0cb5ecc822a8..59d49159cf2a 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -84,7 +84,8 @@ struct rxd_ops {
84 int rxd_size; 84 int rxd_size;
85 void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr); 85 void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr);
86 void (*rxd_refill)(void *rxd, dma_addr_t addr, int len); 86 void (*rxd_refill)(void *rxd, dma_addr_t addr, int len);
87 int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status); 87 int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status,
88 __le16 *qos);
88}; 89};
89 90
90struct mwl8k_device_info { 91struct mwl8k_device_info {
@@ -184,7 +185,7 @@ struct mwl8k_priv {
184 /* PHY parameters */ 185 /* PHY parameters */
185 struct ieee80211_supported_band band; 186 struct ieee80211_supported_band band;
186 struct ieee80211_channel channels[14]; 187 struct ieee80211_channel channels[14];
187 struct ieee80211_rate rates[13]; 188 struct ieee80211_rate rates[14];
188 189
189 bool radio_on; 190 bool radio_on;
190 bool radio_short_preamble; 191 bool radio_short_preamble;
@@ -220,15 +221,6 @@ struct mwl8k_vif {
220 u8 bssid[ETH_ALEN]; 221 u8 bssid[ETH_ALEN];
221 u8 mac_addr[ETH_ALEN]; 222 u8 mac_addr[ETH_ALEN];
222 223
223 /*
224 * Subset of supported legacy rates.
225 * Intersection of AP and STA supported rates.
226 */
227 struct ieee80211_rate legacy_rates[13];
228
229 /* number of supported legacy rates */
230 u8 legacy_nrates;
231
232 /* Index into station database.Returned by update_sta_db call */ 224 /* Index into station database.Returned by update_sta_db call */
233 u8 peer_id; 225 u8 peer_id;
234 226
@@ -266,6 +258,11 @@ static const struct ieee80211_rate mwl8k_rates[] = {
266 { .bitrate = 360, .hw_value = 72, }, 258 { .bitrate = 360, .hw_value = 72, },
267 { .bitrate = 480, .hw_value = 96, }, 259 { .bitrate = 480, .hw_value = 96, },
268 { .bitrate = 540, .hw_value = 108, }, 260 { .bitrate = 540, .hw_value = 108, },
261 { .bitrate = 720, .hw_value = 144, },
262};
263
264static const u8 mwl8k_rateids[12] = {
265 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108,
269}; 266};
270 267
271/* Set or get info from Firmware */ 268/* Set or get info from Firmware */
@@ -574,7 +571,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
574 "helper image\n", pci_name(priv->pdev)); 571 "helper image\n", pci_name(priv->pdev));
575 return rc; 572 return rc;
576 } 573 }
577 msleep(1); 574 msleep(5);
578 575
579 rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); 576 rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
580 } else { 577 } else {
@@ -591,9 +588,8 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
591 iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR); 588 iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR);
592 else 589 else
593 iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); 590 iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR);
594 msleep(1);
595 591
596 loops = 200000; 592 loops = 500000;
597 do { 593 do {
598 u32 ready_code; 594 u32 ready_code;
599 595
@@ -633,9 +629,6 @@ struct ewc_ht_info {
633/* Peer Entry flags - used to define the type of the peer node */ 629/* Peer Entry flags - used to define the type of the peer node */
634#define MWL8K_PEER_TYPE_ACCESSPOINT 2 630#define MWL8K_PEER_TYPE_ACCESSPOINT 2
635 631
636#define MWL8K_IEEE_LEGACY_DATA_RATES 13
637#define MWL8K_MCS_BITMAP_SIZE 16
638
639struct peer_capability_info { 632struct peer_capability_info {
640 /* Peer type - AP vs. STA. */ 633 /* Peer type - AP vs. STA. */
641 __u8 peer_type; 634 __u8 peer_type;
@@ -652,10 +645,10 @@ struct peer_capability_info {
652 struct ewc_ht_info ewc_info; 645 struct ewc_ht_info ewc_info;
653 646
654 /* Legacy rate table. Intersection of our rates and peer rates. */ 647 /* Legacy rate table. Intersection of our rates and peer rates. */
655 __u8 legacy_rates[MWL8K_IEEE_LEGACY_DATA_RATES]; 648 __u8 legacy_rates[12];
656 649
657 /* HT rate table. Intersection of our rates and peer rates. */ 650 /* HT rate table. Intersection of our rates and peer rates. */
658 __u8 ht_rates[MWL8K_MCS_BITMAP_SIZE]; 651 __u8 ht_rates[16];
659 __u8 pad[16]; 652 __u8 pad[16];
660 653
661 /* If set, interoperability mode, no proprietary extensions. */ 654 /* If set, interoperability mode, no proprietary extensions. */
@@ -706,55 +699,64 @@ static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len)
706struct mwl8k_dma_data { 699struct mwl8k_dma_data {
707 __le16 fwlen; 700 __le16 fwlen;
708 struct ieee80211_hdr wh; 701 struct ieee80211_hdr wh;
702 char data[0];
709} __attribute__((packed)); 703} __attribute__((packed));
710 704
711/* Routines to add/remove DMA header from skb. */ 705/* Routines to add/remove DMA header from skb. */
712static inline void mwl8k_remove_dma_header(struct sk_buff *skb) 706static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos)
713{ 707{
714 struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)skb->data; 708 struct mwl8k_dma_data *tr;
715 void *dst, *src = &tr->wh; 709 int hdrlen;
716 int hdrlen = ieee80211_hdrlen(tr->wh.frame_control);
717 u16 space = sizeof(struct mwl8k_dma_data) - hdrlen;
718 710
719 dst = (void *)tr + space; 711 tr = (struct mwl8k_dma_data *)skb->data;
720 if (dst != src) { 712 hdrlen = ieee80211_hdrlen(tr->wh.frame_control);
721 memmove(dst, src, hdrlen); 713
722 skb_pull(skb, space); 714 if (hdrlen != sizeof(tr->wh)) {
715 if (ieee80211_is_data_qos(tr->wh.frame_control)) {
716 memmove(tr->data - hdrlen, &tr->wh, hdrlen - 2);
717 *((__le16 *)(tr->data - 2)) = qos;
718 } else {
719 memmove(tr->data - hdrlen, &tr->wh, hdrlen);
720 }
723 } 721 }
722
723 if (hdrlen != sizeof(*tr))
724 skb_pull(skb, sizeof(*tr) - hdrlen);
724} 725}
725 726
726static inline void mwl8k_add_dma_header(struct sk_buff *skb) 727static inline void mwl8k_add_dma_header(struct sk_buff *skb)
727{ 728{
728 struct ieee80211_hdr *wh; 729 struct ieee80211_hdr *wh;
729 u32 hdrlen, pktlen; 730 int hdrlen;
730 struct mwl8k_dma_data *tr; 731 struct mwl8k_dma_data *tr;
731 732
733 /*
734 * Add a firmware DMA header; the firmware requires that we
735 * present a 2-byte payload length followed by a 4-address
736 * header (without QoS field), followed (optionally) by any
737 * WEP/ExtIV header (but only filled in for CCMP).
738 */
732 wh = (struct ieee80211_hdr *)skb->data; 739 wh = (struct ieee80211_hdr *)skb->data;
740
733 hdrlen = ieee80211_hdrlen(wh->frame_control); 741 hdrlen = ieee80211_hdrlen(wh->frame_control);
734 pktlen = skb->len; 742 if (hdrlen != sizeof(*tr))
743 skb_push(skb, sizeof(*tr) - hdrlen);
735 744
736 /* 745 if (ieee80211_is_data_qos(wh->frame_control))
737 * Copy up/down the 802.11 header; the firmware requires 746 hdrlen -= 2;
738 * we present a 2-byte payload length followed by a
739 * 4-address header (w/o QoS), followed (optionally) by
740 * any WEP/ExtIV header (but only filled in for CCMP).
741 */
742 if (hdrlen != sizeof(struct mwl8k_dma_data))
743 skb_push(skb, sizeof(struct mwl8k_dma_data) - hdrlen);
744 747
745 tr = (struct mwl8k_dma_data *)skb->data; 748 tr = (struct mwl8k_dma_data *)skb->data;
746 if (wh != &tr->wh) 749 if (wh != &tr->wh)
747 memmove(&tr->wh, wh, hdrlen); 750 memmove(&tr->wh, wh, hdrlen);
748 751 if (hdrlen != sizeof(tr->wh))
749 /* Clear addr4 */ 752 memset(((void *)&tr->wh) + hdrlen, 0, sizeof(tr->wh) - hdrlen);
750 memset(tr->wh.addr4, 0, ETH_ALEN);
751 753
752 /* 754 /*
753 * Firmware length is the length of the fully formed "802.11 755 * Firmware length is the length of the fully formed "802.11
754 * payload". That is, everything except for the 802.11 header. 756 * payload". That is, everything except for the 802.11 header.
755 * This includes all crypto material including the MIC. 757 * This includes all crypto material including the MIC.
756 */ 758 */
757 tr->fwlen = cpu_to_le16(pktlen - hdrlen); 759 tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr));
758} 760}
759 761
760 762
@@ -779,6 +781,10 @@ struct mwl8k_rxd_8366 {
779 __u8 rx_ctrl; 781 __u8 rx_ctrl;
780} __attribute__((packed)); 782} __attribute__((packed));
781 783
784#define MWL8K_8366_RATE_INFO_MCS_FORMAT 0x80
785#define MWL8K_8366_RATE_INFO_40MHZ 0x40
786#define MWL8K_8366_RATE_INFO_RATEID(x) ((x) & 0x3f)
787
782#define MWL8K_8366_RX_CTRL_OWNED_BY_HOST 0x80 788#define MWL8K_8366_RX_CTRL_OWNED_BY_HOST 0x80
783 789
784static void mwl8k_rxd_8366_init(void *_rxd, dma_addr_t next_dma_addr) 790static void mwl8k_rxd_8366_init(void *_rxd, dma_addr_t next_dma_addr)
@@ -800,7 +806,8 @@ static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len)
800} 806}
801 807
802static int 808static int
803mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status) 809mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status,
810 __le16 *qos)
804{ 811{
805 struct mwl8k_rxd_8366 *rxd = _rxd; 812 struct mwl8k_rxd_8366 *rxd = _rxd;
806 813
@@ -813,9 +820,11 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status)
813 status->signal = -rxd->rssi; 820 status->signal = -rxd->rssi;
814 status->noise = -rxd->noise_floor; 821 status->noise = -rxd->noise_floor;
815 822
816 if (rxd->rate & 0x80) { 823 if (rxd->rate & MWL8K_8366_RATE_INFO_MCS_FORMAT) {
817 status->flag |= RX_FLAG_HT; 824 status->flag |= RX_FLAG_HT;
818 status->rate_idx = rxd->rate & 0x7f; 825 if (rxd->rate & MWL8K_8366_RATE_INFO_40MHZ)
826 status->flag |= RX_FLAG_40MHZ;
827 status->rate_idx = MWL8K_8366_RATE_INFO_RATEID(rxd->rate);
819 } else { 828 } else {
820 int i; 829 int i;
821 830
@@ -830,6 +839,8 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status)
830 status->band = IEEE80211_BAND_2GHZ; 839 status->band = IEEE80211_BAND_2GHZ;
831 status->freq = ieee80211_channel_to_frequency(rxd->channel); 840 status->freq = ieee80211_channel_to_frequency(rxd->channel);
832 841
842 *qos = rxd->qos_control;
843
833 return le16_to_cpu(rxd->pkt_len); 844 return le16_to_cpu(rxd->pkt_len);
834} 845}
835 846
@@ -888,7 +899,8 @@ static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len)
888} 899}
889 900
890static int 901static int
891mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status) 902mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status,
903 __le16 *qos)
892{ 904{
893 struct mwl8k_rxd_8687 *rxd = _rxd; 905 struct mwl8k_rxd_8687 *rxd = _rxd;
894 u16 rate_info; 906 u16 rate_info;
@@ -903,7 +915,6 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status)
903 915
904 status->signal = -rxd->rssi; 916 status->signal = -rxd->rssi;
905 status->noise = -rxd->noise_level; 917 status->noise = -rxd->noise_level;
906 status->qual = rxd->link_quality;
907 status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info); 918 status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info);
908 status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info); 919 status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info);
909 920
@@ -919,6 +930,8 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status)
919 status->band = IEEE80211_BAND_2GHZ; 930 status->band = IEEE80211_BAND_2GHZ;
920 status->freq = ieee80211_channel_to_frequency(rxd->channel); 931 status->freq = ieee80211_channel_to_frequency(rxd->channel);
921 932
933 *qos = rxd->qos_control;
934
922 return le16_to_cpu(rxd->pkt_len); 935 return le16_to_cpu(rxd->pkt_len);
923} 936}
924 937
@@ -1090,6 +1103,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
1090 void *rxd; 1103 void *rxd;
1091 int pkt_len; 1104 int pkt_len;
1092 struct ieee80211_rx_status status; 1105 struct ieee80211_rx_status status;
1106 __le16 qos;
1093 1107
1094 skb = rxq->buf[rxq->head].skb; 1108 skb = rxq->buf[rxq->head].skb;
1095 if (skb == NULL) 1109 if (skb == NULL)
@@ -1097,7 +1111,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
1097 1111
1098 rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size); 1112 rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size);
1099 1113
1100 pkt_len = priv->rxd_ops->rxd_process(rxd, &status); 1114 pkt_len = priv->rxd_ops->rxd_process(rxd, &status, &qos);
1101 if (pkt_len < 0) 1115 if (pkt_len < 0)
1102 break; 1116 break;
1103 1117
@@ -1115,7 +1129,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
1115 rxq->rxd_count--; 1129 rxq->rxd_count--;
1116 1130
1117 skb_put(skb, pkt_len); 1131 skb_put(skb, pkt_len);
1118 mwl8k_remove_dma_header(skb); 1132 mwl8k_remove_dma_header(skb, qos);
1119 1133
1120 /* 1134 /*
1121 * Check for a pending join operation. Save a 1135 * Check for a pending join operation. Save a
@@ -1221,99 +1235,106 @@ static inline void mwl8k_tx_start(struct mwl8k_priv *priv)
1221 ioread32(priv->regs + MWL8K_HIU_INT_CODE); 1235 ioread32(priv->regs + MWL8K_HIU_INT_CODE);
1222} 1236}
1223 1237
1224struct mwl8k_txq_info { 1238static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw)
1225 u32 fw_owned;
1226 u32 drv_owned;
1227 u32 unused;
1228 u32 len;
1229 u32 head;
1230 u32 tail;
1231};
1232
1233static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
1234 struct mwl8k_txq_info *txinfo)
1235{ 1239{
1236 int count, desc, status; 1240 struct mwl8k_priv *priv = hw->priv;
1237 struct mwl8k_tx_queue *txq; 1241 int i;
1238 struct mwl8k_tx_desc *tx_desc;
1239 int ndescs = 0;
1240 1242
1241 memset(txinfo, 0, MWL8K_TX_QUEUES * sizeof(struct mwl8k_txq_info)); 1243 for (i = 0; i < MWL8K_TX_QUEUES; i++) {
1244 struct mwl8k_tx_queue *txq = priv->txq + i;
1245 int fw_owned = 0;
1246 int drv_owned = 0;
1247 int unused = 0;
1248 int desc;
1242 1249
1243 for (count = 0; count < MWL8K_TX_QUEUES; count++) {
1244 txq = priv->txq + count;
1245 txinfo[count].len = txq->stats.len;
1246 txinfo[count].head = txq->head;
1247 txinfo[count].tail = txq->tail;
1248 for (desc = 0; desc < MWL8K_TX_DESCS; desc++) { 1250 for (desc = 0; desc < MWL8K_TX_DESCS; desc++) {
1249 tx_desc = txq->txd + desc; 1251 struct mwl8k_tx_desc *tx_desc = txq->txd + desc;
1250 status = le32_to_cpu(tx_desc->status); 1252 u32 status;
1251 1253
1254 status = le32_to_cpu(tx_desc->status);
1252 if (status & MWL8K_TXD_STATUS_FW_OWNED) 1255 if (status & MWL8K_TXD_STATUS_FW_OWNED)
1253 txinfo[count].fw_owned++; 1256 fw_owned++;
1254 else 1257 else
1255 txinfo[count].drv_owned++; 1258 drv_owned++;
1256 1259
1257 if (tx_desc->pkt_len == 0) 1260 if (tx_desc->pkt_len == 0)
1258 txinfo[count].unused++; 1261 unused++;
1259 } 1262 }
1260 }
1261 1263
1262 return ndescs; 1264 printk(KERN_ERR "%s: txq[%d] len=%d head=%d tail=%d "
1265 "fw_owned=%d drv_owned=%d unused=%d\n",
1266 wiphy_name(hw->wiphy), i,
1267 txq->stats.len, txq->head, txq->tail,
1268 fw_owned, drv_owned, unused);
1269 }
1263} 1270}
1264 1271
1265/* 1272/*
1266 * Must be called with priv->fw_mutex held and tx queues stopped. 1273 * Must be called with priv->fw_mutex held and tx queues stopped.
1267 */ 1274 */
1275#define MWL8K_TX_WAIT_TIMEOUT_MS 1000
1276
1268static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) 1277static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
1269{ 1278{
1270 struct mwl8k_priv *priv = hw->priv; 1279 struct mwl8k_priv *priv = hw->priv;
1271 DECLARE_COMPLETION_ONSTACK(tx_wait); 1280 DECLARE_COMPLETION_ONSTACK(tx_wait);
1272 u32 count; 1281 int retry;
1273 unsigned long timeout; 1282 int rc;
1274 1283
1275 might_sleep(); 1284 might_sleep();
1276 1285
1286 /*
1287 * The TX queues are stopped at this point, so this test
1288 * doesn't need to take ->tx_lock.
1289 */
1290 if (!priv->pending_tx_pkts)
1291 return 0;
1292
1293 retry = 0;
1294 rc = 0;
1295
1277 spin_lock_bh(&priv->tx_lock); 1296 spin_lock_bh(&priv->tx_lock);
1278 count = priv->pending_tx_pkts; 1297 priv->tx_wait = &tx_wait;
1279 if (count) 1298 while (!rc) {
1280 priv->tx_wait = &tx_wait; 1299 int oldcount;
1281 spin_unlock_bh(&priv->tx_lock); 1300 unsigned long timeout;
1282 1301
1283 if (count) { 1302 oldcount = priv->pending_tx_pkts;
1284 struct mwl8k_txq_info txinfo[MWL8K_TX_QUEUES];
1285 int index;
1286 int newcount;
1287 1303
1304 spin_unlock_bh(&priv->tx_lock);
1288 timeout = wait_for_completion_timeout(&tx_wait, 1305 timeout = wait_for_completion_timeout(&tx_wait,
1289 msecs_to_jiffies(5000)); 1306 msecs_to_jiffies(MWL8K_TX_WAIT_TIMEOUT_MS));
1290 if (timeout)
1291 return 0;
1292
1293 spin_lock_bh(&priv->tx_lock); 1307 spin_lock_bh(&priv->tx_lock);
1294 priv->tx_wait = NULL;
1295 newcount = priv->pending_tx_pkts;
1296 mwl8k_scan_tx_ring(priv, txinfo);
1297 spin_unlock_bh(&priv->tx_lock);
1298 1308
1299 printk(KERN_ERR "%s(%u) TIMEDOUT:5000ms Pend:%u-->%u\n", 1309 if (timeout) {
1300 __func__, __LINE__, count, newcount); 1310 WARN_ON(priv->pending_tx_pkts);
1311 if (retry) {
1312 printk(KERN_NOTICE "%s: tx rings drained\n",
1313 wiphy_name(hw->wiphy));
1314 }
1315 break;
1316 }
1301 1317
1302 for (index = 0; index < MWL8K_TX_QUEUES; index++) 1318 if (priv->pending_tx_pkts < oldcount) {
1303 printk(KERN_ERR "TXQ:%u L:%u H:%u T:%u FW:%u " 1319 printk(KERN_NOTICE "%s: timeout waiting for tx "
1304 "DRV:%u U:%u\n", 1320 "rings to drain (%d -> %d pkts), retrying\n",
1305 index, 1321 wiphy_name(hw->wiphy), oldcount,
1306 txinfo[index].len, 1322 priv->pending_tx_pkts);
1307 txinfo[index].head, 1323 retry = 1;
1308 txinfo[index].tail, 1324 continue;
1309 txinfo[index].fw_owned, 1325 }
1310 txinfo[index].drv_owned,
1311 txinfo[index].unused);
1312 1326
1313 return -ETIMEDOUT; 1327 priv->tx_wait = NULL;
1328
1329 printk(KERN_ERR "%s: tx rings stuck for %d ms\n",
1330 wiphy_name(hw->wiphy), MWL8K_TX_WAIT_TIMEOUT_MS);
1331 mwl8k_dump_tx_rings(hw);
1332
1333 rc = -ETIMEDOUT;
1314 } 1334 }
1335 spin_unlock_bh(&priv->tx_lock);
1315 1336
1316 return 0; 1337 return rc;
1317} 1338}
1318 1339
1319#define MWL8K_TXD_SUCCESS(status) \ 1340#define MWL8K_TXD_SUCCESS(status) \
@@ -1361,7 +1382,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
1361 BUG_ON(skb == NULL); 1382 BUG_ON(skb == NULL);
1362 pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); 1383 pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE);
1363 1384
1364 mwl8k_remove_dma_header(skb); 1385 mwl8k_remove_dma_header(skb, tx_desc->qos_control);
1365 1386
1366 /* Mark descriptor as unused */ 1387 /* Mark descriptor as unused */
1367 tx_desc->pkt_phys_addr = 0; 1388 tx_desc->pkt_phys_addr = 0;
@@ -1563,8 +1584,8 @@ static void mwl8k_fw_unlock(struct ieee80211_hw *hw)
1563 * Command processing. 1584 * Command processing.
1564 */ 1585 */
1565 1586
1566/* Timeout firmware commands after 2000ms */ 1587/* Timeout firmware commands after 10s */
1567#define MWL8K_CMD_TIMEOUT_MS 2000 1588#define MWL8K_CMD_TIMEOUT_MS 10000
1568 1589
1569static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) 1590static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
1570{ 1591{
@@ -1615,12 +1636,21 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
1615 MWL8K_CMD_TIMEOUT_MS); 1636 MWL8K_CMD_TIMEOUT_MS);
1616 rc = -ETIMEDOUT; 1637 rc = -ETIMEDOUT;
1617 } else { 1638 } else {
1639 int ms;
1640
1641 ms = MWL8K_CMD_TIMEOUT_MS - jiffies_to_msecs(timeout);
1642
1618 rc = cmd->result ? -EINVAL : 0; 1643 rc = cmd->result ? -EINVAL : 0;
1619 if (rc) 1644 if (rc)
1620 printk(KERN_ERR "%s: Command %s error 0x%x\n", 1645 printk(KERN_ERR "%s: Command %s error 0x%x\n",
1621 wiphy_name(hw->wiphy), 1646 wiphy_name(hw->wiphy),
1622 mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), 1647 mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
1623 le16_to_cpu(cmd->result)); 1648 le16_to_cpu(cmd->result));
1649 else if (ms > 2000)
1650 printk(KERN_NOTICE "%s: Command %s took %d ms\n",
1651 wiphy_name(hw->wiphy),
1652 mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
1653 ms);
1624 } 1654 }
1625 1655
1626 return rc; 1656 return rc;
@@ -2439,8 +2469,6 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
2439/* 2469/*
2440 * CMD_FINALIZE_JOIN. 2470 * CMD_FINALIZE_JOIN.
2441 */ 2471 */
2442
2443/* FJ beacon buffer size is compiled into the firmware. */
2444#define MWL8K_FJ_BEACON_MAXLEN 128 2472#define MWL8K_FJ_BEACON_MAXLEN 128
2445 2473
2446struct mwl8k_cmd_finalize_join { 2474struct mwl8k_cmd_finalize_join {
@@ -2450,17 +2478,13 @@ struct mwl8k_cmd_finalize_join {
2450} __attribute__((packed)); 2478} __attribute__((packed));
2451 2479
2452static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, 2480static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
2453 __u16 framelen, __u16 dtim) 2481 int framelen, int dtim)
2454{ 2482{
2455 struct mwl8k_cmd_finalize_join *cmd; 2483 struct mwl8k_cmd_finalize_join *cmd;
2456 struct ieee80211_mgmt *payload = frame; 2484 struct ieee80211_mgmt *payload = frame;
2457 u16 hdrlen; 2485 int payload_len;
2458 u32 payload_len;
2459 int rc; 2486 int rc;
2460 2487
2461 if (frame == NULL)
2462 return -EINVAL;
2463
2464 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2488 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2465 if (cmd == NULL) 2489 if (cmd == NULL)
2466 return -ENOMEM; 2490 return -ENOMEM;
@@ -2469,24 +2493,17 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
2469 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2493 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2470 cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); 2494 cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1);
2471 2495
2472 hdrlen = ieee80211_hdrlen(payload->frame_control); 2496 payload_len = framelen - ieee80211_hdrlen(payload->frame_control);
2473 2497 if (payload_len < 0)
2474 payload_len = framelen > hdrlen ? framelen - hdrlen : 0; 2498 payload_len = 0;
2475 2499 else if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
2476 /* XXX TBD Might just have to abort and return an error */
2477 if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
2478 printk(KERN_ERR "%s(): WARNING: Incomplete beacon "
2479 "sent to firmware. Sz=%u MAX=%u\n", __func__,
2480 payload_len, MWL8K_FJ_BEACON_MAXLEN);
2481
2482 if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
2483 payload_len = MWL8K_FJ_BEACON_MAXLEN; 2500 payload_len = MWL8K_FJ_BEACON_MAXLEN;
2484 2501
2485 if (payload && payload_len) 2502 memcpy(cmd->beacon_data, &payload->u.beacon, payload_len);
2486 memcpy(cmd->beacon_data, &payload->u.beacon, payload_len);
2487 2503
2488 rc = mwl8k_post_cmd(hw, &cmd->header); 2504 rc = mwl8k_post_cmd(hw, &cmd->header);
2489 kfree(cmd); 2505 kfree(cmd);
2506
2490 return rc; 2507 return rc;
2491} 2508}
2492 2509
@@ -2515,9 +2532,7 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
2515 struct ieee80211_bss_conf *info = &mv_vif->bss_info; 2532 struct ieee80211_bss_conf *info = &mv_vif->bss_info;
2516 struct mwl8k_cmd_update_sta_db *cmd; 2533 struct mwl8k_cmd_update_sta_db *cmd;
2517 struct peer_capability_info *peer_info; 2534 struct peer_capability_info *peer_info;
2518 struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
2519 int rc; 2535 int rc;
2520 __u8 count, *rates;
2521 2536
2522 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2537 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2523 if (cmd == NULL) 2538 if (cmd == NULL)
@@ -2536,13 +2551,11 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
2536 /* Build peer_info block */ 2551 /* Build peer_info block */
2537 peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; 2552 peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
2538 peer_info->basic_caps = cpu_to_le16(info->assoc_capability); 2553 peer_info->basic_caps = cpu_to_le16(info->assoc_capability);
2554 memcpy(peer_info->legacy_rates, mwl8k_rateids,
2555 sizeof(mwl8k_rateids));
2539 peer_info->interop = 1; 2556 peer_info->interop = 1;
2540 peer_info->amsdu_enabled = 0; 2557 peer_info->amsdu_enabled = 0;
2541 2558
2542 rates = peer_info->legacy_rates;
2543 for (count = 0; count < mv_vif->legacy_nrates; count++)
2544 rates[count] = bitrates[count].hw_value;
2545
2546 rc = mwl8k_post_cmd(hw, &cmd->header); 2559 rc = mwl8k_post_cmd(hw, &cmd->header);
2547 if (rc == 0) 2560 if (rc == 0)
2548 mv_vif->peer_id = peer_info->station_id; 2561 mv_vif->peer_id = peer_info->station_id;
@@ -2565,8 +2578,6 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
2565/* 2578/*
2566 * CMD_SET_AID. 2579 * CMD_SET_AID.
2567 */ 2580 */
2568#define MWL8K_RATE_INDEX_MAX_ARRAY 14
2569
2570#define MWL8K_FRAME_PROT_DISABLED 0x00 2581#define MWL8K_FRAME_PROT_DISABLED 0x00
2571#define MWL8K_FRAME_PROT_11G 0x07 2582#define MWL8K_FRAME_PROT_11G 0x07
2572#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 2583#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02
@@ -2579,7 +2590,7 @@ struct mwl8k_cmd_update_set_aid {
2579 /* AP's MAC address (BSSID) */ 2590 /* AP's MAC address (BSSID) */
2580 __u8 bssid[ETH_ALEN]; 2591 __u8 bssid[ETH_ALEN];
2581 __le16 protection_mode; 2592 __le16 protection_mode;
2582 __u8 supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; 2593 __u8 supp_rates[14];
2583} __attribute__((packed)); 2594} __attribute__((packed));
2584 2595
2585static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, 2596static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
@@ -2588,8 +2599,6 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
2588 struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); 2599 struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
2589 struct ieee80211_bss_conf *info = &mv_vif->bss_info; 2600 struct ieee80211_bss_conf *info = &mv_vif->bss_info;
2590 struct mwl8k_cmd_update_set_aid *cmd; 2601 struct mwl8k_cmd_update_set_aid *cmd;
2591 struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
2592 int count;
2593 u16 prot_mode; 2602 u16 prot_mode;
2594 int rc; 2603 int rc;
2595 2604
@@ -2621,8 +2630,7 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
2621 } 2630 }
2622 cmd->protection_mode = cpu_to_le16(prot_mode); 2631 cmd->protection_mode = cpu_to_le16(prot_mode);
2623 2632
2624 for (count = 0; count < mv_vif->legacy_nrates; count++) 2633 memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids));
2625 cmd->supp_rates[count] = bitrates[count].hw_value;
2626 2634
2627 rc = mwl8k_post_cmd(hw, &cmd->header); 2635 rc = mwl8k_post_cmd(hw, &cmd->header);
2628 kfree(cmd); 2636 kfree(cmd);
@@ -2635,20 +2643,17 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
2635 */ 2643 */
2636struct mwl8k_cmd_update_rateset { 2644struct mwl8k_cmd_update_rateset {
2637 struct mwl8k_cmd_pkt header; 2645 struct mwl8k_cmd_pkt header;
2638 __u8 legacy_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; 2646 __u8 legacy_rates[14];
2639 2647
2640 /* Bitmap for supported MCS codes. */ 2648 /* Bitmap for supported MCS codes. */
2641 __u8 mcs_set[MWL8K_IEEE_LEGACY_DATA_RATES]; 2649 __u8 mcs_set[16];
2642 __u8 reserved[MWL8K_IEEE_LEGACY_DATA_RATES]; 2650 __u8 reserved[16];
2643} __attribute__((packed)); 2651} __attribute__((packed));
2644 2652
2645static int mwl8k_update_rateset(struct ieee80211_hw *hw, 2653static int mwl8k_update_rateset(struct ieee80211_hw *hw,
2646 struct ieee80211_vif *vif) 2654 struct ieee80211_vif *vif)
2647{ 2655{
2648 struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
2649 struct mwl8k_cmd_update_rateset *cmd; 2656 struct mwl8k_cmd_update_rateset *cmd;
2650 struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
2651 int count;
2652 int rc; 2657 int rc;
2653 2658
2654 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2659 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -2657,9 +2662,7 @@ static int mwl8k_update_rateset(struct ieee80211_hw *hw,
2657 2662
2658 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); 2663 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE);
2659 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2664 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2660 2665 memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids));
2661 for (count = 0; count < mv_vif->legacy_nrates; count++)
2662 cmd->legacy_rates[count] = bitrates[count].hw_value;
2663 2666
2664 rc = mwl8k_post_cmd(hw, &cmd->header); 2667 rc = mwl8k_post_cmd(hw, &cmd->header);
2665 kfree(cmd); 2668 kfree(cmd);
@@ -2932,11 +2935,6 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
2932 /* Back pointer to parent config block */ 2935 /* Back pointer to parent config block */
2933 mwl8k_vif->priv = priv; 2936 mwl8k_vif->priv = priv;
2934 2937
2935 /* Setup initial PHY parameters */
2936 memcpy(mwl8k_vif->legacy_rates,
2937 priv->rates, sizeof(mwl8k_vif->legacy_rates));
2938 mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates);
2939
2940 /* Set Initial sequence number to zero */ 2938 /* Set Initial sequence number to zero */
2941 mwl8k_vif->seqno = 0; 2939 mwl8k_vif->seqno = 0;
2942 2940
@@ -3014,9 +3012,6 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
3014 struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); 3012 struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
3015 int rc; 3013 int rc;
3016 3014
3017 if (changed & BSS_CHANGED_BSSID)
3018 memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN);
3019
3020 if ((changed & BSS_CHANGED_ASSOC) == 0) 3015 if ((changed & BSS_CHANGED_ASSOC) == 0)
3021 return; 3016 return;
3022 3017
@@ -3030,6 +3025,8 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
3030 memcpy(&mwl8k_vif->bss_info, info, 3025 memcpy(&mwl8k_vif->bss_info, info,
3031 sizeof(struct ieee80211_bss_conf)); 3026 sizeof(struct ieee80211_bss_conf));
3032 3027
3028 memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN);
3029
3033 /* Install rates */ 3030 /* Install rates */
3034 rc = mwl8k_update_rateset(hw, vif); 3031 rc = mwl8k_update_rateset(hw, vif);
3035 if (rc) 3032 if (rc)
@@ -3366,7 +3363,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
3366 if (rc) { 3363 if (rc) {
3367 printk(KERN_ERR "%s: Cannot obtain PCI resources\n", 3364 printk(KERN_ERR "%s: Cannot obtain PCI resources\n",
3368 MWL8K_NAME); 3365 MWL8K_NAME);
3369 return rc; 3366 goto err_disable_device;
3370 } 3367 }
3371 3368
3372 pci_set_master(pdev); 3369 pci_set_master(pdev);
@@ -3597,6 +3594,8 @@ err_iounmap:
3597 3594
3598err_free_reg: 3595err_free_reg:
3599 pci_release_regions(pdev); 3596 pci_release_regions(pdev);
3597
3598err_disable_device:
3600 pci_disable_device(pdev); 3599 pci_disable_device(pdev);
3601 3600
3602 return rc; 3601 return rc;