diff options
Diffstat (limited to 'drivers')
27 files changed, 344 insertions, 142 deletions
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index a1e76015082..61d78fa03b1 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 cb3356c9af8..04668b47a1d 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 de57a2ba6bd..f444eb0b76d 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 c911d883c27..f8064df10cc 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 434d5af8e6f..c81e278629f 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 c75e11e1b38..afb117c16d2 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 03c2d8d653d..cc7e72010ac 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 fc9f578a1e2..f9819d10b1f 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 8be9bf07bd3..607976c0016 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 9fd6d9a9942..9f31cfa56cc 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 76f07d8c272..1b48414dca9 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 f9a6ec5cf47..8e1559aba49 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 566a4ce4f15..dbc1b7a4cbf 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 31ab82e3ba8..dd45edfa6ba 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 0e630a99b68..f088f4bf9a2 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 36618e3a5e6..378bd70256b 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 2aa4a59c72c..2df17f1e49e 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 67997b39aba..25a1e2f4f73 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) { struct ar9170 *ar = container_of(work, struct ar9170, restart_work); - int err; + int err = -EIO; ar->usedkeys = 0; ar->filter_state = 0; carl9170_cancel_worker(ar); mutex_lock(&ar->mutex); - err = carl9170_usb_restart(ar); - if (net_ratelimit()) { - if (err) { - dev_err(&ar->udev->dev, "Failed to restart device " - " (%d).\n", err); - } else { - dev_info(&ar->udev->dev, "device restarted " - "successfully.\n"); + if (!ar->force_usb_reset) { + err = carl9170_usb_restart(ar); + if (net_ratelimit()) { + if (err) + dev_err(&ar->udev->dev, "Failed to restart device (%d).\n", err); + else + dev_info(&ar->udev->dev, "device restarted successfully.\n"); } } - carl9170_zap_queues(ar); mutex_unlock(&ar->mutex); - if (!err) { + + if (!err && !ar->force_usb_reset) { ar->restart_counter++; atomic_set(&ar->pending_restarts, 0); @@ -526,10 +525,10 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r) if (!ar->registered) return; - if (IS_ACCEPTING_CMD(ar) && !ar->needs_full_reset) - ieee80211_queue_work(ar->hw, &ar->restart_work); - else - carl9170_usb_reset(ar); + if (!IS_ACCEPTING_CMD(ar) || ar->needs_full_reset) + ar->force_usb_reset = true; + + ieee80211_queue_work(ar->hw, &ar->restart_work); /* * At this point, the device instance might have vanished/disabled. diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 2691620393e..0679458a1ba 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/ |