# # Copyright (C) 2016 Jiang Yutang # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/image.mk define Build/append-ls-rcw rm -f $@ dd if=$(STAGING_DIR_IMAGE)/$(1)-rcw.bin >> $@ endef define Build/append-ls-uboot dd if=$(STAGING_DIR_IMAGE)/$(1)-$(SUBTARGET)-uboot.bin >> $@ endef define Build/append-ls-fman dd if=$(STAGING_DIR_IMAGE)/$(1)-fman.bin >> $@ endef define Build/append-ls-dtb $(call Image/BuildDTB,$(DTS_DIR)/$(1).dts,$(DTS_DIR)/$(1).dtb) dd if=$(DTS_DIR)/$(1).dtb >> $@ endef define Build/append-ls-rootfs-ext4 $(STAGING_DIR_HOST)/bin/make_ext4fs -l $(word 2,$(1)) -b 4096 -i 6000 -m 0 -J $(KDIR)/$(word 1,$(1))-$(word 2,$(1)).root.ext4 $(TARGET_DIR) dd if=$(KDIR)/$(word 1,$(1))-$(word 2,$(1)).root.ext4 >> $@ endef define Device/Default PROFILES = Default FILESYSTEMS := squashfs KERNEL := kernel-bin | gzip | uImage gzip DEVICE_DTS := IMAGES = firmware.bin ifeq ($(SUBTARGET),64b) KERNEL_LOADADDR = 0x80080000 KERNEL_ENTRY_POINT = 0x80080000 endif ifeq ($(SUBTARGET),32b) KERNEL_LOADADDR = 0x80008000 KERNEL_ENTRY_POINT = 0x80008000 endif endef define Device/ls1043ardb DEVICE_TITLE := ls1043ardb-$(SUBTARGET) DEVICE_PACKAGES += rcw-layerscape-ls1043ardb uboot-layerscape-$(SUBTARGET)-ls1043ardb fman-layerscape-ls1043ardb ifeq ($(SUBTARGET),64b) DEVICE_DTS = freescale/fsl-ls1043a-rdb endif ifeq ($(SUBTARGET),32b) DEVICE_DTS = ../../../arm64/boot/dts/freescale/fsl-ls1043a-rdb endif IMAGE/firmware.bin = append-ls-rcw $(1) | pad-to 1M | append-ls-uboot $(1) | pad-to 3M | \ append-ls-fman $(1) | pad-to 4M | append-ls-dtb $$(DEVICE_DTS) | pad-to 5M | \ append-kernel | pad-to 10M | append-rootfs | pad-rootfs | check-size 67108865 endef TARGET_DEVICES += ls1043ardb define Device/ls1046ardb DEVICE_TITLE := ls1046ardb-$(SUBTARGET) DEVICE_PACKAGES += rcw-layerscape-ls1046ardb uboot-layerscape-$(SUBTARGET)-ls1046ardb fman-layerscape-ls1046ardb ifeq ($(SUBTARGET),64b) DEVICE_DTS = freescale/fsl-ls1046a-rdb endif ifeq ($(SUBTARGET),32b) DEVICE_DTS = ../../../arm64/boot/dts/freescale/fsl-ls1046a-rdb endif IMAGE/firmware.bin = append-ls-rcw $(1) | pad-to 1M | append-ls-uboot $(1) | pad-to 3M | \ append-ls-fman $(1) | pad-to 4M | append-ls-dtb $$(DEVICE_DTS) | pad-to 5M | \ append-kernel | pad-to 10M | append-ls-rootfs-ext4 $(1) 22M | check-size 33554433 endef TARGET_DEVICES += ls1046ardb define Device/ls1012ardb DEVICE_TITLE := ls1012ardb-$(SUBTARGET) DEVICE_PACKAGES += rcw-layerscape-ls1012ardb uboot-layerscape-$(SUBTARGET)-ls1012ardb kmod-ppfe ppfe-ls1012ardb ifeq ($(SUBTARGET),64b) DEVICE_DTS = freescale/fsl-ls1012a-rdb endif ifeq ($(SUBTARGET),32b) DEVICE_DTS = ../../../arm64/boot/dts/freescale/fsl-ls1012a-rdb endif IMAGE/firmware.bin = append-ls-rcw $(1) | pad-to 1M | append-ls-uboot $(1) | pad-to 3M | \ append-ls-dtb $$(DEVICE_DTS) | pad-to 4M | append-kernel | pad-to 9M | \ append-ls-rootfs-ext4 $(1) 23M | check-size 33554433 endef TARGET_DEVICES += ls1012ardb define Device/ls1088ardb DEVICE_TITLE := ls1088ardb-$(SUBTARGET) DEVICE_PACKAGES += rcw-layerscape-ls1088ardb uboot-layerscape-$(SUBTARGET)-ls1088ardb mc-binary-ls1088ardb ifeq ($(SUBTARGET),64b) DEVICE_DTS = freescale/fsl-ls1088a-rdb endif ifeq ($(SUBTARGET),32b) DEVICE_DTS = ../../../arm64/boot/dts/freescale/fsl-ls1088a-rdb endif IMAGE/firmware.bin = append-ls-dtb $$(DEVICE_DTS) | pad-to 1M | append-kernel | pad-to 6M | \ append-ls-rootfs-ext4 $(1) 17M | check-size 24117249 endef TARGET_DEVICES += ls1088ardb define Device/ls2088ardb DEVICE_TITLE := ls2088ardb-$(SUBTARGET) DEVICE_PACKAGES += rcw-layerscape-ls2088ardb uboot-layerscape-$(SUBTARGET)-ls2088ardb mc-binary-ls2088ardb ifeq ($(SUBTARGET),64b) DEVICE_DTS = freescale/fsl-ls2088a-rdb endif ifeq ($(SUBTARGET),32b) DEVICE_DTS = ../../../arm64/boot/dts/freescale/fsl-ls2088a-rdb endif IMAGE/firmware.bin = append-ls-dtb $$(DEVICE_DTS) | pad-to 1M | append-kernel | pad-to 6M | \ append-rootfs | pad-rootfs | check-size 24117249 endef TARGET_DEVICES += ls2088ardb $(eval $(call BuildImage)) href='#n4'>4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -397,6 +397,7 @@ static int countrycode = -1;
 static int maxvaps = -1;
 static int outdoor = -1;
 static int xchanmode = -1;
