netxen_nic_init.c 28.2 KB
Newer Older
A
Amit S. Kale 已提交
1
/*
D
Dhananjay Phadke 已提交
2
 * Copyright (C) 2003 - 2009 NetXen, Inc.
A
Amit S. Kale 已提交
3
 * All rights reserved.
4
 *
A
Amit S. Kale 已提交
5 6 7 8
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
9
 *
A
Amit S. Kale 已提交
10 11 12 13
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
14
 *
A
Amit S. Kale 已提交
15 16 17 18
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA  02111-1307, USA.
19
 *
A
Amit S. Kale 已提交
20 21
 * The full GNU General Public License is included in this distribution
 * in the file called LICENSE.
22
 *
A
Amit S. Kale 已提交
23 24
 * Contact Information:
 *    info@netxen.com
D
Dhananjay Phadke 已提交
25 26 27
 * NetXen Inc,
 * 18922 Forge Drive
 * Cupertino, CA 95014-0701
A
Amit S. Kale 已提交
28 29 30 31 32 33 34 35 36 37
 *
 */

#include <linux/netdevice.h>
#include <linux/delay.h>
#include "netxen_nic.h"
#include "netxen_nic_hw.h"
#include "netxen_nic_phan_reg.h"

struct crb_addr_pair {
38 39
	u32 addr;
	u32 data;
A
Amit S. Kale 已提交
40 41 42 43
};

#define NETXEN_MAX_CRB_XFORM 60
static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
44
#define NETXEN_ADDR_ERROR (0xffffffff)
A
Amit S. Kale 已提交
45 46 47 48 49

#define crb_addr_transform(name) \
	crb_addr_xform[NETXEN_HW_PX_MAP_CRB_##name] = \
	NETXEN_HW_CRB_HUB_AGT_ADR_##name << 20

50 51
#define NETXEN_NIC_XDMA_RESET 0x8000ff

52 53
static void
netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid);
A
Adrian Bunk 已提交
54

A
Amit S. Kale 已提交
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
static void crb_addr_transform_setup(void)
{
	crb_addr_transform(XDMA);
	crb_addr_transform(TIMR);
	crb_addr_transform(SRE);
	crb_addr_transform(SQN3);
	crb_addr_transform(SQN2);
	crb_addr_transform(SQN1);
	crb_addr_transform(SQN0);
	crb_addr_transform(SQS3);
	crb_addr_transform(SQS2);
	crb_addr_transform(SQS1);
	crb_addr_transform(SQS0);
	crb_addr_transform(RPMX7);
	crb_addr_transform(RPMX6);
	crb_addr_transform(RPMX5);
	crb_addr_transform(RPMX4);
	crb_addr_transform(RPMX3);
	crb_addr_transform(RPMX2);
	crb_addr_transform(RPMX1);
	crb_addr_transform(RPMX0);
	crb_addr_transform(ROMUSB);
	crb_addr_transform(SN);
	crb_addr_transform(QMN);
	crb_addr_transform(QMS);
	crb_addr_transform(PGNI);
	crb_addr_transform(PGND);
	crb_addr_transform(PGN3);
	crb_addr_transform(PGN2);
	crb_addr_transform(PGN1);
	crb_addr_transform(PGN0);
	crb_addr_transform(PGSI);
	crb_addr_transform(PGSD);
	crb_addr_transform(PGS3);
	crb_addr_transform(PGS2);
	crb_addr_transform(PGS1);
	crb_addr_transform(PGS0);
	crb_addr_transform(PS);
	crb_addr_transform(PH);
	crb_addr_transform(NIU);
	crb_addr_transform(I2Q);
	crb_addr_transform(EG);
	crb_addr_transform(MN);
	crb_addr_transform(MS);
	crb_addr_transform(CAS2);
	crb_addr_transform(CAS1);
	crb_addr_transform(CAS0);
	crb_addr_transform(CAM);
	crb_addr_transform(C2C1);
	crb_addr_transform(C2C0);
105
	crb_addr_transform(SMB);
106 107
	crb_addr_transform(OCM0);
	crb_addr_transform(I2C0);
A
Amit S. Kale 已提交
108 109 110 111 112 113 114
}

int netxen_init_firmware(struct netxen_adapter *adapter)
{
	u32 state = 0, loops = 0, err = 0;

	/* Window 1 call */
115
	state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
A
Amit S. Kale 已提交
116 117 118 119 120

	if (state == PHAN_INITIALIZE_ACK)
		return 0;

	while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) {
121
		msleep(1);
A
Amit S. Kale 已提交
122
		/* Window 1 call */
123
		state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
A
Amit S. Kale 已提交
124 125 126 127 128 129 130 131 132 133

		loops++;
	}
	if (loops >= 2000) {
		printk(KERN_ERR "Cmd Peg initialization not complete:%x.\n",
		       state);
		err = -EIO;
		return err;
	}
	/* Window 1 call */
