Beispiel #1
0
static int __exit ar2313_remove(struct platform_device *pdev)
{
    struct net_device *dev = platform_get_drvdata(pdev);
    rx_tasklet_cleanup(dev);
    ar2313_init_cleanup(dev);
    unregister_netdev(dev);
    kfree(dev);
    return 0;
}
Beispiel #2
0
static int ar2313_init(struct net_device *dev)
{
    struct ar2313_private *sp = dev->priv;
    int ecode = 0;

    /*
     * Allocate descriptors
     */
    if (ar2313_allocate_descriptors(dev)) {
        printk("%s: %s: ar2313_allocate_descriptors failed\n",
               dev->name, __FUNCTION__);
        ecode = -EAGAIN;
        goto init_error;
    }

    /*
     * Get the memory for the skb rings.
     */
    if (sp->rx_skb == NULL) {
        sp->rx_skb =
            kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES,
                    GFP_KERNEL);
        if (!(sp->rx_skb)) {
            printk("%s: %s: rx_skb kmalloc failed\n",
                   dev->name, __FUNCTION__);
            ecode = -EAGAIN;
            goto init_error;
        }
    }
    memset(sp->rx_skb, 0, sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES);

    if (sp->tx_skb == NULL) {
        sp->tx_skb =
            kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES,
                    GFP_KERNEL);
        if (!(sp->tx_skb)) {
            printk("%s: %s: tx_skb kmalloc failed\n",
                   dev->name, __FUNCTION__);
            ecode = -EAGAIN;
            goto init_error;
        }
    }
    memset(sp->tx_skb, 0, sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES);

    /*
     * Set tx_csm before we start receiving interrupts, otherwise
     * the interrupt handler might think it is supposed to process
     * tx ints before we are up and running, which may cause a null
     * pointer access in the int handler.
     */
    sp->rx_skbprd = 0;
    sp->cur_rx = 0;
    sp->tx_prd = 0;
    sp->tx_csm = 0;

    /*
     * Zero the stats before starting the interface
     */
    memset(&sp->stats, 0, sizeof(sp->stats));

    /*
     * We load the ring here as there seem to be no way to tell the
     * firmware to wipe the ring without re-initializing it.
     */
    ar2313_load_rx_ring(dev, RX_RING_SIZE);

    /*
     * Init hardware
     */
    ar2313_reset_reg(dev);
    setupADM(dev);

    /*
     * Get the IRQ
     */
    ecode =
        request_irq(dev->irq, &ar2313_interrupt,
                    IRQF_SHARED | IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
                    dev->name, dev);
    if (ecode) {
        printk(KERN_WARNING "%s: %s: Requested IRQ %d is busy\n",
               dev->name, __FUNCTION__, dev->irq);
        goto init_error;
    }


    tasklet_enable(&sp->rx_tasklet);

    return 0;

init_error:
    ar2313_init_cleanup(dev);
    return ecode;
}
Beispiel #3
0
int __init ar2313_probe(struct platform_device *pdev)
{
	struct net_device *dev;
	struct ar2313_private *sp;
	struct resource *res;
	unsigned long ar_eth_base;
	char buf[64];

	dev = alloc_etherdev(sizeof(struct ar2313_private));

	if (dev == NULL) {
		printk(KERN_ERR
			   "ar2313: Unable to allocate net_device structure!\n");
		return -ENOMEM;
	}

	platform_set_drvdata(pdev, dev);

	sp = netdev_priv(dev);
	sp->dev = dev;
	sp->cfg = pdev->dev.platform_data;

	sprintf(buf, "eth%d_membase", pdev->id);
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, buf);
	if (!res)
		return -ENODEV;

	sp->link = 0;
	ar_eth_base = res->start;
	sp->phy = sp->cfg->phy;

	sprintf(buf, "eth%d_irq", pdev->id);
	dev->irq = platform_get_irq_byname(pdev, buf);

	spin_lock_init(&sp->lock);

	/* initialize func pointers */
	dev->open = &ar2313_open;
	dev->stop = &ar2313_close;
	dev->hard_start_xmit = &ar2313_start_xmit;

	dev->set_multicast_list = &ar2313_multicast_list;
