Merge branch 'ewma'
Johannes Berg says: ==================== average: convert users to inline implementation Since there's very little benefit of the out-of-line implementation (a single byte of .text in one driver as far as I've seen), convert all drivers to the inline implementation, saving memory, and remove the out-of-line implementation. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
84b6714e54
@ -282,7 +282,6 @@ config VETH
|
||||
config VIRTIO_NET
|
||||
tristate "Virtio network driver"
|
||||
depends on VIRTIO
|
||||
select AVERAGE
|
||||
---help---
|
||||
This is the virtual network driver for virtio. It can be used with
|
||||
lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
|
||||
|
@ -40,12 +40,12 @@ module_param(gso, bool, 0444);
|
||||
#define GOOD_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN)
|
||||
#define GOOD_COPY_LEN 128
|
||||
|
||||
/* Weight used for the RX packet size EWMA. The average packet size is used to
|
||||
* determine the packet buffer size when refilling RX rings. As the entire RX
|
||||
* ring may be refilled at once, the weight is chosen so that the EWMA will be
|
||||
* insensitive to short-term, transient changes in packet size.
|
||||
/* RX packet size EWMA. The average packet size is used to determine the packet
|
||||
* buffer size when refilling RX rings. As the entire RX ring may be refilled
|
||||
* at once, the weight is chosen so that the EWMA will be insensitive to short-
|
||||
* term, transient changes in packet size.
|
||||
*/
|
||||
#define RECEIVE_AVG_WEIGHT 64
|
||||
DECLARE_EWMA(pkt_len, 1, 64)
|
||||
|
||||
/* Minimum alignment for mergeable packet buffers. */
|
||||
#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, 256)
|
||||
@ -85,7 +85,7 @@ struct receive_queue {
|
||||
struct page *pages;
|
||||
|
||||
/* Average packet length for mergeable receive buffers. */
|
||||
struct ewma mrg_avg_pkt_len;
|
||||
struct ewma_pkt_len mrg_avg_pkt_len;
|
||||
|
||||
/* Page frag for packet buffer allocation. */
|
||||
struct page_frag alloc_frag;
|
||||
@ -407,7 +407,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
ewma_add(&rq->mrg_avg_pkt_len, head_skb->len);
|
||||
ewma_pkt_len_add(&rq->mrg_avg_pkt_len, head_skb->len);
|
||||
return head_skb;
|
||||
|
||||
err_skb:
|
||||
@ -600,12 +600,12 @@ static int add_recvbuf_big(struct virtnet_info *vi, struct receive_queue *rq,
|
||||
return err;
|
||||
}
|
||||
|
||||
static unsigned int get_mergeable_buf_len(struct ewma *avg_pkt_len)
|
||||
static unsigned int get_mergeable_buf_len(struct ewma_pkt_len *avg_pkt_len)
|
||||
{
|
||||
const size_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
|
||||
unsigned int len;
|
||||
|
||||
len = hdr_len + clamp_t(unsigned int, ewma_read(avg_pkt_len),
|
||||
len = hdr_len + clamp_t(unsigned int, ewma_pkt_len_read(avg_pkt_len),
|
||||
GOOD_PACKET_LEN, PAGE_SIZE - hdr_len);
|
||||
return ALIGN(len, MERGEABLE_BUFFER_ALIGN);
|
||||
}
|
||||
@ -1615,7 +1615,7 @@ static int virtnet_alloc_queues(struct virtnet_info *vi)
|
||||
napi_hash_add(&vi->rq[i].napi);
|
||||
|
||||
sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg));
|
||||
ewma_init(&vi->rq[i].mrg_avg_pkt_len, 1, RECEIVE_AVG_WEIGHT);
|
||||
ewma_pkt_len_init(&vi->rq[i].mrg_avg_pkt_len);
|
||||
sg_init_table(vi->sq[i].sg, ARRAY_SIZE(vi->sq[i].sg));
|
||||
}
|
||||
|
||||
@ -1658,7 +1658,7 @@ static ssize_t mergeable_rx_buffer_size_show(struct netdev_rx_queue *queue,
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(queue->dev);
|
||||
unsigned int queue_index = get_netdev_rx_queue_index(queue);
|
||||
struct ewma *avg;
|
||||
struct ewma_pkt_len *avg;
|
||||
|
||||
BUG_ON(queue_index >= vi->max_queue_pairs);
|
||||
avg = &vi->rq[queue_index].mrg_avg_pkt_len;
|
||||
|
@ -5,7 +5,6 @@ config ATH5K
|
||||
select MAC80211_LEDS
|
||||
select LEDS_CLASS
|
||||
select NEW_LEDS
|
||||
select AVERAGE
|
||||
select ATH5K_AHB if ATH25
|
||||
select ATH5K_PCI if !ATH25
|
||||
---help---
|
||||
|
@ -223,7 +223,7 @@ static void
|
||||
ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
|
||||
bool ofdm_trigger)
|
||||
{
|
||||
int rssi = ewma_read(&ah->ah_beacon_rssi_avg);
|
||||
int rssi = ewma_beacon_rssi_read(&ah->ah_beacon_rssi_avg);
|
||||
|
||||
ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "raise immunity (%s)",
|
||||
ofdm_trigger ? "ODFM" : "CCK");
|
||||
@ -309,7 +309,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
|
||||
static void
|
||||
ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as)
|
||||
{
|
||||
int rssi = ewma_read(&ah->ah_beacon_rssi_avg);
|
||||
int rssi = ewma_beacon_rssi_read(&ah->ah_beacon_rssi_avg);
|
||||
|
||||
ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "lower immunity");
|
||||
|
||||
|
@ -1252,6 +1252,8 @@ struct ath5k_statistics {
|
||||
#define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */
|
||||
#define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */
|
||||
|
||||
DECLARE_EWMA(beacon_rssi, 1024, 8)
|
||||
|
||||
/* Driver state associated with an instance of a device */
|
||||
struct ath5k_hw {
|
||||
struct ath_common common;
|
||||
@ -1432,7 +1434,7 @@ struct ath5k_hw {
|
||||
struct ath5k_nfcal_hist ah_nfcal_hist;
|
||||
|
||||
/* average beacon RSSI in our BSS (used by ANI) */
|
||||
struct ewma ah_beacon_rssi_avg;
|
||||
struct ewma_beacon_rssi ah_beacon_rssi_avg;
|
||||
|
||||
/* noise floor from last periodic calibration */
|
||||
s32 ah_noise_floor;
|
||||
|
@ -1430,7 +1430,7 @@ ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb,
|
||||
trace_ath5k_rx(ah, skb);
|
||||
|
||||
if (ath_is_mybeacon(common, (struct ieee80211_hdr *)skb->data)) {
|
||||
ewma_add(&ah->ah_beacon_rssi_avg, rs->rs_rssi);
|
||||
ewma_beacon_rssi_add(&ah->ah_beacon_rssi_avg, rs->rs_rssi);
|
||||
|
||||
/* check beacons in IBSS mode */
|
||||
if (ah->opmode == NL80211_IFTYPE_ADHOC)
|
||||
@ -2936,7 +2936,7 @@ ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
|
||||
ah->ah_cal_next_short = jiffies +
|
||||
msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_SHORT);
|
||||
|
||||
ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8);
|
||||
ewma_beacon_rssi_init(&ah->ah_beacon_rssi_avg);
|
||||
|
||||
/* clear survey data and cycle counters */
|
||||
memset(&ah->survey, 0, sizeof(ah->survey));
|
||||
|
@ -722,7 +722,7 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf,
|
||||
st->mib_intr);
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"beacon RSSI average:\t%d\n",
|
||||
(int)ewma_read(&ah->ah_beacon_rssi_avg));
|
||||
(int)ewma_beacon_rssi_read(&ah->ah_beacon_rssi_avg));
|
||||
|
||||
#define CC_PRINT(_struct, _field) \
|
||||
_struct._field, \
|
||||
|
@ -240,7 +240,6 @@ config RT2X00_LIB_USB
|
||||
|
||||
config RT2X00_LIB
|
||||
tristate
|
||||
select AVERAGE
|
||||
|
||||
config RT2X00_LIB_FIRMWARE
|
||||
bool
|
||||
|
@ -254,6 +254,8 @@ struct link_qual {
|
||||
int tx_failed;
|
||||
};
|
||||
|
||||
DECLARE_EWMA(rssi, 1024, 8)
|
||||
|
||||
/*
|
||||
* Antenna settings about the currently active link.
|
||||
*/
|
||||
@ -285,7 +287,7 @@ struct link_ant {
|
||||
* Similar to the avg_rssi in the link_qual structure
|
||||
* this value is updated by using the walking average.
|
||||
*/
|
||||
struct ewma rssi_ant;
|
||||
struct ewma_rssi rssi_ant;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -314,7 +316,7 @@ struct link {
|
||||
/*
|
||||
* Currently active average RSSI value
|
||||
*/
|
||||
struct ewma avg_rssi;
|
||||
struct ewma_rssi avg_rssi;
|
||||
|
||||
/*
|
||||
* Work structure for scheduling periodic link tuning.
|
||||
|
@ -33,15 +33,11 @@
|
||||
*/
|
||||
#define DEFAULT_RSSI -128
|
||||
|
||||
/* Constants for EWMA calculations. */
|
||||
#define RT2X00_EWMA_FACTOR 1024
|
||||
#define RT2X00_EWMA_WEIGHT 8
|
||||
|
||||
static inline int rt2x00link_get_avg_rssi(struct ewma *ewma)
|
||||
static inline int rt2x00link_get_avg_rssi(struct ewma_rssi *ewma)
|
||||
{
|
||||
unsigned long avg;
|
||||
|
||||
avg = ewma_read(ewma);
|
||||
avg = ewma_rssi_read(ewma);
|
||||
if (avg)
|
||||
return -avg;
|
||||
|
||||
@ -76,8 +72,7 @@ static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
ewma_init(&rt2x00dev->link.ant.rssi_ant, RT2X00_EWMA_FACTOR,
|
||||
RT2X00_EWMA_WEIGHT);
|
||||
ewma_rssi_init(&rt2x00dev->link.ant.rssi_ant);
|
||||
}
|
||||
|
||||
static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev)
|
||||
@ -225,12 +220,12 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* Update global RSSI
|
||||
*/
|
||||
ewma_add(&link->avg_rssi, -rxdesc->rssi);
|
||||
ewma_rssi_add(&link->avg_rssi, -rxdesc->rssi);
|
||||
|
||||
/*
|
||||
* Update antenna RSSI
|
||||
*/
|
||||
ewma_add(&ant->rssi_ant, -rxdesc->rssi);
|
||||
ewma_rssi_add(&ant->rssi_ant, -rxdesc->rssi);
|
||||
}
|
||||
|
||||
void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
|
||||
@ -285,8 +280,7 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)
|
||||
*/
|
||||
rt2x00dev->link.count = 0;
|
||||
memset(qual, 0, sizeof(*qual));
|
||||
ewma_init(&rt2x00dev->link.avg_rssi, RT2X00_EWMA_FACTOR,
|
||||
RT2X00_EWMA_WEIGHT);
|
||||
ewma_rssi_init(&rt2x00dev->link.avg_rssi);
|
||||
|
||||
/*
|
||||
* Restore the VGC level as stored in the registers,
|
||||
|
@ -3,30 +3,6 @@
|
||||
|
||||
/* Exponentially weighted moving average (EWMA) */
|
||||
|
||||
/* For more documentation see lib/average.c */
|
||||
|
||||
struct ewma {
|
||||
unsigned long internal;
|
||||
unsigned long factor;
|
||||
unsigned long weight;
|
||||
};
|
||||
|
||||
extern void ewma_init(struct ewma *avg, unsigned long factor,
|
||||
unsigned long weight);
|
||||
|
||||
extern struct ewma *ewma_add(struct ewma *avg, unsigned long val);
|
||||
|
||||
/**
|
||||
* ewma_read() - Get average value
|
||||
* @avg: Average structure
|
||||
*
|
||||
* Returns the average value held in @avg.
|
||||
*/
|
||||
static inline unsigned long ewma_read(const struct ewma *avg)
|
||||
{
|
||||
return avg->internal >> avg->factor;
|
||||
}
|
||||
|
||||
#define DECLARE_EWMA(name, _factor, _weight) \
|
||||
struct ewma_##name { \
|
||||
unsigned long internal; \
|
||||
|
10
lib/Kconfig
10
lib/Kconfig
@ -460,16 +460,6 @@ config ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
|
||||
config LRU_CACHE
|
||||
tristate
|
||||
|
||||
config AVERAGE
|
||||
bool "Averaging functions"
|
||||
help
|
||||
This option is provided for the case where no in-kernel-tree
|
||||
modules require averaging functions, but a module built outside
|
||||
the kernel tree does. Such modules that use library averaging
|
||||
functions require Y here.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config CLZ_TAB
|
||||
bool
|
||||
|
||||
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* lib/average.c
|
||||
*
|
||||
* This source code is licensed under the GNU General Public License,
|
||||
* Version 2. See the file COPYING for more details.
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/average.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/log2.h>
|
||||
|
||||
/**
|
||||
* DOC: Exponentially Weighted Moving Average (EWMA)
|
||||
*
|
||||
* These are generic functions for calculating Exponentially Weighted Moving
|
||||
* Averages (EWMA). We keep a structure with the EWMA parameters and a scaled
|
||||
* up internal representation of the average value to prevent rounding errors.
|
||||
* The factor for scaling up and the exponential weight (or decay rate) have to
|
||||
* be specified thru the init fuction. The structure should not be accessed
|
||||
* directly but only thru the helper functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ewma_init() - Initialize EWMA parameters
|
||||
* @avg: Average structure
|
||||
* @factor: Factor to use for the scaled up internal value. The maximum value
|
||||
* of averages can be ULONG_MAX/(factor*weight). For performance reasons
|
||||
* factor has to be a power of 2.
|
||||
* @weight: Exponential weight, or decay rate. This defines how fast the
|
||||
* influence of older values decreases. For performance reasons weight has
|
||||
* to be a power of 2.
|
||||
*
|
||||
* Initialize the EWMA parameters for a given struct ewma @avg.
|
||||
*/
|
||||
void ewma_init(struct ewma *avg, unsigned long factor, unsigned long weight)
|
||||
{
|
||||
WARN_ON(!is_power_of_2(weight) || !is_power_of_2(factor));
|
||||
|
||||
avg->weight = ilog2(weight);
|
||||
avg->factor = ilog2(factor);
|
||||
avg->internal = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ewma_init);
|
||||
|
||||
/**
|
||||
* ewma_add() - Exponentially weighted moving average (EWMA)
|
||||
* @avg: Average structure
|
||||
* @val: Current value
|
||||
*
|
||||
* Add a sample to the average.
|
||||
*/
|
||||
struct ewma *ewma_add(struct ewma *avg, unsigned long val)
|
||||
{
|
||||
unsigned long internal = ACCESS_ONCE(avg->internal);
|
||||
|
||||
ACCESS_ONCE(avg->internal) = internal ?
|
||||
(((internal << avg->weight) - internal) +
|
||||
(val << avg->factor)) >> avg->weight :
|
||||
(val << avg->factor);
|
||||
return avg;
|
||||
}
|
||||
EXPORT_SYMBOL(ewma_add);
|
Loading…
Reference in New Issue
Block a user