/* Broadcom B43 wireless driver G PHY LO (LocalOscillator) Measuring and Control routines Copyright (c) 2005 Martin Langer , Copyright (c) 2005, 2006 Stefano Brivio Copyright (c) 2005-2007 Michael Buesch Copyright (c) 2005, 2006 Danny van Dyk Copyright (c) 2005, 2006 Andreas Jaggi This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "b43.h" #include "lo.h" #include "phy_g.h" #include "main.h" #include #include #include static struct b43_lo_calib *b43_find_lo_calib(struct b43_txpower_lo_control *lo, const struct b43_bbatt *bbatt, const struct b43_rfatt *rfatt) { struct b43_lo_calib *c; list_for_each_entry(c, &lo->calib_list, list) { if (!b43_compare_bbatt(&c->bbatt, bbatt)) continue; if (!b43_compare_rfatt(&c->rfatt, rfatt)) continue; return c; } return NULL; } /* Write the LocalOscillator Control (adjust) value-pair. */ static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control) { struct b43_phy *phy = &dev->phy; u16 value; if (B43_DEBUG) { if (unlikely(abs(control->i) > 16 || abs(control->q) > 16)) { b43dbg(dev->wl, "Invalid LO control pair " "(I: %d, Q: %d)\n", control->i, control->q); dump_stack(); return; } } B43_WARN_ON(phy->type != B43_PHYTYPE_G); value = (u8) (control->q); value |= ((u8) (control->i)) << 8; b43_phy_write(dev, B43_PHY_LO_CTL, value); } static u16 lo_measure_feedthrough(struct b43_wldev *dev, u16 lna, u16 pga, u16 trsw_rx) { struct b43_phy *phy = &dev->phy; u16 rfover; u16 feedthrough; if (phy->gmode) { lna <<= B43_PHY_RFOVERVAL_LNA_SHIFT; pga <<= B43_PHY_RFOVERVAL_PGA_SHIFT; B43_WARN_ON(lna & ~B43_PHY_RFOVERVAL_LNA); B43_WARN_ON(pga & ~B43_PHY_RFOVERVAL_PGA); /*FIXME This assertion fails B43_WARN_ON(trsw_rx & ~(B43_PHY_RFOVERVAL_TRSWRX | B43_PHY_RFOVERVAL_BW)); */ trsw_rx &= (B43_PHY_RFOVERVAL_TRSWRX | B43_PHY_RFOVERVAL_BW); /* Construct the RF Override Value */ rfover = B43_PHY_RFOVERVAL_UNK; rfover |= pga; rfover |= lna; rfover |= trsw_rx; if ((dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA) && phy->rev > 6) rfover |= B43_PHY_RFOVERVAL_EXTLNA; b43_phy_write(dev, B43_PHY_PGACTL, 0xE300); b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover); udelay(10); rfover |= B43_PHY_RFOVERVAL_BW_LBW; b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover); udelay(10); rfover |= B43_PHY_RFOVERVAL_BW_LPF; b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover); udelay(10); b43_phy_write(dev, B43_PHY_PGACTL, 0xF300); } else { pga |= B43_PHY_PGACTL_UNKNOWN; b43_phy_write(dev, B43_PHY_PGACTL, pga); udelay(10); pga |= B43_PHY_PGACTL_LOWBANDW; b43_phy_write(dev, B43_PHY_PGACTL, pga); udelay(10); pga |= B43_PHY_PGACTL_LPF; b43_phy_write(dev, B43_PHY_PGACTL, pga); } udelay(21); feedthrough = b43_phy_read(dev, B43_PHY_LO_LEAKAGE); /* This is a good place to check if we need to relax a bit, * as this is the main function called regularly * in the LO calibration. */ cond_resched(); return feedthrough; } /* TXCTL Register and Value Table. * Returns the "TXCTL Register". * "value" is the "TXCTL Value". * "pad_mix_gain" is the PAD Mixer Gain. */ static u16 lo_txctl_register_table(struct b43_wldev *dev, u16 *value, u16 *pad_mix_gain) { struct b43_phy *phy = &dev->phy; u16 reg, v, padmix; if (phy->type == B43_PHYTYPE_B) { v = 0x30; if (phy->radio_rev <= 5) { reg = 0x43; padmix = 0; } else { reg = 0x52; padmix = 5; } } else { if (phy->rev >= 2 && phy->radio_rev == 8) { reg = 0x43; v = 0x10; padmix = 2; } else { reg = 0x52; v = 0x30; padmix = 5; } } if (value) *value = v; if (pad_mix_gain) *pad_mix_gain = padmix; return reg; } static void lo_measure_txctl_values(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; struct b43_txpower_lo_control *lo = gphy->lo_control; u16 reg, mask; u16 trsw_rx, pga; u16 radio_pctl_reg; static const u8 tx_bias_values[] = { 0x09, 0x08, 0x0A, 0x01, 0x00, 0x02, 0x05, 0x04, 0x06, }; static const u8 tx_magn_values[] = { 0x70, 0x40, }; if (!has_loopback_gain(phy)) { radio_pctl_reg = 6; trsw_rx = 2; pga = 0; } else { int lb_gain; /* Loopback gain (in dB) */ trsw_rx = 0; lb_gain = gphy->max_lb_gain / 2; if (lb_gain > 10) { radio_pctl_reg = 0; pga = abs(10 - lb_gain) / 6; pga = clamp_val(pga, 0, 15); } else { int cmp_val; int tmp; pga = 0; cmp_val = 0x24; if ((phy->rev >= 2) && (phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) cmp_val = 0x3C; tmp = lb_gain; if ((10 - lb_gain) < cmp_val) tmp = (10 - lb_gain); if (tmp < 0) tmp += 6; else tmp += 3; cmp_val /= 4; tmp /= 4; if (tmp >= cmp_val) radio_pctl_reg = cmp_val; else radio_pctl_reg = tmp; } } b43_radio_maskset(dev, 0x43, 0xFFF0, radio_pctl_reg); b43_gphy_set_baseband_attenuation(dev, 2); reg = lo_txctl_register_table(dev, &mask, NULL); mask = ~mask; b43_radio_mask(dev, reg, mask); if (has_tx_magnification(phy)) { int i, j; int feedthrough; int min_feedth = 0xFFFF; u8 tx_magn, tx_bias; for (i = 0; i < ARRAY_SIZE(tx_magn_values); i++) { tx_magn = tx_magn_values[i]; b43_radio_maskset(dev, 0x52, 0xFF0F, tx_magn); for (j = 0; j < ARRAY_SIZE(tx_bias_values); j++) { tx_bias = tx_bias_values[j]; b43_radio_maskset(dev, 0x52, 0xFFF0, tx_bias); feedthrough = lo_measure_feedthrough(dev, 0, pga, trsw_rx); if (feedthrough < min_feedth) { lo->tx_bias = tx_bias; lo->tx_magn = tx_magn; min_feedth = feedthrough; } if (lo->tx_bias == 0) break; } b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52) & 0xFF00) | lo->tx_bias | lo-> tx_magn); } } else { lo->tx_magn = 0; lo->tx_bias = 0; b43_radio_mask(dev, 0x52, 0xFFF0); /* TX bias == 0 */ } lo->txctl_measured_time = jiffies; } static void lo_read_power_ve
# Copyright 2016 Intel Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# VSPERF specific configuration file for execution of RFC2544 continuous
# traffic.
# This test uses a dummy traffic generator, which does not execute a real
# traffic. The purpose of this test is to demonstrate vsperf execution
# by yardstick environment. Provided 'test_params' option can modified
# to use a real traffic generator.
# Details about supported test options and test case execution can be
# found in VSPERF documentation:
#
#   http://artifacts.opnfv.org/vswitchperf/docs/userguide/yardstick.html

