summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-13 10:51:48 +0900
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-13 10:51:48 +0900
commit98260daa184c4a171834463cf85ab3a2c509d983 (patch)
tree318c3bfff9edef4da84a69895a3ac2aa39b8256a /drivers
parente225ca27057e70e7cbb14ae4c1e5f758973af645 (diff)
parentdabdaf0caa3af520dbc1df87b2fb4e77224037bd (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking updates from David Miller: 1) Alexey Kuznetsov noticed we routed TCP resets improperly in the assymetric routing case, fix this by reverting a change that made us use the incoming interface in the outgoing route key when we didn't have a socket context to work with. 2) TCP sysctl kernel memory leakage to userspace fix from Alan Cox. 3) Move UAPI bits from David Howells, WIMAX and CAN this time. 4) Fix TX stalls in e1000e wrt. Byte Queue Limits, from Hiroaki SHIMODA, Denys Fedoryshchenko, and Jesse Brandeburg. 5) Fix IPV6 crashes in packet generator module, from Amerigo Wang. 6) Tidies and fixes in the new VXLAN driver from Stephen Hemminger. 7) Bridge IP options parse doesn't check first if SKB header has at least an IP header's worth of content present. Fix from Sarveshwar Bandi. 8) The kernel now generates compound pages on transmit and the Xen netback drivers needs some adjustments in order to handle this. Fix from Ian Campbell. 9) Turn off ASPM in JME driver, from Kevin Bardon and Matthew Garrett. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (43 commits) mcs7830: Fix link state detection net: add doc for in4_pton() net: add doc for in6_pton() vti: fix sparse bit endian warnings tcp: resets are misrouted usbnet: Support devices reporting idleness Add CDC-ACM support for the CX93010-2x UCMxx USB Modem net/ethernet/jme: disable ASPM tcp: sysctl interface leaks 16 bytes of kernel memory kaweth: print correct debug ptr e1000e: Change wthresh to 1 to avoid possible Tx stalls ipv4: fix route mark sparse warning xen: netback: handle compound page fragments on transmit. bridge: Pull ip header into skb->data before looking into ip header. isdn: fix a wrapping bug in isdn_ppp_ioctl() vxlan: fix oops when give unknown ifindex vxlan: fix receive checksum handling vxlan: add additional headroom vxlan: allow configuring port range vxlan: associate with tunnel socket on transmit ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c2
-rw-r--r--drivers/net/ethernet/intel/e1000e/e1000.h6
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c2
-rw-r--r--drivers/net/ethernet/jme.c4
-rw-r--r--drivers/net/usb/cdc_eem.c4
-rw-r--r--drivers/net/usb/kaweth.c2
-rw-r--r--drivers/net/usb/mcs7830.c30
-rw-r--r--drivers/net/usb/usbnet.c17
-rw-r--r--drivers/net/vxlan.c148
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c53
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h1
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c29
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c27
-rw-r--r--drivers/net/wireless/mwifiex/join.c6
-rw-r--r--drivers/net/wireless/mwifiex/main.h2
-rw-r--r--drivers/net/wireless/mwifiex/scan.c38
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c4
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c31
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c4
-rw-r--r--drivers/net/xen-netback/netback.c40
-rw-r--r--drivers/usb/class/cdc-acm.c3
27 files changed, 344 insertions, 142 deletions
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index a1e760150821..61d78fa03b1a 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -595,7 +595,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
j = ipc->num / (sizeof(long) * 8);
i = ipc->num % (sizeof(long) * 8);
if (j < 8)
- protos[j] |= (0x1 << i);
+ protos[j] |= (1UL << i);
ipc = ipc->next;
}
if ((r = set_arg(argp, protos, 8 * sizeof(long))))
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index cb3356c9af80..04668b47a1df 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -175,13 +175,13 @@ struct e1000_info;
/*
* in the case of WTHRESH, it appears at least the 82571/2 hardware
* writes back 4 descriptors when WTHRESH=5, and 3 descriptors when
- * WTHRESH=4, and since we want 64 bytes at a time written back, set
- * it to 5
+ * WTHRESH=4, so a setting of 5 gives the most efficient bus
+ * utilization but to avoid possible Tx stalls, set it to 1
*/
#define E1000_TXDCTL_DMA_BURST_ENABLE \
(E1000_TXDCTL_GRAN | /* set descriptor granularity */ \
E1000_TXDCTL_COUNT_DESC | \
- (5 << 16) | /* wthresh must be +1 more than desired */\
+ (1 << 16) | /* wthresh must be +1 more than desired */\
(1 << 8) | /* hthresh */ \
0x1f) /* pthresh */
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index de57a2ba6bde..f444eb0b76d8 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -2831,7 +2831,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
* set up some performance related parameters to encourage the
* hardware to use the bus more efficiently in bursts, depends
* on the tx_int_delay to be enabled,
- * wthresh = 5 ==> burst write a cacheline (64 bytes) at a time
+ * wthresh = 1 ==> burst write is disabled to avoid Tx stalls
* hthresh = 1 ==> prefetch when one or more available
* pthresh = 0x1f ==> prefetch if internal cache 31 or less
* BEWARE: this seems to work but should be considered first if
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index c911d883c27e..f8064df10cc4 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
+#include <linux/pci-aspm.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
@@ -2973,6 +2974,9 @@ jme_init_one(struct pci_dev *pdev,
/*
* set up PCI device basics
*/
+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+ PCIE_LINK_STATE_CLKPM);
+
rc = pci_enable_device(pdev);
if (rc) {
pr_err("Cannot enable PCI device\n");
diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c
index 434d5af8e6fb..c81e278629ff 100644
--- a/drivers/net/usb/cdc_eem.c
+++ b/drivers/net/usb/cdc_eem.c
@@ -244,8 +244,12 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
* - suspend: peripheral ready to suspend
* - response: suggest N millisec polling
* - response complete: suggest N sec polling
+ *
+ * Suspend is reported and maybe heeded.
*/
case 2: /* Suspend hint */
+ usbnet_device_suggests_idle(dev);
+ continue;
case 3: /* Response hint */
case 4: /* Response complete hint */
continue;
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index c75e11e1b385..afb117c16d2d 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -424,7 +424,7 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth,
netdev_dbg(kaweth->net,
"Downloading firmware at %p to kaweth device at %p\n",
- fw->data, kaweth);
+ kaweth->firmware_buf, kaweth);
netdev_dbg(kaweth->net, "Firmware length: %d\n", data_len);
return kaweth_control(kaweth,
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index 03c2d8d653df..cc7e72010ac3 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -117,6 +117,7 @@ enum {
struct mcs7830_data {
u8 multi_filter[8];
u8 config;
+ u8 link_counter;
};
static const char driver_name[] = "MOSCHIP usb-ethernet driver";
@@ -632,20 +633,31 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
static void mcs7830_status(struct usbnet *dev, struct urb *urb)
{
u8 *buf = urb->transfer_buffer;
- bool link;
+ bool link, link_changed;
+ struct mcs7830_data *data = mcs7830_get_data(dev);
if (urb->actual_length < 16)
return;
link = !(buf[1] & 0x20);
- if (netif_carrier_ok(dev->net) != link) {
- if (link) {
- netif_carrier_on(dev->net);
- usbnet_defer_kevent(dev, EVENT_LINK_RESET);
- } else
- netif_carrier_off(dev->net);
- netdev_dbg(dev->net, "Link Status is: %d\n", link);
- }
+ link_changed = netif_carrier_ok(dev->net) != link;
+ if (link_changed) {
+ data->link_counter++;
+ /*
+ track link state 20 times to guard against erroneous
+ link state changes reported sometimes by the chip
+ */
+ if (data->link_counter > 20) {
+ data->link_counter = 0;
+ if (link) {
+ netif_carrier_on(dev->net);
+ usbnet_defer_kevent(dev, EVENT_LINK_RESET);
+ } else
+ netif_carrier_off(dev->net);
+ netdev_dbg(dev->net, "Link Status is: %d\n", link);
+ }
+ } else
+ data->link_counter = 0;
}
static const struct driver_info moschip_info = {
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index fc9f578a1e25..f9819d10b1f9 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1588,10 +1588,27 @@ int usbnet_resume (struct usb_interface *intf)
tasklet_schedule (&dev->bh);
}
}
+
+ if (test_and_clear_bit(EVENT_DEVICE_REPORT_IDLE, &dev->flags))
+ usb_autopm_get_interface_no_resume(intf);
+
return 0;
}
EXPORT_SYMBOL_GPL(usbnet_resume);
+/*
+ * Either a subdriver implements manage_power, then it is assumed to always
+ * be ready to be suspended or it reports the readiness to be suspended
+ * explicitly
+ */
+void usbnet_device_suggests_idle(struct usbnet *dev)
+{
+ if (!test_and_set_bit(EVENT_DEVICE_REPORT_IDLE, &dev->flags)) {
+ dev->intf->needs_remote_wakeup = 1;
+ usb_autopm_put_interface_async(dev->intf);
+ }
+}
+EXPORT_SYMBOL(usbnet_device_suggests_idle);
/*-------------------------------------------------------------------------*/
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 8be9bf07bd39..607976c00162 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -106,6 +106,8 @@ struct vxlan_dev {
__be32 gaddr; /* multicast group */
__be32 saddr; /* source address */
unsigned int link; /* link to multicast over */
+ __u16 port_min; /* source port range */
+ __u16 port_max;
__u8 tos; /* TOS override */
__u8 ttl;
bool learn;
@@ -228,9 +230,9 @@ static u32 eth_hash(const unsigned char *addr)
/* only want 6 bytes */
#ifdef __BIG_ENDIAN
- value <<= 16;
-#else
value >>= 16;
+#else
+ value <<= 16;
#endif
return hash_64(value, FDB_HASH_BITS);
}
@@ -535,7 +537,6 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
}
__skb_pull(skb, sizeof(struct vxlanhdr));
- skb_postpull_rcsum(skb, eth_hdr(skb), sizeof(struct vxlanhdr));
/* Is this VNI defined? */
vni = ntohl(vxh->vx_vni) >> 8;
@@ -554,7 +555,6 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
/* Re-examine inner Ethernet packet */
oip = ip_hdr(skb);
skb->protocol = eth_type_trans(skb, vxlan->dev);
- skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
/* Ignore packet loops (and multicast echo) */
if (compare_ether_addr(eth_hdr(skb)->h_source,
@@ -566,6 +566,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
__skb_tunnel_rx(skb, vxlan->dev);
skb_reset_network_header(skb);
+ skb->ip_summed = CHECKSUM_NONE;
err = IP_ECN_decapsulate(oip, skb);
if (unlikely(err)) {
@@ -621,46 +622,89 @@ static inline u8 vxlan_ecn_encap(u8 tos,
return INET_ECN_encapsulate(tos, inner);
}
+static __be32 vxlan_find_dst(struct vxlan_dev *vxlan, struct sk_buff *skb)
+{
+ const struct ethhdr *eth = (struct ethhdr *) skb->data;
+ const struct vxlan_fdb *f;
+
+ if (is_multicast_ether_addr(eth->h_dest))
+ return vxlan->gaddr;
+
+ f = vxlan_find_mac(vxlan, eth->h_dest);
+ if (f)
+ return f->remote_ip;
+ else
+ return vxlan->gaddr;
+
+}
+
+static void vxlan_sock_free(struct sk_buff *skb)
+{
+ sock_put(skb->sk);
+}
+
+/* On transmit, associate with the tunnel socket */
+static void vxlan_set_owner(struct net_device *dev, struct sk_buff *skb)
+{
+ struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
+ struct sock *sk = vn->sock->sk;
+
+ skb_orphan(skb);
+ sock_hold(sk);
+ skb->sk = sk;
+ skb->destructor = vxlan_sock_free;
+}
+
+/* Compute source port for outgoing packet
+ * first choice to use L4 flow hash since it will spread
+ * better and maybe available from hardware
+ * secondary choice is to use jhash on the Ethernet header
+ */
+static u16 vxlan_src_port(const struct vxlan_dev *vxlan, struct sk_buff *skb)
+{
+ unsigned int range = (vxlan->port_max - vxlan->port_min) + 1;
+ u32 hash;
+
+ hash = skb_get_rxhash(skb);
+ if (!hash)
+ hash = jhash(skb->data, 2 * ETH_ALEN,
+ (__force u32) skb->protocol);
+
+ return (((u64) hash * range) >> 32) + vxlan->port_min;
+}
+
/* Transmit local packets over Vxlan
*
* Outer IP header inherits ECN and DF from inner header.
* Outer UDP destination is the VXLAN assigned port.
- * source port is based on hash of flow if available
- * otherwise use a random value
+ * source port is based on hash of flow
*/
static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
struct rtable *rt;
- const struct ethhdr *eth;
const struct iphdr *old_iph;
struct iphdr *iph;
struct vxlanhdr *vxh;
struct udphdr *uh;
struct flowi4 fl4;
- struct vxlan_fdb *f;
unsigned int pkt_len = skb->len;
- u32 hash;
__be32 dst;
+ __u16 src_port;
__be16 df = 0;
__u8 tos, ttl;
int err;
+ dst = vxlan_find_dst(vxlan, skb);
+ if (!dst)
+ goto drop;
+
/* Need space for new headers (invalidates iph ptr) */
if (skb_cow_head(skb, VXLAN_HEADROOM))
goto drop;
- eth = (void *)skb->data;
old_iph = ip_hdr(skb);
- if (!is_multicast_ether_addr(eth->h_dest) &&
- (f = vxlan_find_mac(vxlan, eth->h_dest)))
- dst = f->remote_ip;
- else if (vxlan->gaddr) {
- dst = vxlan->gaddr;
- } else
- goto drop;
-
ttl = vxlan->ttl;
if (!ttl && IN_MULTICAST(ntohl(dst)))
ttl = 1;
@@ -669,11 +713,15 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
if (tos == 1)
tos = vxlan_get_dsfield(old_iph, skb);
- hash = skb_get_rxhash(skb);
+ src_port = vxlan_src_port(vxlan, skb);
+
+ memset(&fl4, 0, sizeof(fl4));
+ fl4.flowi4_oif = vxlan->link;
+ fl4.flowi4_tos = RT_TOS(tos);
+ fl4.daddr = dst;
+ fl4.saddr = vxlan->saddr;
- rt = ip_route_output_gre(dev_net(dev), &fl4, dst,
- vxlan->saddr, vxlan->vni,
- RT_TOS(tos), vxlan->link);
+ rt = ip_route_output_key(dev_net(dev), &fl4);
if (IS_ERR(rt)) {
netdev_dbg(dev, "no route to %pI4\n", &dst);
dev->stats.tx_carrier_errors++;
@@ -702,7 +750,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
uh = udp_hdr(skb);
uh->dest = htons(vxlan_port);
- uh->source = hash ? :random32();
+ uh->source = htons(src_port);
uh->len = htons(skb->len);
uh->check = 0;
@@ -715,10 +763,12 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
iph->frag_off = df;
iph->protocol = IPPROTO_UDP;
iph->tos = vxlan_ecn_encap(tos, old_iph, skb);
- iph->daddr = fl4.daddr;
+ iph->daddr = dst;
iph->saddr = fl4.saddr;
iph->ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
+ vxlan_set_owner(dev, skb);
+
/* See __IPTUNNEL_XMIT */
skb->ip_summed = CHECKSUM_NONE;
ip_select_ident(iph, &rt->dst, NULL);
@@ -928,9 +978,11 @@ static void vxlan_setup(struct net_device *dev)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
unsigned h;
+ int low, high;
eth_hw_addr_random(dev);
ether_setup(dev);
+ dev->hard_header_len = ETH_HLEN + VXLAN_HEADROOM;
dev->netdev_ops = &vxlan_netdev_ops;
dev->destructor = vxlan_free;
@@ -947,6 +999,10 @@ static void vxlan_setup(struct net_device *dev)
vxlan->age_timer.function = vxlan_cleanup;
vxlan->age_timer.data = (unsigned long) vxlan;
+ inet_get_local_port_range(&low, &high);
+ vxlan->port_min = low;
+ vxlan->port_max = high;
+
vxlan->dev = dev;
for (h = 0; h < FDB_HASH_SIZE; ++h)
@@ -963,6 +1019,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
[IFLA_VXLAN_LEARNING] = { .type = NLA_U8 },
[IFLA_VXLAN_AGEING] = { .type = NLA_U32 },
[IFLA_VXLAN_LIMIT] = { .type = NLA_U32 },
+ [IFLA_VXLAN_PORT_RANGE] = { .len = sizeof(struct ifla_vxlan_port_range) },
};
static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -995,6 +1052,18 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
return -EADDRNOTAVAIL;
}
}
+
+ if (data[IFLA_VXLAN_PORT_RANGE]) {
+ const struct ifla_vxlan_port_range *p
+ = nla_data(data[IFLA_VXLAN_PORT_RANGE]);
+
+ if (ntohs(p->high) < ntohs(p->low)) {
+ pr_debug("port range %u .. %u not valid\n",
+ ntohs(p->low), ntohs(p->high));
+ return -EINVAL;
+ }
+ }
+
return 0;
}
@@ -1021,14 +1090,18 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
if (data[IFLA_VXLAN_LOCAL])
vxlan->saddr = nla_get_be32(data[IFLA_VXLAN_LOCAL]);
- if (data[IFLA_VXLAN_LINK]) {
- vxlan->link = nla_get_u32(data[IFLA_VXLAN_LINK]);
+ if (data[IFLA_VXLAN_LINK] &&
+ (vxlan->link = nla_get_u32(data[IFLA_VXLAN_LINK]))) {
+ struct net_device *lowerdev
+ = __dev_get_by_index(net, vxlan->link);
- if (!tb[IFLA_MTU]) {
- struct net_device *lowerdev;
- lowerdev = __dev_get_by_index(net, vxlan->link);
- dev->mtu = lowerdev->mtu - VXLAN_HEADROOM;
+ if (!lowerdev) {
+ pr_info("ifindex %d does not exist\n", vxlan->link);
+ return -ENODEV;
}
+
+ if (!tb[IFLA_MTU])
+ dev->mtu = lowerdev->mtu - VXLAN_HEADROOM;
}
if (data[IFLA_VXLAN_TOS])
@@ -1045,6 +1118,13 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
if (data[IFLA_VXLAN_LIMIT])
vxlan->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]);
+ if (data[IFLA_VXLAN_PORT_RANGE]) {
+ const struct ifla_vxlan_port_range *p
+ = nla_data(data[IFLA_VXLAN_PORT_RANGE]);
+ vxlan->port_min = ntohs(p->low);
+ vxlan->port_max = ntohs(p->high);
+ }
+
err = register_netdevice(dev);
if (!err)
hlist_add_head_rcu(&vxlan->hlist, vni_head(net, vxlan->vni));
@@ -1073,12 +1153,17 @@ static size_t vxlan_get_size(const struct net_device *dev)
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LEARNING */
nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */
nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */
+ nla_total_size(sizeof(struct ifla_vxlan_port_range)) +
0;
}
static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
{
const struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct ifla_vxlan_port_range ports = {
+ .low = htons(vxlan->port_min),
+ .high = htons(vxlan->port_max),
+ };
if (nla_put_u32(skb, IFLA_VXLAN_ID, vxlan->vni))
goto nla_put_failure;
@@ -1099,6 +1184,9 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax))
goto nla_put_failure;
+ if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports))
+ goto nla_put_failure;
+
return 0;
nla_put_failure:
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 9fd6d9a9942e..9f31cfa56cc0 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -1804,7 +1804,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
int ret;
struct ath5k_hw *ah = hw->priv;
- struct ath5k_vif *avf = (void *)vif->drv_priv;
+ struct ath5k_vif *avf;
struct sk_buff *skb;
if (WARN_ON(!vif)) {
@@ -1819,6 +1819,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
goto out;
}
+ avf = (void *)vif->drv_priv;
ath5k_txbuf_free_skb(ah, avf->bbuf);
avf->bbuf->skb = skb;
ret = ath5k_beacon_setup(ah, avf->bbuf);
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 76f07d8c272d..1b48414dca95 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -120,7 +120,7 @@ static void ath9k_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
if (ath_tx_start(hw, skb, &txctl) != 0) {
ath_dbg(common, XMIT, "CABQ TX failed\n");
- dev_kfree_skb_any(skb);
+ ieee80211_free_txskb(hw, skb);
}
}
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index f9a6ec5cf470..8e1559aba495 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1450,9 +1450,14 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
REG_WRITE(ah, AR_RTC_FORCE_WAKE,
AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+ if (!ah->reset_power_on)
+ type = ATH9K_RESET_POWER_ON;
+
switch (type) {
case ATH9K_RESET_POWER_ON:
ret = ath9k_hw_set_reset_power_on(ah);
+ if (!ret)
+ ah->reset_power_on = true;
break;
case ATH9K_RESET_WARM:
case ATH9K_RESET_COLD:
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 566a4ce4f156..dbc1b7a4cbfd 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -741,6 +741,7 @@ struct ath_hw {
u32 rfkill_polarity;
u32 ah_flags;
+ bool reset_power_on;
bool htc_reset_init;
enum nl80211_iftype opmode;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 31ab82e3ba85..dd45edfa6bae 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -639,8 +639,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
ath_err(common,
"Unable to reset hardware; reset status %d (freq %u MHz)\n",
r, curchan->center_freq);
- spin_unlock_bh(&sc->sc_pcu_lock);
- goto mutex_unlock;
+ ah->reset_power_on = false;
}
/* Setup our intr mask. */
@@ -665,11 +664,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
clear_bit(SC_OP_INVALID, &sc->sc_flags);
sc->sc_ah->is_monitoring = false;
- if (!ath_complete_reset(sc, false)) {
- r = -EIO;
- spin_unlock_bh(&sc->sc_pcu_lock);
- goto mutex_unlock;
- }
+ if (!ath_complete_reset(sc, false))
+ ah->reset_power_on = false;
if (ah->led_pin >= 0) {
ath9k_hw_cfg_output(ah, ah->led_pin,
@@ -688,12 +684,11 @@ static int ath9k_start(struct ieee80211_hw *hw)
if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
common->bus_ops->extn_synch_en(common);
-mutex_unlock:
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
- return r;
+ return 0;
}
static void ath9k_tx(struct ieee80211_hw *hw,
@@ -770,7 +765,7 @@ static void ath9k_tx(struct ieee80211_hw *hw,
return;
exit:
- dev_kfree_skb_any(skb);
+ ieee80211_free_txskb(hw, skb);
}
static void ath9k_stop(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 0e630a99b68b..f088f4bf9a26 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -324,6 +324,10 @@ static int ath_pci_suspend(struct device *device)
static int ath_pci_resume(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
+ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+ struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
u32 val;
/*
@@ -335,6 +339,9 @@ static int ath_pci_resume(struct device *device)
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+ ath_pci_aspm_init(common);
+ ah->reset_power_on = false;
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 36618e3a5e60..378bd70256b2 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -66,8 +66,7 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_atx_tid *tid,
- struct sk_buff *skb,
- bool dequeue);
+ struct sk_buff *skb);
enum {
MCS_HT20,
@@ -176,7 +175,15 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
fi = get_frame_info(skb);
bf = fi->bf;
- if (bf && fi->retries) {
+ if (!bf) {
+ bf = ath_tx_setup_buffer(sc, txq, tid, skb);
+ if (!bf) {
+ ieee80211_free_txskb(sc->hw, skb);
+ continue;
+ }
+ }
+
+ if (fi->retries) {
list_add_tail(&bf->list, &bf_head);
ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
@@ -785,10 +792,13 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
fi = get_frame_info(skb);
bf = fi->bf;
if (!fi->bf)
- bf = ath_tx_setup_buffer(sc, txq, tid, skb, true);
+ bf = ath_tx_setup_buffer(sc, txq, tid, skb);
- if (!bf)
+ if (!bf) {
+ __skb_unlink(skb, &tid->buf_q);
+ ieee80211_free_txskb(sc->hw, skb);
continue;
+ }
bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
seqno = bf->bf_state.seqno;
@@ -1731,9 +1741,11 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
return;
}
- bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
- if (!bf)
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+ if (!bf) {
+ ieee80211_free_txskb(sc->hw, skb);
return;
+ }
bf->bf_state.bf_type = BUF_AMPDU;
INIT_LIST_HEAD(&bf_head);
@@ -1757,11 +1769,6 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf;
bf = fi->bf;
- if (!bf)
- bf = ath_tx_setup_buffer(sc, txq, tid, skb, false);
-
- if (!bf)
- return;
INIT_LIST_HEAD(&bf_head);
list_add_tail(&bf->list, &bf_head);
@@ -1839,8 +1846,7 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_atx_tid *tid,
- struct sk_buff *skb,
- bool dequeue)
+ struct sk_buff *skb)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_frame_info *fi = get_frame_info(skb);
@@ -1852,7 +1858,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
bf = ath_tx_get_buffer(sc);
if (!bf) {
ath_dbg(common, XMIT, "TX buffers are full\n");
- goto error;
+ return NULL;
}
ATH_TXBUF_RESET(bf);
@@ -1881,18 +1887,12 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
ath_err(ath9k_hw_common(sc->sc_ah),
"dma_mapping_error() on TX\n");
ath_tx_return_buffer(sc, bf);
- goto error;
+ return NULL;
}
fi->bf = bf;
return bf;
-
-error:
- if (dequeue)
- __skb_unlink(skb, &tid->buf_q);
- dev_kfree_skb_any(skb);
- return NULL;
}
/* FIXME: tx power */
@@ -1921,9 +1921,14 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
*/
ath_tx_send_ampdu(sc, tid, skb, txctl);
} else {
- bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
- if (!bf)
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+ if (!bf) {
+ if (txctl->paprd)
+ dev_kfree_skb_any(skb);
+ else
+ ieee80211_free_txskb(sc->hw, skb);
return;
+ }
bf->bf_state.bfs_paprd = txctl->paprd;
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 2aa4a59c72c8..2df17f1e49ef 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -303,6 +303,7 @@ struct ar9170 {
unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
bool needs_full_reset;
+ bool force_usb_reset;
atomic_t pending_restarts;
/* interface mode settings */
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 67997b39aba7..25a1e2f4f738 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -465,27 +465,26 @@ static void carl9170_restart_work(struct work_struct *work)