예제 #1
0
파일: c2.c 프로젝트: mecke/linux-2.6
static void c2_reset(struct c2_port *c2_port)
{
	struct c2_dev *c2dev = c2_port->c2dev;
	unsigned int cur_rx = c2dev->cur_rx;

	/* Tell the hardware to quiesce */
	C2_SET_CUR_RX(c2dev, cur_rx | C2_PCI_HRX_QUI);

	/*
	 * The hardware will reset the C2_PCI_HRX_QUI bit once
	 * the RXP is quiesced.  Wait 2 seconds for this.
	 */
	ssleep(2);

	cur_rx = C2_GET_CUR_RX(c2dev);

	if (cur_rx & C2_PCI_HRX_QUI)
		pr_debug("c2_reset: failed to quiesce the hardware!\n");

	cur_rx &= ~C2_PCI_HRX_QUI;

	c2dev->cur_rx = cur_rx;

	pr_debug("Current RX: %u\n", c2dev->cur_rx);
}
예제 #2
0
static void c2_reset(struct c2_port *c2_port)
{
	struct c2_dev *c2dev = c2_port->c2dev;
	unsigned int cur_rx = c2dev->cur_rx;

	
	C2_SET_CUR_RX(c2dev, cur_rx | C2_PCI_HRX_QUI);

	ssleep(2);

	cur_rx = C2_GET_CUR_RX(c2dev);

	if (cur_rx & C2_PCI_HRX_QUI)
		pr_debug("c2_reset: failed to quiesce the hardware!\n");

	cur_rx &= ~C2_PCI_HRX_QUI;

	c2dev->cur_rx = cur_rx;

	pr_debug("Current RX: %u\n", c2dev->cur_rx);
}
예제 #3
0
static int __devinit c2_probe(struct pci_dev *pcidev,
			      const struct pci_device_id *ent)
{
	int ret = 0, i;
	unsigned long reg0_start, reg0_flags, reg0_len;
	unsigned long reg2_start, reg2_flags, reg2_len;
	unsigned long reg4_start, reg4_flags, reg4_len;
	unsigned kva_map_size;
	struct net_device *netdev = NULL;
	struct c2_dev *c2dev = NULL;
	void __iomem *mmio_regs = NULL;

	printk(KERN_INFO PFX "AMSO1100 Gigabit Ethernet driver v%s loaded\n",
		DRV_VERSION);

	
	ret = pci_enable_device(pcidev);
	if (ret) {
		printk(KERN_ERR PFX "%s: Unable to enable PCI device\n",
			pci_name(pcidev));
		goto bail0;
	}

	reg0_start = pci_resource_start(pcidev, BAR_0);
	reg0_len = pci_resource_len(pcidev, BAR_0);
	reg0_flags = pci_resource_flags(pcidev, BAR_0);

	reg2_start = pci_resource_start(pcidev, BAR_2);
	reg2_len = pci_resource_len(pcidev, BAR_2);
	reg2_flags = pci_resource_flags(pcidev, BAR_2);

	reg4_start = pci_resource_start(pcidev, BAR_4);
	reg4_len = pci_resource_len(pcidev, BAR_4);
	reg4_flags = pci_resource_flags(pcidev, BAR_4);

	pr_debug("BAR0 size = 0x%lX bytes\n", reg0_len);
	pr_debug("BAR2 size = 0x%lX bytes\n", reg2_len);
	pr_debug("BAR4 size = 0x%lX bytes\n", reg4_len);

	
	if (!(reg0_flags & IORESOURCE_MEM) ||
	    !(reg2_flags & IORESOURCE_MEM) || !(reg4_flags & IORESOURCE_MEM)) {
		printk(KERN_ERR PFX "PCI regions not an MMIO resource\n");
		ret = -ENODEV;
		goto bail1;
	}

	
	if ((reg0_len < C2_REG0_SIZE) ||
	    (reg2_len < C2_REG2_SIZE) || (reg4_len < C2_REG4_SIZE)) {
		printk(KERN_ERR PFX "Invalid PCI region sizes\n");
		ret = -ENODEV;
		goto bail1;
	}

	
	ret = pci_request_regions(pcidev, DRV_NAME);
	if (ret) {
		printk(KERN_ERR PFX "%s: Unable to request regions\n",
			pci_name(pcidev));
		goto bail1;
	}

	if ((sizeof(dma_addr_t) > 4)) {
		ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(64));
		if (ret < 0) {
			printk(KERN_ERR PFX "64b DMA configuration failed\n");
			goto bail2;
		}
	} else {
		ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32));
		if (ret < 0) {
			printk(KERN_ERR PFX "32b DMA configuration failed\n");
			goto bail2;
		}
	}

	
	pci_set_master(pcidev);

	
	mmio_regs = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET,
				    sizeof(struct c2_adapter_pci_regs));
	if (!mmio_regs) {
		printk(KERN_ERR PFX
			"Unable to remap adapter PCI registers in BAR4\n");
		ret = -EIO;
		goto bail2;
	}

	
	for (i = 0; i < sizeof(c2_magic); i++) {
		if (c2_magic[i] != readb(mmio_regs + C2_REGS_MAGIC + i)) {
			printk(KERN_ERR PFX "Downlevel Firmware boot loader "
				"[%d/%Zd: got 0x%x, exp 0x%x]. Use the cc_flash "
			       "utility to update your boot loader\n",
				i + 1, sizeof(c2_magic),
				readb(mmio_regs + C2_REGS_MAGIC + i),
				c2_magic[i]);
			printk(KERN_ERR PFX "Adapter not claimed\n");
			iounmap(mmio_regs);
			ret = -EIO;
			goto bail2;
		}
	}

	
	if (be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_VERS)) != C2_VERSION) {
		printk(KERN_ERR PFX "Version mismatch "
			"[fw=%u, c2=%u], Adapter not claimed\n",
			be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_VERS)),
			C2_VERSION);
		ret = -EINVAL;
		iounmap(mmio_regs);
		goto bail2;
	}

	
	if (be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_IVN)) != C2_IVN) {
		printk(KERN_ERR PFX "Downlevel FIrmware level. You should be using "
		       "the OpenIB device support kit. "
		       "[fw=0x%x, c2=0x%x], Adapter not claimed\n",
		       be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_IVN)),
		       C2_IVN);
		ret = -EINVAL;
		iounmap(mmio_regs);
		goto bail2;
	}

	
	c2dev = (struct c2_dev *) ib_alloc_device(sizeof(*c2dev));
	if (!c2dev) {
		printk(KERN_ERR PFX "%s: Unable to alloc hardware struct\n",
			pci_name(pcidev));
		ret = -ENOMEM;
		iounmap(mmio_regs);
		goto bail2;
	}

	memset(c2dev, 0, sizeof(*c2dev));
	spin_lock_init(&c2dev->lock);
	c2dev->pcidev = pcidev;
	c2dev->cur_tx = 0;

	
	c2dev->cur_rx =
	    (be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_HRX_CUR)) -
	     0xffffc000) / sizeof(struct c2_rxp_desc);

	
	ret = request_irq(pcidev->irq, c2_interrupt, IRQF_SHARED, DRV_NAME, c2dev);
	if (ret) {
		printk(KERN_ERR PFX "%s: requested IRQ %u is busy\n",
			pci_name(pcidev), pcidev->irq);
		iounmap(mmio_regs);
		goto bail3;
	}

	
	pci_set_drvdata(pcidev, c2dev);

	
	if ((netdev = c2_devinit(c2dev, mmio_regs)) == NULL) {
		iounmap(mmio_regs);
		goto bail4;
	}

	
	kva_map_size = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_PCI_WINSIZE));

	
	iounmap(mmio_regs);

	
	ret = register_netdev(netdev);
	if (ret) {
		printk(KERN_ERR PFX "Unable to register netdev, ret = %d\n",
			ret);
		goto bail5;
	}

	
	netif_stop_queue(netdev);

	
	c2dev->mmio_rxp_ring = ioremap_nocache(reg4_start + C2_RXP_HRXDQ_OFFSET,
					       C2_RXP_HRXDQ_SIZE);
	if (!c2dev->mmio_rxp_ring) {
		printk(KERN_ERR PFX "Unable to remap MMIO HRXDQ region\n");
		ret = -EIO;
		goto bail6;
	}

	
	c2dev->mmio_txp_ring = ioremap_nocache(reg4_start + C2_TXP_HTXDQ_OFFSET,
					       C2_TXP_HTXDQ_SIZE);
	if (!c2dev->mmio_txp_ring) {
		printk(KERN_ERR PFX "Unable to remap MMIO HTXDQ region\n");
		ret = -EIO;
		goto bail7;
	}

	
	C2_SET_CUR_RX(c2dev, c2dev->cur_rx);

	
	c2dev->regs = ioremap_nocache(reg0_start, reg0_len);
	if (!c2dev->regs) {
		printk(KERN_ERR PFX "Unable to remap BAR0\n");
		ret = -EIO;
		goto bail8;
	}

	
	c2dev->pa = reg4_start + C2_PCI_REGS_OFFSET;
	c2dev->kva = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET,
				     kva_map_size);
	if (!c2dev->kva) {
		printk(KERN_ERR PFX "Unable to remap BAR4\n");
		ret = -EIO;
		goto bail9;
	}

	
	c2_print_macaddr(netdev);

	ret = c2_rnic_init(c2dev);
	if (ret) {
		printk(KERN_ERR PFX "c2_rnic_init failed: %d\n", ret);
		goto bail10;
	}

	if (c2_register_device(c2dev))
		goto bail10;

	return 0;

 bail10:
	iounmap(c2dev->kva);

 bail9:
	iounmap(c2dev->regs);

 bail8:
	iounmap(c2dev->mmio_txp_ring);

 bail7:
	iounmap(c2dev->mmio_rxp_ring);

 bail6:
	unregister_netdev(netdev);

 bail5:
	free_netdev(netdev);

 bail4:
	free_irq(pcidev->irq, c2dev);

 bail3:
	ib_dealloc_device(&c2dev->ibdev);

 bail2:
	pci_release_regions(pcidev);

 bail1:
	pci_disable_device(pcidev);

 bail0:
	return ret;
}
예제 #4
0
static void c2_rx_interrupt(struct net_device *netdev)
{
	struct c2_port *c2_port = netdev_priv(netdev);
	struct c2_dev *c2dev = c2_port->c2dev;
	struct c2_ring *rx_ring = &c2_port->rx_ring;
	struct c2_element *elem;
	struct c2_rx_desc *rx_desc;
	struct c2_rxp_hdr *rxp_hdr;
	struct sk_buff *skb;
	dma_addr_t mapaddr;
	u32 maplen, buflen;
	unsigned long flags;

	spin_lock_irqsave(&c2dev->lock, flags);

	
	rx_ring->to_clean = rx_ring->start + c2dev->cur_rx;

	for (elem = rx_ring->to_clean; elem->next != rx_ring->to_clean;
	     elem = elem->next) {
		rx_desc = elem->ht_desc;
		mapaddr = elem->mapaddr;
		maplen = elem->maplen;
		skb = elem->skb;
		rxp_hdr = (struct c2_rxp_hdr *) skb->data;

		if (rxp_hdr->flags != RXP_HRXD_DONE)
			break;
		buflen = rxp_hdr->len;

		
		if (rxp_hdr->status != RXP_HRXD_OK ||
		    buflen > (rx_desc->len - sizeof(*rxp_hdr))) {
			c2_rx_error(c2_port, elem);
			continue;
		}

		if (c2_rx_alloc(c2_port, elem)) {
			c2_rx_error(c2_port, elem);
			continue;
		}

		
		pci_unmap_single(c2dev->pcidev, mapaddr, maplen,
				 PCI_DMA_FROMDEVICE);

		prefetch(skb->data);

		skb->data += sizeof(*rxp_hdr);
		skb_set_tail_pointer(skb, buflen);
		skb->len = buflen;
		skb->protocol = eth_type_trans(skb, netdev);

		netif_rx(skb);

		netdev->stats.rx_packets++;
		netdev->stats.rx_bytes += buflen;
	}

	
	rx_ring->to_clean = elem;
	c2dev->cur_rx = elem - rx_ring->start;
	C2_SET_CUR_RX(c2dev, c2dev->cur_rx);

	spin_unlock_irqrestore(&c2dev->lock, flags);
}
예제 #5
0
파일: c2.c 프로젝트: mecke/linux-2.6
static void c2_rx_interrupt(struct net_device *netdev)
{
	struct c2_port *c2_port = netdev_priv(netdev);
	struct c2_dev *c2dev = c2_port->c2dev;
	struct c2_ring *rx_ring = &c2_port->rx_ring;
	struct c2_element *elem;
	struct c2_rx_desc *rx_desc;
	struct c2_rxp_hdr *rxp_hdr;
	struct sk_buff *skb;
	dma_addr_t mapaddr;
	u32 maplen, buflen;
	unsigned long flags;

	spin_lock_irqsave(&c2dev->lock, flags);

	/* Begin where we left off */
	rx_ring->to_clean = rx_ring->start + c2dev->cur_rx;

	for (elem = rx_ring->to_clean; elem->next != rx_ring->to_clean;
	     elem = elem->next) {
		rx_desc = elem->ht_desc;
		mapaddr = elem->mapaddr;
		maplen = elem->maplen;
		skb = elem->skb;
		rxp_hdr = (struct c2_rxp_hdr *) skb->data;

		if (rxp_hdr->flags != RXP_HRXD_DONE)
			break;
		buflen = rxp_hdr->len;

		/* Sanity check the RXP header */
		if (rxp_hdr->status != RXP_HRXD_OK ||
		    buflen > (rx_desc->len - sizeof(*rxp_hdr))) {
			c2_rx_error(c2_port, elem);
			continue;
		}

		/*
		 * Allocate and map a new skb for replenishing the host
		 * RX desc
		 */
		if (c2_rx_alloc(c2_port, elem)) {
			c2_rx_error(c2_port, elem);
			continue;
		}

		/* Unmap the old skb */
		pci_unmap_single(c2dev->pcidev, mapaddr, maplen,
				 PCI_DMA_FROMDEVICE);

		prefetch(skb->data);

		/*
		 * Skip past the leading 8 bytes comprising of the
		 * "struct c2_rxp_hdr", prepended by the adapter
		 * to the usual Ethernet header ("struct ethhdr"),
		 * to the start of the raw Ethernet packet.
		 *
		 * Fix up the various fields in the sk_buff before
		 * passing it up to netif_rx(). The transfer size
		 * (in bytes) specified by the adapter len field of
		 * the "struct rxp_hdr_t" does NOT include the
		 * "sizeof(struct c2_rxp_hdr)".
		 */
		skb->data += sizeof(*rxp_hdr);
		skb_set_tail_pointer(skb, buflen);
		skb->len = buflen;
		skb->protocol = eth_type_trans(skb, netdev);

		netif_rx(skb);

		netdev->last_rx = jiffies;
		netdev->stats.rx_packets++;
		netdev->stats.rx_bytes += buflen;
	}

	/* Save where we left off */
	rx_ring->to_clean = elem;
	c2dev->cur_rx = elem - rx_ring->start;
	C2_SET_CUR_RX(c2dev, c2dev->cur_rx);

	spin_unlock_irqrestore(&c2dev->lock, flags);
}