Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

Pull networking fixes from David Miller:

 1) Fix ARM BPF JIT handling of negative 'k' values, from Chen Gang.

 2) Insufficient space reserved for bridge netlink values, fix from
    Stephen Hemminger.

 3) Some dst_neigh_lookup*() callers don't interpret error pointer
    correctly, fix from Zhouyi Zhou.

 4) Fix transport match in SCTP active_path loops, from Xugeng Zhang.

 5) Fix qeth driver handling of multi-order SKB frags, from Frank
    Blaschka.

 6) fec driver is missing napi_disable() call, resulting in crashes on
    unload, from Georg Hofmann.

 7) Don't try to handle PMTU events on a listening socket, fix from Eric
    Dumazet.

 8) Fix timestamp location calculations in IP option processing, from
    David Ward.

 9) FIB_TABLE_HASHSZ setting is not controlled by the correct kconfig
    tests, from Denis V Lunev.

10) Fix TX descriptor push handling in SFC driver, from Ben Hutchings.

11) Fix isdn/hisax and tulip/de4x5 kconfig dependencies, from Arnd
    Bergmann.

12) bnx2x statistics don't handle 4GB rollover correctly, fix from
    Maciej Żenczykowski.

13) Openvswitch bug fixes for vport del/new error reporting, missing
    genlmsg_end() call in netlink processing, and mis-parsing of
    LLC/SNAP ethernet types.  From Rich Lane.

14) SKB pfmemalloc state should only be propagated from the head page of
    a compound page, fix from Pavel Emelyanov.

15) Fix link handling in tg3 driver for 5715 chips when autonegotation
    is disabled.  From Nithin Sujir.

16) Fix inverted test of cpdma_check_free_tx_desc return value in
    davinci_emac driver, from Mugunthan V N.

17) vlan_depth is incorrectly calculated in skb_network_protocol(), from
    Li RongQing.

18) Fix probing of Gobi 1K devices in qmi_wwan driver, and fix NCM
    device mode backwards compat in cdc_ncm driver.  From Bjørn Mork.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (52 commits)
  inet: limit length of fragment queue hash table bucket lists
  qeth: Fix scatter-gather regression
  qeth: Fix invalid router settings handling
  qeth: delay feature trace
  tcp: dont handle MTU reduction on LISTEN socket
  bnx2x: fix occasional statistics off-by-4GB error
  vhost/net: fix heads usage of ubuf_info
  bridge: Add support for setting BR_ROOT_BLOCK flag.
  bnx2x: add missing napi deletion in error path
  drivers: net: ethernet: ti: davinci_emac: fix usage of cpdma_check_free_tx_desc()
  ethernet/tulip: DE4x5 needs VIRT_TO_BUS
  isdn: hisax: netjet requires VIRT_TO_BUS
  net: cdc_ncm, cdc_mbim: allow user to prefer NCM for backwards compatibility
  rtnetlink: Mask the rta_type when range checking
  Revert "ip_gre: make ipgre_tunnel_xmit() not parse network header as IP unconditionally"
  Fix dst_neigh_lookup/dst_neigh_lookup_skb return value handling bug
  smsc75xx: configuration help incorrectly mentions smsc95xx
  net: fec: fix missing napi_disable call
  net: fec: restart the FEC when PHY speed changes
  skb: Propagate pfmemalloc on skb from head page only
  ...
This commit is contained in:
Linus Torvalds 2013-03-19 13:20:51 -07:00
commit 7b1b3fd74e
58 changed files with 396 additions and 253 deletions

View File

@ -576,7 +576,7 @@ load_ind:
/* x = ((*(frame + k)) & 0xf) << 2; */ /* x = ((*(frame + k)) & 0xf) << 2; */
ctx->seen |= SEEN_X | SEEN_DATA | SEEN_CALL; ctx->seen |= SEEN_X | SEEN_DATA | SEEN_CALL;
/* the interpreter should deal with the negative K */ /* the interpreter should deal with the negative K */
if (k < 0) if ((int)k < 0)
return -1; return -1;
/* offset in r1: we might have to take the slow path */ /* offset in r1: we might have to take the slow path */
emit_mov_i(r_off, k, ctx); emit_mov_i(r_off, k, ctx);

View File

@ -74,8 +74,10 @@ static struct usb_device_id ath3k_table[] = {
/* Atheros AR3012 with sflash firmware*/ /* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0CF3, 0x3004) }, { USB_DEVICE(0x0CF3, 0x3004) },
{ USB_DEVICE(0x0CF3, 0x3008) },
{ USB_DEVICE(0x0CF3, 0x311D) }, { USB_DEVICE(0x0CF3, 0x311D) },
{ USB_DEVICE(0x13d3, 0x3375) }, { USB_DEVICE(0x13d3, 0x3375) },
{ USB_DEVICE(0x04CA, 0x3004) },
{ USB_DEVICE(0x04CA, 0x3005) }, { USB_DEVICE(0x04CA, 0x3005) },
{ USB_DEVICE(0x04CA, 0x3006) }, { USB_DEVICE(0x04CA, 0x3006) },
{ USB_DEVICE(0x04CA, 0x3008) }, { USB_DEVICE(0x04CA, 0x3008) },
@ -106,8 +108,10 @@ static struct usb_device_id ath3k_blist_tbl[] = {
/* Atheros AR3012 with sflash firmware*/ /* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },

View File

@ -132,8 +132,10 @@ static struct usb_device_id blacklist_table[] = {
/* Atheros 3012 with sflash firmware */ /* Atheros 3012 with sflash firmware */
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },

View File

@ -1575,6 +1575,12 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
neigh = dst_neigh_lookup(ep->dst, neigh = dst_neigh_lookup(ep->dst,
&ep->com.cm_id->remote_addr.sin_addr.s_addr); &ep->com.cm_id->remote_addr.sin_addr.s_addr);
if (!neigh) {
pr_err("%s - cannot alloc neigh.\n", __func__);
err = -ENOMEM;
goto fail4;
}
/* get a l2t entry */ /* get a l2t entry */
if (neigh->dev->flags & IFF_LOOPBACK) { if (neigh->dev->flags & IFF_LOOPBACK) {
PDBG("%s LOOPBACK\n", __func__); PDBG("%s LOOPBACK\n", __func__);
@ -3053,6 +3059,12 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
dst = &rt->dst; dst = &rt->dst;
neigh = dst_neigh_lookup_skb(dst, skb); neigh = dst_neigh_lookup_skb(dst, skb);
if (!neigh) {
pr_err("%s - failed to allocate neigh!\n",
__func__);
goto free_dst;
}
if (neigh->dev->flags & IFF_LOOPBACK) { if (neigh->dev->flags & IFF_LOOPBACK) {
pdev = ip_dev_find(&init_net, iph->daddr); pdev = ip_dev_find(&init_net, iph->daddr);
e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh,

View File

@ -237,7 +237,8 @@ config HISAX_MIC
config HISAX_NETJET config HISAX_NETJET
bool "NETjet card" bool "NETjet card"
depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN))) depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
depends on VIRT_TO_BUS
help help
This enables HiSax support for the NetJet from Traverse This enables HiSax support for the NetJet from Traverse
Technologies. Technologies.
@ -248,7 +249,8 @@ config HISAX_NETJET
config HISAX_NETJET_U config HISAX_NETJET_U
bool "NETspider U card" bool "NETspider U card"
depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN))) depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
depends on VIRT_TO_BUS
help help
This enables HiSax support for the Netspider U interface ISDN card This enables HiSax support for the Netspider U interface ISDN card
from Traverse Technologies. from Traverse Technologies.

View File

