Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Browse files Browse the repository at this point in the history
Pull networking fixes from David Miller:

 1) Load correct firmware in rtl8192ce wireless driver, from Jurij
    Smakov.

 2) Fix leak of tx_ring and tx_cq due to overwriting in mlx4 driver,
    from Martin KaFai Lau.

 3) Need to reference count PHY driver module when it is attached, from
    Mao Wenan.

 4) Don't do zero length vzalloc() in ethtool register dump, from
    Stanislaw Gruszka.

 5) Defer net_disable_timestamp() to a workqueue to get out of locking
    issues, from Eric Dumazet.

 6) We cannot drop the SKB dst when IP options refer to them, fix also
    from Eric Dumazet.

 7) Incorrect packet header offset calculations in ip6_gre, again from
    Eric Dumazet.

 8) Missing tcp_v6_restore_cb() causes use-after-free, from Eric too.

 9) tcp_splice_read() can get into an infinite loop with URG, and hey
    it's from Eric once more.

10) vnet_hdr_sz can change asynchronously, so read it once during
    decision making in macvtap and tun, from Willem de Bruijn.

11) Can't use kernel stack for DMA transfers in USB networking drivers,
    from Ben Hutchings.

12) Handle csum errors properly in UDP by calling the proper destructor,
    from Eric Dumazet.

13) For non-deterministic softirq run when scheduling NAPI from a
    workqueue in mlx4, from Benjamin Poirier.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (28 commits)
  sctp: check af before verify address in sctp_addr_id2transport
  sctp: avoid BUG_ON on sctp_wait_for_sndbuf
  mlx4: Invoke softirqs after napi_reschedule
  udp: properly cope with csum errors
  catc: Use heap buffer for memory size test
  catc: Combine failure cleanup code in catc_probe()
  rtl8150: Use heap buffers for all register access
  pegasus: Use heap buffers for all register access
  macvtap: read vnet_hdr_size once
  tun: read vnet_hdr_sz once
  tcp: avoid infinite loop in tcp_splice_read()
  hns: avoid stack overflow with CONFIG_KASAN
  ipv6: Fix IPv6 packet loss in scenarios involving roaming + snooping switches
  ipv6: tcp: add a missing tcp_v6_restore_cb()
  nl80211: Fix mesh HT operation check
  mac80211: Fix adding of mesh vendor IEs
  mac80211: Allocate a sync skcipher explicitly for FILS AEAD
  mac80211: Fix FILS AEAD protection in Association Request frame
  ip6_gre: fix ip6gre_err() invalid reads
  netlabel: out of bound access in cipso_v4_validate()
  ...
  • Loading branch information
torvalds committed Feb 7, 2017
2 parents b678912 + 912964e commit 926af62
Show file tree
Hide file tree
Showing 32 changed files with 255 additions and 164 deletions.
8 changes: 2 additions & 6 deletions drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -1014,19 +1014,15 @@

static inline void dsaf_write_reg(void __iomem *base, u32 reg, u32 value)
{
u8 __iomem *reg_addr = ACCESS_ONCE(base);

writel(value, reg_addr + reg);
writel(value, base + reg);
}

#define dsaf_write_dev(a, reg, value) \
dsaf_write_reg((a)->io_base, (reg), (value))

static inline u32 dsaf_read_reg(u8 __iomem *base, u32 reg)
{
u8 __iomem *reg_addr = ACCESS_ONCE(base);

return readl(reg_addr + reg);
return readl(base + reg);
}

static inline void dsaf_write_syscon(struct regmap *base, u32 reg, u32 value)
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1099,7 +1099,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
new_prof.tx_ring_size = tx_size;
new_prof.rx_ring_size = rx_size;
err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true);
if (err)
goto out;

Expand Down Expand Up @@ -1774,7 +1774,7 @@ static int mlx4_en_set_channels(struct net_device *dev,
new_prof.tx_ring_num[TX_XDP] = xdp_count;
new_prof.rx_ring_num = channel->rx_count;

err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true);
if (err)
goto out;

Expand Down
35 changes: 25 additions & 10 deletions drivers/net/ethernet/mellanox/mlx4/en_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2042,6 +2042,8 @@ static void mlx4_en_free_resources(struct mlx4_en_priv *priv)
if (priv->tx_cq[t] && priv->tx_cq[t][i])
mlx4_en_destroy_cq(priv, &priv->tx_cq[t][i]);
}
kfree(priv->tx_ring[t]);
kfree(priv->tx_cq[t]);
}

for (i = 0; i < priv->rx_ring_num; i++) {
Expand Down Expand Up @@ -2184,9 +2186,11 @@ static void mlx4_en_update_priv(struct mlx4_en_priv *dst,

int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv,
struct mlx4_en_priv *tmp,
struct mlx4_en_port_profile *prof)
struct mlx4_en_port_profile *prof,
bool carry_xdp_prog)
{
int t;
struct bpf_prog *xdp_prog;
int i, t;

mlx4_en_copy_priv(tmp, priv, prof);

Expand All @@ -2200,6 +2204,23 @@ int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv,
}
return -ENOMEM;
}

