| 4430 | | /* extract tstamp from last beacon and convert to TU */ |
|---|
| 4431 | | nexttbtt = TSF_TO_TU(LE_READ_4(ni->ni_tstamp.data + 4), |
|---|
| 4432 | | LE_READ_4(ni->ni_tstamp.data)); |
|---|
| | 4433 | hw_tsf = ath_hal_gettsf64(ah); |
|---|
| | 4434 | tsf = le64_to_cpu(ni->ni_tstamp.tsf); |
|---|
| | 4435 | hw_tsftu = hw_tsf >> 10; |
|---|
| | 4436 | tsftu = tsf >> 10; |
|---|
| | 4437 | |
|---|
| | 4438 | /* we should reset hw TSF only once, so we increment |
|---|
| | 4439 | ni_tstamp.tsf to avoid resetting the hw TSF multiple |
|---|
| | 4440 | times */ |
|---|
| | 4441 | |
|---|
| | 4442 | if (tsf == 0) { |
|---|
| | 4443 | should_reset_tsf = 1; |
|---|
| | 4444 | ni->ni_tstamp.tsf = cpu_to_le64(tsf+1); |
|---|
| | 4445 | } |
|---|
| | 4446 | |
|---|
| 4450 | | if (nexttbtt == 0) /* e.g. for ap mode */ |
|---|
| 4451 | | nexttbtt = intval; |
|---|
| 4452 | | else if (intval) /* NB: can be 0 for monitor mode */ |
|---|
| 4453 | | nexttbtt = roundup(nexttbtt, intval); |
|---|
| 4454 | | DPRINTF(sc, ATH_DEBUG_BEACON, "%s: nexttbtt %u intval %u (%u)\n", |
|---|
| 4455 | | __func__, nexttbtt, intval, ni->ni_intval); |
|---|
| | 4466 | |
|---|
| | 4467 | #define FUDGE 2 |
|---|
| | 4468 | sc->sc_syncbeacon = 0; |
|---|
| | 4469 | if (should_reset_tsf) { |
|---|
| | 4470 | |
|---|
| | 4471 | /* We just created the interface and TSF will be reset to |
|---|
| | 4472 | zero, so next beacon will be sent at the next intval |
|---|
| | 4473 | time */ |
|---|
| | 4474 | |
|---|
| | 4475 | nexttbtt = intval; |
|---|
| | 4476 | } else { |
|---|
| | 4477 | if (tsf == 1) { |
|---|
| | 4478 | |
|---|
| | 4479 | /* We do not receive any beacons or probe response. Since |
|---|
| | 4480 | a beacon should be sent every 'intval' ms, we compute |
|---|
| | 4481 | the next beacon timestamp using the hardware TSF. We |
|---|
| | 4482 | ensure that it is at least FUDGE ms ahead of the |
|---|
| | 4483 | current TSF. Otherwise, we use the next beacon |
|---|
| | 4484 | timestamp again */ |
|---|
| | 4485 | |
|---|
| | 4486 | nexttbtt = roundup(hw_tsftu +1, intval); |
|---|
| | 4487 | while (nexttbtt <= hw_tsftu + FUDGE) { |
|---|
| | 4488 | nexttbtt += intval; |
|---|
| | 4489 | } |
|---|
| | 4490 | } else { |
|---|
| | 4491 | if (tsf > hw_tsf) { |
|---|
| | 4492 | |
|---|
| | 4493 | /* We do receive a beacon from someone else in the past, |
|---|
| | 4494 | but the hw TSF has not been updated (otherwise we |
|---|
| | 4495 | would have tsf >= hw_tsf). Since we cannot use the |
|---|
| | 4496 | hardware TSF, we will do nothing and wait for the |
|---|
| | 4497 | next beacon. In order to do so, we set sc->syncbeacon |
|---|
| | 4498 | again */ |
|---|
| | 4499 | |
|---|
| | 4500 | sc->sc_syncbeacon = 1; |
|---|
| | 4501 | goto ath_beacon_config_debug; |
|---|
| | 4502 | |
|---|
| | 4503 | } else { |
|---|
| | 4504 | |
|---|
| | 4505 | /* We do receive a beacon in the past, normal case. We |
|---|
| | 4506 | make sure that the timestamp is at least FUDGE ms |
|---|
| | 4507 | ahead of the hardware TSF */ |
|---|
| | 4508 | |
|---|
| | 4509 | nexttbtt = tsftu + intval; |
|---|
| | 4510 | while (nexttbtt <= hw_tsftu + FUDGE) { |
|---|
| | 4511 | nexttbtt += intval; |
|---|
| | 4512 | } |
|---|
| | 4513 | } |
|---|
| | 4514 | } |
|---|
| | 4515 | } |
|---|
| | 4516 | |
|---|
| | 4657 | |
|---|
| | 4658 | ath_beacon_config_debug: |
|---|
| | 4659 | |
|---|
| | 4660 | /* we print all debug messages here, in order to preserve the |
|---|
| | 4661 | time critical aspect of this function */ |
|---|
| | 4662 | |
|---|
| | 4663 | DPRINTF(sc, ATH_DEBUG_BEACON, |
|---|
| | 4664 | "%s: ni=%p tsf=%llu hw_tsf=%llu tsftu=%u hw_tsftu=%u\n", |
|---|
| | 4665 | __func__, ni, tsf, hw_tsf, tsftu, hw_tsftu); |
|---|
| | 4666 | |
|---|
| | 4667 | if (should_reset_tsf) { |
|---|
| | 4668 | /* we just created the interface */ |
|---|
| | 4669 | DPRINTF(sc, ATH_DEBUG_BEACON, "%s: first beacon\n",__func__); |
|---|
| | 4670 | } else { |
|---|
| | 4671 | if (tsf == 1) { |
|---|
| | 4672 | /* we do not receive any beacons or probe response */ |
|---|
| | 4673 | DPRINTF(sc, ATH_DEBUG_BEACON, |
|---|
| | 4674 | "%s: no beacon received...\n",__func__); |
|---|
| | 4675 | } else { |
|---|
| | 4676 | if (tsf > hw_tsf) { |
|---|
| | 4677 | /* we do receive a beacon and the hw TSF has not been updated */ |
|---|
| | 4678 | DPRINTF(sc, ATH_DEBUG_BEACON, |
|---|
| | 4679 | "%s: beacon received, but TSF is incorrect\n",__func__); |
|---|
| | 4680 | } else { |
|---|
| | 4681 | /* we do receive a beacon in the past, normal case */ |
|---|
| | 4682 | DPRINTF(sc, ATH_DEBUG_BEACON, |
|---|
| | 4683 | "%s: beacon received, TSF is correct\n",__func__); |
|---|
| | 4684 | } |
|---|
| | 4685 | } |
|---|
| | 4686 | } |
|---|
| | 4687 | |
|---|
| | 4688 | DPRINTF(sc, ATH_DEBUG_BEACON, "%s: nexttbtt=%u intval=%u\n", |
|---|
| | 4689 | __func__,nexttbtt, intval & HAL_BEACON_PERIOD); |
|---|