@ -1746,6 +1746,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond_compute_features(bond); bond_compute_features(bond);
bond_update_speed_duplex(new_slave);
read_lock(&bond->lock); read_lock(&bond->lock);
new_slave->last_arp_rx = jiffies - new_slave->last_arp_rx = jiffies -
@ -1798,8 +1800,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
new_slave->link == BOND_LINK_DOWN ? "DOWN" : new_slave->link == BOND_LINK_DOWN ? "DOWN" :
(new_slave->link == BOND_LINK_UP ? "UP" : "BACK")); (new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
bond_update_speed_duplex(new_slave);
if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) { if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
/* if there is a primary slave, remember it */ /* if there is a primary slave, remember it */
if (strcmp(bond->params.primary, new_slave->dev->name) == 0) { if (strcmp(bond->params.primary, new_slave->dev->name) == 0) {
@ -2374,8 +2374,6 @@ static void bond_miimon_commit(struct bonding *bond)
bond_set_backup_slave(slave); bond_set_backup_slave(slave);
} }
bond_update_speed_duplex(slave);
pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n", pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n",
bond->dev->name, slave->dev->name, bond->dev->name, slave->dev->name,
slave->speed, slave->duplex ? "full" : "half"); slave->speed, slave->duplex ? "full" : "half");

View File

@ -2760,6 +2760,7 @@ load_error2:
bp->port.pmf = 0; bp->port.pmf = 0;
load_error1: load_error1:
bnx2x_napi_disable(bp); bnx2x_napi_disable(bp);
bnx2x_del_all_napi(bp);
/* clear pf_load status, as it was already set */ /* clear pf_load status, as it was already set */
if (IS_PF(bp)) if (IS_PF(bp))

View File

@ -459,8 +459,9 @@ struct bnx2x_fw_port_stats_old {
#define UPDATE_QSTAT(s, t) \ #define UPDATE_QSTAT(s, t) \
do { \ do { \
qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi); \
qstats->t##_lo = qstats_old->t##_lo + le32_to_cpu(s.lo); \ qstats->t##_lo = qstats_old->t##_lo + le32_to_cpu(s.lo); \
qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi) \
+ ((qstats->t##_lo < qstats_old->t##_lo) ? 1 : 0); \
} while (0) } while (0)
#define UPDATE_QSTAT_OLD(f) \ #define UPDATE_QSTAT_OLD(f) \

View File

@ -4130,6 +4130,14 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
tp->link_config.active_speed = tp->link_config.speed; tp->link_config.active_speed = tp->link_config.speed;
tp->link_config.active_duplex = tp->link_config.duplex; tp->link_config.active_duplex = tp->link_config.duplex;
if (tg3_asic_rev(tp) == ASIC_REV_5714) {
/* With autoneg disabled, 5715 only links up when the
* advertisement register has the configured speed
* enabled.
*/
tg3_writephy(tp, MII_ADVERTISE, ADVERTISE_ALL);
}
bmcr = 0; bmcr = 0;
switch (tp->link_config.speed) { switch (tp->link_config.speed) {
default: default:

View File

@ -497,8 +497,9 @@ int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len,
} }
#define EEPROM_STAT_ADDR 0x7bfc #define EEPROM_STAT_ADDR 0x7bfc
#define VPD_BASE 0
#define VPD_LEN 512 #define VPD_LEN 512
#define VPD_BASE 0x400
#define VPD_BASE_OLD 0
/** /**
* t4_seeprom_wp - enable/disable EEPROM write protection * t4_seeprom_wp - enable/disable EEPROM write protection
@ -524,7 +525,7 @@ int t4_seeprom_wp(struct adapter *adapter, bool enable)
int get_vpd_params(struct adapter *adapter, struct vpd_params *p) int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
{ {
u32 cclk_param, cclk_val; u32 cclk_param, cclk_val;
int i, ret; int i, ret, addr;
int ec, sn; int ec, sn;
u8 *vpd, csum; u8 *vpd, csum;
unsigned int vpdr_len, kw_offset, id_len; unsigned int vpdr_len, kw_offset, id_len;
@ -533,7 +534,12 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
if (!vpd) if (!vpd)
return -ENOMEM; return -ENOMEM;
ret = pci_read_vpd(adapter->pdev, VPD_BASE, VPD_LEN, vpd); ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(u32), vpd);
if (ret < 0)
goto out;
addr = *vpd == 0x82 ? VPD_BASE : VPD_BASE_OLD;
ret = pci_read_vpd(adapter->pdev, addr, VPD_LEN, vpd);
if (ret < 0) if (ret < 0)
goto out; goto out;

View File

@ -108,6 +108,7 @@ config TULIP_DM910X
config DE4X5 config DE4X5
tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA" tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA"
depends on (PCI || EISA) depends on (PCI || EISA)
depends on VIRT_TO_BUS || ALPHA || PPC || SPARC
select CRC32 select CRC32
---help--- ---help---
This is support for the DIGITAL series of PCI/EISA Ethernet cards. This is support for the DIGITAL series of PCI/EISA Ethernet cards.

View File

@ -934,24 +934,28 @@ static void fec_enet_adjust_link(struct net_device *ndev)
goto spin_unlock; goto spin_unlock;
} }
/* Duplex link change */
if (phy_dev->link) { if (phy_dev->link) {
if (fep->full_duplex != phy_dev->duplex) { if (!fep->link) {
fec_restart(ndev, phy_dev->duplex);
/* prevent unnecessary second fec_restart() below */
fep->link = phy_dev->link; fep->link = phy_dev->link;
status_change = 1; status_change = 1;
} }
}
/* Link on or off change */ if (fep->full_duplex != phy_dev->duplex)
if (phy_dev->link != fep->link) { status_change = 1;
fep->link = phy_dev->link;
if (phy_dev->link) if (phy_dev->speed != fep->speed) {
fep->speed = phy_dev->speed;
status_change = 1;
}
/* if any of the above changed restart the FEC */
if (status_change)
fec_restart(ndev, phy_dev->duplex); fec_restart(ndev, phy_dev->duplex);
else } else {
if (fep->link) {
fec_stop(ndev); fec_stop(ndev);
status_change = 1; status_change = 1;
}
} }
spin_unlock: spin_unlock:
@ -1437,6 +1441,7 @@ fec_enet_close(struct net_device *ndev)
struct fec_enet_private *fep = netdev_priv(ndev); struct fec_enet_private *fep = netdev_priv(ndev);
/* Don't know what to do yet. */ /* Don't know what to do yet. */
napi_disable(&fep->napi);
fep->opened = 0; fep->opened = 0;
netif_stop_queue(ndev); netif_stop_queue(ndev);
fec_stop(ndev); fec_stop(ndev);

View File

@ -240,6 +240,7 @@ struct fec_enet_private {
phy_interface_t phy_interface; phy_interface_t phy_interface;
int link; int link;
int full_duplex; int full_duplex;
int speed;
struct completion mdio_done; struct completion mdio_done;
int irq[FEC_IRQ_NUM]; int irq[FEC_IRQ_NUM];
int bufdesc_ex; int bufdesc_ex;

View File

@ -376,7 +376,8 @@ efx_may_push_tx_desc(struct efx_tx_queue *tx_queue, unsigned int write_count)
return false; return false;
tx_queue->empty_read_count = 0; tx_queue->empty_read_count = 0;
return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0; return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0
&& tx_queue->write_count - write_count == 1;
} }
/* For each entry inserted into the software descriptor ring, create a /* For each entry inserted into the software descriptor ring, create a

View File

@ -905,7 +905,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
/* If there is no more tx desc left free then we need to /* If there is no more tx desc left free then we need to
* tell the kernel to stop sending us tx frames. * tell the kernel to stop sending us tx frames.
*/ */
if (unlikely(cpdma_check_free_tx_desc(priv->txch))) if (unlikely(!cpdma_check_free_tx_desc(priv->txch)))
netif_stop_queue(ndev); netif_stop_queue(ndev);
return NETDEV_TX_OK; return NETDEV_TX_OK;

View File

