* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.