diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt61pci.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.c | 95 |
1 files changed, 57 insertions, 38 deletions
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 432e75f960b7..2e3076f67535 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -1764,7 +1764,8 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1764 | struct txentry_desc *txdesc) | 1764 | struct txentry_desc *txdesc) |
1765 | { | 1765 | { |
1766 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 1766 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); |
1767 | __le32 *txd = skbdesc->desc; | 1767 | struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; |
1768 | __le32 *txd = entry_priv->desc; | ||
1768 | u32 word; | 1769 | u32 word; |
1769 | 1770 | ||
1770 | /* | 1771 | /* |
@@ -1802,17 +1803,23 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1802 | rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); | 1803 | rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); |
1803 | rt2x00_desc_write(txd, 5, word); | 1804 | rt2x00_desc_write(txd, 5, word); |
1804 | 1805 | ||
1805 | rt2x00_desc_read(txd, 6, &word); | 1806 | if (txdesc->queue != QID_BEACON) { |
1806 | rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, | 1807 | rt2x00_desc_read(txd, 6, &word); |
1807 | skbdesc->skb_dma); | 1808 | rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, |
1808 | rt2x00_desc_write(txd, 6, word); | 1809 | skbdesc->skb_dma); |
1810 | rt2x00_desc_write(txd, 6, word); | ||
1809 | 1811 | ||
1810 | if (skbdesc->desc_len > TXINFO_SIZE) { | ||
1811 | rt2x00_desc_read(txd, 11, &word); | 1812 | rt2x00_desc_read(txd, 11, &word); |
1812 | rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skb->len); | 1813 | rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, |
1814 | txdesc->length); | ||
1813 | rt2x00_desc_write(txd, 11, word); | 1815 | rt2x00_desc_write(txd, 11, word); |
1814 | } | 1816 | } |
1815 | 1817 | ||
1818 | /* | ||
1819 | * Writing TXD word 0 must the last to prevent a race condition with | ||
1820 | * the device, whereby the device may take hold of the TXD before we | ||
1821 | * finished updating it. | ||
1822 | */ | ||
1816 | rt2x00_desc_read(txd, 0, &word); | 1823 | rt2x00_desc_read(txd, 0, &word); |
1817 | rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); | 1824 | rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); |
1818 | rt2x00_set_field32(&word, TXD_W0_VALID, 1); | 1825 | rt2x00_set_field32(&word, TXD_W0_VALID, 1); |
@@ -1832,20 +1839,28 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1832 | rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, | 1839 | rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, |
1833 | test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); | 1840 | test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); |
1834 | rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); | 1841 | rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); |
1835 | rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); | 1842 | rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); |
1836 | rt2x00_set_field32(&word, TXD_W0_BURST, | 1843 | rt2x00_set_field32(&word, TXD_W0_BURST, |
1837 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); | 1844 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); |
1838 | rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); | 1845 | rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); |
1839 | rt2x00_desc_write(txd, 0, word); | 1846 | rt2x00_desc_write(txd, 0, word); |
1847 | |||
1848 | /* | ||
1849 | * Register descriptor details in skb frame descriptor. | ||
1850 | */ | ||
1851 | skbdesc->desc = txd; | ||
1852 | skbdesc->desc_len = | ||
1853 | (txdesc->queue == QID_BEACON) ? TXINFO_SIZE : TXD_DESC_SIZE; | ||
1840 | } | 1854 | } |
1841 | 1855 | ||
1842 | /* | 1856 | /* |
1843 | * TX data initialization | 1857 | * TX data initialization |
1844 | */ | 1858 | */ |
1845 | static void rt61pci_write_beacon(struct queue_entry *entry) | 1859 | static void rt61pci_write_beacon(struct queue_entry *entry, |
1860 | struct txentry_desc *txdesc) | ||
1846 | { | 1861 | { |
1847 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 1862 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
1848 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 1863 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
1849 | unsigned int beacon_base; | 1864 | unsigned int beacon_base; |
1850 | u32 reg; | 1865 | u32 reg; |
1851 | 1866 | ||
@@ -1861,14 +1876,25 @@ static void rt61pci_write_beacon(struct queue_entry *entry) | |||
1861 | * Write entire beacon with descriptor to register. | 1876 | * Write entire beacon with descriptor to register. |
1862 | */ | 1877 | */ |
1863 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); | 1878 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); |
1864 | rt2x00pci_register_multiwrite(rt2x00dev, | 1879 | rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, |
1865 | beacon_base, | 1880 | entry_priv->desc, TXINFO_SIZE); |
1866 | skbdesc->desc, skbdesc->desc_len); | 1881 | rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE, |
1867 | rt2x00pci_register_multiwrite(rt2x00dev, | ||
1868 | beacon_base + skbdesc->desc_len, | ||
1869 | entry->skb->data, entry->skb->len); | 1882 | entry->skb->data, entry->skb->len); |
1870 | 1883 | ||
1871 | /* | 1884 | /* |
1885 | * Enable beaconing again. | ||
1886 | * | ||
1887 | * For Wi-Fi faily generated beacons between participating | ||
1888 | * stations. Set TBTT phase adaptive adjustment step to 8us. | ||
1889 | */ | ||
1890 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); | ||
1891 | |||
1892 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | ||
1893 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | ||
1894 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | ||
1895 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
1896 | |||
1897 | /* | ||
1872 | * Clean up beacon skb. | 1898 | * Clean up beacon skb. |
1873 | */ | 1899 | */ |
1874 | dev_kfree_skb_any(entry->skb); | 1900 | dev_kfree_skb_any(entry->skb); |
@@ -1880,23 +1906,6 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | |||
1880 | { | 1906 | { |
1881 | u32 reg; | 1907 | u32 reg; |
1882 | 1908 | ||
1883 | if (queue == QID_BEACON) { | ||
1884 | /* | ||
1885 | * For Wi-Fi faily generated beacons between participating | ||
1886 | * stations. Set TBTT phase adaptive adjustment step to 8us. | ||
1887 | */ | ||
1888 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); | ||
1889 | |||
1890 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | ||
1891 | if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) { | ||
1892 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | ||
1893 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | ||
1894 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | ||
1895 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
1896 | } | ||
1897 | return; | ||
1898 | } | ||
1899 | |||
1900 | rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); | 1909 | rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); |
1901 | rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, (queue == QID_AC_BE)); | 1910 | rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, (queue == QID_AC_BE)); |
1902 | rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, (queue == QID_AC_BK)); | 1911 | rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, (queue == QID_AC_BK)); |
@@ -1968,12 +1977,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry, | |||
1968 | if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) | 1977 | if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) |
1969 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; | 1978 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; |
1970 | 1979 | ||
1971 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { | 1980 | rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG); |
1972 | rxdesc->cipher = | 1981 | rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR); |
1973 | rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG); | ||
1974 | rxdesc->cipher_status = | ||
1975 | rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR); | ||
1976 | } | ||
1977 | 1982 | ||
1978 | if (rxdesc->cipher != CIPHER_NONE) { | 1983 | if (rxdesc->cipher != CIPHER_NONE) { |
1979 | _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv[0]); | 1984 | _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv[0]); |
@@ -2118,6 +2123,14 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2118 | } | 2123 | } |
2119 | } | 2124 | } |
2120 | 2125 | ||
2126 | static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) | ||
2127 | { | ||
2128 | struct ieee80211_conf conf = { .flags = 0 }; | ||
2129 | struct rt2x00lib_conf libconf = { .conf = &conf }; | ||
2130 | |||
2131 | rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | ||
2132 | } | ||
2133 | |||
2121 | static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | 2134 | static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) |
2122 | { | 2135 | { |
2123 | struct rt2x00_dev *rt2x00dev = dev_instance; | 2136 | struct rt2x00_dev *rt2x00dev = dev_instance; |
@@ -2165,6 +2178,12 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | |||
2165 | rt2x00pci_register_write(rt2x00dev, | 2178 | rt2x00pci_register_write(rt2x00dev, |
2166 | M2H_CMD_DONE_CSR, 0xffffffff); | 2179 | M2H_CMD_DONE_CSR, 0xffffffff); |
2167 | 2180 | ||
2181 | /* | ||
2182 | * 4 - MCU Autowakeup interrupt. | ||
2183 | */ | ||
2184 | if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP)) | ||
2185 | rt61pci_wakeup(rt2x00dev); | ||
2186 | |||
2168 | return IRQ_HANDLED; | 2187 | return IRQ_HANDLED; |
2169 | } | 2188 | } |
2170 | 2189 | ||