if_iwm.c (9a6695532b3997e4e2bc3fe57481cc49be5e9e93) if_iwm.c (355c15130aef13484821051a655da9b9066e1015)
1/* $OpenBSD: if_iwm.c,v 1.167 2017/04/04 00:40:52 claudio Exp $ */
2
3/*
4 * Copyright (c) 2014 genua mbh <info@genua.de>
5 * Copyright (c) 2014 Fixup Software Ltd.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above

--- 1900 unchanged lines hidden (view full) ---

1909}
1910
1911/*
1912 * BEGIN IWM_NVM_PARSE
1913 */
1914
1915/* iwlwifi/iwl-nvm-parse.c */
1916
1/* $OpenBSD: if_iwm.c,v 1.167 2017/04/04 00:40:52 claudio Exp $ */
2
3/*
4 * Copyright (c) 2014 genua mbh <info@genua.de>
5 * Copyright (c) 2014 Fixup Software Ltd.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above

--- 1900 unchanged lines hidden (view full) ---

1909}
1910
1911/*
1912 * BEGIN IWM_NVM_PARSE
1913 */
1914
1915/* iwlwifi/iwl-nvm-parse.c */
1916
1917/* NVM offsets (in words) definitions */
1918enum iwm_nvm_offsets {
1919 /* NVM HW-Section offset (in words) definitions */
1920 IWM_HW_ADDR = 0x15,
1921
1922/* NVM SW-Section offset (in words) definitions */
1923 IWM_NVM_SW_SECTION = 0x1C0,
1924 IWM_NVM_VERSION = 0,
1925 IWM_RADIO_CFG = 1,
1926 IWM_SKU = 2,
1927 IWM_N_HW_ADDRS = 3,
1928 IWM_NVM_CHANNELS = 0x1E0 - IWM_NVM_SW_SECTION,
1929
1930/* NVM calibration section offset (in words) definitions */
1931 IWM_NVM_CALIB_SECTION = 0x2B8,
1932 IWM_XTAL_CALIB = 0x316 - IWM_NVM_CALIB_SECTION
1933};
1934
1935enum iwm_8000_nvm_offsets {
1936 /* NVM HW-Section offset (in words) definitions */
1937 IWM_HW_ADDR0_WFPM_8000 = 0x12,
1938 IWM_HW_ADDR1_WFPM_8000 = 0x16,
1939 IWM_HW_ADDR0_PCIE_8000 = 0x8A,
1940 IWM_HW_ADDR1_PCIE_8000 = 0x8E,
1941 IWM_MAC_ADDRESS_OVERRIDE_8000 = 1,
1942
1943 /* NVM SW-Section offset (in words) definitions */
1944 IWM_NVM_SW_SECTION_8000 = 0x1C0,
1945 IWM_NVM_VERSION_8000 = 0,
1946 IWM_RADIO_CFG_8000 = 0,
1947 IWM_SKU_8000 = 2,
1948 IWM_N_HW_ADDRS_8000 = 3,
1949
1950 /* NVM REGULATORY -Section offset (in words) definitions */
1951 IWM_NVM_CHANNELS_8000 = 0,
1952 IWM_NVM_LAR_OFFSET_8000_OLD = 0x4C7,
1953 IWM_NVM_LAR_OFFSET_8000 = 0x507,
1954 IWM_NVM_LAR_ENABLED_8000 = 0x7,
1955
1956 /* NVM calibration section offset (in words) definitions */
1957 IWM_NVM_CALIB_SECTION_8000 = 0x2B8,
1958 IWM_XTAL_CALIB_8000 = 0x316 - IWM_NVM_CALIB_SECTION_8000
1959};
1960
1961/* SKU Capabilities (actual values from NVM definition) */
1962enum nvm_sku_bits {
1963 IWM_NVM_SKU_CAP_BAND_24GHZ = (1 << 0),
1964 IWM_NVM_SKU_CAP_BAND_52GHZ = (1 << 1),
1965 IWM_NVM_SKU_CAP_11N_ENABLE = (1 << 2),
1966 IWM_NVM_SKU_CAP_11AC_ENABLE = (1 << 3),
1967};
1968
1969/* radio config bits (actual values from NVM definition) */
1970#define IWM_NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */
1971#define IWM_NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
1972#define IWM_NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
1973#define IWM_NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
1974#define IWM_NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
1975#define IWM_NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
1976
1977#define IWM_NVM_RF_CFG_FLAVOR_MSK_8000(x) (x & 0xF)
1978#define IWM_NVM_RF_CFG_DASH_MSK_8000(x) ((x >> 4) & 0xF)
1979#define IWM_NVM_RF_CFG_STEP_MSK_8000(x) ((x >> 8) & 0xF)
1980#define IWM_NVM_RF_CFG_TYPE_MSK_8000(x) ((x >> 12) & 0xFFF)
1981#define IWM_NVM_RF_CFG_TX_ANT_MSK_8000(x) ((x >> 24) & 0xF)
1982#define IWM_NVM_RF_CFG_RX_ANT_MSK_8000(x) ((x >> 28) & 0xF)
1983
1984/**
1985 * enum iwm_nvm_channel_flags - channel flags in NVM
1986 * @IWM_NVM_CHANNEL_VALID: channel is usable for this SKU/geo
1987 * @IWM_NVM_CHANNEL_IBSS: usable as an IBSS channel
1988 * @IWM_NVM_CHANNEL_ACTIVE: active scanning allowed
1989 * @IWM_NVM_CHANNEL_RADAR: radar detection required
1990 * XXX cannot find this (DFS) flag in iwm-nvm-parse.c
1991 * @IWM_NVM_CHANNEL_DFS: dynamic freq selection candidate
1992 * @IWM_NVM_CHANNEL_WIDE: 20 MHz channel okay (?)
1993 * @IWM_NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)
1994 * @IWM_NVM_CHANNEL_80MHZ: 80 MHz channel okay (?)
1995 * @IWM_NVM_CHANNEL_160MHZ: 160 MHz channel okay (?)
1996 */
1997enum iwm_nvm_channel_flags {
1998 IWM_NVM_CHANNEL_VALID = (1 << 0),
1999 IWM_NVM_CHANNEL_IBSS = (1 << 1),
2000 IWM_NVM_CHANNEL_ACTIVE = (1 << 3),
2001 IWM_NVM_CHANNEL_RADAR = (1 << 4),
2002 IWM_NVM_CHANNEL_DFS = (1 << 7),
2003 IWM_NVM_CHANNEL_WIDE = (1 << 8),
2004 IWM_NVM_CHANNEL_40MHZ = (1 << 9),
2005 IWM_NVM_CHANNEL_80MHZ = (1 << 10),
2006 IWM_NVM_CHANNEL_160MHZ = (1 << 11),
2007};
2008
2009/*
2010 * Translate EEPROM flags to net80211.
2011 */
2012static uint32_t
2013iwm_eeprom_channel_flags(uint16_t ch_flags)
2014{
2015 uint32_t nflags;
2016

--- 198 unchanged lines hidden (view full) ---

2215 data->radio_cfg_pnum = IWM_NVM_RF_CFG_PNUM_MSK(radio_cfg);
2216 return;
2217 }
2218
2219 /* set the radio configuration for family 8000 */
2220 data->radio_cfg_type = IWM_NVM_RF_CFG_TYPE_MSK_8000(radio_cfg);
2221 data->radio_cfg_step = IWM_NVM_RF_CFG_STEP_MSK_8000(radio_cfg);
2222 data->radio_cfg_dash = IWM_NVM_RF_CFG_DASH_MSK_8000(radio_cfg);
1917/*
1918 * Translate EEPROM flags to net80211.
1919 */
1920static uint32_t
1921iwm_eeprom_channel_flags(uint16_t ch_flags)
1922{
1923 uint32_t nflags;
1924

--- 198 unchanged lines hidden (view full) ---

2123 data->radio_cfg_pnum = IWM_NVM_RF_CFG_PNUM_MSK(radio_cfg);
2124 return;
2125 }
2126
2127 /* set the radio configuration for family 8000 */
2128 data->radio_cfg_type = IWM_NVM_RF_CFG_TYPE_MSK_8000(radio_cfg);
2129 data->radio_cfg_step = IWM_NVM_RF_CFG_STEP_MSK_8000(radio_cfg);
2130 data->radio_cfg_dash = IWM_NVM_RF_CFG_DASH_MSK_8000(radio_cfg);
2223 data->radio_cfg_pnum = IWM_NVM_RF_CFG_FLAVOR_MSK_8000(radio_cfg);
2131 data->radio_cfg_pnum = IWM_NVM_RF_CFG_PNUM_MSK_8000(radio_cfg);
2224 data->valid_tx_ant = IWM_NVM_RF_CFG_TX_ANT_MSK_8000(radio_cfg);
2225 data->valid_rx_ant = IWM_NVM_RF_CFG_RX_ANT_MSK_8000(radio_cfg);
2226}
2227
2228static int
2229iwm_set_hw_address(struct iwm_softc *sc, struct iwm_nvm_data *data,
2230 const uint16_t *nvm_hw, const uint16_t *mac_override)
2231{

--- 146 unchanged lines hidden (view full) ---

2378
2379 return iwm_parse_nvm_data(sc, hw, sw, calib, mac_override,
2380 phy_sku, regulatory);
2381}
2382
2383static int
2384iwm_nvm_init(struct iwm_softc *sc)
2385{
2132 data->valid_tx_ant = IWM_NVM_RF_CFG_TX_ANT_MSK_8000(radio_cfg);
2133 data->valid_rx_ant = IWM_NVM_RF_CFG_RX_ANT_MSK_8000(radio_cfg);
2134}
2135
2136static int
2137iwm_set_hw_address(struct iwm_softc *sc, struct iwm_nvm_data *data,
2138 const uint16_t *nvm_hw, const uint16_t *mac_override)
2139{

--- 146 unchanged lines hidden (view full) ---

2286
2287 return iwm_parse_nvm_data(sc, hw, sw, calib, mac_override,
2288 phy_sku, regulatory);
2289}
2290
2291static int
2292iwm_nvm_init(struct iwm_softc *sc)
2293{
2386 struct iwm_nvm_section nvm_sections[IWM_NVM_MAX_NUM_SECTIONS];
2294 struct iwm_nvm_section nvm_sections[IWM_NVM_NUM_OF_SECTIONS];
2387 int i, ret, section;
2388 uint32_t size_read = 0;
2389 uint8_t *nvm_buffer, *temp;
2390 uint16_t len;
2391
2392 memset(nvm_sections, 0, sizeof(nvm_sections));
2393
2295 int i, ret, section;
2296 uint32_t size_read = 0;
2297 uint8_t *nvm_buffer, *temp;
2298 uint16_t len;
2299
2300 memset(nvm_sections, 0, sizeof(nvm_sections));
2301
2394 if (sc->cfg->nvm_hw_section_num >= IWM_NVM_MAX_NUM_SECTIONS)
2302 if (sc->cfg->nvm_hw_section_num >= IWM_NVM_NUM_OF_SECTIONS)
2395 return EINVAL;
2396
2397 /* load NVM values from nic */
2398 /* Read From FW NVM */
2399 IWM_DPRINTF(sc, IWM_DEBUG_EEPROM, "Read from NVM\n");
2400
2401 nvm_buffer = malloc(sc->cfg->eeprom_size, M_DEVBUF, M_NOWAIT | M_ZERO);
2402 if (!nvm_buffer)
2403 return ENOMEM;
2303 return EINVAL;
2304
2305 /* load NVM values from nic */
2306 /* Read From FW NVM */
2307 IWM_DPRINTF(sc, IWM_DEBUG_EEPROM, "Read from NVM\n");
2308
2309 nvm_buffer = malloc(sc->cfg->eeprom_size, M_DEVBUF, M_NOWAIT | M_ZERO);
2310 if (!nvm_buffer)
2311 return ENOMEM;
2404 for (section = 0; section < IWM_NVM_MAX_NUM_SECTIONS; section++) {
2312 for (section = 0; section < IWM_NVM_NUM_OF_SECTIONS; section++) {
2405 /* we override the constness for initial read */
2406 ret = iwm_nvm_read_section(sc, section, nvm_buffer,
2407 &len, size_read);
2408 if (ret)
2409 continue;
2410 size_read += len;
2411 temp = malloc(len, M_DEVBUF, M_NOWAIT);
2412 if (!temp) {

--- 10 unchanged lines hidden (view full) ---

2423 free(nvm_buffer, M_DEVBUF);
2424
2425 sc->nvm_data = iwm_parse_nvm_sections(sc, nvm_sections);
2426 if (!sc->nvm_data)
2427 return EINVAL;
2428 IWM_DPRINTF(sc, IWM_DEBUG_EEPROM | IWM_DEBUG_RESET,
2429 "nvm version = %x\n", sc->nvm_data->nvm_version);
2430
2313 /* we override the constness for initial read */
2314 ret = iwm_nvm_read_section(sc, section, nvm_buffer,
2315 &len, size_read);
2316 if (ret)
2317 continue;
2318 size_read += len;
2319 temp = malloc(len, M_DEVBUF, M_NOWAIT);
2320 if (!temp) {

--- 10 unchanged lines hidden (view full) ---

2331 free(nvm_buffer, M_DEVBUF);
2332
2333 sc->nvm_data = iwm_parse_nvm_sections(sc, nvm_sections);
2334 if (!sc->nvm_data)
2335 return EINVAL;
2336 IWM_DPRINTF(sc, IWM_DEBUG_EEPROM | IWM_DEBUG_RESET,
2337 "nvm version = %x\n", sc->nvm_data->nvm_version);
2338
2431 for (i = 0; i < IWM_NVM_MAX_NUM_SECTIONS; i++) {
2339 for (i = 0; i < IWM_NVM_NUM_OF_SECTIONS; i++) {
2432 if (nvm_sections[i].data != NULL)
2433 free(nvm_sections[i].data, M_DEVBUF);
2434 }
2435
2436 return 0;
2437}
2438
2439static int

--- 736 unchanged lines hidden (view full) ---

3176 /* For now, just hard-code it to -96 to be safe */
3177 return (-96);
3178#endif
3179}
3180
3181static void
3182iwm_handle_rx_statistics(struct iwm_softc *sc, struct iwm_rx_packet *pkt)
3183{
2340 if (nvm_sections[i].data != NULL)
2341 free(nvm_sections[i].data, M_DEVBUF);
2342 }
2343
2344 return 0;
2345}
2346
2347static int

--- 736 unchanged lines hidden (view full) ---

3084 /* For now, just hard-code it to -96 to be safe */
3085 return (-96);
3086#endif
3087}
3088
3089static void
3090iwm_handle_rx_statistics(struct iwm_softc *sc, struct iwm_rx_packet *pkt)
3091{
3184 struct iwm_notif_statistics_v10 *stats = (void *)&pkt->data;
3092 struct iwm_notif_statistics *stats = (void *)&pkt->data;
3185
3186 memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats));
3187 sc->sc_noise = iwm_get_noise(sc, &stats->rx.general);
3188}
3189
3190/* iwlwifi: mvm/rx.c */
3191/*
3192 * iwm_get_signal_strength - use new rx PHY INFO API

--- 699 unchanged lines hidden (view full) ---

3892 }
3893 } else {
3894 tx->pm_frame_timeout = htole16(IWM_PM_FRAME_NONE);
3895 }
3896
3897 if (hdrlen & 3) {
3898 /* First segment length must be a multiple of 4. */
3899 flags |= IWM_TX_CMD_FLG_MH_PAD;
3093
3094 memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats));
3095 sc->sc_noise = iwm_get_noise(sc, &stats->rx.general);
3096}
3097
3098/* iwlwifi: mvm/rx.c */
3099/*
3100 * iwm_get_signal_strength - use new rx PHY INFO API

--- 699 unchanged lines hidden (view full) ---

3800 }
3801 } else {
3802 tx->pm_frame_timeout = htole16(IWM_PM_FRAME_NONE);
3803 }
3804
3805 if (hdrlen & 3) {
3806 /* First segment length must be a multiple of 4. */
3807 flags |= IWM_TX_CMD_FLG_MH_PAD;
3900 tx->offload_assist |= htole16(1 << IWM_TX_CMD_OFFLD_PAD);
3808 tx->offload_assist |= htole16(IWM_TX_CMD_OFFLD_PAD);
3901 pad = 4 - (hdrlen & 3);
3902 } else {
3903 tx->offload_assist = 0;
3904 pad = 0;
3905 }
3906
3907 tx->len = htole16(totlen);
3908 tx->tid_tspec = tid;

