> Date: Sun, 9 Feb 2014 14:23:18 +0100 > From: Fabian Raetz <fabian.ra...@gmail.com> > > > > Hmm, my cleanup was based on the version you send out on December > > 31st. Can you send me the latest version of your diff? > > > > On Tue, Jan 07, 2014 at 12:08:02PM +0100, Martin Pieuchot wrote: > > On 03/01/14(Fri) 14:24, Fabian Raetz wrote: > > > Hi tech@, > > > > > > here is an updated patch. > > > > > > it seems like Intel Centrino Wireless-N 2030 and > > > Intel Centrino Wireless-N 2230 have the same pciids... > > > > > > this makes patch apply again with newest pcidevs changes. > > > > Please also make sure to use tab and not space when appropriate ;) You > > can check style(9) if in doubt ! > > > ups :) > attached is a diff > - which follows style(9) (hopefully) and > - fixes a firmware error by handling IWN_FW_TLV_ENH_SENS and > IWN_FW_TLV_PHY_CALIB in iwn_read_firmware_tlv(). > > @mike, only style changes since the last patch i send you.
Thanks. I incorporated the changes in my cleaned up version. The change does affect other hardware types now, but I've tested this on a couple of systems: iwn0 at pci3 dev 0 function 0 "Intel WiFi Link 5300" rev 0x00: msi, MIMO 3T3R, MoW iwn0 at pci3 dev 0 function 0 "Intel Centrino Ultimate-N 6300" rev 0x35: msi, MIMO 3T3R, MoW iwn0 at pci2 dev 0 function 0 "Intel Centrino Advanced-N 6205" rev 0x34: msi, MIMO 2T2R, MoW So if this one works for you and Benoit, I'll go ahead and commit this. Index: if_iwn.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v retrieving revision 1.127 diff -u -p -r1.127 if_iwn.c --- if_iwn.c 6 Dec 2013 21:03:04 -0000 1.127 +++ if_iwn.c 9 Feb 2014 20:25:41 -0000 @@ -94,6 +94,8 @@ static const struct pci_matchid iwn_devi { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_130_2 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6235_1 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6235_2 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_2030_1 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_2030_2 }, }; int iwn_match(struct device *, void *, void *); @@ -243,7 +245,8 @@ int iwn5000_query_calibration(struct iw int iwn5000_send_calibration(struct iwn_softc *); int iwn5000_send_wimax_coex(struct iwn_softc *); int iwn5000_crystal_calib(struct iwn_softc *); -int iwn5000_temp_offset_calib(struct iwn_softc *); +int iwn6000_temp_offset_calib(struct iwn_softc *); +int iwn2000_temp_offset_calib(struct iwn_softc *); int iwn4965_post_alive(struct iwn_softc *); int iwn5000_post_alive(struct iwn_softc *); int iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *, @@ -651,6 +654,11 @@ iwn5000_attach(struct iwn_softc *sc, pci } else sc->fwname = "iwn-6005"; break; + case IWN_HW_REV_TYPE_2030: + sc->limits = &iwn2000_sensitivity_limits; + sc->fwname = "iwn-2030"; + sc->sc_flags |= IWN_FLAG_ADV_BT_COEX; + break; default: printf(": adapter type %d not supported\n", sc->hw_type); return ENOTSUP; @@ -1529,6 +1537,14 @@ iwn5000_read_eeprom(struct iwn_softc *sc hdr.version, hdr.pa_type, letoh16(hdr.volt))); sc->calib_ver = hdr.version; + if (sc->hw_type == IWN_HW_REV_TYPE_2030) { + sc->eeprom_voltage = letoh16(hdr.volt); + iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2); + sc->eeprom_temp = letoh16(val); + iwn_read_prom_data(sc, base + IWN2000_EEPROM_RAWTEMP, &val, 2); + sc->eeprom_rawtemp = letoh16(val); + } + if (sc->hw_type == IWN_HW_REV_TYPE_5150) { /* Compute temperature offset. */ iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2); @@ -2095,7 +2111,8 @@ iwn5000_rx_calib_results(struct iwn_soft switch (calib->code) { case IWN5000_PHY_CALIB_DC: - if (sc->hw_type == IWN_HW_REV_TYPE_5150) + if (sc->hw_type == IWN_HW_REV_TYPE_5150 || + sc->hw_type == IWN_HW_REV_TYPE_2030) idx = 0; break; case IWN5000_PHY_CALIB_LO: @@ -3822,7 +3839,7 @@ iwn5000_init_gains(struct iwn_softc *sc) struct iwn_phy_calib cmd; memset(&cmd, 0, sizeof cmd); - cmd.code = IWN5000_PHY_CALIB_RESET_NOISE_GAIN; + cmd.code = sc->reset_noise_gain; cmd.ngroups = 1; cmd.isvalid = 1; DPRINTF(("setting initial differential gains\n")); @@ -3872,7 +3889,7 @@ iwn5000_set_gains(struct iwn_softc *sc) div = (sc->hw_type == IWN_HW_REV_TYPE_6050) ? 20 : 30; memset(&cmd, 0, sizeof cmd); - cmd.code = IWN5000_PHY_CALIB_NOISE_GAIN; + cmd.code = sc->noise_gain; cmd.ngroups = 1; cmd.isvalid = 1; /* Get first available RX antenna as referential. */ @@ -4160,29 +4177,55 @@ iwn_send_advanced_btcoex(struct iwn_soft 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); + if (sc->hw_type == IWN_HW_REV_TYPE_2030) { + struct iwn2000_btcoex_config btconfig; + + memset(&btconfig, 0, sizeof btconfig); + btconfig.flags = IWN_BT_COEX6000_CHAN_INHIBITION | + (IWN_BT_COEX6000_MODE_3W << IWN_BT_COEX6000_MODE_SHIFT) | + IWN_BT_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 = htole32(0xf0); + DPRINTF(("configuring advanced bluetooth coexistence\n")); + error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, + sizeof(btconfig), 1); + if (error != 0) + return (error); + } else { + struct iwn6000_btcoex_config btconfig; + + memset(&btconfig, 0, sizeof btconfig); + btconfig.flags = IWN_BT_COEX6000_CHAN_INHIBITION | + (IWN_BT_COEX6000_MODE_3W << IWN_BT_COEX6000_MODE_SHIFT) | + IWN_BT_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; @@ -4233,9 +4276,16 @@ iwn_config(struct iwn_softc *sc) uint16_t rxchain; int error; + /* Set radio temperature sensor offset. */ if (sc->hw_type == IWN_HW_REV_TYPE_6005) { - /* Set radio temperature sensor offset. */ - error = iwn5000_temp_offset_calib(sc); + error = iwn6000_temp_offset_calib(sc); + if (error != 0) { + printf("%s: could not set temperature offset\n", + sc->sc_dev.dv_xname); + return error; + } + } else if (sc->hw_type == IWN_HW_REV_TYPE_2030) { + error = iwn2000_temp_offset_calib(sc); if (error != 0) { printf("%s: could not set temperature offset\n", sc->sc_dev.dv_xname); @@ -4989,12 +5039,12 @@ iwn5000_crystal_calib(struct iwn_softc * } int -iwn5000_temp_offset_calib(struct iwn_softc *sc) +iwn6000_temp_offset_calib(struct iwn_softc *sc) { - struct iwn5000_phy_calib_temp_offset cmd; + struct iwn6000_phy_calib_temp_offset cmd; memset(&cmd, 0, sizeof cmd); - cmd.code = IWN5000_PHY_CALIB_TEMP_OFFSET; + cmd.code = IWN6000_PHY_CALIB_TEMP_OFFSET; cmd.ngroups = 1; cmd.isvalid = 1; if (sc->eeprom_temp != 0) @@ -5005,6 +5055,29 @@ iwn5000_temp_offset_calib(struct iwn_sof return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0); } +int +iwn2000_temp_offset_calib(struct iwn_softc *sc) +{ + struct iwn2000_phy_calib_temp_offset cmd; + + memset(&cmd, 0, sizeof cmd); + cmd.code = IWN2000_PHY_CALIB_TEMP_OFFSET; + cmd.ngroups = 1; + cmd.isvalid = 1; + if (sc->eeprom_rawtemp != 0) { + cmd.offset_low = htole16(sc->eeprom_rawtemp); + cmd.offset_high = htole16(sc->eeprom_temp); + } else { + cmd.offset_low = htole16(IWN_DEFAULT_TEMP_OFFSET); + cmd.offset_high = htole16(IWN_DEFAULT_TEMP_OFFSET); + } + cmd.burnt_voltage_ref = htole16(sc->eeprom_voltage); + DPRINTF(("setting radio sensor offset to %d:%d, voltage to %d\n", + letoh16(cmd.offset_low), letoh16(cmd.offset_high), + letoh16(cmd.burnt_voltage_ref))); + return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0); +} + /* * This function is called after the runtime firmware notifies us of its * readiness (called in a process context). @@ -5458,6 +5531,27 @@ iwn_read_firmware_tlv(struct iwn_softc * fw->boot.text = ptr; fw->boot.textsz = len; break; + case IWN_FW_TLV_ENH_SENS: + if (len != 0) { + printf("%s: TLV type %d has invalid size %u\n", + sc->sc_dev.dv_xname, letoh16(tlv->type), + len); + goto next; + } + sc->sc_flags |= IWN_FLAG_ENH_SENS; + break; + case IWN_FW_TLV_PHY_CALIB: + if (len != sizeof(uint32_t)) { + printf("%s: TLV type %d has invalid size %u\n", + sc->sc_dev.dv_xname, letoh16(tlv->type), + len); + goto next; + } + if (letoh32(*ptr) <= IWN5000_PHY_CALIB_MAX) { + sc->reset_noise_gain = letoh32(*ptr); + sc->noise_gain = letoh32(*ptr) + 1; + } + break; default: DPRINTF(("TLV type %d not handled\n", letoh16(tlv->type))); @@ -5475,6 +5569,14 @@ iwn_read_firmware(struct iwn_softc *sc) struct iwn_fw_info *fw = &sc->fw; int error; + /* + * Some PHY calibration commands are firmware-dependent; these + * are the default values that will be overridden if + * necessary. + */ + sc->reset_noise_gain = IWN5000_PHY_CALIB_RESET_NOISE_GAIN; + sc->noise_gain = IWN5000_PHY_CALIB_NOISE_GAIN; + memset(fw, 0, sizeof (*fw)); /* Read firmware image from filesystem. */ @@ -5681,6 +5783,8 @@ iwn5000_nic_config(struct iwn_softc *sc) } if (sc->hw_type == IWN_HW_REV_TYPE_6005) IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_6050_1X2); + if (sc->hw_type == IWN_HW_REV_TYPE_2030) + IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_IQ_INVERT); return 0; } Index: if_iwnreg.h =================================================================== RCS file: /cvs/src/sys/dev/pci/if_iwnreg.h,v retrieving revision 1.45 diff -u -p -r1.45 if_iwnreg.h --- if_iwnreg.h 26 Nov 2013 20:33:17 -0000 1.45 +++ if_iwnreg.h 9 Feb 2014 20:25:41 -0000 @@ -205,6 +205,7 @@ #define IWN_HW_REV_TYPE_6000 7 #define IWN_HW_REV_TYPE_6050 8 #define IWN_HW_REV_TYPE_6005 11 +#define IWN_HW_REV_TYPE_2030 12 /* Possible flags for register IWN_GIO_CHICKEN. */ #define IWN_GIO_CHICKEN_L1A_NO_L0S_RX (1 << 23) @@ -219,6 +220,7 @@ #define IWN_GP_DRIVER_RADIO_2X2_IPA (2 << 0) #define IWN_GP_DRIVER_CALIB_VER6 (1 << 2) #define IWN_GP_DRIVER_6050_1X2 (1 << 3) +#define IWN_GP_DRIVER_RADIO_IQ_INVERT (1 << 7) /* Possible flags for register IWN_UCODE_GP1_CLR. */ #define IWN_UCODE_GP1_RFKILL (1 << 1) @@ -852,15 +854,15 @@ struct iwn_bluetooth { 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) +#define IWN_BT_COEX6000_CHAN_INHIBITION 1 +#define IWN_BT_COEX6000_MODE_MASK ((1 << 3) | (1 << 4) | (1 << 5)) +#define IWN_BT_COEX6000_MODE_SHIFT 3 +#define IWN_BT_COEX6000_MODE_DISABLED 0 +#define IWN_BT_COEX6000_MODE_LEGACY_2W 1 +#define IWN_BT_COEX6000_MODE_3W 2 +#define IWN_BT_COEX6000_MODE_4W 3 +#define IWN_BT_UCODE_DEFAULT (1<<6) +#define IWN_BT_SYNC_2_BT_DISABLE (1<<7) uint8_t lead_time; uint8_t max_kill; @@ -878,6 +880,25 @@ struct iwn6000_btcoex_config { uint16_t rx_prio_boost; } __packed; +struct iwn2000_btcoex_config { + uint8_t flags; /* same as in iwn6000_btcoex_config */ + 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; + uint32_t prio_boost; + uint8_t reserved; + 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; @@ -967,11 +988,14 @@ struct iwn_phy_calib { #define IWN5000_PHY_CALIB_CRYSTAL 15 #define IWN5000_PHY_CALIB_BASE_BAND 16 #define IWN5000_PHY_CALIB_TX_IQ_PERIODIC 17 -#define IWN5000_PHY_CALIB_TEMP_OFFSET 18 - #define IWN5000_PHY_CALIB_RESET_NOISE_GAIN 18 #define IWN5000_PHY_CALIB_NOISE_GAIN 19 +#define IWN6000_PHY_CALIB_TEMP_OFFSET 18 +#define IWN2000_PHY_CALIB_TEMP_OFFSET 18 + +#define IWN5000_PHY_CALIB_MAX 253 + uint8_t group; uint8_t ngroups; uint8_t isvalid; @@ -987,7 +1011,7 @@ struct iwn5000_phy_calib_crystal { uint8_t reserved[2]; } __packed; -struct iwn5000_phy_calib_temp_offset { +struct iwn6000_phy_calib_temp_offset { uint8_t code; uint8_t group; uint8_t ngroups; @@ -998,6 +1022,17 @@ struct iwn5000_phy_calib_temp_offset { uint16_t reserved; } __packed; +struct iwn2000_phy_calib_temp_offset { + uint8_t code; + uint8_t group; + uint8_t ngroups; + uint8_t isvalid; + int16_t offset_high; + int16_t offset_low; + int16_t burnt_voltage_ref; + int16_t reserved; +} __packed; + struct iwn_phy_calib_gain { uint8_t code; uint8_t group; @@ -1366,6 +1401,8 @@ struct iwn_fw_tlv { #define IWN_FW_TLV_INIT_DATA 4 #define IWN_FW_TLV_BOOT_TEXT 5 #define IWN_FW_TLV_PBREQ_MAXLEN 6 +#define IWN_FW_TLV_ENH_SENS 14 +#define IWN_FW_TLV_PHY_CALIB 15 uint16_t alt; uint32_t len; @@ -1411,6 +1448,7 @@ struct iwn_fw_tlv { #define IWN5000_EEPROM_CRYSTAL 0x128 #define IWN5000_EEPROM_TEMP 0x12a #define IWN5000_EEPROM_VOLT 0x12b +#define IWN2000_EEPROM_RAWTEMP 0x12b /* Possible flags for IWN_EEPROM_SKU_CAP. */ #define IWN_EEPROM_SKU_CAP_11N (1 << 6) @@ -1708,6 +1746,18 @@ static const struct iwn_sensitivity_limi }; static const struct iwn_sensitivity_limits iwn6000_sensitivity_limits = { + 105, 110, + 192, 232, + 80, 145, + 128, 232, + 125, 175, + 160, 310, + 97, + 97, + 100 +}; + +static const struct iwn_sensitivity_limits iwn2000_sensitivity_limits = { 105, 110, 192, 232, 80, 145, Index: if_iwnvar.h =================================================================== RCS file: /cvs/src/sys/dev/pci/if_iwnvar.h,v retrieving revision 1.26 diff -u -p -r1.26 if_iwnvar.h --- if_iwnvar.h 30 Nov 2013 19:41:21 -0000 1.26 +++ if_iwnvar.h 9 Feb 2014 20:25:41 -0000 @@ -275,10 +275,14 @@ struct iwn_softc { uint32_t eeprom_crystal; int16_t eeprom_temp; int16_t eeprom_voltage; + int16_t eeprom_rawtemp; int8_t maxpwr2GHz; int8_t maxpwr5GHz; int8_t maxpwr[IEEE80211_CHAN_MAX]; int8_t enh_maxpwr[35]; + + uint8_t reset_noise_gain; + uint8_t noise_gain; int32_t temp_off; uint32_t int_mask;