brintos

brintos / linux-shallow public Read only

0
0
Text · 64.6 KiB · b733374 Raw
2601 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * QLogic qlcnic NIC Driver4 * Copyright (c) 2009-2013 QLogic Corporation5 */6 7#include "qlcnic_sriov.h"8#include "qlcnic.h"9#include "qlcnic_hw.h"10 11/* Reset template definitions */12#define QLC_83XX_RESTART_TEMPLATE_SIZE		0x200013#define QLC_83XX_RESET_TEMPLATE_ADDR		0x4F000014#define QLC_83XX_RESET_SEQ_VERSION		0x010115 16#define QLC_83XX_OPCODE_NOP			0x000017#define QLC_83XX_OPCODE_WRITE_LIST		0x000118#define QLC_83XX_OPCODE_READ_WRITE_LIST		0x000219#define QLC_83XX_OPCODE_POLL_LIST		0x000420#define QLC_83XX_OPCODE_POLL_WRITE_LIST		0x000821#define QLC_83XX_OPCODE_READ_MODIFY_WRITE	0x001022#define QLC_83XX_OPCODE_SEQ_PAUSE		0x002023#define QLC_83XX_OPCODE_SEQ_END			0x004024#define QLC_83XX_OPCODE_TMPL_END		0x008025#define QLC_83XX_OPCODE_POLL_READ_LIST		0x010026 27/* EPORT control registers */28#define QLC_83XX_RESET_CONTROL			0x28084E5029#define QLC_83XX_RESET_REG			0x28084E6030#define QLC_83XX_RESET_PORT0			0x28084E7031#define QLC_83XX_RESET_PORT1			0x28084E8032#define QLC_83XX_RESET_PORT2			0x28084E9033#define QLC_83XX_RESET_PORT3			0x28084EA034#define QLC_83XX_RESET_SRESHIM			0x28084EB035#define QLC_83XX_RESET_EPGSHIM			0x28084EC036#define QLC_83XX_RESET_ETHERPCS			0x28084ED037 38static int qlcnic_83xx_init_default_driver(struct qlcnic_adapter *adapter);39static int qlcnic_83xx_check_heartbeat(struct qlcnic_adapter *p_dev);40static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter);41static int qlcnic_83xx_check_hw_status(struct qlcnic_adapter *p_dev);42static int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *);43static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *);44 45/* Template header */46struct qlc_83xx_reset_hdr {47#if defined(__LITTLE_ENDIAN)48	u16	version;49	u16	signature;50	u16	size;51	u16	entries;52	u16	hdr_size;53	u16	checksum;54	u16	init_offset;55	u16	start_offset;56#elif defined(__BIG_ENDIAN)57	u16	signature;58	u16	version;59	u16	entries;60	u16	size;61	u16	checksum;62	u16	hdr_size;63	u16	start_offset;64	u16	init_offset;65#endif66} __packed;67 68/* Command entry header. */69struct qlc_83xx_entry_hdr {70#if defined(__LITTLE_ENDIAN)71	u16	cmd;72	u16	size;73	u16	count;74	u16	delay;75#elif defined(__BIG_ENDIAN)76	u16	size;77	u16	cmd;78	u16	delay;79	u16	count;80#endif81} __packed;82 83/* Generic poll command */84struct qlc_83xx_poll {85	u32	mask;86	u32	status;87} __packed;88 89/* Read modify write command */90struct qlc_83xx_rmw {91	u32	mask;92	u32	xor_value;93	u32	or_value;94#if defined(__LITTLE_ENDIAN)95	u8	shl;96	u8	shr;97	u8	index_a;98	u8	rsvd;99#elif defined(__BIG_ENDIAN)100	u8	rsvd;101	u8	index_a;102	u8	shr;103	u8	shl;104#endif105} __packed;106 107/* Generic command with 2 DWORD */108struct qlc_83xx_entry {109	u32 arg1;110	u32 arg2;111} __packed;112 113/* Generic command with 4 DWORD */114struct qlc_83xx_quad_entry {115	u32 dr_addr;116	u32 dr_value;117	u32 ar_addr;118	u32 ar_value;119} __packed;120static const char *const qlc_83xx_idc_states[] = {121	"Unknown",122	"Cold",123	"Init",124	"Ready",125	"Need Reset",126	"Need Quiesce",127	"Failed",128	"Quiesce"129};130 131static int132qlcnic_83xx_idc_check_driver_presence_reg(struct qlcnic_adapter *adapter)133{134	u32 val;135 136	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);137	if ((val & 0xFFFF))138		return 1;139	else140		return 0;141}142 143static void qlcnic_83xx_idc_log_state_history(struct qlcnic_adapter *adapter)144{145	u32 cur, prev;146	cur = adapter->ahw->idc.curr_state;147	prev = adapter->ahw->idc.prev_state;148 149	dev_info(&adapter->pdev->dev,150		 "current state  = %s,  prev state = %s\n",151		 adapter->ahw->idc.name[cur],152		 adapter->ahw->idc.name[prev]);153}154 155static int qlcnic_83xx_idc_update_audit_reg(struct qlcnic_adapter *adapter,156					    u8 mode, int lock)157{158	u32 val;159	int seconds;160 161	if (lock) {162		if (qlcnic_83xx_lock_driver(adapter))163			return -EBUSY;164	}165 166	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT);167	val |= (adapter->portnum & 0xf);168	val |= mode << 7;169	if (mode)170		seconds = jiffies / HZ - adapter->ahw->idc.sec_counter;171	else172		seconds = jiffies / HZ;173 174	val |= seconds << 8;175	QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT, val);176	adapter->ahw->idc.sec_counter = jiffies / HZ;177 178	if (lock)179		qlcnic_83xx_unlock_driver(adapter);180 181	return 0;182}183 184static void qlcnic_83xx_idc_update_minor_version(struct qlcnic_adapter *adapter)185{186	u32 val;187 188	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MIN_VERSION);189	val = val & ~(0x3 << (adapter->portnum * 2));190	val = val | (QLC_83XX_IDC_MINOR_VERSION << (adapter->portnum * 2));191	QLCWRX(adapter->ahw, QLC_83XX_IDC_MIN_VERSION, val);192}193 194static int qlcnic_83xx_idc_update_major_version(struct qlcnic_adapter *adapter,195						int lock)196{197	u32 val;198 199	if (lock) {200		if (qlcnic_83xx_lock_driver(adapter))201			return -EBUSY;202	}203 204	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION);205	val = val & ~0xFF;206	val = val | QLC_83XX_IDC_MAJOR_VERSION;207	QLCWRX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION, val);208 209	if (lock)210		qlcnic_83xx_unlock_driver(adapter);211 212	return 0;213}214 215static int216qlcnic_83xx_idc_update_drv_presence_reg(struct qlcnic_adapter *adapter,217					int status, int lock)218{219	u32 val;220 221	if (lock) {222		if (qlcnic_83xx_lock_driver(adapter))223			return -EBUSY;224	}225 226	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);227 228	if (status)229		val = val | (1 << adapter->portnum);230	else231		val = val & ~(1 << adapter->portnum);232 233	QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val);234	qlcnic_83xx_idc_update_minor_version(adapter);235 236	if (lock)237		qlcnic_83xx_unlock_driver(adapter);238 239	return 0;240}241 242static int qlcnic_83xx_idc_check_major_version(struct qlcnic_adapter *adapter)243{244	u32 val;245	u8 version;246 247	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION);248	version = val & 0xFF;249 250	if (version != QLC_83XX_IDC_MAJOR_VERSION) {251		dev_info(&adapter->pdev->dev,252			 "%s:mismatch. version 0x%x, expected version 0x%x\n",253			 __func__, version, QLC_83XX_IDC_MAJOR_VERSION);254		return -EIO;255	}256 257	return 0;258}259 260static int qlcnic_83xx_idc_clear_registers(struct qlcnic_adapter *adapter,261					   int lock)262{263	u32 val;264 265	if (lock) {266		if (qlcnic_83xx_lock_driver(adapter))267			return -EBUSY;268	}269 270	QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_ACK, 0);271	/* Clear graceful reset bit */272	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);273	val &= ~QLC_83XX_IDC_GRACEFULL_RESET;274	QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);275 276	if (lock)277		qlcnic_83xx_unlock_driver(adapter);278 279	return 0;280}281 282static int qlcnic_83xx_idc_update_drv_ack_reg(struct qlcnic_adapter *adapter,283					      int flag, int lock)284{285	u32 val;286 287	if (lock) {288		if (qlcnic_83xx_lock_driver(adapter))289			return -EBUSY;290	}291 292	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_ACK);293	if (flag)294		val = val | (1 << adapter->portnum);295	else296		val = val & ~(1 << adapter->portnum);297	QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_ACK, val);298 299	if (lock)300		qlcnic_83xx_unlock_driver(adapter);301 302	return 0;303}304 305static int qlcnic_83xx_idc_check_timeout(struct qlcnic_adapter *adapter,306					 int time_limit)307{308	u64 seconds;309 310	seconds = jiffies / HZ - adapter->ahw->idc.sec_counter;311	if (seconds <= time_limit)312		return 0;313	else314		return -EBUSY;315}316 317/**318 * qlcnic_83xx_idc_check_reset_ack_reg319 *320 * @adapter: adapter structure321 *322 * Check ACK wait limit and clear the functions which failed to ACK323 *324 * Return 0 if all functions have acknowledged the reset request.325 **/326static int qlcnic_83xx_idc_check_reset_ack_reg(struct qlcnic_adapter *adapter)327{328	int timeout;329	u32 ack, presence, val;330 331	timeout = QLC_83XX_IDC_RESET_TIMEOUT_SECS;332	ack = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_ACK);333	presence = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);334	dev_info(&adapter->pdev->dev,335		 "%s: ack = 0x%x, presence = 0x%x\n", __func__, ack, presence);336	if (!((ack & presence) == presence)) {337		if (qlcnic_83xx_idc_check_timeout(adapter, timeout)) {338			/* Clear functions which failed to ACK */339			dev_info(&adapter->pdev->dev,340				 "%s: ACK wait exceeds time limit\n", __func__);341			val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);342			val = val & ~(ack ^ presence);343			if (qlcnic_83xx_lock_driver(adapter))344				return -EBUSY;345			QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val);346			dev_info(&adapter->pdev->dev,347				 "%s: updated drv presence reg = 0x%x\n",348				 __func__, val);349			qlcnic_83xx_unlock_driver(adapter);350			return 0;351 352		} else {353			return 1;354		}355	} else {356		dev_info(&adapter->pdev->dev,357			 "%s: Reset ACK received from all functions\n",358			 __func__);359		return 0;360	}361}362 363/**364 * qlcnic_83xx_idc_tx_soft_reset365 *366 * @adapter: adapter structure367 *368 * Handle context deletion and recreation request from transmit routine369 *370 * Returns -EBUSY  or Success (0)371 *372 **/373static int qlcnic_83xx_idc_tx_soft_reset(struct qlcnic_adapter *adapter)374{375	struct net_device *netdev = adapter->netdev;376 377	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))378		return -EBUSY;379 380	netif_device_detach(netdev);381	qlcnic_down(adapter, netdev);382	qlcnic_up(adapter, netdev);383	netif_device_attach(netdev);384	clear_bit(__QLCNIC_RESETTING, &adapter->state);385	netdev_info(adapter->netdev, "%s: soft reset complete.\n", __func__);386 387	return 0;388}389 390/**391 * qlcnic_83xx_idc_detach_driver392 *393 * @adapter: adapter structure394 * Detach net interface, stop TX and cleanup resources before the HW reset.395 * Returns: None396 *397 **/398static void qlcnic_83xx_idc_detach_driver(struct qlcnic_adapter *adapter)399{400	int i;401	struct net_device *netdev = adapter->netdev;402 403	netif_device_detach(netdev);404	qlcnic_83xx_detach_mailbox_work(adapter);405 406	/* Disable mailbox interrupt */407	qlcnic_83xx_disable_mbx_intr(adapter);408	qlcnic_down(adapter, netdev);409	for (i = 0; i < adapter->ahw->num_msix; i++) {410		adapter->ahw->intr_tbl[i].id = i;411		adapter->ahw->intr_tbl[i].enabled = 0;412		adapter->ahw->intr_tbl[i].src = 0;413	}414 415	if (qlcnic_sriov_pf_check(adapter))416		qlcnic_sriov_pf_reset(adapter);417}418 419/**420 * qlcnic_83xx_idc_attach_driver421 *422 * @adapter: adapter structure423 *424 * Re-attach and re-enable net interface425 * Returns: None426 *427 **/428static void qlcnic_83xx_idc_attach_driver(struct qlcnic_adapter *adapter)429{430	struct net_device *netdev = adapter->netdev;431 432	if (netif_running(netdev)) {433		if (qlcnic_up(adapter, netdev))434			goto done;435		qlcnic_restore_indev_addr(netdev, NETDEV_UP);436	}437done:438	netif_device_attach(netdev);439}440 441static int qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter *adapter,442					      int lock)443{444	if (lock) {445		if (qlcnic_83xx_lock_driver(adapter))446			return -EBUSY;447	}448 449	qlcnic_83xx_idc_clear_registers(adapter, 0);450	QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_FAILED);451	if (lock)452		qlcnic_83xx_unlock_driver(adapter);453 454	qlcnic_83xx_idc_log_state_history(adapter);455	dev_info(&adapter->pdev->dev, "Device will enter failed state\n");456 457	return 0;458}459 460static int qlcnic_83xx_idc_enter_init_state(struct qlcnic_adapter *adapter,461					    int lock)462{463	if (lock) {464		if (qlcnic_83xx_lock_driver(adapter))465			return -EBUSY;466	}467 468	QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_INIT);469 470	if (lock)471		qlcnic_83xx_unlock_driver(adapter);472 473	return 0;474}475 476static int qlcnic_83xx_idc_enter_need_quiesce(struct qlcnic_adapter *adapter,477					      int lock)478{479	if (lock) {480		if (qlcnic_83xx_lock_driver(adapter))481			return -EBUSY;482	}483 484	QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,485	       QLC_83XX_IDC_DEV_NEED_QUISCENT);486 487	if (lock)488		qlcnic_83xx_unlock_driver(adapter);489 490	return 0;491}492 493static int494qlcnic_83xx_idc_enter_need_reset_state(struct qlcnic_adapter *adapter, int lock)495{496	if (lock) {497		if (qlcnic_83xx_lock_driver(adapter))498			return -EBUSY;499	}500 501	QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,502	       QLC_83XX_IDC_DEV_NEED_RESET);503 504	if (lock)505		qlcnic_83xx_unlock_driver(adapter);506 507	return 0;508}509 510static int qlcnic_83xx_idc_enter_ready_state(struct qlcnic_adapter *adapter,511					     int lock)512{513	if (lock) {514		if (qlcnic_83xx_lock_driver(adapter))515			return -EBUSY;516	}517 518	QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_READY);519	if (lock)520		qlcnic_83xx_unlock_driver(adapter);521 522	return 0;523}524 525/**526 * qlcnic_83xx_idc_find_reset_owner_id527 *528 * @adapter: adapter structure529 *530 * NIC gets precedence over ISCSI and ISCSI has precedence over FCOE.531 * Within the same class, function with lowest PCI ID assumes ownership532 *533 * Returns: reset owner id or failure indication (-EIO)534 *535 **/536static int qlcnic_83xx_idc_find_reset_owner_id(struct qlcnic_adapter *adapter)537{538	u32 reg, reg1, reg2, i, j, owner, class;539 540	reg1 = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_PARTITION_INFO_1);541	reg2 = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_PARTITION_INFO_2);542	owner = QLCNIC_TYPE_NIC;543	i = 0;544	j = 0;545	reg = reg1;546 547	do {548		class = (((reg & (0xF << j * 4)) >> j * 4) & 0x3);549		if (class == owner)550			break;551		if (i == (QLC_83XX_IDC_MAX_FUNC_PER_PARTITION_INFO - 1)) {552			reg = reg2;553			j = 0;554		} else {555			j++;556		}557 558		if (i == (QLC_83XX_IDC_MAX_CNA_FUNCTIONS - 1)) {559			if (owner == QLCNIC_TYPE_NIC)560				owner = QLCNIC_TYPE_ISCSI;561			else if (owner == QLCNIC_TYPE_ISCSI)562				owner = QLCNIC_TYPE_FCOE;563			else if (owner == QLCNIC_TYPE_FCOE)564				return -EIO;565			reg = reg1;566			j = 0;567			i = 0;568		}569	} while (i++ < QLC_83XX_IDC_MAX_CNA_FUNCTIONS);570 571	return i;572}573 574static int qlcnic_83xx_idc_restart_hw(struct qlcnic_adapter *adapter, int lock)575{576	int ret = 0;577 578	ret = qlcnic_83xx_restart_hw(adapter);579 580	if (ret) {581		qlcnic_83xx_idc_enter_failed_state(adapter, lock);582	} else {583		qlcnic_83xx_idc_clear_registers(adapter, lock);584		ret = qlcnic_83xx_idc_enter_ready_state(adapter, lock);585	}586 587	return ret;588}589 590static int qlcnic_83xx_idc_check_fan_failure(struct qlcnic_adapter *adapter)591{592	u32 status;593 594	status = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS1);595 596	if (status & QLCNIC_RCODE_FATAL_ERROR) {597		dev_err(&adapter->pdev->dev,598			"peg halt status1=0x%x\n", status);599		if (QLCNIC_FWERROR_CODE(status) == QLCNIC_FWERROR_FAN_FAILURE) {600			dev_err(&adapter->pdev->dev,601				"On board active cooling fan failed. "602				"Device has been halted.\n");603			dev_err(&adapter->pdev->dev,604				"Replace the adapter.\n");605			return -EIO;606		}607	}608 609	return 0;610}611 612int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)613{614	int err;615 616	qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox);617	qlcnic_83xx_enable_mbx_interrupt(adapter);618 619	qlcnic_83xx_initialize_nic(adapter, 1);620 621	err = qlcnic_sriov_pf_reinit(adapter);622	if (err)623		return err;624 625	qlcnic_83xx_enable_mbx_interrupt(adapter);626 627	if (qlcnic_83xx_configure_opmode(adapter)) {628		qlcnic_83xx_idc_enter_failed_state(adapter, 1);629		return -EIO;630	}631 632	if (adapter->nic_ops->init_driver(adapter)) {633		qlcnic_83xx_idc_enter_failed_state(adapter, 1);634		return -EIO;635	}636 637	if (adapter->portnum == 0)638		qlcnic_set_drv_version(adapter);639 640	qlcnic_dcb_get_info(adapter->dcb);641	qlcnic_83xx_idc_attach_driver(adapter);642 643	return 0;644}645 646static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)647{648	struct qlcnic_hardware_context *ahw = adapter->ahw;649 650	qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1);651	qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);652	set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);653 654	ahw->idc.quiesce_req = 0;655	ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;656	ahw->idc.err_code = 0;657	ahw->idc.collect_dump = 0;658	ahw->reset_context = 0;659	adapter->tx_timeo_cnt = 0;660	ahw->idc.delay_reset = 0;661 662	clear_bit(__QLCNIC_RESETTING, &adapter->state);663}664 665/**666 * qlcnic_83xx_idc_ready_state_entry667 *668 * @adapter: adapter structure669 *670 * Perform ready state initialization, this routine will get invoked only671 * once from READY state.672 *673 * Returns: Error code or Success(0)674 *675 **/676int qlcnic_83xx_idc_ready_state_entry(struct qlcnic_adapter *adapter)677{678	struct qlcnic_hardware_context *ahw = adapter->ahw;679 680	if (ahw->idc.prev_state != QLC_83XX_IDC_DEV_READY) {681		qlcnic_83xx_idc_update_idc_params(adapter);682		/* Re-attach the device if required */683		if ((ahw->idc.prev_state == QLC_83XX_IDC_DEV_NEED_RESET) ||684		    (ahw->idc.prev_state == QLC_83XX_IDC_DEV_INIT)) {685			if (qlcnic_83xx_idc_reattach_driver(adapter))686				return -EIO;687		}688	}689 690	return 0;691}692 693/**694 * qlcnic_83xx_idc_vnic_pf_entry695 *696 * @adapter: adapter structure697 *698 * Ensure vNIC mode privileged function starts only after vNIC mode is699 * enabled by management function.700 * If vNIC mode is ready, start initialization.701 *702 * Returns: -EIO or 0703 *704 **/705int qlcnic_83xx_idc_vnic_pf_entry(struct qlcnic_adapter *adapter)706{707	u32 state;708	struct qlcnic_hardware_context *ahw = adapter->ahw;709 710	/* Privileged function waits till mgmt function enables VNIC mode */711	state = QLCRDX(adapter->ahw, QLC_83XX_VNIC_STATE);712	if (state != QLCNIC_DEV_NPAR_OPER) {713		if (!ahw->idc.vnic_wait_limit--) {714			qlcnic_83xx_idc_enter_failed_state(adapter, 1);715			return -EIO;716		}717		dev_info(&adapter->pdev->dev, "vNIC mode disabled\n");718		return -EIO;719 720	} else {721		/* Perform one time initialization from ready state */722		if (ahw->idc.vnic_state != QLCNIC_DEV_NPAR_OPER) {723			qlcnic_83xx_idc_update_idc_params(adapter);724 725			/* If the previous state is UNKNOWN, device will be726			   already attached properly by Init routine*/727			if (ahw->idc.prev_state != QLC_83XX_IDC_DEV_UNKNOWN) {728				if (qlcnic_83xx_idc_reattach_driver(adapter))729					return -EIO;730			}731			adapter->ahw->idc.vnic_state =  QLCNIC_DEV_NPAR_OPER;732			dev_info(&adapter->pdev->dev, "vNIC mode enabled\n");733		}734	}735 736	return 0;737}738 739static int qlcnic_83xx_idc_unknown_state(struct qlcnic_adapter *adapter)740{741	adapter->ahw->idc.err_code = -EIO;742	dev_err(&adapter->pdev->dev,743		"%s: Device in unknown state\n", __func__);744	clear_bit(__QLCNIC_RESETTING, &adapter->state);745	return 0;746}747 748/**749 * qlcnic_83xx_idc_cold_state_handler750 *751 * @adapter: adapter structure752 *753 * If HW is up and running device will enter READY state.754 * If firmware image from host needs to be loaded, device is755 * forced to start with the file firmware image.756 *757 * Returns: Error code or Success(0)758 *759 **/760static int qlcnic_83xx_idc_cold_state_handler(struct qlcnic_adapter *adapter)761{762	qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 0);763	qlcnic_83xx_idc_update_audit_reg(adapter, 1, 0);764 765	if (qlcnic_load_fw_file) {766		qlcnic_83xx_idc_restart_hw(adapter, 0);767	} else {768		if (qlcnic_83xx_check_hw_status(adapter)) {769			qlcnic_83xx_idc_enter_failed_state(adapter, 0);770			return -EIO;771		} else {772			qlcnic_83xx_idc_enter_ready_state(adapter, 0);773		}774	}775	return 0;776}777 778/**779 * qlcnic_83xx_idc_init_state780 *781 * @adapter: adapter structure782 *783 * Reset owner will restart the device from this state.784 * Device will enter failed state if it remains785 * in this state for more than DEV_INIT time limit.786 *787 * Returns: Error code or Success(0)788 *789 **/790static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter)791{792	int timeout, ret = 0;793	u32 owner;794 795	timeout = QLC_83XX_IDC_INIT_TIMEOUT_SECS;796	if (adapter->ahw->idc.prev_state == QLC_83XX_IDC_DEV_NEED_RESET) {797		owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);798		if (adapter->ahw->pci_func == owner)799			ret = qlcnic_83xx_idc_restart_hw(adapter, 1);800	} else {801		ret = qlcnic_83xx_idc_check_timeout(adapter, timeout);802	}803 804	return ret;805}806 807/**808 * qlcnic_83xx_idc_ready_state809 *810 * @adapter: adapter structure811 *812 * Perform IDC protocol specicifed actions after monitoring device state and813 * events.814 *815 * Returns: Error code or Success(0)816 *817 **/818static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)819{820	struct qlcnic_hardware_context *ahw = adapter->ahw;821	struct qlcnic_mailbox *mbx = ahw->mailbox;822	int ret = 0;823	u32 val;824 825	/* Perform NIC configuration based ready state entry actions */826	if (ahw->idc.state_entry(adapter))827		return -EIO;828 829	if (qlcnic_check_temp(adapter)) {830		if (ahw->temp == QLCNIC_TEMP_PANIC) {831			qlcnic_83xx_idc_check_fan_failure(adapter);832			dev_err(&adapter->pdev->dev,833				"Error: device temperature %d above limits\n",834				adapter->ahw->temp);835			clear_bit(QLC_83XX_MBX_READY, &mbx->status);836			set_bit(__QLCNIC_RESETTING, &adapter->state);837			qlcnic_83xx_idc_detach_driver(adapter);838			qlcnic_83xx_idc_enter_failed_state(adapter, 1);839			return -EIO;840		}841	}842 843	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);844	ret = qlcnic_83xx_check_heartbeat(adapter);845	if (ret) {846		adapter->flags |= QLCNIC_FW_HANG;847		if (!(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {848			clear_bit(QLC_83XX_MBX_READY, &mbx->status);849			set_bit(__QLCNIC_RESETTING, &adapter->state);850			qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);851		}  else {852			netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",853				    __func__);854			qlcnic_83xx_idc_enter_failed_state(adapter, 1);855		}856		return -EIO;857	}858 859	if ((val & QLC_83XX_IDC_GRACEFULL_RESET) || ahw->idc.collect_dump) {860		clear_bit(QLC_83XX_MBX_READY, &mbx->status);861 862		/* Move to need reset state and prepare for reset */863		qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);864		return ret;865	}866 867	/* Check for soft reset request */868	if (ahw->reset_context &&869	    !(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {870		adapter->ahw->reset_context = 0;871		qlcnic_83xx_idc_tx_soft_reset(adapter);872		return ret;873	}874 875	/* Move to need quiesce state if requested */876	if (adapter->ahw->idc.quiesce_req) {877		qlcnic_83xx_idc_enter_need_quiesce(adapter, 1);878		qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);879		return ret;880	}881 882	return ret;883}884 885/**886 * qlcnic_83xx_idc_need_reset_state887 *888 * @adapter: adapter structure889 *890 * Device will remain in this state until:891 *	Reset request ACK's are received from all the functions892 *	Wait time exceeds max time limit893 *894 * Returns: Error code or Success(0)895 *896 **/897static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter)898{899	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;900	int ret = 0;901 902	if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) {903		qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);904		set_bit(__QLCNIC_RESETTING, &adapter->state);905		clear_bit(QLC_83XX_MBX_READY, &mbx->status);906		if (adapter->ahw->nic_mode == QLCNIC_VNIC_MODE)907			qlcnic_83xx_disable_vnic_mode(adapter, 1);908 909		if (qlcnic_check_diag_status(adapter)) {910			dev_info(&adapter->pdev->dev,911				 "%s: Wait for diag completion\n", __func__);912			adapter->ahw->idc.delay_reset = 1;913			return 0;914		} else {915			qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);916			qlcnic_83xx_idc_detach_driver(adapter);917		}918	}919 920	if (qlcnic_check_diag_status(adapter)) {921		dev_info(&adapter->pdev->dev,922			 "%s: Wait for diag completion\n", __func__);923		return  -1;924	} else {925		if (adapter->ahw->idc.delay_reset) {926			qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);927			qlcnic_83xx_idc_detach_driver(adapter);928			adapter->ahw->idc.delay_reset = 0;929		}930 931		/* Check for ACK from other functions */932		ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter);933		if (ret) {934			dev_info(&adapter->pdev->dev,935				 "%s: Waiting for reset ACK\n", __func__);936			return -1;937		}938	}939 940	/* Transit to INIT state and restart the HW */941	qlcnic_83xx_idc_enter_init_state(adapter, 1);942 943	return ret;944}945 946static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter)947{948	dev_err(&adapter->pdev->dev, "%s: TBD\n", __func__);949	return 0;950}951 952static void qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)953{954	struct qlcnic_hardware_context *ahw = adapter->ahw;955	u32 val, owner;956 957	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);958	if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {959		owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);960		if (ahw->pci_func == owner) {961			qlcnic_83xx_stop_hw(adapter);962			qlcnic_dump_fw(adapter);963		}964	}965 966	netdev_warn(adapter->netdev, "%s: Reboot will be required to recover the adapter!!\n",967		    __func__);968	clear_bit(__QLCNIC_RESETTING, &adapter->state);969	ahw->idc.err_code = -EIO;970 971	return;972}973 974static int qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter *adapter)975{976	dev_info(&adapter->pdev->dev, "%s: TBD\n", __func__);977	return 0;978}979 980static int qlcnic_83xx_idc_check_state_validity(struct qlcnic_adapter *adapter,981						u32 state)982{983	u32 cur, prev, next;984 985	cur = adapter->ahw->idc.curr_state;986	prev = adapter->ahw->idc.prev_state;987	next = state;988 989	if ((next < QLC_83XX_IDC_DEV_COLD) ||990	    (next > QLC_83XX_IDC_DEV_QUISCENT)) {991		dev_err(&adapter->pdev->dev,992			"%s: curr %d, prev %d, next state %d is  invalid\n",993			__func__, cur, prev, state);994		return 1;995	}996 997	if ((cur == QLC_83XX_IDC_DEV_UNKNOWN) &&998	    (prev == QLC_83XX_IDC_DEV_UNKNOWN)) {999		if ((next != QLC_83XX_IDC_DEV_COLD) &&1000		    (next != QLC_83XX_IDC_DEV_READY)) {1001			dev_err(&adapter->pdev->dev,1002				"%s: failed, cur %d prev %d next %d\n",1003				__func__, cur, prev, next);1004			return 1;1005		}1006	}1007 1008	if (next == QLC_83XX_IDC_DEV_INIT) {1009		if ((prev != QLC_83XX_IDC_DEV_INIT) &&1010		    (prev != QLC_83XX_IDC_DEV_COLD) &&1011		    (prev != QLC_83XX_IDC_DEV_NEED_RESET)) {1012			dev_err(&adapter->pdev->dev,1013				"%s: failed, cur %d prev %d next %d\n",1014				__func__, cur, prev, next);1015			return 1;1016		}1017	}1018 1019	return 0;1020}1021 1022#define QLC_83XX_ENCAP_TYPE_VXLAN	BIT_11023#define QLC_83XX_MATCH_ENCAP_ID		BIT_21024#define QLC_83XX_SET_VXLAN_UDP_DPORT	BIT_31025#define QLC_83XX_VXLAN_UDP_DPORT(PORT)	((PORT & 0xffff) << 16)1026 1027#define QLCNIC_ENABLE_INGRESS_ENCAP_PARSING 11028#define QLCNIC_DISABLE_INGRESS_ENCAP_PARSING 01029 1030int qlcnic_set_vxlan_port(struct qlcnic_adapter *adapter, u16 port)1031{1032	struct qlcnic_cmd_args cmd;1033	int ret = 0;1034 1035	memset(&cmd, 0, sizeof(cmd));1036 1037	ret = qlcnic_alloc_mbx_args(&cmd, adapter,1038				    QLCNIC_CMD_INIT_NIC_FUNC);1039	if (ret)1040		return ret;1041 1042	cmd.req.arg[1] = QLC_83XX_MULTI_TENANCY_INFO;1043	cmd.req.arg[2] = QLC_83XX_ENCAP_TYPE_VXLAN |1044			 QLC_83XX_SET_VXLAN_UDP_DPORT |1045			 QLC_83XX_VXLAN_UDP_DPORT(port);1046 1047	ret = qlcnic_issue_cmd(adapter, &cmd);1048	if (ret)1049		netdev_err(adapter->netdev,1050			   "Failed to set VXLAN port %d in adapter\n",1051			   port);1052 1053	qlcnic_free_mbx_args(&cmd);1054 1055	return ret;1056}1057 1058int qlcnic_set_vxlan_parsing(struct qlcnic_adapter *adapter, u16 port)1059{1060	struct qlcnic_cmd_args cmd;1061	int ret = 0;1062 1063	memset(&cmd, 0, sizeof(cmd));1064 1065	ret = qlcnic_alloc_mbx_args(&cmd, adapter,1066				    QLCNIC_CMD_SET_INGRESS_ENCAP);1067	if (ret)1068		return ret;1069 1070	cmd.req.arg[1] = port ? QLCNIC_ENABLE_INGRESS_ENCAP_PARSING :1071				QLCNIC_DISABLE_INGRESS_ENCAP_PARSING;1072 1073	ret = qlcnic_issue_cmd(adapter, &cmd);1074	if (ret)1075		netdev_err(adapter->netdev,1076			   "Failed to %s VXLAN parsing for port %d\n",1077			   port ? "enable" : "disable", port);1078	else1079		netdev_info(adapter->netdev,1080			    "%s VXLAN parsing for port %d\n",1081			    port ? "Enabled" : "Disabled", port);1082 1083	qlcnic_free_mbx_args(&cmd);1084 1085	return ret;1086}1087 1088static void qlcnic_83xx_periodic_tasks(struct qlcnic_adapter *adapter)1089{1090	if (adapter->fhash.fnum)1091		qlcnic_prune_lb_filters(adapter);1092}1093 1094/**1095 * qlcnic_83xx_idc_poll_dev_state1096 *1097 * @work: kernel work queue structure used to schedule the function1098 *1099 * Poll device state periodically and perform state specific1100 * actions defined by Inter Driver Communication (IDC) protocol.1101 *1102 * Returns: None1103 *1104 **/1105void qlcnic_83xx_idc_poll_dev_state(struct work_struct *work)1106{1107	struct qlcnic_adapter *adapter;1108	u32 state;1109 1110	adapter = container_of(work, struct qlcnic_adapter, fw_work.work);1111	state =	QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE);1112 1113	if (qlcnic_83xx_idc_check_state_validity(adapter, state)) {1114		qlcnic_83xx_idc_log_state_history(adapter);1115		adapter->ahw->idc.curr_state = QLC_83XX_IDC_DEV_UNKNOWN;1116	} else {1117		adapter->ahw->idc.curr_state = state;1118	}1119 1120	switch (adapter->ahw->idc.curr_state) {1121	case QLC_83XX_IDC_DEV_READY:1122		qlcnic_83xx_idc_ready_state(adapter);1123		break;1124	case QLC_83XX_IDC_DEV_NEED_RESET:1125		qlcnic_83xx_idc_need_reset_state(adapter);1126		break;1127	case QLC_83XX_IDC_DEV_NEED_QUISCENT:1128		qlcnic_83xx_idc_need_quiesce_state(adapter);1129		break;1130	case QLC_83XX_IDC_DEV_FAILED:1131		qlcnic_83xx_idc_failed_state(adapter);1132		return;1133	case QLC_83XX_IDC_DEV_INIT:1134		qlcnic_83xx_idc_init_state(adapter);1135		break;1136	case QLC_83XX_IDC_DEV_QUISCENT:1137		qlcnic_83xx_idc_quiesce_state(adapter);1138		break;1139	default:1140		qlcnic_83xx_idc_unknown_state(adapter);1141		return;1142	}1143	adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state;1144	qlcnic_83xx_periodic_tasks(adapter);1145 1146	/* Re-schedule the function */1147	if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status))1148		qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,1149				     adapter->ahw->idc.delay);1150}1151 1152static void qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter *adapter)1153{1154	u32 idc_params, val;1155 1156	if (qlcnic_83xx_flash_read32(adapter, QLC_83XX_IDC_FLASH_PARAM_ADDR,1157				     (u8 *)&idc_params, 1)) {1158		dev_info(&adapter->pdev->dev,1159			 "%s:failed to get IDC params from flash\n", __func__);1160		adapter->dev_init_timeo = QLC_83XX_IDC_INIT_TIMEOUT_SECS;1161		adapter->reset_ack_timeo = QLC_83XX_IDC_RESET_TIMEOUT_SECS;1162	} else {1163		adapter->dev_init_timeo = idc_params & 0xFFFF;1164		adapter->reset_ack_timeo = ((idc_params >> 16) & 0xFFFF);1165	}1166 1167	adapter->ahw->idc.curr_state = QLC_83XX_IDC_DEV_UNKNOWN;1168	adapter->ahw->idc.prev_state = QLC_83XX_IDC_DEV_UNKNOWN;1169	adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;1170	adapter->ahw->idc.err_code = 0;1171	adapter->ahw->idc.collect_dump = 0;1172	adapter->ahw->idc.name = (char **)qlc_83xx_idc_states;1173 1174	clear_bit(__QLCNIC_RESETTING, &adapter->state);1175	set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);1176 1177	/* Check if reset recovery is disabled */1178	if (!qlcnic_auto_fw_reset) {1179		/* Propagate do not reset request to other functions */1180		val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);1181		val = val | QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY;1182		QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);1183	}1184}1185 1186static int1187qlcnic_83xx_idc_first_to_load_function_handler(struct qlcnic_adapter *adapter)1188{1189	u32 state, val;1190 1191	if (qlcnic_83xx_lock_driver(adapter))1192		return -EIO;1193 1194	/* Clear driver lock register */1195	QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, 0);1196	if (qlcnic_83xx_idc_update_major_version(adapter, 0)) {1197		qlcnic_83xx_unlock_driver(adapter);1198		return -EIO;1199	}1200 1201	state =	QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE);1202	if (qlcnic_83xx_idc_check_state_validity(adapter, state)) {1203		qlcnic_83xx_unlock_driver(adapter);1204		return -EIO;1205	}1206 1207	if (state != QLC_83XX_IDC_DEV_COLD && qlcnic_load_fw_file) {1208		QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,1209		       QLC_83XX_IDC_DEV_COLD);1210		state = QLC_83XX_IDC_DEV_COLD;1211	}1212 1213	adapter->ahw->idc.curr_state = state;1214	/* First to load function should cold boot the device */1215	if (state == QLC_83XX_IDC_DEV_COLD)1216		qlcnic_83xx_idc_cold_state_handler(adapter);1217 1218	/* Check if reset recovery is enabled */1219	if (qlcnic_auto_fw_reset) {1220		val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);1221		val = val & ~QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY;1222		QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);1223	}1224 1225	qlcnic_83xx_unlock_driver(adapter);1226 1227	return 0;1228}1229 1230int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter)1231{1232	int ret = -EIO;1233 1234	qlcnic_83xx_setup_idc_parameters(adapter);1235 1236	if (qlcnic_83xx_get_reset_instruction_template(adapter))1237		return ret;1238 1239	if (!qlcnic_83xx_idc_check_driver_presence_reg(adapter)) {1240		if (qlcnic_83xx_idc_first_to_load_function_handler(adapter))1241			return -EIO;1242	} else {1243		if (qlcnic_83xx_idc_check_major_version(adapter))1244			return -EIO;1245	}1246 1247	qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);1248 1249	return 0;1250}1251 1252void qlcnic_83xx_idc_exit(struct qlcnic_adapter *adapter)1253{1254	int id;1255	u32 val;1256 1257	while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))1258		usleep_range(10000, 11000);1259 1260	id = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);1261	id = id & 0xFF;1262 1263	if (id == adapter->portnum) {1264		dev_err(&adapter->pdev->dev,1265			"%s: wait for lock recovery.. %d\n", __func__, id);1266		msleep(20);1267		id = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);1268		id = id & 0xFF;1269	}1270 1271	/* Clear driver presence bit */1272	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);1273	val = val & ~(1 << adapter->portnum);1274	QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val);1275	clear_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);1276	clear_bit(__QLCNIC_RESETTING, &adapter->state);1277 1278	cancel_delayed_work_sync(&adapter->fw_work);1279}1280 1281void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key)1282{1283	u32 val;1284 1285	if (qlcnic_sriov_vf_check(adapter))1286		return;1287 1288	if (qlcnic_83xx_lock_driver(adapter)) {1289		dev_err(&adapter->pdev->dev,1290			"%s:failed, please retry\n", __func__);1291		return;1292	}1293 1294	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);1295	if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {1296		netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",1297			    __func__);1298		qlcnic_83xx_idc_enter_failed_state(adapter, 0);1299		qlcnic_83xx_unlock_driver(adapter);1300		return;1301	}1302 1303	if (key == QLCNIC_FORCE_FW_RESET) {1304		val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);1305		val = val | QLC_83XX_IDC_GRACEFULL_RESET;1306		QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);1307	} else if (key == QLCNIC_FORCE_FW_DUMP_KEY) {1308		adapter->ahw->idc.collect_dump = 1;1309	}1310 1311	qlcnic_83xx_unlock_driver(adapter);1312	return;1313}1314 1315static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)1316{1317	u8 *p_cache;1318	u32 src, size;1319	u64 dest;1320	int ret = -EIO;1321 1322	src = QLC_83XX_BOOTLOADER_FLASH_ADDR;1323	dest = QLCRDX(adapter->ahw, QLCNIC_BOOTLOADER_ADDR);1324	size = QLCRDX(adapter->ahw, QLCNIC_BOOTLOADER_SIZE);1325 1326	/* alignment check */1327	if (size & 0xF)1328		size = (size + 16) & ~0xF;1329 1330	p_cache = vzalloc(size);1331	if (p_cache == NULL)1332		return -ENOMEM;1333 1334	ret = qlcnic_83xx_lockless_flash_read32(adapter, src, p_cache,1335						size / sizeof(u32));1336	if (ret) {1337		vfree(p_cache);1338		return ret;1339	}1340	/* 16 byte write to MS memory */1341	ret = qlcnic_ms_mem_write128(adapter, dest, (u32 *)p_cache,1342				     size / 16);1343	if (ret) {1344		vfree(p_cache);1345		return ret;1346	}1347	vfree(p_cache);1348 1349	return ret;1350}1351 1352static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)1353{1354	struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;1355	const struct firmware *fw = fw_info->fw;1356	u32 dest, *p_cache, *temp;1357	__le32 *temp_le;1358	u8 data[16];1359	size_t size;1360	int i, ret;1361	u64 addr;1362 1363	temp = vzalloc(fw->size);1364	if (!temp) {1365		release_firmware(fw);1366		fw_info->fw = NULL;1367		return -ENOMEM;1368	}1369 1370	temp_le = (__le32 *)fw->data;1371 1372	/* FW image in file is in little endian, swap the data to nullify1373	 * the effect of writel() operation on big endian platform.1374	 */1375	for (i = 0; i < fw->size / sizeof(u32); i++)1376		temp[i] = __le32_to_cpu(temp_le[i]);1377 1378	dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR);1379	size = (fw->size & ~0xF);1380	p_cache = temp;1381	addr = (u64)dest;1382 1383	ret = qlcnic_ms_mem_write128(adapter, addr,1384				     p_cache, size / 16);1385	if (ret) {1386		dev_err(&adapter->pdev->dev, "MS memory write failed\n");1387		goto exit;1388	}1389 1390	/* alignment check */1391	if (fw->size & 0xF) {1392		addr = dest + size;1393		for (i = 0; i < (fw->size & 0xF); i++)1394			data[i] = ((u8 *)temp)[size + i];1395		for (; i < 16; i++)1396			data[i] = 0;1397		ret = qlcnic_ms_mem_write128(adapter, addr,1398					     (u32 *)data, 1);1399		if (ret) {1400			dev_err(&adapter->pdev->dev,1401				"MS memory write failed\n");1402			goto exit;1403		}1404	}1405 1406exit:1407	release_firmware(fw);1408	fw_info->fw = NULL;1409	vfree(temp);1410 1411	return ret;1412}1413 1414static void qlcnic_83xx_dump_pause_control_regs(struct qlcnic_adapter *adapter)1415{1416	int i, j;1417	u32 val = 0, val1 = 0, reg = 0;1418	int err = 0;1419 1420	val = QLCRD32(adapter, QLC_83XX_SRE_SHIM_REG, &err);1421	if (err == -EIO)1422		return;1423	dev_info(&adapter->pdev->dev, "SRE-Shim Ctrl:0x%x\n", val);1424 1425	for (j = 0; j < 2; j++) {1426		if (j == 0) {1427			dev_info(&adapter->pdev->dev,1428				 "Port 0 RxB Pause Threshold Regs[TC7..TC0]:");1429			reg = QLC_83XX_PORT0_THRESHOLD;1430		} else if (j == 1) {1431			dev_info(&adapter->pdev->dev,1432				 "Port 1 RxB Pause Threshold Regs[TC7..TC0]:");1433			reg = QLC_83XX_PORT1_THRESHOLD;1434		}1435		for (i = 0; i < 8; i++) {1436			val = QLCRD32(adapter, reg + (i * 0x4), &err);1437			if (err == -EIO)1438				return;1439			dev_info(&adapter->pdev->dev, "0x%x  ", val);1440		}1441		dev_info(&adapter->pdev->dev, "\n");1442	}1443 1444	for (j = 0; j < 2; j++) {1445		if (j == 0) {1446			dev_info(&adapter->pdev->dev,1447				 "Port 0 RxB TC Max Cell Registers[4..1]:");1448			reg = QLC_83XX_PORT0_TC_MC_REG;1449		} else if (j == 1) {1450			dev_info(&adapter->pdev->dev,1451				 "Port 1 RxB TC Max Cell Registers[4..1]:");1452			reg = QLC_83XX_PORT1_TC_MC_REG;1453		}1454		for (i = 0; i < 4; i++) {1455			val = QLCRD32(adapter, reg + (i * 0x4), &err);1456			if (err == -EIO)1457				return;1458			dev_info(&adapter->pdev->dev, "0x%x  ", val);1459		}1460		dev_info(&adapter->pdev->dev, "\n");1461	}1462 1463	for (j = 0; j < 2; j++) {1464		if (j == 0) {1465			dev_info(&adapter->pdev->dev,1466				 "Port 0 RxB Rx TC Stats[TC7..TC0]:");1467			reg = QLC_83XX_PORT0_TC_STATS;1468		} else if (j == 1) {1469			dev_info(&adapter->pdev->dev,1470				 "Port 1 RxB Rx TC Stats[TC7..TC0]:");1471			reg = QLC_83XX_PORT1_TC_STATS;1472		}1473		for (i = 7; i >= 0; i--) {1474			val = QLCRD32(adapter, reg, &err);1475			if (err == -EIO)1476				return;1477			val &= ~(0x7 << 29);    /* Reset bits 29 to 31 */1478			QLCWR32(adapter, reg, (val | (i << 29)));1479			val = QLCRD32(adapter, reg, &err);1480			if (err == -EIO)1481				return;1482			dev_info(&adapter->pdev->dev, "0x%x  ", val);1483		}1484		dev_info(&adapter->pdev->dev, "\n");1485	}1486 1487	val = QLCRD32(adapter, QLC_83XX_PORT2_IFB_THRESHOLD, &err);1488	if (err == -EIO)1489		return;1490	val1 = QLCRD32(adapter, QLC_83XX_PORT3_IFB_THRESHOLD, &err);1491	if (err == -EIO)1492		return;1493	dev_info(&adapter->pdev->dev,1494		 "IFB-Pause Thresholds: Port 2:0x%x, Port 3:0x%x\n",1495		 val, val1);1496}1497 1498 1499static void qlcnic_83xx_disable_pause_frames(struct qlcnic_adapter *adapter)1500{1501	u32 reg = 0, i, j;1502 1503	if (qlcnic_83xx_lock_driver(adapter)) {1504		dev_err(&adapter->pdev->dev,1505			"%s:failed to acquire driver lock\n", __func__);1506		return;1507	}1508 1509	qlcnic_83xx_dump_pause_control_regs(adapter);1510	QLCWR32(adapter, QLC_83XX_SRE_SHIM_REG, 0x0);1511 1512	for (j = 0; j < 2; j++) {1513		if (j == 0)1514			reg = QLC_83XX_PORT0_THRESHOLD;1515		else if (j == 1)1516			reg = QLC_83XX_PORT1_THRESHOLD;1517 1518		for (i = 0; i < 8; i++)1519			QLCWR32(adapter, reg + (i * 0x4), 0x0);1520	}1521 1522	for (j = 0; j < 2; j++) {1523		if (j == 0)1524			reg = QLC_83XX_PORT0_TC_MC_REG;1525		else if (j == 1)1526			reg = QLC_83XX_PORT1_TC_MC_REG;1527 1528		for (i = 0; i < 4; i++)1529			QLCWR32(adapter, reg + (i * 0x4), 0x03FF03FF);1530	}1531 1532	QLCWR32(adapter, QLC_83XX_PORT2_IFB_THRESHOLD, 0);1533	QLCWR32(adapter, QLC_83XX_PORT3_IFB_THRESHOLD, 0);1534	dev_info(&adapter->pdev->dev,1535		 "Disabled pause frames successfully on all ports\n");1536	qlcnic_83xx_unlock_driver(adapter);1537}1538 1539static void qlcnic_83xx_take_eport_out_of_reset(struct qlcnic_adapter *adapter)1540{1541	QLCWR32(adapter, QLC_83XX_RESET_REG, 0);1542	QLCWR32(adapter, QLC_83XX_RESET_PORT0, 0);1543	QLCWR32(adapter, QLC_83XX_RESET_PORT1, 0);1544	QLCWR32(adapter, QLC_83XX_RESET_PORT2, 0);1545	QLCWR32(adapter, QLC_83XX_RESET_PORT3, 0);1546	QLCWR32(adapter, QLC_83XX_RESET_SRESHIM, 0);1547	QLCWR32(adapter, QLC_83XX_RESET_EPGSHIM, 0);1548	QLCWR32(adapter, QLC_83XX_RESET_ETHERPCS, 0);1549	QLCWR32(adapter, QLC_83XX_RESET_CONTROL, 1);1550}1551 1552static int qlcnic_83xx_check_heartbeat(struct qlcnic_adapter *p_dev)1553{1554	u32 heartbeat, peg_status;1555	int retries, ret = -EIO, err = 0;1556 1557	retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT;1558	p_dev->heartbeat = QLC_SHARED_REG_RD32(p_dev,1559					       QLCNIC_PEG_ALIVE_COUNTER);1560 1561	do {1562		msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);1563		heartbeat = QLC_SHARED_REG_RD32(p_dev,1564						QLCNIC_PEG_ALIVE_COUNTER);1565		if (heartbeat != p_dev->heartbeat) {1566			ret = QLCNIC_RCODE_SUCCESS;1567			break;1568		}1569	} while (--retries);1570 1571	if (ret) {1572		dev_err(&p_dev->pdev->dev, "firmware hang detected\n");1573		qlcnic_83xx_take_eport_out_of_reset(p_dev);1574		qlcnic_83xx_disable_pause_frames(p_dev);1575		peg_status = QLC_SHARED_REG_RD32(p_dev,1576						 QLCNIC_PEG_HALT_STATUS1);1577		dev_info(&p_dev->pdev->dev, "Dumping HW/FW registers\n"1578			 "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n"1579			 "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n"1580			 "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n"1581			 "PEG_NET_4_PC: 0x%x\n", peg_status,1582			 QLC_SHARED_REG_RD32(p_dev, QLCNIC_PEG_HALT_STATUS2),1583			 QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_0, &err),1584			 QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_1, &err),1585			 QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_2, &err),1586			 QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_3, &err),1587			 QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_4, &err));1588 1589		if (QLCNIC_FWERROR_CODE(peg_status) == 0x67)1590			dev_err(&p_dev->pdev->dev,1591				"Device is being reset err code 0x00006700.\n");1592	}1593 1594	return ret;1595}1596 1597static int qlcnic_83xx_check_cmd_peg_status(struct qlcnic_adapter *p_dev)1598{1599	int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT;1600	u32 val;1601 1602	do {1603		val = QLC_SHARED_REG_RD32(p_dev, QLCNIC_CMDPEG_STATE);1604		if (val == QLC_83XX_CMDPEG_COMPLETE)1605			return 0;1606		msleep(QLCNIC_CMDPEG_CHECK_DELAY);1607	} while (--retries);1608 1609	dev_err(&p_dev->pdev->dev, "%s: failed, state = 0x%x\n", __func__, val);1610	return -EIO;1611}1612 1613static int qlcnic_83xx_check_hw_status(struct qlcnic_adapter *p_dev)1614{1615	int err;1616 1617	err = qlcnic_83xx_check_cmd_peg_status(p_dev);1618	if (err)1619		return err;1620 1621	err = qlcnic_83xx_check_heartbeat(p_dev);1622	if (err)1623		return err;1624 1625	return err;1626}1627 1628static int qlcnic_83xx_poll_reg(struct qlcnic_adapter *p_dev, u32 addr,1629				int duration, u32 mask, u32 status)1630{1631	int timeout_error, err = 0;1632	u32 value;1633	u8 retries;1634 1635	value = QLCRD32(p_dev, addr, &err);1636	if (err == -EIO)1637		return err;1638	retries = duration / 10;1639 1640	do {1641		if ((value & mask) != status) {1642			timeout_error = 1;1643			msleep(duration / 10);1644			value = QLCRD32(p_dev, addr, &err);1645			if (err == -EIO)1646				return err;1647		} else {1648			timeout_error = 0;1649			break;1650		}1651	} while (retries--);1652 1653	if (timeout_error) {1654		p_dev->ahw->reset.seq_error++;1655		dev_err(&p_dev->pdev->dev,1656			"%s: Timeout Err, entry_num = %d\n",1657			__func__, p_dev->ahw->reset.seq_index);1658		dev_err(&p_dev->pdev->dev,1659			"0x%08x 0x%08x 0x%08x\n",1660			value, mask, status);1661	}1662 1663	return timeout_error;1664}1665 1666static int qlcnic_83xx_reset_template_checksum(struct qlcnic_adapter *p_dev)1667{1668	u32 sum = 0;1669	u16 *buff = (u16 *)p_dev->ahw->reset.buff;1670	int count = p_dev->ahw->reset.hdr->size / sizeof(u16);1671 1672	while (count-- > 0)1673		sum += *buff++;1674 1675	while (sum >> 16)1676		sum = (sum & 0xFFFF) + (sum >> 16);1677 1678	if (~sum) {1679		return 0;1680	} else {1681		dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);1682		return -1;1683	}1684}1685 1686static int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev)1687{1688	struct qlcnic_hardware_context *ahw = p_dev->ahw;1689	u32 addr, count, prev_ver, curr_ver;1690	u8 *p_buff;1691 1692	if (ahw->reset.buff != NULL) {1693		prev_ver = p_dev->fw_version;1694		curr_ver = qlcnic_83xx_get_fw_version(p_dev);1695		if (curr_ver > prev_ver)1696			kfree(ahw->reset.buff);1697		else1698			return 0;1699	}1700 1701	ahw->reset.seq_error = 0;1702	ahw->reset.buff = kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL);1703	if (ahw->reset.buff == NULL)1704		return -ENOMEM;1705 1706	p_buff = p_dev->ahw->reset.buff;1707	addr = QLC_83XX_RESET_TEMPLATE_ADDR;1708	count = sizeof(struct qlc_83xx_reset_hdr) / sizeof(u32);1709 1710	/* Copy template header from flash */1711	if (qlcnic_83xx_flash_read32(p_dev, addr, p_buff, count)) {1712		dev_err(&p_dev->pdev->dev, "%s: flash read failed\n", __func__);1713		return -EIO;1714	}1715	ahw->reset.hdr = (struct qlc_83xx_reset_hdr *)ahw->reset.buff;1716	addr = QLC_83XX_RESET_TEMPLATE_ADDR + ahw->reset.hdr->hdr_size;1717	p_buff = ahw->reset.buff + ahw->reset.hdr->hdr_size;1718	count = (ahw->reset.hdr->size - ahw->reset.hdr->hdr_size) / sizeof(u32);1719 1720	/* Copy rest of the template */1721	if (qlcnic_83xx_flash_read32(p_dev, addr, p_buff, count)) {1722		dev_err(&p_dev->pdev->dev, "%s: flash read failed\n", __func__);1723		return -EIO;1724	}1725 1726	if (qlcnic_83xx_reset_template_checksum(p_dev))1727		return -EIO;1728	/* Get Stop, Start and Init command offsets */1729	ahw->reset.init_offset = ahw->reset.buff + ahw->reset.hdr->init_offset;1730	ahw->reset.start_offset = ahw->reset.buff +1731				  ahw->reset.hdr->start_offset;1732	ahw->reset.stop_offset = ahw->reset.buff + ahw->reset.hdr->hdr_size;1733	return 0;1734}1735 1736/* Read Write HW register command */1737static void qlcnic_83xx_read_write_crb_reg(struct qlcnic_adapter *p_dev,1738					   u32 raddr, u32 waddr)1739{1740	int err = 0;1741	u32 value;1742 1743	value = QLCRD32(p_dev, raddr, &err);1744	if (err == -EIO)1745		return;1746	qlcnic_83xx_wrt_reg_indirect(p_dev, waddr, value);1747}1748 1749/* Read Modify Write HW register command */1750static void qlcnic_83xx_rmw_crb_reg(struct qlcnic_adapter *p_dev,1751				    u32 raddr, u32 waddr,1752				    struct qlc_83xx_rmw *p_rmw_hdr)1753{1754	int err = 0;1755	u32 value;1756 1757	if (p_rmw_hdr->index_a) {1758		value = p_dev->ahw->reset.array[p_rmw_hdr->index_a];1759	} else {1760		value = QLCRD32(p_dev, raddr, &err);1761		if (err == -EIO)1762			return;1763	}1764 1765	value &= p_rmw_hdr->mask;1766	value <<= p_rmw_hdr->shl;1767	value >>= p_rmw_hdr->shr;1768	value |= p_rmw_hdr->or_value;1769	value ^= p_rmw_hdr->xor_value;1770	qlcnic_83xx_wrt_reg_indirect(p_dev, waddr, value);1771}1772 1773/* Write HW register command */1774static void qlcnic_83xx_write_list(struct qlcnic_adapter *p_dev,1775				   struct qlc_83xx_entry_hdr *p_hdr)1776{1777	int i;1778	struct qlc_83xx_entry *entry;1779 1780	entry = (struct qlc_83xx_entry *)((char *)p_hdr +1781					  sizeof(struct qlc_83xx_entry_hdr));1782 1783	for (i = 0; i < p_hdr->count; i++, entry++) {1784		qlcnic_83xx_wrt_reg_indirect(p_dev, entry->arg1,1785					     entry->arg2);1786		if (p_hdr->delay)1787			udelay((u32)(p_hdr->delay));1788	}1789}1790 1791/* Read and Write instruction */1792static void qlcnic_83xx_read_write_list(struct qlcnic_adapter *p_dev,1793					struct qlc_83xx_entry_hdr *p_hdr)1794{1795	int i;1796	struct qlc_83xx_entry *entry;1797 1798	entry = (struct qlc_83xx_entry *)((char *)p_hdr +1799					  sizeof(struct qlc_83xx_entry_hdr));1800 1801	for (i = 0; i < p_hdr->count; i++, entry++) {1802		qlcnic_83xx_read_write_crb_reg(p_dev, entry->arg1,1803					       entry->arg2);1804		if (p_hdr->delay)1805			udelay((u32)(p_hdr->delay));1806	}1807}1808 1809/* Poll HW register command */1810static void qlcnic_83xx_poll_list(struct qlcnic_adapter *p_dev,1811				  struct qlc_83xx_entry_hdr *p_hdr)1812{1813	long delay;1814	struct qlc_83xx_entry *entry;1815	struct qlc_83xx_poll *poll;1816	int i, err = 0;1817	unsigned long arg1, arg2;1818 1819	poll = (struct qlc_83xx_poll *)((char *)p_hdr +1820					sizeof(struct qlc_83xx_entry_hdr));1821 1822	entry = (struct qlc_83xx_entry *)((char *)poll +1823					  sizeof(struct qlc_83xx_poll));1824	delay = (long)p_hdr->delay;1825 1826	if (!delay) {1827		for (i = 0; i < p_hdr->count; i++, entry++)1828			qlcnic_83xx_poll_reg(p_dev, entry->arg1,1829					     delay, poll->mask,1830					     poll->status);1831	} else {1832		for (i = 0; i < p_hdr->count; i++, entry++) {1833			arg1 = entry->arg1;1834			arg2 = entry->arg2;1835			if (delay) {1836				if (qlcnic_83xx_poll_reg(p_dev,1837							 arg1, delay,1838							 poll->mask,1839							 poll->status)){1840					QLCRD32(p_dev, arg1, &err);1841					if (err == -EIO)1842						return;1843					QLCRD32(p_dev, arg2, &err);1844					if (err == -EIO)1845						return;1846				}1847			}1848		}1849	}1850}1851 1852/* Poll and write HW register command */1853static void qlcnic_83xx_poll_write_list(struct qlcnic_adapter *p_dev,1854					struct qlc_83xx_entry_hdr *p_hdr)1855{1856	int i;1857	long delay;1858	struct qlc_83xx_quad_entry *entry;1859	struct qlc_83xx_poll *poll;1860 1861	poll = (struct qlc_83xx_poll *)((char *)p_hdr +1862					sizeof(struct qlc_83xx_entry_hdr));1863	entry = (struct qlc_83xx_quad_entry *)((char *)poll +1864					       sizeof(struct qlc_83xx_poll));1865	delay = (long)p_hdr->delay;1866 1867	for (i = 0; i < p_hdr->count; i++, entry++) {1868		qlcnic_83xx_wrt_reg_indirect(p_dev, entry->dr_addr,1869					     entry->dr_value);1870		qlcnic_83xx_wrt_reg_indirect(p_dev, entry->ar_addr,1871					     entry->ar_value);1872		if (delay)1873			qlcnic_83xx_poll_reg(p_dev, entry->ar_addr, delay,1874					     poll->mask, poll->status);1875	}1876}1877 1878/* Read Modify Write register command */1879static void qlcnic_83xx_read_modify_write(struct qlcnic_adapter *p_dev,1880					  struct qlc_83xx_entry_hdr *p_hdr)1881{1882	int i;1883	struct qlc_83xx_entry *entry;1884	struct qlc_83xx_rmw *rmw_hdr;1885 1886	rmw_hdr = (struct qlc_83xx_rmw *)((char *)p_hdr +1887					  sizeof(struct qlc_83xx_entry_hdr));1888 1889	entry = (struct qlc_83xx_entry *)((char *)rmw_hdr +1890					  sizeof(struct qlc_83xx_rmw));1891 1892	for (i = 0; i < p_hdr->count; i++, entry++) {1893		qlcnic_83xx_rmw_crb_reg(p_dev, entry->arg1,1894					entry->arg2, rmw_hdr);1895		if (p_hdr->delay)1896			udelay((u32)(p_hdr->delay));1897	}1898}1899 1900static void qlcnic_83xx_pause(struct qlc_83xx_entry_hdr *p_hdr)1901{1902	if (p_hdr->delay)1903		mdelay((u32)((long)p_hdr->delay));1904}1905 1906/* Read and poll register command */1907static void qlcnic_83xx_poll_read_list(struct qlcnic_adapter *p_dev,1908				       struct qlc_83xx_entry_hdr *p_hdr)1909{1910	long delay;1911	int index, i, j, err;1912	struct qlc_83xx_quad_entry *entry;1913	struct qlc_83xx_poll *poll;1914	unsigned long addr;1915 1916	poll = (struct qlc_83xx_poll *)((char *)p_hdr +1917					sizeof(struct qlc_83xx_entry_hdr));1918 1919	entry = (struct qlc_83xx_quad_entry *)((char *)poll +1920					       sizeof(struct qlc_83xx_poll));1921	delay = (long)p_hdr->delay;1922 1923	for (i = 0; i < p_hdr->count; i++, entry++) {1924		qlcnic_83xx_wrt_reg_indirect(p_dev, entry->ar_addr,1925					     entry->ar_value);1926		if (delay) {1927			if (!qlcnic_83xx_poll_reg(p_dev, entry->ar_addr, delay,1928						  poll->mask, poll->status)){1929				index = p_dev->ahw->reset.array_index;1930				addr = entry->dr_addr;1931				j = QLCRD32(p_dev, addr, &err);1932				if (err == -EIO)1933					return;1934 1935				p_dev->ahw->reset.array[index++] = j;1936 1937				if (index == QLC_83XX_MAX_RESET_SEQ_ENTRIES)1938					p_dev->ahw->reset.array_index = 1;1939			}1940		}1941	}1942}1943 1944static inline void qlcnic_83xx_seq_end(struct qlcnic_adapter *p_dev)1945{1946	p_dev->ahw->reset.seq_end = 1;1947}1948 1949static void qlcnic_83xx_template_end(struct qlcnic_adapter *p_dev)1950{1951	p_dev->ahw->reset.template_end = 1;1952	if (p_dev->ahw->reset.seq_error == 0)1953		dev_err(&p_dev->pdev->dev,1954			"HW restart process completed successfully.\n");1955	else1956		dev_err(&p_dev->pdev->dev,1957			"HW restart completed with timeout errors.\n");1958}1959 1960/**1961* qlcnic_83xx_exec_template_cmd1962*1963* @p_dev: adapter structure1964* @p_buff: Poiter to instruction template1965*1966* Template provides instructions to stop, restart and initalize firmware.1967* These instructions are abstracted as a series of read, write and1968* poll operations on hardware registers. Register information and operation1969* specifics are not exposed to the driver. Driver reads the template from1970* flash and executes the instructions located at pre-defined offsets.1971*1972* Returns: None1973* */1974static void qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter *p_dev,1975					  char *p_buff)1976{1977	int index, entries;1978	struct qlc_83xx_entry_hdr *p_hdr;1979	char *entry = p_buff;1980 1981	p_dev->ahw->reset.seq_end = 0;1982	p_dev->ahw->reset.template_end = 0;1983	entries = p_dev->ahw->reset.hdr->entries;1984	index = p_dev->ahw->reset.seq_index;1985 1986	for (; (!p_dev->ahw->reset.seq_end) && (index < entries); index++) {1987		p_hdr = (struct qlc_83xx_entry_hdr *)entry;1988 1989		switch (p_hdr->cmd) {1990		case QLC_83XX_OPCODE_NOP:1991			break;1992		case QLC_83XX_OPCODE_WRITE_LIST:1993			qlcnic_83xx_write_list(p_dev, p_hdr);1994			break;1995		case QLC_83XX_OPCODE_READ_WRITE_LIST:1996			qlcnic_83xx_read_write_list(p_dev, p_hdr);1997			break;1998		case QLC_83XX_OPCODE_POLL_LIST:1999			qlcnic_83xx_poll_list(p_dev, p_hdr);2000			break;2001		case QLC_83XX_OPCODE_POLL_WRITE_LIST:2002			qlcnic_83xx_poll_write_list(p_dev, p_hdr);2003			break;2004		case QLC_83XX_OPCODE_READ_MODIFY_WRITE:2005			qlcnic_83xx_read_modify_write(p_dev, p_hdr);2006			break;2007		case QLC_83XX_OPCODE_SEQ_PAUSE:2008			qlcnic_83xx_pause(p_hdr);2009			break;2010		case QLC_83XX_OPCODE_SEQ_END:2011			qlcnic_83xx_seq_end(p_dev);2012			break;2013		case QLC_83XX_OPCODE_TMPL_END:2014			qlcnic_83xx_template_end(p_dev);2015			break;2016		case QLC_83XX_OPCODE_POLL_READ_LIST:2017			qlcnic_83xx_poll_read_list(p_dev, p_hdr);2018			break;2019		default:2020			dev_err(&p_dev->pdev->dev,2021				"%s: Unknown opcode 0x%04x in template %d\n",2022				__func__, p_hdr->cmd, index);2023			break;2024		}2025		entry += p_hdr->size;2026		cond_resched();2027	}2028	p_dev->ahw->reset.seq_index = index;2029}2030 2031static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)2032{2033	p_dev->ahw->reset.seq_index = 0;2034 2035	qlcnic_83xx_exec_template_cmd(p_dev, p_dev->ahw->reset.stop_offset);2036	if (p_dev->ahw->reset.seq_end != 1)2037		dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);2038}2039 2040static void qlcnic_83xx_start_hw(struct qlcnic_adapter *p_dev)2041{2042	qlcnic_83xx_exec_template_cmd(p_dev, p_dev->ahw->reset.start_offset);2043	if (p_dev->ahw->reset.template_end != 1)2044		dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);2045}2046 2047static void qlcnic_83xx_init_hw(struct qlcnic_adapter *p_dev)2048{2049	qlcnic_83xx_exec_template_cmd(p_dev, p_dev->ahw->reset.init_offset);2050	if (p_dev->ahw->reset.seq_end != 1)2051		dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);2052}2053 2054/* POST FW related definations*/2055#define QLC_83XX_POST_SIGNATURE_REG	0x416020142056#define QLC_83XX_POST_MODE_REG		0x416020182057#define QLC_83XX_POST_FAST_MODE		02058#define QLC_83XX_POST_MEDIUM_MODE	12059#define QLC_83XX_POST_SLOW_MODE		22060 2061/* POST Timeout values in milliseconds */2062#define QLC_83XX_POST_FAST_MODE_TIMEOUT	6902063#define QLC_83XX_POST_MED_MODE_TIMEOUT	29302064#define QLC_83XX_POST_SLOW_MODE_TIMEOUT	75002065 2066/* POST result values */2067#define QLC_83XX_POST_PASS			0xfffffff02068#define QLC_83XX_POST_ASIC_STRESS_TEST_FAIL	0xffffffff2069#define QLC_83XX_POST_DDR_TEST_FAIL		0xfffffffe2070#define QLC_83XX_POST_ASIC_MEMORY_TEST_FAIL	0xfffffffc2071#define QLC_83XX_POST_FLASH_TEST_FAIL		0xfffffff82072 2073static int qlcnic_83xx_run_post(struct qlcnic_adapter *adapter)2074{2075	struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;2076	struct device *dev = &adapter->pdev->dev;2077	int timeout, count, ret = 0;2078	u32 signature;2079 2080	/* Set timeout values with extra 2 seconds of buffer */2081	switch (adapter->ahw->post_mode) {2082	case QLC_83XX_POST_FAST_MODE:2083		timeout = QLC_83XX_POST_FAST_MODE_TIMEOUT + 2000;2084		break;2085	case QLC_83XX_POST_MEDIUM_MODE:2086		timeout = QLC_83XX_POST_MED_MODE_TIMEOUT + 2000;2087		break;2088	case QLC_83XX_POST_SLOW_MODE:2089		timeout = QLC_83XX_POST_SLOW_MODE_TIMEOUT + 2000;2090		break;2091	default:2092		return -EINVAL;2093	}2094 2095	strscpy(fw_info->fw_file_name, QLC_83XX_POST_FW_FILE_NAME,2096		sizeof(fw_info->fw_file_name));2097 2098	ret = request_firmware(&fw_info->fw, fw_info->fw_file_name, dev);2099	if (ret) {2100		dev_err(dev, "POST firmware can not be loaded, skipping POST\n");2101		return 0;2102	}2103 2104	ret = qlcnic_83xx_copy_fw_file(adapter);2105	if (ret)2106		return ret;2107 2108	/* clear QLC_83XX_POST_SIGNATURE_REG register */2109	qlcnic_ind_wr(adapter, QLC_83XX_POST_SIGNATURE_REG, 0);2110 2111	/* Set POST mode */2112	qlcnic_ind_wr(adapter, QLC_83XX_POST_MODE_REG,2113		      adapter->ahw->post_mode);2114 2115	QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,2116			    QLC_83XX_BOOT_FROM_FILE);2117 2118	qlcnic_83xx_start_hw(adapter);2119 2120	count = 0;2121	do {2122		msleep(100);2123		count += 100;2124 2125		signature = qlcnic_ind_rd(adapter, QLC_83XX_POST_SIGNATURE_REG);2126		if (signature == QLC_83XX_POST_PASS)2127			break;2128	} while (timeout > count);2129 2130	if (timeout <= count) {2131		dev_err(dev, "POST timed out, signature = 0x%08x\n", signature);2132		return -EIO;2133	}2134 2135	switch (signature) {2136	case QLC_83XX_POST_PASS:2137		dev_info(dev, "POST passed, Signature = 0x%08x\n", signature);2138		break;2139	case QLC_83XX_POST_ASIC_STRESS_TEST_FAIL:2140		dev_err(dev, "POST failed, Test case : ASIC STRESS TEST, Signature = 0x%08x\n",2141			signature);2142		ret = -EIO;2143		break;2144	case QLC_83XX_POST_DDR_TEST_FAIL:2145		dev_err(dev, "POST failed, Test case : DDT TEST, Signature = 0x%08x\n",2146			signature);2147		ret = -EIO;2148		break;2149	case QLC_83XX_POST_ASIC_MEMORY_TEST_FAIL:2150		dev_err(dev, "POST failed, Test case : ASIC MEMORY TEST, Signature = 0x%08x\n",2151			signature);2152		ret = -EIO;2153		break;2154	case QLC_83XX_POST_FLASH_TEST_FAIL:2155		dev_err(dev, "POST failed, Test case : FLASH TEST, Signature = 0x%08x\n",2156			signature);2157		ret = -EIO;2158		break;2159	default:2160		dev_err(dev, "POST failed, Test case : INVALID, Signature = 0x%08x\n",2161			signature);2162		ret = -EIO;2163		break;2164	}2165 2166	return ret;2167}2168 2169static int qlcnic_83xx_load_fw_image_from_host(struct qlcnic_adapter *adapter)2170{2171	struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;2172	int err = -EIO;2173 2174	if (request_firmware(&fw_info->fw, fw_info->fw_file_name,2175			     &(adapter->pdev->dev))) {2176		dev_err(&adapter->pdev->dev,2177			"No file FW image, loading flash FW image.\n");2178		QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,2179				    QLC_83XX_BOOT_FROM_FLASH);2180	} else {2181		if (qlcnic_83xx_copy_fw_file(adapter))2182			return err;2183		QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,2184				    QLC_83XX_BOOT_FROM_FILE);2185	}2186 2187	return 0;2188}2189 2190static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)2191{2192	u32 val;2193	int err = -EIO;2194 2195	qlcnic_83xx_stop_hw(adapter);2196 2197	/* Collect FW register dump if required */2198	val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);2199	if (!(val & QLC_83XX_IDC_GRACEFULL_RESET))2200		qlcnic_dump_fw(adapter);2201 2202	if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {2203		netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",2204			    __func__);2205		qlcnic_83xx_idc_enter_failed_state(adapter, 1);2206		return err;2207	}2208 2209	qlcnic_83xx_init_hw(adapter);2210 2211	if (qlcnic_83xx_copy_bootloader(adapter))2212		return err;2213 2214	/* Check if POST needs to be run */2215	if (adapter->ahw->run_post) {2216		err = qlcnic_83xx_run_post(adapter);2217		if (err)2218			return err;2219 2220		/* No need to run POST in next reset sequence */2221		adapter->ahw->run_post = false;2222 2223		/* Again reset the adapter to load regular firmware  */2224		qlcnic_83xx_stop_hw(adapter);2225		qlcnic_83xx_init_hw(adapter);2226 2227		err = qlcnic_83xx_copy_bootloader(adapter);2228		if (err)2229			return err;2230	}2231 2232	/* Boot either flash image or firmware image from host file system */2233	if (qlcnic_load_fw_file == 1) {2234		err = qlcnic_83xx_load_fw_image_from_host(adapter);2235		if (err)2236			return err;2237	} else {2238		QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,2239				    QLC_83XX_BOOT_FROM_FLASH);2240	}2241 2242	qlcnic_83xx_start_hw(adapter);2243	if (qlcnic_83xx_check_hw_status(adapter))2244		return -EIO;2245 2246	return 0;2247}2248 2249static int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)2250{2251	int err;2252	struct qlcnic_info nic_info;2253	struct qlcnic_hardware_context *ahw = adapter->ahw;2254 2255	memset(&nic_info, 0, sizeof(struct qlcnic_info));2256	err = qlcnic_get_nic_info(adapter, &nic_info, ahw->pci_func);2257	if (err)2258		return -EIO;2259 2260	ahw->physical_port = (u8) nic_info.phys_port;2261	ahw->switch_mode = nic_info.switch_mode;2262	ahw->max_tx_ques = nic_info.max_tx_ques;2263	ahw->max_rx_ques = nic_info.max_rx_ques;2264	ahw->capabilities = nic_info.capabilities;2265	ahw->max_mac_filters = nic_info.max_mac_filters;2266	ahw->max_mtu = nic_info.max_mtu;2267 2268	/* eSwitch capability indicates vNIC mode.2269	 * vNIC and SRIOV are mutually exclusive operational modes.2270	 * If SR-IOV capability is detected, SR-IOV physical function2271	 * will get initialized in default mode.2272	 * SR-IOV virtual function initialization follows a2273	 * different code path and opmode.2274	 * SRIOV mode has precedence over vNIC mode.2275	 */2276	if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state))2277		return QLC_83XX_DEFAULT_OPMODE;2278 2279	if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)2280		return QLCNIC_VNIC_MODE;2281 2282	return QLC_83XX_DEFAULT_OPMODE;2283}2284 2285int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)2286{2287	struct qlcnic_hardware_context *ahw = adapter->ahw;2288	u16 max_sds_rings, max_tx_rings;2289	int ret;2290 2291	ret = qlcnic_83xx_get_nic_configuration(adapter);2292	if (ret == -EIO)2293		return -EIO;2294 2295	if (ret == QLCNIC_VNIC_MODE) {2296		ahw->nic_mode = QLCNIC_VNIC_MODE;2297 2298		if (qlcnic_83xx_config_vnic_opmode(adapter))2299			return -EIO;2300 2301		max_sds_rings = QLCNIC_MAX_VNIC_SDS_RINGS;2302		max_tx_rings = QLCNIC_MAX_VNIC_TX_RINGS;2303	} else if (ret == QLC_83XX_DEFAULT_OPMODE) {2304		ahw->nic_mode = QLCNIC_DEFAULT_MODE;2305		adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;2306		ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;2307		max_sds_rings = QLCNIC_MAX_SDS_RINGS;2308		max_tx_rings = QLCNIC_MAX_TX_RINGS;2309	} else {2310		dev_err(&adapter->pdev->dev, "%s: Invalid opmode %d\n",2311			__func__, ret);2312		return -EIO;2313	}2314 2315	adapter->max_sds_rings = min(ahw->max_rx_ques, max_sds_rings);2316	adapter->max_tx_rings = min(ahw->max_tx_ques, max_tx_rings);2317 2318	return 0;2319}2320 2321static void qlcnic_83xx_config_buff_descriptors(struct qlcnic_adapter *adapter)2322{2323	struct qlcnic_hardware_context *ahw = adapter->ahw;2324 2325	if (ahw->port_type == QLCNIC_XGBE) {2326		adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;2327		adapter->max_rxd = MAX_RCV_DESCRIPTORS_10G;2328		adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;2329		adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;2330 2331	} else if (ahw->port_type == QLCNIC_GBE) {2332		adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;2333		adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;2334		adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;2335		adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;2336	}2337	adapter->num_txd = MAX_CMD_DESCRIPTORS;2338	adapter->max_rds_rings = MAX_RDS_RINGS;2339}2340 2341static int qlcnic_83xx_init_default_driver(struct qlcnic_adapter *adapter)2342{2343	int err = -EIO;2344 2345	qlcnic_83xx_get_minidump_template(adapter);2346	if (qlcnic_83xx_get_port_info(adapter))2347		return err;2348 2349	qlcnic_83xx_config_buff_descriptors(adapter);2350	adapter->ahw->msix_supported = !!qlcnic_use_msi_x;2351	adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;2352 2353	dev_info(&adapter->pdev->dev, "HAL Version: %d\n",2354		 adapter->ahw->fw_hal_version);2355 2356	return 0;2357}2358 2359#define IS_QLC_83XX_USED(a, b, c) (((1 << a->portnum) & b) || ((c >> 6) & 0x1))2360static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter)2361{2362	struct qlcnic_cmd_args cmd;2363	u32 presence_mask, audit_mask;2364	int status;2365 2366	presence_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);2367	audit_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT);2368 2369	if (IS_QLC_83XX_USED(adapter, presence_mask, audit_mask)) {2370		status = qlcnic_alloc_mbx_args(&cmd, adapter,2371					       QLCNIC_CMD_STOP_NIC_FUNC);2372		if (status)2373			return;2374 2375		cmd.req.arg[1] = BIT_31;2376		status = qlcnic_issue_cmd(adapter, &cmd);2377		if (status)2378			dev_err(&adapter->pdev->dev,2379				"Failed to clean up the function resources\n");2380		qlcnic_free_mbx_args(&cmd);2381	}2382}2383 2384static int qlcnic_83xx_get_fw_info(struct qlcnic_adapter *adapter)2385{2386	struct qlcnic_hardware_context *ahw = adapter->ahw;2387	struct pci_dev *pdev = adapter->pdev;2388	struct qlc_83xx_fw_info *fw_info;2389	int err = 0;2390 2391	ahw->fw_info = kzalloc(sizeof(*fw_info), GFP_KERNEL);2392	if (!ahw->fw_info) {2393		err = -ENOMEM;2394	} else {2395		fw_info = ahw->fw_info;2396		switch (pdev->device) {2397		case PCI_DEVICE_ID_QLOGIC_QLE834X:2398		case PCI_DEVICE_ID_QLOGIC_QLE8830:2399			strscpy(fw_info->fw_file_name, QLC_83XX_FW_FILE_NAME,2400				sizeof(fw_info->fw_file_name));2401			break;2402		case PCI_DEVICE_ID_QLOGIC_QLE844X:2403			strscpy(fw_info->fw_file_name, QLC_84XX_FW_FILE_NAME,2404				sizeof(fw_info->fw_file_name));2405			break;2406		default:2407			dev_err(&pdev->dev, "%s: Invalid device id\n",2408				__func__);2409			err = -EINVAL;2410			break;2411		}2412	}2413 2414	return err;2415}2416 2417static void qlcnic_83xx_init_rings(struct qlcnic_adapter *adapter)2418{2419	u8 rx_cnt = QLCNIC_DEF_SDS_RINGS;2420	u8 tx_cnt = QLCNIC_DEF_TX_RINGS;2421 2422	adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS;2423	adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;2424 2425	if (!adapter->ahw->msix_supported) {2426		rx_cnt = QLCNIC_SINGLE_RING;2427		tx_cnt = QLCNIC_SINGLE_RING;2428	}2429 2430	/* compute and set drv sds rings */2431	qlcnic_set_tx_ring_count(adapter, tx_cnt);2432	qlcnic_set_sds_ring_count(adapter, rx_cnt);2433}2434 2435int qlcnic_83xx_init(struct qlcnic_adapter *adapter)2436{2437	struct qlcnic_hardware_context *ahw = adapter->ahw;2438	int err = 0;2439 2440	adapter->rx_mac_learn = false;2441	ahw->msix_supported = !!qlcnic_use_msi_x;2442 2443	/* Check if POST needs to be run */2444	switch (qlcnic_load_fw_file) {2445	case 2:2446		ahw->post_mode = QLC_83XX_POST_FAST_MODE;2447		ahw->run_post = true;2448		break;2449	case 3:2450		ahw->post_mode = QLC_83XX_POST_MEDIUM_MODE;2451		ahw->run_post = true;2452		break;2453	case 4:2454		ahw->post_mode = QLC_83XX_POST_SLOW_MODE;2455		ahw->run_post = true;2456		break;2457	default:2458		ahw->run_post = false;2459		break;2460	}2461 2462	qlcnic_83xx_init_rings(adapter);2463 2464	err = qlcnic_83xx_init_mailbox_work(adapter);2465	if (err)2466		goto exit;2467 2468	if (qlcnic_sriov_vf_check(adapter)) {2469		err = qlcnic_sriov_vf_init(adapter);2470		if (err)2471			goto detach_mbx;2472		else2473			return err;2474	}2475 2476	if (qlcnic_83xx_read_flash_descriptor_table(adapter) ||2477	    qlcnic_83xx_read_flash_mfg_id(adapter)) {2478		dev_err(&adapter->pdev->dev, "Failed reading flash mfg id\n");2479		err = -ENOTRECOVERABLE;2480		goto detach_mbx;2481	}2482 2483	err = qlcnic_83xx_check_hw_status(adapter);2484	if (err)2485		goto detach_mbx;2486 2487	err = qlcnic_83xx_get_fw_info(adapter);2488	if (err)2489		goto detach_mbx;2490 2491	err = qlcnic_83xx_idc_init(adapter);2492	if (err)2493		goto detach_mbx;2494 2495	err = qlcnic_setup_intr(adapter);2496	if (err) {2497		dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");2498		goto disable_intr;2499	}2500 2501	INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);2502 2503	err = qlcnic_83xx_setup_mbx_intr(adapter);2504	if (err)2505		goto disable_mbx_intr;2506 2507	qlcnic_83xx_clear_function_resources(adapter);2508 2509	err = qlcnic_dcb_enable(adapter->dcb);2510	if (err) {2511		qlcnic_dcb_free(adapter->dcb);2512		goto disable_mbx_intr;2513	}2514 2515	qlcnic_83xx_initialize_nic(adapter, 1);2516	qlcnic_dcb_get_info(adapter->dcb);2517 2518	/* Configure default, SR-IOV or Virtual NIC mode of operation */2519	err = qlcnic_83xx_configure_opmode(adapter);2520	if (err)2521		goto disable_mbx_intr;2522 2523 2524	/* Perform operating mode specific initialization */2525	err = adapter->nic_ops->init_driver(adapter);2526	if (err)2527		goto disable_mbx_intr;2528 2529	/* Periodically monitor device status */2530	qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work);2531	return 0;2532 2533disable_mbx_intr:2534	qlcnic_83xx_free_mbx_intr(adapter);2535 2536disable_intr:2537	qlcnic_teardown_intr(adapter);2538 2539detach_mbx:2540	qlcnic_83xx_detach_mailbox_work(adapter);2541	qlcnic_83xx_free_mailbox(ahw->mailbox);2542	ahw->mailbox = NULL;2543exit:2544	return err;2545}2546 2547void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *adapter)2548{2549	struct qlcnic_hardware_context *ahw = adapter->ahw;2550	struct qlc_83xx_idc *idc = &ahw->idc;2551 2552	clear_bit(QLC_83XX_MBX_READY, &idc->status);2553	cancel_delayed_work_sync(&adapter->fw_work);2554 2555	if (ahw->nic_mode == QLCNIC_VNIC_MODE)2556		qlcnic_83xx_disable_vnic_mode(adapter, 1);2557 2558	qlcnic_83xx_idc_detach_driver(adapter);2559	qlcnic_83xx_initialize_nic(adapter, 0);2560 2561	cancel_delayed_work_sync(&adapter->idc_aen_work);2562}2563 2564int qlcnic_83xx_aer_reset(struct qlcnic_adapter *adapter)2565{2566	struct qlcnic_hardware_context *ahw = adapter->ahw;2567	struct qlc_83xx_idc *idc = &ahw->idc;2568	int ret = 0;2569	u32 owner;2570 2571	/* Mark the previous IDC state as NEED_RESET so2572	 * that state_entry() will perform the reattachment2573	 * and bringup the device2574	 */2575	idc->prev_state = QLC_83XX_IDC_DEV_NEED_RESET;2576	owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);2577	if (ahw->pci_func == owner) {2578		ret = qlcnic_83xx_restart_hw(adapter);2579		if (ret < 0)2580			return ret;2581		qlcnic_83xx_idc_clear_registers(adapter, 0);2582	}2583 2584	ret = idc->state_entry(adapter);2585	return ret;2586}2587 2588void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *adapter)2589{2590	struct qlcnic_hardware_context *ahw = adapter->ahw;2591	struct qlc_83xx_idc *idc = &ahw->idc;2592	u32 owner;2593 2594	idc->prev_state = QLC_83XX_IDC_DEV_READY;2595	owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);2596	if (ahw->pci_func == owner)2597		qlcnic_83xx_idc_enter_ready_state(adapter, 0);2598 2599	qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state, 0);2600}2601