diff options
Diffstat (limited to 'drivers/net/wireless/zd1211rw/zd_mac.c')
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.c | 404 |
1 files changed, 248 insertions, 156 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 5e4f4b707375..44f3cfd4cc1d 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -32,6 +32,8 @@ | |||
32 | 32 | ||
33 | static void ieee_init(struct ieee80211_device *ieee); | 33 | static void ieee_init(struct ieee80211_device *ieee); |
34 | static void softmac_init(struct ieee80211softmac_device *sm); | 34 | static void softmac_init(struct ieee80211softmac_device *sm); |
35 | static void set_rts_cts_work(void *d); | ||
36 | static void set_basic_rates_work(void *d); | ||
35 | 37 | ||
36 | static void housekeeping_init(struct zd_mac *mac); | 38 | static void housekeeping_init(struct zd_mac *mac); |
37 | static void housekeeping_enable(struct zd_mac *mac); | 39 | static void housekeeping_enable(struct zd_mac *mac); |
@@ -46,6 +48,8 @@ int zd_mac_init(struct zd_mac *mac, | |||
46 | memset(mac, 0, sizeof(*mac)); | 48 | memset(mac, 0, sizeof(*mac)); |
47 | spin_lock_init(&mac->lock); | 49 | spin_lock_init(&mac->lock); |
48 | mac->netdev = netdev; | 50 | mac->netdev = netdev; |
51 | INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work, mac); | ||
52 | INIT_WORK(&mac->set_basic_rates_work, set_basic_rates_work, mac); | ||
49 | 53 | ||
50 | ieee_init(ieee); | 54 | ieee_init(ieee); |
51 | softmac_init(ieee80211_priv(netdev)); | 55 | softmac_init(ieee80211_priv(netdev)); |
@@ -213,6 +217,13 @@ int zd_mac_stop(struct net_device *netdev) | |||
213 | housekeeping_disable(mac); | 217 | housekeeping_disable(mac); |
214 | ieee80211softmac_stop(netdev); | 218 | ieee80211softmac_stop(netdev); |
215 | 219 | ||
220 | /* Ensure no work items are running or queued from this point */ | ||
221 | cancel_delayed_work(&mac->set_rts_cts_work); | ||
222 | cancel_delayed_work(&mac->set_basic_rates_work); | ||
223 | flush_workqueue(zd_workqueue); | ||
224 | mac->updating_rts_rate = 0; | ||
225 | mac->updating_basic_rates = 0; | ||
226 | |||
216 | zd_chip_disable_hwint(chip); | 227 | zd_chip_disable_hwint(chip); |
217 | zd_chip_switch_radio_off(chip); | 228 | zd_chip_switch_radio_off(chip); |
218 | zd_chip_disable_int(chip); | 229 | zd_chip_disable_int(chip); |
@@ -286,6 +297,186 @@ u8 zd_mac_get_regdomain(struct zd_mac *mac) | |||
286 | return regdomain; | 297 | return regdomain; |
287 | } | 298 | } |
288 | 299 | ||
300 | /* Fallback to lowest rate, if rate is unknown. */ | ||
301 | static u8 rate_to_zd_rate(u8 rate) | ||
302 | { | ||
303 | switch (rate) { | ||
304 | case IEEE80211_CCK_RATE_2MB: | ||
305 | return ZD_CCK_RATE_2M; | ||
306 | case IEEE80211_CCK_RATE_5MB: | ||
307 | return ZD_CCK_RATE_5_5M; | ||
308 | case IEEE80211_CCK_RATE_11MB: | ||
309 | return ZD_CCK_RATE_11M; | ||
310 | case IEEE80211_OFDM_RATE_6MB: | ||
311 | return ZD_OFDM_RATE_6M; | ||
312 | case IEEE80211_OFDM_RATE_9MB: | ||
313 | return ZD_OFDM_RATE_9M; | ||
314 | case IEEE80211_OFDM_RATE_12MB: | ||
315 | return ZD_OFDM_RATE_12M; | ||
316 | case IEEE80211_OFDM_RATE_18MB: | ||
317 | return ZD_OFDM_RATE_18M; | ||
318 | case IEEE80211_OFDM_RATE_24MB: | ||
319 | return ZD_OFDM_RATE_24M; | ||
320 | case IEEE80211_OFDM_RATE_36MB: | ||
321 | return ZD_OFDM_RATE_36M; | ||
322 | case IEEE80211_OFDM_RATE_48MB: | ||
323 | return ZD_OFDM_RATE_48M; | ||
324 | case IEEE80211_OFDM_RATE_54MB: | ||
325 | return ZD_OFDM_RATE_54M; | ||
326 | } | ||
327 | return ZD_CCK_RATE_1M; | ||
328 | } | ||
329 | |||
330 | static u16 rate_to_cr_rate(u8 rate) | ||
331 | { | ||
332 | switch (rate) { | ||
333 | case IEEE80211_CCK_RATE_2MB: | ||
334 | return CR_RATE_1M; | ||
335 | case IEEE80211_CCK_RATE_5MB: | ||
336 | return CR_RATE_5_5M; | ||
337 | case IEEE80211_CCK_RATE_11MB: | ||
338 | return CR_RATE_11M; | ||
339 | case IEEE80211_OFDM_RATE_6MB: | ||
340 | return CR_RATE_6M; | ||
341 | case IEEE80211_OFDM_RATE_9MB: | ||
342 | return CR_RATE_9M; | ||
343 | case IEEE80211_OFDM_RATE_12MB: | ||
344 | return CR_RATE_12M; | ||
345 | case IEEE80211_OFDM_RATE_18MB: | ||
346 | return CR_RATE_18M; | ||
347 | case IEEE80211_OFDM_RATE_24MB: | ||
348 | return CR_RATE_24M; | ||
349 | case IEEE80211_OFDM_RATE_36MB: | ||
350 | return CR_RATE_36M; | ||
351 | case IEEE80211_OFDM_RATE_48MB: | ||
352 | return CR_RATE_48M; | ||
353 | case IEEE80211_OFDM_RATE_54MB: | ||
354 | return CR_RATE_54M; | ||
355 | } | ||
356 | return CR_RATE_1M; | ||
357 | } | ||
358 | |||
359 | static void try_enable_tx(struct zd_mac *mac) | ||
360 | { | ||
361 | unsigned long flags; | ||
362 | |||
363 | spin_lock_irqsave(&mac->lock, flags); | ||
364 | if (mac->updating_rts_rate == 0 && mac->updating_basic_rates == 0) | ||
365 | netif_wake_queue(mac->netdev); | ||
366 | spin_unlock_irqrestore(&mac->lock, flags); | ||
367 | } | ||
368 | |||
369 | static void set_rts_cts_work(void *d) | ||
370 | { | ||
371 | struct zd_mac *mac = d; | ||
372 | unsigned long flags; | ||
373 | u8 rts_rate; | ||
374 | unsigned int short_preamble; | ||
375 | |||
376 | mutex_lock(&mac->chip.mutex); | ||
377 | |||
378 | spin_lock_irqsave(&mac->lock, flags); | ||
379 | mac->updating_rts_rate = 0; | ||
380 | rts_rate = mac->rts_rate; | ||
381 | short_preamble = mac->short_preamble; | ||
382 | spin_unlock_irqrestore(&mac->lock, flags); | ||
383 | |||
384 | zd_chip_set_rts_cts_rate_locked(&mac->chip, rts_rate, short_preamble); | ||
385 | mutex_unlock(&mac->chip.mutex); | ||
386 | |||
387 | try_enable_tx(mac); | ||
388 | } | ||
389 | |||
390 | static void set_basic_rates_work(void *d) | ||
391 | { | ||
392 | struct zd_mac *mac = d; | ||
393 | unsigned long flags; | ||
394 | u16 basic_rates; | ||
395 | |||
396 | mutex_lock(&mac->chip.mutex); | ||
397 | |||
398 | spin_lock_irqsave(&mac->lock, flags); | ||
399 | mac->updating_basic_rates = 0; | ||
400 | basic_rates = mac->basic_rates; | ||
401 | spin_unlock_irqrestore(&mac->lock, flags); | ||
402 | |||
403 | zd_chip_set_basic_rates_locked(&mac->chip, basic_rates); | ||
404 | mutex_unlock(&mac->chip.mutex); | ||
405 | |||
406 | try_enable_tx(mac); | ||
407 | } | ||
408 | |||
409 | static void bssinfo_change(struct net_device *netdev, u32 changes) | ||
410 | { | ||
411 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
412 | struct ieee80211softmac_device *softmac = ieee80211_priv(netdev); | ||
413 | struct ieee80211softmac_bss_info *bssinfo = &softmac->bssinfo; | ||
414 | int need_set_rts_cts = 0; | ||
415 | int need_set_rates = 0; | ||
416 | u16 basic_rates; | ||
417 | unsigned long flags; | ||
418 | |||
419 | dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes); | ||
420 | |||
421 | if (changes & IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE) { | ||
422 | spin_lock_irqsave(&mac->lock, flags); | ||
423 | mac->short_preamble = bssinfo->short_preamble; | ||
424 | spin_unlock_irqrestore(&mac->lock, flags); | ||
425 | need_set_rts_cts = 1; | ||
426 | } | ||
427 | |||
428 | if (changes & IEEE80211SOFTMAC_BSSINFOCHG_RATES) { | ||
429 | /* Set RTS rate to highest available basic rate */ | ||
430 | u8 rate = ieee80211softmac_highest_supported_rate(softmac, | ||
431 | &bssinfo->supported_rates, 1); | ||
432 | rate = rate_to_zd_rate(rate); | ||
433 | |||
434 | spin_lock_irqsave(&mac->lock, flags); | ||
435 | if (rate != mac->rts_rate) { | ||
436 | mac->rts_rate = rate; | ||
437 | need_set_rts_cts = 1; | ||
438 | } | ||
439 | spin_unlock_irqrestore(&mac->lock, flags); | ||
440 | |||
441 | /* Set basic rates */ | ||
442 | need_set_rates = 1; | ||
443 | if (bssinfo->supported_rates.count == 0) { | ||
444 | /* Allow the device to be flexible */ | ||
445 | basic_rates = CR_RATES_80211B | CR_RATES_80211G; | ||
446 | } else { | ||
447 | int i = 0; | ||
448 | basic_rates = 0; | ||
449 | |||
450 | for (i = 0; i < bssinfo->supported_rates.count; i++) { | ||
451 | u16 rate = bssinfo->supported_rates.rates[i]; | ||
452 | if ((rate & IEEE80211_BASIC_RATE_MASK) == 0) | ||
453 | continue; | ||
454 | |||
455 | rate &= ~IEEE80211_BASIC_RATE_MASK; | ||
456 | basic_rates |= rate_to_cr_rate(rate); | ||
457 | } | ||
458 | } | ||
459 | spin_lock_irqsave(&mac->lock, flags); | ||
460 | mac->basic_rates = basic_rates; | ||
461 | spin_unlock_irqrestore(&mac->lock, flags); | ||
462 | } | ||
463 | |||
464 | /* Schedule any changes we made above */ | ||
465 | |||
466 | spin_lock_irqsave(&mac->lock, flags); | ||
467 | if (need_set_rts_cts && !mac->updating_rts_rate) { | ||
468 | mac->updating_rts_rate = 1; | ||
469 | netif_stop_queue(mac->netdev); | ||
470 | queue_work(zd_workqueue, &mac->set_rts_cts_work); | ||
471 | } | ||
472 | if (need_set_rates && !mac->updating_basic_rates) { | ||
473 | mac->updating_basic_rates = 1; | ||
474 | netif_stop_queue(mac->netdev); | ||
475 | queue_work(zd_workqueue, &mac->set_basic_rates_work); | ||
476 | } | ||
477 | spin_unlock_irqrestore(&mac->lock, flags); | ||
478 | } | ||
479 | |||
289 | static void set_channel(struct net_device *netdev, u8 channel) | 480 | static void set_channel(struct net_device *netdev, u8 channel) |
290 | { | 481 | { |
291 | struct zd_mac *mac = zd_netdev_mac(netdev); | 482 | struct zd_mac *mac = zd_netdev_mac(netdev); |
@@ -295,7 +486,6 @@ static void set_channel(struct net_device *netdev, u8 channel) | |||
295 | zd_chip_set_channel(&mac->chip, channel); | 486 | zd_chip_set_channel(&mac->chip, channel); |
296 | } | 487 | } |
297 | 488 | ||
298 | /* TODO: Should not work in Managed mode. */ | ||
299 | int zd_mac_request_channel(struct zd_mac *mac, u8 channel) | 489 | int zd_mac_request_channel(struct zd_mac *mac, u8 channel) |
300 | { | 490 | { |
301 | unsigned long lock_flags; | 491 | unsigned long lock_flags; |
@@ -317,31 +507,22 @@ int zd_mac_request_channel(struct zd_mac *mac, u8 channel) | |||
317 | return 0; | 507 | return 0; |
318 | } | 508 | } |
319 | 509 | ||
320 | int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags) | 510 | u8 zd_mac_get_channel(struct zd_mac *mac) |
321 | { | 511 | { |
322 | struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); | 512 | u8 channel = zd_chip_get_channel(&mac->chip); |
323 | 513 | ||
324 | *channel = zd_chip_get_channel(&mac->chip); | 514 | dev_dbg_f(zd_mac_dev(mac), "channel %u\n", channel); |
325 | if (ieee->iw_mode != IW_MODE_INFRA) { | 515 | return channel; |
326 | spin_lock_irq(&mac->lock); | ||
327 | *flags = *channel == mac->requested_channel ? | ||
328 | MAC_FIXED_CHANNEL : 0; | ||
329 | spin_unlock(&mac->lock); | ||
330 | } else { | ||
331 | *flags = 0; | ||
332 | } | ||
333 | dev_dbg_f(zd_mac_dev(mac), "channel %u flags %u\n", *channel, *flags); | ||
334 | return 0; | ||
335 | } | 516 | } |
336 | 517 | ||
337 | /* If wrong rate is given, we are falling back to the slowest rate: 1MBit/s */ | 518 | /* If wrong rate is given, we are falling back to the slowest rate: 1MBit/s */ |
338 | static u8 cs_typed_rate(u8 cs_rate) | 519 | static u8 zd_rate_typed(u8 zd_rate) |
339 | { | 520 | { |
340 | static const u8 typed_rates[16] = { | 521 | static const u8 typed_rates[16] = { |
341 | [ZD_CS_CCK_RATE_1M] = ZD_CS_CCK|ZD_CS_CCK_RATE_1M, | 522 | [ZD_CCK_RATE_1M] = ZD_CS_CCK|ZD_CCK_RATE_1M, |
342 | [ZD_CS_CCK_RATE_2M] = ZD_CS_CCK|ZD_CS_CCK_RATE_2M, | 523 | [ZD_CCK_RATE_2M] = ZD_CS_CCK|ZD_CCK_RATE_2M, |
343 | [ZD_CS_CCK_RATE_5_5M] = ZD_CS_CCK|ZD_CS_CCK_RATE_5_5M, | 524 | [ZD_CCK_RATE_5_5M] = ZD_CS_CCK|ZD_CCK_RATE_5_5M, |
344 | [ZD_CS_CCK_RATE_11M] = ZD_CS_CCK|ZD_CS_CCK_RATE_11M, | 525 | [ZD_CCK_RATE_11M] = ZD_CS_CCK|ZD_CCK_RATE_11M, |
345 | [ZD_OFDM_RATE_6M] = ZD_CS_OFDM|ZD_OFDM_RATE_6M, | 526 | [ZD_OFDM_RATE_6M] = ZD_CS_OFDM|ZD_OFDM_RATE_6M, |
346 | [ZD_OFDM_RATE_9M] = ZD_CS_OFDM|ZD_OFDM_RATE_9M, | 527 | [ZD_OFDM_RATE_9M] = ZD_CS_OFDM|ZD_OFDM_RATE_9M, |
347 | [ZD_OFDM_RATE_12M] = ZD_CS_OFDM|ZD_OFDM_RATE_12M, | 528 | [ZD_OFDM_RATE_12M] = ZD_CS_OFDM|ZD_OFDM_RATE_12M, |
@@ -353,37 +534,7 @@ static u8 cs_typed_rate(u8 cs_rate) | |||
353 | }; | 534 | }; |
354 | 535 | ||
355 | ZD_ASSERT(ZD_CS_RATE_MASK == 0x0f); | 536 | ZD_ASSERT(ZD_CS_RATE_MASK == 0x0f); |
356 | return typed_rates[cs_rate & ZD_CS_RATE_MASK]; | 537 | return typed_rates[zd_rate & ZD_CS_RATE_MASK]; |
357 | } | ||
358 | |||
359 | /* Fallback to lowest rate, if rate is unknown. */ | ||
360 | static u8 rate_to_cs_rate(u8 rate) | ||
361 | { | ||
362 | switch (rate) { | ||
363 | case IEEE80211_CCK_RATE_2MB: | ||
364 | return ZD_CS_CCK_RATE_2M; | ||
365 | case IEEE80211_CCK_RATE_5MB: | ||
366 | return ZD_CS_CCK_RATE_5_5M; | ||
367 | case IEEE80211_CCK_RATE_11MB: | ||
368 | return ZD_CS_CCK_RATE_11M; | ||
369 | case IEEE80211_OFDM_RATE_6MB: | ||
370 | return ZD_OFDM_RATE_6M; | ||
371 | case IEEE80211_OFDM_RATE_9MB: | ||
372 | return ZD_OFDM_RATE_9M; | ||
373 | case IEEE80211_OFDM_RATE_12MB: | ||
374 | return ZD_OFDM_RATE_12M; | ||
375 | case IEEE80211_OFDM_RATE_18MB: | ||
376 | return ZD_OFDM_RATE_18M; | ||
377 | case IEEE80211_OFDM_RATE_24MB: | ||
378 | return ZD_OFDM_RATE_24M; | ||
379 | case IEEE80211_OFDM_RATE_36MB: | ||
380 | return ZD_OFDM_RATE_36M; | ||
381 | case IEEE80211_OFDM_RATE_48MB: | ||
382 | return ZD_OFDM_RATE_48M; | ||
383 | case IEEE80211_OFDM_RATE_54MB: | ||
384 | return ZD_OFDM_RATE_54M; | ||
385 | } | ||
386 | return ZD_CS_CCK_RATE_1M; | ||
387 | } | 538 | } |
388 | 539 | ||
389 | int zd_mac_set_mode(struct zd_mac *mac, u32 mode) | 540 | int zd_mac_set_mode(struct zd_mac *mac, u32 mode) |
@@ -484,13 +635,13 @@ int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range) | |||
484 | return 0; | 635 | return 0; |
485 | } | 636 | } |
486 | 637 | ||
487 | static int zd_calc_tx_length_us(u8 *service, u8 cs_rate, u16 tx_length) | 638 | static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length) |
488 | { | 639 | { |
489 | static const u8 rate_divisor[] = { | 640 | static const u8 rate_divisor[] = { |
490 | [ZD_CS_CCK_RATE_1M] = 1, | 641 | [ZD_CCK_RATE_1M] = 1, |
491 | [ZD_CS_CCK_RATE_2M] = 2, | 642 | [ZD_CCK_RATE_2M] = 2, |
492 | [ZD_CS_CCK_RATE_5_5M] = 11, /* bits must be doubled */ | 643 | [ZD_CCK_RATE_5_5M] = 11, /* bits must be doubled */ |
493 | [ZD_CS_CCK_RATE_11M] = 11, | 644 | [ZD_CCK_RATE_11M] = 11, |
494 | [ZD_OFDM_RATE_6M] = 6, | 645 | [ZD_OFDM_RATE_6M] = 6, |
495 | [ZD_OFDM_RATE_9M] = 9, | 646 | [ZD_OFDM_RATE_9M] = 9, |
496 | [ZD_OFDM_RATE_12M] = 12, | 647 | [ZD_OFDM_RATE_12M] = 12, |
@@ -504,15 +655,15 @@ static int zd_calc_tx_length_us(u8 *service, u8 cs_rate, u16 tx_length) | |||
504 | u32 bits = (u32)tx_length * 8; | 655 | u32 bits = (u32)tx_length * 8; |
505 | u32 divisor; | 656 | u32 divisor; |
506 | 657 | ||
507 | divisor = rate_divisor[cs_rate]; | 658 | divisor = rate_divisor[zd_rate]; |
508 | if (divisor == 0) | 659 | if (divisor == 0) |
509 | return -EINVAL; | 660 | return -EINVAL; |
510 | 661 | ||
511 | switch (cs_rate) { | 662 | switch (zd_rate) { |
512 | case ZD_CS_CCK_RATE_5_5M: | 663 | case ZD_CCK_RATE_5_5M: |
513 | bits = (2*bits) + 10; /* round up to the next integer */ | 664 | bits = (2*bits) + 10; /* round up to the next integer */ |
514 | break; | 665 | break; |
515 | case ZD_CS_CCK_RATE_11M: | 666 | case ZD_CCK_RATE_11M: |
516 | if (service) { | 667 | if (service) { |
517 | u32 t = bits % 11; | 668 | u32 t = bits % 11; |
518 | *service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION; | 669 | *service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION; |
@@ -532,16 +683,16 @@ enum { | |||
532 | R2M_11A = 0x02, | 683 | R2M_11A = 0x02, |
533 | }; | 684 | }; |
534 | 685 | ||
535 | static u8 cs_rate_to_modulation(u8 cs_rate, int flags) | 686 | static u8 zd_rate_to_modulation(u8 zd_rate, int flags) |
536 | { | 687 | { |
537 | u8 modulation; | 688 | u8 modulation; |
538 | 689 | ||
539 | modulation = cs_typed_rate(cs_rate); | 690 | modulation = zd_rate_typed(zd_rate); |
540 | if (flags & R2M_SHORT_PREAMBLE) { | 691 | if (flags & R2M_SHORT_PREAMBLE) { |
541 | switch (ZD_CS_RATE(modulation)) { | 692 | switch (ZD_CS_RATE(modulation)) { |
542 | case ZD_CS_CCK_RATE_2M: | 693 | case ZD_CCK_RATE_2M: |
543 | case ZD_CS_CCK_RATE_5_5M: | 694 | case ZD_CCK_RATE_5_5M: |
544 | case ZD_CS_CCK_RATE_11M: | 695 | case ZD_CCK_RATE_11M: |
545 | modulation |= ZD_CS_CCK_PREA_SHORT; | 696 | modulation |= ZD_CS_CCK_PREA_SHORT; |
546 | return modulation; | 697 | return modulation; |
547 | } | 698 | } |
@@ -558,39 +709,36 @@ static void cs_set_modulation(struct zd_mac *mac, struct zd_ctrlset *cs, | |||
558 | { | 709 | { |
559 | struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev); | 710 | struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev); |
560 | u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl)); | 711 | u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl)); |
561 | u8 rate, cs_rate; | 712 | u8 rate, zd_rate; |
562 | int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0; | 713 | int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0; |
714 | int is_multicast = is_multicast_ether_addr(hdr->addr1); | ||
715 | int short_preamble = ieee80211softmac_short_preamble_ok(softmac, | ||
716 | is_multicast, is_mgt); | ||
717 | int flags = 0; | ||
718 | |||
719 | /* FIXME: 802.11a? */ | ||
720 | rate = ieee80211softmac_suggest_txrate(softmac, is_multicast, is_mgt); | ||
563 | 721 | ||
564 | /* FIXME: 802.11a? short preamble? */ | 722 | if (short_preamble) |
565 | rate = ieee80211softmac_suggest_txrate(softmac, | 723 | flags |= R2M_SHORT_PREAMBLE; |
566 | is_multicast_ether_addr(hdr->addr1), is_mgt); | ||
567 | 724 | ||
568 | cs_rate = rate_to_cs_rate(rate); | 725 | zd_rate = rate_to_zd_rate(rate); |
569 | cs->modulation = cs_rate_to_modulation(cs_rate, 0); | 726 | cs->modulation = zd_rate_to_modulation(zd_rate, flags); |
570 | } | 727 | } |
571 | 728 | ||
572 | static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | 729 | static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, |
573 | struct ieee80211_hdr_4addr *header) | 730 | struct ieee80211_hdr_4addr *header) |
574 | { | 731 | { |
732 | struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev); | ||
575 | unsigned int tx_length = le16_to_cpu(cs->tx_length); | 733 | unsigned int tx_length = le16_to_cpu(cs->tx_length); |
576 | u16 fctl = le16_to_cpu(header->frame_ctl); | 734 | u16 fctl = le16_to_cpu(header->frame_ctl); |
577 | u16 ftype = WLAN_FC_GET_TYPE(fctl); | 735 | u16 ftype = WLAN_FC_GET_TYPE(fctl); |
578 | u16 stype = WLAN_FC_GET_STYPE(fctl); | 736 | u16 stype = WLAN_FC_GET_STYPE(fctl); |
579 | 737 | ||
580 | /* | 738 | /* |
581 | * CONTROL: | 739 | * CONTROL TODO: |
582 | * - start at 0x00 | ||
583 | * - if fragment 0, enable bit 0 | ||
584 | * - if backoff needed, enable bit 0 | 740 | * - if backoff needed, enable bit 0 |
585 | * - if burst (backoff not needed) disable bit 0 | 741 | * - if burst (backoff not needed) disable bit 0 |
586 | * - if multicast, enable bit 1 | ||
587 | * - if PS-POLL frame, enable bit 2 | ||
588 | * - if in INDEPENDENT_BSS mode and zd1205_DestPowerSave, then enable | ||
589 | * bit 4 (FIXME: wtf) | ||
590 | * - if frag_len > RTS threshold, set bit 5 as long if it isnt | ||
591 | * multicast or mgt | ||
592 | * - if bit 5 is set, and we are in OFDM mode, unset bit 5 and set bit | ||
593 | * 7 | ||
594 | */ | 742 | */ |
595 | 743 | ||
596 | cs->control = 0; | 744 | cs->control = 0; |
@@ -607,17 +755,18 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | |||
607 | if (stype == IEEE80211_STYPE_PSPOLL) | 755 | if (stype == IEEE80211_STYPE_PSPOLL) |
608 | cs->control |= ZD_CS_PS_POLL_FRAME; | 756 | cs->control |= ZD_CS_PS_POLL_FRAME; |
609 | 757 | ||
758 | /* Unicast data frames over the threshold should have RTS */ | ||
610 | if (!is_multicast_ether_addr(header->addr1) && | 759 | if (!is_multicast_ether_addr(header->addr1) && |
611 | ftype != IEEE80211_FTYPE_MGMT && | 760 | ftype != IEEE80211_FTYPE_MGMT && |
612 | tx_length > zd_netdev_ieee80211(mac->netdev)->rts) | 761 | tx_length > zd_netdev_ieee80211(mac->netdev)->rts) |
613 | { | 762 | cs->control |= ZD_CS_RTS; |
614 | /* FIXME: check the logic */ | 763 | |
615 | if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM) { | 764 | /* Use CTS-to-self protection if required */ |
616 | /* 802.11g */ | 765 | if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM && |
617 | cs->control |= ZD_CS_SELF_CTS; | 766 | ieee80211softmac_protection_needed(softmac)) { |
618 | } else { /* 802.11b */ | 767 | /* FIXME: avoid sending RTS *and* self-CTS, is that correct? */ |
619 | cs->control |= ZD_CS_RTS; | 768 | cs->control &= ~ZD_CS_RTS; |
620 | } | 769 | cs->control |= ZD_CS_SELF_CTS; |
621 | } | 770 | } |
622 | 771 | ||
623 | /* FIXME: Management frame? */ | 772 | /* FIXME: Management frame? */ |
@@ -721,7 +870,7 @@ struct zd_rt_hdr { | |||
721 | u8 rt_rate; | 870 | u8 rt_rate; |
722 | u16 rt_channel; | 871 | u16 rt_channel; |
723 | u16 rt_chbitmask; | 872 | u16 rt_chbitmask; |
724 | }; | 873 | } __attribute__((packed)); |
725 | 874 | ||
726 | static void fill_rt_header(void *buffer, struct zd_mac *mac, | 875 | static void fill_rt_header(void *buffer, struct zd_mac *mac, |
727 | const struct ieee80211_rx_stats *stats, | 876 | const struct ieee80211_rx_stats *stats, |
@@ -782,9 +931,11 @@ static int is_data_packet_for_us(struct ieee80211_device *ieee, | |||
782 | (netdev->flags & IFF_PROMISC); | 931 | (netdev->flags & IFF_PROMISC); |
783 | } | 932 | } |
784 | 933 | ||
785 | /* Filters receiving packets. If it returns 1 send it to ieee80211_rx, if 0 | 934 | /* Filters received packets. The function returns 1 if the packet should be |
786 | * return. If an error is detected -EINVAL is returned. ieee80211_rx_mgt() is | 935 | * forwarded to ieee80211_rx(). If the packet should be ignored the function |
787 | * called here. | 936 | * returns 0. If an invalid packet is found the function returns -EINVAL. |
937 | * | ||
938 | * The function calls ieee80211_rx_mgt() directly. | ||
788 | * | 939 | * |
789 | * It has been based on ieee80211_rx_any. | 940 | * It has been based on ieee80211_rx_any. |
790 | */ | 941 | */ |
@@ -810,9 +961,9 @@ static int filter_rx(struct ieee80211_device *ieee, | |||
810 | ieee80211_rx_mgt(ieee, hdr, stats); | 961 | ieee80211_rx_mgt(ieee, hdr, stats); |
811 | return 0; | 962 | return 0; |
812 | case IEEE80211_FTYPE_CTL: | 963 | case IEEE80211_FTYPE_CTL: |
813 | /* Ignore invalid short buffers */ | ||
814 | return 0; | 964 | return 0; |
815 | case IEEE80211_FTYPE_DATA: | 965 | case IEEE80211_FTYPE_DATA: |
966 | /* Ignore invalid short buffers */ | ||
816 | if (length < sizeof(struct ieee80211_hdr_3addr)) | 967 | if (length < sizeof(struct ieee80211_hdr_3addr)) |
817 | return -EINVAL; | 968 | return -EINVAL; |
818 | return is_data_packet_for_us(ieee, hdr); | 969 | return is_data_packet_for_us(ieee, hdr); |
@@ -993,6 +1144,7 @@ static void ieee_init(struct ieee80211_device *ieee) | |||
993 | static void softmac_init(struct ieee80211softmac_device *sm) | 1144 | static void softmac_init(struct ieee80211softmac_device *sm) |
994 | { | 1145 | { |
995 | sm->set_channel = set_channel; | 1146 | sm->set_channel = set_channel; |
1147 | sm->bssinfo_change = bssinfo_change; | ||
996 | } | 1148 | } |
997 | 1149 | ||
998 | struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) | 1150 | struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) |
@@ -1028,66 +1180,6 @@ struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) | |||
1028 | return iw_stats; | 1180 | return iw_stats; |
1029 | } | 1181 | } |
1030 | 1182 | ||
1031 | #ifdef DEBUG | ||
1032 | static const char* decryption_types[] = { | ||
1033 | [ZD_RX_NO_WEP] = "none", | ||
1034 | [ZD_RX_WEP64] = "WEP64", | ||
1035 | [ZD_RX_TKIP] = "TKIP", | ||
1036 | [ZD_RX_AES] = "AES", | ||
1037 | [ZD_RX_WEP128] = "WEP128", | ||
1038 | [ZD_RX_WEP256] = "WEP256", | ||
1039 | }; | ||
1040 | |||
1041 | static const char *decryption_type_string(u8 type) | ||
1042 | { | ||
1043 | const char *s; | ||
1044 | |||
1045 | if (type < ARRAY_SIZE(decryption_types)) { | ||
1046 | s = decryption_types[type]; | ||
1047 | } else { | ||
1048 | s = NULL; | ||
1049 | } | ||
1050 | return s ? s : "unknown"; | ||
1051 | } | ||
1052 | |||
1053 | static int is_ofdm(u8 frame_status) | ||
1054 | { | ||
1055 | return (frame_status & ZD_RX_OFDM); | ||
1056 | } | ||
1057 | |||
1058 | void zd_dump_rx_status(const struct rx_status *status) | ||
1059 | { | ||
1060 | const char* modulation; | ||
1061 | u8 quality; | ||
1062 | |||
1063 | if (is_ofdm(status->frame_status)) { | ||
1064 | modulation = "ofdm"; | ||
1065 | quality = status->signal_quality_ofdm; | ||
1066 | } else { | ||
1067 | modulation = "cck"; | ||
1068 | quality = status->signal_quality_cck; | ||
1069 | } | ||
1070 | pr_debug("rx status %s strength %#04x qual %#04x decryption %s\n", | ||
1071 | modulation, status->signal_strength, quality, | ||
1072 | decryption_type_string(status->decryption_type)); | ||
1073 | if (status->frame_status & ZD_RX_ERROR) { | ||
1074 | pr_debug("rx error %s%s%s%s%s%s\n", | ||
1075 | (status->frame_status & ZD_RX_TIMEOUT_ERROR) ? | ||
1076 | "timeout " : "", | ||
1077 | (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR) ? | ||
1078 | "fifo " : "", | ||
1079 | (status->frame_status & ZD_RX_DECRYPTION_ERROR) ? | ||
1080 | "decryption " : "", | ||
1081 | (status->frame_status & ZD_RX_CRC32_ERROR) ? | ||
1082 | "crc32 " : "", | ||
1083 | (status->frame_status & ZD_RX_NO_ADDR1_MATCH_ERROR) ? | ||
1084 | "addr1 " : "", | ||
1085 | (status->frame_status & ZD_RX_CRC16_ERROR) ? | ||
1086 | "crc16" : ""); | ||
1087 | } | ||
1088 | } | ||
1089 | #endif /* DEBUG */ | ||
1090 | |||
1091 | #define LINK_LED_WORK_DELAY HZ | 1183 | #define LINK_LED_WORK_DELAY HZ |
1092 | 1184 | ||
1093 | static void link_led_handler(struct work_struct *work) | 1185 | static void link_led_handler(struct work_struct *work) |