X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=net%2Frose%2Faf_rose.c;h=8c34f1ca6c8c8eb8486d084bbd1e17eb6eca224c;hb=920841d8d1d61bc12b43f95a579a5374f6d98f81;hp=7799fe82aeb6fe8bed8a782b8636de851dc855c8;hpb=ba290ab7dace8b3339c0cc86c221d48eed21e956;p=powerpc.git diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 7799fe82ae..8c34f1ca6c 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -66,6 +66,14 @@ static struct proto_ops rose_proto_ops; ax25_address rose_callsign; +/* + * ROSE network devices are virtual network devices encapsulating ROSE + * frames into AX.25 which will be sent through an AX.25 device, so form a + * special "super class" of normal net devices; split their locks off into a + * separate class since they always nest. + */ +static struct lock_class_key rose_netdev_xmit_lock_key; + /* * Convert a ROSE address into text. */ @@ -752,7 +760,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le rose_insert_socket(sk); /* Finish the bind */ } - +rose_try_next_neigh: rose->dest_addr = addr->srose_addr; rose->dest_call = addr->srose_call; rose->rand = ((long)rose & 0xFFFF) + rose->lci; @@ -810,6 +818,11 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le } if (sk->sk_state != TCP_ESTABLISHED) { + /* Try next neighbour */ + rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic); + if (rose->neighbour) + goto rose_try_next_neigh; + /* No more neighbour */ sock->state = SS_UNCONNECTED; return sock_error(sk); /* Always set at this point */ } @@ -1301,7 +1314,8 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) if (copy_from_user(&rose_callsign, argp, sizeof(ax25_address))) return -EFAULT; if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) - ax25_listen_register(&rose_callsign, NULL); + return ax25_listen_register(&rose_callsign, NULL); + return 0; case SIOCRSGL2CALL: @@ -1337,7 +1351,7 @@ static void *rose_info_start(struct seq_file *seq, loff_t *pos) spin_lock_bh(&rose_list_lock); if (*pos == 0) return SEQ_START_TOKEN; - + i = 1; sk_for_each(s, node, &rose_list) { if (i == *pos) @@ -1351,10 +1365,10 @@ static void *rose_info_next(struct seq_file *seq, void *v, loff_t *pos) { ++*pos; - return (v == SEQ_START_TOKEN) ? sk_head(&rose_list) + return (v == SEQ_START_TOKEN) ? sk_head(&rose_list) : sk_next((struct sock *)v); } - + static void rose_info_stop(struct seq_file *seq, void *v) { spin_unlock_bh(&rose_list_lock); @@ -1365,7 +1379,7 @@ static int rose_info_show(struct seq_file *seq, void *v) char buf[11]; if (v == SEQ_START_TOKEN) - seq_puts(seq, + seq_puts(seq, "dest_addr dest_call src_addr src_call dev lci neigh st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q inode\n"); else { @@ -1378,7 +1392,7 @@ static int rose_info_show(struct seq_file *seq, void *v) devname = "???"; else devname = dev->name; - + seq_printf(seq, "%-10s %-9s ", rose2asc(&rose->dest_addr), ax2asc(buf, &rose->dest_call)); @@ -1426,7 +1440,7 @@ static int rose_info_open(struct inode *inode, struct file *file) return seq_open(file, &rose_info_seqops); } -static struct file_operations rose_info_fops = { +static const struct file_operations rose_info_fops = { .owner = THIS_MODULE, .open = rose_info_open, .read = seq_read, @@ -1468,6 +1482,15 @@ static struct notifier_block rose_dev_notifier = { static struct net_device **dev_rose; +static struct ax25_protocol rose_pid = { + .pid = AX25_P_ROSE, + .func = rose_route_frame +}; + +static struct ax25_linkfail rose_linkfail_notifier = { + .func = rose_link_failed +}; + static int __init rose_proto_init(void) { int i; @@ -1485,20 +1508,19 @@ static int __init rose_proto_init(void) rose_callsign = null_ax25_address; - dev_rose = kmalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL); + dev_rose = kzalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL); if (dev_rose == NULL) { printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n"); rc = -ENOMEM; goto out_proto_unregister; } - memset(dev_rose, 0x00, rose_ndevs * sizeof(struct net_device*)); for (i = 0; i < rose_ndevs; i++) { struct net_device *dev; char name[IFNAMSIZ]; sprintf(name, "rose%d", i); - dev = alloc_netdev(sizeof(struct net_device_stats), + dev = alloc_netdev(sizeof(struct net_device_stats), name, rose_setup); if (!dev) { printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n"); @@ -1511,14 +1533,15 @@ static int __init rose_proto_init(void) free_netdev(dev); goto fail; } + lockdep_set_class(&dev->_xmit_lock, &rose_netdev_xmit_lock_key); dev_rose[i] = dev; } sock_register(&rose_family_ops); register_netdevice_notifier(&rose_dev_notifier); - ax25_protocol_register(AX25_P_ROSE, rose_route_frame); - ax25_linkfail_register(rose_link_failed); + ax25_register_pid(&rose_pid); + ax25_linkfail_register(&rose_linkfail_notifier); #ifdef CONFIG_SYSCTL rose_register_sysctl(); @@ -1566,7 +1589,7 @@ static void __exit rose_exit(void) rose_rt_free(); ax25_protocol_release(AX25_P_ROSE); - ax25_linkfail_release(rose_link_failed); + ax25_linkfail_release(&rose_linkfail_notifier); if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) ax25_listen_release(&rose_callsign, NULL);