134 135 136 137 138 139 140 141
	adapter->pci_write_normalize(adapter,
			CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT);
	adapter->pci_write_normalize(adapter,
			CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC);
	adapter->pci_write_normalize(adapter,
			CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
	adapter->pci_write_normalize(adapter,
			CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
A
Amit S. Kale 已提交
142 143 144 145

	return err;
}

146
void netxen_release_rx_buffers(struct netxen_adapter *adapter)
A
Amit S. Kale 已提交
147
{
148
	struct netxen_recv_context *recv_ctx;
D
Dhananjay Phadke 已提交
149
	struct nx_host_rds_ring *rds_ring;
150
	struct netxen_rx_buffer *rx_buf;
151 152 153 154 155
	int i, ring;

	recv_ctx = &adapter->recv_ctx;
	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
		rds_ring = &recv_ctx->rds_rings[ring];
156
		for (i = 0; i < rds_ring->num_desc; ++i) {
157 158 159 160 161 162 163 164 165
			rx_buf = &(rds_ring->rx_buf_arr[i]);
			if (rx_buf->state == NETXEN_BUFFER_FREE)
				continue;
			pci_unmap_single(adapter->pdev,
					rx_buf->dma,
					rds_ring->dma_size,
					PCI_DMA_FROMDEVICE);
			if (rx_buf->skb != NULL)
				dev_kfree_skb_any(rx_buf->skb);
166 167 168 169 170 171 172 173 174 175 176
		}
	}
}

void netxen_release_tx_buffers(struct netxen_adapter *adapter)
{
	struct netxen_cmd_buffer *cmd_buf;
	struct netxen_skb_frag *buffrag;
	int i, j;

	cmd_buf = adapter->cmd_buf_arr;
177
	for (i = 0; i < adapter->num_txd; i++) {
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
		buffrag = cmd_buf->frag_array;
		if (buffrag->dma) {
			pci_unmap_single(adapter->pdev, buffrag->dma,
					 buffrag->length, PCI_DMA_TODEVICE);
			buffrag->dma = 0ULL;
		}
		for (j = 0; j < cmd_buf->frag_count; j++) {
			buffrag++;
			if (buffrag->dma) {
				pci_unmap_page(adapter->pdev, buffrag->dma,
					       buffrag->length,
					       PCI_DMA_TODEVICE);
				buffrag->dma = 0ULL;
			}
		}
		if (cmd_buf->skb) {
			dev_kfree_skb_any(cmd_buf->skb);
			cmd_buf->skb = NULL;
		}
		cmd_buf++;
	}
}

void netxen_free_sw_resources(struct netxen_adapter *adapter)
{
	struct netxen_recv_context *recv_ctx;
D
Dhananjay Phadke 已提交
204
	struct nx_host_rds_ring *rds_ring;
205 206 207 208 209 210 211 212
	int ring;

	recv_ctx = &adapter->recv_ctx;
	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
		rds_ring = &recv_ctx->rds_rings[ring];
		if (rds_ring->rx_buf_arr) {
			vfree(rds_ring->rx_buf_arr);
			rds_ring->rx_buf_arr = NULL;
213 214
		}
	}
215

216 217 218 219 220 221 222 223
	if (adapter->cmd_buf_arr)
		vfree(adapter->cmd_buf_arr);
	return;
}

int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
{
	struct netxen_recv_context *recv_ctx;
D
Dhananjay Phadke 已提交
224
	struct nx_host_rds_ring *rds_ring;
225
	struct netxen_rx_buffer *rx_buf;
226
	int ring, i, num_rx_bufs;
227 228 229 230 231 232 233 234 235 236 237 238 239

	struct netxen_cmd_buffer *cmd_buf_arr;
	struct net_device *netdev = adapter->netdev;

	cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
	if (cmd_buf_arr == NULL) {
		printk(KERN_ERR "%s: Failed to allocate cmd buffer ring\n",
		       netdev->name);
		return -ENOMEM;
	}
	memset(cmd_buf_arr, 0, TX_RINGSIZE);
	adapter->cmd_buf_arr = cmd_buf_arr;

240 241 242
	recv_ctx = &adapter->recv_ctx;
	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
		rds_ring = &recv_ctx->rds_rings[ring];
243 244 245
		switch (ring) {
		case RCV_RING_NORMAL:
			rds_ring->num_desc = adapter->num_rxd;
246 247 248
			if (adapter->ahw.cut_through) {
				rds_ring->dma_size =
					NX_CT_DEFAULT_RX_BUF_LEN;
D
Dhananjay Phadke 已提交
249
				rds_ring->skb_size =
250 251 252 253 254 255 256
					NX_CT_DEFAULT_RX_BUF_LEN;
			} else {
				rds_ring->dma_size = RX_DMA_MAP_LEN;
				rds_ring->skb_size =
					MAX_RX_BUFFER_LENGTH;
			}
			break;
257

258 259
		case RCV_RING_JUMBO:
			rds_ring->num_desc = adapter->num_jumbo_rxd;
260 261 262 263 264 265 266 267 268
			if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
				rds_ring->dma_size =
					NX_P3_RX_JUMBO_BUF_MAX_LEN;
			else
				rds_ring->dma_size =
					NX_P2_RX_JUMBO_BUF_MAX_LEN;
			rds_ring->skb_size =
				rds_ring->dma_size + NET_IP_ALIGN;
			break;
269

270
		case RCV_RING_LRO:
271
			rds_ring->num_desc = adapter->num_lro_rxd;
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
			rds_ring->dma_size = RX_LRO_DMA_MAP_LEN;
			rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
			break;

		}
		rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
			vmalloc(RCV_BUFFSIZE);
		if (rds_ring->rx_buf_arr == NULL) {
			printk(KERN_ERR "%s: Failed to allocate "
				"rx buffer ring %d\n",
				netdev->name, ring);
			/* free whatever was already allocated */
			goto err_out;
		}
		memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE);
		INIT_LIST_HEAD(&rds_ring->free_list);
		/*
		 * Now go through all of them, set reference handles
		 * and put them in the queues.
		 */