@ -1102,7 +1102,7 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
/* If there is no more tx desc left free then we need to /* If there is no more tx desc left free then we need to
* tell the kernel to stop sending us tx frames. * tell the kernel to stop sending us tx frames.
*/ */
if (unlikely(cpdma_check_free_tx_desc(priv->txchan))) if (unlikely(!cpdma_check_free_tx_desc(priv->txchan)))
netif_stop_queue(ndev); netif_stop_queue(ndev);
return NETDEV_TX_OK; return NETDEV_TX_OK;

View File

@ -666,6 +666,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
goto done; goto done;
spin_lock_irqsave(&target_list_lock, flags); spin_lock_irqsave(&target_list_lock, flags);
restart:
list_for_each_entry(nt, &target_list, list) { list_for_each_entry(nt, &target_list, list) {
netconsole_target_get(nt); netconsole_target_get(nt);
if (nt->np.dev == dev) { if (nt->np.dev == dev) {
@ -678,15 +679,17 @@ static int netconsole_netdev_event(struct notifier_block *this,
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
/* /*
* rtnl_lock already held * rtnl_lock already held
* we might sleep in __netpoll_cleanup()
*/ */
if (nt->np.dev) { spin_unlock_irqrestore(&target_list_lock, flags);
__netpoll_cleanup(&nt->np); __netpoll_cleanup(&nt->np);
dev_put(nt->np.dev); spin_lock_irqsave(&target_list_lock, flags);
nt->np.dev = NULL; dev_put(nt->np.dev);
} nt->np.dev = NULL;
nt->enabled = 0; nt->enabled = 0;
stopped = true; stopped = true;
break; netconsole_target_put(nt);
goto restart;
} }
} }
netconsole_target_put(nt); netconsole_target_put(nt);

View File

@ -268,7 +268,7 @@ config USB_NET_SMSC75XX
select CRC16 select CRC16
select CRC32 select CRC32
help help
This option adds support for SMSC LAN95XX based USB 2.0 This option adds support for SMSC LAN75XX based USB 2.0
Gigabit Ethernet adapters. Gigabit Ethernet adapters.
config USB_NET_SMSC95XX config USB_NET_SMSC95XX

View File

@ -68,18 +68,9 @@ static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
struct cdc_ncm_ctx *ctx; struct cdc_ncm_ctx *ctx;
struct usb_driver *subdriver = ERR_PTR(-ENODEV); struct usb_driver *subdriver = ERR_PTR(-ENODEV);
int ret = -ENODEV; int ret = -ENODEV;
u8 data_altsetting = CDC_NCM_DATA_ALTSETTING_NCM; u8 data_altsetting = cdc_ncm_select_altsetting(dev, intf);
struct cdc_mbim_state *info = (void *)&dev->data; struct cdc_mbim_state *info = (void *)&dev->data;
/* see if interface supports MBIM alternate setting */
if (intf->num_altsetting == 2) {
if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
usb_set_interface(dev->udev,
intf->cur_altsetting->desc.bInterfaceNumber,
CDC_NCM_COMM_ALTSETTING_MBIM);
data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM;
}
/* Probably NCM, defer for cdc_ncm_bind */ /* Probably NCM, defer for cdc_ncm_bind */
if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
goto err; goto err;

View File

@ -55,6 +55,14 @@
#define DRIVER_VERSION "14-Mar-2012" #define DRIVER_VERSION "14-Mar-2012"
#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
static bool prefer_mbim = true;
#else
static bool prefer_mbim;
#endif
module_param(prefer_mbim, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(prefer_mbim, "Prefer MBIM setting on dual NCM/MBIM functions");
static void cdc_ncm_txpath_bh(unsigned long param); static void cdc_ncm_txpath_bh(unsigned long param);
static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx); static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer); static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
@ -550,9 +558,12 @@ void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
} }
EXPORT_SYMBOL_GPL(cdc_ncm_unbind); EXPORT_SYMBOL_GPL(cdc_ncm_unbind);
static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) /* Select the MBIM altsetting iff it is preferred and available,
* returning the number of the corresponding data interface altsetting
*/
u8 cdc_ncm_select_altsetting(struct usbnet *dev, struct usb_interface *intf)
{ {
int ret; struct usb_host_interface *alt;
/* The MBIM spec defines a NCM compatible default altsetting, /* The MBIM spec defines a NCM compatible default altsetting,
* which we may have matched: * which we may have matched:
@ -568,23 +579,27 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
* endpoint descriptors, shall be constructed according to * endpoint descriptors, shall be constructed according to
* the rules given in section 6 (USB Device Model) of this * the rules given in section 6 (USB Device Model) of this
* specification." * specification."
*
* Do not bind to such interfaces, allowing cdc_mbim to handle
* them
*/ */
#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM) if (prefer_mbim && intf->num_altsetting == 2) {
if ((intf->num_altsetting == 2) && alt = usb_altnum_to_altsetting(intf, CDC_NCM_COMM_ALTSETTING_MBIM);
!usb_set_interface(dev->udev, if (alt && cdc_ncm_comm_intf_is_mbim(alt) &&
intf->cur_altsetting->desc.bInterfaceNumber, !usb_set_interface(dev->udev,
CDC_NCM_COMM_ALTSETTING_MBIM)) { intf->cur_altsetting->desc.bInterfaceNumber,
if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) CDC_NCM_COMM_ALTSETTING_MBIM))
return -ENODEV; return CDC_NCM_DATA_ALTSETTING_MBIM;
else
usb_set_interface(dev->udev,
intf->cur_altsetting->desc.bInterfaceNumber,
CDC_NCM_COMM_ALTSETTING_NCM);
} }
#endif return CDC_NCM_DATA_ALTSETTING_NCM;
}
EXPORT_SYMBOL_GPL(cdc_ncm_select_altsetting);
static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
{
int ret;
/* MBIM backwards compatible function? */
cdc_ncm_select_altsetting(dev, intf);
if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
return -ENODEV;
/* NCM data altsetting is always 1 */ /* NCM data altsetting is always 1 */
ret = cdc_ncm_bind_common(dev, intf, 1); ret = cdc_ncm_bind_common(dev, intf, 1);

View File

@ -139,16 +139,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state))); BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state)));
/* control and data is shared? */ /* set up initial state */
if (intf->cur_altsetting->desc.bNumEndpoints == 3) { info->control = intf;
info->control = intf; info->data = intf;
info->data = intf;
goto shared;
}
/* else require a single interrupt status endpoint on control intf */
if (intf->cur_altsetting->desc.bNumEndpoints != 1)
goto err;
/* and a number of CDC descriptors */ /* and a number of CDC descriptors */
while (len > 3) { while (len > 3) {
@ -207,25 +200,14 @@ next_desc:
buf += h->bLength; buf += h->bLength;
} }
/* did we find all the required ones? */ /* Use separate control and data interfaces if we found a CDC Union */
if (!(found & (1 << USB_CDC_HEADER_TYPE)) || if (cdc_union) {
!(found & (1 << USB_CDC_UNION_TYPE))) { info->data = usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0);
dev_err(&intf->dev, "CDC functional descriptors missing\n"); if (desc->bInterfaceNumber != cdc_union->bMasterInterface0 || !info->data) {
goto err; dev_err(&intf->dev, "bogus CDC Union: master=%u, slave=%u\n",
} cdc_union->bMasterInterface0, cdc_union->bSlaveInterface0);
goto err;
/* verify CDC Union */ }
if (desc->bInterfaceNumber != cdc_union->bMasterInterface0) {
dev_err(&intf->dev, "bogus CDC Union: master=%u\n", cdc_union->bMasterInterface0);
goto err;
}
/* need to save these for unbind */
info->control = intf;
info->data = usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0);
if (!info->data) {
dev_err(&intf->dev, "bogus CDC Union: slave=%u\n", cdc_union->bSlaveInterface0);
goto err;
} }
/* errors aren't fatal - we can live with the dynamic address */ /* errors aren't fatal - we can live with the dynamic address */
@ -235,11 +217,12 @@ next_desc:
} }
/* claim data interface and set it up */ /* claim data interface and set it up */
status = usb_driver_claim_interface(driver, info->data, dev); if (info->control != info->data) {
if (status < 0) status = usb_driver_claim_interface(driver, info->data, dev);
goto err; if (status < 0)
goto err;
}
shared:
status = qmi_wwan_register_subdriver(dev); status = qmi_wwan_register_subdriver(dev);
if (status < 0 && info->control != info->data) { if (status < 0 && info->control != info->data) {
usb_set_intfdata(info->data, NULL); usb_set_intfdata(info->data, NULL);

View File

@ -1117,10 +1117,9 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
adhoc_join->bss_descriptor.bssid, adhoc_join->bss_descriptor.bssid,
adhoc_join->bss_descriptor.ssid); adhoc_join->bss_descriptor.ssid);
for (i = 0; bss_desc->supported_rates[i] && for (i = 0; i < MWIFIEX_SUPPORTED_RATES &&
i < MWIFIEX_SUPPORTED_RATES; bss_desc->supported_rates[i]; i++)
i++) ;
;
rates_size = i; rates_size = i;
/* Copy Data Rates from the Rates recorded in scan response */ /* Copy Data Rates from the Rates recorded in scan response */