schema: "yardstick:task:0.1"

scenarios:
-
  type: Vsperf
  options:
    testname: 'rfc2544_continuous'
    frame_size: '64'
    test_params: 'TRAFFICGEN_DURATION=30;
        TRAFFICGEN="Dummy";
        TRAFFIC={
            "traffic_type":"rfc2544_continuous"
        };
        TRAFFICGEN_DUMMY_RESULTS={
            "frames tx":15000000,
            "frames rx":15000000,
            "tx rate %":100,
            "rx rate %":100,
            "min latency":1,
            "max latency":15,
            "avg latency":2.5,
            "frameloss %":0,}'

  host: vsperf.demo

  runner:
    type: Sequence
    scenario_option_name: frame_size
    sequence:
    - 64
    - 128
    - 512
    - 1024
    - 1518
  sla:
    # The throughput SLA (or any other SLA) cannot be set to a meaningful
    # value without knowledge of the server and networking environment,
    # possibly including prior testing in that environment to establish
    # a baseline SLA level under well-understood circumstances.
    metrics: 'throughput_rx_fps'
    throughput_rx_fps: 500000
    action: monitor

context:
  name: demo
  image: vsperf
  flavor: vsperf-flavor
  user: ubuntu

  placement_groups:
    pgrp1:
      policy: "availability"

  servers:
    vsperf:
      floating_ip: true
      placement: "pgrp1"

  networks:
    test:
      cidr: '10.0.0.0/24'