292
		num_rx_bufs = rds_ring->num_desc;
293 294 295 296 297 298 299
		rx_buf = rds_ring->rx_buf_arr;
		for (i = 0; i < num_rx_bufs; i++) {
			list_add_tail(&rx_buf->list,
					&rds_ring->free_list);
			rx_buf->ref_handle = i;
			rx_buf->state = NETXEN_BUFFER_FREE;
			rx_buf++;
A
Amit S. Kale 已提交
300 301
		}
	}
302 303 304 305 306 307

	return 0;

err_out:
	netxen_free_sw_resources(adapter);
	return -ENOMEM;
A
Amit S. Kale 已提交
308 309 310 311
}

void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
{
312
	switch (adapter->ahw.port_type) {
A
Amit S. Kale 已提交
313
	case NETXEN_NIC_GBE:
314
		adapter->enable_phy_interrupts =
A
Amit S. Kale 已提交
315
		    netxen_niu_gbe_enable_phy_interrupts;
316
		adapter->disable_phy_interrupts =
A
Amit S. Kale 已提交
317
		    netxen_niu_gbe_disable_phy_interrupts;
318 319 320 321 322
		adapter->macaddr_set = netxen_niu_macaddr_set;
		adapter->set_mtu = netxen_nic_set_mtu_gb;
		adapter->set_promisc = netxen_niu_set_promiscuous_mode;
		adapter->phy_read = netxen_niu_gbe_phy_read;
		adapter->phy_write = netxen_niu_gbe_phy_write;
323
		adapter->init_port = netxen_niu_gbe_init_port;
324
		adapter->stop_port = netxen_niu_disable_gbe_port;
A
Amit S. Kale 已提交
325 326 327
		break;

	case NETXEN_NIC_XGBE:
328
		adapter->enable_phy_interrupts =
A
Amit S. Kale 已提交
329
		    netxen_niu_xgbe_enable_phy_interrupts;
330
		adapter->disable_phy_interrupts =
A
Amit S. Kale 已提交
331
		    netxen_niu_xgbe_disable_phy_interrupts;
332 333 334 335 336
		adapter->macaddr_set = netxen_niu_xg_macaddr_set;
		adapter->set_mtu = netxen_nic_set_mtu_xgb;
		adapter->init_port = netxen_niu_xg_init_port;
		adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode;
		adapter->stop_port = netxen_niu_disable_xg_port;
A
Amit S. Kale 已提交
337 338 339 340 341
		break;

	default:
		break;
	}
342 343 344 345 346

	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
		adapter->set_mtu = nx_fw_cmd_set_mtu;
		adapter->set_promisc = netxen_p3_nic_set_promisc;
	}
A
Amit S. Kale 已提交
347 348 349 350 351 352
}

/*
 * netxen_decode_crb_addr(0 - utility to translate from internal Phantom CRB
 * address to external PCI CRB address.
 */
A
Adrian Bunk 已提交
353
static u32 netxen_decode_crb_addr(u32 addr)
A
Amit S. Kale 已提交
354 355
{
	int i;
356
	u32 base_addr, offset, pci_base;
A
Amit S. Kale 已提交
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375

	crb_addr_transform_setup();

	pci_base = NETXEN_ADDR_ERROR;
	base_addr = addr & 0xfff00000;
	offset = addr & 0x000fffff;

	for (i = 0; i < NETXEN_MAX_CRB_XFORM; i++) {
		if (crb_addr_xform[i] == base_addr) {
			pci_base = i << 20;
			break;
		}
	}
	if (pci_base == NETXEN_ADDR_ERROR)
		return pci_base;
	else
		return (pci_base + offset);
}

376 377
static long rom_max_timeout = 100;
static long rom_lock_timeout = 10000;
A
Amit S. Kale 已提交
378

A
Adrian Bunk 已提交
379
static int rom_lock(struct netxen_adapter *adapter)
A
Amit S. Kale 已提交
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
{
	int iter;
	u32 done = 0;
	int timeout = 0;

	while (!done) {
		/* acquire semaphore2 from PCI HW block */
		netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK),
				   &done);
		if (done == 1)
			break;
		if (timeout >= rom_lock_timeout)
			return -EIO;

		timeout++;
		/*
		 * Yield CPU
		 */
		if (!in_atomic())
			schedule();
		else {
			for (iter = 0; iter < 20; iter++)
				cpu_relax();	/*This a nop instr on i386 */
		}
	}
	netxen_nic_reg_write(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER);
	return 0;
}

A
Adrian Bunk 已提交
409
static int netxen_wait_rom_done(struct netxen_adapter *adapter)
A
Amit S. Kale 已提交
410 411 412 413
{
	long timeout = 0;
	long done = 0;

D
Dhananjay Phadke 已提交
414 415
	cond_resched();

A
Amit S. Kale 已提交
416 417 418 419 420 421 422 423 424 425 426 427
	while (done == 0) {
		done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS);
		done &= 2;
		timeout++;
		if (timeout >= rom_max_timeout) {
			printk("Timeout reached  waiting for rom done");
			return -EIO;
		}
	}
	return 0;
}

A
Adrian Bunk 已提交
428
static void netxen_rom_unlock(struct netxen_adapter *adapter)
429 430 431 432 433 434 435 436
{
	u32 val;

	/* release semaphore2 */
	netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK), &val);

}

