tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: iwn



On Sat, Dec 29, 2012 at 12:30:33PM +0000, Patrick Welche wrote:
> Diro's note in
> 
>   http://mail-index.netbsd.org/tech-net/2012/12/08/msg003778.html
> 
> reminded me that I never applied the patch in
> 
>   http://mail-index.netbsd.org/tech-kern/2011/08/06/msg011131.html
> 
> I am writing this logged in via
> 
>   iwn0 at pci3 dev 0 function 0: Intel Centrino Advanced-N 6230 (rev. 0x34)
> 
> so it does work. The unclean part is that I had to comment out the
> bluetooth coexistence code. This week I wrote some bluetooth coexistence
> code, which doesn't fail, but now crystal callibration fails: 
> 
> Configuring WiMAX coexistence
> sending crystal calibration 121, 121
> iwn0: fatal firmware error
> 
> Do any of you know whether 121 makes any sense?
> The code seems to just copy the values from an eeprom...
> 
> One thing I did change is
>   IWN5000_CMD_WIMAX_COEX
> which I think should be 92 rather than 90...

It turns out that the calibration error goes away when I set
IWN5000_CMD_WIMAX_COEX back to 90. This suggests that the WIMAX_COEX
code is broken, as 90 doesn't do much - but that is another problem...

Attached is a patch which allows the 6230 to work, and which has
bluetooth coexistence code.


Cheers,

Patrick
Index: if_iwn.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_iwn.c,v
retrieving revision 1.62
diff -u -r1.62 if_iwn.c
--- if_iwn.c    30 Jan 2012 19:41:20 -0000      1.62
+++ if_iwn.c    4 Jan 2013 13:09:28 -0000
@@ -35,6 +35,9 @@
 #include <sys/socket.h>
 #include <sys/systm.h>
 #include <sys/malloc.h>
+#ifdef notyetMODULE
+#include <sys/module.h>
+#endif
 #include <sys/mutex.h>
 #include <sys/conf.h>
 #include <sys/kauth.h>
@@ -227,6 +230,11 @@
 static int     iwn_send_sensitivity(struct iwn_softc *);
 static int     iwn_set_pslevel(struct iwn_softc *, int, int, int);
 static int     iwn5000_runtime_calib(struct iwn_softc *);
+
+static int     iwn_config_bt_coex_bluetooth(struct iwn_softc *);
+static int     iwn_config_bt_coex_prio_table(struct iwn_softc *);
+static int     iwn_config_bt_coex_adv1(struct iwn_softc *);
+
 static int     iwn_config(struct iwn_softc *);
 static int     iwn_scan(struct iwn_softc *, uint16_t);
 static int     iwn_auth(struct iwn_softc *);
@@ -618,6 +626,7 @@
        ops->read_eeprom = iwn4965_read_eeprom;
        ops->post_alive = iwn4965_post_alive;
        ops->nic_config = iwn4965_nic_config;
+       ops->config_bt_coex = iwn_config_bt_coex_bluetooth;
        ops->update_sched = iwn4965_update_sched;
        ops->get_temperature = iwn4965_get_temperature;
        ops->get_rssi = iwn4965_get_rssi;
@@ -657,6 +666,7 @@
        ops->read_eeprom = iwn5000_read_eeprom;
        ops->post_alive = iwn5000_post_alive;
        ops->nic_config = iwn5000_nic_config;
+       ops->config_bt_coex = iwn_config_bt_coex_bluetooth;
        ops->update_sched = iwn5000_update_sched;
        ops->get_temperature = iwn5000_get_temperature;
        ops->get_rssi = iwn5000_get_rssi;
@@ -717,7 +727,16 @@
                break;
        case IWN_HW_REV_TYPE_6005:
                sc->limits = &iwn6000_sensitivity_limits;
-               sc->fwname = "iwlwifi-6000g2a-5.ucode";
+               /* Type 6030 cards return IWN_HW_REV_TYPE_6005 */
+               if (pid == PCI_PRODUCT_INTEL_WIFI_LINK_1030_1 ||
+                   pid == PCI_PRODUCT_INTEL_WIFI_LINK_1030_2 ||
+                   pid == PCI_PRODUCT_INTEL_WIFI_LINK_6230_1 ||
+                   pid == PCI_PRODUCT_INTEL_WIFI_LINK_6230_2) {
+                       sc->fwname = "iwlwifi-6000g2b-5.ucode";
+                       ops->config_bt_coex = iwn_config_bt_coex_adv1;
+               }
+               else
+                       sc->fwname = "iwlwifi-6000g2a-5.ucode";
                break;
        default:
                aprint_normal(": adapter type %d not supported\n", sc->hw_type);
@@ -4107,16 +4126,108 @@
 }
 
 static int
