static void aq_pci_remove(struct pci_dev *pdev) { struct aq_nic_s *self = pci_get_drvdata(pdev); if (self->ndev) { aq_clear_rxnfc_all_rules(self); if (self->ndev->reg_state == NETREG_REGISTERED) unregister_netdev(self->ndev); aq_nic_free_vectors(self); aq_pci_free_irq_vectors(self); iounmap(self->aq_hw->mmio); kfree(self->aq_hw); pci_release_regions(pdev); free_netdev(self->ndev); } pci_disable_device(pdev); }
static int aq_set_ringparam(struct net_device *ndev, struct ethtool_ringparam *ring) { int err = 0; bool ndev_running = false; struct aq_nic_s *aq_nic = netdev_priv(ndev); struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic); const struct aq_hw_caps_s *hw_caps = aq_nic_cfg->aq_hw_caps; if (ring->rx_mini_pending || ring->rx_jumbo_pending) { err = -EOPNOTSUPP; goto err_exit; } if (netif_running(ndev)) { ndev_running = true; dev_close(ndev); } aq_nic_free_vectors(aq_nic); aq_nic_cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min); aq_nic_cfg->rxds = min(aq_nic_cfg->rxds, hw_caps->rxds_max); aq_nic_cfg->rxds = ALIGN(aq_nic_cfg->rxds, AQ_HW_RXD_MULTIPLE); aq_nic_cfg->txds = max(ring->tx_pending, hw_caps->txds_min); aq_nic_cfg->txds = min(aq_nic_cfg->txds, hw_caps->txds_max); aq_nic_cfg->txds = ALIGN(aq_nic_cfg->txds, AQ_HW_TXD_MULTIPLE); for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < aq_nic_cfg->vecs; aq_nic->aq_vecs++) { aq_nic->aq_vec[aq_nic->aq_vecs] = aq_vec_alloc(aq_nic, aq_nic->aq_vecs, aq_nic_cfg); if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) { err = -ENOMEM; goto err_exit; } } if (ndev_running) err = dev_open(ndev); err_exit: return err; }
static int aq_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) { struct aq_nic_s *self; int err; struct net_device *ndev; resource_size_t mmio_pa; u32 bar; u32 numvecs; err = pci_enable_device(pdev); if (err) return err; err = aq_pci_func_init(pdev); if (err) goto err_pci_func; ndev = aq_ndev_alloc(); if (!ndev) { err = -ENOMEM; goto err_ndev; } self = netdev_priv(ndev); self->pdev = pdev; SET_NETDEV_DEV(ndev, &pdev->dev); pci_set_drvdata(pdev, self); err = aq_pci_probe_get_hw_by_id(pdev, &self->aq_hw_ops, &aq_nic_get_cfg(self)->aq_hw_caps); if (err) goto err_ioremap; self->aq_hw = kzalloc(sizeof(*self->aq_hw), GFP_KERNEL); if (!self->aq_hw) { err = -ENOMEM; goto err_ioremap; } self->aq_hw->aq_nic_cfg = aq_nic_get_cfg(self); for (bar = 0; bar < 4; ++bar) { if (IORESOURCE_MEM & pci_resource_flags(pdev, bar)) { resource_size_t reg_sz; mmio_pa = pci_resource_start(pdev, bar); if (mmio_pa == 0U) { err = -EIO; goto err_free_aq_hw; } reg_sz = pci_resource_len(pdev, bar); if ((reg_sz <= 24 /*ATL_REGS_SIZE*/)) { err = -EIO; goto err_free_aq_hw; } self->aq_hw->mmio = ioremap_nocache(mmio_pa, reg_sz); if (!self->aq_hw->mmio) { err = -EIO; goto err_free_aq_hw; } break; } } if (bar == 4) { err = -EIO; goto err_free_aq_hw; } numvecs = min((u8)AQ_CFG_VECS_DEF, aq_nic_get_cfg(self)->aq_hw_caps->msix_irqs); numvecs = min(numvecs, num_online_cpus()); /*enable interrupts */ #if !AQ_CFG_FORCE_LEGACY_INT err = pci_alloc_irq_vectors(self->pdev, 1, numvecs, PCI_IRQ_MSIX | PCI_IRQ_MSI | PCI_IRQ_LEGACY); if (err < 0) goto err_hwinit; numvecs = err; #endif self->irqvecs = numvecs; /* net device init */ aq_nic_cfg_start(self); aq_nic_ndev_init(self); err = aq_nic_ndev_register(self); if (err < 0) goto err_register; return 0; err_register: aq_nic_free_vectors(self); aq_pci_free_irq_vectors(self); err_hwinit: iounmap(self->aq_hw->mmio); err_free_aq_hw: kfree(self->aq_hw); err_ioremap: free_netdev(ndev); err_ndev: pci_release_regions(pdev); err_pci_func: pci_disable_device(pdev); return err; }