netxen_nic_init.c 38.7 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
 *
 */

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

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

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

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

49 50
#define NETXEN_NIC_XDMA_RESET 0x8000ff

51
static void
52 53
netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
		struct nx_host_rds_ring *rds_ring);
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
void netxen_release_rx_buffers(struct netxen_adapter *adapter)
A
Amit S. Kale 已提交
111
{
112
	struct netxen_recv_context *recv_ctx;
D
Dhananjay Phadke 已提交
113
	struct nx_host_rds_ring *rds_ring;
114
	struct netxen_rx_buffer *rx_buf;
115 116 117 118 119
	int i, ring;

	recv_ctx = &adapter->recv_ctx;
	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
		rds_ring = &recv_ctx->rds_rings[ring];
120
		for (i = 0; i < rds_ring->num_desc; ++i) {
121 122 123 124 125 126 127 128 129
			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);
130 131 132 133 134 135 136 137 138
		}
	}
}

void netxen_release_tx_buffers(struct netxen_adapter *adapter)
{
	struct netxen_cmd_buffer *cmd_buf;
	struct netxen_skb_frag *buffrag;
	int i, j;
139
	struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
140

141 142
	cmd_buf = tx_ring->cmd_buf_arr;
	for (i = 0; i < tx_ring->num_desc; i++) {
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
		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 已提交
169
	struct nx_host_rds_ring *rds_ring;
170
	struct nx_host_tx_ring *tx_ring;
171 172 173
	int ring;

	recv_ctx = &adapter->recv_ctx;
174 175 176 177

	if (recv_ctx->rds_rings == NULL)
		goto skip_rds;

178 179
	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
		rds_ring = &recv_ctx->rds_rings[ring];
180 181
		vfree(rds_ring->rx_buf_arr);
		rds_ring->rx_buf_arr = NULL;
182
	}
183 184 185 186 187
	kfree(recv_ctx->rds_rings);

skip_rds:
	if (adapter->tx_ring == NULL)
		return;
188

189
	tx_ring = adapter->tx_ring;
190
	vfree(tx_ring->cmd_buf_arr);
191 192 193 194 195
}

int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
{
	struct netxen_recv_context *recv_ctx;
D
Dhananjay Phadke 已提交
196
	struct nx_host_rds_ring *rds_ring;
197
	struct nx_host_sds_ring *sds_ring;
198
	struct nx_host_tx_ring *tx_ring;
199
	struct netxen_rx_buffer *rx_buf;
200
	int ring, i, size;
201 202 203

	struct netxen_cmd_buffer *cmd_buf_arr;
	struct net_device *netdev = adapter->netdev;
204
	struct pci_dev *pdev = adapter->pdev;
205

206 207 208 209 210 211 212 213 214
	size = sizeof(struct nx_host_tx_ring);
	tx_ring = kzalloc(size, GFP_KERNEL);
	if (tx_ring == NULL) {
		dev_err(&pdev->dev, "%s: failed to allocate tx ring struct\n",
		       netdev->name);
		return -ENOMEM;
	}
	adapter->tx_ring = tx_ring;

215
	tx_ring->num_desc = adapter->num_txd;
216
	tx_ring->txq = netdev_get_tx_queue(netdev, 0);
217 218

	cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring));
219
	if (cmd_buf_arr == NULL) {
220
		dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
221 222 223
		       netdev->name);
		return -ENOMEM;
	}
224 225
	memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
	tx_ring->cmd_buf_arr = cmd_buf_arr;
226

227
	recv_ctx = &adapter->recv_ctx;
228 229 230 231 232 233 234 235 236 237

	size = adapter->max_rds_rings * sizeof (struct nx_host_rds_ring);
	rds_ring = kzalloc(size, GFP_KERNEL);
	if (rds_ring == NULL) {
		dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n",
		       netdev->name);
		return -ENOMEM;
	}
	recv_ctx->rds_rings = rds_ring;

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

260 261
		case RCV_RING_JUMBO:
			rds_ring->num_desc = adapter->num_jumbo_rxd;
262 263 264 265 266 267
			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;
268 269 270 271

			if (adapter->capabilities & NX_CAP0_HW_LRO)
				rds_ring->dma_size += NX_LRO_BUFFER_EXTRA;

272 273 274
			rds_ring->skb_size =
				rds_ring->dma_size + NET_IP_ALIGN;
			break;
275

276
		case RCV_RING_LRO:
277
			rds_ring->num_desc = adapter->num_lro_rxd;
278 279
			rds_ring->dma_size = NX_RX_LRO_BUFFER_LENGTH;
			rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN;
280 281 282 283
			break;

		}
		rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
284
			vmalloc(RCV_BUFF_RINGSIZE(rds_ring));
285 286 287 288 289 290 291
		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;
		}
292
		memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring));
293 294 295 296 297 298
		INIT_LIST_HEAD(&rds_ring->free_list);
		/*
		 * Now go through all of them, set reference handles
		 * and put them in the queues.
		 */
		rx_buf = rds_ring->rx_buf_arr;
299
		for (i = 0; i < rds_ring->num_desc; i++) {
300 301 302 303 304
			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 已提交
305
		}
306 307 308 309 310 311 312 313 314 315 316
		spin_lock_init(&rds_ring->lock);
	}

	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
		sds_ring = &recv_ctx->sds_rings[ring];
		sds_ring->irq = adapter->msix_entries[ring].vector;
		sds_ring->adapter = adapter;
		sds_ring->num_desc = adapter->num_rxd;

		for (i = 0; i < NUM_RCV_DESC_RINGS; i++)
			INIT_LIST_HEAD(&sds_ring->free_list[i]);
