Hi,

Here is a patch for advanced btcoex support in iwn(4). I know
that there is no particular reason to do it due to the lack of
bluetooth enabled by default. But as we already do btcoex for
the cards without IWN_FLAG_ADV_BT_COEX flag I was thinking
that we could also do it on other cards.

I take all these things in freebsd without the memset that
overflow:
memset(&btprot, 0, sizeof btprio);

I've also replaced some hardcoded values by defines and added
few comments.

It works on Intel Wifi Link 130 and jca@ have tried it
on his Wifi Link 5300. It would be awesome if someone could 
try it on other chips.

Any ok or this code this is really not needed ?

Cheers,

Index: sys/dev/pci//if_iwn.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
retrieving revision 1.121
diff -u -p -u -p -r1.121 if_iwn.c
--- sys/dev/pci//if_iwn.c       7 Aug 2013 01:06:35 -0000       1.121
+++ sys/dev/pci//if_iwn.c       7 Aug 2013 13:43:35 -0000
@@ -208,6 +208,7 @@ int         iwn_send_sensitivity(struct iwn_sof
 int            iwn_set_pslevel(struct iwn_softc *, int, int, int);
 int            iwn_send_temperature_offset(struct iwn_softc *);
 int            iwn_send_btcoex(struct iwn_softc *);
+int            iwn_send_advanced_btcoex(struct iwn_softc *);
 int            iwn5000_runtime_calib(struct iwn_softc *);
 int            iwn_config(struct iwn_softc *);
 int            iwn_scan(struct iwn_softc *, uint16_t);
@@ -4146,6 +4147,65 @@ iwn_send_btcoex(struct iwn_softc *sc)
 }
 
 int
+iwn_send_advanced_btcoex(struct iwn_softc *sc)
+{
+       static const uint32_t btcoex_3wire[12] = {
+               0xaaaaaaaa, 0xaaaaaaaa, 0xaeaaaaaa, 0xaaaaaaaa,
+               0xcc00ff28, 0x0000aaaa, 0xcc00aaaa, 0x0000aaaa,
+               0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,
+       };
+       struct iwn6000_btcoex_config btconfig;
+       struct iwn_btcoex_priotable btprio;
+       struct iwn_btcoex_prot btprot;
+       int error, i;
+
+       memset(&btconfig, 0, sizeof btconfig);
+       btconfig.flags = IWN_BT_FLAG_COEX6000_CHAN_INHIBITION |
+           (IWN_BT_FLAG_COEX6000_MODE_3W << IWN_BT_FLAG_COEX6000_MODE_SHIFT) |
+           IWN_BT_FLAG_SYNC_2_BT_DISABLE;
+       btconfig.max_kill = 5;
+       btconfig.bt3_t7_timer = 1;
+       btconfig.kill_ack = htole32(0xffff0000);
+       btconfig.kill_cts = htole32(0xffff0000);
+       btconfig.sample_time = 2;
+       btconfig.bt3_t2_timer = 0xc;
+       for (i = 0; i < 12; i++)
+               btconfig.lookup_table[i] = htole32(btcoex_3wire[i]);
+       btconfig.valid = htole16(0xff);
+       btconfig.prio_boost = 0xf0;
+       DPRINTF(("configuring advanced bluetooth coexistence\n"));
+       error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, sizeof(btconfig), 1);
+       if (error != 0)
+               return (error);
+
+       memset(&btprio, 0, sizeof btprio);
+       btprio.calib_init1 = 0x6;
+       btprio.calib_init2 = 0x7;
+       btprio.calib_periodic_low1 = 0x2;
+       btprio.calib_periodic_low2 = 0x3;
+       btprio.calib_periodic_high1 = 0x4;
+       btprio.calib_periodic_high2 = 0x5;
+       btprio.dtim = 0x6;
+       btprio.scan52 = 0x8;
+       btprio.scan24 = 0xa;
+       error = iwn_cmd(sc, IWN_CMD_BT_COEX_PRIOTABLE, &btprio, sizeof(btprio),
+           1);
+       if (error != 0)
+               return (error);
+
+       /* Force BT state machine change */
+       memset(&btprot, 0, sizeof btprot);
+       btprot.open = 1;
+       btprot.type = 1;
+       error = iwn_cmd(sc, IWN_CMD_BT_COEX_PROT, &btprot, sizeof(btprot), 1);
+       if (error != 0)
+               return (error);
+
+       btprot.open = 0;
+       return (iwn_cmd(sc, IWN_CMD_BT_COEX_PROT, &btprot, sizeof(btprot), 1));
+}
+
+int
 iwn5000_runtime_calib(struct iwn_softc *sc)
 {
        struct iwn5000_calib_config cmd;
@@ -4202,15 +4262,14 @@ iwn_config(struct iwn_softc *sc)
        }
 
        /* Configure bluetooth coexistence. */
