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

Commit f73dfc50 authored by Amit Kumar Salecha's avatar Amit Kumar Salecha Committed by David S. Miller
Browse files

qlcnic: fix fw initialization responsibility



Now any pci-func can start fw, whoever sees the reset ack first.
Before this, pci-func which sets the RESET state has the responsibility
to start fw.

Signed-off-by: default avatarAmit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bbd8c6a4
Loading
Loading
Loading
Loading
+37 −29
Original line number Diff line number Diff line
@@ -2015,6 +2015,7 @@ qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter)
	clear_bit(__QLCNIC_RESETTING, &adapter->state);
}

/* Grab api lock, before checking state */
static int
qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
{
@@ -2037,6 +2038,9 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
	u8 dev_init_timeo = adapter->dev_init_timeo;
	int portnum = adapter->portnum;

	if (test_and_clear_bit(__QLCNIC_START_FW, &adapter->state))
		return 1;

	if (qlcnic_api_lock(adapter))
		return -1;

@@ -2044,8 +2048,6 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
	if (!(val & ((int)0x1 << (portnum * 4)))) {
		val |= ((u32)0x1 << (portnum * 4));
		QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val);
	} else if (test_and_clear_bit(__QLCNIC_START_FW, &adapter->state)) {
		goto start_fw;
	}

	prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
@@ -2053,7 +2055,6 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)

	switch (prev_state) {
	case QLCNIC_DEV_COLD:
start_fw:
		QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
		qlcnic_api_unlock(adapter);
		return 1;
@@ -2113,51 +2114,59 @@ qlcnic_fwinit_work(struct work_struct *work)
{
	struct qlcnic_adapter *adapter = container_of(work,
			struct qlcnic_adapter, fw_work.work);
	int dev_state;
	u32 dev_state = 0xf;

	if (test_bit(__QLCNIC_START_FW, &adapter->state)) {
	if (qlcnic_api_lock(adapter))
		goto err_ret;

		if (qlcnic_check_drv_state(adapter) &&
			(adapter->fw_wait_cnt++ < adapter->reset_ack_timeo)) {
			qlcnic_schedule_work(adapter,
					qlcnic_fwinit_work, FW_POLL_DELAY);
			return;
	if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
		dev_err(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n",
					adapter->reset_ack_timeo);
		goto skip_ack_check;
	}

		QLCDB(adapter, DRV, "Resetting FW\n");
	if (!qlcnic_check_drv_state(adapter)) {
skip_ack_check:
		dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
		if (dev_state == QLCNIC_DEV_NEED_RESET) {
			QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
						QLCNIC_DEV_INITIALIZING);
			set_bit(__QLCNIC_START_FW, &adapter->state);
			QLCDB(adapter, DRV, "Restarting fw\n");
		}

		qlcnic_api_unlock(adapter);

		if (!qlcnic_start_firmware(adapter)) {
			qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
			return;
		}

		goto err_ret;
	}

	if (adapter->fw_wait_cnt++ > (adapter->dev_init_timeo / 2)) {
		dev_err(&adapter->pdev->dev,
				"Waiting for device to reset timeout\n");
		goto err_ret;
	}
	qlcnic_api_unlock(adapter);

	dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
	QLCDB(adapter, HW, "Func waiting: Device state=%d\n", dev_state);
	QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);

	switch (dev_state) {
	case QLCNIC_DEV_READY:
		if (!qlcnic_start_firmware(adapter)) {
			qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
	case QLCNIC_DEV_NEED_RESET:
		qlcnic_schedule_work(adapter,
			qlcnic_fwinit_work, FW_POLL_DELAY);
		return;
		}
	case QLCNIC_DEV_FAILED:
		break;

	default:
		qlcnic_schedule_work(adapter,
			qlcnic_fwinit_work, 2 * FW_POLL_DELAY);
		if (!qlcnic_start_firmware(adapter)) {
			qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
			return;
		}
	}

err_ret:
	dev_err(&adapter->pdev->dev, "Fwinit work failed state=%u "
		"fw_wait_cnt=%u\n", dev_state, adapter->fw_wait_cnt);
	netif_device_attach(adapter->netdev);
	qlcnic_clr_all_drv_state(adapter);
}
@@ -2202,6 +2211,7 @@ qlcnic_detach_work(struct work_struct *work)

}

/*Transit to RESET state from READY state only */
static void
qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
{
@@ -2212,10 +2222,8 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)

	state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);

	if (state != QLCNIC_DEV_INITIALIZING &&
					state != QLCNIC_DEV_NEED_RESET) {
	if (state == QLCNIC_DEV_READY) {
		QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET);
		set_bit(__QLCNIC_START_FW, &adapter->state);
		QLCDB(adapter, DRV, "NEED_RESET state set\n");
	}