#ifdef TX_TIMEOUT
	dev->tx_timeout = ar2313_tx_timeout;
	dev->watchdog_timeo = AR2313_TX_TIMEOUT;
#endif
	dev->do_ioctl = &ar2313_ioctl;

	// SAMEER: do we need this?
	dev->features |= NETIF_F_HIGHDMA;

	tasklet_init(&sp->rx_tasklet, rx_tasklet_func, (unsigned long) dev);
	tasklet_disable(&sp->rx_tasklet);

	sp->eth_regs =
		ioremap_nocache(virt_to_phys(ar_eth_base), sizeof(*sp->eth_regs));
	if (!sp->eth_regs) {
		printk("Can't remap eth registers\n");
		return (-ENXIO);
	}

	/*
	 * When there's only one MAC, PHY regs are typically on ENET0,
	 * even though the MAC might be on ENET1.
	 * Needto remap PHY regs separately in this case
	 */
	if (virt_to_phys(ar_eth_base) == virt_to_phys(sp->phy_regs))
		sp->phy_regs = sp->eth_regs;
	else {
		sp->phy_regs =
			ioremap_nocache(virt_to_phys(sp->cfg->phy_base),
							sizeof(*sp->phy_regs));
		if (!sp->phy_regs) {
			printk("Can't remap phy registers\n");
			return (-ENXIO);
		}
	}

	sp->dma_regs =
		ioremap_nocache(virt_to_phys(ar_eth_base + 0x1000),
						sizeof(*sp->dma_regs));
	dev->base_addr = (unsigned int) sp->dma_regs;
	if (!sp->dma_regs) {
		printk("Can't remap DMA registers\n");
		return (-ENXIO);
	}

	sp->int_regs = ioremap_nocache(virt_to_phys(sp->cfg->reset_base), 4);
	if (!sp->int_regs) {
		printk("Can't remap INTERRUPT registers\n");
		return (-ENXIO);
	}

	strncpy(sp->name, "Atheros AR231x", sizeof(sp->name) - 1);
	sp->name[sizeof(sp->name) - 1] = '\0';
	memcpy(dev->dev_addr, sp->cfg->macaddr, 6);
	sp->board_idx = BOARD_IDX_STATIC;

	if (ar2313_init(dev)) {
		/*
		 * ar2313_init() calls ar2313_init_cleanup() on error.
		 */
		kfree(dev);
		return -ENODEV;
	}

	if (register_netdev(dev)) {
		printk("%s: register_netdev failed\n", __func__);
		return -1;
	}

	printk("%s: %s: %02x:%02x:%02x:%02x:%02x:%02x, irq %d\n",
		   dev->name, sp->name,
		   dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
		   dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], dev->irq);

	sp->mii_bus.priv = dev;
	sp->mii_bus.read = mdiobus_read;
	sp->mii_bus.write = mdiobus_write;
	sp->mii_bus.reset = mdiobus_reset;
	sp->mii_bus.name = "ar2313_eth_mii";
	sp->mii_bus.id = 0;
	sp->mii_bus.irq = kmalloc(sizeof(int), GFP_KERNEL);
	*sp->mii_bus.irq = PHY_POLL;

	mdiobus_register(&sp->mii_bus);

	if (mdiobus_probe(dev) != 0) {
		printk(KERN_ERR "ar2313: mdiobus_probe failed");
		rx_tasklet_cleanup(dev);
		ar2313_init_cleanup(dev);
		unregister_netdev(dev);
		kfree(dev);
	} else {
		/* start link poll timer */
		ar2313_setup_timer(dev);
	}

	return 0;
}