A
Adrian Bunk 已提交
437 438
static int do_rom_fast_read(struct netxen_adapter *adapter,
			    int addr, int *valp)
A
Amit S. Kale 已提交
439 440 441
{
	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
D
Dhananjay Phadke 已提交
442
	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
A
Amit S. Kale 已提交
443 444 445 446 447 448 449
	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
	if (netxen_wait_rom_done(adapter)) {
		printk("Error waiting for rom done\n");
		return -EIO;
	}
	/* reset abyte_cnt and dummy_byte_cnt */
	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
D
Dhananjay Phadke 已提交
450
	udelay(10);
A
Amit S. Kale 已提交
451 452 453 454 455 456
	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);

	*valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA);
	return 0;
}

A
Adrian Bunk 已提交
457 458
static int do_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
				  u8 *bytes, size_t size)
459 460 461 462 463
{
	int addridx;
	int ret = 0;

	for (addridx = addr; addridx < (addr + size); addridx += 4) {
A
Al Viro 已提交
464 465
		int v;
		ret = do_rom_fast_read(adapter, addridx, &v);
466 467
		if (ret != 0)
			break;
A
Al Viro 已提交
468
		*(__le32 *)bytes = cpu_to_le32(v);
469 470 471 472 473 474 475
		bytes += 4;
	}

	return ret;
}

int
476
netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
477 478 479 480 481 482 483 484 485 486 487 488 489 490
				u8 *bytes, size_t size)
{
	int ret;

	ret = rom_lock(adapter);
	if (ret < 0)
		return ret;

	ret = do_rom_fast_read_words(adapter, addr, bytes, size);

	netxen_rom_unlock(adapter);
	return ret;
}

A
Amit S. Kale 已提交
491 492 493 494 495 496 497 498
int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
{
	int ret;

	if (rom_lock(adapter) != 0)
		return -EIO;

	ret = do_rom_fast_read(adapter, addr, valp);
499 500 501 502
	netxen_rom_unlock(adapter);
	return ret;
}

A
Amit S. Kale 已提交
503 504 505 506 507 508
#define NETXEN_BOARDTYPE		0x4008
#define NETXEN_BOARDNUM 		0x400c
#define NETXEN_CHIPNUM			0x4010

int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
{
509
	int addr, val;
D
Dhananjay Phadke 已提交
510
	int i, n, init_delay = 0;
A
Amit S. Kale 已提交
511
	struct crb_addr_pair *buf;
D
Dhananjay Phadke 已提交
512
	unsigned offset;
513
	u32 off;
A
Amit S. Kale 已提交
514 515

	/* resetall */
D
Dhananjay Phadke 已提交
516
	rom_lock(adapter);
A
Amit S. Kale 已提交
517
	netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
518
				    0xffffffff);
D
Dhananjay Phadke 已提交
519
	netxen_rom_unlock(adapter);
A
Amit S. Kale 已提交
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535

	if (verbose) {
		if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0)
			printk("P2 ROM board type: 0x%08x\n", val);
		else
			printk("Could not read board type\n");
		if (netxen_rom_fast_read(adapter, NETXEN_BOARDNUM, &val) == 0)
			printk("P2 ROM board  num: 0x%08x\n", val);
		else
			printk("Could not read board number\n");
		if (netxen_rom_fast_read(adapter, NETXEN_CHIPNUM, &val) == 0)
			printk("P2 ROM chip   num: 0x%08x\n", val);
		else
			printk("Could not read chip number\n");
	}

536 537
	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
		if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
D
Dhananjay Phadke 已提交
538
			(n != 0xcafecafe) ||
539 540 541
			netxen_rom_fast_read(adapter, 4, &n) != 0) {
			printk(KERN_ERR "%s: ERROR Reading crb_init area: "
					"n: %08x\n", netxen_nic_driver_name, n);
A
Amit S. Kale 已提交
542 543
			return -EIO;
		}
544 545 546 547 548 549 550 551
		offset = n & 0xffffU;
		n = (n >> 16) & 0xffffU;
	} else {
		if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
			!(n & 0x80000000)) {
			printk(KERN_ERR "%s: ERROR Reading crb_init area: "
					"n: %08x\n", netxen_nic_driver_name, n);
			return -EIO;
A
Amit S. Kale 已提交
552
		}
553 554 555 556 557 558 559 560 561 562 563 564 565
		offset = 1;
		n &= ~0x80000000;
	}

	if (n < 1024) {
		if (verbose)
			printk(KERN_DEBUG "%s: %d CRB init values found"
			       " in ROM.\n", netxen_nic_driver_name, n);
	} else {
		printk(KERN_ERR "%s:n=0x%x Error! NetXen card flash not"
		       " initialized.\n", __func__, n);
		return -EIO;
	}
A
Amit S. Kale 已提交
566

567 568 569 570 571 572 573 574
	buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
	if (buf == NULL) {
		printk("%s: netxen_pinit_from_rom: Unable to calloc memory.\n",
				netxen_nic_driver_name);
		return -ENOMEM;
	}
	for (i = 0; i < n; i++) {
		if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
575 576
		netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) {
			kfree(buf);
577
			return -EIO;
578
		}
