diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 8cb64690a6c21a13717f0430f0d9bd97de37f915..d40fc3b9c46e7e2e7efbed8fd300d6c30c41b1ca 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5354,10 +5354,14 @@ static void i40e_link_event(struct i40e_pf *pf) { bool new_link, old_link; - new_link = (pf->hw.phy.link_info.link_info & I40E_AQ_LINK_UP); + /* set this to force the get_link_status call to refresh state */ + pf->hw.phy.get_link_info = true; + old_link = (pf->hw.phy.link_info_old.link_info & I40E_AQ_LINK_UP); + new_link = i40e_get_link_status(&pf->hw); - if (new_link == old_link) + if (new_link == old_link && + new_link == netif_carrier_ok(pf->vsi[pf->lan_vsi]->netdev)) return; if (!test_bit(__I40E_DOWN, &pf->vsi[pf->lan_vsi]->state)) i40e_print_link_message(pf->vsi[pf->lan_vsi], new_link); @@ -5525,33 +5529,20 @@ static void i40e_handle_link_event(struct i40e_pf *pf, memcpy(&pf->hw.phy.link_info_old, hw_link_info, sizeof(pf->hw.phy.link_info_old)); + /* Do a new status request to re-enable LSE reporting + * and load new status information into the hw struct + * This completely ignores any state information + * in the ARQ event info, instead choosing to always + * issue the AQ update link status command. + */ + i40e_link_event(pf); + /* check for unqualified module, if link is down */ if ((status->link_info & I40E_AQ_MEDIA_AVAILABLE) && (!(status->an_info & I40E_AQ_QUALIFIED_MODULE)) && (!(status->link_info & I40E_AQ_LINK_UP))) dev_err(&pf->pdev->dev, "The driver failed to link because an unqualified module was detected.\n"); - - /* update link status */ - hw_link_info->phy_type = (enum i40e_aq_phy_type)status->phy_type; - hw_link_info->link_speed = (enum i40e_aq_link_speed)status->link_speed; - hw_link_info->link_info = status->link_info; - hw_link_info->an_info = status->an_info; - hw_link_info->ext_info = status->ext_info; - hw_link_info->lse_enable = - le16_to_cpu(status->command_flags) & - I40E_AQ_LSE_ENABLE; - - /* process the event */ - i40e_link_event(pf); - - /* Do a new status request to re-enable LSE reporting - * and load new status information into the hw struct, - * then see if the status changed while processing the - * initial event. - */ - i40e_update_link_info(&pf->hw, true); - i40e_link_event(pf); } /** @@ -6314,6 +6305,8 @@ static void i40e_service_task(struct work_struct *work) #endif i40e_clean_adminq_subtask(pf); + i40e_link_event(pf); + i40e_service_event_complete(pf); /* If the tasks have taken longer than one timer cycle or there