X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fhamradio%2Fbpqether.c;h=5b788d84011fc0ba06c204fca5ac21312f2ead9d;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=fda18722289ef264aad5794965840019df092ef3;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index fda187222..5b788d840 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -54,7 +54,6 @@ * BPQ 004 Joerg(DL1BKE) Fixed to not lock up on ifconfig. */ -#include #include #include #include @@ -89,16 +88,11 @@ static char banner[] __initdata = KERN_INFO "AX.25: bpqether driver version 004\n"; -static unsigned char ax25_bcast[AX25_ADDR_LEN] = - {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1}; -static unsigned char ax25_defaddr[AX25_ADDR_LEN] = - {'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1}; - static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; static char bpq_eth_addr[6]; -static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *); +static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); static int bpq_device_event(struct notifier_block *, unsigned long, void *); static const char *bpq_print_ethaddr(const unsigned char *); @@ -112,8 +106,6 @@ static struct notifier_block bpq_dev_notifier = { }; -#define MAXBPQDEV 100 - struct bpqdev { struct list_head bpq_list; /* list of bpq devices chain */ struct net_device *ethdev; /* link to ethernet device */ @@ -125,6 +117,12 @@ struct bpqdev { static LIST_HEAD(bpq_devices); +/* + * bpqether network devices are paired with ethernet devices below them, so + * form a special "super class" of normal ethernet devices; split their locks + * off into a separate class since they always nest. + */ +static struct lock_class_key bpq_netdev_xmit_lock_key; /* ------------------------------------------------------------------------ */ @@ -134,7 +132,7 @@ static LIST_HEAD(bpq_devices); */ static inline struct net_device *bpq_get_ether_dev(struct net_device *dev) { - struct bpqdev *bpq = (struct bpqdev *) dev->priv; + struct bpqdev *bpq = netdev_priv(dev); return bpq ? bpq->ethdev : NULL; } @@ -146,7 +144,7 @@ static inline struct net_device *bpq_get_ax25_dev(struct net_device *dev) { struct bpqdev *bpq; - list_for_each_entry(bpq, &bpq_devices, bpq_list) { + list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list) { if (bpq->ethdev == dev) return bpq->axdev; } @@ -167,7 +165,7 @@ static inline int dev_is_ethdev(struct net_device *dev) /* * Receive an AX.25 frame via an ethernet interface. */ -static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype) +static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev) { int len; char * ptr; @@ -191,9 +189,9 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty * we check the source address of the sender. */ - bpq = (struct bpqdev *)dev->priv; + bpq = netdev_priv(dev); - eth = (struct ethhdr *)skb->mac.raw; + eth = eth_hdr(skb); if (!(bpq->acpt_addr[0] & 0x01) && memcmp(eth->h_source, bpq->acpt_addr, ETH_ALEN)) @@ -213,11 +211,7 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty ptr = skb_push(skb, 1); *ptr = 0; - skb->dev = dev; - skb->protocol = htons(ETH_P_AX25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = ax25_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; unlock: @@ -274,14 +268,12 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev) skb = newskb; } - skb->protocol = htons(ETH_P_AX25); - ptr = skb_push(skb, 2); *ptr++ = (size + 5) % 256; *ptr++ = (size + 5) / 256; - bpq = (struct bpqdev *)dev->priv; + bpq = netdev_priv(dev); if ((dev = bpq_get_ether_dev(dev)) == NULL) { bpq->stats.tx_dropped++; @@ -289,7 +281,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev) return -ENODEV; } - skb->dev = dev; + skb->protocol = ax25_type_trans(skb, dev); skb->nh.raw = skb->data; dev->hard_header(skb, dev, ETH_P_BPQ, bpq->dest_addr, NULL, 0); bpq->stats.tx_packets++; @@ -305,7 +297,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev) */ static struct net_device_stats *bpq_get_stats(struct net_device *dev) { - struct bpqdev *bpq = (struct bpqdev *) dev->priv; + struct bpqdev *bpq = netdev_priv(dev); return &bpq->stats; } @@ -331,16 +323,13 @@ static int bpq_set_mac_address(struct net_device *dev, void *addr) */ static int bpq_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - struct bpq_ethaddr *ethaddr = (struct bpq_ethaddr *)ifr->ifr_data; - struct bpqdev *bpq = dev->priv; + struct bpq_ethaddr __user *ethaddr = ifr->ifr_data; + struct bpqdev *bpq = netdev_priv(dev); struct bpq_req req; if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (bpq == NULL) /* woops! */ - return -ENODEV; - switch (cmd) { case SIOCSBPQETHOPT: if (copy_from_user(&req, ifr->ifr_data, sizeof(struct bpq_req))) @@ -410,7 +399,7 @@ static void *bpq_seq_start(struct seq_file *seq, loff_t *pos) if (*pos == 0) return SEQ_START_TOKEN; - list_for_each_entry(bpqdev, &bpq_devices, bpq_list) { + list_for_each_entry_rcu(bpqdev, &bpq_devices, bpq_list) { if (i == *pos) return bpqdev; } @@ -429,7 +418,7 @@ static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos) p = ((struct bpqdev *)v)->bpq_list.next; return (p == &bpq_devices) ? NULL - : list_entry(p, struct bpqdev, bpq_list); + : rcu_dereference(list_entry(p, struct bpqdev, bpq_list)); } static void bpq_seq_stop(struct seq_file *seq, void *v) @@ -493,13 +482,13 @@ static void bpq_setup(struct net_device *dev) dev->do_ioctl = bpq_ioctl; dev->destructor = free_netdev; - memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); - memcpy(dev->dev_addr, ax25_defaddr, AX25_ADDR_LEN); + memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); + memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); dev->flags = 0; #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) - dev->hard_header = ax25_encapsulate; + dev->hard_header = ax25_hard_header; dev->rebuild_header = ax25_rebuild_header; #endif @@ -525,7 +514,7 @@ static int bpq_new_device(struct net_device *edev) return -ENOMEM; - bpq = ndev->priv; + bpq = netdev_priv(ndev); dev_hold(edev); bpq->ethdev = edev; bpq->axdev = ndev; @@ -540,6 +529,7 @@ static int bpq_new_device(struct net_device *edev) err = register_netdevice(ndev); if (err) goto error; + lockdep_set_class(&ndev->_xmit_lock, &bpq_netdev_xmit_lock_key); /* List protected by RTNL */ list_add_rcu(&bpq->bpq_list, &bpq_devices); @@ -554,7 +544,7 @@ static int bpq_new_device(struct net_device *edev) static void bpq_free_device(struct net_device *ndev) { - struct bpqdev *bpq = ndev->priv; + struct bpqdev *bpq = netdev_priv(ndev); dev_put(bpq->ethdev); list_del_rcu(&bpq->bpq_list); @@ -572,8 +562,6 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi if (!dev_is_ethdev(dev)) return NOTIFY_DONE; - rcu_read_lock(); - switch (event) { case NETDEV_UP: /* new ethernet device -> new BPQ interface */ if (bpq_get_ax25_dev(dev) == NULL) @@ -592,7 +580,6 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi default: break; } - rcu_read_unlock(); return NOTIFY_DONE; }