579 580 581 582 583 584 585 586 587 588 589 590 591 592

		buf[i].addr = addr;
		buf[i].data = val;

		if (verbose)
			printk(KERN_DEBUG "%s: PCI:     0x%08x == 0x%08x\n",
				netxen_nic_driver_name,
				(u32)netxen_decode_crb_addr(addr), val);
	}
	for (i = 0; i < n; i++) {

		off = netxen_decode_crb_addr(buf[i].addr);
		if (off == NETXEN_ADDR_ERROR) {
			printk(KERN_ERR"CRB init value out of range %x\n",
593
					buf[i].addr);
594 595 596 597 598 599 600 601 602 603
			continue;
		}
		off += NETXEN_PCI_CRBSPACE;
		/* skipping cold reboot MAGIC */
		if (off == NETXEN_CAM_RAM(0x1fc))
			continue;

		if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
			/* do not reset PCI */
			if (off == (ROMUSB_GLB + 0xbc))
604
				continue;
D
Dhananjay Phadke 已提交
605 606 607 608 609 610 611 612
			if (off == (ROMUSB_GLB + 0xa8))
				continue;
			if (off == (ROMUSB_GLB + 0xc8)) /* core clock */
				continue;
			if (off == (ROMUSB_GLB + 0x24)) /* MN clock */
				continue;
			if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */
				continue;
613 614 615 616
			if (off == (NETXEN_CRB_PEG_NET_1 + 0x18))
				buf[i].data = 0x1020;
			/* skip the function enable register */
			if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION))
A
Amit S. Kale 已提交
617
				continue;
618 619 620 621 622
			if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION2))
				continue;
			if ((off & 0x0ff00000) == NETXEN_CRB_SMB)
				continue;
		}
A
Amit S. Kale 已提交
623

624 625 626 627 628 629
		if (off == NETXEN_ADDR_ERROR) {
			printk(KERN_ERR "%s: Err: Unknown addr: 0x%08x\n",
					netxen_nic_driver_name, buf[i].addr);
			continue;
		}

D
Dhananjay Phadke 已提交
630
		init_delay = 1;
631 632 633
		/* After writing this register, HW needs time for CRB */
		/* to quiet down (else crb_window returns 0xffffffff) */
		if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
D
Dhananjay Phadke 已提交
634
			init_delay = 1000;
635
			if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
A
Amit S. Kale 已提交
636
				/* hold xdma in reset also */
637
				buf[i].data = NETXEN_NIC_XDMA_RESET;
D
Dhananjay Phadke 已提交
638
				buf[i].data = 0x8000ff;
A
Amit S. Kale 已提交
639
			}
640
		}
A
Amit S. Kale 已提交
641

642
		adapter->hw_write_wx(adapter, off, &buf[i].data, 4);
A
Amit S. Kale 已提交
643

D
Dhananjay Phadke 已提交
644
		msleep(init_delay);
645 646
	}
	kfree(buf);
A
Amit S. Kale 已提交
647

648
	/* disable_peg_cache_all */
A
Amit S. Kale 已提交
649

650 651 652 653
	/* unreset_net_cache */
	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
		adapter->hw_read_wx(adapter,
				NETXEN_ROMUSB_GLB_SW_RESET, &val, 4);
A
Amit S. Kale 已提交
654
		netxen_crb_writelit_adapter(adapter,
655
				NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f));
A
Amit S. Kale 已提交
656
	}
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678

	/* p2dn replyCount */
	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
	/* disable_peg_cache 0 */
	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8);
	/* disable_peg_cache 1 */
	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8);

	/* peg_clr_all */

	/* peg_clr 0 */
	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0);
	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0);
	/* peg_clr 1 */
	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0);
	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0);
	/* peg_clr 2 */
	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0);
	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0);
	/* peg_clr 3 */
	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0);
	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0);
A
Amit S. Kale 已提交
679 680 681
	return 0;
}

682 683 684 685 686 687 688
int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
{
	uint64_t addr;
	uint32_t hi;
	uint32_t lo;

	adapter->dummy_dma.addr =
689
	    pci_alloc_consistent(adapter->pdev,
690 691 692 693
				 NETXEN_HOST_DUMMY_DMA_SIZE,
				 &adapter->dummy_dma.phys_addr);
	if (adapter->dummy_dma.addr == NULL) {
		printk("%s: ERROR: Could not allocate dummy DMA memory\n",
694
		       __func__);
695 696 697 698 699 700 701
		return -ENOMEM;
	}

	addr = (uint64_t) adapter->dummy_dma.phys_addr;
	hi = (addr >> 32) & 0xffffffff;
	lo = addr & 0xffffffff;

702 703
	adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
	adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
704

705 706 707 708 709
	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
		uint32_t temp = 0;
		adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, &temp, 4);
	}

710 711 712 713 714
	return 0;
}

void netxen_free_adapter_offload(struct netxen_adapter *adapter)
{
D
Dhananjay Phadke 已提交
715 716 717 718
	int i = 100;

	if (!adapter->dummy_dma.addr)
		return;
719

D
Dhananjay Phadke 已提交
720
	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
721 722 723 724 725 726 727
		do {
			if (dma_watchdog_shutdown_request(adapter) == 1)
				break;
			msleep(50);
			if (dma_watchdog_shutdown_poll_result(adapter) == 1)
				break;
		} while (--i);
D
Dhananjay Phadke 已提交
728
	}
729

D
Dhananjay Phadke 已提交
730 731 732 733 734 735 736 737 738
	if (i) {
		pci_free_consistent(adapter->pdev,
			    NETXEN_HOST_DUMMY_DMA_SIZE,
			    adapter->dummy_dma.addr,
			    adapter->dummy_dma.phys_addr);
		adapter->dummy_dma.addr = NULL;
	} else {
		printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n",
				adapter->netdev->name);