A
Amit S. Kale 已提交
317
	}
318 319 320 321 322 323

	return 0;

err_out:
	netxen_free_sw_resources(adapter);
	return -ENOMEM;
A
Amit S. Kale 已提交
324 325 326 327
}

void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
{
D
Dhananjay Phadke 已提交
328 329 330 331 332 333
	adapter->init_port = netxen_niu_xg_init_port;
	adapter->stop_port = netxen_niu_disable_xg_port;

	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
		adapter->macaddr_set = netxen_p2_nic_set_mac_addr;
		adapter->set_multi = netxen_p2_nic_set_multi;
334
		adapter->set_mtu = netxen_nic_set_mtu_xgb;
335
		adapter->set_promisc = netxen_p2_nic_set_promisc;
D
Dhananjay Phadke 已提交
336
	} else {
337 338
		adapter->set_mtu = nx_fw_cmd_set_mtu;
		adapter->set_promisc = netxen_p3_nic_set_promisc;
D
Dhananjay Phadke 已提交
339 340
		adapter->macaddr_set = netxen_p3_nic_set_mac_addr;
		adapter->set_multi = netxen_p3_nic_set_multi;
D
Dhananjay Phadke 已提交
341

342 343 344 345
		if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
			adapter->phy_read = nx_fw_cmd_query_phy;
			adapter->phy_write = nx_fw_cmd_set_phy;
		}
D
Dhananjay Phadke 已提交
346
	}
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
#define NETXEN_MAX_ROM_WAIT_USEC	100
A
Amit S. Kale 已提交
377

A
Adrian Bunk 已提交
378
static int netxen_wait_rom_done(struct netxen_adapter *adapter)
A
Amit S. Kale 已提交
379 380 381 382
{
	long timeout = 0;
	long done = 0;

D
Dhananjay Phadke 已提交
383 384
	cond_resched();

A
Amit S. Kale 已提交
385
	while (done == 0) {
386
		done = NXRD32(adapter, NETXEN_ROMUSB_GLB_STATUS);
A
Amit S. Kale 已提交
387
		done &= 2;
388 389 390
		if (++timeout >= NETXEN_MAX_ROM_WAIT_USEC) {
			dev_err(&adapter->pdev->dev,
				"Timeout reached  waiting for rom done");
A
Amit S. Kale 已提交
391 392
			return -EIO;
		}
393
		udelay(1);
A
Amit S. Kale 已提交
394 395 396 397
	}
	return 0;
}

A
Adrian Bunk 已提交
398 399
static int do_rom_fast_read(struct netxen_adapter *adapter,
			    int addr, int *valp)
A
Amit S. Kale 已提交
400
{
401 402 403 404
	NXWR32(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
	NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
	NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
	NXWR32(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
A
Amit S. Kale 已提交
405 406 407 408 409
	if (netxen_wait_rom_done(adapter)) {
		printk("Error waiting for rom done\n");
		return -EIO;
	}
	/* reset abyte_cnt and dummy_byte_cnt */
410
	NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
D
Dhananjay Phadke 已提交
411
	udelay(10);
412
	NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
A
Amit S. Kale 已提交
413

414
	*valp = NXRD32(adapter, NETXEN_ROMUSB_ROM_RDATA);
A
Amit S. Kale 已提交
415 416 417
	return 0;
}

A
Adrian Bunk 已提交
418 419
static int do_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
				  u8 *bytes, size_t size)
420 421 422 423 424
{
	int addridx;
	int ret = 0;

	for (addridx = addr; addridx < (addr + size); addridx += 4) {
A
Al Viro 已提交
425 426
		int v;
		ret = do_rom_fast_read(adapter, addridx, &v);
427 428
		if (ret != 0)
			break;
A
Al Viro 已提交
429
		*(__le32 *)bytes = cpu_to_le32(v);
430 431 432 433 434 435 436
		bytes += 4;
	}

	return ret;
}

int
437
netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
438 439 440 441
				u8 *bytes, size_t size)
{
	int ret;

442
	ret = netxen_rom_lock(adapter);
443 444 445 446 447 448 449 450 451
	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 已提交
452 453 454 455
int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
{
	int ret;

456
	if (netxen_rom_lock(adapter) != 0)
A
Amit S. Kale 已提交
457 458 459
		return -EIO;

	ret = do_rom_fast_read(adapter, addr, valp);
460 461 462 463
	netxen_rom_unlock(adapter);
	return ret;
}

A
Amit S. Kale 已提交
464 465 466 467 468 469
#define NETXEN_BOARDTYPE		0x4008
#define NETXEN_BOARDNUM 		0x400c
#define NETXEN_CHIPNUM			0x4010

int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
{
470
	int addr, val;
D
Dhananjay Phadke 已提交
471
	int i, n, init_delay = 0;
A
Amit S. Kale 已提交
472
	struct crb_addr_pair *buf;
D
Dhananjay Phadke 已提交
473
	unsigned offset;
474
	u32 off;
A
Amit S. Kale 已提交
475 476

	/* resetall */
477
	netxen_rom_lock(adapter);
478
	NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff);
D
Dhananjay Phadke 已提交
479
	netxen_rom_unlock(adapter);
A
Amit S. Kale 已提交
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495

	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");
	}

496 497
	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
		if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
D
Dhananjay Phadke 已提交
498
			(n != 0xcafecafe) ||
499 500 501
			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 已提交
502 503
			return -EIO;
		}
504 505 506 507 508 509 510 511
		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 已提交
512
		}
513 514 515 516 517 518 519 520 521 522 523 524 525
		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 已提交
526

527 528 529 530 531 532 533 534
	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 ||
535 536
		netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) {
			kfree(buf);
537
			return -EIO;
538
		}
539 540 541 542 543 544 545 546 547 548 549 550 551 552

		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",
553
					buf[i].addr);
554 555 556 557 558 559 560 561 562 563
			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))
564
				continue;
D
Dhananjay Phadke 已提交
565 566 567 568 569 570 571 572
			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;
573 574 575 576
			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 已提交
577
				continue;
578 579 580 581 582
			if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION2))
				continue;
			if ((off & 0x0ff00000) == NETXEN_CRB_SMB)
				continue;
		}
A
Amit S. Kale 已提交
583

584 585 586 587 588 589
		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 已提交
590
		init_delay = 1;
591 592 593
		/* 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 已提交
594
			init_delay = 1000;
595
			if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
A
Amit S. Kale 已提交
596
				/* hold xdma in reset also */
597
				buf[i].data = NETXEN_NIC_XDMA_RESET;
D
Dhananjay Phadke 已提交
598
				buf[i].data = 0x8000ff;
A
Amit S. Kale 已提交
599
			}
600
		}
A
Amit S. Kale 已提交
601

602
		NXWR32(adapter, off, buf[i].data);
A
Amit S. Kale 已提交
603

D
Dhananjay Phadke 已提交
604
		msleep(init_delay);
605 606
	}
	kfree(buf);
A
Amit S. Kale 已提交
607

608
	/* disable_peg_cache_all */
A
Amit S. Kale 已提交
609

610 611
	/* unreset_net_cache */
	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
612 613
		val = NXRD32(adapter, NETXEN_ROMUSB_GLB_SW_RESET);
		NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f));
A
Amit S. Kale 已提交
614
	}
615 616

	/* p2dn replyCount */
617
	NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
618
	/* disable_peg_cache 0 */
619
	NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8);
620
	/* disable_peg_cache 1 */
621
	NXWR32(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8);
622 623 624 625

	/* peg_clr_all */

	/* peg_clr 0 */
626 627
	NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0);
	NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0);
628
	/* peg_clr 1 */
629 630
	NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0);
	NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0);
631
	/* peg_clr 2 */
632 633
	NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0);
	NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0);
634
	/* peg_clr 3 */
635 636
	NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0);
	NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0);
A
Amit S. Kale 已提交
637 638 639
	return 0;
}

640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
int
netxen_need_fw_reset(struct netxen_adapter *adapter)
{
	u32 count, old_count;
	u32 val, version, major, minor, build;
	int i, timeout;
	u8 fw_type;

	/* NX2031 firmware doesn't support heartbit */
	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
		return 1;

	/* last attempt had failed */
	if (NXRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED)
		return 1;

	old_count = count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);

	for (i = 0; i < 10; i++) {

		timeout = msleep_interruptible(200);
		if (timeout) {
			NXWR32(adapter, CRB_CMDPEG_STATE,
					PHAN_INITIALIZE_FAILED);
			return -EINTR;
		}

		count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
		if (count != old_count)
			break;
	}

	/* firmware is dead */
	if (count == old_count)
		return 1;

	/* check if we have got newer or different file firmware */
	if (adapter->fw) {

		const struct firmware *fw = adapter->fw;

		val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
		version = NETXEN_DECODE_VERSION(val);

		major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
		minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
		build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);

		if (version > NETXEN_VERSION_CODE(major, minor, build))
			return 1;

		if (version == NETXEN_VERSION_CODE(major, minor, build)) {

			val = NXRD32(adapter, NETXEN_MIU_MN_CONTROL);
			fw_type = (val & 0x4) ?
				NX_P3_CT_ROMIMAGE : NX_P3_MN_ROMIMAGE;

			if (adapter->fw_type != fw_type)
				return 1;
		}
	}

	return 0;
}

static char *fw_name[] = {
	"nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin", "flash",
};

D
Dhananjay Phadke 已提交
709 710 711 712 713 714
int
netxen_load_firmware(struct netxen_adapter *adapter)
{
	u64 *ptr64;
	u32 i, flashaddr, size;
	const struct firmware *fw = adapter->fw;
715 716 717 718
	struct pci_dev *pdev = adapter->pdev;

	dev_info(&pdev->dev, "loading firmware from %s\n",
			fw_name[adapter->fw_type]);
D
Dhananjay Phadke 已提交
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785

	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
		NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1);

	if (fw) {
		__le64 data;

		size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8;

		ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START];
		flashaddr = NETXEN_BOOTLD_START;

		for (i = 0; i < size; i++) {
			data = cpu_to_le64(ptr64[i]);
			adapter->pci_mem_write(adapter, flashaddr, &data, 8);
			flashaddr += 8;
		}

		size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET];
		size = (__force u32)cpu_to_le32(size) / 8;

		ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START];
		flashaddr = NETXEN_IMAGE_START;

		for (i = 0; i < size; i++) {
			data = cpu_to_le64(ptr64[i]);

			if (adapter->pci_mem_write(adapter,
						flashaddr, &data, 8))
				return -EIO;

			flashaddr += 8;
		}
	} else {
		u32 data;

		size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4;
		flashaddr = NETXEN_BOOTLD_START;

		for (i = 0; i < size; i++) {
			if (netxen_rom_fast_read(adapter,
					flashaddr, (int *)&data) != 0)
				return -EIO;

			if (adapter->pci_mem_write(adapter,
						flashaddr, &data, 4))
				return -EIO;

			flashaddr += 4;
		}
	}
	msleep(1);

	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
		NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d);
	else {
		NXWR32(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff);
		NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 0);
	}

	return 0;
}

static int
netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
{
	__le32 val;
786
	u32 ver, min_ver, bios;
D
Dhananjay Phadke 已提交
787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803
	struct pci_dev *pdev = adapter->pdev;
	const struct firmware *fw = adapter->fw;

	if (fw->size < NX_FW_MIN_SIZE)
		return -EINVAL;

	val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]);
	if ((__force u32)val != NETXEN_BDINFO_MAGIC)
		return -EINVAL;

	val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);

	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
		min_ver = NETXEN_VERSION_CODE(4, 0, 216);
	else
		min_ver = NETXEN_VERSION_CODE(3, 4, 216);

804
	ver = NETXEN_DECODE_VERSION(val);
D
Dhananjay Phadke 已提交
805

806
	if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
D
Dhananjay Phadke 已提交
807 808
		dev_err(&pdev->dev,
				"%s: firmware version %d.%d.%d unsupported\n",
809
				fwname, _major(ver), _minor(ver), _build(ver));
D
Dhananjay Phadke 已提交
810 811 812 813 814 815 816 817 818 819 820 821 822 823 824
		return -EINVAL;
	}

	val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]);
	netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios);
	if ((__force u32)val != bios) {
		dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
				fwname);
		return -EINVAL;
	}

	/* check if flashed firmware is newer */
	if (netxen_rom_fast_read(adapter,
			NX_FW_VERSION_OFFSET, (int *)&val))
		return -EIO;
825 826 827 828
	val = NETXEN_DECODE_VERSION(val);
	if (val > ver) {
		dev_info(&pdev->dev, "%s: firmware is older than flash\n",
				fwname);
D
Dhananjay Phadke 已提交
829
		return -EINVAL;
830
	}
D
Dhananjay Phadke 已提交
831 832 833 834 835

	NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
	return 0;
}

836 837
static int
netxen_p3_has_mn(struct netxen_adapter *adapter)
D
Dhananjay Phadke 已提交
838 839 840 841 842 843
{
	u32 capability, flashed_ver;
	capability = 0;

	netxen_rom_fast_read(adapter,
			NX_FW_VERSION_OFFSET, (int *)&flashed_ver);
844 845
	flashed_ver = NETXEN_DECODE_VERSION(flashed_ver);

D
Dhananjay Phadke 已提交
846
	if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) {
847

D
Dhananjay Phadke 已提交
848
		capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY);
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
		if (capability & NX_PEG_TUNE_MN_PRESENT)
			return 1;
	}
	return 0;
}

void netxen_request_firmware(struct netxen_adapter *adapter)
{
	u8 fw_type;
	struct pci_dev *pdev = adapter->pdev;
	int rc = 0;

	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
		fw_type = NX_P2_MN_ROMIMAGE;
		goto request_fw;
D
Dhananjay Phadke 已提交
864 865
	}

866 867
	fw_type = netxen_p3_has_mn(adapter) ?
		NX_P3_MN_ROMIMAGE : NX_P3_CT_ROMIMAGE;
868

D
Dhananjay Phadke 已提交
869 870 871
request_fw:
	rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev);
	if (rc != 0) {
872
		if (fw_type == NX_P3_MN_ROMIMAGE) {
D
Dhananjay Phadke 已提交
873
			msleep(1);
874 875
			fw_type = NX_P3_CT_ROMIMAGE;
			goto request_fw;
D
Dhananjay Phadke 已提交
876 877
		}

878
		fw_type = NX_FLASH_ROMIMAGE;
D
Dhananjay Phadke 已提交
879 880 881 882 883 884 885 886
		adapter->fw = NULL;
		goto done;
	}

	rc = netxen_validate_firmware(adapter, fw_name[fw_type]);
	if (rc != 0) {
		release_firmware(adapter->fw);

887
		if (fw_type == NX_P3_MN_ROMIMAGE) {
D
Dhananjay Phadke 已提交
888
			msleep(1);
889 890
			fw_type = NX_P3_CT_ROMIMAGE;
			goto request_fw;
D
Dhananjay Phadke 已提交
891 892
		}

893
		fw_type = NX_FLASH_ROMIMAGE;
D
Dhananjay Phadke 已提交
894 895 896 897 898
		adapter->fw = NULL;
		goto done;
	}

done:
899
	adapter->fw_type = fw_type;
D
Dhananjay Phadke 已提交
900 901 902 903 904 905 906 907
}


void
netxen_release_firmware(struct netxen_adapter *adapter)
{
	if (adapter->fw)
		release_firmware(adapter->fw);
908
	adapter->fw = NULL;
D
Dhananjay Phadke 已提交
909 910
}

911
int netxen_init_dummy_dma(struct netxen_adapter *adapter)
912
{
913 914
	u64 addr;
	u32 hi, lo;
915

916 917 918 919
	if (!NX_IS_REVISION_P2(adapter->ahw.revision_id))
		return 0;

	adapter->dummy_dma.addr = pci_alloc_consistent(adapter->pdev,
920 921 922
				 NETXEN_HOST_DUMMY_DMA_SIZE,
				 &adapter->dummy_dma.phys_addr);
	if (adapter->dummy_dma.addr == NULL) {
923 924
		dev_err(&adapter->pdev->dev,
			"ERROR: Could not allocate dummy DMA memory\n");
925 926 927 928 929 930 931
		return -ENOMEM;
	}

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

932 933
	NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
	NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
934 935 936 937

	return 0;
}

