mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 10:41:38 -04:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (92 commits) gianfar: Revive VLAN support vlan: Export symbols as non GPL symbols. bnx2x: tx_has_work should not wait for FW netxen: reduce memory footprint netxen: fix vlan tso/checksum offload net: Fix linux/if_frad.h's suitability for userspace. net: Move config NET_NS to from net/Kconfig to init/Kconfig isdn: Fix missing ifdef in isdn_ppp networking: document "nc" in addition to "netcat" in netconsole.txt e1000e: workaround hw errata af_key: initialize xfrm encap_oa virtio_net: Fix MAX_PACKET_LEN to support 802.1Q VLANs lcs: fix compilation for !CONFIG_IP_MULTICAST rtl8187: Add termination packet to prevent stall iwlwifi: fix rs_get_rate WARN_ON() p54usb: fix packet loss with first generation devices sctp: Fix another socket race during accept/peeloff sctp: Properly timestamp outgoing data chunks for rtx purposes sctp: Correctly start rtx timer on new packet transmissions. sctp: Fix crc32c calculations on big-endian arhes. ...
This commit is contained in:
commit
924d26df6b
67 changed files with 801 additions and 464 deletions
|
|
@ -62,13 +62,13 @@ struct net_device *vlan_dev_real_dev(const struct net_device *dev)
|
|||
{
|
||||
return vlan_dev_info(dev)->real_dev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vlan_dev_real_dev);
|
||||
EXPORT_SYMBOL(vlan_dev_real_dev);
|
||||
|
||||
u16 vlan_dev_vlan_id(const struct net_device *dev)
|
||||
{
|
||||
return vlan_dev_info(dev)->vlan_id;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vlan_dev_vlan_id);
|
||||
EXPORT_SYMBOL(vlan_dev_vlan_id);
|
||||
|
||||
static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,
|
||||
unsigned int vlan_tci, struct sk_buff *skb)
|
||||
|
|
|
|||
|
|
@ -618,7 +618,7 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
|
|||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = p9_idpool_get(clnt->fidpool);
|
||||
if (fid->fid < 0) {
|
||||
if (ret < 0) {
|
||||
ret = -ENOSPC;
|
||||
goto error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,14 +24,6 @@ if NET
|
|||
|
||||
menu "Networking options"
|
||||
|
||||
config NET_NS
|
||||
bool "Network namespace support"
|
||||
default n
|
||||
depends on EXPERIMENTAL && NAMESPACES
|
||||
help
|
||||
Allow user space to create what appear to be multiple instances
|
||||
of the network stack.
|
||||
|
||||
config COMPAT_NET_DEV_OPS
|
||||
def_bool y
|
||||
|
||||
|
|
|
|||
|
|
@ -1534,7 +1534,19 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
|
|||
skb->mac_len = skb->network_header - skb->mac_header;
|
||||
__skb_pull(skb, skb->mac_len);
|
||||
|
||||
if (WARN_ON(skb->ip_summed != CHECKSUM_PARTIAL)) {
|
||||
if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) {
|
||||
struct net_device *dev = skb->dev;
|
||||
struct ethtool_drvinfo info = {};
|
||||
|
||||
if (dev && dev->ethtool_ops && dev->ethtool_ops->get_drvinfo)
|
||||
dev->ethtool_ops->get_drvinfo(dev, &info);
|
||||
|
||||
WARN(1, "%s: caps=(0x%lx, 0x%lx) len=%d data_len=%d "
|
||||
"ip_summed=%d",
|
||||
info.driver, dev ? dev->features : 0L,
|
||||
skb->sk ? skb->sk->sk_route_caps : 0L,
|
||||
skb->len, skb->data_len, skb->ip_summed);
|
||||
|
||||
if (skb_header_cloned(skb) &&
|
||||
(err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
|
||||
return ERR_PTR(err);
|
||||
|
|
@ -2524,6 +2536,7 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi,
|
|||
|
||||
if (!pskb_may_pull(skb, ETH_HLEN)) {
|
||||
napi_reuse_skb(napi, skb);
|
||||
skb = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -341,8 +341,8 @@ again:
|
|||
rv = register_pernet_operations(first_device, ops);
|
||||
if (rv < 0)
|
||||
ida_remove(&net_generic_ids, *id);
|
||||
mutex_unlock(&net_mutex);
|
||||
out:
|
||||
mutex_unlock(&net_mutex);
|
||||
return rv;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(register_pernet_gen_subsys);
|
||||
|
|
|
|||
|
|
@ -73,17 +73,13 @@ static struct kmem_cache *skbuff_fclone_cache __read_mostly;
|
|||
static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
|
||||
struct pipe_buffer *buf)
|
||||
{
|
||||
struct sk_buff *skb = (struct sk_buff *) buf->private;
|
||||
|
||||
kfree_skb(skb);
|
||||
put_page(buf->page);
|
||||
}
|
||||
|
||||
static void sock_pipe_buf_get(struct pipe_inode_info *pipe,
|
||||
struct pipe_buffer *buf)
|
||||
{
|
||||
struct sk_buff *skb = (struct sk_buff *) buf->private;
|
||||
|
||||
skb_get(skb);
|
||||
get_page(buf->page);
|
||||
}
|
||||
|
||||
static int sock_pipe_buf_steal(struct pipe_inode_info *pipe,
|
||||
|
|
@ -1334,9 +1330,19 @@ fault:
|
|||
*/
|
||||
static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i)
|
||||
{
|
||||
struct sk_buff *skb = (struct sk_buff *) spd->partial[i].private;
|
||||
put_page(spd->pages[i]);
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
static inline struct page *linear_to_page(struct page *page, unsigned int len,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct page *p = alloc_pages(GFP_KERNEL, 0);
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
memcpy(page_address(p) + offset, page_address(page) + offset, len);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1344,16 +1350,23 @@ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i)
|
|||
*/
|
||||
static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page,
|
||||
unsigned int len, unsigned int offset,
|
||||
struct sk_buff *skb)
|
||||
struct sk_buff *skb, int linear)
|
||||
{
|
||||
if (unlikely(spd->nr_pages == PIPE_BUFFERS))
|
||||
return 1;
|
||||
|
||||
if (linear) {
|
||||
page = linear_to_page(page, len, offset);
|
||||
if (!page)
|
||||
return 1;
|
||||
} else
|
||||
get_page(page);
|
||||
|
||||
spd->pages[spd->nr_pages] = page;
|
||||
spd->partial[spd->nr_pages].len = len;
|
||||
spd->partial[spd->nr_pages].offset = offset;
|
||||
spd->partial[spd->nr_pages].private = (unsigned long) skb_get(skb);
|
||||
spd->nr_pages++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1369,7 +1382,7 @@ static inline void __segment_seek(struct page **page, unsigned int *poff,
|
|||
static inline int __splice_segment(struct page *page, unsigned int poff,
|
||||
unsigned int plen, unsigned int *off,
|
||||
unsigned int *len, struct sk_buff *skb,
|
||||
struct splice_pipe_desc *spd)
|
||||
struct splice_pipe_desc *spd, int linear)
|
||||
{
|
||||
if (!*len)
|
||||
return 1;
|
||||
|
|
@ -1392,7 +1405,7 @@ static inline int __splice_segment(struct page *page, unsigned int poff,
|
|||
/* the linear region may spread across several pages */
|
||||
flen = min_t(unsigned int, flen, PAGE_SIZE - poff);
|
||||
|
||||
if (spd_fill_page(spd, page, flen, poff, skb))
|
||||
if (spd_fill_page(spd, page, flen, poff, skb, linear))
|
||||
return 1;
|
||||
|
||||
__segment_seek(&page, &poff, &plen, flen);
|
||||
|
|
@ -1419,7 +1432,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
|
|||
if (__splice_segment(virt_to_page(skb->data),
|
||||
(unsigned long) skb->data & (PAGE_SIZE - 1),
|
||||
skb_headlen(skb),
|
||||
offset, len, skb, spd))
|
||||
offset, len, skb, spd, 1))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
|
|
@ -1429,7 +1442,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
|
|||
const skb_frag_t *f = &skb_shinfo(skb)->frags[seg];
|
||||
|
||||
if (__splice_segment(f->page, f->page_offset, f->size,
|
||||
offset, len, skb, spd))
|
||||
offset, len, skb, spd, 0))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -1442,7 +1455,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
|
|||
* the frag list, if such a thing exists. We'd probably need to recurse to
|
||||
* handle that cleanly.
|
||||
*/
|
||||
int skb_splice_bits(struct sk_buff *__skb, unsigned int offset,
|
||||
int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
|
||||
struct pipe_inode_info *pipe, unsigned int tlen,
|
||||
unsigned int flags)
|
||||
{
|
||||
|
|
@ -1455,16 +1468,6 @@ int skb_splice_bits(struct sk_buff *__skb, unsigned int offset,
|
|||
.ops = &sock_pipe_buf_ops,
|
||||
.spd_release = sock_spd_release,
|
||||
};
|
||||
struct sk_buff *skb;
|
||||
|
||||
/*
|
||||
* I'd love to avoid the clone here, but tcp_read_sock()
|
||||
* ignores reference counts and unconditonally kills the sk_buff
|
||||
* on return from the actor.
|
||||
*/
|
||||
skb = skb_clone(__skb, GFP_KERNEL);
|
||||
if (unlikely(!skb))
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* __skb_splice_bits() only fails if the output has no room left,
|
||||
|
|
@ -1488,15 +1491,9 @@ int skb_splice_bits(struct sk_buff *__skb, unsigned int offset,
|
|||
}
|
||||
|
||||
done:
|
||||
/*
|
||||
* drop our reference to the clone, the pipe consumption will
|
||||
* drop the rest.
|
||||
*/
|
||||
kfree_skb(skb);
|
||||
|
||||
if (spd.nr_pages) {
|
||||
struct sock *sk = skb->sk;
|
||||
int ret;
|
||||
struct sock *sk = __skb->sk;
|
||||
|
||||
/*
|
||||
* Drop the socket lock, otherwise we have reverse
|
||||
|
|
@ -2588,8 +2585,9 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
|
|||
struct sk_buff *nskb;
|
||||
unsigned int headroom;
|
||||
unsigned int hlen = p->data - skb_mac_header(p);
|
||||
unsigned int len = skb->len;
|
||||
|
||||
if (hlen + p->len + skb->len >= 65536)
|
||||
if (hlen + p->len + len >= 65536)
|
||||
return -E2BIG;
|
||||
|
||||
if (skb_shinfo(p)->frag_list)
|
||||
|
|
@ -2651,9 +2649,9 @@ merge:
|
|||
|
||||
done:
|
||||
NAPI_GRO_CB(p)->count++;
|
||||
p->data_len += skb->len;
|
||||
p->truesize += skb->len;
|
||||
p->len += skb->len;
|
||||
p->data_len += len;
|
||||
p->truesize += len;
|
||||
p->len += len;
|
||||
|
||||
NAPI_GRO_CB(skb)->same_flow = 1;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -797,6 +797,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
|
|||
unsigned int nlen;
|
||||
int flush = 1;
|
||||
int proto;
|
||||
__wsum csum;
|
||||
|
||||
if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
|
||||
goto out;
|
||||
|
|
@ -808,6 +809,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
|
|||
|
||||
rcu_read_lock();
|
||||
proto = ipv6_gso_pull_exthdrs(skb, iph->nexthdr);
|
||||
iph = ipv6_hdr(skb);
|
||||
IPV6_GRO_CB(skb)->proto = proto;
|
||||
ops = rcu_dereference(inet6_protos[proto]);
|
||||
if (!ops || !ops->gro_receive)
|
||||
|
|
@ -839,8 +841,13 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
|
|||
|
||||
NAPI_GRO_CB(skb)->flush |= flush;
|
||||
|
||||
csum = skb->csum;
|
||||
skb_postpull_rcsum(skb, iph, skb_network_header_len(skb));
|
||||
|
||||
pp = ops->gro_receive(head, skb);
|
||||
|
||||
skb->csum = csum;
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
|
||||
|
|
|
|||
|
|
@ -1285,6 +1285,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
|||
ext_hdrs[SADB_X_EXT_NAT_T_DPORT-1];
|
||||
natt->encap_dport = n_port->sadb_x_nat_t_port_port;
|
||||
}
|
||||
memset(&natt->encap_oa, 0, sizeof(natt->encap_oa));
|
||||
}
|
||||
|
||||
err = xfrm_init_state(x);
|
||||
|
|
|
|||
|
|
@ -620,8 +620,8 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
|
|||
if (use_short_slot != bss_conf->use_short_slot) {
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "%s: switched to %s slot"
|
||||
" (BSSID=%s)\n",
|
||||
printk(KERN_DEBUG "%s: switched to %s slot time"
|
||||
" (BSSID=%pM)\n",
|
||||
sdata->dev->name,
|
||||
use_short_slot ? "short" : "long",
|
||||
ifsta->bssid);
|
||||
|
|
|
|||
|
|
@ -195,7 +195,6 @@ struct sta_ampdu_mlme {
|
|||
* @tx_packets: number of RX/TX MSDUs
|
||||
* @tx_bytes: number of bytes transmitted to this STA
|
||||
* @tx_fragments: number of transmitted MPDUs
|
||||
* @last_txrate: description of the last used transmit rate
|
||||
* @tid_seq: per-TID sequence numbers for sending to this STA
|
||||
* @ampdu_mlme: A-MPDU state machine state
|
||||
* @timer_to_tid: identity mapping to ID timers
|
||||
|
|
|
|||
|
|
@ -1307,8 +1307,10 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
if (is_multicast_ether_addr(hdr->addr3))
|
||||
memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
|
||||
else
|
||||
if (mesh_nexthop_lookup(skb, osdata))
|
||||
return 0;
|
||||
if (mesh_nexthop_lookup(skb, osdata)) {
|
||||
dev_put(odev);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0)
|
||||
IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh,
|
||||
fwded_frames);
|
||||
|
|
|
|||
|
|
@ -831,13 +831,16 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct,
|
|||
if (!parse_nat_setup) {
|
||||
#ifdef CONFIG_MODULES
|
||||
rcu_read_unlock();
|
||||
spin_unlock_bh(&nf_conntrack_lock);
|
||||
nfnl_unlock();
|
||||
if (request_module("nf-nat-ipv4") < 0) {
|
||||
nfnl_lock();
|
||||
spin_lock_bh(&nf_conntrack_lock);
|
||||
rcu_read_lock();
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
nfnl_lock();
|
||||
spin_lock_bh(&nf_conntrack_lock);
|
||||
rcu_read_lock();
|
||||
if (nfnetlink_parse_nat_setup_hook)
|
||||
return -EAGAIN;
|
||||
|
|
|
|||
|
|
@ -249,6 +249,19 @@ int sctp_rcv(struct sk_buff *skb)
|
|||
*/
|
||||
sctp_bh_lock_sock(sk);
|
||||
|
||||
if (sk != rcvr->sk) {
|
||||
/* Our cached sk is different from the rcvr->sk. This is
|
||||
* because migrate()/accept() may have moved the association
|
||||
* to a new socket and released all the sockets. So now we
|
||||
* are holding a lock on the old socket while the user may
|
||||
* be doing something with the new socket. Switch our veiw
|
||||
* of the current sk.
|
||||
*/
|
||||
sctp_bh_unlock_sock(sk);
|
||||
sk = rcvr->sk;
|
||||
sctp_bh_lock_sock(sk);
|
||||
}
|
||||
|
||||
if (sock_owned_by_user(sk)) {
|
||||
SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG);
|
||||
sctp_add_backlog(sk, skb);
|
||||
|
|
|
|||
|
|
@ -324,14 +324,16 @@ append:
|
|||
switch (chunk->chunk_hdr->type) {
|
||||
case SCTP_CID_DATA:
|
||||
retval = sctp_packet_append_data(packet, chunk);
|
||||
if (SCTP_XMIT_OK != retval)
|
||||
goto finish;
|
||||
/* Disallow SACK bundling after DATA. */
|
||||
packet->has_sack = 1;
|
||||
/* Disallow AUTH bundling after DATA */
|
||||
packet->has_auth = 1;
|
||||
/* Let it be knows that packet has DATA in it */
|
||||
packet->has_data = 1;
|
||||
if (SCTP_XMIT_OK != retval)
|
||||
goto finish;
|
||||
/* timestamp the chunk for rtx purposes */
|
||||
chunk->sent_at = jiffies;
|
||||
break;
|
||||
case SCTP_CID_COOKIE_ECHO:
|
||||
packet->has_cookie_echo = 1;
|
||||
|
|
@ -470,7 +472,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|||
} else
|
||||
chunk->resent = 1;
|
||||
|
||||
chunk->sent_at = jiffies;
|
||||
has_data = 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -929,7 +929,6 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
|
|||
}
|
||||
|
||||
/* Finally, transmit new packets. */
|
||||
start_timer = 0;
|
||||
while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
|
||||
/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
|
||||
* stream identifier.
|
||||
|
|
@ -1028,7 +1027,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
|
|||
list_add_tail(&chunk->transmitted_list,
|
||||
&transport->transmitted);
|
||||
|
||||
sctp_transport_reset_timers(transport, start_timer-1);
|
||||
sctp_transport_reset_timers(transport, 0);
|
||||
|
||||
q->empty = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -421,6 +421,31 @@ static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* freq_in_rule_band - tells us if a frequency is in a frequency band
|
||||
* @freq_range: frequency rule we want to query
|
||||
* @freq_khz: frequency we are inquiring about
|
||||
*
|
||||
* This lets us know if a specific frequency rule is or is not relevant to
|
||||
* a specific frequency's band. Bands are device specific and artificial
|
||||
* definitions (the "2.4 GHz band" and the "5 GHz band"), however it is
|
||||
* safe for now to assume that a frequency rule should not be part of a
|
||||
* frequency's band if the start freq or end freq are off by more than 2 GHz.
|
||||
* This resolution can be lowered and should be considered as we add
|
||||
* regulatory rule support for other "bands".
|
||||
**/
|
||||
static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
|
||||
u32 freq_khz)
|
||||
{
|
||||
#define ONE_GHZ_IN_KHZ 1000000
|
||||
if (abs(freq_khz - freq_range->start_freq_khz) <= (2 * ONE_GHZ_IN_KHZ))
|
||||
return true;
|
||||
if (abs(freq_khz - freq_range->end_freq_khz) <= (2 * ONE_GHZ_IN_KHZ))
|
||||
return true;
|
||||
return false;
|
||||
#undef ONE_GHZ_IN_KHZ
|
||||
}
|
||||
|
||||
/* Converts a country IE to a regulatory domain. A regulatory domain
|
||||
* structure has a lot of information which the IE doesn't yet have,
|
||||
* so for the other values we use upper max values as we will intersect
|
||||
|
|
@ -538,6 +563,7 @@ static struct ieee80211_regdomain *country_ie_2_rd(
|
|||
|
||||
/* This time around we fill in the rd */
|
||||
while (country_ie_len >= 3) {
|
||||
int end_channel = 0;
|
||||
struct ieee80211_country_ie_triplet *triplet =
|
||||
(struct ieee80211_country_ie_triplet *) country_ie;
|
||||
struct ieee80211_reg_rule *reg_rule = NULL;
|
||||
|
|
@ -559,6 +585,23 @@ static struct ieee80211_regdomain *country_ie_2_rd(
|
|||
|
||||
reg_rule->flags = flags;
|
||||
|
||||
/* 2 GHz */
|
||||
if (triplet->chans.first_channel <= 14)
|
||||
end_channel = triplet->chans.first_channel +
|
||||
triplet->chans.num_channels;
|
||||
else
|
||||
/*
|
||||
* 5 GHz -- For example in country IEs if the first
|
||||
* channel given is 36 and the number of channels is 4
|
||||
* then the individual channel numbers defined for the
|
||||
* 5 GHz PHY by these parameters are: 36, 40, 44, and 48
|
||||
* and not 36, 37, 38, 39.
|
||||
*
|
||||
* See: http://tinyurl.com/11d-clarification
|
||||
*/
|
||||
end_channel = triplet->chans.first_channel +
|
||||
(4 * (triplet->chans.num_channels - 1));
|
||||
|
||||
/* The +10 is since the regulatory domain expects
|
||||
* the actual band edge, not the center of freq for
|
||||
* its start and end freqs, assuming 20 MHz bandwidth on
|
||||
|
|
@ -568,8 +611,7 @@ static struct ieee80211_regdomain *country_ie_2_rd(
|
|||
triplet->chans.first_channel) - 10);
|
||||
freq_range->end_freq_khz =
|
||||
MHZ_TO_KHZ(ieee80211_channel_to_frequency(
|
||||
triplet->chans.first_channel +
|
||||
triplet->chans.num_channels) + 10);
|
||||
end_channel) + 10);
|
||||
|
||||
/* Large arbitrary values, we intersect later */
|
||||
/* Increment this if we ever support >= 40 MHz channels
|
||||
|
|
@ -748,12 +790,23 @@ static u32 map_regdom_flags(u32 rd_flags)
|
|||
* this value to the maximum allowed bandwidth.
|
||||
* @reg_rule: the regulatory rule which we have for this frequency
|
||||
*
|
||||
* Use this function to get the regulatory rule for a specific frequency.
|
||||
* Use this function to get the regulatory rule for a specific frequency on
|
||||
* a given wireless device. If the device has a specific regulatory domain
|
||||
* it wants to follow we respect that unless a country IE has been received
|
||||
* and processed already.
|
||||
*
|
||||
* Returns 0 if it was able to find a valid regulatory rule which does
|
||||
* apply to the given center_freq otherwise it returns non-zero. It will
|
||||
* also return -ERANGE if we determine the given center_freq does not even have
|
||||
* a regulatory rule for a frequency range in the center_freq's band. See
|
||||
* freq_in_rule_band() for our current definition of a band -- this is purely
|
||||
* subjective and right now its 802.11 specific.
|
||||
*/
|
||||
static int freq_reg_info(u32 center_freq, u32 *bandwidth,
|
||||
const struct ieee80211_reg_rule **reg_rule)
|
||||
{
|
||||
int i;
|
||||
bool band_rule_found = false;
|
||||
u32 max_bandwidth = 0;
|
||||
|
||||
if (!cfg80211_regdomain)
|
||||
|
|
@ -767,7 +820,15 @@ static int freq_reg_info(u32 center_freq, u32 *bandwidth,
|
|||
rr = &cfg80211_regdomain->reg_rules[i];
|
||||
fr = &rr->freq_range;
|
||||
pr = &rr->power_rule;
|
||||
|
||||
/* We only need to know if one frequency rule was
|
||||
* was in center_freq's band, that's enough, so lets
|
||||
* not overwrite it once found */
|
||||
if (!band_rule_found)
|
||||
band_rule_found = freq_in_rule_band(fr, center_freq);
|
||||
|
||||
max_bandwidth = freq_max_bandwidth(fr, center_freq);
|
||||
|
||||
if (max_bandwidth && *bandwidth <= max_bandwidth) {
|
||||
*reg_rule = rr;
|
||||
*bandwidth = max_bandwidth;
|
||||
|
|
@ -775,23 +836,64 @@ static int freq_reg_info(u32 center_freq, u32 *bandwidth,
|
|||
}
|
||||
}
|
||||
|
||||
if (!band_rule_found)
|
||||
return -ERANGE;
|
||||
|
||||
return !max_bandwidth;
|
||||
}
|
||||
|
||||
static void handle_channel(struct ieee80211_channel *chan)
|
||||
static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
|
||||
unsigned int chan_idx)
|
||||
{
|
||||
int r;
|
||||
u32 flags = chan->orig_flags;
|
||||
u32 flags;
|
||||
u32 max_bandwidth = 0;
|
||||
const struct ieee80211_reg_rule *reg_rule = NULL;
|
||||
const struct ieee80211_power_rule *power_rule = NULL;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_channel *chan;
|
||||
|
||||
sband = wiphy->bands[band];
|
||||
BUG_ON(chan_idx >= sband->n_channels);
|
||||
chan = &sband->channels[chan_idx];
|
||||
|
||||
flags = chan->orig_flags;
|
||||
|
||||
r = freq_reg_info(MHZ_TO_KHZ(chan->center_freq),
|
||||
&max_bandwidth, ®_rule);
|
||||
|
||||
if (r) {
|
||||
flags |= IEEE80211_CHAN_DISABLED;
|
||||
chan->flags = flags;
|
||||
/* This means no regulatory rule was found in the country IE
|
||||
* with a frequency range on the center_freq's band, since
|
||||
* IEEE-802.11 allows for a country IE to have a subset of the
|
||||
* regulatory information provided in a country we ignore
|
||||
* disabling the channel unless at least one reg rule was
|
||||
* found on the center_freq's band. For details see this
|
||||
* clarification:
|
||||
*
|
||||
* http://tinyurl.com/11d-clarification
|
||||
*/
|
||||
if (r == -ERANGE &&
|
||||
last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
|
||||
#ifdef CONFIG_CFG80211_REG_DEBUG
|
||||
printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz "
|
||||
"intact on %s - no rule found in band on "
|
||||
"Country IE\n",
|
||||
chan->center_freq, wiphy_name(wiphy));
|
||||
#endif
|
||||
} else {
|
||||
/* In this case we know the country IE has at least one reg rule
|
||||
* for the band so we respect its band definitions */
|
||||
#ifdef CONFIG_CFG80211_REG_DEBUG
|
||||
if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
|
||||
printk(KERN_DEBUG "cfg80211: Disabling "
|
||||
"channel %d MHz on %s due to "
|
||||
"Country IE\n",
|
||||
chan->center_freq, wiphy_name(wiphy));
|
||||
#endif
|
||||
flags |= IEEE80211_CHAN_DISABLED;
|
||||
chan->flags = flags;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -808,12 +910,16 @@ static void handle_channel(struct ieee80211_channel *chan)
|
|||
chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
|
||||
}
|
||||
|
||||
static void handle_band(struct ieee80211_supported_band *sband)
|
||||
static void handle_band(struct wiphy *wiphy, enum ieee80211_band band)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
BUG_ON(!wiphy->bands[band]);
|
||||
sband = wiphy->bands[band];
|
||||
|
||||
for (i = 0; i < sband->n_channels; i++)
|
||||
handle_channel(&sband->channels[i]);
|
||||
handle_channel(wiphy, band, i);
|
||||
}
|
||||
|
||||
static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby)
|
||||
|
|
@ -840,7 +946,7 @@ void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby)
|
|||
enum ieee80211_band band;
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
if (wiphy->bands[band])
|
||||
handle_band(wiphy->bands[band]);
|
||||
handle_band(wiphy, band);
|
||||
if (wiphy->reg_notifier)
|
||||
wiphy->reg_notifier(wiphy, setby);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1914,17 +1914,10 @@ static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* For the xfrm_usersa_info cases we have to work around some 32-bit vs.
|
||||
* 64-bit compatability issues. On 32-bit the structure is 220 bytes, but
|
||||
* for 64-bit it gets padded out to 224 bytes. Those bytes are just
|
||||
* padding and don't have any content we care about. Therefore as long
|
||||
* as we have enough bytes for the content we can make both cases work.
|
||||
*/
|
||||
|
||||
#define XMSGSIZE(type) sizeof(struct type)
|
||||
|
||||
static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
|
||||
[XFRM_MSG_NEWSA - XFRM_MSG_BASE] = 220, /* see above */
|
||||
[XFRM_MSG_NEWSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info),
|
||||
[XFRM_MSG_DELSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id),
|
||||
[XFRM_MSG_GETSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id),
|
||||
[XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info),
|
||||
|
|
@ -1934,7 +1927,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
|
|||
[XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire),
|
||||
[XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire),
|
||||
[XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info),
|
||||
[XFRM_MSG_UPDSA - XFRM_MSG_BASE] = 220, /* see above */
|
||||
[XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info),
|
||||
[XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire),
|
||||
[XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush),
|
||||
[XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = 0,
|
||||
|
|
|
|||
Loading…
Reference in a new issue