Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+105 −92
Original line number Diff line number Diff line
@@ -1546,123 +1546,66 @@ static void iavf_watchdog_timer(struct timer_list *t)
}

/**
 * iavf_watchdog_task - Periodic call-back task
 * @work: pointer to work_struct
 * iavf_process_aq_command - process aq_required flags
 * 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,
						      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. 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_GET_CONFIG)
		return iavf_send_vf_config_msg(adapter);
	if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_QUEUES) {
		iavf_disable_queues(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_MAP_VECTORS) {
		iavf_map_queues(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_ADD_MAC_FILTER) {
		iavf_add_ether_addrs(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_ADD_VLAN_FILTER) {
		iavf_add_vlans(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_DEL_MAC_FILTER) {
		iavf_del_ether_addrs(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_DEL_VLAN_FILTER) {
		iavf_del_vlans(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_VLAN_STRIPPING) {
		iavf_enable_vlan_stripping(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_VLAN_STRIPPING) {
		iavf_disable_vlan_stripping(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_CONFIGURE_QUEUES) {
		iavf_configure_queues(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_QUEUES) {
		iavf_enable_queues(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_CONFIGURE_RSS) {
@@ -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
		 * not get a response through the ARQ.
		 */
		iavf_init_rss(adapter);
		adapter->aq_required &= ~IAVF_FLAG_AQ_CONFIGURE_RSS;
		goto watchdog_done;
		return 0;
	}
	if (adapter->aq_required & IAVF_FLAG_AQ_GET_HENA) {
		iavf_get_hena(adapter);
		goto watchdog_done;
		return 0;
	}
	if (adapter->aq_required & IAVF_FLAG_AQ_SET_HENA) {
		iavf_set_hena(adapter);
		goto watchdog_done;
		return 0;
	}
	if (adapter->aq_required & IAVF_FLAG_AQ_SET_RSS_KEY) {
		iavf_set_rss_key(adapter);
		goto watchdog_done;
		return 0;
	}
	if (adapter->aq_required & IAVF_FLAG_AQ_SET_RSS_LUT) {
		iavf_set_rss_lut(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_REQUEST_PROMISC) {
		iavf_set_promiscuous(adapter, FLAG_VF_UNICAST_PROMISC |
				       FLAG_VF_MULTICAST_PROMISC);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_REQUEST_ALLMULTI) {
		iavf_set_promiscuous(adapter, FLAG_VF_MULTICAST_PROMISC);
		goto watchdog_done;
		return 0;
	}

	if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) &&
	    (adapter->aq_required & IAVF_FLAG_AQ_RELEASE_ALLMULTI)) {
		iavf_set_promiscuous(adapter, 0);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_ENABLE_CHANNELS) {
		iavf_enable_channels(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_CHANNELS) {
		iavf_disable_channels(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_ADD_CLOUD_FILTER) {
		iavf_add_cloud_filter(adapter);
		goto watchdog_done;
		return 0;
	}

	if (adapter->aq_required & IAVF_FLAG_AQ_DEL_CLOUD_FILTER) {
		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;
	}

	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);
	}

	schedule_delayed_work(&adapter->client_task, msecs_to_jiffies(5));

watchdog_done:
	if (adapter->state == __IAVF_RUNNING)
		iavf_detect_recover_hung(&adapter->vsi);