938 939 940 941 942 943 944 945 946
/*
 * NetXen DMA watchdog control:
 *
 *	Bit 0		: enabled => R/O: 1 watchdog active, 0 inactive
 *	Bit 1		: disable_request => 1 req disable dma watchdog
 *	Bit 2		: enable_request =>  1 req enable dma watchdog
 *	Bit 3-31	: unused
 */
void netxen_free_dummy_dma(struct netxen_adapter *adapter)
947
{
D
Dhananjay Phadke 已提交
948
	int i = 100;
949 950 951 952
	u32 ctrl;

	if (!NX_IS_REVISION_P2(adapter->ahw.revision_id))
		return;
D
Dhananjay Phadke 已提交
953 954 955

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

957 958 959 960 961 962
	ctrl = NXRD32(adapter, NETXEN_DMA_WATCHDOG_CTRL);
	if ((ctrl & 0x1) != 0) {
		NXWR32(adapter, NETXEN_DMA_WATCHDOG_CTRL, (ctrl | 0x2));

		while ((ctrl & 0x1) != 0) {

963
			msleep(50);
964 965 966 967

			ctrl = NXRD32(adapter, NETXEN_DMA_WATCHDOG_CTRL);

			if (--i == 0)
968
				break;
969
		};
D
Dhananjay Phadke 已提交
970
	}
971

D
Dhananjay Phadke 已提交
972 973 974 975 976 977
	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;
978 979
	} else
		dev_err(&adapter->pdev->dev, "dma_watchdog_shutdown failed\n");
980 981
}

982
int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
A
Amit S. Kale 已提交
983 984
{
	u32 val = 0;
985
	int retries = 60;
A
Amit S. Kale 已提交
986

987 988 989 990 991
	if (pegtune_val)
		return 0;

	do {
		val = NXRD32(adapter, CRB_CMDPEG_STATE);
992

993 994 995 996 997 998 999 1000 1001
		switch (val) {
		case PHAN_INITIALIZE_COMPLETE:
		case PHAN_INITIALIZE_ACK:
			return 0;
		case PHAN_INITIALIZE_FAILED:
			goto out_err;
		default:
			break;
		}
1002

1003
		msleep(500);
1004

1005
	} while (--retries);
1006

1007
	NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
1008

1009 1010 1011
out_err:
	dev_warn(&adapter->pdev->dev, "firmware init failed\n");
	return -EIO;
A
Amit S. Kale 已提交
1012 1013
}

1014 1015
static int
netxen_receive_peg_ready(struct netxen_adapter *adapter)
1016 1017 1018 1019 1020
{
	u32 val = 0;
	int retries = 2000;

	do {
1021
		val = NXRD32(adapter, CRB_RCVPEG_STATE);
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038

		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;
}

1039 1040 1041 1042 1043 1044 1045 1046
int netxen_init_firmware(struct netxen_adapter *adapter)
{
	int err;

	err = netxen_receive_peg_ready(adapter);
	if (err)
		return err;

1047 1048 1049 1050
	NXWR32(adapter, CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT);
	NXWR32(adapter, CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC);
	NXWR32(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
	NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
1051 1052 1053 1054

	return err;
}

1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
static void
netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg)
{
	u32 cable_OUI;
	u16 cable_len;
	u16 link_speed;
	u8  link_status, module, duplex, autoneg;
	struct net_device *netdev = adapter->netdev;

	adapter->has_link_events = 1;

	cable_OUI = msg->body[1] & 0xffffffff;
	cable_len = (msg->body[1] >> 32) & 0xffff;
	link_speed = (msg->body[1] >> 48) & 0xffff;

	link_status = msg->body[2] & 0xff;
	duplex = (msg->body[2] >> 16) & 0xff;
	autoneg = (msg->body[2] >> 24) & 0xff;

	module = (msg->body[2] >> 8) & 0xff;
	if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) {
		printk(KERN_INFO "%s: unsupported cable: OUI 0x%x, length %d\n",
				netdev->name, cable_OUI, cable_len);
	} else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) {
		printk(KERN_INFO "%s: unsupported cable length %d\n",
				netdev->name, cable_len);
	}

	netxen_advert_link_change(adapter, link_status);

	/* update link parameters */
	if (duplex == LINKEVENT_FULL_DUPLEX)
		adapter->link_duplex = DUPLEX_FULL;
	else
		adapter->link_duplex = DUPLEX_HALF;
	adapter->module_type = module;
	adapter->link_autoneg = autoneg;
	adapter->link_speed = link_speed;
}

static void
netxen_handle_fw_message(int desc_cnt, int index,
		struct nx_host_sds_ring *sds_ring)
{
	nx_fw_msg_t msg;
	struct status_desc *desc;
	int i = 0, opcode;

	while (desc_cnt > 0 && i < 8) {
		desc = &sds_ring->desc_head[index];
		msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
		msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);

		index = get_next_index(index, sds_ring->num_desc);
		desc_cnt--;
	}

	opcode = netxen_get_nic_msg_opcode(msg.body[0]);
	switch (opcode) {
	case NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
		netxen_handle_linkevent(sds_ring->adapter, &msg);
		break;
	default:
		break;
	}
}

