Пример #1
0
/* Actual transmission over a single endpoint */
static void __wrn_tx_desc(struct wrn_ep *ep, int desc,
			  void *data, int len, int id, int do_stamp)
{
	struct wrn_dev *wrn = ep->wrn;
	int offset = __wrn_desc_offset(wrn, WRN_DDIR_TX, desc);
	u32 *ptr = __wrn_desc_mem(wrn, WRN_DDIR_TX, desc);
	struct wrn_txd __iomem *tx = wrn->txd + desc;

	/* data */
	pr_debug("%s: %i -- data %p, len %i ", __func__, __LINE__,
	       data, len);
	pr_debug("-- desc %i (tx %p)\n", desc, tx);

	__wrn_copy_out(ptr, data, len);

	/* TX register 3: mask of endpoints (FIXME: broadcast) */
	//printk("EP Num: %d\n", ep->ep_number);

	writel(1<<ep->ep_number, &tx->tx3);

	/* TX register 2: offset and length */
	writel(offset | (len << 16), &tx->tx2);

	/* TX register 1: id and masks -- and tx_enable if needed */
	writel((len < 60 ? NIC_TX1_D1_PAD_E : 0) | NIC_TX1_D1_READY
	       | (do_stamp ? NIC_TX1_D1_TS_E : 0) | (id << 16),
	       &tx->tx1);
}
Пример #2
0
static int wrn_probe(struct platform_device *pdev)
{
	struct net_device *netdev;
	struct wrn_ep *ep;
	struct wrn_dev *wrn = wrn_from_pdev(pdev);
	int i, err = 0, irq;

	/* Lazily: irqs are not in the resource list */
	static int irqs[] = WRN_IRQ_NUMBERS;
	static char *irq_names[] = WRN_IRQ_NAMES;
	static irq_handler_t irq_handlers[] = WRN_IRQ_HANDLERS;
	struct irq_domain *irqdomain;

	irqdomain = irq_find_host((struct device_node *)irqdomain_name);
	if (!irqdomain) {
		dev_err(&pdev->dev, "The IRQ domain %s does not exist\n",
			irqdomain_name);
		return -EINVAL;
	}

	/* No need to lock_irq: we only protect count and continue unlocked */
	if (WR_IS_SWITCH) {
		spin_lock(&wrn->lock);
		if (++wrn->use_count != 1) {
			--wrn->use_count;
			spin_unlock(&wrn->lock);
			return -EBUSY;
		}
		spin_unlock(&wrn->lock);
	}

	/* Map our resource list and instantiate the shortcut pointers */
	if ( (err = __wrn_map_resources(pdev)) )
		goto out;
	wrn->regs = wrn->bases[WRN_FB_NIC];
	wrn->txtsu_regs = wrn->bases[WRN_FB_TS];
	wrn->ppsg_regs = wrn->bases[WRN_FB_PPSG];
	wrn->txd = ((void *)wrn->regs) + 0x80; /* was: TX1_D1 */
	wrn->rxd = ((void *)wrn->regs) + 0x100; /* was: RX1_D1 */
	wrn->databuf = (void *)wrn->regs + NIC_MEM_BASE;
	tasklet_init(&wrn->rx_tlet, wrn_rx_interrupt, (unsigned long)wrn);
	if (0)
		printk("regs %p, txd %p, rxd %p, buffer %p\n",
		       wrn->regs, wrn->txd, wrn->rxd, wrn->databuf);

	if (WR_IS_SWITCH) {
		/* Register the interrupt handlers (not shared) */
		for (i = 0; i < ARRAY_SIZE(irq_names); i++) {
			irq = irq_find_mapping(irqdomain, irqs[i]);
			err = request_irq(irq, irq_handlers[i],
					  IRQF_TRIGGER_LOW, irq_names[i], wrn);
			if (err)
				goto out;
			wrn->irq_registered |= 1 << i;
		}
	}

	/* Finally, register one interface per endpoint */
	memset(wrn->dev, 0, sizeof(wrn->dev));
	for (i = 0; i < WRN_NR_ENDPOINTS; i++) {
		netdev = alloc_etherdev(sizeof(struct wrn_ep));
		netdev->dev.parent = &pdev->dev;
		if (!netdev) {
			dev_err(&pdev->dev, "Etherdev alloc failed.\n");
			err = -ENOMEM;
			goto out;
		}
		/* The ep structure is filled before calling ep_probe */
		ep = netdev_priv(netdev);
		ep->wrn = wrn;
		ep->ep_regs = wrn->bases[WRN_FB_EP] + i * FPGA_SIZE_EACH_EP;
		ep->ep_number = i;
#if 0 /* FIXME: UPlink or not? */
		if (i < WRN_NR_UPLINK)
			set_bit(WRN_EP_IS_UPLINK, &ep->ep_flags);
#endif

		/* The netdevice thing is registered from the endpoint */
		err = wrn_endpoint_probe(netdev);
		if (err == -ENODEV)
			break;
		if (err)
			goto out;
		/* This endpoint went in properly */
		wrn->dev[i] = netdev;
		err = wrn_mezzanine_init(netdev);
		if (err)
			dev_err(&pdev->dev, "Init mezzanine code: "
				"error %i\n", err);
	}
	if (i == 0)
		return -ENODEV; /* no endpoints */

	for (i = 0; i < WRN_NR_TXDESC; i++) { /* Clear all tx descriptors */
		struct wrn_txd *tx;
		tx = wrn->txd + i;
		writel(0, &tx->tx1);
	}

	/* Now, prepare RX descriptors */
	for (i = 0; i < WRN_NR_RXDESC; i++) {
		struct wrn_rxd *rx;
		int offset;

		rx = wrn->rxd + i;
		offset = __wrn_desc_offset(wrn, WRN_DDIR_RX, i);
		writel( (2000 << 16) | offset, &rx->rx3);
		writel(NIC_RX1_D1_EMPTY, &rx->rx1);
	}

	/*
	 * make sure all head/tail are 0 -- not needed here, but if we
	 * disable and then re-enable, this _is_ needed
	 */
	wrn->next_tx_head = wrn->next_tx_tail = wrn->next_rx = 0;

	writel(NIC_CR_RX_EN | NIC_CR_TX_EN, &wrn->regs->CR);
	writel(WRN_IRQ_ALL, (void *)wrn->regs + 0x24 /* EIC_IER */);

	wrn_tstamp_init(wrn);
	err = 0;
out:
	if (err) {
		/* Call the remove function to avoid duplicating code */
		wrn_remove(pdev);
	} else {
		dev_info(&pdev->dev, "White Rabbit NIC driver\n");
	}
	return err;
}