# HG changeset patch # User Florian Pose # Date 1257419301 -3600 # Node ID daf92232d9c5edc7bb4eec86b08ecae26f317fcb # Parent 52ec7297637ce133d2c3ff14ff79aa2b32f9acd0 Fixed bug in generic driver failing to create debug interfaces, because the interface lock is held. diff -r 52ec7297637c -r daf92232d9c5 devices/generic.c --- a/devices/generic.c Thu Nov 05 10:22:58 2009 +0100 +++ b/devices/generic.c Thu Nov 05 12:08:21 2009 +0100 @@ -72,6 +72,13 @@ ec_device_t *ecdev; } ec_gen_device_t; +typedef struct { + struct list_head list; + char name[IFNAMSIZ]; + int ifindex; + uint8_t dev_addr[ETH_ALEN]; +} ec_gen_interface_desc_t; + int ec_gen_device_open(ec_gen_device_t *); int ec_gen_device_stop(ec_gen_device_t *); int ec_gen_device_start_xmit(ec_gen_device_t *, struct sk_buff *); @@ -127,8 +134,7 @@ /** Init generic device. */ int ec_gen_device_init( - ec_gen_device_t *dev, - struct net_device *real_netdev + ec_gen_device_t *dev ) { ec_gen_device_t **priv; @@ -141,7 +147,6 @@ if (!dev->netdev) { return -ENOMEM; } - memcpy(dev->netdev->dev_addr, real_netdev->dev_addr, ETH_ALEN); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) dev->netdev->netdev_ops = &ec_gen_netdev_ops; @@ -181,7 +186,7 @@ */ int ec_gen_device_create_socket( ec_gen_device_t *dev, - struct net_device *real_netdev + ec_gen_interface_desc_t *desc ) { int ret; @@ -194,12 +199,12 @@ } printk(KERN_ERR PFX "Binding socket to interface %i (%s).\n", - real_netdev->ifindex, real_netdev->name); + desc->ifindex, desc->name); memset(&sa, 0x00, sizeof(sa)); sa.sll_family = AF_PACKET; sa.sll_protocol = htons(ETH_P_ETHERCAT); - sa.sll_ifindex = real_netdev->ifindex; + sa.sll_ifindex = desc->ifindex; ret = kernel_bind(dev->socket, (struct sockaddr *) &sa, sizeof(sa)); if (ret) { printk(KERN_ERR PFX "Failed to bind() socket to interface.\n"); @@ -217,14 +222,16 @@ */ int ec_gen_device_offer( ec_gen_device_t *dev, - struct net_device *real_netdev + ec_gen_interface_desc_t *desc ) { int ret = 0; + memcpy(dev->netdev->dev_addr, desc->dev_addr, ETH_ALEN); + dev->ecdev = ecdev_offer(dev->netdev, ec_gen_poll, THIS_MODULE); if (dev->ecdev) { - if (ec_gen_device_create_socket(dev, real_netdev)) { + if (ec_gen_device_create_socket(dev, desc)) { ecdev_withdraw(dev->ecdev); dev->ecdev = NULL; } else if (ecdev_open(dev->ecdev)) { @@ -316,7 +323,7 @@ /** Offer device. */ int offer_device( - struct net_device *netdev + ec_gen_interface_desc_t *desc ) { ec_gen_device_t *gendev; @@ -327,13 +334,13 @@ return -ENOMEM; } - ret = ec_gen_device_init(gendev, netdev); + ret = ec_gen_device_init(gendev); if (ret) { kfree(gendev); return ret; } - if (ec_gen_device_offer(gendev, netdev)) { + if (ec_gen_device_offer(gendev, desc)) { list_add_tail(&gendev->list, &generic_devices); } else { ec_gen_device_clear(gendev); @@ -368,27 +375,47 @@ int __init ec_gen_init_module(void) { int ret = 0; + struct list_head descs; struct net_device *netdev; + ec_gen_interface_desc_t *desc, *next; printk(KERN_INFO PFX "EtherCAT master generic Ethernet device module %s\n", EC_MASTER_VERSION); INIT_LIST_HEAD(&generic_devices); + INIT_LIST_HEAD(&descs); read_lock(&dev_base_lock); for_each_netdev(&init_net, netdev) { if (netdev->type != ARPHRD_ETHER) continue; - ret = offer_device(netdev); - if (ret) { + desc = kmalloc(sizeof(ec_gen_interface_desc_t), GFP_KERNEL); + if (!desc) { + ret = -ENOMEM; read_unlock(&dev_base_lock); goto out_err; } + strncpy(desc->name, netdev->name, IFNAMSIZ); + desc->ifindex = netdev->ifindex; + memcpy(desc->dev_addr, netdev->dev_addr, ETH_ALEN); + list_add_tail(&desc->list, &descs); } read_unlock(&dev_base_lock); + + list_for_each_entry_safe(desc, next, &descs, list) { + ret = offer_device(desc); + if (ret) { + goto out_err; + } + kfree(desc); + } return ret; out_err: + list_for_each_entry_safe(desc, next, &descs, list) { + list_del(&desc->list); + kfree(desc); + } clear_devices(); return ret; }