--- 145 unchanged lines hidden (view full) ---

4054 * 1) set the station as draining
4055 * 2) flush the Tx path
4056 * 3) wait for the transport queues to be empty
4057 */
4058int
4059iwm_flush_tx_path(struct iwm_softc *sc, uint32_t tfd_msk, uint32_t flags)
4060{
4061 int ret;
3809 pad = 4 - (hdrlen & 3);
3810 } else {
3811 tx->offload_assist = 0;
3812 pad = 0;
3813 }
3814
3815 tx->len = htole16(totlen);
3816 tx->tid_tspec = tid;

--- 145 unchanged lines hidden (view full) ---

3962 * 1) set the station as draining
3963 * 2) flush the Tx path
3964 * 3) wait for the transport queues to be empty
3965 */
3966int
3967iwm_flush_tx_path(struct iwm_softc *sc, uint32_t tfd_msk, uint32_t flags)
3968{
3969 int ret;
4062 struct iwm_tx_path_flush_cmd flush_cmd = {
3970 struct iwm_tx_path_flush_cmd_v1 flush_cmd = {
4063 .queues_ctl = htole32(tfd_msk),
4064 .flush_ctl = htole16(IWM_DUMP_TX_FIFO_FLUSH),
4065 };
4066
4067 ret = iwm_send_cmd_pdu(sc, IWM_TXPATH_FLUSH, flags,
4068 sizeof(flush_cmd), &flush_cmd);
4069 if (ret)
4070 device_printf(sc->sc_dev,
4071 "Flushing tx queue failed: %d\n", ret);
4072 return ret;
4073}
4074
4075/*
4076 * BEGIN mvm/quota.c
4077 */
4078
4079static int
4080iwm_update_quotas(struct iwm_softc *sc, struct iwm_vap *ivp)
4081{
3971 .queues_ctl = htole32(tfd_msk),
3972 .flush_ctl = htole16(IWM_DUMP_TX_FIFO_FLUSH),
3973 };
3974
3975 ret = iwm_send_cmd_pdu(sc, IWM_TXPATH_FLUSH, flags,
3976 sizeof(flush_cmd), &flush_cmd);
3977 if (ret)
3978 device_printf(sc->sc_dev,
3979 "Flushing tx queue failed: %d\n", ret);
3980 return ret;
3981}
3982
3983/*
3984 * BEGIN mvm/quota.c
3985 */
3986
3987static int
3988iwm_update_quotas(struct iwm_softc *sc, struct iwm_vap *ivp)
3989{
4082 struct iwm_time_quota_cmd cmd;
3990 struct iwm_time_quota_cmd_v1 cmd;
4083 int i, idx, ret, num_active_macs, quota, quota_rem;
4084 int colors[IWM_MAX_BINDINGS] = { -1, -1, -1, -1, };
4085 int n_ifs[IWM_MAX_BINDINGS] = {0, };
4086 uint16_t id;
4087
4088 memset(&cmd, 0, sizeof(cmd));
4089
4090 /* currently, PHY ID == binding ID */

--- 615 unchanged lines hidden (view full) ---

4706 .id = IWM_MCC_UPDATE_CMD,
4707 .flags = (IWM_CMD_SYNC | IWM_CMD_WANT_SKB),
4708 .data = { &mcc_cmd },
4709 };
4710 int ret;
4711#ifdef IWM_DEBUG
4712 struct iwm_rx_packet *pkt;
4713 struct iwm_mcc_update_resp_v1 *mcc_resp_v1 = NULL;
3991 int i, idx, ret, num_active_macs, quota, quota_rem;
3992 int colors[IWM_MAX_BINDINGS] = { -1, -1, -1, -1, };
3993 int n_ifs[IWM_MAX_BINDINGS] = {0, };
3994 uint16_t id;
3995
3996 memset(&cmd, 0, sizeof(cmd));
3997
3998 /* currently, PHY ID == binding ID */