+iwn_config_bt_coex_bluetooth(struct iwn_softc *sc)
+{
+       struct iwn_bluetooth bluetooth;
+
+       memset(&bluetooth, 0, sizeof bluetooth);
+       bluetooth.flags = IWN_BT_COEX_ENABLE;
+       bluetooth.lead_time = IWN_BT_LEAD_TIME_DEF;
+       bluetooth.max_kill = IWN_BT_MAX_KILL_DEF;
+
+       DPRINTF(("configuring bluetooth coexistence\n"));
+       return iwn_cmd(sc, IWN_CMD_BT_COEX, &bluetooth, sizeof bluetooth, 0);
+}
+
+static int
+iwn_config_bt_coex_prio_table(struct iwn_softc *sc)
+{
+       uint8_t prio_table[16];
+
+       memset(&prio_table, 0, sizeof prio_table);
+       prio_table[ 0] =  6;    /* init calibration 1           */
+       prio_table[ 1] =  7;    /* init calibration 2           */
+       prio_table[ 2] =  2;    /* periodic calib low 1         */
+       prio_table[ 3] =  3;    /* periodic calib low 2         */
+       prio_table[ 4] =  4;    /* periodic calib high 1        */
+       prio_table[ 5] =  5;    /* periodic calib high 2        */
+       prio_table[ 6] =  6;    /* dtim                         */
+       prio_table[ 7] =  8;    /* scan52                       */
+       prio_table[ 8] = 10;    /* scan24                       */
+
+       DPRINTF(("sending priority lookup table\n"));
+       return iwn_cmd(sc, IWN_CMD_BT_COEX_PRIO_TABLE,
+                      &prio_table, sizeof prio_table, 0);
+}
+
+static int
+iwn_config_bt_coex_adv1(struct iwn_softc *sc)
+{
+       int error;
+       struct iwn_bt_adv1 d;
+
+       memset(&d, 0, sizeof d);
+       d.basic.bt.flags = IWN_BT_COEX_ENABLE;
+       d.basic.bt.lead_time = IWN_BT_LEAD_TIME_DEF;
+       d.basic.bt.max_kill = IWN_BT_MAX_KILL_DEF;
+       d.basic.bt.bt3_timer_t7_value = IWN_BT_BT3_T7_DEF;
+       d.basic.bt.kill_ack_mask = IWN_BT_KILL_ACK_MASK_DEF;
+       d.basic.bt.kill_cts_mask = IWN_BT_KILL_CTS_MASK_DEF;
+       d.basic.bt3_prio_sample_time = IWN_BT_BT3_PRIO_SAMPLE_DEF;
+       d.basic.bt3_timer_t2_value = IWN_BT_BT3_T2_DEF;
+       d.basic.bt3_lookup_table[ 0] = htole32(0xaaaaaaaa); /* Normal */
+       d.basic.bt3_lookup_table[ 1] = htole32(0xaaaaaaaa);
+       d.basic.bt3_lookup_table[ 2] = htole32(0xaeaaaaaa);
+       d.basic.bt3_lookup_table[ 3] = htole32(0xaaaaaaaa);
+       d.basic.bt3_lookup_table[ 4] = htole32(0xcc00ff28);
+       d.basic.bt3_lookup_table[ 5] = htole32(0x0000aaaa);
+       d.basic.bt3_lookup_table[ 6] = htole32(0xcc00aaaa);
+       d.basic.bt3_lookup_table[ 7] = htole32(0x0000aaaa);
+       d.basic.bt3_lookup_table[ 8] = htole32(0xc0004000);
+       d.basic.bt3_lookup_table[ 9] = htole32(0x00004000);
+       d.basic.bt3_lookup_table[10] = htole32(0xf0005000);
+       d.basic.bt3_lookup_table[11] = htole32(0xf0005000);
+       d.basic.reduce_txpower = 0; /* as not implemented */
+       d.basic.valid = IWN_BT_ALL_VALID_MASK;
+       d.prio_boost = IWN_BT_PRIO_BOOST_DEF;
+       d.tx_prio_boost = 0;
+       d.rx_prio_boost = 0;
+
+       DPRINTF(("configuring advanced bluetooth coexistence v1\n"));
+       error = iwn_cmd(sc, IWN_CMD_BT_COEX, &d, sizeof d, 0);
+       if (error != 0) {
+               aprint_error_dev(sc->sc_dev,
+                       "could not configure advanced bluetooth coexistence\n");
+               return error;
+       }
+
+       error = iwn_config_bt_coex_prio_table(sc);
+       if (error != 0) {
+               aprint_error_dev(sc->sc_dev,
+                       "could not configure send BT priority table\n");
+               return error;
+       }
+
+       return error;
+}
+
+static int
 iwn_config(struct iwn_softc *sc)
 {
        struct iwn_ops *ops = &sc->ops;
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = ic->ic_ifp;
-       struct iwn_bluetooth bluetooth;
        uint32_t txmask;
        uint16_t rxchain;
        int error;
 
+       error = ops->config_bt_coex(sc);
+       if (error != 0) {
+               aprint_error_dev(sc->sc_dev,
+                       "could not configure bluetooth coexistence\n");
+               return error;
+       }
+
        if (sc->hw_type == IWN_HW_REV_TYPE_6050 ||
            sc->hw_type == IWN_HW_REV_TYPE_6005) {
                /* Configure runtime DC calibration. */
@@ -4141,19 +4252,6 @@
                }
        }
 
