diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h index 0fd9cd917132..67fd780b1fa1 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -260,6 +260,7 @@ struct enic { u16 num_vfs; #endif enum enic_vf_type vf_type; + unsigned int enable_count; spinlock_t enic_api_lock; bool enic_api_busy; struct enic_port_profile *pp; diff --git a/drivers/net/ethernet/cisco/enic/enic_dev.c b/drivers/net/ethernet/cisco/enic/enic_dev.c index 2cbae7c6cc3d..659787f73cf1 100644 --- a/drivers/net/ethernet/cisco/enic/enic_dev.c +++ b/drivers/net/ethernet/cisco/enic/enic_dev.c @@ -131,10 +131,13 @@ int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic) int enic_dev_enable(struct enic *enic) { - int err; + int err = 0; spin_lock_bh(&enic->devcmd_lock); - err = vnic_dev_enable_wait(enic->vdev); + if (enic->enable_count == 0) + err = vnic_dev_enable_wait(enic->vdev); + if (!err) + enic->enable_count++; spin_unlock_bh(&enic->devcmd_lock); return err; @@ -142,10 +145,16 @@ int enic_dev_enable(struct enic *enic) int enic_dev_disable(struct enic *enic) { - int err; + int err = 0; spin_lock_bh(&enic->devcmd_lock); - err = vnic_dev_disable(enic->vdev); + if (enic->enable_count == 0) { + spin_unlock_bh(&enic->devcmd_lock); + return 0; + } + enic->enable_count--; + if (enic->enable_count == 0) + err = vnic_dev_disable(enic->vdev); spin_unlock_bh(&enic->devcmd_lock); return err; diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index acd05350ec1a..e7125b818087 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1750,7 +1750,11 @@ static int enic_open(struct net_device *netdev) if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX) for (i = 0; i < enic->wq_count; i++) napi_enable(&enic->napi[enic_cq_wq(enic, i)]); - enic_dev_enable(enic); + err = enic_dev_enable(enic); + if (err) { + netdev_err(netdev, "Failed to enable device: %d\n", err); + goto err_out_dev_enable; + } for (i = 0; i < enic->intr_count; i++) vnic_intr_unmask(&enic->intr[i]); @@ -1760,6 +1764,17 @@ static int enic_open(struct net_device *netdev) return 0; +err_out_dev_enable: + for (i = 0; i < enic->rq_count; i++) + napi_disable(&enic->napi[i]); + if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX) + for (i = 0; i < enic->wq_count; i++) + napi_disable(&enic->napi[enic_cq_wq(enic, i)]); + netif_tx_disable(netdev); + if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic)) + enic_dev_del_station_addr(enic); + for (i = 0; i < enic->wq_count; i++) + vnic_wq_disable(&enic->wq[i].vwq); err_out_free_rq: for (i = 0; i < enic->rq_count; i++) { ret = vnic_rq_disable(&enic->rq[i].vrq);