View File

@ -55,10 +55,10 @@ config RT61PCI
config RT2800PCI config RT2800PCI
tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support"
depends on PCI || RALINK_RT288X || RALINK_RT305X depends on PCI || SOC_RT288X || SOC_RT305X
select RT2800_LIB select RT2800_LIB
select RT2X00_LIB_PCI if PCI select RT2X00_LIB_PCI if PCI
select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X
select RT2X00_LIB_FIRMWARE select RT2X00_LIB_FIRMWARE
select RT2X00_LIB_CRYPTO select RT2X00_LIB_CRYPTO
select CRC_CCITT select CRC_CCITT

View File

@ -89,7 +89,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
} }
#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
{ {
void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
@ -107,7 +107,7 @@ static inline int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
{ {
return -ENOMEM; return -ENOMEM;
} }
#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ #endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
@ -1177,7 +1177,7 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table);
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
static int rt2800soc_probe(struct platform_device *pdev) static int rt2800soc_probe(struct platform_device *pdev)
{ {
return rt2x00soc_probe(pdev, &rt2800pci_ops); return rt2x00soc_probe(pdev, &rt2800pci_ops);
@ -1194,7 +1194,7 @@ static struct platform_driver rt2800soc_driver = {
.suspend = rt2x00soc_suspend, .suspend = rt2x00soc_suspend,
.resume = rt2x00soc_resume, .resume = rt2x00soc_resume,
}; };
#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ #endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
static int rt2800pci_probe(struct pci_dev *pci_dev, static int rt2800pci_probe(struct pci_dev *pci_dev,
@ -1217,7 +1217,7 @@ static int __init rt2800pci_init(void)
{ {
int ret = 0; int ret = 0;
#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
ret = platform_driver_register(&rt2800soc_driver); ret = platform_driver_register(&rt2800soc_driver);
if (ret) if (ret)
return ret; return ret;
@ -1225,7 +1225,7 @@ static int __init rt2800pci_init(void)
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
ret = pci_register_driver(&rt2800pci_driver); ret = pci_register_driver(&rt2800pci_driver);
if (ret) { if (ret) {
#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
platform_driver_unregister(&rt2800soc_driver); platform_driver_unregister(&rt2800soc_driver);
#endif #endif
return ret; return ret;
@ -1240,7 +1240,7 @@ static void __exit rt2800pci_exit(void)
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
pci_unregister_driver(&rt2800pci_driver); pci_unregister_driver(&rt2800pci_driver);
#endif #endif
#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
platform_driver_unregister(&rt2800soc_driver); platform_driver_unregister(&rt2800soc_driver);
#endif #endif
} }

View File

@ -1377,74 +1377,57 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw)
void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
{ {
/* dummy routine needed for callback from rtl_op_configure_filter() */ struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR);
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
if (check_bssid) {
u8 tmp;
if (IS_NORMAL_CHIP(rtlhal->version)) {
reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
tmp = BIT(4);
} else {
reg_rcr |= RCR_CBSSID;
tmp = BIT(4) | BIT(5);
}
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
(u8 *) (&reg_rcr));
_rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp);
} else {
u8 tmp;
if (IS_NORMAL_CHIP(rtlhal->version)) {
reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
tmp = BIT(4);
} else {
reg_rcr &= ~RCR_CBSSID;
tmp = BIT(4) | BIT(5);
}
reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
rtlpriv->cfg->ops->set_hw_reg(hw,
HW_VAR_RCR, (u8 *) (&reg_rcr));
_rtl92cu_set_bcn_ctrl_reg(hw, tmp, 0);
}
} }
/*========================================================================== */ /*========================================================================== */
static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw,
enum nl80211_iftype type)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR);
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u8 filterout_non_associated_bssid = false;
switch (type) {
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_STATION:
filterout_non_associated_bssid = true;
break;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_AP:
default:
break;
}
if (filterout_non_associated_bssid) {
if (IS_NORMAL_CHIP(rtlhal->version)) {
switch (rtlphy->current_io_type) {
case IO_CMD_RESUME_DM_BY_SCAN:
reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
rtlpriv->cfg->ops->set_hw_reg(hw,
HW_VAR_RCR, (u8 *)(&reg_rcr));
/* enable update TSF */
_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
break;
case IO_CMD_PAUSE_DM_BY_SCAN:
reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
rtlpriv->cfg->ops->set_hw_reg(hw,
HW_VAR_RCR, (u8 *)(&reg_rcr));
/* disable update TSF */
_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
break;
}
} else {
reg_rcr |= (RCR_CBSSID);
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
(u8 *)(&reg_rcr));
_rtl92cu_set_bcn_ctrl_reg(hw, 0, (BIT(4)|BIT(5)));
}
} else if (filterout_non_associated_bssid == false) {
if (IS_NORMAL_CHIP(rtlhal->version)) {
reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
(u8 *)(&reg_rcr));
_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
} else {
reg_rcr &= (~RCR_CBSSID);
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
(u8 *)(&reg_rcr));
_rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4)|BIT(5)), 0);
}
}
}
int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
{ {
struct rtl_priv *rtlpriv = rtl_priv(hw);
if (_rtl92cu_set_media_status(hw, type)) if (_rtl92cu_set_media_status(hw, type))
return -EOPNOTSUPP; return -EOPNOTSUPP;
_rtl92cu_set_check_bssid(hw, type);
if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
if (type != NL80211_IFTYPE_AP)
rtl92cu_set_check_bssid(hw, true);
} else {
rtl92cu_set_check_bssid(hw, false);
}
return 0; return 0;
} }
@ -2058,8 +2041,6 @@ void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
(shortgi_rate << 4) | (shortgi_rate); (shortgi_rate << 4) | (shortgi_rate);
} }
rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n",
rtl_read_dword(rtlpriv, REG_ARFR0));
} }
void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)

View File

@ -916,6 +916,7 @@ int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
void *reply_param); void *reply_param);
int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int); int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int);
int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int); int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int);
int qeth_get_elements_for_frags(struct sk_buff *);
int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *, int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *,
struct sk_buff *, struct qeth_hdr *, int, int, int); struct sk_buff *, struct qeth_hdr *, int, int, int);
int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *, int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *,

View File

