arm/etherh.c - kill init_etherdev(), use ei_alloc_dev() - make use of the ei_device.priv field for private data (dyna-allocated) - bug-fix: dev->priv was conditionally assiged to ec->irq_data, freed on exit, right after kfree(dev). untested. --- 1.15/drivers/net/arm/etherh.c Sat May 17 15:52:31 2003 +++ edited/arm/etherh.c Tue Jul 1 00:02:12 2003 @@ -59,7 +59,6 @@ static unsigned int net_debug = NET_DEBUG; struct etherh_priv { - struct ei_device eidev; unsigned int id; unsigned int ctrl_port; unsigned int ctrl; @@ -144,8 +143,8 @@ static void etherh_setif(struct net_device *dev) { - struct etherh_priv *eh = (struct etherh_priv *)dev->priv; - struct ei_device *ei_local = &eh->eidev; + struct ei_device *ei_local = dev->priv; + struct etherh_priv *eh = (struct etherh_priv *) ei_local->priv; unsigned long addr, flags; local_irq_save(flags); @@ -188,8 +187,8 @@ static int etherh_getifstat(struct net_device *dev) { - struct etherh_priv *eh = (struct etherh_priv *)dev->priv; - struct ei_device *ei_local = &eh->eidev; + struct ei_device *ei_local = dev->priv; + struct etherh_priv *eh = (struct etherh_priv *) ei_local->priv; int stat = 0; switch (eh->id) { @@ -466,9 +465,7 @@ etherh_setif(dev); etherh_reset(dev); - ei_open(dev); - - return 0; + return ei_open(dev); } /* @@ -551,16 +548,19 @@ etherh_banner(); - dev = init_etherdev(NULL, sizeof(struct etherh_priv)); + dev = ei_alloc_dev(); if (!dev) { ret = -ENOMEM; goto out; } + eh = kmalloc(sizeof(struct etherh_priv)); + if (!eh) { + ret = -ENOMEM; + goto free_dev; + } - /* - * init_etherdev allocs and zeros dev->priv - */ - eh = dev->priv; + ei_local = (struct ei_device *) dev->priv; + ei_local->priv = (unsigned long) eh; spin_lock_init(&eh->eidev.page_lock); @@ -619,12 +619,7 @@ if (!request_region(dev->base_addr, size, dev->name)) { ret = -EBUSY; - goto free; - } - - if (ethdev_init(dev)) { - ret = -ENODEV; - goto release; + goto free_eh; } /* @@ -634,7 +629,7 @@ etherh_set_ctrl(eh, ETHERH_CP_IE); /* - * Unfortunately, ethdev_init eventually calls + * Unfortunately, ei_alloc_dev eventually calls * ether_setup, which re-writes dev->flags. */ switch (ec->cid.product) { @@ -665,13 +660,6 @@ break; } - printk(KERN_INFO "%s: %s in slot %d, ", - dev->name, dev_type, ec->slot_no); - - for (i = 0; i < 6; i++) - printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); - - ei_local = (struct ei_device *) dev->priv; if (ec->cid.product == PROD_ANT_ETHERM) { ei_local->tx_start_page = ETHERM_TX_START_PAGE; ei_local->stop_page = ETHERM_STOP_PAGE; @@ -682,7 +670,6 @@ ei_local->reg_offset = etherh_regoffsets; } - ei_local->name = dev->name; ei_local->word16 = 1; ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES; ei_local->reset_8390 = etherh_reset; @@ -694,15 +681,27 @@ etherh_reset(dev); NS8390_init(dev, 0); + /* device is up, register */ + ret = register_netdev(dev); + if (ret) + goto release; + + ei_local->name = dev->name; ecard_set_drvdata(ec, dev); + + /* make noise */ + printk(KERN_INFO "%s: %s in slot %d, ", + dev->name, dev_type, ec->slot_no); + for (i = 0; i < 6; i++) + printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); return 0; release: release_region(dev->base_addr, 16); -free: - unregister_netdev(dev); - kfree(dev->priv); +free_eh: + kfree(eh); +free_dev: kfree(dev); out: return ret; @@ -711,6 +710,8 @@ static void __devexit etherh_remove(struct expansion_card *ec) { struct net_device *dev = ecard_get_drvdata(ec); + struct ei_device *ei_local = dev->priv; + struct etherh_priv *eh = (struct etherh_priv *) ei_local->priv; int size = 16; ecard_set_drvdata(ec, NULL); @@ -719,10 +720,10 @@ if (ec->cid.product == PROD_ANT_ETHERM) size <<= 3; release_region(dev->base_addr, size); + kfree(eh); kfree(dev); ec->ops = NULL; - kfree(ec->irq_data); } static const struct ecard_id etherh_ids[] = { - : send the line "unsubscribe linux-net" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html