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:
 "A couple interesting SKB fragment handling fixes, plus the usual small
  bits here and there:

   1) Fix 64-bit divide build failure on 32-bit platforms in mlx5, from
      Tim Gardner.

   2) Get rid of a stupid reimplementation on "%*phC" in our sysfs MAC
      address printing helper.

   3) Fix NETIF_F_SG capability advertisement in hyperv driver, if the
      device can't do checksumming offloads then it shouldn't say it can
      do SG either.  From Haiyang Zhang.

   4) bgmac needs to depend on PHYLIB, from Hauke Mehrtens.

   5) Don't leak DMA mappings on mapping failures, from Neil Horman.

   6) We need to reset the transport header of SKBs in ipv4 before we
      attempt to perform early socket demux, just like ipv6 does.  From
      Eric Dumazet.

   7) Add missing locking on vxlan device removal, from Stephen
      Hemminger.

   8) xen-netfront has to make two passes over an SKB to prepare it for
      transfer.  One pass calculates the number of slots needed, the
      second massages the SKB and fills the slots.  Unfortunately, the
      first pass doesn't calculate the number of slots properly so we
      can end up trying to build a MAX_SKB_FRAGS + 1 SKB which doesn't
      work out so well.  Fix from Jan Beulich with help and discussion
      with several others.

   9) Fix a similar problem in tun and macvtap, which have to split up
      scatter-gather elements at PAGE_SIZE boundaries.  Don't do
      zerocopy if it would result in a > MAX_SKB_FRAGS skb.  Fixes from
      Jason Wang.

  10) On receive, once we've decoded the VLAN state completely, clear
      skb->vlan_tci.  Otherwise demuxed tunnels underneath can trigger
      the VLAN code again, corrupting the packet.  Fix from Eric
      Dumazet"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
  vlan: fix a race in egress prio management
  vlan: mask vlan prio bits
  macvtap: do not zerocopy if iov needs more pages than MAX_SKB_FRAGS
  tuntap: do not zerocopy if iov needs more pages than MAX_SKB_FRAGS
  pkt_sched: sch_qfq: remove a source of high packet delay/jitter
  xen-netfront: pull on receive skb may need to happen earlier
  vxlan: add necessary locking on device removal
  hyperv: Fix the NETIF_F_SG flag setting in netvsc
  net: Fix sysfs_format_mac() code duplication.
  be2net: Fix to avoid hardware workaround when not needed
  macvtap: do not assume 802.1Q when send vlan packets
  macvtap: fix the missing ret value of TUNSETQUEUE
  ipv4: set transport header earlier
  mlx5 core: Fix __udivdi3 when compiling for 32 bit arches
  bgmac: add dependency to phylib
  net/irda: fixed style issues in irlan_eth
  ethtool: fixed trailing statements in ethtool
  ndisc: bool initializations should use true and false
  atl1e: unmap partially mapped skb on dma error and free skb
  • Loading branch information
Linus Torvalds committed Jul 19, 2013
2 parents ee114b9 + 3e3aac4 commit ecb2cf1
Show file tree
Hide file tree
Showing 19 changed files with 248 additions and 164 deletions.
24 changes: 23 additions & 1 deletion drivers/net/ethernet/atheros/atl1e/atl1e_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1678,6 +1678,7 @@ static int atl1e_tx_map(struct atl1e_adapter *adapter,
u16 f;
int segment;
int ring_start = adapter->tx_ring.next_to_use;
int ring_end;

nr_frags = skb_shinfo(skb)->nr_frags;
segment = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
Expand Down Expand Up @@ -1721,6 +1722,15 @@ static int atl1e_tx_map(struct atl1e_adapter *adapter,
map_len, PCI_DMA_TODEVICE);

if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) {
/* We need to unwind the mappings we've done */
ring_end = adapter->tx_ring.next_to_use;
adapter->tx_ring.next_to_use = ring_start;
while (adapter->tx_ring.next_to_use != ring_end) {
tpd = atl1e_get_tpd(adapter);
tx_buffer = atl1e_get_tx_buffer(adapter, tpd);
pci_unmap_single(adapter->pdev, tx_buffer->dma,
tx_buffer->length, PCI_DMA_TODEVICE);
}
/* Reset the tx rings next pointer */
adapter->tx_ring.next_to_use = ring_start;
return -ENOSPC;
Expand Down Expand Up @@ -1763,6 +1773,16 @@ static int atl1e_tx_map(struct atl1e_adapter *adapter,
DMA_TO_DEVICE);

if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) {
/* We need to unwind the mappings we've done */
ring_end = adapter->tx_ring.next_to_use;
adapter->tx_ring.next_to_use = ring_start;
while (adapter->tx_ring.next_to_use != ring_end) {
tpd = atl1e_get_tpd(adapter);
tx_buffer = atl1e_get_tx_buffer(adapter, tpd);
dma_unmap_page(&adapter->pdev->dev, tx_buffer->dma,
tx_buffer->length, DMA_TO_DEVICE);
}

/* Reset the ring next to use pointer */
adapter->tx_ring.next_to_use = ring_start;
return -ENOSPC;
Expand Down Expand Up @@ -1853,8 +1873,10 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb,
return NETDEV_TX_OK;
}

