📄 c2.c
字号:
return NETDEV_TX_OK;}static struct net_device_stats *c2_get_stats(struct net_device *netdev){ struct c2_port *c2_port = netdev_priv(netdev); return &c2_port->netstats;}static void c2_tx_timeout(struct net_device *netdev){ struct c2_port *c2_port = netdev_priv(netdev); if (netif_msg_timer(c2_port)) pr_debug("%s: tx timeout\n", netdev->name); c2_tx_clean(c2_port);}static int c2_change_mtu(struct net_device *netdev, int new_mtu){ int ret = 0; if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; netdev->mtu = new_mtu; if (netif_running(netdev)) { c2_down(netdev); c2_up(netdev); } return ret;}/* Initialize network device */static struct net_device *c2_devinit(struct c2_dev *c2dev, void __iomem * mmio_addr){ struct c2_port *c2_port = NULL; struct net_device *netdev = alloc_etherdev(sizeof(*c2_port)); if (!netdev) { pr_debug("c2_port etherdev alloc failed"); return NULL; } SET_NETDEV_DEV(netdev, &c2dev->pcidev->dev); netdev->open = c2_up; netdev->stop = c2_down; netdev->hard_start_xmit = c2_xmit_frame; netdev->get_stats = c2_get_stats; netdev->tx_timeout = c2_tx_timeout; netdev->change_mtu = c2_change_mtu; netdev->watchdog_timeo = C2_TX_TIMEOUT; netdev->irq = c2dev->pcidev->irq; c2_port = netdev_priv(netdev); c2_port->netdev = netdev; c2_port->c2dev = c2dev; c2_port->msg_enable = netif_msg_init(debug, default_msg); c2_port->tx_ring.count = C2_NUM_TX_DESC; c2_port->rx_ring.count = C2_NUM_RX_DESC; spin_lock_init(&c2_port->tx_lock); /* Copy our 48-bit ethernet hardware address */ memcpy_fromio(netdev->dev_addr, mmio_addr + C2_REGS_ENADDR, 6); /* Validate the MAC address */ if (!is_valid_ether_addr(netdev->dev_addr)) { pr_debug("Invalid MAC Address\n"); c2_print_macaddr(netdev); free_netdev(netdev); return NULL; } c2dev->netdev = netdev; return netdev;}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); /* Enable PCI device */ 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); /* Make sure PCI base addr are MMIO */ 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; } /* Check for weird/broken PCI region reporting */ 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; } /* Reserve PCI I/O and memory resources */ 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_64BIT_MASK); if (ret < 0) { printk(KERN_ERR PFX "64b DMA configuration failed\n"); goto bail2; } } else { ret = pci_set_dma_mask(pcidev, DMA_32BIT_MASK); if (ret < 0) { printk(KERN_ERR PFX "32b DMA configuration failed\n"); goto bail2; } } /* Enables bus-mastering on the device */ pci_set_master(pcidev); /* Remap the adapter PCI registers in BAR4 */ mmio_regs = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET, sizeof(struct c2_adapter_pci_regs)); if (mmio_regs == 0UL) { printk(KERN_ERR PFX "Unable to remap adapter PCI registers in BAR4\n"); ret = -EIO; goto bail2; } /* Validate PCI regs magic */ 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; } } /* Validate the adapter version */ if (be32_to_cpu(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(readl(mmio_regs + C2_REGS_VERS)), C2_VERSION); ret = -EINVAL; iounmap(mmio_regs); goto bail2; } /* Validate the adapter IVN */ if (be32_to_cpu(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(readl(mmio_regs + C2_REGS_IVN)), C2_IVN); ret = -EINVAL; iounmap(mmio_regs); goto bail2; } /* Allocate hardware structure */ 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; /* Get the last RX index */ c2dev->cur_rx = (be32_to_cpu(readl(mmio_regs + C2_REGS_HRX_CUR)) - 0xffffc000) / sizeof(struct c2_rxp_desc); /* Request an interrupt line for the driver */ 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; } /* Set driver specific data */ pci_set_drvdata(pcidev, c2dev); /* Initialize network device */ if ((netdev = c2_devinit(c2dev, mmio_regs)) == NULL) { iounmap(mmio_regs); goto bail4; } /* Save off the actual size prior to unmapping mmio_regs */ kva_map_size = be32_to_cpu(readl(mmio_regs + C2_REGS_PCI_WINSIZE)); /* Unmap the adapter PCI registers in BAR4 */ iounmap(mmio_regs); /* Register network device */ ret = register_netdev(netdev); if (ret) { printk(KERN_ERR PFX "Unable to register netdev, ret = %d\n", ret); goto bail5; } /* Disable network packets */ netif_stop_queue(netdev); /* Remap the adapter HRXDQ PA space to kernel VA space */ c2dev->mmio_rxp_ring = ioremap_nocache(reg4_start + C2_RXP_HRXDQ_OFFSET, C2_RXP_HRXDQ_SIZE); if (c2dev->mmio_rxp_ring == 0UL) { printk(KERN_ERR PFX "Unable to remap MMIO HRXDQ region\n"); ret = -EIO; goto bail6; } /* Remap the adapter HTXDQ PA space to kernel VA space */ c2dev->mmio_txp_ring = ioremap_nocache(reg4_start + C2_TXP_HTXDQ_OFFSET, C2_TXP_HTXDQ_SIZE); if (c2dev->mmio_txp_ring == 0UL) { printk(KERN_ERR PFX "Unable to remap MMIO HTXDQ region\n"); ret = -EIO; goto bail7; } /* Save off the current RX index in the last 4 bytes of the TXP Ring */ C2_SET_CUR_RX(c2dev, c2dev->cur_rx); /* Remap the PCI registers in adapter BAR0 to kernel VA space */ c2dev->regs = ioremap_nocache(reg0_start, reg0_len); if (c2dev->regs == 0UL) { printk(KERN_ERR PFX "Unable to remap BAR0\n"); ret = -EIO; goto bail8; } /* Remap the PCI registers in adapter BAR4 to kernel VA space */ c2dev->pa = reg4_start + C2_PCI_REGS_OFFSET; c2dev->kva = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET, kva_map_size); if (c2dev->kva == 0UL) { printk(KERN_ERR PFX "Unable to remap BAR4\n"); ret = -EIO; goto bail9; } /* Print out the MAC address */ 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;}static void __devexit c2_remove(struct pci_dev *pcidev){ struct c2_dev *c2dev = pci_get_drvdata(pcidev); struct net_device *netdev = c2dev->netdev; /* Unregister with OpenIB */ c2_unregister_device(c2dev); /* Clean up the RNIC resources */ c2_rnic_term(c2dev); /* Remove network device from the kernel */ unregister_netdev(netdev); /* Free network device */ free_netdev(netdev); /* Free the interrupt line */ free_irq(pcidev->irq, c2dev); /* missing: Turn LEDs off here */ /* Unmap adapter PA space */ iounmap(c2dev->kva); iounmap(c2dev->regs); iounmap(c2dev->mmio_txp_ring); iounmap(c2dev->mmio_rxp_ring); /* Free the hardware structure */ ib_dealloc_device(&c2dev->ibdev); /* Release reserved PCI I/O and memory resources */ pci_release_regions(pcidev); /* Disable PCI device */ pci_disable_device(pcidev); /* Clear driver specific data */ pci_set_drvdata(pcidev, NULL);}static struct pci_driver c2_pci_driver = { .name = DRV_NAME, .id_table = c2_pci_table, .probe = c2_probe, .remove = __devexit_p(c2_remove),};static int __init c2_init_module(void){ return pci_register_driver(&c2_pci_driver);}static void __exit c2_exit_module(void){ pci_unregister_driver(&c2_pci_driver);}module_init(c2_init_module);module_exit(c2_exit_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -