提交 b527caee 编写于 作者: L Linus Torvalds

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

Pull networking fixes from David Miller:

 1) Make fragmentation IDs less predictable, from Eric Dumazet.

 2) TSO tunneling can crash in bnx2x driver, fix from Dmitry Kravkov.

 3) Don't allow NULL msg->msg_name just because msg->msg_namelen is
    non-zero, from Andrey Ryabinin.

 4) ndm->ndm_type set using wrong macros, from Jun Zhao.

 5) cdc-ether devices can come up with entries in their address filter,
    so explicitly clear the filter after the device initializes.  From
    Oliver Neukum.

 6) Forgotten refcount bump in xfrm_lookup(), from Steffen Klassert.

 7) Short packets not padded properly, exposing random data, in bcmgenet
    driver.  Fix from Florian Fainelli.

 8) xgbe_probe() doesn't return an error code, but rather zero, when
    netif_set_real_num_tx_queues() fails.  Fix from Wei Yongjun.

 9) USB speed not probed properly in r8152 driver, from Hayes Wang.

10) Transmit logic choosing the outgoing port in the sunvnet driver
    needs to consider a) is the port actually up and b) whether it is a
    switch port.  Fix from David L Stevens.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (27 commits)
  net: phy: re-apply PHY fixups during phy_register_device
  cdc-ether: clean packet filter upon probe
  cdc_subset: deal with a device that needs reset for timeout
  net: sendmsg: fix NULL pointer dereference
  isdn/bas_gigaset: fix a leak on failure path in gigaset_probe()
  ip: make IP identifiers less predictable
  neighbour : fix ndm_type type error issue
  sunvnet: only use connected ports when sending
  can: c_can_platform: Fix raminit, use devm_ioremap() instead of devm_ioremap_resource()
  bnx2x: fix crash during TSO tunneling
  r8152: fix the checking of the usb speed
  net: phy: Ensure the MDIO bus module is held
  net: phy: Set the driver when registering an MDIO bus device
  bnx2x: fix set_setting for some PHYs
  hyperv: Fix error return code in netvsc_init_buf()
  amd-xgbe: Fix error return code in xgbe_probe()
  ath9k: fix aggregation session lockup
  net: bcmgenet: correctly pad short packets
  net: sctp: inherit auth_capable on INIT collisions
  mac80211: fix crash on getting sta info with uninitialized rate control
  ...
