brintos

brintos / linux-shallow public Read only

0
0
Text · 65.6 KiB · 89c8b23 Raw
2549 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2003 - 2009 NetXen, Inc.4 * Copyright (C) 2009 - QLogic Corporation.5 * All rights reserved.6 */7 8#include <linux/io-64-nonatomic-lo-hi.h>9#include <linux/slab.h>10#include "netxen_nic.h"11#include "netxen_nic_hw.h"12 13#include <net/ip.h>14 15#define MASK(n) ((1ULL<<(n))-1)16#define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))17#define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff))18#define MS_WIN(addr) (addr & 0x0ffc0000)19 20#define GET_MEM_OFFS_2M(addr) (addr & MASK(18))21 22#define CRB_BLK(off)	((off >> 20) & 0x3f)23#define CRB_SUBBLK(off)	((off >> 16) & 0xf)24#define CRB_WINDOW_2M	(0x130060)25#define CRB_HI(off)	((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))26#define CRB_INDIRECT_2M	(0x1e0000UL)27 28static void netxen_nic_io_write_128M(struct netxen_adapter *adapter,29		void __iomem *addr, u32 data);30static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter,31		void __iomem *addr);32 33#define PCI_OFFSET_FIRST_RANGE(adapter, off)    \34	((adapter)->ahw.pci_base0 + (off))35#define PCI_OFFSET_SECOND_RANGE(adapter, off)   \36	((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START)37#define PCI_OFFSET_THIRD_RANGE(adapter, off)    \38	((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START)39 40static void __iomem *pci_base_offset(struct netxen_adapter *adapter,41					    unsigned long off)42{43	if (ADDR_IN_RANGE(off, FIRST_PAGE_GROUP_START, FIRST_PAGE_GROUP_END))44		return PCI_OFFSET_FIRST_RANGE(adapter, off);45 46	if (ADDR_IN_RANGE(off, SECOND_PAGE_GROUP_START, SECOND_PAGE_GROUP_END))47		return PCI_OFFSET_SECOND_RANGE(adapter, off);48 49	if (ADDR_IN_RANGE(off, THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_END))50		return PCI_OFFSET_THIRD_RANGE(adapter, off);51 52	return NULL;53}54 55static crb_128M_2M_block_map_t56crb_128M_2M_map[64] __cacheline_aligned_in_smp = {57    {{{0, 0,         0,         0} } },		/* 0: PCI */58    {{{1, 0x0100000, 0x0102000, 0x120000},	/* 1: PCIE */59	  {1, 0x0110000, 0x0120000, 0x130000},60	  {1, 0x0120000, 0x0122000, 0x124000},61	  {1, 0x0130000, 0x0132000, 0x126000},62	  {1, 0x0140000, 0x0142000, 0x128000},63	  {1, 0x0150000, 0x0152000, 0x12a000},64	  {1, 0x0160000, 0x0170000, 0x110000},65	  {1, 0x0170000, 0x0172000, 0x12e000},66	  {0, 0x0000000, 0x0000000, 0x000000},67	  {0, 0x0000000, 0x0000000, 0x000000},68	  {0, 0x0000000, 0x0000000, 0x000000},69	  {0, 0x0000000, 0x0000000, 0x000000},70	  {0, 0x0000000, 0x0000000, 0x000000},71	  {0, 0x0000000, 0x0000000, 0x000000},72	  {1, 0x01e0000, 0x01e0800, 0x122000},73	  {0, 0x0000000, 0x0000000, 0x000000} } },74	{{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */75    {{{0, 0,         0,         0} } },	    /* 3: */76    {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */77    {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE   */78    {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU   */79    {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM    */80    {{{1, 0x0800000, 0x0802000, 0x170000},  /* 8: SQM0  */81      {0, 0x0000000, 0x0000000, 0x000000},82      {0, 0x0000000, 0x0000000, 0x000000},83      {0, 0x0000000, 0x0000000, 0x000000},84      {0, 0x0000000, 0x0000000, 0x000000},85      {0, 0x0000000, 0x0000000, 0x000000},86      {0, 0x0000000, 0x0000000, 0x000000},87      {0, 0x0000000, 0x0000000, 0x000000},88      {0, 0x0000000, 0x0000000, 0x000000},89      {0, 0x0000000, 0x0000000, 0x000000},90      {0, 0x0000000, 0x0000000, 0x000000},91      {0, 0x0000000, 0x0000000, 0x000000},92      {0, 0x0000000, 0x0000000, 0x000000},93      {0, 0x0000000, 0x0000000, 0x000000},94      {0, 0x0000000, 0x0000000, 0x000000},95      {1, 0x08f0000, 0x08f2000, 0x172000} } },96    {{{1, 0x0900000, 0x0902000, 0x174000},	/* 9: SQM1*/97      {0, 0x0000000, 0x0000000, 0x000000},98      {0, 0x0000000, 0x0000000, 0x000000},99      {0, 0x0000000, 0x0000000, 0x000000},100      {0, 0x0000000, 0x0000000, 0x000000},101      {0, 0x0000000, 0x0000000, 0x000000},102      {0, 0x0000000, 0x0000000, 0x000000},103      {0, 0x0000000, 0x0000000, 0x000000},104      {0, 0x0000000, 0x0000000, 0x000000},105      {0, 0x0000000, 0x0000000, 0x000000},106      {0, 0x0000000, 0x0000000, 0x000000},107      {0, 0x0000000, 0x0000000, 0x000000},108      {0, 0x0000000, 0x0000000, 0x000000},109      {0, 0x0000000, 0x0000000, 0x000000},110      {0, 0x0000000, 0x0000000, 0x000000},111      {1, 0x09f0000, 0x09f2000, 0x176000} } },112    {{{0, 0x0a00000, 0x0a02000, 0x178000},	/* 10: SQM2*/113      {0, 0x0000000, 0x0000000, 0x000000},114      {0, 0x0000000, 0x0000000, 0x000000},115      {0, 0x0000000, 0x0000000, 0x000000},116      {0, 0x0000000, 0x0000000, 0x000000},117      {0, 0x0000000, 0x0000000, 0x000000},118      {0, 0x0000000, 0x0000000, 0x000000},119      {0, 0x0000000, 0x0000000, 0x000000},120      {0, 0x0000000, 0x0000000, 0x000000},121      {0, 0x0000000, 0x0000000, 0x000000},122      {0, 0x0000000, 0x0000000, 0x000000},123      {0, 0x0000000, 0x0000000, 0x000000},124      {0, 0x0000000, 0x0000000, 0x000000},125      {0, 0x0000000, 0x0000000, 0x000000},126      {0, 0x0000000, 0x0000000, 0x000000},127      {1, 0x0af0000, 0x0af2000, 0x17a000} } },128    {{{0, 0x0b00000, 0x0b02000, 0x17c000},	/* 11: SQM3*/129      {0, 0x0000000, 0x0000000, 0x000000},130      {0, 0x0000000, 0x0000000, 0x000000},131      {0, 0x0000000, 0x0000000, 0x000000},132      {0, 0x0000000, 0x0000000, 0x000000},133      {0, 0x0000000, 0x0000000, 0x000000},134      {0, 0x0000000, 0x0000000, 0x000000},135      {0, 0x0000000, 0x0000000, 0x000000},136      {0, 0x0000000, 0x0000000, 0x000000},137      {0, 0x0000000, 0x0000000, 0x000000},138      {0, 0x0000000, 0x0000000, 0x000000},139      {0, 0x0000000, 0x0000000, 0x000000},140      {0, 0x0000000, 0x0000000, 0x000000},141      {0, 0x0000000, 0x0000000, 0x000000},142      {0, 0x0000000, 0x0000000, 0x000000},143      {1, 0x0bf0000, 0x0bf2000, 0x17e000} } },144	{{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */145	{{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */146	{{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */147	{{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */148	{{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */149	{{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */150	{{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */151	{{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */152	{{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */153	{{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */154	{{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */155	{{{0, 0,         0,         0} } },	/* 23: */156	{{{0, 0,         0,         0} } },	/* 24: */157	{{{0, 0,         0,         0} } },	/* 25: */158	{{{0, 0,         0,         0} } },	/* 26: */159	{{{0, 0,         0,         0} } },	/* 27: */160	{{{0, 0,         0,         0} } },	/* 28: */161	{{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */162    {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */163    {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */164	{{{0} } },				/* 32: PCI */165	{{{1, 0x2100000, 0x2102000, 0x120000},	/* 33: PCIE */166	  {1, 0x2110000, 0x2120000, 0x130000},167	  {1, 0x2120000, 0x2122000, 0x124000},168	  {1, 0x2130000, 0x2132000, 0x126000},169	  {1, 0x2140000, 0x2142000, 0x128000},170	  {1, 0x2150000, 0x2152000, 0x12a000},171	  {1, 0x2160000, 0x2170000, 0x110000},172	  {1, 0x2170000, 0x2172000, 0x12e000},173	  {0, 0x0000000, 0x0000000, 0x000000},174	  {0, 0x0000000, 0x0000000, 0x000000},175	  {0, 0x0000000, 0x0000000, 0x000000},176	  {0, 0x0000000, 0x0000000, 0x000000},177	  {0, 0x0000000, 0x0000000, 0x000000},178	  {0, 0x0000000, 0x0000000, 0x000000},179	  {0, 0x0000000, 0x0000000, 0x000000},180	  {0, 0x0000000, 0x0000000, 0x000000} } },181	{{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */182	{{{0} } },				/* 35: */183	{{{0} } },				/* 36: */184	{{{0} } },				/* 37: */185	{{{0} } },				/* 38: */186	{{{0} } },				/* 39: */187	{{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */188	{{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */189	{{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */190	{{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */191	{{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */192	{{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */193	{{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */194	{{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */195	{{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */196	{{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */197	{{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */198	{{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */199	{{{0} } },				/* 52: */200	{{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */201	{{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */202	{{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */203	{{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */204	{{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */205	{{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */206	{{{0} } },				/* 59: I2C0 */207	{{{0} } },				/* 60: I2C1 */208	{{{1, 0x3d00000, 0x3d04000, 0x1d8000} } },/* 61: LPC */209	{{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */210	{{{1, 0x3f00000, 0x3f01000, 0x168000} } }	/* 63: P2NR0 */211};212 213/*214 * top 12 bits of crb internal address (hub, agent)215 */216static unsigned crb_hub_agt[64] =217{218	0,219	NETXEN_HW_CRB_HUB_AGT_ADR_PS,220	NETXEN_HW_CRB_HUB_AGT_ADR_MN,221	NETXEN_HW_CRB_HUB_AGT_ADR_MS,222	0,223	NETXEN_HW_CRB_HUB_AGT_ADR_SRE,224	NETXEN_HW_CRB_HUB_AGT_ADR_NIU,225	NETXEN_HW_CRB_HUB_AGT_ADR_QMN,226	NETXEN_HW_CRB_HUB_AGT_ADR_SQN0,227	NETXEN_HW_CRB_HUB_AGT_ADR_SQN1,228	NETXEN_HW_CRB_HUB_AGT_ADR_SQN2,229	NETXEN_HW_CRB_HUB_AGT_ADR_SQN3,230	NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,231	NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,232	NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,233	NETXEN_HW_CRB_HUB_AGT_ADR_PGN4,234	NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,235	NETXEN_HW_CRB_HUB_AGT_ADR_PGN0,236	NETXEN_HW_CRB_HUB_AGT_ADR_PGN1,237	NETXEN_HW_CRB_HUB_AGT_ADR_PGN2,238	NETXEN_HW_CRB_HUB_AGT_ADR_PGN3,239	NETXEN_HW_CRB_HUB_AGT_ADR_PGND,240	NETXEN_HW_CRB_HUB_AGT_ADR_PGNI,241	NETXEN_HW_CRB_HUB_AGT_ADR_PGS0,242	NETXEN_HW_CRB_HUB_AGT_ADR_PGS1,243	NETXEN_HW_CRB_HUB_AGT_ADR_PGS2,244	NETXEN_HW_CRB_HUB_AGT_ADR_PGS3,245	0,246	NETXEN_HW_CRB_HUB_AGT_ADR_PGSI,247	NETXEN_HW_CRB_HUB_AGT_ADR_SN,248	0,249	NETXEN_HW_CRB_HUB_AGT_ADR_EG,250	0,251	NETXEN_HW_CRB_HUB_AGT_ADR_PS,252	NETXEN_HW_CRB_HUB_AGT_ADR_CAM,253	0,254	0,255	0,256	0,257	0,258	NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,259	0,260	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX1,261	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX2,262	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX3,263	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX4,264	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX5,265	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX6,266	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX7,267	NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,268	NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,269	NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,270	0,271	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX0,272	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX8,273	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX9,274	NETXEN_HW_CRB_HUB_AGT_ADR_OCM0,275	0,276	NETXEN_HW_CRB_HUB_AGT_ADR_SMB,277	NETXEN_HW_CRB_HUB_AGT_ADR_I2C0,278	NETXEN_HW_CRB_HUB_AGT_ADR_I2C1,279	0,280	NETXEN_HW_CRB_HUB_AGT_ADR_PGNC,281	0,282};283 284/*  PCI Windowing for DDR regions.  */285 286#define NETXEN_WINDOW_ONE 	0x2000000 /*CRB Window: bit 25 of CRB address */287 288#define NETXEN_PCIE_SEM_TIMEOUT	10000289 290static int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);291 292int293netxen_pcie_sem_lock(struct netxen_adapter *adapter, int sem, u32 id_reg)294{295	int done = 0, timeout = 0;296 297	while (!done) {298		done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM_LOCK(sem)));299		if (done == 1)300			break;301		if (++timeout >= NETXEN_PCIE_SEM_TIMEOUT)302			return -EIO;303		msleep(1);304	}305 306	if (id_reg)307		NXWR32(adapter, id_reg, adapter->portnum);308 309	return 0;310}311 312void313netxen_pcie_sem_unlock(struct netxen_adapter *adapter, int sem)314{315	NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM_UNLOCK(sem)));316}317 318static int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)319{320	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {321		NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);322		NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);323	}324 325	return 0;326}327 328/* Disable an XG interface */329static int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)330{331	__u32 mac_cfg;332	u32 port = adapter->physical_port;333 334	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))335		return 0;336 337	if (port >= NETXEN_NIU_MAX_XG_PORTS)338		return -EINVAL;339 340	mac_cfg = 0;341	if (NXWR32(adapter,342			NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg))343		return -EIO;344	return 0;345}346 347#define NETXEN_UNICAST_ADDR(port, index) \348	(NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))349#define NETXEN_MCAST_ADDR(port, index) \350	(NETXEN_MULTICAST_ADDR_BASE+(port*0x80)+(index*8))351#define MAC_HI(addr) \352	((addr[2] << 16) | (addr[1] << 8) | (addr[0]))353#define MAC_LO(addr) \354	((addr[5] << 16) | (addr[4] << 8) | (addr[3]))355 356static int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)357{358	u32 mac_cfg;359	u32 cnt = 0;360	__u32 reg = 0x0200;361	u32 port = adapter->physical_port;362	u16 board_type = adapter->ahw.board_type;363 364	if (port >= NETXEN_NIU_MAX_XG_PORTS)365		return -EINVAL;366 367	mac_cfg = NXRD32(adapter, NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port));368	mac_cfg &= ~0x4;369	NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg);370 371	if ((board_type == NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) ||372			(board_type == NETXEN_BRDTYPE_P2_SB31_10G_HMEZ))373		reg = (0x20 << port);374 375	NXWR32(adapter, NETXEN_NIU_FRAME_COUNT_SELECT, reg);376 377	mdelay(10);378 379	while (NXRD32(adapter, NETXEN_NIU_FRAME_COUNT) && ++cnt < 20)380		mdelay(10);381 382	if (cnt < 20) {383 384		reg = NXRD32(adapter,385			NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port));386 387		if (mode == NETXEN_NIU_PROMISC_MODE)388			reg = (reg | 0x2000UL);389		else390			reg = (reg & ~0x2000UL);391 392		if (mode == NETXEN_NIU_ALLMULTI_MODE)393			reg = (reg | 0x1000UL);394		else395			reg = (reg & ~0x1000UL);396 397		NXWR32(adapter,398			NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);399	}400 401	mac_cfg |= 0x4;402	NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg);403 404	return 0;405}406 407static int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)408{409	u32 mac_hi, mac_lo;410	u32 reg_hi, reg_lo;411 412	u8 phy = adapter->physical_port;413 414	if (phy >= NETXEN_NIU_MAX_XG_PORTS)415		return -EINVAL;416 417	mac_lo = ((u32)addr[0] << 16) | ((u32)addr[1] << 24);418	mac_hi = addr[2] | ((u32)addr[3] << 8) |419		((u32)addr[4] << 16) | ((u32)addr[5] << 24);420 421	reg_lo = NETXEN_NIU_XGE_STATION_ADDR_0_1 + (0x10000 * phy);422	reg_hi = NETXEN_NIU_XGE_STATION_ADDR_0_HI + (0x10000 * phy);423 424	/* write twice to flush */425	if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi))426		return -EIO;427	if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi))428		return -EIO;429 430	return 0;431}432 433static int434netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter)435{436	u32	val = 0;437	u16 port = adapter->physical_port;438	u8 *addr = adapter->mac_addr;439 440	if (adapter->mc_enabled)441		return 0;442 443	val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG);444	val |= (1UL << (28+port));445	NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val);446 447	/* add broadcast addr to filter */448	val = 0xffffff;449	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val);450	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val);451 452	/* add station addr to filter */453	val = MAC_HI(addr);454	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), val);455	val = MAC_LO(addr);456	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, val);457 458	adapter->mc_enabled = 1;459	return 0;460}461 462static int463netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter)464{465	u32	val = 0;466	u16 port = adapter->physical_port;467	u8 *addr = adapter->mac_addr;468 469	if (!adapter->mc_enabled)470		return 0;471 472	val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG);473	val &= ~(1UL << (28+port));474	NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val);475 476	val = MAC_HI(addr);477	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val);478	val = MAC_LO(addr);479	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val);480 481	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);482	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);483 484	adapter->mc_enabled = 0;485	return 0;486}487 488static int489netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,490		int index, u8 *addr)491{492	u32 hi = 0, lo = 0;493	u16 port = adapter->physical_port;494 495	lo = MAC_LO(addr);496	hi = MAC_HI(addr);497 498	NXWR32(adapter, NETXEN_MCAST_ADDR(port, index), hi);499	NXWR32(adapter, NETXEN_MCAST_ADDR(port, index)+4, lo);500 501	return 0;502}503 504static void netxen_p2_nic_set_multi(struct net_device *netdev)505{506	struct netxen_adapter *adapter = netdev_priv(netdev);507	struct netdev_hw_addr *ha;508	u8 null_addr[ETH_ALEN];509	int i;510 511	eth_zero_addr(null_addr);512 513	if (netdev->flags & IFF_PROMISC) {514 515		adapter->set_promisc(adapter,516				NETXEN_NIU_PROMISC_MODE);517 518		/* Full promiscuous mode */519		netxen_nic_disable_mcast_filter(adapter);520 521		return;522	}523 524	if (netdev_mc_empty(netdev)) {525		adapter->set_promisc(adapter,526				NETXEN_NIU_NON_PROMISC_MODE);527		netxen_nic_disable_mcast_filter(adapter);528		return;529	}530 531	adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE);532	if (netdev->flags & IFF_ALLMULTI ||533			netdev_mc_count(netdev) > adapter->max_mc_count) {534		netxen_nic_disable_mcast_filter(adapter);535		return;536	}537 538	netxen_nic_enable_mcast_filter(adapter);539 540	i = 0;541	netdev_for_each_mc_addr(ha, netdev)542		netxen_nic_set_mcast_addr(adapter, i++, ha->addr);543 544	/* Clear out remaining addresses */545	while (i < adapter->max_mc_count)546		netxen_nic_set_mcast_addr(adapter, i++, null_addr);547}548 549static int550netxen_send_cmd_descs(struct netxen_adapter *adapter,551		struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)552{553	u32 i, producer;554	struct netxen_cmd_buffer *pbuf;555	struct nx_host_tx_ring *tx_ring;556 557	i = 0;558 559	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)560		return -EIO;561 562	tx_ring = adapter->tx_ring;563	__netif_tx_lock_bh(tx_ring->txq);564 565	producer = tx_ring->producer;566 567	if (nr_desc >= netxen_tx_avail(tx_ring)) {568		netif_tx_stop_queue(tx_ring->txq);569		smp_mb();570		if (netxen_tx_avail(tx_ring) > nr_desc) {571			if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)572				netif_tx_wake_queue(tx_ring->txq);573		} else {574			__netif_tx_unlock_bh(tx_ring->txq);575			return -EBUSY;576		}577	}578 579	do {580		pbuf = &tx_ring->cmd_buf_arr[producer];581		pbuf->skb = NULL;582		pbuf->frag_count = 0;583 584		memcpy(&tx_ring->desc_head[producer],585			&cmd_desc_arr[i], sizeof(struct cmd_desc_type0));586 587		producer = get_next_index(producer, tx_ring->num_desc);588		i++;589 590	} while (i != nr_desc);591 592	tx_ring->producer = producer;593 594	netxen_nic_update_cmd_producer(adapter, tx_ring);595 596	__netif_tx_unlock_bh(tx_ring->txq);597 598	return 0;599}600 601static int602nx_p3_sre_macaddr_change(struct netxen_adapter *adapter, u8 *addr, unsigned op)603{604	nx_nic_req_t req;605	nx_mac_req_t *mac_req;606	u64 word;607 608	memset(&req, 0, sizeof(nx_nic_req_t));609	req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23);610 611	word = NX_MAC_EVENT | ((u64)adapter->portnum << 16);612	req.req_hdr = cpu_to_le64(word);613 614	mac_req = (nx_mac_req_t *)&req.words[0];615	mac_req->op = op;616	memcpy(mac_req->mac_addr, addr, ETH_ALEN);617 618	return netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);619}620 621static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,622		const u8 *addr, struct list_head *del_list)623{624	struct list_head *head;625	nx_mac_list_t *cur;626 627	/* look up if already exists */628	list_for_each(head, del_list) {629		cur = list_entry(head, nx_mac_list_t, list);630 631		if (ether_addr_equal(addr, cur->mac_addr)) {632			list_move_tail(head, &adapter->mac_list);633			return 0;634		}635	}636 637	cur = kzalloc(sizeof(nx_mac_list_t), GFP_ATOMIC);638	if (cur == NULL)639		return -ENOMEM;640 641	memcpy(cur->mac_addr, addr, ETH_ALEN);642	list_add_tail(&cur->list, &adapter->mac_list);643	return nx_p3_sre_macaddr_change(adapter,644				cur->mac_addr, NETXEN_MAC_ADD);645}646 647static void netxen_p3_nic_set_multi(struct net_device *netdev)648{649	struct netxen_adapter *adapter = netdev_priv(netdev);650	struct netdev_hw_addr *ha;651	static const u8 bcast_addr[ETH_ALEN] = {652		0xff, 0xff, 0xff, 0xff, 0xff, 0xff653	};654	u32 mode = VPORT_MISS_MODE_DROP;655	LIST_HEAD(del_list);656	struct list_head *head;657	nx_mac_list_t *cur;658 659	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)660		return;661 662	list_splice_tail_init(&adapter->mac_list, &del_list);663 664	nx_p3_nic_add_mac(adapter, adapter->mac_addr, &del_list);665	nx_p3_nic_add_mac(adapter, bcast_addr, &del_list);666 667	if (netdev->flags & IFF_PROMISC) {668		mode = VPORT_MISS_MODE_ACCEPT_ALL;669		goto send_fw_cmd;670	}671 672	if ((netdev->flags & IFF_ALLMULTI) ||673			(netdev_mc_count(netdev) > adapter->max_mc_count)) {674		mode = VPORT_MISS_MODE_ACCEPT_MULTI;675		goto send_fw_cmd;676	}677 678	if (!netdev_mc_empty(netdev)) {679		netdev_for_each_mc_addr(ha, netdev)680			nx_p3_nic_add_mac(adapter, ha->addr, &del_list);681	}682 683send_fw_cmd:684	adapter->set_promisc(adapter, mode);685	head = &del_list;686	while (!list_empty(head)) {687		cur = list_entry(head->next, nx_mac_list_t, list);688 689		nx_p3_sre_macaddr_change(adapter,690				cur->mac_addr, NETXEN_MAC_DEL);691		list_del(&cur->list);692		kfree(cur);693	}694}695 696static int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)697{698	nx_nic_req_t req;699	u64 word;700 701	memset(&req, 0, sizeof(nx_nic_req_t));702 703	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);704 705	word = NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE |706			((u64)adapter->portnum << 16);707	req.req_hdr = cpu_to_le64(word);708 709	req.words[0] = cpu_to_le64(mode);710 711	return netxen_send_cmd_descs(adapter,712				(struct cmd_desc_type0 *)&req, 1);713}714 715void netxen_p3_free_mac_list(struct netxen_adapter *adapter)716{717	nx_mac_list_t *cur;718	struct list_head *head = &adapter->mac_list;719 720	while (!list_empty(head)) {721		cur = list_entry(head->next, nx_mac_list_t, list);722		nx_p3_sre_macaddr_change(adapter,723				cur->mac_addr, NETXEN_MAC_DEL);724		list_del(&cur->list);725		kfree(cur);726	}727}728 729static int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)730{731	/* assuming caller has already copied new addr to netdev */732	netxen_p3_nic_set_multi(adapter->netdev);733	return 0;734}735 736#define	NETXEN_CONFIG_INTR_COALESCE	3737 738/*739 * Send the interrupt coalescing parameter set by ethtool to the card.740 */741int netxen_config_intr_coalesce(struct netxen_adapter *adapter)742{743	nx_nic_req_t req;744	u64 word[6];745	int rv, i;746 747	memset(&req, 0, sizeof(nx_nic_req_t));748	memset(word, 0, sizeof(word));749 750	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);751 752	word[0] = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16);753	req.req_hdr = cpu_to_le64(word[0]);754 755	memcpy(&word[0], &adapter->coal, sizeof(adapter->coal));756	for (i = 0; i < 6; i++)757		req.words[i] = cpu_to_le64(word[i]);758 759	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);760	if (rv != 0) {761		printk(KERN_ERR "ERROR. Could not send "762			"interrupt coalescing parameters\n");763	}764 765	return rv;766}767 768int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable)769{770	nx_nic_req_t req;771	u64 word;772	int rv = 0;773 774	if (!test_bit(__NX_FW_ATTACHED, &adapter->state))775		return 0;776 777	memset(&req, 0, sizeof(nx_nic_req_t));778 779	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);780 781	word = NX_NIC_H2C_OPCODE_CONFIG_HW_LRO | ((u64)adapter->portnum << 16);782	req.req_hdr = cpu_to_le64(word);783 784	req.words[0] = cpu_to_le64(enable);785 786	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);787	if (rv != 0) {788		printk(KERN_ERR "ERROR. Could not send "789			"configure hw lro request\n");790	}791 792	return rv;793}794 795int netxen_config_bridged_mode(struct netxen_adapter *adapter, int enable)796{797	nx_nic_req_t req;798	u64 word;799	int rv = 0;800 801	if (!!(adapter->flags & NETXEN_NIC_BRIDGE_ENABLED) == enable)802		return rv;803 804	memset(&req, 0, sizeof(nx_nic_req_t));805 806	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);807 808	word = NX_NIC_H2C_OPCODE_CONFIG_BRIDGING |809		((u64)adapter->portnum << 16);810	req.req_hdr = cpu_to_le64(word);811 812	req.words[0] = cpu_to_le64(enable);813 814	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);815	if (rv != 0) {816		printk(KERN_ERR "ERROR. Could not send "817				"configure bridge mode request\n");818	}819 820	adapter->flags ^= NETXEN_NIC_BRIDGE_ENABLED;821 822	return rv;823}824 825 826#define RSS_HASHTYPE_IP_TCP	0x3827 828int netxen_config_rss(struct netxen_adapter *adapter, int enable)829{830	nx_nic_req_t req;831	u64 word;832	int i, rv;833 834	static const u64 key[] = {835		0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,836		0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,837		0x255b0ec26d5a56daULL838	};839 840 841	memset(&req, 0, sizeof(nx_nic_req_t));842	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);843 844	word = NX_NIC_H2C_OPCODE_CONFIG_RSS | ((u64)adapter->portnum << 16);845	req.req_hdr = cpu_to_le64(word);846 847	/*848	 * RSS request:849	 * bits 3-0: hash_method850	 *      5-4: hash_type_ipv4851	 *	7-6: hash_type_ipv6852	 *	  8: enable853	 *        9: use indirection table854	 *    47-10: reserved855	 *    63-48: indirection table mask856	 */857	word =  ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) |858		((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) |859		((u64)(enable & 0x1) << 8) |860		((0x7ULL) << 48);861	req.words[0] = cpu_to_le64(word);862	for (i = 0; i < ARRAY_SIZE(key); i++)863		req.words[i+1] = cpu_to_le64(key[i]);864 865 866	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);867	if (rv != 0) {868		printk(KERN_ERR "%s: could not configure RSS\n",869				adapter->netdev->name);870	}871 872	return rv;873}874 875int netxen_config_ipaddr(struct netxen_adapter *adapter, __be32 ip, int cmd)876{877	nx_nic_req_t req;878	u64 word;879	int rv;880 881	memset(&req, 0, sizeof(nx_nic_req_t));882	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);883 884	word = NX_NIC_H2C_OPCODE_CONFIG_IPADDR | ((u64)adapter->portnum << 16);885	req.req_hdr = cpu_to_le64(word);886 887	req.words[0] = cpu_to_le64(cmd);888	memcpy(&req.words[1], &ip, sizeof(u32));889 890	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);891	if (rv != 0) {892		printk(KERN_ERR "%s: could not notify %s IP 0x%x request\n",893				adapter->netdev->name,894				(cmd == NX_IP_UP) ? "Add" : "Remove", ip);895	}896	return rv;897}898 899int netxen_linkevent_request(struct netxen_adapter *adapter, int enable)900{901	nx_nic_req_t req;902	u64 word;903	int rv;904 905	memset(&req, 0, sizeof(nx_nic_req_t));906	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);907 908	word = NX_NIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16);909	req.req_hdr = cpu_to_le64(word);910	req.words[0] = cpu_to_le64(enable | (enable << 8));911 912	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);913	if (rv != 0) {914		printk(KERN_ERR "%s: could not configure link notification\n",915				adapter->netdev->name);916	}917 918	return rv;919}920 921int netxen_send_lro_cleanup(struct netxen_adapter *adapter)922{923	nx_nic_req_t req;924	u64 word;925	int rv;926 927	if (!test_bit(__NX_FW_ATTACHED, &adapter->state))928		return 0;929 930	memset(&req, 0, sizeof(nx_nic_req_t));931	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);932 933	word = NX_NIC_H2C_OPCODE_LRO_REQUEST |934		((u64)adapter->portnum << 16) |935		((u64)NX_NIC_LRO_REQUEST_CLEANUP << 56) ;936 937	req.req_hdr = cpu_to_le64(word);938 939	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);940	if (rv != 0) {941		printk(KERN_ERR "%s: could not cleanup lro flows\n",942				adapter->netdev->name);943	}944	return rv;945}946 947/*948 * netxen_nic_change_mtu - Change the Maximum Transfer Unit949 * @returns 0 on success, negative on failure950 */951 952#define MTU_FUDGE_FACTOR	100953 954int netxen_nic_change_mtu(struct net_device *netdev, int mtu)955{956	struct netxen_adapter *adapter = netdev_priv(netdev);957	int rc = 0;958 959	if (adapter->set_mtu)960		rc = adapter->set_mtu(adapter, mtu);961 962	if (!rc)963		WRITE_ONCE(netdev->mtu, mtu);964 965	return rc;966}967 968static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,969				  int size, __le32 * buf)970{971	int i, v, addr;972	__le32 *ptr32;973	int ret;974 975	addr = base;976	ptr32 = buf;977	for (i = 0; i < size / sizeof(u32); i++) {978		ret = netxen_rom_fast_read(adapter, addr, &v);979		if (ret)980			return ret;981 982		*ptr32 = cpu_to_le32(v);983		ptr32++;984		addr += sizeof(u32);985	}986	if ((char *)buf + size > (char *)ptr32) {987		__le32 local;988		ret = netxen_rom_fast_read(adapter, addr, &v);989		if (ret)990			return ret;991		local = cpu_to_le32(v);992		memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32);993	}994 995	return 0;996}997 998int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 *mac)999{1000	__le32 *pmac = (__le32 *) mac;1001	u32 offset;1002 1003	offset = NX_FW_MAC_ADDR_OFFSET + (adapter->portnum * sizeof(u64));1004 1005	if (netxen_get_flash_block(adapter, offset, sizeof(u64), pmac) == -1)1006		return -1;1007 1008	if (*mac == ~0ULL) {1009 1010		offset = NX_OLD_MAC_ADDR_OFFSET +1011			(adapter->portnum * sizeof(u64));1012 1013		if (netxen_get_flash_block(adapter,1014					offset, sizeof(u64), pmac) == -1)1015			return -1;1016 1017		if (*mac == ~0ULL)1018			return -1;1019	}1020	return 0;1021}1022 1023int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, u64 *mac)1024{1025	uint32_t crbaddr, mac_hi, mac_lo;1026	int pci_func = adapter->ahw.pci_func;1027 1028	crbaddr = CRB_MAC_BLOCK_START +1029		(4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1));1030 1031	mac_lo = NXRD32(adapter, crbaddr);1032	mac_hi = NXRD32(adapter, crbaddr+4);1033 1034	if (pci_func & 1)1035		*mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16));1036	else1037		*mac = le64_to_cpu((u64)mac_lo | ((u64)mac_hi << 32));1038 1039	return 0;1040}1041 1042/*1043 * Changes the CRB window to the specified window.1044 */1045static void1046netxen_nic_pci_set_crbwindow_128M(struct netxen_adapter *adapter,1047		u32 window)1048{1049	void __iomem *offset;1050	int count = 10;1051	u8 func = adapter->ahw.pci_func;1052 1053	if (adapter->ahw.crb_win == window)1054		return;1055 1056	offset = PCI_OFFSET_SECOND_RANGE(adapter,1057			NETXEN_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(func)));1058 1059	writel(window, offset);1060	do {1061		if (window == readl(offset))1062			break;1063 1064		if (printk_ratelimit())1065			dev_warn(&adapter->pdev->dev,1066					"failed to set CRB window to %d\n",1067					(window == NETXEN_WINDOW_ONE));1068		udelay(1);1069 1070	} while (--count > 0);1071 1072	if (count > 0)1073		adapter->ahw.crb_win = window;1074}1075 1076/*1077 * Returns < 0 if off is not valid,1078 *	 1 if window access is needed. 'off' is set to offset from1079 *	   CRB space in 128M pci map1080 *	 0 if no window access is needed. 'off' is set to 2M addr1081 * In: 'off' is offset from base in 128M pci map1082 */1083static int1084netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter,1085		ulong off, void __iomem **addr)1086{1087	crb_128M_2M_sub_block_map_t *m;1088 1089 1090	if ((off >= NETXEN_CRB_MAX) || (off < NETXEN_PCI_CRBSPACE))1091		return -EINVAL;1092 1093	off -= NETXEN_PCI_CRBSPACE;1094 1095	/*1096	 * Try direct map1097	 */1098	m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)];1099 1100	if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) {1101		*addr = adapter->ahw.pci_base0 + m->start_2M +1102			(off - m->start_128M);1103		return 0;1104	}1105 1106	/*1107	 * Not in direct map, use crb window1108	 */1109	*addr = adapter->ahw.pci_base0 + CRB_INDIRECT_2M +1110		(off & MASK(16));1111	return 1;1112}1113 1114/*1115 * In: 'off' is offset from CRB space in 128M pci map1116 * Out: 'off' is 2M pci map addr1117 * side effect: lock crb window1118 */1119static void1120netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)1121{1122	u32 window;1123	void __iomem *addr = adapter->ahw.pci_base0 + CRB_WINDOW_2M;1124 1125	off -= NETXEN_PCI_CRBSPACE;1126 1127	window = CRB_HI(off);1128 1129	writel(window, addr);1130	if (readl(addr) != window) {1131		if (printk_ratelimit())1132			dev_warn(&adapter->pdev->dev,1133				"failed to set CRB window to %d off 0x%lx\n",1134				window, off);1135	}1136}1137 1138static void __iomem *1139netxen_nic_map_indirect_address_128M(struct netxen_adapter *adapter,1140		ulong win_off, void __iomem **mem_ptr)1141{1142	ulong off = win_off;1143	void __iomem *addr;1144	resource_size_t mem_base;1145 1146	if (ADDR_IN_WINDOW1(win_off))1147		off = NETXEN_CRB_NORMAL(win_off);1148 1149	addr = pci_base_offset(adapter, off);1150	if (addr)1151		return addr;1152 1153	if (adapter->ahw.pci_len0 == 0)1154		off -= NETXEN_PCI_CRBSPACE;1155 1156	mem_base = pci_resource_start(adapter->pdev, 0);1157	*mem_ptr = ioremap(mem_base + (off & PAGE_MASK), PAGE_SIZE);1158	if (*mem_ptr)1159		addr = *mem_ptr + (off & (PAGE_SIZE - 1));1160 1161	return addr;1162}1163 1164static int1165netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data)1166{1167	unsigned long flags;1168	void __iomem *addr, *mem_ptr = NULL;1169 1170	addr = netxen_nic_map_indirect_address_128M(adapter, off, &mem_ptr);1171	if (!addr)1172		return -EIO;1173 1174	if (ADDR_IN_WINDOW1(off)) { /* Window 1 */1175		netxen_nic_io_write_128M(adapter, addr, data);1176	} else {        /* Window 0 */1177		write_lock_irqsave(&adapter->ahw.crb_lock, flags);1178		netxen_nic_pci_set_crbwindow_128M(adapter, 0);1179		writel(data, addr);1180		netxen_nic_pci_set_crbwindow_128M(adapter,1181				NETXEN_WINDOW_ONE);1182		write_unlock_irqrestore(&adapter->ahw.crb_lock, flags);1183	}1184 1185	if (mem_ptr)1186		iounmap(mem_ptr);1187 1188	return 0;1189}1190 1191static u321192netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off)1193{1194	unsigned long flags;1195	void __iomem *addr, *mem_ptr = NULL;1196	u32 data;1197 1198	addr = netxen_nic_map_indirect_address_128M(adapter, off, &mem_ptr);1199	if (!addr)1200		return -EIO;1201 1202	if (ADDR_IN_WINDOW1(off)) { /* Window 1 */1203		data = netxen_nic_io_read_128M(adapter, addr);1204	} else {        /* Window 0 */1205		write_lock_irqsave(&adapter->ahw.crb_lock, flags);1206		netxen_nic_pci_set_crbwindow_128M(adapter, 0);1207		data = readl(addr);1208		netxen_nic_pci_set_crbwindow_128M(adapter,1209				NETXEN_WINDOW_ONE);1210		write_unlock_irqrestore(&adapter->ahw.crb_lock, flags);1211	}1212 1213	if (mem_ptr)1214		iounmap(mem_ptr);1215 1216	return data;1217}1218 1219static int1220netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data)1221{1222	unsigned long flags;1223	int rv;1224	void __iomem *addr = NULL;1225 1226	rv = netxen_nic_pci_get_crb_addr_2M(adapter, off, &addr);1227 1228	if (rv == 0) {1229		writel(data, addr);1230		return 0;1231	}1232 1233	if (rv > 0) {1234		/* indirect access */1235		write_lock_irqsave(&adapter->ahw.crb_lock, flags);1236		crb_win_lock(adapter);1237		netxen_nic_pci_set_crbwindow_2M(adapter, off);1238		writel(data, addr);1239		crb_win_unlock(adapter);1240		write_unlock_irqrestore(&adapter->ahw.crb_lock, flags);1241		return 0;1242	}1243 1244	dev_err(&adapter->pdev->dev,1245			"%s: invalid offset: 0x%016lx\n", __func__, off);1246	dump_stack();1247	return -EIO;1248}1249 1250static u321251netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off)1252{1253	unsigned long flags;1254	int rv;1255	u32 data;1256	void __iomem *addr = NULL;1257 1258	rv = netxen_nic_pci_get_crb_addr_2M(adapter, off, &addr);1259 1260	if (rv == 0)1261		return readl(addr);1262 1263	if (rv > 0) {1264		/* indirect access */1265		write_lock_irqsave(&adapter->ahw.crb_lock, flags);1266		crb_win_lock(adapter);1267		netxen_nic_pci_set_crbwindow_2M(adapter, off);1268		data = readl(addr);1269		crb_win_unlock(adapter);1270		write_unlock_irqrestore(&adapter->ahw.crb_lock, flags);1271		return data;1272	}1273 1274	dev_err(&adapter->pdev->dev,1275			"%s: invalid offset: 0x%016lx\n", __func__, off);1276	dump_stack();1277	return -1;1278}1279 1280/* window 1 registers only */1281static void netxen_nic_io_write_128M(struct netxen_adapter *adapter,1282		void __iomem *addr, u32 data)1283{1284	read_lock(&adapter->ahw.crb_lock);1285	writel(data, addr);1286	read_unlock(&adapter->ahw.crb_lock);1287}1288 1289static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter,1290		void __iomem *addr)1291{1292	u32 val;1293 1294	read_lock(&adapter->ahw.crb_lock);1295	val = readl(addr);1296	read_unlock(&adapter->ahw.crb_lock);1297 1298	return val;1299}1300 1301static void netxen_nic_io_write_2M(struct netxen_adapter *adapter,1302		void __iomem *addr, u32 data)1303{1304	writel(data, addr);1305}1306 1307static u32 netxen_nic_io_read_2M(struct netxen_adapter *adapter,1308		void __iomem *addr)1309{1310	return readl(addr);1311}1312 1313void __iomem *1314netxen_get_ioaddr(struct netxen_adapter *adapter, u32 offset)1315{1316	void __iomem *addr = NULL;1317 1318	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {1319		if ((offset < NETXEN_CRB_PCIX_HOST2) &&1320				(offset > NETXEN_CRB_PCIX_HOST))1321			addr = PCI_OFFSET_SECOND_RANGE(adapter, offset);1322		else1323			addr = NETXEN_CRB_NORMALIZE(adapter, offset);1324	} else {1325		WARN_ON(netxen_nic_pci_get_crb_addr_2M(adapter,1326					offset, &addr));1327	}1328 1329	return addr;1330}1331 1332static int1333netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter,1334		u64 addr, u32 *start)1335{1336	if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {1337		*start = (addr - NETXEN_ADDR_OCM0  + NETXEN_PCI_OCM0);1338		return 0;1339	} else if (ADDR_IN_RANGE(addr,1340				NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {1341		*start = (addr - NETXEN_ADDR_OCM1 + NETXEN_PCI_OCM1);1342		return 0;1343	}1344 1345	return -EIO;1346}1347 1348static int1349netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,1350		u64 addr, u32 *start)1351{1352	u32 window;1353 1354	window = OCM_WIN(addr);1355 1356	writel(window, adapter->ahw.ocm_win_crb);1357	/* read back to flush */1358	readl(adapter->ahw.ocm_win_crb);1359 1360	adapter->ahw.ocm_win = window;1361	*start = NETXEN_PCI_OCM0_2M + GET_MEM_OFFS_2M(addr);1362	return 0;1363}1364 1365static int1366netxen_nic_pci_mem_access_direct(struct netxen_adapter *adapter, u64 off,1367		u64 *data, int op)1368{1369	void __iomem *addr, *mem_ptr = NULL;1370	resource_size_t mem_base;1371	int ret;1372	u32 start;1373 1374	spin_lock(&adapter->ahw.mem_lock);1375 1376	ret = adapter->pci_set_window(adapter, off, &start);1377	if (ret != 0)1378		goto unlock;1379 1380	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {1381		addr = adapter->ahw.pci_base0 + start;1382	} else {1383		addr = pci_base_offset(adapter, start);1384		if (addr)1385			goto noremap;1386 1387		mem_base = pci_resource_start(adapter->pdev, 0) +1388					(start & PAGE_MASK);1389		mem_ptr = ioremap(mem_base, PAGE_SIZE);1390		if (mem_ptr == NULL) {1391			ret = -EIO;1392			goto unlock;1393		}1394 1395		addr = mem_ptr + (start & (PAGE_SIZE-1));1396	}1397noremap:1398	if (op == 0)	/* read */1399		*data = readq(addr);1400	else		/* write */1401		writeq(*data, addr);1402 1403unlock:1404	spin_unlock(&adapter->ahw.mem_lock);1405 1406	if (mem_ptr)1407		iounmap(mem_ptr);1408	return ret;1409}1410 1411void1412netxen_pci_camqm_read_2M(struct netxen_adapter *adapter, u64 off, u64 *data)1413{1414	void __iomem *addr = adapter->ahw.pci_base0 +1415		NETXEN_PCI_CAMQM_2M_BASE + (off - NETXEN_PCI_CAMQM);1416 1417	spin_lock(&adapter->ahw.mem_lock);1418	*data = readq(addr);1419	spin_unlock(&adapter->ahw.mem_lock);1420}1421 1422void1423netxen_pci_camqm_write_2M(struct netxen_adapter *adapter, u64 off, u64 data)1424{1425	void __iomem *addr = adapter->ahw.pci_base0 +1426		NETXEN_PCI_CAMQM_2M_BASE + (off - NETXEN_PCI_CAMQM);1427 1428	spin_lock(&adapter->ahw.mem_lock);1429	writeq(data, addr);1430	spin_unlock(&adapter->ahw.mem_lock);1431}1432 1433#define MAX_CTL_CHECK   10001434 1435static int1436netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,1437		u64 off, u64 data)1438{1439	int j, ret;1440	u32 temp, off_lo, off_hi, addr_hi, data_hi, data_lo;1441	void __iomem *mem_crb;1442 1443	/* Only 64-bit aligned access */1444	if (off & 7)1445		return -EIO;1446 1447	/* P2 has different SIU and MIU test agent base addr */1448	if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET,1449				NETXEN_ADDR_QDR_NET_MAX_P2)) {1450		mem_crb = pci_base_offset(adapter,1451				NETXEN_CRB_QDR_NET+SIU_TEST_AGT_BASE);1452		addr_hi = SIU_TEST_AGT_ADDR_HI;1453		data_lo = SIU_TEST_AGT_WRDATA_LO;1454		data_hi = SIU_TEST_AGT_WRDATA_HI;1455		off_lo = off & SIU_TEST_AGT_ADDR_MASK;1456		off_hi = SIU_TEST_AGT_UPPER_ADDR(off);1457		goto correct;1458	}1459 1460	if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {1461		mem_crb = pci_base_offset(adapter,1462				NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE);1463		addr_hi = MIU_TEST_AGT_ADDR_HI;1464		data_lo = MIU_TEST_AGT_WRDATA_LO;1465		data_hi = MIU_TEST_AGT_WRDATA_HI;1466		off_lo = off & MIU_TEST_AGT_ADDR_MASK;1467		off_hi = 0;1468		goto correct;1469	}1470 1471	if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX) ||1472		ADDR_IN_RANGE(off, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {1473		if (adapter->ahw.pci_len0 != 0) {1474			return netxen_nic_pci_mem_access_direct(adapter,1475					off, &data, 1);1476		}1477	}1478 1479	return -EIO;1480 1481correct:1482	spin_lock(&adapter->ahw.mem_lock);1483	netxen_nic_pci_set_crbwindow_128M(adapter, 0);1484 1485	writel(off_lo, (mem_crb + MIU_TEST_AGT_ADDR_LO));1486	writel(off_hi, (mem_crb + addr_hi));1487	writel(data & 0xffffffff, (mem_crb + data_lo));1488	writel((data >> 32) & 0xffffffff, (mem_crb + data_hi));1489	writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL));1490	writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE),1491			(mem_crb + TEST_AGT_CTRL));1492 1493	for (j = 0; j < MAX_CTL_CHECK; j++) {1494		temp = readl((mem_crb + TEST_AGT_CTRL));1495		if ((temp & TA_CTL_BUSY) == 0)1496			break;1497	}1498 1499	if (j >= MAX_CTL_CHECK) {1500		if (printk_ratelimit())1501			dev_err(&adapter->pdev->dev,1502					"failed to write through agent\n");1503		ret = -EIO;1504	} else1505		ret = 0;1506 1507	netxen_nic_pci_set_crbwindow_128M(adapter, NETXEN_WINDOW_ONE);1508	spin_unlock(&adapter->ahw.mem_lock);1509	return ret;1510}1511 1512static int1513netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,1514		u64 off, u64 *data)1515{1516	int j, ret;1517	u32 temp, off_lo, off_hi, addr_hi, data_hi, data_lo;1518	u64 val;1519	void __iomem *mem_crb;1520 1521	/* Only 64-bit aligned access */1522	if (off & 7)1523		return -EIO;1524 1525	/* P2 has different SIU and MIU test agent base addr */1526	if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET,1527				NETXEN_ADDR_QDR_NET_MAX_P2)) {1528		mem_crb = pci_base_offset(adapter,1529				NETXEN_CRB_QDR_NET+SIU_TEST_AGT_BASE);1530		addr_hi = SIU_TEST_AGT_ADDR_HI;1531		data_lo = SIU_TEST_AGT_RDDATA_LO;1532		data_hi = SIU_TEST_AGT_RDDATA_HI;1533		off_lo = off & SIU_TEST_AGT_ADDR_MASK;1534		off_hi = SIU_TEST_AGT_UPPER_ADDR(off);1535		goto correct;1536	}1537 1538	if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {1539		mem_crb = pci_base_offset(adapter,1540				NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE);1541		addr_hi = MIU_TEST_AGT_ADDR_HI;1542		data_lo = MIU_TEST_AGT_RDDATA_LO;1543		data_hi = MIU_TEST_AGT_RDDATA_HI;1544		off_lo = off & MIU_TEST_AGT_ADDR_MASK;1545		off_hi = 0;1546		goto correct;1547	}1548 1549	if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX) ||1550		ADDR_IN_RANGE(off, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {1551		if (adapter->ahw.pci_len0 != 0) {1552			return netxen_nic_pci_mem_access_direct(adapter,1553					off, data, 0);1554		}1555	}1556 1557	return -EIO;1558 1559correct:1560	spin_lock(&adapter->ahw.mem_lock);1561	netxen_nic_pci_set_crbwindow_128M(adapter, 0);1562 1563	writel(off_lo, (mem_crb + MIU_TEST_AGT_ADDR_LO));1564	writel(off_hi, (mem_crb + addr_hi));1565	writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL));1566	writel((TA_CTL_START|TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL));1567 1568	for (j = 0; j < MAX_CTL_CHECK; j++) {1569		temp = readl(mem_crb + TEST_AGT_CTRL);1570		if ((temp & TA_CTL_BUSY) == 0)1571			break;1572	}1573 1574	if (j >= MAX_CTL_CHECK) {1575		if (printk_ratelimit())1576			dev_err(&adapter->pdev->dev,1577					"failed to read through agent\n");1578		ret = -EIO;1579	} else {1580 1581		temp = readl(mem_crb + data_hi);1582		val = ((u64)temp << 32);1583		val |= readl(mem_crb + data_lo);1584		*data = val;1585		ret = 0;1586	}1587 1588	netxen_nic_pci_set_crbwindow_128M(adapter, NETXEN_WINDOW_ONE);1589	spin_unlock(&adapter->ahw.mem_lock);1590 1591	return ret;1592}1593 1594static int1595netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,1596		u64 off, u64 data)1597{1598	int j, ret;1599	u32 temp, off8;1600	void __iomem *mem_crb;1601 1602	/* Only 64-bit aligned access */1603	if (off & 7)1604		return -EIO;1605 1606	/* P3 onward, test agent base for MIU and SIU is same */1607	if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET,1608				NETXEN_ADDR_QDR_NET_MAX_P3)) {1609		mem_crb = netxen_get_ioaddr(adapter,1610				NETXEN_CRB_QDR_NET+MIU_TEST_AGT_BASE);1611		goto correct;1612	}1613 1614	if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {1615		mem_crb = netxen_get_ioaddr(adapter,1616				NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE);1617		goto correct;1618	}1619 1620	if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX))1621		return netxen_nic_pci_mem_access_direct(adapter, off, &data, 1);1622 1623	return -EIO;1624 1625correct:1626	off8 = off & 0xfffffff8;1627 1628	spin_lock(&adapter->ahw.mem_lock);1629 1630	writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));1631	writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));1632 1633	writel(data & 0xffffffff,1634			mem_crb + MIU_TEST_AGT_WRDATA_LO);1635	writel((data >> 32) & 0xffffffff,1636			mem_crb + MIU_TEST_AGT_WRDATA_HI);1637 1638	writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL));1639	writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE),1640			(mem_crb + TEST_AGT_CTRL));1641 1642	for (j = 0; j < MAX_CTL_CHECK; j++) {1643		temp = readl(mem_crb + TEST_AGT_CTRL);1644		if ((temp & TA_CTL_BUSY) == 0)1645			break;1646	}1647 1648	if (j >= MAX_CTL_CHECK) {1649		if (printk_ratelimit())1650			dev_err(&adapter->pdev->dev,1651					"failed to write through agent\n");1652		ret = -EIO;1653	} else1654		ret = 0;1655 1656	spin_unlock(&adapter->ahw.mem_lock);1657 1658	return ret;1659}1660 1661static int1662netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,1663		u64 off, u64 *data)1664{1665	int j, ret;1666	u32 temp, off8;1667	u64 val;1668	void __iomem *mem_crb;1669 1670	/* Only 64-bit aligned access */1671	if (off & 7)1672		return -EIO;1673 1674	/* P3 onward, test agent base for MIU and SIU is same */1675	if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET,1676				NETXEN_ADDR_QDR_NET_MAX_P3)) {1677		mem_crb = netxen_get_ioaddr(adapter,1678				NETXEN_CRB_QDR_NET+MIU_TEST_AGT_BASE);1679		goto correct;1680	}1681 1682	if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {1683		mem_crb = netxen_get_ioaddr(adapter,1684				NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE);1685		goto correct;1686	}1687 1688	if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {1689		return netxen_nic_pci_mem_access_direct(adapter,1690				off, data, 0);1691	}1692 1693	return -EIO;1694 1695correct:1696	off8 = off & 0xfffffff8;1697 1698	spin_lock(&adapter->ahw.mem_lock);1699 1700	writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));1701	writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));1702	writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL));1703	writel((TA_CTL_START | TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL));1704 1705	for (j = 0; j < MAX_CTL_CHECK; j++) {1706		temp = readl(mem_crb + TEST_AGT_CTRL);1707		if ((temp & TA_CTL_BUSY) == 0)1708			break;1709	}1710 1711	if (j >= MAX_CTL_CHECK) {1712		if (printk_ratelimit())1713			dev_err(&adapter->pdev->dev,1714					"failed to read through agent\n");1715		ret = -EIO;1716	} else {1717		val = (u64)(readl(mem_crb + MIU_TEST_AGT_RDDATA_HI)) << 32;1718		val |= readl(mem_crb + MIU_TEST_AGT_RDDATA_LO);1719		*data = val;1720		ret = 0;1721	}1722 1723	spin_unlock(&adapter->ahw.mem_lock);1724 1725	return ret;1726}1727 1728void1729netxen_setup_hwops(struct netxen_adapter *adapter)1730{1731	adapter->init_port = netxen_niu_xg_init_port;1732	adapter->stop_port = netxen_niu_disable_xg_port;1733 1734	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {1735		adapter->crb_read = netxen_nic_hw_read_wx_128M,1736		adapter->crb_write = netxen_nic_hw_write_wx_128M,1737		adapter->pci_set_window = netxen_nic_pci_set_window_128M,1738		adapter->pci_mem_read = netxen_nic_pci_mem_read_128M,1739		adapter->pci_mem_write = netxen_nic_pci_mem_write_128M,1740		adapter->io_read = netxen_nic_io_read_128M,1741		adapter->io_write = netxen_nic_io_write_128M,1742 1743		adapter->macaddr_set = netxen_p2_nic_set_mac_addr;1744		adapter->set_multi = netxen_p2_nic_set_multi;1745		adapter->set_mtu = netxen_nic_set_mtu_xgb;1746		adapter->set_promisc = netxen_p2_nic_set_promisc;1747 1748	} else {1749		adapter->crb_read = netxen_nic_hw_read_wx_2M,1750		adapter->crb_write = netxen_nic_hw_write_wx_2M,1751		adapter->pci_set_window = netxen_nic_pci_set_window_2M,1752		adapter->pci_mem_read = netxen_nic_pci_mem_read_2M,1753		adapter->pci_mem_write = netxen_nic_pci_mem_write_2M,1754		adapter->io_read = netxen_nic_io_read_2M,1755		adapter->io_write = netxen_nic_io_write_2M,1756 1757		adapter->set_mtu = nx_fw_cmd_set_mtu;1758		adapter->set_promisc = netxen_p3_nic_set_promisc;1759		adapter->macaddr_set = netxen_p3_nic_set_mac_addr;1760		adapter->set_multi = netxen_p3_nic_set_multi;1761 1762		adapter->phy_read = nx_fw_cmd_query_phy;1763		adapter->phy_write = nx_fw_cmd_set_phy;1764	}1765}1766 1767int netxen_nic_get_board_info(struct netxen_adapter *adapter)1768{1769	int offset, board_type, magic;1770	struct pci_dev *pdev = adapter->pdev;1771 1772	offset = NX_FW_MAGIC_OFFSET;1773	if (netxen_rom_fast_read(adapter, offset, &magic))1774		return -EIO;1775 1776	if (magic != NETXEN_BDINFO_MAGIC) {1777		dev_err(&pdev->dev, "invalid board config, magic=%08x\n",1778			magic);1779		return -EIO;1780	}1781 1782	offset = NX_BRDTYPE_OFFSET;1783	if (netxen_rom_fast_read(adapter, offset, &board_type))1784		return -EIO;1785 1786	if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) {1787		u32 gpio = NXRD32(adapter, NETXEN_ROMUSB_GLB_PAD_GPIO_I);1788		if ((gpio & 0x8000) == 0)1789			board_type = NETXEN_BRDTYPE_P3_10G_TP;1790	}1791 1792	adapter->ahw.board_type = board_type;1793 1794	switch (board_type) {1795	case NETXEN_BRDTYPE_P2_SB35_4G:1796		adapter->ahw.port_type = NETXEN_NIC_GBE;1797		break;1798	case NETXEN_BRDTYPE_P2_SB31_10G:1799	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:1800	case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:1801	case NETXEN_BRDTYPE_P2_SB31_10G_CX4:1802	case NETXEN_BRDTYPE_P3_HMEZ:1803	case NETXEN_BRDTYPE_P3_XG_LOM:1804	case NETXEN_BRDTYPE_P3_10G_CX4:1805	case NETXEN_BRDTYPE_P3_10G_CX4_LP:1806	case NETXEN_BRDTYPE_P3_IMEZ:1807	case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:1808	case NETXEN_BRDTYPE_P3_10G_SFP_CT:1809	case NETXEN_BRDTYPE_P3_10G_SFP_QT:1810	case NETXEN_BRDTYPE_P3_10G_XFP:1811	case NETXEN_BRDTYPE_P3_10000_BASE_T:1812		adapter->ahw.port_type = NETXEN_NIC_XGBE;1813		break;1814	case NETXEN_BRDTYPE_P1_BD:1815	case NETXEN_BRDTYPE_P1_SB:1816	case NETXEN_BRDTYPE_P1_SMAX:1817	case NETXEN_BRDTYPE_P1_SOCK:1818	case NETXEN_BRDTYPE_P3_REF_QG:1819	case NETXEN_BRDTYPE_P3_4_GB:1820	case NETXEN_BRDTYPE_P3_4_GB_MM:1821		adapter->ahw.port_type = NETXEN_NIC_GBE;1822		break;1823	case NETXEN_BRDTYPE_P3_10G_TP:1824		adapter->ahw.port_type = (adapter->portnum < 2) ?1825			NETXEN_NIC_XGBE : NETXEN_NIC_GBE;1826		break;1827	default:1828		dev_err(&pdev->dev, "unknown board type %x\n", board_type);1829		adapter->ahw.port_type = NETXEN_NIC_XGBE;1830		break;1831	}1832 1833	return 0;1834}1835 1836/* NIU access sections */1837static int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)1838{1839	new_mtu += MTU_FUDGE_FACTOR;1840	if (adapter->physical_port == 0)1841		NXWR32(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu);1842	else1843		NXWR32(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE, new_mtu);1844	return 0;1845}1846 1847void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)1848{1849	__u32 status;1850	__u32 autoneg;1851	__u32 port_mode;1852 1853	if (!netif_carrier_ok(adapter->netdev)) {1854		adapter->link_speed   = 0;1855		adapter->link_duplex  = -1;1856		adapter->link_autoneg = AUTONEG_ENABLE;1857		return;1858	}1859 1860	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {1861		port_mode = NXRD32(adapter, NETXEN_PORT_MODE_ADDR);1862		if (port_mode == NETXEN_PORT_MODE_802_3_AP) {1863			adapter->link_speed   = SPEED_1000;1864			adapter->link_duplex  = DUPLEX_FULL;1865			adapter->link_autoneg = AUTONEG_DISABLE;1866			return;1867		}1868 1869		if (adapter->phy_read &&1870		    adapter->phy_read(adapter,1871				      NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,1872				      &status) == 0) {1873			if (netxen_get_phy_link(status)) {1874				switch (netxen_get_phy_speed(status)) {1875				case 0:1876					adapter->link_speed = SPEED_10;1877					break;1878				case 1:1879					adapter->link_speed = SPEED_100;1880					break;1881				case 2:1882					adapter->link_speed = SPEED_1000;1883					break;1884				default:1885					adapter->link_speed = 0;1886					break;1887				}1888				switch (netxen_get_phy_duplex(status)) {1889				case 0:1890					adapter->link_duplex = DUPLEX_HALF;1891					break;1892				case 1:1893					adapter->link_duplex = DUPLEX_FULL;1894					break;1895				default:1896					adapter->link_duplex = -1;1897					break;1898				}1899				if (adapter->phy_read &&1900				    adapter->phy_read(adapter,1901						      NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,1902						      &autoneg) == 0)1903					adapter->link_autoneg = autoneg;1904			} else1905				goto link_down;1906		} else {1907		      link_down:1908			adapter->link_speed = 0;1909			adapter->link_duplex = -1;1910		}1911	}1912}1913 1914int1915netxen_nic_wol_supported(struct netxen_adapter *adapter)1916{1917	u32 wol_cfg;1918 1919	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))1920		return 0;1921 1922	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);1923	if (wol_cfg & (1UL << adapter->portnum)) {1924		wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);1925		if (wol_cfg & (1 << adapter->portnum))1926			return 1;1927	}1928 1929	return 0;1930}1931 1932static u32 netxen_md_cntrl(struct netxen_adapter *adapter,1933			struct netxen_minidump_template_hdr *template_hdr,1934			struct netxen_minidump_entry_crb *crtEntry)1935{1936	int loop_cnt, i, rv = 0, timeout_flag;1937	u32 op_count, stride;1938	u32 opcode, read_value, addr;1939	unsigned long timeout, timeout_jiffies;1940	addr = crtEntry->addr;1941	op_count = crtEntry->op_count;1942	stride = crtEntry->addr_stride;1943 1944	for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {1945		for (i = 0; i < sizeof(crtEntry->opcode) * 8; i++) {1946			opcode = (crtEntry->opcode & (0x1 << i));1947			if (opcode) {1948				switch (opcode) {1949				case NX_DUMP_WCRB:1950					NX_WR_DUMP_REG(addr,1951						adapter->ahw.pci_base0,1952							crtEntry->value_1);1953					break;1954				case NX_DUMP_RWCRB:1955					NX_RD_DUMP_REG(addr,1956						adapter->ahw.pci_base0,1957								&read_value);1958					NX_WR_DUMP_REG(addr,1959						adapter->ahw.pci_base0,1960								read_value);1961					break;1962				case NX_DUMP_ANDCRB:1963					NX_RD_DUMP_REG(addr,1964						adapter->ahw.pci_base0,1965								&read_value);1966					read_value &= crtEntry->value_2;1967					NX_WR_DUMP_REG(addr,1968						adapter->ahw.pci_base0,1969								read_value);1970					break;1971				case NX_DUMP_ORCRB:1972					NX_RD_DUMP_REG(addr,1973						adapter->ahw.pci_base0,1974								&read_value);1975					read_value |= crtEntry->value_3;1976					NX_WR_DUMP_REG(addr,1977						adapter->ahw.pci_base0,1978								read_value);1979					break;1980				case NX_DUMP_POLLCRB:1981					timeout = crtEntry->poll_timeout;1982					NX_RD_DUMP_REG(addr,1983						adapter->ahw.pci_base0,1984								&read_value);1985					timeout_jiffies =1986					msecs_to_jiffies(timeout) + jiffies;1987					for (timeout_flag = 0;1988						!timeout_flag1989					&& ((read_value & crtEntry->value_2)1990					!= crtEntry->value_1);) {1991						if (time_after(jiffies,1992							timeout_jiffies))1993							timeout_flag = 1;1994					NX_RD_DUMP_REG(addr,1995							adapter->ahw.pci_base0,1996								&read_value);1997					}1998 1999					if (timeout_flag) {2000						dev_err(&adapter->pdev->dev, "%s : "2001							"Timeout in poll_crb control operation.\n"2002								, __func__);2003						return -1;2004					}2005					break;2006				case NX_DUMP_RD_SAVE:2007					/* Decide which address to use */2008					if (crtEntry->state_index_a)2009						addr =2010						template_hdr->saved_state_array2011						[crtEntry->state_index_a];2012					NX_RD_DUMP_REG(addr,2013						adapter->ahw.pci_base0,2014								&read_value);2015					template_hdr->saved_state_array2016					[crtEntry->state_index_v]2017						= read_value;2018					break;2019				case NX_DUMP_WRT_SAVED:2020					/* Decide which value to use */2021					if (crtEntry->state_index_v)2022						read_value =2023						template_hdr->saved_state_array2024						[crtEntry->state_index_v];2025					else2026						read_value = crtEntry->value_1;2027 2028					/* Decide which address to use */2029					if (crtEntry->state_index_a)2030						addr =2031						template_hdr->saved_state_array2032						[crtEntry->state_index_a];2033 2034					NX_WR_DUMP_REG(addr,2035						adapter->ahw.pci_base0,2036								read_value);2037					break;2038				case NX_DUMP_MOD_SAVE_ST:2039					read_value =2040					template_hdr->saved_state_array2041						[crtEntry->state_index_v];2042					read_value <<= crtEntry->shl;2043					read_value >>= crtEntry->shr;2044					if (crtEntry->value_2)2045						read_value &=2046						crtEntry->value_2;2047					read_value |= crtEntry->value_3;2048					read_value += crtEntry->value_1;2049					/* Write value back to state area.*/2050					template_hdr->saved_state_array2051						[crtEntry->state_index_v]2052							= read_value;2053					break;2054				default:2055					rv = 1;2056					break;2057				}2058			}2059		}2060		addr = addr + stride;2061	}2062	return rv;2063}2064 2065/* Read memory or MN */2066static u322067netxen_md_rdmem(struct netxen_adapter *adapter,2068		struct netxen_minidump_entry_rdmem2069			*memEntry, u64 *data_buff)2070{2071	u64 addr, value = 0;2072	int i = 0, loop_cnt;2073 2074	addr = (u64)memEntry->read_addr;2075	loop_cnt = memEntry->read_data_size;    /* This is size in bytes */2076	loop_cnt /= sizeof(value);2077 2078	for (i = 0; i < loop_cnt; i++) {2079		if (netxen_nic_pci_mem_read_2M(adapter, addr, &value))2080			goto out;2081		*data_buff++ = value;2082		addr += sizeof(value);2083	}2084out:2085	return i * sizeof(value);2086}2087 2088/* Read CRB operation */2089static u32 netxen_md_rd_crb(struct netxen_adapter *adapter,2090			struct netxen_minidump_entry_crb2091				*crbEntry, u32 *data_buff)2092{2093	int loop_cnt;2094	u32 op_count, addr, stride, value;2095 2096	addr = crbEntry->addr;2097	op_count = crbEntry->op_count;2098	stride = crbEntry->addr_stride;2099 2100	for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {2101		NX_RD_DUMP_REG(addr, adapter->ahw.pci_base0, &value);2102		*data_buff++ = addr;2103		*data_buff++ = value;2104		addr = addr + stride;2105	}2106	return loop_cnt * (2 * sizeof(u32));2107}2108 2109/* Read ROM */2110static u322111netxen_md_rdrom(struct netxen_adapter *adapter,2112			struct netxen_minidump_entry_rdrom2113				*romEntry, __le32 *data_buff)2114{2115	int i, count = 0;2116	u32 size, lck_val;2117	u32 val;2118	u32 fl_addr, waddr, raddr;2119	fl_addr = romEntry->read_addr;2120	size = romEntry->read_data_size/4;2121lock_try:2122	lck_val = readl((void __iomem *)(adapter->ahw.pci_base0 +2123							NX_FLASH_SEM2_LK));2124	if (!lck_val && count < MAX_CTL_CHECK) {2125		msleep(20);2126		count++;2127		goto lock_try;2128	}2129	writel(adapter->ahw.pci_func, (void __iomem *)(adapter->ahw.pci_base0 +2130							NX_FLASH_LOCK_ID));2131	for (i = 0; i < size; i++) {2132		waddr = fl_addr & 0xFFFF0000;2133		NX_WR_DUMP_REG(FLASH_ROM_WINDOW, adapter->ahw.pci_base0, waddr);2134		raddr = FLASH_ROM_DATA + (fl_addr & 0x0000FFFF);2135		NX_RD_DUMP_REG(raddr, adapter->ahw.pci_base0, &val);2136		*data_buff++ = cpu_to_le32(val);2137		fl_addr += sizeof(val);2138	}2139	readl((void __iomem *)(adapter->ahw.pci_base0 + NX_FLASH_SEM2_ULK));2140	return romEntry->read_data_size;2141}2142 2143/* Handle L2 Cache */2144static u322145netxen_md_L2Cache(struct netxen_adapter *adapter,2146				struct netxen_minidump_entry_cache2147					*cacheEntry, u32 *data_buff)2148{2149	int loop_cnt, i, k, timeout_flag = 0;2150	u32 addr, read_addr, read_value, cntrl_addr, tag_reg_addr;2151	u32 tag_value, read_cnt;2152	u8 cntl_value_w, cntl_value_r;2153	unsigned long timeout, timeout_jiffies;2154 2155	loop_cnt = cacheEntry->op_count;2156	read_addr = cacheEntry->read_addr;2157	cntrl_addr = cacheEntry->control_addr;2158	cntl_value_w = (u32) cacheEntry->write_value;2159	tag_reg_addr = cacheEntry->tag_reg_addr;2160	tag_value = cacheEntry->init_tag_value;2161	read_cnt = cacheEntry->read_addr_cnt;2162 2163	for (i = 0; i < loop_cnt; i++) {2164		NX_WR_DUMP_REG(tag_reg_addr, adapter->ahw.pci_base0, tag_value);2165		if (cntl_value_w)2166			NX_WR_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0,2167					(u32)cntl_value_w);2168		if (cacheEntry->poll_mask) {2169			timeout = cacheEntry->poll_wait;2170			NX_RD_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0,2171							&cntl_value_r);2172			timeout_jiffies = msecs_to_jiffies(timeout) + jiffies;2173			for (timeout_flag = 0; !timeout_flag &&2174			((cntl_value_r & cacheEntry->poll_mask) != 0);) {2175				if (time_after(jiffies, timeout_jiffies))2176					timeout_flag = 1;2177				NX_RD_DUMP_REG(cntrl_addr,2178					adapter->ahw.pci_base0,2179							&cntl_value_r);2180			}2181			if (timeout_flag) {2182				dev_err(&adapter->pdev->dev,2183						"Timeout in processing L2 Tag poll.\n");2184				return -1;2185			}2186		}2187		addr = read_addr;2188		for (k = 0; k < read_cnt; k++) {2189			NX_RD_DUMP_REG(addr, adapter->ahw.pci_base0,2190					&read_value);2191			*data_buff++ = read_value;2192			addr += cacheEntry->read_addr_stride;2193		}2194		tag_value += cacheEntry->tag_value_stride;2195	}2196	return read_cnt * loop_cnt * sizeof(read_value);2197}2198 2199 2200/* Handle L1 Cache */2201static u32 netxen_md_L1Cache(struct netxen_adapter *adapter,2202				struct netxen_minidump_entry_cache2203					*cacheEntry, u32 *data_buff)2204{2205	int i, k, loop_cnt;2206	u32 addr, read_addr, read_value, cntrl_addr, tag_reg_addr;2207	u32 tag_value, read_cnt;2208	u8 cntl_value_w;2209 2210	loop_cnt = cacheEntry->op_count;2211	read_addr = cacheEntry->read_addr;2212	cntrl_addr = cacheEntry->control_addr;2213	cntl_value_w = (u32) cacheEntry->write_value;2214	tag_reg_addr = cacheEntry->tag_reg_addr;2215	tag_value = cacheEntry->init_tag_value;2216	read_cnt = cacheEntry->read_addr_cnt;2217 2218	for (i = 0; i < loop_cnt; i++) {2219		NX_WR_DUMP_REG(tag_reg_addr, adapter->ahw.pci_base0, tag_value);2220		NX_WR_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0,2221						(u32) cntl_value_w);2222		addr = read_addr;2223		for (k = 0; k < read_cnt; k++) {2224			NX_RD_DUMP_REG(addr,2225				adapter->ahw.pci_base0,2226						&read_value);2227			*data_buff++ = read_value;2228			addr += cacheEntry->read_addr_stride;2229		}2230		tag_value += cacheEntry->tag_value_stride;2231	}2232	return read_cnt * loop_cnt * sizeof(read_value);2233}2234 2235/* Reading OCM memory */2236static u322237netxen_md_rdocm(struct netxen_adapter *adapter,2238				struct netxen_minidump_entry_rdocm2239					*ocmEntry, u32 *data_buff)2240{2241	int i, loop_cnt;2242	u32 value;2243	void __iomem *addr;2244	addr = (ocmEntry->read_addr + adapter->ahw.pci_base0);2245	loop_cnt = ocmEntry->op_count;2246 2247	for (i = 0; i < loop_cnt; i++) {2248		value = readl(addr);2249		*data_buff++ = value;2250		addr += ocmEntry->read_addr_stride;2251	}2252	return i * sizeof(u32);2253}2254 2255/* Read MUX data */2256static u322257netxen_md_rdmux(struct netxen_adapter *adapter, struct netxen_minidump_entry_mux2258					*muxEntry, u32 *data_buff)2259{2260	int loop_cnt = 0;2261	u32 read_addr, read_value, select_addr, sel_value;2262 2263	read_addr = muxEntry->read_addr;2264	sel_value = muxEntry->select_value;2265	select_addr = muxEntry->select_addr;2266 2267	for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {2268		NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, sel_value);2269		NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0, &read_value);2270		*data_buff++ = sel_value;2271		*data_buff++ = read_value;2272		sel_value += muxEntry->select_value_stride;2273	}2274	return loop_cnt * (2 * sizeof(u32));2275}2276 2277/* Handling Queue State Reads */2278static u322279netxen_md_rdqueue(struct netxen_adapter *adapter,2280				struct netxen_minidump_entry_queue2281					*queueEntry, u32 *data_buff)2282{2283	int loop_cnt, k;2284	u32 queue_id, read_addr, read_value, read_stride, select_addr, read_cnt;2285 2286	read_cnt = queueEntry->read_addr_cnt;2287	read_stride = queueEntry->read_addr_stride;2288	select_addr = queueEntry->select_addr;2289 2290	for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;2291				 loop_cnt++) {2292		NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, queue_id);2293		read_addr = queueEntry->read_addr;2294		for (k = 0; k < read_cnt; k++) {2295			NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0,2296							&read_value);2297			*data_buff++ = read_value;2298			read_addr += read_stride;2299		}2300		queue_id += queueEntry->queue_id_stride;2301	}2302	return loop_cnt * (read_cnt * sizeof(read_value));2303}2304 2305 2306/*2307* We catch an error where driver does not read2308* as much data as we expect from the entry.2309*/2310 2311static int netxen_md_entry_err_chk(struct netxen_adapter *adapter,2312				struct netxen_minidump_entry *entry, int esize)2313{2314	if (esize < 0) {2315		entry->hdr.driver_flags |= NX_DUMP_SKIP;2316		return esize;2317	}2318	if (esize != entry->hdr.entry_capture_size) {2319		entry->hdr.entry_capture_size = esize;2320		entry->hdr.driver_flags |= NX_DUMP_SIZE_ERR;2321		dev_info(&adapter->pdev->dev,2322			"Invalidate dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",2323			entry->hdr.entry_type, entry->hdr.entry_capture_mask,2324			esize, entry->hdr.entry_capture_size);2325		dev_info(&adapter->pdev->dev, "Aborting further dump capture\n");2326	}2327	return 0;2328}2329 2330static int netxen_parse_md_template(struct netxen_adapter *adapter)2331{2332	int num_of_entries, buff_level, e_cnt, esize;2333	int rv = 0, sane_start = 0, sane_end = 0;2334	char *dbuff;2335	void *template_buff = adapter->mdump.md_template;2336	char *dump_buff = adapter->mdump.md_capture_buff;2337	int capture_mask = adapter->mdump.md_capture_mask;2338	struct netxen_minidump_template_hdr *template_hdr;2339	struct netxen_minidump_entry *entry;2340 2341	if ((capture_mask & 0x3) != 0x3) {2342		dev_err(&adapter->pdev->dev, "Capture mask %02x below minimum needed "2343			"for valid firmware dump\n", capture_mask);2344		return -EINVAL;2345	}2346	template_hdr = (struct netxen_minidump_template_hdr *) template_buff;2347	num_of_entries = template_hdr->num_of_entries;2348	entry = (struct netxen_minidump_entry *) ((char *) template_buff +2349				template_hdr->first_entry_offset);2350	memcpy(dump_buff, template_buff, adapter->mdump.md_template_size);2351	dump_buff = dump_buff + adapter->mdump.md_template_size;2352 2353	if (template_hdr->entry_type == TLHDR)2354		sane_start = 1;2355 2356	for (e_cnt = 0, buff_level = 0; e_cnt < num_of_entries; e_cnt++) {2357		if (!(entry->hdr.entry_capture_mask & capture_mask)) {2358			entry->hdr.driver_flags |= NX_DUMP_SKIP;2359			entry = (struct netxen_minidump_entry *)2360				((char *) entry + entry->hdr.entry_size);2361			continue;2362		}2363		switch (entry->hdr.entry_type) {2364		case RDNOP:2365			entry->hdr.driver_flags |= NX_DUMP_SKIP;2366			break;2367		case RDEND:2368			entry->hdr.driver_flags |= NX_DUMP_SKIP;2369			sane_end += 1;2370			break;2371		case CNTRL:2372			rv = netxen_md_cntrl(adapter,2373				template_hdr, (void *)entry);2374			if (rv)2375				entry->hdr.driver_flags |= NX_DUMP_SKIP;2376			break;2377		case RDCRB:2378			dbuff = dump_buff + buff_level;2379			esize = netxen_md_rd_crb(adapter,2380					(void *) entry, (void *) dbuff);2381			rv = netxen_md_entry_err_chk2382				(adapter, entry, esize);2383			if (rv < 0)2384				break;2385			buff_level += esize;2386			break;2387		case RDMN:2388		case RDMEM:2389			dbuff = dump_buff + buff_level;2390			esize = netxen_md_rdmem(adapter,2391				(void *) entry, (void *) dbuff);2392			rv = netxen_md_entry_err_chk2393				(adapter, entry, esize);2394			if (rv < 0)2395				break;2396			buff_level += esize;2397			break;2398		case BOARD:2399		case RDROM:2400			dbuff = dump_buff + buff_level;2401			esize = netxen_md_rdrom(adapter,2402				(void *) entry, (void *) dbuff);2403			rv = netxen_md_entry_err_chk2404				(adapter, entry, esize);2405			if (rv < 0)2406				break;2407			buff_level += esize;2408			break;2409		case L2ITG:2410		case L2DTG:2411		case L2DAT:2412		case L2INS:2413			dbuff = dump_buff + buff_level;2414			esize = netxen_md_L2Cache(adapter,2415				(void *) entry, (void *) dbuff);2416			rv = netxen_md_entry_err_chk2417				(adapter, entry, esize);2418			if (rv < 0)2419				break;2420			buff_level += esize;2421			break;2422		case L1DAT:2423		case L1INS:2424			dbuff = dump_buff + buff_level;2425			esize = netxen_md_L1Cache(adapter,2426				(void *) entry, (void *) dbuff);2427			rv = netxen_md_entry_err_chk2428				(adapter, entry, esize);2429			if (rv < 0)2430				break;2431			buff_level += esize;2432			break;2433		case RDOCM:2434			dbuff = dump_buff + buff_level;2435			esize = netxen_md_rdocm(adapter,2436				(void *) entry, (void *) dbuff);2437			rv = netxen_md_entry_err_chk2438				(adapter, entry, esize);2439			if (rv < 0)2440				break;2441			buff_level += esize;2442			break;2443		case RDMUX:2444			dbuff = dump_buff + buff_level;2445			esize = netxen_md_rdmux(adapter,2446				(void *) entry, (void *) dbuff);2447			rv = netxen_md_entry_err_chk2448				(adapter, entry, esize);2449			if (rv < 0)2450				break;2451			buff_level += esize;2452			break;2453		case QUEUE:2454			dbuff = dump_buff + buff_level;2455			esize = netxen_md_rdqueue(adapter,2456				(void *) entry, (void *) dbuff);2457			rv = netxen_md_entry_err_chk2458				(adapter, entry, esize);2459			if (rv  < 0)2460				break;2461			buff_level += esize;2462			break;2463		default:2464			entry->hdr.driver_flags |= NX_DUMP_SKIP;2465			break;2466		}2467		/* Next entry in the template */2468		entry = (struct netxen_minidump_entry *)2469			((char *) entry + entry->hdr.entry_size);2470	}2471	if (!sane_start || sane_end > 1) {2472		dev_err(&adapter->pdev->dev,2473				"Firmware minidump template configuration error.\n");2474	}2475	return 0;2476}2477 2478static int2479netxen_collect_minidump(struct netxen_adapter *adapter)2480{2481	int ret = 0;2482	struct netxen_minidump_template_hdr *hdr;2483	hdr = (struct netxen_minidump_template_hdr *)2484				adapter->mdump.md_template;2485	hdr->driver_capture_mask = adapter->mdump.md_capture_mask;2486	hdr->driver_timestamp = ktime_get_seconds();2487	hdr->driver_info_word2 = adapter->fw_version;2488	hdr->driver_info_word3 = NXRD32(adapter, CRB_DRIVER_VERSION);2489	ret = netxen_parse_md_template(adapter);2490	if (ret)2491		return ret;2492 2493	return ret;2494}2495 2496 2497void2498netxen_dump_fw(struct netxen_adapter *adapter)2499{2500	struct netxen_minidump_template_hdr *hdr;2501	int i, k, data_size = 0;2502	u32 capture_mask;2503	hdr = (struct netxen_minidump_template_hdr *)2504				adapter->mdump.md_template;2505	capture_mask = adapter->mdump.md_capture_mask;2506 2507	for (i = 0x2, k = 1; (i & NX_DUMP_MASK_MAX); i <<= 1, k++) {2508		if (i & capture_mask)2509			data_size += hdr->capture_size_array[k];2510	}2511	if (!data_size) {2512		dev_err(&adapter->pdev->dev,2513				"Invalid cap sizes for capture_mask=0x%x\n",2514			adapter->mdump.md_capture_mask);2515		return;2516	}2517	adapter->mdump.md_capture_size = data_size;2518	adapter->mdump.md_dump_size = adapter->mdump.md_template_size +2519					adapter->mdump.md_capture_size;2520	if (!adapter->mdump.md_capture_buff) {2521		adapter->mdump.md_capture_buff =2522				vzalloc(adapter->mdump.md_dump_size);2523		if (!adapter->mdump.md_capture_buff)2524			return;2525 2526		if (netxen_collect_minidump(adapter)) {2527			adapter->mdump.has_valid_dump = 0;2528			adapter->mdump.md_dump_size = 0;2529			vfree(adapter->mdump.md_capture_buff);2530			adapter->mdump.md_capture_buff = NULL;2531			dev_err(&adapter->pdev->dev,2532				"Error in collecting firmware minidump.\n");2533		} else {2534			adapter->mdump.md_timestamp = jiffies;2535			adapter->mdump.has_valid_dump = 1;2536			adapter->fw_mdump_rdy = 1;2537			dev_info(&adapter->pdev->dev, "%s Successfully "2538				"collected fw dump.\n", adapter->netdev->name);2539		}2540 2541	} else {2542		dev_info(&adapter->pdev->dev,2543					"Cannot overwrite previously collected "2544							"firmware minidump.\n");2545		adapter->fw_mdump_rdy = 1;2546		return;2547	}2548}2549