diff options
author | David S. Miller <davem@davemloft.net> | 2008-03-11 22:17:18 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-03-11 22:17:18 -0400 |
commit | ba73d4c84a7344f1b5635c2b4e96796e8c13a126 (patch) | |
tree | d4a3e2cfc5f3a046a2b9baa898f0c201c75ba898 /drivers/net/wireless | |
parent | b8ad0cbc58f703972e9e37c4e2a8081dd7e6a551 (diff) | |
parent | deedf504302ff747985db081352e045ff7087a11 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.26
Diffstat (limited to 'drivers/net/wireless')
54 files changed, 3832 insertions, 2466 deletions
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 18223d9833f1..b21830771ea5 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h | |||
@@ -140,7 +140,8 @@ enum ath5k_radio { | |||
140 | AR5K_RF5110 = 0, | 140 | AR5K_RF5110 = 0, |
141 | AR5K_RF5111 = 1, | 141 | AR5K_RF5111 = 1, |
142 | AR5K_RF5112 = 2, | 142 | AR5K_RF5112 = 2, |
143 | AR5K_RF5413 = 3, | 143 | AR5K_RF2413 = 3, |
144 | AR5K_RF5413 = 4, | ||
144 | }; | 145 | }; |
145 | 146 | ||
146 | /* | 147 | /* |
@@ -168,12 +169,15 @@ struct ath5k_srev_name { | |||
168 | #define AR5K_SREV_VER_AR5212 0x50 | 169 | #define AR5K_SREV_VER_AR5212 0x50 |
169 | #define AR5K_SREV_VER_AR5213 0x55 | 170 | #define AR5K_SREV_VER_AR5213 0x55 |
170 | #define AR5K_SREV_VER_AR5213A 0x59 | 171 | #define AR5K_SREV_VER_AR5213A 0x59 |
171 | #define AR5K_SREV_VER_AR2424 0xa0 | 172 | #define AR5K_SREV_VER_AR2413 0x78 |
172 | #define AR5K_SREV_VER_AR5424 0xa3 | 173 | #define AR5K_SREV_VER_AR2414 0x79 |
174 | #define AR5K_SREV_VER_AR2424 0xa0 /* PCI-E */ | ||
175 | #define AR5K_SREV_VER_AR5424 0xa3 /* PCI-E */ | ||
173 | #define AR5K_SREV_VER_AR5413 0xa4 | 176 | #define AR5K_SREV_VER_AR5413 0xa4 |
174 | #define AR5K_SREV_VER_AR5414 0xa5 | 177 | #define AR5K_SREV_VER_AR5414 0xa5 |
175 | #define AR5K_SREV_VER_AR5416 0xc0 /* ? */ | 178 | #define AR5K_SREV_VER_AR5416 0xc0 /* PCI-E */ |
176 | #define AR5K_SREV_VER_AR5418 0xca | 179 | #define AR5K_SREV_VER_AR5418 0xca /* PCI-E */ |
180 | #define AR5K_SREV_VER_AR2425 0xe2 /* PCI-E */ | ||
177 | 181 | ||
178 | #define AR5K_SREV_RAD_5110 0x00 | 182 | #define AR5K_SREV_RAD_5110 0x00 |
179 | #define AR5K_SREV_RAD_5111 0x10 | 183 | #define AR5K_SREV_RAD_5111 0x10 |
@@ -183,8 +187,9 @@ struct ath5k_srev_name { | |||
183 | #define AR5K_SREV_RAD_5112A 0x35 | 187 | #define AR5K_SREV_RAD_5112A 0x35 |
184 | #define AR5K_SREV_RAD_2112 0x40 | 188 | #define AR5K_SREV_RAD_2112 0x40 |
185 | #define AR5K_SREV_RAD_2112A 0x45 | 189 | #define AR5K_SREV_RAD_2112A 0x45 |
190 | #define AR5K_SREV_RAD_SC0 0x56 /* Found on 2413/2414 */ | ||
186 | #define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */ | 191 | #define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */ |
187 | #define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424/5424 */ | 192 | #define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424-5/5424 */ |
188 | #define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */ | 193 | #define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */ |
189 | 194 | ||
190 | /* IEEE defs */ | 195 | /* IEEE defs */ |
@@ -268,12 +273,13 @@ enum ath5k_driver_mode { | |||
268 | #define SHPREAMBLE_FLAG(_ix) \ | 273 | #define SHPREAMBLE_FLAG(_ix) \ |
269 | (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0) | 274 | (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0) |
270 | 275 | ||
276 | |||
271 | /****************\ | 277 | /****************\ |
272 | TX DEFINITIONS | 278 | TX DEFINITIONS |
273 | \****************/ | 279 | \****************/ |
274 | 280 | ||
275 | /* | 281 | /* |
276 | * Tx Descriptor | 282 | * TX Status |
277 | */ | 283 | */ |
278 | struct ath5k_tx_status { | 284 | struct ath5k_tx_status { |
279 | u16 ts_seqnum; | 285 | u16 ts_seqnum; |
@@ -421,7 +427,7 @@ enum ath5k_dmasize { | |||
421 | \****************/ | 427 | \****************/ |
422 | 428 | ||
423 | /* | 429 | /* |
424 | * Rx Descriptor | 430 | * RX Status |
425 | */ | 431 | */ |
426 | struct ath5k_rx_status { | 432 | struct ath5k_rx_status { |
427 | u16 rs_datalen; | 433 | u16 rs_datalen; |
@@ -452,8 +458,6 @@ struct ath5k_mib_stats { | |||
452 | }; | 458 | }; |
453 | 459 | ||
454 | 460 | ||
455 | |||
456 | |||
457 | /**************************\ | 461 | /**************************\ |
458 | BEACON TIMERS DEFINITIONS | 462 | BEACON TIMERS DEFINITIONS |
459 | \**************************/ | 463 | \**************************/ |
@@ -495,29 +499,23 @@ struct ath5k_beacon_state { | |||
495 | #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) | 499 | #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) |
496 | 500 | ||
497 | 501 | ||
498 | |||
499 | /********************\ | 502 | /********************\ |
500 | COMMON DEFINITIONS | 503 | COMMON DEFINITIONS |
501 | \********************/ | 504 | \********************/ |
502 | 505 | ||
503 | /* | 506 | /* |
504 | * Atheros descriptor | 507 | * Atheros hardware descriptor |
508 | * This is read and written to by the hardware | ||
505 | */ | 509 | */ |
506 | struct ath5k_desc { | 510 | struct ath5k_desc { |
507 | u32 ds_link; | 511 | u32 ds_link; /* physical address of the next descriptor */ |
508 | u32 ds_data; | 512 | u32 ds_data; /* physical address of data buffer (skb) */ |
509 | u32 ds_ctl0; | ||
510 | u32 ds_ctl1; | ||
511 | u32 ds_hw[4]; | ||
512 | 513 | ||
513 | union { | 514 | union { |
514 | struct ath5k_rx_status rx; | 515 | struct ath5k_hw_5210_tx_desc ds_tx5210; |
515 | struct ath5k_tx_status tx; | 516 | struct ath5k_hw_5212_tx_desc ds_tx5212; |
516 | } ds_us; | 517 | struct ath5k_hw_all_rx_desc ds_rx; |
517 | 518 | } ud; | |
518 | #define ds_rxstat ds_us.rx | ||
519 | #define ds_txstat ds_us.tx | ||
520 | |||
521 | } __packed; | 519 | } __packed; |
522 | 520 | ||
523 | #define AR5K_RXDESC_INTREQ 0x0020 | 521 | #define AR5K_RXDESC_INTREQ 0x0020 |
@@ -961,6 +959,7 @@ struct ath5k_hw { | |||
961 | u16 ah_phy_revision; | 959 | u16 ah_phy_revision; |
962 | u16 ah_radio_5ghz_revision; | 960 | u16 ah_radio_5ghz_revision; |
963 | u16 ah_radio_2ghz_revision; | 961 | u16 ah_radio_2ghz_revision; |
962 | u32 ah_phy_spending; | ||
964 | 963 | ||
965 | enum ath5k_version ah_version; | 964 | enum ath5k_version ah_version; |
966 | enum ath5k_radio ah_radio; | 965 | enum ath5k_radio ah_radio; |
@@ -1036,8 +1035,10 @@ struct ath5k_hw { | |||
1036 | int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1035 | int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
1037 | unsigned int, unsigned int, unsigned int, unsigned int, | 1036 | unsigned int, unsigned int, unsigned int, unsigned int, |
1038 | unsigned int, unsigned int); | 1037 | unsigned int, unsigned int); |
1039 | int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *); | 1038 | int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
1040 | int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *); | 1039 | struct ath5k_tx_status *); |
1040 | int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *, | ||
1041 | struct ath5k_rx_status *); | ||
1041 | }; | 1042 | }; |
1042 | 1043 | ||
1043 | /* | 1044 | /* |
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 393b5f3c25a7..b5c0a0d7a81c 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -118,6 +118,8 @@ static struct ath5k_srev_name srev_names[] = { | |||
118 | { "5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212 }, | 118 | { "5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212 }, |
119 | { "5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213 }, | 119 | { "5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213 }, |
120 | { "5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A }, | 120 | { "5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A }, |
121 | { "2413", AR5K_VERSION_VER, AR5K_SREV_VER_AR2413 }, | ||
122 | { "2414", AR5K_VERSION_VER, AR5K_SREV_VER_AR2414 }, | ||
121 | { "2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424 }, | 123 | { "2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424 }, |
122 | { "5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424 }, | 124 | { "5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424 }, |
123 | { "5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413 }, | 125 | { "5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413 }, |
@@ -132,6 +134,7 @@ static struct ath5k_srev_name srev_names[] = { | |||
132 | { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A }, | 134 | { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A }, |
133 | { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 }, | 135 | { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 }, |
134 | { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A }, | 136 | { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A }, |
137 | { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC0 }, | ||
135 | { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1 }, | 138 | { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1 }, |
136 | { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2 }, | 139 | { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2 }, |
137 | { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, | 140 | { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, |
@@ -280,7 +283,8 @@ static int ath5k_rx_start(struct ath5k_softc *sc); | |||
280 | static void ath5k_rx_stop(struct ath5k_softc *sc); | 283 | static void ath5k_rx_stop(struct ath5k_softc *sc); |
281 | static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, | 284 | static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, |
282 | struct ath5k_desc *ds, | 285 | struct ath5k_desc *ds, |
283 | struct sk_buff *skb); | 286 | struct sk_buff *skb, |
287 | struct ath5k_rx_status *rs); | ||
284 | static void ath5k_tasklet_rx(unsigned long data); | 288 | static void ath5k_tasklet_rx(unsigned long data); |
285 | /* Tx handling */ | 289 | /* Tx handling */ |
286 | static void ath5k_tx_processq(struct ath5k_softc *sc, | 290 | static void ath5k_tx_processq(struct ath5k_softc *sc, |
@@ -1560,8 +1564,7 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1560 | */ | 1564 | */ |
1561 | spin_lock_bh(&txq->lock); | 1565 | spin_lock_bh(&txq->lock); |
1562 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { | 1566 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { |
1563 | ath5k_debug_printtxbuf(sc, bf, !sc->ah->ah_proc_tx_desc(sc->ah, | 1567 | ath5k_debug_printtxbuf(sc, bf); |
1564 | bf->desc)); | ||
1565 | 1568 | ||
1566 | ath5k_txbuf_free(sc, bf); | 1569 | ath5k_txbuf_free(sc, bf); |
1567 | 1570 | ||
@@ -1686,20 +1689,20 @@ ath5k_rx_stop(struct ath5k_softc *sc) | |||
1686 | 1689 | ||
1687 | static unsigned int | 1690 | static unsigned int |
1688 | ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, | 1691 | ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, |
1689 | struct sk_buff *skb) | 1692 | struct sk_buff *skb, struct ath5k_rx_status *rs) |
1690 | { | 1693 | { |
1691 | struct ieee80211_hdr *hdr = (void *)skb->data; | 1694 | struct ieee80211_hdr *hdr = (void *)skb->data; |
1692 | unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb); | 1695 | unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb); |
1693 | 1696 | ||
1694 | if (!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) && | 1697 | if (!(rs->rs_status & AR5K_RXERR_DECRYPT) && |
1695 | ds->ds_rxstat.rs_keyix != AR5K_RXKEYIX_INVALID) | 1698 | rs->rs_keyix != AR5K_RXKEYIX_INVALID) |
1696 | return RX_FLAG_DECRYPTED; | 1699 | return RX_FLAG_DECRYPTED; |
1697 | 1700 | ||
1698 | /* Apparently when a default key is used to decrypt the packet | 1701 | /* Apparently when a default key is used to decrypt the packet |
1699 | the hw does not set the index used to decrypt. In such cases | 1702 | the hw does not set the index used to decrypt. In such cases |
1700 | get the index from the packet. */ | 1703 | get the index from the packet. */ |
1701 | if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) && | 1704 | if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) && |
1702 | !(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) && | 1705 | !(rs->rs_status & AR5K_RXERR_DECRYPT) && |
1703 | skb->len >= hlen + 4) { | 1706 | skb->len >= hlen + 4) { |
1704 | keyix = skb->data[hlen + 3] >> 6; | 1707 | keyix = skb->data[hlen + 3] >> 6; |
1705 | 1708 | ||
@@ -1712,8 +1715,10 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, | |||
1712 | 1715 | ||
1713 | 1716 | ||
1714 | static void | 1717 | static void |
1715 | ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb) | 1718 | ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, |
1719 | struct ieee80211_rx_status *rxs) | ||
1716 | { | 1720 | { |
1721 | u64 tsf, bc_tstamp; | ||
1717 | u32 hw_tu; | 1722 | u32 hw_tu; |
1718 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; | 1723 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; |
1719 | 1724 | ||
@@ -1724,16 +1729,45 @@ ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb) | |||
1724 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && | 1729 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && |
1725 | memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { | 1730 | memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { |
1726 | /* | 1731 | /* |
1727 | * Received an IBSS beacon with the same BSSID. Hardware might | 1732 | * Received an IBSS beacon with the same BSSID. Hardware *must* |
1728 | * have updated the TSF, check if we need to update timers. | 1733 | * have updated the local TSF. We have to work around various |
1734 | * hardware bugs, though... | ||
1729 | */ | 1735 | */ |
1730 | hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah)); | 1736 | tsf = ath5k_hw_get_tsf64(sc->ah); |
1731 | if (hw_tu >= sc->nexttbtt) { | 1737 | bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp); |
1732 | ath5k_beacon_update_timers(sc, | 1738 | hw_tu = TSF_TO_TU(tsf); |
1733 | le64_to_cpu(mgmt->u.beacon.timestamp)); | 1739 | |
1740 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, | ||
1741 | "beacon %llx mactime %llx (diff %lld) tsf now %llx\n", | ||
1742 | bc_tstamp, rxs->mactime, | ||
1743 | (rxs->mactime - bc_tstamp), tsf); | ||
1744 | |||
1745 | /* | ||
1746 | * Sometimes the HW will give us a wrong tstamp in the rx | ||
1747 | * status, causing the timestamp extension to go wrong. | ||
1748 | * (This seems to happen especially with beacon frames bigger | ||
1749 | * than 78 byte (incl. FCS)) | ||
1750 | * But we know that the receive timestamp must be later than the | ||
1751 | * timestamp of the beacon since HW must have synced to that. | ||
1752 | * | ||
1753 | * NOTE: here we assume mactime to be after the frame was | ||
1754 | * received, not like mac80211 which defines it at the start. | ||
1755 | */ | ||
1756 | if (bc_tstamp > rxs->mactime) { | ||
1734 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, | 1757 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, |
1735 | "detected HW merge from received beacon\n"); | 1758 | "fixing mactime from %llx to %llx\n", |
1759 | rxs->mactime, tsf); | ||
1760 | rxs->mactime = tsf; | ||
1736 | } | 1761 | } |
1762 | |||
1763 | /* | ||
1764 | * Local TSF might have moved higher than our beacon timers, | ||
1765 | * in that case we have to update them to continue sending | ||
1766 | * beacons. This also takes care of synchronizing beacon sending | ||
1767 | * times with other stations. | ||
1768 | */ | ||
1769 | if (hw_tu >= sc->nexttbtt) | ||
1770 | ath5k_beacon_update_timers(sc, bc_tstamp); | ||
1737 | } | 1771 | } |
1738 | } | 1772 | } |
1739 | 1773 | ||
@@ -1742,12 +1776,11 @@ static void | |||
1742 | ath5k_tasklet_rx(unsigned long data) | 1776 | ath5k_tasklet_rx(unsigned long data) |
1743 | { | 1777 | { |
1744 | struct ieee80211_rx_status rxs = {}; | 1778 | struct ieee80211_rx_status rxs = {}; |
1779 | struct ath5k_rx_status rs = {}; | ||
1745 | struct sk_buff *skb; | 1780 | struct sk_buff *skb; |
1746 | struct ath5k_softc *sc = (void *)data; | 1781 | struct ath5k_softc *sc = (void *)data; |
1747 | struct ath5k_buf *bf; | 1782 | struct ath5k_buf *bf; |
1748 | struct ath5k_desc *ds; | 1783 | struct ath5k_desc *ds; |
1749 | u16 len; | ||
1750 | u8 stat; | ||
1751 | int ret; | 1784 | int ret; |
1752 | int hdrlen; | 1785 | int hdrlen; |
1753 | int pad; | 1786 | int pad; |
@@ -1770,7 +1803,7 @@ ath5k_tasklet_rx(unsigned long data) | |||
1770 | if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */ | 1803 | if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */ |
1771 | break; | 1804 | break; |
1772 | 1805 | ||
1773 | ret = sc->ah->ah_proc_rx_desc(sc->ah, ds); | 1806 | ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); |
1774 | if (unlikely(ret == -EINPROGRESS)) | 1807 | if (unlikely(ret == -EINPROGRESS)) |
1775 | break; | 1808 | break; |
1776 | else if (unlikely(ret)) { | 1809 | else if (unlikely(ret)) { |
@@ -1779,16 +1812,15 @@ ath5k_tasklet_rx(unsigned long data) | |||
1779 | return; | 1812 | return; |
1780 | } | 1813 | } |
1781 | 1814 | ||
1782 | if (unlikely(ds->ds_rxstat.rs_more)) { | 1815 | if (unlikely(rs.rs_more)) { |
1783 | ATH5K_WARN(sc, "unsupported jumbo\n"); | 1816 | ATH5K_WARN(sc, "unsupported jumbo\n"); |
1784 | goto next; | 1817 | goto next; |
1785 | } | 1818 | } |
1786 | 1819 | ||
1787 | stat = ds->ds_rxstat.rs_status; | 1820 | if (unlikely(rs.rs_status)) { |
1788 | if (unlikely(stat)) { | 1821 | if (rs.rs_status & AR5K_RXERR_PHY) |
1789 | if (stat & AR5K_RXERR_PHY) | ||
1790 | goto next; | 1822 | goto next; |
1791 | if (stat & AR5K_RXERR_DECRYPT) { | 1823 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { |
1792 | /* | 1824 | /* |
1793 | * Decrypt error. If the error occurred | 1825 | * Decrypt error. If the error occurred |
1794 | * because there was no hardware key, then | 1826 | * because there was no hardware key, then |
@@ -1799,30 +1831,29 @@ ath5k_tasklet_rx(unsigned long data) | |||
1799 | * | 1831 | * |
1800 | * XXX do key cache faulting | 1832 | * XXX do key cache faulting |
1801 | */ | 1833 | */ |
1802 | if (ds->ds_rxstat.rs_keyix == | 1834 | if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && |
1803 | AR5K_RXKEYIX_INVALID && | 1835 | !(rs.rs_status & AR5K_RXERR_CRC)) |
1804 | !(stat & AR5K_RXERR_CRC)) | ||
1805 | goto accept; | 1836 | goto accept; |
1806 | } | 1837 | } |
1807 | if (stat & AR5K_RXERR_MIC) { | 1838 | if (rs.rs_status & AR5K_RXERR_MIC) { |
1808 | rxs.flag |= RX_FLAG_MMIC_ERROR; | 1839 | rxs.flag |= RX_FLAG_MMIC_ERROR; |
1809 | goto accept; | 1840 | goto accept; |
1810 | } | 1841 | } |
1811 | 1842 | ||
1812 | /* let crypto-error packets fall through in MNTR */ | 1843 | /* let crypto-error packets fall through in MNTR */ |
1813 | if ((stat & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || | 1844 | if ((rs.rs_status & |
1845 | ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || | ||
1814 | sc->opmode != IEEE80211_IF_TYPE_MNTR) | 1846 | sc->opmode != IEEE80211_IF_TYPE_MNTR) |
1815 | goto next; | 1847 | goto next; |
1816 | } | 1848 | } |
1817 | accept: | 1849 | accept: |
1818 | len = ds->ds_rxstat.rs_datalen; | 1850 | pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, |
1819 | pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, len, | 1851 | rs.rs_datalen, PCI_DMA_FROMDEVICE); |
1820 | PCI_DMA_FROMDEVICE); | ||
1821 | pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, | 1852 | pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, |
1822 | PCI_DMA_FROMDEVICE); | 1853 | PCI_DMA_FROMDEVICE); |
1823 | bf->skb = NULL; | 1854 | bf->skb = NULL; |
1824 | 1855 | ||
1825 | skb_put(skb, len); | 1856 | skb_put(skb, rs.rs_datalen); |
1826 | 1857 | ||
1827 | /* | 1858 | /* |
1828 | * the hardware adds a padding to 4 byte boundaries between | 1859 | * the hardware adds a padding to 4 byte boundaries between |
@@ -1844,8 +1875,19 @@ accept: | |||
1844 | * 15bit only. that means TSF extension has to be done within | 1875 | * 15bit only. that means TSF extension has to be done within |
1845 | * 32768usec (about 32ms). it might be necessary to move this to | 1876 | * 32768usec (about 32ms). it might be necessary to move this to |
1846 | * the interrupt handler, like it is done in madwifi. | 1877 | * the interrupt handler, like it is done in madwifi. |
1878 | * | ||
1879 | * Unfortunately we don't know when the hardware takes the rx | ||
1880 | * timestamp (beginning of phy frame, data frame, end of rx?). | ||
1881 | * The only thing we know is that it is hardware specific... | ||
1882 | * On AR5213 it seems the rx timestamp is at the end of the | ||
1883 | * frame, but i'm not sure. | ||
1884 | * | ||
1885 | * NOTE: mac80211 defines mactime at the beginning of the first | ||
1886 | * data symbol. Since we don't have any time references it's | ||
1887 | * impossible to comply to that. This affects IBSS merge only | ||
1888 | * right now, so it's not too bad... | ||
1847 | */ | 1889 | */ |
1848 | rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp); | 1890 | rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp); |
1849 | rxs.flag |= RX_FLAG_TSFT; | 1891 | rxs.flag |= RX_FLAG_TSFT; |
1850 | 1892 | ||
1851 | rxs.freq = sc->curchan->center_freq; | 1893 | rxs.freq = sc->curchan->center_freq; |
@@ -1859,26 +1901,25 @@ accept: | |||
1859 | /* noise floor in dBm, from the last noise calibration */ | 1901 | /* noise floor in dBm, from the last noise calibration */ |
1860 | rxs.noise = sc->ah->ah_noise_floor; | 1902 | rxs.noise = sc->ah->ah_noise_floor; |
1861 | /* signal level in dBm */ | 1903 | /* signal level in dBm */ |
1862 | rxs.ssi = rxs.noise + ds->ds_rxstat.rs_rssi; | 1904 | rxs.ssi = rxs.noise + rs.rs_rssi; |
1863 | /* | 1905 | /* |
1864 | * "signal" is actually displayed as Link Quality by iwconfig | 1906 | * "signal" is actually displayed as Link Quality by iwconfig |
1865 | * we provide a percentage based on rssi (assuming max rssi 64) | 1907 | * we provide a percentage based on rssi (assuming max rssi 64) |
1866 | */ | 1908 | */ |
1867 | rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64; | 1909 | rxs.signal = rs.rs_rssi * 100 / 64; |
1868 | 1910 | ||
1869 | rxs.antenna = ds->ds_rxstat.rs_antenna; | 1911 | rxs.antenna = rs.rs_antenna; |
1870 | rxs.rate_idx = ath5k_hw_to_driver_rix(sc, | 1912 | rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); |
1871 | ds->ds_rxstat.rs_rate); | 1913 | rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); |
1872 | rxs.flag |= ath5k_rx_decrypted(sc, ds, skb); | ||
1873 | 1914 | ||
1874 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | 1915 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); |
1875 | 1916 | ||
1876 | /* check beacons in IBSS mode */ | 1917 | /* check beacons in IBSS mode */ |
1877 | if (sc->opmode == IEEE80211_IF_TYPE_IBSS) | 1918 | if (sc->opmode == IEEE80211_IF_TYPE_IBSS) |
1878 | ath5k_check_ibss_hw_merge(sc, skb); | 1919 | ath5k_check_ibss_tsf(sc, skb, &rxs); |
1879 | 1920 | ||
1880 | __ieee80211_rx(sc->hw, skb, &rxs); | 1921 | __ieee80211_rx(sc->hw, skb, &rxs); |
1881 | sc->led_rxrate = ds->ds_rxstat.rs_rate; | 1922 | sc->led_rxrate = rs.rs_rate; |
1882 | ath5k_led_event(sc, ATH_LED_RX); | 1923 | ath5k_led_event(sc, ATH_LED_RX); |
1883 | next: | 1924 | next: |
1884 | list_move_tail(&bf->list, &sc->rxbuf); | 1925 | list_move_tail(&bf->list, &sc->rxbuf); |
@@ -1897,6 +1938,7 @@ static void | |||
1897 | ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | 1938 | ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) |
1898 | { | 1939 | { |
1899 | struct ieee80211_tx_status txs = {}; | 1940 | struct ieee80211_tx_status txs = {}; |
1941 | struct ath5k_tx_status ts = {}; | ||
1900 | struct ath5k_buf *bf, *bf0; | 1942 | struct ath5k_buf *bf, *bf0; |
1901 | struct ath5k_desc *ds; | 1943 | struct ath5k_desc *ds; |
1902 | struct sk_buff *skb; | 1944 | struct sk_buff *skb; |
@@ -1909,7 +1951,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1909 | /* TODO only one segment */ | 1951 | /* TODO only one segment */ |
1910 | pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr, | 1952 | pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr, |
1911 | sc->desc_len, PCI_DMA_FROMDEVICE); | 1953 | sc->desc_len, PCI_DMA_FROMDEVICE); |
1912 | ret = sc->ah->ah_proc_tx_desc(sc->ah, ds); | 1954 | ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); |
1913 | if (unlikely(ret == -EINPROGRESS)) | 1955 | if (unlikely(ret == -EINPROGRESS)) |
1914 | break; | 1956 | break; |
1915 | else if (unlikely(ret)) { | 1957 | else if (unlikely(ret)) { |
@@ -1924,17 +1966,16 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1924 | PCI_DMA_TODEVICE); | 1966 | PCI_DMA_TODEVICE); |
1925 | 1967 | ||
1926 | txs.control = bf->ctl; | 1968 | txs.control = bf->ctl; |
1927 | txs.retry_count = ds->ds_txstat.ts_shortretry + | 1969 | txs.retry_count = ts.ts_shortretry + ts.ts_longretry / 6; |
1928 | ds->ds_txstat.ts_longretry / 6; | 1970 | if (unlikely(ts.ts_status)) { |
1929 | if (unlikely(ds->ds_txstat.ts_status)) { | ||
1930 | sc->ll_stats.dot11ACKFailureCount++; | 1971 | sc->ll_stats.dot11ACKFailureCount++; |
1931 | if (ds->ds_txstat.ts_status & AR5K_TXERR_XRETRY) | 1972 | if (ts.ts_status & AR5K_TXERR_XRETRY) |
1932 | txs.excessive_retries = 1; | 1973 | txs.excessive_retries = 1; |
1933 | else if (ds->ds_txstat.ts_status & AR5K_TXERR_FILT) | 1974 | else if (ts.ts_status & AR5K_TXERR_FILT) |
1934 | txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED; | 1975 | txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED; |
1935 | } else { | 1976 | } else { |
1936 | txs.flags |= IEEE80211_TX_STATUS_ACK; | 1977 | txs.flags |= IEEE80211_TX_STATUS_ACK; |
1937 | txs.ack_signal = ds->ds_txstat.ts_rssi; | 1978 | txs.ack_signal = ts.ts_rssi; |
1938 | } | 1979 | } |
1939 | 1980 | ||
1940 | ieee80211_tx_status(sc->hw, skb, &txs); | 1981 | ieee80211_tx_status(sc->hw, skb, &txs); |
@@ -2108,7 +2149,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
2108 | * beacon timer registers. | 2149 | * beacon timer registers. |
2109 | * | 2150 | * |
2110 | * This is called in a variety of situations, e.g. when a beacon is received, | 2151 | * This is called in a variety of situations, e.g. when a beacon is received, |
2111 | * when a HW merge has been detected, but also when an new IBSS is created or | 2152 | * when a TSF update has been detected, but also when an new IBSS is created or |
2112 | * when we otherwise know we have to update the timers, but we keep it in this | 2153 | * when we otherwise know we have to update the timers, but we keep it in this |
2113 | * function to have it all together in one place. | 2154 | * function to have it all together in one place. |
2114 | */ | 2155 | */ |
@@ -2208,7 +2249,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) | |||
2208 | * another AP to associate with. | 2249 | * another AP to associate with. |
2209 | * | 2250 | * |
2210 | * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA | 2251 | * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA |
2211 | * interrupts to detect HW merges only. | 2252 | * interrupts to detect TSF updates only. |
2212 | * | 2253 | * |
2213 | * AP mode is missing. | 2254 | * AP mode is missing. |
2214 | */ | 2255 | */ |
@@ -2228,7 +2269,7 @@ ath5k_beacon_config(struct ath5k_softc *sc) | |||
2228 | * hardware send the beacons automatically. We have to load it | 2269 | * hardware send the beacons automatically. We have to load it |
2229 | * only once here. | 2270 | * only once here. |
2230 | * We use the SWBA interrupt only to keep track of the beacon | 2271 | * We use the SWBA interrupt only to keep track of the beacon |
2231 | * timers in order to detect HW merges (automatic TSF updates). | 2272 | * timers in order to detect automatic TSF updates. |
2232 | */ | 2273 | */ |
2233 | ath5k_beaconq_config(sc); | 2274 | ath5k_beaconq_config(sc); |
2234 | 2275 | ||
@@ -2441,8 +2482,8 @@ ath5k_intr(int irq, void *dev_id) | |||
2441 | * | 2482 | * |
2442 | * In IBSS mode we use this interrupt just to | 2483 | * In IBSS mode we use this interrupt just to |
2443 | * keep track of the next TBTT (target beacon | 2484 | * keep track of the next TBTT (target beacon |
2444 | * transmission time) in order to detect hardware | 2485 | * transmission time) in order to detect wether |
2445 | * merges (TSF updates). | 2486 | * automatic TSF updates happened. |
2446 | */ | 2487 | */ |
2447 | if (sc->opmode == IEEE80211_IF_TYPE_IBSS) { | 2488 | if (sc->opmode == IEEE80211_IF_TYPE_IBSS) { |
2448 | /* XXX: only if VEOL suppported */ | 2489 | /* XXX: only if VEOL suppported */ |
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 05bf4fb8f907..41d5fa34b544 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c | |||
@@ -200,7 +200,8 @@ static ssize_t read_file_tsf(struct file *file, char __user *user_buf, | |||
200 | { | 200 | { |
201 | struct ath5k_softc *sc = file->private_data; | 201 | struct ath5k_softc *sc = file->private_data; |
202 | char buf[100]; | 202 | char buf[100]; |
203 | snprintf(buf, sizeof(buf), "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah)); | 203 | snprintf(buf, sizeof(buf), "0x%016llx\n", |
204 | (unsigned long long)ath5k_hw_get_tsf64(sc->ah)); | ||
204 | return simple_read_from_buffer(user_buf, count, ppos, buf, 19); | 205 | return simple_read_from_buffer(user_buf, count, ppos, buf, 19); |
205 | } | 206 | } |
206 | 207 | ||
@@ -271,7 +272,8 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf, | |||
271 | 272 | ||
272 | tsf = ath5k_hw_get_tsf64(sc->ah); | 273 | tsf = ath5k_hw_get_tsf64(sc->ah); |
273 | len += snprintf(buf+len, sizeof(buf)-len, | 274 | len += snprintf(buf+len, sizeof(buf)-len, |
274 | "TSF\t\t0x%016llx\tTU: %08x\n", tsf, TSF_TO_TU(tsf)); | 275 | "TSF\t\t0x%016llx\tTU: %08x\n", |
276 | (unsigned long long)tsf, TSF_TO_TU(tsf)); | ||
275 | 277 | ||
276 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 278 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
277 | } | 279 | } |
@@ -497,15 +499,18 @@ ath5k_debug_dump_bands(struct ath5k_softc *sc) | |||
497 | } | 499 | } |
498 | 500 | ||
499 | static inline void | 501 | static inline void |
500 | ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done) | 502 | ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done, |
503 | struct ath5k_rx_status *rs) | ||
501 | { | 504 | { |
502 | struct ath5k_desc *ds = bf->desc; | 505 | struct ath5k_desc *ds = bf->desc; |
506 | struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx; | ||
503 | 507 | ||
504 | printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n", | 508 | printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n", |
505 | ds, (unsigned long long)bf->daddr, | 509 | ds, (unsigned long long)bf->daddr, |
506 | ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1, | 510 | ds->ds_link, ds->ds_data, |
507 | ds->ds_hw[0], ds->ds_hw[1], | 511 | rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1, |
508 | !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!'); | 512 | rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0, |
513 | !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'); | ||
509 | } | 514 | } |
510 | 515 | ||
511 | void | 516 | void |
@@ -513,6 +518,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) | |||
513 | { | 518 | { |
514 | struct ath5k_desc *ds; | 519 | struct ath5k_desc *ds; |
515 | struct ath5k_buf *bf; | 520 | struct ath5k_buf *bf; |
521 | struct ath5k_rx_status rs = {}; | ||
516 | int status; | 522 | int status; |
517 | 523 | ||
518 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) | 524 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) |
@@ -524,9 +530,9 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) | |||
524 | spin_lock_bh(&sc->rxbuflock); | 530 | spin_lock_bh(&sc->rxbuflock); |
525 | list_for_each_entry(bf, &sc->rxbuf, list) { | 531 | list_for_each_entry(bf, &sc->rxbuf, list) { |
526 | ds = bf->desc; | 532 | ds = bf->desc; |
527 | status = ah->ah_proc_rx_desc(ah, ds); | 533 | status = ah->ah_proc_rx_desc(ah, ds, &rs); |
528 | if (!status) | 534 | if (!status) |
529 | ath5k_debug_printrxbuf(bf, status == 0); | 535 | ath5k_debug_printrxbuf(bf, status == 0, &rs); |
530 | } | 536 | } |
531 | spin_unlock_bh(&sc->rxbuflock); | 537 | spin_unlock_bh(&sc->rxbuflock); |
532 | } | 538 | } |
@@ -550,19 +556,24 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc, | |||
550 | } | 556 | } |
551 | 557 | ||
552 | void | 558 | void |
553 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, | 559 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) |
554 | struct ath5k_buf *bf, int done) | ||
555 | { | 560 | { |
556 | struct ath5k_desc *ds = bf->desc; | 561 | struct ath5k_desc *ds = bf->desc; |
562 | struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212; | ||
563 | struct ath5k_tx_status ts = {}; | ||
564 | int done; | ||
557 | 565 | ||
558 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) | 566 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) |
559 | return; | 567 | return; |
560 | 568 | ||
569 | done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts); | ||
570 | |||
561 | printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x " | 571 | printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x " |
562 | "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link, | 572 | "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link, |
563 | ds->ds_data, ds->ds_ctl0, ds->ds_ctl1, | 573 | ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1, |
564 | ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3], | 574 | td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3, |
565 | !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!'); | 575 | td->tx_stat.tx_status_0, td->tx_stat.tx_status_1, |
576 | done ? ' ' : (ts.ts_status == 0) ? '*' : '!'); | ||
566 | } | 577 | } |
567 | 578 | ||
568 | #endif /* ifdef CONFIG_ATH5K_DEBUG */ | 579 | #endif /* ifdef CONFIG_ATH5K_DEBUG */ |
diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h index 8c0b5c57c76b..2cf8d18b10e3 100644 --- a/drivers/net/wireless/ath5k/debug.h +++ b/drivers/net/wireless/ath5k/debug.h | |||
@@ -160,8 +160,7 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc, | |||
160 | struct sk_buff *skb, const char *prefix, int tx); | 160 | struct sk_buff *skb, const char *prefix, int tx); |
161 | 161 | ||
162 | void | 162 | void |
163 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, | 163 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf); |
164 | struct ath5k_buf *bf, int done); | ||
165 | 164 | ||
166 | #else /* no debugging */ | 165 | #else /* no debugging */ |
167 | 166 | ||
@@ -199,8 +198,7 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc, | |||
199 | struct sk_buff *skb, const char *prefix, int tx) {} | 198 | struct sk_buff *skb, const char *prefix, int tx) {} |
200 | 199 | ||
201 | static inline void | 200 | static inline void |
202 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, | 201 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {} |
203 | struct ath5k_buf *bf, int done) {} | ||
204 | 202 | ||
205 | #endif /* ifdef CONFIG_ATH5K_DEBUG */ | 203 | #endif /* ifdef CONFIG_ATH5K_DEBUG */ |
206 | 204 | ||
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index eec2b806a0de..a4e312d4226e 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c | |||
@@ -48,14 +48,18 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, | |||
48 | static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *, | 48 | static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *, |
49 | unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, | 49 | unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, |
50 | unsigned int); | 50 | unsigned int); |
51 | static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *); | 51 | static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *, |
52 | struct ath5k_tx_status *); | ||
52 | static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, | 53 | static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, |
53 | unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, | 54 | unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, |
54 | unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, | 55 | unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, |
55 | unsigned int, unsigned int); | 56 | unsigned int, unsigned int); |
56 | static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *); | 57 | static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *, |
57 | static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *, struct ath5k_desc *); | 58 | struct ath5k_tx_status *); |
58 | static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *, struct ath5k_desc *); | 59 | static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *, |
60 | struct ath5k_rx_status *); | ||
61 | static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *, | ||
62 | struct ath5k_rx_status *); | ||
59 | static int ath5k_hw_get_capabilities(struct ath5k_hw *); | 63 | static int ath5k_hw_get_capabilities(struct ath5k_hw *); |
60 | 64 | ||
61 | static int ath5k_eeprom_init(struct ath5k_hw *); | 65 | static int ath5k_eeprom_init(struct ath5k_hw *); |
@@ -174,9 +178,9 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | |||
174 | } | 178 | } |
175 | 179 | ||
176 | if (ah->ah_version == AR5K_AR5212) | 180 | if (ah->ah_version == AR5K_AR5212) |
177 | ah->ah_proc_rx_desc = ath5k_hw_proc_new_rx_status; | 181 | ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; |
178 | else if (ah->ah_version <= AR5K_AR5211) | 182 | else if (ah->ah_version <= AR5K_AR5211) |
179 | ah->ah_proc_rx_desc = ath5k_hw_proc_old_rx_status; | 183 | ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status; |
180 | 184 | ||
181 | /* Bring device out of sleep and reset it's units */ | 185 | /* Bring device out of sleep and reset it's units */ |
182 | ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true); | 186 | ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true); |
@@ -208,7 +212,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | |||
208 | 212 | ||
209 | /* Identify single chip solutions */ | 213 | /* Identify single chip solutions */ |
210 | if((srev <= AR5K_SREV_VER_AR5414) && | 214 | if((srev <= AR5K_SREV_VER_AR5414) && |
211 | (srev >= AR5K_SREV_VER_AR2424)) { | 215 | (srev >= AR5K_SREV_VER_AR2413)) { |
212 | ah->ah_single_chip = true; | 216 | ah->ah_single_chip = true; |
213 | } else { | 217 | } else { |
214 | ah->ah_single_chip = false; | 218 | ah->ah_single_chip = false; |
@@ -223,10 +227,33 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | |||
223 | ah->ah_radio = AR5K_RF5110; | 227 | ah->ah_radio = AR5K_RF5110; |
224 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) { | 228 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) { |
225 | ah->ah_radio = AR5K_RF5111; | 229 | ah->ah_radio = AR5K_RF5111; |
226 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { | 230 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111; |
231 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) { | ||
232 | |||
227 | ah->ah_radio = AR5K_RF5112; | 233 | ah->ah_radio = AR5K_RF5112; |
234 | |||
235 | if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) { | ||
236 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; | ||
237 | } else { | ||
238 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; | ||
239 | } | ||
240 | |||
241 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { | ||
242 | ah->ah_radio = AR5K_RF2413; | ||
243 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; | ||
228 | } else { | 244 | } else { |
245 | |||
229 | ah->ah_radio = AR5K_RF5413; | 246 | ah->ah_radio = AR5K_RF5413; |
247 | |||
248 | if (ah->ah_mac_srev <= AR5K_SREV_VER_AR5424 && | ||
249 | ah->ah_mac_srev >= AR5K_SREV_VER_AR2424) | ||
250 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424; | ||
251 | else if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2425) | ||
252 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; | ||
253 | else | ||
254 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; | ||
255 | |||
256 | |||
230 | } | 257 | } |
231 | 258 | ||
232 | ah->ah_phy = AR5K_PHY(0); | 259 | ah->ah_phy = AR5K_PHY(0); |
@@ -277,7 +304,8 @@ err: | |||
277 | */ | 304 | */ |
278 | static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | 305 | static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) |
279 | { | 306 | { |
280 | u32 turbo, mode, clock; | 307 | struct pci_dev *pdev = ah->ah_sc->pdev; |
308 | u32 turbo, mode, clock, bus_flags; | ||
281 | int ret; | 309 | int ret; |
282 | 310 | ||
283 | turbo = 0; | 311 | turbo = 0; |
@@ -354,9 +382,15 @@ static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
354 | AR5K_PHY_TURBO); | 382 | AR5K_PHY_TURBO); |
355 | } | 383 | } |
356 | 384 | ||
357 | /* ...reset chipset and PCI device */ | 385 | /* reseting PCI on PCI-E cards results card to hang |
358 | if (ah->ah_single_chip == false && ath5k_hw_nic_reset(ah, | 386 | * and always return 0xffff... so we ingore that flag |
359 | AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI)) { | 387 | * for PCI-E cards */ |
388 | bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; | ||
389 | |||
390 | /* Reset chipset */ | ||
391 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | ||
392 | AR5K_RESET_CTL_BASEBAND | bus_flags); | ||
393 | if (ret) { | ||
360 | ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n"); | 394 | ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n"); |
361 | return -EIO; | 395 | return -EIO; |
362 | } | 396 | } |
@@ -565,7 +599,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, | |||
565 | struct ieee80211_channel *channel, bool change_channel) | 599 | struct ieee80211_channel *channel, bool change_channel) |
566 | { | 600 | { |
567 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 601 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
568 | u32 data, s_seq, s_ant, s_led[3]; | 602 | struct pci_dev *pdev = ah->ah_sc->pdev; |
603 | u32 data, s_seq, s_ant, s_led[3], dma_size; | ||
569 | unsigned int i, mode, freq, ee_mode, ant[2]; | 604 | unsigned int i, mode, freq, ee_mode, ant[2]; |
570 | int ret; | 605 | int ret; |
571 | 606 | ||
@@ -617,7 +652,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, | |||
617 | if (ah->ah_version != AR5K_AR5210) { | 652 | if (ah->ah_version != AR5K_AR5210) { |
618 | if (ah->ah_radio != AR5K_RF5111 && | 653 | if (ah->ah_radio != AR5K_RF5111 && |
619 | ah->ah_radio != AR5K_RF5112 && | 654 | ah->ah_radio != AR5K_RF5112 && |
620 | ah->ah_radio != AR5K_RF5413) { | 655 | ah->ah_radio != AR5K_RF5413 && |
656 | ah->ah_radio != AR5K_RF2413) { | ||
621 | ATH5K_ERR(ah->ah_sc, | 657 | ATH5K_ERR(ah->ah_sc, |
622 | "invalid phy radio: %u\n", ah->ah_radio); | 658 | "invalid phy radio: %u\n", ah->ah_radio); |
623 | return -EINVAL; | 659 | return -EINVAL; |
@@ -692,15 +728,26 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, | |||
692 | /* | 728 | /* |
693 | * Write some more initial register settings | 729 | * Write some more initial register settings |
694 | */ | 730 | */ |
695 | if (ah->ah_version > AR5K_AR5211){ /* found on 5213+ */ | 731 | if (ah->ah_version == AR5K_AR5212) { |
696 | ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11)); | 732 | ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11)); |
697 | 733 | ||
698 | if (channel->hw_value == CHANNEL_G) | 734 | if (channel->hw_value == CHANNEL_G) |
699 | ath5k_hw_reg_write(ah, 0x00f80d80, AR5K_PHY(83)); /* 0x00fc0ec0 */ | 735 | if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413) |
736 | ath5k_hw_reg_write(ah, 0x00f80d80, | ||
737 | AR5K_PHY(83)); | ||
738 | else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424) | ||
739 | ath5k_hw_reg_write(ah, 0x00380140, | ||
740 | AR5K_PHY(83)); | ||
741 | else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425) | ||
742 | ath5k_hw_reg_write(ah, 0x00fc0ec0, | ||
743 | AR5K_PHY(83)); | ||
744 | else /* 2425 */ | ||
745 | ath5k_hw_reg_write(ah, 0x00fc0fc0, | ||
746 | AR5K_PHY(83)); | ||
700 | else | 747 | else |
701 | ath5k_hw_reg_write(ah, 0x00000000, AR5K_PHY(83)); | 748 | ath5k_hw_reg_write(ah, 0x00000000, |
749 | AR5K_PHY(83)); | ||
702 | 750 | ||
703 | ath5k_hw_reg_write(ah, 0x000001b5, 0xa228); /* 0x000009b5 */ | ||
704 | ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); | 751 | ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); |
705 | ath5k_hw_reg_write(ah, 0x0000000f, 0x8060); | 752 | ath5k_hw_reg_write(ah, 0x0000000f, 0x8060); |
706 | ath5k_hw_reg_write(ah, 0x00000000, 0xa254); | 753 | ath5k_hw_reg_write(ah, 0x00000000, 0xa254); |
@@ -876,13 +923,24 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, | |||
876 | 923 | ||
877 | /* | 924 | /* |
878 | * Set Rx/Tx DMA Configuration | 925 | * Set Rx/Tx DMA Configuration |
879 | *(passing dma size not available on 5210) | 926 | * |
927 | * Set maximum DMA size (512) except for PCI-E cards since | ||
928 | * it causes rx overruns and tx errors (tested on 5424 but since | ||
929 | * rx overruns also occur on 5416/5418 with madwifi we set 128 | ||
930 | * for all PCI-E cards to be safe). | ||
931 | * | ||
932 | * In dumps this is 128 for allchips. | ||
933 | * | ||
934 | * XXX: need to check 5210 for this | ||
935 | * TODO: Check out tx triger level, it's always 64 on dumps but I | ||
936 | * guess we can tweak it and see how it goes ;-) | ||
880 | */ | 937 | */ |
938 | dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B; | ||
881 | if (ah->ah_version != AR5K_AR5210) { | 939 | if (ah->ah_version != AR5K_AR5210) { |
882 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_SDMAMR, | 940 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, |
883 | AR5K_DMASIZE_512B | AR5K_TXCFG_DMASIZE); | 941 | AR5K_TXCFG_SDMAMR, dma_size); |
884 | AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_SDMAMW, | 942 | AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, |
885 | AR5K_DMASIZE_512B); | 943 | AR5K_RXCFG_SDMAMW, dma_size); |
886 | } | 944 | } |
887 | 945 | ||
888 | /* | 946 | /* |
@@ -972,6 +1030,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, | |||
972 | 1030 | ||
973 | /* | 1031 | /* |
974 | * Set the 32MHz reference clock on 5212 phy clock sleep register | 1032 | * Set the 32MHz reference clock on 5212 phy clock sleep register |
1033 | * | ||
1034 | * TODO: Find out how to switch to external 32Khz clock to save power | ||
975 | */ | 1035 | */ |
976 | if (ah->ah_version == AR5K_AR5212) { | 1036 | if (ah->ah_version == AR5K_AR5212) { |
977 | ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR); | 1037 | ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR); |
@@ -979,9 +1039,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, | |||
979 | ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL); | 1039 | ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL); |
980 | ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); | 1040 | ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); |
981 | ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); | 1041 | ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); |
982 | ath5k_hw_reg_write(ah, ah->ah_radio == AR5K_RF5111 ? | 1042 | ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING); |
983 | AR5K_PHY_SPENDING_RF5111 : AR5K_PHY_SPENDING_RF5112, | 1043 | } |
984 | AR5K_PHY_SPENDING); | 1044 | |
1045 | if (ah->ah_version == AR5K_AR5212) { | ||
1046 | ath5k_hw_reg_write(ah, 0x000100aa, 0x8118); | ||
1047 | ath5k_hw_reg_write(ah, 0x00003210, 0x811c); | ||
1048 | ath5k_hw_reg_write(ah, 0x00000052, 0x8108); | ||
1049 | if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2413) | ||
1050 | ath5k_hw_reg_write(ah, 0x00000004, 0x8120); | ||
985 | } | 1051 | } |
986 | 1052 | ||
987 | /* | 1053 | /* |
@@ -2228,8 +2294,8 @@ void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) | |||
2228 | * Set simple BSSID mask on 5212 | 2294 | * Set simple BSSID mask on 5212 |
2229 | */ | 2295 | */ |
2230 | if (ah->ah_version == AR5K_AR5212) { | 2296 | if (ah->ah_version == AR5K_AR5212) { |
2231 | ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM0); | 2297 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0); |
2232 | ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM1); | 2298 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1); |
2233 | } | 2299 | } |
2234 | 2300 | ||
2235 | /* | 2301 | /* |
@@ -2374,6 +2440,8 @@ void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | |||
2374 | { | 2440 | { |
2375 | ATH5K_TRACE(ah->ah_sc); | 2441 | ATH5K_TRACE(ah->ah_sc); |
2376 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | 2442 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); |
2443 | |||
2444 | /* TODO: ANI Support */ | ||
2377 | } | 2445 | } |
2378 | 2446 | ||
2379 | /* | 2447 | /* |
@@ -2383,6 +2451,8 @@ void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah) | |||
2383 | { | 2451 | { |
2384 | ATH5K_TRACE(ah->ah_sc); | 2452 | ATH5K_TRACE(ah->ah_sc); |
2385 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | 2453 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); |
2454 | |||
2455 | /* TODO: ANI Support */ | ||
2386 | } | 2456 | } |
2387 | 2457 | ||
2388 | /* | 2458 | /* |
@@ -3456,10 +3526,10 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
3456 | unsigned int rtscts_rate, unsigned int rtscts_duration) | 3526 | unsigned int rtscts_rate, unsigned int rtscts_duration) |
3457 | { | 3527 | { |
3458 | u32 frame_type; | 3528 | u32 frame_type; |
3459 | struct ath5k_hw_2w_tx_desc *tx_desc; | 3529 | struct ath5k_hw_2w_tx_ctl *tx_ctl; |
3460 | unsigned int frame_len; | 3530 | unsigned int frame_len; |
3461 | 3531 | ||
3462 | tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0; | 3532 | tx_ctl = &desc->ud.ds_tx5210.tx_ctl; |
3463 | 3533 | ||
3464 | /* | 3534 | /* |
3465 | * Validate input | 3535 | * Validate input |
@@ -3478,12 +3548,8 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
3478 | return -EINVAL; | 3548 | return -EINVAL; |
3479 | } | 3549 | } |
3480 | 3550 | ||
3481 | /* Clear status descriptor */ | 3551 | /* Clear descriptor */ |
3482 | memset(desc->ds_hw, 0, sizeof(struct ath5k_hw_tx_status)); | 3552 | memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc)); |
3483 | |||
3484 | /* Initialize control descriptor */ | ||
3485 | tx_desc->tx_control_0 = 0; | ||
3486 | tx_desc->tx_control_1 = 0; | ||
3487 | 3553 | ||
3488 | /* Setup control descriptor */ | 3554 | /* Setup control descriptor */ |
3489 | 3555 | ||
@@ -3495,7 +3561,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
3495 | if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) | 3561 | if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) |
3496 | return -EINVAL; | 3562 | return -EINVAL; |
3497 | 3563 | ||
3498 | tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; | 3564 | tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; |
3499 | 3565 | ||
3500 | /* Verify and set buffer length */ | 3566 | /* Verify and set buffer length */ |
3501 | 3567 | ||
@@ -3506,7 +3572,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
3506 | if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) | 3572 | if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) |
3507 | return -EINVAL; | 3573 | return -EINVAL; |
3508 | 3574 | ||
3509 | tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; | 3575 | tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; |
3510 | 3576 | ||
3511 | /* | 3577 | /* |
3512 | * Verify and set header length | 3578 | * Verify and set header length |
@@ -3515,7 +3581,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
3515 | if (ah->ah_version == AR5K_AR5210) { | 3581 | if (ah->ah_version == AR5K_AR5210) { |
3516 | if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN) | 3582 | if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN) |
3517 | return -EINVAL; | 3583 | return -EINVAL; |
3518 | tx_desc->tx_control_0 |= | 3584 | tx_ctl->tx_control_0 |= |
3519 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); | 3585 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); |
3520 | } | 3586 | } |
3521 | 3587 | ||
@@ -3531,19 +3597,19 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
3531 | frame_type = type /*<< 2 ?*/; | 3597 | frame_type = type /*<< 2 ?*/; |
3532 | } | 3598 | } |
3533 | 3599 | ||
3534 | tx_desc->tx_control_0 |= | 3600 | tx_ctl->tx_control_0 |= |
3535 | AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) | | 3601 | AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) | |
3536 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | 3602 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); |
3537 | } else { | 3603 | } else { |
3538 | tx_desc->tx_control_0 |= | 3604 | tx_ctl->tx_control_0 |= |
3539 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) | | 3605 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) | |
3540 | AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); | 3606 | AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); |
3541 | tx_desc->tx_control_1 |= | 3607 | tx_ctl->tx_control_1 |= |
3542 | AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE); | 3608 | AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE); |
3543 | } | 3609 | } |
3544 | #define _TX_FLAGS(_c, _flag) \ | 3610 | #define _TX_FLAGS(_c, _flag) \ |
3545 | if (flags & AR5K_TXDESC_##_flag) \ | 3611 | if (flags & AR5K_TXDESC_##_flag) \ |
3546 | tx_desc->tx_control_##_c |= \ | 3612 | tx_ctl->tx_control_##_c |= \ |
3547 | AR5K_2W_TX_DESC_CTL##_c##_##_flag | 3613 | AR5K_2W_TX_DESC_CTL##_c##_##_flag |
3548 | 3614 | ||
3549 | _TX_FLAGS(0, CLRDMASK); | 3615 | _TX_FLAGS(0, CLRDMASK); |
@@ -3558,9 +3624,9 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
3558 | * WEP crap | 3624 | * WEP crap |
3559 | */ | 3625 | */ |
3560 | if (key_index != AR5K_TXKEYIX_INVALID) { | 3626 | if (key_index != AR5K_TXKEYIX_INVALID) { |
3561 | tx_desc->tx_control_0 |= | 3627 | tx_ctl->tx_control_0 |= |
3562 | AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | 3628 | AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; |
3563 | tx_desc->tx_control_1 |= | 3629 | tx_ctl->tx_control_1 |= |
3564 | AR5K_REG_SM(key_index, | 3630 | AR5K_REG_SM(key_index, |
3565 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); | 3631 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); |
3566 | } | 3632 | } |
@@ -3570,7 +3636,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
3570 | */ | 3636 | */ |
3571 | if ((ah->ah_version == AR5K_AR5210) && | 3637 | if ((ah->ah_version == AR5K_AR5210) && |
3572 | (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) | 3638 | (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) |
3573 | tx_desc->tx_control_1 |= rtscts_duration & | 3639 | tx_ctl->tx_control_1 |= rtscts_duration & |
3574 | AR5K_2W_TX_DESC_CTL1_RTS_DURATION; | 3640 | AR5K_2W_TX_DESC_CTL1_RTS_DURATION; |
3575 | 3641 | ||
3576 | return 0; | 3642 | return 0; |
@@ -3586,13 +3652,11 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
3586 | unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate, | 3652 | unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate, |
3587 | unsigned int rtscts_duration) | 3653 | unsigned int rtscts_duration) |
3588 | { | 3654 | { |
3589 | struct ath5k_hw_4w_tx_desc *tx_desc; | 3655 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
3590 | struct ath5k_hw_tx_status *tx_status; | ||
3591 | unsigned int frame_len; | 3656 | unsigned int frame_len; |
3592 | 3657 | ||
3593 | ATH5K_TRACE(ah->ah_sc); | 3658 | ATH5K_TRACE(ah->ah_sc); |
3594 | tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0; | 3659 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; |
3595 | tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2]; | ||
3596 | 3660 | ||
3597 | /* | 3661 | /* |
3598 | * Validate input | 3662 | * Validate input |
@@ -3611,14 +3675,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
3611 | return -EINVAL; | 3675 | return -EINVAL; |
3612 | } | 3676 | } |
3613 | 3677 | ||
3614 | /* Clear status descriptor */ | 3678 | /* Clear descriptor */ |
3615 | memset(tx_status, 0, sizeof(struct ath5k_hw_tx_status)); | 3679 | memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); |
3616 | |||
3617 | /* Initialize control descriptor */ | ||
3618 | tx_desc->tx_control_0 = 0; | ||
3619 | tx_desc->tx_control_1 = 0; | ||
3620 | tx_desc->tx_control_2 = 0; | ||
3621 | tx_desc->tx_control_3 = 0; | ||
3622 | 3680 | ||
3623 | /* Setup control descriptor */ | 3681 | /* Setup control descriptor */ |
3624 | 3682 | ||
@@ -3630,7 +3688,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
3630 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) | 3688 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) |
3631 | return -EINVAL; | 3689 | return -EINVAL; |
3632 | 3690 | ||
3633 | tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; | 3691 | tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; |
3634 | 3692 | ||
3635 | /* Verify and set buffer length */ | 3693 | /* Verify and set buffer length */ |
3636 | 3694 | ||
@@ -3641,20 +3699,20 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
3641 | if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) | 3699 | if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) |
3642 | return -EINVAL; | 3700 | return -EINVAL; |
3643 | 3701 | ||
3644 | tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; | 3702 | tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; |
3645 | 3703 | ||
3646 | tx_desc->tx_control_0 |= | 3704 | tx_ctl->tx_control_0 |= |
3647 | AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | | 3705 | AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | |
3648 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); | 3706 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); |
3649 | tx_desc->tx_control_1 |= AR5K_REG_SM(type, | 3707 | tx_ctl->tx_control_1 |= AR5K_REG_SM(type, |
3650 | AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); | 3708 | AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); |
3651 | tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, | 3709 | tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, |
3652 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); | 3710 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); |
3653 | tx_desc->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | 3711 | tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; |
3654 | 3712 | ||
3655 | #define _TX_FLAGS(_c, _flag) \ | 3713 | #define _TX_FLAGS(_c, _flag) \ |
3656 | if (flags & AR5K_TXDESC_##_flag) \ | 3714 | if (flags & AR5K_TXDESC_##_flag) \ |
3657 | tx_desc->tx_control_##_c |= \ | 3715 | tx_ctl->tx_control_##_c |= \ |
3658 | AR5K_4W_TX_DESC_CTL##_c##_##_flag | 3716 | AR5K_4W_TX_DESC_CTL##_c##_##_flag |
3659 | 3717 | ||
3660 | _TX_FLAGS(0, CLRDMASK); | 3718 | _TX_FLAGS(0, CLRDMASK); |
@@ -3670,8 +3728,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
3670 | * WEP crap | 3728 | * WEP crap |
3671 | */ | 3729 | */ |
3672 | if (key_index != AR5K_TXKEYIX_INVALID) { | 3730 | if (key_index != AR5K_TXKEYIX_INVALID) { |
3673 | tx_desc->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | 3731 | tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; |
3674 | tx_desc->tx_control_1 |= AR5K_REG_SM(key_index, | 3732 | tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, |
3675 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); | 3733 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); |
3676 | } | 3734 | } |
3677 | 3735 | ||
@@ -3682,9 +3740,9 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
3682 | if ((flags & AR5K_TXDESC_RTSENA) && | 3740 | if ((flags & AR5K_TXDESC_RTSENA) && |
3683 | (flags & AR5K_TXDESC_CTSENA)) | 3741 | (flags & AR5K_TXDESC_CTSENA)) |
3684 | return -EINVAL; | 3742 | return -EINVAL; |
3685 | tx_desc->tx_control_2 |= rtscts_duration & | 3743 | tx_ctl->tx_control_2 |= rtscts_duration & |
3686 | AR5K_4W_TX_DESC_CTL2_RTS_DURATION; | 3744 | AR5K_4W_TX_DESC_CTL2_RTS_DURATION; |
3687 | tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate, | 3745 | tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, |
3688 | AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); | 3746 | AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); |
3689 | } | 3747 | } |
3690 | 3748 | ||
@@ -3699,7 +3757,7 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
3699 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2, | 3757 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2, |
3700 | unsigned int tx_rate3, u_int tx_tries3) | 3758 | unsigned int tx_rate3, u_int tx_tries3) |
3701 | { | 3759 | { |
3702 | struct ath5k_hw_4w_tx_desc *tx_desc; | 3760 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
3703 | 3761 | ||
3704 | /* | 3762 | /* |
3705 | * Rates can be 0 as long as the retry count is 0 too. | 3763 | * Rates can be 0 as long as the retry count is 0 too. |
@@ -3716,14 +3774,14 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
3716 | } | 3774 | } |
3717 | 3775 | ||
3718 | if (ah->ah_version == AR5K_AR5212) { | 3776 | if (ah->ah_version == AR5K_AR5212) { |
3719 | tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0; | 3777 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; |
3720 | 3778 | ||
3721 | #define _XTX_TRIES(_n) \ | 3779 | #define _XTX_TRIES(_n) \ |
3722 | if (tx_tries##_n) { \ | 3780 | if (tx_tries##_n) { \ |
3723 | tx_desc->tx_control_2 |= \ | 3781 | tx_ctl->tx_control_2 |= \ |
3724 | AR5K_REG_SM(tx_tries##_n, \ | 3782 | AR5K_REG_SM(tx_tries##_n, \ |
3725 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \ | 3783 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \ |
3726 | tx_desc->tx_control_3 |= \ | 3784 | tx_ctl->tx_control_3 |= \ |
3727 | AR5K_REG_SM(tx_rate##_n, \ | 3785 | AR5K_REG_SM(tx_rate##_n, \ |
3728 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \ | 3786 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \ |
3729 | } | 3787 | } |
@@ -3744,13 +3802,15 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
3744 | * Proccess the tx status descriptor on 5210/5211 | 3802 | * Proccess the tx status descriptor on 5210/5211 |
3745 | */ | 3803 | */ |
3746 | static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | 3804 | static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, |
3747 | struct ath5k_desc *desc) | 3805 | struct ath5k_desc *desc, struct ath5k_tx_status *ts) |
3748 | { | 3806 | { |
3807 | struct ath5k_hw_2w_tx_ctl *tx_ctl; | ||
3749 | struct ath5k_hw_tx_status *tx_status; | 3808 | struct ath5k_hw_tx_status *tx_status; |
3750 | struct ath5k_hw_2w_tx_desc *tx_desc; | ||
3751 | 3809 | ||
3752 | tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0; | 3810 | ATH5K_TRACE(ah->ah_sc); |
3753 | tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[0]; | 3811 | |
3812 | tx_ctl = &desc->ud.ds_tx5210.tx_ctl; | ||
3813 | tx_status = &desc->ud.ds_tx5210.tx_stat; | ||
3754 | 3814 | ||
3755 | /* No frame has been send or error */ | 3815 | /* No frame has been send or error */ |
3756 | if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) | 3816 | if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) |
@@ -3759,32 +3819,32 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | |||
3759 | /* | 3819 | /* |
3760 | * Get descriptor status | 3820 | * Get descriptor status |
3761 | */ | 3821 | */ |
3762 | desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, | 3822 | ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, |
3763 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); | 3823 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); |
3764 | desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, | 3824 | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, |
3765 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); | 3825 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); |
3766 | desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, | 3826 | ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, |
3767 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); | 3827 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); |
3768 | /*TODO: desc->ds_us.tx.ts_virtcol + test*/ | 3828 | /*TODO: ts->ts_virtcol + test*/ |
3769 | desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, | 3829 | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, |
3770 | AR5K_DESC_TX_STATUS1_SEQ_NUM); | 3830 | AR5K_DESC_TX_STATUS1_SEQ_NUM); |
3771 | desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, | 3831 | ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, |
3772 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | 3832 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); |
3773 | desc->ds_us.tx.ts_antenna = 1; | 3833 | ts->ts_antenna = 1; |
3774 | desc->ds_us.tx.ts_status = 0; | 3834 | ts->ts_status = 0; |
3775 | desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0, | 3835 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0, |
3776 | AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | 3836 | AR5K_2W_TX_DESC_CTL0_XMIT_RATE); |
3777 | 3837 | ||
3778 | if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){ | 3838 | if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){ |
3779 | if (tx_status->tx_status_0 & | 3839 | if (tx_status->tx_status_0 & |
3780 | AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) | 3840 | AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) |
3781 | desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY; | 3841 | ts->ts_status |= AR5K_TXERR_XRETRY; |
3782 | 3842 | ||
3783 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) | 3843 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) |
3784 | desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO; | 3844 | ts->ts_status |= AR5K_TXERR_FIFO; |
3785 | 3845 | ||
3786 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) | 3846 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) |
3787 | desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT; | 3847 | ts->ts_status |= AR5K_TXERR_FILT; |
3788 | } | 3848 | } |
3789 | 3849 | ||
3790 | return 0; | 3850 | return 0; |
@@ -3794,14 +3854,15 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | |||
3794 | * Proccess a tx descriptor on 5212 | 3854 | * Proccess a tx descriptor on 5212 |
3795 | */ | 3855 | */ |
3796 | static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | 3856 | static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, |
3797 | struct ath5k_desc *desc) | 3857 | struct ath5k_desc *desc, struct ath5k_tx_status *ts) |
3798 | { | 3858 | { |
3859 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | ||
3799 | struct ath5k_hw_tx_status *tx_status; | 3860 | struct ath5k_hw_tx_status *tx_status; |
3800 | struct ath5k_hw_4w_tx_desc *tx_desc; | ||
3801 | 3861 | ||
3802 | ATH5K_TRACE(ah->ah_sc); | 3862 | ATH5K_TRACE(ah->ah_sc); |
3803 | tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0; | 3863 | |
3804 | tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2]; | 3864 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; |
3865 | tx_status = &desc->ud.ds_tx5212.tx_stat; | ||
3805 | 3866 | ||
3806 | /* No frame has been send or error */ | 3867 | /* No frame has been send or error */ |
3807 | if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) | 3868 | if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) |
@@ -3810,42 +3871,42 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
3810 | /* | 3871 | /* |
3811 | * Get descriptor status | 3872 | * Get descriptor status |
3812 | */ | 3873 | */ |
3813 | desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, | 3874 | ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, |
3814 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); | 3875 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); |
3815 | desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, | 3876 | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, |
3816 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); | 3877 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); |
3817 | desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, | 3878 | ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, |
3818 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); | 3879 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); |
3819 | desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, | 3880 | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, |
3820 | AR5K_DESC_TX_STATUS1_SEQ_NUM); | 3881 | AR5K_DESC_TX_STATUS1_SEQ_NUM); |
3821 | desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, | 3882 | ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, |
3822 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | 3883 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); |
3823 | desc->ds_us.tx.ts_antenna = (tx_status->tx_status_1 & | 3884 | ts->ts_antenna = (tx_status->tx_status_1 & |
3824 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; | 3885 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; |
3825 | desc->ds_us.tx.ts_status = 0; | 3886 | ts->ts_status = 0; |
3826 | 3887 | ||
3827 | switch (AR5K_REG_MS(tx_status->tx_status_1, | 3888 | switch (AR5K_REG_MS(tx_status->tx_status_1, |
3828 | AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) { | 3889 | AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) { |
3829 | case 0: | 3890 | case 0: |
3830 | desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 & | 3891 | ts->ts_rate = tx_ctl->tx_control_3 & |
3831 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | 3892 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; |
3832 | break; | 3893 | break; |
3833 | case 1: | 3894 | case 1: |
3834 | desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3, | 3895 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, |
3835 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); | 3896 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); |
3836 | desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2, | 3897 | ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, |
3837 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); | 3898 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); |
3838 | break; | 3899 | break; |
3839 | case 2: | 3900 | case 2: |
3840 | desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3, | 3901 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, |
3841 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); | 3902 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); |
3842 | desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2, | 3903 | ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, |
3843 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); | 3904 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); |
3844 | break; | 3905 | break; |
3845 | case 3: | 3906 | case 3: |
3846 | desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3, | 3907 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, |
3847 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); | 3908 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); |
3848 | desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2, | 3909 | ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, |
3849 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3); | 3910 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3); |
3850 | break; | 3911 | break; |
3851 | } | 3912 | } |
@@ -3853,13 +3914,13 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
3853 | if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){ | 3914 | if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){ |
3854 | if (tx_status->tx_status_0 & | 3915 | if (tx_status->tx_status_0 & |
3855 | AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) | 3916 | AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) |
3856 | desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY; | 3917 | ts->ts_status |= AR5K_TXERR_XRETRY; |
3857 | 3918 | ||
3858 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) | 3919 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) |
3859 | desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO; | 3920 | ts->ts_status |= AR5K_TXERR_FIFO; |
3860 | 3921 | ||
3861 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) | 3922 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) |
3862 | desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT; | 3923 | ts->ts_status |= AR5K_TXERR_FILT; |
3863 | } | 3924 | } |
3864 | 3925 | ||
3865 | return 0; | 3926 | return 0; |
@@ -3875,31 +3936,27 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
3875 | int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | 3936 | int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, |
3876 | u32 size, unsigned int flags) | 3937 | u32 size, unsigned int flags) |
3877 | { | 3938 | { |
3878 | struct ath5k_rx_desc *rx_desc; | 3939 | struct ath5k_hw_rx_ctl *rx_ctl; |
3879 | 3940 | ||
3880 | ATH5K_TRACE(ah->ah_sc); | 3941 | ATH5K_TRACE(ah->ah_sc); |
3881 | rx_desc = (struct ath5k_rx_desc *)&desc->ds_ctl0; | 3942 | rx_ctl = &desc->ud.ds_rx.rx_ctl; |
3882 | 3943 | ||
3883 | /* | 3944 | /* |
3884 | *Clear ds_hw | 3945 | * Clear the descriptor |
3885 | * If we don't clean the status descriptor, | 3946 | * If we don't clean the status descriptor, |
3886 | * while scanning we get too many results, | 3947 | * while scanning we get too many results, |
3887 | * most of them virtual, after some secs | 3948 | * most of them virtual, after some secs |
3888 | * of scanning system hangs. M.F. | 3949 | * of scanning system hangs. M.F. |
3889 | */ | 3950 | */ |
3890 | memset(desc->ds_hw, 0, sizeof(desc->ds_hw)); | 3951 | memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc)); |
3891 | |||
3892 | /*Initialize rx descriptor*/ | ||
3893 | rx_desc->rx_control_0 = 0; | ||
3894 | rx_desc->rx_control_1 = 0; | ||
3895 | 3952 | ||
3896 | /* Setup descriptor */ | 3953 | /* Setup descriptor */ |
3897 | rx_desc->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; | 3954 | rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; |
3898 | if (unlikely(rx_desc->rx_control_1 != size)) | 3955 | if (unlikely(rx_ctl->rx_control_1 != size)) |
3899 | return -EINVAL; | 3956 | return -EINVAL; |
3900 | 3957 | ||
3901 | if (flags & AR5K_RXDESC_INTREQ) | 3958 | if (flags & AR5K_RXDESC_INTREQ) |
3902 | rx_desc->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; | 3959 | rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; |
3903 | 3960 | ||
3904 | return 0; | 3961 | return 0; |
3905 | } | 3962 | } |
@@ -3907,67 +3964,68 @@ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
3907 | /* | 3964 | /* |
3908 | * Proccess the rx status descriptor on 5210/5211 | 3965 | * Proccess the rx status descriptor on 5210/5211 |
3909 | */ | 3966 | */ |
3910 | static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah, | 3967 | static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, |
3911 | struct ath5k_desc *desc) | 3968 | struct ath5k_desc *desc, struct ath5k_rx_status *rs) |
3912 | { | 3969 | { |
3913 | struct ath5k_hw_old_rx_status *rx_status; | 3970 | struct ath5k_hw_rx_status *rx_status; |
3914 | 3971 | ||
3915 | rx_status = (struct ath5k_hw_old_rx_status *)&desc->ds_hw[0]; | 3972 | rx_status = &desc->ud.ds_rx.u.rx_stat; |
3916 | 3973 | ||
3917 | /* No frame received / not ready */ | 3974 | /* No frame received / not ready */ |
3918 | if (unlikely((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_DONE) | 3975 | if (unlikely((rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE) |
3919 | == 0)) | 3976 | == 0)) |
3920 | return -EINPROGRESS; | 3977 | return -EINPROGRESS; |
3921 | 3978 | ||
3922 | /* | 3979 | /* |
3923 | * Frame receive status | 3980 | * Frame receive status |
3924 | */ | 3981 | */ |
3925 | desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 & | 3982 | rs->rs_datalen = rx_status->rx_status_0 & |
3926 | AR5K_OLD_RX_DESC_STATUS0_DATA_LEN; | 3983 | AR5K_5210_RX_DESC_STATUS0_DATA_LEN; |
3927 | desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, | 3984 | rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, |
3928 | AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL); | 3985 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); |
3929 | desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0, | 3986 | rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, |
3930 | AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE); | 3987 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); |
3931 | desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 & | 3988 | rs->rs_antenna = rx_status->rx_status_0 & |
3932 | AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA; | 3989 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA; |
3933 | desc->ds_us.rx.rs_more = rx_status->rx_status_0 & | 3990 | rs->rs_more = rx_status->rx_status_0 & |
3934 | AR5K_OLD_RX_DESC_STATUS0_MORE; | 3991 | AR5K_5210_RX_DESC_STATUS0_MORE; |
3935 | desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | 3992 | /* TODO: this timestamp is 13 bit, later on we assume 15 bit */ |
3936 | AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | 3993 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, |
3937 | desc->ds_us.rx.rs_status = 0; | 3994 | AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); |
3995 | rs->rs_status = 0; | ||
3938 | 3996 | ||
3939 | /* | 3997 | /* |
3940 | * Key table status | 3998 | * Key table status |
3941 | */ | 3999 | */ |
3942 | if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID) | 4000 | if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID) |
3943 | desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, | 4001 | rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, |
3944 | AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX); | 4002 | AR5K_5210_RX_DESC_STATUS1_KEY_INDEX); |
3945 | else | 4003 | else |
3946 | desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID; | 4004 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; |
3947 | 4005 | ||
3948 | /* | 4006 | /* |
3949 | * Receive/descriptor errors | 4007 | * Receive/descriptor errors |
3950 | */ | 4008 | */ |
3951 | if ((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK) | 4009 | if ((rx_status->rx_status_1 & |
3952 | == 0) { | 4010 | AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) { |
3953 | if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR) | 4011 | if (rx_status->rx_status_1 & |
3954 | desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC; | 4012 | AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) |
4013 | rs->rs_status |= AR5K_RXERR_CRC; | ||
3955 | 4014 | ||
3956 | if (rx_status->rx_status_1 & | 4015 | if (rx_status->rx_status_1 & |
3957 | AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN) | 4016 | AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN) |
3958 | desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO; | 4017 | rs->rs_status |= AR5K_RXERR_FIFO; |
3959 | 4018 | ||
3960 | if (rx_status->rx_status_1 & | 4019 | if (rx_status->rx_status_1 & |
3961 | AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR) { | 4020 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { |
3962 | desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY; | 4021 | rs->rs_status |= AR5K_RXERR_PHY; |
3963 | desc->ds_us.rx.rs_phyerr = | 4022 | rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, |
3964 | AR5K_REG_MS(rx_status->rx_status_1, | 4023 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); |
3965 | AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR); | ||
3966 | } | 4024 | } |
3967 | 4025 | ||
3968 | if (rx_status->rx_status_1 & | 4026 | if (rx_status->rx_status_1 & |
3969 | AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) | 4027 | AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) |
3970 | desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT; | 4028 | rs->rs_status |= AR5K_RXERR_DECRYPT; |
3971 | } | 4029 | } |
3972 | 4030 | ||
3973 | return 0; | 4031 | return 0; |
@@ -3976,71 +4034,72 @@ static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah, | |||
3976 | /* | 4034 | /* |
3977 | * Proccess the rx status descriptor on 5212 | 4035 | * Proccess the rx status descriptor on 5212 |
3978 | */ | 4036 | */ |
3979 | static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah, | 4037 | static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, |
3980 | struct ath5k_desc *desc) | 4038 | struct ath5k_desc *desc, struct ath5k_rx_status *rs) |
3981 | { | 4039 | { |
3982 | struct ath5k_hw_new_rx_status *rx_status; | 4040 | struct ath5k_hw_rx_status *rx_status; |
3983 | struct ath5k_hw_rx_error *rx_err; | 4041 | struct ath5k_hw_rx_error *rx_err; |
3984 | 4042 | ||
3985 | ATH5K_TRACE(ah->ah_sc); | 4043 | ATH5K_TRACE(ah->ah_sc); |
3986 | rx_status = (struct ath5k_hw_new_rx_status *)&desc->ds_hw[0]; | 4044 | rx_status = &desc->ud.ds_rx.u.rx_stat; |
3987 | 4045 | ||
3988 | /* Overlay on error */ | 4046 | /* Overlay on error */ |
3989 | rx_err = (struct ath5k_hw_rx_error *)&desc->ds_hw[0]; | 4047 | rx_err = &desc->ud.ds_rx.u.rx_err; |
3990 | 4048 | ||
3991 | /* No frame received / not ready */ | 4049 | /* No frame received / not ready */ |
3992 | if (unlikely((rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_DONE) | 4050 | if (unlikely((rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE) |
3993 | == 0)) | 4051 | == 0)) |
3994 | return -EINPROGRESS; | 4052 | return -EINPROGRESS; |
3995 | 4053 | ||
3996 | /* | 4054 | /* |
3997 | * Frame receive status | 4055 | * Frame receive status |
3998 | */ | 4056 | */ |
3999 | desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 & | 4057 | rs->rs_datalen = rx_status->rx_status_0 & |
4000 | AR5K_NEW_RX_DESC_STATUS0_DATA_LEN; | 4058 | AR5K_5212_RX_DESC_STATUS0_DATA_LEN; |
4001 | desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, | 4059 | rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, |
4002 | AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL); | 4060 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); |
4003 | desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0, | 4061 | rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, |
4004 | AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE); | 4062 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); |
4005 | desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 & | 4063 | rs->rs_antenna = rx_status->rx_status_0 & |
4006 | AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA; | 4064 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA; |
4007 | desc->ds_us.rx.rs_more = rx_status->rx_status_0 & | 4065 | rs->rs_more = rx_status->rx_status_0 & |
4008 | AR5K_NEW_RX_DESC_STATUS0_MORE; | 4066 | AR5K_5212_RX_DESC_STATUS0_MORE; |
4009 | desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | 4067 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, |
4010 | AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | 4068 | AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); |
4011 | desc->ds_us.rx.rs_status = 0; | 4069 | rs->rs_status = 0; |
4012 | 4070 | ||
4013 | /* | 4071 | /* |
4014 | * Key table status | 4072 | * Key table status |
4015 | */ | 4073 | */ |
4016 | if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID) | 4074 | if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) |
4017 | desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, | 4075 | rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, |
4018 | AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX); | 4076 | AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); |
4019 | else | 4077 | else |
4020 | desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID; | 4078 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; |
4021 | 4079 | ||
4022 | /* | 4080 | /* |
4023 | * Receive/descriptor errors | 4081 | * Receive/descriptor errors |
4024 | */ | 4082 | */ |
4025 | if ((rx_status->rx_status_1 & | 4083 | if ((rx_status->rx_status_1 & |
4026 | AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) { | 4084 | AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) { |
4027 | if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR) | 4085 | if (rx_status->rx_status_1 & |
4028 | desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC; | 4086 | AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) |
4087 | rs->rs_status |= AR5K_RXERR_CRC; | ||
4029 | 4088 | ||
4030 | if (rx_status->rx_status_1 & | 4089 | if (rx_status->rx_status_1 & |
4031 | AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR) { | 4090 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { |
4032 | desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY; | 4091 | rs->rs_status |= AR5K_RXERR_PHY; |
4033 | desc->ds_us.rx.rs_phyerr = | 4092 | rs->rs_phyerr = AR5K_REG_MS(rx_err->rx_error_1, |
4034 | AR5K_REG_MS(rx_err->rx_error_1, | 4093 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); |
4035 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); | ||
4036 | } | 4094 | } |
4037 | 4095 | ||
4038 | if (rx_status->rx_status_1 & | 4096 | if (rx_status->rx_status_1 & |
4039 | AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) | 4097 | AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) |
4040 | desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT; | 4098 | rs->rs_status |= AR5K_RXERR_DECRYPT; |
4041 | 4099 | ||
4042 | if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR) | 4100 | if (rx_status->rx_status_1 & |
4043 | desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC; | 4101 | AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) |
4102 | rs->rs_status |= AR5K_RXERR_MIC; | ||
4044 | } | 4103 | } |
4045 | 4104 | ||
4046 | return 0; | 4105 | return 0; |
diff --git a/drivers/net/wireless/ath5k/hw.h b/drivers/net/wireless/ath5k/hw.h index d9a7c0973f53..64fca8dcb386 100644 --- a/drivers/net/wireless/ath5k/hw.h +++ b/drivers/net/wireless/ath5k/hw.h | |||
@@ -173,7 +173,10 @@ struct ath5k_eeprom_info { | |||
173 | * (rX: reserved fields possibily used by future versions of the ar5k chipset) | 173 | * (rX: reserved fields possibily used by future versions of the ar5k chipset) |
174 | */ | 174 | */ |
175 | 175 | ||
176 | struct ath5k_rx_desc { | 176 | /* |
177 | * common hardware RX control descriptor | ||
178 | */ | ||
179 | struct ath5k_hw_rx_ctl { | ||
177 | u32 rx_control_0; /* RX control word 0 */ | 180 | u32 rx_control_0; /* RX control word 0 */ |
178 | 181 | ||
179 | #define AR5K_DESC_RX_CTL0 0x00000000 | 182 | #define AR5K_DESC_RX_CTL0 0x00000000 |
@@ -185,69 +188,63 @@ struct ath5k_rx_desc { | |||
185 | } __packed; | 188 | } __packed; |
186 | 189 | ||
187 | /* | 190 | /* |
188 | * 5210/5211 rx status descriptor | 191 | * common hardware RX status descriptor |
192 | * 5210/11 and 5212 differ only in the flags defined below | ||
189 | */ | 193 | */ |
190 | struct ath5k_hw_old_rx_status { | 194 | struct ath5k_hw_rx_status { |
191 | u32 rx_status_0; /* RX status word 0 */ | 195 | u32 rx_status_0; /* RX status word 0 */ |
192 | |||
193 | #define AR5K_OLD_RX_DESC_STATUS0_DATA_LEN 0x00000fff | ||
194 | #define AR5K_OLD_RX_DESC_STATUS0_MORE 0x00001000 | ||
195 | #define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 | ||
196 | #define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE_S 15 | ||
197 | #define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 | ||
198 | #define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 | ||
199 | #define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 | ||
200 | #define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 | ||
201 | |||
202 | u32 rx_status_1; /* RX status word 1 */ | 196 | u32 rx_status_1; /* RX status word 1 */ |
203 | |||
204 | #define AR5K_OLD_RX_DESC_STATUS1_DONE 0x00000001 | ||
205 | #define AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 | ||
206 | #define AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR 0x00000004 | ||
207 | #define AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008 | ||
208 | #define AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 | ||
209 | #define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 | ||
210 | #define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR_S 5 | ||
211 | #define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 | ||
212 | #define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 | ||
213 | #define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_S 9 | ||
214 | #define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 | ||
215 | #define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 | ||
216 | #define AR5K_OLD_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 | ||
217 | } __packed; | 197 | } __packed; |
218 | 198 | ||
199 | /* 5210/5211 */ | ||
200 | #define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff | ||
201 | #define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 | ||
202 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 | ||
203 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15 | ||
204 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 | ||
205 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 | ||
206 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 | ||
207 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 | ||
208 | #define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 | ||
209 | #define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 | ||
210 | #define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 | ||
211 | #define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008 | ||
212 | #define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 | ||
213 | #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 | ||
214 | #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5 | ||
215 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 | ||
216 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 | ||
217 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9 | ||
218 | #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 | ||
219 | #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 | ||
220 | #define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 | ||
221 | |||
222 | /* 5212 */ | ||
223 | #define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff | ||
224 | #define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 | ||
225 | #define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 | ||
226 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 | ||
227 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15 | ||
228 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 | ||
229 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 | ||
230 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 | ||
231 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 | ||
232 | #define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 | ||
233 | #define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 | ||
234 | #define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 | ||
235 | #define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 | ||
236 | #define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010 | ||
237 | #define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020 | ||
238 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 | ||
239 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 | ||
240 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9 | ||
241 | #define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 | ||
242 | #define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 | ||
243 | #define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 | ||
244 | |||
219 | /* | 245 | /* |
220 | * 5212 rx status descriptor | 246 | * common hardware RX error descriptor |
221 | */ | 247 | */ |
222 | struct ath5k_hw_new_rx_status { | ||
223 | u32 rx_status_0; /* RX status word 0 */ | ||
224 | |||
225 | #define AR5K_NEW_RX_DESC_STATUS0_DATA_LEN 0x00000fff | ||
226 | #define AR5K_NEW_RX_DESC_STATUS0_MORE 0x00001000 | ||
227 | #define AR5K_NEW_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 | ||
228 | #define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 | ||
229 | #define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE_S 15 | ||
230 | #define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 | ||
231 | #define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 | ||
232 | #define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 | ||
233 | #define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 | ||
234 | |||
235 | u32 rx_status_1; /* RX status word 1 */ | ||
236 | |||
237 | #define AR5K_NEW_RX_DESC_STATUS1_DONE 0x00000001 | ||
238 | #define AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 | ||
239 | #define AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR 0x00000004 | ||
240 | #define AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 | ||
241 | #define AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR 0x00000010 | ||
242 | #define AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR 0x00000020 | ||
243 | #define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 | ||
244 | #define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 | ||
245 | #define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_S 9 | ||
246 | #define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 | ||
247 | #define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 | ||
248 | #define AR5K_NEW_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 | ||
249 | } __packed; | ||
250 | |||
251 | struct ath5k_hw_rx_error { | 248 | struct ath5k_hw_rx_error { |
252 | u32 rx_error_0; /* RX error word 0 */ | 249 | u32 rx_error_0; /* RX error word 0 */ |
253 | 250 | ||
@@ -268,7 +265,10 @@ struct ath5k_hw_rx_error { | |||
268 | #define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0 | 265 | #define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0 |
269 | #define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 | 266 | #define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 |
270 | 267 | ||
271 | struct ath5k_hw_2w_tx_desc { | 268 | /* |
269 | * 5210/5211 hardware 2-word TX control descriptor | ||
270 | */ | ||
271 | struct ath5k_hw_2w_tx_ctl { | ||
272 | u32 tx_control_0; /* TX control word 0 */ | 272 | u32 tx_control_0; /* TX control word 0 */ |
273 | 273 | ||
274 | #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff | 274 | #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff |
@@ -314,9 +314,9 @@ struct ath5k_hw_2w_tx_desc { | |||
314 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10 | 314 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10 |
315 | 315 | ||
316 | /* | 316 | /* |
317 | * 5212 4-word tx control descriptor | 317 | * 5212 hardware 4-word TX control descriptor |
318 | */ | 318 | */ |
319 | struct ath5k_hw_4w_tx_desc { | 319 | struct ath5k_hw_4w_tx_ctl { |
320 | u32 tx_control_0; /* TX control word 0 */ | 320 | u32 tx_control_0; /* TX control word 0 */ |
321 | 321 | ||
322 | #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff | 322 | #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff |
@@ -374,7 +374,7 @@ struct ath5k_hw_4w_tx_desc { | |||
374 | } __packed; | 374 | } __packed; |
375 | 375 | ||
376 | /* | 376 | /* |
377 | * Common tx status descriptor | 377 | * Common TX status descriptor |
378 | */ | 378 | */ |
379 | struct ath5k_hw_tx_status { | 379 | struct ath5k_hw_tx_status { |
380 | u32 tx_status_0; /* TX status word 0 */ | 380 | u32 tx_status_0; /* TX status word 0 */ |
@@ -415,6 +415,34 @@ struct ath5k_hw_tx_status { | |||
415 | 415 | ||
416 | 416 | ||
417 | /* | 417 | /* |
418 | * 5210/5211 hardware TX descriptor | ||
419 | */ | ||
420 | struct ath5k_hw_5210_tx_desc { | ||
421 | struct ath5k_hw_2w_tx_ctl tx_ctl; | ||
422 | struct ath5k_hw_tx_status tx_stat; | ||
423 | } __packed; | ||
424 | |||
425 | /* | ||
426 | * 5212 hardware TX descriptor | ||
427 | */ | ||
428 | struct ath5k_hw_5212_tx_desc { | ||
429 | struct ath5k_hw_4w_tx_ctl tx_ctl; | ||
430 | struct ath5k_hw_tx_status tx_stat; | ||
431 | } __packed; | ||
432 | |||
433 | /* | ||
434 | * common hardware RX descriptor | ||
435 | */ | ||
436 | struct ath5k_hw_all_rx_desc { | ||
437 | struct ath5k_hw_rx_ctl rx_ctl; | ||
438 | union { | ||
439 | struct ath5k_hw_rx_status rx_stat; | ||
440 | struct ath5k_hw_rx_error rx_err; | ||
441 | } u; | ||
442 | } __packed; | ||
443 | |||
444 | |||
445 | /* | ||
418 | * AR5K REGISTER ACCESS | 446 | * AR5K REGISTER ACCESS |
419 | */ | 447 | */ |
420 | 448 | ||
diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c index cfcb1fe7bd34..fdbab2f08178 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath5k/initvals.c | |||
@@ -678,8 +678,8 @@ static const struct ath5k_ini ar5212_ini[] = { | |||
678 | { AR5K_PHY(644), 0x00806333 }, | 678 | { AR5K_PHY(644), 0x00806333 }, |
679 | { AR5K_PHY(645), 0x00106c10 }, | 679 | { AR5K_PHY(645), 0x00106c10 }, |
680 | { AR5K_PHY(646), 0x009c4060 }, | 680 | { AR5K_PHY(646), 0x009c4060 }, |
681 | /*{ AR5K_PHY(647), 0x1483800a },*/ /* Old value */ | ||
682 | { AR5K_PHY(647), 0x1483800a }, | 681 | { AR5K_PHY(647), 0x1483800a }, |
682 | /* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413 */ | ||
683 | { AR5K_PHY(648), 0x01831061 }, | 683 | { AR5K_PHY(648), 0x01831061 }, |
684 | { AR5K_PHY(649), 0x00000400 }, | 684 | { AR5K_PHY(649), 0x00000400 }, |
685 | /*{ AR5K_PHY(650), 0x000001b5 },*/ | 685 | /*{ AR5K_PHY(650), 0x000001b5 },*/ |
@@ -1081,6 +1081,207 @@ static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { | |||
1081 | { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } }, | 1081 | { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } }, |
1082 | }; | 1082 | }; |
1083 | 1083 | ||
1084 | /* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */ | ||
1085 | /* XXX: No dumps for turbog yet, so turbog is the same with g here with some | ||
1086 | * minor tweaking based on dumps from other chips */ | ||
1087 | static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { | ||
1088 | { AR5K_TXCFG, | ||
1089 | /* b g gTurbo */ | ||
1090 | { 0x00000015, 0x00000015, 0x00000015 } }, | ||
1091 | { AR5K_USEC_5211, | ||
1092 | { 0x04e01395, 0x12e013ab, 0x098813cf } }, | ||
1093 | { AR5K_PHY(10), | ||
1094 | { 0x05020000, 0x0a020001, 0x0a020001 } }, | ||
1095 | { AR5K_PHY(13), | ||
1096 | { 0x00000e00, 0x00000e00, 0x00000e00 } }, | ||
1097 | { AR5K_PHY(14), | ||
1098 | { 0x0000000a, 0x0000000a, 0x0000000a } }, | ||
1099 | { AR5K_PHY(18), | ||
1100 | { 0x001a6a64, 0x001a6a64, 0x001a6a64 } }, | ||
1101 | { AR5K_PHY(20), | ||
1102 | { 0x0de8b0da, 0x0c98b0da, 0x0c98b0da } }, | ||
1103 | { AR5K_PHY_SIG, | ||
1104 | { 0x7ee80d2e, 0x7ec80d2e, 0x7ec80d2e } }, | ||
1105 | { AR5K_PHY_AGCCOARSE, | ||
1106 | { 0x3137665e, 0x3139605e, 0x3139605e } }, | ||
1107 | { AR5K_PHY(27), | ||
1108 | { 0x050cb081, 0x050cb081, 0x050cb081 } }, | ||
1109 | { AR5K_PHY_RX_DELAY, | ||
1110 | { 0x0000044c, 0x00000898, 0x000007d0 } }, | ||
1111 | { AR5K_PHY_FRAME_CTL_5211, | ||
1112 | { 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, | ||
1113 | { AR5K_PHY_CCKTXCTL, | ||
1114 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1115 | { AR5K_PHY(642), | ||
1116 | { 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, | ||
1117 | { AR5K_PHY_GAIN_2GHZ, | ||
1118 | { 0x0042c140, 0x0042c140, 0x0042c140 } }, | ||
1119 | { 0xa21c, | ||
1120 | { 0x1863800a, 0x1883800a, 0x1883800a } }, | ||
1121 | { AR5K_DCU_FP, | ||
1122 | { 0x000003e0, 0x000003e0, 0x000003e0 } }, | ||
1123 | { 0x8060, | ||
1124 | { 0x0000000f, 0x0000000f, 0x0000000f } }, | ||
1125 | { 0x8118, | ||
1126 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1127 | { 0x811c, | ||
1128 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1129 | { 0x8120, | ||
1130 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1131 | { 0x8124, | ||
1132 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1133 | { 0x8128, | ||
1134 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1135 | { 0x812c, | ||
1136 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1137 | { 0x8130, | ||
1138 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1139 | { 0x8134, | ||
1140 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1141 | { 0x8138, | ||
1142 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1143 | { 0x813c, | ||
1144 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1145 | { 0x8140, | ||
1146 | { 0x800000a8, 0x800000a8, 0x800000a8 } }, | ||
1147 | { 0x8144, | ||
1148 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1149 | { AR5K_PHY_AGC, | ||
1150 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1151 | { AR5K_PHY(11), | ||
1152 | { 0x0000a000, 0x0000a000, 0x0000a000 } }, | ||
1153 | { AR5K_PHY(15), | ||
1154 | { 0x00200400, 0x00200400, 0x00200400 } }, | ||
1155 | { AR5K_PHY(19), | ||
1156 | { 0x1284233c, 0x1284233c, 0x1284233c } }, | ||
1157 | { AR5K_PHY_SCR, | ||
1158 | { 0x0000001f, 0x0000001f, 0x0000001f } }, | ||
1159 | { AR5K_PHY_SLMT, | ||
1160 | { 0x00000080, 0x00000080, 0x00000080 } }, | ||
1161 | { AR5K_PHY_SCAL, | ||
1162 | { 0x0000000e, 0x0000000e, 0x0000000e } }, | ||
1163 | { AR5K_PHY(86), | ||
1164 | { 0x000000ff, 0x000000ff, 0x000000ff } }, | ||
1165 | { AR5K_PHY(96), | ||
1166 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1167 | { AR5K_PHY(97), | ||
1168 | { 0x02800000, 0x02800000, 0x02800000 } }, | ||
1169 | { AR5K_PHY(104), | ||
1170 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1171 | { AR5K_PHY(120), | ||
1172 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1173 | { AR5K_PHY(121), | ||
1174 | { 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa } }, | ||
1175 | { AR5K_PHY(122), | ||
1176 | { 0x3c466478, 0x3c466478, 0x3c466478 } }, | ||
1177 | { AR5K_PHY(123), | ||
1178 | { 0x000000aa, 0x000000aa, 0x000000aa } }, | ||
1179 | { AR5K_PHY_SCLOCK, | ||
1180 | { 0x0000000c, 0x0000000c, 0x0000000c } }, | ||
1181 | { AR5K_PHY_SDELAY, | ||
1182 | { 0x000000ff, 0x000000ff, 0x000000ff } }, | ||
1183 | { AR5K_PHY_SPENDING, | ||
1184 | { 0x00000014, 0x00000014, 0x00000014 } }, | ||
1185 | { 0xa228, | ||
1186 | { 0x000009b5, 0x000009b5, 0x000009b5 } }, | ||
1187 | { 0xa23c, | ||
1188 | { 0x93c889af, 0x93c889af, 0x93c889af } }, | ||
1189 | { 0xa24c, | ||
1190 | { 0x00000001, 0x00000001, 0x00000001 } }, | ||
1191 | { 0xa250, | ||
1192 | { 0x0000a000, 0x0000a000, 0x0000a000 } }, | ||
1193 | { 0xa254, | ||
1194 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1195 | { 0xa258, | ||
1196 | { 0x0cc75380, 0x0cc75380, 0x0cc75380 } }, | ||
1197 | { 0xa25c, | ||
1198 | { 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01 } }, | ||
1199 | { 0xa260, | ||
1200 | { 0x5f690f01, 0x5f690f01, 0x5f690f01 } }, | ||
1201 | { 0xa264, | ||
1202 | { 0x00418a11, 0x00418a11, 0x00418a11 } }, | ||
1203 | { 0xa268, | ||
1204 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1205 | { 0xa26c, | ||
1206 | { 0x0c30c16a, 0x0c30c16a, 0x0c30c16a } }, | ||
1207 | { 0xa270, | ||
1208 | { 0x00820820, 0x00820820, 0x00820820 } }, | ||
1209 | { 0xa274, | ||
1210 | { 0x001b7caa, 0x001b7caa, 0x001b7caa } }, | ||
1211 | { 0xa278, | ||
1212 | { 0x1ce739ce, 0x1ce739ce, 0x1ce739ce } }, | ||
1213 | { 0xa27c, | ||
1214 | { 0x051701ce, 0x051701ce, 0x051701ce } }, | ||
1215 | { 0xa300, | ||
1216 | { 0x18010000, 0x18010000, 0x18010000 } }, | ||
1217 | { 0xa304, | ||
1218 | { 0x30032602, 0x30032602, 0x30032602 } }, | ||
1219 | { 0xa308, | ||
1220 | { 0x48073e06, 0x48073e06, 0x48073e06 } }, | ||
1221 | { 0xa30c, | ||
1222 | { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } }, | ||
1223 | { 0xa310, | ||
1224 | { 0x641a600f, 0x641a600f, 0x641a600f } }, | ||
1225 | { 0xa314, | ||
1226 | { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } }, | ||
1227 | { 0xa318, | ||
1228 | { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } }, | ||
1229 | { 0xa31c, | ||
1230 | { 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } }, | ||
1231 | { 0xa320, | ||
1232 | { 0x9d4f970f, 0x9d4f970f, 0x9d4f970f } }, | ||
1233 | { 0xa324, | ||
1234 | { 0xa5cfa18f, 0xa5cfa18f, 0xa5cfa18f } }, | ||
1235 | { 0xa328, | ||
1236 | { 0xb55faf1f, 0xb55faf1f, 0xb55faf1f } }, | ||
1237 | { 0xa32c, | ||
1238 | { 0xbddfb99f, 0xbddfb99f, 0xbddfb99f } }, | ||
1239 | { 0xa330, | ||
1240 | { 0xcd7fc73f, 0xcd7fc73f, 0xcd7fc73f } }, | ||
1241 | { 0xa334, | ||
1242 | { 0xd5ffd1bf, 0xd5ffd1bf, 0xd5ffd1bf } }, | ||
1243 | { 0xa338, | ||
1244 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1245 | { 0xa33c, | ||
1246 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1247 | { 0xa340, | ||
1248 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1249 | { 0xa344, | ||
1250 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
1251 | { 0xa348, | ||
1252 | { 0x3fffffff, 0x3fffffff, 0x3fffffff } }, | ||
1253 | { 0xa34c, | ||
1254 | { 0x3fffffff, 0x3fffffff, 0x3fffffff } }, | ||
1255 | { 0xa350, | ||
1256 | { 0x3fffffff, 0x3fffffff, 0x3fffffff } }, | ||
1257 | { 0xa354, | ||
1258 | { 0x0003ffff, 0x0003ffff, 0x0003ffff } }, | ||
1259 | { 0xa358, | ||
1260 | { 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f } }, | ||
1261 | { 0xa35c, | ||
1262 | { 0x066c420f, 0x066c420f, 0x066c420f } }, | ||
1263 | { 0xa360, | ||
1264 | { 0x0f282207, 0x0f282207, 0x0f282207 } }, | ||
1265 | { 0xa364, | ||
1266 | { 0x17601685, 0x17601685, 0x17601685 } }, | ||
1267 | { 0xa368, | ||
1268 | { 0x1f801104, 0x1f801104, 0x1f801104 } }, | ||
1269 | { 0xa36c, | ||
1270 | { 0x37a00c03, 0x37a00c03, 0x37a00c03 } }, | ||
1271 | { 0xa370, | ||
1272 | { 0x3fc40883, 0x3fc40883, 0x3fc40883 } }, | ||
1273 | { 0xa374, | ||
1274 | { 0x57c00803, 0x57c00803, 0x57c00803 } }, | ||
1275 | { 0xa378, | ||
1276 | { 0x5fd80682, 0x5fd80682, 0x5fd80682 } }, | ||
1277 | { 0xa37c, | ||
1278 | { 0x7fe00482, 0x7fe00482, 0x7fe00482 } }, | ||
1279 | { 0xa380, | ||
1280 | { 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba } }, | ||
1281 | { 0xa384, | ||
1282 | { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } }, | ||
1283 | }; | ||
1284 | |||
1084 | /* | 1285 | /* |
1085 | * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with | 1286 | * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with |
1086 | * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI) | 1287 | * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI) |
@@ -1290,29 +1491,57 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) | |||
1290 | 1491 | ||
1291 | /* Second set of mode-specific settings */ | 1492 | /* Second set of mode-specific settings */ |
1292 | if (ah->ah_radio == AR5K_RF5111){ | 1493 | if (ah->ah_radio == AR5K_RF5111){ |
1494 | |||
1293 | ath5k_hw_ini_mode_registers(ah, | 1495 | ath5k_hw_ini_mode_registers(ah, |
1294 | ARRAY_SIZE(ar5212_rf5111_ini_mode_end), | 1496 | ARRAY_SIZE(ar5212_rf5111_ini_mode_end), |
1295 | ar5212_rf5111_ini_mode_end, mode); | 1497 | ar5212_rf5111_ini_mode_end, mode); |
1498 | |||
1296 | /* Baseband gain table */ | 1499 | /* Baseband gain table */ |
1297 | ath5k_hw_ini_registers(ah, | 1500 | ath5k_hw_ini_registers(ah, |
1298 | ARRAY_SIZE(rf5111_ini_bbgain), | 1501 | ARRAY_SIZE(rf5111_ini_bbgain), |
1299 | rf5111_ini_bbgain, change_channel); | 1502 | rf5111_ini_bbgain, change_channel); |
1503 | |||
1300 | } else if (ah->ah_radio == AR5K_RF5112){ | 1504 | } else if (ah->ah_radio == AR5K_RF5112){ |
1505 | |||
1301 | ath5k_hw_ini_mode_registers(ah, | 1506 | ath5k_hw_ini_mode_registers(ah, |
1302 | ARRAY_SIZE(ar5212_rf5112_ini_mode_end), | 1507 | ARRAY_SIZE(ar5212_rf5112_ini_mode_end), |
1303 | ar5212_rf5112_ini_mode_end, mode); | 1508 | ar5212_rf5112_ini_mode_end, mode); |
1304 | /* Baseband gain table */ | 1509 | |
1305 | ath5k_hw_ini_registers(ah, | 1510 | ath5k_hw_ini_registers(ah, |
1306 | ARRAY_SIZE(rf5112_ini_bbgain), | 1511 | ARRAY_SIZE(rf5112_ini_bbgain), |
1307 | rf5112_ini_bbgain, change_channel); | 1512 | rf5112_ini_bbgain, change_channel); |
1513 | |||
1308 | } else if (ah->ah_radio == AR5K_RF5413){ | 1514 | } else if (ah->ah_radio == AR5K_RF5413){ |
1515 | |||
1309 | ath5k_hw_ini_mode_registers(ah, | 1516 | ath5k_hw_ini_mode_registers(ah, |
1310 | ARRAY_SIZE(rf5413_ini_mode_end), | 1517 | ARRAY_SIZE(rf5413_ini_mode_end), |
1311 | rf5413_ini_mode_end, mode); | 1518 | rf5413_ini_mode_end, mode); |
1519 | |||
1520 | ath5k_hw_ini_registers(ah, | ||
1521 | ARRAY_SIZE(rf5112_ini_bbgain), | ||
1522 | rf5112_ini_bbgain, change_channel); | ||
1523 | |||
1524 | } else if (ah->ah_radio == AR5K_RF2413) { | ||
1525 | |||
1526 | if (mode < 2) { | ||
1527 | ATH5K_ERR(ah->ah_sc, | ||
1528 | "unsupported channel mode: %d\n", mode); | ||
1529 | return -EINVAL; | ||
1530 | } | ||
1531 | mode = mode - 2; | ||
1532 | |||
1533 | /* Override a setting from ar5212_ini */ | ||
1534 | ath5k_hw_reg_write(ah, 0x018830c6, AR5K_PHY(648)); | ||
1535 | |||
1536 | ath5k_hw_ini_mode_registers(ah, | ||
1537 | ARRAY_SIZE(rf2413_ini_mode_end), | ||
1538 | rf2413_ini_mode_end, mode); | ||
1539 | |||
1312 | /* Baseband gain table */ | 1540 | /* Baseband gain table */ |
1313 | ath5k_hw_ini_registers(ah, | 1541 | ath5k_hw_ini_registers(ah, |
1314 | ARRAY_SIZE(rf5112_ini_bbgain), | 1542 | ARRAY_SIZE(rf5112_ini_bbgain), |
1315 | rf5112_ini_bbgain, change_channel); | 1543 | rf5112_ini_bbgain, change_channel); |
1544 | |||
1316 | } | 1545 | } |
1317 | /* For AR5211 */ | 1546 | /* For AR5211 */ |
1318 | } else if (ah->ah_version == AR5K_AR5211) { | 1547 | } else if (ah->ah_version == AR5K_AR5211) { |
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 405195ffb24d..ee1dc0fc6ea2 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c | |||
@@ -666,6 +666,75 @@ static const struct ath5k_ini_rf rfregs_5413[] = { | |||
666 | { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, | 666 | { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, |
667 | }; | 667 | }; |
668 | 668 | ||
669 | /* RF2413/2414 mode-specific init registers */ | ||
670 | static const struct ath5k_ini_rf rfregs_2413[] = { | ||
671 | { 1, AR5K_RF_BUFFER_CONTROL_4, | ||
672 | { 0x00000020, 0x00000020, 0x00000020 } }, | ||
673 | { 2, AR5K_RF_BUFFER_CONTROL_3, | ||
674 | { 0x02001408, 0x02001408, 0x02001408 } }, | ||
675 | { 3, AR5K_RF_BUFFER_CONTROL_6, | ||
676 | { 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, | ||
677 | { 6, AR5K_RF_BUFFER, | ||
678 | { 0xf0000000, 0xf0000000, 0xf0000000 } }, | ||
679 | { 6, AR5K_RF_BUFFER, | ||
680 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
681 | { 6, AR5K_RF_BUFFER, | ||
682 | { 0x03000000, 0x03000000, 0x03000000 } }, | ||
683 | { 6, AR5K_RF_BUFFER, | ||
684 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
685 | { 6, AR5K_RF_BUFFER, | ||
686 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
687 | { 6, AR5K_RF_BUFFER, | ||
688 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
689 | { 6, AR5K_RF_BUFFER, | ||
690 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
691 | { 6, AR5K_RF_BUFFER, | ||
692 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
693 | { 6, AR5K_RF_BUFFER, | ||
694 | { 0x40400000, 0x40400000, 0x40400000 } }, | ||
695 | { 6, AR5K_RF_BUFFER, | ||
696 | { 0x65050000, 0x65050000, 0x65050000 } }, | ||
697 | { 6, AR5K_RF_BUFFER, | ||
698 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
699 | { 6, AR5K_RF_BUFFER, | ||
700 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
701 | { 6, AR5K_RF_BUFFER, | ||
702 | { 0x00420000, 0x00420000, 0x00420000 } }, | ||
703 | { 6, AR5K_RF_BUFFER, | ||
704 | { 0x00b50000, 0x00b50000, 0x00b50000 } }, | ||
705 | { 6, AR5K_RF_BUFFER, | ||
706 | { 0x00030000, 0x00030000, 0x00030000 } }, | ||
707 | { 6, AR5K_RF_BUFFER, | ||
708 | { 0x00f70000, 0x00f70000, 0x00f70000 } }, | ||
709 | { 6, AR5K_RF_BUFFER, | ||
710 | { 0x009d0000, 0x009d0000, 0x009d0000 } }, | ||
711 | { 6, AR5K_RF_BUFFER, | ||
712 | { 0x00220000, 0x00220000, 0x00220000 } }, | ||
713 | { 6, AR5K_RF_BUFFER, | ||
714 | { 0x04220000, 0x04220000, 0x04220000 } }, | ||
715 | { 6, AR5K_RF_BUFFER, | ||
716 | { 0x00230018, 0x00230018, 0x00230018 } }, | ||
717 | { 6, AR5K_RF_BUFFER, | ||
718 | { 0x00280050, 0x00280050, 0x00280050 } }, | ||
719 | { 6, AR5K_RF_BUFFER, | ||
720 | { 0x005000c3, 0x005000c3, 0x005000c3 } }, | ||
721 | { 6, AR5K_RF_BUFFER, | ||
722 | { 0x0004007f, 0x0004007f, 0x0004007f } }, | ||
723 | { 6, AR5K_RF_BUFFER, | ||
724 | { 0x00000458, 0x00000458, 0x00000458 } }, | ||
725 | { 6, AR5K_RF_BUFFER, | ||
726 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
727 | { 6, AR5K_RF_BUFFER, | ||
728 | { 0x0000c000, 0x0000c000, 0x0000c000 } }, | ||
729 | { 6, AR5K_RF_BUFFER_CONTROL_5, | ||
730 | { 0x00400230, 0x00400230, 0x00400230 } }, | ||
731 | { 7, AR5K_RF_BUFFER, | ||
732 | { 0x00006400, 0x00006400, 0x00006400 } }, | ||
733 | { 7, AR5K_RF_BUFFER, | ||
734 | { 0x00000800, 0x00000800, 0x00000800 } }, | ||
735 | { 7, AR5K_RF_BUFFER_CONTROL_2, | ||
736 | { 0x0000000e, 0x0000000e, 0x0000000e } }, | ||
737 | }; | ||
669 | 738 | ||
670 | /* Initial RF Gain settings for RF5112 */ | 739 | /* Initial RF Gain settings for RF5112 */ |
671 | static const struct ath5k_ini_rfgain rfgain_5112[] = { | 740 | static const struct ath5k_ini_rfgain rfgain_5112[] = { |
@@ -805,6 +874,74 @@ static const struct ath5k_ini_rfgain rfgain_5413[] = { | |||
805 | { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } }, | 874 | { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } }, |
806 | }; | 875 | }; |
807 | 876 | ||
877 | /* Initial RF Gain settings for RF2413 */ | ||
878 | static const struct ath5k_ini_rfgain rfgain_2413[] = { | ||
879 | { AR5K_RF_GAIN(0), { 0x00000000 } }, | ||
880 | { AR5K_RF_GAIN(1), { 0x00000040 } }, | ||
881 | { AR5K_RF_GAIN(2), { 0x00000080 } }, | ||
882 | { AR5K_RF_GAIN(3), { 0x00000181 } }, | ||
883 | { AR5K_RF_GAIN(4), { 0x000001c1 } }, | ||
884 | { AR5K_RF_GAIN(5), { 0x00000001 } }, | ||
885 | { AR5K_RF_GAIN(6), { 0x00000041 } }, | ||
886 | { AR5K_RF_GAIN(7), { 0x00000081 } }, | ||
887 | { AR5K_RF_GAIN(8), { 0x00000168 } }, | ||
888 | { AR5K_RF_GAIN(9), { 0x000001a8 } }, | ||
889 | { AR5K_RF_GAIN(10), { 0x000001e8 } }, | ||
890 | { AR5K_RF_GAIN(11), { 0x00000028 } }, | ||
891 | { AR5K_RF_GAIN(12), { 0x00000068 } }, | ||
892 | { AR5K_RF_GAIN(13), { 0x00000189 } }, | ||
893 | { AR5K_RF_GAIN(14), { 0x000001c9 } }, | ||
894 | { AR5K_RF_GAIN(15), { 0x00000009 } }, | ||
895 | { AR5K_RF_GAIN(16), { 0x00000049 } }, | ||
896 | { AR5K_RF_GAIN(17), { 0x00000089 } }, | ||
897 | { AR5K_RF_GAIN(18), { 0x00000190 } }, | ||
898 | { AR5K_RF_GAIN(19), { 0x000001d0 } }, | ||
899 | { AR5K_RF_GAIN(20), { 0x00000010 } }, | ||
900 | { AR5K_RF_GAIN(21), { 0x00000050 } }, | ||
901 | { AR5K_RF_GAIN(22), { 0x00000090 } }, | ||
902 | { AR5K_RF_GAIN(23), { 0x00000191 } }, | ||
903 | { AR5K_RF_GAIN(24), { 0x000001d1 } }, | ||
904 | { AR5K_RF_GAIN(25), { 0x00000011 } }, | ||
905 | { AR5K_RF_GAIN(26), { 0x00000051 } }, | ||
906 | { AR5K_RF_GAIN(27), { 0x00000091 } }, | ||
907 | { AR5K_RF_GAIN(28), { 0x00000178 } }, | ||
908 | { AR5K_RF_GAIN(29), { 0x000001b8 } }, | ||
909 | { AR5K_RF_GAIN(30), { 0x000001f8 } }, | ||
910 | { AR5K_RF_GAIN(31), { 0x00000038 } }, | ||
911 | { AR5K_RF_GAIN(32), { 0x00000078 } }, | ||
912 | { AR5K_RF_GAIN(33), { 0x00000199 } }, | ||
913 | { AR5K_RF_GAIN(34), { 0x000001d9 } }, | ||
914 | { AR5K_RF_GAIN(35), { 0x00000019 } }, | ||
915 | { AR5K_RF_GAIN(36), { 0x00000059 } }, | ||
916 | { AR5K_RF_GAIN(37), { 0x00000099 } }, | ||
917 | { AR5K_RF_GAIN(38), { 0x000000d9 } }, | ||
918 | { AR5K_RF_GAIN(39), { 0x000000f9 } }, | ||
919 | { AR5K_RF_GAIN(40), { 0x000000f9 } }, | ||
920 | { AR5K_RF_GAIN(41), { 0x000000f9 } }, | ||
921 | { AR5K_RF_GAIN(42), { 0x000000f9 } }, | ||
922 | { AR5K_RF_GAIN(43), { 0x000000f9 } }, | ||
923 | { AR5K_RF_GAIN(44), { 0x000000f9 } }, | ||
924 | { AR5K_RF_GAIN(45), { 0x000000f9 } }, | ||
925 | { AR5K_RF_GAIN(46), { 0x000000f9 } }, | ||
926 | { AR5K_RF_GAIN(47), { 0x000000f9 } }, | ||
927 | { AR5K_RF_GAIN(48), { 0x000000f9 } }, | ||
928 | { AR5K_RF_GAIN(49), { 0x000000f9 } }, | ||
929 | { AR5K_RF_GAIN(50), { 0x000000f9 } }, | ||
930 | { AR5K_RF_GAIN(51), { 0x000000f9 } }, | ||
931 | { AR5K_RF_GAIN(52), { 0x000000f9 } }, | ||
932 | { AR5K_RF_GAIN(53), { 0x000000f9 } }, | ||
933 | { AR5K_RF_GAIN(54), { 0x000000f9 } }, | ||
934 | { AR5K_RF_GAIN(55), { 0x000000f9 } }, | ||
935 | { AR5K_RF_GAIN(56), { 0x000000f9 } }, | ||
936 | { AR5K_RF_GAIN(57), { 0x000000f9 } }, | ||
937 | { AR5K_RF_GAIN(58), { 0x000000f9 } }, | ||
938 | { AR5K_RF_GAIN(59), { 0x000000f9 } }, | ||
939 | { AR5K_RF_GAIN(60), { 0x000000f9 } }, | ||
940 | { AR5K_RF_GAIN(61), { 0x000000f9 } }, | ||
941 | { AR5K_RF_GAIN(62), { 0x000000f9 } }, | ||
942 | { AR5K_RF_GAIN(63), { 0x000000f9 } }, | ||
943 | }; | ||
944 | |||
808 | static const struct ath5k_gain_opt rfgain_opt_5112 = { | 945 | static const struct ath5k_gain_opt rfgain_opt_5112 = { |
809 | 1, | 946 | 1, |
810 | 8, | 947 | 8, |
@@ -955,7 +1092,6 @@ static s32 ath5k_hw_rfregs_gain_adjust(struct ath5k_hw *ah) | |||
955 | go = &rfgain_opt_5111; | 1092 | go = &rfgain_opt_5111; |
956 | break; | 1093 | break; |
957 | case AR5K_RF5112: | 1094 | case AR5K_RF5112: |
958 | case AR5K_RF5413: /* ??? */ | ||
959 | go = &rfgain_opt_5112; | 1095 | go = &rfgain_opt_5112; |
960 | break; | 1096 | break; |
961 | default: | 1097 | default: |
@@ -1226,8 +1362,21 @@ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, | |||
1226 | 1362 | ||
1227 | rf = ah->ah_rf_banks; | 1363 | rf = ah->ah_rf_banks; |
1228 | 1364 | ||
1229 | rf_ini = rfregs_5413; | 1365 | if (ah->ah_radio == AR5K_RF5413) { |
1230 | rf_size = ARRAY_SIZE(rfregs_5413); | 1366 | rf_ini = rfregs_5413; |
1367 | rf_size = ARRAY_SIZE(rfregs_5413); | ||
1368 | } else if (ah->ah_radio == AR5K_RF2413) { | ||
1369 | rf_ini = rfregs_2413; | ||
1370 | rf_size = ARRAY_SIZE(rfregs_2413); | ||
1371 | if (mode < 2) { | ||
1372 | ATH5K_ERR(ah->ah_sc, | ||
1373 | "invalid channel mode: %i\n", mode); | ||
1374 | return -EINVAL; | ||
1375 | } | ||
1376 | mode = mode - 2; | ||
1377 | } else { | ||
1378 | return -EINVAL; | ||
1379 | } | ||
1231 | 1380 | ||
1232 | /* Copy values to modify them */ | 1381 | /* Copy values to modify them */ |
1233 | for (i = 0; i < rf_size; i++) { | 1382 | for (i = 0; i < rf_size; i++) { |
@@ -1286,6 +1435,10 @@ int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
1286 | ah->ah_rf_banks_size = sizeof(rfregs_5413); | 1435 | ah->ah_rf_banks_size = sizeof(rfregs_5413); |
1287 | func = ath5k_hw_rf5413_rfregs; | 1436 | func = ath5k_hw_rf5413_rfregs; |
1288 | break; | 1437 | break; |
1438 | case AR5K_RF2413: | ||
1439 | ah->ah_rf_banks_size = sizeof(rfregs_2413); | ||
1440 | func = ath5k_hw_rf5413_rfregs; | ||
1441 | break; | ||
1289 | default: | 1442 | default: |
1290 | return -EINVAL; | 1443 | return -EINVAL; |
1291 | } | 1444 | } |
@@ -1324,6 +1477,11 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq) | |||
1324 | ath5k_rfg = rfgain_5413; | 1477 | ath5k_rfg = rfgain_5413; |
1325 | size = ARRAY_SIZE(rfgain_5413); | 1478 | size = ARRAY_SIZE(rfgain_5413); |
1326 | break; | 1479 | break; |
1480 | case AR5K_RF2413: | ||
1481 | ath5k_rfg = rfgain_2413; | ||
1482 | size = ARRAY_SIZE(rfgain_2413); | ||
1483 | freq = 0; /* only 2Ghz */ | ||
1484 | break; | ||
1327 | default: | 1485 | default: |
1328 | return -EINVAL; | 1486 | return -EINVAL; |
1329 | } | 1487 | } |
@@ -1398,7 +1556,6 @@ int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah) | |||
1398 | ah->ah_gain.g_active = 1; | 1556 | ah->ah_gain.g_active = 1; |
1399 | break; | 1557 | break; |
1400 | case AR5K_RF5112: | 1558 | case AR5K_RF5112: |
1401 | case AR5K_RF5413: /* ??? */ | ||
1402 | ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default; | 1559 | ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default; |
1403 | ah->ah_gain.g_step = | 1560 | ah->ah_gain.g_step = |
1404 | &rfgain_opt_5112.go_step[ah->ah_gain.g_step_idx]; | 1561 | &rfgain_opt_5112.go_step[ah->ah_gain.g_step_idx]; |
@@ -2019,6 +2176,15 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
2019 | return -EINVAL; | 2176 | return -EINVAL; |
2020 | } | 2177 | } |
2021 | 2178 | ||
2179 | /* | ||
2180 | * RF2413 for some reason can't | ||
2181 | * transmit anything if we call | ||
2182 | * this funtion, so we skip it | ||
2183 | * until we fix txpower. | ||
2184 | */ | ||
2185 | if (ah->ah_radio == AR5K_RF2413) | ||
2186 | return 0; | ||
2187 | |||
2022 | /* Reset TX power values */ | 2188 | /* Reset TX power values */ |
2023 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); | 2189 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); |
2024 | ah->ah_txpower.txp_tpc = tpc; | 2190 | ah->ah_txpower.txp_tpc = tpc; |
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index 2f41c8398602..30629b3e37c2 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h | |||
@@ -1923,7 +1923,9 @@ after DFS is enabled */ | |||
1923 | #define AR5K_PHY_SDELAY_32MHZ 0x000000ff | 1923 | #define AR5K_PHY_SDELAY_32MHZ 0x000000ff |
1924 | #define AR5K_PHY_SPENDING 0x99f8 | 1924 | #define AR5K_PHY_SPENDING 0x99f8 |
1925 | #define AR5K_PHY_SPENDING_RF5111 0x00000018 | 1925 | #define AR5K_PHY_SPENDING_RF5111 0x00000018 |
1926 | #define AR5K_PHY_SPENDING_RF5112 0x00000014 | 1926 | #define AR5K_PHY_SPENDING_RF5112 0x00000014 /* <- i 've only seen this on 2425 dumps ! */ |
1927 | #define AR5K_PHY_SPENDING_RF5112A 0x0000000e /* but since i only have 5112A-based chips */ | ||
1928 | #define AR5K_PHY_SPENDING_RF5424 0x00000012 /* to test it might be also for old 5112. */ | ||
1927 | 1929 | ||
1928 | /* | 1930 | /* |
1929 | * Misc PHY/radio registers [5110 - 5111] | 1931 | * Misc PHY/radio registers [5110 - 5111] |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 33459d61a717..d40be1568517 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -99,6 +99,8 @@ | |||
99 | #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ | 99 | #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ |
100 | #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */ | 100 | #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */ |
101 | #define B43_MMIO_RNG 0x65A | 101 | #define B43_MMIO_RNG 0x65A |
102 | #define B43_MMIO_IFSCTL 0x688 /* Interframe space control */ | ||
103 | #define B43_MMIO_IFSCTL_USE_EDCF 0x0004 | ||
102 | #define B43_MMIO_POWERUP_DELAY 0x6A8 | 104 | #define B43_MMIO_POWERUP_DELAY 0x6A8 |
103 | 105 | ||
104 | /* SPROM boardflags_lo values */ | 106 | /* SPROM boardflags_lo values */ |
@@ -587,15 +589,13 @@ struct b43_phy { | |||
587 | 589 | ||
588 | /* Data structures for DMA transmission, per 80211 core. */ | 590 | /* Data structures for DMA transmission, per 80211 core. */ |
589 | struct b43_dma { | 591 | struct b43_dma { |
590 | struct b43_dmaring *tx_ring0; | 592 | struct b43_dmaring *tx_ring_AC_BK; /* Background */ |
591 | struct b43_dmaring *tx_ring1; | 593 | struct b43_dmaring *tx_ring_AC_BE; /* Best Effort */ |
592 | struct b43_dmaring *tx_ring2; | 594 | struct b43_dmaring *tx_ring_AC_VI; /* Video */ |
593 | struct b43_dmaring *tx_ring3; | 595 | struct b43_dmaring *tx_ring_AC_VO; /* Voice */ |
594 | struct b43_dmaring *tx_ring4; | 596 | struct b43_dmaring *tx_ring_mcast; /* Multicast */ |
595 | struct b43_dmaring *tx_ring5; | 597 | |
596 | 598 | struct b43_dmaring *rx_ring; | |
597 | struct b43_dmaring *rx_ring0; | ||
598 | struct b43_dmaring *rx_ring3; /* only available on core.rev < 5 */ | ||
599 | }; | 599 | }; |
600 | 600 | ||
601 | /* Context information for a noise calculation (Link Quality). */ | 601 | /* Context information for a noise calculation (Link Quality). */ |
@@ -621,6 +621,35 @@ struct b43_key { | |||
621 | u8 algorithm; | 621 | u8 algorithm; |
622 | }; | 622 | }; |
623 | 623 | ||
624 | /* SHM offsets to the QOS data structures for the 4 different queues. */ | ||
625 | #define B43_QOS_PARAMS(queue) (B43_SHM_SH_EDCFQ + \ | ||
626 | (B43_NR_QOSPARAMS * sizeof(u16) * (queue))) | ||
627 | #define B43_QOS_BACKGROUND B43_QOS_PARAMS(0) | ||
628 | #define B43_QOS_BESTEFFORT B43_QOS_PARAMS(1) | ||
629 | #define B43_QOS_VIDEO B43_QOS_PARAMS(2) | ||
630 | #define B43_QOS_VOICE B43_QOS_PARAMS(3) | ||
631 | |||
632 | /* QOS parameter hardware data structure offsets. */ | ||
633 | #define B43_NR_QOSPARAMS 22 | ||
634 | enum { | ||
635 | B43_QOSPARAM_TXOP = 0, | ||
636 | B43_QOSPARAM_CWMIN, | ||
637 | B43_QOSPARAM_CWMAX, | ||
638 | B43_QOSPARAM_CWCUR, | ||
639 | B43_QOSPARAM_AIFS, | ||
640 | B43_QOSPARAM_BSLOTS, | ||
641 | B43_QOSPARAM_REGGAP, | ||
642 | B43_QOSPARAM_STATUS, | ||
643 | }; | ||
644 | |||
645 | /* QOS parameters for a queue. */ | ||
646 | struct b43_qos_params { | ||
647 | /* The QOS parameters */ | ||
648 | struct ieee80211_tx_queue_params p; | ||
649 | /* Does this need to get uploaded to hardware? */ | ||
650 | bool need_hw_update; | ||
651 | }; | ||
652 | |||
624 | struct b43_wldev; | 653 | struct b43_wldev; |
625 | 654 | ||
626 | /* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */ | 655 | /* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */ |
@@ -673,6 +702,12 @@ struct b43_wl { | |||
673 | struct sk_buff *current_beacon; | 702 | struct sk_buff *current_beacon; |
674 | bool beacon0_uploaded; | 703 | bool beacon0_uploaded; |
675 | bool beacon1_uploaded; | 704 | bool beacon1_uploaded; |
705 | |||
706 | /* The current QOS parameters for the 4 queues. | ||
707 | * This is protected by the irq_lock. */ | ||
708 | struct b43_qos_params qos_params[4]; | ||
709 | /* Workqueue for updating QOS parameters in hardware. */ | ||
710 | struct work_struct qos_update_work; | ||
676 | }; | 711 | }; |
677 | 712 | ||
678 | /* In-memory representation of a cached microcode file. */ | 713 | /* In-memory representation of a cached microcode file. */ |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 3dfb28a34be9..663aed4e9e05 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
39 | #include <linux/skbuff.h> | 39 | #include <linux/skbuff.h> |
40 | #include <linux/etherdevice.h> | 40 | #include <linux/etherdevice.h> |
41 | #include <asm/div64.h> | ||
41 | 42 | ||
42 | 43 | ||
43 | /* 32bit DMA ops. */ | 44 | /* 32bit DMA ops. */ |
@@ -291,52 +292,6 @@ static inline int request_slot(struct b43_dmaring *ring) | |||
291 | return slot; | 292 | return slot; |
292 | } | 293 | } |
293 | 294 | ||
294 | /* Mac80211-queue to b43-ring mapping */ | ||
295 | static struct b43_dmaring *priority_to_txring(struct b43_wldev *dev, | ||
296 | int queue_priority) | ||
297 | { | ||
298 | struct b43_dmaring *ring; | ||
299 | |||
300 | /*FIXME: For now we always run on TX-ring-1 */ | ||
301 | return dev->dma.tx_ring1; | ||
302 | |||
303 | /* 0 = highest priority */ | ||
304 | switch (queue_priority) { | ||
305 | default: | ||
306 | B43_WARN_ON(1); | ||
307 | /* fallthrough */ | ||
308 | case 0: | ||
309 | ring = dev->dma.tx_ring3; | ||
310 | break; | ||
311 | case 1: | ||
312 | ring = dev->dma.tx_ring2; | ||
313 | break; | ||
314 | case 2: | ||
315 | ring = dev->dma.tx_ring1; | ||
316 | break; | ||
317 | case 3: | ||
318 | ring = dev->dma.tx_ring0; | ||
319 | break; | ||
320 | } | ||
321 | |||
322 | return ring; | ||
323 | } | ||
324 | |||
325 | /* b43-ring to mac80211-queue mapping */ | ||
326 | static inline int txring_to_priority(struct b43_dmaring *ring) | ||
327 | { | ||
328 | static const u8 idx_to_prio[] = { 3, 2, 1, 0, }; | ||
329 | unsigned int index; | ||
330 | |||
331 | /*FIXME: have only one queue, for now */ | ||
332 | return 0; | ||
333 | |||
334 | index = ring->index; | ||
335 | if (B43_WARN_ON(index >= ARRAY_SIZE(idx_to_prio))) | ||
336 | index = 0; | ||
337 | return idx_to_prio[index]; | ||
338 | } | ||
339 | |||
340 | static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx) | 295 | static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx) |
341 | { | 296 | { |
342 | static const u16 map64[] = { | 297 | static const u16 map64[] = { |
@@ -924,16 +879,52 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
924 | goto out; | 879 | goto out; |
925 | } | 880 | } |
926 | 881 | ||
882 | #define divide(a, b) ({ \ | ||
883 | typeof(a) __a = a; \ | ||
884 | do_div(__a, b); \ | ||
885 | __a; \ | ||
886 | }) | ||
887 | |||
888 | #define modulo(a, b) ({ \ | ||
889 | typeof(a) __a = a; \ | ||
890 | do_div(__a, b); \ | ||
891 | }) | ||
892 | |||
927 | /* Main cleanup function. */ | 893 | /* Main cleanup function. */ |
928 | static void b43_destroy_dmaring(struct b43_dmaring *ring) | 894 | static void b43_destroy_dmaring(struct b43_dmaring *ring, |
895 | const char *ringname) | ||
929 | { | 896 | { |
930 | if (!ring) | 897 | if (!ring) |
931 | return; | 898 | return; |
932 | 899 | ||
933 | b43dbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots: %d/%d\n", | 900 | #ifdef CONFIG_B43_DEBUG |
934 | (unsigned int)(ring->type), | 901 | { |
935 | ring->mmio_base, | 902 | /* Print some statistics. */ |
936 | (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots); | 903 | u64 failed_packets = ring->nr_failed_tx_packets; |
904 | u64 succeed_packets = ring->nr_succeed_tx_packets; | ||
905 | u64 nr_packets = failed_packets + succeed_packets; | ||
906 | u64 permille_failed = 0, average_tries = 0; | ||
907 | |||
908 | if (nr_packets) | ||
909 | permille_failed = divide(failed_packets * 1000, nr_packets); | ||
910 | if (nr_packets) | ||
911 | average_tries = divide(ring->nr_total_packet_tries * 100, nr_packets); | ||
912 | |||
913 | b43dbg(ring->dev->wl, "DMA-%u %s: " | ||
914 | "Used slots %d/%d, Failed frames %llu/%llu = %llu.%01llu%%, " | ||
915 | "Average tries %llu.%02llu\n", | ||
916 | (unsigned int)(ring->type), ringname, | ||
917 | ring->max_used_slots, | ||
918 | ring->nr_slots, | ||
919 | (unsigned long long)failed_packets, | ||
920 | (unsigned long long)nr_packets, | ||
921 | (unsigned long long)divide(permille_failed, 10), | ||
922 | (unsigned long long)modulo(permille_failed, 10), | ||
923 | (unsigned long long)divide(average_tries, 100), | ||
924 | (unsigned long long)modulo(average_tries, 100)); | ||
925 | } | ||
926 | #endif /* DEBUG */ | ||
927 | |||
937 | /* Device IRQs are disabled prior entering this function, | 928 | /* Device IRQs are disabled prior entering this function, |
938 | * so no need to take care of concurrency with rx handler stuff. | 929 | * so no need to take care of concurrency with rx handler stuff. |
939 | */ | 930 | */ |
@@ -946,33 +937,26 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring) | |||
946 | kfree(ring); | 937 | kfree(ring); |
947 | } | 938 | } |
948 | 939 | ||
940 | #define destroy_ring(dma, ring) do { \ | ||
941 | b43_destroy_dmaring((dma)->ring, __stringify(ring)); \ | ||
942 | (dma)->ring = NULL; \ | ||
943 | } while (0) | ||
944 | |||
949 | void b43_dma_free(struct b43_wldev *dev) | 945 | void b43_dma_free(struct b43_wldev *dev) |
950 | { | 946 | { |
951 | struct b43_dma *dma = &dev->dma; | 947 | struct b43_dma *dma = &dev->dma; |
952 | 948 | ||
953 | b43_destroy_dmaring(dma->rx_ring3); | 949 | destroy_ring(dma, rx_ring); |
954 | dma->rx_ring3 = NULL; | 950 | destroy_ring(dma, tx_ring_AC_BK); |
955 | b43_destroy_dmaring(dma->rx_ring0); | 951 | destroy_ring(dma, tx_ring_AC_BE); |
956 | dma->rx_ring0 = NULL; | 952 | destroy_ring(dma, tx_ring_AC_VI); |
957 | 953 | destroy_ring(dma, tx_ring_AC_VO); | |
958 | b43_destroy_dmaring(dma->tx_ring5); | 954 | destroy_ring(dma, tx_ring_mcast); |
959 | dma->tx_ring5 = NULL; | ||
960 | b43_destroy_dmaring(dma->tx_ring4); | ||
961 | dma->tx_ring4 = NULL; | ||
962 | b43_destroy_dmaring(dma->tx_ring3); | ||
963 | dma->tx_ring3 = NULL; | ||
964 | b43_destroy_dmaring(dma->tx_ring2); | ||
965 | dma->tx_ring2 = NULL; | ||
966 | b43_destroy_dmaring(dma->tx_ring1); | ||
967 | dma->tx_ring1 = NULL; | ||
968 | b43_destroy_dmaring(dma->tx_ring0); | ||
969 | dma->tx_ring0 = NULL; | ||
970 | } | 955 | } |
971 | 956 | ||
972 | int b43_dma_init(struct b43_wldev *dev) | 957 | int b43_dma_init(struct b43_wldev *dev) |
973 | { | 958 | { |
974 | struct b43_dma *dma = &dev->dma; | 959 | struct b43_dma *dma = &dev->dma; |
975 | struct b43_dmaring *ring; | ||
976 | int err; | 960 | int err; |
977 | u64 dmamask; | 961 | u64 dmamask; |
978 | enum b43_dmatype type; | 962 | enum b43_dmatype type; |
@@ -1002,83 +986,57 @@ int b43_dma_init(struct b43_wldev *dev) | |||
1002 | 986 | ||
1003 | err = -ENOMEM; | 987 | err = -ENOMEM; |
1004 | /* setup TX DMA channels. */ | 988 | /* setup TX DMA channels. */ |
1005 | ring = b43_setup_dmaring(dev, 0, 1, type); | 989 | dma->tx_ring_AC_BK = b43_setup_dmaring(dev, 0, 1, type); |
1006 | if (!ring) | 990 | if (!dma->tx_ring_AC_BK) |
1007 | goto out; | 991 | goto out; |
1008 | dma->tx_ring0 = ring; | ||
1009 | 992 | ||
1010 | ring = b43_setup_dmaring(dev, 1, 1, type); | 993 | dma->tx_ring_AC_BE = b43_setup_dmaring(dev, 1, 1, type); |
1011 | if (!ring) | 994 | if (!dma->tx_ring_AC_BE) |
1012 | goto err_destroy_tx0; | 995 | goto err_destroy_bk; |
1013 | dma->tx_ring1 = ring; | ||
1014 | 996 | ||
1015 | ring = b43_setup_dmaring(dev, 2, 1, type); | 997 | dma->tx_ring_AC_VI = b43_setup_dmaring(dev, 2, 1, type); |
1016 | if (!ring) | 998 | if (!dma->tx_ring_AC_VI) |
1017 | goto err_destroy_tx1; | 999 | goto err_destroy_be; |
1018 | dma->tx_ring2 = ring; | ||
1019 | 1000 | ||
1020 | ring = b43_setup_dmaring(dev, 3, 1, type); | 1001 | dma->tx_ring_AC_VO = b43_setup_dmaring(dev, 3, 1, type); |
1021 | if (!ring) | 1002 | if (!dma->tx_ring_AC_VO) |
1022 | goto err_destroy_tx2; | 1003 | goto err_destroy_vi; |
1023 | dma->tx_ring3 = ring; | ||
1024 | 1004 | ||
1025 | ring = b43_setup_dmaring(dev, 4, 1, type); | 1005 | dma->tx_ring_mcast = b43_setup_dmaring(dev, 4, 1, type); |
1026 | if (!ring) | 1006 | if (!dma->tx_ring_mcast) |
1027 | goto err_destroy_tx3; | 1007 | goto err_destroy_vo; |
1028 | dma->tx_ring4 = ring; | ||
1029 | 1008 | ||
1030 | ring = b43_setup_dmaring(dev, 5, 1, type); | 1009 | /* setup RX DMA channel. */ |
1031 | if (!ring) | 1010 | dma->rx_ring = b43_setup_dmaring(dev, 0, 0, type); |
1032 | goto err_destroy_tx4; | 1011 | if (!dma->rx_ring) |
1033 | dma->tx_ring5 = ring; | 1012 | goto err_destroy_mcast; |
1034 | 1013 | ||
1035 | /* setup RX DMA channels. */ | 1014 | /* No support for the TX status DMA ring. */ |
1036 | ring = b43_setup_dmaring(dev, 0, 0, type); | 1015 | B43_WARN_ON(dev->dev->id.revision < 5); |
1037 | if (!ring) | ||
1038 | goto err_destroy_tx5; | ||
1039 | dma->rx_ring0 = ring; | ||
1040 | |||
1041 | if (dev->dev->id.revision < 5) { | ||
1042 | ring = b43_setup_dmaring(dev, 3, 0, type); | ||
1043 | if (!ring) | ||
1044 | goto err_destroy_rx0; | ||
1045 | dma->rx_ring3 = ring; | ||
1046 | } | ||
1047 | 1016 | ||
1048 | b43dbg(dev->wl, "%u-bit DMA initialized\n", | 1017 | b43dbg(dev->wl, "%u-bit DMA initialized\n", |
1049 | (unsigned int)type); | 1018 | (unsigned int)type); |
1050 | err = 0; | 1019 | err = 0; |
1051 | out: | 1020 | out: |
1052 | return err; | 1021 | return err; |
1053 | 1022 | ||
1054 | err_destroy_rx0: | 1023 | err_destroy_mcast: |
1055 | b43_destroy_dmaring(dma->rx_ring0); | 1024 | destroy_ring(dma, tx_ring_mcast); |
1056 | dma->rx_ring0 = NULL; | 1025 | err_destroy_vo: |
1057 | err_destroy_tx5: | 1026 | destroy_ring(dma, tx_ring_AC_VO); |
1058 | b43_destroy_dmaring(dma->tx_ring5); | 1027 | err_destroy_vi: |
1059 | dma->tx_ring5 = NULL; | 1028 | destroy_ring(dma, tx_ring_AC_VI); |
1060 | err_destroy_tx4: | 1029 | err_destroy_be: |
1061 | b43_destroy_dmaring(dma->tx_ring4); | 1030 | destroy_ring(dma, tx_ring_AC_BE); |
1062 | dma->tx_ring4 = NULL; | 1031 | err_destroy_bk: |
1063 | err_destroy_tx3: | 1032 | destroy_ring(dma, tx_ring_AC_BK); |
1064 | b43_destroy_dmaring(dma->tx_ring3); | 1033 | return err; |
1065 | dma->tx_ring3 = NULL; | ||
1066 | err_destroy_tx2: | ||
1067 | b43_destroy_dmaring(dma->tx_ring2); | ||
1068 | dma->tx_ring2 = NULL; | ||
1069 | err_destroy_tx1: | ||
1070 | b43_destroy_dmaring(dma->tx_ring1); | ||
1071 | dma->tx_ring1 = NULL; | ||
1072 | err_destroy_tx0: | ||
1073 | b43_destroy_dmaring(dma->tx_ring0); | ||
1074 | dma->tx_ring0 = NULL; | ||
1075 | goto out; | ||
1076 | } | 1034 | } |
1077 | 1035 | ||
1078 | /* Generate a cookie for the TX header. */ | 1036 | /* Generate a cookie for the TX header. */ |
1079 | static u16 generate_cookie(struct b43_dmaring *ring, int slot) | 1037 | static u16 generate_cookie(struct b43_dmaring *ring, int slot) |
1080 | { | 1038 | { |
1081 | u16 cookie = 0x1000; | 1039 | u16 cookie; |
1082 | 1040 | ||
1083 | /* Use the upper 4 bits of the cookie as | 1041 | /* Use the upper 4 bits of the cookie as |
1084 | * DMA controller ID and store the slot number | 1042 | * DMA controller ID and store the slot number |
@@ -1088,30 +1046,9 @@ static u16 generate_cookie(struct b43_dmaring *ring, int slot) | |||
1088 | * It can also not be 0xFFFF because that is special | 1046 | * It can also not be 0xFFFF because that is special |
1089 | * for multicast frames. | 1047 | * for multicast frames. |
1090 | */ | 1048 | */ |
1091 | switch (ring->index) { | 1049 | cookie = (((u16)ring->index + 1) << 12); |
1092 | case 0: | ||
1093 | cookie = 0x1000; | ||
1094 | break; | ||
1095 | case 1: | ||
1096 | cookie = 0x2000; | ||
1097 | break; | ||
1098 | case 2: | ||
1099 | cookie = 0x3000; | ||
1100 | break; | ||
1101 | case 3: | ||
1102 | cookie = 0x4000; | ||
1103 | break; | ||
1104 | case 4: | ||
1105 | cookie = 0x5000; | ||
1106 | break; | ||
1107 | case 5: | ||
1108 | cookie = 0x6000; | ||
1109 | break; | ||
1110 | default: | ||
1111 | B43_WARN_ON(1); | ||
1112 | } | ||
1113 | B43_WARN_ON(slot & ~0x0FFF); | 1050 | B43_WARN_ON(slot & ~0x0FFF); |
1114 | cookie |= (u16) slot; | 1051 | cookie |= (u16)slot; |
1115 | 1052 | ||
1116 | return cookie; | 1053 | return cookie; |
1117 | } | 1054 | } |
@@ -1125,22 +1062,19 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot) | |||
1125 | 1062 | ||
1126 | switch (cookie & 0xF000) { | 1063 | switch (cookie & 0xF000) { |
1127 | case 0x1000: | 1064 | case 0x1000: |
1128 | ring = dma->tx_ring0; | 1065 | ring = dma->tx_ring_AC_BK; |
1129 | break; | 1066 | break; |
1130 | case 0x2000: | 1067 | case 0x2000: |
1131 | ring = dma->tx_ring1; | 1068 | ring = dma->tx_ring_AC_BE; |
1132 | break; | 1069 | break; |
1133 | case 0x3000: | 1070 | case 0x3000: |
1134 | ring = dma->tx_ring2; | 1071 | ring = dma->tx_ring_AC_VI; |
1135 | break; | 1072 | break; |
1136 | case 0x4000: | 1073 | case 0x4000: |
1137 | ring = dma->tx_ring3; | 1074 | ring = dma->tx_ring_AC_VO; |
1138 | break; | 1075 | break; |
1139 | case 0x5000: | 1076 | case 0x5000: |
1140 | ring = dma->tx_ring4; | 1077 | ring = dma->tx_ring_mcast; |
1141 | break; | ||
1142 | case 0x6000: | ||
1143 | ring = dma->tx_ring5; | ||
1144 | break; | 1078 | break; |
1145 | default: | 1079 | default: |
1146 | B43_WARN_ON(1); | 1080 | B43_WARN_ON(1); |
@@ -1272,6 +1206,37 @@ static inline int should_inject_overflow(struct b43_dmaring *ring) | |||
1272 | return 0; | 1206 | return 0; |
1273 | } | 1207 | } |
1274 | 1208 | ||
1209 | /* Static mapping of mac80211's queues (priorities) to b43 DMA rings. */ | ||
1210 | static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev, | ||
1211 | u8 queue_prio) | ||
1212 | { | ||
1213 | struct b43_dmaring *ring; | ||
1214 | |||
1215 | if (b43_modparam_qos) { | ||
1216 | /* 0 = highest priority */ | ||
1217 | switch (queue_prio) { | ||
1218 | default: | ||
1219 | B43_WARN_ON(1); | ||
1220 | /* fallthrough */ | ||
1221 | case 0: | ||
1222 | ring = dev->dma.tx_ring_AC_VO; | ||
1223 | break; | ||
1224 | case 1: | ||
1225 | ring = dev->dma.tx_ring_AC_VI; | ||
1226 | break; | ||
1227 | case 2: | ||
1228 | ring = dev->dma.tx_ring_AC_BE; | ||
1229 | break; | ||
1230 | case 3: | ||
1231 | ring = dev->dma.tx_ring_AC_BK; | ||
1232 | break; | ||
1233 | } | ||
1234 | } else | ||
1235 | ring = dev->dma.tx_ring_AC_BE; | ||
1236 | |||
1237 | return ring; | ||
1238 | } | ||
1239 | |||
1275 | int b43_dma_tx(struct b43_wldev *dev, | 1240 | int b43_dma_tx(struct b43_wldev *dev, |
1276 | struct sk_buff *skb, struct ieee80211_tx_control *ctl) | 1241 | struct sk_buff *skb, struct ieee80211_tx_control *ctl) |
1277 | { | 1242 | { |
@@ -1288,13 +1253,13 @@ int b43_dma_tx(struct b43_wldev *dev, | |||
1288 | hdr = (struct ieee80211_hdr *)skb->data; | 1253 | hdr = (struct ieee80211_hdr *)skb->data; |
1289 | if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { | 1254 | if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { |
1290 | /* The multicast ring will be sent after the DTIM */ | 1255 | /* The multicast ring will be sent after the DTIM */ |
1291 | ring = dev->dma.tx_ring4; | 1256 | ring = dev->dma.tx_ring_mcast; |
1292 | /* Set the more-data bit. Ucode will clear it on | 1257 | /* Set the more-data bit. Ucode will clear it on |
1293 | * the last frame for us. */ | 1258 | * the last frame for us. */ |
1294 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 1259 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
1295 | } else { | 1260 | } else { |
1296 | /* Decide by priority where to put this frame. */ | 1261 | /* Decide by priority where to put this frame. */ |
1297 | ring = priority_to_txring(dev, ctl->queue); | 1262 | ring = select_ring_by_priority(dev, ctl->queue); |
1298 | } | 1263 | } |
1299 | 1264 | ||
1300 | spin_lock_irqsave(&ring->lock, flags); | 1265 | spin_lock_irqsave(&ring->lock, flags); |
@@ -1309,6 +1274,11 @@ int b43_dma_tx(struct b43_wldev *dev, | |||
1309 | * That would be a mac80211 bug. */ | 1274 | * That would be a mac80211 bug. */ |
1310 | B43_WARN_ON(ring->stopped); | 1275 | B43_WARN_ON(ring->stopped); |
1311 | 1276 | ||
1277 | /* Assign the queue number to the ring (if not already done before) | ||
1278 | * so TX status handling can use it. The queue to ring mapping is | ||
1279 | * static, so we don't need to store it per frame. */ | ||
1280 | ring->queue_prio = ctl->queue; | ||
1281 | |||
1312 | err = dma_tx_fragment(ring, skb, ctl); | 1282 | err = dma_tx_fragment(ring, skb, ctl); |
1313 | if (unlikely(err == -ENOKEY)) { | 1283 | if (unlikely(err == -ENOKEY)) { |
1314 | /* Drop this packet, as we don't have the encryption key | 1284 | /* Drop this packet, as we don't have the encryption key |
@@ -1325,7 +1295,7 @@ int b43_dma_tx(struct b43_wldev *dev, | |||
1325 | if ((free_slots(ring) < SLOTS_PER_PACKET) || | 1295 | if ((free_slots(ring) < SLOTS_PER_PACKET) || |
1326 | should_inject_overflow(ring)) { | 1296 | should_inject_overflow(ring)) { |
1327 | /* This TX ring is full. */ | 1297 | /* This TX ring is full. */ |
1328 | ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring)); | 1298 | ieee80211_stop_queue(dev->wl->hw, ctl->queue); |
1329 | ring->stopped = 1; | 1299 | ring->stopped = 1; |
1330 | if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { | 1300 | if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { |
1331 | b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); | 1301 | b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); |
@@ -1337,6 +1307,38 @@ out_unlock: | |||
1337 | return err; | 1307 | return err; |
1338 | } | 1308 | } |
1339 | 1309 | ||
1310 | static void b43_fill_txstatus_report(struct b43_dmaring *ring, | ||
1311 | struct ieee80211_tx_status *report, | ||
1312 | const struct b43_txstatus *status) | ||
1313 | { | ||
1314 | bool frame_failed = 0; | ||
1315 | |||
1316 | if (status->acked) { | ||
1317 | /* The frame was ACKed. */ | ||
1318 | report->flags |= IEEE80211_TX_STATUS_ACK; | ||
1319 | } else { | ||
1320 | /* The frame was not ACKed... */ | ||
1321 | if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) { | ||
1322 | /* ...but we expected an ACK. */ | ||
1323 | frame_failed = 1; | ||
1324 | report->excessive_retries = 1; | ||
1325 | } | ||
1326 | } | ||
1327 | if (status->frame_count == 0) { | ||
1328 | /* The frame was not transmitted at all. */ | ||
1329 | report->retry_count = 0; | ||
1330 | } else { | ||
1331 | report->retry_count = status->frame_count - 1; | ||
1332 | #ifdef CONFIG_B43_DEBUG | ||
1333 | if (frame_failed) | ||
1334 | ring->nr_failed_tx_packets++; | ||
1335 | else | ||
1336 | ring->nr_succeed_tx_packets++; | ||
1337 | ring->nr_total_packet_tries += status->frame_count; | ||
1338 | #endif /* DEBUG */ | ||
1339 | } | ||
1340 | } | ||
1341 | |||
1340 | void b43_dma_handle_txstatus(struct b43_wldev *dev, | 1342 | void b43_dma_handle_txstatus(struct b43_wldev *dev, |
1341 | const struct b43_txstatus *status) | 1343 | const struct b43_txstatus *status) |
1342 | { | 1344 | { |
@@ -1371,18 +1373,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1371 | * status of the transmission. | 1373 | * status of the transmission. |
1372 | * Some fields of txstat are already filled in dma_tx(). | 1374 | * Some fields of txstat are already filled in dma_tx(). |
1373 | */ | 1375 | */ |
1374 | if (status->acked) { | 1376 | b43_fill_txstatus_report(ring, &(meta->txstat), status); |
1375 | meta->txstat.flags |= IEEE80211_TX_STATUS_ACK; | ||
1376 | } else { | ||
1377 | if (!(meta->txstat.control.flags | ||
1378 | & IEEE80211_TXCTL_NO_ACK)) | ||
1379 | meta->txstat.excessive_retries = 1; | ||
1380 | } | ||
1381 | if (status->frame_count == 0) { | ||
1382 | /* The frame was not transmitted at all. */ | ||
1383 | meta->txstat.retry_count = 0; | ||
1384 | } else | ||
1385 | meta->txstat.retry_count = status->frame_count - 1; | ||
1386 | ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb, | 1377 | ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb, |
1387 | &(meta->txstat)); | 1378 | &(meta->txstat)); |
1388 | /* skb is freed by ieee80211_tx_status_irqsafe() */ | 1379 | /* skb is freed by ieee80211_tx_status_irqsafe() */ |
@@ -1404,7 +1395,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1404 | dev->stats.last_tx = jiffies; | 1395 | dev->stats.last_tx = jiffies; |
1405 | if (ring->stopped) { | 1396 | if (ring->stopped) { |
1406 | B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET); | 1397 | B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET); |
1407 | ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring)); | 1398 | ieee80211_wake_queue(dev->wl->hw, ring->queue_prio); |
1408 | ring->stopped = 0; | 1399 | ring->stopped = 0; |
1409 | if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { | 1400 | if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { |
1410 | b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index); | 1401 | b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index); |
@@ -1425,7 +1416,7 @@ void b43_dma_get_tx_stats(struct b43_wldev *dev, | |||
1425 | 1416 | ||
1426 | for (i = 0; i < nr_queues; i++) { | 1417 | for (i = 0; i < nr_queues; i++) { |
1427 | data = &(stats->data[i]); | 1418 | data = &(stats->data[i]); |
1428 | ring = priority_to_txring(dev, i); | 1419 | ring = select_ring_by_priority(dev, i); |
1429 | 1420 | ||
1430 | spin_lock_irqsave(&ring->lock, flags); | 1421 | spin_lock_irqsave(&ring->lock, flags); |
1431 | data->len = ring->used_slots / SLOTS_PER_PACKET; | 1422 | data->len = ring->used_slots / SLOTS_PER_PACKET; |
@@ -1451,25 +1442,6 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) | |||
1451 | sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); | 1442 | sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); |
1452 | skb = meta->skb; | 1443 | skb = meta->skb; |
1453 | 1444 | ||
1454 | if (ring->index == 3) { | ||
1455 | /* We received an xmit status. */ | ||
1456 | struct b43_hwtxstatus *hw = (struct b43_hwtxstatus *)skb->data; | ||
1457 | int i = 0; | ||
1458 | |||
1459 | while (hw->cookie == 0) { | ||
1460 | if (i > 100) | ||
1461 | break; | ||
1462 | i++; | ||
1463 | udelay(2); | ||
1464 | barrier(); | ||
1465 | } | ||
1466 | b43_handle_hwtxstatus(ring->dev, hw); | ||
1467 | /* recycle the descriptor buffer. */ | ||
1468 | sync_descbuffer_for_device(ring, meta->dmaaddr, | ||
1469 | ring->rx_buffersize); | ||
1470 | |||
1471 | return; | ||
1472 | } | ||
1473 | rxhdr = (struct b43_rxhdr_fw4 *)skb->data; | 1445 | rxhdr = (struct b43_rxhdr_fw4 *)skb->data; |
1474 | len = le16_to_cpu(rxhdr->frame_len); | 1446 | len = le16_to_cpu(rxhdr->frame_len); |
1475 | if (len == 0) { | 1447 | if (len == 0) { |
@@ -1526,7 +1498,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) | |||
1526 | skb_pull(skb, ring->frameoffset); | 1498 | skb_pull(skb, ring->frameoffset); |
1527 | 1499 | ||
1528 | b43_rx(ring->dev, skb, rxhdr); | 1500 | b43_rx(ring->dev, skb, rxhdr); |
1529 | drop: | 1501 | drop: |
1530 | return; | 1502 | return; |
1531 | } | 1503 | } |
1532 | 1504 | ||
@@ -1572,21 +1544,19 @@ static void b43_dma_tx_resume_ring(struct b43_dmaring *ring) | |||
1572 | void b43_dma_tx_suspend(struct b43_wldev *dev) | 1544 | void b43_dma_tx_suspend(struct b43_wldev *dev) |
1573 | { | 1545 | { |
1574 | b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); | 1546 | b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); |
1575 | b43_dma_tx_suspend_ring(dev->dma.tx_ring0); | 1547 | b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BK); |
1576 | b43_dma_tx_suspend_ring(dev->dma.tx_ring1); | 1548 | b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BE); |
1577 | b43_dma_tx_suspend_ring(dev->dma.tx_ring2); | 1549 | b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VI); |
1578 | b43_dma_tx_suspend_ring(dev->dma.tx_ring3); | 1550 | b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VO); |
1579 | b43_dma_tx_suspend_ring(dev->dma.tx_ring4); | 1551 | b43_dma_tx_suspend_ring(dev->dma.tx_ring_mcast); |
1580 | b43_dma_tx_suspend_ring(dev->dma.tx_ring5); | ||
1581 | } | 1552 | } |
1582 | 1553 | ||
1583 | void b43_dma_tx_resume(struct b43_wldev *dev) | 1554 | void b43_dma_tx_resume(struct b43_wldev *dev) |
1584 | { | 1555 | { |
1585 | b43_dma_tx_resume_ring(dev->dma.tx_ring5); | 1556 | b43_dma_tx_resume_ring(dev->dma.tx_ring_mcast); |
1586 | b43_dma_tx_resume_ring(dev->dma.tx_ring4); | 1557 | b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VO); |
1587 | b43_dma_tx_resume_ring(dev->dma.tx_ring3); | 1558 | b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VI); |
1588 | b43_dma_tx_resume_ring(dev->dma.tx_ring2); | 1559 | b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BE); |
1589 | b43_dma_tx_resume_ring(dev->dma.tx_ring1); | 1560 | b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK); |
1590 | b43_dma_tx_resume_ring(dev->dma.tx_ring0); | ||
1591 | b43_power_saving_ctl_bits(dev, 0); | 1561 | b43_power_saving_ctl_bits(dev, 0); |
1592 | } | 1562 | } |
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index c0d6b69e6501..ea27085dec0e 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h | |||
@@ -245,6 +245,9 @@ struct b43_dmaring { | |||
245 | enum b43_dmatype type; | 245 | enum b43_dmatype type; |
246 | /* Boolean. Is this ring stopped at ieee80211 level? */ | 246 | /* Boolean. Is this ring stopped at ieee80211 level? */ |
247 | bool stopped; | 247 | bool stopped; |
248 | /* The QOS priority assigned to this ring. Only used for TX rings. | ||
249 | * This is the mac80211 "queue" value. */ | ||
250 | u8 queue_prio; | ||
248 | /* Lock, only used for TX. */ | 251 | /* Lock, only used for TX. */ |
249 | spinlock_t lock; | 252 | spinlock_t lock; |
250 | struct b43_wldev *dev; | 253 | struct b43_wldev *dev; |
@@ -253,7 +256,13 @@ struct b43_dmaring { | |||
253 | int max_used_slots; | 256 | int max_used_slots; |
254 | /* Last time we injected a ring overflow. */ | 257 | /* Last time we injected a ring overflow. */ |
255 | unsigned long last_injected_overflow; | 258 | unsigned long last_injected_overflow; |
256 | #endif /* CONFIG_B43_DEBUG */ | 259 | /* Statistics: Number of successfully transmitted packets */ |
260 | u64 nr_succeed_tx_packets; | ||
261 | /* Statistics: Number of failed TX packets */ | ||
262 | u64 nr_failed_tx_packets; | ||
263 | /* Statistics: Total number of TX plus all retries. */ | ||
264 | u64 nr_total_packet_tries; | ||
265 | #endif /* CONFIG_B43_DEBUG */ | ||
257 | }; | 266 | }; |
258 | 267 | ||
259 | static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset) | 268 | static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset) |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index f745308faaad..694e29570e5d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -78,6 +78,11 @@ static int modparam_nohwcrypt; | |||
78 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); | 78 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); |
79 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 79 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
80 | 80 | ||
81 | int b43_modparam_qos = 1; | ||
82 | module_param_named(qos, b43_modparam_qos, int, 0444); | ||
83 | MODULE_PARM_DESC(qos, "Enable QOS support (default on)"); | ||
84 | |||
85 | |||
81 | static const struct ssb_device_id b43_ssb_tbl[] = { | 86 | static const struct ssb_device_id b43_ssb_tbl[] = { |
82 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), | 87 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), |
83 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6), | 88 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6), |
@@ -1589,11 +1594,10 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev) | |||
1589 | 1594 | ||
1590 | /* Check the DMA reason registers for received data. */ | 1595 | /* Check the DMA reason registers for received data. */ |
1591 | if (dma_reason[0] & B43_DMAIRQ_RX_DONE) | 1596 | if (dma_reason[0] & B43_DMAIRQ_RX_DONE) |
1592 | b43_dma_rx(dev->dma.rx_ring0); | 1597 | b43_dma_rx(dev->dma.rx_ring); |
1593 | if (dma_reason[3] & B43_DMAIRQ_RX_DONE) | ||
1594 | b43_dma_rx(dev->dma.rx_ring3); | ||
1595 | B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE); | 1598 | B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE); |
1596 | B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE); | 1599 | B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE); |
1600 | B43_WARN_ON(dma_reason[3] & B43_DMAIRQ_RX_DONE); | ||
1597 | B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE); | 1601 | B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE); |
1598 | B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE); | 1602 | B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE); |
1599 | 1603 | ||
@@ -2708,10 +2712,178 @@ out: | |||
2708 | return NETDEV_TX_OK; | 2712 | return NETDEV_TX_OK; |
2709 | } | 2713 | } |
2710 | 2714 | ||
2715 | /* Locking: wl->irq_lock */ | ||
2716 | static void b43_qos_params_upload(struct b43_wldev *dev, | ||
2717 | const struct ieee80211_tx_queue_params *p, | ||
2718 | u16 shm_offset) | ||
2719 | { | ||
2720 | u16 params[B43_NR_QOSPARAMS]; | ||
2721 | int cw_min, cw_max, aifs, bslots, tmp; | ||
2722 | unsigned int i; | ||
2723 | |||
2724 | const u16 aCWmin = 0x0001; | ||
2725 | const u16 aCWmax = 0x03FF; | ||
2726 | |||
2727 | /* Calculate the default values for the parameters, if needed. */ | ||
2728 | switch (shm_offset) { | ||
2729 | case B43_QOS_VOICE: | ||
2730 | aifs = (p->aifs == -1) ? 2 : p->aifs; | ||
2731 | cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 4 - 1) : p->cw_min; | ||
2732 | cw_max = (p->cw_max == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_max; | ||
2733 | break; | ||
2734 | case B43_QOS_VIDEO: | ||
2735 | aifs = (p->aifs == -1) ? 2 : p->aifs; | ||
2736 | cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_min; | ||
2737 | cw_max = (p->cw_max == 0) ? aCWmin : p->cw_max; | ||
2738 | break; | ||
2739 | case B43_QOS_BESTEFFORT: | ||
2740 | aifs = (p->aifs == -1) ? 3 : p->aifs; | ||
2741 | cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min; | ||
2742 | cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max; | ||
2743 | break; | ||
2744 | case B43_QOS_BACKGROUND: | ||
2745 | aifs = (p->aifs == -1) ? 7 : p->aifs; | ||
2746 | cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min; | ||
2747 | cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max; | ||
2748 | break; | ||
2749 | default: | ||
2750 | B43_WARN_ON(1); | ||
2751 | return; | ||
2752 | } | ||
2753 | if (cw_min <= 0) | ||
2754 | cw_min = aCWmin; | ||
2755 | if (cw_max <= 0) | ||
2756 | cw_max = aCWmin; | ||
2757 | bslots = b43_read16(dev, B43_MMIO_RNG) % cw_min; | ||
2758 | |||
2759 | memset(¶ms, 0, sizeof(params)); | ||
2760 | |||
2761 | params[B43_QOSPARAM_TXOP] = p->txop * 32; | ||
2762 | params[B43_QOSPARAM_CWMIN] = cw_min; | ||
2763 | params[B43_QOSPARAM_CWMAX] = cw_max; | ||
2764 | params[B43_QOSPARAM_CWCUR] = cw_min; | ||
2765 | params[B43_QOSPARAM_AIFS] = aifs; | ||
2766 | params[B43_QOSPARAM_BSLOTS] = bslots; | ||
2767 | params[B43_QOSPARAM_REGGAP] = bslots + aifs; | ||
2768 | |||
2769 | for (i = 0; i < ARRAY_SIZE(params); i++) { | ||
2770 | if (i == B43_QOSPARAM_STATUS) { | ||
2771 | tmp = b43_shm_read16(dev, B43_SHM_SHARED, | ||
2772 | shm_offset + (i * 2)); | ||
2773 | /* Mark the parameters as updated. */ | ||
2774 | tmp |= 0x100; | ||
2775 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
2776 | shm_offset + (i * 2), | ||
2777 | tmp); | ||
2778 | } else { | ||
2779 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
2780 | shm_offset + (i * 2), | ||
2781 | params[i]); | ||
2782 | } | ||
2783 | } | ||
2784 | } | ||
2785 | |||
2786 | /* Update the QOS parameters in hardware. */ | ||
2787 | static void b43_qos_update(struct b43_wldev *dev) | ||
2788 | { | ||
2789 | struct b43_wl *wl = dev->wl; | ||
2790 | struct b43_qos_params *params; | ||
2791 | unsigned long flags; | ||
2792 | unsigned int i; | ||
2793 | |||
2794 | /* Mapping of mac80211 queues to b43 SHM offsets. */ | ||
2795 | static const u16 qos_shm_offsets[] = { | ||
2796 | [0] = B43_QOS_VOICE, | ||
2797 | [1] = B43_QOS_VIDEO, | ||
2798 | [2] = B43_QOS_BESTEFFORT, | ||
2799 | [3] = B43_QOS_BACKGROUND, | ||
2800 | }; | ||
2801 | BUILD_BUG_ON(ARRAY_SIZE(qos_shm_offsets) != ARRAY_SIZE(wl->qos_params)); | ||
2802 | |||
2803 | b43_mac_suspend(dev); | ||
2804 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
2805 | |||
2806 | for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) { | ||
2807 | params = &(wl->qos_params[i]); | ||
2808 | if (params->need_hw_update) { | ||
2809 | b43_qos_params_upload(dev, &(params->p), | ||
2810 | qos_shm_offsets[i]); | ||
2811 | params->need_hw_update = 0; | ||
2812 | } | ||
2813 | } | ||
2814 | |||
2815 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
2816 | b43_mac_enable(dev); | ||
2817 | } | ||
2818 | |||
2819 | static void b43_qos_clear(struct b43_wl *wl) | ||
2820 | { | ||
2821 | struct b43_qos_params *params; | ||
2822 | unsigned int i; | ||
2823 | |||
2824 | for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) { | ||
2825 | params = &(wl->qos_params[i]); | ||
2826 | |||
2827 | memset(&(params->p), 0, sizeof(params->p)); | ||
2828 | params->p.aifs = -1; | ||
2829 | params->need_hw_update = 1; | ||
2830 | } | ||
2831 | } | ||
2832 | |||
2833 | /* Initialize the core's QOS capabilities */ | ||
2834 | static void b43_qos_init(struct b43_wldev *dev) | ||
2835 | { | ||
2836 | struct b43_wl *wl = dev->wl; | ||
2837 | unsigned int i; | ||
2838 | |||
2839 | /* Upload the current QOS parameters. */ | ||
2840 | for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) | ||
2841 | wl->qos_params[i].need_hw_update = 1; | ||
2842 | b43_qos_update(dev); | ||
2843 | |||
2844 | /* Enable QOS support. */ | ||
2845 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF); | ||
2846 | b43_write16(dev, B43_MMIO_IFSCTL, | ||
2847 | b43_read16(dev, B43_MMIO_IFSCTL) | ||
2848 | | B43_MMIO_IFSCTL_USE_EDCF); | ||
2849 | } | ||
2850 | |||
2851 | static void b43_qos_update_work(struct work_struct *work) | ||
2852 | { | ||
2853 | struct b43_wl *wl = container_of(work, struct b43_wl, qos_update_work); | ||
2854 | struct b43_wldev *dev; | ||
2855 | |||
2856 | mutex_lock(&wl->mutex); | ||
2857 | dev = wl->current_dev; | ||
2858 | if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) | ||
2859 | b43_qos_update(dev); | ||
2860 | mutex_unlock(&wl->mutex); | ||
2861 | } | ||
2862 | |||
2711 | static int b43_op_conf_tx(struct ieee80211_hw *hw, | 2863 | static int b43_op_conf_tx(struct ieee80211_hw *hw, |
2712 | int queue, | 2864 | int _queue, |
2713 | const struct ieee80211_tx_queue_params *params) | 2865 | const struct ieee80211_tx_queue_params *params) |
2714 | { | 2866 | { |
2867 | struct b43_wl *wl = hw_to_b43_wl(hw); | ||
2868 | unsigned long flags; | ||
2869 | unsigned int queue = (unsigned int)_queue; | ||
2870 | struct b43_qos_params *p; | ||
2871 | |||
2872 | if (queue >= ARRAY_SIZE(wl->qos_params)) { | ||
2873 | /* Queue not available or don't support setting | ||
2874 | * params on this queue. Return success to not | ||
2875 | * confuse mac80211. */ | ||
2876 | return 0; | ||
2877 | } | ||
2878 | |||
2879 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
2880 | p = &(wl->qos_params[queue]); | ||
2881 | memcpy(&(p->p), params, sizeof(p->p)); | ||
2882 | p->need_hw_update = 1; | ||
2883 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
2884 | |||
2885 | queue_work(hw->workqueue, &wl->qos_update_work); | ||
2886 | |||
2715 | return 0; | 2887 | return 0; |
2716 | } | 2888 | } |
2717 | 2889 | ||
@@ -3732,6 +3904,7 @@ static int b43_op_start(struct ieee80211_hw *hw) | |||
3732 | memset(wl->mac_addr, 0, ETH_ALEN); | 3904 | memset(wl->mac_addr, 0, ETH_ALEN); |
3733 | wl->filter_flags = 0; | 3905 | wl->filter_flags = 0; |
3734 | wl->radiotap_enabled = 0; | 3906 | wl->radiotap_enabled = 0; |
3907 | b43_qos_clear(wl); | ||
3735 | 3908 | ||
3736 | /* First register RFkill. | 3909 | /* First register RFkill. |
3737 | * LEDs that are registered later depend on it. */ | 3910 | * LEDs that are registered later depend on it. */ |
@@ -3773,6 +3946,7 @@ static void b43_op_stop(struct ieee80211_hw *hw) | |||
3773 | struct b43_wldev *dev = wl->current_dev; | 3946 | struct b43_wldev *dev = wl->current_dev; |
3774 | 3947 | ||
3775 | b43_rfkill_exit(dev); | 3948 | b43_rfkill_exit(dev); |
3949 | cancel_work_sync(&(wl->qos_update_work)); | ||
3776 | 3950 | ||
3777 | mutex_lock(&wl->mutex); | 3951 | mutex_lock(&wl->mutex); |
3778 | if (b43_status(dev) >= B43_STAT_STARTED) | 3952 | if (b43_status(dev) >= B43_STAT_STARTED) |
@@ -3835,6 +4009,16 @@ static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw, | |||
3835 | return 0; | 4009 | return 0; |
3836 | } | 4010 | } |
3837 | 4011 | ||
4012 | static void b43_op_sta_notify(struct ieee80211_hw *hw, | ||
4013 | struct ieee80211_vif *vif, | ||
4014 | enum sta_notify_cmd notify_cmd, | ||
4015 | const u8 *addr) | ||
4016 | { | ||
4017 | struct b43_wl *wl = hw_to_b43_wl(hw); | ||
4018 | |||
4019 | B43_WARN_ON(!vif || wl->vif != vif); | ||
4020 | } | ||
4021 | |||
3838 | static const struct ieee80211_ops b43_hw_ops = { | 4022 | static const struct ieee80211_ops b43_hw_ops = { |
3839 | .tx = b43_op_tx, | 4023 | .tx = b43_op_tx, |
3840 | .conf_tx = b43_op_conf_tx, | 4024 | .conf_tx = b43_op_conf_tx, |
@@ -3851,6 +4035,7 @@ static const struct ieee80211_ops b43_hw_ops = { | |||
3851 | .set_retry_limit = b43_op_set_retry_limit, | 4035 | .set_retry_limit = b43_op_set_retry_limit, |
3852 | .set_tim = b43_op_beacon_set_tim, | 4036 | .set_tim = b43_op_beacon_set_tim, |
3853 | .beacon_update = b43_op_ibss_beacon_update, | 4037 | .beacon_update = b43_op_ibss_beacon_update, |
4038 | .sta_notify = b43_op_sta_notify, | ||
3854 | }; | 4039 | }; |
3855 | 4040 | ||
3856 | /* Hard-reset the chip. Do not call this directly. | 4041 | /* Hard-reset the chip. Do not call this directly. |
@@ -4122,7 +4307,7 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
4122 | hw->max_signal = 100; | 4307 | hw->max_signal = 100; |
4123 | hw->max_rssi = -110; | 4308 | hw->max_rssi = -110; |
4124 | hw->max_noise = -110; | 4309 | hw->max_noise = -110; |
4125 | hw->queues = 1; /* FIXME: hardware has more queues */ | 4310 | hw->queues = b43_modparam_qos ? 4 : 1; |
4126 | SET_IEEE80211_DEV(hw, dev->dev); | 4311 | SET_IEEE80211_DEV(hw, dev->dev); |
4127 | if (is_valid_ether_addr(sprom->et1mac)) | 4312 | if (is_valid_ether_addr(sprom->et1mac)) |
4128 | SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); | 4313 | SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); |
@@ -4138,6 +4323,7 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
4138 | spin_lock_init(&wl->shm_lock); | 4323 | spin_lock_init(&wl->shm_lock); |
4139 | mutex_init(&wl->mutex); | 4324 | mutex_init(&wl->mutex); |
4140 | INIT_LIST_HEAD(&wl->devlist); | 4325 | INIT_LIST_HEAD(&wl->devlist); |
4326 | INIT_WORK(&wl->qos_update_work, b43_qos_update_work); | ||
4141 | 4327 | ||
4142 | ssb_set_devtypedata(dev, wl); | 4328 | ssb_set_devtypedata(dev, wl); |
4143 | b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); | 4329 | b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); |
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 24a79f5d6ff5..1197975f9207 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h | |||
@@ -38,6 +38,10 @@ | |||
38 | /* Magic helper macro to pad structures. Ignore those above. It's magic. */ | 38 | /* Magic helper macro to pad structures. Ignore those above. It's magic. */ |
39 | #define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) | 39 | #define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) |
40 | 40 | ||
41 | |||
42 | extern int b43_modparam_qos; | ||
43 | |||
44 | |||
41 | /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ | 45 | /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ |
42 | static inline u8 b43_freq_to_channel_5ghz(int freq) | 46 | static inline u8 b43_freq_to_channel_5ghz(int freq) |
43 | { | 47 | { |
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 187c11bee0f1..ec10a8e182f9 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -705,30 +705,3 @@ void b43_tx_resume(struct b43_wldev *dev) | |||
705 | { | 705 | { |
706 | b43_dma_tx_resume(dev); | 706 | b43_dma_tx_resume(dev); |
707 | } | 707 | } |
708 | |||
709 | #if 0 | ||
710 | static void upload_qos_parms(struct b43_wldev *dev, | ||
711 | const u16 * parms, u16 offset) | ||
712 | { | ||
713 | int i; | ||
714 | |||
715 | for (i = 0; i < B43_NR_QOSPARMS; i++) { | ||
716 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
717 | offset + (i * 2), parms[i]); | ||
718 | } | ||
719 | } | ||
720 | #endif | ||
721 | |||
722 | /* Initialize the QoS parameters */ | ||
723 | void b43_qos_init(struct b43_wldev *dev) | ||
724 | { | ||
725 | /* FIXME: This function must probably be called from the mac80211 | ||
726 | * config callback. */ | ||
727 | return; | ||
728 | |||
729 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF); | ||
730 | //FIXME kill magic | ||
731 | b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4); | ||
732 | |||
733 | /*TODO: We might need some stack support here to get the values. */ | ||
734 | } | ||
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 41765039552b..bf58a8a85258 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h | |||
@@ -302,18 +302,6 @@ void b43_handle_hwtxstatus(struct b43_wldev *dev, | |||
302 | void b43_tx_suspend(struct b43_wldev *dev); | 302 | void b43_tx_suspend(struct b43_wldev *dev); |
303 | void b43_tx_resume(struct b43_wldev *dev); | 303 | void b43_tx_resume(struct b43_wldev *dev); |
304 | 304 | ||
305 | #define B43_NR_QOSPARMS 22 | ||
306 | enum { | ||
307 | B43_QOSPARM_TXOP = 0, | ||
308 | B43_QOSPARM_CWMIN, | ||
309 | B43_QOSPARM_CWMAX, | ||
310 | B43_QOSPARM_CWCUR, | ||
311 | B43_QOSPARM_AIFS, | ||
312 | B43_QOSPARM_BSLOTS, | ||
313 | B43_QOSPARM_REGGAP, | ||
314 | B43_QOSPARM_STATUS, | ||
315 | }; | ||
316 | void b43_qos_init(struct b43_wldev *dev); | ||
317 | 305 | ||
318 | /* Helper functions for converting the key-table index from "firmware-format" | 306 | /* Helper functions for converting the key-table index from "firmware-format" |
319 | * to "raw-format" and back. The firmware API changed for this at some revision. | 307 | * to "raw-format" and back. The firmware API changed for this at some revision. |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 24c3e3ddafc6..5b7c0160e1fa 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -1,7 +1,12 @@ | |||
1 | config IWLCORE | ||
2 | tristate "Intel Wireless Wifi Core" | ||
3 | depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL | ||
4 | |||
1 | config IWL4965 | 5 | config IWL4965 |
2 | tristate "Intel Wireless WiFi 4965AGN" | 6 | tristate "Intel Wireless WiFi 4965AGN" |
3 | depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL | 7 | depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL |
4 | select FW_LOADER | 8 | select FW_LOADER |
9 | select IWLCORE | ||
5 | ---help--- | 10 | ---help--- |
6 | Select to build the driver supporting the: | 11 | Select to build the driver supporting the: |
7 | 12 | ||
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 3bbd38358d53..6b85cca9b3f1 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -1,3 +1,6 @@ | |||
1 | obj-$(CONFIG_IWLCORE) += iwlcore.o | ||
2 | iwlcore-objs = iwl-core.o | ||
3 | |||
1 | obj-$(CONFIG_IWL3945) += iwl3945.o | 4 | obj-$(CONFIG_IWL3945) += iwl3945.o |
2 | iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o | 5 | iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o |
3 | 6 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index 20fbb32c33bd..8b7ef9f1b57b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h | |||
@@ -666,26 +666,26 @@ struct iwl3945_rx_frame_hdr { | |||
666 | u8 payload[0]; | 666 | u8 payload[0]; |
667 | } __attribute__ ((packed)); | 667 | } __attribute__ ((packed)); |
668 | 668 | ||
669 | #define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0) | 669 | #define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0) |
670 | #define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1) | 670 | #define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1) |
671 | 671 | ||
672 | #define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0) | 672 | #define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0) |
673 | #define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1) | 673 | #define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1) |
674 | #define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2) | 674 | #define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2) |
675 | #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3) | 675 | #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3) |
676 | #define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0) | 676 | #define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0) |
677 | 677 | ||
678 | #define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) | 678 | #define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) |
679 | #define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) | 679 | #define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) |
680 | #define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) | 680 | #define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) |
681 | #define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) | 681 | #define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) |
682 | #define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) | 682 | #define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) |
683 | 683 | ||
684 | #define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) | 684 | #define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) |
685 | #define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) | 685 | #define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) |
686 | #define RX_RES_STATUS_DECRYPT_OK (0x3 << 11) | 686 | #define RX_RES_STATUS_DECRYPT_OK (0x3 << 11) |
687 | #define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) | 687 | #define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) |
688 | #define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) | 688 | #define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) |
689 | 689 | ||
690 | struct iwl3945_rx_frame_end { | 690 | struct iwl3945_rx_frame_end { |
691 | __le32 status; | 691 | __le32 status; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-core.h b/drivers/net/wireless/iwlwifi/iwl-3945-core.h new file mode 100644 index 000000000000..bc12f97ba0b1 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-3945-core.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Tomas Winkler <tomas.winkler@intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __iwl_3945_dev_h__ | ||
64 | #define __iwl_3945_dev_h__ | ||
65 | |||
66 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | ||
67 | .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ | ||
68 | .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ | ||
69 | .driver_data = (kernel_ulong_t)&(cfg) | ||
70 | |||
71 | #define IWL_SKU_G 0x1 | ||
72 | #define IWL_SKU_A 0x2 | ||
73 | |||
74 | struct iwl_3945_cfg { | ||
75 | const char *name; | ||
76 | const char *fw_name; | ||
77 | unsigned int sku; | ||
78 | }; | ||
79 | |||
80 | #endif /* __iwl_dev_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h index f853c6b9f76e..28ecfe8d39a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h | |||
@@ -40,6 +40,15 @@ do { if (iwl3945_debug_level & (level)) \ | |||
40 | do { if ((iwl3945_debug_level & (level)) && net_ratelimit()) \ | 40 | do { if ((iwl3945_debug_level & (level)) && net_ratelimit()) \ |
41 | printk(KERN_ERR DRV_NAME": %c %s " fmt, \ | 41 | printk(KERN_ERR DRV_NAME": %c %s " fmt, \ |
42 | in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) | 42 | in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) |
43 | |||
44 | static inline void iwl3945_print_hex_dump(int level, void *p, u32 len) | ||
45 | { | ||
46 | if (!(iwl3945_debug_level & level)) | ||
47 | return; | ||
48 | |||
49 | print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, | ||
50 | p, len, 1); | ||
51 | } | ||
43 | #else | 52 | #else |
44 | static inline void IWL_DEBUG(int level, const char *fmt, ...) | 53 | static inline void IWL_DEBUG(int level, const char *fmt, ...) |
45 | { | 54 | { |
@@ -47,7 +56,12 @@ static inline void IWL_DEBUG(int level, const char *fmt, ...) | |||
47 | static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) | 56 | static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) |
48 | { | 57 | { |
49 | } | 58 | } |
50 | #endif /* CONFIG_IWL3945_DEBUG */ | 59 | static inline void iwl3945_print_hex_dump(int level, void *p, u32 len) |
60 | { | ||
61 | } | ||
62 | #endif /* CONFIG_IWL3945_DEBUG */ | ||
63 | |||
64 | |||
51 | 65 | ||
52 | /* | 66 | /* |
53 | * To use the debug system; | 67 | * To use the debug system; |
@@ -143,6 +157,7 @@ static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) | |||
143 | IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) | 157 | IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) |
144 | #define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a) | 158 | #define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a) |
145 | #define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a) | 159 | #define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a) |
160 | #define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a) | ||
146 | #define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a) | 161 | #define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a) |
147 | #define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a) | 162 | #define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a) |
148 | #define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a) | 163 | #define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 6693767adc9f..7dc19136f41a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h | |||
@@ -321,180 +321,6 @@ struct iwl3945_eeprom { | |||
321 | #define PCI_REG_WUM8 0x0E8 | 321 | #define PCI_REG_WUM8 0x0E8 |
322 | #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000) | 322 | #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000) |
323 | 323 | ||
324 | /*=== CSR (control and status registers) ===*/ | ||
325 | #define CSR_BASE (0x000) | ||
326 | |||
327 | #define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ | ||
328 | #define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ | ||
329 | #define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ | ||
330 | #define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ | ||
331 | #define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ | ||
332 | #define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */ | ||
333 | #define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ | ||
334 | #define CSR_GP_CNTRL (CSR_BASE+0x024) | ||
335 | |||
336 | /* | ||
337 | * Hardware revision info | ||
338 | * Bit fields: | ||
339 | * 31-8: Reserved | ||
340 | * 7-4: Type of device: 0x0 = 4965, 0xd = 3945 | ||
341 | * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D | ||
342 | * 1-0: "Dash" value, as in A-1, etc. | ||
343 | */ | ||
344 | #define CSR_HW_REV (CSR_BASE+0x028) | ||
345 | |||
346 | /* EEPROM reads */ | ||
347 | #define CSR_EEPROM_REG (CSR_BASE+0x02c) | ||
348 | #define CSR_EEPROM_GP (CSR_BASE+0x030) | ||
349 | #define CSR_GP_UCODE (CSR_BASE+0x044) | ||
350 | #define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) | ||
351 | #define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) | ||
352 | #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) | ||
353 | #define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) | ||
354 | #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) | ||
355 | |||
356 | /* Analog phase-lock-loop configuration (3945 only) | ||
357 | * Set bit 24. */ | ||
358 | #define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) | ||
359 | |||
360 | /* Bits for CSR_HW_IF_CONFIG_REG */ | ||
361 | #define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB (0x00000100) | ||
362 | #define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM (0x00000200) | ||
363 | #define CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400) | ||
364 | #define CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800) | ||
365 | #define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) | ||
366 | #define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) | ||
367 | #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) | ||
368 | |||
369 | /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), | ||
370 | * acknowledged (reset) by host writing "1" to flagged bits. */ | ||
371 | #define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */ | ||
372 | #define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ | ||
373 | #define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ | ||
374 | #define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ | ||
375 | #define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ | ||
376 | #define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ | ||
377 | #define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ | ||
378 | #define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ | ||
379 | #define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */ | ||
380 | #define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */ | ||
381 | #define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */ | ||
382 | |||
383 | #define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \ | ||
384 | CSR_INT_BIT_HW_ERR | \ | ||
385 | CSR_INT_BIT_FH_TX | \ | ||
386 | CSR_INT_BIT_SW_ERR | \ | ||
387 | CSR_INT_BIT_RF_KILL | \ | ||
388 | CSR_INT_BIT_SW_RX | \ | ||
389 | CSR_INT_BIT_WAKEUP | \ | ||
390 | CSR_INT_BIT_ALIVE) | ||
391 | |||
392 | /* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ | ||
393 | #define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */ | ||
394 | #define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */ | ||
395 | #define CSR_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */ | ||
396 | #define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */ | ||
397 | #define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */ | ||
398 | #define CSR_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */ | ||
399 | #define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */ | ||
400 | #define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */ | ||
401 | |||
402 | #define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ | ||
403 | CSR_FH_INT_BIT_RX_CHNL2 | \ | ||
404 | CSR_FH_INT_BIT_RX_CHNL1 | \ | ||
405 | CSR_FH_INT_BIT_RX_CHNL0) | ||
406 | |||
407 | #define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL6 | \ | ||
408 | CSR_FH_INT_BIT_TX_CHNL1 | \ | ||
409 | CSR_FH_INT_BIT_TX_CHNL0) | ||
410 | |||
411 | |||
412 | /* RESET */ | ||
413 | #define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001) | ||
414 | #define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002) | ||
415 | #define CSR_RESET_REG_FLAG_SW_RESET (0x00000080) | ||
416 | #define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100) | ||
417 | #define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) | ||
418 | |||
419 | /* GP (general purpose) CONTROL */ | ||
420 | #define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) | ||
421 | #define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) | ||
422 | #define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) | ||
423 | #define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010) | ||
424 | |||
425 | #define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001) | ||
426 | |||
427 | #define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000) | ||
428 | #define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000) | ||
429 | #define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000) | ||
430 | |||
431 | |||
432 | /* EEPROM REG */ | ||
433 | #define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001) | ||
434 | #define CSR_EEPROM_REG_BIT_CMD (0x00000002) | ||
435 | |||
436 | /* EEPROM GP */ | ||
437 | #define CSR_EEPROM_GP_VALID_MSK (0x00000006) | ||
438 | #define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) | ||
439 | #define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) | ||
440 | |||
441 | /* UCODE DRV GP */ | ||
442 | #define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001) | ||
443 | #define CSR_UCODE_SW_BIT_RFKILL (0x00000002) | ||
444 | #define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) | ||
445 | #define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008) | ||
446 | |||
447 | /* GPIO */ | ||
448 | #define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200) | ||
449 | #define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000) | ||
450 | #define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER | ||
451 | |||
452 | /* GI Chicken Bits */ | ||
453 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) | ||
454 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) | ||
455 | |||
456 | /* CSR_ANA_PLL_CFG */ | ||
457 | #define CSR_ANA_PLL_CFG_SH (0x00880300) | ||
458 | |||
459 | /*=== HBUS (Host-side Bus) ===*/ | ||
460 | #define HBUS_BASE (0x400) | ||
461 | |||
462 | /* | ||
463 | * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM | ||
464 | * structures, error log, event log, verifying uCode load). | ||
465 | * First write to address register, then read from or write to data register | ||
466 | * to complete the job. Once the address register is set up, accesses to | ||
467 | * data registers auto-increment the address by one dword. | ||
468 | * Bit usage for address registers (read or write): | ||
469 | * 0-31: memory address within device | ||
470 | */ | ||
471 | #define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c) | ||
472 | #define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010) | ||
473 | #define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) | ||
474 | #define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) | ||
475 | |||
476 | /* | ||
477 | * Registers for accessing device's internal peripheral registers | ||
478 | * (e.g. SCD, BSM, etc.). First write to address register, | ||
479 | * then read from or write to data register to complete the job. | ||
480 | * Bit usage for address registers (read or write): | ||
481 | * 0-15: register address (offset) within device | ||
482 | * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword) | ||
483 | */ | ||
484 | #define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044) | ||
485 | #define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048) | ||
486 | #define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c) | ||
487 | #define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) | ||
488 | |||
489 | /* | ||
490 | * Per-Tx-queue write pointer (index, really!) (3945 and 4965). | ||
491 | * Indicates index to next TFD that driver will fill (1 past latest filled). | ||
492 | * Bit usage: | ||
493 | * 0-7: queue write index | ||
494 | * 11-8: queue selector | ||
495 | */ | ||
496 | #define HBUS_TARG_WRPTR (HBUS_BASE+0x060) | ||
497 | |||
498 | /* SCD (3945 Tx Frame Scheduler) */ | 324 | /* SCD (3945 Tx Frame Scheduler) */ |
499 | #define SCD_BASE (CSR_BASE + 0x2E00) | 325 | #define SCD_BASE (CSR_BASE + 0x2E00) |
500 | 326 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index a8223c4cc97c..08604eb8291b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c | |||
@@ -158,9 +158,9 @@ static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window) | |||
158 | { | 158 | { |
159 | window->data = 0; | 159 | window->data = 0; |
160 | window->success_counter = 0; | 160 | window->success_counter = 0; |
161 | window->success_ratio = IWL_INVALID_VALUE; | 161 | window->success_ratio = -1; |
162 | window->counter = 0; | 162 | window->counter = 0; |
163 | window->average_tpt = IWL_INVALID_VALUE; | 163 | window->average_tpt = IWL_INV_TPT; |
164 | window->stamp = 0; | 164 | window->stamp = 0; |
165 | } | 165 | } |
166 | 166 | ||
@@ -459,22 +459,23 @@ static void rs_tx_status(void *priv_rate, | |||
459 | struct iwl3945_rs_sta *rs_sta; | 459 | struct iwl3945_rs_sta *rs_sta; |
460 | struct ieee80211_supported_band *sband; | 460 | struct ieee80211_supported_band *sband; |
461 | 461 | ||
462 | IWL_DEBUG_RATE("enter\n"); | ||
463 | |||
462 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 464 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
463 | 465 | ||
464 | IWL_DEBUG_RATE("enter\n"); | ||
465 | 466 | ||
466 | retries = tx_resp->retry_count; | 467 | retries = tx_resp->retry_count; |
467 | /* FIXME : this is wrong */ | 468 | first_index = tx_resp->control.tx_rate->hw_value; |
468 | first_index = &sband->bitrates[0] - tx_resp->control.tx_rate; | ||
469 | if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { | 469 | if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { |
470 | IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); | 470 | IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); |
471 | return; | 471 | return; |
472 | } | 472 | } |
473 | 473 | ||
474 | rcu_read_lock(); | ||
475 | |||
474 | sta = sta_info_get(local, hdr->addr1); | 476 | sta = sta_info_get(local, hdr->addr1); |
475 | if (!sta || !sta->rate_ctrl_priv) { | 477 | if (!sta || !sta->rate_ctrl_priv) { |
476 | if (sta) | 478 | rcu_read_unlock(); |
477 | sta_info_put(sta); | ||
478 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); | 479 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); |
479 | return; | 480 | return; |
480 | } | 481 | } |
@@ -547,7 +548,7 @@ static void rs_tx_status(void *priv_rate, | |||
547 | 548 | ||
548 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 549 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
549 | 550 | ||
550 | sta_info_put(sta); | 551 | rcu_read_unlock(); |
551 | 552 | ||
552 | IWL_DEBUG_RATE("leave\n"); | 553 | IWL_DEBUG_RATE("leave\n"); |
553 | 554 | ||
@@ -633,7 +634,7 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, | |||
633 | * | 634 | * |
634 | */ | 635 | */ |
635 | static void rs_get_rate(void *priv_rate, struct net_device *dev, | 636 | static void rs_get_rate(void *priv_rate, struct net_device *dev, |
636 | struct ieee80211_supported_band *band, | 637 | struct ieee80211_supported_band *sband, |
637 | struct sk_buff *skb, | 638 | struct sk_buff *skb, |
638 | struct rate_selection *sel) | 639 | struct rate_selection *sel) |
639 | { | 640 | { |
@@ -643,9 +644,9 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
643 | int index; | 644 | int index; |
644 | struct iwl3945_rs_sta *rs_sta; | 645 | struct iwl3945_rs_sta *rs_sta; |
645 | struct iwl3945_rate_scale_data *window = NULL; | 646 | struct iwl3945_rate_scale_data *window = NULL; |
646 | int current_tpt = IWL_INVALID_VALUE; | 647 | int current_tpt = IWL_INV_TPT; |
647 | int low_tpt = IWL_INVALID_VALUE; | 648 | int low_tpt = IWL_INV_TPT; |
648 | int high_tpt = IWL_INVALID_VALUE; | 649 | int high_tpt = IWL_INV_TPT; |
649 | u32 fail_count; | 650 | u32 fail_count; |
650 | s8 scale_action = 0; | 651 | s8 scale_action = 0; |
651 | unsigned long flags; | 652 | unsigned long flags; |
@@ -658,6 +659,8 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
658 | 659 | ||
659 | IWL_DEBUG_RATE("enter\n"); | 660 | IWL_DEBUG_RATE("enter\n"); |
660 | 661 | ||
662 | rcu_read_lock(); | ||
663 | |||
661 | sta = sta_info_get(local, hdr->addr1); | 664 | sta = sta_info_get(local, hdr->addr1); |
662 | 665 | ||
663 | /* Send management frames and broadcast/multicast data using lowest | 666 | /* Send management frames and broadcast/multicast data using lowest |
@@ -667,16 +670,15 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
667 | is_multicast_ether_addr(hdr->addr1) || | 670 | is_multicast_ether_addr(hdr->addr1) || |
668 | !sta || !sta->rate_ctrl_priv) { | 671 | !sta || !sta->rate_ctrl_priv) { |
669 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); | 672 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); |
670 | sel->rate = rate_lowest(local, band, sta); | 673 | sel->rate = rate_lowest(local, sband, sta); |
671 | if (sta) | 674 | rcu_read_unlock(); |
672 | sta_info_put(sta); | ||
673 | return; | 675 | return; |
674 | } | 676 | } |
675 | 677 | ||
676 | rate_mask = sta->supp_rates[band->band]; | 678 | rate_mask = sta->supp_rates[sband->band]; |
677 | index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); | 679 | index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); |
678 | 680 | ||
679 | if (priv->band == IEEE80211_BAND_5GHZ) | 681 | if (sband->band == IEEE80211_BAND_5GHZ) |
680 | rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; | 682 | rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; |
681 | 683 | ||
682 | rs_sta = (void *)sta->rate_ctrl_priv; | 684 | rs_sta = (void *)sta->rate_ctrl_priv; |
@@ -708,7 +710,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
708 | 710 | ||
709 | if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) && | 711 | if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) && |
710 | (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { | 712 | (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { |
711 | window->average_tpt = IWL_INVALID_VALUE; | 713 | window->average_tpt = IWL_INV_TPT; |
712 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 714 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
713 | 715 | ||
714 | IWL_DEBUG_RATE("Invalid average_tpt on rate %d: " | 716 | IWL_DEBUG_RATE("Invalid average_tpt on rate %d: " |
@@ -727,7 +729,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
727 | current_tpt = window->average_tpt; | 729 | current_tpt = window->average_tpt; |
728 | 730 | ||
729 | high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask, | 731 | high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask, |
730 | band->band); | 732 | sband->band); |
731 | low = high_low & 0xff; | 733 | low = high_low & 0xff; |
732 | high = (high_low >> 8) & 0xff; | 734 | high = (high_low >> 8) & 0xff; |
733 | 735 | ||
@@ -744,19 +746,16 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
744 | if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { | 746 | if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { |
745 | IWL_DEBUG_RATE("decrease rate because of low success_ratio\n"); | 747 | IWL_DEBUG_RATE("decrease rate because of low success_ratio\n"); |
746 | scale_action = -1; | 748 | scale_action = -1; |
747 | } else if ((low_tpt == IWL_INVALID_VALUE) && | 749 | } else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT)) |
748 | (high_tpt == IWL_INVALID_VALUE)) | ||
749 | scale_action = 1; | 750 | scale_action = 1; |
750 | else if ((low_tpt != IWL_INVALID_VALUE) && | 751 | else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) && |
751 | (high_tpt != IWL_INVALID_VALUE) | 752 | (low_tpt < current_tpt) && (high_tpt < current_tpt)) { |
752 | && (low_tpt < current_tpt) | ||
753 | && (high_tpt < current_tpt)) { | ||
754 | IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < " | 753 | IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < " |
755 | "current_tpt [%d]\n", | 754 | "current_tpt [%d]\n", |
756 | low_tpt, high_tpt, current_tpt); | 755 | low_tpt, high_tpt, current_tpt); |
757 | scale_action = 0; | 756 | scale_action = 0; |
758 | } else { | 757 | } else { |
759 | if (high_tpt != IWL_INVALID_VALUE) { | 758 | if (high_tpt != IWL_INV_TPT) { |
760 | if (high_tpt > current_tpt) | 759 | if (high_tpt > current_tpt) |
761 | scale_action = 1; | 760 | scale_action = 1; |
762 | else { | 761 | else { |
@@ -764,7 +763,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
764 | ("decrease rate because of high tpt\n"); | 763 | ("decrease rate because of high tpt\n"); |
765 | scale_action = -1; | 764 | scale_action = -1; |
766 | } | 765 | } |
767 | } else if (low_tpt != IWL_INVALID_VALUE) { | 766 | } else if (low_tpt != IWL_INV_TPT) { |
768 | if (low_tpt > current_tpt) { | 767 | if (low_tpt > current_tpt) { |
769 | IWL_DEBUG_RATE | 768 | IWL_DEBUG_RATE |
770 | ("decrease rate because of low tpt\n"); | 769 | ("decrease rate because of low tpt\n"); |
@@ -806,16 +805,16 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
806 | out: | 805 | out: |
807 | 806 | ||
808 | sta->last_txrate_idx = index; | 807 | sta->last_txrate_idx = index; |
809 | if (priv->band == IEEE80211_BAND_5GHZ) | 808 | if (sband->band == IEEE80211_BAND_5GHZ) |
810 | sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; | 809 | sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; |
811 | else | 810 | else |
812 | sta->txrate_idx = sta->last_txrate_idx; | 811 | sta->txrate_idx = sta->last_txrate_idx; |
813 | 812 | ||
814 | sta_info_put(sta); | 813 | rcu_read_unlock(); |
815 | 814 | ||
816 | IWL_DEBUG_RATE("leave: %d\n", index); | 815 | IWL_DEBUG_RATE("leave: %d\n", index); |
817 | 816 | ||
818 | sel->rate = &priv->ieee_rates[index]; | 817 | sel->rate = &sband->bitrates[sta->txrate_idx]; |
819 | } | 818 | } |
820 | 819 | ||
821 | static struct rate_control_ops rs_ops = { | 820 | static struct rate_control_ops rs_ops = { |
@@ -843,13 +842,15 @@ int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) | |||
843 | unsigned long now = jiffies; | 842 | unsigned long now = jiffies; |
844 | u32 max_time = 0; | 843 | u32 max_time = 0; |
845 | 844 | ||
845 | rcu_read_lock(); | ||
846 | |||
846 | sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); | 847 | sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); |
847 | if (!sta || !sta->rate_ctrl_priv) { | 848 | if (!sta || !sta->rate_ctrl_priv) { |
848 | if (sta) { | 849 | if (sta) |
849 | sta_info_put(sta); | ||
850 | IWL_DEBUG_RATE("leave - no private rate data!\n"); | 850 | IWL_DEBUG_RATE("leave - no private rate data!\n"); |
851 | } else | 851 | else |
852 | IWL_DEBUG_RATE("leave - no station!\n"); | 852 | IWL_DEBUG_RATE("leave - no station!\n"); |
853 | rcu_read_unlock(); | ||
853 | return sprintf(buf, "station %d not found\n", sta_id); | 854 | return sprintf(buf, "station %d not found\n", sta_id); |
854 | } | 855 | } |
855 | 856 | ||
@@ -890,7 +891,7 @@ int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) | |||
890 | i = j; | 891 | i = j; |
891 | } | 892 | } |
892 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 893 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
893 | sta_info_put(sta); | 894 | rcu_read_unlock(); |
894 | 895 | ||
895 | /* Display the average rate of all samples taken. | 896 | /* Display the average rate of all samples taken. |
896 | * | 897 | * |
@@ -927,11 +928,12 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | |||
927 | return; | 928 | return; |
928 | } | 929 | } |
929 | 930 | ||
931 | rcu_read_lock(); | ||
932 | |||
930 | sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); | 933 | sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); |
931 | if (!sta || !sta->rate_ctrl_priv) { | 934 | if (!sta || !sta->rate_ctrl_priv) { |
932 | if (sta) | ||
933 | sta_info_put(sta); | ||
934 | IWL_DEBUG_RATE("leave - no private rate data!\n"); | 935 | IWL_DEBUG_RATE("leave - no private rate data!\n"); |
936 | rcu_read_unlock(); | ||
935 | return; | 937 | return; |
936 | } | 938 | } |
937 | 939 | ||
@@ -958,7 +960,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | |||
958 | break; | 960 | break; |
959 | } | 961 | } |
960 | 962 | ||
961 | sta_info_put(sta); | 963 | rcu_read_unlock(); |
962 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 964 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
963 | 965 | ||
964 | rssi = priv->last_rx_rssi; | 966 | rssi = priv->last_rx_rssi; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h index d5e9220f871d..b082a093ee26 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h | |||
@@ -36,8 +36,8 @@ struct iwl3945_rate_info { | |||
36 | u8 next_rs; /* next rate used in rs algo */ | 36 | u8 next_rs; /* next rate used in rs algo */ |
37 | u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ | 37 | u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ |
38 | u8 next_rs_tgg; /* next rate used in TGG rs algo */ | 38 | u8 next_rs_tgg; /* next rate used in TGG rs algo */ |
39 | u8 table_rs_index; /* index in rate scale table cmd */ | 39 | u8 table_rs_index; /* index in rate scale table cmd */ |
40 | u8 prev_table_rs; /* prev in rate table cmd */ | 40 | u8 prev_table_rs; /* prev in rate table cmd */ |
41 | }; | 41 | }; |
42 | 42 | ||
43 | /* | 43 | /* |
@@ -159,7 +159,7 @@ enum { | |||
159 | 159 | ||
160 | #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) | 160 | #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) |
161 | 161 | ||
162 | #define IWL_INVALID_VALUE -1 | 162 | #define IWL_INV_TPT -1 |
163 | 163 | ||
164 | #define IWL_MIN_RSSI_VAL -100 | 164 | #define IWL_MIN_RSSI_VAL -100 |
165 | #define IWL_MAX_RSSI_VAL 0 | 165 | #define IWL_MAX_RSSI_VAL 0 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 82d282730b75..50a641c0c5b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <asm/unaligned.h> | 39 | #include <asm/unaligned.h> |
40 | #include <net/mac80211.h> | 40 | #include <net/mac80211.h> |
41 | 41 | ||
42 | #include "iwl-3945-core.h" | ||
42 | #include "iwl-3945.h" | 43 | #include "iwl-3945.h" |
43 | #include "iwl-helpers.h" | 44 | #include "iwl-helpers.h" |
44 | #include "iwl-3945-rs.h" | 45 | #include "iwl-3945-rs.h" |
@@ -183,6 +184,16 @@ void iwl3945_disable_events(struct iwl3945_priv *priv) | |||
183 | 184 | ||
184 | } | 185 | } |
185 | 186 | ||
187 | static int iwl3945_hwrate_to_plcp_idx(u8 plcp) | ||
188 | { | ||
189 | int idx; | ||
190 | |||
191 | for (idx = 0; idx < IWL_RATE_COUNT; idx++) | ||
192 | if (iwl3945_rates[idx].plcp == plcp) | ||
193 | return idx; | ||
194 | return -1; | ||
195 | } | ||
196 | |||
186 | /** | 197 | /** |
187 | * iwl3945_get_antenna_flags - Get antenna flags for RXON command | 198 | * iwl3945_get_antenna_flags - Get antenna flags for RXON command |
188 | * @priv: eeprom and antenna fields are used to determine antenna flags | 199 | * @priv: eeprom and antenna fields are used to determine antenna flags |
@@ -216,14 +227,126 @@ __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv) | |||
216 | return 0; /* "diversity" is default if error */ | 227 | return 0; /* "diversity" is default if error */ |
217 | } | 228 | } |
218 | 229 | ||
230 | #ifdef CONFIG_IWL3945_DEBUG | ||
231 | #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x | ||
232 | |||
233 | static const char *iwl3945_get_tx_fail_reason(u32 status) | ||
234 | { | ||
235 | switch (status & TX_STATUS_MSK) { | ||
236 | case TX_STATUS_SUCCESS: | ||
237 | return "SUCCESS"; | ||
238 | TX_STATUS_ENTRY(SHORT_LIMIT); | ||
239 | TX_STATUS_ENTRY(LONG_LIMIT); | ||
240 | TX_STATUS_ENTRY(FIFO_UNDERRUN); | ||
241 | TX_STATUS_ENTRY(MGMNT_ABORT); | ||
242 | TX_STATUS_ENTRY(NEXT_FRAG); | ||
243 | TX_STATUS_ENTRY(LIFE_EXPIRE); | ||
244 | TX_STATUS_ENTRY(DEST_PS); | ||
245 | TX_STATUS_ENTRY(ABORTED); | ||
246 | TX_STATUS_ENTRY(BT_RETRY); | ||
247 | TX_STATUS_ENTRY(STA_INVALID); | ||
248 | TX_STATUS_ENTRY(FRAG_DROPPED); | ||
249 | TX_STATUS_ENTRY(TID_DISABLE); | ||
250 | TX_STATUS_ENTRY(FRAME_FLUSHED); | ||
251 | TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); | ||
252 | TX_STATUS_ENTRY(TX_LOCKED); | ||
253 | TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); | ||
254 | } | ||
255 | |||
256 | return "UNKNOWN"; | ||
257 | } | ||
258 | #else | ||
259 | static inline const char *iwl3945_get_tx_fail_reason(u32 status) | ||
260 | { | ||
261 | return ""; | ||
262 | } | ||
263 | #endif | ||
264 | |||
265 | |||
266 | /** | ||
267 | * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd | ||
268 | * | ||
269 | * When FW advances 'R' index, all entries between old and new 'R' index | ||
270 | * need to be reclaimed. As result, some free space forms. If there is | ||
271 | * enough free space (> low mark), wake the stack that feeds us. | ||
272 | */ | ||
273 | static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, | ||
274 | int txq_id, int index) | ||
275 | { | ||
276 | struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; | ||
277 | struct iwl3945_queue *q = &txq->q; | ||
278 | struct iwl3945_tx_info *tx_info; | ||
279 | |||
280 | BUG_ON(txq_id == IWL_CMD_QUEUE_NUM); | ||
281 | |||
282 | for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; | ||
283 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
284 | |||
285 | tx_info = &txq->txb[txq->q.read_ptr]; | ||
286 | ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0], | ||
287 | &tx_info->status); | ||
288 | tx_info->skb[0] = NULL; | ||
289 | iwl3945_hw_txq_free_tfd(priv, txq); | ||
290 | } | ||
291 | |||
292 | if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) && | ||
293 | (txq_id != IWL_CMD_QUEUE_NUM) && | ||
294 | priv->mac80211_registered) | ||
295 | ieee80211_wake_queue(priv->hw, txq_id); | ||
296 | } | ||
297 | |||
298 | /** | ||
299 | * iwl3945_rx_reply_tx - Handle Tx response | ||
300 | */ | ||
301 | static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, | ||
302 | struct iwl3945_rx_mem_buffer *rxb) | ||
303 | { | ||
304 | struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; | ||
305 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
306 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
307 | int index = SEQ_TO_INDEX(sequence); | ||
308 | struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; | ||
309 | struct ieee80211_tx_status *tx_status; | ||
310 | struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | ||
311 | u32 status = le32_to_cpu(tx_resp->status); | ||
312 | int rate_idx; | ||
313 | |||
314 | if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) { | ||
315 | IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " | ||
316 | "is out of range [0-%d] %d %d\n", txq_id, | ||
317 | index, txq->q.n_bd, txq->q.write_ptr, | ||
318 | txq->q.read_ptr); | ||
319 | return; | ||
320 | } | ||
321 | |||
322 | tx_status = &(txq->txb[txq->q.read_ptr].status); | ||
323 | |||
324 | tx_status->retry_count = tx_resp->failure_frame; | ||
325 | /* tx_status->rts_retry_count = tx_resp->failure_rts; */ | ||
326 | tx_status->flags = ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ? | ||
327 | IEEE80211_TX_STATUS_ACK : 0; | ||
328 | |||
329 | IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", | ||
330 | txq_id, iwl3945_get_tx_fail_reason(status), status, | ||
331 | tx_resp->rate, tx_resp->failure_frame); | ||
332 | |||
333 | rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); | ||
334 | tx_status->control.tx_rate = &priv->ieee_rates[rate_idx]; | ||
335 | IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); | ||
336 | iwl3945_tx_queue_reclaim(priv, txq_id, index); | ||
337 | |||
338 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | ||
339 | IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); | ||
340 | } | ||
341 | |||
342 | |||
343 | |||
219 | /***************************************************************************** | 344 | /***************************************************************************** |
220 | * | 345 | * |
221 | * Intel PRO/Wireless 3945ABG/BG Network Connection | 346 | * Intel PRO/Wireless 3945ABG/BG Network Connection |
222 | * | 347 | * |
223 | * RX handler implementations | 348 | * RX handler implementations |
224 | * | 349 | * |
225 | * Used by iwl-base.c | ||
226 | * | ||
227 | *****************************************************************************/ | 350 | *****************************************************************************/ |
228 | 351 | ||
229 | void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) | 352 | void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) |
@@ -238,6 +361,156 @@ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_b | |||
238 | priv->last_statistics_time = jiffies; | 361 | priv->last_statistics_time = jiffies; |
239 | } | 362 | } |
240 | 363 | ||
364 | /****************************************************************************** | ||
365 | * | ||
366 | * Misc. internal state and helper functions | ||
367 | * | ||
368 | ******************************************************************************/ | ||
369 | #ifdef CONFIG_IWL3945_DEBUG | ||
370 | |||
371 | /** | ||
372 | * iwl3945_report_frame - dump frame to syslog during debug sessions | ||
373 | * | ||
374 | * You may hack this function to show different aspects of received frames, | ||
375 | * including selective frame dumps. | ||
376 | * group100 parameter selects whether to show 1 out of 100 good frames. | ||
377 | */ | ||
378 | static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, | ||
379 | struct iwl3945_rx_packet *pkt, | ||
380 | struct ieee80211_hdr *header, int group100) | ||
381 | { | ||
382 | u32 to_us; | ||
383 | u32 print_summary = 0; | ||
384 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
385 | u32 hundred = 0; | ||
386 | u32 dataframe = 0; | ||
387 | u16 fc; | ||
388 | u16 seq_ctl; | ||
389 | u16 channel; | ||
390 | u16 phy_flags; | ||
391 | u16 length; | ||
392 | u16 status; | ||
393 | u16 bcn_tmr; | ||
394 | u32 tsf_low; | ||
395 | u64 tsf; | ||
396 | u8 rssi; | ||
397 | u8 agc; | ||
398 | u16 sig_avg; | ||
399 | u16 noise_diff; | ||
400 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | ||
401 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | ||
402 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | ||
403 | u8 *data = IWL_RX_DATA(pkt); | ||
404 | |||
405 | /* MAC header */ | ||
406 | fc = le16_to_cpu(header->frame_control); | ||
407 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
408 | |||
409 | /* metadata */ | ||
410 | channel = le16_to_cpu(rx_hdr->channel); | ||
411 | phy_flags = le16_to_cpu(rx_hdr->phy_flags); | ||
412 | length = le16_to_cpu(rx_hdr->len); | ||
413 | |||
414 | /* end-of-frame status and timestamp */ | ||
415 | status = le32_to_cpu(rx_end->status); | ||
416 | bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); | ||
417 | tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; | ||
418 | tsf = le64_to_cpu(rx_end->timestamp); | ||
419 | |||
420 | /* signal statistics */ | ||
421 | rssi = rx_stats->rssi; | ||
422 | agc = rx_stats->agc; | ||
423 | sig_avg = le16_to_cpu(rx_stats->sig_avg); | ||
424 | noise_diff = le16_to_cpu(rx_stats->noise_diff); | ||
425 | |||
426 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
427 | |||
428 | /* if data frame is to us and all is good, | ||
429 | * (optionally) print summary for only 1 out of every 100 */ | ||
430 | if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) == | ||
431 | (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
432 | dataframe = 1; | ||
433 | if (!group100) | ||
434 | print_summary = 1; /* print each frame */ | ||
435 | else if (priv->framecnt_to_us < 100) { | ||
436 | priv->framecnt_to_us++; | ||
437 | print_summary = 0; | ||
438 | } else { | ||
439 | priv->framecnt_to_us = 0; | ||
440 | print_summary = 1; | ||
441 | hundred = 1; | ||
442 | } | ||
443 | } else { | ||
444 | /* print summary for all other frames */ | ||
445 | print_summary = 1; | ||
446 | } | ||
447 | |||
448 | if (print_summary) { | ||
449 | char *title; | ||
450 | u32 rate; | ||
451 | |||
452 | if (hundred) | ||
453 | title = "100Frames"; | ||
454 | else if (fc & IEEE80211_FCTL_RETRY) | ||
455 | title = "Retry"; | ||
456 | else if (ieee80211_is_assoc_response(fc)) | ||
457 | title = "AscRsp"; | ||
458 | else if (ieee80211_is_reassoc_response(fc)) | ||
459 | title = "RasRsp"; | ||
460 | else if (ieee80211_is_probe_response(fc)) { | ||
461 | title = "PrbRsp"; | ||
462 | print_dump = 1; /* dump frame contents */ | ||
463 | } else if (ieee80211_is_beacon(fc)) { | ||
464 | title = "Beacon"; | ||
465 | print_dump = 1; /* dump frame contents */ | ||
466 | } else if (ieee80211_is_atim(fc)) | ||
467 | title = "ATIM"; | ||
468 | else if (ieee80211_is_auth(fc)) | ||
469 | title = "Auth"; | ||
470 | else if (ieee80211_is_deauth(fc)) | ||
471 | title = "DeAuth"; | ||
472 | else if (ieee80211_is_disassoc(fc)) | ||
473 | title = "DisAssoc"; | ||
474 | else | ||
475 | title = "Frame"; | ||
476 | |||
477 | rate = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); | ||
478 | if (rate == -1) | ||
479 | rate = 0; | ||
480 | else | ||
481 | rate = iwl3945_rates[rate].ieee / 2; | ||
482 | |||
483 | /* print frame summary. | ||
484 | * MAC addresses show just the last byte (for brevity), | ||
485 | * but you can hack it to show more, if you'd like to. */ | ||
486 | if (dataframe) | ||
487 | IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " | ||
488 | "len=%u, rssi=%d, chnl=%d, rate=%u, \n", | ||
489 | title, fc, header->addr1[5], | ||
490 | length, rssi, channel, rate); | ||
491 | else { | ||
492 | /* src/dst addresses assume managed mode */ | ||
493 | IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " | ||
494 | "src=0x%02x, rssi=%u, tim=%lu usec, " | ||
495 | "phy=0x%02x, chnl=%d\n", | ||
496 | title, fc, header->addr1[5], | ||
497 | header->addr3[5], rssi, | ||
498 | tsf_low - priv->scan_start_tsf, | ||
499 | phy_flags, channel); | ||
500 | } | ||
501 | } | ||
502 | if (print_dump) | ||
503 | iwl3945_print_hex_dump(IWL_DL_RX, data, length); | ||
504 | } | ||
505 | #else | ||
506 | static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, | ||
507 | struct iwl3945_rx_packet *pkt, | ||
508 | struct ieee80211_hdr *header, int group100) | ||
509 | { | ||
510 | } | ||
511 | #endif | ||
512 | |||
513 | |||
241 | static void iwl3945_add_radiotap(struct iwl3945_priv *priv, | 514 | static void iwl3945_add_radiotap(struct iwl3945_priv *priv, |
242 | struct sk_buff *skb, | 515 | struct sk_buff *skb, |
243 | struct iwl3945_rx_frame_hdr *rx_hdr, | 516 | struct iwl3945_rx_frame_hdr *rx_hdr, |
@@ -376,24 +649,28 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, | |||
376 | static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, | 649 | static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, |
377 | struct iwl3945_rx_mem_buffer *rxb) | 650 | struct iwl3945_rx_mem_buffer *rxb) |
378 | { | 651 | { |
652 | struct ieee80211_hdr *header; | ||
653 | struct ieee80211_rx_status rx_status; | ||
379 | struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; | 654 | struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; |
380 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | 655 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); |
381 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | 656 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); |
382 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 657 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
383 | struct ieee80211_hdr *header; | 658 | int snr; |
384 | u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg); | 659 | u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg); |
385 | u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); | 660 | u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); |
386 | struct ieee80211_rx_status stats = { | ||
387 | .mactime = le64_to_cpu(rx_end->timestamp), | ||
388 | .freq = ieee80211chan2mhz(le16_to_cpu(rx_hdr->channel)), | ||
389 | .band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
390 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ, | ||
391 | .antenna = 0, | ||
392 | .rate_idx = iwl3945_rate_index_from_plcp(rx_hdr->rate), | ||
393 | .flag = 0, | ||
394 | }; | ||
395 | u8 network_packet; | 661 | u8 network_packet; |
396 | int snr; | 662 | |
663 | rx_status.antenna = 0; | ||
664 | rx_status.flag = 0; | ||
665 | rx_status.mactime = le64_to_cpu(rx_end->timestamp); | ||
666 | rx_status.freq = ieee80211chan2mhz(le16_to_cpu(rx_hdr->channel)); | ||
667 | rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
668 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
669 | |||
670 | rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); | ||
671 | |||
672 | if (rx_status.band == IEEE80211_BAND_5GHZ) | ||
673 | rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; | ||
397 | 674 | ||
398 | if ((unlikely(rx_stats->phy_count > 20))) { | 675 | if ((unlikely(rx_stats->phy_count > 20))) { |
399 | IWL_DEBUG_DROP | 676 | IWL_DEBUG_DROP |
@@ -409,12 +686,12 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, | |||
409 | } | 686 | } |
410 | 687 | ||
411 | if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { | 688 | if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { |
412 | iwl3945_handle_data_packet(priv, 1, rxb, &stats); | 689 | iwl3945_handle_data_packet(priv, 1, rxb, &rx_status); |
413 | return; | 690 | return; |
414 | } | 691 | } |
415 | 692 | ||
416 | /* Convert 3945's rssi indicator to dBm */ | 693 | /* Convert 3945's rssi indicator to dBm */ |
417 | stats.ssi = rx_stats->rssi - IWL_RSSI_OFFSET; | 694 | rx_status.ssi = rx_stats->rssi - IWL_RSSI_OFFSET; |
418 | 695 | ||
419 | /* Set default noise value to -127 */ | 696 | /* Set default noise value to -127 */ |
420 | if (priv->last_rx_noise == 0) | 697 | if (priv->last_rx_noise == 0) |
@@ -430,50 +707,47 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, | |||
430 | * signal-to-noise ratio (SNR) is (sig_avg / noise_diff). | 707 | * signal-to-noise ratio (SNR) is (sig_avg / noise_diff). |
431 | * Convert linear SNR to dB SNR, then subtract that from rssi dBm | 708 | * Convert linear SNR to dB SNR, then subtract that from rssi dBm |
432 | * to obtain noise level in dBm. | 709 | * to obtain noise level in dBm. |
433 | * Calculate stats.signal (quality indicator in %) based on SNR. */ | 710 | * Calculate rx_status.signal (quality indicator in %) based on SNR. */ |
434 | if (rx_stats_noise_diff) { | 711 | if (rx_stats_noise_diff) { |
435 | snr = rx_stats_sig_avg / rx_stats_noise_diff; | 712 | snr = rx_stats_sig_avg / rx_stats_noise_diff; |
436 | stats.noise = stats.ssi - iwl3945_calc_db_from_ratio(snr); | 713 | rx_status.noise = rx_status.ssi - |
437 | stats.signal = iwl3945_calc_sig_qual(stats.ssi, stats.noise); | 714 | iwl3945_calc_db_from_ratio(snr); |
715 | rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi, | ||
716 | rx_status.noise); | ||
438 | 717 | ||
439 | /* If noise info not available, calculate signal quality indicator (%) | 718 | /* If noise info not available, calculate signal quality indicator (%) |
440 | * using just the dBm signal level. */ | 719 | * using just the dBm signal level. */ |
441 | } else { | 720 | } else { |
442 | stats.noise = priv->last_rx_noise; | 721 | rx_status.noise = priv->last_rx_noise; |
443 | stats.signal = iwl3945_calc_sig_qual(stats.ssi, 0); | 722 | rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi, 0); |
444 | } | 723 | } |
445 | 724 | ||
446 | 725 | ||
447 | IWL_DEBUG_STATS("Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n", | 726 | IWL_DEBUG_STATS("Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n", |
448 | stats.ssi, stats.noise, stats.signal, | 727 | rx_status.ssi, rx_status.noise, rx_status.signal, |
449 | rx_stats_sig_avg, rx_stats_noise_diff); | 728 | rx_stats_sig_avg, rx_stats_noise_diff); |
450 | 729 | ||
451 | /* can be covered by iwl3945_report_frame() in most cases */ | ||
452 | /* IWL_DEBUG_RX("RX status: 0x%08X\n", rx_end->status); */ | ||
453 | |||
454 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | 730 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); |
455 | 731 | ||
456 | network_packet = iwl3945_is_network_packet(priv, header); | 732 | network_packet = iwl3945_is_network_packet(priv, header); |
457 | 733 | ||
458 | #ifdef CONFIG_IWL3945_DEBUG | 734 | IWL_DEBUG_STATS_LIMIT("[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n", |
459 | if (iwl3945_debug_level & IWL_DL_STATS && net_ratelimit()) | 735 | network_packet ? '*' : ' ', |
460 | IWL_DEBUG_STATS | 736 | le16_to_cpu(rx_hdr->channel), |
461 | ("[%c] %d RSSI: %d Signal: %u, Noise: %u, Rate: %u\n", | 737 | rx_status.ssi, rx_status.ssi, |
462 | network_packet ? '*' : ' ', | 738 | rx_status.ssi, rx_status.rate_idx); |
463 | le16_to_cpu(rx_hdr->channel), | ||
464 | stats.ssi, stats.ssi, | ||
465 | stats.ssi, stats.rate_idx); | ||
466 | 739 | ||
740 | #ifdef CONFIG_IWL3945_DEBUG | ||
467 | if (iwl3945_debug_level & (IWL_DL_RX)) | 741 | if (iwl3945_debug_level & (IWL_DL_RX)) |
468 | /* Set "1" to report good data frames in groups of 100 */ | 742 | /* Set "1" to report good data frames in groups of 100 */ |
469 | iwl3945_report_frame(priv, pkt, header, 1); | 743 | iwl3945_dbg_report_frame(priv, pkt, header, 1); |
470 | #endif | 744 | #endif |
471 | 745 | ||
472 | if (network_packet) { | 746 | if (network_packet) { |
473 | priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp); | 747 | priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp); |
474 | priv->last_tsf = le64_to_cpu(rx_end->timestamp); | 748 | priv->last_tsf = le64_to_cpu(rx_end->timestamp); |
475 | priv->last_rx_rssi = stats.ssi; | 749 | priv->last_rx_rssi = rx_status.ssi; |
476 | priv->last_rx_noise = stats.noise; | 750 | priv->last_rx_noise = rx_status.noise; |
477 | } | 751 | } |
478 | 752 | ||
479 | switch (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FTYPE) { | 753 | switch (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FTYPE) { |
@@ -560,7 +834,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, | |||
560 | } | 834 | } |
561 | } | 835 | } |
562 | 836 | ||
563 | iwl3945_handle_data_packet(priv, 0, rxb, &stats); | 837 | iwl3945_handle_data_packet(priv, 0, rxb, &rx_status); |
564 | break; | 838 | break; |
565 | 839 | ||
566 | case IEEE80211_FTYPE_CTL: | 840 | case IEEE80211_FTYPE_CTL: |
@@ -577,7 +851,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, | |||
577 | print_mac(mac2, header->addr2), | 851 | print_mac(mac2, header->addr2), |
578 | print_mac(mac3, header->addr3)); | 852 | print_mac(mac3, header->addr3)); |
579 | else | 853 | else |
580 | iwl3945_handle_data_packet(priv, 1, rxb, &stats); | 854 | iwl3945_handle_data_packet(priv, 1, rxb, &rx_status); |
581 | break; | 855 | break; |
582 | } | 856 | } |
583 | } | 857 | } |
@@ -993,19 +1267,19 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv) | |||
993 | if (rev_id & PCI_CFG_REV_ID_BIT_RTP) | 1267 | if (rev_id & PCI_CFG_REV_ID_BIT_RTP) |
994 | IWL_DEBUG_INFO("RTP type \n"); | 1268 | IWL_DEBUG_INFO("RTP type \n"); |
995 | else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { | 1269 | else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { |
996 | IWL_DEBUG_INFO("ALM-MB type\n"); | 1270 | IWL_DEBUG_INFO("3945 RADIO-MB type\n"); |
997 | iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, | 1271 | iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, |
998 | CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB); | 1272 | CSR39_HW_IF_CONFIG_REG_BIT_3945_MB); |
999 | } else { | 1273 | } else { |
1000 | IWL_DEBUG_INFO("ALM-MM type\n"); | 1274 | IWL_DEBUG_INFO("3945 RADIO-MM type\n"); |
1001 | iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, | 1275 | iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, |
1002 | CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM); | 1276 | CSR39_HW_IF_CONFIG_REG_BIT_3945_MM); |
1003 | } | 1277 | } |
1004 | 1278 | ||
1005 | if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom.sku_cap) { | 1279 | if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom.sku_cap) { |
1006 | IWL_DEBUG_INFO("SKU OP mode is mrc\n"); | 1280 | IWL_DEBUG_INFO("SKU OP mode is mrc\n"); |
1007 | iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, | 1281 | iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, |
1008 | CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC); | 1282 | CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC); |
1009 | } else | 1283 | } else |
1010 | IWL_DEBUG_INFO("SKU OP mode is basic\n"); | 1284 | IWL_DEBUG_INFO("SKU OP mode is basic\n"); |
1011 | 1285 | ||
@@ -1013,24 +1287,24 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv) | |||
1013 | IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", | 1287 | IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", |
1014 | priv->eeprom.board_revision); | 1288 | priv->eeprom.board_revision); |
1015 | iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, | 1289 | iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, |
1016 | CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); | 1290 | CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); |
1017 | } else { | 1291 | } else { |
1018 | IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", | 1292 | IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", |
1019 | priv->eeprom.board_revision); | 1293 | priv->eeprom.board_revision); |
1020 | iwl3945_clear_bit(priv, CSR_HW_IF_CONFIG_REG, | 1294 | iwl3945_clear_bit(priv, CSR_HW_IF_CONFIG_REG, |
1021 | CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); | 1295 | CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); |
1022 | } | 1296 | } |
1023 | 1297 | ||
1024 | if (priv->eeprom.almgor_m_version <= 1) { | 1298 | if (priv->eeprom.almgor_m_version <= 1) { |
1025 | iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, | 1299 | iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, |
1026 | CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A); | 1300 | CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A); |
1027 | IWL_DEBUG_INFO("Card M type A version is 0x%X\n", | 1301 | IWL_DEBUG_INFO("Card M type A version is 0x%X\n", |
1028 | priv->eeprom.almgor_m_version); | 1302 | priv->eeprom.almgor_m_version); |
1029 | } else { | 1303 | } else { |
1030 | IWL_DEBUG_INFO("Card M type B version is 0x%X\n", | 1304 | IWL_DEBUG_INFO("Card M type B version is 0x%X\n", |
1031 | priv->eeprom.almgor_m_version); | 1305 | priv->eeprom.almgor_m_version); |
1032 | iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, | 1306 | iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, |
1033 | CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B); | 1307 | CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B); |
1034 | } | 1308 | } |
1035 | spin_unlock_irqrestore(&priv->lock, flags); | 1309 | spin_unlock_irqrestore(&priv->lock, flags); |
1036 | 1310 | ||
@@ -2348,6 +2622,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv, | |||
2348 | 2622 | ||
2349 | void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv) | 2623 | void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv) |
2350 | { | 2624 | { |
2625 | priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx; | ||
2351 | priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx; | 2626 | priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx; |
2352 | } | 2627 | } |
2353 | 2628 | ||
@@ -2362,9 +2637,25 @@ void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv) | |||
2362 | cancel_delayed_work(&priv->thermal_periodic); | 2637 | cancel_delayed_work(&priv->thermal_periodic); |
2363 | } | 2638 | } |
2364 | 2639 | ||
2640 | static struct iwl_3945_cfg iwl3945_bg_cfg = { | ||
2641 | .name = "3945BG", | ||
2642 | .fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode", | ||
2643 | .sku = IWL_SKU_G, | ||
2644 | }; | ||
2645 | |||
2646 | static struct iwl_3945_cfg iwl3945_abg_cfg = { | ||
2647 | .name = "3945ABG", | ||
2648 | .fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode", | ||
2649 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
2650 | }; | ||
2651 | |||
2365 | struct pci_device_id iwl3945_hw_card_ids[] = { | 2652 | struct pci_device_id iwl3945_hw_card_ids[] = { |
2366 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4222)}, | 2653 | {IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)}, |
2367 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4227)}, | 2654 | {IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)}, |
2655 | {IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)}, | ||
2656 | {IWL_PCI_DEVICE(0x4227, 0x1014, iwl3945_bg_cfg)}, | ||
2657 | {IWL_PCI_DEVICE(0x4222, PCI_ANY_ID, iwl3945_abg_cfg)}, | ||
2658 | {IWL_PCI_DEVICE(0x4227, PCI_ANY_ID, iwl3945_abg_cfg)}, | ||
2368 | {0} | 2659 | {0} |
2369 | }; | 2660 | }; |
2370 | 2661 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index dde389d31637..0ab22d366d93 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -40,10 +40,17 @@ | |||
40 | extern struct pci_device_id iwl3945_hw_card_ids[]; | 40 | extern struct pci_device_id iwl3945_hw_card_ids[]; |
41 | 41 | ||
42 | #define DRV_NAME "iwl3945" | 42 | #define DRV_NAME "iwl3945" |
43 | #include "iwl-3945-hw.h" | 43 | #include "iwl-csr.h" |
44 | #include "iwl-prph.h" | 44 | #include "iwl-prph.h" |
45 | #include "iwl-3945-hw.h" | ||
45 | #include "iwl-3945-debug.h" | 46 | #include "iwl-3945-debug.h" |
46 | 47 | ||
48 | /* Change firmware file name, using "-" and incrementing number, | ||
49 | * *only* when uCode interface or architecture changes so that it | ||
50 | * is not compatible with earlier drivers. | ||
51 | * This number will also appear in << 8 position of 1st dword of uCode file */ | ||
52 | #define IWL3945_UCODE_API "-1" | ||
53 | |||
47 | /* Default noise level to report when noise measurement is not available. | 54 | /* Default noise level to report when noise measurement is not available. |
48 | * This may be because we're: | 55 | * This may be because we're: |
49 | * 1) Not associated (4965, no beacon statistics being sent to driver) | 56 | * 1) Not associated (4965, no beacon statistics being sent to driver) |
@@ -109,6 +116,9 @@ struct iwl3945_queue { | |||
109 | * space less than this */ | 116 | * space less than this */ |
110 | } __attribute__ ((packed)); | 117 | } __attribute__ ((packed)); |
111 | 118 | ||
119 | int iwl3945_queue_space(const struct iwl3945_queue *q); | ||
120 | int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i); | ||
121 | |||
112 | #define MAX_NUM_OF_TBS (20) | 122 | #define MAX_NUM_OF_TBS (20) |
113 | 123 | ||
114 | /* One for each TFD */ | 124 | /* One for each TFD */ |
@@ -558,16 +568,6 @@ extern int iwl3945_is_network_packet(struct iwl3945_priv *priv, | |||
558 | struct ieee80211_hdr *header); | 568 | struct ieee80211_hdr *header); |
559 | extern int iwl3945_power_init_handle(struct iwl3945_priv *priv); | 569 | extern int iwl3945_power_init_handle(struct iwl3945_priv *priv); |
560 | extern int iwl3945_eeprom_init(struct iwl3945_priv *priv); | 570 | extern int iwl3945_eeprom_init(struct iwl3945_priv *priv); |
561 | #ifdef CONFIG_IWL3945_DEBUG | ||
562 | extern void iwl3945_report_frame(struct iwl3945_priv *priv, | ||
563 | struct iwl3945_rx_packet *pkt, | ||
564 | struct ieee80211_hdr *header, int group100); | ||
565 | #else | ||
566 | static inline void iwl3945_report_frame(struct iwl3945_priv *priv, | ||
567 | struct iwl3945_rx_packet *pkt, | ||
568 | struct ieee80211_hdr *header, | ||
569 | int group100) {} | ||
570 | #endif | ||
571 | extern void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv, | 571 | extern void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv, |
572 | struct iwl3945_rx_mem_buffer *rxb, | 572 | struct iwl3945_rx_mem_buffer *rxb, |
573 | void *data, short len, | 573 | void *data, short len, |
@@ -691,6 +691,7 @@ struct iwl3945_priv { | |||
691 | struct ieee80211_hw *hw; | 691 | struct ieee80211_hw *hw; |
692 | struct ieee80211_channel *ieee_channels; | 692 | struct ieee80211_channel *ieee_channels; |
693 | struct ieee80211_rate *ieee_rates; | 693 | struct ieee80211_rate *ieee_rates; |
694 | struct iwl_3945_cfg *cfg; /* device configuration */ | ||
694 | 695 | ||
695 | /* temporary frame storage list */ | 696 | /* temporary frame storage list */ |
696 | struct list_head free_frames; | 697 | struct list_head free_frames; |
@@ -800,7 +801,6 @@ struct iwl3945_priv { | |||
800 | struct iwl3945_tx_queue txq[IWL_MAX_NUM_QUEUES]; | 801 | struct iwl3945_tx_queue txq[IWL_MAX_NUM_QUEUES]; |
801 | 802 | ||
802 | unsigned long status; | 803 | unsigned long status; |
803 | u32 config; | ||
804 | 804 | ||
805 | int last_rx_rssi; /* From Rx packet statisitics */ | 805 | int last_rx_rssi; /* From Rx packet statisitics */ |
806 | int last_rx_noise; /* From beacon statistics */ | 806 | int last_rx_noise; /* From beacon statistics */ |
@@ -830,7 +830,6 @@ struct iwl3945_priv { | |||
830 | int is_open; | 830 | int is_open; |
831 | 831 | ||
832 | u8 mac80211_registered; | 832 | u8 mac80211_registered; |
833 | int is_abg; | ||
834 | 833 | ||
835 | u32 notif_missed_beacons; | 834 | u32 notif_missed_beacons; |
836 | 835 | ||
@@ -950,16 +949,6 @@ static inline int is_channel_ibss(const struct iwl3945_channel_info *ch) | |||
950 | return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; | 949 | return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; |
951 | } | 950 | } |
952 | 951 | ||
953 | static inline int iwl3945_rate_index_from_plcp(int plcp) | ||
954 | { | ||
955 | int i; | ||
956 | |||
957 | for (i = 0; i < IWL_RATE_COUNT; i++) | ||
958 | if (iwl3945_rates[i].plcp == plcp) | ||
959 | return i; | ||
960 | return -1; | ||
961 | } | ||
962 | |||
963 | extern const struct iwl3945_channel_info *iwl3945_get_channel_info( | 952 | extern const struct iwl3945_channel_info *iwl3945_get_channel_info( |
964 | const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel); | 953 | const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel); |
965 | 954 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index b21ffea325cf..327eabce182c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h | |||
@@ -875,26 +875,26 @@ struct iwl4965_rx_frame_hdr { | |||
875 | u8 payload[0]; | 875 | u8 payload[0]; |
876 | } __attribute__ ((packed)); | 876 | } __attribute__ ((packed)); |
877 | 877 | ||
878 | #define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0) | 878 | #define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0) |
879 | #define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1) | 879 | #define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1) |
880 | 880 | ||
881 | #define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0) | 881 | #define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0) |
882 | #define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1) | 882 | #define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1) |
883 | #define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2) | 883 | #define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2) |
884 | #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3) | 884 | #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3) |
885 | #define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0) | 885 | #define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0) |
886 | 886 | ||
887 | #define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) | 887 | #define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) |
888 | #define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) | 888 | #define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) |
889 | #define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) | 889 | #define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) |
890 | #define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) | 890 | #define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) |
891 | #define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) | 891 | #define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) |
892 | 892 | ||
893 | #define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) | 893 | #define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) |
894 | #define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) | 894 | #define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) |
895 | #define RX_RES_STATUS_DECRYPT_OK (0x3 << 11) | 895 | #define RX_RES_STATUS_DECRYPT_OK (0x3 << 11) |
896 | #define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) | 896 | #define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) |
897 | #define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) | 897 | #define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) |
898 | 898 | ||
899 | struct iwl4965_rx_frame_end { | 899 | struct iwl4965_rx_frame_end { |
900 | __le32 status; | 900 | __le32 status; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h b/drivers/net/wireless/iwlwifi/iwl-4965-debug.h index 36696bbf170c..baf07c715cf8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-debug.h | |||
@@ -40,15 +40,30 @@ do { if (iwl4965_debug_level & (level)) \ | |||
40 | do { if ((iwl4965_debug_level & (level)) && net_ratelimit()) \ | 40 | do { if ((iwl4965_debug_level & (level)) && net_ratelimit()) \ |
41 | printk(KERN_ERR DRV_NAME": %c %s " fmt, \ | 41 | printk(KERN_ERR DRV_NAME": %c %s " fmt, \ |
42 | in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) | 42 | in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) |
43 | |||
44 | static inline void iwl4965_print_hex_dump(int level, void *p, u32 len) | ||
45 | { | ||
46 | if (!(iwl4965_debug_level & level)) | ||
47 | return; | ||
48 | |||
49 | print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, | ||
50 | p, len, 1); | ||
51 | } | ||
43 | #else | 52 | #else |
53 | |||
44 | static inline void IWL_DEBUG(int level, const char *fmt, ...) | 54 | static inline void IWL_DEBUG(int level, const char *fmt, ...) |
45 | { | 55 | { |
46 | } | 56 | } |
47 | static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) | 57 | static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) |
48 | { | 58 | { |
49 | } | 59 | } |
60 | static inline void iwl4965_print_hex_dump(int level, void *p, u32 len) | ||
61 | { | ||
62 | } | ||
50 | #endif /* CONFIG_IWL4965_DEBUG */ | 63 | #endif /* CONFIG_IWL4965_DEBUG */ |
51 | 64 | ||
65 | |||
66 | |||
52 | /* | 67 | /* |
53 | * To use the debug system; | 68 | * To use the debug system; |
54 | * | 69 | * |
@@ -143,6 +158,7 @@ static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) | |||
143 | IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) | 158 | IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) |
144 | #define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a) | 159 | #define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a) |
145 | #define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a) | 160 | #define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a) |
161 | #define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a) | ||
146 | #define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a) | 162 | #define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a) |
147 | #define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a) | 163 | #define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a) |
148 | #define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a) | 164 | #define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index cc726215ab93..24413a479a3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h | |||
@@ -410,181 +410,6 @@ struct iwl4965_eeprom { | |||
410 | #define PCI_REG_WUM8 0x0E8 | 410 | #define PCI_REG_WUM8 0x0E8 |
411 | #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000) | 411 | #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000) |
412 | 412 | ||
413 | /*=== CSR (control and status registers) ===*/ | ||
414 | #define CSR_BASE (0x000) | ||
415 | |||
416 | #define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ | ||
417 | #define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ | ||
418 | #define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ | ||
419 | #define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ | ||
420 | #define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ | ||
421 | #define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */ | ||
422 | #define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ | ||
423 | #define CSR_GP_CNTRL (CSR_BASE+0x024) | ||
424 | |||
425 | /* | ||
426 | * Hardware revision info | ||
427 | * Bit fields: | ||
428 | * 31-8: Reserved | ||
429 | * 7-4: Type of device: 0x0 = 4965, 0xd = 3945 | ||
430 | * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D | ||
431 | * 1-0: "Dash" value, as in A-1, etc. | ||
432 | * | ||
433 | * NOTE: Revision step affects calculation of CCK txpower for 4965. | ||
434 | */ | ||
435 | #define CSR_HW_REV (CSR_BASE+0x028) | ||
436 | |||
437 | /* EEPROM reads */ | ||
438 | #define CSR_EEPROM_REG (CSR_BASE+0x02c) | ||
439 | #define CSR_EEPROM_GP (CSR_BASE+0x030) | ||
440 | #define CSR_GP_UCODE (CSR_BASE+0x044) | ||
441 | #define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) | ||
442 | #define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) | ||
443 | #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) | ||
444 | #define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) | ||
445 | #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) | ||
446 | |||
447 | /* | ||
448 | * Indicates hardware rev, to determine CCK backoff for txpower calculation. | ||
449 | * Bit fields: | ||
450 | * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step | ||
451 | */ | ||
452 | #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) | ||
453 | |||
454 | /* Hardware interface configuration bits */ | ||
455 | #define CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R (0x00000010) | ||
456 | #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) | ||
457 | #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) | ||
458 | #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) | ||
459 | #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) | ||
460 | |||
461 | /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), | ||
462 | * acknowledged (reset) by host writing "1" to flagged bits. */ | ||
463 | #define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */ | ||
464 | #define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ | ||
465 | #define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ | ||
466 | #define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ | ||
467 | #define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ | ||
468 | #define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ | ||
469 | #define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ | ||
470 | #define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ | ||
471 | #define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */ | ||
472 | #define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */ | ||
473 | #define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */ | ||
474 | |||
475 | #define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \ | ||
476 | CSR_INT_BIT_HW_ERR | \ | ||
477 | CSR_INT_BIT_FH_TX | \ | ||
478 | CSR_INT_BIT_SW_ERR | \ | ||
479 | CSR_INT_BIT_RF_KILL | \ | ||
480 | CSR_INT_BIT_SW_RX | \ | ||
481 | CSR_INT_BIT_WAKEUP | \ | ||
482 | CSR_INT_BIT_ALIVE) | ||
483 | |||
484 | /* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ | ||
485 | #define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */ | ||
486 | #define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */ | ||
487 | #define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */ | ||
488 | #define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */ | ||
489 | #define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */ | ||
490 | #define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */ | ||
491 | |||
492 | #define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ | ||
493 | CSR_FH_INT_BIT_RX_CHNL1 | \ | ||
494 | CSR_FH_INT_BIT_RX_CHNL0) | ||
495 | |||
496 | #define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \ | ||
497 | CSR_FH_INT_BIT_TX_CHNL0) | ||
498 | |||
499 | |||
500 | /* RESET */ | ||
501 | #define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001) | ||
502 | #define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002) | ||
503 | #define CSR_RESET_REG_FLAG_SW_RESET (0x00000080) | ||
504 | #define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100) | ||
505 | #define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) | ||
506 | |||
507 | /* GP (general purpose) CONTROL */ | ||
508 | #define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) | ||
509 | #define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) | ||
510 | #define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) | ||
511 | #define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010) | ||
512 | |||
513 | #define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001) | ||
514 | |||
515 | #define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000) | ||
516 | #define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000) | ||
517 | #define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000) | ||
518 | |||
519 | |||
520 | /* EEPROM REG */ | ||
521 | #define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001) | ||
522 | #define CSR_EEPROM_REG_BIT_CMD (0x00000002) | ||
523 | |||
524 | /* EEPROM GP */ | ||
525 | #define CSR_EEPROM_GP_VALID_MSK (0x00000006) | ||
526 | #define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) | ||
527 | #define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) | ||
528 | |||
529 | /* UCODE DRV GP */ | ||
530 | #define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001) | ||
531 | #define CSR_UCODE_SW_BIT_RFKILL (0x00000002) | ||
532 | #define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) | ||
533 | #define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008) | ||
534 | |||
535 | /* GPIO */ | ||
536 | #define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200) | ||
537 | #define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000) | ||
538 | #define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER | ||
539 | |||
540 | /* GI Chicken Bits */ | ||
541 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) | ||
542 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) | ||
543 | |||
544 | /*=== HBUS (Host-side Bus) ===*/ | ||
545 | #define HBUS_BASE (0x400) | ||
546 | |||
547 | /* | ||
548 | * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM | ||
549 | * structures, error log, event log, verifying uCode load). | ||
550 | * First write to address register, then read from or write to data register | ||
551 | * to complete the job. Once the address register is set up, accesses to | ||
552 | * data registers auto-increment the address by one dword. | ||
553 | * Bit usage for address registers (read or write): | ||
554 | * 0-31: memory address within device | ||
555 | */ | ||
556 | #define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c) | ||
557 | #define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010) | ||
558 | #define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) | ||
559 | #define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) | ||
560 | |||
561 | /* | ||
562 | * Registers for accessing device's internal peripheral registers | ||
563 | * (e.g. SCD, BSM, etc.). First write to address register, | ||
564 | * then read from or write to data register to complete the job. | ||
565 | * Bit usage for address registers (read or write): | ||
566 | * 0-15: register address (offset) within device | ||
567 | * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword) | ||
568 | */ | ||
569 | #define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044) | ||
570 | #define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048) | ||
571 | #define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c) | ||
572 | #define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) | ||
573 | |||
574 | /* | ||
575 | * Per-Tx-queue write pointer (index, really!) (3945 and 4965). | ||
576 | * Driver sets this to indicate index to next TFD that driver will fill | ||
577 | * (1 past latest filled). | ||
578 | * Bit usage: | ||
579 | * 0-7: queue write index (0-255) | ||
580 | * 11-8: queue selector (0-15) | ||
581 | */ | ||
582 | #define HBUS_TARG_WRPTR (HBUS_BASE+0x060) | ||
583 | |||
584 | #define HBUS_TARG_MBX_C (HBUS_BASE+0x030) | ||
585 | |||
586 | #define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) | ||
587 | |||
588 | #define TFD_QUEUE_SIZE_MAX (256) | 413 | #define TFD_QUEUE_SIZE_MAX (256) |
589 | 414 | ||
590 | #define IWL_NUM_SCAN_RATES (2) | 415 | #define IWL_NUM_SCAN_RATES (2) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 48a6a85355ec..25e73864c2a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c | |||
@@ -570,7 +570,7 @@ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate, | |||
570 | int index; | 570 | int index; |
571 | u32 ant_msk; | 571 | u32 ant_msk; |
572 | 572 | ||
573 | index = iwl4965_rate_index_from_plcp(mcs_rate->rate_n_flags); | 573 | index = iwl4965_hwrate_to_plcp_idx(mcs_rate->rate_n_flags); |
574 | 574 | ||
575 | if (index == IWL_RATE_INVALID) { | 575 | if (index == IWL_RATE_INVALID) { |
576 | *rate_idx = -1; | 576 | *rate_idx = -1; |
@@ -823,6 +823,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, | |||
823 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 823 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
824 | struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate; | 824 | struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate; |
825 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 825 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
826 | struct ieee80211_hw *hw = local_to_hw(local); | ||
826 | struct iwl4965_rate_scale_data *window = NULL; | 827 | struct iwl4965_rate_scale_data *window = NULL; |
827 | struct iwl4965_rate_scale_data *search_win = NULL; | 828 | struct iwl4965_rate_scale_data *search_win = NULL; |
828 | struct iwl4965_rate tx_mcs; | 829 | struct iwl4965_rate tx_mcs; |
@@ -847,23 +848,22 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, | |||
847 | if (retries > 15) | 848 | if (retries > 15) |
848 | retries = 15; | 849 | retries = 15; |
849 | 850 | ||
851 | rcu_read_lock(); | ||
850 | 852 | ||
851 | sta = sta_info_get(local, hdr->addr1); | 853 | sta = sta_info_get(local, hdr->addr1); |
852 | 854 | ||
853 | if (!sta || !sta->rate_ctrl_priv) { | 855 | if (!sta || !sta->rate_ctrl_priv) |
854 | if (sta) | 856 | goto out; |
855 | sta_info_put(sta); | 857 | |
856 | return; | ||
857 | } | ||
858 | 858 | ||
859 | lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; | 859 | lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; |
860 | 860 | ||
861 | if (!priv->lq_mngr.lq_ready) | 861 | if (!priv->lq_mngr.lq_ready) |
862 | return; | 862 | goto out; |
863 | 863 | ||
864 | if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && | 864 | if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && |
865 | !lq_sta->ibss_sta_added) | 865 | !lq_sta->ibss_sta_added) |
866 | return; | 866 | goto out; |
867 | 867 | ||
868 | table = &lq_sta->lq; | 868 | table = &lq_sta->lq; |
869 | active_index = lq_sta->active_tbl; | 869 | active_index = lq_sta->active_tbl; |
@@ -884,17 +884,6 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, | |||
884 | search_win = (struct iwl4965_rate_scale_data *) | 884 | search_win = (struct iwl4965_rate_scale_data *) |
885 | &(search_tbl->win[0]); | 885 | &(search_tbl->win[0]); |
886 | 886 | ||
887 | tx_mcs.rate_n_flags = tx_resp->control.tx_rate->hw_value; | ||
888 | |||
889 | rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, | ||
890 | &tbl_type, &rs_index); | ||
891 | if ((rs_index < 0) || (rs_index >= IWL_RATE_COUNT)) { | ||
892 | IWL_DEBUG_RATE("bad rate index at: %d rate 0x%X\n", | ||
893 | rs_index, tx_mcs.rate_n_flags); | ||
894 | sta_info_put(sta); | ||
895 | return; | ||
896 | } | ||
897 | |||
898 | /* | 887 | /* |
899 | * Ignore this Tx frame response if its initial rate doesn't match | 888 | * Ignore this Tx frame response if its initial rate doesn't match |
900 | * that of latest Link Quality command. There may be stragglers | 889 | * that of latest Link Quality command. There may be stragglers |
@@ -903,14 +892,29 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, | |||
903 | * to check "search" mode, or a prior "search" mode after we've moved | 892 | * to check "search" mode, or a prior "search" mode after we've moved |
904 | * to a new "search" mode (which might become the new "active" mode). | 893 | * to a new "search" mode (which might become the new "active" mode). |
905 | */ | 894 | */ |
906 | if (retries && | 895 | tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[0].rate_n_flags); |
907 | (tx_mcs.rate_n_flags != | 896 | rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index); |
908 | le32_to_cpu(table->rs_table[0].rate_n_flags))) { | 897 | if (priv->band == IEEE80211_BAND_5GHZ) |
909 | IWL_DEBUG_RATE("initial rate does not match 0x%x 0x%x\n", | 898 | rs_index -= IWL_FIRST_OFDM_RATE; |
910 | tx_mcs.rate_n_flags, | 899 | |
911 | le32_to_cpu(table->rs_table[0].rate_n_flags)); | 900 | if ((tx_resp->control.tx_rate == NULL) || |
912 | sta_info_put(sta); | 901 | (tbl_type.is_SGI ^ |
913 | return; | 902 | !!(tx_resp->control.flags & IEEE80211_TXCTL_SHORT_GI)) || |
903 | (tbl_type.is_fat ^ | ||
904 | !!(tx_resp->control.flags & IEEE80211_TXCTL_40_MHZ_WIDTH)) || | ||
905 | (tbl_type.is_dup ^ | ||
906 | !!(tx_resp->control.flags & IEEE80211_TXCTL_DUP_DATA)) || | ||
907 | (tbl_type.antenna_type ^ | ||
908 | tx_resp->control.antenna_sel_tx) || | ||
909 | (!!(tx_mcs.rate_n_flags & RATE_MCS_HT_MSK) ^ | ||
910 | !!(tx_resp->control.flags & IEEE80211_TXCTL_OFDM_HT)) || | ||
911 | (!!(tx_mcs.rate_n_flags & RATE_MCS_GF_MSK) ^ | ||
912 | !!(tx_resp->control.flags & IEEE80211_TXCTL_GREEN_FIELD)) || | ||
913 | (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate != | ||
914 | tx_resp->control.tx_rate->bitrate)) { | ||
915 | IWL_DEBUG_RATE("initial rate does not match 0x%x\n", | ||
916 | tx_mcs.rate_n_flags); | ||
917 | goto out; | ||
914 | } | 918 | } |
915 | 919 | ||
916 | /* Update frame history window with "failure" for each Tx retry. */ | 920 | /* Update frame history window with "failure" for each Tx retry. */ |
@@ -959,14 +963,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, | |||
959 | * if Tx was successful first try, use original rate, | 963 | * if Tx was successful first try, use original rate, |
960 | * else look up the rate that was, finally, successful. | 964 | * else look up the rate that was, finally, successful. |
961 | */ | 965 | */ |
962 | if (!tx_resp->retry_count) | 966 | tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[index].rate_n_flags); |
963 | tx_mcs.rate_n_flags = tx_resp->control.tx_rate->hw_value; | 967 | rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index); |
964 | else | ||
965 | tx_mcs.rate_n_flags = | ||
966 | le32_to_cpu(table->rs_table[index].rate_n_flags); | ||
967 | |||
968 | rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, | ||
969 | &tbl_type, &rs_index); | ||
970 | 968 | ||
971 | /* Update frame history window with "success" if Tx got ACKed ... */ | 969 | /* Update frame history window with "success" if Tx got ACKed ... */ |
972 | if (tx_resp->flags & IEEE80211_TX_STATUS_ACK) | 970 | if (tx_resp->flags & IEEE80211_TX_STATUS_ACK) |
@@ -1025,7 +1023,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, | |||
1025 | 1023 | ||
1026 | /* See if there's a better rate or modulation mode to try. */ | 1024 | /* See if there's a better rate or modulation mode to try. */ |
1027 | rs_rate_scale_perform(priv, dev, hdr, sta); | 1025 | rs_rate_scale_perform(priv, dev, hdr, sta); |
1028 | sta_info_put(sta); | 1026 | out: |
1027 | rcu_read_unlock(); | ||
1029 | return; | 1028 | return; |
1030 | } | 1029 | } |
1031 | 1030 | ||
@@ -1921,7 +1920,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, | |||
1921 | tbl = &(lq_sta->lq_info[active_tbl]); | 1920 | tbl = &(lq_sta->lq_info[active_tbl]); |
1922 | 1921 | ||
1923 | /* Revert to "active" rate and throughput info */ | 1922 | /* Revert to "active" rate and throughput info */ |
1924 | index = iwl4965_rate_index_from_plcp( | 1923 | index = iwl4965_hwrate_to_plcp_idx( |
1925 | tbl->current_rate.rate_n_flags); | 1924 | tbl->current_rate.rate_n_flags); |
1926 | current_tpt = lq_sta->last_tpt; | 1925 | current_tpt = lq_sta->last_tpt; |
1927 | 1926 | ||
@@ -2077,7 +2076,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, | |||
2077 | rs_rate_scale_clear_window(&(tbl->win[i])); | 2076 | rs_rate_scale_clear_window(&(tbl->win[i])); |
2078 | 2077 | ||
2079 | /* Use new "search" start rate */ | 2078 | /* Use new "search" start rate */ |
2080 | index = iwl4965_rate_index_from_plcp( | 2079 | index = iwl4965_hwrate_to_plcp_idx( |
2081 | tbl->current_rate.rate_n_flags); | 2080 | tbl->current_rate.rate_n_flags); |
2082 | 2081 | ||
2083 | IWL_DEBUG_HT("Switch current mcs: %X index: %d\n", | 2082 | IWL_DEBUG_HT("Switch current mcs: %X index: %d\n", |
@@ -2219,6 +2218,8 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
2219 | 2218 | ||
2220 | IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); | 2219 | IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); |
2221 | 2220 | ||
2221 | rcu_read_lock(); | ||
2222 | |||
2222 | sta = sta_info_get(local, hdr->addr1); | 2223 | sta = sta_info_get(local, hdr->addr1); |
2223 | 2224 | ||
2224 | /* Send management frames and broadcast/multicast data using lowest | 2225 | /* Send management frames and broadcast/multicast data using lowest |
@@ -2227,9 +2228,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
2227 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || | 2228 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || |
2228 | !sta || !sta->rate_ctrl_priv) { | 2229 | !sta || !sta->rate_ctrl_priv) { |
2229 | sel->rate = rate_lowest(local, sband, sta); | 2230 | sel->rate = rate_lowest(local, sband, sta); |
2230 | if (sta) | 2231 | goto out; |
2231 | sta_info_put(sta); | ||
2232 | return; | ||
2233 | } | 2232 | } |
2234 | 2233 | ||
2235 | lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; | 2234 | lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; |
@@ -2256,14 +2255,15 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
2256 | goto done; | 2255 | goto done; |
2257 | } | 2256 | } |
2258 | 2257 | ||
2259 | done: | 2258 | done: |
2260 | if ((i < 0) || (i > IWL_RATE_COUNT)) { | 2259 | if ((i < 0) || (i > IWL_RATE_COUNT)) { |
2261 | sel->rate = rate_lowest(local, sband, sta); | 2260 | sel->rate = rate_lowest(local, sband, sta); |
2262 | return; | 2261 | goto out; |
2263 | } | 2262 | } |
2264 | sta_info_put(sta); | ||
2265 | 2263 | ||
2266 | sel->rate = &priv->ieee_rates[i]; | 2264 | sel->rate = &priv->ieee_rates[i]; |
2265 | out: | ||
2266 | rcu_read_unlock(); | ||
2267 | } | 2267 | } |
2268 | 2268 | ||
2269 | static void *rs_alloc_sta(void *priv, gfp_t gfp) | 2269 | static void *rs_alloc_sta(void *priv, gfp_t gfp) |
@@ -2735,13 +2735,15 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) | |||
2735 | u32 max_time = 0; | 2735 | u32 max_time = 0; |
2736 | u8 lq_type, antenna; | 2736 | u8 lq_type, antenna; |
2737 | 2737 | ||
2738 | rcu_read_lock(); | ||
2739 | |||
2738 | sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); | 2740 | sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); |
2739 | if (!sta || !sta->rate_ctrl_priv) { | 2741 | if (!sta || !sta->rate_ctrl_priv) { |
2740 | if (sta) { | 2742 | if (sta) |
2741 | sta_info_put(sta); | ||
2742 | IWL_DEBUG_RATE("leave - no private rate data!\n"); | 2743 | IWL_DEBUG_RATE("leave - no private rate data!\n"); |
2743 | } else | 2744 | else |
2744 | IWL_DEBUG_RATE("leave - no station!\n"); | 2745 | IWL_DEBUG_RATE("leave - no station!\n"); |
2746 | rcu_read_unlock(); | ||
2745 | return sprintf(buf, "station %d not found\n", sta_id); | 2747 | return sprintf(buf, "station %d not found\n", sta_id); |
2746 | } | 2748 | } |
2747 | 2749 | ||
@@ -2808,7 +2810,7 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) | |||
2808 | "active_search %d rate index %d\n", lq_type, antenna, | 2810 | "active_search %d rate index %d\n", lq_type, antenna, |
2809 | lq_sta->search_better_tbl, sta->last_txrate_idx); | 2811 | lq_sta->search_better_tbl, sta->last_txrate_idx); |
2810 | 2812 | ||
2811 | sta_info_put(sta); | 2813 | rcu_read_unlock(); |
2812 | return cnt; | 2814 | return cnt; |
2813 | } | 2815 | } |
2814 | 2816 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h index 13b6c72eeb73..911f21396fd0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h | |||
@@ -259,7 +259,7 @@ static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index) | |||
259 | return rate; | 259 | return rate; |
260 | } | 260 | } |
261 | 261 | ||
262 | extern int iwl4965_rate_index_from_plcp(int plcp); | 262 | extern int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags); |
263 | 263 | ||
264 | /** | 264 | /** |
265 | * iwl4965_fill_rs_info - Fill an output text buffer with the rate representation | 265 | * iwl4965_fill_rs_info - Fill an output text buffer with the rate representation |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a9c30bcb65b8..2f01a490c9ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/etherdevice.h> | 38 | #include <linux/etherdevice.h> |
39 | #include <asm/unaligned.h> | 39 | #include <asm/unaligned.h> |
40 | 40 | ||
41 | #include "iwl-core.h" | ||
41 | #include "iwl-4965.h" | 42 | #include "iwl-4965.h" |
42 | #include "iwl-helpers.h" | 43 | #include "iwl-helpers.h" |
43 | 44 | ||
@@ -122,6 +123,64 @@ static u8 is_single_stream(struct iwl4965_priv *priv) | |||
122 | return 0; | 123 | return 0; |
123 | } | 124 | } |
124 | 125 | ||
126 | int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags) | ||
127 | { | ||
128 | int idx = 0; | ||
129 | |||
130 | /* 4965 HT rate format */ | ||
131 | if (rate_n_flags & RATE_MCS_HT_MSK) { | ||
132 | idx = (rate_n_flags & 0xff); | ||
133 | |||
134 | if (idx >= IWL_RATE_MIMO_6M_PLCP) | ||
135 | idx = idx - IWL_RATE_MIMO_6M_PLCP; | ||
136 | |||
137 | idx += IWL_FIRST_OFDM_RATE; | ||
138 | /* skip 9M not supported in ht*/ | ||
139 | if (idx >= IWL_RATE_9M_INDEX) | ||
140 | idx += 1; | ||
141 | if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE)) | ||
142 | return idx; | ||
143 | |||
144 | /* 4965 legacy rate format, search for match in table */ | ||
145 | } else { | ||
146 | for (idx = 0; idx < ARRAY_SIZE(iwl4965_rates); idx++) | ||
147 | if (iwl4965_rates[idx].plcp == (rate_n_flags & 0xFF)) | ||
148 | return idx; | ||
149 | } | ||
150 | |||
151 | return -1; | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * translate ucode response to mac80211 tx status control values | ||
156 | */ | ||
157 | void iwl4965_hwrate_to_tx_control(struct iwl4965_priv *priv, u32 rate_n_flags, | ||
158 | struct ieee80211_tx_control *control) | ||
159 | { | ||
160 | int rate_index; | ||
161 | |||
162 | control->antenna_sel_tx = | ||
163 | ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_A_POS); | ||
164 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
165 | control->flags |= IEEE80211_TXCTL_OFDM_HT; | ||
166 | if (rate_n_flags & RATE_MCS_GF_MSK) | ||
167 | control->flags |= IEEE80211_TXCTL_GREEN_FIELD; | ||
168 | if (rate_n_flags & RATE_MCS_FAT_MSK) | ||
169 | control->flags |= IEEE80211_TXCTL_40_MHZ_WIDTH; | ||
170 | if (rate_n_flags & RATE_MCS_DUP_MSK) | ||
171 | control->flags |= IEEE80211_TXCTL_DUP_DATA; | ||
172 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
173 | control->flags |= IEEE80211_TXCTL_SHORT_GI; | ||
174 | /* since iwl4965_hwrate_to_plcp_idx is band indifferent, we always use | ||
175 | * IEEE80211_BAND_2GHZ band as it contains all the rates */ | ||
176 | rate_index = iwl4965_hwrate_to_plcp_idx(rate_n_flags); | ||
177 | if (rate_index == -1) | ||
178 | control->tx_rate = NULL; | ||
179 | else | ||
180 | control->tx_rate = | ||
181 | &priv->bands[IEEE80211_BAND_2GHZ].bitrates[rate_index]; | ||
182 | } | ||
183 | |||
125 | /* | 184 | /* |
126 | * Determine how many receiver/antenna chains to use. | 185 | * Determine how many receiver/antenna chains to use. |
127 | * More provides better reception via diversity. Fewer saves power. | 186 | * More provides better reception via diversity. Fewer saves power. |
@@ -546,9 +605,9 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv) | |||
546 | /* set CSR_HW_CONFIG_REG for uCode use */ | 605 | /* set CSR_HW_CONFIG_REG for uCode use */ |
547 | 606 | ||
548 | iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG, | 607 | iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG, |
549 | CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R | | 608 | CSR49_HW_IF_CONFIG_REG_BIT_4965_R | |
550 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | 609 | CSR49_HW_IF_CONFIG_REG_BIT_RADIO_SI | |
551 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | 610 | CSR49_HW_IF_CONFIG_REG_BIT_MAC_SI); |
552 | 611 | ||
553 | rc = iwl4965_grab_nic_access(priv); | 612 | rc = iwl4965_grab_nic_access(priv); |
554 | if (rc < 0) { | 613 | if (rc < 0) { |
@@ -3523,6 +3582,160 @@ static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *ad | |||
3523 | } | 3582 | } |
3524 | } | 3583 | } |
3525 | } | 3584 | } |
3585 | #ifdef CONFIG_IWL4965_DEBUG | ||
3586 | |||
3587 | /** | ||
3588 | * iwl4965_dbg_report_frame - dump frame to syslog during debug sessions | ||
3589 | * | ||
3590 | * You may hack this function to show different aspects of received frames, | ||
3591 | * including selective frame dumps. | ||
3592 | * group100 parameter selects whether to show 1 out of 100 good frames. | ||
3593 | * | ||
3594 | * TODO: This was originally written for 3945, need to audit for | ||
3595 | * proper operation with 4965. | ||
3596 | */ | ||
3597 | static void iwl4965_dbg_report_frame(struct iwl4965_priv *priv, | ||
3598 | struct iwl4965_rx_packet *pkt, | ||
3599 | struct ieee80211_hdr *header, int group100) | ||
3600 | { | ||
3601 | u32 to_us; | ||
3602 | u32 print_summary = 0; | ||
3603 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
3604 | u32 hundred = 0; | ||
3605 | u32 dataframe = 0; | ||
3606 | u16 fc; | ||
3607 | u16 seq_ctl; | ||
3608 | u16 channel; | ||
3609 | u16 phy_flags; | ||
3610 | int rate_sym; | ||
3611 | u16 length; | ||
3612 | u16 status; | ||
3613 | u16 bcn_tmr; | ||
3614 | u32 tsf_low; | ||
3615 | u64 tsf; | ||
3616 | u8 rssi; | ||
3617 | u8 agc; | ||
3618 | u16 sig_avg; | ||
3619 | u16 noise_diff; | ||
3620 | struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | ||
3621 | struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | ||
3622 | struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt); | ||
3623 | u8 *data = IWL_RX_DATA(pkt); | ||
3624 | |||
3625 | if (likely(!(iwl4965_debug_level & IWL_DL_RX))) | ||
3626 | return; | ||
3627 | |||
3628 | /* MAC header */ | ||
3629 | fc = le16_to_cpu(header->frame_control); | ||
3630 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
3631 | |||
3632 | /* metadata */ | ||
3633 | channel = le16_to_cpu(rx_hdr->channel); | ||
3634 | phy_flags = le16_to_cpu(rx_hdr->phy_flags); | ||
3635 | rate_sym = rx_hdr->rate; | ||
3636 | length = le16_to_cpu(rx_hdr->len); | ||
3637 | |||
3638 | /* end-of-frame status and timestamp */ | ||
3639 | status = le32_to_cpu(rx_end->status); | ||
3640 | bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); | ||
3641 | tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; | ||
3642 | tsf = le64_to_cpu(rx_end->timestamp); | ||
3643 | |||
3644 | /* signal statistics */ | ||
3645 | rssi = rx_stats->rssi; | ||
3646 | agc = rx_stats->agc; | ||
3647 | sig_avg = le16_to_cpu(rx_stats->sig_avg); | ||
3648 | noise_diff = le16_to_cpu(rx_stats->noise_diff); | ||
3649 | |||
3650 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
3651 | |||
3652 | /* if data frame is to us and all is good, | ||
3653 | * (optionally) print summary for only 1 out of every 100 */ | ||
3654 | if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) == | ||
3655 | (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
3656 | dataframe = 1; | ||
3657 | if (!group100) | ||
3658 | print_summary = 1; /* print each frame */ | ||
3659 | else if (priv->framecnt_to_us < 100) { | ||
3660 | priv->framecnt_to_us++; | ||
3661 | print_summary = 0; | ||
3662 | } else { | ||
3663 | priv->framecnt_to_us = 0; | ||
3664 | print_summary = 1; | ||
3665 | hundred = 1; | ||
3666 | } | ||
3667 | } else { | ||
3668 | /* print summary for all other frames */ | ||
3669 | print_summary = 1; | ||
3670 | } | ||
3671 | |||
3672 | if (print_summary) { | ||
3673 | char *title; | ||
3674 | int rate_idx; | ||
3675 | u32 bitrate; | ||
3676 | |||
3677 | if (hundred) | ||
3678 | title = "100Frames"; | ||
3679 | else if (fc & IEEE80211_FCTL_RETRY) | ||
3680 | title = "Retry"; | ||
3681 | else if (ieee80211_is_assoc_response(fc)) | ||
3682 | title = "AscRsp"; | ||
3683 | else if (ieee80211_is_reassoc_response(fc)) | ||
3684 | title = "RasRsp"; | ||
3685 | else if (ieee80211_is_probe_response(fc)) { | ||
3686 | title = "PrbRsp"; | ||
3687 | print_dump = 1; /* dump frame contents */ | ||
3688 | } else if (ieee80211_is_beacon(fc)) { | ||
3689 | title = "Beacon"; | ||
3690 | print_dump = 1; /* dump frame contents */ | ||
3691 | } else if (ieee80211_is_atim(fc)) | ||
3692 | title = "ATIM"; | ||
3693 | else if (ieee80211_is_auth(fc)) | ||
3694 | title = "Auth"; | ||
3695 | else if (ieee80211_is_deauth(fc)) | ||
3696 | title = "DeAuth"; | ||
3697 | else if (ieee80211_is_disassoc(fc)) | ||
3698 | title = "DisAssoc"; | ||
3699 | else | ||
3700 | title = "Frame"; | ||
3701 | |||
3702 | rate_idx = iwl4965_hwrate_to_plcp_idx(rate_sym); | ||
3703 | if (unlikely(rate_idx == -1)) | ||
3704 | bitrate = 0; | ||
3705 | else | ||
3706 | bitrate = iwl4965_rates[rate_idx].ieee / 2; | ||
3707 | |||
3708 | /* print frame summary. | ||
3709 | * MAC addresses show just the last byte (for brevity), | ||
3710 | * but you can hack it to show more, if you'd like to. */ | ||
3711 | if (dataframe) | ||
3712 | IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " | ||
3713 | "len=%u, rssi=%d, chnl=%d, rate=%u, \n", | ||
3714 | title, fc, header->addr1[5], | ||
3715 | length, rssi, channel, bitrate); | ||
3716 | else { | ||
3717 | /* src/dst addresses assume managed mode */ | ||
3718 | IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " | ||
3719 | "src=0x%02x, rssi=%u, tim=%lu usec, " | ||
3720 | "phy=0x%02x, chnl=%d\n", | ||
3721 | title, fc, header->addr1[5], | ||
3722 | header->addr3[5], rssi, | ||
3723 | tsf_low - priv->scan_start_tsf, | ||
3724 | phy_flags, channel); | ||
3725 | } | ||
3726 | } | ||
3727 | if (print_dump) | ||
3728 | iwl4965_print_hex_dump(IWL_DL_RX, data, length); | ||
3729 | } | ||
3730 | #else | ||
3731 | static inline void iwl4965_dbg_report_frame(struct iwl4965_priv *priv, | ||
3732 | struct iwl4965_rx_packet *pkt, | ||
3733 | struct ieee80211_hdr *header, | ||
3734 | int group100) | ||
3735 | { | ||
3736 | } | ||
3737 | #endif | ||
3738 | |||
3526 | 3739 | ||
3527 | #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) | 3740 | #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) |
3528 | 3741 | ||
@@ -3531,6 +3744,8 @@ static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *ad | |||
3531 | static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, | 3744 | static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, |
3532 | struct iwl4965_rx_mem_buffer *rxb) | 3745 | struct iwl4965_rx_mem_buffer *rxb) |
3533 | { | 3746 | { |
3747 | struct ieee80211_hdr *header; | ||
3748 | struct ieee80211_rx_status rx_status; | ||
3534 | struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; | 3749 | struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; |
3535 | /* Use phy data (Rx signal strength, etc.) contained within | 3750 | /* Use phy data (Rx signal strength, etc.) contained within |
3536 | * this rx packet for legacy frames, | 3751 | * this rx packet for legacy frames, |
@@ -3541,27 +3756,29 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, | |||
3541 | (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; | 3756 | (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; |
3542 | __le32 *rx_end; | 3757 | __le32 *rx_end; |
3543 | unsigned int len = 0; | 3758 | unsigned int len = 0; |
3544 | struct ieee80211_hdr *header; | ||
3545 | u16 fc; | 3759 | u16 fc; |
3546 | struct ieee80211_rx_status stats = { | ||
3547 | .mactime = le64_to_cpu(rx_start->timestamp), | ||
3548 | .freq = ieee80211chan2mhz(le16_to_cpu(rx_start->channel)), | ||
3549 | .band = | ||
3550 | (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
3551 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ, | ||
3552 | .antenna = 0, | ||
3553 | .rate_idx = iwl4965_rate_index_from_plcp( | ||
3554 | le32_to_cpu(rx_start->rate_n_flags)), | ||
3555 | .flag = 0, | ||
3556 | }; | ||
3557 | u8 network_packet; | 3760 | u8 network_packet; |
3558 | 3761 | ||
3762 | rx_status.mactime = le64_to_cpu(rx_start->timestamp); | ||
3763 | rx_status.freq = ieee80211chan2mhz(le16_to_cpu(rx_start->channel)); | ||
3764 | rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
3765 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
3766 | rx_status.rate_idx = iwl4965_hwrate_to_plcp_idx( | ||
3767 | le32_to_cpu(rx_start->rate_n_flags)); | ||
3768 | |||
3769 | if (rx_status.band == IEEE80211_BAND_5GHZ) | ||
3770 | rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; | ||
3771 | |||
3772 | rx_status.antenna = 0; | ||
3773 | rx_status.flag = 0; | ||
3774 | |||
3559 | if ((unlikely(rx_start->cfg_phy_cnt > 20))) { | 3775 | if ((unlikely(rx_start->cfg_phy_cnt > 20))) { |
3560 | IWL_DEBUG_DROP | 3776 | IWL_DEBUG_DROP |
3561 | ("dsp size out of range [0,20]: " | 3777 | ("dsp size out of range [0,20]: " |
3562 | "%d/n", rx_start->cfg_phy_cnt); | 3778 | "%d/n", rx_start->cfg_phy_cnt); |
3563 | return; | 3779 | return; |
3564 | } | 3780 | } |
3781 | |||
3565 | if (!include_phy) { | 3782 | if (!include_phy) { |
3566 | if (priv->last_phy_res[0]) | 3783 | if (priv->last_phy_res[0]) |
3567 | rx_start = (struct iwl4965_rx_phy_res *) | 3784 | rx_start = (struct iwl4965_rx_phy_res *) |
@@ -3580,7 +3797,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, | |||
3580 | + rx_start->cfg_phy_cnt); | 3797 | + rx_start->cfg_phy_cnt); |
3581 | 3798 | ||
3582 | len = le16_to_cpu(rx_start->byte_count); | 3799 | len = le16_to_cpu(rx_start->byte_count); |
3583 | rx_end = (__le32 *) (pkt->u.raw + rx_start->cfg_phy_cnt + | 3800 | rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt + |
3584 | sizeof(struct iwl4965_rx_phy_res) + len); | 3801 | sizeof(struct iwl4965_rx_phy_res) + len); |
3585 | } else { | 3802 | } else { |
3586 | struct iwl4965_rx_mpdu_res_start *amsdu = | 3803 | struct iwl4965_rx_mpdu_res_start *amsdu = |
@@ -3603,7 +3820,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, | |||
3603 | priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp); | 3820 | priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp); |
3604 | 3821 | ||
3605 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | 3822 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ |
3606 | stats.ssi = iwl4965_calc_rssi(rx_start); | 3823 | rx_status.ssi = iwl4965_calc_rssi(rx_start); |
3607 | 3824 | ||
3608 | /* Meaningful noise values are available only from beacon statistics, | 3825 | /* Meaningful noise values are available only from beacon statistics, |
3609 | * which are gathered only when associated, and indicate noise | 3826 | * which are gathered only when associated, and indicate noise |
@@ -3611,32 +3828,29 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, | |||
3611 | * Ignore these noise values while scanning (other channels) */ | 3828 | * Ignore these noise values while scanning (other channels) */ |
3612 | if (iwl4965_is_associated(priv) && | 3829 | if (iwl4965_is_associated(priv) && |
3613 | !test_bit(STATUS_SCANNING, &priv->status)) { | 3830 | !test_bit(STATUS_SCANNING, &priv->status)) { |
3614 | stats.noise = priv->last_rx_noise; | 3831 | rx_status.noise = priv->last_rx_noise; |
3615 | stats.signal = iwl4965_calc_sig_qual(stats.ssi, stats.noise); | 3832 | rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi, |
3833 | rx_status.noise); | ||
3616 | } else { | 3834 | } else { |
3617 | stats.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | 3835 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; |
3618 | stats.signal = iwl4965_calc_sig_qual(stats.ssi, 0); | 3836 | rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi, 0); |
3619 | } | 3837 | } |
3620 | 3838 | ||
3621 | /* Reset beacon noise level if not associated. */ | 3839 | /* Reset beacon noise level if not associated. */ |
3622 | if (!iwl4965_is_associated(priv)) | 3840 | if (!iwl4965_is_associated(priv)) |
3623 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | 3841 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; |
3624 | 3842 | ||
3625 | #ifdef CONFIG_IWL4965_DEBUG | 3843 | /* Set "1" to report good data frames in groups of 100 */ |
3626 | /* TODO: Parts of iwl4965_report_frame are broken for 4965 */ | 3844 | /* FIXME: need to optimze the call: */ |
3627 | if (iwl4965_debug_level & (IWL_DL_RX)) | 3845 | iwl4965_dbg_report_frame(priv, pkt, header, 1); |
3628 | /* Set "1" to report good data frames in groups of 100 */ | 3846 | |
3629 | iwl4965_report_frame(priv, pkt, header, 1); | 3847 | IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n", |
3630 | 3848 | rx_status.ssi, rx_status.noise, rx_status.signal, | |
3631 | if (iwl4965_debug_level & (IWL_DL_RX | IWL_DL_STATS)) | 3849 | rx_status.mactime); |
3632 | IWL_DEBUG_RX("Rssi %d, noise %d, qual %d, TSF %lu\n", | ||
3633 | stats.ssi, stats.noise, stats.signal, | ||
3634 | (long unsigned int)le64_to_cpu(rx_start->timestamp)); | ||
3635 | #endif | ||
3636 | 3850 | ||
3637 | network_packet = iwl4965_is_network_packet(priv, header); | 3851 | network_packet = iwl4965_is_network_packet(priv, header); |
3638 | if (network_packet) { | 3852 | if (network_packet) { |
3639 | priv->last_rx_rssi = stats.ssi; | 3853 | priv->last_rx_rssi = rx_status.ssi; |
3640 | priv->last_beacon_time = priv->ucode_beacon_time; | 3854 | priv->last_beacon_time = priv->ucode_beacon_time; |
3641 | priv->last_tsf = le64_to_cpu(rx_start->timestamp); | 3855 | priv->last_tsf = le64_to_cpu(rx_start->timestamp); |
3642 | } | 3856 | } |
@@ -3739,7 +3953,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, | |||
3739 | return; | 3953 | return; |
3740 | } | 3954 | } |
3741 | } | 3955 | } |
3742 | iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &stats); | 3956 | iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &rx_status); |
3743 | break; | 3957 | break; |
3744 | 3958 | ||
3745 | case IEEE80211_FTYPE_CTL: | 3959 | case IEEE80211_FTYPE_CTL: |
@@ -3748,7 +3962,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, | |||
3748 | case IEEE80211_STYPE_BACK_REQ: | 3962 | case IEEE80211_STYPE_BACK_REQ: |
3749 | IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n"); | 3963 | IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n"); |
3750 | iwl4965_handle_data_packet(priv, 0, include_phy, | 3964 | iwl4965_handle_data_packet(priv, 0, include_phy, |
3751 | rxb, &stats); | 3965 | rxb, &rx_status); |
3752 | break; | 3966 | break; |
3753 | default: | 3967 | default: |
3754 | break; | 3968 | break; |
@@ -3778,7 +3992,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, | |||
3778 | print_mac(mac3, header->addr3)); | 3992 | print_mac(mac3, header->addr3)); |
3779 | else | 3993 | else |
3780 | iwl4965_handle_data_packet(priv, 1, include_phy, rxb, | 3994 | iwl4965_handle_data_packet(priv, 1, include_phy, rxb, |
3781 | &stats); | 3995 | &rx_status); |
3782 | break; | 3996 | break; |
3783 | } | 3997 | } |
3784 | default: | 3998 | default: |
@@ -3900,11 +4114,10 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, | |||
3900 | tx_status->flags |= IEEE80211_TX_STATUS_AMPDU; | 4114 | tx_status->flags |= IEEE80211_TX_STATUS_AMPDU; |
3901 | tx_status->ampdu_ack_map = successes; | 4115 | tx_status->ampdu_ack_map = successes; |
3902 | tx_status->ampdu_ack_len = agg->frame_count; | 4116 | tx_status->ampdu_ack_len = agg->frame_count; |
3903 | /* FIXME Wrong rate | 4117 | iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags, |
3904 | tx_status->control.tx_rate = agg->rate_n_flags; | 4118 | &tx_status->control); |
3905 | */ | ||
3906 | 4119 | ||
3907 | IWL_DEBUG_TX_REPLY("Bitmap %llx\n", bitmap); | 4120 | IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap); |
3908 | 4121 | ||
3909 | return 0; | 4122 | return 0; |
3910 | } | 4123 | } |
@@ -3925,16 +4138,23 @@ static void iwl4965_tx_queue_stop_scheduler(struct iwl4965_priv *priv, | |||
3925 | 4138 | ||
3926 | /** | 4139 | /** |
3927 | * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID | 4140 | * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID |
4141 | * priv->lock must be held by the caller | ||
3928 | */ | 4142 | */ |
3929 | static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id, | 4143 | static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id, |
3930 | u16 ssn_idx, u8 tx_fifo) | 4144 | u16 ssn_idx, u8 tx_fifo) |
3931 | { | 4145 | { |
4146 | int ret = 0; | ||
4147 | |||
3932 | if (IWL_BACK_QUEUE_FIRST_ID > txq_id) { | 4148 | if (IWL_BACK_QUEUE_FIRST_ID > txq_id) { |
3933 | IWL_WARNING("queue number too small: %d, must be > %d\n", | 4149 | IWL_WARNING("queue number too small: %d, must be > %d\n", |
3934 | txq_id, IWL_BACK_QUEUE_FIRST_ID); | 4150 | txq_id, IWL_BACK_QUEUE_FIRST_ID); |
3935 | return -EINVAL; | 4151 | return -EINVAL; |
3936 | } | 4152 | } |
3937 | 4153 | ||
4154 | ret = iwl4965_grab_nic_access(priv); | ||
4155 | if (ret) | ||
4156 | return ret; | ||
4157 | |||
3938 | iwl4965_tx_queue_stop_scheduler(priv, txq_id); | 4158 | iwl4965_tx_queue_stop_scheduler(priv, txq_id); |
3939 | 4159 | ||
3940 | iwl4965_clear_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id)); | 4160 | iwl4965_clear_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id)); |
@@ -3948,6 +4168,8 @@ static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id, | |||
3948 | iwl4965_txq_ctx_deactivate(priv, txq_id); | 4168 | iwl4965_txq_ctx_deactivate(priv, txq_id); |
3949 | iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); | 4169 | iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); |
3950 | 4170 | ||
4171 | iwl4965_release_nic_access(priv); | ||
4172 | |||
3951 | return 0; | 4173 | return 0; |
3952 | } | 4174 | } |
3953 | 4175 | ||
@@ -4040,12 +4262,12 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv, | |||
4040 | "%d, scd_ssn = %d\n", | 4262 | "%d, scd_ssn = %d\n", |
4041 | ba_resp->tid, | 4263 | ba_resp->tid, |
4042 | ba_resp->seq_ctl, | 4264 | ba_resp->seq_ctl, |
4043 | ba_resp->bitmap, | 4265 | (unsigned long long)ba_resp->bitmap, |
4044 | ba_resp->scd_flow, | 4266 | ba_resp->scd_flow, |
4045 | ba_resp->scd_ssn); | 4267 | ba_resp->scd_ssn); |
4046 | IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n", | 4268 | IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n", |
4047 | agg->start_idx, | 4269 | agg->start_idx, |
4048 | agg->bitmap); | 4270 | (unsigned long long)agg->bitmap); |
4049 | 4271 | ||
4050 | /* Update driver's record of ACK vs. not for each frame in window */ | 4272 | /* Update driver's record of ACK vs. not for each frame in window */ |
4051 | iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp); | 4273 | iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp); |
@@ -4232,7 +4454,7 @@ static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, | |||
4232 | if (!is_channel_valid(ch_info)) | 4454 | if (!is_channel_valid(ch_info)) |
4233 | return 0; | 4455 | return 0; |
4234 | 4456 | ||
4235 | if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO) | 4457 | if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE) |
4236 | return 0; | 4458 | return 0; |
4237 | 4459 | ||
4238 | if ((ch_info->fat_extension_channel == extension_chan_offset) || | 4460 | if ((ch_info->fat_extension_channel == extension_chan_offset) || |
@@ -4249,7 +4471,7 @@ static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv, | |||
4249 | 4471 | ||
4250 | if ((!iwl_ht_conf->is_ht) || | 4472 | if ((!iwl_ht_conf->is_ht) || |
4251 | (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) || | 4473 | (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) || |
4252 | (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO)) | 4474 | (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE)) |
4253 | return 0; | 4475 | return 0; |
4254 | 4476 | ||
4255 | if (sta_ht_inf) { | 4477 | if (sta_ht_inf) { |
@@ -4294,9 +4516,7 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info) | |||
4294 | case IWL_EXT_CHANNEL_OFFSET_BELOW: | 4516 | case IWL_EXT_CHANNEL_OFFSET_BELOW: |
4295 | rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | 4517 | rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; |
4296 | break; | 4518 | break; |
4297 | case IWL_EXT_CHANNEL_OFFSET_AUTO: | 4519 | case IWL_EXT_CHANNEL_OFFSET_NONE: |
4298 | rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK; | ||
4299 | break; | ||
4300 | default: | 4520 | default: |
4301 | rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK; | 4521 | rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK; |
4302 | break; | 4522 | break; |
@@ -4419,7 +4639,7 @@ static int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, const u8 *da, | |||
4419 | int tx_fifo; | 4639 | int tx_fifo; |
4420 | int txq_id; | 4640 | int txq_id; |
4421 | int ssn = -1; | 4641 | int ssn = -1; |
4422 | int rc = 0; | 4642 | int ret = 0; |
4423 | unsigned long flags; | 4643 | unsigned long flags; |
4424 | struct iwl4965_tid_data *tid_data; | 4644 | struct iwl4965_tid_data *tid_data; |
4425 | DECLARE_MAC_BUF(mac); | 4645 | DECLARE_MAC_BUF(mac); |
@@ -4452,12 +4672,12 @@ static int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, const u8 *da, | |||
4452 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 4672 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
4453 | 4673 | ||
4454 | *start_seq_num = ssn; | 4674 | *start_seq_num = ssn; |
4455 | rc = iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo, | 4675 | ret = iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo, |
4456 | sta_id, tid, ssn); | 4676 | sta_id, tid, ssn); |
4457 | if (rc) | 4677 | if (ret) |
4458 | return rc; | 4678 | return ret; |
4459 | 4679 | ||
4460 | rc = 0; | 4680 | ret = 0; |
4461 | if (tid_data->tfds_in_queue == 0) { | 4681 | if (tid_data->tfds_in_queue == 0) { |
4462 | printk(KERN_ERR "HW queue is empty\n"); | 4682 | printk(KERN_ERR "HW queue is empty\n"); |
4463 | tid_data->agg.state = IWL_AGG_ON; | 4683 | tid_data->agg.state = IWL_AGG_ON; |
@@ -4467,7 +4687,7 @@ static int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, const u8 *da, | |||
4467 | tid_data->tfds_in_queue); | 4687 | tid_data->tfds_in_queue); |
4468 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | 4688 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; |
4469 | } | 4689 | } |
4470 | return rc; | 4690 | return ret; |
4471 | } | 4691 | } |
4472 | 4692 | ||
4473 | static int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da, | 4693 | static int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da, |
@@ -4477,7 +4697,7 @@ static int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da, | |||
4477 | struct iwl4965_priv *priv = hw->priv; | 4697 | struct iwl4965_priv *priv = hw->priv; |
4478 | int tx_fifo_id, txq_id, sta_id, ssn = -1; | 4698 | int tx_fifo_id, txq_id, sta_id, ssn = -1; |
4479 | struct iwl4965_tid_data *tid_data; | 4699 | struct iwl4965_tid_data *tid_data; |
4480 | int rc, write_ptr, read_ptr; | 4700 | int ret, write_ptr, read_ptr; |
4481 | unsigned long flags; | 4701 | unsigned long flags; |
4482 | DECLARE_MAC_BUF(mac); | 4702 | DECLARE_MAC_BUF(mac); |
4483 | 4703 | ||
@@ -4517,17 +4737,11 @@ static int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da, | |||
4517 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | 4737 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; |
4518 | 4738 | ||
4519 | spin_lock_irqsave(&priv->lock, flags); | 4739 | spin_lock_irqsave(&priv->lock, flags); |
4520 | rc = iwl4965_grab_nic_access(priv); | 4740 | ret = iwl4965_tx_queue_agg_disable(priv, txq_id, ssn, tx_fifo_id); |
4521 | if (rc) { | ||
4522 | spin_unlock_irqrestore(&priv->lock, flags); | ||
4523 | return rc; | ||
4524 | } | ||
4525 | rc = iwl4965_tx_queue_agg_disable(priv, txq_id, ssn, tx_fifo_id); | ||
4526 | iwl4965_release_nic_access(priv); | ||
4527 | spin_unlock_irqrestore(&priv->lock, flags); | 4741 | spin_unlock_irqrestore(&priv->lock, flags); |
4528 | 4742 | ||
4529 | if (rc) | 4743 | if (ret) |
4530 | return rc; | 4744 | return ret; |
4531 | 4745 | ||
4532 | ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, da, tid); | 4746 | ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, da, tid); |
4533 | 4747 | ||
@@ -4610,9 +4824,15 @@ void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv) | |||
4610 | cancel_delayed_work(&priv->init_alive_start); | 4824 | cancel_delayed_work(&priv->init_alive_start); |
4611 | } | 4825 | } |
4612 | 4826 | ||
4827 | static struct iwl_cfg iwl4965_agn_cfg = { | ||
4828 | .name = "4965AGN", | ||
4829 | .fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode", | ||
4830 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
4831 | }; | ||
4832 | |||
4613 | struct pci_device_id iwl4965_hw_card_ids[] = { | 4833 | struct pci_device_id iwl4965_hw_card_ids[] = { |
4614 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4229)}, | 4834 | {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, |
4615 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4230)}, | 4835 | {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, |
4616 | {0} | 4836 | {0} |
4617 | }; | 4837 | }; |
4618 | 4838 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index ce17e4fec838..057fa15d62fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h | |||
@@ -41,9 +41,17 @@ extern struct pci_device_id iwl4965_hw_card_ids[]; | |||
41 | 41 | ||
42 | #define DRV_NAME "iwl4965" | 42 | #define DRV_NAME "iwl4965" |
43 | #include "iwl-4965-hw.h" | 43 | #include "iwl-4965-hw.h" |
44 | #include "iwl-csr.h" | ||
44 | #include "iwl-prph.h" | 45 | #include "iwl-prph.h" |
45 | #include "iwl-4965-debug.h" | 46 | #include "iwl-4965-debug.h" |
46 | 47 | ||
48 | /* Change firmware file name, using "-" and incrementing number, | ||
49 | * *only* when uCode interface or architecture changes so that it | ||
50 | * is not compatible with earlier drivers. | ||
51 | * This number will also appear in << 8 position of 1st dword of uCode file */ | ||
52 | #define IWL4965_UCODE_API "-1" | ||
53 | |||
54 | |||
47 | /* Default noise level to report when noise measurement is not available. | 55 | /* Default noise level to report when noise measurement is not available. |
48 | * This may be because we're: | 56 | * This may be because we're: |
49 | * 1) Not associated (4965, no beacon statistics being sent to driver) | 57 | * 1) Not associated (4965, no beacon statistics being sent to driver) |
@@ -633,16 +641,6 @@ extern int iwl4965_is_network_packet(struct iwl4965_priv *priv, | |||
633 | struct ieee80211_hdr *header); | 641 | struct ieee80211_hdr *header); |
634 | extern int iwl4965_power_init_handle(struct iwl4965_priv *priv); | 642 | extern int iwl4965_power_init_handle(struct iwl4965_priv *priv); |
635 | extern int iwl4965_eeprom_init(struct iwl4965_priv *priv); | 643 | extern int iwl4965_eeprom_init(struct iwl4965_priv *priv); |
636 | #ifdef CONFIG_IWL4965_DEBUG | ||
637 | extern void iwl4965_report_frame(struct iwl4965_priv *priv, | ||
638 | struct iwl4965_rx_packet *pkt, | ||
639 | struct ieee80211_hdr *header, int group100); | ||
640 | #else | ||
641 | static inline void iwl4965_report_frame(struct iwl4965_priv *priv, | ||
642 | struct iwl4965_rx_packet *pkt, | ||
643 | struct ieee80211_hdr *header, | ||
644 | int group100) {} | ||
645 | #endif | ||
646 | extern void iwl4965_handle_data_packet_monitor(struct iwl4965_priv *priv, | 644 | extern void iwl4965_handle_data_packet_monitor(struct iwl4965_priv *priv, |
647 | struct iwl4965_rx_mem_buffer *rxb, | 645 | struct iwl4965_rx_mem_buffer *rxb, |
648 | void *data, short len, | 646 | void *data, short len, |
@@ -767,6 +765,9 @@ extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, | |||
767 | const struct iwl4965_eeprom_channel *eeprom_ch, | 765 | const struct iwl4965_eeprom_channel *eeprom_ch, |
768 | u8 fat_extension_channel); | 766 | u8 fat_extension_channel); |
769 | extern void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv); | 767 | extern void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv); |
768 | extern void iwl4965_hwrate_to_tx_control(struct iwl4965_priv *priv, | ||
769 | u32 rate_n_flags, | ||
770 | struct ieee80211_tx_control *control); | ||
770 | 771 | ||
771 | #ifdef CONFIG_IWL4965_HT | 772 | #ifdef CONFIG_IWL4965_HT |
772 | void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, | 773 | void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, |
@@ -808,11 +809,10 @@ struct iwl4965_kw { | |||
808 | #define IWL_OPERATION_MODE_MIXED 2 | 809 | #define IWL_OPERATION_MODE_MIXED 2 |
809 | #define IWL_OPERATION_MODE_20MHZ 3 | 810 | #define IWL_OPERATION_MODE_20MHZ 3 |
810 | 811 | ||
811 | #define IWL_EXT_CHANNEL_OFFSET_AUTO 0 | 812 | #define IWL_EXT_CHANNEL_OFFSET_NONE 0 |
812 | #define IWL_EXT_CHANNEL_OFFSET_ABOVE 1 | 813 | #define IWL_EXT_CHANNEL_OFFSET_ABOVE 1 |
813 | #define IWL_EXT_CHANNEL_OFFSET_ 2 | 814 | #define IWL_EXT_CHANNEL_OFFSET_RESERVE1 2 |
814 | #define IWL_EXT_CHANNEL_OFFSET_BELOW 3 | 815 | #define IWL_EXT_CHANNEL_OFFSET_BELOW 3 |
815 | #define IWL_EXT_CHANNEL_OFFSET_MAX 4 | ||
816 | 816 | ||
817 | #define NRG_NUM_PREV_STAT_L 20 | 817 | #define NRG_NUM_PREV_STAT_L 20 |
818 | #define NUM_RX_CHAINS (3) | 818 | #define NUM_RX_CHAINS (3) |
@@ -974,6 +974,7 @@ struct iwl4965_priv { | |||
974 | struct ieee80211_hw *hw; | 974 | struct ieee80211_hw *hw; |
975 | struct ieee80211_channel *ieee_channels; | 975 | struct ieee80211_channel *ieee_channels; |
976 | struct ieee80211_rate *ieee_rates; | 976 | struct ieee80211_rate *ieee_rates; |
977 | struct iwl_cfg *cfg; | ||
977 | 978 | ||
978 | /* temporary frame storage list */ | 979 | /* temporary frame storage list */ |
979 | struct list_head free_frames; | 980 | struct list_head free_frames; |
@@ -1104,7 +1105,6 @@ struct iwl4965_priv { | |||
1104 | u32 scd_base_addr; /* scheduler sram base address */ | 1105 | u32 scd_base_addr; /* scheduler sram base address */ |
1105 | 1106 | ||
1106 | unsigned long status; | 1107 | unsigned long status; |
1107 | u32 config; | ||
1108 | 1108 | ||
1109 | int last_rx_rssi; /* From Rx packet statisitics */ | 1109 | int last_rx_rssi; /* From Rx packet statisitics */ |
1110 | int last_rx_noise; /* From beacon statistics */ | 1110 | int last_rx_noise; /* From beacon statistics */ |
@@ -1134,7 +1134,6 @@ struct iwl4965_priv { | |||
1134 | int is_open; | 1134 | int is_open; |
1135 | 1135 | ||
1136 | u8 mac80211_registered; | 1136 | u8 mac80211_registered; |
1137 | int is_abg; | ||
1138 | 1137 | ||
1139 | u32 notif_missed_beacons; | 1138 | u32 notif_missed_beacons; |
1140 | 1139 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c new file mode 100644 index 000000000000..675b34b696b4 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -0,0 +1,47 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Tomas Winkler <tomas.winkler@intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | *****************************************************************************/ | ||
31 | |||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/version.h> | ||
35 | |||
36 | #include "iwl-4965-debug.h" | ||
37 | #include "iwl-core.h" | ||
38 | |||
39 | MODULE_DESCRIPTION("iwl core"); | ||
40 | MODULE_VERSION(IWLWIFI_VERSION); | ||
41 | MODULE_AUTHOR(DRV_COPYRIGHT); | ||
42 | MODULE_LICENSE("GPL/BSD"); | ||
43 | |||
44 | #ifdef CONFIG_IWL4965_DEBUG | ||
45 | u32 iwl4965_debug_level; | ||
46 | EXPORT_SYMBOL(iwl4965_debug_level); | ||
47 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h new file mode 100644 index 000000000000..bdd32f891683 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -0,0 +1,84 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Tomas Winkler <tomas.winkler@intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __iwl_core_h__ | ||
64 | #define __iwl_core_h__ | ||
65 | |||
66 | #define IWLWIFI_VERSION "1.2.26k" | ||
67 | #define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation" | ||
68 | |||
69 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | ||
70 | .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ | ||
71 | .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ | ||
72 | .driver_data = (kernel_ulong_t)&(cfg) | ||
73 | |||
74 | #define IWL_SKU_G 0x1 | ||
75 | #define IWL_SKU_A 0x2 | ||
76 | #define IWL_SKU_N 0x8 | ||
77 | |||
78 | struct iwl_cfg { | ||
79 | const char *name; | ||
80 | const char *fw_name; | ||
81 | unsigned int sku; | ||
82 | }; | ||
83 | |||
84 | #endif /* __iwl_core_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h new file mode 100644 index 000000000000..7016e5b41c58 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -0,0 +1,259 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * James P. Ketrenos <ipw2100-admin@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | /*=== CSR (control and status registers) ===*/ | ||
64 | #define CSR_BASE (0x000) | ||
65 | |||
66 | #define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ | ||
67 | #define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ | ||
68 | #define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ | ||
69 | #define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ | ||
70 | #define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ | ||
71 | #define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */ | ||
72 | #define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ | ||
73 | #define CSR_GP_CNTRL (CSR_BASE+0x024) | ||
74 | |||
75 | /* | ||
76 | * Hardware revision info | ||
77 | * Bit fields: | ||
78 | * 31-8: Reserved | ||
79 | * 7-4: Type of device: 0x0 = 4965, 0xd = 3945 | ||
80 | * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D | ||
81 | * 1-0: "Dash" value, as in A-1, etc. | ||
82 | * | ||
83 | * NOTE: Revision step affects calculation of CCK txpower for 4965. | ||
84 | */ | ||
85 | #define CSR_HW_REV (CSR_BASE+0x028) | ||
86 | |||
87 | /* EEPROM reads */ | ||
88 | #define CSR_EEPROM_REG (CSR_BASE+0x02c) | ||
89 | #define CSR_EEPROM_GP (CSR_BASE+0x030) | ||
90 | #define CSR_GP_UCODE (CSR_BASE+0x044) | ||
91 | #define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) | ||
92 | #define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) | ||
93 | #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) | ||
94 | #define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) | ||
95 | #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) | ||
96 | |||
97 | /* Analog phase-lock-loop configuration (3945 only) | ||
98 | * Set bit 24. */ | ||
99 | #define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) | ||
100 | /* | ||
101 | * Indicates hardware rev, to determine CCK backoff for txpower calculation. | ||
102 | * Bit fields: | ||
103 | * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step | ||
104 | */ | ||
105 | #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) | ||
106 | |||
107 | /* Bits for CSR_HW_IF_CONFIG_REG */ | ||
108 | #define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010) | ||
109 | #define CSR49_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) | ||
110 | #define CSR49_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) | ||
111 | #define CSR49_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) | ||
112 | |||
113 | #define CSR39_HW_IF_CONFIG_REG_BIT_3945_MB (0x00000100) | ||
114 | #define CSR39_HW_IF_CONFIG_REG_BIT_3945_MM (0x00000200) | ||
115 | #define CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400) | ||
116 | #define CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800) | ||
117 | #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) | ||
118 | #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) | ||
119 | |||
120 | #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) | ||
121 | |||
122 | /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), | ||
123 | * acknowledged (reset) by host writing "1" to flagged bits. */ | ||
124 | #define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */ | ||
125 | #define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ | ||
126 | #define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ | ||
127 | #define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ | ||
128 | #define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ | ||
129 | #define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ | ||
130 | #define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ | ||
131 | #define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ | ||
132 | #define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */ | ||
133 | #define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */ | ||
134 | #define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */ | ||
135 | |||
136 | #define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \ | ||
137 | CSR_INT_BIT_HW_ERR | \ | ||
138 | CSR_INT_BIT_FH_TX | \ | ||
139 | CSR_INT_BIT_SW_ERR | \ | ||
140 | CSR_INT_BIT_RF_KILL | \ | ||
141 | CSR_INT_BIT_SW_RX | \ | ||
142 | CSR_INT_BIT_WAKEUP | \ | ||
143 | CSR_INT_BIT_ALIVE) | ||
144 | |||
145 | /* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ | ||
146 | #define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */ | ||
147 | #define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */ | ||
148 | #define CSR39_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */ | ||
149 | #define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */ | ||
150 | #define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */ | ||
151 | #define CSR39_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */ | ||
152 | #define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */ | ||
153 | #define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */ | ||
154 | |||
155 | #define CSR39_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ | ||
156 | CSR39_FH_INT_BIT_RX_CHNL2 | \ | ||
157 | CSR_FH_INT_BIT_RX_CHNL1 | \ | ||
158 | CSR_FH_INT_BIT_RX_CHNL0) | ||
159 | |||
160 | |||
161 | #define CSR39_FH_INT_TX_MASK (CSR39_FH_INT_BIT_TX_CHNL6 | \ | ||
162 | CSR_FH_INT_BIT_TX_CHNL1 | \ | ||
163 | CSR_FH_INT_BIT_TX_CHNL0) | ||
164 | |||
165 | #define CSR49_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ | ||
166 | CSR_FH_INT_BIT_RX_CHNL1 | \ | ||
167 | CSR_FH_INT_BIT_RX_CHNL0) | ||
168 | |||
169 | #define CSR49_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \ | ||
170 | CSR_FH_INT_BIT_TX_CHNL0) | ||
171 | |||
172 | |||
173 | /* RESET */ | ||
174 | #define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001) | ||
175 | #define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002) | ||
176 | #define CSR_RESET_REG_FLAG_SW_RESET (0x00000080) | ||
177 | #define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100) | ||
178 | #define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) | ||
179 | |||
180 | /* GP (general purpose) CONTROL */ | ||
181 | #define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) | ||
182 | #define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) | ||
183 | #define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) | ||
184 | #define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010) | ||
185 | |||
186 | #define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001) | ||
187 | |||
188 | #define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000) | ||
189 | #define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000) | ||
190 | #define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000) | ||
191 | |||
192 | |||
193 | /* EEPROM REG */ | ||
194 | #define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001) | ||
195 | #define CSR_EEPROM_REG_BIT_CMD (0x00000002) | ||
196 | |||
197 | /* EEPROM GP */ | ||
198 | #define CSR_EEPROM_GP_VALID_MSK (0x00000006) | ||
199 | #define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) | ||
200 | #define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) | ||
201 | |||
202 | /* UCODE DRV GP */ | ||
203 | #define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001) | ||
204 | #define CSR_UCODE_SW_BIT_RFKILL (0x00000002) | ||
205 | #define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) | ||
206 | #define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008) | ||
207 | |||
208 | /* GPIO */ | ||
209 | #define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200) | ||
210 | #define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000) | ||
211 | #define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER | ||
212 | |||
213 | /* GI Chicken Bits */ | ||
214 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) | ||
215 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) | ||
216 | |||
217 | /*=== HBUS (Host-side Bus) ===*/ | ||
218 | #define HBUS_BASE (0x400) | ||
219 | /* | ||
220 | * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM | ||
221 | * structures, error log, event log, verifying uCode load). | ||
222 | * First write to address register, then read from or write to data register | ||
223 | * to complete the job. Once the address register is set up, accesses to | ||
224 | * data registers auto-increment the address by one dword. | ||
225 | * Bit usage for address registers (read or write): | ||
226 | * 0-31: memory address within device | ||
227 | */ | ||
228 | #define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c) | ||
229 | #define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010) | ||
230 | #define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) | ||
231 | #define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) | ||
232 | |||
233 | /* | ||
234 | * Registers for accessing device's internal peripheral registers | ||
235 | * (e.g. SCD, BSM, etc.). First write to address register, | ||
236 | * then read from or write to data register to complete the job. | ||
237 | * Bit usage for address registers (read or write): | ||
238 | * 0-15: register address (offset) within device | ||
239 | * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword) | ||
240 | */ | ||
241 | #define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044) | ||
242 | #define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048) | ||
243 | #define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c) | ||
244 | #define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) | ||
245 | |||
246 | /* | ||
247 | * Per-Tx-queue write pointer (index, really!) (3945 and 4965). | ||
248 | * Indicates index to next TFD that driver will fill (1 past latest filled). | ||
249 | * Bit usage: | ||
250 | * 0-7: queue write index | ||
251 | * 11-8: queue selector | ||
252 | */ | ||
253 | #define HBUS_TARG_WRPTR (HBUS_BASE+0x060) | ||
254 | #define HBUS_TARG_MBX_C (HBUS_BASE+0x030) | ||
255 | |||
256 | #define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) | ||
257 | |||
258 | |||
259 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c new file mode 100644 index 000000000000..0064387dea91 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -0,0 +1,205 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Tomas Winkler <tomas.winkler@intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | |||
64 | #include <linux/kernel.h> | ||
65 | #include <linux/module.h> | ||
66 | #include <linux/version.h> | ||
67 | #include <linux/init.h> | ||
68 | |||
69 | #include <net/mac80211.h> | ||
70 | |||
71 | #include "iwl-4965-commands.h" | ||
72 | #include "iwl-4965.h" | ||
73 | #include "iwl-core.h" | ||
74 | #include "iwl-4965-debug.h" | ||
75 | #include "iwl-eeprom.h" | ||
76 | #include "iwl-4965-io.h" | ||
77 | |||
78 | /****************************************************************************** | ||
79 | * | ||
80 | * EEPROM related functions | ||
81 | * | ||
82 | ******************************************************************************/ | ||
83 | |||
84 | int iwlcore_eeprom_verify_signature(struct iwl4965_priv *priv) | ||
85 | { | ||
86 | u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP); | ||
87 | if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { | ||
88 | IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); | ||
89 | return -ENOENT; | ||
90 | } | ||
91 | return 0; | ||
92 | } | ||
93 | EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); | ||
94 | |||
95 | /* | ||
96 | * The device's EEPROM semaphore prevents conflicts between driver and uCode | ||
97 | * when accessing the EEPROM; each access is a series of pulses to/from the | ||
98 | * EEPROM chip, not a single event, so even reads could conflict if they | ||
99 | * weren't arbitrated by the semaphore. | ||
100 | */ | ||
101 | int iwlcore_eeprom_acquire_semaphore(struct iwl4965_priv *priv) | ||
102 | { | ||
103 | u16 count; | ||
104 | int ret; | ||
105 | |||
106 | for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { | ||
107 | /* Request semaphore */ | ||
108 | iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
109 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
110 | |||
111 | /* See if we got it */ | ||
112 | ret = iwl4965_poll_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
113 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
114 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
115 | EEPROM_SEM_TIMEOUT); | ||
116 | if (ret >= 0) { | ||
117 | IWL_DEBUG_IO("Acquired semaphore after %d tries.\n", | ||
118 | count+1); | ||
119 | return ret; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | return ret; | ||
124 | } | ||
125 | EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore); | ||
126 | |||
127 | void iwlcore_eeprom_release_semaphore(struct iwl4965_priv *priv) | ||
128 | { | ||
129 | iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
130 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
131 | |||
132 | } | ||
133 | EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore); | ||
134 | |||
135 | |||
136 | /** | ||
137 | * iwl_eeprom_init - read EEPROM contents | ||
138 | * | ||
139 | * Load the EEPROM contents from adapter into priv->eeprom | ||
140 | * | ||
141 | * NOTE: This routine uses the non-debug IO access functions. | ||
142 | */ | ||
143 | int iwl_eeprom_init(struct iwl4965_priv *priv) | ||
144 | { | ||
145 | u16 *e = (u16 *)&priv->eeprom; | ||
146 | u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP); | ||
147 | u32 r; | ||
148 | int sz = sizeof(priv->eeprom); | ||
149 | int ret; | ||
150 | int i; | ||
151 | u16 addr; | ||
152 | |||
153 | /* The EEPROM structure has several padding buffers within it | ||
154 | * and when adding new EEPROM maps is subject to programmer errors | ||
155 | * which may be very difficult to identify without explicitly | ||
156 | * checking the resulting size of the eeprom map. */ | ||
157 | BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE); | ||
158 | |||
159 | if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { | ||
160 | IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); | ||
161 | return -ENOENT; | ||
162 | } | ||
163 | |||
164 | /* Make sure driver (instead of uCode) is allowed to read EEPROM */ | ||
165 | ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv); | ||
166 | if (ret < 0) { | ||
167 | IWL_ERROR("Failed to acquire EEPROM semaphore.\n"); | ||
168 | return -ENOENT; | ||
169 | } | ||
170 | |||
171 | /* eeprom is an array of 16bit values */ | ||
172 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | ||
173 | _iwl4965_write32(priv, CSR_EEPROM_REG, addr << 1); | ||
174 | _iwl4965_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD); | ||
175 | |||
176 | for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT; | ||
177 | i += IWL_EEPROM_ACCESS_DELAY) { | ||
178 | r = _iwl4965_read_direct32(priv, CSR_EEPROM_REG); | ||
179 | if (r & CSR_EEPROM_REG_READ_VALID_MSK) | ||
180 | break; | ||
181 | udelay(IWL_EEPROM_ACCESS_DELAY); | ||
182 | } | ||
183 | |||
184 | if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) { | ||
185 | IWL_ERROR("Time out reading EEPROM[%d]", addr); | ||
186 | ret = -ETIMEDOUT; | ||
187 | goto done; | ||
188 | } | ||
189 | e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); | ||
190 | } | ||
191 | ret = 0; | ||
192 | |||
193 | done: | ||
194 | priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); | ||
195 | return ret; | ||
196 | } | ||
197 | EXPORT_SYMBOL(iwl_eeprom_init); | ||
198 | |||
199 | |||
200 | void iwl_eeprom_get_mac(const struct iwl4965_priv *priv, u8 *mac) | ||
201 | { | ||
202 | memcpy(mac, priv->eeprom.mac_address, 6); | ||
203 | } | ||
204 | EXPORT_SYMBOL(iwl_eeprom_get_mac); | ||
205 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h new file mode 100644 index 000000000000..7827566dcc8b --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -0,0 +1,399 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Tomas Winkler <tomas.winkler@intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __iwl_eeprom_h__ | ||
64 | #define __iwl_eeprom_h__ | ||
65 | |||
66 | struct iwl4965_priv; | ||
67 | |||
68 | /* | ||
69 | * EEPROM access time values: | ||
70 | * | ||
71 | * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG, | ||
72 | * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit | ||
73 | * CSR_EEPROM_REG_BIT_CMD (0x2). | ||
74 | * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). | ||
75 | * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. | ||
76 | * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. | ||
77 | */ | ||
78 | #define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ | ||
79 | #define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */ | ||
80 | |||
81 | #define IWL_EEPROM_SEM_TIMEOUT 10 /* milliseconds */ | ||
82 | #define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
83 | |||
84 | |||
85 | /* | ||
86 | * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags. | ||
87 | * | ||
88 | * IBSS and/or AP operation is allowed *only* on those channels with | ||
89 | * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because | ||
90 | * RADAR detection is not supported by the 4965 driver, but is a | ||
91 | * requirement for establishing a new network for legal operation on channels | ||
92 | * requiring RADAR detection or restricting ACTIVE scanning. | ||
93 | * | ||
94 | * NOTE: "WIDE" flag does not indicate anything about "FAT" 40 MHz channels. | ||
95 | * It only indicates that 20 MHz channel use is supported; FAT channel | ||
96 | * usage is indicated by a separate set of regulatory flags for each | ||
97 | * FAT channel pair. | ||
98 | * | ||
99 | * NOTE: Using a channel inappropriately will result in a uCode error! | ||
100 | */ | ||
101 | #define IWL_NUM_TX_CALIB_GROUPS 5 | ||
102 | enum { | ||
103 | EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */ | ||
104 | EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */ | ||
105 | /* Bit 2 Reserved */ | ||
106 | EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */ | ||
107 | EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */ | ||
108 | EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */ | ||
109 | EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel (not used) */ | ||
110 | EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */ | ||
111 | }; | ||
112 | |||
113 | /* SKU Capabilities */ | ||
114 | #define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0) | ||
115 | #define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) | ||
116 | |||
117 | /* *regulatory* channel data format in eeprom, one for each channel. | ||
118 | * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */ | ||
119 | struct iwl4965_eeprom_channel { | ||
120 | u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */ | ||
121 | s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ | ||
122 | } __attribute__ ((packed)); | ||
123 | |||
124 | /* 4965 has two radio transmitters (and 3 radio receivers) */ | ||
125 | #define EEPROM_TX_POWER_TX_CHAINS (2) | ||
126 | |||
127 | /* 4965 has room for up to 8 sets of txpower calibration data */ | ||
128 | #define EEPROM_TX_POWER_BANDS (8) | ||
129 | |||
130 | /* 4965 factory calibration measures txpower gain settings for | ||
131 | * each of 3 target output levels */ | ||
132 | #define EEPROM_TX_POWER_MEASUREMENTS (3) | ||
133 | |||
134 | #define EEPROM_4965_TX_POWER_VERSION (2) | ||
135 | |||
136 | /* 4965 driver does not work with txpower calibration version < 5. | ||
137 | * Look for this in calib_version member of struct iwl4965_eeprom. */ | ||
138 | #define EEPROM_TX_POWER_VERSION_NEW (5) | ||
139 | |||
140 | |||
141 | /* | ||
142 | * 4965 factory calibration data for one txpower level, on one channel, | ||
143 | * measured on one of the 2 tx chains (radio transmitter and associated | ||
144 | * antenna). EEPROM contains: | ||
145 | * | ||
146 | * 1) Temperature (degrees Celsius) of device when measurement was made. | ||
147 | * | ||
148 | * 2) Gain table index used to achieve the target measurement power. | ||
149 | * This refers to the "well-known" gain tables (see iwl-4965-hw.h). | ||
150 | * | ||
151 | * 3) Actual measured output power, in half-dBm ("34" = 17 dBm). | ||
152 | * | ||
153 | * 4) RF power amplifier detector level measurement (not used). | ||
154 | */ | ||
155 | struct iwl4965_eeprom_calib_measure { | ||
156 | u8 temperature; /* Device temperature (Celsius) */ | ||
157 | u8 gain_idx; /* Index into gain table */ | ||
158 | u8 actual_pow; /* Measured RF output power, half-dBm */ | ||
159 | s8 pa_det; /* Power amp detector level (not used) */ | ||
160 | } __attribute__ ((packed)); | ||
161 | |||
162 | |||
163 | /* | ||
164 | * 4965 measurement set for one channel. EEPROM contains: | ||
165 | * | ||
166 | * 1) Channel number measured | ||
167 | * | ||
168 | * 2) Measurements for each of 3 power levels for each of 2 radio transmitters | ||
169 | * (a.k.a. "tx chains") (6 measurements altogether) | ||
170 | */ | ||
171 | struct iwl4965_eeprom_calib_ch_info { | ||
172 | u8 ch_num; | ||
173 | struct iwl4965_eeprom_calib_measure | ||
174 | measurements[EEPROM_TX_POWER_TX_CHAINS] | ||
175 | [EEPROM_TX_POWER_MEASUREMENTS]; | ||
176 | } __attribute__ ((packed)); | ||
177 | |||
178 | /* | ||
179 | * 4965 txpower subband info. | ||
180 | * | ||
181 | * For each frequency subband, EEPROM contains the following: | ||
182 | * | ||
183 | * 1) First and last channels within range of the subband. "0" values | ||
184 | * indicate that this sample set is not being used. | ||
185 | * | ||
186 | * 2) Sample measurement sets for 2 channels close to the range endpoints. | ||
187 | */ | ||
188 | struct iwl4965_eeprom_calib_subband_info { | ||
189 | u8 ch_from; /* channel number of lowest channel in subband */ | ||
190 | u8 ch_to; /* channel number of highest channel in subband */ | ||
191 | struct iwl4965_eeprom_calib_ch_info ch1; | ||
192 | struct iwl4965_eeprom_calib_ch_info ch2; | ||
193 | } __attribute__ ((packed)); | ||
194 | |||
195 | |||
196 | /* | ||
197 | * 4965 txpower calibration info. EEPROM contains: | ||
198 | * | ||
199 | * 1) Factory-measured saturation power levels (maximum levels at which | ||
200 | * tx power amplifier can output a signal without too much distortion). | ||
201 | * There is one level for 2.4 GHz band and one for 5 GHz band. These | ||
202 | * values apply to all channels within each of the bands. | ||
203 | * | ||
204 | * 2) Factory-measured power supply voltage level. This is assumed to be | ||
205 | * constant (i.e. same value applies to all channels/bands) while the | ||
206 | * factory measurements are being made. | ||
207 | * | ||
208 | * 3) Up to 8 sets of factory-measured txpower calibration values. | ||
209 | * These are for different frequency ranges, since txpower gain | ||
210 | * characteristics of the analog radio circuitry vary with frequency. | ||
211 | * | ||
212 | * Not all sets need to be filled with data; | ||
213 | * struct iwl4965_eeprom_calib_subband_info contains range of channels | ||
214 | * (0 if unused) for each set of data. | ||
215 | */ | ||
216 | struct iwl4965_eeprom_calib_info { | ||
217 | u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ | ||
218 | u8 saturation_power52; /* half-dBm */ | ||
219 | s16 voltage; /* signed */ | ||
220 | struct iwl4965_eeprom_calib_subband_info | ||
221 | band_info[EEPROM_TX_POWER_BANDS]; | ||
222 | } __attribute__ ((packed)); | ||
223 | |||
224 | |||
225 | |||
226 | /* | ||
227 | * 4965 EEPROM map | ||
228 | */ | ||
229 | struct iwl4965_eeprom { | ||
230 | u8 reserved0[16]; | ||
231 | #define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ | ||
232 | u16 device_id; /* abs.ofs: 16 */ | ||
233 | u8 reserved1[2]; | ||
234 | #define EEPROM_PMC (2*0x0A) /* 2 bytes */ | ||
235 | u16 pmc; /* abs.ofs: 20 */ | ||
236 | u8 reserved2[20]; | ||
237 | #define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */ | ||
238 | u8 mac_address[6]; /* abs.ofs: 42 */ | ||
239 | u8 reserved3[58]; | ||
240 | #define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ | ||
241 | u16 board_revision; /* abs.ofs: 106 */ | ||
242 | u8 reserved4[11]; | ||
243 | #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ | ||
244 | u8 board_pba_number[9]; /* abs.ofs: 119 */ | ||
245 | u8 reserved5[8]; | ||
246 | #define EEPROM_VERSION (2*0x44) /* 2 bytes */ | ||
247 | u16 version; /* abs.ofs: 136 */ | ||
248 | #define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */ | ||
249 | u8 sku_cap; /* abs.ofs: 138 */ | ||
250 | #define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */ | ||
251 | u8 leds_mode; /* abs.ofs: 139 */ | ||
252 | #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ | ||
253 | u16 oem_mode; | ||
254 | #define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ | ||
255 | u16 wowlan_mode; /* abs.ofs: 142 */ | ||
256 | #define EEPROM_LEDS_TIME_INTERVAL (2*0x48) /* 2 bytes */ | ||
257 | u16 leds_time_interval; /* abs.ofs: 144 */ | ||
258 | #define EEPROM_LEDS_OFF_TIME (2*0x49) /* 1 bytes */ | ||
259 | u8 leds_off_time; /* abs.ofs: 146 */ | ||
260 | #define EEPROM_LEDS_ON_TIME (2*0x49+1) /* 1 bytes */ | ||
261 | u8 leds_on_time; /* abs.ofs: 147 */ | ||
262 | #define EEPROM_ALMGOR_M_VERSION (2*0x4A) /* 1 bytes */ | ||
263 | u8 almgor_m_version; /* abs.ofs: 148 */ | ||
264 | #define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */ | ||
265 | u8 antenna_switch_type; /* abs.ofs: 149 */ | ||
266 | u8 reserved6[8]; | ||
267 | #define EEPROM_4965_BOARD_REVISION (2*0x4F) /* 2 bytes */ | ||
268 | u16 board_revision_4965; /* abs.ofs: 158 */ | ||
269 | u8 reserved7[13]; | ||
270 | #define EEPROM_4965_BOARD_PBA (2*0x56+1) /* 9 bytes */ | ||
271 | u8 board_pba_number_4965[9]; /* abs.ofs: 173 */ | ||
272 | u8 reserved8[10]; | ||
273 | #define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */ | ||
274 | u8 sku_id[4]; /* abs.ofs: 192 */ | ||
275 | |||
276 | /* | ||
277 | * Per-channel regulatory data. | ||
278 | * | ||
279 | * Each channel that *might* be supported by 3945 or 4965 has a fixed location | ||
280 | * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory | ||
281 | * txpower (MSB). | ||
282 | * | ||
283 | * Entries immediately below are for 20 MHz channel width. FAT (40 MHz) | ||
284 | * channels (only for 4965, not supported by 3945) appear later in the EEPROM. | ||
285 | * | ||
286 | * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 | ||
287 | */ | ||
288 | #define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */ | ||
289 | u16 band_1_count; /* abs.ofs: 196 */ | ||
290 | #define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */ | ||
291 | struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */ | ||
292 | |||
293 | /* | ||
294 | * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, | ||
295 | * 5.0 GHz channels 7, 8, 11, 12, 16 | ||
296 | * (4915-5080MHz) (none of these is ever supported) | ||
297 | */ | ||
298 | #define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */ | ||
299 | u16 band_2_count; /* abs.ofs: 226 */ | ||
300 | #define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */ | ||
301 | struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ | ||
302 | |||
303 | /* | ||
304 | * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 | ||
305 | * (5170-5320MHz) | ||
306 | */ | ||
307 | #define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */ | ||
308 | u16 band_3_count; /* abs.ofs: 254 */ | ||
309 | #define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */ | ||
310 | struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ | ||
311 | |||
312 | /* | ||
313 | * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 | ||
314 | * (5500-5700MHz) | ||
315 | */ | ||
316 | #define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */ | ||
317 | u16 band_4_count; /* abs.ofs: 280 */ | ||
318 | #define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */ | ||
319 | struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ | ||
320 | |||
321 | /* | ||
322 | * 5.7 GHz channels 145, 149, 153, 157, 161, 165 | ||
323 | * (5725-5825MHz) | ||
324 | */ | ||
325 | #define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */ | ||
326 | u16 band_5_count; /* abs.ofs: 304 */ | ||
327 | #define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ | ||
328 | struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ | ||
329 | |||
330 | u8 reserved10[2]; | ||
331 | |||
332 | |||
333 | /* | ||
334 | * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11) | ||
335 | * | ||
336 | * The channel listed is the center of the lower 20 MHz half of the channel. | ||
337 | * The overall center frequency is actually 2 channels (10 MHz) above that, | ||
338 | * and the upper half of each FAT channel is centered 4 channels (20 MHz) away | ||
339 | * from the lower half; e.g. the upper half of FAT channel 1 is channel 5, | ||
340 | * and the overall FAT channel width centers on channel 3. | ||
341 | * | ||
342 | * NOTE: The RXON command uses 20 MHz channel numbers to specify the | ||
343 | * control channel to which to tune. RXON also specifies whether the | ||
344 | * control channel is the upper or lower half of a FAT channel. | ||
345 | * | ||
346 | * NOTE: 4965 does not support FAT channels on 2.4 GHz. | ||
347 | */ | ||
348 | #define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0) /* 14 bytes */ | ||
349 | struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */ | ||
350 | u8 reserved11[2]; | ||
351 | |||
352 | /* | ||
353 | * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64), | ||
354 | * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161) | ||
355 | */ | ||
356 | #define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8) /* 22 bytes */ | ||
357 | struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */ | ||
358 | u8 reserved12[6]; | ||
359 | |||
360 | /* | ||
361 | * 4965 driver requires txpower calibration format version 5 or greater. | ||
362 | * Driver does not work with txpower calibration version < 5. | ||
363 | * This value is simply a 16-bit number, no major/minor versions here. | ||
364 | */ | ||
365 | #define EEPROM_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */ | ||
366 | u16 calib_version; /* abs.ofs: 364 */ | ||
367 | u8 reserved13[2]; | ||
368 | u8 reserved14[96]; /* abs.ofs: 368 */ | ||
369 | |||
370 | /* | ||
371 | * 4965 Txpower calibration data. | ||
372 | */ | ||
373 | #define EEPROM_IWL_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */ | ||
374 | struct iwl4965_eeprom_calib_info calib_info; /* abs.ofs: 464 */ | ||
375 | |||
376 | u8 reserved16[140]; /* fill out to full 1024 byte block */ | ||
377 | |||
378 | |||
379 | } __attribute__ ((packed)); | ||
380 | |||
381 | #define IWL_EEPROM_IMAGE_SIZE 1024 | ||
382 | |||
383 | /* End of EEPROM */ | ||
384 | |||
385 | struct iwl_eeprom_ops { | ||
386 | int (*verify_signature) (struct iwl4965_priv *priv); | ||
387 | int (*acquire_semaphore) (struct iwl4965_priv *priv); | ||
388 | void (*release_semaphore) (struct iwl4965_priv *priv); | ||
389 | }; | ||
390 | |||
391 | |||
392 | void iwl_eeprom_get_mac(const struct iwl4965_priv *priv, u8 *mac); | ||
393 | int iwl_eeprom_init(struct iwl4965_priv *priv); | ||
394 | |||
395 | int iwlcore_eeprom_verify_signature(struct iwl4965_priv *priv); | ||
396 | int iwlcore_eeprom_acquire_semaphore(struct iwl4965_priv *priv); | ||
397 | void iwlcore_eeprom_release_semaphore(struct iwl4965_priv *priv); | ||
398 | |||
399 | #endif /* __iwl_eeprom_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 8993cca81b40..736b88881b03 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h | |||
@@ -254,6 +254,26 @@ static inline u8 iwl_get_dma_hi_address(dma_addr_t addr) | |||
254 | return sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0; | 254 | return sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0; |
255 | } | 255 | } |
256 | 256 | ||
257 | /** | ||
258 | * iwl_queue_inc_wrap - increment queue index, wrap back to beginning | ||
259 | * @index -- current index | ||
260 | * @n_bd -- total number of entries in queue (must be power of 2) | ||
261 | */ | ||
262 | static inline int iwl_queue_inc_wrap(int index, int n_bd) | ||
263 | { | ||
264 | return ++index & (n_bd - 1); | ||
265 | } | ||
266 | |||
267 | /** | ||
268 | * iwl_queue_dec_wrap - decrement queue index, wrap back to end | ||
269 | * @index -- current index | ||
270 | * @n_bd -- total number of entries in queue (must be power of 2) | ||
271 | */ | ||
272 | static inline int iwl_queue_dec_wrap(int index, int n_bd) | ||
273 | { | ||
274 | return --index & (n_bd - 1); | ||
275 | } | ||
276 | |||
257 | /* TODO: Move fw_desc functions to iwl-pci.ko */ | 277 | /* TODO: Move fw_desc functions to iwl-pci.ko */ |
258 | static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, | 278 | static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, |
259 | struct fw_desc *desc) | 279 | struct fw_desc *desc) |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0fab832ce8c2..ecf749c2dc0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -46,6 +46,7 @@ | |||
46 | 46 | ||
47 | #include <asm/div64.h> | 47 | #include <asm/div64.h> |
48 | 48 | ||
49 | #include "iwl-3945-core.h" | ||
49 | #include "iwl-3945.h" | 50 | #include "iwl-3945.h" |
50 | #include "iwl-helpers.h" | 51 | #include "iwl-helpers.h" |
51 | 52 | ||
@@ -95,11 +96,6 @@ int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */ | |||
95 | #define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" | 96 | #define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" |
96 | #define DRV_VERSION IWLWIFI_VERSION | 97 | #define DRV_VERSION IWLWIFI_VERSION |
97 | 98 | ||
98 | /* Change firmware file name, using "-" and incrementing number, | ||
99 | * *only* when uCode interface or architecture changes so that it | ||
100 | * is not compatible with earlier drivers. | ||
101 | * This number will also appear in << 8 position of 1st dword of uCode file */ | ||
102 | #define IWL3945_UCODE_API "-1" | ||
103 | 99 | ||
104 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | 100 | MODULE_DESCRIPTION(DRV_DESCRIPTION); |
105 | MODULE_VERSION(DRV_VERSION); | 101 | MODULE_VERSION(DRV_VERSION); |
@@ -162,17 +158,6 @@ static const char *iwl3945_escape_essid(const char *essid, u8 essid_len) | |||
162 | return escaped; | 158 | return escaped; |
163 | } | 159 | } |
164 | 160 | ||
165 | static void iwl3945_print_hex_dump(int level, void *p, u32 len) | ||
166 | { | ||
167 | #ifdef CONFIG_IWL3945_DEBUG | ||
168 | if (!(iwl3945_debug_level & level)) | ||
169 | return; | ||
170 | |||
171 | print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, | ||
172 | p, len, 1); | ||
173 | #endif | ||
174 | } | ||
175 | |||
176 | /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** | 161 | /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** |
177 | * DMA services | 162 | * DMA services |
178 | * | 163 | * |
@@ -198,7 +183,7 @@ static void iwl3945_print_hex_dump(int level, void *p, u32 len) | |||
198 | * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused. | 183 | * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused. |
199 | ***************************************************/ | 184 | ***************************************************/ |
200 | 185 | ||
201 | static int iwl3945_queue_space(const struct iwl3945_queue *q) | 186 | int iwl3945_queue_space(const struct iwl3945_queue *q) |
202 | { | 187 | { |
203 | int s = q->read_ptr - q->write_ptr; | 188 | int s = q->read_ptr - q->write_ptr; |
204 | 189 | ||
@@ -214,33 +199,14 @@ static int iwl3945_queue_space(const struct iwl3945_queue *q) | |||
214 | return s; | 199 | return s; |
215 | } | 200 | } |
216 | 201 | ||
217 | /** | 202 | int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i) |
218 | * iwl3945_queue_inc_wrap - increment queue index, wrap back to beginning | ||
219 | * @index -- current index | ||
220 | * @n_bd -- total number of entries in queue (must be power of 2) | ||
221 | */ | ||
222 | static inline int iwl3945_queue_inc_wrap(int index, int n_bd) | ||
223 | { | ||
224 | return ++index & (n_bd - 1); | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * iwl3945_queue_dec_wrap - increment queue index, wrap back to end | ||
229 | * @index -- current index | ||
230 | * @n_bd -- total number of entries in queue (must be power of 2) | ||
231 | */ | ||
232 | static inline int iwl3945_queue_dec_wrap(int index, int n_bd) | ||
233 | { | ||
234 | return --index & (n_bd - 1); | ||
235 | } | ||
236 | |||
237 | static inline int x2_queue_used(const struct iwl3945_queue *q, int i) | ||
238 | { | 203 | { |
239 | return q->write_ptr > q->read_ptr ? | 204 | return q->write_ptr > q->read_ptr ? |
240 | (i >= q->read_ptr && i < q->write_ptr) : | 205 | (i >= q->read_ptr && i < q->write_ptr) : |
241 | !(i < q->read_ptr && i >= q->write_ptr); | 206 | !(i < q->read_ptr && i >= q->write_ptr); |
242 | } | 207 | } |
243 | 208 | ||
209 | |||
244 | static inline u8 get_cmd_index(struct iwl3945_queue *q, u32 index, int is_huge) | 210 | static inline u8 get_cmd_index(struct iwl3945_queue *q, u32 index, int is_huge) |
245 | { | 211 | { |
246 | /* This is for scan command, the big buffer at end of command array */ | 212 | /* This is for scan command, the big buffer at end of command array */ |
@@ -261,8 +227,8 @@ static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl3945_queue *q | |||
261 | q->n_window = slots_num; | 227 | q->n_window = slots_num; |
262 | q->id = id; | 228 | q->id = id; |
263 | 229 | ||
264 | /* count must be power-of-two size, otherwise iwl3945_queue_inc_wrap | 230 | /* count must be power-of-two size, otherwise iwl_queue_inc_wrap |
265 | * and iwl3945_queue_dec_wrap are broken. */ | 231 | * and iwl_queue_dec_wrap are broken. */ |
266 | BUG_ON(!is_power_of_2(count)); | 232 | BUG_ON(!is_power_of_2(count)); |
267 | 233 | ||
268 | /* slots_num must be power-of-two size, otherwise | 234 | /* slots_num must be power-of-two size, otherwise |
@@ -362,7 +328,7 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv, | |||
362 | txq->need_update = 0; | 328 | txq->need_update = 0; |
363 | 329 | ||
364 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise | 330 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise |
365 | * iwl3945_queue_inc_wrap and iwl3945_queue_dec_wrap are broken. */ | 331 | * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ |
366 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); | 332 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); |
367 | 333 | ||
368 | /* Initialize queue high/low-water, head/tail indexes */ | 334 | /* Initialize queue high/low-water, head/tail indexes */ |
@@ -393,7 +359,7 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t | |||
393 | 359 | ||
394 | /* first, empty all BD's */ | 360 | /* first, empty all BD's */ |
395 | for (; q->write_ptr != q->read_ptr; | 361 | for (; q->write_ptr != q->read_ptr; |
396 | q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd)) | 362 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) |
397 | iwl3945_hw_txq_free_tfd(priv, txq); | 363 | iwl3945_hw_txq_free_tfd(priv, txq); |
398 | 364 | ||
399 | len = sizeof(struct iwl3945_cmd) * q->n_window; | 365 | len = sizeof(struct iwl3945_cmd) * q->n_window; |
@@ -732,7 +698,7 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c | |||
732 | txq->need_update = 1; | 698 | txq->need_update = 1; |
733 | 699 | ||
734 | /* Increment and update queue's write index */ | 700 | /* Increment and update queue's write index */ |
735 | q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd); | 701 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
736 | ret = iwl3945_tx_queue_update_write_ptr(priv, txq); | 702 | ret = iwl3945_tx_queue_update_write_ptr(priv, txq); |
737 | 703 | ||
738 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); | 704 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); |
@@ -1630,151 +1596,6 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) | |||
1630 | return 0; | 1596 | return 0; |
1631 | } | 1597 | } |
1632 | 1598 | ||
1633 | /****************************************************************************** | ||
1634 | * | ||
1635 | * Misc. internal state and helper functions | ||
1636 | * | ||
1637 | ******************************************************************************/ | ||
1638 | #ifdef CONFIG_IWL3945_DEBUG | ||
1639 | |||
1640 | /** | ||
1641 | * iwl3945_report_frame - dump frame to syslog during debug sessions | ||
1642 | * | ||
1643 | * You may hack this function to show different aspects of received frames, | ||
1644 | * including selective frame dumps. | ||
1645 | * group100 parameter selects whether to show 1 out of 100 good frames. | ||
1646 | */ | ||
1647 | void iwl3945_report_frame(struct iwl3945_priv *priv, | ||
1648 | struct iwl3945_rx_packet *pkt, | ||
1649 | struct ieee80211_hdr *header, int group100) | ||
1650 | { | ||
1651 | u32 to_us; | ||
1652 | u32 print_summary = 0; | ||
1653 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
1654 | u32 hundred = 0; | ||
1655 | u32 dataframe = 0; | ||
1656 | u16 fc; | ||
1657 | u16 seq_ctl; | ||
1658 | u16 channel; | ||
1659 | u16 phy_flags; | ||
1660 | int rate_sym; | ||
1661 | u16 length; | ||
1662 | u16 status; | ||
1663 | u16 bcn_tmr; | ||
1664 | u32 tsf_low; | ||
1665 | u64 tsf; | ||
1666 | u8 rssi; | ||
1667 | u8 agc; | ||
1668 | u16 sig_avg; | ||
1669 | u16 noise_diff; | ||
1670 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | ||
1671 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | ||
1672 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | ||
1673 | u8 *data = IWL_RX_DATA(pkt); | ||
1674 | |||
1675 | /* MAC header */ | ||
1676 | fc = le16_to_cpu(header->frame_control); | ||
1677 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
1678 | |||
1679 | /* metadata */ | ||
1680 | channel = le16_to_cpu(rx_hdr->channel); | ||
1681 | phy_flags = le16_to_cpu(rx_hdr->phy_flags); | ||
1682 | rate_sym = rx_hdr->rate; | ||
1683 | length = le16_to_cpu(rx_hdr->len); | ||
1684 | |||
1685 | /* end-of-frame status and timestamp */ | ||
1686 | status = le32_to_cpu(rx_end->status); | ||
1687 | bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); | ||
1688 | tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; | ||
1689 | tsf = le64_to_cpu(rx_end->timestamp); | ||
1690 | |||
1691 | /* signal statistics */ | ||
1692 | rssi = rx_stats->rssi; | ||
1693 | agc = rx_stats->agc; | ||
1694 | sig_avg = le16_to_cpu(rx_stats->sig_avg); | ||
1695 | noise_diff = le16_to_cpu(rx_stats->noise_diff); | ||
1696 | |||
1697 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
1698 | |||
1699 | /* if data frame is to us and all is good, | ||
1700 | * (optionally) print summary for only 1 out of every 100 */ | ||
1701 | if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) == | ||
1702 | (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
1703 | dataframe = 1; | ||
1704 | if (!group100) | ||
1705 | print_summary = 1; /* print each frame */ | ||
1706 | else if (priv->framecnt_to_us < 100) { | ||
1707 | priv->framecnt_to_us++; | ||
1708 | print_summary = 0; | ||
1709 | } else { | ||
1710 | priv->framecnt_to_us = 0; | ||
1711 | print_summary = 1; | ||
1712 | hundred = 1; | ||
1713 | } | ||
1714 | } else { | ||
1715 | /* print summary for all other frames */ | ||
1716 | print_summary = 1; | ||
1717 | } | ||
1718 | |||
1719 | if (print_summary) { | ||
1720 | char *title; | ||
1721 | u32 rate; | ||
1722 | |||
1723 | if (hundred) | ||
1724 | title = "100Frames"; | ||
1725 | else if (fc & IEEE80211_FCTL_RETRY) | ||
1726 | title = "Retry"; | ||
1727 | else if (ieee80211_is_assoc_response(fc)) | ||
1728 | title = "AscRsp"; | ||
1729 | else if (ieee80211_is_reassoc_response(fc)) | ||
1730 | title = "RasRsp"; | ||
1731 | else if (ieee80211_is_probe_response(fc)) { | ||
1732 | title = "PrbRsp"; | ||
1733 | print_dump = 1; /* dump frame contents */ | ||
1734 | } else if (ieee80211_is_beacon(fc)) { | ||
1735 | title = "Beacon"; | ||
1736 | print_dump = 1; /* dump frame contents */ | ||
1737 | } else if (ieee80211_is_atim(fc)) | ||
1738 | title = "ATIM"; | ||
1739 | else if (ieee80211_is_auth(fc)) | ||
1740 | title = "Auth"; | ||
1741 | else if (ieee80211_is_deauth(fc)) | ||
1742 | title = "DeAuth"; | ||
1743 | else if (ieee80211_is_disassoc(fc)) | ||
1744 | title = "DisAssoc"; | ||
1745 | else | ||
1746 | title = "Frame"; | ||
1747 | |||
1748 | rate = iwl3945_rate_index_from_plcp(rate_sym); | ||
1749 | if (rate == -1) | ||
1750 | rate = 0; | ||
1751 | else | ||
1752 | rate = iwl3945_rates[rate].ieee / 2; | ||
1753 | |||
1754 | /* print frame summary. | ||
1755 | * MAC addresses show just the last byte (for brevity), | ||
1756 | * but you can hack it to show more, if you'd like to. */ | ||
1757 | if (dataframe) | ||
1758 | IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " | ||
1759 | "len=%u, rssi=%d, chnl=%d, rate=%u, \n", | ||
1760 | title, fc, header->addr1[5], | ||
1761 | length, rssi, channel, rate); | ||
1762 | else { | ||
1763 | /* src/dst addresses assume managed mode */ | ||
1764 | IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " | ||
1765 | "src=0x%02x, rssi=%u, tim=%lu usec, " | ||
1766 | "phy=0x%02x, chnl=%d\n", | ||
1767 | title, fc, header->addr1[5], | ||
1768 | header->addr3[5], rssi, | ||
1769 | tsf_low - priv->scan_start_tsf, | ||
1770 | phy_flags, channel); | ||
1771 | } | ||
1772 | } | ||
1773 | if (print_dump) | ||
1774 | iwl3945_print_hex_dump(IWL_DL_RX, data, length); | ||
1775 | } | ||
1776 | #endif | ||
1777 | |||
1778 | static void iwl3945_unset_hw_setting(struct iwl3945_priv *priv) | 1599 | static void iwl3945_unset_hw_setting(struct iwl3945_priv *priv) |
1779 | { | 1600 | { |
1780 | if (priv->hw_setting.shared_virt) | 1601 | if (priv->hw_setting.shared_virt) |
@@ -2242,34 +2063,6 @@ int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *h | |||
2242 | return 1; | 2063 | return 1; |
2243 | } | 2064 | } |
2244 | 2065 | ||
2245 | #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x | ||
2246 | |||
2247 | static const char *iwl3945_get_tx_fail_reason(u32 status) | ||
2248 | { | ||
2249 | switch (status & TX_STATUS_MSK) { | ||
2250 | case TX_STATUS_SUCCESS: | ||
2251 | return "SUCCESS"; | ||
2252 | TX_STATUS_ENTRY(SHORT_LIMIT); | ||
2253 | TX_STATUS_ENTRY(LONG_LIMIT); | ||
2254 | TX_STATUS_ENTRY(FIFO_UNDERRUN); | ||
2255 | TX_STATUS_ENTRY(MGMNT_ABORT); | ||
2256 | TX_STATUS_ENTRY(NEXT_FRAG); | ||
2257 | TX_STATUS_ENTRY(LIFE_EXPIRE); | ||
2258 | TX_STATUS_ENTRY(DEST_PS); | ||
2259 | TX_STATUS_ENTRY(ABORTED); | ||
2260 | TX_STATUS_ENTRY(BT_RETRY); | ||
2261 | TX_STATUS_ENTRY(STA_INVALID); | ||
2262 | TX_STATUS_ENTRY(FRAG_DROPPED); | ||
2263 | TX_STATUS_ENTRY(TID_DISABLE); | ||
2264 | TX_STATUS_ENTRY(FRAME_FLUSHED); | ||
2265 | TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); | ||
2266 | TX_STATUS_ENTRY(TX_LOCKED); | ||
2267 | TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); | ||
2268 | } | ||
2269 | |||
2270 | return "UNKNOWN"; | ||
2271 | } | ||
2272 | |||
2273 | /** | 2066 | /** |
2274 | * iwl3945_scan_cancel - Cancel any currently executing HW scan | 2067 | * iwl3945_scan_cancel - Cancel any currently executing HW scan |
2275 | * | 2068 | * |
@@ -2957,7 +2750,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, | |||
2957 | ieee80211_get_hdrlen(fc)); | 2750 | ieee80211_get_hdrlen(fc)); |
2958 | 2751 | ||
2959 | /* Tell device the write index *just past* this latest filled TFD */ | 2752 | /* Tell device the write index *just past* this latest filled TFD */ |
2960 | q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd); | 2753 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
2961 | rc = iwl3945_tx_queue_update_write_ptr(priv, txq); | 2754 | rc = iwl3945_tx_queue_update_write_ptr(priv, txq); |
2962 | spin_unlock_irqrestore(&priv->lock, flags); | 2755 | spin_unlock_irqrestore(&priv->lock, flags); |
2963 | 2756 | ||
@@ -3317,125 +3110,6 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv, | |||
3317 | } | 3110 | } |
3318 | #endif | 3111 | #endif |
3319 | 3112 | ||
3320 | static void iwl3945_txstatus_to_ieee(struct iwl3945_priv *priv, | ||
3321 | struct iwl3945_tx_info *tx_sta) | ||
3322 | { | ||
3323 | |||
3324 | tx_sta->status.ack_signal = 0; | ||
3325 | tx_sta->status.excessive_retries = 0; | ||
3326 | tx_sta->status.queue_length = 0; | ||
3327 | tx_sta->status.queue_number = 0; | ||
3328 | |||
3329 | if (in_interrupt()) | ||
3330 | ieee80211_tx_status_irqsafe(priv->hw, | ||
3331 | tx_sta->skb[0], &(tx_sta->status)); | ||
3332 | else | ||
3333 | ieee80211_tx_status(priv->hw, | ||
3334 | tx_sta->skb[0], &(tx_sta->status)); | ||
3335 | |||
3336 | tx_sta->skb[0] = NULL; | ||
3337 | } | ||
3338 | |||
3339 | /** | ||
3340 | * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd | ||
3341 | * | ||
3342 | * When FW advances 'R' index, all entries between old and new 'R' index | ||
3343 | * need to be reclaimed. As result, some free space forms. If there is | ||
3344 | * enough free space (> low mark), wake the stack that feeds us. | ||
3345 | */ | ||
3346 | static int iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index) | ||
3347 | { | ||
3348 | struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; | ||
3349 | struct iwl3945_queue *q = &txq->q; | ||
3350 | int nfreed = 0; | ||
3351 | |||
3352 | if ((index >= q->n_bd) || (x2_queue_used(q, index) == 0)) { | ||
3353 | IWL_ERROR("Read index for DMA queue txq id (%d), index %d, " | ||
3354 | "is out of range [0-%d] %d %d.\n", txq_id, | ||
3355 | index, q->n_bd, q->write_ptr, q->read_ptr); | ||
3356 | return 0; | ||
3357 | } | ||
3358 | |||
3359 | for (index = iwl3945_queue_inc_wrap(index, q->n_bd); | ||
3360 | q->read_ptr != index; | ||
3361 | q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
3362 | if (txq_id != IWL_CMD_QUEUE_NUM) { | ||
3363 | iwl3945_txstatus_to_ieee(priv, | ||
3364 | &(txq->txb[txq->q.read_ptr])); | ||
3365 | iwl3945_hw_txq_free_tfd(priv, txq); | ||
3366 | } else if (nfreed > 1) { | ||
3367 | IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index, | ||
3368 | q->write_ptr, q->read_ptr); | ||
3369 | queue_work(priv->workqueue, &priv->restart); | ||
3370 | } | ||
3371 | nfreed++; | ||
3372 | } | ||
3373 | |||
3374 | if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) && | ||
3375 | (txq_id != IWL_CMD_QUEUE_NUM) && | ||
3376 | priv->mac80211_registered) | ||
3377 | ieee80211_wake_queue(priv->hw, txq_id); | ||
3378 | |||
3379 | |||
3380 | return nfreed; | ||
3381 | } | ||
3382 | |||
3383 | static int iwl3945_is_tx_success(u32 status) | ||
3384 | { | ||
3385 | return (status & 0xFF) == 0x1; | ||
3386 | } | ||
3387 | |||
3388 | /****************************************************************************** | ||
3389 | * | ||
3390 | * Generic RX handler implementations | ||
3391 | * | ||
3392 | ******************************************************************************/ | ||
3393 | /** | ||
3394 | * iwl3945_rx_reply_tx - Handle Tx response | ||
3395 | */ | ||
3396 | static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, | ||
3397 | struct iwl3945_rx_mem_buffer *rxb) | ||
3398 | { | ||
3399 | struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; | ||
3400 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
3401 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
3402 | int index = SEQ_TO_INDEX(sequence); | ||
3403 | struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; | ||
3404 | struct ieee80211_tx_status *tx_status; | ||
3405 | struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | ||
3406 | u32 status = le32_to_cpu(tx_resp->status); | ||
3407 | |||
3408 | if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) { | ||
3409 | IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " | ||
3410 | "is out of range [0-%d] %d %d\n", txq_id, | ||
3411 | index, txq->q.n_bd, txq->q.write_ptr, | ||
3412 | txq->q.read_ptr); | ||
3413 | return; | ||
3414 | } | ||
3415 | |||
3416 | tx_status = &(txq->txb[txq->q.read_ptr].status); | ||
3417 | |||
3418 | tx_status->retry_count = tx_resp->failure_frame; | ||
3419 | tx_status->queue_number = status; | ||
3420 | tx_status->queue_length = tx_resp->bt_kill_count; | ||
3421 | tx_status->queue_length |= tx_resp->failure_rts; | ||
3422 | |||
3423 | tx_status->flags = | ||
3424 | iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0; | ||
3425 | |||
3426 | IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", | ||
3427 | txq_id, iwl3945_get_tx_fail_reason(status), status, | ||
3428 | tx_resp->rate, tx_resp->failure_frame); | ||
3429 | |||
3430 | IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); | ||
3431 | if (index != -1) | ||
3432 | iwl3945_tx_queue_reclaim(priv, txq_id, index); | ||
3433 | |||
3434 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | ||
3435 | IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); | ||
3436 | } | ||
3437 | |||
3438 | |||
3439 | static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv, | 3113 | static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv, |
3440 | struct iwl3945_rx_mem_buffer *rxb) | 3114 | struct iwl3945_rx_mem_buffer *rxb) |
3441 | { | 3115 | { |
@@ -3782,13 +3456,44 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv) | |||
3782 | priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] = | 3456 | priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] = |
3783 | iwl3945_rx_scan_complete_notif; | 3457 | iwl3945_rx_scan_complete_notif; |
3784 | priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; | 3458 | priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; |
3785 | priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx; | ||
3786 | 3459 | ||
3787 | /* Set up hardware specific Rx handlers */ | 3460 | /* Set up hardware specific Rx handlers */ |
3788 | iwl3945_hw_rx_handler_setup(priv); | 3461 | iwl3945_hw_rx_handler_setup(priv); |
3789 | } | 3462 | } |
3790 | 3463 | ||
3791 | /** | 3464 | /** |
3465 | * iwl3945_cmd_queue_reclaim - Reclaim CMD queue entries | ||
3466 | * When FW advances 'R' index, all entries between old and new 'R' index | ||
3467 | * need to be reclaimed. | ||
3468 | */ | ||
3469 | static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv, | ||
3470 | int txq_id, int index) | ||
3471 | { | ||
3472 | struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; | ||
3473 | struct iwl3945_queue *q = &txq->q; | ||
3474 | int nfreed = 0; | ||
3475 | |||
3476 | if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) { | ||
3477 | IWL_ERROR("Read index for DMA queue txq id (%d), index %d, " | ||
3478 | "is out of range [0-%d] %d %d.\n", txq_id, | ||
3479 | index, q->n_bd, q->write_ptr, q->read_ptr); | ||
3480 | return; | ||
3481 | } | ||
3482 | |||
3483 | for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; | ||
3484 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
3485 | if (nfreed > 1) { | ||
3486 | IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index, | ||
3487 | q->write_ptr, q->read_ptr); | ||
3488 | queue_work(priv->workqueue, &priv->restart); | ||
3489 | break; | ||
3490 | } | ||
3491 | nfreed++; | ||
3492 | } | ||
3493 | } | ||
3494 | |||
3495 | |||
3496 | /** | ||
3792 | * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them | 3497 | * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them |
3793 | * @rxb: Rx buffer to reclaim | 3498 | * @rxb: Rx buffer to reclaim |
3794 | * | 3499 | * |
@@ -3807,12 +3512,6 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, | |||
3807 | int cmd_index; | 3512 | int cmd_index; |
3808 | struct iwl3945_cmd *cmd; | 3513 | struct iwl3945_cmd *cmd; |
3809 | 3514 | ||
3810 | /* If a Tx command is being handled and it isn't in the actual | ||
3811 | * command queue then there a command routing bug has been introduced | ||
3812 | * in the queue management code. */ | ||
3813 | if (txq_id != IWL_CMD_QUEUE_NUM) | ||
3814 | IWL_ERROR("Error wrong command queue %d command id 0x%X\n", | ||
3815 | txq_id, pkt->hdr.cmd); | ||
3816 | BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); | 3515 | BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); |
3817 | 3516 | ||
3818 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); | 3517 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); |
@@ -3826,7 +3525,7 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, | |||
3826 | !cmd->meta.u.callback(priv, cmd, rxb->skb)) | 3525 | !cmd->meta.u.callback(priv, cmd, rxb->skb)) |
3827 | rxb->skb = NULL; | 3526 | rxb->skb = NULL; |
3828 | 3527 | ||
3829 | iwl3945_tx_queue_reclaim(priv, txq_id, index); | 3528 | iwl3945_cmd_queue_reclaim(priv, txq_id, index); |
3830 | 3529 | ||
3831 | if (!(cmd->meta.flags & CMD_ASYNC)) { | 3530 | if (!(cmd->meta.flags & CMD_ASYNC)) { |
3832 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 3531 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
@@ -4506,8 +4205,7 @@ static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv) | |||
4506 | 4205 | ||
4507 | if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { | 4206 | if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { |
4508 | IWL_ERROR("Start IWL Error Log Dump:\n"); | 4207 | IWL_ERROR("Start IWL Error Log Dump:\n"); |
4509 | IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n", | 4208 | IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count); |
4510 | priv->status, priv->config, count); | ||
4511 | } | 4209 | } |
4512 | 4210 | ||
4513 | IWL_ERROR("Desc Time asrtPC blink2 " | 4211 | IWL_ERROR("Desc Time asrtPC blink2 " |
@@ -4727,9 +4425,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) | |||
4727 | * atomic, make sure that inta covers all the interrupts that | 4425 | * atomic, make sure that inta covers all the interrupts that |
4728 | * we've discovered, even if FH interrupt came in just after | 4426 | * we've discovered, even if FH interrupt came in just after |
4729 | * reading CSR_INT. */ | 4427 | * reading CSR_INT. */ |
4730 | if (inta_fh & CSR_FH_INT_RX_MASK) | 4428 | if (inta_fh & CSR39_FH_INT_RX_MASK) |
4731 | inta |= CSR_INT_BIT_FH_RX; | 4429 | inta |= CSR_INT_BIT_FH_RX; |
4732 | if (inta_fh & CSR_FH_INT_TX_MASK) | 4430 | if (inta_fh & CSR39_FH_INT_TX_MASK) |
4733 | inta |= CSR_INT_BIT_FH_TX; | 4431 | inta |= CSR_INT_BIT_FH_TX; |
4734 | 4432 | ||
4735 | /* Now service all interrupt bits discovered above. */ | 4433 | /* Now service all interrupt bits discovered above. */ |
@@ -5119,11 +4817,12 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) | |||
5119 | ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; | 4817 | ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; |
5120 | ch_info->min_power = 0; | 4818 | ch_info->min_power = 0; |
5121 | 4819 | ||
5122 | IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x" | 4820 | IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x" |
5123 | " %ddBm): Ad-Hoc %ssupported\n", | 4821 | " %ddBm): Ad-Hoc %ssupported\n", |
5124 | ch_info->channel, | 4822 | ch_info->channel, |
5125 | is_channel_a_band(ch_info) ? | 4823 | is_channel_a_band(ch_info) ? |
5126 | "5.2" : "2.4", | 4824 | "5.2" : "2.4", |
4825 | CHECK_AND_PRINT(VALID), | ||
5127 | CHECK_AND_PRINT(IBSS), | 4826 | CHECK_AND_PRINT(IBSS), |
5128 | CHECK_AND_PRINT(ACTIVE), | 4827 | CHECK_AND_PRINT(ACTIVE), |
5129 | CHECK_AND_PRINT(RADAR), | 4828 | CHECK_AND_PRINT(RADAR), |
@@ -5333,7 +5032,7 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv, | |||
5333 | static int iwl3945_init_geos(struct iwl3945_priv *priv) | 5032 | static int iwl3945_init_geos(struct iwl3945_priv *priv) |
5334 | { | 5033 | { |
5335 | struct iwl3945_channel_info *ch; | 5034 | struct iwl3945_channel_info *ch; |
5336 | struct ieee80211_supported_band *band; | 5035 | struct ieee80211_supported_band *sband; |
5337 | struct ieee80211_channel *channels; | 5036 | struct ieee80211_channel *channels; |
5338 | struct ieee80211_channel *geo_ch; | 5037 | struct ieee80211_channel *geo_ch; |
5339 | struct ieee80211_rate *rates; | 5038 | struct ieee80211_rate *rates; |
@@ -5351,7 +5050,7 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) | |||
5351 | if (!channels) | 5050 | if (!channels) |
5352 | return -ENOMEM; | 5051 | return -ENOMEM; |
5353 | 5052 | ||
5354 | rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)), | 5053 | rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)), |
5355 | GFP_KERNEL); | 5054 | GFP_KERNEL); |
5356 | if (!rates) { | 5055 | if (!rates) { |
5357 | kfree(channels); | 5056 | kfree(channels); |
@@ -5359,38 +5058,38 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) | |||
5359 | } | 5058 | } |
5360 | 5059 | ||
5361 | /* 5.2GHz channels start after the 2.4GHz channels */ | 5060 | /* 5.2GHz channels start after the 2.4GHz channels */ |
5362 | band = &priv->bands[IEEE80211_BAND_5GHZ]; | 5061 | sband = &priv->bands[IEEE80211_BAND_5GHZ]; |
5363 | band->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)]; | 5062 | sband->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)]; |
5364 | band->bitrates = &rates[4]; | 5063 | /* just OFDM */ |
5365 | band->n_bitrates = 8; /* just OFDM */ | 5064 | sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; |
5366 | 5065 | sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; | |
5367 | band = &priv->bands[IEEE80211_BAND_2GHZ]; | 5066 | |
5368 | band->channels = channels; | 5067 | sband = &priv->bands[IEEE80211_BAND_2GHZ]; |
5369 | band->bitrates = rates; | 5068 | sband->channels = channels; |
5370 | band->n_bitrates = 12; /* OFDM & CCK */ | 5069 | /* OFDM & CCK */ |
5070 | sband->bitrates = rates; | ||
5071 | sband->n_bitrates = IWL_RATE_COUNT; | ||
5371 | 5072 | ||
5372 | priv->ieee_channels = channels; | 5073 | priv->ieee_channels = channels; |
5373 | priv->ieee_rates = rates; | 5074 | priv->ieee_rates = rates; |
5374 | 5075 | ||
5375 | iwl3945_init_hw_rates(priv, rates); | 5076 | iwl3945_init_hw_rates(priv, rates); |
5376 | 5077 | ||
5377 | for (i = 0, geo_ch = channels; i < priv->channel_count; i++) { | 5078 | for (i = 0; i < priv->channel_count; i++) { |
5378 | ch = &priv->channel_info[i]; | 5079 | ch = &priv->channel_info[i]; |
5379 | 5080 | ||
5380 | if (!is_channel_valid(ch)) { | 5081 | /* FIXME: might be removed if scan is OK*/ |
5381 | IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- " | 5082 | if (!is_channel_valid(ch)) |
5382 | "skipping.\n", | ||
5383 | ch->channel, is_channel_a_band(ch) ? | ||
5384 | "5.2" : "2.4"); | ||
5385 | continue; | 5083 | continue; |
5386 | } | ||
5387 | 5084 | ||
5388 | if (is_channel_a_band(ch)) | 5085 | if (is_channel_a_band(ch)) |
5389 | geo_ch = &priv->bands[IEEE80211_BAND_5GHZ].channels[priv->bands[IEEE80211_BAND_5GHZ].n_channels++]; | 5086 | sband = &priv->bands[IEEE80211_BAND_5GHZ]; |
5390 | else | 5087 | else |
5391 | geo_ch = &priv->bands[IEEE80211_BAND_2GHZ].channels[priv->bands[IEEE80211_BAND_2GHZ].n_channels++]; | 5088 | sband = &priv->bands[IEEE80211_BAND_2GHZ]; |
5392 | 5089 | ||
5393 | geo_ch->center_freq = ieee80211chan2mhz(ch->channel); | 5090 | geo_ch = &sband->channels[sband->n_channels++]; |
5091 | |||
5092 | geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel); | ||
5394 | geo_ch->max_power = ch->max_power_avg; | 5093 | geo_ch->max_power = ch->max_power_avg; |
5395 | geo_ch->max_antenna_gain = 0xff; | 5094 | geo_ch->max_antenna_gain = 0xff; |
5396 | geo_ch->hw_value = ch->channel; | 5095 | geo_ch->hw_value = ch->channel; |
@@ -5408,16 +5107,28 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) | |||
5408 | if (ch->max_power_avg > priv->max_channel_txpower_limit) | 5107 | if (ch->max_power_avg > priv->max_channel_txpower_limit) |
5409 | priv->max_channel_txpower_limit = | 5108 | priv->max_channel_txpower_limit = |
5410 | ch->max_power_avg; | 5109 | ch->max_power_avg; |
5411 | } else | 5110 | } else { |
5412 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; | 5111 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; |
5112 | } | ||
5113 | |||
5114 | /* Save flags for reg domain usage */ | ||
5115 | geo_ch->orig_flags = geo_ch->flags; | ||
5116 | |||
5117 | IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n", | ||
5118 | ch->channel, geo_ch->center_freq, | ||
5119 | is_channel_a_band(ch) ? "5.2" : "2.4", | ||
5120 | geo_ch->flags & IEEE80211_CHAN_DISABLED ? | ||
5121 | "restricted" : "valid", | ||
5122 | geo_ch->flags); | ||
5413 | } | 5123 | } |
5414 | 5124 | ||
5415 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) { | 5125 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && |
5126 | priv->cfg->sku & IWL_SKU_A) { | ||
5416 | printk(KERN_INFO DRV_NAME | 5127 | printk(KERN_INFO DRV_NAME |
5417 | ": Incorrectly detected BG card as ABG. Please send " | 5128 | ": Incorrectly detected BG card as ABG. Please send " |
5418 | "your PCI ID 0x%04X:0x%04X to maintainer.\n", | 5129 | "your PCI ID 0x%04X:0x%04X to maintainer.\n", |
5419 | priv->pci_dev->device, priv->pci_dev->subsystem_device); | 5130 | priv->pci_dev->device, priv->pci_dev->subsystem_device); |
5420 | priv->is_abg = 0; | 5131 | priv->cfg->sku &= ~IWL_SKU_A; |
5421 | } | 5132 | } |
5422 | 5133 | ||
5423 | printk(KERN_INFO DRV_NAME | 5134 | printk(KERN_INFO DRV_NAME |
@@ -5764,7 +5475,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv) | |||
5764 | int ret = 0; | 5475 | int ret = 0; |
5765 | const struct firmware *ucode_raw; | 5476 | const struct firmware *ucode_raw; |
5766 | /* firmware file name contains uCode/driver compatibility version */ | 5477 | /* firmware file name contains uCode/driver compatibility version */ |
5767 | const char *name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode"; | 5478 | const char *name = priv->cfg->fw_name; |
5768 | u8 *src; | 5479 | u8 *src; |
5769 | size_t len; | 5480 | size_t len; |
5770 | u32 ver, inst_size, data_size, init_size, init_data_size, boot_size; | 5481 | u32 ver, inst_size, data_size, init_size, init_data_size, boot_size; |
@@ -7152,6 +6863,12 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, | |||
7152 | if (conf == NULL) | 6863 | if (conf == NULL) |
7153 | return -EIO; | 6864 | return -EIO; |
7154 | 6865 | ||
6866 | if (priv->vif != vif) { | ||
6867 | IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); | ||
6868 | mutex_unlock(&priv->mutex); | ||
6869 | return 0; | ||
6870 | } | ||
6871 | |||
7155 | /* XXX: this MUST use conf->mac_addr */ | 6872 | /* XXX: this MUST use conf->mac_addr */ |
7156 | 6873 | ||
7157 | if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && | 6874 | if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && |
@@ -7176,17 +6893,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, | |||
7176 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && | 6893 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && |
7177 | !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { | 6894 | !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { |
7178 | */ | 6895 | */ |
7179 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { | ||
7180 | IWL_DEBUG_MAC80211("leave - scanning\n"); | ||
7181 | mutex_unlock(&priv->mutex); | ||
7182 | return 0; | ||
7183 | } | ||
7184 | |||
7185 | if (priv->vif != vif) { | ||
7186 | IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); | ||
7187 | mutex_unlock(&priv->mutex); | ||
7188 | return 0; | ||
7189 | } | ||
7190 | 6896 | ||
7191 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { | 6897 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { |
7192 | if (!conf->bssid) { | 6898 | if (!conf->bssid) { |
@@ -7884,31 +7590,6 @@ static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, | |||
7884 | show_measurement, store_measurement); | 7590 | show_measurement, store_measurement); |
7885 | #endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */ | 7591 | #endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */ |
7886 | 7592 | ||
7887 | static ssize_t show_rate(struct device *d, | ||
7888 | struct device_attribute *attr, char *buf) | ||
7889 | { | ||
7890 | struct iwl3945_priv *priv = dev_get_drvdata(d); | ||
7891 | unsigned long flags; | ||
7892 | int i; | ||
7893 | |||
7894 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
7895 | if (priv->iw_mode == IEEE80211_IF_TYPE_STA) | ||
7896 | i = priv->stations[IWL_AP_ID].current_rate.s.rate; | ||
7897 | else | ||
7898 | i = priv->stations[IWL_STA_ID].current_rate.s.rate; | ||
7899 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
7900 | |||
7901 | i = iwl3945_rate_index_from_plcp(i); | ||
7902 | if (i == -1) | ||
7903 | return sprintf(buf, "0\n"); | ||
7904 | |||
7905 | return sprintf(buf, "%d%s\n", | ||
7906 | (iwl3945_rates[i].ieee >> 1), | ||
7907 | (iwl3945_rates[i].ieee & 0x1) ? ".5" : ""); | ||
7908 | } | ||
7909 | |||
7910 | static DEVICE_ATTR(rate, S_IRUSR, show_rate, NULL); | ||
7911 | |||
7912 | static ssize_t store_retry_rate(struct device *d, | 7593 | static ssize_t store_retry_rate(struct device *d, |
7913 | struct device_attribute *attr, | 7594 | struct device_attribute *attr, |
7914 | const char *buf, size_t count) | 7595 | const char *buf, size_t count) |
@@ -8199,7 +7880,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { | |||
8199 | &dev_attr_measurement.attr, | 7880 | &dev_attr_measurement.attr, |
8200 | #endif | 7881 | #endif |
8201 | &dev_attr_power_level.attr, | 7882 | &dev_attr_power_level.attr, |
8202 | &dev_attr_rate.attr, | ||
8203 | &dev_attr_retry_rate.attr, | 7883 | &dev_attr_retry_rate.attr, |
8204 | &dev_attr_rf_kill.attr, | 7884 | &dev_attr_rf_kill.attr, |
8205 | &dev_attr_rs_window.attr, | 7885 | &dev_attr_rs_window.attr, |
@@ -8238,9 +7918,9 @@ static struct ieee80211_ops iwl3945_hw_ops = { | |||
8238 | static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 7918 | static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
8239 | { | 7919 | { |
8240 | int err = 0; | 7920 | int err = 0; |
8241 | u32 pci_id; | ||
8242 | struct iwl3945_priv *priv; | 7921 | struct iwl3945_priv *priv; |
8243 | struct ieee80211_hw *hw; | 7922 | struct ieee80211_hw *hw; |
7923 | struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data); | ||
8244 | int i; | 7924 | int i; |
8245 | DECLARE_MAC_BUF(mac); | 7925 | DECLARE_MAC_BUF(mac); |
8246 | 7926 | ||
@@ -8276,6 +7956,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8276 | priv->hw = hw; | 7956 | priv->hw = hw; |
8277 | 7957 | ||
8278 | priv->pci_dev = pdev; | 7958 | priv->pci_dev = pdev; |
7959 | priv->cfg = cfg; | ||
8279 | 7960 | ||
8280 | /* Select antenna (may be helpful if only one antenna is connected) */ | 7961 | /* Select antenna (may be helpful if only one antenna is connected) */ |
8281 | priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna; | 7962 | priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna; |
@@ -8365,32 +8046,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8365 | 8046 | ||
8366 | priv->iw_mode = IEEE80211_IF_TYPE_STA; | 8047 | priv->iw_mode = IEEE80211_IF_TYPE_STA; |
8367 | 8048 | ||
8368 | pci_id = | ||
8369 | (priv->pci_dev->device << 16) | priv->pci_dev->subsystem_device; | ||
8370 | |||
8371 | switch (pci_id) { | ||
8372 | case 0x42221005: /* 0x4222 0x8086 0x1005 is BG SKU */ | ||
8373 | case 0x42221034: /* 0x4222 0x8086 0x1034 is BG SKU */ | ||
8374 | case 0x42271014: /* 0x4227 0x8086 0x1014 is BG SKU */ | ||
8375 | case 0x42221044: /* 0x4222 0x8086 0x1044 is BG SKU */ | ||
8376 | priv->is_abg = 0; | ||
8377 | break; | ||
8378 | |||
8379 | /* | ||
8380 | * Rest are assumed ABG SKU -- if this is not the | ||
8381 | * case then the card will get the wrong 'Detected' | ||
8382 | * line in the kernel log however the code that | ||
8383 | * initializes the GEO table will detect no A-band | ||
8384 | * channels and remove the is_abg mask. | ||
8385 | */ | ||
8386 | default: | ||
8387 | priv->is_abg = 1; | ||
8388 | break; | ||
8389 | } | ||
8390 | |||
8391 | printk(KERN_INFO DRV_NAME | 8049 | printk(KERN_INFO DRV_NAME |
8392 | ": Detected Intel PRO/Wireless 3945%sBG Network Connection\n", | 8050 | ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); |
8393 | priv->is_abg ? "A" : ""); | ||
8394 | 8051 | ||
8395 | /* Device-specific setup */ | 8052 | /* Device-specific setup */ |
8396 | if (iwl3945_hw_set_hw_setting(priv)) { | 8053 | if (iwl3945_hw_set_hw_setting(priv)) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 20d012d4f37e..28c64c39ef02 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -45,13 +45,10 @@ | |||
45 | 45 | ||
46 | #include <asm/div64.h> | 46 | #include <asm/div64.h> |
47 | 47 | ||
48 | #include "iwl-core.h" | ||
48 | #include "iwl-4965.h" | 49 | #include "iwl-4965.h" |
49 | #include "iwl-helpers.h" | 50 | #include "iwl-helpers.h" |
50 | 51 | ||
51 | #ifdef CONFIG_IWL4965_DEBUG | ||
52 | u32 iwl4965_debug_level; | ||
53 | #endif | ||
54 | |||
55 | static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv, | 52 | static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv, |
56 | struct iwl4965_tx_queue *txq); | 53 | struct iwl4965_tx_queue *txq); |
57 | 54 | ||
@@ -90,15 +87,8 @@ int iwl4965_param_amsdu_size_8K; /* def: enable 8K amsdu size */ | |||
90 | #define VS | 87 | #define VS |
91 | #endif | 88 | #endif |
92 | 89 | ||
93 | #define IWLWIFI_VERSION "1.2.26k" VD VS | 90 | #define DRV_VERSION IWLWIFI_VERSION VD VS |
94 | #define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" | ||
95 | #define DRV_VERSION IWLWIFI_VERSION | ||
96 | 91 | ||
97 | /* Change firmware file name, using "-" and incrementing number, | ||
98 | * *only* when uCode interface or architecture changes so that it | ||
99 | * is not compatible with earlier drivers. | ||
100 | * This number will also appear in << 8 position of 1st dword of uCode file */ | ||
101 | #define IWL4965_UCODE_API "-1" | ||
102 | 92 | ||
103 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | 93 | MODULE_DESCRIPTION(DRV_DESCRIPTION); |
104 | MODULE_VERSION(DRV_VERSION); | 94 | MODULE_VERSION(DRV_VERSION); |
@@ -161,17 +151,6 @@ static const char *iwl4965_escape_essid(const char *essid, u8 essid_len) | |||
161 | return escaped; | 151 | return escaped; |
162 | } | 152 | } |
163 | 153 | ||
164 | static void iwl4965_print_hex_dump(int level, void *p, u32 len) | ||
165 | { | ||
166 | #ifdef CONFIG_IWL4965_DEBUG | ||
167 | if (!(iwl4965_debug_level & level)) | ||
168 | return; | ||
169 | |||
170 | print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, | ||
171 | p, len, 1); | ||
172 | #endif | ||
173 | } | ||
174 | |||
175 | /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** | 154 | /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** |
176 | * DMA services | 155 | * DMA services |
177 | * | 156 | * |
@@ -215,25 +194,6 @@ int iwl4965_queue_space(const struct iwl4965_queue *q) | |||
215 | return s; | 194 | return s; |
216 | } | 195 | } |
217 | 196 | ||
218 | /** | ||
219 | * iwl4965_queue_inc_wrap - increment queue index, wrap back to beginning | ||
220 | * @index -- current index | ||
221 | * @n_bd -- total number of entries in queue (must be power of 2) | ||
222 | */ | ||
223 | static inline int iwl4965_queue_inc_wrap(int index, int n_bd) | ||
224 | { | ||
225 | return ++index & (n_bd - 1); | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * iwl4965_queue_dec_wrap - decrement queue index, wrap back to end | ||
230 | * @index -- current index | ||
231 | * @n_bd -- total number of entries in queue (must be power of 2) | ||
232 | */ | ||
233 | static inline int iwl4965_queue_dec_wrap(int index, int n_bd) | ||
234 | { | ||
235 | return --index & (n_bd - 1); | ||
236 | } | ||
237 | 197 | ||
238 | static inline int x2_queue_used(const struct iwl4965_queue *q, int i) | 198 | static inline int x2_queue_used(const struct iwl4965_queue *q, int i) |
239 | { | 199 | { |
@@ -262,8 +222,8 @@ static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q | |||
262 | q->n_window = slots_num; | 222 | q->n_window = slots_num; |
263 | q->id = id; | 223 | q->id = id; |
264 | 224 | ||
265 | /* count must be power-of-two size, otherwise iwl4965_queue_inc_wrap | 225 | /* count must be power-of-two size, otherwise iwl_queue_inc_wrap |
266 | * and iwl4965_queue_dec_wrap are broken. */ | 226 | * and iwl_queue_dec_wrap are broken. */ |
267 | BUG_ON(!is_power_of_2(count)); | 227 | BUG_ON(!is_power_of_2(count)); |
268 | 228 | ||
269 | /* slots_num must be power-of-two size, otherwise | 229 | /* slots_num must be power-of-two size, otherwise |
@@ -363,7 +323,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv, | |||
363 | txq->need_update = 0; | 323 | txq->need_update = 0; |
364 | 324 | ||
365 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise | 325 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise |
366 | * iwl4965_queue_inc_wrap and iwl4965_queue_dec_wrap are broken. */ | 326 | * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ |
367 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); | 327 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); |
368 | 328 | ||
369 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | 329 | /* Initialize queue's high/low-water marks, and head/tail indexes */ |
@@ -394,7 +354,7 @@ void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *t | |||
394 | 354 | ||
395 | /* first, empty all BD's */ | 355 | /* first, empty all BD's */ |
396 | for (; q->write_ptr != q->read_ptr; | 356 | for (; q->write_ptr != q->read_ptr; |
397 | q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd)) | 357 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) |
398 | iwl4965_hw_txq_free_tfd(priv, txq); | 358 | iwl4965_hw_txq_free_tfd(priv, txq); |
399 | 359 | ||
400 | len = sizeof(struct iwl4965_cmd) * q->n_window; | 360 | len = sizeof(struct iwl4965_cmd) * q->n_window; |
@@ -735,7 +695,7 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c | |||
735 | ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0); | 695 | ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0); |
736 | 696 | ||
737 | /* Increment and update queue's write index */ | 697 | /* Increment and update queue's write index */ |
738 | q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd); | 698 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
739 | iwl4965_tx_queue_update_write_ptr(priv, txq); | 699 | iwl4965_tx_queue_update_write_ptr(priv, txq); |
740 | 700 | ||
741 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); | 701 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); |
@@ -1551,34 +1511,6 @@ unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv, | |||
1551 | return priv->ibss_beacon->len; | 1511 | return priv->ibss_beacon->len; |
1552 | } | 1512 | } |
1553 | 1513 | ||
1554 | int iwl4965_rate_index_from_plcp(int plcp) | ||
1555 | { | ||
1556 | int i = 0; | ||
1557 | |||
1558 | /* 4965 HT rate format */ | ||
1559 | if (plcp & RATE_MCS_HT_MSK) { | ||
1560 | i = (plcp & 0xff); | ||
1561 | |||
1562 | if (i >= IWL_RATE_MIMO_6M_PLCP) | ||
1563 | i = i - IWL_RATE_MIMO_6M_PLCP; | ||
1564 | |||
1565 | i += IWL_FIRST_OFDM_RATE; | ||
1566 | /* skip 9M not supported in ht*/ | ||
1567 | if (i >= IWL_RATE_9M_INDEX) | ||
1568 | i += 1; | ||
1569 | if ((i >= IWL_FIRST_OFDM_RATE) && | ||
1570 | (i <= IWL_LAST_OFDM_RATE)) | ||
1571 | return i; | ||
1572 | |||
1573 | /* 4965 legacy rate format, search for match in table */ | ||
1574 | } else { | ||
1575 | for (i = 0; i < ARRAY_SIZE(iwl4965_rates); i++) | ||
1576 | if (iwl4965_rates[i].plcp == (plcp &0xFF)) | ||
1577 | return i; | ||
1578 | } | ||
1579 | return -1; | ||
1580 | } | ||
1581 | |||
1582 | static u8 iwl4965_rate_get_lowest_plcp(int rate_mask) | 1514 | static u8 iwl4965_rate_get_lowest_plcp(int rate_mask) |
1583 | { | 1515 | { |
1584 | u8 i; | 1516 | u8 i; |
@@ -1712,148 +1644,6 @@ done: | |||
1712 | * Misc. internal state and helper functions | 1644 | * Misc. internal state and helper functions |
1713 | * | 1645 | * |
1714 | ******************************************************************************/ | 1646 | ******************************************************************************/ |
1715 | #ifdef CONFIG_IWL4965_DEBUG | ||
1716 | |||
1717 | /** | ||
1718 | * iwl4965_report_frame - dump frame to syslog during debug sessions | ||
1719 | * | ||
1720 | * You may hack this function to show different aspects of received frames, | ||
1721 | * including selective frame dumps. | ||
1722 | * group100 parameter selects whether to show 1 out of 100 good frames. | ||
1723 | * | ||
1724 | * TODO: This was originally written for 3945, need to audit for | ||
1725 | * proper operation with 4965. | ||
1726 | */ | ||
1727 | void iwl4965_report_frame(struct iwl4965_priv *priv, | ||
1728 | struct iwl4965_rx_packet *pkt, | ||
1729 | struct ieee80211_hdr *header, int group100) | ||
1730 | { | ||
1731 | u32 to_us; | ||
1732 | u32 print_summary = 0; | ||
1733 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
1734 | u32 hundred = 0; | ||
1735 | u32 dataframe = 0; | ||
1736 | u16 fc; | ||
1737 | u16 seq_ctl; | ||
1738 | u16 channel; | ||
1739 | u16 phy_flags; | ||
1740 | int rate_sym; | ||
1741 | u16 length; | ||
1742 | u16 status; | ||
1743 | u16 bcn_tmr; | ||
1744 | u32 tsf_low; | ||
1745 | u64 tsf; | ||
1746 | u8 rssi; | ||
1747 | u8 agc; | ||
1748 | u16 sig_avg; | ||
1749 | u16 noise_diff; | ||
1750 | struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | ||
1751 | struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | ||
1752 | struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt); | ||
1753 | u8 *data = IWL_RX_DATA(pkt); | ||
1754 | |||
1755 | /* MAC header */ | ||
1756 | fc = le16_to_cpu(header->frame_control); | ||
1757 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
1758 | |||
1759 | /* metadata */ | ||
1760 | channel = le16_to_cpu(rx_hdr->channel); | ||
1761 | phy_flags = le16_to_cpu(rx_hdr->phy_flags); | ||
1762 | rate_sym = rx_hdr->rate; | ||
1763 | length = le16_to_cpu(rx_hdr->len); | ||
1764 | |||
1765 | /* end-of-frame status and timestamp */ | ||
1766 | status = le32_to_cpu(rx_end->status); | ||
1767 | bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); | ||
1768 | tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; | ||
1769 | tsf = le64_to_cpu(rx_end->timestamp); | ||
1770 | |||
1771 | /* signal statistics */ | ||
1772 | rssi = rx_stats->rssi; | ||
1773 | agc = rx_stats->agc; | ||
1774 | sig_avg = le16_to_cpu(rx_stats->sig_avg); | ||
1775 | noise_diff = le16_to_cpu(rx_stats->noise_diff); | ||
1776 | |||
1777 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
1778 | |||
1779 | /* if data frame is to us and all is good, | ||
1780 | * (optionally) print summary for only 1 out of every 100 */ | ||
1781 | if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) == | ||
1782 | (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
1783 | dataframe = 1; | ||
1784 | if (!group100) | ||
1785 | print_summary = 1; /* print each frame */ | ||
1786 | else if (priv->framecnt_to_us < 100) { | ||
1787 | priv->framecnt_to_us++; | ||
1788 | print_summary = 0; | ||
1789 | } else { | ||
1790 | priv->framecnt_to_us = 0; | ||
1791 | print_summary = 1; | ||
1792 | hundred = 1; | ||
1793 | } | ||
1794 | } else { | ||
1795 | /* print summary for all other frames */ | ||
1796 | print_summary = 1; | ||
1797 | } | ||
1798 | |||
1799 | if (print_summary) { | ||
1800 | char *title; | ||
1801 | u32 rate; | ||
1802 | |||
1803 | if (hundred) | ||
1804 | title = "100Frames"; | ||
1805 | else if (fc & IEEE80211_FCTL_RETRY) | ||
1806 | title = "Retry"; | ||
1807 | else if (ieee80211_is_assoc_response(fc)) | ||
1808 | title = "AscRsp"; | ||
1809 | else if (ieee80211_is_reassoc_response(fc)) | ||
1810 | title = "RasRsp"; | ||
1811 | else if (ieee80211_is_probe_response(fc)) { | ||
1812 | title = "PrbRsp"; | ||
1813 | print_dump = 1; /* dump frame contents */ | ||
1814 | } else if (ieee80211_is_beacon(fc)) { | ||
1815 | title = "Beacon"; | ||
1816 | print_dump = 1; /* dump frame contents */ | ||
1817 | } else if (ieee80211_is_atim(fc)) | ||
1818 | title = "ATIM"; | ||
1819 | else if (ieee80211_is_auth(fc)) | ||
1820 | title = "Auth"; | ||
1821 | else if (ieee80211_is_deauth(fc)) | ||
1822 | title = "DeAuth"; | ||
1823 | else if (ieee80211_is_disassoc(fc)) | ||
1824 | title = "DisAssoc"; | ||
1825 | else | ||
1826 | title = "Frame"; | ||
1827 | |||
1828 | rate = iwl4965_rate_index_from_plcp(rate_sym); | ||
1829 | if (rate == -1) | ||
1830 | rate = 0; | ||
1831 | else | ||
1832 | rate = iwl4965_rates[rate].ieee / 2; | ||
1833 | |||
1834 | /* print frame summary. | ||
1835 | * MAC addresses show just the last byte (for brevity), | ||
1836 | * but you can hack it to show more, if you'd like to. */ | ||
1837 | if (dataframe) | ||
1838 | IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " | ||
1839 | "len=%u, rssi=%d, chnl=%d, rate=%u, \n", | ||
1840 | title, fc, header->addr1[5], | ||
1841 | length, rssi, channel, rate); | ||
1842 | else { | ||
1843 | /* src/dst addresses assume managed mode */ | ||
1844 | IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " | ||
1845 | "src=0x%02x, rssi=%u, tim=%lu usec, " | ||
1846 | "phy=0x%02x, chnl=%d\n", | ||
1847 | title, fc, header->addr1[5], | ||
1848 | header->addr3[5], rssi, | ||
1849 | tsf_low - priv->scan_start_tsf, | ||
1850 | phy_flags, channel); | ||
1851 | } | ||
1852 | } | ||
1853 | if (print_dump) | ||
1854 | iwl4965_print_hex_dump(IWL_DL_RX, data, length); | ||
1855 | } | ||
1856 | #endif | ||
1857 | 1647 | ||
1858 | static void iwl4965_unset_hw_setting(struct iwl4965_priv *priv) | 1648 | static void iwl4965_unset_hw_setting(struct iwl4965_priv *priv) |
1859 | { | 1649 | { |
@@ -3088,7 +2878,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, | |||
3088 | iwl4965_tx_queue_update_wr_ptr(priv, txq, len); | 2878 | iwl4965_tx_queue_update_wr_ptr(priv, txq, len); |
3089 | 2879 | ||
3090 | /* Tell device the write index *just past* this latest filled TFD */ | 2880 | /* Tell device the write index *just past* this latest filled TFD */ |
3091 | q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd); | 2881 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
3092 | rc = iwl4965_tx_queue_update_write_ptr(priv, txq); | 2882 | rc = iwl4965_tx_queue_update_write_ptr(priv, txq); |
3093 | spin_unlock_irqrestore(&priv->lock, flags); | 2883 | spin_unlock_irqrestore(&priv->lock, flags); |
3094 | 2884 | ||
@@ -3482,9 +3272,9 @@ int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index) | |||
3482 | return 0; | 3272 | return 0; |
3483 | } | 3273 | } |
3484 | 3274 | ||
3485 | for (index = iwl4965_queue_inc_wrap(index, q->n_bd); | 3275 | for (index = iwl_queue_inc_wrap(index, q->n_bd); |
3486 | q->read_ptr != index; | 3276 | q->read_ptr != index; |
3487 | q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 3277 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
3488 | if (txq_id != IWL_CMD_QUEUE_NUM) { | 3278 | if (txq_id != IWL_CMD_QUEUE_NUM) { |
3489 | iwl4965_txstatus_to_ieee(priv, | 3279 | iwl4965_txstatus_to_ieee(priv, |
3490 | &(txq->txb[txq->q.read_ptr])); | 3280 | &(txq->txb[txq->q.read_ptr])); |
@@ -3591,9 +3381,9 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, | |||
3591 | tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU; | 3381 | tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU; |
3592 | tx_status->flags = iwl4965_is_tx_success(status)? | 3382 | tx_status->flags = iwl4965_is_tx_success(status)? |
3593 | IEEE80211_TX_STATUS_ACK : 0; | 3383 | IEEE80211_TX_STATUS_ACK : 0; |
3594 | /* FIXME Wrong Rate | 3384 | iwl4965_hwrate_to_tx_control(priv, |
3595 | tx_status->control.tx_rate = | 3385 | le32_to_cpu(tx_resp->rate_n_flags), |
3596 | iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags); */ | 3386 | &tx_status->control); |
3597 | /* FIXME: code repetition end */ | 3387 | /* FIXME: code repetition end */ |
3598 | 3388 | ||
3599 | IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n", | 3389 | IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n", |
@@ -3729,7 +3519,7 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, | |||
3729 | 3519 | ||
3730 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { | 3520 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { |
3731 | int freed; | 3521 | int freed; |
3732 | index = iwl4965_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); | 3522 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); |
3733 | IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn " | 3523 | IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn " |
3734 | "%d index %d\n", scd_ssn , index); | 3524 | "%d index %d\n", scd_ssn , index); |
3735 | freed = iwl4965_tx_queue_reclaim(priv, txq_id, index); | 3525 | freed = iwl4965_tx_queue_reclaim(priv, txq_id, index); |
@@ -3750,9 +3540,10 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, | |||
3750 | tx_status->queue_number = status; | 3540 | tx_status->queue_number = status; |
3751 | tx_status->queue_length = tx_resp->bt_kill_count; | 3541 | tx_status->queue_length = tx_resp->bt_kill_count; |
3752 | tx_status->queue_length |= tx_resp->failure_rts; | 3542 | tx_status->queue_length |= tx_resp->failure_rts; |
3753 | |||
3754 | tx_status->flags = | 3543 | tx_status->flags = |
3755 | iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0; | 3544 | iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0; |
3545 | iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), | ||
3546 | &tx_status->control); | ||
3756 | 3547 | ||
3757 | IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x " | 3548 | IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x " |
3758 | "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status), | 3549 | "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status), |
@@ -4886,8 +4677,7 @@ static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv) | |||
4886 | 4677 | ||
4887 | if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { | 4678 | if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { |
4888 | IWL_ERROR("Start IWL Error Log Dump:\n"); | 4679 | IWL_ERROR("Start IWL Error Log Dump:\n"); |
4889 | IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n", | 4680 | IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count); |
4890 | priv->status, priv->config, count); | ||
4891 | } | 4681 | } |
4892 | 4682 | ||
4893 | desc = iwl4965_read_targ_mem(priv, base + 1 * sizeof(u32)); | 4683 | desc = iwl4965_read_targ_mem(priv, base + 1 * sizeof(u32)); |
@@ -5099,9 +4889,9 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) | |||
5099 | * atomic, make sure that inta covers all the interrupts that | 4889 | * atomic, make sure that inta covers all the interrupts that |
5100 | * we've discovered, even if FH interrupt came in just after | 4890 | * we've discovered, even if FH interrupt came in just after |
5101 | * reading CSR_INT. */ | 4891 | * reading CSR_INT. */ |
5102 | if (inta_fh & CSR_FH_INT_RX_MASK) | 4892 | if (inta_fh & CSR49_FH_INT_RX_MASK) |
5103 | inta |= CSR_INT_BIT_FH_RX; | 4893 | inta |= CSR_INT_BIT_FH_RX; |
5104 | if (inta_fh & CSR_FH_INT_TX_MASK) | 4894 | if (inta_fh & CSR49_FH_INT_TX_MASK) |
5105 | inta |= CSR_INT_BIT_FH_TX; | 4895 | inta |= CSR_INT_BIT_FH_TX; |
5106 | 4896 | ||
5107 | /* Now service all interrupt bits discovered above. */ | 4897 | /* Now service all interrupt bits discovered above. */ |
@@ -5502,11 +5292,12 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) | |||
5502 | ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; | 5292 | ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; |
5503 | ch_info->min_power = 0; | 5293 | ch_info->min_power = 0; |
5504 | 5294 | ||
5505 | IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x" | 5295 | IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x" |
5506 | " %ddBm): Ad-Hoc %ssupported\n", | 5296 | " %ddBm): Ad-Hoc %ssupported\n", |
5507 | ch_info->channel, | 5297 | ch_info->channel, |
5508 | is_channel_a_band(ch_info) ? | 5298 | is_channel_a_band(ch_info) ? |
5509 | "5.2" : "2.4", | 5299 | "5.2" : "2.4", |
5300 | CHECK_AND_PRINT(VALID), | ||
5510 | CHECK_AND_PRINT(IBSS), | 5301 | CHECK_AND_PRINT(IBSS), |
5511 | CHECK_AND_PRINT(ACTIVE), | 5302 | CHECK_AND_PRINT(ACTIVE), |
5512 | CHECK_AND_PRINT(RADAR), | 5303 | CHECK_AND_PRINT(RADAR), |
@@ -5749,7 +5540,7 @@ static void iwl4965_init_hw_rates(struct iwl4965_priv *priv, | |||
5749 | static int iwl4965_init_geos(struct iwl4965_priv *priv) | 5540 | static int iwl4965_init_geos(struct iwl4965_priv *priv) |
5750 | { | 5541 | { |
5751 | struct iwl4965_channel_info *ch; | 5542 | struct iwl4965_channel_info *ch; |
5752 | struct ieee80211_supported_band *band; | 5543 | struct ieee80211_supported_band *sband; |
5753 | struct ieee80211_channel *channels; | 5544 | struct ieee80211_channel *channels; |
5754 | struct ieee80211_channel *geo_ch; | 5545 | struct ieee80211_channel *geo_ch; |
5755 | struct ieee80211_rate *rates; | 5546 | struct ieee80211_rate *rates; |
@@ -5767,7 +5558,7 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) | |||
5767 | if (!channels) | 5558 | if (!channels) |
5768 | return -ENOMEM; | 5559 | return -ENOMEM; |
5769 | 5560 | ||
5770 | rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)), | 5561 | rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)), |
5771 | GFP_KERNEL); | 5562 | GFP_KERNEL); |
5772 | if (!rates) { | 5563 | if (!rates) { |
5773 | kfree(channels); | 5564 | kfree(channels); |
@@ -5775,42 +5566,42 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) | |||
5775 | } | 5566 | } |
5776 | 5567 | ||
5777 | /* 5.2GHz channels start after the 2.4GHz channels */ | 5568 | /* 5.2GHz channels start after the 2.4GHz channels */ |
5778 | band = &priv->bands[IEEE80211_BAND_5GHZ]; | 5569 | sband = &priv->bands[IEEE80211_BAND_5GHZ]; |
5779 | band->channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)]; | 5570 | sband->channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)]; |
5780 | band->bitrates = &rates[4]; | 5571 | /* just OFDM */ |
5781 | band->n_bitrates = 8; /* just OFDM */ | 5572 | sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; |
5573 | sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; | ||
5782 | 5574 | ||
5783 | iwl4965_init_ht_hw_capab(&band->ht_info, IEEE80211_BAND_5GHZ); | 5575 | iwl4965_init_ht_hw_capab(&sband->ht_info, IEEE80211_BAND_5GHZ); |
5784 | 5576 | ||
5785 | band = &priv->bands[IEEE80211_BAND_2GHZ]; | 5577 | sband = &priv->bands[IEEE80211_BAND_2GHZ]; |
5786 | band->channels = channels; | 5578 | sband->channels = channels; |
5787 | band->bitrates = rates; | 5579 | /* OFDM & CCK */ |
5788 | band->n_bitrates = 12; /* OFDM & CCK */ | 5580 | sband->bitrates = rates; |
5581 | sband->n_bitrates = IWL_RATE_COUNT; | ||
5789 | 5582 | ||
5790 | iwl4965_init_ht_hw_capab(&band->ht_info, IEEE80211_BAND_2GHZ); | 5583 | iwl4965_init_ht_hw_capab(&sband->ht_info, IEEE80211_BAND_2GHZ); |
5791 | 5584 | ||
5792 | priv->ieee_channels = channels; | 5585 | priv->ieee_channels = channels; |
5793 | priv->ieee_rates = rates; | 5586 | priv->ieee_rates = rates; |
5794 | 5587 | ||
5795 | iwl4965_init_hw_rates(priv, rates); | 5588 | iwl4965_init_hw_rates(priv, rates); |
5796 | 5589 | ||
5797 | for (i = 0, geo_ch = channels; i < priv->channel_count; i++) { | 5590 | for (i = 0; i < priv->channel_count; i++) { |
5798 | ch = &priv->channel_info[i]; | 5591 | ch = &priv->channel_info[i]; |
5799 | 5592 | ||
5800 | if (!is_channel_valid(ch)) { | 5593 | /* FIXME: might be removed if scan is OK */ |
5801 | IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- " | 5594 | if (!is_channel_valid(ch)) |
5802 | "skipping.\n", | ||
5803 | ch->channel, is_channel_a_band(ch) ? | ||
5804 | "5.2" : "2.4"); | ||
5805 | continue; | 5595 | continue; |
5806 | } | ||
5807 | 5596 | ||
5808 | if (is_channel_a_band(ch)) { | 5597 | if (is_channel_a_band(ch)) |
5809 | geo_ch = &priv->bands[IEEE80211_BAND_5GHZ].channels[priv->bands[IEEE80211_BAND_5GHZ].n_channels++]; | 5598 | sband = &priv->bands[IEEE80211_BAND_5GHZ]; |
5810 | } else | 5599 | else |
5811 | geo_ch = &priv->bands[IEEE80211_BAND_2GHZ].channels[priv->bands[IEEE80211_BAND_2GHZ].n_channels++]; | 5600 | sband = &priv->bands[IEEE80211_BAND_2GHZ]; |
5601 | |||
5602 | geo_ch = &sband->channels[sband->n_channels++]; | ||
5812 | 5603 | ||
5813 | geo_ch->center_freq = ieee80211chan2mhz(ch->channel); | 5604 | geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel); |
5814 | geo_ch->max_power = ch->max_power_avg; | 5605 | geo_ch->max_power = ch->max_power_avg; |
5815 | geo_ch->max_antenna_gain = 0xff; | 5606 | geo_ch->max_antenna_gain = 0xff; |
5816 | geo_ch->hw_value = ch->channel; | 5607 | geo_ch->hw_value = ch->channel; |
@@ -5828,16 +5619,28 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) | |||
5828 | if (ch->max_power_avg > priv->max_channel_txpower_limit) | 5619 | if (ch->max_power_avg > priv->max_channel_txpower_limit) |
5829 | priv->max_channel_txpower_limit = | 5620 | priv->max_channel_txpower_limit = |
5830 | ch->max_power_avg; | 5621 | ch->max_power_avg; |
5831 | } else | 5622 | } else { |
5832 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; | 5623 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; |
5624 | } | ||
5625 | |||
5626 | /* Save flags for reg domain usage */ | ||
5627 | geo_ch->orig_flags = geo_ch->flags; | ||
5628 | |||
5629 | IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n", | ||
5630 | ch->channel, geo_ch->center_freq, | ||
5631 | is_channel_a_band(ch) ? "5.2" : "2.4", | ||
5632 | geo_ch->flags & IEEE80211_CHAN_DISABLED ? | ||
5633 | "restricted" : "valid", | ||
5634 | geo_ch->flags); | ||
5833 | } | 5635 | } |
5834 | 5636 | ||
5835 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) { | 5637 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && |
5638 | priv->cfg->sku & IWL_SKU_A) { | ||
5836 | printk(KERN_INFO DRV_NAME | 5639 | printk(KERN_INFO DRV_NAME |
5837 | ": Incorrectly detected BG card as ABG. Please send " | 5640 | ": Incorrectly detected BG card as ABG. Please send " |
5838 | "your PCI ID 0x%04X:0x%04X to maintainer.\n", | 5641 | "your PCI ID 0x%04X:0x%04X to maintainer.\n", |
5839 | priv->pci_dev->device, priv->pci_dev->subsystem_device); | 5642 | priv->pci_dev->device, priv->pci_dev->subsystem_device); |
5840 | priv->is_abg = 0; | 5643 | priv->cfg->sku &= ~IWL_SKU_A; |
5841 | } | 5644 | } |
5842 | 5645 | ||
5843 | printk(KERN_INFO DRV_NAME | 5646 | printk(KERN_INFO DRV_NAME |
@@ -6186,7 +5989,7 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) | |||
6186 | struct iwl4965_ucode *ucode; | 5989 | struct iwl4965_ucode *ucode; |
6187 | int ret; | 5990 | int ret; |
6188 | const struct firmware *ucode_raw; | 5991 | const struct firmware *ucode_raw; |
6189 | const char *name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode"; | 5992 | const char *name = priv->cfg->fw_name; |
6190 | u8 *src; | 5993 | u8 *src; |
6191 | size_t len; | 5994 | size_t len; |
6192 | u32 ver, inst_size, data_size, init_size, init_data_size, boot_size; | 5995 | u32 ver, inst_size, data_size, init_size, init_data_size, boot_size; |
@@ -7596,6 +7399,12 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, | |||
7596 | if (conf == NULL) | 7399 | if (conf == NULL) |
7597 | return -EIO; | 7400 | return -EIO; |
7598 | 7401 | ||
7402 | if (priv->vif != vif) { | ||
7403 | IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); | ||
7404 | mutex_unlock(&priv->mutex); | ||
7405 | return 0; | ||
7406 | } | ||
7407 | |||
7599 | if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && | 7408 | if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && |
7600 | (!conf->beacon || !conf->ssid_len)) { | 7409 | (!conf->beacon || !conf->ssid_len)) { |
7601 | IWL_DEBUG_MAC80211 | 7410 | IWL_DEBUG_MAC80211 |
@@ -7618,17 +7427,6 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, | |||
7618 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && | 7427 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && |
7619 | !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { | 7428 | !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { |
7620 | */ | 7429 | */ |
7621 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { | ||
7622 | IWL_DEBUG_MAC80211("leave - scanning\n"); | ||
7623 | mutex_unlock(&priv->mutex); | ||
7624 | return 0; | ||
7625 | } | ||
7626 | |||
7627 | if (priv->vif != vif) { | ||
7628 | IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); | ||
7629 | mutex_unlock(&priv->mutex); | ||
7630 | return 0; | ||
7631 | } | ||
7632 | 7430 | ||
7633 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { | 7431 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { |
7634 | if (!conf->bssid) { | 7432 | if (!conf->bssid) { |
@@ -8127,15 +7925,21 @@ static void iwl4965_ht_info_fill(struct ieee80211_conf *conf, | |||
8127 | iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); | 7925 | iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); |
8128 | iwl_conf->max_amsdu_size = | 7926 | iwl_conf->max_amsdu_size = |
8129 | !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); | 7927 | !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); |
7928 | |||
8130 | iwl_conf->supported_chan_width = | 7929 | iwl_conf->supported_chan_width = |
8131 | !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH); | 7930 | !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH); |
7931 | iwl_conf->extension_chan_offset = | ||
7932 | ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET; | ||
7933 | /* If no above or below channel supplied disable FAT channel */ | ||
7934 | if (iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_ABOVE && | ||
7935 | iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_BELOW) | ||
7936 | iwl_conf->supported_chan_width = 0; | ||
7937 | |||
8132 | iwl_conf->tx_mimo_ps_mode = | 7938 | iwl_conf->tx_mimo_ps_mode = |
8133 | (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2); | 7939 | (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2); |
8134 | memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16); | 7940 | memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16); |
8135 | 7941 | ||
8136 | iwl_conf->control_channel = ht_bss_conf->primary_channel; | 7942 | iwl_conf->control_channel = ht_bss_conf->primary_channel; |
8137 | iwl_conf->extension_chan_offset = | ||
8138 | ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET; | ||
8139 | iwl_conf->tx_chan_width = | 7943 | iwl_conf->tx_chan_width = |
8140 | !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH); | 7944 | !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH); |
8141 | iwl_conf->ht_protection = | 7945 | iwl_conf->ht_protection = |
@@ -8776,6 +8580,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8776 | int err = 0; | 8580 | int err = 0; |
8777 | struct iwl4965_priv *priv; | 8581 | struct iwl4965_priv *priv; |
8778 | struct ieee80211_hw *hw; | 8582 | struct ieee80211_hw *hw; |
8583 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); | ||
8779 | int i; | 8584 | int i; |
8780 | DECLARE_MAC_BUF(mac); | 8585 | DECLARE_MAC_BUF(mac); |
8781 | 8586 | ||
@@ -8809,6 +8614,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8809 | IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); | 8614 | IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); |
8810 | priv = hw->priv; | 8615 | priv = hw->priv; |
8811 | priv->hw = hw; | 8616 | priv->hw = hw; |
8617 | priv->cfg = cfg; | ||
8812 | 8618 | ||
8813 | priv->pci_dev = pdev; | 8619 | priv->pci_dev = pdev; |
8814 | priv->antenna = (enum iwl4965_antenna)iwl4965_param_antenna; | 8620 | priv->antenna = (enum iwl4965_antenna)iwl4965_param_antenna; |
@@ -8911,8 +8717,9 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8911 | /* Choose which receivers/antennas to use */ | 8717 | /* Choose which receivers/antennas to use */ |
8912 | iwl4965_set_rxon_chain(priv); | 8718 | iwl4965_set_rxon_chain(priv); |
8913 | 8719 | ||
8720 | |||
8914 | printk(KERN_INFO DRV_NAME | 8721 | printk(KERN_INFO DRV_NAME |
8915 | ": Detected Intel Wireless WiFi Link 4965AGN\n"); | 8722 | ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); |
8916 | 8723 | ||
8917 | /* Device-specific setup */ | 8724 | /* Device-specific setup */ |
8918 | if (iwl4965_hw_set_hw_setting(priv)) { | 8725 | if (iwl4965_hw_set_hw_setting(priv)) { |
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 75f6191e718d..7fe37bedf313 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c | |||
@@ -349,11 +349,7 @@ static int assoc_helper_wpa_keys(struct lbs_private *priv, | |||
349 | 349 | ||
350 | if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { | 350 | if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { |
351 | clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); | 351 | clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); |
352 | ret = lbs_prepare_and_send_command(priv, | 352 | ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req); |
353 | CMD_802_11_KEY_MATERIAL, | ||
354 | CMD_ACT_SET, | ||
355 | CMD_OPTION_WAITFORRSP, | ||
356 | 0, assoc_req); | ||
357 | assoc_req->flags = flags; | 353 | assoc_req->flags = flags; |
358 | } | 354 | } |
359 | 355 | ||
@@ -363,11 +359,7 @@ static int assoc_helper_wpa_keys(struct lbs_private *priv, | |||
363 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { | 359 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { |
364 | clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); | 360 | clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); |
365 | 361 | ||
366 | ret = lbs_prepare_and_send_command(priv, | 362 | ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req); |
367 | CMD_802_11_KEY_MATERIAL, | ||
368 | CMD_ACT_SET, | ||
369 | CMD_OPTION_WAITFORRSP, | ||
370 | 0, assoc_req); | ||
371 | assoc_req->flags = flags; | 363 | assoc_req->flags = flags; |
372 | } | 364 | } |
373 | 365 | ||
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 3f9074df91e4..445c6dc09786 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -338,75 +338,103 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | |||
338 | return ret; | 338 | return ret; |
339 | } | 339 | } |
340 | 340 | ||
341 | static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset, | 341 | static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam, |
342 | struct enc_key * pkey) | 342 | struct enc_key *key) |
343 | { | 343 | { |
344 | lbs_deb_enter(LBS_DEB_CMD); | 344 | lbs_deb_enter(LBS_DEB_CMD); |
345 | 345 | ||
346 | if (pkey->flags & KEY_INFO_WPA_ENABLED) { | 346 | if (key->flags & KEY_INFO_WPA_ENABLED) |
347 | pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); | 347 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); |
348 | } | 348 | if (key->flags & KEY_INFO_WPA_UNICAST) |
349 | if (pkey->flags & KEY_INFO_WPA_UNICAST) { | 349 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); |
350 | pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); | 350 | if (key->flags & KEY_INFO_WPA_MCAST) |
351 | } | 351 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); |
352 | if (pkey->flags & KEY_INFO_WPA_MCAST) { | 352 | |
353 | pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); | 353 | keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); |
354 | } | 354 | keyparam->keytypeid = cpu_to_le16(key->type); |
355 | keyparam->keylen = cpu_to_le16(key->len); | ||
356 | memcpy(keyparam->key, key->key, key->len); | ||
355 | 357 | ||
356 | pkeyparamset->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); | 358 | /* Length field doesn't include the {type,length} header */ |
357 | pkeyparamset->keytypeid = cpu_to_le16(pkey->type); | 359 | keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4); |
358 | pkeyparamset->keylen = cpu_to_le16(pkey->len); | ||
359 | memcpy(pkeyparamset->key, pkey->key, pkey->len); | ||
360 | pkeyparamset->length = cpu_to_le16( sizeof(pkeyparamset->keytypeid) | ||
361 | + sizeof(pkeyparamset->keyinfo) | ||
362 | + sizeof(pkeyparamset->keylen) | ||
363 | + sizeof(pkeyparamset->key)); | ||
364 | lbs_deb_leave(LBS_DEB_CMD); | 360 | lbs_deb_leave(LBS_DEB_CMD); |
365 | } | 361 | } |
366 | 362 | ||
367 | static int lbs_cmd_802_11_key_material(struct lbs_private *priv, | 363 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, |
368 | struct cmd_ds_command *cmd, | 364 | struct assoc_request *assoc) |
369 | u16 cmd_action, | ||
370 | u32 cmd_oid, void *pdata_buf) | ||
371 | { | 365 | { |
372 | struct cmd_ds_802_11_key_material *pkeymaterial = | 366 | struct cmd_ds_802_11_key_material cmd; |
373 | &cmd->params.keymaterial; | ||
374 | struct assoc_request * assoc_req = pdata_buf; | ||
375 | int ret = 0; | 367 | int ret = 0; |
376 | int index = 0; | 368 | int index = 0; |
377 | 369 | ||
378 | lbs_deb_enter(LBS_DEB_CMD); | 370 | lbs_deb_enter(LBS_DEB_CMD); |
379 | 371 | ||
380 | cmd->command = cpu_to_le16(CMD_802_11_KEY_MATERIAL); | 372 | cmd.action = cpu_to_le16(cmd_action); |
381 | pkeymaterial->action = cpu_to_le16(cmd_action); | 373 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
382 | 374 | ||
383 | if (cmd_action == CMD_ACT_GET) { | 375 | if (cmd_action == CMD_ACT_GET) { |
384 | cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action)); | 376 | cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2); |
385 | ret = 0; | 377 | } else { |
386 | goto done; | 378 | memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet)); |
387 | } | ||
388 | 379 | ||
389 | memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet)); | 380 | if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) { |
381 | set_one_wpa_key(&cmd.keyParamSet[index], | ||
382 | &assoc->wpa_unicast_key); | ||
383 | index++; | ||
384 | } | ||
390 | 385 | ||
391 | if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { | 386 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) { |
392 | set_one_wpa_key(&pkeymaterial->keyParamSet[index], | 387 | set_one_wpa_key(&cmd.keyParamSet[index], |
393 | &assoc_req->wpa_unicast_key); | 388 | &assoc->wpa_mcast_key); |
394 | index++; | 389 | index++; |
395 | } | 390 | } |
396 | 391 | ||
397 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { | 392 | /* The common header and as many keys as we included */ |
398 | set_one_wpa_key(&pkeymaterial->keyParamSet[index], | 393 | cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd), |
399 | &assoc_req->wpa_mcast_key); | 394 | keyParamSet[index])); |
400 | index++; | ||
401 | } | 395 | } |
396 | ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd); | ||
397 | /* Copy the returned key to driver private data */ | ||
398 | if (!ret && cmd_action == CMD_ACT_GET) { | ||
399 | void *buf_ptr = cmd.keyParamSet; | ||
400 | void *resp_end = &(&cmd)[1]; | ||
401 | |||
402 | while (buf_ptr < resp_end) { | ||
403 | struct MrvlIEtype_keyParamSet *keyparam = buf_ptr; | ||
404 | struct enc_key *key; | ||
405 | uint16_t param_set_len = le16_to_cpu(keyparam->length); | ||
406 | uint16_t key_len = le16_to_cpu(keyparam->keylen); | ||
407 | uint16_t key_flags = le16_to_cpu(keyparam->keyinfo); | ||
408 | uint16_t key_type = le16_to_cpu(keyparam->keytypeid); | ||
409 | void *end; | ||
410 | |||
411 | end = (void *)keyparam + sizeof(keyparam->type) | ||
412 | + sizeof(keyparam->length) + param_set_len; | ||
413 | |||
414 | /* Make sure we don't access past the end of the IEs */ | ||
415 | if (end > resp_end) | ||
416 | break; | ||
402 | 417 | ||
403 | cmd->size = cpu_to_le16( S_DS_GEN | 418 | if (key_flags & KEY_INFO_WPA_UNICAST) |
404 | + sizeof (pkeymaterial->action) | 419 | key = &priv->wpa_unicast_key; |
405 | + (index * sizeof(struct MrvlIEtype_keyParamSet))); | 420 | else if (key_flags & KEY_INFO_WPA_MCAST) |
421 | key = &priv->wpa_mcast_key; | ||
422 | else | ||
423 | break; | ||
406 | 424 | ||
407 | ret = 0; | 425 | /* Copy returned key into driver */ |
426 | memset(key, 0, sizeof(struct enc_key)); | ||
427 | if (key_len > sizeof(key->key)) | ||
428 | break; | ||
429 | key->type = key_type; | ||
430 | key->flags = key_flags; | ||
431 | key->len = key_len; | ||
432 | memcpy(key->key, keyparam->key, key->len); | ||
433 | |||
434 | buf_ptr = end + 1; | ||
435 | } | ||
436 | } | ||
408 | 437 | ||
409 | done: | ||
410 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | 438 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); |
411 | return ret; | 439 | return ret; |
412 | } | 440 | } |
@@ -1354,10 +1382,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1354 | ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action); | 1382 | ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action); |
1355 | break; | 1383 | break; |
1356 | 1384 | ||
1357 | case CMD_802_11_SCAN: | ||
1358 | ret = lbs_cmd_80211_scan(priv, cmdptr, pdata_buf); | ||
1359 | break; | ||
1360 | |||
1361 | case CMD_MAC_CONTROL: | 1385 | case CMD_MAC_CONTROL: |
1362 | ret = lbs_cmd_mac_control(priv, cmdptr); | 1386 | ret = lbs_cmd_mac_control(priv, cmdptr); |
1363 | break; | 1387 | break; |
@@ -1435,11 +1459,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1435 | ret = lbs_cmd_80211_ad_hoc_stop(priv, cmdptr); | 1459 | ret = lbs_cmd_80211_ad_hoc_stop(priv, cmdptr); |
1436 | break; | 1460 | break; |
1437 | 1461 | ||
1438 | case CMD_802_11_KEY_MATERIAL: | ||
1439 | ret = lbs_cmd_802_11_key_material(priv, cmdptr, cmd_action, | ||
1440 | cmd_oid, pdata_buf); | ||
1441 | break; | ||
1442 | |||
1443 | case CMD_802_11_PAIRWISE_TSC: | 1462 | case CMD_802_11_PAIRWISE_TSC: |
1444 | break; | 1463 | break; |
1445 | case CMD_802_11_GROUP_TSC: | 1464 | case CMD_802_11_GROUP_TSC: |
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index b9ab85cc7913..d250e6bc0609 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h | |||
@@ -57,5 +57,7 @@ int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | |||
57 | struct assoc_request *assoc); | 57 | struct assoc_request *assoc); |
58 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | 58 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, |
59 | uint16_t *enable); | 59 | uint16_t *enable); |
60 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | ||
61 | struct assoc_request *assoc); | ||
60 | 62 | ||
61 | #endif /* _LBS_CMD_H */ | 63 | #endif /* _LBS_CMD_H */ |
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 5d90b83f28eb..15e4ebdcd477 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -204,61 +204,6 @@ static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv, | |||
204 | return 0; | 204 | return 0; |
205 | } | 205 | } |
206 | 206 | ||
207 | static int lbs_ret_802_11_key_material(struct lbs_private *priv, | ||
208 | struct cmd_ds_command *resp) | ||
209 | { | ||
210 | struct cmd_ds_802_11_key_material *pkeymaterial = | ||
211 | &resp->params.keymaterial; | ||
212 | u16 action = le16_to_cpu(pkeymaterial->action); | ||
213 | |||
214 | lbs_deb_enter(LBS_DEB_CMD); | ||
215 | |||
216 | /* Copy the returned key to driver private data */ | ||
217 | if (action == CMD_ACT_GET) { | ||
218 | u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet; | ||
219 | u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size)); | ||
220 | |||
221 | while (buf_ptr < resp_end) { | ||
222 | struct MrvlIEtype_keyParamSet * pkeyparamset = | ||
223 | (struct MrvlIEtype_keyParamSet *) buf_ptr; | ||
224 | struct enc_key * pkey; | ||
225 | u16 param_set_len = le16_to_cpu(pkeyparamset->length); | ||
226 | u16 key_len = le16_to_cpu(pkeyparamset->keylen); | ||
227 | u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo); | ||
228 | u16 key_type = le16_to_cpu(pkeyparamset->keytypeid); | ||
229 | u8 * end; | ||
230 | |||
231 | end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type) | ||
232 | + sizeof (pkeyparamset->length) | ||
233 | + param_set_len; | ||
234 | /* Make sure we don't access past the end of the IEs */ | ||
235 | if (end > resp_end) | ||
236 | break; | ||
237 | |||
238 | if (key_flags & KEY_INFO_WPA_UNICAST) | ||
239 | pkey = &priv->wpa_unicast_key; | ||
240 | else if (key_flags & KEY_INFO_WPA_MCAST) | ||
241 | pkey = &priv->wpa_mcast_key; | ||
242 | else | ||
243 | break; | ||
244 | |||
245 | /* Copy returned key into driver */ | ||
246 | memset(pkey, 0, sizeof(struct enc_key)); | ||
247 | if (key_len > sizeof(pkey->key)) | ||
248 | break; | ||
249 | pkey->type = key_type; | ||
250 | pkey->flags = key_flags; | ||
251 | pkey->len = key_len; | ||
252 | memcpy(pkey->key, pkeyparamset->key, pkey->len); | ||
253 | |||
254 | buf_ptr = end + 1; | ||
255 | } | ||
256 | } | ||
257 | |||
258 | lbs_deb_enter(LBS_DEB_CMD); | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static int lbs_ret_802_11_mac_address(struct lbs_private *priv, | 207 | static int lbs_ret_802_11_mac_address(struct lbs_private *priv, |
263 | struct cmd_ds_command *resp) | 208 | struct cmd_ds_command *resp) |
264 | { | 209 | { |
@@ -407,10 +352,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, | |||
407 | ret = lbs_ret_reg_access(priv, respcmd, resp); | 352 | ret = lbs_ret_reg_access(priv, respcmd, resp); |
408 | break; | 353 | break; |
409 | 354 | ||
410 | case CMD_RET(CMD_802_11_SCAN): | ||
411 | ret = lbs_ret_80211_scan(priv, resp); | ||
412 | break; | ||
413 | |||
414 | case CMD_RET(CMD_802_11_GET_LOG): | 355 | case CMD_RET(CMD_802_11_GET_LOG): |
415 | ret = lbs_ret_get_log(priv, resp); | 356 | ret = lbs_ret_get_log(priv, resp); |
416 | break; | 357 | break; |
@@ -475,10 +416,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, | |||
475 | ret = lbs_ret_80211_ad_hoc_stop(priv, resp); | 416 | ret = lbs_ret_80211_ad_hoc_stop(priv, resp); |
476 | break; | 417 | break; |
477 | 418 | ||
478 | case CMD_RET(CMD_802_11_KEY_MATERIAL): | ||
479 | ret = lbs_ret_802_11_key_material(priv, resp); | ||
480 | break; | ||
481 | |||
482 | case CMD_RET(CMD_802_11_EEPROM_ACCESS): | 419 | case CMD_RET(CMD_802_11_EEPROM_ACCESS): |
483 | ret = lbs_ret_802_11_eeprom_access(priv, resp); | 420 | ret = lbs_ret_802_11_eeprom_access(priv, resp); |
484 | break; | 421 | break; |
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index d35b015b6657..56bc1aa2bb00 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h | |||
@@ -174,9 +174,11 @@ struct cmd_ds_802_11_subscribe_event { | |||
174 | * Define data structure for CMD_802_11_SCAN | 174 | * Define data structure for CMD_802_11_SCAN |
175 | */ | 175 | */ |
176 | struct cmd_ds_802_11_scan { | 176 | struct cmd_ds_802_11_scan { |
177 | u8 bsstype; | 177 | struct cmd_header hdr; |
178 | u8 bssid[ETH_ALEN]; | 178 | |
179 | u8 tlvbuffer[1]; | 179 | uint8_t bsstype; |
180 | uint8_t bssid[ETH_ALEN]; | ||
181 | uint8_t tlvbuffer[0]; | ||
180 | #if 0 | 182 | #if 0 |
181 | mrvlietypes_ssidparamset_t ssidParamSet; | 183 | mrvlietypes_ssidparamset_t ssidParamSet; |
182 | mrvlietypes_chanlistparamset_t ChanListParamSet; | 184 | mrvlietypes_chanlistparamset_t ChanListParamSet; |
@@ -185,9 +187,11 @@ struct cmd_ds_802_11_scan { | |||
185 | }; | 187 | }; |
186 | 188 | ||
187 | struct cmd_ds_802_11_scan_rsp { | 189 | struct cmd_ds_802_11_scan_rsp { |
190 | struct cmd_header hdr; | ||
191 | |||
188 | __le16 bssdescriptsize; | 192 | __le16 bssdescriptsize; |
189 | u8 nr_sets; | 193 | uint8_t nr_sets; |
190 | u8 bssdesc_and_tlvbuffer[1]; | 194 | uint8_t bssdesc_and_tlvbuffer[0]; |
191 | }; | 195 | }; |
192 | 196 | ||
193 | struct cmd_ds_802_11_get_log { | 197 | struct cmd_ds_802_11_get_log { |
@@ -572,6 +576,8 @@ struct cmd_ds_host_sleep { | |||
572 | } __attribute__ ((packed)); | 576 | } __attribute__ ((packed)); |
573 | 577 | ||
574 | struct cmd_ds_802_11_key_material { | 578 | struct cmd_ds_802_11_key_material { |
579 | struct cmd_header hdr; | ||
580 | |||
575 | __le16 action; | 581 | __le16 action; |
576 | struct MrvlIEtype_keyParamSet keyParamSet[2]; | 582 | struct MrvlIEtype_keyParamSet keyParamSet[2]; |
577 | } __attribute__ ((packed)); | 583 | } __attribute__ ((packed)); |
@@ -689,8 +695,6 @@ struct cmd_ds_command { | |||
689 | /* command Body */ | 695 | /* command Body */ |
690 | union { | 696 | union { |
691 | struct cmd_ds_802_11_ps_mode psmode; | 697 | struct cmd_ds_802_11_ps_mode psmode; |
692 | struct cmd_ds_802_11_scan scan; | ||
693 | struct cmd_ds_802_11_scan_rsp scanresp; | ||
694 | struct cmd_ds_mac_control macctrl; | 698 | struct cmd_ds_mac_control macctrl; |
695 | struct cmd_ds_802_11_associate associate; | 699 | struct cmd_ds_802_11_associate associate; |
696 | struct cmd_ds_802_11_deauthenticate deauth; | 700 | struct cmd_ds_802_11_deauthenticate deauth; |
@@ -712,7 +716,6 @@ struct cmd_ds_command { | |||
712 | struct cmd_ds_802_11_rssi_rsp rssirsp; | 716 | struct cmd_ds_802_11_rssi_rsp rssirsp; |
713 | struct cmd_ds_802_11_disassociate dassociate; | 717 | struct cmd_ds_802_11_disassociate dassociate; |
714 | struct cmd_ds_802_11_mac_address macadd; | 718 | struct cmd_ds_802_11_mac_address macadd; |
715 | struct cmd_ds_802_11_key_material keymaterial; | ||
716 | struct cmd_ds_mac_reg_access macreg; | 719 | struct cmd_ds_mac_reg_access macreg; |
717 | struct cmd_ds_bbp_reg_access bbpreg; | 720 | struct cmd_ds_bbp_reg_access bbpreg; |
718 | struct cmd_ds_rf_reg_access rfreg; | 721 | struct cmd_ds_rf_reg_access rfreg; |
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 7d4f3afa8cc5..99f11a56d84e 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "dev.h" | 20 | #include "dev.h" |
21 | #include "scan.h" | 21 | #include "scan.h" |
22 | #include "join.h" | 22 | #include "join.h" |
23 | #include "cmd.h" | ||
23 | 24 | ||
24 | //! Approximate amount of data needed to pass a scan result back to iwlist | 25 | //! Approximate amount of data needed to pass a scan result back to iwlist |
25 | #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ | 26 | #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ |
@@ -39,10 +40,9 @@ | |||
39 | //! Memory needed to store a max number/size SSID TLV for a firmware scan | 40 | //! Memory needed to store a max number/size SSID TLV for a firmware scan |
40 | #define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset)) | 41 | #define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset)) |
41 | 42 | ||
42 | //! Maximum memory needed for a lbs_scan_cmd_config with all TLVs at max | 43 | //! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max |
43 | #define MAX_SCAN_CFG_ALLOC (sizeof(struct lbs_scan_cmd_config) \ | 44 | #define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \ |
44 | + CHAN_TLV_MAX_SIZE \ | 45 | + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE) |
45 | + SSID_TLV_MAX_SIZE) | ||
46 | 46 | ||
47 | //! The maximum number of channels the firmware can scan per command | 47 | //! The maximum number of channels the firmware can scan per command |
48 | #define MRVDRV_MAX_CHANNELS_PER_SCAN 14 | 48 | #define MRVDRV_MAX_CHANNELS_PER_SCAN 14 |
@@ -61,11 +61,8 @@ | |||
61 | //! Scan time specified in the channel TLV for each channel for active scans | 61 | //! Scan time specified in the channel TLV for each channel for active scans |
62 | #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 | 62 | #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 |
63 | 63 | ||
64 | static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | 64 | static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, |
65 | static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 65 | struct cmd_header *resp); |
66 | |||
67 | |||
68 | |||
69 | 66 | ||
70 | /*********************************************************************/ | 67 | /*********************************************************************/ |
71 | /* */ | 68 | /* */ |
@@ -90,7 +87,7 @@ static void lbs_unset_basic_rate_flags(u8 *rates, size_t len) | |||
90 | } | 87 | } |
91 | 88 | ||
92 | 89 | ||
93 | static inline void clear_bss_descriptor (struct bss_descriptor * bss) | 90 | static inline void clear_bss_descriptor(struct bss_descriptor *bss) |
94 | { | 91 | { |
95 | /* Don't blow away ->list, just BSS data */ | 92 | /* Don't blow away ->list, just BSS data */ |
96 | memset(bss, 0, offsetof(struct bss_descriptor, list)); | 93 | memset(bss, 0, offsetof(struct bss_descriptor, list)); |
@@ -104,7 +101,8 @@ static inline void clear_bss_descriptor (struct bss_descriptor * bss) | |||
104 | * | 101 | * |
105 | * @return 0: ssid is same, otherwise is different | 102 | * @return 0: ssid is same, otherwise is different |
106 | */ | 103 | */ |
107 | int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) | 104 | int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2, |
105 | uint8_t ssid2_len) | ||
108 | { | 106 | { |
109 | if (ssid1_len != ssid2_len) | 107 | if (ssid1_len != ssid2_len) |
110 | return -1; | 108 | return -1; |
@@ -113,73 +111,66 @@ int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) | |||
113 | } | 111 | } |
114 | 112 | ||
115 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, | 113 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, |
116 | struct bss_descriptor * match_bss) | 114 | struct bss_descriptor *match_bss) |
117 | { | 115 | { |
118 | if ( !secinfo->wep_enabled | 116 | if (!secinfo->wep_enabled && !secinfo->WPAenabled |
119 | && !secinfo->WPAenabled | ||
120 | && !secinfo->WPA2enabled | 117 | && !secinfo->WPA2enabled |
121 | && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC | 118 | && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC |
122 | && match_bss->rsn_ie[0] != MFIE_TYPE_RSN | 119 | && match_bss->rsn_ie[0] != MFIE_TYPE_RSN |
123 | && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | 120 | && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) |
124 | return 1; | 121 | return 1; |
125 | } | 122 | else |
126 | return 0; | 123 | return 0; |
127 | } | 124 | } |
128 | 125 | ||
129 | static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, | 126 | static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, |
130 | struct bss_descriptor * match_bss) | 127 | struct bss_descriptor *match_bss) |
131 | { | 128 | { |
132 | if ( secinfo->wep_enabled | 129 | if (secinfo->wep_enabled && !secinfo->WPAenabled |
133 | && !secinfo->WPAenabled | 130 | && !secinfo->WPA2enabled |
134 | && !secinfo->WPA2enabled | 131 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) |
135 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | ||
136 | return 1; | 132 | return 1; |
137 | } | 133 | else |
138 | return 0; | 134 | return 0; |
139 | } | 135 | } |
140 | 136 | ||
141 | static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, | 137 | static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, |
142 | struct bss_descriptor * match_bss) | 138 | struct bss_descriptor *match_bss) |
143 | { | 139 | { |
144 | if ( !secinfo->wep_enabled | 140 | if (!secinfo->wep_enabled && secinfo->WPAenabled |
145 | && secinfo->WPAenabled | 141 | && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC) |
146 | && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC) | 142 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G |
147 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G | 143 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ |
148 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | 144 | ) |
149 | */ | ||
150 | ) { | ||
151 | return 1; | 145 | return 1; |
152 | } | 146 | else |
153 | return 0; | 147 | return 0; |
154 | } | 148 | } |
155 | 149 | ||
156 | static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, | 150 | static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, |
157 | struct bss_descriptor * match_bss) | 151 | struct bss_descriptor *match_bss) |
158 | { | 152 | { |
159 | if ( !secinfo->wep_enabled | 153 | if (!secinfo->wep_enabled && secinfo->WPA2enabled |
160 | && secinfo->WPA2enabled | 154 | && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN) |
161 | && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN) | 155 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G |
162 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G | 156 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ |
163 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | 157 | ) |
164 | */ | ||
165 | ) { | ||
166 | return 1; | 158 | return 1; |
167 | } | 159 | else |
168 | return 0; | 160 | return 0; |
169 | } | 161 | } |
170 | 162 | ||
171 | static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, | 163 | static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, |
172 | struct bss_descriptor * match_bss) | 164 | struct bss_descriptor *match_bss) |
173 | { | 165 | { |
174 | if ( !secinfo->wep_enabled | 166 | if (!secinfo->wep_enabled && !secinfo->WPAenabled |
175 | && !secinfo->WPAenabled | 167 | && !secinfo->WPA2enabled |
176 | && !secinfo->WPA2enabled | 168 | && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC) |
177 | && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC) | 169 | && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN) |
178 | && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN) | 170 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) |
179 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | ||
180 | return 1; | 171 | return 1; |
181 | } | 172 | else |
182 | return 0; | 173 | return 0; |
183 | } | 174 | } |
184 | 175 | ||
185 | static inline int is_same_network(struct bss_descriptor *src, | 176 | static inline int is_same_network(struct bss_descriptor *src, |
@@ -214,7 +205,7 @@ static inline int is_same_network(struct bss_descriptor *src, | |||
214 | * @return Index in scantable, or error code if negative | 205 | * @return Index in scantable, or error code if negative |
215 | */ | 206 | */ |
216 | static int is_network_compatible(struct lbs_private *priv, | 207 | static int is_network_compatible(struct lbs_private *priv, |
217 | struct bss_descriptor * bss, u8 mode) | 208 | struct bss_descriptor *bss, uint8_t mode) |
218 | { | 209 | { |
219 | int matched = 0; | 210 | int matched = 0; |
220 | 211 | ||
@@ -228,43 +219,39 @@ static int is_network_compatible(struct lbs_private *priv, | |||
228 | } else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) { | 219 | } else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) { |
229 | goto done; | 220 | goto done; |
230 | } else if ((matched = match_bss_wpa(&priv->secinfo, bss))) { | 221 | } else if ((matched = match_bss_wpa(&priv->secinfo, bss))) { |
231 | lbs_deb_scan( | 222 | lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x " |
232 | "is_network_compatible() WPA: wpa_ie 0x%x " | 223 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " |
233 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " | 224 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], |
234 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], | 225 | priv->secinfo.wep_enabled ? "e" : "d", |
235 | priv->secinfo.wep_enabled ? "e" : "d", | 226 | priv->secinfo.WPAenabled ? "e" : "d", |
236 | priv->secinfo.WPAenabled ? "e" : "d", | 227 | priv->secinfo.WPA2enabled ? "e" : "d", |
237 | priv->secinfo.WPA2enabled ? "e" : "d", | 228 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); |
238 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
239 | goto done; | 229 | goto done; |
240 | } else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) { | 230 | } else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) { |
241 | lbs_deb_scan( | 231 | lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x " |
242 | "is_network_compatible() WPA2: wpa_ie 0x%x " | 232 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " |
243 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " | 233 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], |
244 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], | 234 | priv->secinfo.wep_enabled ? "e" : "d", |
245 | priv->secinfo.wep_enabled ? "e" : "d", | 235 | priv->secinfo.WPAenabled ? "e" : "d", |
246 | priv->secinfo.WPAenabled ? "e" : "d", | 236 | priv->secinfo.WPA2enabled ? "e" : "d", |
247 | priv->secinfo.WPA2enabled ? "e" : "d", | 237 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); |
248 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
249 | goto done; | 238 | goto done; |
250 | } else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) { | 239 | } else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) { |
251 | lbs_deb_scan( | 240 | lbs_deb_scan("is_network_compatible() dynamic WEP: " |
252 | "is_network_compatible() dynamic WEP: " | 241 | "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", |
253 | "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", | 242 | bss->wpa_ie[0], bss->rsn_ie[0], |
254 | bss->wpa_ie[0], bss->rsn_ie[0], | 243 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); |
255 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
256 | goto done; | 244 | goto done; |
257 | } | 245 | } |
258 | 246 | ||
259 | /* bss security settings don't match those configured on card */ | 247 | /* bss security settings don't match those configured on card */ |
260 | lbs_deb_scan( | 248 | lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x " |
261 | "is_network_compatible() FAILED: wpa_ie 0x%x " | 249 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", |
262 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", | 250 | bss->wpa_ie[0], bss->rsn_ie[0], |
263 | bss->wpa_ie[0], bss->rsn_ie[0], | 251 | priv->secinfo.wep_enabled ? "e" : "d", |
264 | priv->secinfo.wep_enabled ? "e" : "d", | 252 | priv->secinfo.WPAenabled ? "e" : "d", |
265 | priv->secinfo.WPAenabled ? "e" : "d", | 253 | priv->secinfo.WPA2enabled ? "e" : "d", |
266 | priv->secinfo.WPA2enabled ? "e" : "d", | 254 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); |
267 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
268 | 255 | ||
269 | done: | 256 | done: |
270 | lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched); | 257 | lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched); |
@@ -311,16 +298,15 @@ void lbs_scan_worker(struct work_struct *work) | |||
311 | * @return void | 298 | * @return void |
312 | */ | 299 | */ |
313 | static int lbs_scan_create_channel_list(struct lbs_private *priv, | 300 | static int lbs_scan_create_channel_list(struct lbs_private *priv, |
314 | struct chanscanparamset * scanchanlist, | 301 | struct chanscanparamset *scanchanlist, |
315 | u8 filteredscan) | 302 | uint8_t filteredscan) |
316 | { | 303 | { |
317 | |||
318 | struct region_channel *scanregion; | 304 | struct region_channel *scanregion; |
319 | struct chan_freq_power *cfp; | 305 | struct chan_freq_power *cfp; |
320 | int rgnidx; | 306 | int rgnidx; |
321 | int chanidx; | 307 | int chanidx; |
322 | int nextchan; | 308 | int nextchan; |
323 | u8 scantype; | 309 | uint8_t scantype; |
324 | 310 | ||
325 | chanidx = 0; | 311 | chanidx = 0; |
326 | 312 | ||
@@ -331,9 +317,8 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
331 | scantype = CMD_SCAN_TYPE_ACTIVE; | 317 | scantype = CMD_SCAN_TYPE_ACTIVE; |
332 | 318 | ||
333 | for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { | 319 | for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { |
334 | if (priv->enable11d && | 320 | if (priv->enable11d && (priv->connect_status != LBS_CONNECTED) |
335 | (priv->connect_status != LBS_CONNECTED) && | 321 | && (priv->mesh_connect_status != LBS_CONNECTED)) { |
336 | (priv->mesh_connect_status != LBS_CONNECTED)) { | ||
337 | /* Scan all the supported chan for the first scan */ | 322 | /* Scan all the supported chan for the first scan */ |
338 | if (!priv->universal_channel[rgnidx].valid) | 323 | if (!priv->universal_channel[rgnidx].valid) |
339 | continue; | 324 | continue; |
@@ -348,45 +333,30 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
348 | scanregion = &priv->region_channel[rgnidx]; | 333 | scanregion = &priv->region_channel[rgnidx]; |
349 | } | 334 | } |
350 | 335 | ||
351 | for (nextchan = 0; | 336 | for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) { |
352 | nextchan < scanregion->nrcfp; nextchan++, chanidx++) { | 337 | struct chanscanparamset *chan = &scanchanlist[chanidx]; |
353 | 338 | ||
354 | cfp = scanregion->CFP + nextchan; | 339 | cfp = scanregion->CFP + nextchan; |
355 | 340 | ||
356 | if (priv->enable11d) { | 341 | if (priv->enable11d) |
357 | scantype = | 342 | scantype = lbs_get_scan_type_11d(cfp->channel, |
358 | lbs_get_scan_type_11d(cfp->channel, | 343 | &priv->parsed_region_chan); |
359 | &priv-> | ||
360 | parsed_region_chan); | ||
361 | } | ||
362 | 344 | ||
363 | switch (scanregion->band) { | 345 | if (scanregion->band == BAND_B || scanregion->band == BAND_G) |
364 | case BAND_B: | 346 | chan->radiotype = CMD_SCAN_RADIO_TYPE_BG; |
365 | case BAND_G: | ||
366 | default: | ||
367 | scanchanlist[chanidx].radiotype = | ||
368 | CMD_SCAN_RADIO_TYPE_BG; | ||
369 | break; | ||
370 | } | ||
371 | 347 | ||
372 | if (scantype == CMD_SCAN_TYPE_PASSIVE) { | 348 | if (scantype == CMD_SCAN_TYPE_PASSIVE) { |
373 | scanchanlist[chanidx].maxscantime = | 349 | chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); |
374 | cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); | 350 | chan->chanscanmode.passivescan = 1; |
375 | scanchanlist[chanidx].chanscanmode.passivescan = | ||
376 | 1; | ||
377 | } else { | 351 | } else { |
378 | scanchanlist[chanidx].maxscantime = | 352 | chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); |
379 | cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); | 353 | chan->chanscanmode.passivescan = 0; |
380 | scanchanlist[chanidx].chanscanmode.passivescan = | ||
381 | 0; | ||
382 | } | 354 | } |
383 | 355 | ||
384 | scanchanlist[chanidx].channumber = cfp->channel; | 356 | chan->channumber = cfp->channel; |
385 | 357 | ||
386 | if (filteredscan) { | 358 | if (filteredscan) |
387 | scanchanlist[chanidx].chanscanmode. | 359 | chan->chanscanmode.disablechanfilt = 1; |
388 | disablechanfilt = 1; | ||
389 | } | ||
390 | } | 360 | } |
391 | } | 361 | } |
392 | return chanidx; | 362 | return chanidx; |
@@ -400,11 +370,11 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
400 | * length 06 00 | 370 | * length 06 00 |
401 | * ssid 4d 4e 54 45 53 54 | 371 | * ssid 4d 4e 54 45 53 54 |
402 | */ | 372 | */ |
403 | static int lbs_scan_add_ssid_tlv(u8 *tlv, | 373 | static int lbs_scan_add_ssid_tlv(uint8_t *tlv, |
404 | const struct lbs_ioctl_user_scan_cfg *user_cfg) | 374 | const struct lbs_ioctl_user_scan_cfg *user_cfg) |
405 | { | 375 | { |
406 | struct mrvlietypes_ssidparamset *ssid_tlv = | 376 | struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv; |
407 | (struct mrvlietypes_ssidparamset *)tlv; | 377 | |
408 | ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); | 378 | ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); |
409 | ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len); | 379 | ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len); |
410 | memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len); | 380 | memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len); |
@@ -437,13 +407,12 @@ static int lbs_scan_add_ssid_tlv(u8 *tlv, | |||
437 | * channel 13 00 0d 00 00 00 64 00 | 407 | * channel 13 00 0d 00 00 00 64 00 |
438 | * | 408 | * |
439 | */ | 409 | */ |
440 | static int lbs_scan_add_chanlist_tlv(u8 *tlv, | 410 | static int lbs_scan_add_chanlist_tlv(uint8_t *tlv, |
441 | struct chanscanparamset *chan_list, | 411 | struct chanscanparamset *chan_list, |
442 | int chan_count) | 412 | int chan_count) |
443 | { | 413 | { |
444 | size_t size = sizeof(struct chanscanparamset) * chan_count; | 414 | size_t size = sizeof(struct chanscanparamset) *chan_count; |
445 | struct mrvlietypes_chanlistparamset *chan_tlv = | 415 | struct mrvlietypes_chanlistparamset *chan_tlv = (void *)tlv; |
446 | (struct mrvlietypes_chanlistparamset *) tlv; | ||
447 | 416 | ||
448 | chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); | 417 | chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); |
449 | memcpy(chan_tlv->chanscanparam, chan_list, size); | 418 | memcpy(chan_tlv->chanscanparam, chan_list, size); |
@@ -462,11 +431,10 @@ static int lbs_scan_add_chanlist_tlv(u8 *tlv, | |||
462 | * The rates are in lbs_bg_rates[], but for the 802.11b | 431 | * The rates are in lbs_bg_rates[], but for the 802.11b |
463 | * rates the high bit isn't set. | 432 | * rates the high bit isn't set. |
464 | */ | 433 | */ |
465 | static int lbs_scan_add_rates_tlv(u8 *tlv) | 434 | static int lbs_scan_add_rates_tlv(uint8_t *tlv) |
466 | { | 435 | { |
467 | int i; | 436 | int i; |
468 | struct mrvlietypes_ratesparamset *rate_tlv = | 437 | struct mrvlietypes_ratesparamset *rate_tlv = (void *)tlv; |
469 | (struct mrvlietypes_ratesparamset *) tlv; | ||
470 | 438 | ||
471 | rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); | 439 | rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); |
472 | tlv += sizeof(rate_tlv->header); | 440 | tlv += sizeof(rate_tlv->header); |
@@ -492,24 +460,22 @@ static int lbs_scan_add_rates_tlv(u8 *tlv) | |||
492 | * Generate the CMD_802_11_SCAN command with the proper tlv | 460 | * Generate the CMD_802_11_SCAN command with the proper tlv |
493 | * for a bunch of channels. | 461 | * for a bunch of channels. |
494 | */ | 462 | */ |
495 | static int lbs_do_scan(struct lbs_private *priv, | 463 | static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, |
496 | u8 bsstype, | 464 | struct chanscanparamset *chan_list, int chan_count, |
497 | struct chanscanparamset *chan_list, | 465 | const struct lbs_ioctl_user_scan_cfg *user_cfg) |
498 | int chan_count, | ||
499 | const struct lbs_ioctl_user_scan_cfg *user_cfg) | ||
500 | { | 466 | { |
501 | int ret = -ENOMEM; | 467 | int ret = -ENOMEM; |
502 | struct lbs_scan_cmd_config *scan_cmd; | 468 | struct cmd_ds_802_11_scan *scan_cmd; |
503 | u8 *tlv; /* pointer into our current, growing TLV storage area */ | 469 | uint8_t *tlv; /* pointer into our current, growing TLV storage area */ |
504 | 470 | ||
505 | lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, " | 471 | lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d", |
506 | "chan_count %d", | 472 | bsstype, chan_list[0].channumber, chan_count); |
507 | bsstype, chan_list[0].channumber, chan_count); | ||
508 | 473 | ||
509 | /* create the fixed part for scan command */ | 474 | /* create the fixed part for scan command */ |
510 | scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL); | 475 | scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL); |
511 | if (scan_cmd == NULL) | 476 | if (scan_cmd == NULL) |
512 | goto out; | 477 | goto out; |
478 | |||
513 | tlv = scan_cmd->tlvbuffer; | 479 | tlv = scan_cmd->tlvbuffer; |
514 | if (user_cfg) | 480 | if (user_cfg) |
515 | memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN); | 481 | memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN); |
@@ -523,13 +489,16 @@ static int lbs_do_scan(struct lbs_private *priv, | |||
523 | tlv += lbs_scan_add_rates_tlv(tlv); | 489 | tlv += lbs_scan_add_rates_tlv(tlv); |
524 | 490 | ||
525 | /* This is the final data we are about to send */ | 491 | /* This is the final data we are about to send */ |
526 | scan_cmd->tlvbufferlen = tlv - scan_cmd->tlvbuffer; | 492 | scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd); |
527 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, 1+6); | 493 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, |
494 | sizeof(*scan_cmd)); | ||
528 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer, | 495 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer, |
529 | scan_cmd->tlvbufferlen); | 496 | tlv - scan_cmd->tlvbuffer); |
497 | |||
498 | ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr, | ||
499 | le16_to_cpu(scan_cmd->hdr.size), | ||
500 | lbs_ret_80211_scan, 0); | ||
530 | 501 | ||
531 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, 0, | ||
532 | CMD_OPTION_WAITFORRSP, 0, scan_cmd); | ||
533 | out: | 502 | out: |
534 | kfree(scan_cmd); | 503 | kfree(scan_cmd); |
535 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | 504 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); |
@@ -553,14 +522,14 @@ out: | |||
553 | * @return 0 or < 0 if error | 522 | * @return 0 or < 0 if error |
554 | */ | 523 | */ |
555 | int lbs_scan_networks(struct lbs_private *priv, | 524 | int lbs_scan_networks(struct lbs_private *priv, |
556 | const struct lbs_ioctl_user_scan_cfg *user_cfg, | 525 | const struct lbs_ioctl_user_scan_cfg *user_cfg, |
557 | int full_scan) | 526 | int full_scan) |
558 | { | 527 | { |
559 | int ret = -ENOMEM; | 528 | int ret = -ENOMEM; |
560 | struct chanscanparamset *chan_list; | 529 | struct chanscanparamset *chan_list; |
561 | struct chanscanparamset *curr_chans; | 530 | struct chanscanparamset *curr_chans; |
562 | int chan_count; | 531 | int chan_count; |
563 | u8 bsstype = CMD_BSS_TYPE_ANY; | 532 | uint8_t bsstype = CMD_BSS_TYPE_ANY; |
564 | int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; | 533 | int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; |
565 | int filteredscan = 0; | 534 | int filteredscan = 0; |
566 | union iwreq_data wrqu; | 535 | union iwreq_data wrqu; |
@@ -570,8 +539,7 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
570 | DECLARE_MAC_BUF(mac); | 539 | DECLARE_MAC_BUF(mac); |
571 | #endif | 540 | #endif |
572 | 541 | ||
573 | lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", | 542 | lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan); |
574 | full_scan); | ||
575 | 543 | ||
576 | /* Cancel any partial outstanding partial scans if this scan | 544 | /* Cancel any partial outstanding partial scans if this scan |
577 | * is a full scan. | 545 | * is a full scan. |
@@ -583,26 +551,24 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
583 | if (user_cfg) { | 551 | if (user_cfg) { |
584 | if (user_cfg->bsstype) | 552 | if (user_cfg->bsstype) |
585 | bsstype = user_cfg->bsstype; | 553 | bsstype = user_cfg->bsstype; |
586 | if (compare_ether_addr(user_cfg->bssid, &zeromac[0]) != 0) { | 554 | if (!is_zero_ether_addr(user_cfg->bssid)) { |
587 | numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN; | 555 | numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN; |
588 | filteredscan = 1; | 556 | filteredscan = 1; |
589 | } | 557 | } |
590 | } | 558 | } |
591 | lbs_deb_scan("numchannels %d, bsstype %d, " | 559 | lbs_deb_scan("numchannels %d, bsstype %d, filteredscan %d\n", |
592 | "filteredscan %d\n", | 560 | numchannels, bsstype, filteredscan); |
593 | numchannels, bsstype, filteredscan); | ||
594 | 561 | ||
595 | /* Create list of channels to scan */ | 562 | /* Create list of channels to scan */ |
596 | chan_list = kzalloc(sizeof(struct chanscanparamset) * | 563 | chan_list = kzalloc(sizeof(struct chanscanparamset) * |
597 | LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); | 564 | LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); |
598 | if (!chan_list) { | 565 | if (!chan_list) { |
599 | lbs_pr_alert("SCAN: chan_list empty\n"); | 566 | lbs_pr_alert("SCAN: chan_list empty\n"); |
600 | goto out; | 567 | goto out; |
601 | } | 568 | } |
602 | 569 | ||
603 | /* We want to scan all channels */ | 570 | /* We want to scan all channels */ |
604 | chan_count = lbs_scan_create_channel_list(priv, chan_list, | 571 | chan_count = lbs_scan_create_channel_list(priv, chan_list, filteredscan); |
605 | filteredscan); | ||
606 | 572 | ||
607 | netif_stop_queue(priv->dev); | 573 | netif_stop_queue(priv->dev); |
608 | netif_carrier_off(priv->dev); | 574 | netif_carrier_off(priv->dev); |
@@ -629,9 +595,9 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
629 | while (chan_count) { | 595 | while (chan_count) { |
630 | int to_scan = min(numchannels, chan_count); | 596 | int to_scan = min(numchannels, chan_count); |
631 | lbs_deb_scan("scanning %d of %d channels\n", | 597 | lbs_deb_scan("scanning %d of %d channels\n", |
632 | to_scan, chan_count); | 598 | to_scan, chan_count); |
633 | ret = lbs_do_scan(priv, bsstype, curr_chans, | 599 | ret = lbs_do_scan(priv, bsstype, curr_chans, |
634 | to_scan, user_cfg); | 600 | to_scan, user_cfg); |
635 | if (ret) { | 601 | if (ret) { |
636 | lbs_pr_err("SCAN_CMD failed\n"); | 602 | lbs_pr_err("SCAN_CMD failed\n"); |
637 | goto out2; | 603 | goto out2; |
@@ -640,8 +606,7 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
640 | chan_count -= to_scan; | 606 | chan_count -= to_scan; |
641 | 607 | ||
642 | /* somehow schedule the next part of the scan */ | 608 | /* somehow schedule the next part of the scan */ |
643 | if (chan_count && | 609 | if (chan_count && !full_scan && |
644 | !full_scan && | ||
645 | !priv->surpriseremoved) { | 610 | !priv->surpriseremoved) { |
646 | /* -1 marks just that we're currently scanning */ | 611 | /* -1 marks just that we're currently scanning */ |
647 | if (priv->scan_channel < 0) | 612 | if (priv->scan_channel < 0) |
@@ -650,7 +615,7 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
650 | priv->scan_channel += to_scan; | 615 | priv->scan_channel += to_scan; |
651 | cancel_delayed_work(&priv->scan_work); | 616 | cancel_delayed_work(&priv->scan_work); |
652 | queue_delayed_work(priv->work_thread, &priv->scan_work, | 617 | queue_delayed_work(priv->work_thread, &priv->scan_work, |
653 | msecs_to_jiffies(300)); | 618 | msecs_to_jiffies(300)); |
654 | /* skip over GIWSCAN event */ | 619 | /* skip over GIWSCAN event */ |
655 | goto out; | 620 | goto out; |
656 | } | 621 | } |
@@ -665,8 +630,8 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
665 | lbs_deb_scan("scan table:\n"); | 630 | lbs_deb_scan("scan table:\n"); |
666 | list_for_each_entry(iter, &priv->network_list, list) | 631 | list_for_each_entry(iter, &priv->network_list, list) |
667 | lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n", | 632 | lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n", |
668 | i++, print_mac(mac, iter->bssid), (s32) iter->rssi, | 633 | i++, print_mac(mac, iter->bssid), (int)iter->rssi, |
669 | escape_essid(iter->ssid, iter->ssid_len)); | 634 | escape_essid(iter->ssid, iter->ssid_len)); |
670 | mutex_unlock(&priv->lock); | 635 | mutex_unlock(&priv->lock); |
671 | #endif | 636 | #endif |
672 | 637 | ||
@@ -711,7 +676,7 @@ out: | |||
711 | * @return 0 or -1 | 676 | * @return 0 or -1 |
712 | */ | 677 | */ |
713 | static int lbs_process_bss(struct bss_descriptor *bss, | 678 | static int lbs_process_bss(struct bss_descriptor *bss, |
714 | u8 ** pbeaconinfo, int *bytesleft) | 679 | uint8_t **pbeaconinfo, int *bytesleft) |
715 | { | 680 | { |
716 | struct ieeetypes_fhparamset *pFH; | 681 | struct ieeetypes_fhparamset *pFH; |
717 | struct ieeetypes_dsparamset *pDS; | 682 | struct ieeetypes_dsparamset *pDS; |
@@ -719,9 +684,9 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
719 | struct ieeetypes_ibssparamset *pibss; | 684 | struct ieeetypes_ibssparamset *pibss; |
720 | DECLARE_MAC_BUF(mac); | 685 | DECLARE_MAC_BUF(mac); |
721 | struct ieeetypes_countryinfoset *pcountryinfo; | 686 | struct ieeetypes_countryinfoset *pcountryinfo; |
722 | u8 *pos, *end, *p; | 687 | uint8_t *pos, *end, *p; |
723 | u8 n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; | 688 | uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; |
724 | u16 beaconsize = 0; | 689 | uint16_t beaconsize = 0; |
725 | int ret; | 690 | int ret; |
726 | 691 | ||
727 | lbs_deb_enter(LBS_DEB_SCAN); | 692 | lbs_deb_enter(LBS_DEB_SCAN); |
@@ -793,12 +758,11 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
793 | 758 | ||
794 | /* process variable IE */ | 759 | /* process variable IE */ |
795 | while (pos <= end - 2) { | 760 | while (pos <= end - 2) { |
796 | struct ieee80211_info_element * elem = | 761 | struct ieee80211_info_element * elem = (void *)pos; |
797 | (struct ieee80211_info_element *) pos; | ||
798 | 762 | ||
799 | if (pos + elem->len > end) { | 763 | if (pos + elem->len > end) { |
800 | lbs_deb_scan("process_bss: error in processing IE, " | 764 | lbs_deb_scan("process_bss: error in processing IE, " |
801 | "bytes left < IE length\n"); | 765 | "bytes left < IE length\n"); |
802 | break; | 766 | break; |
803 | } | 767 | } |
804 | 768 | ||
@@ -812,7 +776,7 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
812 | break; | 776 | break; |
813 | 777 | ||
814 | case MFIE_TYPE_RATES: | 778 | case MFIE_TYPE_RATES: |
815 | n_basic_rates = min_t(u8, MAX_RATES, elem->len); | 779 | n_basic_rates = min_t(uint8_t, MAX_RATES, elem->len); |
816 | memcpy(bss->rates, elem->data, n_basic_rates); | 780 | memcpy(bss->rates, elem->data, n_basic_rates); |
817 | got_basic_rates = 1; | 781 | got_basic_rates = 1; |
818 | lbs_deb_scan("got RATES IE\n"); | 782 | lbs_deb_scan("got RATES IE\n"); |
@@ -853,19 +817,16 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
853 | lbs_deb_scan("got COUNTRY IE\n"); | 817 | lbs_deb_scan("got COUNTRY IE\n"); |
854 | if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) | 818 | if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) |
855 | || pcountryinfo->len > 254) { | 819 | || pcountryinfo->len > 254) { |
856 | lbs_deb_scan("process_bss: 11D- Err " | 820 | lbs_deb_scan("process_bss: 11D- Err CountryInfo len %d, min %zd, max 254\n", |
857 | "CountryInfo len %d, min %zd, max 254\n", | 821 | pcountryinfo->len, sizeof(pcountryinfo->countrycode)); |
858 | pcountryinfo->len, | ||
859 | sizeof(pcountryinfo->countrycode)); | ||
860 | ret = -1; | 822 | ret = -1; |
861 | goto done; | 823 | goto done; |
862 | } | 824 | } |
863 | 825 | ||
864 | memcpy(&bss->countryinfo, | 826 | memcpy(&bss->countryinfo, pcountryinfo, pcountryinfo->len + 2); |
865 | pcountryinfo, pcountryinfo->len + 2); | ||
866 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo", | 827 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo", |
867 | (u8 *) pcountryinfo, | 828 | (uint8_t *) pcountryinfo, |
868 | (u32) (pcountryinfo->len + 2)); | 829 | (int) (pcountryinfo->len + 2)); |
869 | break; | 830 | break; |
870 | 831 | ||
871 | case MFIE_TYPE_RATES_EX: | 832 | case MFIE_TYPE_RATES_EX: |
@@ -889,26 +850,19 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
889 | 850 | ||
890 | case MFIE_TYPE_GENERIC: | 851 | case MFIE_TYPE_GENERIC: |
891 | if (elem->len >= 4 && | 852 | if (elem->len >= 4 && |
892 | elem->data[0] == 0x00 && | 853 | elem->data[0] == 0x00 && elem->data[1] == 0x50 && |
893 | elem->data[1] == 0x50 && | 854 | elem->data[2] == 0xf2 && elem->data[3] == 0x01) { |
894 | elem->data[2] == 0xf2 && | 855 | bss->wpa_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); |
895 | elem->data[3] == 0x01) { | ||
896 | bss->wpa_ie_len = min(elem->len + 2, | ||
897 | MAX_WPA_IE_LEN); | ||
898 | memcpy(bss->wpa_ie, elem, bss->wpa_ie_len); | 856 | memcpy(bss->wpa_ie, elem, bss->wpa_ie_len); |
899 | lbs_deb_scan("got WPA IE\n"); | 857 | lbs_deb_scan("got WPA IE\n"); |
900 | lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, | 858 | lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, elem->len); |
901 | elem->len); | ||
902 | } else if (elem->len >= MARVELL_MESH_IE_LENGTH && | 859 | } else if (elem->len >= MARVELL_MESH_IE_LENGTH && |
903 | elem->data[0] == 0x00 && | 860 | elem->data[0] == 0x00 && elem->data[1] == 0x50 && |
904 | elem->data[1] == 0x50 && | 861 | elem->data[2] == 0x43 && elem->data[3] == 0x04) { |
905 | elem->data[2] == 0x43 && | ||
906 | elem->data[3] == 0x04) { | ||
907 | lbs_deb_scan("got mesh IE\n"); | 862 | lbs_deb_scan("got mesh IE\n"); |
908 | bss->mesh = 1; | 863 | bss->mesh = 1; |
909 | } else { | 864 | } else { |
910 | lbs_deb_scan("got generiec IE: " | 865 | lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n", |
911 | "%02x:%02x:%02x:%02x, len %d\n", | ||
912 | elem->data[0], elem->data[1], | 866 | elem->data[0], elem->data[1], |
913 | elem->data[2], elem->data[3], | 867 | elem->data[2], elem->data[3], |
914 | elem->len); | 868 | elem->len); |
@@ -920,12 +874,12 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
920 | bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); | 874 | bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); |
921 | memcpy(bss->rsn_ie, elem, bss->rsn_ie_len); | 875 | memcpy(bss->rsn_ie, elem, bss->rsn_ie_len); |
922 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", | 876 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", |
923 | bss->rsn_ie, elem->len); | 877 | bss->rsn_ie, elem->len); |
924 | break; | 878 | break; |
925 | 879 | ||
926 | default: | 880 | default: |
927 | lbs_deb_scan("got IE 0x%04x, len %d\n", | 881 | lbs_deb_scan("got IE 0x%04x, len %d\n", |
928 | elem->id, elem->len); | 882 | elem->id, elem->len); |
929 | break; | 883 | break; |
930 | } | 884 | } |
931 | 885 | ||
@@ -955,18 +909,17 @@ done: | |||
955 | * @return index in BSSID list, or error return code (< 0) | 909 | * @return index in BSSID list, or error return code (< 0) |
956 | */ | 910 | */ |
957 | struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv, | 911 | struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv, |
958 | u8 * bssid, u8 mode) | 912 | uint8_t *bssid, uint8_t mode) |
959 | { | 913 | { |
960 | struct bss_descriptor * iter_bss; | 914 | struct bss_descriptor *iter_bss; |
961 | struct bss_descriptor * found_bss = NULL; | 915 | struct bss_descriptor *found_bss = NULL; |
962 | 916 | ||
963 | lbs_deb_enter(LBS_DEB_SCAN); | 917 | lbs_deb_enter(LBS_DEB_SCAN); |
964 | 918 | ||
965 | if (!bssid) | 919 | if (!bssid) |
966 | goto out; | 920 | goto out; |
967 | 921 | ||
968 | lbs_deb_hex(LBS_DEB_SCAN, "looking for", | 922 | lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN); |
969 | bssid, ETH_ALEN); | ||
970 | 923 | ||
971 | /* Look through the scan table for a compatible match. The loop will | 924 | /* Look through the scan table for a compatible match. The loop will |
972 | * continue past a matched bssid that is not compatible in case there | 925 | * continue past a matched bssid that is not compatible in case there |
@@ -1008,10 +961,11 @@ out: | |||
1008 | * @return index in BSSID list | 961 | * @return index in BSSID list |
1009 | */ | 962 | */ |
1010 | struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, | 963 | struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, |
1011 | u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode, | 964 | uint8_t *ssid, uint8_t ssid_len, |
1012 | int channel) | 965 | uint8_t *bssid, uint8_t mode, |
966 | int channel) | ||
1013 | { | 967 | { |
1014 | u8 bestrssi = 0; | 968 | uint8_t bestrssi = 0; |
1015 | struct bss_descriptor * iter_bss = NULL; | 969 | struct bss_descriptor * iter_bss = NULL; |
1016 | struct bss_descriptor * found_bss = NULL; | 970 | struct bss_descriptor * found_bss = NULL; |
1017 | struct bss_descriptor * tmp_oldest = NULL; | 971 | struct bss_descriptor * tmp_oldest = NULL; |
@@ -1026,7 +980,7 @@ struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, | |||
1026 | tmp_oldest = iter_bss; | 980 | tmp_oldest = iter_bss; |
1027 | 981 | ||
1028 | if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, | 982 | if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, |
1029 | ssid, ssid_len) != 0) | 983 | ssid, ssid_len) != 0) |
1030 | continue; /* ssid doesn't match */ | 984 | continue; /* ssid doesn't match */ |
1031 | if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) | 985 | if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) |
1032 | continue; /* bssid doesn't match */ | 986 | continue; /* bssid doesn't match */ |
@@ -1076,13 +1030,12 @@ out: | |||
1076 | * | 1030 | * |
1077 | * @return index in BSSID list | 1031 | * @return index in BSSID list |
1078 | */ | 1032 | */ |
1079 | static struct bss_descriptor *lbs_find_best_ssid_in_list( | 1033 | static struct bss_descriptor *lbs_find_best_ssid_in_list(struct lbs_private *priv, |
1080 | struct lbs_private *priv, | 1034 | uint8_t mode) |
1081 | u8 mode) | ||
1082 | { | 1035 | { |
1083 | u8 bestrssi = 0; | 1036 | uint8_t bestrssi = 0; |
1084 | struct bss_descriptor * iter_bss; | 1037 | struct bss_descriptor *iter_bss; |
1085 | struct bss_descriptor * best_bss = NULL; | 1038 | struct bss_descriptor *best_bss = NULL; |
1086 | 1039 | ||
1087 | lbs_deb_enter(LBS_DEB_SCAN); | 1040 | lbs_deb_enter(LBS_DEB_SCAN); |
1088 | 1041 | ||
@@ -1124,11 +1077,12 @@ static struct bss_descriptor *lbs_find_best_ssid_in_list( | |||
1124 | * | 1077 | * |
1125 | * @return 0--success, otherwise--fail | 1078 | * @return 0--success, otherwise--fail |
1126 | */ | 1079 | */ |
1127 | int lbs_find_best_network_ssid(struct lbs_private *priv, | 1080 | int lbs_find_best_network_ssid(struct lbs_private *priv, uint8_t *out_ssid, |
1128 | u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode) | 1081 | uint8_t *out_ssid_len, uint8_t preferred_mode, |
1082 | uint8_t *out_mode) | ||
1129 | { | 1083 | { |
1130 | int ret = -1; | 1084 | int ret = -1; |
1131 | struct bss_descriptor * found; | 1085 | struct bss_descriptor *found; |
1132 | 1086 | ||
1133 | lbs_deb_enter(LBS_DEB_SCAN); | 1087 | lbs_deb_enter(LBS_DEB_SCAN); |
1134 | 1088 | ||
@@ -1163,14 +1117,14 @@ out: | |||
1163 | * | 1117 | * |
1164 | * @return 0-success, otherwise fail | 1118 | * @return 0-success, otherwise fail |
1165 | */ | 1119 | */ |
1166 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, | 1120 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, |
1167 | u8 *ssid, u8 ssid_len, u8 clear_ssid) | 1121 | uint8_t ssid_len, uint8_t clear_ssid) |
1168 | { | 1122 | { |
1169 | struct lbs_ioctl_user_scan_cfg scancfg; | 1123 | struct lbs_ioctl_user_scan_cfg scancfg; |
1170 | int ret = 0; | 1124 | int ret = 0; |
1171 | 1125 | ||
1172 | lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d", | 1126 | lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d", |
1173 | escape_essid(ssid, ssid_len), clear_ssid); | 1127 | escape_essid(ssid, ssid_len), clear_ssid); |
1174 | 1128 | ||
1175 | if (!ssid_len) | 1129 | if (!ssid_len) |
1176 | goto out; | 1130 | goto out; |
@@ -1204,17 +1158,17 @@ out: | |||
1204 | #define MAX_CUSTOM_LEN 64 | 1158 | #define MAX_CUSTOM_LEN 64 |
1205 | 1159 | ||
1206 | static inline char *lbs_translate_scan(struct lbs_private *priv, | 1160 | static inline char *lbs_translate_scan(struct lbs_private *priv, |
1207 | char *start, char *stop, | 1161 | char *start, char *stop, |
1208 | struct bss_descriptor *bss) | 1162 | struct bss_descriptor *bss) |
1209 | { | 1163 | { |
1210 | struct chan_freq_power *cfp; | 1164 | struct chan_freq_power *cfp; |
1211 | char *current_val; /* For rates */ | 1165 | char *current_val; /* For rates */ |
1212 | struct iw_event iwe; /* Temporary buffer */ | 1166 | struct iw_event iwe; /* Temporary buffer */ |
1213 | int j; | 1167 | int j; |
1214 | #define PERFECT_RSSI ((u8)50) | 1168 | #define PERFECT_RSSI ((uint8_t)50) |
1215 | #define WORST_RSSI ((u8)0) | 1169 | #define WORST_RSSI ((uint8_t)0) |
1216 | #define RSSI_DIFF ((u8)(PERFECT_RSSI - WORST_RSSI)) | 1170 | #define RSSI_DIFF ((uint8_t)(PERFECT_RSSI - WORST_RSSI)) |
1217 | u8 rssi; | 1171 | uint8_t rssi; |
1218 | 1172 | ||
1219 | lbs_deb_enter(LBS_DEB_SCAN); | 1173 | lbs_deb_enter(LBS_DEB_SCAN); |
1220 | 1174 | ||
@@ -1234,7 +1188,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1234 | /* SSID */ | 1188 | /* SSID */ |
1235 | iwe.cmd = SIOCGIWESSID; | 1189 | iwe.cmd = SIOCGIWESSID; |
1236 | iwe.u.data.flags = 1; | 1190 | iwe.u.data.flags = 1; |
1237 | iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE); | 1191 | iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE); |
1238 | start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); | 1192 | start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); |
1239 | 1193 | ||
1240 | /* Mode */ | 1194 | /* Mode */ |
@@ -1255,28 +1209,26 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1255 | 1209 | ||
1256 | rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE; | 1210 | rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE; |
1257 | iwe.u.qual.qual = | 1211 | iwe.u.qual.qual = |
1258 | (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * | 1212 | (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * |
1259 | (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / | 1213 | (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / |
1260 | (RSSI_DIFF * RSSI_DIFF); | 1214 | (RSSI_DIFF * RSSI_DIFF); |
1261 | if (iwe.u.qual.qual > 100) | 1215 | if (iwe.u.qual.qual > 100) |
1262 | iwe.u.qual.qual = 100; | 1216 | iwe.u.qual.qual = 100; |
1263 | 1217 | ||
1264 | if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { | 1218 | if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { |
1265 | iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; | 1219 | iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; |
1266 | } else { | 1220 | } else { |
1267 | iwe.u.qual.noise = | 1221 | iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); |
1268 | CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); | ||
1269 | } | 1222 | } |
1270 | 1223 | ||
1271 | /* Locally created ad-hoc BSSs won't have beacons if this is the | 1224 | /* Locally created ad-hoc BSSs won't have beacons if this is the |
1272 | * only station in the adhoc network; so get signal strength | 1225 | * only station in the adhoc network; so get signal strength |
1273 | * from receive statistics. | 1226 | * from receive statistics. |
1274 | */ | 1227 | */ |
1275 | if ((priv->mode == IW_MODE_ADHOC) | 1228 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate |
1276 | && priv->adhoccreate | ||
1277 | && !lbs_ssid_cmp(priv->curbssparams.ssid, | 1229 | && !lbs_ssid_cmp(priv->curbssparams.ssid, |
1278 | priv->curbssparams.ssid_len, | 1230 | priv->curbssparams.ssid_len, |
1279 | bss->ssid, bss->ssid_len)) { | 1231 | bss->ssid, bss->ssid_len)) { |
1280 | int snr, nf; | 1232 | int snr, nf; |
1281 | snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; | 1233 | snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; |
1282 | nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; | 1234 | nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; |
@@ -1307,14 +1259,13 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1307 | current_val = iwe_stream_add_value(start, current_val, | 1259 | current_val = iwe_stream_add_value(start, current_val, |
1308 | stop, &iwe, IW_EV_PARAM_LEN); | 1260 | stop, &iwe, IW_EV_PARAM_LEN); |
1309 | } | 1261 | } |
1310 | if ((bss->mode == IW_MODE_ADHOC) | 1262 | if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate |
1311 | && !lbs_ssid_cmp(priv->curbssparams.ssid, | 1263 | && !lbs_ssid_cmp(priv->curbssparams.ssid, |
1312 | priv->curbssparams.ssid_len, | 1264 | priv->curbssparams.ssid_len, |
1313 | bss->ssid, bss->ssid_len) | 1265 | bss->ssid, bss->ssid_len)) { |
1314 | && priv->adhoccreate) { | ||
1315 | iwe.u.bitrate.value = 22 * 500000; | 1266 | iwe.u.bitrate.value = 22 * 500000; |
1316 | current_val = iwe_stream_add_value(start, current_val, | 1267 | current_val = iwe_stream_add_value(start, current_val, |
1317 | stop, &iwe, IW_EV_PARAM_LEN); | 1268 | stop, &iwe, IW_EV_PARAM_LEN); |
1318 | } | 1269 | } |
1319 | /* Check if we added any event */ | 1270 | /* Check if we added any event */ |
1320 | if((current_val - start) > IW_EV_LCP_LEN) | 1271 | if((current_val - start) > IW_EV_LCP_LEN) |
@@ -1343,8 +1294,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1343 | char *p = custom; | 1294 | char *p = custom; |
1344 | 1295 | ||
1345 | iwe.cmd = IWEVCUSTOM; | 1296 | iwe.cmd = IWEVCUSTOM; |
1346 | p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), | 1297 | p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc"); |
1347 | "mesh-type: olpc"); | ||
1348 | iwe.u.data.length = p - custom; | 1298 | iwe.u.data.length = p - custom; |
1349 | if (iwe.u.data.length) | 1299 | if (iwe.u.data.length) |
1350 | start = iwe_stream_add_point(start, stop, &iwe, custom); | 1300 | start = iwe_stream_add_point(start, stop, &iwe, custom); |
@@ -1367,7 +1317,7 @@ out: | |||
1367 | * @return 0 --success, otherwise fail | 1317 | * @return 0 --success, otherwise fail |
1368 | */ | 1318 | */ |
1369 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | 1319 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, |
1370 | struct iw_param *wrqu, char *extra) | 1320 | struct iw_param *wrqu, char *extra) |
1371 | { | 1321 | { |
1372 | struct lbs_private *priv = dev->priv; | 1322 | struct lbs_private *priv = dev->priv; |
1373 | 1323 | ||
@@ -1391,7 +1341,7 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | |||
1391 | 1341 | ||
1392 | if (!delayed_work_pending(&priv->scan_work)) | 1342 | if (!delayed_work_pending(&priv->scan_work)) |
1393 | queue_delayed_work(priv->work_thread, &priv->scan_work, | 1343 | queue_delayed_work(priv->work_thread, &priv->scan_work, |
1394 | msecs_to_jiffies(50)); | 1344 | msecs_to_jiffies(50)); |
1395 | /* set marker that currently a scan is taking place */ | 1345 | /* set marker that currently a scan is taking place */ |
1396 | priv->scan_channel = -1; | 1346 | priv->scan_channel = -1; |
1397 | 1347 | ||
@@ -1414,15 +1364,15 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | |||
1414 | * @return 0 --success, otherwise fail | 1364 | * @return 0 --success, otherwise fail |
1415 | */ | 1365 | */ |
1416 | int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | 1366 | int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, |
1417 | struct iw_point *dwrq, char *extra) | 1367 | struct iw_point *dwrq, char *extra) |
1418 | { | 1368 | { |
1419 | #define SCAN_ITEM_SIZE 128 | 1369 | #define SCAN_ITEM_SIZE 128 |
1420 | struct lbs_private *priv = dev->priv; | 1370 | struct lbs_private *priv = dev->priv; |
1421 | int err = 0; | 1371 | int err = 0; |
1422 | char *ev = extra; | 1372 | char *ev = extra; |
1423 | char *stop = ev + dwrq->length; | 1373 | char *stop = ev + dwrq->length; |
1424 | struct bss_descriptor * iter_bss; | 1374 | struct bss_descriptor *iter_bss; |
1425 | struct bss_descriptor * safe; | 1375 | struct bss_descriptor *safe; |
1426 | 1376 | ||
1427 | lbs_deb_enter(LBS_DEB_SCAN); | 1377 | lbs_deb_enter(LBS_DEB_SCAN); |
1428 | 1378 | ||
@@ -1431,14 +1381,13 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1431 | return -EAGAIN; | 1381 | return -EAGAIN; |
1432 | 1382 | ||
1433 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ | 1383 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ |
1434 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) { | 1384 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) |
1435 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, | 1385 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, |
1436 | CMD_OPTION_WAITFORRSP, 0, NULL); | 1386 | CMD_OPTION_WAITFORRSP, 0, NULL); |
1437 | } | ||
1438 | 1387 | ||
1439 | mutex_lock(&priv->lock); | 1388 | mutex_lock(&priv->lock); |
1440 | list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { | 1389 | list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { |
1441 | char * next_ev; | 1390 | char *next_ev; |
1442 | unsigned long stale_time; | 1391 | unsigned long stale_time; |
1443 | 1392 | ||
1444 | if (stop - ev < SCAN_ITEM_SIZE) { | 1393 | if (stop - ev < SCAN_ITEM_SIZE) { |
@@ -1453,8 +1402,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1453 | /* Prune old an old scan result */ | 1402 | /* Prune old an old scan result */ |
1454 | stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; | 1403 | stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; |
1455 | if (time_after(jiffies, stale_time)) { | 1404 | if (time_after(jiffies, stale_time)) { |
1456 | list_move_tail (&iter_bss->list, | 1405 | list_move_tail(&iter_bss->list, &priv->network_free_list); |
1457 | &priv->network_free_list); | ||
1458 | clear_bss_descriptor(iter_bss); | 1406 | clear_bss_descriptor(iter_bss); |
1459 | continue; | 1407 | continue; |
1460 | } | 1408 | } |
@@ -1485,44 +1433,6 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1485 | 1433 | ||
1486 | 1434 | ||
1487 | /** | 1435 | /** |
1488 | * @brief Prepare a scan command to be sent to the firmware | ||
1489 | * | ||
1490 | * Called via lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, ...) | ||
1491 | * from cmd.c | ||
1492 | * | ||
1493 | * Sends a fixed length data part (specifying the BSS type and BSSID filters) | ||
1494 | * as well as a variable number/length of TLVs to the firmware. | ||
1495 | * | ||
1496 | * @param priv A pointer to struct lbs_private structure | ||
1497 | * @param cmd A pointer to cmd_ds_command structure to be sent to | ||
1498 | * firmware with the cmd_DS_801_11_SCAN structure | ||
1499 | * @param pdata_buf Void pointer cast of a lbs_scan_cmd_config struct used | ||
1500 | * to set the fields/TLVs for the command sent to firmware | ||
1501 | * | ||
1502 | * @return 0 or -1 | ||
1503 | */ | ||
1504 | int lbs_cmd_80211_scan(struct lbs_private *priv, | ||
1505 | struct cmd_ds_command *cmd, void *pdata_buf) | ||
1506 | { | ||
1507 | struct cmd_ds_802_11_scan *pscan = &cmd->params.scan; | ||
1508 | struct lbs_scan_cmd_config *pscancfg = pdata_buf; | ||
1509 | |||
1510 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1511 | |||
1512 | /* Set fixed field variables in scan command */ | ||
1513 | pscan->bsstype = pscancfg->bsstype; | ||
1514 | memcpy(pscan->bssid, pscancfg->bssid, ETH_ALEN); | ||
1515 | memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen); | ||
1516 | |||
1517 | /* size is equal to the sizeof(fixed portions) + the TLV len + header */ | ||
1518 | cmd->size = cpu_to_le16(sizeof(pscan->bsstype) + ETH_ALEN | ||
1519 | + pscancfg->tlvbufferlen + S_DS_GEN); | ||
1520 | |||
1521 | lbs_deb_leave(LBS_DEB_SCAN); | ||
1522 | return 0; | ||
1523 | } | ||
1524 | |||
1525 | /** | ||
1526 | * @brief This function handles the command response of scan | 1436 | * @brief This function handles the command response of scan |
1527 | * | 1437 | * |
1528 | * Called from handle_cmd_response() in cmdrespc. | 1438 | * Called from handle_cmd_response() in cmdrespc. |
@@ -1548,13 +1458,14 @@ int lbs_cmd_80211_scan(struct lbs_private *priv, | |||
1548 | * | 1458 | * |
1549 | * @return 0 or -1 | 1459 | * @return 0 or -1 |
1550 | */ | 1460 | */ |
1551 | int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) | 1461 | static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, |
1462 | struct cmd_header *resp) | ||
1552 | { | 1463 | { |
1553 | struct cmd_ds_802_11_scan_rsp *pscan; | 1464 | struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp; |
1554 | struct bss_descriptor * iter_bss; | 1465 | struct bss_descriptor *iter_bss; |
1555 | struct bss_descriptor * safe; | 1466 | struct bss_descriptor *safe; |
1556 | u8 *pbssinfo; | 1467 | uint8_t *bssinfo; |
1557 | u16 scanrespsize; | 1468 | uint16_t scanrespsize; |
1558 | int bytesleft; | 1469 | int bytesleft; |
1559 | int idx; | 1470 | int idx; |
1560 | int tlvbufsize; | 1471 | int tlvbufsize; |
@@ -1571,48 +1482,45 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) | |||
1571 | clear_bss_descriptor(iter_bss); | 1482 | clear_bss_descriptor(iter_bss); |
1572 | } | 1483 | } |
1573 | 1484 | ||
1574 | pscan = &resp->params.scanresp; | 1485 | if (scanresp->nr_sets > MAX_NETWORK_COUNT) { |
1575 | 1486 | lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n", | |
1576 | if (pscan->nr_sets > MAX_NETWORK_COUNT) { | 1487 | scanresp->nr_sets, MAX_NETWORK_COUNT); |
1577 | lbs_deb_scan( | ||
1578 | "SCAN_RESP: too many scan results (%d, max %d)!!\n", | ||
1579 | pscan->nr_sets, MAX_NETWORK_COUNT); | ||
1580 | ret = -1; | 1488 | ret = -1; |
1581 | goto done; | 1489 | goto done; |
1582 | } | 1490 | } |
1583 | 1491 | ||
1584 | bytesleft = le16_to_cpu(pscan->bssdescriptsize); | 1492 | bytesleft = le16_to_cpu(scanresp->bssdescriptsize); |
1585 | lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); | 1493 | lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); |
1586 | 1494 | ||
1587 | scanrespsize = le16_to_cpu(resp->size); | 1495 | scanrespsize = le16_to_cpu(resp->size); |
1588 | lbs_deb_scan("SCAN_RESP: scan results %d\n", pscan->nr_sets); | 1496 | lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets); |
1589 | 1497 | ||
1590 | pbssinfo = pscan->bssdesc_and_tlvbuffer; | 1498 | bssinfo = scanresp->bssdesc_and_tlvbuffer; |
1591 | 1499 | ||
1592 | /* The size of the TLV buffer is equal to the entire command response | 1500 | /* The size of the TLV buffer is equal to the entire command response |
1593 | * size (scanrespsize) minus the fixed fields (sizeof()'s), the | 1501 | * size (scanrespsize) minus the fixed fields (sizeof()'s), the |
1594 | * BSS Descriptions (bssdescriptsize as bytesLef) and the command | 1502 | * BSS Descriptions (bssdescriptsize as bytesLef) and the command |
1595 | * response header (S_DS_GEN) | 1503 | * response header (S_DS_GEN) |
1596 | */ | 1504 | */ |
1597 | tlvbufsize = scanrespsize - (bytesleft + sizeof(pscan->bssdescriptsize) | 1505 | tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize) |
1598 | + sizeof(pscan->nr_sets) | 1506 | + sizeof(scanresp->nr_sets) |
1599 | + S_DS_GEN); | 1507 | + S_DS_GEN); |
1600 | 1508 | ||
1601 | /* | 1509 | /* |
1602 | * Process each scan response returned (pscan->nr_sets). Save | 1510 | * Process each scan response returned (scanresp->nr_sets). Save |
1603 | * the information in the newbssentry and then insert into the | 1511 | * the information in the newbssentry and then insert into the |
1604 | * driver scan table either as an update to an existing entry | 1512 | * driver scan table either as an update to an existing entry |
1605 | * or as an addition at the end of the table | 1513 | * or as an addition at the end of the table |
1606 | */ | 1514 | */ |
1607 | for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) { | 1515 | for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) { |
1608 | struct bss_descriptor new; | 1516 | struct bss_descriptor new; |
1609 | struct bss_descriptor * found = NULL; | 1517 | struct bss_descriptor *found = NULL; |
1610 | struct bss_descriptor * oldest = NULL; | 1518 | struct bss_descriptor *oldest = NULL; |
1611 | DECLARE_MAC_BUF(mac); | 1519 | DECLARE_MAC_BUF(mac); |
1612 | 1520 | ||
1613 | /* Process the data fields and IEs returned for this BSS */ | 1521 | /* Process the data fields and IEs returned for this BSS */ |
1614 | memset(&new, 0, sizeof (struct bss_descriptor)); | 1522 | memset(&new, 0, sizeof (struct bss_descriptor)); |
1615 | if (lbs_process_bss(&new, &pbssinfo, &bytesleft) != 0) { | 1523 | if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) { |
1616 | /* error parsing the scan response, skipped */ | 1524 | /* error parsing the scan response, skipped */ |
1617 | lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n"); | 1525 | lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n"); |
1618 | continue; | 1526 | continue; |
@@ -1647,8 +1555,7 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) | |||
1647 | continue; | 1555 | continue; |
1648 | } | 1556 | } |
1649 | 1557 | ||
1650 | lbs_deb_scan("SCAN_RESP: BSSID %s\n", | 1558 | lbs_deb_scan("SCAN_RESP: BSSID %s\n", print_mac(mac, new.bssid)); |
1651 | print_mac(mac, new.bssid)); | ||
1652 | 1559 | ||
1653 | /* Copy the locally created newbssentry to the scan table */ | 1560 | /* Copy the locally created newbssentry to the scan table */ |
1654 | memcpy(found, &new, offsetof(struct bss_descriptor, list)); | 1561 | memcpy(found, &new, offsetof(struct bss_descriptor, list)); |
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h index 319f70dde350..10d1196acf78 100644 --- a/drivers/net/wireless/libertas/scan.h +++ b/drivers/net/wireless/libertas/scan.h | |||
@@ -17,57 +17,16 @@ | |||
17 | */ | 17 | */ |
18 | #define LBS_IOCTL_USER_SCAN_CHAN_MAX 50 | 18 | #define LBS_IOCTL_USER_SCAN_CHAN_MAX 50 |
19 | 19 | ||
20 | //! Infrastructure BSS scan type in lbs_scan_cmd_config | 20 | //! Infrastructure BSS scan type in cmd_ds_802_11_scan |
21 | #define LBS_SCAN_BSS_TYPE_BSS 1 | 21 | #define LBS_SCAN_BSS_TYPE_BSS 1 |
22 | 22 | ||
23 | //! Adhoc BSS scan type in lbs_scan_cmd_config | 23 | //! Adhoc BSS scan type in cmd_ds_802_11_scan |
24 | #define LBS_SCAN_BSS_TYPE_IBSS 2 | 24 | #define LBS_SCAN_BSS_TYPE_IBSS 2 |
25 | 25 | ||
26 | //! Adhoc or Infrastructure BSS scan type in lbs_scan_cmd_config, no filter | 26 | //! Adhoc or Infrastructure BSS scan type in cmd_ds_802_11_scan, no filter |
27 | #define LBS_SCAN_BSS_TYPE_ANY 3 | 27 | #define LBS_SCAN_BSS_TYPE_ANY 3 |
28 | 28 | ||
29 | /** | 29 | /** |
30 | * @brief Structure used internally in the wlan driver to configure a scan. | ||
31 | * | ||
32 | * Sent to the command processing module to configure the firmware | ||
33 | * scan command prepared by lbs_cmd_80211_scan. | ||
34 | * | ||
35 | * @sa lbs_scan_networks | ||
36 | * | ||
37 | */ | ||
38 | struct lbs_scan_cmd_config { | ||
39 | /** | ||
40 | * @brief BSS type to be sent in the firmware command | ||
41 | * | ||
42 | * Field can be used to restrict the types of networks returned in the | ||
43 | * scan. valid settings are: | ||
44 | * | ||
45 | * - LBS_SCAN_BSS_TYPE_BSS (infrastructure) | ||
46 | * - LBS_SCAN_BSS_TYPE_IBSS (adhoc) | ||
47 | * - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure) | ||
48 | */ | ||
49 | u8 bsstype; | ||
50 | |||
51 | /** | ||
52 | * @brief Specific BSSID used to filter scan results in the firmware | ||
53 | */ | ||
54 | u8 bssid[ETH_ALEN]; | ||
55 | |||
56 | /** | ||
57 | * @brief length of TLVs sent in command starting at tlvBuffer | ||
58 | */ | ||
59 | int tlvbufferlen; | ||
60 | |||
61 | /** | ||
62 | * @brief SSID TLV(s) and ChanList TLVs to be sent in the firmware command | ||
63 | * | ||
64 | * @sa TLV_TYPE_CHANLIST, mrvlietypes_chanlistparamset_t | ||
65 | * @sa TLV_TYPE_SSID, mrvlietypes_ssidparamset_t | ||
66 | */ | ||
67 | u8 tlvbuffer[1]; //!< SSID TLV(s) and ChanList TLVs are stored here | ||
68 | }; | ||
69 | |||
70 | /** | ||
71 | * @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg | 30 | * @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg |
72 | * | 31 | * |
73 | * Multiple instances of this structure are included in the IOCTL command | 32 | * Multiple instances of this structure are included in the IOCTL command |
@@ -179,13 +138,6 @@ int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid, | |||
179 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, | 138 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, |
180 | u8 ssid_len, u8 clear_ssid); | 139 | u8 ssid_len, u8 clear_ssid); |
181 | 140 | ||
182 | int lbs_cmd_80211_scan(struct lbs_private *priv, | ||
183 | struct cmd_ds_command *cmd, | ||
184 | void *pdata_buf); | ||
185 | |||
186 | int lbs_ret_80211_scan(struct lbs_private *priv, | ||
187 | struct cmd_ds_command *resp); | ||
188 | |||
189 | int lbs_scan_networks(struct lbs_private *priv, | 141 | int lbs_scan_networks(struct lbs_private *priv, |
190 | const struct lbs_ioctl_user_scan_cfg *puserscanin, | 142 | const struct lbs_ioctl_user_scan_cfg *puserscanin, |
191 | int full_scan); | 143 | int full_scan); |
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h index f0d57958b34b..4031be420862 100644 --- a/drivers/net/wireless/libertas/types.h +++ b/drivers/net/wireless/libertas/types.h | |||
@@ -239,4 +239,17 @@ struct mrvlietypes_ledgpio { | |||
239 | struct led_pin ledpin[1]; | 239 | struct led_pin ledpin[1]; |
240 | } __attribute__ ((packed)); | 240 | } __attribute__ ((packed)); |
241 | 241 | ||
242 | struct led_bhv { | ||
243 | uint8_t firmwarestate; | ||
244 | uint8_t led; | ||
245 | uint8_t ledstate; | ||
246 | uint8_t ledarg; | ||
247 | } __attribute__ ((packed)); | ||
248 | |||
249 | |||
250 | struct mrvlietypes_ledbhv { | ||
251 | struct mrvlietypesheader header; | ||
252 | struct led_bhv ledbhv[1]; | ||
253 | } __attribute__ ((packed)); | ||
254 | |||
242 | #endif | 255 | #endif |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index db96adf90ae2..0acb5c345734 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
@@ -809,6 +809,7 @@ static int hw_init_hmac(struct zd_chip *chip) | |||
809 | { CR_AFTER_PNP, 0x1 }, | 809 | { CR_AFTER_PNP, 0x1 }, |
810 | { CR_WEP_PROTECT, 0x114 }, | 810 | { CR_WEP_PROTECT, 0x114 }, |
811 | { CR_IFS_VALUE, IFS_VALUE_DEFAULT }, | 811 | { CR_IFS_VALUE, IFS_VALUE_DEFAULT }, |
812 | { CR_CAM_MODE, MODE_AP_WDS}, | ||
812 | }; | 813 | }; |
813 | 814 | ||
814 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | 815 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 5b6e3a3751ba..f8c061a9b6ec 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h | |||
@@ -489,6 +489,7 @@ enum { | |||
489 | 489 | ||
490 | #define CR_RX_OFFSET CTL_REG(0x065c) | 490 | #define CR_RX_OFFSET CTL_REG(0x065c) |
491 | 491 | ||
492 | #define CR_BCN_LENGTH CTL_REG(0x0664) | ||
492 | #define CR_PHY_DELAY CTL_REG(0x066C) | 493 | #define CR_PHY_DELAY CTL_REG(0x066C) |
493 | #define CR_BCN_FIFO CTL_REG(0x0670) | 494 | #define CR_BCN_FIFO CTL_REG(0x0670) |
494 | #define CR_SNIFFER_ON CTL_REG(0x0674) | 495 | #define CR_SNIFFER_ON CTL_REG(0x0674) |
@@ -545,6 +546,8 @@ enum { | |||
545 | #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \ | 546 | #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \ |
546 | RX_FILTER_CFEND | RX_FILTER_CFACK) | 547 | RX_FILTER_CFEND | RX_FILTER_CFACK) |
547 | 548 | ||
549 | #define BCN_MODE_IBSS 0x2000000 | ||
550 | |||
548 | /* Monitor mode sets filter to 0xfffff */ | 551 | /* Monitor mode sets filter to 0xfffff */ |
549 | 552 | ||
550 | #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) | 553 | #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) |
@@ -578,6 +581,11 @@ enum { | |||
578 | 581 | ||
579 | /* CAM: Continuous Access Mode (power management) */ | 582 | /* CAM: Continuous Access Mode (power management) */ |
580 | #define CR_CAM_MODE CTL_REG(0x0700) | 583 | #define CR_CAM_MODE CTL_REG(0x0700) |
584 | #define MODE_IBSS 0x0 | ||
585 | #define MODE_AP 0x1 | ||
586 | #define MODE_STA 0x2 | ||
587 | #define MODE_AP_WDS 0x3 | ||
588 | |||
581 | #define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704) | 589 | #define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704) |
582 | #define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708) | 590 | #define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708) |
583 | #define CR_CAM_ADDRESS CTL_REG(0x070C) | 591 | #define CR_CAM_ADDRESS CTL_REG(0x070C) |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index f90f03f676de..69c45ca99051 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -475,6 +475,46 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | |||
475 | /* FIXME: Management frame? */ | 475 | /* FIXME: Management frame? */ |
476 | } | 476 | } |
477 | 477 | ||
478 | void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) | ||
479 | { | ||
480 | struct zd_mac *mac = zd_hw_mac(hw); | ||
481 | u32 tmp, j = 0; | ||
482 | /* 4 more bytes for tail CRC */ | ||
483 | u32 full_len = beacon->len + 4; | ||
484 | zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0); | ||
485 | zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); | ||
486 | while (tmp & 0x2) { | ||
487 | zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); | ||
488 | if ((++j % 100) == 0) { | ||
489 | printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n"); | ||
490 | if (j >= 500) { | ||
491 | printk(KERN_ERR "Giving up beacon config.\n"); | ||
492 | return; | ||
493 | } | ||
494 | } | ||
495 | msleep(1); | ||
496 | } | ||
497 | |||
498 | zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1); | ||
499 | if (zd_chip_is_zd1211b(&mac->chip)) | ||
500 | zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1); | ||
501 | |||
502 | for (j = 0 ; j < beacon->len; j++) | ||
503 | zd_iowrite32(&mac->chip, CR_BCN_FIFO, | ||
504 | *((u8 *)(beacon->data + j))); | ||
505 | |||
506 | for (j = 0; j < 4; j++) | ||
507 | zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0); | ||
508 | |||
509 | zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1); | ||
510 | /* 802.11b/g 2.4G CCK 1Mb | ||
511 | * 802.11a, not yet implemented, uses different values (see GPL vendor | ||
512 | * driver) | ||
513 | */ | ||
514 | zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 | | ||
515 | (full_len << 19)); | ||
516 | } | ||
517 | |||
478 | static int fill_ctrlset(struct zd_mac *mac, | 518 | static int fill_ctrlset(struct zd_mac *mac, |
479 | struct sk_buff *skb, | 519 | struct sk_buff *skb, |
480 | struct ieee80211_tx_control *control) | 520 | struct ieee80211_tx_control *control) |
@@ -709,6 +749,7 @@ static int zd_op_add_interface(struct ieee80211_hw *hw, | |||
709 | 749 | ||
710 | switch (conf->type) { | 750 | switch (conf->type) { |
711 | case IEEE80211_IF_TYPE_MNTR: | 751 | case IEEE80211_IF_TYPE_MNTR: |
752 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
712 | case IEEE80211_IF_TYPE_STA: | 753 | case IEEE80211_IF_TYPE_STA: |
713 | mac->type = conf->type; | 754 | mac->type = conf->type; |
714 | break; | 755 | break; |
@@ -738,15 +779,43 @@ static int zd_op_config_interface(struct ieee80211_hw *hw, | |||
738 | struct ieee80211_if_conf *conf) | 779 | struct ieee80211_if_conf *conf) |
739 | { | 780 | { |
740 | struct zd_mac *mac = zd_hw_mac(hw); | 781 | struct zd_mac *mac = zd_hw_mac(hw); |
782 | int associated; | ||
783 | |||
784 | if (mac->type == IEEE80211_IF_TYPE_MESH_POINT) { | ||
785 | associated = true; | ||
786 | if (conf->beacon) { | ||
787 | zd_mac_config_beacon(hw, conf->beacon); | ||
788 | kfree_skb(conf->beacon); | ||
789 | zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | | ||
790 | hw->conf.beacon_int); | ||
791 | } | ||
792 | } else | ||
793 | associated = is_valid_ether_addr(conf->bssid); | ||
741 | 794 | ||
742 | spin_lock_irq(&mac->lock); | 795 | spin_lock_irq(&mac->lock); |
743 | mac->associated = is_valid_ether_addr(conf->bssid); | 796 | mac->associated = associated; |
744 | spin_unlock_irq(&mac->lock); | 797 | spin_unlock_irq(&mac->lock); |
745 | 798 | ||
746 | /* TODO: do hardware bssid filtering */ | 799 | /* TODO: do hardware bssid filtering */ |
747 | return 0; | 800 | return 0; |
748 | } | 801 | } |
749 | 802 | ||
803 | void zd_process_intr(struct work_struct *work) | ||
804 | { | ||
805 | u16 int_status; | ||
806 | struct zd_mac *mac = container_of(work, struct zd_mac, process_intr); | ||
807 | |||
808 | int_status = le16_to_cpu(*(u16 *)(mac->intr_buffer+4)); | ||
809 | if (int_status & INT_CFG_NEXT_BCN) { | ||
810 | if (net_ratelimit()) | ||
811 | dev_dbg_f(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n"); | ||
812 | } else | ||
813 | dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n"); | ||
814 | |||
815 | zd_chip_enable_hwint(&mac->chip); | ||
816 | } | ||
817 | |||
818 | |||
750 | static void set_multicast_hash_handler(struct work_struct *work) | 819 | static void set_multicast_hash_handler(struct work_struct *work) |
751 | { | 820 | { |
752 | struct zd_mac *mac = | 821 | struct zd_mac *mac = |
@@ -912,7 +981,8 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | |||
912 | 981 | ||
913 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; | 982 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; |
914 | 983 | ||
915 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS; | 984 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
985 | IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE; | ||
916 | hw->max_rssi = 100; | 986 | hw->max_rssi = 100; |
917 | hw->max_signal = 100; | 987 | hw->max_signal = 100; |
918 | 988 | ||
@@ -926,6 +996,7 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | |||
926 | INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler); | 996 | INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler); |
927 | INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work); | 997 | INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work); |
928 | INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler); | 998 | INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler); |
999 | INIT_WORK(&mac->process_intr, zd_process_intr); | ||
929 | 1000 | ||
930 | SET_IEEE80211_DEV(hw, &intf->dev); | 1001 | SET_IEEE80211_DEV(hw, &intf->dev); |
931 | return hw; | 1002 | return hw; |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 67dea9739c8f..71170244d2c9 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h | |||
@@ -172,12 +172,15 @@ struct zd_tx_skb_control_block { | |||
172 | struct zd_mac { | 172 | struct zd_mac { |
173 | struct zd_chip chip; | 173 | struct zd_chip chip; |
174 | spinlock_t lock; | 174 | spinlock_t lock; |
175 | spinlock_t intr_lock; | ||
175 | struct ieee80211_hw *hw; | 176 | struct ieee80211_hw *hw; |
176 | struct housekeeping housekeeping; | 177 | struct housekeeping housekeeping; |
177 | struct work_struct set_multicast_hash_work; | 178 | struct work_struct set_multicast_hash_work; |
178 | struct work_struct set_rts_cts_work; | 179 | struct work_struct set_rts_cts_work; |
179 | struct work_struct set_rx_filter_work; | 180 | struct work_struct set_rx_filter_work; |
181 | struct work_struct process_intr; | ||
180 | struct zd_mc_hash multicast_hash; | 182 | struct zd_mc_hash multicast_hash; |
183 | u8 intr_buffer[USB_MAX_EP_INT_BUFFER]; | ||
181 | u8 regdomain; | 184 | u8 regdomain; |
182 | u8 default_regdomain; | 185 | u8 default_regdomain; |
183 | int type; | 186 | int type; |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 7942b15acfe7..e34675c2f8fc 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -97,6 +97,7 @@ MODULE_DEVICE_TABLE(usb, usb_ids); | |||
97 | #define FW_ZD1211B_PREFIX "zd1211/zd1211b_" | 97 | #define FW_ZD1211B_PREFIX "zd1211/zd1211b_" |
98 | 98 | ||
99 | /* USB device initialization */ | 99 | /* USB device initialization */ |
100 | static void int_urb_complete(struct urb *urb); | ||
100 | 101 | ||
101 | static int request_fw_file( | 102 | static int request_fw_file( |
102 | const struct firmware **fw, const char *name, struct device *device) | 103 | const struct firmware **fw, const char *name, struct device *device) |
@@ -336,11 +337,18 @@ static inline void handle_regs_int(struct urb *urb) | |||
336 | struct zd_usb *usb = urb->context; | 337 | struct zd_usb *usb = urb->context; |
337 | struct zd_usb_interrupt *intr = &usb->intr; | 338 | struct zd_usb_interrupt *intr = &usb->intr; |
338 | int len; | 339 | int len; |
340 | u16 int_num; | ||
339 | 341 | ||
340 | ZD_ASSERT(in_interrupt()); | 342 | ZD_ASSERT(in_interrupt()); |
341 | spin_lock(&intr->lock); | 343 | spin_lock(&intr->lock); |
342 | 344 | ||
343 | if (intr->read_regs_enabled) { | 345 | int_num = le16_to_cpu(*(u16 *)(urb->transfer_buffer+2)); |
346 | if (int_num == CR_INTERRUPT) { | ||
347 | struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context)); | ||
348 | memcpy(&mac->intr_buffer, urb->transfer_buffer, | ||
349 | USB_MAX_EP_INT_BUFFER); | ||
350 | schedule_work(&mac->process_intr); | ||
351 | } else if (intr->read_regs_enabled) { | ||
344 | intr->read_regs.length = len = urb->actual_length; | 352 | intr->read_regs.length = len = urb->actual_length; |
345 | 353 | ||
346 | if (len > sizeof(intr->read_regs.buffer)) | 354 | if (len > sizeof(intr->read_regs.buffer)) |
@@ -351,7 +359,6 @@ static inline void handle_regs_int(struct urb *urb) | |||
351 | goto out; | 359 | goto out; |
352 | } | 360 | } |
353 | 361 | ||
354 | dev_dbg_f(urb_dev(urb), "regs interrupt ignored\n"); | ||
355 | out: | 362 | out: |
356 | spin_unlock(&intr->lock); | 363 | spin_unlock(&intr->lock); |
357 | } | 364 | } |