@ -3679,6 +3679,25 @@ int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
} }
EXPORT_SYMBOL_GPL(qeth_get_priority_queue); EXPORT_SYMBOL_GPL(qeth_get_priority_queue);
int qeth_get_elements_for_frags(struct sk_buff *skb)
{
int cnt, length, e, elements = 0;
struct skb_frag_struct *frag;
char *data;
for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) {
frag = &skb_shinfo(skb)->frags[cnt];
data = (char *)page_to_phys(skb_frag_page(frag)) +
frag->page_offset;
length = frag->size;
e = PFN_UP((unsigned long)data + length - 1) -
PFN_DOWN((unsigned long)data);
elements += e;
}
return elements;
}
EXPORT_SYMBOL_GPL(qeth_get_elements_for_frags);
int qeth_get_elements_no(struct qeth_card *card, void *hdr, int qeth_get_elements_no(struct qeth_card *card, void *hdr,
struct sk_buff *skb, int elems) struct sk_buff *skb, int elems)
{ {
@ -3686,7 +3705,8 @@ int qeth_get_elements_no(struct qeth_card *card, void *hdr,
int elements_needed = PFN_UP((unsigned long)skb->data + dlen - 1) - int elements_needed = PFN_UP((unsigned long)skb->data + dlen - 1) -
PFN_DOWN((unsigned long)skb->data); PFN_DOWN((unsigned long)skb->data);
elements_needed += skb_shinfo(skb)->nr_frags; elements_needed += qeth_get_elements_for_frags(skb);
if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) {
QETH_DBF_MESSAGE(2, "Invalid size of IP packet " QETH_DBF_MESSAGE(2, "Invalid size of IP packet "
"(Number=%d / Length=%d). Discarded.\n", "(Number=%d / Length=%d). Discarded.\n",
@ -3771,12 +3791,23 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb,
for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) { for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) {
frag = &skb_shinfo(skb)->frags[cnt]; frag = &skb_shinfo(skb)->frags[cnt];
buffer->element[element].addr = (char *) data = (char *)page_to_phys(skb_frag_page(frag)) +
page_to_phys(skb_frag_page(frag)) frag->page_offset;
+ frag->page_offset; length = frag->size;
buffer->element[element].length = frag->size; while (length > 0) {
buffer->element[element].eflags = SBAL_EFLAGS_MIDDLE_FRAG; length_here = PAGE_SIZE -
element++; ((unsigned long) data % PAGE_SIZE);
if (length < length_here)
length_here = length;
buffer->element[element].addr = data;
buffer->element[element].length = length_here;
buffer->element[element].eflags =
SBAL_EFLAGS_MIDDLE_FRAG;
length -= length_here;
data += length_here;
element++;
}
} }
if (buffer->element[element - 1].eflags) if (buffer->element[element - 1].eflags)

View File

@ -623,7 +623,7 @@ static int qeth_l3_send_setrouting(struct qeth_card *card,
return rc; return rc;
} }
static void qeth_l3_correct_routing_type(struct qeth_card *card, static int qeth_l3_correct_routing_type(struct qeth_card *card,
enum qeth_routing_types *type, enum qeth_prot_versions prot) enum qeth_routing_types *type, enum qeth_prot_versions prot)
{ {
if (card->info.type == QETH_CARD_TYPE_IQD) { if (card->info.type == QETH_CARD_TYPE_IQD) {
@ -632,7 +632,7 @@ static void qeth_l3_correct_routing_type(struct qeth_card *card,
case PRIMARY_CONNECTOR: case PRIMARY_CONNECTOR:
case SECONDARY_CONNECTOR: case SECONDARY_CONNECTOR:
case MULTICAST_ROUTER: case MULTICAST_ROUTER:
return; return 0;
default: default:
goto out_inval; goto out_inval;
} }
@ -641,17 +641,18 @@ static void qeth_l3_correct_routing_type(struct qeth_card *card,
case NO_ROUTER: case NO_ROUTER:
case PRIMARY_ROUTER: case PRIMARY_ROUTER:
case SECONDARY_ROUTER: case SECONDARY_ROUTER:
return; return 0;
case MULTICAST_ROUTER: case MULTICAST_ROUTER:
if (qeth_is_ipafunc_supported(card, prot, if (qeth_is_ipafunc_supported(card, prot,
IPA_OSA_MC_ROUTER)) IPA_OSA_MC_ROUTER))
return; return 0;
default: default:
goto out_inval; goto out_inval;
} }
} }
out_inval: out_inval:
*type = NO_ROUTER; *type = NO_ROUTER;
return -EINVAL;
} }
int qeth_l3_setrouting_v4(struct qeth_card *card) int qeth_l3_setrouting_v4(struct qeth_card *card)
@ -660,8 +661,10 @@ int qeth_l3_setrouting_v4(struct qeth_card *card)
QETH_CARD_TEXT(card, 3, "setrtg4"); QETH_CARD_TEXT(card, 3, "setrtg4");
qeth_l3_correct_routing_type(card, &card->options.route4.type, rc = qeth_l3_correct_routing_type(card, &card->options.route4.type,
QETH_PROT_IPV4); QETH_PROT_IPV4);
if (rc)
return rc;
rc = qeth_l3_send_setrouting(card, card->options.route4.type, rc = qeth_l3_send_setrouting(card, card->options.route4.type,
QETH_PROT_IPV4); QETH_PROT_IPV4);
@ -683,8 +686,10 @@ int qeth_l3_setrouting_v6(struct qeth_card *card)
if (!qeth_is_supported(card, IPA_IPV6)) if (!qeth_is_supported(card, IPA_IPV6))
return 0; return 0;
qeth_l3_correct_routing_type(card, &card->options.route6.type, rc = qeth_l3_correct_routing_type(card, &card->options.route6.type,
QETH_PROT_IPV6); QETH_PROT_IPV6);
if (rc)
return rc;
rc = qeth_l3_send_setrouting(card, card->options.route6.type, rc = qeth_l3_send_setrouting(card, card->options.route6.type,
QETH_PROT_IPV6); QETH_PROT_IPV6);
@ -2898,7 +2903,9 @@ static inline int qeth_l3_tso_elements(struct sk_buff *skb)
tcp_hdr(skb)->doff * 4; tcp_hdr(skb)->doff * 4;
int tcpd_len = skb->len - (tcpd - (unsigned long)skb->data); int tcpd_len = skb->len - (tcpd - (unsigned long)skb->data);
int elements = PFN_UP(tcpd + tcpd_len - 1) - PFN_DOWN(tcpd); int elements = PFN_UP(tcpd + tcpd_len - 1) - PFN_DOWN(tcpd);
elements += skb_shinfo(skb)->nr_frags;
elements += qeth_get_elements_for_frags(skb);
return elements; return elements;
} }
@ -3348,7 +3355,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
rc = -ENODEV; rc = -ENODEV;
goto out_remove; goto out_remove;
} }
qeth_trace_features(card);
if (!card->dev && qeth_l3_setup_netdev(card)) { if (!card->dev && qeth_l3_setup_netdev(card)) {
rc = -ENODEV; rc = -ENODEV;
@ -3425,6 +3431,7 @@ contin:
qeth_l3_set_multicast_list(card->dev); qeth_l3_set_multicast_list(card->dev);
rtnl_unlock(); rtnl_unlock();
} }
qeth_trace_features(card);
/* let user_space know that device is online */ /* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
mutex_unlock(&card->conf_mutex); mutex_unlock(&card->conf_mutex);

View File

@ -87,6 +87,8 @@ static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
rc = qeth_l3_setrouting_v6(card); rc = qeth_l3_setrouting_v6(card);
} }
out: out:
if (rc)
route->type = old_route_type;
mutex_unlock(&card->conf_mutex); mutex_unlock(&card->conf_mutex);
return rc ? rc : count; return rc ? rc : count;
} }

View File

@ -339,7 +339,8 @@ static void handle_tx(struct vhost_net *net)
msg.msg_controllen = 0; msg.msg_controllen = 0;
ubufs = NULL; ubufs = NULL;
} else { } else {
struct ubuf_info *ubuf = &vq->ubuf_info[head]; struct ubuf_info *ubuf;
ubuf = vq->ubuf_info + vq->upend_idx;
vq->heads[vq->upend_idx].len = vq->heads[vq->upend_idx].len =
VHOST_DMA_IN_PROGRESS; VHOST_DMA_IN_PROGRESS;

View File

@ -500,7 +500,7 @@ struct sk_buff {
union { union {
__u32 mark; __u32 mark;
__u32 dropcount; __u32 dropcount;
__u32 avail_size; __u32 reserved_tailroom;
}; };
sk_buff_data_t inner_transport_header; sk_buff_data_t inner_transport_header;
@ -1288,11 +1288,13 @@ static inline void __skb_fill_page_desc(struct sk_buff *skb, int i,
* do not lose pfmemalloc information as the pages would not be * do not lose pfmemalloc information as the pages would not be
* allocated using __GFP_MEMALLOC. * allocated using __GFP_MEMALLOC.
*/ */
if (page->pfmemalloc && !page->mapping)
skb->pfmemalloc = true;
frag->page.p = page; frag->page.p = page;
frag->page_offset = off; frag->page_offset = off;
skb_frag_size_set(frag, size); skb_frag_size_set(frag, size);
page = compound_head(page);
if (page->pfmemalloc && !page->mapping)
skb->pfmemalloc = true;
} }
/** /**
@ -1447,7 +1449,10 @@ static inline int skb_tailroom(const struct sk_buff *skb)
*/ */
static inline int skb_availroom(const struct sk_buff *skb) static inline int skb_availroom(const struct sk_buff *skb)
{ {
return skb_is_nonlinear(skb) ? 0 : skb->avail_size - skb->len; if (skb_is_nonlinear(skb))
return 0;
return skb->end - skb->tail - skb->reserved_tailroom;
} }
/** /**

View File

@ -127,6 +127,7 @@ struct cdc_ncm_ctx {
u16 connected; u16 connected;
}; };
extern u8 cdc_ncm_select_altsetting(struct usbnet *dev, struct usb_interface *intf);
extern int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting); extern int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting);
extern void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf); extern void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
extern struct sk_buff *cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign); extern struct sk_buff *cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign);

View File

@ -413,13 +413,15 @@ static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n,
static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
{ {
return dst->ops->neigh_lookup(dst, NULL, daddr); struct neighbour *n = dst->ops->neigh_lookup(dst, NULL, daddr);
return IS_ERR(n) ? NULL : n;
} }
static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst, static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst,
struct sk_buff *skb) struct sk_buff *skb)
{ {
return dst->ops->neigh_lookup(dst, skb, NULL); struct neighbour *n = dst->ops->neigh_lookup(dst, skb, NULL);
return IS_ERR(n) ? NULL : n;
} }
static inline void dst_link_failure(struct sk_buff *skb) static inline void dst_link_failure(struct sk_buff *skb)

View File

@ -43,6 +43,13 @@ struct inet_frag_queue {
#define INETFRAGS_HASHSZ 64 #define INETFRAGS_HASHSZ 64
/* averaged:
* max_depth = default ipfrag_high_thresh / INETFRAGS_HASHSZ /
* rounded up (SKB_TRUELEN(0) + sizeof(struct ipq or
* struct frag_queue))
*/
#define INETFRAGS_MAXDEPTH 128
struct inet_frags { struct inet_frags {
struct hlist_head hash[INETFRAGS_HASHSZ]; struct hlist_head hash[INETFRAGS_HASHSZ];
/* This rwlock is a global lock (seperate per IPv4, IPv6 and /* This rwlock is a global lock (seperate per IPv4, IPv6 and
@ -76,6 +83,8 @@ int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force);
struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
struct inet_frags *f, void *key, unsigned int hash) struct inet_frags *f, void *key, unsigned int hash)
__releases(&f->lock); __releases(&f->lock);
void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
const char *prefix);
static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f) static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
{ {

View File

@ -152,19 +152,17 @@ struct fib_result_nl {
}; };
#ifdef CONFIG_IP_ROUTE_MULTIPATH #ifdef CONFIG_IP_ROUTE_MULTIPATH
#define FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel]) #define FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
#define FIB_TABLE_HASHSZ 2
#else /* CONFIG_IP_ROUTE_MULTIPATH */ #else /* CONFIG_IP_ROUTE_MULTIPATH */
#define FIB_RES_NH(res) ((res).fi->fib_nh[0]) #define FIB_RES_NH(res) ((res).fi->fib_nh[0])
#define FIB_TABLE_HASHSZ 256
#endif /* CONFIG_IP_ROUTE_MULTIPATH */ #endif /* CONFIG_IP_ROUTE_MULTIPATH */
#ifdef CONFIG_IP_MULTIPLE_TABLES
#define FIB_TABLE_HASHSZ 256
#else
#define FIB_TABLE_HASHSZ 2
#endif
extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh); extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
#define FIB_RES_SADDR(net, res) \ #define FIB_RES_SADDR(net, res) \

View File

@ -1288,7 +1288,8 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff; batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff;
/* unpack the aggregated packets and process them one by one */ /* unpack the aggregated packets and process them one by one */
do { while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
batadv_ogm_packet->tt_num_changes)) {
tt_buff = packet_buff + buff_pos + BATADV_OGM_HLEN; tt_buff = packet_buff + buff_pos + BATADV_OGM_HLEN;
batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, tt_buff, batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, tt_buff,
@ -1299,8 +1300,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
packet_pos = packet_buff + buff_pos; packet_pos = packet_buff + buff_pos;
batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
} while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, }
batadv_ogm_packet->tt_num_changes));
kfree_skb(skb); kfree_skb(skb);
return NET_RX_SUCCESS; return NET_RX_SUCCESS;