739 740 741
	}
}

742
int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
A
Amit S. Kale 已提交
743 744
{
	u32 val = 0;
745
	int retries = 60;
A
Amit S. Kale 已提交
746

747
	if (!pegtune_val) {
748
		do {
749 750
			val = adapter->pci_read_normalize(adapter,
					CRB_CMDPEG_STATE);
751 752 753 754 755

			if (val == PHAN_INITIALIZE_COMPLETE ||
				val == PHAN_INITIALIZE_ACK)
				return 0;

756 757
			msleep(500);

758
		} while (--retries);
759

760
		if (!retries) {
761 762
			pegtune_val = adapter->pci_read_normalize(adapter,
					NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
763 764 765
			printk(KERN_WARNING "netxen_phantom_init: init failed, "
					"pegtune_val=%x\n", pegtune_val);
			return -1;
A
Amit S. Kale 已提交
766 767
		}
	}
768 769

	return 0;
A
Amit S. Kale 已提交
770 771
}

772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
int netxen_receive_peg_ready(struct netxen_adapter *adapter)
{
	u32 val = 0;
	int retries = 2000;

	do {
		val = adapter->pci_read_normalize(adapter, CRB_RCVPEG_STATE);

		if (val == PHAN_PEG_RCV_INITIALIZED)
			return 0;

		msleep(10);

	} while (--retries);

	if (!retries) {
		printk(KERN_ERR "Receive Peg initialization not "
			      "complete, state: 0x%x.\n", val);
		return -EIO;
	}

	return 0;
}

796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter,
		struct nx_host_rds_ring *rds_ring, u16 index, u16 cksum)
{
	struct netxen_rx_buffer *buffer;
	struct sk_buff *skb;

	buffer = &rds_ring->rx_buf_arr[index];

	pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
			PCI_DMA_FROMDEVICE);

	skb = buffer->skb;
	if (!skb)
		goto no_skb;

	if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) {
		adapter->stats.csummed++;
		skb->ip_summed = CHECKSUM_UNNECESSARY;
	} else
		skb->ip_summed = CHECKSUM_NONE;

	skb->dev = adapter->netdev;

	buffer->skb = NULL;

no_skb:
	buffer->state = NETXEN_BUFFER_FREE;
	list_add_tail(&buffer->list, &rds_ring->free_list);
	return skb;
}

D
Dhananjay Phadke 已提交
827 828 829
static void
netxen_process_rcv(struct netxen_adapter *adapter,
		int ring, int index, int length, int cksum, int pkt_offset)
A
Amit S. Kale 已提交
830
{
831
	struct net_device *netdev = adapter->netdev;
832
	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
A
Amit S. Kale 已提交
833 834
	struct netxen_rx_buffer *buffer;
	struct sk_buff *skb;
D
Dhananjay Phadke 已提交
835
	struct nx_host_rds_ring *rds_ring = &recv_ctx->rds_rings[ring];
A
Amit S. Kale 已提交
836

837
	if (unlikely(index > rds_ring->num_desc))
838
		return;
839

D
Dhananjay Phadke 已提交
840
	buffer = &rds_ring->rx_buf_arr[index];
A
Amit S. Kale 已提交
841

842 843 844
	skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum);
	if (!skb)
		return;
D
Dhananjay Phadke 已提交
845

D
Dhananjay Phadke 已提交
846 847 848 849
	if (length > rds_ring->skb_size)
		skb_put(skb, rds_ring->skb_size);
	else
		skb_put(skb, length);
850

D
Dhananjay Phadke 已提交
851 852 853

	if (pkt_offset)
		skb_pull(skb, pkt_offset);
854

A
Amit S. Kale 已提交
855 856
	skb->protocol = eth_type_trans(skb, netdev);

D
Dhananjay Phadke 已提交
857
	netif_receive_skb(skb);
858

D
Dhananjay Phadke 已提交
859 860
	adapter->stats.no_rcv++;
	adapter->stats.rxbytes += length;
A
Amit S. Kale 已提交
861 862
}

863 864
int
netxen_process_rcv_ring(struct netxen_adapter *adapter, int max)
A
Amit S. Kale 已提交
865
{
866
	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
A
Amit S. Kale 已提交
867
	struct status_desc *desc_head = recv_ctx->rcv_status_desc_head;
D
Dhananjay Phadke 已提交
868
	struct status_desc *desc;
A
Amit S. Kale 已提交
869
	u32 consumer = recv_ctx->status_rx_consumer;
D
Dhananjay Phadke 已提交
870
	int count = 0;
871
	u64 sts_data;
D
Dhananjay Phadke 已提交
872
	int opcode, ring, index, length, cksum, pkt_offset;
A
Amit S. Kale 已提交
873 874 875

	while (count < max) {
		desc = &desc_head[consumer];
D
Dhananjay Phadke 已提交
876 877 878
		sts_data = le64_to_cpu(desc->status_desc_data);

		if (!(sts_data & STATUS_OWNER_HOST))
A
Amit S. Kale 已提交
879
			break;
880

D
Dhananjay Phadke 已提交
881 882 883 884
		ring   = netxen_get_sts_type(sts_data);
		if (ring > RCV_RING_JUMBO)
			continue;

885 886
		opcode = netxen_get_sts_opcode(sts_data);

D
Dhananjay Phadke 已提交
887 888 889 890 891 892 893
		index  = netxen_get_sts_refhandle(sts_data);
		length = netxen_get_sts_totallength(sts_data);
		cksum  = netxen_get_sts_status(sts_data);
		pkt_offset = netxen_get_sts_pkt_offset(sts_data);

		netxen_process_rcv(adapter, ring, index,
				length, cksum, pkt_offset);
894

D
Dhananjay Phadke 已提交
895
		desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM);
896

897
		consumer = get_next_index(consumer, adapter->num_rxd);
A
Amit S. Kale 已提交
898 899
		count++;
	}
D
Dhananjay Phadke 已提交
900

D
Dhananjay Phadke 已提交
901
	for (ring = 0; ring < adapter->max_rds_rings; ring++)
902
		netxen_post_rx_buffers_nodb(adapter, ring);
A
Amit S. Kale 已提交
903 904 905

	if (count) {
		recv_ctx->status_rx_consumer = consumer;
906 907
		adapter->pci_write_normalize(adapter,
				recv_ctx->crb_sts_consumer, consumer);
A
Amit S. Kale 已提交
908 909 910 911 912 913
	}

	return count;
}

/* Process Command status ring */
D
Dhananjay Phadke 已提交
914
int netxen_process_cmd_ring(struct netxen_adapter *adapter)
A
Amit S. Kale 已提交
915
{
916 917
	u32 last_consumer, consumer;
	int count = 0, i;
A
Amit S. Kale 已提交
918
	struct netxen_cmd_buffer *buffer;
919 920
	struct pci_dev *pdev = adapter->pdev;
	struct net_device *netdev = adapter->netdev;
A
Amit S. Kale 已提交
921
	struct netxen_skb_frag *frag;
922
	int done = 0;
A
Amit S. Kale 已提交
923 924

	last_consumer = adapter->last_cmd_consumer;
925
	barrier(); /* cmd_consumer can change underneath */
926
	consumer = le32_to_cpu(*(adapter->cmd_consumer));
A
Amit S. Kale 已提交
927

928
	while (last_consumer != consumer) {
A
Amit S. Kale 已提交
929
		buffer = &adapter->cmd_buf_arr[last_consumer];
930 931
		if (buffer->skb) {
			frag = &buffer->frag_array[0];
A
Amit S. Kale 已提交
932 933
			pci_unmap_single(pdev, frag->dma, frag->length,
					 PCI_DMA_TODEVICE);
934
			frag->dma = 0ULL;
A
Amit S. Kale 已提交
935 936 937 938
			for (i = 1; i < buffer->frag_count; i++) {
				frag++;	/* Get the next frag */
				pci_unmap_page(pdev, frag->dma, frag->length,
					       PCI_DMA_TODEVICE);
939
				frag->dma = 0ULL;
A
Amit S. Kale 已提交
940 941
			}

942
			adapter->stats.xmitfinished++;
943 944
			dev_kfree_skb_any(buffer->skb);
			buffer->skb = NULL;
A
Amit S. Kale 已提交
945 946 947
		}

		last_consumer = get_next_index(last_consumer,
948
					       adapter->num_txd);
949 950
		if (++count >= MAX_STATUS_HANDLE)
			break;
A
Amit S. Kale 已提交
951 952
	}

953
	if (count) {
A
Amit S. Kale 已提交
954
		adapter->last_cmd_consumer = last_consumer;
955 956 957 958 959 960
		smp_mb();
		if (netif_queue_stopped(netdev) && netif_running(netdev)) {
			netif_tx_lock(netdev);
			netif_wake_queue(netdev);
			smp_mb();
			netif_tx_unlock(netdev);
A
Amit S. Kale 已提交
961 962
		}
	}
963 964 965 966 967 968 969 970 971 972 973 974 975
	/*
	 * If everything is freed up to consumer then check if the ring is full
	 * If the ring is full then check if more needs to be freed and
	 * schedule the call back again.
	 *
	 * This happens when there are 2 CPUs. One could be freeing and the
	 * other filling it. If the ring is full when we get out of here and
	 * the card has already interrupted the host then the host can miss the
	 * interrupt.
	 *
	 * There is still a possible race condition and the host could miss an
	 * interrupt. The card has to take care of this.
	 */
976
	barrier(); /* cmd_consumer can change underneath */
977 978
	consumer = le32_to_cpu(*(adapter->cmd_consumer));
	done = (last_consumer == consumer);
A
Amit S. Kale 已提交
979

980
	return (done);
A
Amit S. Kale 已提交
981 982
}

983 984
void
netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid)
A
Amit S. Kale 已提交
985
{
986
	struct pci_dev *pdev = adapter->pdev;
A
Amit S. Kale 已提交
987
	struct sk_buff *skb;
988
	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
D
Dhananjay Phadke 已提交
989
	struct nx_host_rds_ring *rds_ring = NULL;
990
	uint producer;
A
Amit S. Kale 已提交
991 992 993
	struct rcv_desc *pdesc;
	struct netxen_rx_buffer *buffer;
	int count = 0;
994 995
	netxen_ctx_msg msg = 0;
	dma_addr_t dma;
996
	struct list_head *head;
A
Amit S. Kale 已提交
997

D
Dhananjay Phadke 已提交
998
	rds_ring = &recv_ctx->rds_rings[ringid];
A
Amit S. Kale 已提交
999

D
Dhananjay Phadke 已提交
1000
	producer = rds_ring->producer;
1001 1002 1003 1004
	head = &rds_ring->free_list;

	while (!list_empty(head)) {

D
Dhananjay Phadke 已提交
1005
		skb = dev_alloc_skb(rds_ring->skb_size);
A
Amit S. Kale 已提交
1006 1007 1008
		if (unlikely(!skb)) {
			break;
		}
1009

1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
		if (!adapter->ahw.cut_through)
			skb_reserve(skb, 2);

		dma = pci_map_single(pdev, skb->data,
				rds_ring->dma_size, PCI_DMA_FROMDEVICE);
		if (pci_dma_mapping_error(pdev, dma)) {
			dev_kfree_skb_any(skb);
			break;
		}

		count++;
1021 1022 1023
		buffer = list_entry(head->next, struct netxen_rx_buffer, list);
		list_del(&buffer->list);

1024 1025 1026
		buffer->skb = skb;
		buffer->state = NETXEN_BUFFER_BUSY;
		buffer->dma = dma;
1027

1028
		/* make a rcv descriptor  */
1029 1030
		pdesc = &rds_ring->desc_head[producer];
		pdesc->addr_buffer = cpu_to_le64(dma);
A
Amit S. Kale 已提交
1031
		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
D
Dhananjay Phadke 已提交
1032
		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
1033

1034
		producer = get_next_index(producer, rds_ring->num_desc);
1035
	}
D
Dhananjay Phadke 已提交
1036

1037
	if (count) {
D
Dhananjay Phadke 已提交
1038
		rds_ring->producer = producer;
1039
		adapter->pci_write_normalize(adapter,
D
Dhananjay Phadke 已提交
1040
				rds_ring->crb_rcv_producer,
1041
				(producer-1) & (rds_ring->num_desc-1));
D
Dhananjay Phadke 已提交
1042 1043

		if (adapter->fw_major < 4) {
1044 1045 1046
			/*
			 * Write a doorbell msg to tell phanmon of change in
			 * receive ring producer
D
Dhananjay Phadke 已提交
1047
			 * Only for firmware version < 4.0.0
1048 1049 1050 1051
			 */
			netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID);
			netxen_set_msg_privid(msg);
			netxen_set_msg_count(msg,
1052 1053
					     ((producer - 1) &
					      (rds_ring->num_desc - 1)));
1054
			netxen_set_msg_ctxid(msg, adapter->portnum);
1055 1056 1057 1058
			netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid));
			writel(msg,
			       DB_NORMALIZE(adapter,
					    NETXEN_RCV_PRODUCER_OFFSET));
D
Dhananjay Phadke 已提交
1059
		}
1060 1061 1062
	}
}

1063 1064
static void
netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid)
1065
{
1066
	struct pci_dev *pdev = adapter->pdev;
1067
	struct sk_buff *skb;
1068
	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
D
Dhananjay Phadke 已提交
1069
	struct nx_host_rds_ring *rds_ring = NULL;
1070 1071 1072 1073
	u32 producer;
	struct rcv_desc *pdesc;
	struct netxen_rx_buffer *buffer;
	int count = 0;
1074
	struct list_head *head;
1075
	dma_addr_t dma;
1076

D
Dhananjay Phadke 已提交
1077
	rds_ring = &recv_ctx->rds_rings[ringid];
1078

D
Dhananjay Phadke 已提交
1079
	producer = rds_ring->producer;
1080 1081 1082
	head = &rds_ring->free_list;
	while (!list_empty(head)) {

D
Dhananjay Phadke 已提交
1083
		skb = dev_alloc_skb(rds_ring->skb_size);
1084 1085 1086
		if (unlikely(!skb)) {
			break;
		}
1087

1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
		if (!adapter->ahw.cut_through)
			skb_reserve(skb, 2);

		dma = pci_map_single(pdev, skb->data,
				rds_ring->dma_size, PCI_DMA_FROMDEVICE);
		if (pci_dma_mapping_error(pdev, dma)) {
			dev_kfree_skb_any(skb);
			break;
		}

		count++;
1099 1100 1101
		buffer = list_entry(head->next, struct netxen_rx_buffer, list);
		list_del(&buffer->list);

A
Amit S. Kale 已提交
1102 1103
		buffer->skb = skb;
		buffer->state = NETXEN_BUFFER_BUSY;
1104
		buffer->dma = dma;
1105

A
Amit S. Kale 已提交
1106
		/* make a rcv descriptor  */
1107
		pdesc = &rds_ring->desc_head[producer];
A
Amit S. Kale 已提交
1108
		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
D
Dhananjay Phadke 已提交
1109
		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
A
Amit S. Kale 已提交
1110
		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
1111

1112
		producer = get_next_index(producer, rds_ring->num_desc);
A
Amit S. Kale 已提交
1113 1114 1115
	}

	if (count) {
D
Dhananjay Phadke 已提交
1116
		rds_ring->producer = producer;
1117
		adapter->pci_write_normalize(adapter,
D
Dhananjay Phadke 已提交
1118
			rds_ring->crb_rcv_producer,
1119
				(producer - 1) & (rds_ring->num_desc - 1));
A
Amit S. Kale 已提交
1120 1121 1122 1123 1124 1125 1126
			wmb();
	}
}

void netxen_nic_clear_stats(struct netxen_adapter *adapter)
{
	memset(&adapter->stats, 0, sizeof(adapter->stats));
1127
	return;
A
Amit S. Kale 已提交
1128 1129
}