提交 80445de5 编写于 作者: L Linus Torvalds

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: (30 commits)
  e1000: fix virtualization bug
  bonding: fix alb mode locking regression
  Bluetooth: Fix issue with sysfs handling for connections
  usbnet: CDC EEM support (v5)
  tcp: Fix tcp_prequeue() to get correct rto_min value
  ehea: fix invalid pointer access
  ne2k-pci: Do not register device until initialized.
  Subject: [PATCH] br2684: restore net_dev initialization
  net: Only store high 16 bits of kernel generated filter priorities
  virtio_net: Fix function name typo
  virtio_net: Cleanup command queue scatterlist usage
  bonding: correct the cleanup in bond_create()
  virtio: add missing include to virtio_net.h
  smsc95xx: add support for LAN9512 and LAN9514
  smsc95xx: configure LED outputs
  netconsole: take care of NETDEV_UNREGISTER event
  xt_socket: checks for the state of nf_conntrack
  bonding: bond_slave_info_query() fix
  cxgb3: fixing gcc 4.4 compiler warning: suggest parentheses around operand of ‘!’
  netfilter: use likely() in xt_info_rdlock_bh()
  ...
...@@ -1706,10 +1706,8 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave ...@@ -1706,10 +1706,8 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
* Called with RTNL * Called with RTNL
*/ */
int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
__releases(&bond->curr_slave_lock)
__releases(&bond->lock)
__acquires(&bond->lock) __acquires(&bond->lock)
__acquires(&bond->curr_slave_lock) __releases(&bond->lock)
{ {
struct bonding *bond = netdev_priv(bond_dev); struct bonding *bond = netdev_priv(bond_dev);
struct sockaddr *sa = addr; struct sockaddr *sa = addr;
...@@ -1745,9 +1743,6 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) ...@@ -1745,9 +1743,6 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
} }
} }
write_unlock_bh(&bond->curr_slave_lock);
read_unlock(&bond->lock);
if (swap_slave) { if (swap_slave) {
alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave); alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave); alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
...@@ -1755,16 +1750,15 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) ...@@ -1755,16 +1750,15 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr, alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
bond->alb_info.rlb_enabled); bond->alb_info.rlb_enabled);
read_lock(&bond->lock);
alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr); alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
if (bond->alb_info.rlb_enabled) { if (bond->alb_info.rlb_enabled) {
/* inform clients mac address has changed */ /* inform clients mac address has changed */
rlb_req_update_slave_clients(bond, bond->curr_active_slave); rlb_req_update_slave_clients(bond, bond->curr_active_slave);
} }
read_unlock(&bond->lock);
} }
read_lock(&bond->lock);
write_lock_bh(&bond->curr_slave_lock);
return 0; return 0;
} }
......
...@@ -2213,33 +2213,24 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in ...@@ -2213,33 +2213,24 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
{ {
struct bonding *bond = netdev_priv(bond_dev); struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave; struct slave *slave;
int i, found = 0; int i, res = -ENODEV;
if (info->slave_id < 0) {
return -ENODEV;
}
read_lock(&bond->lock); read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i) { bond_for_each_slave(bond, slave, i) {
if (i == (int)info->slave_id) { if (i == (int)info->slave_id) {
found = 1; res = 0;
strcpy(info->slave_name, slave->dev->name);
info->link = slave->link;
info->state = slave->state;
info->link_failure_count = slave->link_failure_count;
break; break;
} }
} }
read_unlock(&bond->lock); read_unlock(&bond->lock);
if (found) { return res;
strcpy(info->slave_name, slave->dev->name);
info->link = slave->link;
info->state = slave->state;
info->link_failure_count = slave->link_failure_count;
} else {
return -ENODEV;
}
return 0;
} }
/*-------------------------------- Monitoring -------------------------------*/ /*-------------------------------- Monitoring -------------------------------*/
...@@ -5167,16 +5158,15 @@ int bond_create(char *name, struct bond_params *params) ...@@ -5167,16 +5158,15 @@ int bond_create(char *name, struct bond_params *params)
up_write(&bonding_rwsem); up_write(&bonding_rwsem);
rtnl_unlock(); /* allows sysfs registration of net device */ rtnl_unlock(); /* allows sysfs registration of net device */
res = bond_create_sysfs_entry(netdev_priv(bond_dev)); res = bond_create_sysfs_entry(netdev_priv(bond_dev));
if (res < 0) { if (res < 0)
rtnl_lock(); goto out_unreg;
down_write(&bonding_rwsem);
bond_deinit(bond_dev);
unregister_netdevice(bond_dev);
goto out_rtnl;
}
return 0; return 0;
out_unreg:
rtnl_lock();
down_write(&bonding_rwsem);
unregister_netdevice(bond_dev);
out_bond: out_bond:
bond_deinit(bond_dev); bond_deinit(bond_dev);
out_netdev: out_netdev:
......
...@@ -3779,7 +3779,7 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, ...@@ -3779,7 +3779,7 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
adapter->params.info = ai; adapter->params.info = ai;
adapter->params.nports = ai->nports0 + ai->nports1; adapter->params.nports = ai->nports0 + ai->nports1;
adapter->params.chan_map = !!ai->nports0 | (!!ai->nports1 << 1); adapter->params.chan_map = (!!ai->nports0) | (!!ai->nports1 << 1);
adapter->params.rev = t3_read_reg(adapter, A_PL_REV); adapter->params.rev = t3_read_reg(adapter, A_PL_REV);
/* /*
* We used to only run the "adapter check task" once a second if * We used to only run the "adapter check task" once a second if
......
...@@ -3738,7 +3738,7 @@ static irqreturn_t e1000_intr(int irq, void *data) ...@@ -3738,7 +3738,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 rctl, icr = er32(ICR); u32 rctl, icr = er32(ICR);
if (unlikely((!icr) || test_bit(__E1000_RESETTING, &adapter->flags))) if (unlikely((!icr) || test_bit(__E1000_DOWN, &adapter->flags)))
return IRQ_NONE; /* Not our interrupt */ return IRQ_NONE; /* Not our interrupt */
/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#include <asm/io.h> #include <asm/io.h>
#define DRV_NAME "ehea" #define DRV_NAME "ehea"
#define DRV_VERSION "EHEA_0100" #define DRV_VERSION "EHEA_0101"
/* eHEA capability flags */ /* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1 #define DLPAR_PORT_ADD_REM 1
......
...@@ -545,14 +545,17 @@ static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array, ...@@ -545,14 +545,17 @@ static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array,
x &= (arr_len - 1); x &= (arr_len - 1);
pref = skb_array[x]; pref = skb_array[x];
prefetchw(pref); if (pref) {
prefetchw(pref + EHEA_CACHE_LINE); prefetchw(pref);
prefetchw(pref + EHEA_CACHE_LINE);
pref = (skb_array[x]->data);
prefetch(pref); pref = (skb_array[x]->data);
prefetch(pref + EHEA_CACHE_LINE); prefetch(pref);
prefetch(pref + EHEA_CACHE_LINE * 2); prefetch(pref + EHEA_CACHE_LINE);
prefetch(pref + EHEA_CACHE_LINE * 3); prefetch(pref + EHEA_CACHE_LINE * 2);
prefetch(pref + EHEA_CACHE_LINE * 3);
}
skb = skb_array[skb_index]; skb = skb_array[skb_index];
skb_array[skb_index] = NULL; skb_array[skb_index] = NULL;
return skb; return skb;
...@@ -569,12 +572,14 @@ static inline struct sk_buff *get_skb_by_index_ll(struct sk_buff **skb_array, ...@@ -569,12 +572,14 @@ static inline struct sk_buff *get_skb_by_index_ll(struct sk_buff **skb_array,
x &= (arr_len - 1); x &= (arr_len - 1);
pref = skb_array[x]; pref = skb_array[x];
prefetchw(pref); if (pref) {
prefetchw(pref + EHEA_CACHE_LINE); prefetchw(pref);
prefetchw(pref + EHEA_CACHE_LINE);
pref = (skb_array[x]->data); pref = (skb_array[x]->data);
prefetchw(pref); prefetchw(pref);
prefetchw(pref + EHEA_CACHE_LINE); prefetchw(pref + EHEA_CACHE_LINE);
}
skb = skb_array[wqe_index]; skb = skb_array[wqe_index];
skb_array[wqe_index] = NULL; skb_array[wqe_index] = NULL;
......
...@@ -393,12 +393,12 @@ struct mv643xx_eth_private { ...@@ -393,12 +393,12 @@ struct mv643xx_eth_private {
struct work_struct tx_timeout_task; struct work_struct tx_timeout_task;
struct napi_struct napi; struct napi_struct napi;
u8 oom;
u8 work_link; u8 work_link;
u8 work_tx; u8 work_tx;
u8 work_tx_end; u8 work_tx_end;
u8 work_rx; u8 work_rx;
u8 work_rx_refill; u8 work_rx_refill;
u8 work_rx_oom;
int skb_size; int skb_size;
struct sk_buff_head rx_recycle; struct sk_buff_head rx_recycle;
...@@ -661,7 +661,7 @@ static int rxq_refill(struct rx_queue *rxq, int budget) ...@@ -661,7 +661,7 @@ static int rxq_refill(struct rx_queue *rxq, int budget)
dma_get_cache_alignment() - 1); dma_get_cache_alignment() - 1);
if (skb == NULL) { if (skb == NULL) {
mp->work_rx_oom |= 1 << rxq->index; mp->oom = 1;
goto oom; goto oom;
} }
...@@ -1255,7 +1255,6 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) ...@@ -1255,7 +1255,6 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
spin_lock_bh(&mp->mib_counters_lock); spin_lock_bh(&mp->mib_counters_lock);
p->good_octets_received += mib_read(mp, 0x00); p->good_octets_received += mib_read(mp, 0x00);
p->good_octets_received += (u64)mib_read(mp, 0x04) << 32;
p->bad_octets_received += mib_read(mp, 0x08); p->bad_octets_received += mib_read(mp, 0x08);
p->internal_mac_transmit_err += mib_read(mp, 0x0c); p->internal_mac_transmit_err += mib_read(mp, 0x0c);
p->good_frames_received += mib_read(mp, 0x10); p->good_frames_received += mib_read(mp, 0x10);
...@@ -1269,7 +1268,6 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) ...@@ -1269,7 +1268,6 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
p->frames_512_to_1023_octets += mib_read(mp, 0x30); p->frames_512_to_1023_octets += mib_read(mp, 0x30);
p->frames_1024_to_max_octets += mib_read(mp, 0x34); p->frames_1024_to_max_octets += mib_read(mp, 0x34);
p->good_octets_sent += mib_read(mp, 0x38); p->good_octets_sent += mib_read(mp, 0x38);
p->good_octets_sent += (u64)mib_read(mp, 0x3c) << 32;
p->good_frames_sent += mib_read(mp, 0x40); p->good_frames_sent += mib_read(mp, 0x40);
p->excessive_collision += mib_read(mp, 0x44); p->excessive_collision += mib_read(mp, 0x44);
p->multicast_frames_sent += mib_read(mp, 0x48); p->multicast_frames_sent += mib_read(mp, 0x48);
...@@ -2167,8 +2165,10 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) ...@@ -2167,8 +2165,10 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
mp = container_of(napi, struct mv643xx_eth_private, napi); mp = container_of(napi, struct mv643xx_eth_private, napi);
mp->work_rx_refill |= mp->work_rx_oom; if (unlikely(mp->oom)) {
mp->work_rx_oom = 0; mp->oom = 0;
del_timer(&mp->rx_oom);
}
work_done = 0; work_done = 0;
while (work_done < budget) { while (work_done < budget) {
...@@ -2182,8 +2182,10 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) ...@@ -2182,8 +2182,10 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
continue; continue;
} }
queue_mask = mp->work_tx | mp->work_tx_end | queue_mask = mp->work_tx | mp->work_tx_end | mp->work_rx;
mp->work_rx | mp->work_rx_refill; if (likely(!mp->oom))
queue_mask |= mp->work_rx_refill;
if (!queue_mask) { if (!queue_mask) {
if (mv643xx_eth_collect_events(mp)) if (mv643xx_eth_collect_events(mp))
continue; continue;
...@@ -2204,7 +2206,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) ...@@ -2204,7 +2206,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
txq_maybe_wake(mp->txq + queue); txq_maybe_wake(mp->txq + queue);
} else if (mp->work_rx & queue_mask) { } else if (mp->work_rx & queue_mask) {
work_done += rxq_process(mp->rxq + queue, work_tbd); work_done += rxq_process(mp->rxq + queue, work_tbd);
} else if (mp->work_rx_refill & queue_mask) { } else if (!mp->oom && (mp->work_rx_refill & queue_mask)) {
work_done += rxq_refill(mp->rxq + queue, work_tbd); work_done += rxq_refill(mp->rxq + queue, work_tbd);
} else { } else {
BUG(); BUG();
...@@ -2212,7 +2214,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) ...@@ -2212,7 +2214,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
} }
if (work_done < budget) { if (work_done < budget) {
if (mp->work_rx_oom) if (mp->oom)
mod_timer(&mp->rx_oom, jiffies + (HZ / 10)); mod_timer(&mp->rx_oom, jiffies + (HZ / 10));
napi_complete(napi); napi_complete(napi);
wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT);
...@@ -2372,7 +2374,7 @@ static int mv643xx_eth_open(struct net_device *dev) ...@@ -2372,7 +2374,7 @@ static int mv643xx_eth_open(struct net_device *dev)
rxq_refill(mp->rxq + i, INT_MAX); rxq_refill(mp->rxq + i, INT_MAX);
} }
if (mp->work_rx_oom) { if (mp->oom) {
mp->rx_oom.expires = jiffies + (HZ / 10); mp->rx_oom.expires = jiffies + (HZ / 10);
add_timer(&mp->rx_oom); add_timer(&mp->rx_oom);
} }
......
...@@ -374,18 +374,17 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev, ...@@ -374,18 +374,17 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
dev->ethtool_ops = &ne2k_pci_ethtool_ops; dev->ethtool_ops = &ne2k_pci_ethtool_ops;
NS8390_init(dev, 0); NS8390_init(dev, 0);
memcpy(dev->dev_addr, SA_prom, 6);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
i = register_netdev(dev); i = register_netdev(dev);
if (i) if (i)
goto err_out_free_netdev; goto err_out_free_netdev;
for(i = 0; i < 6; i++)
dev->dev_addr[i] = SA_prom[i];
printk("%s: %s found at %#lx, IRQ %d, %pM.\n", printk("%s: %s found at %#lx, IRQ %d, %pM.\n",
dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq, dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq,
dev->dev_addr); dev->dev_addr);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
return 0; return 0;
err_out_free_netdev: err_out_free_netdev:
......
...@@ -664,7 +664,7 @@ static int netconsole_netdev_event(struct notifier_block *this, ...@@ -664,7 +664,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
struct netconsole_target *nt; struct netconsole_target *nt;
struct net_device *dev = ptr; struct net_device *dev = ptr;
if (!(event == NETDEV_CHANGENAME)) if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER))
goto done; goto done;
spin_lock_irqsave(&target_list_lock, flags); spin_lock_irqsave(&target_list_lock, flags);
...@@ -675,6 +675,15 @@ static int netconsole_netdev_event(struct notifier_block *this, ...@@ -675,6 +675,15 @@ static int netconsole_netdev_event(struct notifier_block *this,
case NETDEV_CHANGENAME: case NETDEV_CHANGENAME:
strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ); strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ);
break; break;
case NETDEV_UNREGISTER:
if (!nt->enabled)
break;
netpoll_cleanup(&nt->np);
nt->enabled = 0;
printk(KERN_INFO "netconsole: network logging stopped"
", interface %s unregistered\n",
dev->name);
break;
} }
} }
netconsole_target_put(nt); netconsole_target_put(nt);
......
...@@ -180,6 +180,20 @@ config USB_NET_CDCETHER ...@@ -180,6 +180,20 @@ config USB_NET_CDCETHER
IEEE 802 "local assignment" bit is set in the address, a "usbX" IEEE 802 "local assignment" bit is set in the address, a "usbX"
name is used instead. name is used instead.
config USB_NET_CDC_EEM
tristate "CDC EEM support"
depends on USB_USBNET && EXPERIMENTAL
help
This option supports devices conforming to the Communication Device
Class (CDC) Ethernet Emulation Model, a specification that's easy to
implement in device firmware. The CDC EEM specifications are available
from <http://www.usb.org/>.
This driver creates an interface named "ethX", where X depends on
what other networking devices you have in use. However, if the
IEEE 802 "local assignment" bit is set in the address, a "usbX"
name is used instead.
config USB_NET_DM9601 config USB_NET_DM9601
tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices" tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
depends on USB_USBNET depends on USB_USBNET
......
...@@ -9,6 +9,7 @@ obj-$(CONFIG_USB_RTL8150) += rtl8150.o ...@@ -9,6 +9,7 @@ obj-$(CONFIG_USB_RTL8150) += rtl8150.o
obj-$(CONFIG_USB_HSO) += hso.o obj-$(CONFIG_USB_HSO) += hso.o
obj-$(CONFIG_USB_NET_AX8817X) += asix.o obj-$(CONFIG_USB_NET_AX8817X) += asix.o
obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o
obj-$(CONFIG_USB_NET_DM9601) += dm9601.o obj-$(CONFIG_USB_NET_DM9601) += dm9601.o
obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o
obj-$(CONFIG_USB_NET_GL620A) += gl620a.o obj-$(CONFIG_USB_NET_GL620A) += gl620a.o
......
/*
* USB CDC EEM network interface driver
* Copyright (C) 2009 Oberthur Technologies
* by Omar Laazimani, Olivier Condemine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ctype.h>
#include <linux/ethtool.h>
#include <linux/workqueue.h>
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/crc32.h>
#include <linux/usb/cdc.h>
#include <linux/usb/usbnet.h>
/*
* This driver is an implementation of the CDC "Ethernet Emulation
* Model" (EEM) specification, which encapsulates Ethernet frames
* for transport over USB using a simpler USB device model than the
* previous CDC "Ethernet Control Model" (ECM, or "CDC Ethernet").
*
* For details, see www.usb.org/developers/devclass_docs/CDC_EEM10.pdf
*
* This version has been tested with GIGAntIC WuaoW SIM Smart Card on 2.6.24,
* 2.6.27 and 2.6.30rc2 kernel.
* It has also been validated on Openmoko Om 2008.12 (based on 2.6.24 kernel).
* build on 23-April-2009
*/
#define EEM_HEAD 2 /* 2 byte header */
/*-------------------------------------------------------------------------*/
static void eem_linkcmd_complete(struct urb *urb)
{
dev_kfree_skb(urb->context);
usb_free_urb(urb);
}
static void eem_linkcmd(struct usbnet *dev, struct sk_buff *skb)
{
struct urb *urb;
int status;
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb)
goto fail;
usb_fill_bulk_urb(urb, dev->udev, dev->out,
skb->data, skb->len, eem_linkcmd_complete, skb);
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
usb_free_urb(urb);
fail:
dev_kfree_skb(skb);
devwarn(dev, "link cmd failure\n");
return;
}
}
static int eem_bind(struct usbnet *dev, struct usb_interface *intf)
{
int status = 0;
status = usbnet_get_endpoints(dev, intf);
if (status < 0) {
usb_set_intfdata(intf, NULL);
usb_driver_release_interface(driver_of(intf), intf);
return status;
}
/* no jumbogram (16K) support for now */
dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN;
return 0;
}
/*
* EEM permits packing multiple Ethernet frames into USB transfers
* (a "bundle"), but for TX we don't try to do that.
*/
static struct sk_buff *eem_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
gfp_t flags)
{
struct sk_buff *skb2 = NULL;
u16 len = skb->len;
u32 crc = 0;
int padlen = 0;
/* When ((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket) is
* zero, stick two bytes of zero length EEM packet on the end.
* Else the framework would add invalid single byte padding,
* since it can't know whether ZLPs will be handled right by
* all the relevant hardware and software.
*/
if (!((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket))
padlen += 2;
if (!skb_cloned(skb)) {
int headroom = skb_headroom(skb);
int tailroom = skb_tailroom(skb);
if ((tailroom >= ETH_FCS_LEN + padlen)
&& (headroom >= EEM_HEAD))
goto done;
if ((headroom + tailroom)
> (EEM_HEAD + ETH_FCS_LEN + padlen)) {
skb->data = memmove(skb->head +
EEM_HEAD,
skb->data,
skb->len);
skb_set_tail_pointer(skb, len);
goto done;
}
}
skb2 = skb_copy_expand(skb, EEM_HEAD, ETH_FCS_LEN + padlen, flags);
if (!skb2)
return NULL;
dev_kfree_skb_any(skb);
skb = skb2;
done:
/* we don't use the "no Ethernet CRC" option */
crc = crc32_le(~0, skb->data, skb->len);
crc = ~crc;
put_unaligned_le32(crc, skb_put(skb, 4));
/* EEM packet header format:
* b0..13: length of ethernet frame
* b14: bmCRC (1 == valid Ethernet CRC)
* b15: bmType (0 == data)
*/
len = skb->len;
put_unaligned_le16(BIT(14) | len, skb_push(skb, 2));
/* Bundle a zero length EEM packet if needed */
if (padlen)
put_unaligned_le16(0, skb_put(skb, 2));
return skb;
}
static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{
/*
* Our task here is to strip off framing, leaving skb with one
* data frame for the usbnet framework code to process. But we
* may have received multiple EEM payloads, or command payloads.
* So we must process _everything_ as if it's a header, except
* maybe the last data payload
*
* REVISIT the framework needs updating so that when we consume
* all payloads (the last or only message was a command, or a
* zero length EEM packet) that is not accounted as an rx_error.
*/
do {
struct sk_buff *skb2 = NULL;
u16 header;
u16 len = 0;
/* incomplete EEM header? */
if (skb->len < EEM_HEAD)
return 0;
/*
* EEM packet header format:
* b0..14: EEM type dependant (Data or Command)
* b15: bmType
*/
header = get_unaligned_le16(skb->data);
skb_pull(skb, EEM_HEAD);
/*
* The bmType bit helps to denote when EEM
* packet is data or command :
* bmType = 0 : EEM data payload
* bmType = 1 : EEM (link) command
*/
if (header & BIT(15)) {
u16 bmEEMCmd;
/*
* EEM (link) command packet:
* b0..10: bmEEMCmdParam
* b11..13: bmEEMCmd
* b14: bmReserved (must be 0)
* b15: 1 (EEM command)
*/
if (header & BIT(14)) {
devdbg(dev, "reserved command %04x\n", header);
continue;
}
bmEEMCmd = (header >> 11) & 0x7;
switch (bmEEMCmd) {
/* Responding to echo requests is mandatory. */
case 0: /* Echo command */
len = header & 0x7FF;
/* bogus command? */
if (skb->len < len)
return 0;
skb2 = skb_clone(skb, GFP_ATOMIC);
if (unlikely(!skb2))
goto next;
skb_trim(skb2, len);
put_unaligned_le16(BIT(15) | (1 << 11) | len,
skb_push(skb2, 2));
eem_linkcmd(dev, skb2);
break;
/*
* Host may choose to ignore hints.
* - suspend: peripheral ready to suspend
* - response: suggest N millisec polling
* - response complete: suggest N sec polling
*/
case 2: /* Suspend hint */
case 3: /* Response hint */
case 4: /* Response complete hint */
continue;
/*
* Hosts should never receive host-to-peripheral
* or reserved command codes; or responses to an
* echo command we didn't send.
*/
case 1: /* Echo response */
case 5: /* Tickle */
default: /* reserved */
devwarn(dev, "unexpected link command %d\n",
bmEEMCmd);
continue;
}
} else {
u32 crc, crc2;
int is_last;
/* zero length EEM packet? */
if (header == 0)
continue;
/*
* EEM data packet header :
* b0..13: length of ethernet frame
* b14: bmCRC
* b15: 0 (EEM data)
*/
len = header & 0x3FFF;
/* bogus EEM payload? */
if (skb->len < len)
return 0;
/* bogus ethernet frame? */
if (len < (ETH_HLEN + ETH_FCS_LEN))
goto next;
/*
* Treat the last payload differently: framework
* code expects our "fixup" to have stripped off
* headers, so "skb" is a data packet (or error).
* Else if it's not the last payload, keep "skb"
* for further processing.
*/
is_last = (len == skb->len);
if (is_last)
skb2 = skb;
else {
skb2 = skb_clone(skb, GFP_ATOMIC);
if (unlikely(!skb2))
return 0;
}
crc = get_unaligned_le32(skb2->data
+ len - ETH_FCS_LEN);
skb_trim(skb2, len - ETH_FCS_LEN);
/*
* The bmCRC helps to denote when the CRC field in
* the Ethernet frame contains a calculated CRC:
* bmCRC = 1 : CRC is calculated
* bmCRC = 0 : CRC = 0xDEADBEEF
*/
if (header & BIT(14))
crc2 = ~crc32_le(~0, skb2->data, len);
else
crc2 = 0xdeadbeef;
if (is_last)
return crc == crc2;
if (unlikely(crc != crc2)) {
dev->stats.rx_errors++;
dev_kfree_skb_any(skb2);
} else
usbnet_skb_return(dev, skb2);
}
next:
skb_pull(skb, len);
} while (skb->len);
return 1;
}
static const struct driver_info eem_info = {
.description = "CDC EEM Device",
.flags = FLAG_ETHER,
.bind = eem_bind,
.rx_fixup = eem_rx_fixup,
.tx_fixup = eem_tx_fixup,
};
/*-------------------------------------------------------------------------*/
static const struct usb_device_id products[] = {
{
USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_EEM,
USB_CDC_PROTO_EEM),
.driver_info = (unsigned long) &eem_info,
},
{
/* EMPTY == end of list */
},
};
MODULE_DEVICE_TABLE(usb, products);
static struct usb_driver eem_driver = {
.name = "cdc_eem",
.id_table = products,
.probe = usbnet_probe,
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
};
static int __init eem_init(void)
{
return usb_register(&eem_driver);
}
module_init(eem_init);
static void __exit eem_exit(void)
{
usb_deregister(&eem_driver);
}
module_exit(eem_exit);
MODULE_AUTHOR("Omar Laazimani <omar.oberthur@gmail.com>");
MODULE_DESCRIPTION("USB CDC EEM");
MODULE_LICENSE("GPL");
...@@ -941,6 +941,16 @@ static int smsc95xx_reset(struct usbnet *dev) ...@@ -941,6 +941,16 @@ static int smsc95xx_reset(struct usbnet *dev)
if (netif_msg_ifup(dev)) if (netif_msg_ifup(dev))
devdbg(dev, "ID_REV = 0x%08x", read_buf); devdbg(dev, "ID_REV = 0x%08x", read_buf);
/* Configure GPIO pins as LED outputs */
write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED |
LED_GPIO_CFG_FDX_LED;
ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf);
if (ret < 0) {
devwarn(dev, "Failed to write LED_GPIO_CFG register, ret=%d",
ret);
return ret;
}
/* Init Tx */ /* Init Tx */
write_buf = 0; write_buf = 0;
ret = smsc95xx_write_reg(dev, FLOW, write_buf); ret = smsc95xx_write_reg(dev, FLOW, write_buf);
...@@ -1231,6 +1241,11 @@ static const struct usb_device_id products[] = { ...@@ -1231,6 +1241,11 @@ static const struct usb_device_id products[] = {
USB_DEVICE(0x0424, 0x9500), USB_DEVICE(0x0424, 0x9500),
.driver_info = (unsigned long) &smsc95xx_info, .driver_info = (unsigned long) &smsc95xx_info,
}, },
{
/* SMSC9512/9514 USB Hub & Ethernet Device */
USB_DEVICE(0x0424, 0xec00),
.driver_info = (unsigned long) &smsc95xx_info,
},
{ }, /* END */ { }, /* END */
}; };
MODULE_DEVICE_TABLE(usb, products); MODULE_DEVICE_TABLE(usb, products);
......
...@@ -99,6 +99,9 @@ ...@@ -99,6 +99,9 @@
#define PM_CTL_WUPS_MULTI_ (0x00000003) #define PM_CTL_WUPS_MULTI_ (0x00000003)
#define LED_GPIO_CFG (0x24) #define LED_GPIO_CFG (0x24)
#define LED_GPIO_CFG_SPD_LED (0x01000000)
#define LED_GPIO_CFG_LNK_LED (0x00100000)
#define LED_GPIO_CFG_FDX_LED (0x00010000)
#define GPIO_CFG (0x28) #define GPIO_CFG (0x28)
......
...@@ -616,10 +616,11 @@ static int virtnet_open(struct net_device *dev) ...@@ -616,10 +616,11 @@ static int virtnet_open(struct net_device *dev)
static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
struct scatterlist *data, int out, int in) struct scatterlist *data, int out, int in)
{ {
struct scatterlist sg[VIRTNET_SEND_COMMAND_SG_MAX + 2]; struct scatterlist *s, sg[VIRTNET_SEND_COMMAND_SG_MAX + 2];
struct virtio_net_ctrl_hdr ctrl; struct virtio_net_ctrl_hdr ctrl;
virtio_net_ctrl_ack status = ~0; virtio_net_ctrl_ack status = ~0;
unsigned int tmp; unsigned int tmp;
int i;
if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) { if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
BUG(); /* Caller should know better */ BUG(); /* Caller should know better */
...@@ -637,7 +638,8 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, ...@@ -637,7 +638,8 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
sg_init_table(sg, out + in); sg_init_table(sg, out + in);
sg_set_buf(&sg[0], &ctrl, sizeof(ctrl)); sg_set_buf(&sg[0], &ctrl, sizeof(ctrl));
memcpy(&sg[1], data, sizeof(struct scatterlist) * (out + in - 2)); for_each_sg(data, s, out + in - 2, i)
sg_set_buf(&sg[i + 1], sg_virt(s), s->length);
sg_set_buf(&sg[out + in - 1], &status, sizeof(status)); sg_set_buf(&sg[out + in - 1], &status, sizeof(status));
if (vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) != 0) if (vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) != 0)
...@@ -692,7 +694,7 @@ static void virtnet_set_rx_mode(struct net_device *dev) ...@@ -692,7 +694,7 @@ static void virtnet_set_rx_mode(struct net_device *dev)
promisc = ((dev->flags & IFF_PROMISC) != 0); promisc = ((dev->flags & IFF_PROMISC) != 0);
allmulti = ((dev->flags & IFF_ALLMULTI) != 0); allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
sg_set_buf(sg, &promisc, sizeof(promisc)); sg_init_one(sg, &promisc, sizeof(promisc));
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
VIRTIO_NET_CTRL_RX_PROMISC, VIRTIO_NET_CTRL_RX_PROMISC,
...@@ -700,7 +702,7 @@ static void virtnet_set_rx_mode(struct net_device *dev) ...@@ -700,7 +702,7 @@ static void virtnet_set_rx_mode(struct net_device *dev)
dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", dev_warn(&dev->dev, "Failed to %sable promisc mode.\n",
promisc ? "en" : "dis"); promisc ? "en" : "dis");
sg_set_buf(sg, &allmulti, sizeof(allmulti)); sg_init_one(sg, &allmulti, sizeof(allmulti));
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
VIRTIO_NET_CTRL_RX_ALLMULTI, VIRTIO_NET_CTRL_RX_ALLMULTI,
...@@ -716,6 +718,8 @@ static void virtnet_set_rx_mode(struct net_device *dev) ...@@ -716,6 +718,8 @@ static void virtnet_set_rx_mode(struct net_device *dev)
return; return;
} }
sg_init_table(sg, 2);
/* Store the unicast list and count in the front of the buffer */ /* Store the unicast list and count in the front of the buffer */
mac_data->entries = dev->uc_count; mac_data->entries = dev->uc_count;
addr = dev->uc_list; addr = dev->uc_list;
...@@ -744,24 +748,24 @@ static void virtnet_set_rx_mode(struct net_device *dev) ...@@ -744,24 +748,24 @@ static void virtnet_set_rx_mode(struct net_device *dev)
kfree(buf); kfree(buf);
} }
static void virnet_vlan_rx_add_vid(struct net_device *dev, u16 vid) static void virtnet_vlan_rx_add_vid(struct net_device *dev, u16 vid)
{ {
struct virtnet_info *vi = netdev_priv(dev); struct virtnet_info *vi = netdev_priv(dev);
struct scatterlist sg; struct scatterlist sg;
sg_set_buf(&sg, &vid, sizeof(vid)); sg_init_one(&sg, &vid, sizeof(vid));
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
VIRTIO_NET_CTRL_VLAN_ADD, &sg, 1, 0)) VIRTIO_NET_CTRL_VLAN_ADD, &sg, 1, 0))
dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid); dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid);
} }
static void virnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
{ {
struct virtnet_info *vi = netdev_priv(dev); struct virtnet_info *vi = netdev_priv(dev);
struct scatterlist sg; struct scatterlist sg;
sg_set_buf(&sg, &vid, sizeof(vid)); sg_init_one(&sg, &vid, sizeof(vid));
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
VIRTIO_NET_CTRL_VLAN_DEL, &sg, 1, 0)) VIRTIO_NET_CTRL_VLAN_DEL, &sg, 1, 0))
...@@ -794,8 +798,8 @@ static const struct net_device_ops virtnet_netdev = { ...@@ -794,8 +798,8 @@ static const struct net_device_ops virtnet_netdev = {
.ndo_set_mac_address = virtnet_set_mac_address, .ndo_set_mac_address = virtnet_set_mac_address,
.ndo_set_rx_mode = virtnet_set_rx_mode, .ndo_set_rx_mode = virtnet_set_rx_mode,
.ndo_change_mtu = virtnet_change_mtu, .ndo_change_mtu = virtnet_change_mtu,
.ndo_vlan_rx_add_vid = virnet_vlan_rx_add_vid, .ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = virnet_vlan_rx_kill_vid, .ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = virtnet_netpoll, .ndo_poll_controller = virtnet_netpoll,
#endif #endif
......
...@@ -424,7 +424,7 @@ ath5k_debug_dump_bands(struct ath5k_softc *sc) ...@@ -424,7 +424,7 @@ ath5k_debug_dump_bands(struct ath5k_softc *sc)
for (b = 0; b < IEEE80211_NUM_BANDS; b++) { for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
struct ieee80211_supported_band *band = &sc->sbands[b]; struct ieee80211_supported_band *band = &sc->sbands[b];
char bname[5]; char bname[6];
switch (band->band) { switch (band->band) {
case IEEE80211_BAND_2GHZ: case IEEE80211_BAND_2GHZ:
strcpy(bname, "2 GHz"); strcpy(bname, "2 GHz");
......
...@@ -925,11 +925,11 @@ void iwl_bg_scan_completed(struct work_struct *work) ...@@ -925,11 +925,11 @@ void iwl_bg_scan_completed(struct work_struct *work)
IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
ieee80211_scan_completed(priv->hw, false);
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return; return;
ieee80211_scan_completed(priv->hw, false);
/* Since setting the TXPOWER may have been deferred while /* Since setting the TXPOWER may have been deferred while
* performing the scan, fire one off */ * performing the scan, fire one off */
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
......
...@@ -1694,7 +1694,6 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) ...@@ -1694,7 +1694,6 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
rxq->free_count = 0; rxq->free_count = 0;
spin_unlock_irqrestore(&rxq->lock, flags); spin_unlock_irqrestore(&rxq->lock, flags);
} }
EXPORT_SYMBOL(iwl3945_rx_queue_reset);
/* /*
* this should be called while priv->lock is locked * this should be called while priv->lock is locked
......
...@@ -2558,6 +2558,11 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) ...@@ -2558,6 +2558,11 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
mutex_init(&priv->command_lock); mutex_init(&priv->command_lock);
spin_lock_init(&priv->stats_lock); spin_lock_init(&priv->stats_lock);
/* because rndis_command() sleeps we need to use workqueue */
priv->workqueue = create_singlethread_workqueue("rndis_wlan");
INIT_WORK(&priv->work, rndis_wext_worker);
INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats);
/* try bind rndis_host */ /* try bind rndis_host */
retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS); retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS);
if (retval < 0) if (retval < 0)
...@@ -2603,16 +2608,17 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) ...@@ -2603,16 +2608,17 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
disassociate(usbdev, 1); disassociate(usbdev, 1);
netif_carrier_off(usbdev->net); netif_carrier_off(usbdev->net);
/* because rndis_command() sleeps we need to use workqueue */
priv->workqueue = create_singlethread_workqueue("rndis_wlan");
INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats);
queue_delayed_work(priv->workqueue, &priv->stats_work, queue_delayed_work(priv->workqueue, &priv->stats_work,
round_jiffies_relative(STATS_UPDATE_JIFFIES)); round_jiffies_relative(STATS_UPDATE_JIFFIES));
INIT_WORK(&priv->work, rndis_wext_worker);
return 0; return 0;
fail: fail:
cancel_delayed_work_sync(&priv->stats_work);
cancel_work_sync(&priv->work);
flush_workqueue(priv->workqueue);
destroy_workqueue(priv->workqueue);
kfree(priv); kfree(priv);
return retval; return retval;
} }
......
...@@ -472,7 +472,7 @@ static inline void xt_info_rdlock_bh(void) ...@@ -472,7 +472,7 @@ static inline void xt_info_rdlock_bh(void)
local_bh_disable(); local_bh_disable();
lock = &__get_cpu_var(xt_info_locks); lock = &__get_cpu_var(xt_info_locks);
if (!lock->readers++) if (likely(!lock->readers++))
spin_lock(&lock->lock); spin_lock(&lock->lock);
} }
...@@ -480,7 +480,7 @@ static inline void xt_info_rdunlock_bh(void) ...@@ -480,7 +480,7 @@ static inline void xt_info_rdunlock_bh(void)
{ {
struct xt_info_lock *lock = &__get_cpu_var(xt_info_locks); struct xt_info_lock *lock = &__get_cpu_var(xt_info_locks);
if (!--lock->readers) if (likely(!--lock->readers))
spin_unlock(&lock->lock); spin_unlock(&lock->lock);
local_bh_enable(); local_bh_enable();
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#define USB_CDC_SUBCLASS_DMM 0x09 #define USB_CDC_SUBCLASS_DMM 0x09
#define USB_CDC_SUBCLASS_MDLM 0x0a #define USB_CDC_SUBCLASS_MDLM 0x0a
#define USB_CDC_SUBCLASS_OBEX 0x0b #define USB_CDC_SUBCLASS_OBEX 0x0b
#define USB_CDC_SUBCLASS_EEM 0x0c
#define USB_CDC_PROTO_NONE 0 #define USB_CDC_PROTO_NONE 0
...@@ -28,6 +29,8 @@ ...@@ -28,6 +29,8 @@
#define USB_CDC_ACM_PROTO_AT_CDMA 6 #define USB_CDC_ACM_PROTO_AT_CDMA 6
#define USB_CDC_ACM_PROTO_VENDOR 0xff #define USB_CDC_ACM_PROTO_VENDOR 0xff
#define USB_CDC_PROTO_EEM 7
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* /*
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* compatible drivers/servers. */ * compatible drivers/servers. */
#include <linux/types.h> #include <linux/types.h>
#include <linux/virtio_config.h> #include <linux/virtio_config.h>
#include <linux/if_ether.h>
/* The ID for virtio_net */ /* The ID for virtio_net */
#define VIRTIO_ID_NET 1 #define VIRTIO_ID_NET 1
......
...@@ -457,6 +457,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); ...@@ -457,6 +457,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count);
int hci_register_sysfs(struct hci_dev *hdev); int hci_register_sysfs(struct hci_dev *hdev);
void hci_unregister_sysfs(struct hci_dev *hdev); void hci_unregister_sysfs(struct hci_dev *hdev);
void hci_conn_init_sysfs(struct hci_conn *conn);
void hci_conn_add_sysfs(struct hci_conn *conn); void hci_conn_add_sysfs(struct hci_conn *conn);
void hci_conn_del_sysfs(struct hci_conn *conn); void hci_conn_del_sysfs(struct hci_conn *conn);
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <net/ip.h> #include <net/ip.h>
#include <net/tcp_states.h> #include <net/tcp_states.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
#include <net/dst.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
...@@ -530,6 +531,17 @@ static inline void tcp_fast_path_check(struct sock *sk) ...@@ -530,6 +531,17 @@ static inline void tcp_fast_path_check(struct sock *sk)
tcp_fast_path_on(tp); tcp_fast_path_on(tp);
} }
/* Compute the actual rto_min value */
static inline u32 tcp_rto_min(struct sock *sk)
{
struct dst_entry *dst = __sk_dst_get(sk);
u32 rto_min = TCP_RTO_MIN;
if (dst && dst_metric_locked(dst, RTAX_RTO_MIN))
rto_min = dst_metric_rtt(dst, RTAX_RTO_MIN);
return rto_min;
}
/* Compute the actual receive window we are currently advertising. /* Compute the actual receive window we are currently advertising.
* Rcv_nxt can be after the window if our peer push more data * Rcv_nxt can be after the window if our peer push more data
* than the offered window. * than the offered window.
...@@ -895,7 +907,7 @@ static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb) ...@@ -895,7 +907,7 @@ static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb)
wake_up_interruptible(sk->sk_sleep); wake_up_interruptible(sk->sk_sleep);
if (!inet_csk_ack_scheduled(sk)) if (!inet_csk_ack_scheduled(sk))
inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
(3 * TCP_RTO_MIN) / 4, (3 * tcp_rto_min(sk)) / 4,
TCP_RTO_MAX); TCP_RTO_MAX);
} }
return 1; return 1;
......
...@@ -549,6 +549,7 @@ static void br2684_setup(struct net_device *netdev) ...@@ -549,6 +549,7 @@ static void br2684_setup(struct net_device *netdev)
struct br2684_dev *brdev = BRPRIV(netdev); struct br2684_dev *brdev = BRPRIV(netdev);
ether_setup(netdev); ether_setup(netdev);
brdev->net_dev = netdev;
netdev->netdev_ops = &br2684_netdev_ops; netdev->netdev_ops = &br2684_netdev_ops;
......
...@@ -248,6 +248,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) ...@@ -248,6 +248,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
if (hdev->notify) if (hdev->notify)
hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
hci_conn_init_sysfs(conn);
tasklet_enable(&hdev->tx_task); tasklet_enable(&hdev->tx_task);
return conn; return conn;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
struct class *bt_class = NULL; struct class *bt_class = NULL;
EXPORT_SYMBOL_GPL(bt_class); EXPORT_SYMBOL_GPL(bt_class);
static struct workqueue_struct *bluetooth; static struct workqueue_struct *bt_workq;
static inline char *link_typetostr(int type) static inline char *link_typetostr(int type)
{ {
...@@ -89,8 +89,8 @@ static void add_conn(struct work_struct *work) ...@@ -89,8 +89,8 @@ static void add_conn(struct work_struct *work)
{ {
struct hci_conn *conn = container_of(work, struct hci_conn, work_add); struct hci_conn *conn = container_of(work, struct hci_conn, work_add);
/* ensure previous add/del is complete */ /* ensure previous del is complete */
flush_workqueue(bluetooth); flush_work(&conn->work_del);
if (device_add(&conn->dev) < 0) { if (device_add(&conn->dev) < 0) {
BT_ERR("Failed to register connection device"); BT_ERR("Failed to register connection device");
...@@ -98,27 +98,6 @@ static void add_conn(struct work_struct *work) ...@@ -98,27 +98,6 @@ static void add_conn(struct work_struct *work)
} }
} }
void hci_conn_add_sysfs(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
BT_DBG("conn %p", conn);
conn->dev.type = &bt_link;
conn->dev.class = bt_class;
conn->dev.parent = &hdev->dev;
dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
dev_set_drvdata(&conn->dev, conn);
device_initialize(&conn->dev);
INIT_WORK(&conn->work_add, add_conn);
queue_work(bluetooth, &conn->work_add);
}
/* /*
* The rfcomm tty device will possibly retain even when conn * The rfcomm tty device will possibly retain even when conn
* is down, and sysfs doesn't support move zombie device, * is down, and sysfs doesn't support move zombie device,
...@@ -134,8 +113,11 @@ static void del_conn(struct work_struct *work) ...@@ -134,8 +113,11 @@ static void del_conn(struct work_struct *work)
struct hci_conn *conn = container_of(work, struct hci_conn, work_del); struct hci_conn *conn = container_of(work, struct hci_conn, work_del);
struct hci_dev *hdev = conn->hdev; struct hci_dev *hdev = conn->hdev;
/* ensure previous add/del is complete */ /* ensure previous add is complete */
flush_workqueue(bluetooth); flush_work(&conn->work_add);
if (!device_is_registered(&conn->dev))
return;
while (1) { while (1) {
struct device *dev; struct device *dev;
...@@ -152,16 +134,40 @@ static void del_conn(struct work_struct *work) ...@@ -152,16 +134,40 @@ static void del_conn(struct work_struct *work)
hci_dev_put(hdev); hci_dev_put(hdev);
} }
void hci_conn_del_sysfs(struct hci_conn *conn) void hci_conn_init_sysfs(struct hci_conn *conn)
{ {
struct hci_dev *hdev = conn->hdev;
BT_DBG("conn %p", conn); BT_DBG("conn %p", conn);
if (!device_is_registered(&conn->dev)) conn->dev.type = &bt_link;
return; conn->dev.class = bt_class;
conn->dev.parent = &hdev->dev;
dev_set_drvdata(&conn->dev, conn);
device_initialize(&conn->dev);
INIT_WORK(&conn->work_add, add_conn);
INIT_WORK(&conn->work_del, del_conn); INIT_WORK(&conn->work_del, del_conn);
}
void hci_conn_add_sysfs(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
BT_DBG("conn %p", conn);
dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
queue_work(bt_workq, &conn->work_add);
}
void hci_conn_del_sysfs(struct hci_conn *conn)
{
BT_DBG("conn %p", conn);
queue_work(bluetooth, &conn->work_del); queue_work(bt_workq, &conn->work_del);
} }
static inline char *host_typetostr(int type) static inline char *host_typetostr(int type)
...@@ -438,13 +444,13 @@ void hci_unregister_sysfs(struct hci_dev *hdev) ...@@ -438,13 +444,13 @@ void hci_unregister_sysfs(struct hci_dev *hdev)
int __init bt_sysfs_init(void) int __init bt_sysfs_init(void)
{ {
bluetooth = create_singlethread_workqueue("bluetooth"); bt_workq = create_singlethread_workqueue("bluetooth");
if (!bluetooth) if (!bt_workq)
return -ENOMEM; return -ENOMEM;
bt_class = class_create(THIS_MODULE, "bluetooth"); bt_class = class_create(THIS_MODULE, "bluetooth");
if (IS_ERR(bt_class)) { if (IS_ERR(bt_class)) {
destroy_workqueue(bluetooth); destroy_workqueue(bt_workq);
return PTR_ERR(bt_class); return PTR_ERR(bt_class);
} }
...@@ -453,7 +459,7 @@ int __init bt_sysfs_init(void) ...@@ -453,7 +459,7 @@ int __init bt_sysfs_init(void)
void bt_sysfs_cleanup(void) void bt_sysfs_cleanup(void)
{ {
destroy_workqueue(bluetooth); destroy_workqueue(bt_workq);
class_destroy(bt_class); class_destroy(bt_class);
} }
...@@ -1735,11 +1735,12 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) ...@@ -1735,11 +1735,12 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb)
{ {
u32 hash; u32 hash;
if (skb_rx_queue_recorded(skb)) { if (skb_rx_queue_recorded(skb))
hash = skb_get_rx_queue(skb); return skb_get_rx_queue(skb) % dev->real_num_tx_queues;
} else if (skb->sk && skb->sk->sk_hash) {
if (skb->sk && skb->sk->sk_hash)
hash = skb->sk->sk_hash; hash = skb->sk->sk_hash;
} else else
hash = skb->protocol; hash = skb->protocol;
hash = jhash_1word(hash, skb_tx_hashrnd); hash = jhash_1word(hash, skb_tx_hashrnd);
......
...@@ -1365,9 +1365,8 @@ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) ...@@ -1365,9 +1365,8 @@ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i)
static inline struct page *linear_to_page(struct page *page, unsigned int *len, static inline struct page *linear_to_page(struct page *page, unsigned int *len,
unsigned int *offset, unsigned int *offset,
struct sk_buff *skb) struct sk_buff *skb, struct sock *sk)
{ {
struct sock *sk = skb->sk;
struct page *p = sk->sk_sndmsg_page; struct page *p = sk->sk_sndmsg_page;
unsigned int off; unsigned int off;
...@@ -1405,13 +1404,14 @@ static inline struct page *linear_to_page(struct page *page, unsigned int *len, ...@@ -1405,13 +1404,14 @@ static inline struct page *linear_to_page(struct page *page, unsigned int *len,
*/ */
static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page, static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page,
unsigned int *len, unsigned int offset, unsigned int *len, unsigned int offset,
struct sk_buff *skb, int linear) struct sk_buff *skb, int linear,
struct sock *sk)
{ {
if (unlikely(spd->nr_pages == PIPE_BUFFERS)) if (unlikely(spd->nr_pages == PIPE_BUFFERS))
return 1; return 1;
if (linear) { if (linear) {
page = linear_to_page(page, len, &offset, skb); page = linear_to_page(page, len, &offset, skb, sk);
if (!page) if (!page)
return 1; return 1;
} else } else
...@@ -1442,7 +1442,8 @@ static inline void __segment_seek(struct page **page, unsigned int *poff, ...@@ -1442,7 +1442,8 @@ static inline void __segment_seek(struct page **page, unsigned int *poff,
static inline int __splice_segment(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 plen, unsigned int *off,
unsigned int *len, struct sk_buff *skb, unsigned int *len, struct sk_buff *skb,
struct splice_pipe_desc *spd, int linear) struct splice_pipe_desc *spd, int linear,
struct sock *sk)
{ {
if (!*len) if (!*len)
return 1; return 1;
...@@ -1465,7 +1466,7 @@ static inline int __splice_segment(struct page *page, unsigned int poff, ...@@ -1465,7 +1466,7 @@ static inline int __splice_segment(struct page *page, unsigned int poff,
/* the linear region may spread across several pages */ /* the linear region may spread across several pages */
flen = min_t(unsigned int, flen, PAGE_SIZE - poff); flen = min_t(unsigned int, flen, PAGE_SIZE - poff);
if (spd_fill_page(spd, page, &flen, poff, skb, linear)) if (spd_fill_page(spd, page, &flen, poff, skb, linear, sk))
return 1; return 1;
__segment_seek(&page, &poff, &plen, flen); __segment_seek(&page, &poff, &plen, flen);
...@@ -1481,8 +1482,8 @@ static inline int __splice_segment(struct page *page, unsigned int poff, ...@@ -1481,8 +1482,8 @@ static inline int __splice_segment(struct page *page, unsigned int poff,
* pipe is full or if we already spliced the requested length. * pipe is full or if we already spliced the requested length.
*/ */
static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
unsigned int *len, unsigned int *len, struct splice_pipe_desc *spd,
struct splice_pipe_desc *spd) struct sock *sk)
{ {
int seg; int seg;
...@@ -1492,7 +1493,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, ...@@ -1492,7 +1493,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
if (__splice_segment(virt_to_page(skb->data), if (__splice_segment(virt_to_page(skb->data),
(unsigned long) skb->data & (PAGE_SIZE - 1), (unsigned long) skb->data & (PAGE_SIZE - 1),
skb_headlen(skb), skb_headlen(skb),
offset, len, skb, spd, 1)) offset, len, skb, spd, 1, sk))
return 1; return 1;
/* /*
...@@ -1502,7 +1503,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, ...@@ -1502,7 +1503,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
const skb_frag_t *f = &skb_shinfo(skb)->frags[seg]; const skb_frag_t *f = &skb_shinfo(skb)->frags[seg];
if (__splice_segment(f->page, f->page_offset, f->size, if (__splice_segment(f->page, f->page_offset, f->size,
offset, len, skb, spd, 0)) offset, len, skb, spd, 0, sk))
return 1; return 1;
} }
...@@ -1528,12 +1529,13 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, ...@@ -1528,12 +1529,13 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
.ops = &sock_pipe_buf_ops, .ops = &sock_pipe_buf_ops,
.spd_release = sock_spd_release, .spd_release = sock_spd_release,
}; };
struct sock *sk = skb->sk;
/* /*
* __skb_splice_bits() only fails if the output has no room left, * __skb_splice_bits() only fails if the output has no room left,
* so no point in going over the frag_list for the error case. * so no point in going over the frag_list for the error case.
*/ */
if (__skb_splice_bits(skb, &offset, &tlen, &spd)) if (__skb_splice_bits(skb, &offset, &tlen, &spd, sk))
goto done; goto done;
else if (!tlen) else if (!tlen)
goto done; goto done;
...@@ -1545,14 +1547,13 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, ...@@ -1545,14 +1547,13 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
struct sk_buff *list = skb_shinfo(skb)->frag_list; struct sk_buff *list = skb_shinfo(skb)->frag_list;
for (; list && tlen; list = list->next) { for (; list && tlen; list = list->next) {
if (__skb_splice_bits(list, &offset, &tlen, &spd)) if (__skb_splice_bits(list, &offset, &tlen, &spd, sk))
break; break;
} }
} }
done: done:
if (spd.nr_pages) { if (spd.nr_pages) {
struct sock *sk = skb->sk;
int ret; int ret;
/* /*
......
...@@ -597,16 +597,6 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb) ...@@ -597,16 +597,6 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb)
tcp_grow_window(sk, skb); tcp_grow_window(sk, skb);
} }
static u32 tcp_rto_min(struct sock *sk)
{
struct dst_entry *dst = __sk_dst_get(sk);
u32 rto_min = TCP_RTO_MIN;
if (dst && dst_metric_locked(dst, RTAX_RTO_MIN))
rto_min = dst_metric_rtt(dst, RTAX_RTO_MIN);
return rto_min;
}
/* Called to compute a smoothed rtt estimate. The data fed to this /* Called to compute a smoothed rtt estimate. The data fed to this
* routine either comes from timestamps, or from segments that were * routine either comes from timestamps, or from segments that were
* known _not_ to have been retransmitted [see Karn/Partridge * known _not_ to have been retransmitted [see Karn/Partridge
......
...@@ -757,6 +757,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, ...@@ -757,6 +757,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
local->hw.conf.long_frame_max_tx_count = 4; local->hw.conf.long_frame_max_tx_count = 4;
local->hw.conf.short_frame_max_tx_count = 7; local->hw.conf.short_frame_max_tx_count = 7;
local->hw.conf.radio_enabled = true; local->hw.conf.radio_enabled = true;
local->user_power_level = -1;
INIT_LIST_HEAD(&local->interfaces); INIT_LIST_HEAD(&local->interfaces);
mutex_init(&local->iflist_mtx); mutex_init(&local->iflist_mtx);
...@@ -909,6 +910,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -909,6 +910,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (result < 0) if (result < 0)
goto fail_sta_info; goto fail_sta_info;
result = ieee80211_wep_init(local);
if (result < 0) {
printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
wiphy_name(local->hw.wiphy), result);
goto fail_wep;
}
rtnl_lock(); rtnl_lock();
result = dev_alloc_name(local->mdev, local->mdev->name); result = dev_alloc_name(local->mdev, local->mdev->name);
if (result < 0) if (result < 0)
...@@ -930,14 +938,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -930,14 +938,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
goto fail_rate; goto fail_rate;
} }
result = ieee80211_wep_init(local);
if (result < 0) {
printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
wiphy_name(local->hw.wiphy), result);
goto fail_wep;
}
/* add one default STA interface if supported */ /* add one default STA interface if supported */
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
result = ieee80211_if_add(local, "wlan%d", NULL, result = ieee80211_if_add(local, "wlan%d", NULL,
...@@ -967,13 +967,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -967,13 +967,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
return 0; return 0;
fail_wep:
rate_control_deinitialize(local);
fail_rate: fail_rate:
unregister_netdevice(local->mdev); unregister_netdevice(local->mdev);
local->mdev = NULL; local->mdev = NULL;
fail_dev: fail_dev:
rtnl_unlock(); rtnl_unlock();
ieee80211_wep_free(local);
fail_wep:
sta_info_stop(local); sta_info_stop(local);
fail_sta_info: fail_sta_info:
debugfs_hw_del(local); debugfs_hw_del(local);
......
...@@ -837,6 +837,7 @@ config NETFILTER_XT_MATCH_SOCKET ...@@ -837,6 +837,7 @@ config NETFILTER_XT_MATCH_SOCKET
depends on NETFILTER_TPROXY depends on NETFILTER_TPROXY
depends on NETFILTER_XTABLES depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED depends on NETFILTER_ADVANCED
depends on !NF_CONNTRACK || NF_CONNTRACK
select NF_DEFRAG_IPV4 select NF_DEFRAG_IPV4
help help
This option adds a `socket' match, which can be used to match This option adds a `socket' match, which can be used to match
......
...@@ -254,7 +254,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -254,7 +254,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
} }
tp->ops = tp_ops; tp->ops = tp_ops;
tp->protocol = protocol; tp->protocol = protocol;
tp->prio = nprio ? : tcf_auto_prio(*back); tp->prio = nprio ? : TC_H_MAJ(tcf_auto_prio(*back));
tp->q = q; tp->q = q;
tp->classify = tp_ops->classify; tp->classify = tp_ops->classify;
tp->classid = parent; tp->classid = parent;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册