diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2500usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 134 |
1 files changed, 129 insertions, 5 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 0447e93306ad..30028e2422fc 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -36,6 +36,13 @@ | |||
36 | #include "rt2500usb.h" | 36 | #include "rt2500usb.h" |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Allow hardware encryption to be disabled. | ||
40 | */ | ||
41 | static int modparam_nohwcrypt = 1; | ||
42 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | ||
43 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | ||
44 | |||
45 | /* | ||
39 | * Register access. | 46 | * Register access. |
40 | * All access to the CSR registers will go through the methods | 47 | * All access to the CSR registers will go through the methods |
41 | * rt2500usb_register_read and rt2500usb_register_write. | 48 | * rt2500usb_register_read and rt2500usb_register_write. |
@@ -323,6 +330,82 @@ static void rt2500usb_init_led(struct rt2x00_dev *rt2x00dev, | |||
323 | /* | 330 | /* |
324 | * Configuration handlers. | 331 | * Configuration handlers. |
325 | */ | 332 | */ |
333 | |||
334 | /* | ||
335 | * rt2500usb does not differentiate between shared and pairwise | ||
336 | * keys, so we should use the same function for both key types. | ||
337 | */ | ||
338 | static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, | ||
339 | struct rt2x00lib_crypto *crypto, | ||
340 | struct ieee80211_key_conf *key) | ||
341 | { | ||
342 | int timeout; | ||
343 | u32 mask; | ||
344 | u16 reg; | ||
345 | |||
346 | if (crypto->cmd == SET_KEY) { | ||
347 | /* | ||
348 | * Pairwise key will always be entry 0, but this | ||
349 | * could collide with a shared key on the same | ||
350 | * position... | ||
351 | */ | ||
352 | mask = TXRX_CSR0_KEY_ID.bit_mask; | ||
353 | |||
354 | rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); | ||
355 | reg &= mask; | ||
356 | |||
357 | if (reg && reg == mask) | ||
358 | return -ENOSPC; | ||
359 | |||
360 | reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); | ||
361 | |||
362 | key->hw_key_idx += reg ? ffz(reg) : 0; | ||
363 | |||
364 | /* | ||
365 | * The encryption key doesn't fit within the CSR cache, | ||
366 | * this means we should allocate it seperately and use | ||
367 | * rt2x00usb_vendor_request() to send the key to the hardware. | ||
368 | */ | ||
369 | reg = KEY_ENTRY(key->hw_key_idx); | ||
370 | timeout = REGISTER_TIMEOUT32(sizeof(crypto->key)); | ||
371 | rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, | ||
372 | USB_VENDOR_REQUEST_OUT, reg, | ||
373 | crypto->key, | ||
374 | sizeof(crypto->key), | ||
375 | timeout); | ||
376 | |||
377 | /* | ||
378 | * The driver does not support the IV/EIV generation | ||
379 | * in hardware. However it doesn't support the IV/EIV | ||
380 | * inside the ieee80211 frame either, but requires it | ||
381 | * to be provided seperately for the descriptor. | ||
382 | * rt2x00lib will cut the IV/EIV data out of all frames | ||
383 | * given to us by mac80211, but we must tell mac80211 | ||
384 | * to generate the IV/EIV data. | ||
385 | */ | ||
386 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
387 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
388 | } | ||
389 | |||
390 | /* | ||
391 | * TXRX_CSR0_KEY_ID contains only single-bit fields to indicate | ||
392 | * a particular key is valid. | ||
393 | */ | ||
394 | rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); | ||
395 | rt2x00_set_field16(®, TXRX_CSR0_ALGORITHM, crypto->cipher); | ||
396 | rt2x00_set_field16(®, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER); | ||
397 | |||
398 | mask = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); | ||
399 | if (crypto->cmd == SET_KEY) | ||
400 | mask |= 1 << key->hw_key_idx; | ||
401 | else if (crypto->cmd == DISABLE_KEY) | ||
402 | mask &= ~(1 << key->hw_key_idx); | ||
403 | rt2x00_set_field16(®, TXRX_CSR0_KEY_ID, mask); | ||
404 | rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg); | ||
405 | |||
406 | return 0; | ||
407 | } | ||
408 | |||
326 | static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev, | 409 | static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev, |
327 | const unsigned int filter_flags) | 410 | const unsigned int filter_flags) |
328 | { | 411 | { |
@@ -844,7 +927,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
844 | 927 | ||
845 | rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); | 928 | rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); |
846 | rt2x00_set_field16(®, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER); | 929 | rt2x00_set_field16(®, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER); |
847 | rt2x00_set_field16(®, TXRX_CSR0_KEY_ID, 0xff); | 930 | rt2x00_set_field16(®, TXRX_CSR0_KEY_ID, 0); |
848 | rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg); | 931 | rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg); |
849 | 932 | ||
850 | rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); | 933 | rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); |
@@ -1066,7 +1149,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1066 | * Start writing the descriptor words. | 1149 | * Start writing the descriptor words. |
1067 | */ | 1150 | */ |
1068 | rt2x00_desc_read(txd, 1, &word); | 1151 | rt2x00_desc_read(txd, 1, &word); |
1069 | rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); | 1152 | rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); |
1070 | rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs); | 1153 | rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs); |
1071 | rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); | 1154 | rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); |
1072 | rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); | 1155 | rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); |
@@ -1079,6 +1162,11 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1079 | rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); | 1162 | rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); |
1080 | rt2x00_desc_write(txd, 2, word); | 1163 | rt2x00_desc_write(txd, 2, word); |
1081 | 1164 | ||
1165 | if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { | ||
1166 | _rt2x00_desc_write(txd, 3, skbdesc->iv[0]); | ||
1167 | _rt2x00_desc_write(txd, 4, skbdesc->iv[1]); | ||
1168 | } | ||
1169 | |||
1082 | rt2x00_desc_read(txd, 0, &word); | 1170 | rt2x00_desc_read(txd, 0, &word); |
1083 | rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit); | 1171 | rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit); |
1084 | rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, | 1172 | rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, |
@@ -1093,7 +1181,8 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1093 | test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); | 1181 | test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); |
1094 | rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); | 1182 | rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); |
1095 | rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); | 1183 | rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); |
1096 | rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE); | 1184 | rt2x00_set_field32(&word, TXD_W0_CIPHER, txdesc->cipher); |
1185 | rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx); | ||
1097 | rt2x00_desc_write(txd, 0, word); | 1186 | rt2x00_desc_write(txd, 0, word); |
1098 | } | 1187 | } |
1099 | 1188 | ||
@@ -1204,6 +1293,7 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | |||
1204 | static void rt2500usb_fill_rxdone(struct queue_entry *entry, | 1293 | static void rt2500usb_fill_rxdone(struct queue_entry *entry, |
1205 | struct rxdone_entry_desc *rxdesc) | 1294 | struct rxdone_entry_desc *rxdesc) |
1206 | { | 1295 | { |
1296 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
1207 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 1297 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
1208 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 1298 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
1209 | __le32 *rxd = | 1299 | __le32 *rxd = |
@@ -1231,6 +1321,33 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, | |||
1231 | if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) | 1321 | if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) |
1232 | rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; | 1322 | rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; |
1233 | 1323 | ||
1324 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { | ||
1325 | rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER); | ||
1326 | if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR)) | ||
1327 | rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY; | ||
1328 | } | ||
1329 | |||
1330 | if (rxdesc->cipher != CIPHER_NONE) { | ||
1331 | _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]); | ||
1332 | _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]); | ||
1333 | rxdesc->dev_flags |= RXDONE_CRYPTO_IV; | ||
1334 | |||
1335 | /* ICV is located at the end of frame */ | ||
1336 | |||
1337 | /* | ||
1338 | * Hardware has stripped IV/EIV data from 802.11 frame during | ||
1339 | * decryption. It has provided the data seperately but rt2x00lib | ||
1340 | * should decide if it should be reinserted. | ||
1341 | */ | ||
1342 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | ||
1343 | if (rxdesc->cipher != CIPHER_TKIP) | ||
1344 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | ||
1345 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) | ||
1346 | rxdesc->flags |= RX_FLAG_DECRYPTED; | ||
1347 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) | ||
1348 | rxdesc->flags |= RX_FLAG_MMIC_ERROR; | ||
1349 | } | ||
1350 | |||
1234 | /* | 1351 | /* |
1235 | * Obtain the status about this packet. | 1352 | * Obtain the status about this packet. |
1236 | * When frame was received with an OFDM bitrate, | 1353 | * When frame was received with an OFDM bitrate, |
@@ -1238,8 +1355,8 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, | |||
1238 | * a CCK bitrate the signal is the rate in 100kbit/s. | 1355 | * a CCK bitrate the signal is the rate in 100kbit/s. |
1239 | */ | 1356 | */ |
1240 | rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); | 1357 | rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); |
1241 | rxdesc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) - | 1358 | rxdesc->rssi = |
1242 | entry->queue->rt2x00dev->rssi_offset; | 1359 | rt2x00_get_field32(word1, RXD_W1_RSSI) - rt2x00dev->rssi_offset; |
1243 | rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); | 1360 | rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); |
1244 | 1361 | ||
1245 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) | 1362 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) |
@@ -1727,6 +1844,10 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1727 | __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); | 1844 | __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); |
1728 | __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); | 1845 | __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); |
1729 | __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); | 1846 | __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); |
1847 | if (!modparam_nohwcrypt) { | ||
1848 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | ||
1849 | __set_bit(CONFIG_CRYPTO_COPY_IV, &rt2x00dev->flags); | ||
1850 | } | ||
1730 | __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); | 1851 | __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); |
1731 | 1852 | ||
1732 | /* | 1853 | /* |
@@ -1746,6 +1867,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { | |||
1746 | .config = rt2x00mac_config, | 1867 | .config = rt2x00mac_config, |
1747 | .config_interface = rt2x00mac_config_interface, | 1868 | .config_interface = rt2x00mac_config_interface, |
1748 | .configure_filter = rt2x00mac_configure_filter, | 1869 | .configure_filter = rt2x00mac_configure_filter, |
1870 | .set_key = rt2x00mac_set_key, | ||
1749 | .get_stats = rt2x00mac_get_stats, | 1871 | .get_stats = rt2x00mac_get_stats, |
1750 | .bss_info_changed = rt2x00mac_bss_info_changed, | 1872 | .bss_info_changed = rt2x00mac_bss_info_changed, |
1751 | .conf_tx = rt2x00mac_conf_tx, | 1873 | .conf_tx = rt2x00mac_conf_tx, |
@@ -1767,6 +1889,8 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { | |||
1767 | .get_tx_data_len = rt2500usb_get_tx_data_len, | 1889 | .get_tx_data_len = rt2500usb_get_tx_data_len, |
1768 | .kick_tx_queue = rt2500usb_kick_tx_queue, | 1890 | .kick_tx_queue = rt2500usb_kick_tx_queue, |
1769 | .fill_rxdone = rt2500usb_fill_rxdone, | 1891 | .fill_rxdone = rt2500usb_fill_rxdone, |
1892 | .config_shared_key = rt2500usb_config_key, | ||
1893 | .config_pairwise_key = rt2500usb_config_key, | ||
1770 | .config_filter = rt2500usb_config_filter, | 1894 | .config_filter = rt2500usb_config_filter, |
1771 | .config_intf = rt2500usb_config_intf, | 1895 | .config_intf = rt2500usb_config_intf, |
1772 | .config_erp = rt2500usb_config_erp, | 1896 | .config_erp = rt2500usb_config_erp, |