View File

@ -29,6 +29,7 @@ static inline size_t br_port_info_size(void)
+ nla_total_size(1) /* IFLA_BRPORT_MODE */ + nla_total_size(1) /* IFLA_BRPORT_MODE */
+ nla_total_size(1) /* IFLA_BRPORT_GUARD */ + nla_total_size(1) /* IFLA_BRPORT_GUARD */
+ nla_total_size(1) /* IFLA_BRPORT_PROTECT */ + nla_total_size(1) /* IFLA_BRPORT_PROTECT */
+ nla_total_size(1) /* IFLA_BRPORT_FAST_LEAVE */
+ 0; + 0;
} }
@ -329,6 +330,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE); br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD); br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE); br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
if (tb[IFLA_BRPORT_COST]) { if (tb[IFLA_BRPORT_COST]) {
err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST])); err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST]));

View File

@ -2219,9 +2219,9 @@ struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
struct packet_offload *ptype; struct packet_offload *ptype;
__be16 type = skb->protocol; __be16 type = skb->protocol;
int vlan_depth = ETH_HLEN;
while (type == htons(ETH_P_8021Q)) { while (type == htons(ETH_P_8021Q)) {
int vlan_depth = ETH_HLEN;
struct vlan_hdr *vh; struct vlan_hdr *vh;
if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN))) if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN)))

View File

@ -2621,7 +2621,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len);
while (RTA_OK(attr, attrlen)) { while (RTA_OK(attr, attrlen)) {
unsigned int flavor = attr->rta_type; unsigned int flavor = attr->rta_type & NLA_TYPE_MASK;
if (flavor) { if (flavor) {
if (flavor > rta_max[sz_idx]) if (flavor > rta_max[sz_idx])
return -EINVAL; return -EINVAL;

View File

@ -21,6 +21,7 @@
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <net/sock.h>
#include <net/inet_frag.h> #include <net/inet_frag.h>
static void inet_frag_secret_rebuild(unsigned long dummy) static void inet_frag_secret_rebuild(unsigned long dummy)
@ -277,6 +278,7 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
__releases(&f->lock) __releases(&f->lock)
{ {
struct inet_frag_queue *q; struct inet_frag_queue *q;
int depth = 0;
hlist_for_each_entry(q, &f->hash[hash], list) { hlist_for_each_entry(q, &f->hash[hash], list) {
if (q->net == nf && f->match(q, key)) { if (q->net == nf && f->match(q, key)) {
@ -284,9 +286,25 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
read_unlock(&f->lock); read_unlock(&f->lock);
return q; return q;
} }
depth++;
} }
read_unlock(&f->lock); read_unlock(&f->lock);
return inet_frag_create(nf, f, key); if (depth <= INETFRAGS_MAXDEPTH)
return inet_frag_create(nf, f, key);
else
return ERR_PTR(-ENOBUFS);
} }
EXPORT_SYMBOL(inet_frag_find); EXPORT_SYMBOL(inet_frag_find);
void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
const char *prefix)
{
static const char msg[] = "inet_frag_find: Fragment hash bucket"
" list length grew over limit " __stringify(INETFRAGS_MAXDEPTH)
". Dropping fragment.\n";
if (PTR_ERR(q) == -ENOBUFS)
LIMIT_NETDEBUG(KERN_WARNING "%s%s", prefix, msg);
}
EXPORT_SYMBOL(inet_frag_maybe_warn_overflow);

View File

@ -292,14 +292,11 @@ static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user)
hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash); q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash);
if (q == NULL) if (IS_ERR_OR_NULL(q)) {
goto out_nomem; inet_frag_maybe_warn_overflow(q, pr_fmt());
return NULL;
}
return container_of(q, struct ipq, q); return container_of(q, struct ipq, q);
out_nomem:
LIMIT_NETDEBUG(KERN_ERR pr_fmt("ip_frag_create: no memory left !\n"));
return NULL;
} }
/* Is the fragment too far ahead to be part of ipq? */ /* Is the fragment too far ahead to be part of ipq? */