if (atl1e_tx_map(adapter, skb, tpd))
if (atl1e_tx_map(adapter, skb, tpd)) {
dev_kfree_skb_any(skb);
goto out;
}

atl1e_tx_queue(adapter, tpd_req, tpd);

Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/broadcom/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ config BNX2X_SRIOV
config BGMAC
tristate "BCMA bus GBit core support"
depends on BCMA_HOST_SOC && HAS_DMA
select PHYLIB
---help---
This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus.
They can be found on BCM47xx SoCs and provide gigabit ethernet.
Expand Down
14 changes: 10 additions & 4 deletions drivers/net/ethernet/emulex/benet/be_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -782,16 +782,22 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,

if (vlan_tx_tag_present(skb))
vlan_tag = be_get_tx_vlan_tag(adapter, skb);
else if (qnq_async_evt_rcvd(adapter) && adapter->pvid)
vlan_tag = adapter->pvid;

if (qnq_async_evt_rcvd(adapter) && adapter->pvid) {
if (!vlan_tag)
vlan_tag = adapter->pvid;
/* f/w workaround to set skip_hw_vlan = 1, informs the F/W to
* skip VLAN insertion
*/
if (skip_hw_vlan)
*skip_hw_vlan = true;
}

if (vlan_tag) {
skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
if (unlikely(!skb))
return skb;
skb->vlan_tci = 0;
if (skip_hw_vlan)
*skip_hw_vlan = true;
}

/* Insert the outer VLAN, if any */
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ static ssize_t average_read(struct file *filp, char __user *buf, size_t count,
stats = filp->private_data;
spin_lock(&stats->lock);
if (stats->n)
field = stats->sum / stats->n;
field = div64_u64(stats->sum, stats->n);
spin_unlock(&stats->lock);
ret = snprintf(tbuf, sizeof(tbuf), "%llu\n", field);
if (ret > 0) {
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/hyperv/netvsc_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,8 @@ static int netvsc_probe(struct hv_device *dev,
net->netdev_ops = &device_ops;

/* TODO: Add GSO and Checksum offload */
net->hw_features = NETIF_F_SG;
net->features = NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_TX;
net->hw_features = 0;
net->features = NETIF_F_HW_VLAN_CTAG_TX;

SET_ETHTOOL_OPS(net, &ethtool_ops);
SET_NETDEV_DEV(net, &dev->device);
Expand Down
65 changes: 39 additions & 26 deletions drivers/net/macvtap.c
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,28 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
return 0;
}

static unsigned long iov_pages(const struct iovec *iv, int offset,
unsigned long nr_segs)
{
unsigned long seg, base;
int pages = 0, len, size;

while (nr_segs && (offset >= iv->iov_len)) {
offset -= iv->iov_len;
++iv;
--nr_segs;
}

for (seg = 0; seg < nr_segs; seg++) {
base = (unsigned long)iv[seg].iov_base + offset;
len = iv[seg].iov_len - offset;
size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
pages += size;
offset = 0;
}

return pages;
}

/* Get packet from user space buffer */
static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
Expand Down Expand Up @@ -744,31 +766,15 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
if (unlikely(count > UIO_MAXIOV))
goto err;

if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY))
zerocopy = true;

