diff --git a/[refs] b/[refs] index 16f89b9d93f1..fa568731703a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: e254c274ae19888e5693ba6d32576ab03a8ae8a4 +refs/heads/master: 4874c131d79695e3d372042781a408a1a8a762d8 diff --git a/trunk/drivers/net/qlcnic/qlcnic_init.c b/trunk/drivers/net/qlcnic/qlcnic_init.c index 16dd9ebd36c9..e26fa9593311 100644 --- a/trunk/drivers/net/qlcnic/qlcnic_init.c +++ b/trunk/drivers/net/qlcnic/qlcnic_init.c @@ -1418,6 +1418,8 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); + skb->truesize = skb->len + sizeof(struct sk_buff); + if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { adapter->stats.rxdropped++; dev_kfree_skb(skb); @@ -1489,6 +1491,8 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, skb_put(skb, lro_length + data_offset); + skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); + skb_pull(skb, l2_hdr_offset); if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { @@ -1728,6 +1732,8 @@ qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); + skb->truesize = skb->len + sizeof(struct sk_buff); + if (!qlcnic_check_loopback_buff(skb->data)) adapter->diag_cnt++; diff --git a/trunk/drivers/net/sfc/Makefile b/trunk/drivers/net/sfc/Makefile index fd9272b5873a..1047b19c60a5 100644 --- a/trunk/drivers/net/sfc/Makefile +++ b/trunk/drivers/net/sfc/Makefile @@ -1,4 +1,4 @@ -sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \ +sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o \ falcon_gmac.o falcon_xmac.o mcdi_mac.o \ selftest.o ethtool.o qt202x_phy.o mdio_10g.o \ tenxpress.o falcon_boards.o mcdi.o mcdi_phy.o diff --git a/trunk/drivers/net/sfc/efx.c b/trunk/drivers/net/sfc/efx.c index 5be71f49a205..f702f1fb63b6 100644 --- a/trunk/drivers/net/sfc/efx.c +++ b/trunk/drivers/net/sfc/efx.c @@ -124,9 +124,8 @@ MODULE_PARM_DESC(separate_tx_channels, static int napi_weight = 64; /* This is the time (in jiffies) between invocations of the hardware - * monitor. On Falcon-based NICs, this will: - * - Check the on-board hardware monitor; - * - Poll the link state and reconfigure the hardware as necessary. + * monitor, which checks for known hardware bugs and resets the + * hardware and driver as necessary. */ unsigned int efx_monitor_interval = 1 * HZ; @@ -1358,17 +1357,8 @@ static int efx_probe_all(struct efx_nic *efx) if (rc) goto fail3; - rc = efx_probe_filters(efx); - if (rc) { - netif_err(efx, probe, efx->net_dev, - "failed to create filter tables\n"); - goto fail4; - } - return 0; - fail4: - efx_remove_channels(efx); fail3: efx_remove_port(efx); fail2: @@ -1499,7 +1489,6 @@ static void efx_stop_all(struct efx_nic *efx) static void efx_remove_all(struct efx_nic *efx) { - efx_remove_filters(efx); efx_remove_channels(efx); efx_remove_port(efx); efx_remove_nic(efx); @@ -1546,7 +1535,8 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs, * **************************************************************************/ -/* Run periodically off the general workqueue */ +/* Run periodically off the general workqueue. Serialised against + * efx_reconfigure_port via the mac_lock */ static void efx_monitor(struct work_struct *data) { struct efx_nic *efx = container_of(data, struct efx_nic, @@ -1559,13 +1549,16 @@ static void efx_monitor(struct work_struct *data) /* If the mac_lock is already held then it is likely a port * reconfiguration is already in place, which will likely do - * most of the work of monitor() anyway. */ - if (mutex_trylock(&efx->mac_lock)) { - if (efx->port_enabled) - efx->type->monitor(efx); - mutex_unlock(&efx->mac_lock); - } + * most of the work of check_hw() anyway. */ + if (!mutex_trylock(&efx->mac_lock)) + goto out_requeue; + if (!efx->port_enabled) + goto out_unlock; + efx->type->monitor(efx); +out_unlock: + mutex_unlock(&efx->mac_lock); +out_requeue: queue_delayed_work(efx->workqueue, &efx->monitor_work, efx_monitor_interval); } @@ -2009,7 +2002,6 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) efx->mac_op->reconfigure(efx); efx_init_channels(efx); - efx_restore_filters(efx); mutex_unlock(&efx->spi_lock); mutex_unlock(&efx->mac_lock); diff --git a/trunk/drivers/net/sfc/efx.h b/trunk/drivers/net/sfc/efx.h index f502b14eb22c..e783c0fedfd8 100644 --- a/trunk/drivers/net/sfc/efx.h +++ b/trunk/drivers/net/sfc/efx.h @@ -12,7 +12,6 @@ #define EFX_EFX_H #include "net_driver.h" -#include "filter.h" /* PCI IDs */ #define EFX_VENDID_SFC 0x1924 @@ -65,19 +64,6 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue); * skb. Falcon/A1 may require up to three descriptors per skb_frag. */ #define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS)) -/* Filters */ -extern int efx_probe_filters(struct efx_nic *efx); -extern void efx_restore_filters(struct efx_nic *efx); -extern void efx_remove_filters(struct efx_nic *efx); -extern int efx_filter_insert_filter(struct efx_nic *efx, - struct efx_filter_spec *spec, - bool replace); -extern int efx_filter_remove_filter(struct efx_nic *efx, - struct efx_filter_spec *spec); -extern void efx_filter_table_clear(struct efx_nic *efx, - enum efx_filter_table_id table_id, - enum efx_filter_priority priority); - /* Channels */ extern void efx_process_channel_now(struct efx_channel *channel); extern int diff --git a/trunk/drivers/net/sfc/ethtool.c b/trunk/drivers/net/sfc/ethtool.c index c95328fa3ee8..7f735d804801 100644 --- a/trunk/drivers/net/sfc/ethtool.c +++ b/trunk/drivers/net/sfc/ethtool.c @@ -15,7 +15,6 @@ #include "workarounds.h" #include "selftest.h" #include "efx.h" -#include "filter.h" #include "nic.h" #include "spi.h" #include "mdio_10g.h" @@ -552,22 +551,9 @@ static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev) static int efx_ethtool_set_flags(struct net_device *net_dev, u32 data) { struct efx_nic *efx = netdev_priv(net_dev); - u32 supported = (efx->type->offload_features & - (ETH_FLAG_RXHASH | ETH_FLAG_NTUPLE)); - int rc; - - rc = ethtool_op_set_flags(net_dev, data, supported); - if (rc) - return rc; - - if (!(data & ETH_FLAG_NTUPLE)) { - efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_IP, - EFX_FILTER_PRI_MANUAL); - efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_MAC, - EFX_FILTER_PRI_MANUAL); - } + u32 supported = efx->type->offload_features & ETH_FLAG_RXHASH; - return 0; + return ethtool_op_set_flags(net_dev, data, supported); } static void efx_ethtool_self_test(struct net_device *net_dev, @@ -969,105 +955,6 @@ efx_ethtool_get_rxnfc(struct net_device *net_dev, } } -static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev, - struct ethtool_rx_ntuple *ntuple) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct ethtool_tcpip4_spec *ip_entry = &ntuple->fs.h_u.tcp_ip4_spec; - struct ethtool_tcpip4_spec *ip_mask = &ntuple->fs.m_u.tcp_ip4_spec; - struct ethhdr *mac_entry = &ntuple->fs.h_u.ether_spec; - struct ethhdr *mac_mask = &ntuple->fs.m_u.ether_spec; - struct efx_filter_spec filter; - - /* Range-check action */ - if (ntuple->fs.action < ETHTOOL_RXNTUPLE_ACTION_CLEAR || - ntuple->fs.action >= (s32)efx->n_rx_channels) - return -EINVAL; - - if (~ntuple->fs.data_mask) - return -EINVAL; - - switch (ntuple->fs.flow_type) { - case TCP_V4_FLOW: - case UDP_V4_FLOW: - /* Must match all of destination, */ - if (ip_mask->ip4dst | ip_mask->pdst) - return -EINVAL; - /* all or none of source, */ - if ((ip_mask->ip4src | ip_mask->psrc) && - ((__force u32)~ip_mask->ip4src | - (__force u16)~ip_mask->psrc)) - return -EINVAL; - /* and nothing else */ - if ((u8)~ip_mask->tos | (u16)~ntuple->fs.vlan_tag_mask) - return -EINVAL; - break; - case ETHER_FLOW: - /* Must match all of destination, */ - if (!is_zero_ether_addr(mac_mask->h_dest)) - return -EINVAL; - /* all or none of VID, */ - if (ntuple->fs.vlan_tag_mask != 0xf000 && - ntuple->fs.vlan_tag_mask != 0xffff) - return -EINVAL; - /* and nothing else */ - if (!is_broadcast_ether_addr(mac_mask->h_source) || - mac_mask->h_proto != htons(0xffff)) - return -EINVAL; - break; - default: - return -EINVAL; - } - - filter.priority = EFX_FILTER_PRI_MANUAL; - filter.flags = 0; - - switch (ntuple->fs.flow_type) { - case TCP_V4_FLOW: - if (!ip_mask->ip4src) - efx_filter_set_rx_tcp_full(&filter, - htonl(ip_entry->ip4src), - htons(ip_entry->psrc), - htonl(ip_entry->ip4dst), - htons(ip_entry->pdst)); - else - efx_filter_set_rx_tcp_wild(&filter, - htonl(ip_entry->ip4dst), - htons(ip_entry->pdst)); - break; - case UDP_V4_FLOW: - if (!ip_mask->ip4src) - efx_filter_set_rx_udp_full(&filter, - htonl(ip_entry->ip4src), - htons(ip_entry->psrc), - htonl(ip_entry->ip4dst), - htons(ip_entry->pdst)); - else - efx_filter_set_rx_udp_wild(&filter, - htonl(ip_entry->ip4dst), - htons(ip_entry->pdst)); - break; - case ETHER_FLOW: - if (ntuple->fs.vlan_tag_mask == 0xf000) - efx_filter_set_rx_mac_full(&filter, - ntuple->fs.vlan_tag & 0xfff, - mac_entry->h_dest); - else - efx_filter_set_rx_mac_wild(&filter, mac_entry->h_dest); - break; - } - - if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_CLEAR) { - return efx_filter_remove_filter(efx, &filter); - } else { - if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP) - filter.dmaq_id = 0xfff; - else - filter.dmaq_id = ntuple->fs.action; - return efx_filter_insert_filter(efx, &filter, true); - } -} - static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev, struct ethtool_rxfh_indir *indir) { @@ -1146,7 +1033,6 @@ const struct ethtool_ops efx_ethtool_ops = { .set_wol = efx_ethtool_set_wol, .reset = efx_ethtool_reset, .get_rxnfc = efx_ethtool_get_rxnfc, - .set_rx_ntuple = efx_ethtool_set_rx_ntuple, .get_rxfh_indir = efx_ethtool_get_rxfh_indir, .set_rxfh_indir = efx_ethtool_set_rxfh_indir, }; diff --git a/trunk/drivers/net/sfc/falcon.c b/trunk/drivers/net/sfc/falcon.c index b398a4198042..b4d8efe67772 100644 --- a/trunk/drivers/net/sfc/falcon.c +++ b/trunk/drivers/net/sfc/falcon.c @@ -1874,7 +1874,7 @@ struct efx_nic_type falcon_b0_nic_type = { * channels */ .tx_dc_base = 0x130000, .rx_dc_base = 0x100000, - .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE, + .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH, .reset_world_flags = ETH_RESET_IRQ, }; diff --git a/trunk/drivers/net/sfc/filter.c b/trunk/drivers/net/sfc/filter.c deleted file mode 100644 index abc884d09d57..000000000000 --- a/trunk/drivers/net/sfc/filter.c +++ /dev/null @@ -1,445 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2010 Solarflare Communications Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, incorporated herein by reference. - */ - -#include "efx.h" -#include "filter.h" -#include "io.h" -#include "nic.h" -#include "regs.h" - -/* "Fudge factors" - difference between programmed value and actual depth. - * Due to pipelined implementation we need to program H/W with a value that - * is larger than the hop limit we want. - */ -#define FILTER_CTL_SRCH_FUDGE_WILD 3 -#define FILTER_CTL_SRCH_FUDGE_FULL 1 - -struct efx_filter_table { - u32 offset; /* address of table relative to BAR */ - unsigned size; /* number of entries */ - unsigned step; /* step between entries */ - unsigned used; /* number currently used */ - unsigned long *used_bitmap; - struct efx_filter_spec *spec; -}; - -struct efx_filter_state { - spinlock_t lock; - struct efx_filter_table table[EFX_FILTER_TABLE_COUNT]; - unsigned search_depth[EFX_FILTER_TYPE_COUNT]; -}; - -/* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit - * key derived from the n-tuple. The initial LFSR state is 0xffff. */ -static u16 efx_filter_hash(u32 key) -{ - u16 tmp; - - /* First 16 rounds */ - tmp = 0x1fff ^ key >> 16; - tmp = tmp ^ tmp >> 3 ^ tmp >> 6; - tmp = tmp ^ tmp >> 9; - /* Last 16 rounds */ - tmp = tmp ^ tmp << 13 ^ key; - tmp = tmp ^ tmp >> 3 ^ tmp >> 6; - return tmp ^ tmp >> 9; -} - -/* To allow for hash collisions, filter search continues at these - * increments from the first possible entry selected by the hash. */ -static u16 efx_filter_increment(u32 key) -{ - return key * 2 - 1; -} - -static enum efx_filter_table_id -efx_filter_type_table_id(enum efx_filter_type type) -{ - BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_TCP_FULL >> 2)); - BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_TCP_WILD >> 2)); - BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_UDP_FULL >> 2)); - BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_UDP_WILD >> 2)); - BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_RX_MAC_FULL >> 2)); - BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_RX_MAC_WILD >> 2)); - return type >> 2; -} - -static void -efx_filter_table_reset_search_depth(struct efx_filter_state *state, - enum efx_filter_table_id table_id) -{ - memset(state->search_depth + (table_id << 2), 0, - sizeof(state->search_depth[0]) << 2); -} - -static void efx_filter_push_rx_limits(struct efx_nic *efx) -{ - struct efx_filter_state *state = efx->filter_state; - efx_oword_t filter_ctl; - - efx_reado(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL); - - EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_FULL_SRCH_LIMIT, - state->search_depth[EFX_FILTER_RX_TCP_FULL] + - FILTER_CTL_SRCH_FUDGE_FULL); - EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_WILD_SRCH_LIMIT, - state->search_depth[EFX_FILTER_RX_TCP_WILD] + - FILTER_CTL_SRCH_FUDGE_WILD); - EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_FULL_SRCH_LIMIT, - state->search_depth[EFX_FILTER_RX_UDP_FULL] + - FILTER_CTL_SRCH_FUDGE_FULL); - EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_WILD_SRCH_LIMIT, - state->search_depth[EFX_FILTER_RX_UDP_WILD] + - FILTER_CTL_SRCH_FUDGE_WILD); - - if (state->table[EFX_FILTER_TABLE_RX_MAC].size) { - EFX_SET_OWORD_FIELD( - filter_ctl, FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT, - state->search_depth[EFX_FILTER_RX_MAC_FULL] + - FILTER_CTL_SRCH_FUDGE_FULL); - EFX_SET_OWORD_FIELD( - filter_ctl, FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT, - state->search_depth[EFX_FILTER_RX_MAC_WILD] + - FILTER_CTL_SRCH_FUDGE_WILD); - } - - efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL); -} - -/* Build a filter entry and return its n-tuple key. */ -static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec) -{ - u32 data3; - - switch (efx_filter_type_table_id(spec->type)) { - case EFX_FILTER_TABLE_RX_IP: { - bool is_udp = (spec->type == EFX_FILTER_RX_UDP_FULL || - spec->type == EFX_FILTER_RX_UDP_WILD); - EFX_POPULATE_OWORD_7( - *filter, - FRF_BZ_RSS_EN, - !!(spec->flags & EFX_FILTER_FLAG_RX_RSS), - FRF_BZ_SCATTER_EN, - !!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER), - FRF_BZ_TCP_UDP, is_udp, - FRF_BZ_RXQ_ID, spec->dmaq_id, - EFX_DWORD_2, spec->data[2], - EFX_DWORD_1, spec->data[1], - EFX_DWORD_0, spec->data[0]); - data3 = is_udp; - break; - } - - case EFX_FILTER_TABLE_RX_MAC: { - bool is_wild = spec->type == EFX_FILTER_RX_MAC_WILD; - EFX_POPULATE_OWORD_8( - *filter, - FRF_CZ_RMFT_RSS_EN, - !!(spec->flags & EFX_FILTER_FLAG_RX_RSS), - FRF_CZ_RMFT_SCATTER_EN, - !!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER), - FRF_CZ_RMFT_IP_OVERRIDE, - !!(spec->flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP), - FRF_CZ_RMFT_RXQ_ID, spec->dmaq_id, - FRF_CZ_RMFT_WILDCARD_MATCH, is_wild, - FRF_CZ_RMFT_DEST_MAC_HI, spec->data[2], - FRF_CZ_RMFT_DEST_MAC_LO, spec->data[1], - FRF_CZ_RMFT_VLAN_ID, spec->data[0]); - data3 = is_wild; - break; - } - - default: - BUG(); - } - - return spec->data[0] ^ spec->data[1] ^ spec->data[2] ^ data3; -} - -static bool efx_filter_equal(const struct efx_filter_spec *left, - const struct efx_filter_spec *right) -{ - if (left->type != right->type || - memcmp(left->data, right->data, sizeof(left->data))) - return false; - - return true; -} - -static int efx_filter_search(struct efx_filter_table *table, - struct efx_filter_spec *spec, u32 key, - bool for_insert, int *depth_required) -{ - unsigned hash, incr, filter_idx, depth; - struct efx_filter_spec *cmp; - - hash = efx_filter_hash(key); - incr = efx_filter_increment(key); - - for (depth = 1, filter_idx = hash & (table->size - 1); - test_bit(filter_idx, table->used_bitmap); - ++depth) { - cmp = &table->spec[filter_idx]; - if (efx_filter_equal(spec, cmp)) - goto found; - filter_idx = (filter_idx + incr) & (table->size - 1); - } - if (!for_insert) - return -ENOENT; -found: - *depth_required = depth; - return filter_idx; -} - -/** - * efx_filter_insert_filter - add or replace a filter - * @efx: NIC in which to insert the filter - * @spec: Specification for the filter - * @replace: Flag for whether the specified filter may replace a filter - * with an identical match expression and equal or lower priority - * - * On success, return the filter index within its table. - * On failure, return a negative error code. - */ -int efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec, - bool replace) -{ - struct efx_filter_state *state = efx->filter_state; - enum efx_filter_table_id table_id = - efx_filter_type_table_id(spec->type); - struct efx_filter_table *table = &state->table[table_id]; - struct efx_filter_spec *saved_spec; - efx_oword_t filter; - int filter_idx, depth; - u32 key; - int rc; - - if (table->size == 0) - return -EINVAL; - - key = efx_filter_build(&filter, spec); - - netif_vdbg(efx, hw, efx->net_dev, - "%s: type %d search_depth=%d", __func__, spec->type, - state->search_depth[spec->type]); - - spin_lock_bh(&state->lock); - - rc = efx_filter_search(table, spec, key, true, &depth); - if (rc < 0) - goto out; - filter_idx = rc; - BUG_ON(filter_idx >= table->size); - saved_spec = &table->spec[filter_idx]; - - if (test_bit(filter_idx, table->used_bitmap)) { - /* Should we replace the existing filter? */ - if (!replace) { - rc = -EEXIST; - goto out; - } - if (spec->priority < saved_spec->priority) { - rc = -EPERM; - goto out; - } - } else { - __set_bit(filter_idx, table->used_bitmap); - ++table->used; - } - *saved_spec = *spec; - - if (state->search_depth[spec->type] < depth) { - state->search_depth[spec->type] = depth; - efx_filter_push_rx_limits(efx); - } - - efx_writeo(efx, &filter, table->offset + table->step * filter_idx); - - netif_vdbg(efx, hw, efx->net_dev, - "%s: filter type %d index %d rxq %u set", - __func__, spec->type, filter_idx, spec->dmaq_id); - -out: - spin_unlock_bh(&state->lock); - return rc; -} - -static void efx_filter_table_clear_entry(struct efx_nic *efx, - struct efx_filter_table *table, - int filter_idx) -{ - static efx_oword_t filter; - - if (test_bit(filter_idx, table->used_bitmap)) { - __clear_bit(filter_idx, table->used_bitmap); - --table->used; - memset(&table->spec[filter_idx], 0, sizeof(table->spec[0])); - - efx_writeo(efx, &filter, - table->offset + table->step * filter_idx); - } -} - -/** - * efx_filter_remove_filter - remove a filter by specification - * @efx: NIC from which to remove the filter - * @spec: Specification for the filter - * - * On success, return zero. - * On failure, return a negative error code. - */ -int efx_filter_remove_filter(struct efx_nic *efx, struct efx_filter_spec *spec) -{ - struct efx_filter_state *state = efx->filter_state; - enum efx_filter_table_id table_id = - efx_filter_type_table_id(spec->type); - struct efx_filter_table *table = &state->table[table_id]; - struct efx_filter_spec *saved_spec; - efx_oword_t filter; - int filter_idx, depth; - u32 key; - int rc; - - key = efx_filter_build(&filter, spec); - - spin_lock_bh(&state->lock); - - rc = efx_filter_search(table, spec, key, false, &depth); - if (rc < 0) - goto out; - filter_idx = rc; - saved_spec = &table->spec[filter_idx]; - - if (spec->priority < saved_spec->priority) { - rc = -EPERM; - goto out; - } - - efx_filter_table_clear_entry(efx, table, filter_idx); - if (table->used == 0) - efx_filter_table_reset_search_depth(state, table_id); - rc = 0; - -out: - spin_unlock_bh(&state->lock); - return rc; -} - -/** - * efx_filter_table_clear - remove filters from a table by priority - * @efx: NIC from which to remove the filters - * @table_id: Table from which to remove the filters - * @priority: Maximum priority to remove - */ -void efx_filter_table_clear(struct efx_nic *efx, - enum efx_filter_table_id table_id, - enum efx_filter_priority priority) -{ - struct efx_filter_state *state = efx->filter_state; - struct efx_filter_table *table = &state->table[table_id]; - int filter_idx; - - spin_lock_bh(&state->lock); - - for (filter_idx = 0; filter_idx < table->size; ++filter_idx) - if (table->spec[filter_idx].priority <= priority) - efx_filter_table_clear_entry(efx, table, filter_idx); - if (table->used == 0) - efx_filter_table_reset_search_depth(state, table_id); - - spin_unlock_bh(&state->lock); -} - -/* Restore filter stater after reset */ -void efx_restore_filters(struct efx_nic *efx) -{ - struct efx_filter_state *state = efx->filter_state; - enum efx_filter_table_id table_id; - struct efx_filter_table *table; - efx_oword_t filter; - int filter_idx; - - spin_lock_bh(&state->lock); - - for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) { - table = &state->table[table_id]; - for (filter_idx = 0; filter_idx < table->size; filter_idx++) { - if (!test_bit(filter_idx, table->used_bitmap)) - continue; - efx_filter_build(&filter, &table->spec[filter_idx]); - efx_writeo(efx, &filter, - table->offset + table->step * filter_idx); - } - } - - efx_filter_push_rx_limits(efx); - - spin_unlock_bh(&state->lock); -} - -int efx_probe_filters(struct efx_nic *efx) -{ - struct efx_filter_state *state; - struct efx_filter_table *table; - unsigned table_id; - - state = kzalloc(sizeof(*efx->filter_state), GFP_KERNEL); - if (!state) - return -ENOMEM; - efx->filter_state = state; - - spin_lock_init(&state->lock); - - if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) { - table = &state->table[EFX_FILTER_TABLE_RX_IP]; - table->offset = FR_BZ_RX_FILTER_TBL0; - table->size = FR_BZ_RX_FILTER_TBL0_ROWS; - table->step = FR_BZ_RX_FILTER_TBL0_STEP; - } - - if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) { - table = &state->table[EFX_FILTER_TABLE_RX_MAC]; - table->offset = FR_CZ_RX_MAC_FILTER_TBL0; - table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS; - table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP; - } - - for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) { - table = &state->table[table_id]; - if (table->size == 0) - continue; - table->used_bitmap = kcalloc(BITS_TO_LONGS(table->size), - sizeof(unsigned long), - GFP_KERNEL); - if (!table->used_bitmap) - goto fail; - table->spec = vmalloc(table->size * sizeof(*table->spec)); - if (!table->spec) - goto fail; - memset(table->spec, 0, table->size * sizeof(*table->spec)); - } - - return 0; - -fail: - efx_remove_filters(efx); - return -ENOMEM; -} - -void efx_remove_filters(struct efx_nic *efx) -{ - struct efx_filter_state *state = efx->filter_state; - enum efx_filter_table_id table_id; - - for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) { - kfree(state->table[table_id].used_bitmap); - vfree(state->table[table_id].spec); - } - kfree(state); -} diff --git a/trunk/drivers/net/sfc/filter.h b/trunk/drivers/net/sfc/filter.h deleted file mode 100644 index a53319ded79c..000000000000 --- a/trunk/drivers/net/sfc/filter.h +++ /dev/null @@ -1,189 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2010 Solarflare Communications Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, incorporated herein by reference. - */ - -#ifndef EFX_FILTER_H -#define EFX_FILTER_H - -#include - -enum efx_filter_table_id { - EFX_FILTER_TABLE_RX_IP = 0, - EFX_FILTER_TABLE_RX_MAC, - EFX_FILTER_TABLE_COUNT, -}; - -/** - * enum efx_filter_type - type of hardware filter - * @EFX_FILTER_RX_TCP_FULL: RX, matching TCP/IPv4 4-tuple - * @EFX_FILTER_RX_TCP_WILD: RX, matching TCP/IPv4 destination (host, port) - * @EFX_FILTER_RX_UDP_FULL: RX, matching UDP/IPv4 4-tuple - * @EFX_FILTER_RX_UDP_WILD: RX, matching UDP/IPv4 destination (host, port) - * @EFX_FILTER_RX_MAC_FULL: RX, matching Ethernet destination MAC address, VID - * @EFX_FILTER_RX_MAC_WILD: RX, matching Ethernet destination MAC address - * - * Falcon NICs only support the RX TCP/IPv4 and UDP/IPv4 filter types. - */ -enum efx_filter_type { - EFX_FILTER_RX_TCP_FULL = 0, - EFX_FILTER_RX_TCP_WILD, - EFX_FILTER_RX_UDP_FULL, - EFX_FILTER_RX_UDP_WILD, - EFX_FILTER_RX_MAC_FULL = 4, - EFX_FILTER_RX_MAC_WILD, - EFX_FILTER_TYPE_COUNT, -}; - -/** - * enum efx_filter_priority - priority of a hardware filter specification - * @EFX_FILTER_PRI_HINT: Performance hint - * @EFX_FILTER_PRI_MANUAL: Manually configured filter - * @EFX_FILTER_PRI_REQUIRED: Required for correct behaviour - */ -enum efx_filter_priority { - EFX_FILTER_PRI_HINT = 0, - EFX_FILTER_PRI_MANUAL, - EFX_FILTER_PRI_REQUIRED, -}; - -/** - * enum efx_filter_flags - flags for hardware filter specifications - * @EFX_FILTER_FLAG_RX_RSS: Use RSS to spread across multiple queues. - * By default, matching packets will be delivered only to the - * specified queue. If this flag is set, they will be delivered - * to a range of queues offset from the specified queue number - * according to the indirection table. - * @EFX_FILTER_FLAG_RX_SCATTER: Enable DMA scatter on the receiving - * queue. - * @EFX_FILTER_FLAG_RX_OVERRIDE_IP: Enables a MAC filter to override - * any IP filter that matches the same packet. By default, IP - * filters take precedence. - * - * Currently, no flags are defined for TX filters. - */ -enum efx_filter_flags { - EFX_FILTER_FLAG_RX_RSS = 0x01, - EFX_FILTER_FLAG_RX_SCATTER = 0x02, - EFX_FILTER_FLAG_RX_OVERRIDE_IP = 0x04, -}; - -/** - * struct efx_filter_spec - specification for a hardware filter - * @type: Type of match to be performed, from &enum efx_filter_type - * @priority: Priority of the filter, from &enum efx_filter_priority - * @flags: Miscellaneous flags, from &enum efx_filter_flags - * @dmaq_id: Source/target queue index - * @data: Match data (type-dependent) - * - * Use the efx_filter_set_*() functions to initialise the @type and - * @data fields. - */ -struct efx_filter_spec { - u8 type:4; - u8 priority:4; - u8 flags; - u16 dmaq_id; - u32 data[3]; -}; - -/** - * efx_filter_set_rx_tcp_full - specify RX filter with TCP/IPv4 full match - * @spec: Specification to initialise - * @shost: Source host address (host byte order) - * @sport: Source port (host byte order) - * @dhost: Destination host address (host byte order) - * @dport: Destination port (host byte order) - */ -static inline void -efx_filter_set_rx_tcp_full(struct efx_filter_spec *spec, - u32 shost, u16 sport, u32 dhost, u16 dport) -{ - spec->type = EFX_FILTER_RX_TCP_FULL; - spec->data[0] = sport | shost << 16; - spec->data[1] = dport << 16 | shost >> 16; - spec->data[2] = dhost; -} - -/** - * efx_filter_set_rx_tcp_wild - specify RX filter with TCP/IPv4 wildcard match - * @spec: Specification to initialise - * @dhost: Destination host address (host byte order) - * @dport: Destination port (host byte order) - */ -static inline void -efx_filter_set_rx_tcp_wild(struct efx_filter_spec *spec, u32 dhost, u16 dport) -{ - spec->type = EFX_FILTER_RX_TCP_WILD; - spec->data[0] = 0; - spec->data[1] = dport << 16; - spec->data[2] = dhost; -} - -/** - * efx_filter_set_rx_udp_full - specify RX filter with UDP/IPv4 full match - * @spec: Specification to initialise - * @shost: Source host address (host byte order) - * @sport: Source port (host byte order) - * @dhost: Destination host address (host byte order) - * @dport: Destination port (host byte order) - */ -static inline void -efx_filter_set_rx_udp_full(struct efx_filter_spec *spec, - u32 shost, u16 sport, u32 dhost, u16 dport) -{ - spec->type = EFX_FILTER_RX_UDP_FULL; - spec->data[0] = sport | shost << 16; - spec->data[1] = dport << 16 | shost >> 16; - spec->data[2] = dhost; -} - -/** - * efx_filter_set_rx_udp_wild - specify RX filter with UDP/IPv4 wildcard match - * @spec: Specification to initialise - * @dhost: Destination host address (host byte order) - * @dport: Destination port (host byte order) - */ -static inline void -efx_filter_set_rx_udp_wild(struct efx_filter_spec *spec, u32 dhost, u16 dport) -{ - spec->type = EFX_FILTER_RX_UDP_WILD; - spec->data[0] = dport; - spec->data[1] = 0; - spec->data[2] = dhost; -} - -/** - * efx_filter_set_rx_mac_full - specify RX filter with MAC full match - * @spec: Specification to initialise - * @vid: VLAN ID - * @addr: Destination MAC address - */ -static inline void efx_filter_set_rx_mac_full(struct efx_filter_spec *spec, - u16 vid, const u8 *addr) -{ - spec->type = EFX_FILTER_RX_MAC_FULL; - spec->data[0] = vid; - spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5]; - spec->data[2] = addr[0] << 8 | addr[1]; -} - -/** - * efx_filter_set_rx_mac_full - specify RX filter with MAC wildcard match - * @spec: Specification to initialise - * @addr: Destination MAC address - */ -static inline void efx_filter_set_rx_mac_wild(struct efx_filter_spec *spec, - const u8 *addr) -{ - spec->type = EFX_FILTER_RX_MAC_WILD; - spec->data[0] = 0; - spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5]; - spec->data[2] = addr[0] << 8 | addr[1]; -} - -#endif /* EFX_FILTER_H */ diff --git a/trunk/drivers/net/sfc/net_driver.h b/trunk/drivers/net/sfc/net_driver.h index ea6691c83fba..152342dbff29 100644 --- a/trunk/drivers/net/sfc/net_driver.h +++ b/trunk/drivers/net/sfc/net_driver.h @@ -619,8 +619,6 @@ union efx_multicast_hash { efx_oword_t oword[EFX_MCAST_HASH_ENTRIES / sizeof(efx_oword_t) / 8]; }; -struct efx_filter_state; - /** * struct efx_nic - an Efx NIC * @name: Device name (net device name or bus id before net device registered) @@ -801,8 +799,6 @@ struct efx_nic { u64 loopback_modes; void *loopback_selftest; - - struct efx_filter_state *filter_state; }; static inline int efx_dev_registered(struct efx_nic *efx) diff --git a/trunk/drivers/net/sfc/nic.c b/trunk/drivers/net/sfc/nic.c index c4de0014441c..6c5c0cefa9d8 100644 --- a/trunk/drivers/net/sfc/nic.c +++ b/trunk/drivers/net/sfc/nic.c @@ -1849,7 +1849,8 @@ static const struct efx_nic_reg_table efx_nic_reg_tables[] = { REGISTER_TABLE_BB_CZ(TX_DESC_PTR_TBL), REGISTER_TABLE_AA(EVQ_PTR_TBL_KER), REGISTER_TABLE_BB_CZ(EVQ_PTR_TBL), - /* We can't reasonably read all of the buffer table (up to 8MB!). + /* The register buffer is allocated with slab, so we can't + * reasonably read all of the buffer table (up to 8MB!). * However this driver will only use a few entries. Reading * 1K entries allows for some expansion of queue count and * size before we need to change the version. */ @@ -1857,6 +1858,7 @@ static const struct efx_nic_reg_table efx_nic_reg_tables[] = { A, A, 8, 1024), REGISTER_TABLE_DIMENSIONS(BUF_FULL_TBL, FR_BZ_BUF_FULL_TBL, B, Z, 8, 1024), + /* RX_FILTER_TBL{0,1} is huge and not used by this driver */ REGISTER_TABLE_CZ(RX_MAC_FILTER_TBL0), REGISTER_TABLE_BB_CZ(TIMER_TBL), REGISTER_TABLE_BB_CZ(TX_PACE_TBL), @@ -1866,7 +1868,6 @@ static const struct efx_nic_reg_table efx_nic_reg_tables[] = { REGISTER_TABLE_CZ(MC_TREG_SMEM), /* MSIX_PBA_TABLE is not mapped */ /* SRM_DBG is not mapped (and is redundant with BUF_FLL_TBL) */ - REGISTER_TABLE_BZ(RX_FILTER_TBL0), }; size_t efx_nic_get_regs_len(struct efx_nic *efx) diff --git a/trunk/drivers/net/sfc/regs.h b/trunk/drivers/net/sfc/regs.h index 96430ed81c36..18a3be428348 100644 --- a/trunk/drivers/net/sfc/regs.h +++ b/trunk/drivers/net/sfc/regs.h @@ -2893,20 +2893,6 @@ #define FRF_AB_XX_FORCE_SIG_WIDTH 8 #define FFE_AB_XX_FORCE_SIG_ALL_LANES 0xff -/* RX_MAC_FILTER_TBL0 */ -/* RMFT_DEST_MAC is wider than 32 bits */ -#define FRF_CZ_RMFT_DEST_MAC_LO_LBN 12 -#define FRF_CZ_RMFT_DEST_MAC_LO_WIDTH 32 -#define FRF_CZ_RMFT_DEST_MAC_HI_LBN 44 -#define FRF_CZ_RMFT_DEST_MAC_HI_WIDTH 16 - -/* TX_MAC_FILTER_TBL0 */ -/* TMFT_SRC_MAC is wider than 32 bits */ -#define FRF_CZ_TMFT_SRC_MAC_LO_LBN 12 -#define FRF_CZ_TMFT_SRC_MAC_LO_WIDTH 32 -#define FRF_CZ_TMFT_SRC_MAC_HI_LBN 44 -#define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH 16 - /* DRIVER_EV */ /* Sub-fields of an RX flush completion event */ #define FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_LBN 12 diff --git a/trunk/drivers/net/sfc/siena.c b/trunk/drivers/net/sfc/siena.c index 2115f95ddc88..9f5368049694 100644 --- a/trunk/drivers/net/sfc/siena.c +++ b/trunk/drivers/net/sfc/siena.c @@ -651,6 +651,6 @@ struct efx_nic_type siena_a0_nic_type = { .tx_dc_base = 0x88000, .rx_dc_base = 0x68000, .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXHASH | NETIF_F_NTUPLE), + NETIF_F_RXHASH), .reset_world_flags = ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT, }; diff --git a/trunk/include/linux/ethtool.h b/trunk/include/linux/ethtool.h index 8a3338ceb438..b67af60a8890 100644 --- a/trunk/include/linux/ethtool.h +++ b/trunk/include/linux/ethtool.h @@ -14,7 +14,6 @@ #define _LINUX_ETHTOOL_H #include -#include /* This should work for both 32 and 64 bit userland. */ struct ethtool_cmd { @@ -392,7 +391,6 @@ struct ethtool_rx_flow_spec { struct ethtool_ah_espip4_spec ah_ip4_spec; struct ethtool_ah_espip4_spec esp_ip4_spec; struct ethtool_usrip4_spec usr_ip4_spec; - struct ethhdr ether_spec; __u8 hdata[72]; } h_u, m_u; __u64 ring_cookie; @@ -485,7 +483,6 @@ struct ethtool_rx_ntuple_flow_spec { struct ethtool_ah_espip4_spec ah_ip4_spec; struct ethtool_ah_espip4_spec esp_ip4_spec; struct ethtool_usrip4_spec usr_ip4_spec; - struct ethhdr ether_spec; __u8 hdata[72]; } h_u, m_u; @@ -495,12 +492,11 @@ struct ethtool_rx_ntuple_flow_spec { __u64 data_mask; __s32 action; -#define ETHTOOL_RXNTUPLE_ACTION_DROP (-1) /* drop packet */ -#define ETHTOOL_RXNTUPLE_ACTION_CLEAR (-2) /* clear filter */ +#define ETHTOOL_RXNTUPLE_ACTION_DROP -1 /* drop packet */ }; /** - * struct ethtool_rx_ntuple - command to set or clear RX flow filter + * struct ethtool_rx_ntuple - command to set RX flow filter * @cmd: Command number - %ETHTOOL_SRXNTUPLE * @fs: Flow filter specification */ @@ -844,7 +840,7 @@ struct ethtool_ops { #define WAKE_MAGIC (1 << 5) #define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ -/* L2-L4 network traffic flow types */ +/* L3-L4 network traffic flow types */ #define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */ #define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */ #define SCTP_V4_FLOW 0x03 /* hash or spec (sctp_ip4_spec) */ @@ -860,7 +856,6 @@ struct ethtool_ops { #define IP_USER_FLOW 0x0d /* spec only (usr_ip4_spec) */ #define IPV4_FLOW 0x10 /* hash only */ #define IPV6_FLOW 0x11 /* hash only */ -#define ETHER_FLOW 0x12 /* spec only (ether_spec) */ /* L3-L4 network traffic flow hash options */ #define RXH_L2DA (1 << 1) diff --git a/trunk/net/8021q/vlan.h b/trunk/net/8021q/vlan.h index b26ce343072c..8d9503ad01da 100644 --- a/trunk/net/8021q/vlan.h +++ b/trunk/net/8021q/vlan.h @@ -25,7 +25,6 @@ struct vlan_priority_tci_mapping { * @rx_multicast: number of received multicast packets * @syncp: synchronization point for 64bit counters * @rx_errors: number of errors - * @rx_dropped: number of dropped packets */ struct vlan_rx_stats { u64 rx_packets; @@ -33,7 +32,6 @@ struct vlan_rx_stats { u64 rx_multicast; struct u64_stats_sync syncp; unsigned long rx_errors; - unsigned long rx_dropped; }; /** diff --git a/trunk/net/8021q/vlan_dev.c b/trunk/net/8021q/vlan_dev.c index 94a1feddeb49..3bccdd12a264 100644 --- a/trunk/net/8021q/vlan_dev.c +++ b/trunk/net/8021q/vlan_dev.c @@ -225,10 +225,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, } } - if (unlikely(netif_rx(skb) == NET_RX_DROP)) { - if (rx_stats) - rx_stats->rx_dropped++; - } + netif_rx(skb); rcu_read_unlock(); return NET_RX_SUCCESS; @@ -846,15 +843,13 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st accum.rx_packets += rxpackets; accum.rx_bytes += rxbytes; accum.rx_multicast += rxmulticast; - /* rx_errors, rx_dropped are ulong, not protected by syncp */ + /* rx_errors is an ulong, not protected by syncp */ accum.rx_errors += p->rx_errors; - accum.rx_dropped += p->rx_dropped; } stats->rx_packets = accum.rx_packets; stats->rx_bytes = accum.rx_bytes; stats->rx_errors = accum.rx_errors; stats->multicast = accum.rx_multicast; - stats->rx_dropped = accum.rx_dropped; } return stats; } diff --git a/trunk/net/core/ethtool.c b/trunk/net/core/ethtool.c index dae2fd053c2b..91ffce20c36b 100644 --- a/trunk/net/core/ethtool.c +++ b/trunk/net/core/ethtool.c @@ -815,7 +815,7 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) if (regs.len > reglen) regs.len = reglen; - regbuf = vmalloc(reglen); + regbuf = kmalloc(reglen, GFP_USER); if (!regbuf) return -ENOMEM; @@ -830,7 +830,7 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) ret = 0; out: - vfree(regbuf); + kfree(regbuf); return ret; } diff --git a/trunk/net/dccp/ccid.h b/trunk/net/dccp/ccid.h index 6df6f8ac9636..6d16a9070ff0 100644 --- a/trunk/net/dccp/ccid.h +++ b/trunk/net/dccp/ccid.h @@ -62,18 +62,14 @@ struct ccid_operations { void (*ccid_hc_tx_exit)(struct sock *sk); void (*ccid_hc_rx_packet_recv)(struct sock *sk, struct sk_buff *skb); - int (*ccid_hc_rx_parse_options)(struct sock *sk, - unsigned char option, - unsigned char len, u16 idx, - unsigned char* value); + int (*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt, + u8 opt, u8 *val, u8 len); int (*ccid_hc_rx_insert_options)(struct sock *sk, struct sk_buff *skb); void (*ccid_hc_tx_packet_recv)(struct sock *sk, struct sk_buff *skb); - int (*ccid_hc_tx_parse_options)(struct sock *sk, - unsigned char option, - unsigned char len, u16 idx, - unsigned char* value); + int (*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt, + u8 opt, u8 *val, u8 len); int (*ccid_hc_tx_send_packet)(struct sock *sk, struct sk_buff *skb); void (*ccid_hc_tx_packet_sent)(struct sock *sk, @@ -168,27 +164,31 @@ static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk, ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb); } +/** + * ccid_hc_tx_parse_options - Parse CCID-specific options sent by the receiver + * @pkt: type of packet that @opt appears on (RFC 4340, 5.1) + * @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3) + * @val: value of @opt + * @len: length of @val in bytes + */ static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, - unsigned char option, - unsigned char len, u16 idx, - unsigned char* value) + u8 pkt, u8 opt, u8 *val, u8 len) { - int rc = 0; - if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL) - rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx, - value); - return rc; + if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL) + return 0; + return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len); } +/** + * ccid_hc_rx_parse_options - Parse CCID-specific options sent by the sender + * Arguments are analogous to ccid_hc_tx_parse_options() + */ static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk, - unsigned char option, - unsigned char len, u16 idx, - unsigned char* value) + u8 pkt, u8 opt, u8 *val, u8 len) { - int rc = 0; - if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL) - rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value); - return rc; + if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL) + return 0; + return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len); } static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk, diff --git a/trunk/net/dccp/ccids/ccid3.c b/trunk/net/dccp/ccids/ccid3.c index ce8059130070..be1b8baaf298 100644 --- a/trunk/net/dccp/ccids/ccid3.c +++ b/trunk/net/dccp/ccids/ccid3.c @@ -481,9 +481,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) jiffies + usecs_to_jiffies(t_nfb)); } -static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, - unsigned char len, u16 idx, - unsigned char *value) +static int ccid3_hc_tx_parse_options(struct sock *sk, u8 packet_type, + u8 option, u8 *optval, u8 optlen) { struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); struct ccid3_options_received *opt_recv = &hc->tx_options_received; @@ -492,12 +491,15 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, switch (option) { case TFRC_OPT_RECEIVE_RATE: case TFRC_OPT_LOSS_EVENT_RATE: - if (unlikely(len != 4)) { + /* Must be ignored on Data packets, cf. RFC 4342 8.3 and 8.5 */ + if (packet_type == DCCP_PKT_DATA) + break; + if (unlikely(optlen != 4)) { DCCP_WARN("%s(%p), invalid len %d for %u\n", - dccp_role(sk), sk, len, option); + dccp_role(sk), sk, optlen, option); return -EINVAL; } - opt_val = ntohl(get_unaligned((__be32 *)value)); + opt_val = ntohl(get_unaligned((__be32 *)optval)); if (option == TFRC_OPT_RECEIVE_RATE) { opt_recv->ccid3or_receive_rate = opt_val; diff --git a/trunk/net/dccp/options.c b/trunk/net/dccp/options.c index bfda087bd90d..e4983e3d2616 100644 --- a/trunk/net/dccp/options.c +++ b/trunk/net/dccp/options.c @@ -226,23 +226,15 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n", dccp_role(sk), elapsed_time); break; - case 128 ... 191: { - const u16 idx = value - options; - + case 128 ... 191: if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk, - opt, len, idx, - value) != 0) + pkt_type, opt, value, len)) goto out_invalid_option; - } break; - case 192 ... 255: { - const u16 idx = value - options; - + case 192 ... 255: if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk, - opt, len, idx, - value) != 0) + pkt_type, opt, value, len)) goto out_invalid_option; - } break; default: DCCP_CRIT("DCCP(%p): option %d(len=%d) not " diff --git a/trunk/net/ipv4/ip_gre.c b/trunk/net/ipv4/ip_gre.c index 714b6a80361d..fc20e687e933 100644 --- a/trunk/net/ipv4/ip_gre.c +++ b/trunk/net/ipv4/ip_gre.c @@ -647,11 +647,9 @@ static int ipgre_rcv(struct sk_buff *skb) skb_reset_network_header(skb); ipgre_ecn_decapsulate(iph, skb); - if (netif_rx(skb) == NET_RX_DROP) - stats->rx_dropped++; - + netif_rx(skb); rcu_read_unlock(); - return 0; + return(0); } icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); diff --git a/trunk/net/ipv4/ipip.c b/trunk/net/ipv4/ipip.c index babd25278106..8de8888dc95a 100644 --- a/trunk/net/ipv4/ipip.c +++ b/trunk/net/ipv4/ipip.c @@ -377,10 +377,7 @@ static int ipip_rcv(struct sk_buff *skb) skb_tunnel_rx(skb, tunnel->dev); ipip_ecn_decapsulate(iph, skb); - - if (netif_rx(skb) == NET_RX_DROP) - tunnel->dev->stats.rx_dropped++; - + netif_rx(skb); rcu_read_unlock(); return 0; } diff --git a/trunk/net/ipv6/ip6_tunnel.c b/trunk/net/ipv6/ip6_tunnel.c index f6d9f683543e..9289cecac4de 100644 --- a/trunk/net/ipv6/ip6_tunnel.c +++ b/trunk/net/ipv6/ip6_tunnel.c @@ -725,10 +725,7 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, skb_tunnel_rx(skb, t->dev); dscp_ecn_decapsulate(t, ipv6h, skb); - - if (netif_rx(skb) == NET_RX_DROP) - t->dev->stats.rx_dropped++; - + netif_rx(skb); rcu_read_unlock(); return 0; } diff --git a/trunk/net/ipv6/ip6mr.c b/trunk/net/ipv6/ip6mr.c index 2640c9be589d..66078dad7fe8 100644 --- a/trunk/net/ipv6/ip6mr.c +++ b/trunk/net/ipv6/ip6mr.c @@ -666,9 +666,7 @@ static int pim6_rcv(struct sk_buff *skb) skb_tunnel_rx(skb, reg_dev); - if (netif_rx(skb) == NET_RX_DROP) - reg_dev->stats.rx_dropped++; - + netif_rx(skb); dev_put(reg_dev); return 0; drop: diff --git a/trunk/net/ipv6/sit.c b/trunk/net/ipv6/sit.c index 8a0399822230..6822481ff766 100644 --- a/trunk/net/ipv6/sit.c +++ b/trunk/net/ipv6/sit.c @@ -564,10 +564,7 @@ static int ipip6_rcv(struct sk_buff *skb) skb_tunnel_rx(skb, tunnel->dev); ipip6_ecn_decapsulate(iph, skb); - - if (netif_rx(skb) == NET_RX_DROP) - tunnel->dev->stats.rx_dropped++; - + netif_rx(skb); rcu_read_unlock(); return 0; }