diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 1afba42cc128d04ffb3672bace53835a8d245a5d..e87ad43e8e8d36f599494bbddfc81c9c6ac65988 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -600,35 +600,36 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
 	qual->false_cca = bbp;
 }
 
+static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level)
+{
+	rt2400pci_bbp_write(rt2x00dev, 13, vgc_level);
+	rt2x00dev->link.vgc_level = vgc_level;
+	rt2x00dev->link.vgc_level_reg = vgc_level;
+}
+
 static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
 {
-	rt2400pci_bbp_write(rt2x00dev, 13, 0x08);
-	rt2x00dev->link.vgc_level = 0x08;
+	rt2400pci_set_vgc(rt2x00dev, 0x08);
 }
 
 static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 {
-	u8 reg;
+	struct link *link = &rt2x00dev->link;
 
 	/*
 	 * The link tuner should not run longer then 60 seconds,
 	 * and should run once every 2 seconds.
 	 */
-	if (rt2x00dev->link.count > 60 || !(rt2x00dev->link.count & 1))
+	if (link->count > 60 || !(link->count & 1))
 		return;
 
 	/*
 	 * Base r13 link tuning on the false cca count.
 	 */
-	rt2400pci_bbp_read(rt2x00dev, 13, &reg);
-
-	if (rt2x00dev->link.qual.false_cca > 512 && reg < 0x20) {
-		rt2400pci_bbp_write(rt2x00dev, 13, ++reg);
-		rt2x00dev->link.vgc_level = reg;
-	} else if (rt2x00dev->link.qual.false_cca < 100 && reg > 0x08) {
-		rt2400pci_bbp_write(rt2x00dev, 13, --reg);
-		rt2x00dev->link.vgc_level = reg;
-	}
+	if ((link->qual.false_cca > 512) && (link->vgc_level < 0x20))
+		rt2400pci_set_vgc(rt2x00dev, ++link->vgc_level);
+	else if ((link->qual.false_cca < 100) && (link->vgc_level > 0x08))
+		rt2400pci_set_vgc(rt2x00dev, --link->vgc_level);
 }
 
 /*
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index bf5e81162f2598d98c39a159461c7d80912cabea..5b98a74a25549bf8f51d24da5503db73568921a6 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -639,16 +639,23 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,
 	qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
 }
 
+static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level)
+{
+	if (rt2x00dev->link.vgc_level_reg != vgc_level) {
+		rt2500pci_bbp_write(rt2x00dev, 17, vgc_level);
+		rt2x00dev->link.vgc_level_reg = vgc_level;
+	}
+}
+
 static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
 {
-	rt2500pci_bbp_write(rt2x00dev, 17, 0x48);
-	rt2x00dev->link.vgc_level = 0x48;
+	rt2500pci_set_vgc(rt2x00dev, 0x48);
 }
 
 static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 {
-	int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
-	u8 r17;
+	struct link *link = &rt2x00dev->link;
+	int rssi = rt2x00_get_link_rssi(link);
 
 	/*
 	 * To prevent collisions with MAC ASIC on chipsets
@@ -656,12 +663,9 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * seconds while being associated.
 	 */
 	if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
-	    rt2x00dev->intf_associated &&
-	    rt2x00dev->link.count > 20)
+	    rt2x00dev->intf_associated && link->count > 20)
 		return;
 
-	rt2500pci_bbp_read(rt2x00dev, 17, &r17);
-
 	/*
 	 * Chipset versions C and lower should directly continue
 	 * to the dynamic CCA tuning. Chipset version D and higher
@@ -677,11 +681,9 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * then corrupt the R17 tuning. To remidy this the tuning should
 	 * be stopped (While making sure the R17 value will not exceed limits)
 	 */
-	if (rssi < -80 && rt2x00dev->link.count > 20) {
-		if (r17 >= 0x41) {
-			r17 = rt2x00dev->link.vgc_level;
-			rt2500pci_bbp_write(rt2x00dev, 17, r17);
-		}
+	if (rssi < -80 && link->count > 20) {
+		if (link->vgc_level_reg >= 0x41)
+			rt2500pci_set_vgc(rt2x00dev, link->vgc_level);
 		return;
 	}
 
@@ -689,8 +691,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * Special big-R17 for short distance
 	 */
 	if (rssi >= -58) {
-		if (r17 != 0x50)
-			rt2500pci_bbp_write(rt2x00dev, 17, 0x50);
+		rt2500pci_set_vgc(rt2x00dev, 0x50);
 		return;
 	}
 
@@ -698,8 +699,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * Special mid-R17 for middle distance
 	 */
 	if (rssi >= -74) {
-		if (r17 != 0x41)
-			rt2500pci_bbp_write(rt2x00dev, 17, 0x41);
+		rt2500pci_set_vgc(rt2x00dev, 0x41);
 		return;
 	}
 
@@ -707,8 +707,8 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * Leave short or middle distance condition, restore r17
 	 * to the dynamic tuning range.
 	 */
-	if (r17 >= 0x41) {
-		rt2500pci_bbp_write(rt2x00dev, 17, rt2x00dev->link.vgc_level);
+	if (link->vgc_level_reg >= 0x41) {
+		rt2500pci_set_vgc(rt2x00dev, link->vgc_level);
 		return;
 	}
 
@@ -718,12 +718,12 @@ dynamic_cca_tune:
 	 * R17 is inside the dynamic tuning range,
 	 * start tuning the link based on the false cca counter.
 	 */
-	if (rt2x00dev->link.qual.false_cca > 512 && r17 < 0x40) {
-		rt2500pci_bbp_write(rt2x00dev, 17, ++r17);
-		rt2x00dev->link.vgc_level = r17;
-	} else if (rt2x00dev->link.qual.false_cca < 100 && r17 > 0x32) {
-		rt2500pci_bbp_write(rt2x00dev, 17, --r17);
-		rt2x00dev->link.vgc_level = r17;
+	if (link->qual.false_cca > 512 && link->vgc_level_reg < 0x40) {
+		rt2500pci_set_vgc(rt2x00dev, ++link->vgc_level_reg);
+		link->vgc_level = link->vgc_level_reg;
+	} else if (link->qual.false_cca < 100 && link->vgc_level_reg > 0x32) {
+		rt2500pci_set_vgc(rt2x00dev, --link->vgc_level_reg);
+		link->vgc_level = link->vgc_level_reg;
 	}
 }
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 19c068727a85b6be634eccae2a46a9e91318bb9d..8935f2c005ceb6a6509208e387786717b8275422 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -286,9 +286,14 @@ struct link {
 	struct link_ant ant;
 
 	/*
-	 * Active VGC level
+	 * Active VGC level (for false cca tuning)
 	 */
-	int vgc_level;
+	u8 vgc_level;
+
+	/*
+	 * VGC level as configured in register
+	 */
+	u8 vgc_level_reg;
 
 	/*
 	 * Work structure for scheduling periodic link tuning.
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index c7ab744f0052cf6915eb52d26080af3f6cabec53..94523f7f0d8815150758d21c2f5ff21c500e81b6 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1046,21 +1046,27 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
 	qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
 }
 
+static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level)
+{
+	if (rt2x00dev->link.vgc_level != vgc_level) {
+		rt61pci_bbp_write(rt2x00dev, 17, vgc_level);
+		rt2x00dev->link.vgc_level = vgc_level;
+		rt2x00dev->link.vgc_level_reg = vgc_level;
+	}
+}
+
 static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
 {
-	rt61pci_bbp_write(rt2x00dev, 17, 0x20);
-	rt2x00dev->link.vgc_level = 0x20;
+	rt61pci_set_vgc(rt2x00dev, 0x20);
 }
 
 static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 {
-	int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
-	u8 r17;
+	struct link *link = &rt2x00dev->link;
+	int rssi = rt2x00_get_link_rssi(link);
 	u8 up_bound;
 	u8 low_bound;
 
-	rt61pci_bbp_read(rt2x00dev, 17, &r17);
-
 	/*
 	 * Determine r17 bounds.
 	 */
@@ -1091,8 +1097,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * Special big-R17 for very short distance
 	 */
 	if (rssi >= -35) {
-		if (r17 != 0x60)
-			rt61pci_bbp_write(rt2x00dev, 17, 0x60);
+		rt61pci_set_vgc(rt2x00dev, 0x60);
 		return;
 	}
 
@@ -1100,8 +1105,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * Special big-R17 for short distance
 	 */
 	if (rssi >= -58) {
-		if (r17 != up_bound)
-			rt61pci_bbp_write(rt2x00dev, 17, up_bound);
+		rt61pci_set_vgc(rt2x00dev, up_bound);
 		return;
 	}
 
@@ -1109,9 +1113,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * Special big-R17 for middle-short distance
 	 */
 	if (rssi >= -66) {
-		low_bound += 0x10;
-		if (r17 != low_bound)
-			rt61pci_bbp_write(rt2x00dev, 17, low_bound);
+		rt61pci_set_vgc(rt2x00dev, low_bound + 0x10);
 		return;
 	}
 
@@ -1119,9 +1121,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * Special mid-R17 for middle distance
 	 */
 	if (rssi >= -74) {
-		low_bound += 0x08;
-		if (r17 != low_bound)
-			rt61pci_bbp_write(rt2x00dev, 17, low_bound);
+		rt61pci_set_vgc(rt2x00dev, low_bound + 0x08);
 		return;
 	}
 
@@ -1133,8 +1133,8 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 	if (low_bound > up_bound)
 		up_bound = low_bound;
 
-	if (r17 > up_bound) {
-		rt61pci_bbp_write(rt2x00dev, 17, up_bound);
+	if (link->vgc_level > up_bound) {
+		rt61pci_set_vgc(rt2x00dev, up_bound);
 		return;
 	}
 
@@ -1144,15 +1144,10 @@ dynamic_cca_tune:
 	 * r17 does not yet exceed upper limit, continue and base
 	 * the r17 tuning on the false CCA count.
 	 */
-	if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
-		if (++r17 > up_bound)
-			r17 = up_bound;
-		rt61pci_bbp_write(rt2x00dev, 17, r17);
-	} else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
-		if (--r17 < low_bound)
-			r17 = low_bound;
-		rt61pci_bbp_write(rt2x00dev, 17, r17);
-	}
+	if ((link->qual.false_cca > 512) && (link->vgc_level < up_bound))
+		rt61pci_set_vgc(rt2x00dev, ++link->vgc_level);
+	else if ((link->qual.false_cca < 100) && (link->vgc_level > low_bound))
+		rt61pci_set_vgc(rt2x00dev, --link->vgc_level);
 }
 
 /*
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index ae3b31d0d511f0828e8994e3f677426b8ca53eb9..b5443148d621e48c33c69973ead9b64cad30ef84 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -924,21 +924,27 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
 	qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
 }
 
+static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level)
+{
+	if (rt2x00dev->link.vgc_level != vgc_level) {
+		rt73usb_bbp_write(rt2x00dev, 17, vgc_level);
+		rt2x00dev->link.vgc_level = vgc_level;
+		rt2x00dev->link.vgc_level_reg = vgc_level;
+	}
+}
+
 static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev)
 {
-	rt73usb_bbp_write(rt2x00dev, 17, 0x20);
-	rt2x00dev->link.vgc_level = 0x20;
+	rt73usb_set_vgc(rt2x00dev, 0x20);
 }
 
 static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
 {
-	int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
-	u8 r17;
+	struct link *link = &rt2x00dev->link;
+	int rssi = rt2x00_get_link_rssi(link);
 	u8 up_bound;
 	u8 low_bound;
 
-	rt73usb_bbp_read(rt2x00dev, 17, &r17);
-
 	/*
 	 * Determine r17 bounds.
 	 */
@@ -979,8 +985,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * Special big-R17 for very short distance
 	 */
 	if (rssi > -35) {
-		if (r17 != 0x60)
-			rt73usb_bbp_write(rt2x00dev, 17, 0x60);
+		rt73usb_set_vgc(rt2x00dev, 0x60);
 		return;
 	}
 
@@ -988,8 +993,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * Special big-R17 for short distance
 	 */
 	if (rssi >= -58) {
-		if (r17 != up_bound)
-			rt73usb_bbp_write(rt2x00dev, 17, up_bound);
+		rt73usb_set_vgc(rt2x00dev, up_bound);
 		return;
 	}
 
@@ -997,9 +1001,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * Special big-R17 for middle-short distance
 	 */
 	if (rssi >= -66) {
-		low_bound += 0x10;
-		if (r17 != low_bound)
-			rt73usb_bbp_write(rt2x00dev, 17, low_bound);
+		rt73usb_set_vgc(rt2x00dev, low_bound + 0x10);
 		return;
 	}
 
@@ -1007,8 +1009,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
 	 * Special mid-R17 for middle distance
 	 */
 	if (rssi >= -74) {
-		if (r17 != (low_bound + 0x10))
-			rt73usb_bbp_write(rt2x00dev, 17, low_bound + 0x08);
+		rt73usb_set_vgc(rt2x00dev, low_bound + 0x08);
 		return;
 	}
 
@@ -1020,8 +1021,8 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
 	if (low_bound > up_bound)
 		up_bound = low_bound;
 
-	if (r17 > up_bound) {
-		rt73usb_bbp_write(rt2x00dev, 17, up_bound);
+	if (link->vgc_level > up_bound) {
+		rt73usb_set_vgc(rt2x00dev, up_bound);
 		return;
 	}
 
@@ -1031,17 +1032,12 @@ dynamic_cca_tune:
 	 * r17 does not yet exceed upper limit, continue and base
 	 * the r17 tuning on the false CCA count.
 	 */
-	if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
-		r17 += 4;
-		if (r17 > up_bound)
-			r17 = up_bound;
-		rt73usb_bbp_write(rt2x00dev, 17, r17);
-	} else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
-		r17 -= 4;
-		if (r17 < low_bound)
-			r17 = low_bound;
-		rt73usb_bbp_write(rt2x00dev, 17, r17);
-	}
+	if ((link->qual.false_cca > 512) && (link->vgc_level < up_bound))
+		rt73usb_set_vgc(rt2x00dev,
+				min_t(u8, link->vgc_level + 4, up_bound));
+	else if ((link->qual.false_cca < 100) && (link->vgc_level > low_bound))
+		rt73usb_set_vgc(rt2x00dev,
+				max_t(u8, link->vgc_level - 4, low_bound));
 }
 
 /*