On 02/09/14 12:30, Mark Kettenis wrote:
>> Date: Sun, 09 Feb 2014 10:34:04 +0100
>> From: Benoit Lecocq <b...@arcane-labs.net>
>>
>> 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.
> 
> Does the interface work despite this message?
> 
> Does the following diff work better?
> 

Yes the interface work despite the message.

Same messages with the new diff :

iwn0: fatal firmware error
firmware error log:
  error type      = "UNKNOWN" (0x00001967)
  program counter = 0x000099C4
  source line     = 0x0000009F
  error data      = 0x000000FF00000013
  branch link     = 0x000099BA000099BA
  interrupt link  = 0x0000EC7A00000000
  time            = 254992438
driver status:
  tx ring  0: qid=0  cur=70  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


> 
> 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 11:18:29 -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_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).
> @@ -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       9 Feb 2014 11:18:29 -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,
> +     128, 232,               /* Linux has 192, 232 */
> +      80, 145,
> +     128, 232,
> +     125, 175,
> +     160, 310,
> +      97,
> +      97,
> +     110                     /* Linux has 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       9 Feb 2014 11:18:29 -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];
> 

Reply via email to