On 02/08/14 23:34, Mark Kettenis wrote: >> >> Hi tech@, >> >> the diff below adds support for the Intel Centrino Wireless-N 2230 >> card found in my Lenovo E330 to iwn(4). >> >> iwn0 at pci2 dev 0 function 0 "Intel Centrino Wireless-N 2230" rev 0xc4: >> msi, MIMO 2T2R, BGN, address 60:6c:66:3b:ea:39 >> >> This is the 0x0888 version. >> >> I've got most changes from >> https://github.com/seanbruno/freebsd-iwl/commit/53e6056c2df7355650abab77068943ac097a70c6#diff-7a5322b995ac8545b4f5d9096c3b5a5aR5445 >> >> which (i think) mostly landed in freebsd as part of >> http://svnweb.freebsd.org/base?view=revision&revision=258035 >> >> This is the only iwn(4) device i have, so hopefully i did not broke >> another supported device. >> Any feedback and tests are welcome. >> >> Regards, >> Fabian Raetz > > Hi Fabian, > > Finally had some time to look at this. I cleaned your diff up a bit. > Also noticed that the sensitivy limits didn't match the Linux driver I > was looking at. Does the diff below still result in working hardware > for you? > > Thanks, > > Mark > >
Hi, With your patch the network card is detected : iwn0 at pci3 dev 0 function 0 "Intel Centrino Wireless-N 2030" rev 0xc4: msi, MIMO 2T2R, BGN, address 68:5d:43:20:8b:68 But I have the following message : iwn0: fatal firmware error firmware error log: error type = "UNKNOWN" (0x00001038) program counter = 0x0002A698 source line = 0x00001014 error data = 0x0000000000001014 branch link = 0x0002A5B40002A5B4 interrupt link = 0x0000EC7A00000000 time = 969333536 driver status: tx ring 0: qid=0 cur=6 queued=0 tx ring 1: qid=1 cur=0 queued=0 tx ring 2: qid=2 cur=0 queued=0 tx ring 3: qid=3 cur=0 queued=0 tx ring 4: qid=4 cur=36 queued=0 tx ring 5: qid=5 cur=0 queued=0 tx ring 6: qid=6 cur=0 queued=0 tx ring 7: qid=7 cur=0 queued=0 tx ring 8: qid=8 cur=0 queued=0 tx ring 9: qid=9 cur=0 queued=0 tx ring 10: qid=10 cur=0 queued=0 tx ring 11: qid=11 cur=0 queued=0 tx ring 12: qid=12 cur=0 queued=0 tx ring 13: qid=13 cur=0 queued=0 tx ring 14: qid=14 cur=0 queued=0 tx ring 15: qid=15 cur=0 queued=0 tx ring 16: qid=16 cur=0 queued=0 tx ring 17: qid=17 cur=0 queued=0 tx ring 18: qid=18 cur=0 queued=0 tx ring 19: qid=19 cur=0 queued=0 rx ring: cur=22 802.11 state 4 I have not the same issue with the patch from Fabian. Cheers, benoit > 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 8 Feb 2014 22:31:37 -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 *); > @@ -244,6 +246,7 @@ int iwn5000_send_calibration(struct iwn > int iwn5000_send_wimax_coex(struct iwn_softc *); > int iwn5000_crystal_calib(struct iwn_softc *); > int iwn5000_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: > @@ -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,14 +4276,21 @@ 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); > 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); > + return error; > + } > } > > if (sc->hw_type == IWN_HW_REV_TYPE_6050 || > @@ -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_temp != 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). > @@ -5681,6 +5754,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 8 Feb 2014 22:31:37 -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; > @@ -972,6 +993,8 @@ struct iwn_phy_calib { > #define IWN5000_PHY_CALIB_RESET_NOISE_GAIN 18 > #define IWN5000_PHY_CALIB_NOISE_GAIN 19 > > +#define IWN2000_PHY_CALIB_TEMP_OFFSET 18 > + > uint8_t group; > uint8_t ngroups; > uint8_t isvalid; > @@ -998,6 +1021,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; > @@ -1411,6 +1445,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) > @@ -1718,6 +1753,18 @@ static const struct iwn_sensitivity_limi > 97, > 100 > }; > + > +static const struct iwn_sensitivity_limits iwn2000_sensitivity_limits = { > + 105, 110, > + 192, 232, > + 80, 145, > + 128, 232, > + 125, 175, > + 160, 310, > + 97, > + 97, > + 100 > + }; > > /* Map TID to TX scheduler's FIFO. */ > static const uint8_t iwn_tid2fifo[] = { > 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 8 Feb 2014 22:31:37 -0000 > @@ -275,6 +275,7 @@ 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]; >