diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt61pci.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.c | 169 |
1 files changed, 95 insertions, 74 deletions
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index b5ab771bbac2..b432cc21d248 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -271,63 +271,60 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) | |||
271 | /* | 271 | /* |
272 | * Configuration handlers. | 272 | * Configuration handlers. |
273 | */ | 273 | */ |
274 | static void rt61pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac) | 274 | static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, |
275 | struct rt2x00_intf *intf, | ||
276 | struct rt2x00intf_conf *conf, | ||
277 | const unsigned int flags) | ||
275 | { | 278 | { |
276 | u32 tmp; | 279 | unsigned int beacon_base; |
277 | 280 | u32 reg; | |
278 | tmp = le32_to_cpu(mac[1]); | ||
279 | rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); | ||
280 | mac[1] = cpu_to_le32(tmp); | ||
281 | |||
282 | rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, mac, | ||
283 | (2 * sizeof(__le32))); | ||
284 | } | ||
285 | 281 | ||
286 | static void rt61pci_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid) | 282 | if (flags & CONFIG_UPDATE_TYPE) { |
287 | { | 283 | /* |
288 | u32 tmp; | 284 | * Clear current synchronisation setup. |
285 | * For the Beacon base registers we only need to clear | ||
286 | * the first byte since that byte contains the VALID and OWNER | ||
287 | * bits which (when set to 0) will invalidate the entire beacon. | ||
288 | */ | ||
289 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | ||
290 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); | ||
291 | rt2x00pci_register_write(rt2x00dev, beacon_base, 0); | ||
289 | 292 | ||
290 | tmp = le32_to_cpu(bssid[1]); | 293 | /* |
291 | rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3); | 294 | * Enable synchronisation. |
292 | bssid[1] = cpu_to_le32(tmp); | 295 | */ |
296 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | ||
297 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | ||
298 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, | ||
299 | (conf->sync == TSF_SYNC_BEACON)); | ||
300 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | ||
301 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); | ||
302 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
303 | } | ||
293 | 304 | ||
294 | rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, bssid, | 305 | if (flags & CONFIG_UPDATE_MAC) { |
295 | (2 * sizeof(__le32))); | 306 | reg = le32_to_cpu(conf->mac[1]); |
296 | } | 307 | rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); |
308 | conf->mac[1] = cpu_to_le32(reg); | ||
297 | 309 | ||
298 | static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, | 310 | rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, |
299 | const int tsf_sync) | 311 | conf->mac, sizeof(conf->mac)); |
300 | { | 312 | } |
301 | u32 reg; | ||
302 | 313 | ||
303 | /* | 314 | if (flags & CONFIG_UPDATE_BSSID) { |
304 | * Clear current synchronisation setup. | 315 | reg = le32_to_cpu(conf->bssid[1]); |
305 | * For the Beacon base registers we only need to clear | 316 | rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); |
306 | * the first byte since that byte contains the VALID and OWNER | 317 | conf->bssid[1] = cpu_to_le32(reg); |
307 | * bits which (when set to 0) will invalidate the entire beacon. | ||
308 | */ | ||
309 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); | ||
310 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); | ||
311 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); | ||
312 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); | ||
313 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); | ||
314 | 318 | ||
315 | /* | 319 | rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, |
316 | * Enable synchronisation. | 320 | conf->bssid, sizeof(conf->bssid)); |
317 | */ | 321 | } |
318 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | ||
319 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | ||
320 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, | ||
321 | (tsf_sync == TSF_SYNC_BEACON)); | ||
322 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | ||
323 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync); | ||
324 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
325 | } | 322 | } |
326 | 323 | ||
327 | static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, | 324 | static int rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, |
328 | const int short_preamble, | 325 | const int short_preamble, |
329 | const int ack_timeout, | 326 | const int ack_timeout, |
330 | const int ack_consume_time) | 327 | const int ack_consume_time) |
331 | { | 328 | { |
332 | u32 reg; | 329 | u32 reg; |
333 | 330 | ||
@@ -339,6 +336,8 @@ static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, | |||
339 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, | 336 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, |
340 | !!short_preamble); | 337 | !!short_preamble); |
341 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); | 338 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); |
339 | |||
340 | return 0; | ||
342 | } | 341 | } |
343 | 342 | ||
344 | static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev, | 343 | static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev, |
@@ -667,8 +666,8 @@ static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev, | |||
667 | } | 666 | } |
668 | 667 | ||
669 | static void rt61pci_config(struct rt2x00_dev *rt2x00dev, | 668 | static void rt61pci_config(struct rt2x00_dev *rt2x00dev, |
670 | const unsigned int flags, | 669 | struct rt2x00lib_conf *libconf, |
671 | struct rt2x00lib_conf *libconf) | 670 | const unsigned int flags) |
672 | { | 671 | { |
673 | if (flags & CONFIG_UPDATE_PHYMODE) | 672 | if (flags & CONFIG_UPDATE_PHYMODE) |
674 | rt61pci_config_phymode(rt2x00dev, libconf->basic_rates); | 673 | rt61pci_config_phymode(rt2x00dev, libconf->basic_rates); |
@@ -816,6 +815,13 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) | |||
816 | } | 815 | } |
817 | 816 | ||
818 | /* | 817 | /* |
818 | * If we are not associated, we should go straight to the | ||
819 | * dynamic CCA tuning. | ||
820 | */ | ||
821 | if (!rt2x00dev->intf_associated) | ||
822 | goto dynamic_cca_tune; | ||
823 | |||
824 | /* | ||
819 | * Special big-R17 for very short distance | 825 | * Special big-R17 for very short distance |
820 | */ | 826 | */ |
821 | if (rssi >= -35) { | 827 | if (rssi >= -35) { |
@@ -866,6 +872,8 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) | |||
866 | return; | 872 | return; |
867 | } | 873 | } |
868 | 874 | ||
875 | dynamic_cca_tune: | ||
876 | |||
869 | /* | 877 | /* |
870 | * r17 does not yet exceed upper limit, continue and base | 878 | * r17 does not yet exceed upper limit, continue and base |
871 | * the r17 tuning on the false CCA count. | 879 | * the r17 tuning on the false CCA count. |
@@ -1215,6 +1223,17 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1215 | rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg); | 1223 | rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg); |
1216 | 1224 | ||
1217 | /* | 1225 | /* |
1226 | * Clear all beacons | ||
1227 | * For the Beacon base registers we only need to clear | ||
1228 | * the first byte since that byte contains the VALID and OWNER | ||
1229 | * bits which (when set to 0) will invalidate the entire beacon. | ||
1230 | */ | ||
1231 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); | ||
1232 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); | ||
1233 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); | ||
1234 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); | ||
1235 | |||
1236 | /* | ||
1218 | * We must clear the error counters. | 1237 | * We must clear the error counters. |
1219 | * These registers are cleared on read, | 1238 | * These registers are cleared on read, |
1220 | * so we may pass a useless variable to store the value. | 1239 | * so we may pass a useless variable to store the value. |
@@ -2378,25 +2397,20 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2378 | struct ieee80211_tx_control *control) | 2397 | struct ieee80211_tx_control *control) |
2379 | { | 2398 | { |
2380 | struct rt2x00_dev *rt2x00dev = hw->priv; | 2399 | struct rt2x00_dev *rt2x00dev = hw->priv; |
2400 | struct rt2x00_intf *intf = vif_to_intf(control->vif); | ||
2381 | struct skb_frame_desc *skbdesc; | 2401 | struct skb_frame_desc *skbdesc; |
2382 | struct data_queue *queue; | 2402 | unsigned int beacon_base; |
2383 | struct queue_entry *entry; | ||
2384 | 2403 | ||
2385 | /* | 2404 | if (unlikely(!intf->beacon)) |
2386 | * Just in case the ieee80211 doesn't set this, | 2405 | return -ENOBUFS; |
2387 | * but we need this queue set for the descriptor | ||
2388 | * initialization. | ||
2389 | */ | ||
2390 | control->queue = IEEE80211_TX_QUEUE_BEACON; | ||
2391 | queue = rt2x00queue_get_queue(rt2x00dev, control->queue); | ||
2392 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
2393 | 2406 | ||
2394 | /* | 2407 | /* |
2395 | * We need to append the descriptor in front of the | 2408 | * We need to append the descriptor in front of the |
2396 | * beacon frame. | 2409 | * beacon frame. |
2397 | */ | 2410 | */ |
2398 | if (skb_headroom(skb) < queue->desc_size) { | 2411 | if (skb_headroom(skb) < intf->beacon->queue->desc_size) { |
2399 | if (pskb_expand_head(skb, queue->desc_size, 0, GFP_ATOMIC)) { | 2412 | if (pskb_expand_head(skb, intf->beacon->queue->desc_size, |
2413 | 0, GFP_ATOMIC)) { | ||
2400 | dev_kfree_skb(skb); | 2414 | dev_kfree_skb(skb); |
2401 | return -ENOMEM; | 2415 | return -ENOMEM; |
2402 | } | 2416 | } |
@@ -2405,29 +2419,36 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2405 | /* | 2419 | /* |
2406 | * Add the descriptor in front of the skb. | 2420 | * Add the descriptor in front of the skb. |
2407 | */ | 2421 | */ |
2408 | skb_push(skb, queue->desc_size); | 2422 | skb_push(skb, intf->beacon->queue->desc_size); |
2409 | memset(skb->data, 0, queue->desc_size); | 2423 | memset(skb->data, 0, intf->beacon->queue->desc_size); |
2410 | 2424 | ||
2411 | /* | 2425 | /* |
2412 | * Fill in skb descriptor | 2426 | * Fill in skb descriptor |
2413 | */ | 2427 | */ |
2414 | skbdesc = get_skb_frame_desc(skb); | 2428 | skbdesc = get_skb_frame_desc(skb); |
2415 | memset(skbdesc, 0, sizeof(*skbdesc)); | 2429 | memset(skbdesc, 0, sizeof(*skbdesc)); |
2416 | skbdesc->data = skb->data + queue->desc_size; | 2430 | skbdesc->data = skb->data + intf->beacon->queue->desc_size; |
2417 | skbdesc->data_len = queue->data_size; | 2431 | skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; |
2418 | skbdesc->desc = skb->data; | 2432 | skbdesc->desc = skb->data; |
2419 | skbdesc->desc_len = queue->desc_size; | 2433 | skbdesc->desc_len = intf->beacon->queue->desc_size; |
2420 | skbdesc->entry = entry; | 2434 | skbdesc->entry = intf->beacon; |
2421 | 2435 | ||
2436 | /* | ||
2437 | * Just in case the ieee80211 doesn't set this, | ||
2438 | * but we need this queue set for the descriptor | ||
2439 | * initialization. | ||
2440 | */ | ||
2441 | control->queue = IEEE80211_TX_QUEUE_BEACON; | ||
2422 | rt2x00lib_write_tx_desc(rt2x00dev, skb, control); | 2442 | rt2x00lib_write_tx_desc(rt2x00dev, skb, control); |
2423 | 2443 | ||
2424 | /* | 2444 | /* |
2425 | * Write entire beacon with descriptor to register, | 2445 | * Write entire beacon with descriptor to register, |
2426 | * and kick the beacon generator. | 2446 | * and kick the beacon generator. |
2427 | */ | 2447 | */ |
2428 | rt2x00pci_register_multiwrite(rt2x00dev, HW_BEACON_BASE0, | 2448 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); |
2449 | rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, | ||
2429 | skb->data, skb->len); | 2450 | skb->data, skb->len); |
2430 | rt61pci_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); | 2451 | rt61pci_kick_tx_queue(rt2x00dev, control->queue); |
2431 | 2452 | ||
2432 | return 0; | 2453 | return 0; |
2433 | } | 2454 | } |
@@ -2469,9 +2490,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | |||
2469 | .write_tx_data = rt2x00pci_write_tx_data, | 2490 | .write_tx_data = rt2x00pci_write_tx_data, |
2470 | .kick_tx_queue = rt61pci_kick_tx_queue, | 2491 | .kick_tx_queue = rt61pci_kick_tx_queue, |
2471 | .fill_rxdone = rt61pci_fill_rxdone, | 2492 | .fill_rxdone = rt61pci_fill_rxdone, |
2472 | .config_mac_addr = rt61pci_config_mac_addr, | 2493 | .config_intf = rt61pci_config_intf, |
2473 | .config_bssid = rt61pci_config_bssid, | ||
2474 | .config_type = rt61pci_config_type, | ||
2475 | .config_preamble = rt61pci_config_preamble, | 2494 | .config_preamble = rt61pci_config_preamble, |
2476 | .config = rt61pci_config, | 2495 | .config = rt61pci_config, |
2477 | }; | 2496 | }; |
@@ -2491,7 +2510,7 @@ static const struct data_queue_desc rt61pci_queue_tx = { | |||
2491 | }; | 2510 | }; |
2492 | 2511 | ||
2493 | static const struct data_queue_desc rt61pci_queue_bcn = { | 2512 | static const struct data_queue_desc rt61pci_queue_bcn = { |
2494 | .entry_num = BEACON_ENTRIES, | 2513 | .entry_num = 4 * BEACON_ENTRIES, |
2495 | .data_size = MGMT_FRAME_SIZE, | 2514 | .data_size = MGMT_FRAME_SIZE, |
2496 | .desc_size = TXINFO_SIZE, | 2515 | .desc_size = TXINFO_SIZE, |
2497 | .priv_size = sizeof(struct queue_entry_priv_pci_tx), | 2516 | .priv_size = sizeof(struct queue_entry_priv_pci_tx), |
@@ -2499,6 +2518,8 @@ static const struct data_queue_desc rt61pci_queue_bcn = { | |||
2499 | 2518 | ||
2500 | static const struct rt2x00_ops rt61pci_ops = { | 2519 | static const struct rt2x00_ops rt61pci_ops = { |
2501 | .name = KBUILD_MODNAME, | 2520 | .name = KBUILD_MODNAME, |
2521 | .max_sta_intf = 1, | ||
2522 | .max_ap_intf = 4, | ||
2502 | .eeprom_size = EEPROM_SIZE, | 2523 | .eeprom_size = EEPROM_SIZE, |
2503 | .rf_size = RF_SIZE, | 2524 | .rf_size = RF_SIZE, |
2504 | .rx = &rt61pci_queue_rx, | 2525 | .rx = &rt61pci_queue_rx, |