brintos

brintos / linux-shallow public Read only

0
0
Text · 34.5 KiB · 7ecb3df Raw
1456 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * QLogic qlcnic NIC Driver4 * Copyright (c) 2009-2013 QLogic Corporation5 */6 7#include <net/ip.h>8 9#include "qlcnic.h"10#include "qlcnic_hdr.h"11#include "qlcnic_83xx_hw.h"12#include "qlcnic_hw.h"13 14#define QLC_83XX_MINIDUMP_FLASH		0x52000015#define QLC_83XX_OCM_INDEX			316#define QLC_83XX_PCI_INDEX			017#define QLC_83XX_DMA_ENGINE_INDEX		818 19static const u32 qlcnic_ms_read_data[] = {20	0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC21};22 23#define QLCNIC_DUMP_WCRB	BIT_024#define QLCNIC_DUMP_RWCRB	BIT_125#define QLCNIC_DUMP_ANDCRB	BIT_226#define QLCNIC_DUMP_ORCRB	BIT_327#define QLCNIC_DUMP_POLLCRB	BIT_428#define QLCNIC_DUMP_RD_SAVE	BIT_529#define QLCNIC_DUMP_WRT_SAVED	BIT_630#define QLCNIC_DUMP_MOD_SAVE_ST	BIT_731#define QLCNIC_DUMP_SKIP	BIT_732 33#define QLCNIC_DUMP_MASK_MAX	0xff34 35struct qlcnic_pex_dma_descriptor {36	u32	read_data_size;37	u32	dma_desc_cmd;38	u32	src_addr_low;39	u32	src_addr_high;40	u32	dma_bus_addr_low;41	u32	dma_bus_addr_high;42	u32	rsvd[6];43} __packed;44 45struct qlcnic_common_entry_hdr {46	u32     type;47	u32     offset;48	u32     cap_size;49#if defined(__LITTLE_ENDIAN)50	u8      mask;51	u8      rsvd[2];52	u8      flags;53#else54	u8      flags;55	u8      rsvd[2];56	u8      mask;57#endif58} __packed;59 60struct __crb {61	u32	addr;62#if defined(__LITTLE_ENDIAN)63	u8	stride;64	u8	rsvd1[3];65#else66	u8	rsvd1[3];67	u8	stride;68#endif69	u32	data_size;70	u32	no_ops;71	u32	rsvd2[4];72} __packed;73 74struct __ctrl {75	u32	addr;76#if defined(__LITTLE_ENDIAN)77	u8	stride;78	u8	index_a;79	u16	timeout;80#else81	u16	timeout;82	u8	index_a;83	u8	stride;84#endif85	u32	data_size;86	u32	no_ops;87#if defined(__LITTLE_ENDIAN)88	u8	opcode;89	u8	index_v;90	u8	shl_val;91	u8	shr_val;92#else93	u8	shr_val;94	u8	shl_val;95	u8	index_v;96	u8	opcode;97#endif98	u32	val1;99	u32	val2;100	u32	val3;101} __packed;102 103struct __cache {104	u32	addr;105#if defined(__LITTLE_ENDIAN)106	u16	stride;107	u16	init_tag_val;108#else109	u16	init_tag_val;110	u16	stride;111#endif112	u32	size;113	u32	no_ops;114	u32	ctrl_addr;115	u32	ctrl_val;116	u32	read_addr;117#if defined(__LITTLE_ENDIAN)118	u8	read_addr_stride;119	u8	read_addr_num;120	u8	rsvd1[2];121#else122	u8	rsvd1[2];123	u8	read_addr_num;124	u8	read_addr_stride;125#endif126} __packed;127 128struct __ocm {129	u8	rsvd[8];130	u32	size;131	u32	no_ops;132	u8	rsvd1[8];133	u32	read_addr;134	u32	read_addr_stride;135} __packed;136 137struct __mem {138	u32	desc_card_addr;139	u32	dma_desc_cmd;140	u32	start_dma_cmd;141	u32	rsvd[3];142	u32	addr;143	u32	size;144} __packed;145 146struct __mux {147	u32	addr;148	u8	rsvd[4];149	u32	size;150	u32	no_ops;151	u32	val;152	u32	val_stride;153	u32	read_addr;154	u8	rsvd2[4];155} __packed;156 157struct __queue {158	u32	sel_addr;159#if defined(__LITTLE_ENDIAN)160	u16	stride;161	u8	rsvd[2];162#else163	u8	rsvd[2];164	u16	stride;165#endif166	u32	size;167	u32	no_ops;168	u8	rsvd2[8];169	u32	read_addr;170#if defined(__LITTLE_ENDIAN)171	u8	read_addr_stride;172	u8	read_addr_cnt;173	u8	rsvd3[2];174#else175	u8	rsvd3[2];176	u8	read_addr_cnt;177	u8	read_addr_stride;178#endif179} __packed;180 181struct __pollrd {182	u32	sel_addr;183	u32	read_addr;184	u32	sel_val;185#if defined(__LITTLE_ENDIAN)186	u16	sel_val_stride;187	u16	no_ops;188#else189	u16	no_ops;190	u16	sel_val_stride;191#endif192	u32	poll_wait;193	u32	poll_mask;194	u32	data_size;195	u8	rsvd[4];196} __packed;197 198struct __mux2 {199	u32	sel_addr1;200	u32	sel_addr2;201	u32	sel_val1;202	u32	sel_val2;203	u32	no_ops;204	u32	sel_val_mask;205	u32	read_addr;206#if defined(__LITTLE_ENDIAN)207	u8	sel_val_stride;208	u8	data_size;209	u8	rsvd[2];210#else211	u8	rsvd[2];212	u8	data_size;213	u8	sel_val_stride;214#endif215} __packed;216 217struct __pollrdmwr {218	u32	addr1;219	u32	addr2;220	u32	val1;221	u32	val2;222	u32	poll_wait;223	u32	poll_mask;224	u32	mod_mask;225	u32	data_size;226} __packed;227 228struct qlcnic_dump_entry {229	struct qlcnic_common_entry_hdr hdr;230	union {231		struct __crb		crb;232		struct __cache		cache;233		struct __ocm		ocm;234		struct __mem		mem;235		struct __mux		mux;236		struct __queue		que;237		struct __ctrl		ctrl;238		struct __pollrdmwr	pollrdmwr;239		struct __mux2		mux2;240		struct __pollrd		pollrd;241	} region;242} __packed;243 244enum qlcnic_minidump_opcode {245	QLCNIC_DUMP_NOP		= 0,246	QLCNIC_DUMP_READ_CRB	= 1,247	QLCNIC_DUMP_READ_MUX	= 2,248	QLCNIC_DUMP_QUEUE	= 3,249	QLCNIC_DUMP_BRD_CONFIG	= 4,250	QLCNIC_DUMP_READ_OCM	= 6,251	QLCNIC_DUMP_PEG_REG	= 7,252	QLCNIC_DUMP_L1_DTAG	= 8,253	QLCNIC_DUMP_L1_ITAG	= 9,254	QLCNIC_DUMP_L1_DATA	= 11,255	QLCNIC_DUMP_L1_INST	= 12,256	QLCNIC_DUMP_L2_DTAG	= 21,257	QLCNIC_DUMP_L2_ITAG	= 22,258	QLCNIC_DUMP_L2_DATA	= 23,259	QLCNIC_DUMP_L2_INST	= 24,260	QLCNIC_DUMP_POLL_RD	= 35,261	QLCNIC_READ_MUX2	= 36,262	QLCNIC_READ_POLLRDMWR	= 37,263	QLCNIC_DUMP_READ_ROM	= 71,264	QLCNIC_DUMP_READ_MEM	= 72,265	QLCNIC_DUMP_READ_CTRL	= 98,266	QLCNIC_DUMP_TLHDR	= 99,267	QLCNIC_DUMP_RDEND	= 255268};269 270inline u32 qlcnic_82xx_get_saved_state(void *t_hdr, u32 index)271{272	struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr;273 274	return hdr->saved_state[index];275}276 277inline void qlcnic_82xx_set_saved_state(void *t_hdr, u32 index,278					u32 value)279{280	struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr;281 282	hdr->saved_state[index] = value;283}284 285void qlcnic_82xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump)286{287	struct qlcnic_82xx_dump_template_hdr *hdr;288 289	hdr = fw_dump->tmpl_hdr;290	fw_dump->tmpl_hdr_size = hdr->size;291	fw_dump->version = hdr->version;292	fw_dump->num_entries = hdr->num_entries;293	fw_dump->offset = hdr->offset;294 295	hdr->drv_cap_mask = hdr->cap_mask;296	fw_dump->cap_mask = hdr->cap_mask;297 298	fw_dump->use_pex_dma = (hdr->capabilities & BIT_0) ? true : false;299}300 301inline u32 qlcnic_82xx_get_cap_size(void *t_hdr, int index)302{303	struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr;304 305	return hdr->cap_sizes[index];306}307 308void qlcnic_82xx_set_sys_info(void *t_hdr, int idx, u32 value)309{310	struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr;311 312	hdr->sys_info[idx] = value;313}314 315void qlcnic_82xx_store_cap_mask(void *tmpl_hdr, u32 mask)316{317	struct qlcnic_82xx_dump_template_hdr *hdr = tmpl_hdr;318 319	hdr->drv_cap_mask = mask;320}321 322inline u32 qlcnic_83xx_get_saved_state(void *t_hdr, u32 index)323{324	struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr;325 326	return hdr->saved_state[index];327}328 329inline void qlcnic_83xx_set_saved_state(void *t_hdr, u32 index,330					u32 value)331{332	struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr;333 334	hdr->saved_state[index] = value;335}336 337#define QLCNIC_TEMPLATE_VERSION (0x20001)338 339void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump)340{341	struct qlcnic_83xx_dump_template_hdr *hdr;342 343	hdr = fw_dump->tmpl_hdr;344	fw_dump->tmpl_hdr_size = hdr->size;345	fw_dump->version = hdr->version;346	fw_dump->num_entries = hdr->num_entries;347	fw_dump->offset = hdr->offset;348 349	hdr->drv_cap_mask = hdr->cap_mask;350	fw_dump->cap_mask = hdr->cap_mask;351 352	fw_dump->use_pex_dma = (fw_dump->version & 0xfffff) >=353			       QLCNIC_TEMPLATE_VERSION;354}355 356inline u32 qlcnic_83xx_get_cap_size(void *t_hdr, int index)357{358	struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr;359 360	return hdr->cap_sizes[index];361}362 363void qlcnic_83xx_set_sys_info(void *t_hdr, int idx, u32 value)364{365	struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr;366 367	hdr->sys_info[idx] = value;368}369 370void qlcnic_83xx_store_cap_mask(void *tmpl_hdr, u32 mask)371{372	struct qlcnic_83xx_dump_template_hdr *hdr;373 374	hdr = tmpl_hdr;375	hdr->drv_cap_mask = mask;376}377 378struct qlcnic_dump_operations {379	enum qlcnic_minidump_opcode opcode;380	u32 (*handler)(struct qlcnic_adapter *, struct qlcnic_dump_entry *,381		       __le32 *);382};383 384static u32 qlcnic_dump_crb(struct qlcnic_adapter *adapter,385			   struct qlcnic_dump_entry *entry, __le32 *buffer)386{387	int i;388	u32 addr, data;389	struct __crb *crb = &entry->region.crb;390 391	addr = crb->addr;392 393	for (i = 0; i < crb->no_ops; i++) {394		data = qlcnic_ind_rd(adapter, addr);395		*buffer++ = cpu_to_le32(addr);396		*buffer++ = cpu_to_le32(data);397		addr += crb->stride;398	}399	return crb->no_ops * 2 * sizeof(u32);400}401 402static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,403			    struct qlcnic_dump_entry *entry, __le32 *buffer)404{405	void *hdr = adapter->ahw->fw_dump.tmpl_hdr;406	struct __ctrl *ctr = &entry->region.ctrl;407	int i, k, timeout = 0;408	u32 addr, data, temp;409	u8 no_ops;410 411	addr = ctr->addr;412	no_ops = ctr->no_ops;413 414	for (i = 0; i < no_ops; i++) {415		k = 0;416		for (k = 0; k < 8; k++) {417			if (!(ctr->opcode & (1 << k)))418				continue;419			switch (1 << k) {420			case QLCNIC_DUMP_WCRB:421				qlcnic_ind_wr(adapter, addr, ctr->val1);422				break;423			case QLCNIC_DUMP_RWCRB:424				data = qlcnic_ind_rd(adapter, addr);425				qlcnic_ind_wr(adapter, addr, data);426				break;427			case QLCNIC_DUMP_ANDCRB:428				data = qlcnic_ind_rd(adapter, addr);429				qlcnic_ind_wr(adapter, addr,430					      (data & ctr->val2));431				break;432			case QLCNIC_DUMP_ORCRB:433				data = qlcnic_ind_rd(adapter, addr);434				qlcnic_ind_wr(adapter, addr,435					      (data | ctr->val3));436				break;437			case QLCNIC_DUMP_POLLCRB:438				while (timeout <= ctr->timeout) {439					data = qlcnic_ind_rd(adapter, addr);440					if ((data & ctr->val2) == ctr->val1)441						break;442					usleep_range(1000, 2000);443					timeout++;444				}445				if (timeout > ctr->timeout) {446					dev_info(&adapter->pdev->dev,447					"Timed out, aborting poll CRB\n");448					return -EINVAL;449				}450				break;451			case QLCNIC_DUMP_RD_SAVE:452				temp = ctr->index_a;453				if (temp)454					addr = qlcnic_get_saved_state(adapter,455								      hdr,456								      temp);457				data = qlcnic_ind_rd(adapter, addr);458				qlcnic_set_saved_state(adapter, hdr,459						       ctr->index_v, data);460				break;461			case QLCNIC_DUMP_WRT_SAVED:462				temp = ctr->index_v;463				if (temp)464					data = qlcnic_get_saved_state(adapter,465								      hdr,466								      temp);467				else468					data = ctr->val1;469 470				temp = ctr->index_a;471				if (temp)472					addr = qlcnic_get_saved_state(adapter,473								      hdr,474								      temp);475				qlcnic_ind_wr(adapter, addr, data);476				break;477			case QLCNIC_DUMP_MOD_SAVE_ST:478				data = qlcnic_get_saved_state(adapter, hdr,479							      ctr->index_v);480				data <<= ctr->shl_val;481				data >>= ctr->shr_val;482				if (ctr->val2)483					data &= ctr->val2;484				data |= ctr->val3;485				data += ctr->val1;486				qlcnic_set_saved_state(adapter, hdr,487						       ctr->index_v, data);488				break;489			default:490				dev_info(&adapter->pdev->dev,491					 "Unknown opcode\n");492				break;493			}494		}495		addr += ctr->stride;496	}497	return 0;498}499 500static u32 qlcnic_dump_mux(struct qlcnic_adapter *adapter,501			   struct qlcnic_dump_entry *entry, __le32 *buffer)502{503	int loop;504	u32 val, data = 0;505	struct __mux *mux = &entry->region.mux;506 507	val = mux->val;508	for (loop = 0; loop < mux->no_ops; loop++) {509		qlcnic_ind_wr(adapter, mux->addr, val);510		data = qlcnic_ind_rd(adapter, mux->read_addr);511		*buffer++ = cpu_to_le32(val);512		*buffer++ = cpu_to_le32(data);513		val += mux->val_stride;514	}515	return 2 * mux->no_ops * sizeof(u32);516}517 518static u32 qlcnic_dump_que(struct qlcnic_adapter *adapter,519			   struct qlcnic_dump_entry *entry, __le32 *buffer)520{521	int i, loop;522	u32 cnt, addr, data, que_id = 0;523	struct __queue *que = &entry->region.que;524 525	addr = que->read_addr;526	cnt = que->read_addr_cnt;527 528	for (loop = 0; loop < que->no_ops; loop++) {529		qlcnic_ind_wr(adapter, que->sel_addr, que_id);530		addr = que->read_addr;531		for (i = 0; i < cnt; i++) {532			data = qlcnic_ind_rd(adapter, addr);533			*buffer++ = cpu_to_le32(data);534			addr += que->read_addr_stride;535		}536		que_id += que->stride;537	}538	return que->no_ops * cnt * sizeof(u32);539}540 541static u32 qlcnic_dump_ocm(struct qlcnic_adapter *adapter,542			   struct qlcnic_dump_entry *entry, __le32 *buffer)543{544	int i;545	u32 data;546	void __iomem *addr;547	struct __ocm *ocm = &entry->region.ocm;548 549	addr = adapter->ahw->pci_base0 + ocm->read_addr;550	for (i = 0; i < ocm->no_ops; i++) {551		data = readl(addr);552		*buffer++ = cpu_to_le32(data);553		addr += ocm->read_addr_stride;554	}555	return ocm->no_ops * sizeof(u32);556}557 558static u32 qlcnic_read_rom(struct qlcnic_adapter *adapter,559			   struct qlcnic_dump_entry *entry, __le32 *buffer)560{561	int i, count = 0;562	u32 fl_addr, size, val, lck_val, addr;563	struct __mem *rom = &entry->region.mem;564 565	fl_addr = rom->addr;566	size = rom->size / 4;567lock_try:568	lck_val = QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_LOCK);569	if (!lck_val && count < MAX_CTL_CHECK) {570		usleep_range(10000, 11000);571		count++;572		goto lock_try;573	}574	QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER,575			    adapter->ahw->pci_func);576	for (i = 0; i < size; i++) {577		addr = fl_addr & 0xFFFF0000;578		qlcnic_ind_wr(adapter, FLASH_ROM_WINDOW, addr);579		addr = LSW(fl_addr) + FLASH_ROM_DATA;580		val = qlcnic_ind_rd(adapter, addr);581		fl_addr += 4;582		*buffer++ = cpu_to_le32(val);583	}584	QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_UNLOCK);585	return rom->size;586}587 588static u32 qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter,589				struct qlcnic_dump_entry *entry, __le32 *buffer)590{591	int i;592	u32 cnt, val, data, addr;593	struct __cache *l1 = &entry->region.cache;594 595	val = l1->init_tag_val;596 597	for (i = 0; i < l1->no_ops; i++) {598		qlcnic_ind_wr(adapter, l1->addr, val);599		qlcnic_ind_wr(adapter, l1->ctrl_addr, LSW(l1->ctrl_val));600		addr = l1->read_addr;601		cnt = l1->read_addr_num;602		while (cnt) {603			data = qlcnic_ind_rd(adapter, addr);604			*buffer++ = cpu_to_le32(data);605			addr += l1->read_addr_stride;606			cnt--;607		}608		val += l1->stride;609	}610	return l1->no_ops * l1->read_addr_num * sizeof(u32);611}612 613static u32 qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter,614				struct qlcnic_dump_entry *entry, __le32 *buffer)615{616	int i;617	u32 cnt, val, data, addr;618	u8 poll_mask, poll_to, time_out = 0;619	struct __cache *l2 = &entry->region.cache;620 621	val = l2->init_tag_val;622	poll_mask = LSB(MSW(l2->ctrl_val));623	poll_to = MSB(MSW(l2->ctrl_val));624 625	for (i = 0; i < l2->no_ops; i++) {626		qlcnic_ind_wr(adapter, l2->addr, val);627		if (LSW(l2->ctrl_val))628			qlcnic_ind_wr(adapter, l2->ctrl_addr,629				      LSW(l2->ctrl_val));630		if (!poll_mask)631			goto skip_poll;632		do {633			data = qlcnic_ind_rd(adapter, l2->ctrl_addr);634			if (!(data & poll_mask))635				break;636			usleep_range(1000, 2000);637			time_out++;638		} while (time_out <= poll_to);639 640		if (time_out > poll_to) {641			dev_err(&adapter->pdev->dev,642				"Timeout exceeded in %s, aborting dump\n",643				__func__);644			return -EINVAL;645		}646skip_poll:647		addr = l2->read_addr;648		cnt = l2->read_addr_num;649		while (cnt) {650			data = qlcnic_ind_rd(adapter, addr);651			*buffer++ = cpu_to_le32(data);652			addr += l2->read_addr_stride;653			cnt--;654		}655		val += l2->stride;656	}657	return l2->no_ops * l2->read_addr_num * sizeof(u32);658}659 660static u32 qlcnic_read_memory_test_agent(struct qlcnic_adapter *adapter,661					 struct __mem *mem, __le32 *buffer,662					 int *ret)663{664	u32 addr, data, test;665	int i, reg_read;666 667	reg_read = mem->size;668	addr = mem->addr;669	/* check for data size of multiple of 16 and 16 byte alignment */670	if ((addr & 0xf) || (reg_read%16)) {671		dev_info(&adapter->pdev->dev,672			 "Unaligned memory addr:0x%x size:0x%x\n",673			 addr, reg_read);674		*ret = -EINVAL;675		return 0;676	}677 678	mutex_lock(&adapter->ahw->mem_lock);679 680	while (reg_read != 0) {681		qlcnic_ind_wr(adapter, QLCNIC_MS_ADDR_LO, addr);682		qlcnic_ind_wr(adapter, QLCNIC_MS_ADDR_HI, 0);683		qlcnic_ind_wr(adapter, QLCNIC_MS_CTRL, QLCNIC_TA_START_ENABLE);684 685		for (i = 0; i < MAX_CTL_CHECK; i++) {686			test = qlcnic_ind_rd(adapter, QLCNIC_MS_CTRL);687			if (!(test & TA_CTL_BUSY))688				break;689		}690		if (i == MAX_CTL_CHECK) {691			if (printk_ratelimit()) {692				dev_err(&adapter->pdev->dev,693					"failed to read through agent\n");694				*ret = -EIO;695				goto out;696			}697		}698		for (i = 0; i < 4; i++) {699			data = qlcnic_ind_rd(adapter, qlcnic_ms_read_data[i]);700			*buffer++ = cpu_to_le32(data);701		}702		addr += 16;703		reg_read -= 16;704		ret += 16;705		cond_resched();706	}707out:708	mutex_unlock(&adapter->ahw->mem_lock);709	return mem->size;710}711 712/* DMA register base address */713#define QLC_DMA_REG_BASE_ADDR(dma_no)	(0x77320000 + (dma_no * 0x10000))714 715/* DMA register offsets w.r.t base address */716#define QLC_DMA_CMD_BUFF_ADDR_LOW	0717#define QLC_DMA_CMD_BUFF_ADDR_HI	4718#define QLC_DMA_CMD_STATUS_CTRL		8719 720static int qlcnic_start_pex_dma(struct qlcnic_adapter *adapter,721				struct __mem *mem)722{723	struct device *dev = &adapter->pdev->dev;724	u32 dma_no, dma_base_addr, temp_addr;725	int i, ret, dma_sts;726	void *tmpl_hdr;727 728	tmpl_hdr = adapter->ahw->fw_dump.tmpl_hdr;729	dma_no = qlcnic_get_saved_state(adapter, tmpl_hdr,730					QLC_83XX_DMA_ENGINE_INDEX);731	dma_base_addr = QLC_DMA_REG_BASE_ADDR(dma_no);732 733	temp_addr = dma_base_addr + QLC_DMA_CMD_BUFF_ADDR_LOW;734	ret = qlcnic_ind_wr(adapter, temp_addr, mem->desc_card_addr);735	if (ret)736		return ret;737 738	temp_addr = dma_base_addr + QLC_DMA_CMD_BUFF_ADDR_HI;739	ret = qlcnic_ind_wr(adapter, temp_addr, 0);740	if (ret)741		return ret;742 743	temp_addr = dma_base_addr + QLC_DMA_CMD_STATUS_CTRL;744	ret = qlcnic_ind_wr(adapter, temp_addr, mem->start_dma_cmd);745	if (ret)746		return ret;747 748	/* Wait for DMA to complete */749	temp_addr = dma_base_addr + QLC_DMA_CMD_STATUS_CTRL;750	for (i = 0; i < 400; i++) {751		dma_sts = qlcnic_ind_rd(adapter, temp_addr);752 753		if (dma_sts & BIT_1)754			usleep_range(250, 500);755		else756			break;757	}758 759	if (i >= 400) {760		dev_info(dev, "PEX DMA operation timed out");761		ret = -EIO;762	}763 764	return ret;765}766 767static u32 qlcnic_read_memory_pexdma(struct qlcnic_adapter *adapter,768				     struct __mem *mem,769				     __le32 *buffer, int *ret)770{771	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;772	u32 temp, dma_base_addr, size = 0, read_size = 0;773	struct qlcnic_pex_dma_descriptor *dma_descr;774	struct device *dev = &adapter->pdev->dev;775	dma_addr_t dma_phys_addr;776	void *dma_buffer;777	void *tmpl_hdr;778 779	tmpl_hdr = fw_dump->tmpl_hdr;780 781	/* Check if DMA engine is available */782	temp = qlcnic_get_saved_state(adapter, tmpl_hdr,783				      QLC_83XX_DMA_ENGINE_INDEX);784	dma_base_addr = QLC_DMA_REG_BASE_ADDR(temp);785	temp = qlcnic_ind_rd(adapter,786			     dma_base_addr + QLC_DMA_CMD_STATUS_CTRL);787 788	if (!(temp & BIT_31)) {789		dev_info(dev, "%s: DMA engine is not available\n", __func__);790		*ret = -EIO;791		return 0;792	}793 794	/* Create DMA descriptor */795	dma_descr = kzalloc(sizeof(struct qlcnic_pex_dma_descriptor),796			    GFP_KERNEL);797	if (!dma_descr) {798		*ret = -ENOMEM;799		return 0;800	}801 802	/* dma_desc_cmd  0:15  = 0803	 * dma_desc_cmd 16:19  = mem->dma_desc_cmd 0:3804	 * dma_desc_cmd 20:23  = pci function number805	 * dma_desc_cmd 24:31  = mem->dma_desc_cmd 8:15806	 */807	dma_phys_addr = fw_dump->phys_addr;808	dma_buffer = fw_dump->dma_buffer;809	temp = 0;810	temp = mem->dma_desc_cmd & 0xff0f;811	temp |= (adapter->ahw->pci_func & 0xf) << 4;812	dma_descr->dma_desc_cmd = (temp << 16) & 0xffff0000;813	dma_descr->dma_bus_addr_low = LSD(dma_phys_addr);814	dma_descr->dma_bus_addr_high = MSD(dma_phys_addr);815	dma_descr->src_addr_high = 0;816 817	/* Collect memory dump using multiple DMA operations if required */818	while (read_size < mem->size) {819		if (mem->size - read_size >= QLC_PEX_DMA_READ_SIZE)820			size = QLC_PEX_DMA_READ_SIZE;821		else822			size = mem->size - read_size;823 824		dma_descr->src_addr_low = mem->addr + read_size;825		dma_descr->read_data_size = size;826 827		/* Write DMA descriptor to MS memory*/828		temp = sizeof(struct qlcnic_pex_dma_descriptor) / 16;829		*ret = qlcnic_ms_mem_write128(adapter, mem->desc_card_addr,830					      (u32 *)dma_descr, temp);831		if (*ret) {832			dev_info(dev, "Failed to write DMA descriptor to MS memory at address 0x%x\n",833				 mem->desc_card_addr);834			goto free_dma_descr;835		}836 837		*ret = qlcnic_start_pex_dma(adapter, mem);838		if (*ret) {839			dev_info(dev, "Failed to start PEX DMA operation\n");840			goto free_dma_descr;841		}842 843		memcpy(buffer, dma_buffer, size);844		buffer += size / 4;845		read_size += size;846	}847 848free_dma_descr:849	kfree(dma_descr);850 851	return read_size;852}853 854static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter,855			      struct qlcnic_dump_entry *entry, __le32 *buffer)856{857	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;858	struct device *dev = &adapter->pdev->dev;859	struct __mem *mem = &entry->region.mem;860	u32 data_size;861	int ret = 0;862 863	if (fw_dump->use_pex_dma) {864		data_size = qlcnic_read_memory_pexdma(adapter, mem, buffer,865						      &ret);866		if (ret)867			dev_info(dev,868				 "Failed to read memory dump using PEX DMA: mask[0x%x]\n",869				 entry->hdr.mask);870		else871			return data_size;872	}873 874	data_size = qlcnic_read_memory_test_agent(adapter, mem, buffer, &ret);875	if (ret) {876		dev_info(dev,877			 "Failed to read memory dump using test agent method: mask[0x%x]\n",878			 entry->hdr.mask);879		return 0;880	} else {881		return data_size;882	}883}884 885static u32 qlcnic_dump_nop(struct qlcnic_adapter *adapter,886			   struct qlcnic_dump_entry *entry, __le32 *buffer)887{888	entry->hdr.flags |= QLCNIC_DUMP_SKIP;889	return 0;890}891 892static int qlcnic_valid_dump_entry(struct device *dev,893				   struct qlcnic_dump_entry *entry, u32 size)894{895	int ret = 1;896	if (size != entry->hdr.cap_size) {897		dev_err(dev,898			"Invalid entry, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",899			entry->hdr.type, entry->hdr.mask, size,900			entry->hdr.cap_size);901		ret = 0;902	}903	return ret;904}905 906static u32 qlcnic_read_pollrdmwr(struct qlcnic_adapter *adapter,907				 struct qlcnic_dump_entry *entry,908				 __le32 *buffer)909{910	struct __pollrdmwr *poll = &entry->region.pollrdmwr;911	u32 data, wait_count, poll_wait, temp;912 913	poll_wait = poll->poll_wait;914 915	qlcnic_ind_wr(adapter, poll->addr1, poll->val1);916	wait_count = 0;917 918	while (wait_count < poll_wait) {919		data = qlcnic_ind_rd(adapter, poll->addr1);920		if ((data & poll->poll_mask) != 0)921			break;922		wait_count++;923	}924 925	if (wait_count == poll_wait) {926		dev_err(&adapter->pdev->dev,927			"Timeout exceeded in %s, aborting dump\n",928			__func__);929		return 0;930	}931 932	data = qlcnic_ind_rd(adapter, poll->addr2) & poll->mod_mask;933	qlcnic_ind_wr(adapter, poll->addr2, data);934	qlcnic_ind_wr(adapter, poll->addr1, poll->val2);935	wait_count = 0;936 937	while (wait_count < poll_wait) {938		temp = qlcnic_ind_rd(adapter, poll->addr1);939		if ((temp & poll->poll_mask) != 0)940			break;941		wait_count++;942	}943 944	*buffer++ = cpu_to_le32(poll->addr2);945	*buffer++ = cpu_to_le32(data);946 947	return 2 * sizeof(u32);948 949}950 951static u32 qlcnic_read_pollrd(struct qlcnic_adapter *adapter,952			      struct qlcnic_dump_entry *entry, __le32 *buffer)953{954	struct __pollrd *pollrd = &entry->region.pollrd;955	u32 data, wait_count, poll_wait, sel_val;956	int i;957 958	poll_wait = pollrd->poll_wait;959	sel_val = pollrd->sel_val;960 961	for (i = 0; i < pollrd->no_ops; i++) {962		qlcnic_ind_wr(adapter, pollrd->sel_addr, sel_val);963		wait_count = 0;964		while (wait_count < poll_wait) {965			data = qlcnic_ind_rd(adapter, pollrd->sel_addr);966			if ((data & pollrd->poll_mask) != 0)967				break;968			wait_count++;969		}970 971		if (wait_count == poll_wait) {972			dev_err(&adapter->pdev->dev,973				"Timeout exceeded in %s, aborting dump\n",974				__func__);975			return 0;976		}977 978		data = qlcnic_ind_rd(adapter, pollrd->read_addr);979		*buffer++ = cpu_to_le32(sel_val);980		*buffer++ = cpu_to_le32(data);981		sel_val += pollrd->sel_val_stride;982	}983	return pollrd->no_ops * (2 * sizeof(u32));984}985 986static u32 qlcnic_read_mux2(struct qlcnic_adapter *adapter,987			    struct qlcnic_dump_entry *entry, __le32 *buffer)988{989	struct __mux2 *mux2 = &entry->region.mux2;990	u32 data;991	u32 t_sel_val, sel_val1, sel_val2;992	int i;993 994	sel_val1 = mux2->sel_val1;995	sel_val2 = mux2->sel_val2;996 997	for (i = 0; i < mux2->no_ops; i++) {998		qlcnic_ind_wr(adapter, mux2->sel_addr1, sel_val1);999		t_sel_val = sel_val1 & mux2->sel_val_mask;1000		qlcnic_ind_wr(adapter, mux2->sel_addr2, t_sel_val);1001		data = qlcnic_ind_rd(adapter, mux2->read_addr);1002		*buffer++ = cpu_to_le32(t_sel_val);1003		*buffer++ = cpu_to_le32(data);1004		qlcnic_ind_wr(adapter, mux2->sel_addr1, sel_val2);1005		t_sel_val = sel_val2 & mux2->sel_val_mask;1006		qlcnic_ind_wr(adapter, mux2->sel_addr2, t_sel_val);1007		data = qlcnic_ind_rd(adapter, mux2->read_addr);1008		*buffer++ = cpu_to_le32(t_sel_val);1009		*buffer++ = cpu_to_le32(data);1010		sel_val1 += mux2->sel_val_stride;1011		sel_val2 += mux2->sel_val_stride;1012	}1013 1014	return mux2->no_ops * (4 * sizeof(u32));1015}1016 1017static u32 qlcnic_83xx_dump_rom(struct qlcnic_adapter *adapter,1018				struct qlcnic_dump_entry *entry, __le32 *buffer)1019{1020	u32 fl_addr, size;1021	struct __mem *rom = &entry->region.mem;1022 1023	fl_addr = rom->addr;1024	size = rom->size / 4;1025 1026	if (!qlcnic_83xx_lockless_flash_read32(adapter, fl_addr,1027					       (u8 *)buffer, size))1028		return rom->size;1029 1030	return 0;1031}1032 1033static const struct qlcnic_dump_operations qlcnic_fw_dump_ops[] = {1034	{QLCNIC_DUMP_NOP, qlcnic_dump_nop},1035	{QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb},1036	{QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux},1037	{QLCNIC_DUMP_QUEUE, qlcnic_dump_que},1038	{QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom},1039	{QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm},1040	{QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl},1041	{QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache},1042	{QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache},1043	{QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache},1044	{QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache},1045	{QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache},1046	{QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache},1047	{QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache},1048	{QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache},1049	{QLCNIC_DUMP_READ_ROM, qlcnic_read_rom},1050	{QLCNIC_DUMP_READ_MEM, qlcnic_read_memory},1051	{QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl},1052	{QLCNIC_DUMP_TLHDR, qlcnic_dump_nop},1053	{QLCNIC_DUMP_RDEND, qlcnic_dump_nop},1054};1055 1056static const struct qlcnic_dump_operations qlcnic_83xx_fw_dump_ops[] = {1057	{QLCNIC_DUMP_NOP, qlcnic_dump_nop},1058	{QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb},1059	{QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux},1060	{QLCNIC_DUMP_QUEUE, qlcnic_dump_que},1061	{QLCNIC_DUMP_BRD_CONFIG, qlcnic_83xx_dump_rom},1062	{QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm},1063	{QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl},1064	{QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache},1065	{QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache},1066	{QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache},1067	{QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache},1068	{QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache},1069	{QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache},1070	{QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache},1071	{QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache},1072	{QLCNIC_DUMP_POLL_RD, qlcnic_read_pollrd},1073	{QLCNIC_READ_MUX2, qlcnic_read_mux2},1074	{QLCNIC_READ_POLLRDMWR, qlcnic_read_pollrdmwr},1075	{QLCNIC_DUMP_READ_ROM, qlcnic_83xx_dump_rom},1076	{QLCNIC_DUMP_READ_MEM, qlcnic_read_memory},1077	{QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl},1078	{QLCNIC_DUMP_TLHDR, qlcnic_dump_nop},1079	{QLCNIC_DUMP_RDEND, qlcnic_dump_nop},1080};1081 1082static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u32 temp_size)1083{1084	uint64_t sum = 0;1085	int count = temp_size / sizeof(uint32_t);1086	while (count-- > 0)1087		sum += *temp_buffer++;1088	while (sum >> 32)1089		sum = (sum & 0xFFFFFFFF) + (sum >> 32);1090	return ~sum;1091}1092 1093static int qlcnic_fw_flash_get_minidump_temp(struct qlcnic_adapter *adapter,1094					     u8 *buffer, u32 size)1095{1096	int ret = 0;1097 1098	if (qlcnic_82xx_check(adapter))1099		return -EIO;1100 1101	if (qlcnic_83xx_lock_flash(adapter))1102		return -EIO;1103 1104	ret = qlcnic_83xx_lockless_flash_read32(adapter,1105						QLC_83XX_MINIDUMP_FLASH,1106						buffer, size / sizeof(u32));1107 1108	qlcnic_83xx_unlock_flash(adapter);1109 1110	return ret;1111}1112 1113static int1114qlcnic_fw_flash_get_minidump_temp_size(struct qlcnic_adapter *adapter,1115				       struct qlcnic_cmd_args *cmd)1116{1117	struct qlcnic_83xx_dump_template_hdr tmp_hdr;1118	u32 size = sizeof(tmp_hdr) / sizeof(u32);1119	int ret = 0;1120 1121	if (qlcnic_82xx_check(adapter))1122		return -EIO;1123 1124	if (qlcnic_83xx_lock_flash(adapter))1125		return -EIO;1126 1127	ret = qlcnic_83xx_lockless_flash_read32(adapter,1128						QLC_83XX_MINIDUMP_FLASH,1129						(u8 *)&tmp_hdr, size);1130 1131	qlcnic_83xx_unlock_flash(adapter);1132 1133	cmd->rsp.arg[2] = tmp_hdr.size;1134	cmd->rsp.arg[3] = tmp_hdr.version;1135 1136	return ret;1137}1138 1139static int qlcnic_fw_get_minidump_temp_size(struct qlcnic_adapter *adapter,1140					    u32 *version, u32 *temp_size,1141					    u8 *use_flash_temp)1142{1143	int err = 0;1144	struct qlcnic_cmd_args cmd;1145 1146	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TEMP_SIZE))1147		return -ENOMEM;1148 1149	err = qlcnic_issue_cmd(adapter, &cmd);1150	if (err != QLCNIC_RCODE_SUCCESS) {1151		if (qlcnic_fw_flash_get_minidump_temp_size(adapter, &cmd)) {1152			qlcnic_free_mbx_args(&cmd);1153			return -EIO;1154		}1155		*use_flash_temp = 1;1156	}1157 1158	*temp_size = cmd.rsp.arg[2];1159	*version = cmd.rsp.arg[3];1160	qlcnic_free_mbx_args(&cmd);1161 1162	if (!(*temp_size))1163		return -EIO;1164 1165	return 0;1166}1167 1168static int __qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter,1169					     u32 *buffer, u32 temp_size)1170{1171	int err = 0, i;1172	void *tmp_addr;1173	__le32 *tmp_buf;1174	struct qlcnic_cmd_args cmd;1175	dma_addr_t tmp_addr_t = 0;1176 1177	tmp_addr = dma_alloc_coherent(&adapter->pdev->dev, temp_size,1178				      &tmp_addr_t, GFP_KERNEL);1179	if (!tmp_addr)1180		return -ENOMEM;1181 1182	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_TEMP_HDR)) {1183		err = -ENOMEM;1184		goto free_mem;1185	}1186 1187	cmd.req.arg[1] = LSD(tmp_addr_t);1188	cmd.req.arg[2] = MSD(tmp_addr_t);1189	cmd.req.arg[3] = temp_size;1190	err = qlcnic_issue_cmd(adapter, &cmd);1191 1192	tmp_buf = tmp_addr;1193	if (err == QLCNIC_RCODE_SUCCESS) {1194		for (i = 0; i < temp_size / sizeof(u32); i++)1195			*buffer++ = __le32_to_cpu(*tmp_buf++);1196	}1197 1198	qlcnic_free_mbx_args(&cmd);1199 1200free_mem:1201	dma_free_coherent(&adapter->pdev->dev, temp_size, tmp_addr, tmp_addr_t);1202 1203	return err;1204}1205 1206int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)1207{1208	struct qlcnic_hardware_context *ahw;1209	struct qlcnic_fw_dump *fw_dump;1210	u32 version, csum, *tmp_buf;1211	u8 use_flash_temp = 0;1212	u32 temp_size = 0;1213	void *temp_buffer;1214	int err;1215 1216	ahw = adapter->ahw;1217	fw_dump = &ahw->fw_dump;1218	err = qlcnic_fw_get_minidump_temp_size(adapter, &version, &temp_size,1219					       &use_flash_temp);1220	if (err) {1221		dev_err(&adapter->pdev->dev,1222			"Can't get template size %d\n", err);1223		return -EIO;1224	}1225 1226	fw_dump->tmpl_hdr = vzalloc(temp_size);1227	if (!fw_dump->tmpl_hdr)1228		return -ENOMEM;1229 1230	tmp_buf = (u32 *)fw_dump->tmpl_hdr;1231	if (use_flash_temp)1232		goto flash_temp;1233 1234	err = __qlcnic_fw_cmd_get_minidump_temp(adapter, tmp_buf, temp_size);1235 1236	if (err) {1237flash_temp:1238		err = qlcnic_fw_flash_get_minidump_temp(adapter, (u8 *)tmp_buf,1239							temp_size);1240 1241		if (err) {1242			dev_err(&adapter->pdev->dev,1243				"Failed to get minidump template header %d\n",1244				err);1245			vfree(fw_dump->tmpl_hdr);1246			fw_dump->tmpl_hdr = NULL;1247			return -EIO;1248		}1249	}1250 1251	csum = qlcnic_temp_checksum((uint32_t *)tmp_buf, temp_size);1252 1253	if (csum) {1254		dev_err(&adapter->pdev->dev,1255			"Template header checksum validation failed\n");1256		vfree(fw_dump->tmpl_hdr);1257		fw_dump->tmpl_hdr = NULL;1258		return -EIO;1259	}1260 1261	qlcnic_cache_tmpl_hdr_values(adapter, fw_dump);1262 1263	if (fw_dump->use_pex_dma) {1264		fw_dump->dma_buffer = NULL;1265		temp_buffer = dma_alloc_coherent(&adapter->pdev->dev,1266						 QLC_PEX_DMA_READ_SIZE,1267						 &fw_dump->phys_addr,1268						 GFP_KERNEL);1269		if (!temp_buffer)1270			fw_dump->use_pex_dma = false;1271		else1272			fw_dump->dma_buffer = temp_buffer;1273	}1274 1275 1276	dev_info(&adapter->pdev->dev,1277		 "Default minidump capture mask 0x%x\n",1278		 fw_dump->cap_mask);1279 1280	qlcnic_enable_fw_dump_state(adapter);1281 1282	return 0;1283}1284 1285int qlcnic_dump_fw(struct qlcnic_adapter *adapter)1286{1287	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;1288	const struct qlcnic_dump_operations *fw_dump_ops;1289	struct qlcnic_83xx_dump_template_hdr *hdr_83xx;1290	u32 entry_offset, dump, no_entries, buf_offset = 0;1291	int i, k, ops_cnt, ops_index, dump_size = 0;1292	struct device *dev = &adapter->pdev->dev;1293	struct qlcnic_hardware_context *ahw;1294	struct qlcnic_dump_entry *entry;1295	void *tmpl_hdr;1296	u32 ocm_window;1297	__le32 *buffer;1298	char mesg[64];1299	char *msg[] = {mesg, NULL};1300 1301	ahw = adapter->ahw;1302	tmpl_hdr = fw_dump->tmpl_hdr;1303 1304	/* Return if we don't have firmware dump template header */1305	if (!tmpl_hdr)1306		return -EIO;1307 1308	if (!qlcnic_check_fw_dump_state(adapter)) {1309		dev_info(&adapter->pdev->dev, "Dump not enabled\n");1310		return -EIO;1311	}1312 1313	if (fw_dump->clr) {1314		dev_info(&adapter->pdev->dev,1315			 "Previous dump not cleared, not capturing dump\n");1316		return -EIO;1317	}1318 1319	netif_info(adapter->ahw, drv, adapter->netdev, "Take FW dump\n");1320	/* Calculate the size for dump data area only */1321	for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++)1322		if (i & fw_dump->cap_mask)1323			dump_size += qlcnic_get_cap_size(adapter, tmpl_hdr, k);1324 1325	if (!dump_size)1326		return -EIO;1327 1328	fw_dump->data = vzalloc(dump_size);1329	if (!fw_dump->data)1330		return -ENOMEM;1331 1332	buffer = fw_dump->data;1333	fw_dump->size = dump_size;1334	no_entries = fw_dump->num_entries;1335	entry_offset = fw_dump->offset;1336	qlcnic_set_sys_info(adapter, tmpl_hdr, 0, QLCNIC_DRIVER_VERSION);1337	qlcnic_set_sys_info(adapter, tmpl_hdr, 1, adapter->fw_version);1338 1339	if (qlcnic_82xx_check(adapter)) {1340		ops_cnt = ARRAY_SIZE(qlcnic_fw_dump_ops);1341		fw_dump_ops = qlcnic_fw_dump_ops;1342	} else {1343		hdr_83xx = tmpl_hdr;1344		ops_cnt = ARRAY_SIZE(qlcnic_83xx_fw_dump_ops);1345		fw_dump_ops = qlcnic_83xx_fw_dump_ops;1346		ocm_window = hdr_83xx->ocm_wnd_reg[ahw->pci_func];1347		hdr_83xx->saved_state[QLC_83XX_OCM_INDEX] = ocm_window;1348		hdr_83xx->saved_state[QLC_83XX_PCI_INDEX] = ahw->pci_func;1349	}1350 1351	for (i = 0; i < no_entries; i++) {1352		entry = tmpl_hdr + entry_offset;1353		if (!(entry->hdr.mask & fw_dump->cap_mask)) {1354			entry->hdr.flags |= QLCNIC_DUMP_SKIP;1355			entry_offset += entry->hdr.offset;1356			continue;1357		}1358 1359		/* Find the handler for this entry */1360		ops_index = 0;1361		while (ops_index < ops_cnt) {1362			if (entry->hdr.type == fw_dump_ops[ops_index].opcode)1363				break;1364			ops_index++;1365		}1366 1367		if (ops_index == ops_cnt) {1368			dev_info(dev, "Skipping unknown entry opcode %d\n",1369				 entry->hdr.type);1370			entry->hdr.flags |= QLCNIC_DUMP_SKIP;1371			entry_offset += entry->hdr.offset;1372			continue;1373		}1374 1375		/* Collect dump for this entry */1376		dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer);1377		if (!qlcnic_valid_dump_entry(dev, entry, dump)) {1378			entry->hdr.flags |= QLCNIC_DUMP_SKIP;1379			entry_offset += entry->hdr.offset;1380			continue;1381		}1382 1383		buf_offset += entry->hdr.cap_size;1384		entry_offset += entry->hdr.offset;1385		buffer = fw_dump->data + buf_offset;1386		cond_resched();1387	}1388 1389	fw_dump->clr = 1;1390	snprintf(mesg, sizeof(mesg), "FW_DUMP=%s", adapter->netdev->name);1391	netdev_info(adapter->netdev,1392		    "Dump data %d bytes captured, dump data address = %p, template header size %d bytes, template address = %p\n",1393		    fw_dump->size, fw_dump->data, fw_dump->tmpl_hdr_size,1394		    fw_dump->tmpl_hdr);1395	/* Send a udev event to notify availability of FW dump */1396	kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, msg);1397 1398	return 0;1399}1400 1401static inline bool1402qlcnic_83xx_md_check_extended_dump_capability(struct qlcnic_adapter *adapter)1403{1404	/* For special adapters (with 0x8830 device ID), where iSCSI firmware1405	 * dump needs to be captured as part of regular firmware dump1406	 * collection process, firmware exports it's capability through1407	 * capability registers1408	 */1409	return ((adapter->pdev->device == PCI_DEVICE_ID_QLOGIC_QLE8830) &&1410		(adapter->ahw->extra_capability[0] &1411		 QLCNIC_FW_CAPABILITY_2_EXT_ISCSI_DUMP));1412}1413 1414void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *adapter)1415{1416	u32 prev_version, current_version;1417	struct qlcnic_hardware_context *ahw = adapter->ahw;1418	struct qlcnic_fw_dump *fw_dump = &ahw->fw_dump;1419	struct pci_dev *pdev = adapter->pdev;1420	bool extended = false;1421	int ret;1422 1423	prev_version = adapter->fw_version;1424	current_version = qlcnic_83xx_get_fw_version(adapter);1425 1426	if (fw_dump->tmpl_hdr == NULL || current_version > prev_version) {1427		vfree(fw_dump->tmpl_hdr);1428		fw_dump->tmpl_hdr = NULL;1429 1430		if (qlcnic_83xx_md_check_extended_dump_capability(adapter))1431			extended = !qlcnic_83xx_extend_md_capab(adapter);1432 1433		ret = qlcnic_fw_cmd_get_minidump_temp(adapter);1434		if (ret)1435			return;1436 1437		dev_info(&pdev->dev, "Supports FW dump capability\n");1438 1439		/* Once we have minidump template with extended iSCSI dump1440		 * capability, update the minidump capture mask to 0x1f as1441		 * per FW requirement1442		 */1443		if (extended) {1444			struct qlcnic_83xx_dump_template_hdr *hdr;1445 1446			hdr = fw_dump->tmpl_hdr;1447			if (!hdr)1448				return;1449			hdr->drv_cap_mask = 0x1f;1450			fw_dump->cap_mask = 0x1f;1451			dev_info(&pdev->dev,1452				 "Extended iSCSI dump capability and updated capture mask to 0x1f\n");1453		}1454	}1455}1456