diff options
Diffstat (limited to 'drivers')
62 files changed, 4347 insertions, 2538 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 | } |
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index adea792fb675..f69ef0ba2613 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig | |||
| @@ -125,4 +125,13 @@ config SSB_DRIVER_EXTIF | |||
| 125 | 125 | ||
| 126 | If unsure, say N | 126 | If unsure, say N |
| 127 | 127 | ||
| 128 | config SSB_DRIVER_GIGE | ||
| 129 | bool "SSB Broadcom Gigabit Ethernet driver" | ||
| 130 | depends on SSB_PCIHOST_POSSIBLE && SSB_EMBEDDED && MIPS | ||
| 131 | help | ||
| 132 | Driver for the Sonics Silicon Backplane attached | ||
| 133 | Broadcom Gigabit Ethernet. | ||
| 134 | |||
| 135 | If unsure, say N | ||
| 136 | |||
| 128 | endmenu | 137 | endmenu |
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile index de94c2eb7a37..910f35e32fc9 100644 --- a/drivers/ssb/Makefile +++ b/drivers/ssb/Makefile | |||
| @@ -11,6 +11,7 @@ ssb-y += driver_chipcommon.o | |||
| 11 | ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o | 11 | ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o |
| 12 | ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o | 12 | ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o |
| 13 | ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o | 13 | ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o |
| 14 | ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o | ||
| 14 | 15 | ||
| 15 | # b43 pci-ssb-bridge driver | 16 | # b43 pci-ssb-bridge driver |
| 16 | # Not strictly a part of SSB, but kept here for convenience | 17 | # Not strictly a part of SSB, but kept here for convenience |
diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c new file mode 100644 index 000000000000..172f90407b93 --- /dev/null +++ b/drivers/ssb/driver_gige.c | |||
| @@ -0,0 +1,294 @@ | |||
| 1 | /* | ||
| 2 | * Sonics Silicon Backplane | ||
| 3 | * Broadcom Gigabit Ethernet core driver | ||
| 4 | * | ||
| 5 | * Copyright 2008, Broadcom Corporation | ||
| 6 | * Copyright 2008, Michael Buesch <mb@bu3sch.de> | ||
| 7 | * | ||
| 8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/ssb/ssb.h> | ||
| 12 | #include <linux/ssb/ssb_driver_gige.h> | ||
| 13 | #include <linux/pci.h> | ||
| 14 | #include <linux/pci_regs.h> | ||
| 15 | |||
| 16 | |||
| 17 | /* | ||
| 18 | MODULE_DESCRIPTION("SSB Broadcom Gigabit Ethernet driver"); | ||
| 19 | MODULE_AUTHOR("Michael Buesch"); | ||
| 20 | MODULE_LICENSE("GPL"); | ||
| 21 | */ | ||
| 22 | |||
| 23 | static const struct ssb_device_id ssb_gige_tbl[] = { | ||
| 24 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET_GBIT, SSB_ANY_REV), | ||
| 25 | SSB_DEVTABLE_END | ||
| 26 | }; | ||
| 27 | /* MODULE_DEVICE_TABLE(ssb, ssb_gige_tbl); */ | ||
| 28 | |||
| 29 | |||
| 30 | static inline u8 gige_read8(struct ssb_gige *dev, u16 offset) | ||
| 31 | { | ||
| 32 | return ssb_read8(dev->dev, offset); | ||
| 33 | } | ||
| 34 | |||
| 35 | static inline u16 gige_read16(struct ssb_gige *dev, u16 offset) | ||
| 36 | { | ||
| 37 | return ssb_read16(dev->dev, offset); | ||
| 38 | } | ||
| 39 | |||
| 40 | static inline u32 gige_read32(struct ssb_gige *dev, u16 offset) | ||
| 41 | { | ||
| 42 | return ssb_read32(dev->dev, offset); | ||
| 43 | } | ||
| 44 | |||
| 45 | static inline void gige_write8(struct ssb_gige *dev, | ||
| 46 | u16 offset, u8 value) | ||
| 47 | { | ||
| 48 | ssb_write8(dev->dev, offset, value); | ||
| 49 | } | ||
| 50 | |||
| 51 | static inline void gige_write16(struct ssb_gige *dev, | ||
| 52 | u16 offset, u16 value) | ||
| 53 | { | ||
| 54 | ssb_write16(dev->dev, offset, value); | ||
| 55 | } | ||
| 56 | |||
| 57 | static inline void gige_write32(struct ssb_gige *dev, | ||
| 58 | u16 offset, u32 value) | ||
| 59 | { | ||
| 60 | ssb_write32(dev->dev, offset, value); | ||
| 61 | } | ||
| 62 | |||
| 63 | static inline | ||
| 64 | u8 gige_pcicfg_read8(struct ssb_gige *dev, unsigned int offset) | ||
| 65 | { | ||
| 66 | BUG_ON(offset >= 256); | ||
| 67 | return gige_read8(dev, SSB_GIGE_PCICFG + offset); | ||
| 68 | } | ||
| 69 | |||
| 70 | static inline | ||
| 71 | u16 gige_pcicfg_read16(struct ssb_gige *dev, unsigned int offset) | ||
| 72 | { | ||
| 73 | BUG_ON(offset >= 256); | ||
| 74 | return gige_read16(dev, SSB_GIGE_PCICFG + offset); | ||
| 75 | } | ||
| 76 | |||
| 77 | static inline | ||
| 78 | u32 gige_pcicfg_read32(struct ssb_gige *dev, unsigned int offset) | ||
| 79 | { | ||
| 80 | BUG_ON(offset >= 256); | ||
| 81 | return gige_read32(dev, SSB_GIGE_PCICFG + offset); | ||
| 82 | } | ||
| 83 | |||
| 84 | static inline | ||
| 85 | void gige_pcicfg_write8(struct ssb_gige *dev, | ||
| 86 | unsigned int offset, u8 value) | ||
| 87 | { | ||
| 88 | BUG_ON(offset >= 256); | ||
| 89 | gige_write8(dev, SSB_GIGE_PCICFG + offset, value); | ||
| 90 | } | ||
| 91 | |||
| 92 | static inline | ||
| 93 | void gige_pcicfg_write16(struct ssb_gige *dev, | ||
| 94 | unsigned int offset, u16 value) | ||
| 95 | { | ||
| 96 | BUG_ON(offset >= 256); | ||
| 97 | gige_write16(dev, SSB_GIGE_PCICFG + offset, value); | ||
| 98 | } | ||
| 99 | |||
| 100 | static inline | ||
| 101 | void gige_pcicfg_write32(struct ssb_gige *dev, | ||
| 102 | unsigned int offset, u32 value) | ||
| 103 | { | ||
| 104 | BUG_ON(offset >= 256); | ||
| 105 | gige_write32(dev, SSB_GIGE_PCICFG + offset, value); | ||
| 106 | } | ||
| 107 | |||
| 108 | static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
| 109 | int reg, int size, u32 *val) | ||
| 110 | { | ||
| 111 | struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops); | ||
| 112 | unsigned long flags; | ||
| 113 | |||
| 114 | if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0)) | ||
| 115 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 116 | if (reg >= 256) | ||
| 117 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 118 | |||
| 119 | spin_lock_irqsave(&dev->lock, flags); | ||
| 120 | switch (size) { | ||
| 121 | case 1: | ||
| 122 | *val = gige_pcicfg_read8(dev, reg); | ||
| 123 | break; | ||
| 124 | case 2: | ||
| 125 | *val = gige_pcicfg_read16(dev, reg); | ||
| 126 | break; | ||
| 127 | case 4: | ||
| 128 | *val = gige_pcicfg_read32(dev, reg); | ||
| 129 | break; | ||
| 130 | default: | ||
| 131 | WARN_ON(1); | ||
| 132 | } | ||
| 133 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 134 | |||
| 135 | return PCIBIOS_SUCCESSFUL; | ||
| 136 | } | ||
| 137 | |||
| 138 | static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
| 139 | int reg, int size, u32 val) | ||
| 140 | { | ||
| 141 | struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops); | ||
| 142 | unsigned long flags; | ||
| 143 | |||
| 144 | if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0)) | ||
| 145 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 146 | if (reg >= 256) | ||
| 147 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 148 | |||
| 149 | spin_lock_irqsave(&dev->lock, flags); | ||
| 150 | switch (size) { | ||
| 151 | case 1: | ||
| 152 | gige_pcicfg_write8(dev, reg, val); | ||
| 153 | break; | ||
| 154 | case 2: | ||
| 155 | gige_pcicfg_write16(dev, reg, val); | ||
| 156 | break; | ||
| 157 | case 4: | ||
| 158 | gige_pcicfg_write32(dev, reg, val); | ||
| 159 | break; | ||
| 160 | default: | ||
| 161 | WARN_ON(1); | ||
| 162 | } | ||
| 163 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 164 | |||
| 165 | return PCIBIOS_SUCCESSFUL; | ||
| 166 | } | ||
| 167 | |||
| 168 | static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id) | ||
| 169 | { | ||
| 170 | struct ssb_gige *dev; | ||
| 171 | u32 base, tmslow, tmshigh; | ||
| 172 | |||
| 173 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
| 174 | if (!dev) | ||
| 175 | return -ENOMEM; | ||
| 176 | dev->dev = sdev; | ||
| 177 | |||
| 178 | spin_lock_init(&dev->lock); | ||
| 179 | dev->pci_controller.pci_ops = &dev->pci_ops; | ||
| 180 | dev->pci_controller.io_resource = &dev->io_resource; | ||
| 181 | dev->pci_controller.mem_resource = &dev->mem_resource; | ||
| 182 | dev->pci_controller.io_map_base = 0x800; | ||
| 183 | dev->pci_ops.read = ssb_gige_pci_read_config; | ||
| 184 | dev->pci_ops.write = ssb_gige_pci_write_config; | ||
| 185 | |||
| 186 | dev->io_resource.name = SSB_GIGE_IO_RES_NAME; | ||
| 187 | dev->io_resource.start = 0x800; | ||
| 188 | dev->io_resource.end = 0x8FF; | ||
| 189 | dev->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED; | ||
| 190 | |||
| 191 | if (!ssb_device_is_enabled(sdev)) | ||
| 192 | ssb_device_enable(sdev, 0); | ||
| 193 | |||
| 194 | /* Setup BAR0. This is a 64k MMIO region. */ | ||
| 195 | base = ssb_admatch_base(ssb_read32(sdev, SSB_ADMATCH1)); | ||
| 196 | gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_0, base); | ||
| 197 | gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_1, 0); | ||
| 198 | |||
| 199 | dev->mem_resource.name = SSB_GIGE_MEM_RES_NAME; | ||
| 200 | dev->mem_resource.start = base; | ||
| 201 | dev->mem_resource.end = base + 0x10000 - 1; | ||
| 202 | dev->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED; | ||
| 203 | |||
| 204 | /* Enable the memory region. */ | ||
| 205 | gige_pcicfg_write16(dev, PCI_COMMAND, | ||
| 206 | gige_pcicfg_read16(dev, PCI_COMMAND) | ||
| 207 | | PCI_COMMAND_MEMORY); | ||
| 208 | |||
| 209 | /* Write flushing is controlled by the Flush Status Control register. | ||
| 210 | * We want to flush every register write with a timeout and we want | ||
| 211 | * to disable the IRQ mask while flushing to avoid concurrency. | ||
| 212 | * Note that automatic write flushing does _not_ work from | ||
| 213 | * an IRQ handler. The driver must flush manually by reading a register. | ||
| 214 | */ | ||
| 215 | gige_write32(dev, SSB_GIGE_SHIM_FLUSHSTAT, 0x00000068); | ||
| 216 | |||
| 217 | /* Check if we have an RGMII or GMII PHY-bus. | ||
| 218 | * On RGMII do not bypass the DLLs */ | ||
| 219 | tmslow = ssb_read32(sdev, SSB_TMSLOW); | ||
| 220 | tmshigh = ssb_read32(sdev, SSB_TMSHIGH); | ||
| 221 | if (tmshigh & SSB_GIGE_TMSHIGH_RGMII) { | ||
| 222 | tmslow &= ~SSB_GIGE_TMSLOW_TXBYPASS; | ||
| 223 | tmslow &= ~SSB_GIGE_TMSLOW_RXBYPASS; | ||
| 224 | dev->has_rgmii = 1; | ||
| 225 | } else { | ||
| 226 | tmslow |= SSB_GIGE_TMSLOW_TXBYPASS; | ||
| 227 | tmslow |= SSB_GIGE_TMSLOW_RXBYPASS; | ||
| 228 | dev->has_rgmii = 0; | ||
| 229 | } | ||
| 230 | tmslow |= SSB_GIGE_TMSLOW_DLLEN; | ||
| 231 | ssb_write32(sdev, SSB_TMSLOW, tmslow); | ||
| 232 | |||
| 233 | ssb_set_drvdata(sdev, dev); | ||
| 234 | register_pci_controller(&dev->pci_controller); | ||
| 235 | |||
| 236 | return 0; | ||
| 237 | } | ||
| 238 | |||
| 239 | bool pdev_is_ssb_gige_core(struct pci_dev *pdev) | ||
| 240 | { | ||
| 241 | if (!pdev->resource[0].name) | ||
| 242 | return 0; | ||
| 243 | return (strcmp(pdev->resource[0].name, SSB_GIGE_MEM_RES_NAME) == 0); | ||
| 244 | } | ||
| 245 | EXPORT_SYMBOL(pdev_is_ssb_gige_core); | ||
| 246 | |||
| 247 | int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev, | ||
| 248 | struct pci_dev *pdev) | ||
| 249 | { | ||
| 250 | struct ssb_gige *dev = ssb_get_drvdata(sdev); | ||
| 251 | struct resource *res; | ||
| 252 | |||
| 253 | if (pdev->bus->ops != &dev->pci_ops) { | ||
| 254 | /* The PCI device is not on this SSB GigE bridge device. */ | ||
| 255 | return -ENODEV; | ||
| 256 | } | ||
| 257 | |||
| 258 | /* Fixup the PCI resources. */ | ||
| 259 | res = &(pdev->resource[0]); | ||
| 260 | res->flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED; | ||
| 261 | res->name = dev->mem_resource.name; | ||
| 262 | res->start = dev->mem_resource.start; | ||
| 263 | res->end = dev->mem_resource.end; | ||
| 264 | |||
| 265 | /* Fixup interrupt lines. */ | ||
| 266 | pdev->irq = ssb_mips_irq(sdev) + 2; | ||
| 267 | pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq); | ||
| 268 | |||
| 269 | return 0; | ||
| 270 | } | ||
| 271 | |||
| 272 | int ssb_gige_map_irq(struct ssb_device *sdev, | ||
| 273 | const struct pci_dev *pdev) | ||
| 274 | { | ||
| 275 | struct ssb_gige *dev = ssb_get_drvdata(sdev); | ||
| 276 | |||
| 277 | if (pdev->bus->ops != &dev->pci_ops) { | ||
| 278 | /* The PCI device is not on this SSB GigE bridge device. */ | ||
| 279 | return -ENODEV; | ||
| 280 | } | ||
| 281 | |||
| 282 | return ssb_mips_irq(sdev) + 2; | ||
| 283 | } | ||
| 284 | |||
| 285 | static struct ssb_driver ssb_gige_driver = { | ||
| 286 | .name = "BCM-GigE", | ||
| 287 | .id_table = ssb_gige_tbl, | ||
| 288 | .probe = ssb_gige_probe, | ||
| 289 | }; | ||
| 290 | |||
| 291 | int ssb_gige_init(void) | ||
| 292 | { | ||
| 293 | return ssb_driver_register(&ssb_gige_driver); | ||
| 294 | } | ||
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 3d3dd32bf3ab..e3fad3123ecb 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c | |||
| @@ -209,6 +209,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
| 209 | /* fallthrough */ | 209 | /* fallthrough */ |
| 210 | case SSB_DEV_PCI: | 210 | case SSB_DEV_PCI: |
| 211 | case SSB_DEV_ETHERNET: | 211 | case SSB_DEV_ETHERNET: |
| 212 | case SSB_DEV_ETHERNET_GBIT: | ||
| 212 | case SSB_DEV_80211: | 213 | case SSB_DEV_80211: |
| 213 | case SSB_DEV_USB20_HOST: | 214 | case SSB_DEV_USB20_HOST: |
| 214 | /* These devices get their own IRQ line if available, the rest goes on IRQ0 */ | 215 | /* These devices get their own IRQ line if available, the rest goes on IRQ0 */ |
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 74b9a8aea52b..33a7d5620474 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c | |||
| @@ -60,77 +60,6 @@ static DEFINE_SPINLOCK(cfgspace_lock); | |||
| 60 | /* Core to access the external PCI config space. Can only have one. */ | 60 | /* Core to access the external PCI config space. Can only have one. */ |
| 61 | static struct ssb_pcicore *extpci_core; | 61 | static struct ssb_pcicore *extpci_core; |
| 62 | 62 | ||
| 63 | static u32 ssb_pcicore_pcibus_iobase = 0x100; | ||
| 64 | static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA; | ||
| 65 | |||
| 66 | int pcibios_plat_dev_init(struct pci_dev *d) | ||
| 67 | { | ||
| 68 | struct resource *res; | ||
| 69 | int pos, size; | ||
| 70 | u32 *base; | ||
| 71 | |||
| 72 | ssb_printk(KERN_INFO "PCI: Fixing up device %s\n", | ||
| 73 | pci_name(d)); | ||
| 74 | |||
| 75 | /* Fix up resource bases */ | ||
| 76 | for (pos = 0; pos < 6; pos++) { | ||
| 77 | res = &d->resource[pos]; | ||
| 78 | if (res->flags & IORESOURCE_IO) | ||
| 79 | base = &ssb_pcicore_pcibus_iobase; | ||
| 80 | else | ||
| 81 | base = &ssb_pcicore_pcibus_membase; | ||
| 82 | res->flags |= IORESOURCE_PCI_FIXED; | ||
| 83 | if (res->end) { | ||
| 84 | size = res->end - res->start + 1; | ||
| 85 | if (*base & (size - 1)) | ||
| 86 | *base = (*base + size) & ~(size - 1); | ||
| 87 | res->start = *base; | ||
| 88 | res->end = res->start + size - 1; | ||
| 89 | *base += size; | ||
| 90 | pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start); | ||
| 91 | } | ||
| 92 | /* Fix up PCI bridge BAR0 only */ | ||
| 93 | if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0) | ||
| 94 | break; | ||
| 95 | } | ||
| 96 | /* Fix up interrupt lines */ | ||
| 97 | d->irq = ssb_mips_irq(extpci_core->dev) + 2; | ||
| 98 | pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); | ||
| 99 | |||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | static void __init ssb_fixup_pcibridge(struct pci_dev *dev) | ||
| 104 | { | ||
| 105 | u8 lat; | ||
| 106 | |||
| 107 | if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) | ||
| 108 | return; | ||
| 109 | |||
| 110 | ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev)); | ||
| 111 | |||
| 112 | /* Enable PCI bridge bus mastering and memory space */ | ||
| 113 | pci_set_master(dev); | ||
| 114 | if (pcibios_enable_device(dev, ~0) < 0) { | ||
| 115 | ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n"); | ||
| 116 | return; | ||
| 117 | } | ||
| 118 | |||
| 119 | /* Enable PCI bridge BAR1 prefetch and burst */ | ||
| 120 | pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3); | ||
| 121 | |||
| 122 | /* Make sure our latency is high enough to handle the devices behind us */ | ||
| 123 | lat = 168; | ||
| 124 | ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n", | ||
| 125 | pci_name(dev), lat); | ||
| 126 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); | ||
| 127 | } | ||
| 128 | DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge); | ||
| 129 | |||
| 130 | int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
| 131 | { | ||
| 132 | return ssb_mips_irq(extpci_core->dev) + 2; | ||
| 133 | } | ||
| 134 | 63 | ||
| 135 | static u32 get_cfgspace_addr(struct ssb_pcicore *pc, | 64 | static u32 get_cfgspace_addr(struct ssb_pcicore *pc, |
| 136 | unsigned int bus, unsigned int dev, | 65 | unsigned int bus, unsigned int dev, |
| @@ -320,6 +249,95 @@ static struct pci_controller ssb_pcicore_controller = { | |||
| 320 | .mem_offset = 0x24000000, | 249 | .mem_offset = 0x24000000, |
| 321 | }; | 250 | }; |
| 322 | 251 | ||
| 252 | static u32 ssb_pcicore_pcibus_iobase = 0x100; | ||
| 253 | static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA; | ||
| 254 | |||
| 255 | /* This function is called when doing a pci_enable_device(). | ||
| 256 | * We must first check if the device is a device on the PCI-core bridge. */ | ||
| 257 | int ssb_pcicore_plat_dev_init(struct pci_dev *d) | ||
| 258 | { | ||
| 259 | struct resource *res; | ||
| 260 | int pos, size; | ||
| 261 | u32 *base; | ||
| 262 | |||
| 263 | if (d->bus->ops != &ssb_pcicore_pciops) { | ||
| 264 | /* This is not a device on the PCI-core bridge. */ | ||
| 265 | return -ENODEV; | ||
| 266 | } | ||
| 267 | |||
| 268 | ssb_printk(KERN_INFO "PCI: Fixing up device %s\n", | ||
| 269 | pci_name(d)); | ||
| 270 | |||
| 271 | /* Fix up resource bases */ | ||
| 272 | for (pos = 0; pos < 6; pos++) { | ||
| 273 | res = &d->resource[pos]; | ||
| 274 | if (res->flags & IORESOURCE_IO) | ||
| 275 | base = &ssb_pcicore_pcibus_iobase; | ||
| 276 | else | ||
| 277 | base = &ssb_pcicore_pcibus_membase; | ||
| 278 | res->flags |= IORESOURCE_PCI_FIXED; | ||
| 279 | if (res->end) { | ||
| 280 | size = res->end - res->start + 1; | ||
| 281 | if (*base & (size - 1)) | ||
| 282 | *base = (*base + size) & ~(size - 1); | ||
| 283 | res->start = *base; | ||
| 284 | res->end = res->start + size - 1; | ||
| 285 | *base += size; | ||
| 286 | pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start); | ||
| 287 | } | ||
| 288 | /* Fix up PCI bridge BAR0 only */ | ||
| 289 | if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0) | ||
| 290 | break; | ||
| 291 | } | ||
| 292 | /* Fix up interrupt lines */ | ||
| 293 | d->irq = ssb_mips_irq(extpci_core->dev) + 2; | ||
| 294 | pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); | ||
| 295 | |||
| 296 | return 0; | ||
| 297 | } | ||
| 298 | |||
| 299 | /* Early PCI fixup for a device on the PCI-core bridge. */ | ||
| 300 | static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev) | ||
| 301 | { | ||
| 302 | u8 lat; | ||
| 303 | |||
| 304 | if (dev->bus->ops != &ssb_pcicore_pciops) { | ||
| 305 | /* This is not a device on the PCI-core bridge. */ | ||
| 306 | return; | ||
| 307 | } | ||
| 308 | if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) | ||
| 309 | return; | ||
| 310 | |||
| 311 | ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev)); | ||
| 312 | |||
| 313 | /* Enable PCI bridge bus mastering and memory space */ | ||
| 314 | pci_set_master(dev); | ||
| 315 | if (pcibios_enable_device(dev, ~0) < 0) { | ||
| 316 | ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n"); | ||
| 317 | return; | ||
| 318 | } | ||
| 319 | |||
| 320 | /* Enable PCI bridge BAR1 prefetch and burst */ | ||
| 321 | pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3); | ||
| 322 | |||
| 323 | /* Make sure our latency is high enough to handle the devices behind us */ | ||
| 324 | lat = 168; | ||
| 325 | ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n", | ||
| 326 | pci_name(dev), lat); | ||
| 327 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); | ||
| 328 | } | ||
| 329 | DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge); | ||
| 330 | |||
| 331 | /* PCI device IRQ mapping. */ | ||
| 332 | int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
| 333 | { | ||
| 334 | if (dev->bus->ops != &ssb_pcicore_pciops) { | ||
| 335 | /* This is not a device on the PCI-core bridge. */ | ||
| 336 | return -ENODEV; | ||
| 337 | } | ||
| 338 | return ssb_mips_irq(extpci_core->dev) + 2; | ||
| 339 | } | ||
| 340 | |||
| 323 | static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) | 341 | static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) |
| 324 | { | 342 | { |
| 325 | u32 val; | 343 | u32 val; |
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c index d3ade821555c..7dc3a6b41397 100644 --- a/drivers/ssb/embedded.c +++ b/drivers/ssb/embedded.c | |||
| @@ -10,6 +10,9 @@ | |||
| 10 | 10 | ||
| 11 | #include <linux/ssb/ssb.h> | 11 | #include <linux/ssb/ssb.h> |
| 12 | #include <linux/ssb/ssb_embedded.h> | 12 | #include <linux/ssb/ssb_embedded.h> |
| 13 | #include <linux/ssb/ssb_driver_pci.h> | ||
| 14 | #include <linux/ssb/ssb_driver_gige.h> | ||
| 15 | #include <linux/pci.h> | ||
| 13 | 16 | ||
| 14 | #include "ssb_private.h" | 17 | #include "ssb_private.h" |
| 15 | 18 | ||
| @@ -130,3 +133,90 @@ u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value) | |||
| 130 | return res; | 133 | return res; |
| 131 | } | 134 | } |
| 132 | EXPORT_SYMBOL(ssb_gpio_polarity); | 135 | EXPORT_SYMBOL(ssb_gpio_polarity); |
| 136 | |||
| 137 | #ifdef CONFIG_SSB_DRIVER_GIGE | ||
| 138 | static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data) | ||
| 139 | { | ||
| 140 | struct pci_dev *pdev = (struct pci_dev *)data; | ||
| 141 | struct ssb_device *dev; | ||
| 142 | unsigned int i; | ||
| 143 | int res; | ||
| 144 | |||
| 145 | for (i = 0; i < bus->nr_devices; i++) { | ||
| 146 | dev = &(bus->devices[i]); | ||
| 147 | if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT) | ||
| 148 | continue; | ||
| 149 | if (!dev->dev || | ||
| 150 | !dev->dev->driver || | ||
| 151 | !device_is_registered(dev->dev)) | ||
| 152 | continue; | ||
| 153 | res = ssb_gige_pcibios_plat_dev_init(dev, pdev); | ||
| 154 | if (res >= 0) | ||
| 155 | return res; | ||
| 156 | } | ||
| 157 | |||
| 158 | return -ENODEV; | ||
| 159 | } | ||
| 160 | #endif /* CONFIG_SSB_DRIVER_GIGE */ | ||
| 161 | |||
| 162 | int ssb_pcibios_plat_dev_init(struct pci_dev *dev) | ||
| 163 | { | ||
| 164 | int err; | ||
| 165 | |||
| 166 | err = ssb_pcicore_plat_dev_init(dev); | ||
| 167 | if (!err) | ||
| 168 | return 0; | ||
| 169 | #ifdef CONFIG_SSB_DRIVER_GIGE | ||
| 170 | err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback); | ||
| 171 | if (err >= 0) | ||
| 172 | return err; | ||
| 173 | #endif | ||
| 174 | /* This is not a PCI device on any SSB device. */ | ||
| 175 | |||
| 176 | return -ENODEV; | ||
| 177 | } | ||
| 178 | |||
| 179 | #ifdef CONFIG_SSB_DRIVER_GIGE | ||
| 180 | static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data) | ||
| 181 | { | ||
| 182 | const struct pci_dev *pdev = (const struct pci_dev *)data; | ||
| 183 | struct ssb_device *dev; | ||
| 184 | unsigned int i; | ||
| 185 | int res; | ||
| 186 | |||
| 187 | for (i = 0; i < bus->nr_devices; i++) { | ||
| 188 | dev = &(bus->devices[i]); | ||
| 189 | if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT) | ||
| 190 | continue; | ||
| 191 | if (!dev->dev || | ||
| 192 | !dev->dev->driver || | ||
| 193 | !device_is_registered(dev->dev)) | ||
| 194 | continue; | ||
| 195 | res = ssb_gige_map_irq(dev, pdev); | ||
| 196 | if (res >= 0) | ||
| 197 | return res; | ||
| 198 | } | ||
| 199 | |||
| 200 | return -ENODEV; | ||
| 201 | } | ||
| 202 | #endif /* CONFIG_SSB_DRIVER_GIGE */ | ||
| 203 | |||
| 204 | int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
| 205 | { | ||
| 206 | int res; | ||
| 207 | |||
| 208 | /* Check if this PCI device is a device on a SSB bus or device | ||
| 209 | * and return the IRQ number for it. */ | ||
| 210 | |||
| 211 | res = ssb_pcicore_pcibios_map_irq(dev, slot, pin); | ||
| 212 | if (res >= 0) | ||
| 213 | return res; | ||
| 214 | #ifdef CONFIG_SSB_DRIVER_GIGE | ||
| 215 | res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback); | ||
| 216 | if (res >= 0) | ||
| 217 | return res; | ||
| 218 | #endif | ||
| 219 | /* This is not a PCI device on any SSB device. */ | ||
| 220 | |||
| 221 | return -ENODEV; | ||
| 222 | } | ||
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 8db40c4b86e9..49d7bbb9bea7 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
| 15 | #include <linux/ssb/ssb.h> | 15 | #include <linux/ssb/ssb.h> |
| 16 | #include <linux/ssb/ssb_regs.h> | 16 | #include <linux/ssb/ssb_regs.h> |
| 17 | #include <linux/ssb/ssb_driver_gige.h> | ||
| 17 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
| 18 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
| 19 | 20 | ||
| @@ -68,6 +69,25 @@ found: | |||
| 68 | } | 69 | } |
| 69 | #endif /* CONFIG_SSB_PCIHOST */ | 70 | #endif /* CONFIG_SSB_PCIHOST */ |
| 70 | 71 | ||
| 72 | int ssb_for_each_bus_call(unsigned long data, | ||
| 73 | int (*func)(struct ssb_bus *bus, unsigned long data)) | ||
| 74 | { | ||
| 75 | struct ssb_bus *bus; | ||
| 76 | int res; | ||
| 77 | |||
| 78 | ssb_buses_lock(); | ||
| 79 | list_for_each_entry(bus, &buses, list) { | ||
| 80 | res = func(bus, data); | ||
| 81 | if (res >= 0) { | ||
| 82 | ssb_buses_unlock(); | ||
| 83 | return res; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | ssb_buses_unlock(); | ||
| 87 | |||
| 88 | return -ENODEV; | ||
| 89 | } | ||
| 90 | |||
| 71 | static struct ssb_device *ssb_device_get(struct ssb_device *dev) | 91 | static struct ssb_device *ssb_device_get(struct ssb_device *dev) |
| 72 | { | 92 | { |
| 73 | if (dev) | 93 | if (dev) |
| @@ -1171,7 +1191,14 @@ static int __init ssb_modinit(void) | |||
| 1171 | err = b43_pci_ssb_bridge_init(); | 1191 | err = b43_pci_ssb_bridge_init(); |
| 1172 | if (err) { | 1192 | if (err) { |
| 1173 | ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge " | 1193 | ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge " |
| 1174 | "initialization failed"); | 1194 | "initialization failed\n"); |
| 1195 | /* don't fail SSB init because of this */ | ||
| 1196 | err = 0; | ||
| 1197 | } | ||
| 1198 | err = ssb_gige_init(); | ||
| 1199 | if (err) { | ||
| 1200 | ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet " | ||
| 1201 | "driver initialization failed\n"); | ||
| 1175 | /* don't fail SSB init because of this */ | 1202 | /* don't fail SSB init because of this */ |
| 1176 | err = 0; | 1203 | err = 0; |
| 1177 | } | 1204 | } |
| @@ -1185,6 +1212,7 @@ fs_initcall(ssb_modinit); | |||
| 1185 | 1212 | ||
| 1186 | static void __exit ssb_modexit(void) | 1213 | static void __exit ssb_modexit(void) |
| 1187 | { | 1214 | { |
| 1215 | ssb_gige_exit(); | ||
| 1188 | b43_pci_ssb_bridge_exit(); | 1216 | b43_pci_ssb_bridge_exit(); |
| 1189 | bus_unregister(&ssb_bustype); | 1217 | bus_unregister(&ssb_bustype); |
| 1190 | } | 1218 | } |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 21eca2b5118b..d03b20983b1e 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
| @@ -118,6 +118,8 @@ extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m); | |||
| 118 | extern int ssb_devices_freeze(struct ssb_bus *bus); | 118 | extern int ssb_devices_freeze(struct ssb_bus *bus); |
| 119 | extern int ssb_devices_thaw(struct ssb_bus *bus); | 119 | extern int ssb_devices_thaw(struct ssb_bus *bus); |
| 120 | extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev); | 120 | extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev); |
| 121 | int ssb_for_each_bus_call(unsigned long data, | ||
| 122 | int (*func)(struct ssb_bus *bus, unsigned long data)); | ||
| 121 | 123 | ||
| 122 | /* b43_pci_bridge.c */ | 124 | /* b43_pci_bridge.c */ |
| 123 | #ifdef CONFIG_SSB_B43_PCI_BRIDGE | 125 | #ifdef CONFIG_SSB_B43_PCI_BRIDGE |