View File

@ -798,10 +798,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
if (dev->header_ops && dev->type == ARPHRD_IPGRE) { if (dev->header_ops && dev->type == ARPHRD_IPGRE) {
gre_hlen = 0; gre_hlen = 0;
if (skb->protocol == htons(ETH_P_IP)) tiph = (const struct iphdr *)skb->data;
tiph = (const struct iphdr *)skb->data;
else
tiph = &tunnel->parms.iph;
} else { } else {
gre_hlen = tunnel->hlen; gre_hlen = tunnel->hlen;
tiph = &tunnel->parms.iph; tiph = &tunnel->parms.iph;

View File

@ -370,7 +370,6 @@ int ip_options_compile(struct net *net,
} }
switch (optptr[3]&0xF) { switch (optptr[3]&0xF) {
case IPOPT_TS_TSONLY: case IPOPT_TS_TSONLY:
opt->ts = optptr - iph;
if (skb) if (skb)
timeptr = &optptr[optptr[2]-1]; timeptr = &optptr[optptr[2]-1];
opt->ts_needtime = 1; opt->ts_needtime = 1;
@ -381,7 +380,6 @@ int ip_options_compile(struct net *net,
pp_ptr = optptr + 2; pp_ptr = optptr + 2;
goto error; goto error;
} }
opt->ts = optptr - iph;
if (rt) { if (rt) {
spec_dst_fill(&spec_dst, skb); spec_dst_fill(&spec_dst, skb);
memcpy(&optptr[optptr[2]-1], &spec_dst, 4); memcpy(&optptr[optptr[2]-1], &spec_dst, 4);
@ -396,7 +394,6 @@ int ip_options_compile(struct net *net,
pp_ptr = optptr + 2; pp_ptr = optptr + 2;
goto error; goto error;
} }
opt->ts = optptr - iph;
{ {
__be32 addr; __be32 addr;
memcpy(&addr, &optptr[optptr[2]-1], 4); memcpy(&addr, &optptr[optptr[2]-1], 4);
@ -429,12 +426,12 @@ int ip_options_compile(struct net *net,
pp_ptr = optptr + 3; pp_ptr = optptr + 3;
goto error; goto error;
} }
opt->ts = optptr - iph;
if (skb) { if (skb) {
optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4); optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
opt->is_changed = 1; opt->is_changed = 1;
} }
} }
opt->ts = optptr - iph;
break; break;
case IPOPT_RA: case IPOPT_RA:
if (optlen < 4) { if (optlen < 4) {

View File

@ -775,7 +775,7 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp)
* Make sure that we have exactly size bytes * Make sure that we have exactly size bytes
* available to the caller, no more, no less. * available to the caller, no more, no less.
*/ */
skb->avail_size = size; skb->reserved_tailroom = skb->end - skb->tail - size;
return skb; return skb;
} }
__kfree_skb(skb); __kfree_skb(skb);

View File

@ -274,13 +274,6 @@ static void tcp_v4_mtu_reduced(struct sock *sk)
struct inet_sock *inet = inet_sk(sk); struct inet_sock *inet = inet_sk(sk);
u32 mtu = tcp_sk(sk)->mtu_info; u32 mtu = tcp_sk(sk)->mtu_info;
/* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs
* send out by Linux are always <576bytes so they should go through
* unfragmented).
*/
if (sk->sk_state == TCP_LISTEN)
return;
dst = inet_csk_update_pmtu(sk, mtu); dst = inet_csk_update_pmtu(sk, mtu);
if (!dst) if (!dst)
return; return;
@ -408,6 +401,13 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
goto out; goto out;
if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
/* We are not interested in TCP_LISTEN and open_requests
* (SYN-ACKs send out by Linux are always <576bytes so
* they should go through unfragmented).
*/
if (sk->sk_state == TCP_LISTEN)
goto out;
tp->mtu_info = info; tp->mtu_info = info;
if (!sock_owned_by_user(sk)) { if (!sock_owned_by_user(sk)) {
tcp_v4_mtu_reduced(sk); tcp_v4_mtu_reduced(sk);

View File

@ -1298,7 +1298,6 @@ static void __pskb_trim_head(struct sk_buff *skb, int len)
eat = min_t(int, len, skb_headlen(skb)); eat = min_t(int, len, skb_headlen(skb));
if (eat) { if (eat) {
__skb_pull(skb, eat); __skb_pull(skb, eat);
skb->avail_size -= eat;
len -= eat; len -= eat;
if (!len) if (!len)
return; return;

View File

@ -14,6 +14,8 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#define pr_fmt(fmt) "IPv6-nf: " fmt
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/string.h> #include <linux/string.h>
@ -180,13 +182,11 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id,
q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash); q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash);
local_bh_enable(); local_bh_enable();
if (q == NULL) if (IS_ERR_OR_NULL(q)) {
goto oom; inet_frag_maybe_warn_overflow(q, pr_fmt());
return NULL;
}
return container_of(q, struct frag_queue, q); return container_of(q, struct frag_queue, q);
oom:
return NULL;
} }

View File

@ -26,6 +26,9 @@
* YOSHIFUJI,H. @USAGI Always remove fragment header to * YOSHIFUJI,H. @USAGI Always remove fragment header to
* calculate ICV correctly. * calculate ICV correctly.
*/ */
#define pr_fmt(fmt) "IPv6: " fmt
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/string.h> #include <linux/string.h>
@ -185,9 +188,10 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6
hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd); hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd);
q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash);
if (q == NULL) if (IS_ERR_OR_NULL(q)) {
inet_frag_maybe_warn_overflow(q, pr_fmt());
return NULL; return NULL;
}
return container_of(q, struct frag_queue, q); return container_of(q, struct frag_queue, q);
} }

View File

