Commit b476b003 authored by Jakub Pawlak's avatar Jakub Pawlak Committed by Jeff Kirsher

iavf: Move commands processing to the separate function

Move the commands processing outside the watchdog_task()
function. This reduce length and complexity of the function
which is mainly designed to process the watchdog state machine.
Signed-off-by: default avatarJakub Pawlak <jakub.pawlak@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 16e00c25
...@@ -1546,123 +1546,66 @@ static void iavf_watchdog_timer(struct timer_list *t) ...@@ -1546,123 +1546,66 @@ static void iavf_watchdog_timer(struct timer_list *t)
} }
/** /**
* iavf_watchdog_task - Periodic call-back task * iavf_process_aq_command - process aq_required flags
* @work: pointer to work_struct * and sends aq command
* @adapter: pointer to iavf adapter structure
*
* Returns 0 on success
* Returns error code if no command was sent
* or error code if the command failed.
**/ **/
static void iavf_watchdog_task(struct work_struct *work) static int iavf_process_aq_command(struct iavf_adapter *adapter)
{ {
struct iavf_adapter *adapter = container_of(work, if (adapter->aq_required & IAVF_FLAG_AQ_GET_CONFIG)
struct iavf_adapter, return iavf_send_vf_config_msg(adapter);
watchdog_task);
struct iavf_hw *hw = &adapter->hw;
u32 reg_val;
if (test_and_set_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section))
goto restart_watchdog;
if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED) {
reg_val = rd32(hw, IAVF_VFGEN_RSTAT) &
IAVF_VFGEN_RSTAT_VFR_STATE_MASK;
if ((reg_val == VIRTCHNL_VFR_VFACTIVE) ||
(reg_val == VIRTCHNL_VFR_COMPLETED)) {
/* A chance for redemption! */
dev_err(&adapter->pdev->dev, "Hardware came out of reset. Attempting reinit.\n");
adapter->state = __IAVF_STARTUP;
adapter->flags &= ~IAVF_FLAG_PF_COMMS_FAILED;
schedule_delayed_work(&adapter->init_task, 10);
clear_bit(__IAVF_IN_CRITICAL_TASK,
&adapter->crit_section);
/* Don't reschedule the watchdog, since we've restarted
* the init task. When init_task contacts the PF and
* gets everything set up again, it'll restart the
* watchdog for us. Down, boy. Sit. Stay. Woof.
*/
return;
}
adapter->aq_required = 0;
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
goto watchdog_done;
}
if ((adapter->state < __IAVF_DOWN) ||
(adapter->flags & IAVF_FLAG_RESET_PENDING))
goto watchdog_done;
/* check for reset */
reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;
if (!(adapter->flags & IAVF_FLAG_RESET_PENDING) && !reg_val) {
adapter->state = __IAVF_RESETTING;
adapter->flags |= IAVF_FLAG_RESET_PENDING;
dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
schedule_work(&adapter->reset_task);
adapter->aq_required = 0;
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
goto watchdog_done;
}
/* Process admin queue tasks. After init, everything gets done
* here so we don't race on the admin queue.
*/
if (adapter->current_op) {
if (!iavf_asq_done(hw)) {
dev_dbg(&adapter->pdev->dev, "Admin queue timeout\n");
iavf_send_api_ver(adapter);
}
goto watchdog_done;
}
if (adapter->aq_required & IAVF_FLAG_AQ_GET_CONFIG) {
iavf_send_vf_config_msg(adapter);
goto watchdog_done;
}
if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_QUEUES) { if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_QUEUES) {
iavf_disable_queues(adapter); iavf_disable_queues(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_MAP_VECTORS) { if (adapter->aq_required & IAVF_FLAG_AQ_MAP_VECTORS) {
iavf_map_queues(adapter); iavf_map_queues(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_ADD_MAC_FILTER) { if (adapter->aq_required & IAVF_FLAG_AQ_ADD_MAC_FILTER) {
iavf_add_ether_addrs(adapter); iavf_add_ether_addrs(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_ADD_VLAN_FILTER) { if (adapter->aq_required & IAVF_FLAG_AQ_ADD_VLAN_FILTER) {
iavf_add_vlans(adapter); iavf_add_vlans(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_DEL_MAC_FILTER) { if (adapter->aq_required & IAVF_FLAG_AQ_DEL_MAC_FILTER) {
iavf_del_ether_addrs(adapter); iavf_del_ether_addrs(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_DEL_VLAN_FILTER) { if (adapter->aq_required & IAVF_FLAG_AQ_DEL_VLAN_FILTER) {
iavf_del_vlans(adapter); iavf_del_vlans(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_VLAN_STRIPPING) { if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_VLAN_STRIPPING) {
iavf_enable_vlan_stripping(adapter); iavf_enable_vlan_stripping(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_VLAN_STRIPPING) { if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_VLAN_STRIPPING) {
iavf_disable_vlan_stripping(adapter); iavf_disable_vlan_stripping(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_CONFIGURE_QUEUES) { if (adapter->aq_required & IAVF_FLAG_AQ_CONFIGURE_QUEUES) {
iavf_configure_queues(adapter); iavf_configure_queues(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_QUEUES) { if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_QUEUES) {
iavf_enable_queues(adapter); iavf_enable_queues(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_CONFIGURE_RSS) { if (adapter->aq_required & IAVF_FLAG_AQ_CONFIGURE_RSS) {
...@@ -1670,68 +1613,138 @@ static void iavf_watchdog_task(struct work_struct *work) ...@@ -1670,68 +1613,138 @@ static void iavf_watchdog_task(struct work_struct *work)
* PF, so we don't have to set current_op as we will * PF, so we don't have to set current_op as we will
* not get a response through the ARQ. * not get a response through the ARQ.
*/ */
iavf_init_rss(adapter);
adapter->aq_required &= ~IAVF_FLAG_AQ_CONFIGURE_RSS; adapter->aq_required &= ~IAVF_FLAG_AQ_CONFIGURE_RSS;
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_GET_HENA) { if (adapter->aq_required & IAVF_FLAG_AQ_GET_HENA) {
iavf_get_hena(adapter); iavf_get_hena(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_SET_HENA) { if (adapter->aq_required & IAVF_FLAG_AQ_SET_HENA) {
iavf_set_hena(adapter); iavf_set_hena(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_SET_RSS_KEY) { if (adapter->aq_required & IAVF_FLAG_AQ_SET_RSS_KEY) {
iavf_set_rss_key(adapter); iavf_set_rss_key(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_SET_RSS_LUT) { if (adapter->aq_required & IAVF_FLAG_AQ_SET_RSS_LUT) {
iavf_set_rss_lut(adapter); iavf_set_rss_lut(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_REQUEST_PROMISC) { if (adapter->aq_required & IAVF_FLAG_AQ_REQUEST_PROMISC) {
iavf_set_promiscuous(adapter, FLAG_VF_UNICAST_PROMISC | iavf_set_promiscuous(adapter, FLAG_VF_UNICAST_PROMISC |
FLAG_VF_MULTICAST_PROMISC); FLAG_VF_MULTICAST_PROMISC);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_REQUEST_ALLMULTI) { if (adapter->aq_required & IAVF_FLAG_AQ_REQUEST_ALLMULTI) {
iavf_set_promiscuous(adapter, FLAG_VF_MULTICAST_PROMISC); iavf_set_promiscuous(adapter, FLAG_VF_MULTICAST_PROMISC);
goto watchdog_done; return 0;
} }
if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) && if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) &&
(adapter->aq_required & IAVF_FLAG_AQ_RELEASE_ALLMULTI)) { (adapter->aq_required & IAVF_FLAG_AQ_RELEASE_ALLMULTI)) {
iavf_set_promiscuous(adapter, 0); iavf_set_promiscuous(adapter, 0);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_CHANNELS) { if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_CHANNELS) {
iavf_enable_channels(adapter); iavf_enable_channels(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_CHANNELS) { if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_CHANNELS) {
iavf_disable_channels(adapter); iavf_disable_channels(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_ADD_CLOUD_FILTER) { if (adapter->aq_required & IAVF_FLAG_AQ_ADD_CLOUD_FILTER) {
iavf_add_cloud_filter(adapter); iavf_add_cloud_filter(adapter);
goto watchdog_done; return 0;
} }
if (adapter->aq_required & IAVF_FLAG_AQ_DEL_CLOUD_FILTER) { if (adapter->aq_required & IAVF_FLAG_AQ_DEL_CLOUD_FILTER) {
iavf_del_cloud_filter(adapter); iavf_del_cloud_filter(adapter);
return 0;
}
return -EAGAIN;
}
/**
* iavf_watchdog_task - Periodic call-back task
* @work: pointer to work_struct
**/
static void iavf_watchdog_task(struct work_struct *work)
{
struct iavf_adapter *adapter = container_of(work,
struct iavf_adapter,
watchdog_task);
struct iavf_hw *hw = &adapter->hw;
u32 reg_val;
if (test_and_set_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section))
goto restart_watchdog;
if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED) {
reg_val = rd32(hw, IAVF_VFGEN_RSTAT) &
IAVF_VFGEN_RSTAT_VFR_STATE_MASK;
if (reg_val == VIRTCHNL_VFR_VFACTIVE ||
reg_val == VIRTCHNL_VFR_COMPLETED) {
/* A chance for redemption! */
dev_err(&adapter->pdev->dev, "Hardware came out of reset. Attemptingreinit.\n");
adapter->state = __IAVF_STARTUP;
adapter->flags &= ~IAVF_FLAG_PF_COMMS_FAILED;
schedule_delayed_work(&adapter->init_task, 10);
clear_bit(__IAVF_IN_CRITICAL_TASK,
&adapter->crit_section);
/* Don't reschedule the watchdog, since we've restarted
* the init task. When init_task contacts the PF and
* gets everything set up again, it'll restart the
* watchdog for us. Down, boy. Sit. Stay. Woof.
*/
return;
}
adapter->aq_required = 0;
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
goto watchdog_done; goto watchdog_done;
} }
schedule_delayed_work(&adapter->client_task, msecs_to_jiffies(5)); if (adapter->state < __IAVF_DOWN ||
(adapter->flags & IAVF_FLAG_RESET_PENDING))
goto watchdog_done;
if (adapter->state == __IAVF_RUNNING) /* check for reset */
reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;
if (!(adapter->flags & IAVF_FLAG_RESET_PENDING) && !reg_val) {
adapter->state = __IAVF_RESETTING;
adapter->flags |= IAVF_FLAG_RESET_PENDING;
dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
schedule_work(&adapter->reset_task);
adapter->aq_required = 0;
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
goto watchdog_done;
}
/* Process admin queue tasks. After init, everything gets done
* here so we don't race on the admin queue.
* The check is made against -EAGAIN, as it's the error code that
* would be returned on no op to run. Failures of called functions
* return other values.
*/
if (adapter->current_op) {
if (!iavf_asq_done(hw)) {
dev_dbg(&adapter->pdev->dev, "Admin queue timeout\n");
iavf_send_api_ver(adapter);
}
} else if (iavf_process_aq_command(adapter) == -EAGAIN &&
adapter->state == __IAVF_RUNNING) {
iavf_request_stats(adapter); iavf_request_stats(adapter);
}
schedule_delayed_work(&adapter->client_task, msecs_to_jiffies(5));
watchdog_done: watchdog_done:
if (adapter->state == __IAVF_RUNNING) if (adapter->state == __IAVF_RUNNING)
iavf_detect_recover_hung(&adapter->vsi); iavf_detect_recover_hung(&adapter->vsi);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment