diff options
Diffstat (limited to 'net')
81 files changed, 3594 insertions, 969 deletions
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index dd86a1dc4cd..6c132394026 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -3,46 +3,35 @@ #include <linux/if_vlan.h> #include "vlan.h" -struct vlan_hwaccel_cb { - struct net_device *dev; -}; - -static inline struct vlan_hwaccel_cb *vlan_hwaccel_cb(struct sk_buff *skb) -{ - return (struct vlan_hwaccel_cb *)skb->cb; -} - /* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci, int polling) { - struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb); - - if (skb_bond_should_drop(skb)) { - dev_kfree_skb_any(skb); - return NET_RX_DROP; - } + if (skb_bond_should_drop(skb)) + goto drop; skb->vlan_tci = vlan_tci; - cb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); + skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); + + if (!skb->dev) + goto drop; return (polling ? netif_receive_skb(skb) : netif_rx(skb)); + +drop: + dev_kfree_skb_any(skb); + return NET_RX_DROP; } EXPORT_SYMBOL(__vlan_hwaccel_rx); int vlan_hwaccel_do_receive(struct sk_buff *skb) { - struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb); - struct net_device *dev = cb->dev; + struct net_device *dev = skb->dev; struct net_device_stats *stats; + skb->dev = vlan_dev_info(dev)->real_dev; netif_nit_deliver(skb); - if (dev == NULL) { - kfree_skb(skb); - return -1; - } - skb->dev = dev; skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci); skb->vlan_tci = 0; @@ -80,3 +69,79 @@ u16 vlan_dev_vlan_id(const struct net_device *dev) return vlan_dev_info(dev)->vlan_id; } EXPORT_SYMBOL_GPL(vlan_dev_vlan_id); + +static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, + unsigned int vlan_tci, struct sk_buff *skb) +{ + struct sk_buff *p; + + if (skb_bond_should_drop(skb)) + goto drop; + + skb->vlan_tci = vlan_tci; + skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); + + if (!skb->dev) + goto drop; + + for (p = napi->gro_list; p; p = p->next) { + NAPI_GRO_CB(p)->same_flow = p->dev == skb->dev; + NAPI_GRO_CB(p)->flush = 0; + } + + return dev_gro_receive(napi, skb); + +drop: + return 2; +} + +int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, + unsigned int vlan_tci, struct sk_buff *skb) +{ + int err = NET_RX_SUCCESS; + + switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { + case -1: + return netif_receive_skb(skb); + + case 2: + err = NET_RX_DROP; + /* fall through */ + + case 1: + kfree_skb(skb); + break; + } + + return err; +} +EXPORT_SYMBOL(vlan_gro_receive); + +int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, + unsigned int vlan_tci, struct napi_gro_fraginfo *info) +{ + struct sk_buff *skb = napi_fraginfo_skb(napi, info); + int err = NET_RX_DROP; + + if (!skb) + goto out; + + err = NET_RX_SUCCESS; + + switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { + case -1: + return netif_receive_skb(skb); + + case 2: + err = NET_RX_DROP; + /* fall through */ + + case 1: + napi_reuse_skb(napi, skb); + break; + } + +out: + return err; +} +EXPORT_SYMBOL(vlan_gro_frags); diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 89a3bbdfca3..4a19acd3a32 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -546,6 +546,18 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return err; } +static int vlan_dev_neigh_setup(struct net_device *dev, struct neigh_parms *pa) +{ + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; + const struct net_device_ops *ops = real_dev->netdev_ops; + int err = 0; + + if (netif_device_present(real_dev) && ops->ndo_neigh_setup) + err = ops->ndo_neigh_setup(dev, pa); + + return err; +} + static void vlan_dev_change_rx_flags(struct net_device *dev, int change) { struct net_device *real_dev = vlan_dev_info(dev)->real_dev; @@ -713,6 +725,7 @@ static const struct net_device_ops vlan_netdev_ops = { .ndo_set_multicast_list = vlan_dev_set_rx_mode, .ndo_change_rx_flags = vlan_dev_change_rx_flags, .ndo_do_ioctl = vlan_dev_ioctl, + .ndo_neigh_setup = vlan_dev_neigh_setup, }; static const struct net_device_ops vlan_netdev_accel_ops = { @@ -728,6 +741,7 @@ static const struct net_device_ops vlan_netdev_accel_ops = { .ndo_set_multicast_list = vlan_dev_set_rx_mode, .ndo_change_rx_flags = vlan_dev_change_rx_flags, .ndo_do_ioctl = vlan_dev_ioctl, + .ndo_neigh_setup = vlan_dev_neigh_setup, }; void vlan_setup(struct net_device *dev) diff --git a/net/Kconfig b/net/Kconfig index 6ec2cce7c16..bf2776018f7 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -254,6 +254,8 @@ source "net/mac80211/Kconfig" endif # WIRELESS +source "net/wimax/Kconfig" + source "net/rfkill/Kconfig" source "net/9p/Kconfig" diff --git a/net/Makefile b/net/Makefile index ba4460432b7..0fcce89d716 100644 --- a/net/Makefile +++ b/net/Makefile @@ -63,3 +63,4 @@ endif ifeq ($(CONFIG_NET),y) obj-$(CONFIG_SYSCTL) += sysctl_net.o endif +obj-$(CONFIG_WIMAX) += wimax/ diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index b03ff58e930..89f99d3beb6 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c @@ -443,13 +443,14 @@ static void aarp_send_probe_phase1(struct atalk_iface *iface) { struct ifreq atreq; struct sockaddr_at *sa = (struct sockaddr_at *)&atreq.ifr_addr; + const struct net_device_ops *ops = iface->dev->netdev_ops; sa->sat_addr.s_node = iface->address.s_node; sa->sat_addr.s_net = ntohs(iface->address.s_net); /* We pass the Net:Node to the drivers/cards by a Device ioctl. */ - if (!(iface->dev->do_ioctl(iface->dev, &atreq, SIOCSIFADDR))) { - (void)iface->dev->do_ioctl(iface->dev, &atreq, SIOCGIFADDR); + if (!(ops->ndo_do_ioctl(iface->dev, &atreq, SIOCSIFADDR))) { + ops->ndo_do_ioctl(iface->dev, &atreq, SIOCGIFADDR); if (iface->address.s_net != htons(sa->sat_addr.s_net) || iface->address.s_node != sa->sat_addr.s_node) iface->status |= ATIF_PROBE_FAIL; diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h index d20f8a40f36..0d9e506f5d5 100644 --- a/net/bluetooth/bnep/bnep.h +++ b/net/bluetooth/bnep/bnep.h @@ -165,7 +165,6 @@ struct bnep_session { struct socket *sock; struct net_device *dev; - struct net_device_stats stats; }; void bnep_net_setup(struct net_device *dev); diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 70fea8bdb4e..52a6ce0d772 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -306,7 +306,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) struct sk_buff *nskb; u8 type; - s->stats.rx_bytes += skb->len; + dev->stats.rx_bytes += skb->len; type = *(u8 *) skb->data; skb_pull(skb, 1); @@ -343,7 +343,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) * may not be modified and because of the alignment requirements. */ nskb = alloc_skb(2 + ETH_HLEN + skb->len, GFP_KERNEL); if (!nskb) { - s->stats.rx_dropped++; + dev->stats.rx_dropped++; kfree_skb(skb); return -ENOMEM; } @@ -378,14 +378,14 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) skb_copy_from_linear_data(skb, __skb_put(nskb, skb->len), skb->len); kfree_skb(skb); - s->stats.rx_packets++; + dev->stats.rx_packets++; nskb->ip_summed = CHECKSUM_NONE; nskb->protocol = eth_type_trans(nskb, dev); netif_rx_ni(nskb); return 0; badframe: - s->stats.rx_errors++; + dev->stats.rx_errors++; kfree_skb(skb); return 0; } @@ -448,8 +448,8 @@ send: kfree_skb(skb); if (len > 0) { - s->stats.tx_bytes += len; - s->stats.tx_packets++; + s->dev->stats.tx_bytes += len; + s->dev->stats.tx_packets++; return 0; } diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index f897da6e044..d7a0e9722de 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c @@ -55,12 +55,6 @@ static int bnep_net_close(struct net_device *dev) return 0; } -static struct net_device_stats *bnep_net_get_stats(struct net_device *dev) -{ - struct bnep_session *s = netdev_priv(dev); - return &s->stats; -} - static void bnep_net_set_mc_list(struct net_device *dev) { #ifdef CONFIG_BT_BNEP_MC_FILTER @@ -128,11 +122,6 @@ static void bnep_net_timeout(struct net_device *dev) netif_wake_queue(dev); } -static int bnep_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - return -EINVAL; -} - #ifdef CONFIG_BT_BNEP_MC_FILTER static inline int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s) { @@ -217,6 +206,18 @@ static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } +static const struct net_device_ops bnep_netdev_ops = { + .ndo_open = bnep_net_open, + .ndo_stop = bnep_net_close, + .ndo_start_xmit = bnep_net_xmit, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_multicast_list = bnep_net_set_mc_list, + .ndo_set_mac_address = bnep_net_set_mac_addr, + .ndo_tx_timeout = bnep_net_timeout, + .ndo_change_mtu = eth_change_mtu, + +}; + void bnep_net_setup(struct net_device *dev) { @@ -224,15 +225,7 @@ void bnep_net_setup(struct net_device *dev) dev->addr_len = ETH_ALEN; ether_setup(dev); - - dev->open = bnep_net_open; - dev->stop = bnep_net_close; - dev->hard_start_xmit = bnep_net_xmit; - dev->get_stats = bnep_net_get_stats; - dev->do_ioctl = bnep_net_ioctl; - dev->set_mac_address = bnep_net_set_mac_addr; - dev->set_multicast_list = bnep_net_set_mc_list; + dev->netdev_ops = &bnep_netdev_ops; dev->watchdog_timeo = HZ * 2; - dev->tx_timeout = bnep_net_timeout; } diff --git a/net/can/af_can.c b/net/can/af_can.c index 3dadb338add..fa417ca6cbe 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -414,6 +414,12 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can * filter for error frames (CAN_ERR_FLAG bit set in mask). * + * The provided pointer to the sk_buff is guaranteed to be valid as long as + * the callback function is running. The callback function must *not* free + * the given sk_buff while processing it's task. When the given sk_buff is + * needed after the end of the callback function it must be cloned inside + * the callback function with skb_clone(). + * * Return: * 0 on success * -ENOMEM on missing cache mem to create subscription entry @@ -569,13 +575,8 @@ EXPORT_SYMBOL(can_rx_unregister); static inline void deliver(struct sk_buff *skb, struct receiver *r) { - struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); - - if (clone) { - clone->sk = skb->sk; - r->func(clone, r->data); - r->matches++; - } + r->func(skb, r->data); + r->matches++; } static int can_rcv_filter(struct dev_rcv_lists *d, struct sk_buff *skb) diff --git a/net/can/bcm.c b/net/can/bcm.c index da0d426c0ce..1649c8ab2c2 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -70,7 +70,7 @@ #define CAN_BCM_VERSION CAN_VERSION static __initdata const char banner[] = KERN_INFO - "can: broadcast manager protocol (rev " CAN_BCM_VERSION ")\n"; + "can: broadcast manager protocol (rev " CAN_BCM_VERSION " t)\n"; MODULE_DESCRIPTION("PF_CAN broadcast manager protocol"); MODULE_LICENSE("Dual BSD/GPL"); @@ -90,6 +90,7 @@ struct bcm_op { unsigned long frames_abs, frames_filtered; struct timeval ival1, ival2; struct hrtimer timer, thrtimer; + struct tasklet_struct tsklet, thrtsklet; ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg; int rx_ifindex; int count; @@ -341,6 +342,23 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head, } } +static void bcm_tx_timeout_tsklet(unsigned long data) +{ + struct bcm_op *op = (struct bcm_op *)data; + struct bcm_msg_head msg_head; + + /* create notification to user */ + msg_head.opcode = TX_EXPIRED; + msg_head.flags = op->flags; + msg_head.count = op->count; + msg_head.ival1 = op->ival1; + msg_head.ival2 = op->ival2; + msg_head.can_id = op->can_id; + msg_head.nframes = 0; + + bcm_send_to_user(op, &msg_head, NULL, 0); +} + /* * bcm_tx_timeout_handler - performes cyclic CAN frame transmissions */ @@ -352,20 +370,8 @@ static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer) if (op->kt_ival1.tv64 && (op->count > 0)) { op->count--; - if (!op->count && (op->flags & TX_COUNTEVT)) { - struct bcm_msg_head msg_head; - - /* create notification to user */ - msg_head.opcode = TX_EXPIRED; - msg_head.flags = op->flags; - msg_head.count = op->count; - msg_head.ival1 = op->ival1; - msg_head.ival2 = op->ival2; - msg_head.can_id = op->can_id; - msg_head.nframes = 0; - - bcm_send_to_user(op, &msg_head, NULL, 0); - } + if (!op->count && (op->flags & TX_COUNTEVT)) + tasklet_schedule(&op->tsklet); } if (op->kt_ival1.tv64 && (op->count > 0)) { @@ -402,6 +408,9 @@ static void bcm_rx_changed(struct bcm_op *op, struct can_frame *data) if (op->frames_filtered > ULONG_MAX/100) op->frames_filtered = op->frames_abs = 0; + /* this element is not throttled anymore */ + data->can_dlc &= (BCM_CAN_DLC_MASK|RX_RECV); + head.opcode = RX_CHANGED; head.flags = op->flags; head.count = op->count; @@ -420,37 +429,32 @@ static void bcm_rx_changed(struct bcm_op *op, struct can_frame *data) */ static void bcm_rx_update_and_send(struct bcm_op *op, struct can_frame *lastdata, - struct can_frame *rxdata) + const struct can_frame *rxdata) { memcpy(lastdata, rxdata, CFSIZ); - /* mark as used */ - lastdata->can_dlc |= RX_RECV; + /* mark as used and throttled by default */ + lastdata->can_dlc |= (RX_RECV|RX_THR); - /* throtteling mode inactive OR data update already on the run ? */ - if (!op->kt_ival2.tv64 || hrtimer_callback_running(&op->thrtimer)) { + /* throtteling mode inactive ? */ + if (!op->kt_ival2.tv64) { /* send RX_CHANGED to the user immediately */ - bcm_rx_changed(op, rxdata); + bcm_rx_changed(op, lastdata); return; } - if (hrtimer_active(&op->thrtimer)) { - /* mark as 'throttled' */ - lastdata->can_dlc |= RX_THR; + /* with active throttling timer we are just done here */ + if (hrtimer_active(&op->thrtimer)) return; - } - if (!op->kt_lastmsg.tv64) { - /* send first RX_CHANGED to the user immediately */ - bcm_rx_changed(op, rxdata); - op->kt_lastmsg = ktime_get(); |