@ -389,6 +389,13 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
} }
if (type == ICMPV6_PKT_TOOBIG) { if (type == ICMPV6_PKT_TOOBIG) {
/* We are not interested in TCP_LISTEN and open_requests
* (SYN-ACKs send out by Linux are always <576bytes so
* they should go through unfragmented).
*/
if (sk->sk_state == TCP_LISTEN)
goto out;
tp->mtu_info = ntohl(info); tp->mtu_info = ntohl(info);
if (!sock_owned_by_user(sk)) if (!sock_owned_by_user(sk))
tcp_v6_mtu_reduced(sk); tcp_v6_mtu_reduced(sk);

View File

@ -68,7 +68,8 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
} }
} }
static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
int err)
{ {
struct sock *sk; struct sock *sk;
struct hlist_node *tmp; struct hlist_node *tmp;
@ -100,7 +101,10 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
nfc_llcp_accept_unlink(accept_sk); nfc_llcp_accept_unlink(accept_sk);
if (err)
accept_sk->sk_err = err;
accept_sk->sk_state = LLCP_CLOSED; accept_sk->sk_state = LLCP_CLOSED;
accept_sk->sk_state_change(sk);
bh_unlock_sock(accept_sk); bh_unlock_sock(accept_sk);
@ -123,7 +127,10 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
continue; continue;
} }
if (err)
sk->sk_err = err;
sk->sk_state = LLCP_CLOSED; sk->sk_state = LLCP_CLOSED;
sk->sk_state_change(sk);
bh_unlock_sock(sk); bh_unlock_sock(sk);
@ -133,6 +140,36 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
} }
write_unlock(&local->sockets.lock); write_unlock(&local->sockets.lock);
/*
* If we want to keep the listening sockets alive,
* we don't touch the RAW ones.
*/
if (listen == true)
return;
write_lock(&local->raw_sockets.lock);
sk_for_each_safe(sk, tmp, &local->raw_sockets.head) {
llcp_sock = nfc_llcp_sock(sk);
bh_lock_sock(sk);
nfc_llcp_socket_purge(llcp_sock);
if (err)
sk->sk_err = err;
sk->sk_state = LLCP_CLOSED;
sk->sk_state_change(sk);
bh_unlock_sock(sk);
sock_orphan(sk);
sk_del_node_init(sk);
}
write_unlock(&local->raw_sockets.lock);
} }
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
@ -142,6 +179,17 @@ struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
return local; return local;
} }
static void local_cleanup(struct nfc_llcp_local *local, bool listen)
{
nfc_llcp_socket_release(local, listen, ENXIO);
del_timer_sync(&local->link_timer);
skb_queue_purge(&local->tx_queue);
cancel_work_sync(&local->tx_work);
cancel_work_sync(&local->rx_work);
cancel_work_sync(&local->timeout_work);
kfree_skb(local->rx_pending);
}
static void local_release(struct kref *ref) static void local_release(struct kref *ref)
{ {
struct nfc_llcp_local *local; struct nfc_llcp_local *local;
@ -149,13 +197,7 @@ static void local_release(struct kref *ref)
local = container_of(ref, struct nfc_llcp_local, ref); local = container_of(ref, struct nfc_llcp_local, ref);
list_del(&local->list); list_del(&local->list);
nfc_llcp_socket_release(local, false); local_cleanup(local, false);
del_timer_sync(&local->link_timer);
skb_queue_purge(&local->tx_queue);
cancel_work_sync(&local->tx_work);
cancel_work_sync(&local->rx_work);
cancel_work_sync(&local->timeout_work);
kfree_skb(local->rx_pending);
kfree(local); kfree(local);
} }
@ -1348,7 +1390,7 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
return; return;
/* Close and purge all existing sockets */ /* Close and purge all existing sockets */
nfc_llcp_socket_release(local, true); nfc_llcp_socket_release(local, true, 0);
} }
void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
@ -1427,6 +1469,8 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
return; return;
} }
local_cleanup(local, false);
nfc_llcp_local_put(local); nfc_llcp_local_put(local);
} }

View File

@ -278,6 +278,8 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
pr_debug("Returning sk state %d\n", sk->sk_state); pr_debug("Returning sk state %d\n", sk->sk_state);
sk_acceptq_removed(parent);
return sk; return sk;
} }

View File

@ -58,7 +58,7 @@ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci)
if (skb->ip_summed == CHECKSUM_COMPLETE) if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->csum = csum_sub(skb->csum, csum_partial(skb->data skb->csum = csum_sub(skb->csum, csum_partial(skb->data
+ ETH_HLEN, VLAN_HLEN, 0)); + (2 * ETH_ALEN), VLAN_HLEN, 0));
vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN); vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN);
*current_tci = vhdr->h_vlan_TCI; *current_tci = vhdr->h_vlan_TCI;
@ -115,7 +115,7 @@ static int push_vlan(struct sk_buff *skb, const struct ovs_action_push_vlan *vla
if (skb->ip_summed == CHECKSUM_COMPLETE) if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->csum = csum_add(skb->csum, csum_partial(skb->data skb->csum = csum_add(skb->csum, csum_partial(skb->data
+ ETH_HLEN, VLAN_HLEN, 0)); + (2 * ETH_ALEN), VLAN_HLEN, 0));
} }
__vlan_hwaccel_put_tag(skb, ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT); __vlan_hwaccel_put_tag(skb, ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);

View File

@ -394,6 +394,7 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
skb_copy_and_csum_dev(skb, nla_data(nla)); skb_copy_and_csum_dev(skb, nla_data(nla));
genlmsg_end(user_skb, upcall);
err = genlmsg_unicast(net, user_skb, upcall_info->portid); err = genlmsg_unicast(net, user_skb, upcall_info->portid);
out: out:
@ -1690,6 +1691,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
if (IS_ERR(vport)) if (IS_ERR(vport))
goto exit_unlock; goto exit_unlock;
err = 0;
reply = ovs_vport_cmd_build_info(vport, info->snd_portid, info->snd_seq, reply = ovs_vport_cmd_build_info(vport, info->snd_portid, info->snd_seq,
OVS_VPORT_CMD_NEW); OVS_VPORT_CMD_NEW);
if (IS_ERR(reply)) { if (IS_ERR(reply)) {
@ -1771,6 +1773,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
if (IS_ERR(reply)) if (IS_ERR(reply))
goto exit_unlock; goto exit_unlock;
err = 0;
ovs_dp_detach_port(vport); ovs_dp_detach_port(vport);
genl_notify(reply, genl_info_net(info), info->snd_portid, genl_notify(reply, genl_info_net(info), info->snd_portid,

View File

@ -482,7 +482,11 @@ static __be16 parse_ethertype(struct sk_buff *skb)
return htons(ETH_P_802_2); return htons(ETH_P_802_2);
__skb_pull(skb, sizeof(struct llc_snap_hdr)); __skb_pull(skb, sizeof(struct llc_snap_hdr));
return llc->ethertype;
if (ntohs(llc->ethertype) >= 1536)
return llc->ethertype;
return htons(ETH_P_802_2);
} }
static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key, static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,

View File

@ -43,8 +43,7 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
/* Make our own copy of the packet. Otherwise we will mangle the /* Make our own copy of the packet. Otherwise we will mangle the
* packet for anyone who came before us (e.g. tcpdump via AF_PACKET). * packet for anyone who came before us (e.g. tcpdump via AF_PACKET).
* (No one comes after us, since we tell handle_bridge() that we took */
* the packet.) */
skb = skb_share_check(skb, GFP_ATOMIC); skb = skb_share_check(skb, GFP_ATOMIC);
if (unlikely(!skb)) if (unlikely(!skb))
return; return;

View File

@ -325,8 +325,7 @@ int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
* @skb: skb that was received * @skb: skb that was received
* *
* Must be called with rcu_read_lock. The packet cannot be shared and * Must be called with rcu_read_lock. The packet cannot be shared and
* skb->data should point to the Ethernet header. The caller must have already * skb->data should point to the Ethernet header.
* called compute_ip_summed() to initialize the checksumming fields.
*/ */
void ovs_vport_receive(struct vport *vport, struct sk_buff *skb) void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)
{ {

View File

@ -1079,7 +1079,7 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc,
transports) { transports) {
if (transport == active) if (transport == active)
break; continue;
list_for_each_entry(chunk, &transport->transmitted, list_for_each_entry(chunk, &transport->transmitted,
transmitted_list) { transmitted_list) {
if (key == chunk->subh.data_hdr->tsn) { if (key == chunk->subh.data_hdr->tsn) {

View File

@ -2082,7 +2082,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(struct net *net,
} }
/* Delete the tempory new association. */ /* Delete the tempory new association. */
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); sctp_add_cmd_sf(commands, SCTP_CMD_SET_ASOC, SCTP_ASOC(new_asoc));
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
/* Restore association pointer to provide SCTP command interpeter /* Restore association pointer to provide SCTP command interpeter