/* All rx_rings has the same xdp_prog. Pick the first one. */
xdp_prog = rcu_dereference_protected(
priv->rx_ring[0]->xdp_prog,
lockdep_is_held(&priv->mdev->state_lock));

if (xdp_prog && carry_xdp_prog) {
xdp_prog = bpf_prog_add(xdp_prog, tmp->rx_ring_num);
if (IS_ERR(xdp_prog)) {
mlx4_en_free_resources(tmp);
return PTR_ERR(xdp_prog);
}
for (i = 0; i < tmp->rx_ring_num; i++)
rcu_assign_pointer(tmp->rx_ring[i]->xdp_prog,
xdp_prog);
}

return 0;
}

Expand All @@ -2214,7 +2235,6 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
int t;

en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);

Expand Down Expand Up @@ -2248,11 +2268,6 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
mlx4_en_free_resources(priv);
mutex_unlock(&mdev->state_lock);

for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
kfree(priv->tx_ring[t]);
kfree(priv->tx_cq[t]);
}

free_netdev(dev);
}

Expand Down Expand Up @@ -2755,7 +2770,7 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog)
en_warn(priv, "Reducing the number of TX rings, to not exceed the max total rings number.\n");
}

err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, false);
if (err) {
if (prog)
bpf_prog_sub(prog, priv->rx_ring_num - 1);
Expand Down Expand Up @@ -3499,7 +3514,7 @@ int mlx4_en_reset_config(struct net_device *dev,
memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
memcpy(&new_prof.hwtstamp_config, &ts_config, sizeof(ts_config));

err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true);
if (err)
goto out;

Expand Down
5 changes: 4 additions & 1 deletion drivers/net/ethernet/mellanox/mlx4/en_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -514,8 +514,11 @@ void mlx4_en_recover_from_oom(struct mlx4_en_priv *priv)
return;

for (ring = 0; ring < priv->rx_ring_num; ring++) {
if (mlx4_en_is_ring_empty(priv->rx_ring[ring]))
if (mlx4_en_is_ring_empty(priv->rx_ring[ring])) {
local_bh_disable();
napi_reschedule(&priv->rx_cq[ring]->napi);
local_bh_enable();
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,8 @@ void mlx4_en_set_stats_bitmap(struct mlx4_dev *dev,

int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv,
struct mlx4_en_priv *tmp,
struct mlx4_en_port_profile *prof);
struct mlx4_en_port_profile *prof,
bool carry_xdp_prog);
void mlx4_en_safe_replace_resources(struct mlx4_en_priv *priv,
struct mlx4_en_priv *tmp);

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/macvtap.c
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
size_t linear;

if (q->flags & IFF_VNET_HDR) {
vnet_hdr_len = q->vnet_hdr_sz;
vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);

err = -EINVAL;
if (len < vnet_hdr_len)
Expand Down Expand Up @@ -820,7 +820,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,

if (q->flags & IFF_VNET_HDR) {
struct virtio_net_hdr vnet_hdr;
vnet_hdr_len = q->vnet_hdr_sz;
vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
if (iov_iter_count(iter) < vnet_hdr_len)
return -EINVAL;

Expand Down
7 changes: 7 additions & 0 deletions drivers/net/phy/phy_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,11 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
return -EIO;
}

if (!try_module_get(d->driver->owner)) {
dev_err(&dev->dev, "failed to get the device driver module\n");
return -EIO;
}

get_device(d);

/* Assume that if there is no driver, that it doesn't
Expand Down Expand Up @@ -977,6 +982,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
error:
phy_detach(phydev);
put_device(d);
module_put(d->driver->owner);
if (ndev_owner != bus->owner)
module_put(bus->owner);
return err;
Expand Down Expand Up @@ -1059,6 +1065,7 @@ void phy_detach(struct phy_device *phydev)
bus = phydev->mdio.bus;

put_device(&phydev->mdio.dev);
module_put(phydev->mdio.dev.driver->owner);
if (ndev_owner != bus->owner)
module_put(bus->owner);
}
Expand Down
10 changes: 6 additions & 4 deletions drivers/net/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -1170,9 +1170,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
}

if (tun->flags & IFF_VNET_HDR) {
if (len < tun->vnet_hdr_sz)
int vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz);

if (len < vnet_hdr_sz)
return -EINVAL;
len -= tun->vnet_hdr_sz;
len -= vnet_hdr_sz;

if (!copy_from_iter_full(&gso, sizeof(gso), from))
return -EFAULT;
Expand All @@ -1183,7 +1185,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,

if (tun16_to_cpu(tun, gso.hdr_len) > len)
return -EINVAL;
iov_iter_advance(from, tun->vnet_hdr_sz - sizeof(gso));
iov_iter_advance(from, vnet_hdr_sz - sizeof(gso));
}

if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP) {
Expand Down Expand Up @@ -1335,7 +1337,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
vlan_hlen = VLAN_HLEN;

if (tun->flags & IFF_VNET_HDR)
vnet_hdr_sz = tun->vnet_hdr_sz;
vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz);

total = skb->len + vlan_hlen + vnet_hdr_sz;

Expand Down
56 changes: 34 additions & 22 deletions drivers/net/usb/catc.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
struct net_device *netdev;
struct catc *catc;
u8 broadcast[ETH_ALEN];
int i, pktsz;
int pktsz, ret;

if (usb_set_interface(usbdev,
intf->altsetting->desc.bInterfaceNumber, 1)) {
Expand Down Expand Up @@ -811,12 +811,8 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
(!catc->rx_urb) || (!catc->irq_urb)) {
dev_err(&intf->dev, "No free urbs available.\n");
usb_free_urb(catc->ctrl_urb);
usb_free_urb(catc->tx_urb);
usb_free_urb(catc->rx_urb);
usb_free_urb(catc->irq_urb);
free_netdev(netdev);
return -ENOMEM;
ret = -ENOMEM;
goto fail_free;
}

/* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
Expand Down Expand Up @@ -844,15 +840,24 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
catc->irq_buf, 2, catc_irq_done, catc, 1);

if (!catc->is_f5u011) {
u32 *buf;
int i;

dev_dbg(dev, "Checking memory size\n");

i = 0x12345678;
catc_write_mem(catc, 0x7a80, &i, 4);
i = 0x87654321;
catc_write_mem(catc, 0xfa80, &i, 4);
catc_read_mem(catc, 0x7a80, &i, 4);
buf = kmalloc(4, GFP_KERNEL);
if (!buf) {
ret = -ENOMEM;
goto fail_free;
}

*buf = 0x12345678;
catc_write_mem(catc, 0x7a80, buf, 4);
*buf = 0x87654321;
catc_write_mem(catc, 0xfa80, buf, 4);
catc_read_mem(catc, 0x7a80, buf, 4);

switch (i) {
switch (*buf) {
case 0x12345678:
catc_set_reg(catc, TxBufCount, 8);
catc_set_reg(catc, RxBufCount, 32);
Expand All @@ -867,6 +872,8 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
dev_dbg(dev, "32k Memory\n");
break;
}

kfree(buf);

dev_dbg(dev, "Getting MAC from SEEROM.\n");

Expand Down Expand Up @@ -913,16 +920,21 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
usb_set_intfdata(intf, catc);

SET_NETDEV_DEV(netdev, &intf->dev);
if (register_netdev(netdev) != 0) {
usb_set_intfdata(intf, NULL);
usb_free_urb(catc->ctrl_urb);
usb_free_urb(catc->tx_urb);
usb_free_urb(catc->rx_urb);
usb_free_urb(catc->irq_urb);
free_netdev(netdev);
return -EIO;
}
ret = register_netdev(netdev);
if (ret)
goto fail_clear_intfdata;

return 0;

fail_clear_intfdata:
usb_set_intfdata(intf, NULL);
fail_free:
usb_free_urb(catc->ctrl_urb);
usb_free_urb(catc->tx_urb);
usb_free_urb(catc->rx_urb);
usb_free_urb(catc->irq_urb);
free_netdev(netdev);
return ret;
}

static void catc_disconnect(struct usb_interface *intf)
Expand Down
29 changes: 25 additions & 4 deletions drivers/net/usb/pegasus.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,40 +126,61 @@ static void async_ctrl_callback(struct urb *urb)

static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
{
u8 *buf;
int ret;

buf = kmalloc(size, GFP_NOIO);
if (!buf)
return -ENOMEM;

ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0),
PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0,
indx, data, size, 1000);
indx, buf, size, 1000);
if (ret < 0)
netif_dbg(pegasus, drv, pegasus->net,
"%s returned %d\n", __func__, ret);
else if (ret <= size)
memcpy(data, buf, ret);
kfree(buf);
return ret;
}

static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size,
const void *data)
{
u8 *buf;
int ret;

buf = kmemdup(data, size, GFP_NOIO);
if (!buf)
return -ENOMEM;

ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0,
indx, data, size, 100);
indx, buf, size, 100);
if (ret < 0)
netif_dbg(pegasus, drv, pegasus->net,
"%s returned %d\n", __func__, ret);
kfree(buf);
return ret;
}

static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data)
{
u8 *buf;
int ret;

buf = kmemdup(&data, 1, GFP_NOIO);
if (!buf)
return -ENOMEM;

ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data,
indx, &data, 1, 1000);
indx, buf, 1, 1000);
if (ret < 0)
netif_dbg(pegasus, drv, pegasus->net,
"%s returned %d\n", __func__, ret);
kfree(buf);
return ret;
}

Expand Down
Loading

0 comments on commit 926af62

Please sign in to comment.