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];
>