if (zerocopy) {
/* Userspace may produce vectors with count greater than
* MAX_SKB_FRAGS, so we need to linearize parts of the skb
* to let the rest of data to be fit in the frags.
*/
if (count > MAX_SKB_FRAGS) {
copylen = iov_length(iv, count - MAX_SKB_FRAGS);
if (copylen < vnet_hdr_len)
copylen = 0;
else
copylen -= vnet_hdr_len;
}
/* There are 256 bytes to be copied in skb, so there is enough
* room for skb expand head in case it is used.
* The rest buffer is mapped from userspace.
*/
if (copylen < vnet_hdr.hdr_len)
copylen = vnet_hdr.hdr_len;
if (!copylen)
copylen = GOODCOPY_LEN;
if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) {
copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN;
linear = copylen;
} else {
if (iov_pages(iv, vnet_hdr_len + copylen, count)
<= MAX_SKB_FRAGS)
zerocopy = true;
}

if (!zerocopy) {
copylen = len;
linear = vnet_hdr.hdr_len;
}
Expand All @@ -780,9 +786,15 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,

if (zerocopy)
err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count);
else
else {
err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len,
len);
if (!err && m && m->msg_control) {
struct ubuf_info *uarg = m->msg_control;
uarg->callback(uarg, false);
}
}

if (err)
goto err_kfree;

Expand Down Expand Up @@ -873,7 +885,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
__be16 h_vlan_proto;
__be16 h_vlan_TCI;
} veth;
veth.h_vlan_proto = htons(ETH_P_8021Q);
veth.h_vlan_proto = skb->vlan_proto;
veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb));

vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
Expand Down Expand Up @@ -1107,6 +1119,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
rtnl_lock();
ret = macvtap_ioctl_set_queue(file, u);
rtnl_unlock();
return ret;

case TUNGETFEATURES:
if (put_user(IFF_TAP | IFF_NO_PI | IFF_VNET_HDR |
Expand Down
62 changes: 38 additions & 24 deletions drivers/net/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,29 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
return 0;
}

static unsigned long iov_pages(const struct iovec *iv, int offset,
unsigned long nr_segs)
{
unsigned long seg, base;
int pages = 0, len, size;

while (nr_segs && (offset >= iv->iov_len)) {
offset -= iv->iov_len;
++iv;
--nr_segs;
}

for (seg = 0; seg < nr_segs; seg++) {
base = (unsigned long)iv[seg].iov_base + offset;
len = iv[seg].iov_len - offset;
size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
pages += size;
offset = 0;
}

return pages;
}

/* Get packet from user space buffer */
static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
void *msg_control, const struct iovec *iv,
Expand Down Expand Up @@ -1082,32 +1105,18 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
return -EINVAL;
}

if (msg_control)
zerocopy = true;

if (zerocopy) {
/* Userspace may produce vectors with count greater than
* MAX_SKB_FRAGS, so we need to linearize parts of the skb
* to let the rest of data to be fit in the frags.
*/
if (count > MAX_SKB_FRAGS) {
copylen = iov_length(iv, count - MAX_SKB_FRAGS);
if (copylen < offset)
copylen = 0;
else
copylen -= offset;
} else
copylen = 0;
/* There are 256 bytes to be copied in skb, so there is enough
* room for skb expand head in case it is used.
if (msg_control) {
/* There are 256 bytes to be copied in skb, so there is
* enough room for skb expand head in case it is used.
* The rest of the buffer is mapped from userspace.
*/
if (copylen < gso.hdr_len)
copylen = gso.hdr_len;
if (!copylen)
copylen = GOODCOPY_LEN;
copylen = gso.hdr_len ? gso.hdr_len : GOODCOPY_LEN;
linear = copylen;
} else {
if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS)
zerocopy = true;
}

if (!zerocopy) {
copylen = len;
linear = gso.hdr_len;
}
Expand All @@ -1121,8 +1130,13 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,

if (zerocopy)
err = zerocopy_sg_from_iovec(skb, iv, offset, count);
else
else {
err = skb_copy_datagram_from_iovec(skb, 0, iv, offset, len);
if (!err && msg_control) {
struct ubuf_info *uarg = msg_control;
uarg->callback(uarg, false);
}
}

