diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_attach.c b/sys/dev/rtwn/rtl8188e/pci/r88ee_attach.c index e4c0027c39a5..d8c0a98e43a3 100644 --- a/sys/dev/rtwn/rtl8188e/pci/r88ee_attach.c +++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_attach.c @@ -1,242 +1,242 @@ /*- * Copyright (c) 2018 Farhan Khan * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* for 'macaddr' field */ #include #include #include #include static struct rtwn_r88e_txpwr r88ee_txpwr; void r88ee_attach(struct rtwn_pci_softc *); static void r88ee_set_macaddr(struct rtwn_softc *sc, uint8_t *buf) { struct r88e_rom *rom = (struct r88e_rom *)buf; IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->diff_d0.pci.macaddr); } static void r88ee_postattach(struct rtwn_softc *sc) { struct r92c_softc *rs = sc->sc_priv; struct ieee80211com *ic = &sc->sc_ic; rs->rs_scan_start = ic->ic_scan_start; ic->ic_scan_start = r92c_scan_start; rs->rs_scan_end = ic->ic_scan_end; ic->ic_scan_end = r92c_scan_end; } static void r88ee_attach_private(struct rtwn_softc *sc) { struct r92c_softc *rs; rs = malloc(sizeof(struct r92c_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO); rs->rs_txpwr = &r88ee_txpwr; rs->rs_set_bw20 = r88e_set_bw20; rs->rs_get_txpower = r88e_get_txpower; rs->rs_set_gain = r88e_set_gain; rs->rs_tx_enable_ampdu = r88e_tx_enable_ampdu; rs->rs_tx_setup_hwseq = r88e_tx_setup_hwseq; rs->rs_tx_setup_macid = r88e_tx_setup_macid; rs->rs_set_rom_opts = r88ee_set_macaddr; rs->rf_read_delay[0] = 1000; rs->rf_read_delay[1] = 1000; rs->rf_read_delay[2] = 1000; sc->sc_priv = rs; } static void r88ee_adj_devcaps(struct rtwn_softc *sc) { /* XXX TODO */ } void r88ee_attach(struct rtwn_pci_softc *pc) { struct rtwn_softc *sc = &pc->pc_sc; /* PCIe part. */ pc->pc_setup_tx_desc = r92ce_setup_tx_desc; pc->pc_tx_postsetup = r92ce_tx_postsetup; pc->pc_copy_tx_desc = r92ce_copy_tx_desc; pc->pc_enable_intr = r88ee_enable_intr; pc->pc_get_intr_status = r88ee_get_intr_status; pc->pc_qmap = 0xe771; pc->tcr = 0x8200; /* Common part. */ sc->sc_flags = RTWN_FLAG_EXT_HDR; sc->sc_start_xfers = r88ee_start_xfers; sc->sc_set_chan = r92c_set_chan; sc->sc_fill_tx_desc = r92c_fill_tx_desc; sc->sc_fill_tx_desc_raw = r92c_fill_tx_desc_raw; sc->sc_fill_tx_desc_null = r92c_fill_tx_desc_null; /* XXX recheck */ sc->sc_dump_tx_desc = r92ce_dump_tx_desc; sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags; sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags; sc->sc_get_rx_stats = r88e_get_rx_stats; sc->sc_get_rssi_cck = r88e_get_rssi_cck; sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; sc->sc_classify_intr = r88e_classify_intr; sc->sc_handle_tx_report = r88e_ratectl_tx_complete; sc->sc_handle_tx_report2 = rtwn_nop_softc_uint8_int; sc->sc_handle_c2h_report = r88e_handle_c2h_report; sc->sc_check_frame = rtwn_nop_int_softc_mbuf; sc->sc_rf_read = r92c_rf_read; sc->sc_rf_write = r88e_rf_write; sc->sc_check_condition = r92c_check_condition; sc->sc_efuse_postread = rtwn_nop_softc; sc->sc_parse_rom = r88e_parse_rom; sc->sc_set_led = r88e_set_led; sc->sc_power_on = r88ee_power_on; sc->sc_power_off = r88ee_power_off; #ifndef RTWN_WITHOUT_UCODE sc->sc_fw_reset = r88e_fw_reset; sc->sc_fw_download_enable = r88e_fw_download_enable; #endif sc->sc_llt_init = r92c_llt_init; sc->sc_set_page_size = r92c_set_page_size; sc->sc_lc_calib = r92c_lc_calib; sc->sc_iq_calib = r88e_iq_calib; sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32; sc->sc_adj_devcaps = r88ee_adj_devcaps; sc->sc_vap_preattach = rtwn_nop_softc_vap; sc->sc_postattach = r88ee_postattach; sc->sc_detach_private = r92c_detach_private; sc->sc_set_media_status = r88e_set_media_status; #ifndef RTWN_WITHOUT_UCODE sc->sc_set_rsvd_page = r88e_set_rsvd_page; sc->sc_set_pwrmode = r88e_set_pwrmode; sc->sc_set_rssi = r92c_set_rssi; #endif sc->sc_beacon_init = r92c_beacon_init; sc->sc_beacon_enable = r88e_beacon_enable; sc->sc_beacon_set_rate = rtwn_nop_void_int; sc->sc_beacon_select = rtwn_nop_softc_int; sc->sc_temp_measure = r88e_temp_measure; sc->sc_temp_read = r88e_temp_read; sc->sc_init_tx_agg = rtwn_nop_softc; sc->sc_init_rx_agg = rtwn_nop_softc; sc->sc_init_ampdu = r92ce_init_ampdu; sc->sc_init_intr = r88ee_init_intr; sc->sc_init_edca = r92ce_init_edca; sc->sc_init_bb = r88ee_init_bb; sc->sc_init_rf = r92c_init_rf; sc->sc_init_antsel = rtwn_nop_softc; sc->sc_post_init = r88ee_post_init; sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc; - sc->sc_set_tx_power = rtwn_nop_int_softc_vap; + sc->sc_set_tx_power = r92c_set_tx_power; sc->mac_prog = &rtl8188e_mac[0]; sc->mac_size = nitems(rtl8188e_mac); sc->bb_prog = &rtl8188e_bb[0]; sc->bb_size = nitems(rtl8188e_bb); sc->agc_prog = &rtl8188e_agc[0]; sc->agc_size = nitems(rtl8188e_agc); sc->rf_prog = &rtl8188e_rf[0]; sc->name = "RTL8188EE"; sc->fwname = "rtwn-rtl8188eefw"; sc->fwsig = 0x88e; sc->page_count = R88EE_TX_PAGE_COUNT; sc->pktbuf_count = R88E_TXPKTBUF_COUNT; sc->ackto = 0x40; sc->npubqpages = R88EE_PUBQ_NPAGES; sc->nhqpages = R88EE_HPQ_NPAGES; sc->nnqpages = R88EE_NPQ_NPAGES; sc->nlqpages = R88EE_LPQ_NPAGES; sc->page_size = R92C_TX_PAGE_SIZE; sc->txdesc_len = sizeof(struct r92ce_tx_desc); sc->efuse_maxlen = R88E_EFUSE_MAX_LEN; sc->efuse_maplen = R88E_EFUSE_MAP_LEN; sc->rx_dma_size = R88E_RX_DMA_BUFFER_SIZE; sc->macid_limit = R88E_MACID_MAX + 1; sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT; sc->fwsize_limit = R92C_MAX_FW_SIZE; sc->temp_delta = R88E_CALIB_THRESHOLD; sc->bcn_status_reg[0] = R92C_TDECTRL; /* * TODO: some additional setup is required * to maintain few beacons at the same time. * * XXX BCNQ1 mechanism is not needed here; move it to the USB module. */ sc->bcn_status_reg[1] = R92C_TDECTRL; sc->rcr = 0; sc->ntxchains = 1; sc->nrxchains = 1; r88ee_attach_private(sc); } diff --git a/sys/dev/rtwn/rtl8188e/r88e_chan.c b/sys/dev/rtwn/rtl8188e/r88e_chan.c index 51474bc1b819..f91862720639 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_chan.c +++ b/sys/dev/rtwn/rtl8188e/r88e_chan.c @@ -1,150 +1,176 @@ /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini * Copyright (c) 2014 Kevin Lo * Copyright (c) 2015-2016 Andriy Voskoboinyk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int r88e_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c) { uint8_t chan; int group; chan = rtwn_chan2centieee(c); if (IEEE80211_IS_CHAN_2GHZ(c)) { if (chan <= 2) group = 0; else if (chan <= 5) group = 1; else if (chan <= 8) group = 2; else if (chan <= 11) group = 3; else if (chan <= 13) group = 4; else if (chan <= 14) group = 5; else { KASSERT(0, ("wrong 2GHz channel %d!\n", chan)); return (-1); } } else { KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags)); return (-1); } return (group); } void r88e_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT]) { + const struct ieee80211com *ic = &sc->sc_ic; struct r92c_softc *rs = sc->sc_priv; const struct rtwn_r88e_txpwr *rt = rs->rs_txpwr; uint8_t cckpow, ofdmpow, bw20pow, htpow = 0; int max_mcs, ridx, group; /* Determine channel group. */ group = r88e_get_power_group(sc, c); if (group == -1) { /* shouldn't happen */ device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__); return; } - /* XXX net80211 regulatory */ + /* + * Treat the entries in 1/2 dBm resolution where 0 = 0dBm. + * Apply the adjustments afterwards; assume that the vendor + * driver is applying offsets to make up for the actual + * target power in dBm. + */ max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); KASSERT(max_mcs <= RTWN_RIDX_LEGACY_HT_COUNT, ("increase ridx limit\n")); /* Compute per-CCK rate Tx power. */ - cckpow = rt->cck_tx_pwr[group]; for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) { - power[ridx] = (ridx == RTWN_RIDX_CCK2) ? cckpow - 9 : cckpow; + /* + * Note: the regulatory limit is applied to cckpow before + * it's subtracted for CCK2. + */ + cckpow = rt->cck_tx_pwr[group]; + if (cckpow > ic->ic_txpowlimit) + cckpow = ic->ic_txpowlimit; + + /* + * If it's CCK2 then we subtract the 9 (4.5dB?) offset + * and make sure we aren't going to underflow. + */ + if (ridx == RTWN_RIDX_CCK2 && cckpow < 9) + cckpow = 0; + else if (ridx == RTWN_RIDX_CCK2) + cckpow = cckpow - 9; + + power[ridx] = cckpow; } if (group < 5) htpow = rt->ht40_tx_pwr[group]; /* Compute per-OFDM rate Tx power. */ ofdmpow = htpow + rt->ofdm_tx_pwr_diff; + if (ofdmpow > ic->ic_txpowlimit) + ofdmpow = ic->ic_txpowlimit; for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) power[ridx] = ofdmpow; bw20pow = htpow + rt->bw20_tx_pwr_diff; + if (bw20pow > ic->ic_txpowlimit) + bw20pow = ic->ic_txpowlimit; for (ridx = RTWN_RIDX_HT_MCS(0); ridx <= max_mcs; ridx++) power[ridx] = bw20pow; - /* Apply max limit. */ + /* Apply max limit */ for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) { if (power[ridx] > R92C_MAX_TX_PWR) power[ridx] = R92C_MAX_TX_PWR; } } void r88e_set_bw20(struct rtwn_softc *sc, uint8_t chan) { struct r92c_softc *rs = sc->sc_priv; rtwn_setbits_1(sc, R92C_BWOPMODE, 0, R92C_BWOPMODE_20MHZ); rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ, 0); rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0); /* Select 20MHz bandwidth. */ rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, (rs->rf_chnlbw[0] & ~0xfff) | chan | R88E_RF_CHNLBW_BW20); } void r88e_set_gain(struct rtwn_softc *sc, uint8_t gain) { rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(0), R92C_OFDM0_AGCCORE1_GAIN_M, gain); } diff --git a/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c b/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c index 400c0a148f35..752761415bce 100644 --- a/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c +++ b/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c @@ -1,226 +1,226 @@ /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini * Copyright (c) 2014 Kevin Lo * Copyright (c) 2015-2016 Andriy Voskoboinyk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* for 'macaddr' field */ #include static struct rtwn_r88e_txpwr r88e_txpwr; void r88eu_attach(struct rtwn_usb_softc *); static void r88eu_set_macaddr(struct rtwn_softc *sc, uint8_t *buf) { struct r88e_rom *rom = (struct r88e_rom *)buf; IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->diff_d0.usb.macaddr); } static void r88e_postattach(struct rtwn_softc *sc) { struct r92c_softc *rs = sc->sc_priv; struct ieee80211com *ic = &sc->sc_ic; rs->rs_scan_start = ic->ic_scan_start; ic->ic_scan_start = r92c_scan_start; rs->rs_scan_end = ic->ic_scan_end; ic->ic_scan_end = r92c_scan_end; } static void r88eu_attach_private(struct rtwn_softc *sc) { struct r92c_softc *rs; rs = malloc(sizeof(struct r92c_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO); rs->rs_txpwr = &r88e_txpwr; rs->rs_txagc = NULL; rs->rs_set_bw20 = r88e_set_bw20; rs->rs_get_txpower = r88e_get_txpower; rs->rs_set_gain = r88e_set_gain; rs->rs_tx_enable_ampdu = r88e_tx_enable_ampdu; rs->rs_tx_setup_hwseq = r88e_tx_setup_hwseq; rs->rs_tx_setup_macid = r88e_tx_setup_macid; rs->rs_set_rom_opts = r88eu_set_macaddr; rs->rf_read_delay[0] = 10; rs->rf_read_delay[1] = 100; rs->rf_read_delay[2] = 10; sc->sc_priv = rs; } static void r88eu_adj_devcaps(struct rtwn_softc *sc) { /* XXX TODO? */ } void r88eu_attach(struct rtwn_usb_softc *uc) { struct rtwn_softc *sc = &uc->uc_sc; /* USB part. */ uc->uc_align_rx = r92cu_align_rx; uc->tx_agg_desc_num = 6; /* Common part. */ sc->sc_flags = RTWN_FLAG_EXT_HDR; sc->sc_set_chan = r92c_set_chan; sc->sc_fill_tx_desc = r92c_fill_tx_desc; sc->sc_fill_tx_desc_raw = r92c_fill_tx_desc_raw; sc->sc_fill_tx_desc_null = r92c_fill_tx_desc_null; sc->sc_dump_tx_desc = r92cu_dump_tx_desc; sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags; sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags; sc->sc_get_rx_stats = r88e_get_rx_stats; sc->sc_get_rssi_cck = r88e_get_rssi_cck; sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; sc->sc_classify_intr = r88e_classify_intr; sc->sc_handle_tx_report = r88e_ratectl_tx_complete; sc->sc_handle_tx_report2 = rtwn_nop_softc_uint8_int; sc->sc_handle_c2h_report = r88e_handle_c2h_report; sc->sc_check_frame = rtwn_nop_int_softc_mbuf; sc->sc_rf_read = r92c_rf_read; sc->sc_rf_write = r88e_rf_write; sc->sc_check_condition = r92c_check_condition; sc->sc_efuse_postread = rtwn_nop_softc; sc->sc_parse_rom = r88e_parse_rom; sc->sc_set_led = r88e_set_led; sc->sc_power_on = r88eu_power_on; sc->sc_power_off = r88eu_power_off; #ifndef RTWN_WITHOUT_UCODE sc->sc_fw_reset = r88e_fw_reset; sc->sc_fw_download_enable = r88e_fw_download_enable; #endif sc->sc_llt_init = r92c_llt_init; sc->sc_set_page_size = r92c_set_page_size; sc->sc_lc_calib = r92c_lc_calib; sc->sc_iq_calib = r88e_iq_calib; sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32; sc->sc_adj_devcaps = r88eu_adj_devcaps; sc->sc_vap_preattach = rtwn_nop_softc_vap; sc->sc_postattach = r88e_postattach; sc->sc_detach_private = r92c_detach_private; sc->sc_set_media_status = r88e_set_media_status; #ifndef RTWN_WITHOUT_UCODE sc->sc_set_rsvd_page = r88e_set_rsvd_page; sc->sc_set_pwrmode = r88e_set_pwrmode; sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO? */ #endif sc->sc_beacon_init = r92c_beacon_init; sc->sc_beacon_enable = r88e_beacon_enable; sc->sc_beacon_set_rate = rtwn_nop_void_int; sc->sc_beacon_select = rtwn_nop_softc_int; sc->sc_temp_measure = r88e_temp_measure; sc->sc_temp_read = r88e_temp_read; sc->sc_init_tx_agg = r92cu_init_tx_agg; sc->sc_init_rx_agg = r88eu_init_rx_agg; sc->sc_init_ampdu = rtwn_nop_softc; sc->sc_init_intr = r88eu_init_intr; sc->sc_init_edca = r92c_init_edca; sc->sc_init_bb = r88eu_init_bb; sc->sc_init_rf = r92c_init_rf; sc->sc_init_antsel = rtwn_nop_softc; sc->sc_post_init = r88eu_post_init; sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc; - sc->sc_set_tx_power = rtwn_nop_int_softc_vap; + sc->sc_set_tx_power = r92c_set_tx_power; sc->mac_prog = &rtl8188e_mac[0]; sc->mac_size = nitems(rtl8188e_mac); sc->bb_prog = &rtl8188e_bb[0]; sc->bb_size = nitems(rtl8188e_bb); sc->agc_prog = &rtl8188e_agc[0]; sc->agc_size = nitems(rtl8188e_agc); sc->rf_prog = &rtl8188e_rf[0]; sc->name = "RTL8188EU"; sc->fwname = "rtwn-rtl8188eufw"; sc->fwsig = 0x88e; sc->page_count = R88EU_TX_PAGE_COUNT; sc->pktbuf_count = R88E_TXPKTBUF_COUNT; sc->ackto = 0x40; sc->npubqpages = R88EU_PUBQ_NPAGES; sc->page_size = R92C_TX_PAGE_SIZE; sc->txdesc_len = sizeof(struct r92cu_tx_desc); sc->efuse_maxlen = R88E_EFUSE_MAX_LEN; sc->efuse_maplen = R88E_EFUSE_MAP_LEN; sc->rx_dma_size = R88E_RX_DMA_BUFFER_SIZE; sc->macid_limit = R88E_MACID_MAX + 1; sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT; sc->fwsize_limit = R92C_MAX_FW_SIZE; sc->temp_delta = R88E_CALIB_THRESHOLD; sc->bcn_status_reg[0] = R92C_TDECTRL; sc->bcn_status_reg[1] = R92C_TDECTRL; sc->rcr = 0; sc->ntxchains = 1; sc->nrxchains = 1; r88eu_attach_private(sc); } diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c b/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c index e992f1c50f26..ddb9fa9ae8c1 100644 --- a/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c +++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c @@ -1,265 +1,265 @@ /* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini * Copyright (c) 2015 Stefan Sperling * Copyright (c) 2016 Andriy Voskoboinyk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct rtwn_r92c_txpwr r92c_txpwr; void r92ce_attach(struct rtwn_pci_softc *); static void r92ce_postattach(struct rtwn_softc *sc) { struct r92c_softc *rs = sc->sc_priv; struct ieee80211com *ic = &sc->sc_ic; if (!(rs->chip & R92C_CHIP_92C) && rs->board_type == R92C_BOARD_TYPE_HIGHPA) rs->rs_txagc = &rtl8188ru_txagc[0]; else rs->rs_txagc = &rtl8192cu_txagc[0]; if ((rs->chip & (R92C_CHIP_UMC_A_CUT | R92C_CHIP_92C)) == R92C_CHIP_UMC_A_CUT) sc->fwname = "rtwn-rtl8192cfwE"; else sc->fwname = "rtwn-rtl8192cfwE_B"; sc->fwsig = 0x88c; rs->rs_scan_start = ic->ic_scan_start; ic->ic_scan_start = r92c_scan_start; rs->rs_scan_end = ic->ic_scan_end; ic->ic_scan_end = r92c_scan_end; } static void r92ce_set_name(struct rtwn_softc *sc, uint8_t *buf) { struct r92c_softc *rs = sc->sc_priv; if (rs->chip & R92C_CHIP_92C) sc->name = "RTL8192CE"; else sc->name = "RTL8188CE"; } static void r92ce_attach_private(struct rtwn_softc *sc) { struct r92c_softc *rs; rs = malloc(sizeof(struct r92c_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO); rs->rs_txpwr = &r92c_txpwr; rs->rs_set_bw20 = r92c_set_bw20; rs->rs_get_txpower = r92c_get_txpower; rs->rs_set_gain = r92c_set_gain; rs->rs_tx_enable_ampdu = r92c_tx_enable_ampdu; rs->rs_tx_setup_hwseq = r92c_tx_setup_hwseq; rs->rs_tx_setup_macid = r92c_tx_setup_macid; rs->rs_set_rom_opts = r92ce_set_name; /* XXX TODO: test with net80211 ratectl! */ #ifndef RTWN_WITHOUT_UCODE rs->rs_c2h_timeout = hz; callout_init_mtx(&rs->rs_c2h_report, &sc->sc_mtx, 0); #endif rs->rf_read_delay[0] = 1000; rs->rf_read_delay[1] = 1000; rs->rf_read_delay[2] = 1000; sc->sc_priv = rs; } static void r92ce_adj_devcaps(struct rtwn_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; /* * XXX do NOT enable PMGT until RSVD_PAGE command * will not be tested / fixed + HRPWM register must be set too. */ ic->ic_caps &= ~IEEE80211_C_PMGT; } void r92ce_attach(struct rtwn_pci_softc *pc) { struct rtwn_softc *sc = &pc->pc_sc; /* PCIe part. */ pc->pc_setup_tx_desc = r92ce_setup_tx_desc; pc->pc_tx_postsetup = r92ce_tx_postsetup; pc->pc_copy_tx_desc = r92ce_copy_tx_desc; pc->pc_enable_intr = r92ce_enable_intr; pc->pc_get_intr_status = r92ce_get_intr_status; pc->pc_qmap = 0xf771; pc->tcr = R92C_TCR_CFENDFORM | (1 << 12) | (1 << 13); /* Common part. */ /* RTL8192C* cannot use pairwise keys from first 4 slots */ sc->sc_flags = RTWN_FLAG_CAM_FIXED; sc->sc_start_xfers = r92ce_start_xfers; sc->sc_set_chan = r92c_set_chan; sc->sc_fill_tx_desc = r92c_fill_tx_desc; sc->sc_fill_tx_desc_raw = r92c_fill_tx_desc_raw; sc->sc_fill_tx_desc_null = r92c_fill_tx_desc_null; /* XXX recheck */ sc->sc_dump_tx_desc = r92ce_dump_tx_desc; sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags; sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags; sc->sc_get_rx_stats = r92c_get_rx_stats; sc->sc_get_rssi_cck = r92c_get_rssi_cck; sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm; sc->sc_classify_intr = r92c_classify_intr; sc->sc_handle_tx_report = rtwn_nop_softc_uint8_int; sc->sc_handle_tx_report2 = rtwn_nop_softc_uint8_int; sc->sc_handle_c2h_report = rtwn_nop_softc_uint8_int; sc->sc_check_frame = rtwn_nop_int_softc_mbuf; sc->sc_rf_read = r92c_rf_read; sc->sc_rf_write = r92c_rf_write; sc->sc_check_condition = r92c_check_condition; sc->sc_efuse_postread = r92c_efuse_postread; sc->sc_parse_rom = r92c_parse_rom; sc->sc_set_led = r92ce_set_led; sc->sc_power_on = r92ce_power_on; sc->sc_power_off = r92ce_power_off; #ifndef RTWN_WITHOUT_UCODE sc->sc_fw_reset = r92ce_fw_reset; sc->sc_fw_download_enable = r92c_fw_download_enable; #endif sc->sc_llt_init = r92c_llt_init; sc->sc_set_page_size = r92c_set_page_size; sc->sc_lc_calib = r92c_lc_calib; sc->sc_iq_calib = r92ce_iq_calib; sc->sc_read_chipid_vendor = r92c_read_chipid_vendor; sc->sc_adj_devcaps = r92ce_adj_devcaps; sc->sc_vap_preattach = rtwn_nop_softc_vap; sc->sc_postattach = r92ce_postattach; sc->sc_detach_private = r92c_detach_private; sc->sc_set_media_status = r92c_joinbss_rpt; #ifndef RTWN_WITHOUT_UCODE sc->sc_set_rsvd_page = r92c_set_rsvd_page; sc->sc_set_pwrmode = r92c_set_pwrmode; sc->sc_set_rssi = r92c_set_rssi; #endif sc->sc_beacon_init = r92c_beacon_init; sc->sc_beacon_enable = r92c_beacon_enable; sc->sc_beacon_set_rate = rtwn_nop_void_int; sc->sc_beacon_select = rtwn_nop_softc_int; sc->sc_temp_measure = r92c_temp_measure; sc->sc_temp_read = r92c_temp_read; sc->sc_init_tx_agg = rtwn_nop_softc; sc->sc_init_rx_agg = rtwn_nop_softc; sc->sc_init_ampdu = r92ce_init_ampdu; sc->sc_init_intr = r92ce_init_intr; sc->sc_init_edca = r92ce_init_edca; sc->sc_init_bb = r92ce_init_bb; sc->sc_init_rf = r92c_init_rf; sc->sc_init_antsel = rtwn_nop_softc; sc->sc_post_init = r92ce_post_init; sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc; - sc->sc_set_tx_power = rtwn_nop_int_softc_vap; + sc->sc_set_tx_power = r92c_set_tx_power; sc->mac_prog = &rtl8192ce_mac[0]; sc->mac_size = nitems(rtl8192ce_mac); sc->bb_prog = &rtl8192ce_bb[0]; sc->bb_size = nitems(rtl8192ce_bb); sc->agc_prog = &rtl8192ce_agc[0]; sc->agc_size = nitems(rtl8192ce_agc); sc->rf_prog = &rtl8192c_rf[0]; sc->page_count = R92CE_TX_PAGE_COUNT; sc->pktbuf_count = R92C_TXPKTBUF_COUNT; sc->ackto = 0x40; sc->npubqpages = R92CE_PUBQ_NPAGES; sc->nhqpages = R92CE_HPQ_NPAGES; sc->nnqpages = 0; sc->nlqpages = R92CE_LPQ_NPAGES; sc->page_size = R92C_TX_PAGE_SIZE; sc->txdesc_len = sizeof(struct r92ce_tx_desc); sc->efuse_maxlen = R92C_EFUSE_MAX_LEN; sc->efuse_maplen = R92C_EFUSE_MAP_LEN; sc->rx_dma_size = R92C_RX_DMA_BUFFER_SIZE; sc->macid_limit = R92C_MACID_MAX + 1; sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT; sc->fwsize_limit = R92C_MAX_FW_SIZE; sc->temp_delta = R92C_CALIB_THRESHOLD; sc->bcn_status_reg[0] = R92C_TDECTRL; /* * TODO: some additional setup is required * to maintain few beacons at the same time. * * XXX BCNQ1 mechanism is not needed here; move it to the USB module. */ sc->bcn_status_reg[1] = R92C_TDECTRL; sc->rcr = 0; r92ce_attach_private(sc); } diff --git a/sys/dev/rtwn/rtl8192c/r92c.h b/sys/dev/rtwn/rtl8192c/r92c.h index 759a946dac3c..c602f314825a 100644 --- a/sys/dev/rtwn/rtl8192c/r92c.h +++ b/sys/dev/rtwn/rtl8192c/r92c.h @@ -1,124 +1,125 @@ /*- * Copyright (c) 2010 Damien Bergamini * Copyright (c) 2015-2016 Andriy Voskoboinyk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ */ #ifndef RTL8192C_H #define RTL8192C_H #include /* * Global definitions. */ #define R92C_TXPKTBUF_COUNT 256 #define R92C_TX_PAGE_SIZE 128 #define R92C_RX_DMA_BUFFER_SIZE 0x2800 #define R92C_MAX_FW_SIZE 0x4000 #define R92C_MACID_MAX 31 #define R92C_CAM_ENTRY_COUNT 32 #define R92C_CALIB_THRESHOLD 2 /* * Function declarations. */ /* r92c_attach.c */ void r92c_detach_private(struct rtwn_softc *); void r92c_read_chipid_vendor(struct rtwn_softc *, uint32_t); /* r92c_beacon.c */ void r92c_beacon_init(struct rtwn_softc *, void *, int); void r92c_beacon_enable(struct rtwn_softc *, int, int); /* r92c_calib.c */ void r92c_iq_calib(struct rtwn_softc *); void r92c_lc_calib(struct rtwn_softc *); void r92c_temp_measure(struct rtwn_softc *); uint8_t r92c_temp_read(struct rtwn_softc *); /* r92c_chan.c */ void r92c_dump_txpower(struct rtwn_softc *, int, uint8_t[RTWN_RIDX_COUNT]); void r92c_get_txpower(struct rtwn_softc *, int, struct ieee80211_channel *, uint8_t[RTWN_RIDX_COUNT]); void r92c_write_txpower(struct rtwn_softc *, int, uint8_t power[RTWN_RIDX_COUNT]); +int r92c_set_tx_power(struct rtwn_softc *, struct ieee80211vap *); void r92c_set_bw20(struct rtwn_softc *, uint8_t); void r92c_set_chan(struct rtwn_softc *, struct ieee80211_channel *); void r92c_set_gain(struct rtwn_softc *, uint8_t); void r92c_scan_start(struct ieee80211com *); void r92c_scan_end(struct ieee80211com *); /* r92c_fw.c */ #ifndef RTWN_WITHOUT_UCODE void r92c_fw_reset(struct rtwn_softc *, int); void r92c_fw_download_enable(struct rtwn_softc *, int); #endif void r92c_joinbss_rpt(struct rtwn_softc *, int); #ifndef RTWN_WITHOUT_UCODE int r92c_set_rsvd_page(struct rtwn_softc *, int, int, int); int r92c_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int); void r92c_set_rssi(struct rtwn_softc *); void r92c_handle_c2h_report(void *); #endif /* r92c_init.c */ int r92c_check_condition(struct rtwn_softc *, const uint8_t[]); int r92c_llt_init(struct rtwn_softc *); int r92c_set_page_size(struct rtwn_softc *); void r92c_init_bb_common(struct rtwn_softc *); int r92c_init_rf_chain(struct rtwn_softc *, const struct rtwn_rf_prog *, int); void r92c_init_rf(struct rtwn_softc *); void r92c_init_edca(struct rtwn_softc *); void r92c_init_ampdu(struct rtwn_softc *); void r92c_init_antsel(struct rtwn_softc *); void r92c_pa_bias_init(struct rtwn_softc *); /* r92c_llt.c */ int r92c_llt_write(struct rtwn_softc *, uint32_t, uint32_t); /* r92c_rf.c */ uint32_t r92c_rf_read(struct rtwn_softc *, int, uint8_t); void r92c_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t); /* r92c_rom.c */ void r92c_efuse_postread(struct rtwn_softc *); void r92c_parse_rom(struct rtwn_softc *, uint8_t *); /* r92c_rx.c */ int r92c_classify_intr(struct rtwn_softc *, void *, int); int8_t r92c_get_rssi_cck(struct rtwn_softc *, void *); int8_t r92c_get_rssi_ofdm(struct rtwn_softc *, void *); uint8_t r92c_rx_radiotap_flags(const void *); void r92c_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *, const void *, const void *); /* r92c_tx.c */ void r92c_tx_enable_ampdu(void *, int); void r92c_tx_setup_hwseq(void *); void r92c_tx_setup_macid(void *, int); void r92c_fill_tx_desc(struct rtwn_softc *, struct ieee80211_node *, struct mbuf *, void *, uint8_t, int); void r92c_fill_tx_desc_raw(struct rtwn_softc *, struct ieee80211_node *, struct mbuf *, void *, const struct ieee80211_bpf_params *); void r92c_fill_tx_desc_null(struct rtwn_softc *, void *, int, int, int); uint8_t r92c_tx_radiotap_flags(const void *); #endif /* RTL8192C_H */ diff --git a/sys/dev/rtwn/rtl8192c/r92c_chan.c b/sys/dev/rtwn/rtl8192c/r92c_chan.c index 5404ad4a81bf..f93159a3c94e 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_chan.c +++ b/sys/dev/rtwn/rtl8192c/r92c_chan.c @@ -1,389 +1,418 @@ /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini * Copyright (c) 2014 Kevin Lo * Copyright (c) 2016 Andriy Voskoboinyk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void r92c_dump_txpower(struct rtwn_softc *sc, int chain, uint8_t power[RTWN_RIDX_COUNT]) { #ifdef RTWN_DEBUG if (sc->sc_debug & RTWN_DEBUG_TXPWR) { int i; /* Print CCK */ RTWN_DPRINTF(sc, RTWN_DEBUG_TXPWR, "TX [%d]: CCK: 1M: %d 2M: %d 5.5M: %d 11M: %d\n", chain, power[RTWN_RIDX_CCK1], power[RTWN_RIDX_CCK2], power[RTWN_RIDX_CCK55], power[RTWN_RIDX_CCK11]); /* Print OFDM */ RTWN_DPRINTF(sc, RTWN_DEBUG_TXPWR, "TX [%d]: OFDM: 6M: %d 9M: %d 12M: %d 18M: %d 24M: %d " "36M: %d 48M: %d 54M: %d\n", chain, power[RTWN_RIDX_OFDM6], power[RTWN_RIDX_OFDM9], power[RTWN_RIDX_OFDM12], power[RTWN_RIDX_OFDM18], power[RTWN_RIDX_OFDM24], power[RTWN_RIDX_OFDM36], power[RTWN_RIDX_OFDM48], power[RTWN_RIDX_OFDM54]); /* Print HT, 1 and 2 stream */ for (i = 0; i < sc->ntxchains; i++) { RTWN_DPRINTF(sc, RTWN_DEBUG_TXPWR, "TX [%d]: MCS%d-%d: %d %d %d %d %d %d %d %d\n", chain, i * 8, i * 8 + 7, power[RTWN_RIDX_HT_MCS(i * 8 + 0)], power[RTWN_RIDX_HT_MCS(i * 8 + 1)], power[RTWN_RIDX_HT_MCS(i * 8 + 2)], power[RTWN_RIDX_HT_MCS(i * 8 + 3)], power[RTWN_RIDX_HT_MCS(i * 8 + 4)], power[RTWN_RIDX_HT_MCS(i * 8 + 5)], power[RTWN_RIDX_HT_MCS(i * 8 + 6)], power[RTWN_RIDX_HT_MCS(i * 8 + 7)]); } } #endif } static int r92c_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c) { uint8_t chan; int group; chan = rtwn_chan2centieee(c); if (IEEE80211_IS_CHAN_2GHZ(c)) { if (chan <= 3) group = 0; else if (chan <= 9) group = 1; else if (chan <= 14) group = 2; else { KASSERT(0, ("wrong 2GHz channel %d!\n", chan)); return (-1); } } else { KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags)); return (-1); } return (group); } /* XXX recheck */ void r92c_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT]) { + const struct ieee80211com *ic = &sc->sc_ic; struct r92c_softc *rs = sc->sc_priv; struct rtwn_r92c_txpwr *rt = rs->rs_txpwr; const struct rtwn_r92c_txagc *base = rs->rs_txagc; uint8_t ofdmpow, htpow, diff, max; int max_mcs, ridx, group; /* Determine channel group. */ group = r92c_get_power_group(sc, c); if (group == -1) { /* shouldn't happen */ device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__); return; } - /* XXX net80211 regulatory */ + /* + * Treat the entries in 1/2 dBm resolution where 0 = 0dBm. + * Apply the adjustments afterwards; assume that the vendor + * driver is applying offsets to make up for the actual + * target power in dBm. + */ max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); KASSERT(max_mcs <= RTWN_RIDX_LEGACY_HT_COUNT, ("increase ridx limit\n")); if (rs->regulatory == 0) { for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) power[ridx] = base[chain].pwr[0][ridx]; } for (ridx = RTWN_RIDX_OFDM6; ridx < RTWN_RIDX_LEGACY_HT_COUNT; ridx++) { if (rs->regulatory == 3) { power[ridx] = base[chain].pwr[0][ridx]; /* Apply vendor limits. */ if (IEEE80211_IS_CHAN_HT40(c)) max = rt->ht40_max_pwr[chain][group]; else max = rt->ht20_max_pwr[chain][group]; if (power[ridx] > max) power[ridx] = max; } else if (rs->regulatory == 1) { if (!IEEE80211_IS_CHAN_HT40(c)) power[ridx] = base[chain].pwr[group][ridx]; } else if (rs->regulatory != 2) power[ridx] = base[chain].pwr[0][ridx]; } /* Compute per-CCK rate Tx power. */ for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) power[ridx] += rt->cck_tx_pwr[chain][group]; htpow = rt->ht40_1s_tx_pwr[chain][group]; if (sc->ntxchains > 1) { /* Apply reduction for 2 spatial streams. */ diff = rt->ht40_2s_tx_pwr_diff[chain][group]; htpow = (htpow > diff) ? htpow - diff : 0; } /* Compute per-OFDM rate Tx power. */ diff = rt->ofdm_tx_pwr_diff[chain][group]; ofdmpow = htpow + diff; /* HT->OFDM correction. */ for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) power[ridx] += ofdmpow; /* Compute per-MCS Tx power. */ if (!IEEE80211_IS_CHAN_HT40(c)) { diff = rt->ht20_tx_pwr_diff[chain][group]; htpow += diff; /* HT40->HT20 correction. */ } for (ridx = RTWN_RIDX_HT_MCS(0); ridx <= max_mcs; ridx++) power[ridx] += htpow; /* Apply max limit. */ for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) { if (power[ridx] > R92C_MAX_TX_PWR) power[ridx] = R92C_MAX_TX_PWR; + /* Apply net80211 limits */ + if (power[ridx] > ic->ic_txpowlimit) + power[ridx] = ic->ic_txpowlimit; + } } void r92c_write_txpower(struct rtwn_softc *sc, int chain, uint8_t power[RTWN_RIDX_COUNT]) { uint32_t reg; /* Write per-CCK rate Tx power. */ if (chain == 0) { reg = rtwn_bb_read(sc, R92C_TXAGC_A_CCK1_MCS32); reg = RW(reg, R92C_TXAGC_A_CCK1, power[RTWN_RIDX_CCK1]); rtwn_bb_write(sc, R92C_TXAGC_A_CCK1_MCS32, reg); reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11); reg = RW(reg, R92C_TXAGC_A_CCK2, power[RTWN_RIDX_CCK2]); reg = RW(reg, R92C_TXAGC_A_CCK55, power[RTWN_RIDX_CCK55]); reg = RW(reg, R92C_TXAGC_A_CCK11, power[RTWN_RIDX_CCK11]); rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg); } else { reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK1_55_MCS32); reg = RW(reg, R92C_TXAGC_B_CCK1, power[RTWN_RIDX_CCK1]); reg = RW(reg, R92C_TXAGC_B_CCK2, power[RTWN_RIDX_CCK2]); reg = RW(reg, R92C_TXAGC_B_CCK55, power[RTWN_RIDX_CCK55]); rtwn_bb_write(sc, R92C_TXAGC_B_CCK1_55_MCS32, reg); reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11); reg = RW(reg, R92C_TXAGC_B_CCK11, power[RTWN_RIDX_CCK11]); rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg); } /* Write per-OFDM rate Tx power. */ rtwn_bb_write(sc, R92C_TXAGC_RATE18_06(chain), SM(R92C_TXAGC_RATE06, power[RTWN_RIDX_OFDM6]) | SM(R92C_TXAGC_RATE09, power[RTWN_RIDX_OFDM9]) | SM(R92C_TXAGC_RATE12, power[RTWN_RIDX_OFDM12]) | SM(R92C_TXAGC_RATE18, power[RTWN_RIDX_OFDM18])); rtwn_bb_write(sc, R92C_TXAGC_RATE54_24(chain), SM(R92C_TXAGC_RATE24, power[RTWN_RIDX_OFDM24]) | SM(R92C_TXAGC_RATE36, power[RTWN_RIDX_OFDM36]) | SM(R92C_TXAGC_RATE48, power[RTWN_RIDX_OFDM48]) | SM(R92C_TXAGC_RATE54, power[RTWN_RIDX_OFDM54])); /* Write per-MCS Tx power. */ rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain), SM(R92C_TXAGC_MCS00, power[RTWN_RIDX_HT_MCS(0)]) | SM(R92C_TXAGC_MCS01, power[RTWN_RIDX_HT_MCS(1)]) | SM(R92C_TXAGC_MCS02, power[RTWN_RIDX_HT_MCS(2)]) | SM(R92C_TXAGC_MCS03, power[RTWN_RIDX_HT_MCS(3)])); rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain), SM(R92C_TXAGC_MCS04, power[RTWN_RIDX_HT_MCS(4)]) | SM(R92C_TXAGC_MCS05, power[RTWN_RIDX_HT_MCS(5)]) | SM(R92C_TXAGC_MCS06, power[RTWN_RIDX_HT_MCS(6)]) | SM(R92C_TXAGC_MCS07, power[RTWN_RIDX_HT_MCS(7)])); if (sc->ntxchains >= 2) { rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain), SM(R92C_TXAGC_MCS08, power[RTWN_RIDX_HT_MCS(8)]) | SM(R92C_TXAGC_MCS09, power[RTWN_RIDX_HT_MCS(9)]) | SM(R92C_TXAGC_MCS10, power[RTWN_RIDX_HT_MCS(10)]) | SM(R92C_TXAGC_MCS11, power[RTWN_RIDX_HT_MCS(11)])); rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain), SM(R92C_TXAGC_MCS12, power[RTWN_RIDX_HT_MCS(12)]) | SM(R92C_TXAGC_MCS13, power[RTWN_RIDX_HT_MCS(13)]) | SM(R92C_TXAGC_MCS14, power[RTWN_RIDX_HT_MCS(14)]) | SM(R92C_TXAGC_MCS15, power[RTWN_RIDX_HT_MCS(15)])); } } static void r92c_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c) { uint8_t power[RTWN_RIDX_COUNT]; int i; for (i = 0; i < sc->ntxchains; i++) { memset(power, 0, sizeof(power)); /* Compute per-rate Tx power values. */ rtwn_r92c_get_txpower(sc, i, c, power); /* Optionally print out the power table */ r92c_dump_txpower(sc, i, power); /* Write per-rate Tx power values to hardware. */ r92c_write_txpower(sc, i, power); } } +/* + * Only reconfigure the transmit power if there's a valid BSS node and + * channel. Otherwise just let the next call to r92c_set_chan() + * configure the transmit power. + */ +int +r92c_set_tx_power(struct rtwn_softc *sc, struct ieee80211vap *vap) +{ + if (vap->iv_bss == NULL) + return (EINVAL); + if (vap->iv_bss->ni_chan == IEEE80211_CHAN_ANYC) + return (EINVAL); + + /* Set it for the current channel */ + r92c_set_txpower(sc, vap->iv_bss->ni_chan); + + return (0); +} + static void r92c_set_bw40(struct rtwn_softc *sc, uint8_t chan, int prichlo) { struct r92c_softc *rs = sc->sc_priv; rtwn_setbits_1(sc, R92C_BWOPMODE, R92C_BWOPMODE_20MHZ, 0); rtwn_setbits_1(sc, R92C_RRSR + 2, 0x6f, (prichlo ? 1 : 2) << 5); rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_40MHZ); rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, 0, R92C_RFMOD_40MHZ); /* Set CCK side band. */ rtwn_bb_setbits(sc, R92C_CCK0_SYSTEM, 0x10, (prichlo ? 0 : 1) << 4); rtwn_bb_setbits(sc, R92C_OFDM1_LSTF, 0x0c00, (prichlo ? 1 : 2) << 10); rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2, R92C_FPGA0_ANAPARAM2_CBW20, 0); rtwn_bb_setbits(sc, R92C_FPGA0_POWER_SAVE, R92C_FPGA0_POWER_SAVE_PS_MASK, (prichlo ? 2 : 1) << 26); /* Select 40MHz bandwidth. */ rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, (rs->rf_chnlbw[0] & ~0xfff) | chan); } void r92c_set_bw20(struct rtwn_softc *sc, uint8_t chan) { struct r92c_softc *rs = sc->sc_priv; rtwn_setbits_1(sc, R92C_BWOPMODE, 0, R92C_BWOPMODE_20MHZ); rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ, 0); rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0); rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2, 0, R92C_FPGA0_ANAPARAM2_CBW20); /* Select 20MHz bandwidth. */ rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, (rs->rf_chnlbw[0] & ~0xfff) | chan | R92C_RF_CHNLBW_BW20); } void r92c_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c) { struct r92c_softc *rs = sc->sc_priv; u_int chan; int i; chan = rtwn_chan2centieee(c); /* Set Tx power for this new channel. */ r92c_set_txpower(sc, c); for (i = 0; i < sc->nrxchains; i++) { rtwn_rf_write(sc, i, R92C_RF_CHNLBW, RW(rs->rf_chnlbw[i], R92C_RF_CHNLBW_CHNL, chan)); } if (IEEE80211_IS_CHAN_HT40(c)) r92c_set_bw40(sc, chan, IEEE80211_IS_CHAN_HT40U(c)); else rtwn_r92c_set_bw20(sc, chan); } void r92c_set_gain(struct rtwn_softc *sc, uint8_t gain) { rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(0), R92C_OFDM0_AGCCORE1_GAIN_M, gain); rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(1), R92C_OFDM0_AGCCORE1_GAIN_M, gain); } void r92c_scan_start(struct ieee80211com *ic) { struct rtwn_softc *sc = ic->ic_softc; struct r92c_softc *rs = sc->sc_priv; RTWN_LOCK(sc); /* Set gain for scanning. */ rtwn_r92c_set_gain(sc, 0x20); RTWN_UNLOCK(sc); rs->rs_scan_start(ic); } void r92c_scan_end(struct ieee80211com *ic) { struct rtwn_softc *sc = ic->ic_softc; struct r92c_softc *rs = sc->sc_priv; RTWN_LOCK(sc); /* Set gain under link. */ rtwn_r92c_set_gain(sc, 0x32); RTWN_UNLOCK(sc); rs->rs_scan_end(ic); } diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c b/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c index 6482c933eec2..8e9c4987a359 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c @@ -1,246 +1,246 @@ /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini * Copyright (c) 2014 Kevin Lo * Copyright (c) 2016 Andriy Voskoboinyk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct rtwn_r92c_txpwr r92c_txpwr; void r92cu_attach(struct rtwn_usb_softc *); static void r92cu_postattach(struct rtwn_softc *sc) { struct r92c_softc *rs = sc->sc_priv; struct ieee80211com *ic = &sc->sc_ic; if (!(rs->chip & R92C_CHIP_92C) && rs->board_type == R92C_BOARD_TYPE_HIGHPA) { sc->agc_prog = &rtl8188ru_agc[0]; sc->agc_size = nitems(rtl8188ru_agc); rs->rs_txagc = &rtl8188ru_txagc[0]; } else { sc->agc_prog = &rtl8192ce_agc[0]; sc->agc_size = nitems(rtl8192ce_agc); rs->rs_txagc = &rtl8192cu_txagc[0]; } if ((rs->chip & (R92C_CHIP_UMC_A_CUT | R92C_CHIP_92C)) == R92C_CHIP_UMC_A_CUT) { sc->fwname = "rtwn-rtl8192cfwU"; } else { sc->fwname = "rtwn-rtl8192cfwT"; } sc->fwsig = 0x88c; rs->rs_scan_start = ic->ic_scan_start; ic->ic_scan_start = r92c_scan_start; rs->rs_scan_end = ic->ic_scan_end; ic->ic_scan_end = r92c_scan_end; } static void r92cu_set_name(struct rtwn_softc *sc, uint8_t *buf) { struct r92c_softc *rs = sc->sc_priv; if (!(rs->chip & R92C_CHIP_92C)) { if (rs->board_type == R92C_BOARD_TYPE_HIGHPA) sc->name = "RTL8188RU"; else if (rs->board_type == R92C_BOARD_TYPE_MINICARD) sc->name = "RTL8188CU-VAU"; else sc->name = "RTL8188CUS"; } else sc->name = "RTL8192CU"; } static void r92cu_attach_private(struct rtwn_softc *sc) { struct r92c_softc *rs; rs = malloc(sizeof(struct r92c_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO); rs->rs_txpwr = &r92c_txpwr; rs->rs_set_bw20 = r92c_set_bw20; rs->rs_get_txpower = r92c_get_txpower; rs->rs_set_gain = r92c_set_gain; rs->rs_tx_enable_ampdu = r92c_tx_enable_ampdu; rs->rs_tx_setup_hwseq = r92c_tx_setup_hwseq; rs->rs_tx_setup_macid = r92c_tx_setup_macid; rs->rs_set_rom_opts = r92cu_set_name; #ifndef RTWN_WITHOUT_UCODE rs->rs_c2h_timeout = hz; callout_init_mtx(&rs->rs_c2h_report, &sc->sc_mtx, 0); #endif rs->rf_read_delay[0] = 10; rs->rf_read_delay[1] = 100; rs->rf_read_delay[2] = 10; sc->sc_priv = rs; } static void r92cu_adj_devcaps(struct rtwn_softc *sc) { /* XXX Currently broken / incomplete. */ sc->sc_ic.ic_caps &= ~IEEE80211_C_PMGT; } void r92cu_attach(struct rtwn_usb_softc *uc) { struct rtwn_softc *sc = &uc->uc_sc; /* USB part. */ uc->uc_align_rx = r92cu_align_rx; uc->tx_agg_desc_num = 6; /* Common part. */ sc->sc_flags = RTWN_FLAG_CAM_FIXED; sc->sc_set_chan = r92c_set_chan; sc->sc_fill_tx_desc = r92c_fill_tx_desc; sc->sc_fill_tx_desc_raw = r92c_fill_tx_desc_raw; sc->sc_fill_tx_desc_null = r92c_fill_tx_desc_null; sc->sc_dump_tx_desc = r92cu_dump_tx_desc; sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags; sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags; sc->sc_get_rx_stats = r92c_get_rx_stats; sc->sc_get_rssi_cck = r92c_get_rssi_cck; sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm; sc->sc_classify_intr = r92c_classify_intr; sc->sc_handle_tx_report = rtwn_nop_softc_uint8_int; sc->sc_handle_tx_report2 = rtwn_nop_softc_uint8_int; sc->sc_handle_c2h_report = rtwn_nop_softc_uint8_int; sc->sc_check_frame = rtwn_nop_int_softc_mbuf; sc->sc_rf_read = r92c_rf_read; sc->sc_rf_write = r92c_rf_write; sc->sc_check_condition = r92c_check_condition; sc->sc_efuse_postread = r92c_efuse_postread; sc->sc_parse_rom = r92c_parse_rom; sc->sc_set_led = r92cu_set_led; sc->sc_power_on = r92cu_power_on; sc->sc_power_off = r92cu_power_off; #ifndef RTWN_WITHOUT_UCODE sc->sc_fw_reset = r92c_fw_reset; sc->sc_fw_download_enable = r92c_fw_download_enable; #endif sc->sc_llt_init = r92c_llt_init; sc->sc_set_page_size = r92c_set_page_size; sc->sc_lc_calib = r92c_lc_calib; sc->sc_iq_calib = r92c_iq_calib; sc->sc_read_chipid_vendor = r92c_read_chipid_vendor; sc->sc_adj_devcaps = r92cu_adj_devcaps; sc->sc_vap_preattach = rtwn_nop_softc_vap; sc->sc_postattach = r92cu_postattach; sc->sc_detach_private = r92c_detach_private; sc->sc_set_media_status = r92c_joinbss_rpt; #ifndef RTWN_WITHOUT_UCODE sc->sc_set_rsvd_page = r92c_set_rsvd_page; sc->sc_set_pwrmode = r92c_set_pwrmode; sc->sc_set_rssi = r92c_set_rssi; #endif sc->sc_beacon_init = r92c_beacon_init; sc->sc_beacon_enable = r92c_beacon_enable; sc->sc_beacon_set_rate = rtwn_nop_void_int; sc->sc_beacon_select = rtwn_nop_softc_int; sc->sc_temp_measure = r92c_temp_measure; sc->sc_temp_read = r92c_temp_read; sc->sc_init_tx_agg = r92cu_init_tx_agg; sc->sc_init_rx_agg = r92cu_init_rx_agg; sc->sc_init_ampdu = r92c_init_ampdu; sc->sc_init_intr = r92cu_init_intr; sc->sc_init_edca = r92c_init_edca; sc->sc_init_bb = r92cu_init_bb; sc->sc_init_rf = r92c_init_rf; sc->sc_init_antsel = r92c_init_antsel; sc->sc_post_init = r92cu_post_init; sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc; - sc->sc_set_tx_power = rtwn_nop_int_softc_vap; + sc->sc_set_tx_power = r92c_set_tx_power; sc->mac_prog = &rtl8192cu_mac[0]; sc->mac_size = nitems(rtl8192cu_mac); sc->bb_prog = &rtl8192cu_bb[0]; sc->bb_size = nitems(rtl8192cu_bb); sc->rf_prog = &rtl8192c_rf[0]; sc->page_count = R92CU_TX_PAGE_COUNT; sc->pktbuf_count = R92C_TXPKTBUF_COUNT; sc->ackto = 0x40; sc->npubqpages = R92CU_PUBQ_NPAGES; sc->page_size = R92C_TX_PAGE_SIZE; sc->txdesc_len = sizeof(struct r92cu_tx_desc); sc->efuse_maxlen = R92C_EFUSE_MAX_LEN; sc->efuse_maplen = R92C_EFUSE_MAP_LEN; sc->rx_dma_size = R92C_RX_DMA_BUFFER_SIZE; sc->macid_limit = R92C_MACID_MAX + 1; sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT; sc->fwsize_limit = R92C_MAX_FW_SIZE; sc->temp_delta = R92C_CALIB_THRESHOLD; sc->bcn_status_reg[0] = R92C_TDECTRL; sc->bcn_status_reg[1] = R92C_TDECTRL; sc->rcr = 0; r92cu_attach_private(sc); } diff --git a/sys/dev/rtwn/rtl8192e/r92e.h b/sys/dev/rtwn/rtl8192e/r92e.h index 331750c48726..280cc1464ac6 100644 --- a/sys/dev/rtwn/rtl8192e/r92e.h +++ b/sys/dev/rtwn/rtl8192e/r92e.h @@ -1,79 +1,80 @@ /*- * Copyright (c) 2017 Kevin Lo * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef RTL8192E_H #define RTL8192E_H /* * Global definitions. */ #define R92E_PUBQ_NPAGES 222 #define R92E_TX_PAGE_COUNT 243 #define R92E_TX_PAGE_SIZE 256 #define R92E_RX_DMA_BUFFER_SIZE 0x3d00 #define R92E_MAX_FW_SIZE 0x8000 /* * Function declarations. */ /* r92e_attach.c */ void r92e_detach_private(struct rtwn_softc *); /* r92e_chan.c */ void r92e_set_chan(struct rtwn_softc *, struct ieee80211_channel *); +int r92e_set_tx_power(struct rtwn_softc *sc, struct ieee80211vap *vap); /* r92e_fw.c */ #ifndef RTWN_WITHOUT_UCODE void r92e_fw_reset(struct rtwn_softc *, int); void r92e_set_media_status(struct rtwn_softc *, int); int r92e_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int); #endif /* r92e_init.c */ int r92e_llt_init(struct rtwn_softc *); void r92e_init_bb(struct rtwn_softc *); void r92e_init_rf(struct rtwn_softc *); int r92e_power_on(struct rtwn_softc *); void r92e_power_off(struct rtwn_softc *); /* r92e_led.c */ void r92e_set_led(struct rtwn_softc *, int, int); /* r92e_rf.c */ uint32_t r92e_rf_read(struct rtwn_softc *, int, uint8_t); void r92e_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t); /* r92e_rom.c */ void r92e_parse_rom_common(struct rtwn_softc *, uint8_t *); void r92e_parse_rom(struct rtwn_softc *, uint8_t *); /* r92e_rx.c */ void r92e_handle_c2h_report(struct rtwn_softc *, uint8_t *, int); int8_t r92e_get_rssi_cck(struct rtwn_softc *, void *); #endif /* RTL8192E_H */ diff --git a/sys/dev/rtwn/rtl8192e/r92e_chan.c b/sys/dev/rtwn/rtl8192e/r92e_chan.c index 4c761f61809d..4c7121a80c89 100644 --- a/sys/dev/rtwn/rtl8192e/r92e_chan.c +++ b/sys/dev/rtwn/rtl8192e/r92e_chan.c @@ -1,223 +1,255 @@ /*- * Copyright (c) 2017 Kevin Lo * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int r92e_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c) { uint8_t chan; int group; chan = rtwn_chan2centieee(c); if (IEEE80211_IS_CHAN_2GHZ(c)) { if (chan <= 2) group = 0; else if (chan <= 5) group = 1; else if (chan <= 8) group = 2; else if (chan <= 11) group = 3; else if (chan <= 14) group = 4; else { KASSERT(0, ("wrong 2GHz channel %d!\n", chan)); return (-1); } } else { KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags)); return (-1); } return (group); } static void r92e_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT]) { + const struct ieee80211com *ic = &sc->sc_ic; struct r92e_softc *rs = sc->sc_priv; int i, ridx, group, max_mcs; /* Determine channel group. */ group = r92e_get_power_group(sc, c); if (group == -1) { /* shouldn't happen */ device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__); return; } max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); /* XXX regulatory */ - /* XXX net80211 regulatory */ - for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) + for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) { power[ridx] = rs->cck_tx_pwr[chain][group]; - for (ridx = RTWN_RIDX_OFDM6; ridx <= max_mcs; ridx++) + if (power[ridx] > ic->ic_txpowlimit) + power[ridx] = ic->ic_txpowlimit; + } + for (ridx = RTWN_RIDX_OFDM6; ridx <= max_mcs; ridx++) { power[ridx] = rs->ht40_tx_pwr_2g[chain][group]; + if (power[ridx] > ic->ic_txpowlimit) + power[ridx] = ic->ic_txpowlimit; + } + + for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) { + /* Ensure we don't underflow if the power delta is -ve */ + int8_t pwr; - for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) - power[ridx] += rs->ofdm_tx_pwr_diff_2g[chain][0]; + pwr = power[ridx] + rs->ofdm_tx_pwr_diff_2g[chain][0]; + if (pwr < 0) + pwr = 0; + + power[ridx] = pwr; + } for (i = 0; i < sc->ntxchains; i++) { uint8_t min_mcs; - uint8_t pwr_diff; + int8_t pwr_diff, pwr; if (IEEE80211_IS_CHAN_HT40(c)) pwr_diff = rs->bw40_tx_pwr_diff_2g[chain][i]; else pwr_diff = rs->bw20_tx_pwr_diff_2g[chain][i]; min_mcs = RTWN_RIDX_HT_MCS(i * 8); - for (ridx = min_mcs; ridx <= max_mcs; ridx++) - power[ridx] += pwr_diff; + for (ridx = min_mcs; ridx <= max_mcs; ridx++) { + /* Ensure we don't underflow */ + pwr = power[ridx] + pwr_diff; + if (pwr < 0) + pwr = 0; + power[ridx] = pwr; + } } /* Apply max limit. */ for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) { if (power[ridx] > R92C_MAX_TX_PWR) power[ridx] = R92C_MAX_TX_PWR; } } static void r92e_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c) { uint8_t power[RTWN_RIDX_COUNT]; int i; for (i = 0; i < sc->ntxchains; i++) { memset(power, 0, sizeof(power)); /* Compute per-rate Tx power values. */ r92e_get_txpower(sc, i, c, power); /* Optionally print out the power table */ r92c_dump_txpower(sc, i, power); /* Write per-rate Tx power values to hardware. */ r92c_write_txpower(sc, i, power); } } +int +r92e_set_tx_power(struct rtwn_softc *sc, struct ieee80211vap *vap) +{ + + if (vap->iv_bss == NULL) + return (EINVAL); + if (vap->iv_bss->ni_chan == IEEE80211_CHAN_ANYC) + return (EINVAL); + + r92e_set_txpower(sc, vap->iv_bss->ni_chan); + return (0); +} + static void r92e_set_bw40(struct rtwn_softc *sc, uint8_t chan, int prichlo) { int i; rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x100, 0x80); rtwn_write_1(sc, R12A_DATA_SEC, prichlo ? R12A_DATA_SEC_PRIM_DOWN_20 : R12A_DATA_SEC_PRIM_UP_20); rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_40MHZ); rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, 0, R92C_RFMOD_40MHZ); /* Select 40MHz bandwidth. */ for (i = 0; i < sc->nrxchains; i++) rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW, R88E_RF_CHNLBW_BW20, 0x400); /* Set CCK side band. */ rtwn_bb_setbits(sc, R92C_CCK0_SYSTEM, R92C_CCK0_SYSTEM_CCK_SIDEBAND, (prichlo ? 0 : 1) << 4); rtwn_bb_setbits(sc, R92C_OFDM1_LSTF, 0x0c00, (prichlo ? 1 : 2) << 10); rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2, R92C_FPGA0_ANAPARAM2_CBW20, 0); rtwn_bb_setbits(sc, 0x818, 0x0c000000, (prichlo ? 2 : 1) << 26); } static void r92e_set_bw20(struct rtwn_softc *sc, uint8_t chan) { int i; rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x180, 0); rtwn_write_1(sc, R12A_DATA_SEC, R12A_DATA_SEC_NO_EXT); rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ, 0); rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0); /* Select 20MHz bandwidth. */ for (i = 0; i < sc->nrxchains; i++) rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW, R88E_RF_CHNLBW_BW20, 0xc00); rtwn_bb_setbits(sc, R92C_OFDM0_TXPSEUDONOISEWGT, 0xc0000000, 0); } void r92e_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c) { struct r92e_softc *rs = sc->sc_priv; u_int chan; int i; chan = rtwn_chan2centieee(c); for (i = 0; i < sc->nrxchains; i++) { rtwn_rf_write(sc, i, R92C_RF_CHNLBW, RW(rs->rf_chnlbw[0], R92C_RF_CHNLBW_CHNL, chan)); } if (IEEE80211_IS_CHAN_HT40(c)) r92e_set_bw40(sc, chan, IEEE80211_IS_CHAN_HT40U(c)); else r92e_set_bw20(sc, chan); /* Set Tx power for this new channel. */ r92e_set_txpower(sc, c); } diff --git a/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c b/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c index c134ba22a430..35ff5cb65853 100644 --- a/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c +++ b/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c @@ -1,204 +1,204 @@ /*- * Copyright (c) 2017 Kevin Lo * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void r92eu_attach(struct rtwn_usb_softc *); static void r92eu_attach_private(struct rtwn_softc *sc) { struct r92e_softc *rs; rs = malloc(sizeof(struct r92e_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO); rs->ac_usb_dma_size = 0x06; rs->ac_usb_dma_time = 0x20; sc->sc_priv = rs; } void r92e_detach_private(struct rtwn_softc *sc) { struct r92e_softc *rs = sc->sc_priv; free(rs, M_RTWN_PRIV); } static void r92eu_adj_devcaps(struct rtwn_softc *sc) { /* XXX TODO? */ } void r92eu_attach(struct rtwn_usb_softc *uc) { struct rtwn_softc *sc = &uc->uc_sc; /* USB part. */ uc->uc_align_rx = r12au_align_rx; uc->tx_agg_desc_num = 3; /* Common part. */ sc->sc_flags = RTWN_FLAG_EXT_HDR; sc->sc_set_chan = r92e_set_chan; sc->sc_fill_tx_desc = r12a_fill_tx_desc; sc->sc_fill_tx_desc_raw = r12a_fill_tx_desc_raw; sc->sc_fill_tx_desc_null = r12a_fill_tx_desc_null; sc->sc_dump_tx_desc = r12au_dump_tx_desc; sc->sc_tx_radiotap_flags = r12a_tx_radiotap_flags; sc->sc_rx_radiotap_flags = r12a_rx_radiotap_flags; sc->sc_get_rx_stats = r12a_get_rx_stats; sc->sc_get_rssi_cck = r92e_get_rssi_cck; sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; sc->sc_classify_intr = r12au_classify_intr; sc->sc_handle_tx_report = r12a_ratectl_tx_complete; sc->sc_handle_tx_report2 = rtwn_nop_softc_uint8_int; sc->sc_handle_c2h_report = r92e_handle_c2h_report; sc->sc_check_frame = rtwn_nop_int_softc_mbuf; sc->sc_rf_read = r92e_rf_read; sc->sc_rf_write = r92e_rf_write; sc->sc_check_condition = r92c_check_condition; sc->sc_efuse_postread = rtwn_nop_softc; sc->sc_parse_rom = r92e_parse_rom; sc->sc_set_led = r92e_set_led; sc->sc_power_on = r92e_power_on; sc->sc_power_off = r92e_power_off; #ifndef RTWN_WITHOUT_UCODE sc->sc_fw_reset = r92e_fw_reset; sc->sc_fw_download_enable = r12a_fw_download_enable; #endif sc->sc_llt_init = r92e_llt_init; sc->sc_set_page_size = rtwn_nop_int_softc; sc->sc_lc_calib = r92c_lc_calib; sc->sc_iq_calib = rtwn_nop_softc; /* XXX TODO */ sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32; sc->sc_adj_devcaps = r92eu_adj_devcaps; sc->sc_vap_preattach = rtwn_nop_softc_vap; sc->sc_postattach = rtwn_nop_softc; sc->sc_detach_private = r92e_detach_private; #ifndef RTWN_WITHOUT_UCODE sc->sc_set_media_status = r92e_set_media_status; sc->sc_set_rsvd_page = r88e_set_rsvd_page; sc->sc_set_pwrmode = r92e_set_pwrmode; sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO? */ #else sc->sc_set_media_status = rtwn_nop_softc_int; #endif sc->sc_beacon_init = r12a_beacon_init; sc->sc_beacon_enable = r92c_beacon_enable; sc->sc_beacon_set_rate = rtwn_nop_void_int; sc->sc_beacon_select = r21a_beacon_select; sc->sc_temp_measure = r88e_temp_measure; sc->sc_temp_read = r88e_temp_read; sc->sc_init_tx_agg = r21au_init_tx_agg; sc->sc_init_rx_agg = r92eu_init_rx_agg; sc->sc_init_ampdu = rtwn_nop_softc; sc->sc_init_intr = r12a_init_intr; sc->sc_init_edca = r92c_init_edca; sc->sc_init_bb = r92e_init_bb; sc->sc_init_rf = r92e_init_rf; sc->sc_init_antsel = rtwn_nop_softc; sc->sc_post_init = r92eu_post_init; sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc; - sc->sc_set_tx_power = rtwn_nop_int_softc_vap; + sc->sc_set_tx_power = r92e_set_tx_power; sc->mac_prog = &rtl8192eu_mac[0]; sc->mac_size = nitems(rtl8192eu_mac); sc->bb_prog = &rtl8192eu_bb[0]; sc->bb_size = nitems(rtl8192eu_bb); sc->agc_prog = &rtl8192eu_agc[0]; sc->agc_size = nitems(rtl8192eu_agc); sc->rf_prog = &rtl8192eu_rf[0]; sc->name = "RTL8192EU"; sc->fwname = "rtwn-rtl8192eufw"; sc->fwsig = 0x92e; sc->page_count = R92E_TX_PAGE_COUNT; sc->pktbuf_count = 0; /* Unused */ sc->ackto = 0x40; sc->npubqpages = R92E_PUBQ_NPAGES; sc->page_size = R92E_TX_PAGE_SIZE; sc->txdesc_len = sizeof(struct r12au_tx_desc); sc->efuse_maxlen = R92E_EFUSE_MAX_LEN; sc->efuse_maplen = R92E_EFUSE_MAP_LEN; sc->rx_dma_size = R92E_RX_DMA_BUFFER_SIZE; sc->macid_limit = R12A_MACID_MAX + 1; sc->cam_entry_limit = R12A_CAM_ENTRY_COUNT; sc->fwsize_limit = R92E_MAX_FW_SIZE; sc->temp_delta = R88E_CALIB_THRESHOLD; sc->bcn_status_reg[0] = R92C_TDECTRL; sc->bcn_status_reg[1] = R21A_DWBCN1_CTRL; sc->rcr = 0; sc->ntxchains = 2; sc->nrxchains = 2; r92eu_attach_private(sc); }