-       if (sc->sc_flags & IWN_FLAG_ADV_BT_COEX) {
-               /* XXX Advanced bluetooth coexistence isn't implemented yet. */
-       } else {
+       if (sc->sc_flags & IWN_FLAG_ADV_BT_COEX)
+               error = iwn_send_advanced_btcoex(sc);
+       else
                error = iwn_send_btcoex(sc);
-               if (error != 0) {
-                       printf("%s: could not configure bluetooth 
coexistence\n",
-                           sc->sc_dev.dv_xname);
-                       return error;
-               }
+       if (error != 0) {
+               printf("%s: could not configure bluetooth coexistence\n",
+                   sc->sc_dev.dv_xname);
+               return error;
        }
 
        /* Set mode, channel, RX filter and enable RX. */
Index: sys/dev/pci//if_iwnreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwnreg.h,v
retrieving revision 1.43
diff -u -p -u -p -r1.43 if_iwnreg.h
--- sys/dev/pci//if_iwnreg.h    1 Sep 2011 18:49:56 -0000       1.43
+++ sys/dev/pci//if_iwnreg.h    7 Aug 2013 13:43:35 -0000
@@ -433,6 +433,8 @@ struct iwn_tx_cmd {
 #define IWN_CMD_SET_CRITICAL_TEMP      164
 #define IWN_CMD_SET_SENSITIVITY                168
 #define IWN_CMD_PHY_CALIB              176
+#define IWN_CMD_BT_COEX_PRIOTABLE      204
+#define IWN_CMD_BT_COEX_PROT           205
 
        uint8_t flags;
        uint8_t idx;
@@ -830,7 +832,7 @@ struct iwn5000_cmd_txpower {
        uint8_t reserved;
 } __packed;
 
-/* Structure for command IWN_CMD_BLUETOOTH. */
+/* Structures for command IWN_CMD_BLUETOOTH. */
 struct iwn_bluetooth {
        uint8_t         flags;
 #define IWN_BT_COEX_CHAN_ANN   (1 << 0)
@@ -846,6 +848,55 @@ struct iwn_bluetooth {
        uint8_t         reserved;
        uint32_t        kill_ack;
        uint32_t        kill_cts;
+} __packed;
+
+struct iwn6000_btcoex_config {
+       uint8_t         flags;
+#define        IWN_BT_FLAG_COEX6000_CHAN_INHIBITION    1
+#define        IWN_BT_FLAG_COEX6000_MODE_MASK          ((1 << 3) | (1 << 4) | 
(1 << 5))
+#define        IWN_BT_FLAG_COEX6000_MODE_SHIFT         3
+#define        IWN_BT_FLAG_COEX6000_MODE_DISABLED      0
+#define        IWN_BT_FLAG_COEX6000_MODE_LEGACY_2W     1
+#define        IWN_BT_FLAG_COEX6000_MODE_3W            2
+#define        IWN_BT_FLAG_COEX6000_MODE_4W            3
+#define        IWN_BT_FLAG_UCODE_DEFAULT               (1<<6)
+#define        IWN_BT_FLAG_SYNC_2_BT_DISABLE           (1<<7)
+
+       uint8_t         lead_time;
+       uint8_t         max_kill;
+       uint8_t         bt3_t7_timer;
+       uint32_t        kill_ack;
+       uint32_t        kill_cts;
+       uint8_t         sample_time;
+       uint8_t         bt3_t2_timer;
+       uint16_t        bt4_reaction;
+       uint32_t        lookup_table[12];
+       uint16_t        bt4_decision;
+       uint16_t        valid;
+       uint8_t         prio_boost;
+       uint8_t         tx_prio_boost;
+       uint16_t        rx_prio_boost;
+} __packed;
+
+/* Structure for command IWN_CMD_BT_COEX_PRIOTABLE */
+struct iwn_btcoex_priotable {
+       uint8_t         calib_init1;
+       uint8_t         calib_init2;
+       uint8_t         calib_periodic_low1;
+       uint8_t         calib_periodic_low2;
+       uint8_t         calib_periodic_high1;
+       uint8_t         calib_periodic_high2;
+       uint8_t         dtim;
+       uint8_t         scan52;
+       uint8_t         scan24;
+       uint8_t         reserved[7];
+} __packed;
+
+/* Structure for command IWN_CMD_BT_COEX_PROT */
+struct iwn_btcoex_prot {
+       uint8_t         open;
+       uint8_t         type;
+       uint8_t         reserved[2];
 } __packed;
 
 /* Structure for command IWN_CMD_SET_CRITICAL_TEMP. */

Reply via email to