if (err) {
tun->dev->stats.rx_dropped++;
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1767,9 +1767,15 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,

static void vxlan_dellink(struct net_device *dev, struct list_head *head)
{
struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
struct vxlan_dev *vxlan = netdev_priv(dev);

flush_workqueue(vxlan_wq);

spin_lock(&vn->sock_lock);
hlist_del_rcu(&vxlan->hlist);
spin_unlock(&vn->sock_lock);

list_del(&vxlan->next);
unregister_netdevice_queue(dev, head);
}
Expand Down
31 changes: 13 additions & 18 deletions drivers/net/xen-netfront.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,7 @@ static void xennet_alloc_rx_buffers(struct net_device *dev)
break;
}

__skb_fill_page_desc(skb, 0, page, 0, 0);
skb_shinfo(skb)->nr_frags = 1;
skb_add_rx_frag(skb, 0, page, 0, 0, PAGE_SIZE);
__skb_queue_tail(&np->rx_batch, skb);
}

Expand Down Expand Up @@ -831,7 +830,6 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np,
struct sk_buff_head *list)
{
struct skb_shared_info *shinfo = skb_shinfo(skb);
int nr_frags = shinfo->nr_frags;
RING_IDX cons = np->rx.rsp_cons;
struct sk_buff *nskb;

Expand All @@ -840,19 +838,21 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np,
RING_GET_RESPONSE(&np->rx, ++cons);
skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0];

__skb_fill_page_desc(skb, nr_frags,
skb_frag_page(nfrag),
rx->offset, rx->status);
if (shinfo->nr_frags == MAX_SKB_FRAGS) {
unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to;

skb->data_len += rx->status;
BUG_ON(pull_to <= skb_headlen(skb));
__pskb_pull_tail(skb, pull_to - skb_headlen(skb));
}
BUG_ON(shinfo->nr_frags >= MAX_SKB_FRAGS);

skb_add_rx_frag(skb, shinfo->nr_frags, skb_frag_page(nfrag),
rx->offset, rx->status, PAGE_SIZE);

skb_shinfo(nskb)->nr_frags = 0;
kfree_skb(nskb);

nr_frags++;
}

shinfo->nr_frags = nr_frags;
return cons;
}

Expand Down Expand Up @@ -933,7 +933,8 @@ static int handle_incoming_queue(struct net_device *dev,
while ((skb = __skb_dequeue(rxq)) != NULL) {
int pull_to = NETFRONT_SKB_CB(skb)->pull_to;

__pskb_pull_tail(skb, pull_to - skb_headlen(skb));
if (pull_to > skb_headlen(skb))
__pskb_pull_tail(skb, pull_to - skb_headlen(skb));

/* Ethernet work: Delayed to here as it peeks the header. */
skb->protocol = eth_type_trans(skb, dev);
Expand Down Expand Up @@ -1019,16 +1020,10 @@ static int xennet_poll(struct napi_struct *napi, int budget)
skb_shinfo(skb)->frags[0].page_offset = rx->offset;
skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status);
skb->data_len = rx->status;
skb->len += rx->status;

i = xennet_fill_frags(np, skb, &tmpq);

/*
* Truesize is the actual allocation size, even if the
* allocation is only partially used.
*/
skb->truesize += PAGE_SIZE * skb_shinfo(skb)->nr_frags;
skb->len += skb->data_len;

if (rx->flags & XEN_NETRXF_csum_blank)
skb->ip_summed = CHECKSUM_PARTIAL;
else if (rx->flags & XEN_NETRXF_data_validated)
Expand Down
3 changes: 1 addition & 2 deletions include/linux/if_vlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,8 @@ static inline int is_vlan_dev(struct net_device *dev)
}

#define vlan_tx_tag_present(__skb) ((__skb)->vlan_tci & VLAN_TAG_PRESENT)
#define vlan_tx_nonzero_tag_present(__skb) \
(vlan_tx_tag_present(__skb) && ((__skb)->vlan_tci & VLAN_VID_MASK))
#define vlan_tx_tag_get(__skb) ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
#define vlan_tx_tag_get_id(__skb) ((__skb)->vlan_tci & VLAN_VID_MASK)

#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)

Expand Down
Loading

0 comments on commit ecb2cf1

Please sign in to comment.