--- 615 unchanged lines hidden (view full) ---

4614 .id = IWM_MCC_UPDATE_CMD,
4615 .flags = (IWM_CMD_SYNC | IWM_CMD_WANT_SKB),
4616 .data = { &mcc_cmd },
4617 };
4618 int ret;
4619#ifdef IWM_DEBUG
4620 struct iwm_rx_packet *pkt;
4621 struct iwm_mcc_update_resp_v1 *mcc_resp_v1 = NULL;
4714 struct iwm_mcc_update_resp *mcc_resp;
4622 struct iwm_mcc_update_resp_v2 *mcc_resp;
4715 int n_channels;
4716 uint16_t mcc;
4717#endif
4718 int resp_v2 = iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_LAR_SUPPORT_V2);
4719
4720 if (!iwm_is_lar_supported(sc)) {
4721 IWM_DPRINTF(sc, IWM_DEBUG_LAR, "%s: no LAR support\n",
4722 __func__);

--- 1967 unchanged lines hidden ---
4623 int n_channels;
4624 uint16_t mcc;
4625#endif
4626 int resp_v2 = iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_LAR_SUPPORT_V2);
4627
4628 if (!iwm_is_lar_supported(sc)) {
4629 IWM_DPRINTF(sc, IWM_DEBUG_LAR, "%s: no LAR support\n",
4630 __func__);

--- 1967 unchanged lines hidden ---