-       /* Configure bluetooth coexistence. */
-       memset(&bluetooth, 0, sizeof bluetooth);
-       bluetooth.flags = IWN_BT_COEX_CHAN_ANN | IWN_BT_COEX_BT_PRIO;
-       bluetooth.lead_time = IWN_BT_LEAD_TIME_DEF;
-       bluetooth.max_kill = IWN_BT_MAX_KILL_DEF;
-       DPRINTF(("configuring bluetooth coexistence\n"));
-       error = iwn_cmd(sc, IWN_CMD_BT_COEX, &bluetooth, sizeof bluetooth, 0);
-       if (error != 0) {
-               aprint_error_dev(sc->sc_dev,
-                   "could not configure bluetooth coexistence\n");
-               return error;
-       }
-
        /* Set mode, channel, RX filter and enable RX. */
        memset(&sc->rxon, 0, sizeof (struct iwn_rxon));
        IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
@@ -6110,3 +6208,39 @@
        }
 }
 
+#ifdef notyetMODULE
+
+MODULE(MODULE_CLASS_DRIVER, if_iwn, "pci");
+
+#ifdef _MODULE
+#include "ioconf.c"
+#endif
+
+static int
+if_iwn_modcmd(modcmd_t cmd, void *data)
+{
+       int error = 0;
+
+       switch (cmd) {
+       case MODULE_CMD_INIT:
+#ifdef _MODULE
+               error = config_init_component(cfdriver_ioconf_if_iwn,
+                       cfattach_ioconf_if_iwn, cfdata_ioconf_if_iwn);
+#endif
+               return error;
+       case MODULE_CMD_FINI:
+#ifdef _MODULE
+               error = config_fini_component(cfdriver_ioconf_if_iwn,
+                       cfattach_ioconf_if_iwn, cfdata_ioconf_if_iwn);
+#endif
+               return error;
+       case MODULE_CMD_AUTOUNLOAD:
+#ifdef _MODULE
+               /* XXX This is not optional! */
+#endif
+               return error;
+       default:
+               return ENOTTY;
+       }
+}
+#endif
Index: if_iwnreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_iwnreg.h,v
retrieving revision 1.10
diff -u -r1.10 if_iwnreg.h
--- if_iwnreg.h 8 Oct 2011 09:15:08 -0000       1.10
+++ if_iwnreg.h 4 Jan 2013 13:09:31 -0000
@@ -18,6 +18,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <sys/endian.h>
+
 /* XXX Added for NetBSD */
 #define EDCA_NUM_AC            4
 #define IEEE80211_TKIP_MICLEN  8
@@ -210,6 +212,7 @@
 #define IWN_HW_REV_TYPE_6000   7
 #define IWN_HW_REV_TYPE_6050   8
 #define IWN_HW_REV_TYPE_6005   11
+/* Types 6030 and 6035 also return 11 */
 
 /* Possible flags for register IWN_GIO_CHICKEN. */
 #define IWN_GIO_CHICKEN_L1A_NO_L0S_RX  (1 << 23)
@@ -424,8 +427,8 @@
 #define IWN_CMD_TIMING                  20
 #define IWN_CMD_ADD_NODE                24
 #define IWN_CMD_TX_DATA                         28
-#define IWN_CMD_LINK_QUALITY            78
 #define IWN_CMD_SET_LED                         72
+#define IWN_CMD_LINK_QUALITY            78
 #define IWN5000_CMD_WIMAX_COEX          90
 #define IWN5000_CMD_CALIB_CONFIG       101
 #define IWN_CMD_SET_POWER_MODE         119
@@ -438,6 +441,7 @@
 #define IWN_CMD_SET_CRITICAL_TEMP      164
 #define IWN_CMD_SET_SENSITIVITY                168
 #define IWN_CMD_PHY_CALIB              176
+#define IWN_CMD_BT_COEX_PRIO_TABLE     204
 
        uint8_t flags;
        uint8_t idx;
@@ -834,22 +838,71 @@
        uint8_t reserved;
 } __packed;
 