1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
static int
netxen_alloc_rx_skb(struct netxen_adapter *adapter,
		struct nx_host_rds_ring *rds_ring,
		struct netxen_rx_buffer *buffer)
{
	struct sk_buff *skb;
	dma_addr_t dma;
	struct pci_dev *pdev = adapter->pdev;

	buffer->skb = dev_alloc_skb(rds_ring->skb_size);
	if (!buffer->skb)
		return 1;

	skb = buffer->skb;

	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);
		buffer->skb = NULL;
		return 1;
	}

	buffer->skb = skb;
	buffer->dma = dma;
	buffer->state = NETXEN_BUFFER_BUSY;

	return 0;
}

1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
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;
	return skb;
}

1185
static struct netxen_rx_buffer *
D
Dhananjay Phadke 已提交
1186
netxen_process_rcv(struct netxen_adapter *adapter,
1187 1188
		struct nx_host_sds_ring *sds_ring,
		int ring, u64 sts_data0)
A
Amit S. Kale 已提交
1189
{
1190
	struct net_device *netdev = adapter->netdev;
1191
	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
A
Amit S. Kale 已提交
1192 1193
	struct netxen_rx_buffer *buffer;
	struct sk_buff *skb;
1194 1195
	struct nx_host_rds_ring *rds_ring;
	int index, length, cksum, pkt_offset;
A
Amit S. Kale 已提交
1196

1197 1198 1199 1200 1201 1202 1203
	if (unlikely(ring >= adapter->max_rds_rings))
		return NULL;

	rds_ring = &recv_ctx->rds_rings[ring];

	index = netxen_get_sts_refhandle(sts_data0);
	if (unlikely(index >= rds_ring->num_desc))
1204
		return NULL;
1205

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

1208 1209 1210 1211
	length = netxen_get_sts_totallength(sts_data0);
	cksum  = netxen_get_sts_status(sts_data0);
	pkt_offset = netxen_get_sts_pkt_offset(sts_data0);

1212 1213
	skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum);
	if (!skb)
1214
		return buffer;
D
Dhananjay Phadke 已提交
1215

D
Dhananjay Phadke 已提交
1216 1217 1218 1219
	if (length > rds_ring->skb_size)
		skb_put(skb, rds_ring->skb_size);
	else
		skb_put(skb, length);
1220

D
Dhananjay Phadke 已提交
1221 1222 1223

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

1225
	skb->truesize = skb->len + sizeof(struct sk_buff);
A
Amit S. Kale 已提交
1226 1227
	skb->protocol = eth_type_trans(skb, netdev);

A
Amit Kumar Salecha 已提交
1228
	napi_gro_receive(&sds_ring->napi, skb);
1229

1230
	adapter->stats.rx_pkts++;
D
Dhananjay Phadke 已提交
1231
	adapter->stats.rxbytes += length;
1232 1233

	return buffer;
A
Amit S. Kale 已提交
1234 1235
}

1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
#define TCP_HDR_SIZE            20
#define TCP_TS_OPTION_SIZE      12
#define TCP_TS_HDR_SIZE         (TCP_HDR_SIZE + TCP_TS_OPTION_SIZE)

static struct netxen_rx_buffer *
netxen_process_lro(struct netxen_adapter *adapter,
		struct nx_host_sds_ring *sds_ring,
		int ring, u64 sts_data0, u64 sts_data1)
{
	struct net_device *netdev = adapter->netdev;
	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
	struct netxen_rx_buffer *buffer;
	struct sk_buff *skb;
	struct nx_host_rds_ring *rds_ring;
	struct iphdr *iph;
	struct tcphdr *th;
	bool push, timestamp;
	int l2_hdr_offset, l4_hdr_offset;
	int index;
	u16 lro_length, length, data_offset;
	u32 seq_number;

	if (unlikely(ring > adapter->max_rds_rings))
		return NULL;

	rds_ring = &recv_ctx->rds_rings[ring];

	index = netxen_get_lro_sts_refhandle(sts_data0);
	if (unlikely(index > rds_ring->num_desc))
		return NULL;

	buffer = &rds_ring->rx_buf_arr[index];

	timestamp = netxen_get_lro_sts_timestamp(sts_data0);
	lro_length = netxen_get_lro_sts_length(sts_data0);
	l2_hdr_offset = netxen_get_lro_sts_l2_hdr_offset(sts_data0);
	l4_hdr_offset = netxen_get_lro_sts_l4_hdr_offset(sts_data0);
	push = netxen_get_lro_sts_push_flag(sts_data0);
	seq_number = netxen_get_lro_sts_seq_number(sts_data1);

	skb = netxen_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
	if (!skb)
		return buffer;

	if (timestamp)
		data_offset = l4_hdr_offset + TCP_TS_HDR_SIZE;
	else
		data_offset = l4_hdr_offset + TCP_HDR_SIZE;

	skb_put(skb, lro_length + data_offset);

1287
	skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb);
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301

	skb_pull(skb, l2_hdr_offset);
	skb->protocol = eth_type_trans(skb, netdev);

	iph = (struct iphdr *)skb->data;
	th = (struct tcphdr *)(skb->data + (iph->ihl << 2));

	length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
	iph->tot_len = htons(length);
	iph->check = 0;
	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
	th->psh = push;
	th->seq = htonl(seq_number);

1302 1303
	length = skb->len;

1304 1305
	netif_receive_skb(skb);

1306 1307 1308
	adapter->stats.lro_pkts++;
	adapter->stats.rxbytes += length;

1309 1310 1311
	return buffer;
}

1312 1313 1314
#define netxen_merge_rx_buffers(list, head) \
	do { list_splice_tail_init(list, head); } while (0);

1315
int
1316
netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max)
A
Amit S. Kale 已提交
1317
{
1318 1319 1320 1321
	struct netxen_adapter *adapter = sds_ring->adapter;

	struct list_head *cur;

D
Dhananjay Phadke 已提交
1322
	struct status_desc *desc;
1323 1324 1325 1326
	struct netxen_rx_buffer *rxbuf;

	u32 consumer = sds_ring->consumer;

D
Dhananjay Phadke 已提交
1327
	int count = 0;
1328 1329
	u64 sts_data0, sts_data1;
	int opcode, ring = 0, desc_cnt;
A
Amit S. Kale 已提交
1330 1331

	while (count < max) {
1332
		desc = &sds_ring->desc_head[consumer];
1333
		sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
D
Dhananjay Phadke 已提交
1334

1335
		if (!(sts_data0 & STATUS_OWNER_HOST))
A
Amit S. Kale 已提交
1336
			break;
1337

1338
		desc_cnt = netxen_get_sts_desc_cnt(sts_data0);
1339

1340
		opcode = netxen_get_sts_opcode(sts_data0);
1341

1342 1343 1344
		switch (opcode) {
		case NETXEN_NIC_RXPKT_DESC:
		case NETXEN_OLD_RXPKT_DESC:
1345
		case NETXEN_NIC_SYN_OFFLOAD:
1346 1347 1348 1349 1350 1351 1352 1353 1354
			ring = netxen_get_sts_type(sts_data0);
			rxbuf = netxen_process_rcv(adapter, sds_ring,
					ring, sts_data0);
			break;
		case NETXEN_NIC_LRO_DESC:
			ring = netxen_get_lro_sts_type(sts_data0);
			sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
			rxbuf = netxen_process_lro(adapter, sds_ring,
					ring, sts_data0, sts_data1);
1355 1356 1357 1358 1359 1360 1361 1362 1363
			break;
		case NETXEN_NIC_RESPONSE_DESC:
			netxen_handle_fw_message(desc_cnt, consumer, sds_ring);
		default:
			goto skip;
		}

		WARN_ON(desc_cnt > 1);

1364 1365 1366
		if (rxbuf)
			list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);

1367 1368 1369 1370 1371 1372 1373
skip:
		for (; desc_cnt > 0; desc_cnt--) {
			desc = &sds_ring->desc_head[consumer];
			desc->status_desc_data[0] =
				cpu_to_le64(STATUS_OWNER_PHANTOM);
			consumer = get_next_index(consumer, sds_ring->num_desc);
		}
A
Amit S. Kale 已提交
1374 1375
		count++;
	}
D
Dhananjay Phadke 已提交
1376

1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
		struct nx_host_rds_ring *rds_ring =
			&adapter->recv_ctx.rds_rings[ring];

		if (!list_empty(&sds_ring->free_list[ring])) {
			list_for_each(cur, &sds_ring->free_list[ring]) {
				rxbuf = list_entry(cur,
						struct netxen_rx_buffer, list);
				netxen_alloc_rx_skb(adapter, rds_ring, rxbuf);
			}
			spin_lock(&rds_ring->lock);
			netxen_merge_rx_buffers(&sds_ring->free_list[ring],
						&rds_ring->free_list);
			spin_unlock(&rds_ring->lock);
		}

		netxen_post_rx_buffers_nodb(adapter, rds_ring);
	}
A
Amit S. Kale 已提交
1395 1396

	if (count) {
1397
		sds_ring->consumer = consumer;
1398
		NXWR32(adapter, sds_ring->crb_sts_consumer, consumer);
A
Amit S. Kale 已提交
1399 1400 1401 1402 1403 1404
	}

	return count;
}

/* Process Command status ring */
D
Dhananjay Phadke 已提交
1405
int netxen_process_cmd_ring(struct netxen_adapter *adapter)
A
Amit S. Kale 已提交
1406
{
1407
	u32 sw_consumer, hw_consumer;
1408
	int count = 0, i;
A
Amit S. Kale 已提交
1409
	struct netxen_cmd_buffer *buffer;
1410 1411
	struct pci_dev *pdev = adapter->pdev;
	struct net_device *netdev = adapter->netdev;
A
Amit S. Kale 已提交
1412
	struct netxen_skb_frag *frag;
1413
	int done = 0;
1414
	struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
A
Amit S. Kale 已提交
1415

1416 1417 1418
	if (!spin_trylock(&adapter->tx_clean_lock))
		return 1;

1419 1420
	sw_consumer = tx_ring->sw_consumer;
	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
A
Amit S. Kale 已提交
1421

1422 1423
	while (sw_consumer != hw_consumer) {
		buffer = &tx_ring->cmd_buf_arr[sw_consumer];
1424 1425
		if (buffer->skb) {
			frag = &buffer->frag_array[0];
A
Amit S. Kale 已提交
1426 1427
			pci_unmap_single(pdev, frag->dma, frag->length,
					 PCI_DMA_TODEVICE);
1428
			frag->dma = 0ULL;
A
Amit S. Kale 已提交
1429 1430 1431 1432
			for (i = 1; i < buffer->frag_count; i++) {
				frag++;	/* Get the next frag */
				pci_unmap_page(pdev, frag->dma, frag->length,
					       PCI_DMA_TODEVICE);
1433
				frag->dma = 0ULL;
A
Amit S. Kale 已提交
1434 1435
			}

1436
			adapter->stats.xmitfinished++;
1437 1438
			dev_kfree_skb_any(buffer->skb);
			buffer->skb = NULL;
A
Amit S. Kale 已提交
1439 1440
		}

1441
		sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
1442 1443
		if (++count >= MAX_STATUS_HANDLE)
			break;
A
Amit S. Kale 已提交
1444 1445
	}

1446
	if (count && netif_running(netdev)) {
1447 1448
		tx_ring->sw_consumer = sw_consumer;

1449
		smp_mb();
1450

1451
		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
1452
			__netif_tx_lock(tx_ring->txq, smp_processor_id());
1453 1454
			if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
				netif_wake_queue(netdev);
1455
			__netif_tx_unlock(tx_ring->txq);
A
Amit S. Kale 已提交
1456 1457
		}
	}
1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470
	/*
	 * 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.
	 */
1471 1472
	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
	done = (sw_consumer == hw_consumer);
1473
	spin_unlock(&adapter->tx_clean_lock);
A
Amit S. Kale 已提交
1474

1475
	return (done);
A
Amit S. Kale 已提交
1476 1477
}

1478
void
1479 1480
netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
	struct nx_host_rds_ring *rds_ring)
A
Amit S. Kale 已提交
1481 1482 1483
{
	struct rcv_desc *pdesc;
	struct netxen_rx_buffer *buffer;
1484
	int producer, count = 0;
1485
	netxen_ctx_msg msg = 0;
1486
	struct list_head *head;
A
Amit S. Kale 已提交
1487

D
Dhananjay Phadke 已提交
1488
	producer = rds_ring->producer;
1489

1490 1491
	spin_lock(&rds_ring->lock);
	head = &rds_ring->free_list;
1492 1493
	while (!list_empty(head)) {

1494
		buffer = list_entry(head->next, struct netxen_rx_buffer, list);
1495

1496 1497 1498
		if (!buffer->skb) {
			if (netxen_alloc_rx_skb(adapter, rds_ring, buffer))
				break;
1499 1500 1501
		}

		count++;
1502 1503
		list_del(&buffer->list);

1504
		/* make a rcv descriptor  */
1505
		pdesc = &rds_ring->desc_head[producer];
1506
		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
A
Amit S. Kale 已提交
1507
		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
D
Dhananjay Phadke 已提交
1508
		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
1509

1510
		producer = get_next_index(producer, rds_ring->num_desc);
1511
	}
1512
	spin_unlock(&rds_ring->lock);
D
Dhananjay Phadke 已提交
1513

1514
	if (count) {
D
Dhananjay Phadke 已提交
1515
		rds_ring->producer = producer;
1516
		NXWR32(adapter, rds_ring->crb_rcv_producer,
1517
				(producer-1) & (rds_ring->num_desc-1));
D
Dhananjay Phadke 已提交
1518

1519
		if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
1520 1521 1522
			/*
			 * Write a doorbell msg to tell phanmon of change in
			 * receive ring producer
D
Dhananjay Phadke 已提交
1523
			 * Only for firmware version < 4.0.0
1524 1525 1526 1527
			 */
			netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID);
			netxen_set_msg_privid(msg);
			netxen_set_msg_count(msg,
1528 1529
					     ((producer - 1) &
					      (rds_ring->num_desc - 1)));
1530
			netxen_set_msg_ctxid(msg, adapter->portnum);
1531 1532 1533 1534
			netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid));
			writel(msg,
			       DB_NORMALIZE(adapter,
					    NETXEN_RCV_PRODUCER_OFFSET));
D
Dhananjay Phadke 已提交
1535
		}
1536 1537 1538
	}
}

1539
static void
1540 1541
netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
		struct nx_host_rds_ring *rds_ring)
1542 1543 1544
{
	struct rcv_desc *pdesc;
	struct netxen_rx_buffer *buffer;
1545
	int producer, count = 0;
1546
	struct list_head *head;
1547

D
Dhananjay Phadke 已提交
1548
	producer = rds_ring->producer;
1549 1550 1551
	if (!spin_trylock(&rds_ring->lock))
		return;

1552 1553 1554
	head = &rds_ring->free_list;
	while (!list_empty(head)) {

1555
		buffer = list_entry(head->next, struct netxen_rx_buffer, list);
1556

1557 1558 1559
		if (!buffer->skb) {
			if (netxen_alloc_rx_skb(adapter, rds_ring, buffer))
				break;
1560 1561 1562
		}

		count++;
1563 1564
		list_del(&buffer->list);

A
Amit S. Kale 已提交
1565
		/* make a rcv descriptor  */
1566
		pdesc = &rds_ring->desc_head[producer];
A
Amit S. Kale 已提交
1567
		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
D
Dhananjay Phadke 已提交
1568
		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
A
Amit S. Kale 已提交
1569
		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
1570

1571
		producer = get_next_index(producer, rds_ring->num_desc);
A
Amit S. Kale 已提交
1572 1573 1574
	}

	if (count) {
D
Dhananjay Phadke 已提交
1575
		rds_ring->producer = producer;
1576
		NXWR32(adapter, rds_ring->crb_rcv_producer,
1577
				(producer - 1) & (rds_ring->num_desc - 1));
A
Amit S. Kale 已提交
1578
	}
1579
	spin_unlock(&rds_ring->lock);
A
Amit S. Kale 已提交
1580 1581 1582 1583 1584
}

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