ware DC LT. */ idx = i / 2; /* Change the table in memory. */ if (i % 2) { /* Change the high byte. */ lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00FF) | ((val & 0x00FF) << 8); } else { /* Change the low byte. */ lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xFF00) | (val & 0x00FF); } table_changed = true; } if (table_changed) { /* The table changed in memory. Update the hardware table. */ for (i = 0; i < B43_DC_LT_SIZE; i++) b43_phy_write(dev, 0x3A0 + i, lo->dc_lt[i]); } b43_mac_enable(dev); } /* Fixup the RF attenuation value for the case where we are * using the PAD mixer. */ static inline void b43_lo_fixup_rfatt(struct b43_rfatt *rf) { if (!rf->with_padmix) return; if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3)) rf->att = 4; } void b43_lo_g_adjust(struct b43_wldev *dev) { struct b43_phy_g *gphy = dev->phy.g; struct b43_lo_calib *cal; struct b43_rfatt rf; memcpy(&rf, &gphy->rfatt, sizeof(rf)); b43_lo_fixup_rfatt(&rf); cal = b43_get_calib_lo_settings(dev, &gphy->bbatt, &rf); if (!cal) return; b43_lo_write(dev, &cal->ctl); } void b43_lo_g_adjust_to(struct b43_wldev *dev, u16 rfatt, u16 bbatt, u16 tx_control) { struct b43_rfatt rf; struct b43_bbatt bb; struct b43_lo_calib *cal; memset(&rf, 0, sizeof(rf)); memset(&bb, 0, sizeof(bb)); rf.att = rfatt; bb.att = bbatt; b43_lo_fixup_rfatt(&rf); cal = b43_get_calib_lo_settings(dev, &bb, &rf); if (!cal) return; b43_lo_write(dev, &cal->ctl); } /* Periodic LO maintenance work */ void b43_lo_g_maintenance_work(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; struct b43_txpower_lo_control *lo = gphy->lo_control; unsigned long now; unsigned long expire; struct b43_lo_calib *cal, *tmp; bool current_item_expired = false; bool hwpctl; if (!lo) return; now = jiffies; hwpctl = b43_has_hardware_pctl(dev); if (hwpctl) { /* Read the power vector and update it, if needed. */ expire = now - B43_LO_PWRVEC_EXPIRE; if (time_before(lo->pwr_vec_read_time, expire)) { lo_read_power_vector(dev); b43_gphy_dc_lt_init(dev, 0); } //FIXME Recalc the whole DC table from time to time? } if (hwpctl) return; /* Search for expired LO settings. Remove them. * Recalibrate the current setting, if expired. */ expire = now - B43_LO_CALIB_EXPIRE; list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) { if (!time_before(cal->calib_time, expire)) continue; /* This item expired. */ if (b43_compare_bbatt(&cal->bbatt, &gphy->bbatt) && b43_compare_rfatt(&cal->rfatt, &gphy->rfatt)) { B43_WARN_ON(current_item_expired); current_item_expired = true; } if (b43_debug(dev, B43_DBG_LO)) { b43dbg(dev->wl, "LO: Item BB(%u), RF(%u,%u), " "I=%d, Q=%d expired\n", cal->bbatt.att, cal->rfatt.att, cal->rfatt.with_padmix, cal->ctl.i, cal->ctl.q); } list_del(&cal->list); kfree(cal); } if (current_item_expired || unlikely(list_empty(&lo->calib_list))) { /* Recalibrate currently used LO setting. */ if (b43_debug(dev, B43_DBG_LO)) b43dbg(dev->wl, "LO: Recalibrating current LO setting\n"); cal = b43_calibrate_lo_setting(dev, &gphy->bbatt, &gphy->rfatt); if (cal) { list_add(&cal->list, &lo->calib_list); b43_lo_write(dev, &cal->ctl); } else b43warn(dev->wl, "Failed to recalibrate current LO setting\n"); } } void b43_lo_g_cleanup(struct b43_wldev *dev) { struct b43_txpower_lo_control *lo = dev->phy.g->lo_control; struct b43_lo_calib *cal, *tmp; if (!lo) return; list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) { list_del(&cal->list); kfree(cal); } } /* LO Initialization */ void b43_lo_g_init(struct b43_wldev *dev) { if (b43_has_hardware_pctl(dev)) { lo_read_power_vector(dev); b43_gphy_dc_lt_init(dev, 1); } }