...@@ -2400,6 +2400,7 @@ static int gigaset_probe(struct usb_interface *interface, ...@@ -2400,6 +2400,7 @@ static int gigaset_probe(struct usb_interface *interface,
error: error:
freeurbs(cs); freeurbs(cs);
usb_set_intfdata(interface, NULL); usb_set_intfdata(interface, NULL);
usb_put_dev(udev);
gigaset_freecs(cs); gigaset_freecs(cs);
return rc; return rc;
} }
......
...@@ -287,7 +287,8 @@ static int c_can_plat_probe(struct platform_device *pdev) ...@@ -287,7 +287,8 @@ static int c_can_plat_probe(struct platform_device *pdev)
break; break;
} }
priv->raminit_ctrlreg = devm_ioremap_resource(&pdev->dev, res); priv->raminit_ctrlreg = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0) if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0)
dev_info(&pdev->dev, "control memory is not used for raminit\n"); dev_info(&pdev->dev, "control memory is not used for raminit\n");
else else
......
...@@ -339,7 +339,8 @@ static int xgbe_probe(struct platform_device *pdev) ...@@ -339,7 +339,8 @@ static int xgbe_probe(struct platform_device *pdev)
/* Calculate the number of Tx and Rx rings to be created */ /* Calculate the number of Tx and Rx rings to be created */
pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(), pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(),
pdata->hw_feat.tx_ch_cnt); pdata->hw_feat.tx_ch_cnt);
if (netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count)) { ret = netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count);
if (ret) {
dev_err(dev, "error setting real tx queue count\n"); dev_err(dev, "error setting real tx queue count\n");
goto err_io; goto err_io;
} }
......
...@@ -346,6 +346,7 @@ struct sw_tx_bd { ...@@ -346,6 +346,7 @@ struct sw_tx_bd {
u8 flags; u8 flags;
/* Set on the first BD descriptor when there is a split BD */ /* Set on the first BD descriptor when there is a split BD */
#define BNX2X_TSO_SPLIT_BD (1<<0) #define BNX2X_TSO_SPLIT_BD (1<<0)
#define BNX2X_HAS_SECOND_PBD (1<<1)
}; };
struct sw_rx_page { struct sw_rx_page {
......
...@@ -227,6 +227,12 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, ...@@ -227,6 +227,12 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
--nbd; --nbd;
bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
if (tx_buf->flags & BNX2X_HAS_SECOND_PBD) {
/* Skip second parse bd... */
--nbd;
bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
}
/* TSO headers+data bds share a common mapping. See bnx2x_tx_split() */ /* TSO headers+data bds share a common mapping. See bnx2x_tx_split() */
if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) { if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) {
tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd; tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd;
...@@ -3889,6 +3895,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -3889,6 +3895,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* set encapsulation flag in start BD */ /* set encapsulation flag in start BD */
SET_FLAG(tx_start_bd->general_data, SET_FLAG(tx_start_bd->general_data,
ETH_TX_START_BD_TUNNEL_EXIST, 1); ETH_TX_START_BD_TUNNEL_EXIST, 1);
tx_buf->flags |= BNX2X_HAS_SECOND_PBD;
nbd++; nbd++;
} else if (xmit_type & XMIT_CSUM) { } else if (xmit_type & XMIT_CSUM) {
/* Set PBD in checksum offload case w/o encapsulation */ /* Set PBD in checksum offload case w/o encapsulation */
......
...@@ -379,6 +379,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -379,6 +379,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
break; break;
case PORT_FIBRE: case PORT_FIBRE:
case PORT_DA: case PORT_DA:
case PORT_NONE:
if (!(bp->port.supported[0] & SUPPORTED_FIBRE || if (!(bp->port.supported[0] & SUPPORTED_FIBRE ||
bp->port.supported[1] & SUPPORTED_FIBRE)) { bp->port.supported[1] & SUPPORTED_FIBRE)) {
DP(BNX2X_MSG_ETHTOOL, DP(BNX2X_MSG_ETHTOOL,
......
...@@ -1149,6 +1149,11 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1149,6 +1149,11 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
goto out; goto out;
} }
if (skb_padto(skb, ETH_ZLEN)) {
ret = NETDEV_TX_OK;
goto out;
}
/* set the SKB transmit checksum */ /* set the SKB transmit checksum */
if (priv->desc_64b_en) { if (priv->desc_64b_en) {
ret = bcmgenet_put_tx_csum(dev, skb); ret = bcmgenet_put_tx_csum(dev, skb);
......
...@@ -610,6 +610,13 @@ static int __vnet_tx_trigger(struct vnet_port *port) ...@@ -610,6 +610,13 @@ static int __vnet_tx_trigger(struct vnet_port *port)
return err; return err;
} }
static inline bool port_is_up(struct vnet_port *vnet)
{
struct vio_driver_state *vio = &vnet->vio;
return !!(vio->hs_state & VIO_HS_COMPLETE);
}
struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb) struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb)
{ {
unsigned int hash = vnet_hashfn(skb->data); unsigned int hash = vnet_hashfn(skb->data);
...@@ -617,14 +624,19 @@ struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb) ...@@ -617,14 +624,19 @@ struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb)
struct vnet_port *port; struct vnet_port *port;
hlist_for_each_entry(port, hp, hash) { hlist_for_each_entry(port, hp, hash) {
if (!port_is_up(port))
continue;
if (ether_addr_equal(port->raddr, skb->data)) if (ether_addr_equal(port->raddr, skb->data))
return port; return port;
} }
port = NULL; list_for_each_entry(port, &vp->port_list, list) {
if (!list_empty(&vp->port_list)) if (!port->switch_port)
port = list_entry(vp->port_list.next, struct vnet_port, list); continue;
if (!port_is_up(port))
return port; continue;
return port;
}
return NULL;
} }
struct vnet_port *tx_port_find(struct vnet *vp, struct sk_buff *skb) struct vnet_port *tx_port_find(struct vnet *vp, struct sk_buff *skb)
......
...@@ -378,8 +378,10 @@ static int netvsc_init_buf(struct hv_device *device) ...@@ -378,8 +378,10 @@ static int netvsc_init_buf(struct hv_device *device)
net_device->send_section_map = net_device->send_section_map =
kzalloc(net_device->map_words * sizeof(ulong), GFP_KERNEL); kzalloc(net_device->map_words * sizeof(ulong), GFP_KERNEL);
if (net_device->send_section_map == NULL) if (net_device->send_section_map == NULL) {
ret = -ENOMEM;
goto cleanup; goto cleanup;
}
goto exit; goto exit;
......
...@@ -255,6 +255,7 @@ int mdiobus_register(struct mii_bus *bus) ...@@ -255,6 +255,7 @@ int mdiobus_register(struct mii_bus *bus)
bus->dev.parent = bus->parent; bus->dev.parent = bus->parent;
bus->dev.class = &mdio_bus_class; bus->dev.class = &mdio_bus_class;
bus->dev.driver = bus->parent->driver;
bus->dev.groups = NULL; bus->dev.groups = NULL;
dev_set_name(&bus->dev, "%s", bus->id); dev_set_name(&bus->dev, "%s", bus->id);
......
...@@ -355,7 +355,7 @@ int phy_device_register(struct phy_device *phydev) ...@@ -355,7 +355,7 @@ int phy_device_register(struct phy_device *phydev)
phydev->bus->phy_map[phydev->addr] = phydev; phydev->bus->phy_map[phydev->addr] = phydev;
/* Run all of the fixups for this PHY */ /* Run all of the fixups for this PHY */
err = phy_init_hw(phydev); err = phy_scan_fixups(phydev);
if (err) { if (err) {
pr_err("PHY %d failed to initialize\n", phydev->addr); pr_err("PHY %d failed to initialize\n", phydev->addr);
goto out; goto out;
...@@ -575,6 +575,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, ...@@ -575,6 +575,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
u32 flags, phy_interface_t interface) u32 flags, phy_interface_t interface)
{ {
struct device *d = &phydev->dev; struct device *d = &phydev->dev;
struct module *bus_module;
int err; int err;
/* Assume that if there is no driver, that it doesn't /* Assume that if there is no driver, that it doesn't
...@@ -599,6 +600,14 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, ...@@ -599,6 +600,14 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
return -EBUSY; return -EBUSY;
} }
/* Increment the bus module reference count */
bus_module = phydev->bus->dev.driver ?
phydev->bus->dev.driver->owner : NULL;
if (!try_module_get(bus_module)) {
dev_err(&dev->dev, "failed to get the bus module\n");
return -EIO;
}
phydev->attached_dev = dev; phydev->attached_dev = dev;
dev->phydev = phydev; dev->phydev = phydev;
...@@ -664,6 +673,10 @@ EXPORT_SYMBOL(phy_attach); ...@@ -664,6 +673,10 @@ EXPORT_SYMBOL(phy_attach);
void phy_detach(struct phy_device *phydev) void phy_detach(struct phy_device *phydev)
{ {
int i; int i;
if (phydev->bus->dev.driver)
module_put(phydev->bus->dev.driver->owner);
phydev->attached_dev->phydev = NULL; phydev->attached_dev->phydev = NULL;
phydev->attached_dev = NULL; phydev->attached_dev = NULL;
phy_suspend(phydev); phy_suspend(phydev);
......
...@@ -341,6 +341,22 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -341,6 +341,22 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
usb_driver_release_interface(driver, info->data); usb_driver_release_interface(driver, info->data);
return -ENODEV; return -ENODEV;
} }
/* Some devices don't initialise properly. In particular
* the packet filter is not reset. There are devices that
* don't do reset all the way. So the packet filter should
* be set to a sane initial value.
*/
usb_control_msg(dev->udev,
usb_sndctrlpipe(dev->udev, 0),
USB_CDC_SET_ETHERNET_PACKET_FILTER,
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
USB_CDC_PACKET_TYPE_ALL_MULTICAST | USB_CDC_PACKET_TYPE_DIRECTED | USB_CDC_PACKET_TYPE_BROADCAST,
intf->cur_altsetting->desc.bInterfaceNumber,
NULL,
0,
USB_CTRL_SET_TIMEOUT
);
return 0; return 0;
bad_desc: bad_desc:
......
...@@ -85,9 +85,34 @@ static int always_connected (struct usbnet *dev) ...@@ -85,9 +85,34 @@ static int always_connected (struct usbnet *dev)
* *
*-------------------------------------------------------------------------*/ *-------------------------------------------------------------------------*/
static void m5632_recover(struct usbnet *dev)
{
struct usb_device *udev = dev->udev;
struct usb_interface *intf = dev->intf;
int r;
r = usb_lock_device_for_reset(udev, intf);
if (r < 0)
return;
usb_reset_device(udev);
usb_unlock_device(udev);
}
static int dummy_prereset(struct usb_interface *intf)
{
return 0;
}
static int dummy_postreset(struct usb_interface *intf)
{
return 0;
}
static const struct driver_info ali_m5632_info = { static const struct driver_info ali_m5632_info = {
.description = "ALi M5632", .description = "ALi M5632",
.flags = FLAG_POINTTOPOINT, .flags = FLAG_POINTTOPOINT,
.recover = m5632_recover,
}; };
#endif #endif
...@@ -332,6 +357,8 @@ static struct usb_driver cdc_subset_driver = { ...@@ -332,6 +357,8 @@ static struct usb_driver cdc_subset_driver = {
.probe = usbnet_probe, .probe = usbnet_probe,
.suspend = usbnet_suspend, .suspend = usbnet_suspend,
.resume = usbnet_resume, .resume = usbnet_resume,
.pre_reset = dummy_prereset,
.post_reset = dummy_postreset,
.disconnect = usbnet_disconnect, .disconnect = usbnet_disconnect,
.id_table = products, .id_table = products,
.disable_hub_initiated_lpm = 1, .disable_hub_initiated_lpm = 1,
......
...@@ -282,7 +282,7 @@ ...@@ -282,7 +282,7 @@
/* USB_DEV_STAT */ /* USB_DEV_STAT */
#define STAT_SPEED_MASK 0x0006 #define STAT_SPEED_MASK 0x0006
#define STAT_SPEED_HIGH 0x0000 #define STAT_SPEED_HIGH 0x0000
#define STAT_SPEED_FULL 0x0001 #define STAT_SPEED_FULL 0x0002
/* USB_TX_AGG */ /* USB_TX_AGG */
#define TX_AGG_MAX_THRESHOLD 0x03 #define TX_AGG_MAX_THRESHOLD 0x03
...@@ -2292,9 +2292,8 @@ static void r8152b_exit_oob(struct r8152 *tp) ...@@ -2292,9 +2292,8 @@ static void r8152b_exit_oob(struct r8152 *tp)
/* rx share fifo credit full threshold */ /* rx share fifo credit full threshold */
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL); ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL);
ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_DEV_STAT); if (tp->udev->speed == USB_SPEED_FULL ||
ocp_data &= STAT_SPEED_MASK; tp->udev->speed == USB_SPEED_LOW) {
if (ocp_data == STAT_SPEED_FULL) {
/* rx share fifo credit near full threshold */ /* rx share fifo credit near full threshold */
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
RXFIFO_THR2_FULL); RXFIFO_THR2_FULL);
......
...@@ -1218,8 +1218,12 @@ void usbnet_tx_timeout (struct net_device *net) ...@@ -1218,8 +1218,12 @@ void usbnet_tx_timeout (struct net_device *net)
unlink_urbs (dev, &dev->txq); unlink_urbs (dev, &dev->txq);
tasklet_schedule (&dev->bh); tasklet_schedule (&dev->bh);
/* this needs to be handled individually because the generic layer
// FIXME: device recovery -- reset? * doesn't know what is sufficient and could not restore private
* information if a remedy of an unconditional reset were used.
*/
if (dev->driver_info->recover)
(dev->driver_info->recover)(dev);
} }
EXPORT_SYMBOL_GPL(usbnet_tx_timeout); EXPORT_SYMBOL_GPL(usbnet_tx_timeout);
......
...@@ -339,7 +339,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan, ...@@ -339,7 +339,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
ndm->ndm_state = fdb->state; ndm->ndm_state = fdb->state;
ndm->ndm_ifindex = vxlan->dev->ifindex; ndm->ndm_ifindex = vxlan->dev->ifindex;
ndm->ndm_flags = fdb->flags; ndm->ndm_flags = fdb->flags;
ndm->ndm_type = NDA_DST; ndm->ndm_type = RTN_UNICAST;
if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr)) if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
goto nla_put_failure; goto nla_put_failure;
......
...@@ -887,6 +887,15 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, ...@@ -887,6 +887,15 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
tx_info = IEEE80211_SKB_CB(skb); tx_info = IEEE80211_SKB_CB(skb);
tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT; tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
/*
* No aggregation session is running, but there may be frames
* from a previous session or a failed attempt in the queue.
* Send them out as normal data frames
*/
if (!tid->active)
tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU;
if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
bf->bf_state.bf_type = 0; bf->bf_state.bf_type = 0;
return bf; return bf;
......
...@@ -1072,8 +1072,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, ...@@ -1072,8 +1072,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
/* Fill the common data for all mac context types */ /* Fill the common data for all mac context types */
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
/* Also enable probe requests to pass */ /*
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); * pass probe requests and beacons from other APs (needed
* for ht protection)
*/
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST |
MAC_FILTER_IN_BEACON);
/* Fill the data specific for ap mode */ /* Fill the data specific for ap mode */
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap, iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap,
...@@ -1094,6 +1098,13 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm, ...@@ -1094,6 +1098,13 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
/* Fill the common data for all mac context types */ /* Fill the common data for all mac context types */
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
/*
* pass probe requests and beacons from other APs (needed
* for ht protection)
*/
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST |
MAC_FILTER_IN_BEACON);
/* Fill the data specific for GO mode */ /* Fill the data specific for GO mode */
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap, iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap,
action == FW_CTXT_ACTION_ADD); action == FW_CTXT_ACTION_ADD);
......
...@@ -303,13 +303,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -303,13 +303,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
} }
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT &&
!iwlwifi_mod_params.uapsd_disable) {
hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
hw->uapsd_queues = IWL_UAPSD_AC_INFO;
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
}
hw->sta_data_size = sizeof(struct iwl_mvm_sta); hw->sta_data_size = sizeof(struct iwl_mvm_sta);
hw->vif_data_size = sizeof(struct iwl_mvm_vif); hw->vif_data_size = sizeof(struct iwl_mvm_vif);
hw->chanctx_data_size = sizeof(u16); hw->chanctx_data_size = sizeof(u16);
......
...@@ -148,6 +148,9 @@ struct driver_info { ...@@ -148,6 +148,9 @@ struct driver_info {
struct sk_buff *(*tx_fixup)(struct usbnet *dev, struct sk_buff *(*tx_fixup)(struct usbnet *dev,
struct sk_buff *skb, gfp_t flags); struct sk_buff *skb, gfp_t flags);
/* recover from timeout */
void (*recover)(struct usbnet *dev);
/* early initialization code, can sleep. This is for minidrivers /* early initialization code, can sleep. This is for minidrivers
* having 'subminidrivers' that need to do extra initialization * having 'subminidrivers' that need to do extra initialization
* right after minidriver have initialized hardware. */ * right after minidriver have initialized hardware. */
......
...@@ -309,16 +309,7 @@ static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb) ...@@ -309,16 +309,7 @@ static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb)
} }
} }
#define IP_IDENTS_SZ 2048u u32 ip_idents_reserve(u32 hash, int segs);
extern atomic_t *ip_idents;
static inline u32 ip_idents_reserve(u32 hash, int segs)
{
atomic_t *id_ptr = ip_idents + hash % IP_IDENTS_SZ;
return atomic_add_return(segs, id_ptr) - segs;
}
void __ip_select_ident(struct iphdr *iph, int segs); void __ip_select_ident(struct iphdr *iph, int segs);
static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, int segs) static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, int segs)
......
...@@ -85,7 +85,7 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, ...@@ -85,7 +85,7 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
{ {
int tot_len; int tot_len;
if (kern_msg->msg_namelen) { if (kern_msg->msg_name && kern_msg->msg_namelen) {
if (mode == VERIFY_READ) { if (mode == VERIFY_READ) {
int err = move_addr_to_kernel(kern_msg->msg_name, int err = move_addr_to_kernel(kern_msg->msg_name,
kern_msg->msg_namelen, kern_msg->msg_namelen,
...@@ -93,10 +93,11 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, ...@@ -93,10 +93,11 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
if (err < 0) if (err < 0)
return err; return err;
} }
if (kern_msg->msg_name) kern_msg->msg_name = kern_address;
kern_msg->msg_name = kern_address; } else {
} else
kern_msg->msg_name = NULL; kern_msg->msg_name = NULL;
kern_msg->msg_namelen = 0;
}
tot_len = iov_from_user_compat_to_kern(kern_iov, tot_len = iov_from_user_compat_to_kern(kern_iov,
(struct compat_iovec __user *)kern_msg->msg_iov, (struct compat_iovec __user *)kern_msg->msg_iov,
......
...@@ -39,7 +39,7 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a ...@@ -39,7 +39,7 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a
{ {
int size, ct, err; int size, ct, err;
if (m->msg_namelen) { if (m->msg_name && m->msg_namelen) {
if (mode == VERIFY_READ) { if (mode == VERIFY_READ) {
void __user *namep; void __user *namep;
namep = (void __user __force *) m->msg_name; namep = (void __user __force *) m->msg_name;
...@@ -48,10 +48,10 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a ...@@ -48,10 +48,10 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a
if (err < 0) if (err < 0)
return err; return err;
} }
if (m->msg_name) m->msg_name = address;
m->msg_name = address;
} else { } else {
m->msg_name = NULL; m->msg_name = NULL;
m->msg_namelen = 0;
} }
size = m->msg_iovlen * sizeof(struct iovec); size = m->msg_iovlen * sizeof(struct iovec);
......
...@@ -2249,7 +2249,7 @@ static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn, ...@@ -2249,7 +2249,7 @@ static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
ndm->ndm_pad1 = 0; ndm->ndm_pad1 = 0;
ndm->ndm_pad2 = 0; ndm->ndm_pad2 = 0;
ndm->ndm_flags = pn->flags | NTF_PROXY; ndm->ndm_flags = pn->flags | NTF_PROXY;
ndm->ndm_type = NDA_DST; ndm->ndm_type = RTN_UNICAST;
ndm->ndm_ifindex = pn->dev->ifindex; ndm->ndm_ifindex = pn->dev->ifindex;
ndm->ndm_state = NUD_NONE; ndm->ndm_state = NUD_NONE;
......
...@@ -457,8 +457,31 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, ...@@ -457,8 +457,31 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
return neigh_create(&arp_tbl, pkey, dev); return neigh_create(&arp_tbl, pkey, dev);
} }
atomic_t *ip_idents __read_mostly; #define IP_IDENTS_SZ 2048u
EXPORT_SYMBOL(ip_idents); struct ip_ident_bucket {
atomic_t id;
u32 stamp32;
};
static struct ip_ident_bucket *ip_idents __read_mostly;
/* In order to protect privacy, we add a perturbation to identifiers
* if one generator is seldom used. This makes hard for an attacker
* to infer how many packets were sent between two points in time.
*/
u32 ip_idents_reserve(u32 hash, int segs)
{
struct ip_ident_bucket *bucket = ip_idents + hash % IP_IDENTS_SZ;
u32 old = ACCESS_ONCE(bucket->stamp32);
u32 now = (u32)jiffies;
u32 delta = 0;
if (old != now && cmpxchg(&bucket->stamp32, old, now) == old)
delta = prandom_u32_max(now - old);
return atomic_add_return(segs + delta, &bucket->id) - segs;
}
EXPORT_SYMBOL(ip_idents_reserve);
void __ip_select_ident(struct iphdr *iph, int segs) void __ip_select_ident(struct iphdr *iph, int segs)
{ {
...@@ -467,7 +490,10 @@ void __ip_select_ident(struct iphdr *iph, int segs) ...@@ -467,7 +490,10 @@ void __ip_select_ident(struct iphdr *iph, int segs)
net_get_random_once(&ip_idents_hashrnd, sizeof(ip_idents_hashrnd)); net_get_random_once(&ip_idents_hashrnd, sizeof(ip_idents_hashrnd));
hash = jhash_1word((__force u32)iph->daddr, ip_idents_hashrnd); hash = jhash_3words((__force u32)iph->daddr,
(__force u32)iph->saddr,
iph->protocol,
ip_idents_hashrnd);
id = ip_idents_reserve(hash, segs); id = ip_idents_reserve(hash, segs);
iph->id = htons(id); iph->id = htons(id);
} }
......
...@@ -545,6 +545,8 @@ static void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) ...@@ -545,6 +545,8 @@ static void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd)); net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd));
hash = __ipv6_addr_jhash(&rt->rt6i_dst.addr, ip6_idents_hashrnd); hash = __ipv6_addr_jhash(&rt->rt6i_dst.addr, ip6_idents_hashrnd);
hash = __ipv6_addr_jhash(&rt->rt6i_src.addr, hash);
id = ip_idents_reserve(hash, 1); id = ip_idents_reserve(hash, 1);
fhdr->identification = htonl(id); fhdr->identification = htonl(id);
} }
......
...@@ -472,12 +472,15 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) ...@@ -472,12 +472,15 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
{ {
struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct rate_control_ref *ref = local->rate_ctrl; struct rate_control_ref *ref = NULL;
struct timespec uptime; struct timespec uptime;
u64 packets = 0; u64 packets = 0;
u32 thr = 0; u32 thr = 0;
int i, ac; int i, ac;
if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
ref = local->rate_ctrl;
sinfo->generation = sdata->local->sta_generation; sinfo->generation = sdata->local->sta_generation;
sinfo->filled = STATION_INFO_INACTIVE_TIME | sinfo->filled = STATION_INFO_INACTIVE_TIME |
......
...@@ -414,6 +414,9 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) ...@@ -414,6 +414,9 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
if (ieee80211_has_order(hdr->frame_control)) if (ieee80211_has_order(hdr->frame_control))
return TX_CONTINUE; return TX_CONTINUE;
if (ieee80211_is_probe_req(hdr->frame_control))
return TX_CONTINUE;
if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
info->hw_queue = tx->sdata->vif.cab_queue; info->hw_queue = tx->sdata->vif.cab_queue;
...@@ -463,6 +466,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) ...@@ -463,6 +466,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
{ {
struct sta_info *sta = tx->sta; struct sta_info *sta = tx->sta;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
struct ieee80211_local *local = tx->local; struct ieee80211_local *local = tx->local;
if (unlikely(!sta)) if (unlikely(!sta))
...@@ -473,6 +477,12 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) ...@@ -473,6 +477,12 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
!(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) { !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
int ac = skb_get_queue_mapping(tx->skb); int ac = skb_get_queue_mapping(tx->skb);
if (ieee80211_is_mgmt(hdr->frame_control) &&
!ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
return TX_CONTINUE;
}
ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n", ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n",
sta->sta.addr, sta->sta.aid, ac); sta->sta.addr, sta->sta.aid, ac);
if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
...@@ -531,19 +541,9 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) ...@@ -531,19 +541,9 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
static ieee80211_tx_result debug_noinline static ieee80211_tx_result debug_noinline
ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
{ {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
return TX_CONTINUE; return TX_CONTINUE;
if (ieee80211_is_mgmt(hdr->frame_control) &&
!ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
if (tx->flags & IEEE80211_TX_UNICAST)
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
return TX_CONTINUE;
}
if (tx->flags & IEEE80211_TX_UNICAST) if (tx->flags & IEEE80211_TX_UNICAST)
return ieee80211_tx_h_unicast_ps_buf(tx); return ieee80211_tx_h_unicast_ps_buf(tx);
else else
......
...@@ -797,7 +797,6 @@ static void ip_vs_conn_expire(unsigned long data) ...@@ -797,7 +797,6 @@ static void ip_vs_conn_expire(unsigned long data)
ip_vs_control_del(cp); ip_vs_control_del(cp);
if (cp->flags & IP_VS_CONN_F_NFCT) { if (cp->flags & IP_VS_CONN_F_NFCT) {
ip_vs_conn_drop_conntrack(cp);
/* Do not access conntracks during subsys cleanup /* Do not access conntracks during subsys cleanup
* because nf_conntrack_find_get can not be used after * because nf_conntrack_find_get can not be used after
* conntrack cleanup for the net. * conntrack cleanup for the net.
......
...@@ -1097,6 +1097,7 @@ void sctp_assoc_update(struct sctp_association *asoc, ...@@ -1097,6 +1097,7 @@ void sctp_assoc_update(struct sctp_association *asoc,
asoc->c = new->c; asoc->c = new->c;
asoc->peer.rwnd = new->peer.rwnd; asoc->peer.rwnd = new->peer.rwnd;
asoc->peer.sack_needed = new->peer.sack_needed; asoc->peer.sack_needed = new->peer.sack_needed;
asoc->peer.auth_capable = new->peer.auth_capable;
asoc->peer.i = new->peer.i; asoc->peer.i = new->peer.i;
sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
asoc->peer.i.initial_tsn, GFP_ATOMIC); asoc->peer.i.initial_tsn, GFP_ATOMIC);
......
...@@ -2094,7 +2094,8 @@ TRACE_EVENT(cfg80211_michael_mic_failure, ...@@ -2094,7 +2094,8 @@ TRACE_EVENT(cfg80211_michael_mic_failure,
MAC_ASSIGN(addr, addr); MAC_ASSIGN(addr, addr);
__entry->key_type = key_type; __entry->key_type = key_type;
__entry->key_id = key_id; __entry->key_id = key_id;
memcpy(__entry->tsc, tsc, 6); if (tsc)
memcpy(__entry->tsc, tsc, 6);
), ),
TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm", TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm",
NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type, NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type,
......
...@@ -2097,6 +2097,8 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, ...@@ -2097,6 +2097,8 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
goto no_transform; goto no_transform;
} }
dst_hold(&xdst->u.dst);
xdst->u.dst.flags |= DST_NOCACHE;
route = xdst->route; route = xdst->route;
} }
} }
......
...@@ -177,9 +177,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, ...@@ -177,9 +177,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
attrs[XFRMA_ALG_AEAD] || attrs[XFRMA_ALG_AEAD] ||
attrs[XFRMA_ALG_CRYPT] || attrs[XFRMA_ALG_CRYPT] ||
attrs[XFRMA_ALG_COMP] || attrs[XFRMA_ALG_COMP] ||
attrs[XFRMA_TFCPAD] || attrs[XFRMA_TFCPAD])
(ntohl(p->id.spi) >= 0x10000))
goto out; goto out;
break; break;
...@@ -207,7 +205,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, ...@@ -207,7 +205,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
attrs[XFRMA_ALG_AUTH] || attrs[XFRMA_ALG_AUTH] ||
attrs[XFRMA_ALG_AUTH_TRUNC] || attrs[XFRMA_ALG_AUTH_TRUNC] ||
attrs[XFRMA_ALG_CRYPT] || attrs[XFRMA_ALG_CRYPT] ||
attrs[XFRMA_TFCPAD]) attrs[XFRMA_TFCPAD] ||
(ntohl(p->id.spi) >= 0x10000))
goto out; goto out;
break; break;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册