Please test the following patch. It syncs ACI (Adjacent Channels
Interference) code to specs. I can't test it right now. Will port to
mac80211 branch ASAP.


Signed-off-by: Stefano Brivio <[EMAIL PROTECTED]>
----

diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h 
b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 95ff175..7023327 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -398,6 +398,9 @@
 #define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT      7
 #define BCM43xx_DEFAULT_LONG_RETRY_LIMIT       4
 
+/* Statscounter offsets. */
+#define BCM43xx_SC_ACI         0x2E
+
 /* FIXME: the next line is a guess as to what the maximum RSSI value might be 
*/
 #define RX_RSSI_MAX                            60
 
@@ -550,7 +553,11 @@ struct bcm43xx_phyinfo {
        u8 connected:1,
           calibrated:1,
           is_locked:1, /* used in bcm43xx_phy_{un}lock() */
-          dyn_tssi_tbl:1; /* used in bcm43xx_phy_init_tssi2dbm_table() */
+          dyn_tssi_tbl:1, /* used in bcm43xx_phy_init_tssi2dbm_table() */
+          g_interfmode:1; /* bit 4000 in PHY_G_CRS, used in periodic tasks */
+       u8 g_interfmode_timer; /* how much time ago g_interfmode was unset */
+       u16 g_sc_saved; /* used in periodic tasks for ACI */
+
        /* LO Measurement Data.
         * Use bcm43xx_get_lopair() to get a value.
         */
@@ -629,7 +636,9 @@ struct bcm43xx_radioinfo {
        /* ACI (adjacent channel interference) flags. */
        u8 aci_enable:1,
           aci_wlan_automatic:1,
-          aci_hw_rssi:1;
+          aci_hw_rssi:1,
+          aci_delay:5;
+       u8 aci_start;
 };
 
 /* Data structures for DMA transmission, per 80211 core. */
@@ -699,6 +708,18 @@ struct bcm43xx_noise_calculation {
        s8 samples[8][4];
 };
 
+/* Statscounter data (currently ACI only). */
+struct bcm43xx_statscounter_saved {
+       u16 aci;
+};
+
+/* Values for ACI moving average calculation. */
+struct bcm43xx_aci_saved {
+       u16 value[8];
+       u8 next:3,
+          set:3;
+};
+
 struct bcm43xx_stats {
        u8 noise;
        struct iw_statistics wstats;
@@ -812,6 +833,10 @@ struct bcm43xx_private {
        u32 irq_savedstate;
        /* Link Quality calculation context. */
        struct bcm43xx_noise_calculation noisecalc;
+       /* Statscounter tracking. */
+       struct bcm43xx_statscounter_saved sc;
+       /* ACI tracking. */
+       struct bcm43xx_aci_saved aci;
        /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
        int mac_suspended;
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c 
b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index e594af4..27ec519 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -3059,6 +3059,44 @@ static void bcm43xx_pcie_mdio_write(stru
        bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0);
 }
 
+/* We don't use any statscounter other than ACI for now */
+static u16 bcm43xx_sc_read(struct bcm43xx_private *bcm)
+{
+       struct bcm43xx_statscounter_saved *sc = &bcm->sc;
+       u16 tmp;
+
+       tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x80 + BCM43xx_SC_ACI)
+               - sc->aci;
+       if (tmp)
+               sc->aci += tmp;
+
+       return tmp;
+}
+
+static u16 bcm43xx_aci_moving_average(struct bcm43xx_private *bcm)
+{
+       struct bcm43xx_aci_saved *aci = &bcm->aci;
+
+       u8 i;
+       u16 avg;
+       u32 sum = 0;
+
+       aci->value[aci->next] = bcm43xx_sc_read(bcm);
+       if (unlikely(aci->set < 7))
+               aci->set++;
+       for (i = 0; i < aci->set; i++)
+               sum += aci->value[i];
+       avg = sum / (u16)8;
+       if ((sum % 8) > 3)
+               avg++;
+       if (aci->next < 7)
+               aci->next++;
+       else
+               aci->next = 0;
+
+       return avg;
+}
+
 /* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
  * To enable core 0, pass a core_mask of 1<<0
  */
@@ -3182,6 +3220,8 @@ static void bcm43xx_periodic_every1sec(s
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
        int radio_hw_enable;
+       unsigned long phylock_flags;
+       u16 tmp;
 
        /* check if radio hardware enabled status changed */
        radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm);
@@ -3191,27 +3231,56 @@ static void bcm43xx_periodic_every1sec(s
                       (radio_hw_enable == 0) ? "disabled" : "enabled");
                bcm43xx_leds_update(bcm, 0);
        }
