svn commit: r313312 - head/sys/dev/iwm

Adrian Chadd adrian at FreeBSD.org
Mon Feb 6 03:29:51 UTC 2017


Author: adrian
Date: Mon Feb  6 03:29:50 2017
New Revision: 313312
URL: https://svnweb.freebsd.org/changeset/base/313312

Log:
  [iwm] Use chipset configuration structs like iwlwifi does.
  
  * This makes it a bit easier to factor out common parts for e.g. the
    7000 chipset family.
  
  * Add iwm7265d config, and recognize the 7265D chipset variant via the
    hardware revision.
  
  Tested:
  
  * 7260, STA mode (2ghz)
  
  Obtained from:	Dragonflybsd commit cc8d6ccf5583fd45964f3bde9b057ee4f834c0e0

Modified:
  head/sys/dev/iwm/if_iwm.c
  head/sys/dev/iwm/if_iwm_pcie_trans.c
  head/sys/dev/iwm/if_iwmvar.h

Modified: head/sys/dev/iwm/if_iwm.c
==============================================================================
--- head/sys/dev/iwm/if_iwm.c	Mon Feb  6 03:06:11 2017	(r313311)
+++ head/sys/dev/iwm/if_iwm.c	Mon Feb  6 03:29:50 2017	(r313312)
@@ -165,6 +165,67 @@ __FBSDID("$FreeBSD$");
 #include <dev/iwm/if_iwm_pcie_trans.h>
 #include <dev/iwm/if_iwm_led.h>
 
+#define IWM_NVM_HW_SECTION_NUM_FAMILY_7000	0
+#define IWM_NVM_HW_SECTION_NUM_FAMILY_8000	10
+
+/* lower blocks contain EEPROM image and calibration data */
+#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000	(16 * 512 * sizeof(uint16_t)) /* 16 KB */
+#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_8000	(32 * 512 * sizeof(uint16_t)) /* 32 KB */
+
+#define IWM7260_FW	"iwm7260fw"
+#define IWM3160_FW	"iwm3160fw"
+#define IWM7265_FW	"iwm7265fw"
+#define IWM7265D_FW	"iwm7265Dfw"
+#define IWM8000_FW	"iwm8000Cfw"
+
+#define IWM_DEVICE_7000_COMMON						\
+	.device_family = IWM_DEVICE_FAMILY_7000,			\
+	.eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000,		\
+	.nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_7000
+
+const struct iwm_cfg iwm7260_cfg = {
+	.fw_name = IWM7260_FW,
+	IWM_DEVICE_7000_COMMON,
+	.host_interrupt_operation_mode = 1,
+};
+
+const struct iwm_cfg iwm3160_cfg = {
+	.fw_name = IWM3160_FW,
+	IWM_DEVICE_7000_COMMON,
+	.host_interrupt_operation_mode = 1,
+};
+
+const struct iwm_cfg iwm3165_cfg = {
+	/* XXX IWM7265D_FW doesn't seem to work properly yet */
+	.fw_name = IWM7265_FW,
+	IWM_DEVICE_7000_COMMON,
+	.host_interrupt_operation_mode = 0,
+};
+
+const struct iwm_cfg iwm7265_cfg = {
+	.fw_name = IWM7265_FW,
+	IWM_DEVICE_7000_COMMON,
+	.host_interrupt_operation_mode = 0,
+};
+
+const struct iwm_cfg iwm7265d_cfg = {
+	/* XXX IWM7265D_FW doesn't seem to work properly yet */
+	.fw_name = IWM7265_FW,
+	IWM_DEVICE_7000_COMMON,
+	.host_interrupt_operation_mode = 0,
+};
+
+#define IWM_DEVICE_8000_COMMON						\
+	.device_family = IWM_DEVICE_FAMILY_8000,			\
+	.eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_8000,		\
+	.nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_8000
+
+const struct iwm_cfg iwm8260_cfg = {
+	.fw_name = IWM8000_FW,
+	IWM_DEVICE_8000_COMMON,
+	.host_interrupt_operation_mode = 0,
+};
+
 const uint8_t iwm_nvm_channels[] = {
 	/* 2.4 GHz */
 	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
@@ -512,12 +573,12 @@ iwm_read_firmware(struct iwm_softc *sc, 
 	 * fw_fp will be set.
 	 */
 	IWM_UNLOCK(sc);
-	fwp = firmware_get(sc->sc_fwname);
+	fwp = firmware_get(sc->cfg->fw_name);
 	IWM_LOCK(sc);
 	if (fwp == NULL) {
 		device_printf(sc->sc_dev,
 		    "could not read firmware %s (error %d)\n",
-		    sc->sc_fwname, error);
+		    sc->cfg->fw_name, error);
 		goto out;
 	}
 	fw->fw_fp = fwp;
@@ -536,7 +597,7 @@ iwm_read_firmware(struct iwm_softc *sc, 
 	if (*(const uint32_t *)fw->fw_fp->data != 0
 	    || le32toh(uhdr->magic) != IWM_TLV_UCODE_MAGIC) {
 		device_printf(sc->sc_dev, "invalid firmware %s\n",
-		    sc->sc_fwname);
+		    sc->cfg->fw_name);
 		error = EINVAL;
 		goto out;
 	}
@@ -1370,7 +1431,7 @@ iwm_mvm_nic_config(struct iwm_softc *sc)
 	 * (PCIe power is lost before PERST# is asserted), causing ME FW
 	 * to lose ownership and not being able to obtain it back.
 	 */
-	if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
+	if (sc->cfg->device_family == IWM_DEVICE_FAMILY_7000) {
 		iwm_set_bits_mask_prph(sc, IWM_APMG_PS_CTRL_REG,
 		    IWM_APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
 		    ~IWM_APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
@@ -1416,7 +1477,7 @@ iwm_nic_rx_init(struct iwm_softc *sc)
 	IWM_WRITE_1(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_TIMEOUT_DEF);
 
 	/* W/A for interrupt coalescing bug in 7260 and 3160 */
-	if (sc->host_interrupt_operation_mode)
+	if (sc->cfg->host_interrupt_operation_mode)
 		IWM_SETBITS(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_OPER_MODE);
 
 	/*
@@ -1473,7 +1534,7 @@ iwm_nic_init(struct iwm_softc *sc)
 	int error;
 
 	iwm_apm_init(sc);
-	if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)
+	if (sc->cfg->device_family == IWM_DEVICE_FAMILY_7000)
 		iwm_set_pwr(sc);
 
 	iwm_mvm_nic_config(sc);
@@ -1633,7 +1694,7 @@ iwm_post_alive(struct iwm_softc *sc)
 	    IWM_FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
 
 	/* Enable L1-Active */
-	if (sc->sc_device_family != IWM_DEVICE_FAMILY_8000) {
+	if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) {
 		iwm_clear_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,
 		    IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 	}
@@ -1649,9 +1710,6 @@ iwm_post_alive(struct iwm_softc *sc)
  * iwlwifi/mvm/nvm.c
  */
 
-#define IWM_NVM_HW_SECTION_NUM_FAMILY_7000	0
-#define IWM_NVM_HW_SECTION_NUM_FAMILY_8000	10
-
 /* Default NVM size to read */
 #define IWM_NVM_DEFAULT_CHUNK_SIZE	(2*1024)
 
@@ -1777,7 +1835,7 @@ iwm_nvm_read_section(struct iwm_softc *s
 	while (seglen == length) {
 		/* Check no memory assumptions fail and cause an overflow */
 		if ((size_read + offset + length) >
-		    sc->eeprom_size) {
+		    sc->cfg->eeprom_size) {
 			device_printf(sc->sc_dev,
 			    "EEPROM size is too small for NVM\n");
 			return ENOBUFS;
@@ -1899,10 +1957,6 @@ enum iwm_nvm_channel_flags {
 	IWM_NVM_CHANNEL_160MHZ = (1 << 11),
 };
 
-/* lower blocks contain EEPROM image and calibration data */
-#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000	(16 * 512 * sizeof(uint16_t)) /* 16 KB */
-#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_8000	(32 * 512 * sizeof(uint16_t)) /* 32 KB */
-
 /*
  * Translate EEPROM flags to net80211.
  */
@@ -1938,7 +1992,7 @@ iwm_add_channel_band(struct iwm_softc *s
 
 	for (; ch_idx < ch_num; ch_idx++) {
 		ch_flags = le16_to_cpup(nvm_ch_flags + ch_idx);
-		if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)
+		if (sc->cfg->device_family == IWM_DEVICE_FAMILY_7000)
 			ieee = iwm_nvm_channels[ch_idx];
 		else
 			ieee = iwm_nvm_channels_8000[ch_idx];
@@ -1988,7 +2042,7 @@ iwm_init_channel_map(struct ieee80211com
 	    IWM_NUM_2GHZ_CHANNELS - 1, IWM_NUM_2GHZ_CHANNELS, bands);
 
 	if (data->sku_cap_band_52GHz_enable) {
-		if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)
+		if (sc->cfg->device_family == IWM_DEVICE_FAMILY_7000)
 			ch_num = nitems(iwm_nvm_channels);
 		else
 			ch_num = nitems(iwm_nvm_channels_8000);
@@ -2062,7 +2116,7 @@ static int
 iwm_get_sku(const struct iwm_softc *sc, const uint16_t *nvm_sw,
 	    const uint16_t *phy_sku)
 {
-	if (sc->sc_device_family != IWM_DEVICE_FAMILY_8000)
+	if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000)
 		return le16_to_cpup(nvm_sw + IWM_SKU);
 
 	return le32_to_cpup((const uint32_t *)(phy_sku + IWM_SKU_8000));
@@ -2071,7 +2125,7 @@ iwm_get_sku(const struct iwm_softc *sc, 
 static int
 iwm_get_nvm_version(const struct iwm_softc *sc, const uint16_t *nvm_sw)
 {
-	if (sc->sc_device_family != IWM_DEVICE_FAMILY_8000)
+	if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000)
 		return le16_to_cpup(nvm_sw + IWM_NVM_VERSION);
 	else
 		return le32_to_cpup((const uint32_t *)(nvm_sw +
@@ -2082,7 +2136,7 @@ static int
 iwm_get_radio_cfg(const struct iwm_softc *sc, const uint16_t *nvm_sw,
 		  const uint16_t *phy_sku)
 {
-        if (sc->sc_device_family != IWM_DEVICE_FAMILY_8000)
+        if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000)
                 return le16_to_cpup(nvm_sw + IWM_RADIO_CFG);
 
         return le32_to_cpup((const uint32_t *)(phy_sku + IWM_RADIO_CFG_8000));
@@ -2093,7 +2147,7 @@ iwm_get_n_hw_addrs(const struct iwm_soft
 {
 	int n_hw_addr;
 
-	if (sc->sc_device_family != IWM_DEVICE_FAMILY_8000)
+	if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000)
 		return le16_to_cpup(nvm_sw + IWM_N_HW_ADDRS);
 
 	n_hw_addr = le32_to_cpup((const uint32_t *)(nvm_sw + IWM_N_HW_ADDRS_8000));
@@ -2105,7 +2159,7 @@ static void
 iwm_set_radio_cfg(const struct iwm_softc *sc, struct iwm_nvm_data *data,
 		  uint32_t radio_cfg)
 {
-	if (sc->sc_device_family != IWM_DEVICE_FAMILY_8000) {
+	if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) {
 		data->radio_cfg_type = IWM_NVM_RF_CFG_TYPE_MSK(radio_cfg);
 		data->radio_cfg_step = IWM_NVM_RF_CFG_STEP_MSK(radio_cfg);
 		data->radio_cfg_dash = IWM_NVM_RF_CFG_DASH_MSK(radio_cfg);
@@ -2131,7 +2185,7 @@ iwm_set_hw_address(struct iwm_softc *sc,
 		iwm_set_hw_address_from_csr(sc, data);
         } else
 #endif
-	if (sc->sc_device_family != IWM_DEVICE_FAMILY_8000) {
+	if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) {
 		const uint8_t *hw_addr = (const uint8_t *)(nvm_hw + IWM_HW_ADDR);
 
 		/* The byte order is little endian 16 bit, meaning 214365 */
@@ -2162,7 +2216,7 @@ iwm_parse_nvm_data(struct iwm_softc *sc,
 	struct iwm_nvm_data *data;
 	uint32_t sku, radio_cfg;
 
-	if (sc->sc_device_family != IWM_DEVICE_FAMILY_8000) {
+	if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) {
 		data = malloc(sizeof(*data) +
 		    IWM_NUM_CHANNELS * sizeof(uint16_t),
 		    M_DEVBUF, M_NOWAIT | M_ZERO);
@@ -2192,7 +2246,7 @@ iwm_parse_nvm_data(struct iwm_softc *sc,
 		return NULL;
 	}
 
-	if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
+	if (sc->cfg->device_family == IWM_DEVICE_FAMILY_7000) {
 		memcpy(data->nvm_ch_flags, &nvm_sw[IWM_NVM_CHANNELS],
 		    IWM_NUM_CHANNELS * sizeof(uint16_t));
 	} else {
@@ -2216,14 +2270,14 @@ iwm_parse_nvm_sections(struct iwm_softc 
 	const uint16_t *hw, *sw, *calib, *regulatory, *mac_override, *phy_sku;
 
 	/* Checking for required sections */
-	if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
+	if (sc->cfg->device_family == IWM_DEVICE_FAMILY_7000) {
 		if (!sections[IWM_NVM_SECTION_TYPE_SW].data ||
-		    !sections[sc->nvm_hw_section_num].data) {
+		    !sections[sc->cfg->nvm_hw_section_num].data) {
 			device_printf(sc->sc_dev,
 			    "Can't parse empty OTP/NVM sections\n");
 			return NULL;
 		}
-	} else if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) {
+	} else if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) {
 		/* SW and REGULATORY sections are mandatory */
 		if (!sections[IWM_NVM_SECTION_TYPE_SW].data ||
 		    !sections[IWM_NVM_SECTION_TYPE_REGULATORY].data) {
@@ -2232,7 +2286,7 @@ iwm_parse_nvm_sections(struct iwm_softc 
 			return NULL;
 		}
 		/* MAC_OVERRIDE or at least HW section must exist */
-		if (!sections[sc->nvm_hw_section_num].data &&
+		if (!sections[sc->cfg->nvm_hw_section_num].data &&
 		    !sections[IWM_NVM_SECTION_TYPE_MAC_OVERRIDE].data) {
 			device_printf(sc->sc_dev,
 			    "Can't parse mac_address, empty sections\n");
@@ -2246,10 +2300,10 @@ iwm_parse_nvm_sections(struct iwm_softc 
 			return NULL;
 		}
 	} else {
-		panic("unknown device family %d\n", sc->sc_device_family);
+		panic("unknown device family %d\n", sc->cfg->device_family);
 	}
 
-	hw = (const uint16_t *) sections[sc->nvm_hw_section_num].data;
+	hw = (const uint16_t *) sections[sc->cfg->nvm_hw_section_num].data;
 	sw = (const uint16_t *)sections[IWM_NVM_SECTION_TYPE_SW].data;
 	calib = (const uint16_t *)
 	    sections[IWM_NVM_SECTION_TYPE_CALIBRATION].data;
@@ -2274,14 +2328,14 @@ iwm_nvm_init(struct iwm_softc *sc)
 
 	memset(nvm_sections, 0, sizeof(nvm_sections));
 
-	if (sc->nvm_hw_section_num >= IWM_NVM_MAX_NUM_SECTIONS)
+	if (sc->cfg->nvm_hw_section_num >= IWM_NVM_MAX_NUM_SECTIONS)
 		return EINVAL;
 
 	/* load NVM values from nic */
 	/* Read From FW NVM */
 	IWM_DPRINTF(sc, IWM_DEBUG_EEPROM, "Read from NVM\n");
 
-	nvm_buffer = malloc(sc->eeprom_size, M_DEVBUF, M_NOWAIT | M_ZERO);
+	nvm_buffer = malloc(sc->cfg->eeprom_size, M_DEVBUF, M_NOWAIT | M_ZERO);
 	if (!nvm_buffer)
 		return ENOMEM;
 	for (section = 0; section < IWM_NVM_MAX_NUM_SECTIONS; section++) {
@@ -2562,7 +2616,7 @@ iwm_load_firmware(struct iwm_softc *sc, 
 {
 	int error, w;
 
-	if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000)
+	if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000)
 		error = iwm_load_firmware_8000(sc, ucode_type);
 	else
 		error = iwm_load_firmware_7000(sc, ucode_type);
@@ -2575,7 +2629,7 @@ iwm_load_firmware(struct iwm_softc *sc, 
 	}
 	if (error || !sc->sc_uc.uc_ok) {
 		device_printf(sc->sc_dev, "could not load firmware\n");
-		if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) {
+		if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) {
 			device_printf(sc->sc_dev, "cpu1 status: 0x%x\n",
 			    iwm_read_prph(sc, IWM_SB_CPU_1_STATUS));
 			device_printf(sc->sc_dev, "cpu2 status: 0x%x\n",
@@ -4498,7 +4552,7 @@ iwm_mvm_sf_config(struct iwm_softc *sc, 
 	};
 	int ret = 0;
 
-	if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000)
+	if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000)
 		sf_cmd.state |= htole32(IWM_SF_CFG_DUMMY_NOTIF_OFF);
 
 	switch (new_state) {
@@ -4686,7 +4740,7 @@ iwm_init_hw(struct iwm_softc *sc)
 	}
 
 	/* Initialize tx backoffs to the minimum. */
-	if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000)
+	if (sc->cfg->device_family == IWM_DEVICE_FAMILY_7000)
 		iwm_mvm_tt_tx_backoff(sc, 0);
 
 	error = iwm_mvm_power_update_device(sc);
@@ -5682,51 +5736,30 @@ iwm_dev_check(device_t dev)
 
 	sc = device_get_softc(dev);
 
-	sc->sc_hw_rev = IWM_READ(sc, IWM_CSR_HW_REV);
 	switch (pci_get_device(dev)) {
 	case PCI_PRODUCT_INTEL_WL_3160_1:
 	case PCI_PRODUCT_INTEL_WL_3160_2:
-		sc->sc_fwname = "iwm3160fw";
-		sc->host_interrupt_operation_mode = 1;
-		sc->eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000;
-		sc->nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_7000;
-		sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
+		sc->cfg = &iwm3160_cfg;
 		sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
 		return (0);
 	case PCI_PRODUCT_INTEL_WL_3165_1:
 	case PCI_PRODUCT_INTEL_WL_3165_2:
-		sc->sc_fwname = "iwm7265fw";
-		sc->host_interrupt_operation_mode = 0;
-		sc->eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000;
-		sc->nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_7000;
-		sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
+		sc->cfg = &iwm3165_cfg;
 		sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
 		return (0);
 	case PCI_PRODUCT_INTEL_WL_7260_1:
 	case PCI_PRODUCT_INTEL_WL_7260_2:
-		sc->sc_fwname = "iwm7260fw";
-		sc->host_interrupt_operation_mode = 1;
-		sc->eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000;
-		sc->nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_7000;
-		sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
+		sc->cfg = &iwm7260_cfg;
 		sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
 		return (0);
 	case PCI_PRODUCT_INTEL_WL_7265_1:
 	case PCI_PRODUCT_INTEL_WL_7265_2:
-		sc->sc_fwname = "iwm7265fw";
-		sc->host_interrupt_operation_mode = 0;
-		sc->eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000;
-		sc->nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_7000;
-		sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
+		sc->cfg = &iwm7265_cfg;
 		sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
 		return (0);
 	case PCI_PRODUCT_INTEL_WL_8260_1:
 	case PCI_PRODUCT_INTEL_WL_8260_2:
-		sc->sc_fwname = "iwm8000Cfw";
-		sc->host_interrupt_operation_mode = 0;
-		sc->eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_8000;
-		sc->nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_8000;
-		sc->sc_device_family = IWM_DEVICE_FAMILY_8000;
+		sc->cfg = &iwm8260_cfg;
 		sc->sc_fwdmasegsz = IWM_FWDMASEGSZ_8000;
 		return (0);
 	default:
@@ -5842,16 +5875,14 @@ iwm_attach(device_t dev)
 	if (error != 0)
 		goto fail;
 
-	/*
-	 * We now start fiddling with the hardware
-	 */
+	sc->sc_hw_rev = IWM_READ(sc, IWM_CSR_HW_REV);
 	/*
 	 * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have
 	 * changed, and now the revision step also includes bit 0-1 (no more
 	 * "dash" value). To keep hw_rev backwards compatible - we'll store it
 	 * in the old format.
 	 */
-	if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000)
+	if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000)
 		sc->sc_hw_rev = (sc->sc_hw_rev & 0xfff0) |
 				(IWM_CSR_HW_REV_STEP(sc->sc_hw_rev << 2) << 2);
 
@@ -5860,7 +5891,7 @@ iwm_attach(device_t dev)
 		goto fail;
 	}
 
-	if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000) {
+	if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) {
 		int ret;
 		uint32_t hw_step;
 
@@ -5898,6 +5929,12 @@ iwm_attach(device_t dev)
 		}
 	}
 
+	/* special-case 7265D, it has the same PCI IDs. */
+	if (sc->cfg == &iwm7265_cfg &&
+	    (sc->sc_hw_rev & IWM_CSR_HW_REV_TYPE_MSK) == IWM_CSR_HW_REV_TYPE_7265D) {
+		sc->cfg = &iwm7265d_cfg;
+	}
+
 	/* Allocate DMA memory for firmware transfers. */
 	if ((error = iwm_alloc_fwmem(sc)) != 0) {
 		device_printf(dev, "could not allocate memory for firmware\n");

Modified: head/sys/dev/iwm/if_iwm_pcie_trans.c
==============================================================================
--- head/sys/dev/iwm/if_iwm_pcie_trans.c	Mon Feb  6 03:06:11 2017	(r313311)
+++ head/sys/dev/iwm/if_iwm_pcie_trans.c	Mon Feb  6 03:29:50 2017	(r313312)
@@ -256,7 +256,7 @@ iwm_nic_lock(struct iwm_softc *sc)
 	IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
 	    IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 
-	if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000)
+	if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000)
 		DELAY(2);
 
 	if (iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
@@ -425,7 +425,7 @@ iwm_apm_init(struct iwm_softc *sc)
 	IWM_DPRINTF(sc, IWM_DEBUG_RESET, "iwm apm start\n");
 
 	/* Disable L0S exit timer (platform NMI Work/Around) */
-	if (sc->sc_device_family != IWM_DEVICE_FAMILY_8000) {
+	if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) {
 		IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,
 		    IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
 	}
@@ -476,7 +476,7 @@ iwm_apm_init(struct iwm_softc *sc)
 		goto out;
 	}
 
-	if (sc->host_interrupt_operation_mode) {
+	if (sc->cfg->host_interrupt_operation_mode) {
 		/*
 		 * This is a bit of an abuse - This is needed for 7260 / 3160
 		 * only check host_interrupt_operation_mode even if this is
@@ -505,7 +505,7 @@ iwm_apm_init(struct iwm_softc *sc)
 	 * do not disable clocks.  This preserves any hardware bits already
 	 * set by default in "CLK_CTRL_REG" after reset.
 	 */
-	if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
+	if (sc->cfg->device_family == IWM_DEVICE_FAMILY_7000) {
 		iwm_write_prph(sc, IWM_APMG_CLK_EN_REG,
 		    IWM_APMG_CLK_VAL_DMA_CLK_RQT);
 		DELAY(20);

Modified: head/sys/dev/iwm/if_iwmvar.h
==============================================================================
--- head/sys/dev/iwm/if_iwmvar.h	Mon Feb  6 03:06:11 2017	(r313311)
+++ head/sys/dev/iwm/if_iwmvar.h	Mon Feb  6 03:29:50 2017	(r313312)
@@ -362,6 +362,27 @@ struct iwm_node {
 #define IWM_ICT_COUNT		(IWM_ICT_SIZE / sizeof (uint32_t))
 #define IWM_ICT_PADDR_SHIFT	12
 
+enum iwm_device_family {
+	IWM_DEVICE_FAMILY_UNDEFINED,
+	IWM_DEVICE_FAMILY_7000,
+	IWM_DEVICE_FAMILY_8000,
+};
+
+/**
+ * struct iwm_cfg
+ * @fw_name: Firmware filename.
+ * @host_interrupt_operation_mode: device needs host interrupt operation
+ *      mode set
+ * @nvm_hw_section_num: the ID of the HW NVM section
+ */
+struct iwm_cfg {
+	const char *fw_name;
+	uint16_t eeprom_size;
+	enum iwm_device_family device_family;
+	int host_interrupt_operation_mode;
+	uint8_t nvm_hw_section_num;
+};
+
 struct iwm_softc {
 	device_t		sc_dev;
 	uint32_t		sc_debug;
@@ -411,9 +432,6 @@ struct iwm_softc {
 
 	int			sc_hw_rev;
 	int			sc_hw_id;
-	int			sc_device_family;
-#define IWM_DEVICE_FAMILY_7000	1
-#define IWM_DEVICE_FAMILY_8000	2
 
 	struct iwm_dma_info	kw_dma;
 	struct iwm_dma_info	fw_dma;
@@ -445,12 +463,12 @@ struct iwm_softc {
 	 */
 	int			sc_generation;
 
-	const char		*sc_fwname;
 	bus_size_t		sc_fwdmasegsz;
 	struct iwm_fw_info	sc_fw;
 	int			sc_fw_phy_config;
 	struct iwm_tlv_calib_ctrl sc_default_calib[IWM_UCODE_TYPE_MAX];
 
+	const struct iwm_cfg	*cfg;
 	struct iwm_nvm_data	*nvm_data;
 	struct iwm_phy_db	*sc_phy_db;
 
@@ -481,17 +499,12 @@ struct iwm_softc {
 	struct iwm_notif_statistics sc_stats;
 	int			sc_noise;
 
-	int			host_interrupt_operation_mode;
-
 	caddr_t			sc_drvbpf;
 
 	struct iwm_rx_radiotap_header sc_rxtap;
 	struct iwm_tx_radiotap_header sc_txtap;
 
 	int			sc_max_rssi;
-
-	uint16_t		eeprom_size;
-	uint8_t			nvm_hw_section_num;
 };
 
 #define IWM_LOCK_INIT(_sc) \


More information about the svn-src-head mailing list