+static int beacon_cal = 1;
 
 static const char *hal_status_desc[] = {
 	"No error",
@@ -422,6 +423,7 @@ static struct notifier_block ath_event_b
 };
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
+MODULE_PARM(beacon_cal, "i");
 MODULE_PARM(countrycode, "i");
 MODULE_PARM(maxvaps, "i");
 MODULE_PARM(outdoor, "i");
@@ -434,6 +436,7 @@ MODULE_PARM(autocreate, "s");
 MODULE_PARM(ratectl, "s");
 #else
 #include <linux/moduleparam.h>
+module_param(beacon_cal, int, 0600);
 module_param(countrycode, int, 0600);
 module_param(maxvaps, int, 0600);
 module_param(outdoor, int, 0600);
@@ -2600,7 +2603,8 @@ ath_stop_locked(struct net_device *dev)
 		}
 		if (!sc->sc_invalid) {
 			del_timer_sync(&sc->sc_dfs_cac_timer);
-			del_timer_sync(&sc->sc_cal_ch);
+			if (!sc->sc_beacon_cal)
+				del_timer_sync(&sc->sc_cal_ch);
 		}
 		ath_draintxq(sc);
 		if (!sc->sc_invalid) {
@@ -2617,6 +2621,20 @@ ath_stop_locked(struct net_device *dev)
 	return 0;
 }
 
+static void ath_set_beacon_cal(struct ath_softc *sc, int val)
+{
+	if (sc->sc_beacon_cal == !!val)
+		return;
+
+	if (val) {
+		del_timer_sync(&sc->sc_cal_ch);
+	} else {
+		sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
+		add_timer(&sc->sc_cal_ch);
+	}
+	sc->sc_beacon_cal = !!val && beacon_cal;
+}
+
 /*
  * Stop the device, grabbing the top-level lock to protect
  * against concurrent entry through ath_init (which can happen
@@ -2742,6 +2760,12 @@ ath_reset(struct net_device *dev)
 	HAL_STATUS status;
 
 	/*
+	 * XXX: starting the calibration too early seems to lead to
+	 * problems with the beacons.
+	 */
+	sc->sc_lastcal = jiffies;
+
+	/*
 	 * Convert to a HAL channel description with the flags
 	 * constrained to reflect the current operating mode.
 	 */
@@ -5154,6 +5178,10 @@ ath_beacon_send(struct ath_softc *sc, in
 			"Invoking ath_hal_txstart with sc_bhalq: %d\n",
 			sc->sc_bhalq);
 		ath_hal_txstart(ah, sc->sc_bhalq);
