Skip to content

Commit

Permalink
Merge remote-tracking branch 'stable/linux-4.4.y' into rpi-4.4.y
Browse files Browse the repository at this point in the history
  • Loading branch information
popcornmix committed Feb 20, 2017
2 parents 8d1dd63 + c50b74d commit e223d71
Show file tree
Hide file tree
Showing 29 changed files with 172 additions and 89 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 4
SUBLEVEL = 49
SUBLEVEL = 50
EXTRAVERSION =
NAME = Blurry Fish Butt

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 @@ -502,8 +502,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
1 change: 1 addition & 0 deletions drivers/net/loopback.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ static void loopback_setup(struct net_device *dev)
{
dev->mtu = 64 * 1024;
dev->hard_header_len = ETH_HLEN; /* 14 */
dev->min_header_len = ETH_HLEN; /* 14 */
dev->addr_len = ETH_ALEN; /* 6 */
dev->type = ARPHRD_LOOPBACK; /* 0x0001*/
dev->flags = IFF_LOOPBACK;
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/macvtap.c
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
ssize_t n;

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 @@ -865,7 +865,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
10 changes: 6 additions & 4 deletions drivers/net/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -1108,9 +1108,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;

n = copy_from_iter(&gso, sizeof(gso), from);
if (n != sizeof(gso))
Expand All @@ -1122,7 +1124,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 @@ -1301,7 +1303,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
7 changes: 3 additions & 4 deletions include/linux/can/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,9 @@ struct can_proto {
extern int can_proto_register(const struct can_proto *cp);
extern void can_proto_unregister(const struct can_proto *cp);

extern int can_rx_register(struct net_device *dev, canid_t can_id,
canid_t mask,
void (*func)(struct sk_buff *, void *),
void *data, char *ident);
int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
void (*func)(struct sk_buff *, void *),
void *data, char *ident, struct sock *sk);

extern void can_rx_unregister(struct net_device *dev, canid_t can_id,
canid_t mask,
Expand Down
4 changes: 4 additions & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,7 @@ enum netdev_priv_flags {
* @mtu: Interface MTU value
* @type: Interface hardware type
* @hard_header_len: Maximum hardware header length.
* @min_header_len: Minimum hardware header length
*
* @needed_headroom: Extra headroom the hardware may need, but not in all
* cases can this be guaranteed
Expand Down Expand Up @@ -1619,6 +1620,7 @@ struct net_device {
unsigned int mtu;
unsigned short type;
unsigned short hard_header_len;
unsigned short min_header_len;

unsigned short needed_headroom;
unsigned short needed_tailroom;
Expand Down Expand Up @@ -2541,6 +2543,8 @@ static inline bool dev_validate_header(const struct net_device *dev,
{
if (likely(len >= dev->hard_header_len))
return true;
if (len < dev->min_header_len)
return false;

if (capable(CAP_SYS_RAWIO)) {
memset(ll_header + len, 0, dev->hard_header_len - len);
Expand Down
4 changes: 4 additions & 0 deletions include/net/cipso_ipv4.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,10 @@ static inline int cipso_v4_validate(const struct sk_buff *skb,
}

for (opt_iter = 6; opt_iter < opt_len;) {
if (opt_iter + 1 == opt_len) {
err_offset = opt_iter;
goto out;
}
tag_len = opt[opt_iter + 1];
if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) {
err_offset = opt_iter + 1;
Expand Down
12 changes: 10 additions & 2 deletions net/can/af_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
* @func: callback function on filter match
* @data: returned parameter for callback function
* @ident: string for calling module identification
* @sk: socket pointer (might be NULL)
*
* Description:
* Invokes the callback function with the received sk_buff and the given
Expand All @@ -468,7 +469,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
*/
int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
void (*func)(struct sk_buff *, void *), void *data,
char *ident)
char *ident, struct sock *sk)
{
struct receiver *r;
struct hlist_head *rl;
Expand Down Expand Up @@ -496,6 +497,7 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
r->func = func;
r->data = data;
r->ident = ident;
r->sk = sk;

hlist_add_head_rcu(&r->list, rl);
d->entries++;
Expand All @@ -520,8 +522,11 @@ EXPORT_SYMBOL(can_rx_register);
static void can_rx_delete_receiver(struct rcu_head *rp)
{
struct receiver *r = container_of(rp, struct receiver, rcu);
struct sock *sk = r->sk;

kmem_cache_free(rcv_cache, r);
if (sk)
sock_put(sk);
}

/**
Expand Down Expand Up @@ -596,8 +601,11 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
spin_unlock(&can_rcvlists_lock);

/* schedule the receiver item for deletion */
if (r)
if (r) {
if (r->sk)
sock_hold(r->sk);
call_rcu(&r->rcu, can_rx_delete_receiver);
}
}
EXPORT_SYMBOL(can_rx_unregister);

Expand Down
3 changes: 2 additions & 1 deletion net/can/af_can.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,14 @@

struct receiver {
struct hlist_node list;
struct rcu_head rcu;
canid_t can_id;
canid_t mask;
unsigned long matches;
void (*func)(struct sk_buff *, void *);
void *data;
char *ident;
struct sock *sk;
struct rcu_head rcu;
};

#define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS)
Expand Down
4 changes: 2 additions & 2 deletions net/can/bcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1179,7 +1179,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
err = can_rx_register(dev, op->can_id,
REGMASK(op->can_id),
bcm_rx_handler, op,
"bcm");
"bcm", sk);

op->rx_reg_dev = dev;
dev_put(dev);
Expand All @@ -1188,7 +1188,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
} else
err = can_rx_register(NULL, op->can_id,
REGMASK(op->can_id),
bcm_rx_handler, op, "bcm");
bcm_rx_handler, op, "bcm", sk);
if (err) {
/* this bcm rx op is broken -> remove it */
list_del(&op->list);
Expand Down
2 changes: 1 addition & 1 deletion net/can/gw.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ static inline int cgw_register_filter(struct cgw_job *gwj)
{
return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id,
gwj->ccgw.filter.can_mask, can_can_gw_rcv,
gwj, "gw");
gwj, "gw", NULL);
}

static inline void cgw_unregister_filter(struct cgw_job *gwj)
Expand Down
4 changes: 2 additions & 2 deletions net/can/raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ static int raw_enable_filters(struct net_device *dev, struct sock *sk,
for (i = 0; i < count; i++) {
err = can_rx_register(dev, filter[i].can_id,
filter[i].can_mask,
raw_rcv, sk, "raw");
raw_rcv, sk, "raw", sk);
if (err) {
/* clean up successfully registered filters */
while (--i >= 0)
Expand All @@ -211,7 +211,7 @@ static int raw_enable_errfilter(struct net_device *dev, struct sock *sk,

if (err_mask)
err = can_rx_register(dev, 0, err_mask | CAN_ERR_FLAG,
raw_rcv, sk, "raw");
raw_rcv, sk, "raw", sk);

return err;
}
Expand Down
31 changes: 13 additions & 18 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1676,37 +1676,32 @@ EXPORT_SYMBOL_GPL(net_dec_ingress_queue);

static struct static_key netstamp_needed __read_mostly;
#ifdef HAVE_JUMP_LABEL
/* We are not allowed to call static_key_slow_dec() from irq context
* If net_disable_timestamp() is called from irq context, defer the
* static_key_slow_dec() calls.
*/
static atomic_t netstamp_needed_deferred;
#endif

void net_enable_timestamp(void)
static void netstamp_clear(struct work_struct *work)
{
#ifdef HAVE_JUMP_LABEL
int deferred = atomic_xchg(&netstamp_needed_deferred, 0);

if (deferred) {
while (--deferred)
static_key_slow_dec(&netstamp_needed);
return;
}
while (deferred--)
static_key_slow_dec(&netstamp_needed);
}
static DECLARE_WORK(netstamp_work, netstamp_clear);
#endif

void net_enable_timestamp(void)
{
static_key_slow_inc(&netstamp_needed);
}
EXPORT_SYMBOL(net_enable_timestamp);

void net_disable_timestamp(void)
{
#ifdef HAVE_JUMP_LABEL
if (in_interrupt()) {
atomic_inc(&netstamp_needed_deferred);
return;
}
#endif
/* net_disable_timestamp() can be called from non process context */
atomic_inc(&netstamp_needed_deferred);
schedule_work(&netstamp_work);
#else
static_key_slow_dec(&netstamp_needed);
#endif
}
EXPORT_SYMBOL(net_disable_timestamp);

Expand Down
1 change: 1 addition & 0 deletions net/ethernet/eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ void ether_setup(struct net_device *dev)
dev->header_ops = &eth_header_ops;
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
dev->min_header_len = ETH_HLEN;
dev->mtu = ETH_DATA_LEN;
dev->addr_len = ETH_ALEN;
dev->tx_queue_len = 1000; /* Ethernet wants good queues */
Expand Down
4 changes: 4 additions & 0 deletions net/ipv4/cipso_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -1657,6 +1657,10 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option)
goto validate_return_locked;
}

if (opt_iter + 1 == opt_len) {
err_offset = opt_iter;
goto validate_return_locked;
}
tag_len = tag[1];
if (tag_len > (opt_len - opt_iter)) {
err_offset = opt_iter + 1;
Expand Down
9 changes: 8 additions & 1 deletion net/ipv4/ip_sockglue.c
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,14 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
pktinfo->ipi_ifindex = 0;
pktinfo->ipi_spec_dst.s_addr = 0;
}
skb_dst_drop(skb);
/* We need to keep the dst for __ip_options_echo()
* We could restrict the test to opt.ts_needtime || opt.srr,
* but the following is good enough as IP options are not often used.
*/
if (unlikely(IPCB(skb)->opt.optlen))
skb_dst_force(skb);
else
skb_dst_drop(skb);
}