+
        if (phy->type == BCM43xx_PHYTYPE_G) {
-               //TODO: update_aci_moving_average
-               if (radio->aci_enable && radio->aci_wlan_automatic) {
+               
+               if (radio->aci_start < 60)
+                       radio->aci_start++;
+               if (radio->aci_delay)
+                       radio->aci_delay--;
+               if (phy->g_interfmode && phy->g_interfmode_timer < 30)
+                       phy->g_interfmode_timer++;
+
+               if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN &&
+                               !radio->aci_delay) {
                        bcm43xx_mac_suspend(bcm);
-                       if (!radio->aci_enable && 1 /*TODO: not scanning? */) {
-                               if (0 /*TODO: bunch of conditions*/) {
-                                       
bcm43xx_radio_set_interference_mitigation(bcm,
-                                                                               
  BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
-                               }
-                       } else if (1/*TODO*/) {
-                               /*
-                               if ((aci_average > 1000) && 
!(bcm43xx_radio_aci_scan(bcm))) {
-                                       
bcm43xx_radio_set_interference_mitigation(bcm,
-                                                                               
  BCM43xx_RADIO_INTERFMODE_NONE);
+                       if (!radio->aci_enable)
+                       {
+                               if (bcm43xx_aci_moving_average(bcm) < 200) {
+                                       if (bcm43xx_radio_aci_scan(bcm)) {
+                                               
bcm43xx_radio_set_interference_mitigation(bcm,
+                                                       
BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
+                                               radio->aci_start = 0;
+                                       } else
+                                               radio->aci_delay = 20;
                                }
-                               */
+                       } else if (radio->aci_start == 60) {
+                               if (bcm43xx_aci_moving_average(bcm) > 1000)
+                                       if (!bcm43xx_radio_aci_scan(bcm))
+                                               
bcm43xx_radio_set_interference_mitigation(bcm,
+                                                       
BCM43xx_RADIO_INTERFMODE_NONE);
                        }
                        bcm43xx_mac_enable(bcm);
                } else if (radio->interfmode == 
BCM43xx_RADIO_INTERFMODE_NONWLAN &&
-                          phy->rev == 1) {
-                       //TODO: implement rev1 workaround
+                               phy->rev == 1) {
+                       tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 
0x00AE);
+                       if (phy->g_interfmode) {
+                               if (tmp && ((tmp - phy->g_sc_saved) > 1500)) {
+                                       bcm43xx_phy_lock(bcm, phylock_flags);
+                                       bcm43xx_phy_write(bcm, 0x00AE,
+                                               bcm43xx_phy_read(bcm, 0x00AE) & 
~0x4000);
+                                       bcm43xx_phy_unlock(bcm, phylock_flags);
+                                       phy->g_interfmode = 1;
+                                       phy->g_interfmode_timer = 0;
+                               }
+                       } else if (phy->g_interfmode_timer == 30) {
+                                               bcm43xx_phy_lock(bcm, 
phylock_flags);
+                                               bcm43xx_phy_write(bcm, 0x00AE,
+                                                       bcm43xx_phy_read(bcm, 
0x00AE & 0x4000));
+                                               bcm43xx_phy_unlock(bcm, 
phylock_flags);
+                                               phy->g_interfmode = 0;
+                       }
+                       phy->g_sc_saved = tmp;
                }
        }
 }
@@ -3297,10 +3366,16 @@ void bcm43xx_periodic_tasks_delete(struc
 void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
 {
        struct delayed_work *work = &bcm->periodic_work;
+       struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 
        assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
        INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler);
        schedule_delayed_work(work, 0);
+       
+       if (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000)
+               phy->g_interfmode = 1;
+       else
+               phy->g_interfmode = 0;
 }
 
 static void bcm43xx_security_init(struct bcm43xx_private *bcm)
@@ -3429,6 +3504,8 @@ static void prepare_radiodata_for_init(s
        radio->aci_enable = 0;
        radio->aci_wlan_automatic = 0;
        radio->aci_hw_rssi = 0;
+       radio->aci_start = 0;
+       radio->aci_delay = 0;
 }
 
 static void prepare_priv_for_init(struct bcm43xx_private *bcm)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c 
b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
_______________________________________________
Bcm43xx-dev mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev

Reply via email to