Commit 898ef1cb authored by Mateusz Palczewski's avatar Mateusz Palczewski Committed by Tony Nguyen

iavf: Combine init and watchdog state machines

Use single state machine for driver initialization and for service
initialized driver. The init state machine implemented in init_task()
is merged into the watchdog_task(). The init_task() function is
removed.
Signed-off-by: default avatarJakub Pawlak <jakub.pawlak@intel.com>
Signed-off-by: default avatarJan Sokolowski <jan.sokolowski@intel.com>
Signed-off-by: default avatarMateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: default avatarKonrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 59756ad6
...@@ -226,7 +226,6 @@ struct iavf_adapter { ...@@ -226,7 +226,6 @@ struct iavf_adapter {
struct work_struct reset_task; struct work_struct reset_task;
struct work_struct adminq_task; struct work_struct adminq_task;
struct delayed_work client_task; struct delayed_work client_task;
struct delayed_work init_task;
wait_queue_head_t down_waitqueue; wait_queue_head_t down_waitqueue;
struct iavf_q_vector *q_vectors; struct iavf_q_vector *q_vectors;
struct list_head vlan_filter_list; struct list_head vlan_filter_list;
......
...@@ -1944,7 +1944,48 @@ static void iavf_watchdog_task(struct work_struct *work) ...@@ -1944,7 +1944,48 @@ static void iavf_watchdog_task(struct work_struct *work)
if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED) if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
iavf_change_state(adapter, __IAVF_COMM_FAILED); iavf_change_state(adapter, __IAVF_COMM_FAILED);
if (adapter->flags & IAVF_FLAG_RESET_NEEDED &&
adapter->state != __IAVF_RESETTING) {
iavf_change_state(adapter, __IAVF_RESETTING);
adapter->aq_required = 0;
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
}
switch (adapter->state) { switch (adapter->state) {
case __IAVF_STARTUP:
iavf_startup(adapter);
mutex_unlock(&adapter->crit_lock);
queue_delayed_work(iavf_wq, &adapter->watchdog_task,
msecs_to_jiffies(30));
return;
case __IAVF_INIT_VERSION_CHECK:
iavf_init_version_check(adapter);
mutex_unlock(&adapter->crit_lock);
queue_delayed_work(iavf_wq, &adapter->watchdog_task,
msecs_to_jiffies(30));
return;
case __IAVF_INIT_GET_RESOURCES:
iavf_init_get_resources(adapter);
mutex_unlock(&adapter->crit_lock);
queue_delayed_work(iavf_wq, &adapter->watchdog_task,
msecs_to_jiffies(1));
return;
case __IAVF_INIT_FAILED:
if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) {
dev_err(&adapter->pdev->dev,
"Failed to communicate with PF; waiting before retry\n");
adapter->flags |= IAVF_FLAG_PF_COMMS_FAILED;
iavf_shutdown_adminq(hw);
mutex_unlock(&adapter->crit_lock);
queue_delayed_work(iavf_wq,
&adapter->watchdog_task, (5 * HZ));
return;
}
/* Try again from failed step*/
iavf_change_state(adapter, adapter->last_state);
mutex_unlock(&adapter->crit_lock);
queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ);
return;
case __IAVF_COMM_FAILED: case __IAVF_COMM_FAILED:
reg_val = rd32(hw, IAVF_VFGEN_RSTAT) & reg_val = rd32(hw, IAVF_VFGEN_RSTAT) &
IAVF_VFGEN_RSTAT_VFR_STATE_MASK; IAVF_VFGEN_RSTAT_VFR_STATE_MASK;
...@@ -1953,23 +1994,19 @@ static void iavf_watchdog_task(struct work_struct *work) ...@@ -1953,23 +1994,19 @@ static void iavf_watchdog_task(struct work_struct *work)
/* A chance for redemption! */ /* A chance for redemption! */
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Hardware came out of reset. Attempting reinit.\n"); "Hardware came out of reset. Attempting reinit.\n");
iavf_change_state(adapter, __IAVF_STARTUP); /* When init task contacts the PF and
adapter->flags &= ~IAVF_FLAG_PF_COMMS_FAILED;
queue_delayed_work(iavf_wq, &adapter->init_task, 10);
mutex_unlock(&adapter->crit_lock);
/* 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 * gets everything set up again, it'll restart the
* watchdog for us. Down, boy. Sit. Stay. Woof. * watchdog for us. Down, boy. Sit. Stay. Woof.
*/ */
return; iavf_change_state(adapter, __IAVF_STARTUP);
adapter->flags &= ~IAVF_FLAG_PF_COMMS_FAILED;
} }
adapter->aq_required = 0; adapter->aq_required = 0;
adapter->current_op = VIRTCHNL_OP_UNKNOWN; adapter->current_op = VIRTCHNL_OP_UNKNOWN;
queue_delayed_work(iavf_wq, queue_delayed_work(iavf_wq,
&adapter->watchdog_task, &adapter->watchdog_task,
msecs_to_jiffies(10)); msecs_to_jiffies(10));
goto watchdog_done; return;
case __IAVF_RESETTING: case __IAVF_RESETTING:
mutex_unlock(&adapter->crit_lock); mutex_unlock(&adapter->crit_lock);
queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2); queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2);
...@@ -1992,12 +2029,14 @@ static void iavf_watchdog_task(struct work_struct *work) ...@@ -1992,12 +2029,14 @@ static void iavf_watchdog_task(struct work_struct *work)
adapter->state == __IAVF_RUNNING) adapter->state == __IAVF_RUNNING)
iavf_request_stats(adapter); iavf_request_stats(adapter);
} }
if (adapter->state == __IAVF_RUNNING)
iavf_detect_recover_hung(&adapter->vsi);
break; break;
case __IAVF_REMOVE: case __IAVF_REMOVE:
mutex_unlock(&adapter->crit_lock); mutex_unlock(&adapter->crit_lock);
return; return;
default: default:
goto restart_watchdog; return;
} }
/* check for hw reset */ /* check for hw reset */
...@@ -2009,22 +2048,21 @@ static void iavf_watchdog_task(struct work_struct *work) ...@@ -2009,22 +2048,21 @@ static void iavf_watchdog_task(struct work_struct *work)
adapter->current_op = VIRTCHNL_OP_UNKNOWN; adapter->current_op = VIRTCHNL_OP_UNKNOWN;
dev_err(&adapter->pdev->dev, "Hardware reset detected\n"); dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
queue_work(iavf_wq, &adapter->reset_task); queue_work(iavf_wq, &adapter->reset_task);
goto watchdog_done; mutex_unlock(&adapter->crit_lock);
queue_delayed_work(iavf_wq,
&adapter->watchdog_task, HZ * 2);
return;
} }
schedule_delayed_work(&adapter->client_task, msecs_to_jiffies(5)); schedule_delayed_work(&adapter->client_task, msecs_to_jiffies(5));
watchdog_done:
if (adapter->state == __IAVF_RUNNING ||
adapter->state == __IAVF_COMM_FAILED)
iavf_detect_recover_hung(&adapter->vsi);
mutex_unlock(&adapter->crit_lock); mutex_unlock(&adapter->crit_lock);
restart_watchdog: restart_watchdog:
queue_work(iavf_wq, &adapter->adminq_task);
if (adapter->aq_required) if (adapter->aq_required)
queue_delayed_work(iavf_wq, &adapter->watchdog_task, queue_delayed_work(iavf_wq, &adapter->watchdog_task,
msecs_to_jiffies(20)); msecs_to_jiffies(20));
else else
queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2); queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2);
queue_work(iavf_wq, &adapter->adminq_task);
} }
static void iavf_disable_vf(struct iavf_adapter *adapter) static void iavf_disable_vf(struct iavf_adapter *adapter)
...@@ -2310,6 +2348,8 @@ static void iavf_reset_task(struct work_struct *work) ...@@ -2310,6 +2348,8 @@ static void iavf_reset_task(struct work_struct *work)
reset_err: reset_err:
mutex_unlock(&adapter->client_lock); mutex_unlock(&adapter->client_lock);
mutex_unlock(&adapter->crit_lock); mutex_unlock(&adapter->crit_lock);
if (running)
iavf_change_state(adapter, __IAVF_RUNNING);
dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n"); dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
iavf_close(netdev); iavf_close(netdev);
} }
...@@ -3635,67 +3675,6 @@ int iavf_process_config(struct iavf_adapter *adapter) ...@@ -3635,67 +3675,6 @@ int iavf_process_config(struct iavf_adapter *adapter)
return 0; return 0;
} }
/**
* iavf_init_task - worker thread to perform delayed initialization
* @work: pointer to work_struct containing our data
*
* This task completes the work that was begun in probe. Due to the nature
* of VF-PF communications, we may need to wait tens of milliseconds to get
* responses back from the PF. Rather than busy-wait in probe and bog down the
* whole system, we'll do it in a task so we can sleep.
* This task only runs during driver init. Once we've established
* communications with the PF driver and set up our netdev, the watchdog
* takes over.
**/
static void iavf_init_task(struct work_struct *work)
{
struct iavf_adapter *adapter = container_of(work,
struct iavf_adapter,
init_task.work);
struct iavf_hw *hw = &adapter->hw;
if (iavf_lock_timeout(&adapter->crit_lock, 5000)) {
dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__);
return;
}
switch (adapter->state) {
case __IAVF_STARTUP:
iavf_startup(adapter);
if (adapter->state == __IAVF_INIT_FAILED)
goto init_failed;
break;
case __IAVF_INIT_VERSION_CHECK:
iavf_init_version_check(adapter);
if (adapter->state == __IAVF_INIT_FAILED)
goto init_failed;
break;
case __IAVF_INIT_GET_RESOURCES:
iavf_init_get_resources(adapter);
if (adapter->state == __IAVF_INIT_FAILED)
goto init_failed;
goto out;
default:
goto init_failed;
}
queue_delayed_work(iavf_wq, &adapter->init_task,
msecs_to_jiffies(30));
goto out;
init_failed:
if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) {
dev_err(&adapter->pdev->dev,
"Failed to communicate with PF; waiting before retry\n");
adapter->flags |= IAVF_FLAG_PF_COMMS_FAILED;
iavf_shutdown_adminq(hw);
iavf_change_state(adapter, __IAVF_STARTUP);
queue_delayed_work(iavf_wq, &adapter->init_task, HZ * 5);
goto out;
}
queue_delayed_work(iavf_wq, &adapter->init_task, HZ);
out:
mutex_unlock(&adapter->crit_lock);
}
/** /**
* iavf_shutdown - Shutdown the device in preparation for a reboot * iavf_shutdown - Shutdown the device in preparation for a reboot
* @pdev: pci device structure * @pdev: pci device structure
...@@ -3830,8 +3809,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3830,8 +3809,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&adapter->adminq_task, iavf_adminq_task); INIT_WORK(&adapter->adminq_task, iavf_adminq_task);
INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task); INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task);
INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task); INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task);
INIT_DELAYED_WORK(&adapter->init_task, iavf_init_task); queue_delayed_work(iavf_wq, &adapter->watchdog_task,
queue_delayed_work(iavf_wq, &adapter->init_task,
msecs_to_jiffies(5 * (pdev->devfn & 0x07))); msecs_to_jiffies(5 * (pdev->devfn & 0x07)));
/* Setup the wait queue for indicating transition to down status */ /* Setup the wait queue for indicating transition to down status */
...@@ -3937,8 +3915,8 @@ static void iavf_remove(struct pci_dev *pdev) ...@@ -3937,8 +3915,8 @@ static void iavf_remove(struct pci_dev *pdev)
int err; int err;
/* Indicate we are in remove and not to run reset_task */ /* Indicate we are in remove and not to run reset_task */
mutex_lock(&adapter->remove_lock); mutex_lock(&adapter->remove_lock);
cancel_delayed_work_sync(&adapter->init_task);
cancel_work_sync(&adapter->reset_task); cancel_work_sync(&adapter->reset_task);
cancel_delayed_work_sync(&adapter->watchdog_task);
cancel_delayed_work_sync(&adapter->client_task); cancel_delayed_work_sync(&adapter->client_task);
if (adapter->netdev_registered) { if (adapter->netdev_registered) {
unregister_netdev(netdev); unregister_netdev(netdev);
......
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