Going back over the full list of commands the Linux driver sends to an ax200 device when it connects to an access point, I have noticed some that are missing from our driver.
One of those is the SOC_CONFIGURATION command which provides some low-level details about the hardware device to firmware. This command doesn't seem to be needed with the ax200 device we currently support. But it does not hurt and will be needed for other devices this driver intends to support in the future. ok? diff 275365c274c71989968d3bae8c5244a411c26876 812326fa38786e39e6b9062983fda1ea32c571ac blob - 585527d032e511ae31b3c06c212f6f99d494494e blob + 05a96a041a182e2326bc3f745e20150e5053e064 --- sys/dev/pci/if_iwx.c +++ sys/dev/pci/if_iwx.c @@ -409,6 +409,7 @@ void iwx_fill_sf_command(struct iwx_softc *, struct iw struct ieee80211_node *); int iwx_sf_config(struct iwx_softc *, int); int iwx_send_bt_init_conf(struct iwx_softc *); +int iwx_send_soc_conf(struct iwx_softc *); int iwx_send_update_mcc_cmd(struct iwx_softc *, const char *); int iwx_init_hw(struct iwx_softc *); int iwx_init(struct ifnet *); @@ -437,7 +438,6 @@ int iwx_resume(struct iwx_softc *); void iwx_radiotap_attach(struct iwx_softc *); #endif -#ifdef notyet uint8_t iwx_lookup_cmd_ver(struct iwx_softc *sc, uint8_t grp, uint8_t cmd) { @@ -452,7 +452,6 @@ iwx_lookup_cmd_ver(struct iwx_softc *sc, uint8_t grp, return IWX_FW_CMD_VER_UNKNOWN; } -#endif int iwx_is_mimo_ht_plcp(uint8_t ht_plcp) @@ -6255,6 +6254,44 @@ iwx_send_bt_init_conf(struct iwx_softc *sc) } int +iwx_send_soc_conf(struct iwx_softc *sc) +{ + struct iwx_soc_configuration_cmd cmd; + int err; + uint32_t cmd_id, flags = 0; + + memset(&cmd, 0, sizeof(cmd)); + + /* + * In VER_1 of this command, the discrete value is considered + * an integer; In VER_2, it's a bitmask. Since we have only 2 + * values in VER_1, this is backwards-compatible with VER_2, + * as long as we don't set any other flag bits. + */ + if (!sc->sc_integrated) { /* VER_1 */ + flags = IWX_SOC_CONFIG_CMD_FLAGS_DISCRETE; + } else { /* VER_2 */ + uint8_t scan_cmd_ver; + if (sc->sc_ltr_delay != IWX_SOC_FLAGS_LTR_APPLY_DELAY_NONE) + flags |= (sc->sc_ltr_delay & + IWX_SOC_FLAGS_LTR_APPLY_DELAY_MASK); + scan_cmd_ver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, + IWX_SCAN_REQ_UMAC); + if (scan_cmd_ver >= 2 && sc->sc_low_latency_xtal) + flags |= IWX_SOC_CONFIG_CMD_FLAGS_LOW_LATENCY; + } + cmd.flags = htole32(flags); + + cmd.latency = htole32(sc->sc_xtal_latency); + + cmd_id = iwx_cmd_id(IWX_SOC_CONFIGURATION_CMD, IWX_SYSTEM_GROUP, 0); + err = iwx_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd); + if (err) + printf("%s: failed to set soc latency: %d\n", DEVNAME(sc), err); + return err; +} + +int iwx_send_update_mcc_cmd(struct iwx_softc *sc, const char *alpha2) { struct iwx_mcc_update_cmd mcc_cmd; @@ -6346,6 +6383,10 @@ iwx_init_hw(struct iwx_softc *sc) return err; } + err = iwx_send_soc_conf(sc); + if (err) + return err; + err = iwx_send_dqa_cmd(sc); if (err) return err; @@ -7207,6 +7248,9 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *d case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, IWX_DQA_ENABLE_CMD): break; + case IWX_WIDE_ID(IWX_SYSTEM_GROUP, IWX_SOC_CONFIGURATION_CMD): + break; + case IWX_WIDE_ID(IWX_SYSTEM_GROUP, IWX_INIT_EXTENDED_CFG_CMD): break; @@ -7673,6 +7717,9 @@ iwx_attach(struct device *parent, struct device *self, sc->sc_fwdmasegsz = IWX_FWDMASEGSZ_8000; sc->sc_nvm_max_section_size = 32768; sc->sc_integrated = 1; + sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_NONE; + sc->sc_low_latency_xtal = 0; + sc->sc_xtal_latency = 0; sc->sc_tx_with_siso_diversity = 0; break; default: blob - 04653f5d23e199b791eef8421b881a6a1854343a blob + f49a482ac2e6f5196c0c2de5c0426d5c87735070 --- sys/dev/pci/if_iwxreg.h +++ sys/dev/pci/if_iwxreg.h @@ -1866,6 +1866,31 @@ struct iwx_alive_resp_v4 { struct iwx_umac_alive umac_data; } __packed; /* ALIVE_RES_API_S_VER_4 */ +#define IWX_SOC_CONFIG_CMD_FLAGS_DISCRETE (1 << 0) +#define IWX_SOC_CONFIG_CMD_FLAGS_LOW_LATENCY (1 << 1) + +#define IWX_SOC_FLAGS_LTR_APPLY_DELAY_MASK 0xc +#define IWX_SOC_FLAGS_LTR_APPLY_DELAY_NONE 0 +#define IWX_SOC_FLAGS_LTR_APPLY_DELAY_200 1 +#define IWX_SOC_FLAGS_LTR_APPLY_DELAY_2500 2 +#define IWX_SOC_FLAGS_LTR_APPLY_DELAY_1820 3 + +/** + * struct iwx_soc_configuration_cmd - Set device stabilization latency + * + * @flags: soc settings flags. In VER_1, we can only set the DISCRETE + * flag, because the FW treats the whole value as an integer. In + * VER_2, we can set the bits independently. + * @latency: time for SOC to ensure stable power & XTAL + */ +struct iwx_soc_configuration_cmd { + uint32_t flags; + uint32_t latency; +} __packed; /* + * SOC_CONFIGURATION_CMD_S_VER_1 (see description above) + * SOC_CONFIGURATION_CMD_S_VER_2 + */ + /** * commands driver may send before finishing init flow * @IWX_INIT_DEBUG_CFG: driver is going to send debug config command blob - bcc35edb65d7aaa96a0b190eaebf6fdd44d65314 blob + ea95ff156fc9b75d8b198f979ee0f79edaa9ef1a --- sys/dev/pci/if_iwxvar.h +++ sys/dev/pci/if_iwxvar.h @@ -496,6 +496,10 @@ struct iwx_softc { int sc_integrated; int sc_tx_with_siso_diversity; int sc_max_tfd_queue_size; + int sc_ltr_delay; + int sc_xtal_latency; + int sc_low_latency_xtal; + #if NBPFILTER > 0 caddr_t sc_drvbpf;