/* rtnl lock is held, process context */ static int enic_open(struct net_device *netdev) { struct enic *enic = netdev_priv(netdev); unsigned int i; int err; err = enic_request_intr(enic); if (err) { printk(KERN_ERR PFX "%s: Unable to request irq.\n", netdev->name); return err; } err = enic_notify_set(enic); if (err) { printk(KERN_ERR PFX "%s: Failed to alloc notify buffer, aborting.\n", netdev->name); goto err_out_free_intr; } for (i = 0; i < enic->rq_count; i++) { err = vnic_rq_fill(&enic->rq[i], enic_rq_alloc_buf); if (err) { printk(KERN_ERR PFX "%s: Unable to alloc receive buffers.\n", netdev->name); goto err_out_notify_unset; } } for (i = 0; i < enic->wq_count; i++) vnic_wq_enable(&enic->wq[i]); for (i = 0; i < enic->rq_count; i++) vnic_rq_enable(&enic->rq[i]); enic_add_station_addr(enic); enic_set_multicast_list(netdev); netif_wake_queue(netdev); napi_enable(&enic->napi); vnic_dev_enable(enic->vdev); for (i = 0; i < enic->intr_count; i++) vnic_intr_unmask(&enic->intr[i]); enic_notify_timer_start(enic); return 0; err_out_notify_unset: vnic_dev_notify_unset(enic->vdev); err_out_free_intr: enic_free_intr(enic); return err; }
static int enic_stop(struct net_device *netdev) { struct enic *enic = netdev_priv(netdev); unsigned int i; int err; del_timer_sync(&enic->notify_timer); spin_lock(&enic->devcmd_lock); vnic_dev_disable(enic->vdev); spin_unlock(&enic->devcmd_lock); napi_disable(&enic->napi); netif_stop_queue(netdev); for (i = 0; i < enic->intr_count; i++) vnic_intr_mask(&enic->intr[i]); for (i = 0; i < enic->wq_count; i++) { err = vnic_wq_disable(&enic->wq[i]); if (err) return err; } for (i = 0; i < enic->rq_count; i++) { err = vnic_rq_disable(&enic->rq[i]); if (err) return err; } spin_lock(&enic->devcmd_lock); vnic_dev_notify_unset(enic->vdev); spin_unlock(&enic->devcmd_lock); enic_free_intr(enic); (void)vnic_cq_service(&enic->cq[ENIC_CQ_RQ], -1, enic_rq_service_drop, NULL); (void)vnic_cq_service(&enic->cq[ENIC_CQ_WQ], -1, enic_wq_service, NULL); for (i = 0; i < enic->wq_count; i++) vnic_wq_clean(&enic->wq[i], enic_free_wq_buf); for (i = 0; i < enic->rq_count; i++) vnic_rq_clean(&enic->rq[i], enic_free_rq_buf); for (i = 0; i < enic->cq_count; i++) vnic_cq_clean(&enic->cq[i]); for (i = 0; i < enic->intr_count; i++) vnic_intr_clean(&enic->intr[i]); return 0; }
static int enic_request_intr(struct enic *enic) { struct net_device *netdev = enic->netdev; unsigned int i; int err = 0; switch (vnic_dev_get_intr_mode(enic->vdev)) { case VNIC_DEV_INTR_MODE_INTX: err = request_irq(enic->pdev->irq, enic_isr_legacy, IRQF_SHARED, netdev->name, netdev); break; case VNIC_DEV_INTR_MODE_MSI: err = request_irq(enic->pdev->irq, enic_isr_msi, 0, netdev->name, enic); break; case VNIC_DEV_INTR_MODE_MSIX: sprintf(enic->msix[ENIC_MSIX_RQ].devname, "%.11s-rx-0", netdev->name); enic->msix[ENIC_MSIX_RQ].isr = enic_isr_msix_rq; enic->msix[ENIC_MSIX_RQ].devid = enic; sprintf(enic->msix[ENIC_MSIX_WQ].devname, "%.11s-tx-0", netdev->name); enic->msix[ENIC_MSIX_WQ].isr = enic_isr_msix_wq; enic->msix[ENIC_MSIX_WQ].devid = enic; sprintf(enic->msix[ENIC_MSIX_ERR].devname, "%.11s-err", netdev->name); enic->msix[ENIC_MSIX_ERR].isr = enic_isr_msix_err; enic->msix[ENIC_MSIX_ERR].devid = enic; sprintf(enic->msix[ENIC_MSIX_NOTIFY].devname, "%.11s-notify", netdev->name); enic->msix[ENIC_MSIX_NOTIFY].isr = enic_isr_msix_notify; enic->msix[ENIC_MSIX_NOTIFY].devid = enic; for (i = 0; i < ARRAY_SIZE(enic->msix); i++) { err = request_irq(enic->msix_entry[i].vector, enic->msix[i].isr, 0, enic->msix[i].devname, enic->msix[i].devid); if (err) { enic_free_intr(enic); break; } enic->msix[i].requested = 1; } break; default: break; } return err; }