* [PATCH 13/32] rt2x00: Tune link depending on link quality
@ 2006-04-27 22:03 Ivo van Doorn
0 siblings, 0 replies; only message in thread
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 7739 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Add link tuning capabilities, and call this function
every time the rxdone handler has finished.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:42:29.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:45:08.000000000 +0200
@@ -618,6 +618,41 @@ rt2400pci_config_rate(struct rt2x00_pci
}
/*
+ * Link tuning
+ */
+static void
+rt2400pci_link_tuner(struct rt2x00_pci *rt2x00pci)
+{
+ u8 reg;
+ char false_cca_delta;
+
+ /*
+ * Read false CCA counter.
+ */
+ rt2x00_bbp_read(rt2x00pci, 39, ®);
+
+ /*
+ * Determine difference with previous CCA counter.
+ */
+ false_cca_delta = reg - rt2x00pci->false_cca;
+ rt2x00pci->false_cca = reg;
+
+ /*
+ * Check if the difference is higher than the
+ * threshold and if so, tune the link.
+ */
+ if (false_cca_delta >= 8) {
+ /*
+ * Read and update RX AGC VGC.
+ */
+ rt2x00_bbp_read(rt2x00pci, 13, ®);
+ reg += 2;
+ if (reg < 0x20)
+ rt2x00_bbp_write(rt2x00pci, 13, reg);
+ }
+}
+
+/*
* TX descriptor initialization
*/
static void
@@ -779,6 +814,9 @@ rt2400pci_rxdone(void *data)
memcpy(skb_put(skb, size), entry->data_addr, size);
+ ring->params.rx.ssi =
+ rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
+
__ieee80211_rx(net_dev, skb, &ring->params.rx);
}
@@ -786,6 +824,11 @@ rt2400pci_rxdone(void *data)
rt2x00_ring_index_inc(&rt2x00pci->rx);
}
+
+ /*
+ * Tune link for optimal performance.
+ */
+ rt2400pci_link_tuner(rt2x00pci);
}
static void
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 21:36:19.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 21:45:08.000000000 +0200
@@ -926,6 +926,11 @@ struct rt2x00_pci{
struct workqueue_struct *workqueue;
/*
+ * False CCA count.
+ */
+ int false_cca;
+
+ /*
* EEPROM bus width.
*/
u8 eeprom_width;
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:42:29.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:45:08.000000000 +0200
@@ -661,6 +661,51 @@ rt2500pci_config_rate(struct rt2x00_pci
}
/*
+ * Link tuning
+ */
+static void
+rt2500pci_link_tuner(struct rt2x00_pci *rt2x00pci, char rssi)
+{
+ u32 reg;
+ u8 reg_r17;
+
+ /*
+ * Don't perform any tuning during scan.
+ */
+ if (rt2x00pci->scan)
+ return;
+
+ rt2x00_register_read(rt2x00pci, CSR0, ®);
+ rt2x00_bbp_read(rt2x00pci, 17, ®_r17);
+
+ if (reg < RT2560_VERSION_D)
+ goto dynamic_cca_tune;
+
+ if (rssi < 40) {
+ if (reg_r17 >= 0x41)
+ rt2x00_bbp_write(rt2x00pci, 17, reg_r17);
+ return;
+ } else if (rssi >= 62) {
+ if (reg_r17 != 0x50)
+ rt2x00_bbp_write(rt2x00pci, 17, 0x50);
+ return;
+ } else if (reg_r17 >= 0x41) {
+ rt2x00_bbp_write(rt2x00pci, 17, reg_r17);
+ return;
+ }
+
+dynamic_cca_tune:
+ rt2x00_register_read(rt2x00pci, CNT3, ®);
+
+ reg = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
+
+ if (reg > 512 && reg_r17 < 0x40)
+ rt2x00_bbp_write(rt2x00pci, 17, ++reg_r17);
+ else if (reg < 100 && reg_r17 > 0x32)
+ rt2x00_bbp_write(rt2x00pci, 17, --reg_r17);
+}
+
+/*
* TX descriptor initialization
*/
static void
@@ -819,6 +864,14 @@ rt2500pci_rxdone(void *data)
struct sk_buff *skb;
struct rxd *rxd;
u16 size;
+ u8 rssi_count;
+ char total_rssi;
+
+ /*
+ * Initialize variable for average RSSI calculation.
+ */
+ rssi_count = 0;
+ total_rssi = 0;
while (1) {
entry = rt2x00_get_data_entry(ring);
@@ -843,12 +896,24 @@ rt2500pci_rxdone(void *data)
memcpy(skb_put(skb, size), entry->data_addr, size);
+ ring->params.rx.ssi =
+ rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
+
__ieee80211_rx(net_dev, skb, &ring->params.rx);
+
+ rssi_count++;
+ total_rssi += ring->params.rx.ssi;
}
rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
rt2x00_ring_index_inc(&rt2x00pci->rx);
}
+
+ /*
+ * Tune link for optimal performance.
+ */
+ if (total_rssi && rssi_count)
+ rt2500pci_link_tuner(rt2x00pci, total_rssi / rssi_count);
}
static void
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:44:33.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:45:08.000000000 +0200
@@ -485,6 +485,68 @@ rt2500usb_config_rate(struct rt2x00_usb
}
/*
+ * Link tuning
+ */
+static void
+rt2500usb_link_tuner(struct rt2x00_usb *rt2x00usb, char rssi)
+{
+ u16 reg;
+ u8 reg_r17;
+ u8 up_bound;
+ u8 low_bound;
+
+ /*
+ * Don't perform any tuning during scan.
+ */
+ if (rt2x00usb->scan)
+ return;
+
+ low_bound = 0x32;
+ if (rssi >= 43)
+ up_bound = 0x40;
+ else
+ up_bound = 0x40 - (43 - rssi);
+ if (up_bound < low_bound)
+ up_bound = low_bound;
+
+ if (rssi > 75) {
+ rt2x00_bbp_write(rt2x00usb, 24, 0x70);
+ rt2x00_bbp_write(rt2x00usb, 25, 0x40);
+ rt2x00_bbp_write(rt2x00usb, 61, 0x6d);
+ } else {
+ rt2x00_bbp_write(rt2x00usb, 24, 0x80);
+ rt2x00_bbp_write(rt2x00usb, 25, 0x50);
+ rt2x00_bbp_write(rt2x00usb, 61, 0x60);
+ }
+
+ rt2x00_bbp_read(rt2x00usb, 17, ®_r17);
+
+ if (rssi > 80) {
+ if (reg_r17 != 0x60)
+ rt2x00_bbp_write(rt2x00usb, 17, 0x60);
+ return;
+ } else if (rssi >= 62) {
+ if (reg_r17 != 0x48)
+ rt2x00_bbp_write(rt2x00usb, 17, 0x48);
+ return;
+ } else if (rssi >= 46) {
+ if (reg_r17 != 0x41)
+ rt2x00_bbp_write(rt2x00usb, 17, 0x41);
+ return;
+ } else if (reg_r17 > up_bound) {
+ rt2x00_bbp_write(rt2x00usb, 17, up_bound);
+ return;
+ }
+
+ rt2x00_register_read(rt2x00usb, STA_CSR3, ®);
+
+ if (reg > 512 && reg_r17 < up_bound)
+ rt2x00_bbp_write(rt2x00usb, 17, ++reg_r17);
+ else if (reg < 100 && reg_r17 > low_bound)
+ rt2x00_bbp_write(rt2x00usb, 17, --reg_r17);
+}
+
+/*
* TX descriptor initialization
*/
static void
@@ -636,6 +698,14 @@ rt2500usb_rxdone(void *data)
struct sk_buff *skb;
struct rxd *rxd;
u16 size;
+ u8 rssi_count;
+ char total_rssi;
+
+ /*
+ * Initialize variable for average RSSI calculation.
+ */
+ rssi_count = 0;
+ total_rssi = 0;
while (1) {
entry = rt2x00_get_data_entry(ring);
@@ -670,13 +740,25 @@ rt2500usb_rxdone(void *data)
memcpy(skb_put(skb, size), entry->data_addr, size);
+ ring->params.rx.ssi =
+ rt2x00_get_field32(rxd->word1, RXD_W1_RSSI);
+
__ieee80211_rx(net_dev, skb, &ring->params.rx);
+
+ rssi_count++;
+ total_rssi += ring->params.rx.ssi;
}
usb_submit_urb(entry->urb, GFP_ATOMIC);
rt2x00_ring_index_inc(ring);
}
+
+ /*
+ * Tune link for optimal performance.
+ */
+ if (total_rssi && rssi_count)
+ rt2500usb_link_tuner(rt2x00usb, total_rssi / rssi_count);
}
static void
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2006-04-27 22:02 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-27 22:03 [PATCH 13/32] rt2x00: Tune link depending on link quality Ivo van Doorn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).