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() ...
This commit is contained in:
commit
80445de577
@ -1706,10 +1706,8 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
|
||||
* Called with RTNL
|
||||
*/
|
||||
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->curr_slave_lock)
|
||||
__releases(&bond->lock)
|
||||
{
|
||||
struct bonding *bond = netdev_priv(bond_dev);
|
||||
struct sockaddr *sa = 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) {
|
||||
alb_swap_mac_addr(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)
|
||||
alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
|
||||
bond->alb_info.rlb_enabled);
|
||||
|
||||
read_lock(&bond->lock);
|
||||
alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
|
||||
if (bond->alb_info.rlb_enabled) {
|
||||
/* inform clients mac address has changed */
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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 slave *slave;
|
||||
int i, found = 0;
|
||||
|
||||
if (info->slave_id < 0) {
|
||||
return -ENODEV;
|
||||
}
|
||||
int i, res = -ENODEV;
|
||||
|
||||
read_lock(&bond->lock);
|
||||
|
||||
bond_for_each_slave(bond, slave, i) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
read_unlock(&bond->lock);
|
||||
|
||||
if (found) {
|
||||
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;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*-------------------------------- Monitoring -------------------------------*/
|
||||
@ -5167,16 +5158,15 @@ int bond_create(char *name, struct bond_params *params)
|
||||
up_write(&bonding_rwsem);
|
||||
rtnl_unlock(); /* allows sysfs registration of net device */
|
||||
res = bond_create_sysfs_entry(netdev_priv(bond_dev));
|
||||
if (res < 0) {
|
||||
rtnl_lock();
|
||||
down_write(&bonding_rwsem);
|
||||
bond_deinit(bond_dev);
|
||||
unregister_netdevice(bond_dev);
|
||||
goto out_rtnl;
|
||||
}
|
||||
if (res < 0)
|
||||
goto out_unreg;
|
||||
|
||||
return 0;
|
||||
|
||||
out_unreg:
|
||||
rtnl_lock();
|
||||
down_write(&bonding_rwsem);
|
||||
unregister_netdevice(bond_dev);
|
||||
out_bond:
|
||||
bond_deinit(bond_dev);
|
||||
out_netdev:
|
||||
|
@ -3779,7 +3779,7 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
|
||||
|
||||
adapter->params.info = ai;
|
||||
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);
|
||||
/*
|
||||
* 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)
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
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 */
|
||||
|
||||
/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
|
||||
|
@ -40,7 +40,7 @@
|
||||
#include <asm/io.h>
|
||||
|
||||
#define DRV_NAME "ehea"
|
||||
#define DRV_VERSION "EHEA_0100"
|
||||
#define DRV_VERSION "EHEA_0101"
|
||||
|
||||
/* eHEA capability flags */
|
||||
#define DLPAR_PORT_ADD_REM 1
|
||||
|
@ -545,14 +545,17 @@ static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array,
|
||||
x &= (arr_len - 1);
|
||||
|
||||
pref = skb_array[x];
|
||||
prefetchw(pref);
|
||||
prefetchw(pref + EHEA_CACHE_LINE);
|
||||
if (pref) {
|
||||
prefetchw(pref);
|
||||
prefetchw(pref + EHEA_CACHE_LINE);
|
||||
|
||||
pref = (skb_array[x]->data);
|
||||
prefetch(pref);
|
||||
prefetch(pref + EHEA_CACHE_LINE);
|
||||
prefetch(pref + EHEA_CACHE_LINE * 2);
|
||||
prefetch(pref + EHEA_CACHE_LINE * 3);
|
||||
}
|
||||
|
||||
pref = (skb_array[x]->data);
|
||||
prefetch(pref);
|
||||
prefetch(pref + EHEA_CACHE_LINE);
|
||||
prefetch(pref + EHEA_CACHE_LINE * 2);
|
||||
prefetch(pref + EHEA_CACHE_LINE * 3);
|
||||
skb = skb_array[skb_index];
|
||||
skb_array[skb_index] = NULL;
|
||||
return skb;
|
||||
@ -569,12 +572,14 @@ static inline struct sk_buff *get_skb_by_index_ll(struct sk_buff **skb_array,
|
||||
x &= (arr_len - 1);
|
||||
|
||||
pref = skb_array[x];
|
||||
prefetchw(pref);
|
||||
prefetchw(pref + EHEA_CACHE_LINE);
|
||||
if (pref) {
|
||||
prefetchw(pref);
|
||||
prefetchw(pref + EHEA_CACHE_LINE);
|
||||
|
||||
pref = (skb_array[x]->data);
|
||||
prefetchw(pref);
|
||||
prefetchw(pref + EHEA_CACHE_LINE);
|
||||
pref = (skb_array[x]->data);
|
||||
prefetchw(pref);
|
||||
prefetchw(pref + EHEA_CACHE_LINE);
|
||||
}
|
||||
|
||||
skb = skb_array[wqe_index];
|
||||
skb_array[wqe_index] = NULL;
|
||||
|
@ -393,12 +393,12 @@ struct mv643xx_eth_private {
|
||||
struct work_struct tx_timeout_task;
|
||||
|
||||
struct napi_struct napi;
|
||||
u8 oom;
|
||||
u8 work_link;
|
||||
u8 work_tx;
|
||||
u8 work_tx_end;
|
||||
u8 work_rx;
|
||||
u8 work_rx_refill;
|
||||
u8 work_rx_oom;
|
||||
|
||||
int skb_size;
|
||||
struct sk_buff_head rx_recycle;
|
||||
@ -661,7 +661,7 @@ static int rxq_refill(struct rx_queue *rxq, int budget)
|
||||
dma_get_cache_alignment() - 1);
|
||||
|
||||
if (skb == NULL) {
|
||||
mp->work_rx_oom |= 1 << rxq->index;
|
||||
mp->oom = 1;
|
||||
goto oom;
|
||||
}
|
||||
|
||||
@ -1255,7 +1255,6 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
|
||||
|
||||
spin_lock_bh(&mp->mib_counters_lock);
|
||||
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->internal_mac_transmit_err += mib_read(mp, 0x0c);
|
||||
p->good_frames_received += mib_read(mp, 0x10);
|
||||
@ -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_1024_to_max_octets += mib_read(mp, 0x34);
|
||||
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->excessive_collision += mib_read(mp, 0x44);
|
||||
p->multicast_frames_sent += mib_read(mp, 0x48);
|
||||
@ -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->work_rx_refill |= mp->work_rx_oom;
|
||||
mp->work_rx_oom = 0;
|
||||
if (unlikely(mp->oom)) {
|
||||
mp->oom = 0;
|
||||
del_timer(&mp->rx_oom);
|
||||
}
|
||||
|
||||
work_done = 0;
|
||||
while (work_done < budget) {
|
||||
@ -2182,8 +2182,10 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
|
||||
continue;
|
||||
}
|
||||
|
||||
queue_mask = mp->work_tx | mp->work_tx_end |
|
||||
mp->work_rx | mp->work_rx_refill;
|
||||
queue_mask = mp->work_tx | mp->work_tx_end | mp->work_rx;
|
||||
if (likely(!mp->oom))
|
||||
queue_mask |= mp->work_rx_refill;
|
||||
|
||||
if (!queue_mask) {
|
||||
if (mv643xx_eth_collect_events(mp))
|
||||
continue;
|
||||
@ -2204,7 +2206,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
|
||||
txq_maybe_wake(mp->txq + queue);
|
||||
} else if (mp->work_rx & queue_mask) {
|
||||
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);
|
||||
} else {
|
||||
BUG();
|
||||
@ -2212,7 +2214,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
|
||||
}
|
||||
|
||||
if (work_done < budget) {
|
||||
if (mp->work_rx_oom)
|
||||
if (mp->oom)
|
||||
mod_timer(&mp->rx_oom, jiffies + (HZ / 10));
|
||||
napi_complete(napi);
|
||||
wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT);
|
||||
@ -2372,7 +2374,7 @@ static int mv643xx_eth_open(struct net_device *dev)
|
||||
rxq_refill(mp->rxq + i, INT_MAX);
|
||||
}
|
||||
|
||||
if (mp->work_rx_oom) {
|
||||
if (mp->oom) {
|
||||
mp->rx_oom.expires = jiffies + (HZ / 10);
|
||||
add_timer(&mp->rx_oom);
|
||||
}
|
||||
|
@ -374,18 +374,17 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
|
||||
dev->ethtool_ops = &ne2k_pci_ethtool_ops;
|
||||
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);
|
||||
if (i)
|
||||
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",
|
||||
dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq,
|
||||
dev->dev_addr);
|
||||
|
||||
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_free_netdev:
|
||||
|
@ -664,7 +664,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
|
||||
struct netconsole_target *nt;
|
||||
struct net_device *dev = ptr;
|
||||
|
||||
if (!(event == NETDEV_CHANGENAME))
|
||||
if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER))
|
||||
goto done;
|
||||
|
||||
spin_lock_irqsave(&target_list_lock, flags);
|
||||
@ -675,6 +675,15 @@ static int netconsole_netdev_event(struct notifier_block *this,
|
||||
case NETDEV_CHANGENAME:
|
||||
strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ);
|
||||
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);
|
||||
|
@ -180,6 +180,20 @@ config USB_NET_CDCETHER
|
||||
IEEE 802 "local assignment" bit is set in the address, a "usbX"
|
||||
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
|
||||
tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
|
||||
depends on USB_USBNET
|
||||
|
@ -9,6 +9,7 @@ obj-$(CONFIG_USB_RTL8150) += rtl8150.o
|
||||
obj-$(CONFIG_USB_HSO) += hso.o
|
||||
obj-$(CONFIG_USB_NET_AX8817X) += asix.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_SMSC95XX) += smsc95xx.o
|
||||
obj-$(CONFIG_USB_NET_GL620A) += gl620a.o
|
||||
|
381
drivers/net/usb/cdc_eem.c
Normal file
381
drivers/net/usb/cdc_eem.c
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
* 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)
|
||||
if (netif_msg_ifup(dev))
|
||||
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 */
|
||||
write_buf = 0;
|
||||
ret = smsc95xx_write_reg(dev, FLOW, write_buf);
|
||||
@ -1231,6 +1241,11 @@ static const struct usb_device_id products[] = {
|
||||
USB_DEVICE(0x0424, 0x9500),
|
||||
.driver_info = (unsigned long) &smsc95xx_info,
|
||||
},
|
||||
{
|
||||
/* SMSC9512/9514 USB Hub & Ethernet Device */
|
||||
USB_DEVICE(0x0424, 0xec00),
|
||||
.driver_info = (unsigned long) &smsc95xx_info,
|
||||
},
|
||||
{ }, /* END */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, products);
|
||||
|
@ -99,6 +99,9 @@
|
||||
#define PM_CTL_WUPS_MULTI_ (0x00000003)
|
||||
|
||||
#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)
|
||||
|
||||
|
@ -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,
|
||||
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;
|
||||
virtio_net_ctrl_ack status = ~0;
|
||||
unsigned int tmp;
|
||||
int i;
|
||||
|
||||
if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
|
||||
BUG(); /* Caller should know better */
|
||||
@ -637,7 +638,8 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
|
||||
sg_init_table(sg, out + in);
|
||||
|
||||
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));
|
||||
|
||||
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)
|
||||
promisc = ((dev->flags & IFF_PROMISC) != 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,
|
||||
VIRTIO_NET_CTRL_RX_PROMISC,
|
||||
@ -700,7 +702,7 @@ static void virtnet_set_rx_mode(struct net_device *dev)
|
||||
dev_warn(&dev->dev, "Failed to %sable promisc mode.\n",
|
||||
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,
|
||||
VIRTIO_NET_CTRL_RX_ALLMULTI,
|
||||
@ -716,6 +718,8 @@ static void virtnet_set_rx_mode(struct net_device *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
sg_init_table(sg, 2);
|
||||
|
||||
/* Store the unicast list and count in the front of the buffer */
|
||||
mac_data->entries = dev->uc_count;
|
||||
addr = dev->uc_list;
|
||||
@ -744,24 +748,24 @@ static void virtnet_set_rx_mode(struct net_device *dev)
|
||||
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 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,
|
||||
VIRTIO_NET_CTRL_VLAN_ADD, &sg, 1, 0))
|
||||
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 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,
|
||||
VIRTIO_NET_CTRL_VLAN_DEL, &sg, 1, 0))
|
||||
@ -794,8 +798,8 @@ static const struct net_device_ops virtnet_netdev = {
|
||||
.ndo_set_mac_address = virtnet_set_mac_address,
|
||||
.ndo_set_rx_mode = virtnet_set_rx_mode,
|
||||
.ndo_change_mtu = virtnet_change_mtu,
|
||||
.ndo_vlan_rx_add_vid = virnet_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = virnet_vlan_rx_kill_vid,
|
||||
.ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = virtnet_netpoll,
|
||||
#endif
|
||||
|
@ -424,7 +424,7 @@ ath5k_debug_dump_bands(struct ath5k_softc *sc)
|
||||
|
||||
for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
|
||||
struct ieee80211_supported_band *band = &sc->sbands[b];
|
||||
char bname[5];
|
||||
char bname[6];
|
||||
switch (band->band) {
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
strcpy(bname, "2 GHz");
|
||||
|
@ -925,11 +925,11 @@ void iwl_bg_scan_completed(struct work_struct *work)
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
|
||||
|
||||
ieee80211_scan_completed(priv->hw, false);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
ieee80211_scan_completed(priv->hw, false);
|
||||
|
||||
/* Since setting the TXPOWER may have been deferred while
|
||||
* performing the scan, fire one off */
|
||||
mutex_lock(&priv->mutex);
|
||||
|
@ -1694,7 +1694,6 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
|
||||
rxq->free_count = 0;
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl3945_rx_queue_reset);
|
||||
|
||||
/*
|
||||
* 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)
|
||||
mutex_init(&priv->command_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 */
|
||||
retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS);
|
||||
if (retval < 0)
|
||||
@ -2603,16 +2608,17 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
|
||||
disassociate(usbdev, 1);
|
||||
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,
|
||||
round_jiffies_relative(STATS_UPDATE_JIFFIES));
|
||||
INIT_WORK(&priv->work, rndis_wext_worker);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
cancel_delayed_work_sync(&priv->stats_work);
|
||||
cancel_work_sync(&priv->work);
|
||||
flush_workqueue(priv->workqueue);
|
||||
destroy_workqueue(priv->workqueue);
|
||||
|
||||
kfree(priv);
|
||||
return retval;
|
||||
}
|
||||
|
@ -472,7 +472,7 @@ static inline void xt_info_rdlock_bh(void)
|
||||
|
||||
local_bh_disable();
|
||||
lock = &__get_cpu_var(xt_info_locks);
|
||||
if (!lock->readers++)
|
||||
if (likely(!lock->readers++))
|
||||
spin_lock(&lock->lock);
|
||||
}
|
||||
|
||||
@ -480,7 +480,7 @@ static inline void xt_info_rdunlock_bh(void)
|
||||
{
|
||||
struct xt_info_lock *lock = &__get_cpu_var(xt_info_locks);
|
||||
|
||||
if (!--lock->readers)
|
||||
if (likely(!--lock->readers))
|
||||
spin_unlock(&lock->lock);
|
||||
local_bh_enable();
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define USB_CDC_SUBCLASS_DMM 0x09
|
||||
#define USB_CDC_SUBCLASS_MDLM 0x0a
|
||||
#define USB_CDC_SUBCLASS_OBEX 0x0b
|
||||
#define USB_CDC_SUBCLASS_EEM 0x0c
|
||||
|
||||
#define USB_CDC_PROTO_NONE 0
|
||||
|
||||
@ -28,6 +29,8 @@
|
||||
#define USB_CDC_ACM_PROTO_AT_CDMA 6
|
||||
#define USB_CDC_ACM_PROTO_VENDOR 0xff
|
||||
|
||||
#define USB_CDC_PROTO_EEM 7
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
@ -4,6 +4,7 @@
|
||||
* compatible drivers/servers. */
|
||||
#include <linux/types.h>
|
||||
#include <linux/virtio_config.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
/* The ID for virtio_net */
|
||||
#define VIRTIO_ID_NET 1
|
||||
|
@ -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);
|
||||
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_del_sysfs(struct hci_conn *conn);
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <net/ip.h>
|
||||
#include <net/tcp_states.h>
|
||||
#include <net/inet_ecn.h>
|
||||
#include <net/dst.h>
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
@ -530,6 +531,17 @@ static inline void tcp_fast_path_check(struct sock *sk)
|
||||
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.
|
||||
* Rcv_nxt can be after the window if our peer push more data
|
||||
* than the offered window.
|
||||
@ -895,7 +907,7 @@ static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb)
|
||||
wake_up_interruptible(sk->sk_sleep);
|
||||
if (!inet_csk_ack_scheduled(sk))
|
||||
inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
|
||||
(3 * TCP_RTO_MIN) / 4,
|
||||
(3 * tcp_rto_min(sk)) / 4,
|
||||
TCP_RTO_MAX);
|
||||
}
|
||||
return 1;
|
||||
|
@ -549,6 +549,7 @@ static void br2684_setup(struct net_device *netdev)
|
||||
struct br2684_dev *brdev = BRPRIV(netdev);
|
||||
|
||||
ether_setup(netdev);
|
||||
brdev->net_dev = netdev;
|
||||
|
||||
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)
|
||||
if (hdev->notify)
|
||||
hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
|
||||
|
||||
hci_conn_init_sysfs(conn);
|
||||
|
||||
tasklet_enable(&hdev->tx_task);
|
||||
|
||||
return conn;
|
||||
|
@ -9,7 +9,7 @@
|
||||
struct class *bt_class = NULL;
|
||||
EXPORT_SYMBOL_GPL(bt_class);
|
||||
|
||||
static struct workqueue_struct *bluetooth;
|
||||
static struct workqueue_struct *bt_workq;
|
||||
|
||||
static inline char *link_typetostr(int type)
|
||||
{
|
||||
@ -89,8 +89,8 @@ static void add_conn(struct work_struct *work)
|
||||
{
|
||||
struct hci_conn *conn = container_of(work, struct hci_conn, work_add);
|
||||
|
||||
/* ensure previous add/del is complete */
|
||||
flush_workqueue(bluetooth);
|
||||
/* ensure previous del is complete */
|
||||
flush_work(&conn->work_del);
|
||||
|
||||
if (device_add(&conn->dev) < 0) {
|
||||
BT_ERR("Failed to register connection device");
|
||||
@ -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
|
||||
* is down, and sysfs doesn't support move zombie device,
|
||||
@ -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_dev *hdev = conn->hdev;
|
||||
|
||||
/* ensure previous add/del is complete */
|
||||
flush_workqueue(bluetooth);
|
||||
/* ensure previous add is complete */
|
||||
flush_work(&conn->work_add);
|
||||
|
||||
if (!device_is_registered(&conn->dev))
|
||||
return;
|
||||
|
||||
while (1) {
|
||||
struct device *dev;
|
||||
@ -152,16 +134,40 @@ static void del_conn(struct work_struct *work)
|
||||
hci_dev_put(hdev);
|
||||
}
|
||||
|
||||
void hci_conn_init_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_drvdata(&conn->dev, conn);
|
||||
|
||||
device_initialize(&conn->dev);
|
||||
|
||||
INIT_WORK(&conn->work_add, add_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);
|
||||
|
||||
if (!device_is_registered(&conn->dev))
|
||||
return;
|
||||
|
||||
INIT_WORK(&conn->work_del, del_conn);
|
||||
|
||||
queue_work(bluetooth, &conn->work_del);
|
||||
queue_work(bt_workq, &conn->work_del);
|
||||
}
|
||||
|
||||
static inline char *host_typetostr(int type)
|
||||
@ -438,13 +444,13 @@ void hci_unregister_sysfs(struct hci_dev *hdev)
|
||||
|
||||
int __init bt_sysfs_init(void)
|
||||
{
|
||||
bluetooth = create_singlethread_workqueue("bluetooth");
|
||||
if (!bluetooth)
|
||||
bt_workq = create_singlethread_workqueue("bluetooth");
|
||||
if (!bt_workq)
|
||||
return -ENOMEM;
|
||||
|
||||
bt_class = class_create(THIS_MODULE, "bluetooth");
|
||||
if (IS_ERR(bt_class)) {
|
||||
destroy_workqueue(bluetooth);
|
||||
destroy_workqueue(bt_workq);
|
||||
return PTR_ERR(bt_class);
|
||||
}
|
||||
|
||||
@ -453,7 +459,7 @@ int __init bt_sysfs_init(void)
|
||||
|
||||
void bt_sysfs_cleanup(void)
|
||||
{
|
||||
destroy_workqueue(bluetooth);
|
||||
destroy_workqueue(bt_workq);
|
||||
|
||||
class_destroy(bt_class);
|
||||
}
|
||||
|
@ -1735,11 +1735,12 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb)
|
||||
{
|
||||
u32 hash;
|
||||
|
||||
if (skb_rx_queue_recorded(skb)) {
|
||||
hash = skb_get_rx_queue(skb);
|
||||
} else if (skb->sk && skb->sk->sk_hash) {
|
||||
if (skb_rx_queue_recorded(skb))
|
||||
return skb_get_rx_queue(skb) % dev->real_num_tx_queues;
|
||||
|
||||
if (skb->sk && skb->sk->sk_hash)
|
||||
hash = skb->sk->sk_hash;
|
||||
} else
|
||||
else
|
||||
hash = skb->protocol;
|
||||
|
||||
hash = jhash_1word(hash, skb_tx_hashrnd);
|
||||
|
@ -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,
|
||||
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;
|
||||
unsigned int off;
|
||||
|
||||
@ -1405,13 +1404,14 @@ new_page:
|
||||
*/
|
||||
static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page,
|
||||
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))
|
||||
return 1;
|
||||
|
||||
if (linear) {
|
||||
page = linear_to_page(page, len, &offset, skb);
|
||||
page = linear_to_page(page, len, &offset, skb, sk);
|
||||
if (!page)
|
||||
return 1;
|
||||
} else
|
||||
@ -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,
|
||||
unsigned int plen, unsigned int *off,
|
||||
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)
|
||||
return 1;
|
||||
@ -1465,7 +1466,7 @@ static inline int __splice_segment(struct page *page, unsigned int poff,
|
||||
/* the linear region may spread across several pages */
|
||||
flen = min_t(unsigned int, flen, PAGE_SIZE - poff);
|
||||
|
||||
if (spd_fill_page(spd, page, &flen, poff, skb, linear))
|
||||
if (spd_fill_page(spd, page, &flen, poff, skb, linear, sk))
|
||||
return 1;
|
||||
|
||||
__segment_seek(&page, &poff, &plen, flen);
|
||||
@ -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.
|
||||
*/
|
||||
static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
|
||||
unsigned int *len,
|
||||
struct splice_pipe_desc *spd)
|
||||
unsigned int *len, struct splice_pipe_desc *spd,
|
||||
struct sock *sk)
|
||||
{
|
||||
int seg;
|
||||
|
||||
@ -1492,7 +1493,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
|
||||
if (__splice_segment(virt_to_page(skb->data),
|
||||
(unsigned long) skb->data & (PAGE_SIZE - 1),
|
||||
skb_headlen(skb),
|
||||
offset, len, skb, spd, 1))
|
||||
offset, len, skb, spd, 1, sk))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
@ -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];
|
||||
|
||||
if (__splice_segment(f->page, f->page_offset, f->size,
|
||||
offset, len, skb, spd, 0))
|
||||
offset, len, skb, spd, 0, sk))
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1528,12 +1529,13 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
|
||||
.ops = &sock_pipe_buf_ops,
|
||||
.spd_release = sock_spd_release,
|
||||
};
|
||||
struct sock *sk = skb->sk;
|
||||
|
||||
/*
|
||||
* __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.
|
||||
*/
|
||||
if (__skb_splice_bits(skb, &offset, &tlen, &spd))
|
||||
if (__skb_splice_bits(skb, &offset, &tlen, &spd, sk))
|
||||
goto done;
|
||||
else if (!tlen)
|
||||
goto done;
|
||||
@ -1545,14 +1547,13 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
|
||||
struct sk_buff *list = skb_shinfo(skb)->frag_list;
|
||||
|
||||
for (; list && tlen; list = list->next) {
|
||||
if (__skb_splice_bits(list, &offset, &tlen, &spd))
|
||||
if (__skb_splice_bits(list, &offset, &tlen, &spd, sk))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (spd.nr_pages) {
|
||||
struct sock *sk = skb->sk;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
@ -597,16 +597,6 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *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
|
||||
* routine either comes from timestamps, or from segments that were
|
||||
* known _not_ to have been retransmitted [see Karn/Partridge
|
||||
|
@ -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.short_frame_max_tx_count = 7;
|
||||
local->hw.conf.radio_enabled = true;
|
||||
local->user_power_level = -1;
|
||||
|
||||
INIT_LIST_HEAD(&local->interfaces);
|
||||
mutex_init(&local->iflist_mtx);
|
||||
@ -909,6 +910,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
if (result < 0)
|
||||
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();
|
||||
result = dev_alloc_name(local->mdev, local->mdev->name);
|
||||
if (result < 0)
|
||||
@ -930,14 +938,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
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 */
|
||||
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
|
||||
result = ieee80211_if_add(local, "wlan%d", NULL,
|
||||
@ -967,13 +967,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
|
||||
return 0;
|
||||
|
||||
fail_wep:
|
||||
rate_control_deinitialize(local);
|
||||
fail_rate:
|
||||
unregister_netdevice(local->mdev);
|
||||
local->mdev = NULL;
|
||||
fail_dev:
|
||||
rtnl_unlock();
|
||||
ieee80211_wep_free(local);
|
||||
fail_wep:
|
||||
sta_info_stop(local);
|
||||
fail_sta_info:
|
||||
debugfs_hw_del(local);
|
||||
|
@ -837,6 +837,7 @@ config NETFILTER_XT_MATCH_SOCKET
|
||||
depends on NETFILTER_TPROXY
|
||||
depends on NETFILTER_XTABLES
|
||||
depends on NETFILTER_ADVANCED
|
||||
depends on !NF_CONNTRACK || NF_CONNTRACK
|
||||
select NF_DEFRAG_IPV4
|
||||
help
|
||||
This option adds a `socket' match, which can be used to match
|
||||
|
@ -254,7 +254,7 @@ replay:
|
||||
}
|
||||
tp->ops = tp_ops;
|
||||
tp->protocol = protocol;
|
||||
tp->prio = nprio ? : tcf_auto_prio(*back);
|
||||
tp->prio = nprio ? : TC_H_MAJ(tcf_auto_prio(*back));
|
||||
tp->q = q;
|
||||
tp->classify = tp_ops->classify;
|
||||
tp->classid = parent;
|
||||
|
Loading…
Reference in New Issue
Block a user