int ip_setsockopt(struct sock *sk, int level,
Expand Down
2 changes: 2 additions & 0 deletions net/ipv4/ping.c
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,8 @@ static int ping_v4_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh,
{
struct sk_buff *skb = skb_peek(&sk->sk_write_queue);

if (!skb)
return 0;
pfh->wcheck = csum_partial((char *)&pfh->icmph,
sizeof(struct icmphdr), pfh->wcheck);
pfh->icmph.checksum = csum_fold(pfh->wcheck);
Expand Down
6 changes: 6 additions & 0 deletions net/ipv4/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,12 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,
ret = -EAGAIN;
break;
}
/* if __tcp_splice_read() got nothing while we have
* an skb in receive queue, we do not want to loop.
* This might happen with URG data.
*/
if (!skb_queue_empty(&sk->sk_receive_queue))
break;
sk_wait_data(sk, &timeo, NULL);
if (signal_pending(current)) {
ret = sock_intr_errno(timeo);
Expand Down
6 changes: 4 additions & 2 deletions net/ipv4/tcp_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -2383,9 +2383,11 @@ u32 __tcp_select_window(struct sock *sk)
int full_space = min_t(int, tp->window_clamp, allowed_space);
int window;

if (mss > full_space)
if (unlikely(mss > full_space)) {
mss = full_space;

if (mss <= 0)
return 0;
}
if (free_space < (full_space >> 1)) {
icsk->icsk_ack.quick = 0;

Expand Down

0 comments on commit e223d71

Please sign in to comment.