-/* Structure for command IWN_CMD_BLUETOOTH. */
+/* Structure for command IWN_CMD_BT_COEX. */
 struct iwn_bluetooth {
        uint8_t         flags;
 #define IWN_BT_COEX_CHAN_ANN   (1 << 0)
 #define IWN_BT_COEX_BT_PRIO    (1 << 1)
 #define IWN_BT_COEX_2_WIRE     (1 << 2)
-
+#define IWN_BT_COEX_ENABLE     IWN_BT_COEX_CHAN_ANN | IWN_BT_COEX_BT_PRIO
        uint8_t         lead_time;
 #define IWN_BT_LEAD_TIME_DEF   30
-
        uint8_t         max_kill;
 #define IWN_BT_MAX_KILL_DEF    5
-
+       uint8_t         bt3_timer_t7_value;
+#define IWN_BT_BT3_T7_DEF      1
+       uint32_t        kill_ack_mask;
+#define IWN_BT_KILL_ACK_MASK_DEF       htole32(0xffff0000)
+       uint32_t        kill_cts_mask;
+#define IWN_BT_KILL_CTS_MASK_DEF       htole32(0xffff0000)
+} __packed;
+
+struct iwn_bt_basic {
+       struct iwn_bluetooth bt;
+       uint8_t         bt3_prio_sample_time;
+#define IWN_BT_BT3_PRIO_SAMPLE_DEF     2
+       uint8_t         bt3_timer_t2_value;
+#define IWN_BT_BT3_T2_DEF      12
+       uint16_t        bt4_reaction_time; /* unused */
+       uint32_t        bt3_lookup_table[12];
+       uint8_t         reduce_txpower; /* bit 0 */
+       uint8_t         reserved;
+       uint16_t        valid;
+#define IWN_BT_VALID_ENABLE_FLAGS      htole16(1 << 0)
+#define IWN_BT_VALID_BOOST             htole16(1 << 1)
+#define IWN_BT_VALID_MAX_KILL          htole16(1 << 2)
+#define IWN_BT_VALID_3W_TIMERS         htole16(1 << 3)
+#define IWN_BT_VALID_KILL_ACK_MASK     htole16(1 << 4)
+#define IWN_BT_VALID_KILL_CTS_MASK     htole16(1 << 5)
+#define IWN_BT_VALID_REDUCED_TX_PWR    htole16(1 << 6)
+#define IWN_BT_VALID_3W_LUT            htole16(1 << 7)
+#define IWN_BT_ALL_VALID_MASK          (IWN_BT_VALID_ENABLE_FLAGS | \
+                                        IWN_BT_VALID_BOOST | \
+                                        IWN_BT_VALID_MAX_KILL | \
+                                        IWN_BT_VALID_3W_TIMERS | \
+                                        IWN_BT_VALID_KILL_ACK_MASK | \
+                                        IWN_BT_VALID_KILL_CTS_MASK | \
+                                        IWN_BT_VALID_REDUCED_TX_PWR | \
+                                        IWN_BT_VALID_3W_LUT)
+} __packed;
+
+struct iwn_bt_adv1 {
+       struct iwn_bt_basic basic;
+       uint8_t         prio_boost;
+#define IWN_BT_PRIO_BOOST_DEF  0xf0
+       /* set IWLAGN_BT_VALID_BOOST to "1" in "valid" bitmask for */
+       uint8_t         tx_prio_boost;
+       uint16_t        rx_prio_boost;
+} __packed;
+
+struct iwn_bt_adv2 {
+       struct iwn_bt_basic basic;
+       uint32_t        prio_boost;
+#define IWN_BT_PRIO_BOOST_DEF32        0xf0f0f0
        uint8_t         reserved;
-       uint32_t        kill_ack;
-       uint32_t        kill_cts;
+       /* set IWLAGN_BT_VALID_BOOST to "1" in "valid" bitmask for */
+       uint8_t         tx_prio_boost;
+       uint16_t        rx_prio_boost;
 } __packed;
 
 /* Structure for command IWN_CMD_SET_CRITICAL_TEMP. */
Index: if_iwnvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_iwnvar.h,v
retrieving revision 1.13
diff -u -r1.13 if_iwnvar.h
--- if_iwnvar.h 15 May 2011 13:56:20 -0000      1.13
+++ if_iwnvar.h 4 Jan 2013 13:09:31 -0000
@@ -179,6 +179,7 @@
        void            (*read_eeprom)(struct iwn_softc *);
        int             (*post_alive)(struct iwn_softc *);
        int             (*nic_config)(struct iwn_softc *);
+       int             (*config_bt_coex)(struct iwn_softc *);
        void            (*update_sched)(struct iwn_softc *, int, int, uint8_t,
                            uint16_t);
        int             (*get_temperature)(struct iwn_softc *);


Home | Main Index | Thread Index | Old Index