+		if (sc->sc_beacon_cal && (jiffies > sc->sc_lastcal + (ath_calinterval * HZ))) {
+			sc->sc_cal_ch.expires = jiffies + msecs_to_jiffies(10);
+			add_timer(&sc->sc_cal_ch);
+		}
 
 		sc->sc_stats.ast_be_xmit++;		/* XXX per-VAP? */
 	}
@@ -5403,6 +5431,7 @@ ath_beacon_config(struct ath_softc *sc,
 		ath_hal_beacontimers(ah, &bs);
 		sc->sc_imask |= HAL_INT_BMISS;
 		ath_hal_intrset(ah, sc->sc_imask);
+		ath_set_beacon_cal(sc, 0);
 	} else {
 		ath_hal_intrset(ah, 0);
 		if (reset_tsf)
@@ -5414,8 +5443,11 @@ ath_beacon_config(struct ath_softc *sc,
 			 */
 			intval |= HAL_BEACON_ENA;
 			sc->sc_imask |= HAL_INT_SWBA;
+			ath_set_beacon_cal(sc, 1);
 			ath_beaconq_config(sc);
-		}
+		} else
+			ath_set_beacon_cal(sc, 0);
+
 #ifdef ATH_SUPERG_DYNTURBO
 		ath_beacon_dturbo_config(vap, intval &
 				~(HAL_BEACON_RESET_TSF | HAL_BEACON_ENA));
@@ -8879,6 +8911,9 @@ ath_chan_set(struct ath_softc *sc, struc
 			/* Enter DFS wait period */
 			mod_timer(&sc->sc_dfs_cac_timer,
 				jiffies + (sc->sc_dfs_cac_period * HZ));
+
+			/* This is a good time to start a calibration */
+			ath_set_beacon_cal(sc, 1);
 		}
 		/*
 		 * re configure beacons when it is a turbo mode switch.
@@ -8988,8 +9023,11 @@ ath_calibrate(unsigned long arg)
 		sc->sc_curchan.channel, sc->sc_curchan.channelFlags,
 		isIQdone ? "done" : "not done");
 
-	sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
-	add_timer(&sc->sc_cal_ch);
+	sc->sc_lastcal = jiffies;
+	if (!sc->sc_beacon_cal) {
+		sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
+		add_timer(&sc->sc_cal_ch);
+	}
 }
 
 static void
@@ -9096,7 +9134,8 @@ ath_newstate(struct ieee80211vap *vap, e
 		ieee80211_state_name[vap->iv_state],
 		ieee80211_state_name[nstate]);
 
-	del_timer(&sc->sc_cal_ch);		/* periodic calibration timer */
+	if (!sc->sc_beacon_cal)
+		del_timer(&sc->sc_cal_ch);		/* periodic calibration timer */
 
 	ath_hal_setledstate(ah, leds[nstate]);	/* set LED */
 	netif_stop_queue(dev);			/* before we do anything else */
@@ -9321,7 +9360,8 @@ ath_newstate(struct ieee80211vap *vap, e
 				"VAP -> DFSWAIT_PENDING \n");
 			/* start calibration timer with a really small value 
 			 * 1/10 sec */
-			mod_timer(&sc->sc_cal_ch, jiffies + (HZ/10));
+			if (!sc->sc_beacon_cal)
+				mod_timer(&sc->sc_cal_ch, jiffies + (HZ/10));
 			/* wake the receiver */
 			netif_wake_queue(dev);
 			/* don't do the other usual stuff... */
@@ -9364,7 +9404,7 @@ done:
 	error = avp->av_newstate(vap, nstate, arg);
 
 	/* Finally, start any timers. */
-	if (nstate == IEEE80211_S_RUN) {
+	if (nstate == IEEE80211_S_RUN && !sc->sc_beacon_cal) {
 		/* start periodic recalibration timer */
 		mod_timer(&sc->sc_cal_ch, jiffies + (ath_calinterval * HZ));
 	}
--- a/ath/if_athvar.h
+++ b/ath/if_athvar.h
@@ -778,6 +778,8 @@ struct ath_softc {
 	struct ieee80211vap **sc_bslot;		/* beacon xmit slots */
 	int sc_bnext;				/* next slot for beacon xmit */
 
+	int sc_beacon_cal;			/* use beacon timer for calibration */
+	u_int64_t sc_lastcal;			/* last time the calibration was performed */
 	struct timer_list sc_cal_ch;		/* calibration timer */
 	HAL_NODE_STATS sc_halstats;		/* station-mode rssi stats */