blob: 1b8f79f7f8ce83a606c8acfac936500a82c99f87 [file] [log] [blame]
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001/*
Dhananjay Phadke5d242f12009-02-25 15:57:56 +00002 * Copyright (C) 2003 - 2009 NetXen, Inc.
Amit S. Kale3d396eb2006-10-21 15:33:03 -04003 * All rights reserved.
Amit S. Kale80922fb2006-12-04 09:18:00 -08004 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -04005 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
Amit S. Kale80922fb2006-12-04 09:18:00 -08009 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -040010 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Amit S. Kale80922fb2006-12-04 09:18:00 -080014 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -040015 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 * MA 02111-1307, USA.
Amit S. Kale80922fb2006-12-04 09:18:00 -080019 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -040020 * The full GNU General Public License is included in this distribution
21 * in the file called LICENSE.
Amit S. Kale80922fb2006-12-04 09:18:00 -080022 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -040023 * Contact Information:
24 * info@netxen.com
Dhananjay Phadke5d242f12009-02-25 15:57:56 +000025 * NetXen Inc,
26 * 18922 Forge Drive
27 * Cupertino, CA 95014-0701
Amit S. Kale3d396eb2006-10-21 15:33:03 -040028 *
29 */
30
31#include <linux/netdevice.h>
32#include <linux/delay.h>
33#include "netxen_nic.h"
34#include "netxen_nic_hw.h"
Amit S. Kale3d396eb2006-10-21 15:33:03 -040035#include "netxen_nic_phan_reg.h"
36
37struct crb_addr_pair {
Linsys Contractor Mithlesh Thukrale0e20a12007-02-28 05:16:40 -080038 u32 addr;
39 u32 data;
Amit S. Kale3d396eb2006-10-21 15:33:03 -040040};
41
42#define NETXEN_MAX_CRB_XFORM 60
43static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
Linsys Contractor Mithlesh Thukrale0e20a12007-02-28 05:16:40 -080044#define NETXEN_ADDR_ERROR (0xffffffff)
Amit S. Kale3d396eb2006-10-21 15:33:03 -040045
46#define crb_addr_transform(name) \
47 crb_addr_xform[NETXEN_HW_PX_MAP_CRB_##name] = \
48 NETXEN_HW_CRB_HUB_AGT_ADR_##name << 20
49
Amit S. Kalecb8011a2006-11-29 09:00:10 -080050#define NETXEN_NIC_XDMA_RESET 0x8000ff
51
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +000052static void
53netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid);
Adrian Bunk993fb902007-11-05 18:07:31 +010054
Amit S. Kale3d396eb2006-10-21 15:33:03 -040055static void crb_addr_transform_setup(void)
56{
57 crb_addr_transform(XDMA);
58 crb_addr_transform(TIMR);
59 crb_addr_transform(SRE);
60 crb_addr_transform(SQN3);
61 crb_addr_transform(SQN2);
62 crb_addr_transform(SQN1);
63 crb_addr_transform(SQN0);
64 crb_addr_transform(SQS3);
65 crb_addr_transform(SQS2);
66 crb_addr_transform(SQS1);
67 crb_addr_transform(SQS0);
68 crb_addr_transform(RPMX7);
69 crb_addr_transform(RPMX6);
70 crb_addr_transform(RPMX5);
71 crb_addr_transform(RPMX4);
72 crb_addr_transform(RPMX3);
73 crb_addr_transform(RPMX2);
74 crb_addr_transform(RPMX1);
75 crb_addr_transform(RPMX0);
76 crb_addr_transform(ROMUSB);
77 crb_addr_transform(SN);
78 crb_addr_transform(QMN);
79 crb_addr_transform(QMS);
80 crb_addr_transform(PGNI);
81 crb_addr_transform(PGND);
82 crb_addr_transform(PGN3);
83 crb_addr_transform(PGN2);
84 crb_addr_transform(PGN1);
85 crb_addr_transform(PGN0);
86 crb_addr_transform(PGSI);
87 crb_addr_transform(PGSD);
88 crb_addr_transform(PGS3);
89 crb_addr_transform(PGS2);
90 crb_addr_transform(PGS1);
91 crb_addr_transform(PGS0);
92 crb_addr_transform(PS);
93 crb_addr_transform(PH);
94 crb_addr_transform(NIU);
95 crb_addr_transform(I2Q);
96 crb_addr_transform(EG);
97 crb_addr_transform(MN);
98 crb_addr_transform(MS);
99 crb_addr_transform(CAS2);
100 crb_addr_transform(CAS1);
101 crb_addr_transform(CAS0);
102 crb_addr_transform(CAM);
103 crb_addr_transform(C2C1);
104 crb_addr_transform(C2C0);
Amit S. Kale1fcca1a2007-02-05 07:35:26 -0800105 crb_addr_transform(SMB);
Dhananjay Phadkee4c93c82008-07-21 19:44:02 -0700106 crb_addr_transform(OCM0);
107 crb_addr_transform(I2C0);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400108}
109
110int netxen_init_firmware(struct netxen_adapter *adapter)
111{
112 u32 state = 0, loops = 0, err = 0;
113
114 /* Window 1 call */
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700115 state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400116
117 if (state == PHAN_INITIALIZE_ACK)
118 return 0;
119
120 while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) {
Dhananjay Phadke29566402008-07-21 19:44:04 -0700121 msleep(1);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400122 /* Window 1 call */
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700123 state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400124
125 loops++;
126 }
127 if (loops >= 2000) {
128 printk(KERN_ERR "Cmd Peg initialization not complete:%x.\n",
129 state);
130 err = -EIO;
131 return err;
132 }
133 /* Window 1 call */
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700134 adapter->pci_write_normalize(adapter,
135 CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT);
136 adapter->pci_write_normalize(adapter,
137 CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC);
138 adapter->pci_write_normalize(adapter,
139 CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
140 adapter->pci_write_normalize(adapter,
141 CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400142
143 return err;
144}
145
Dhananjay Phadke29566402008-07-21 19:44:04 -0700146void netxen_release_rx_buffers(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400147{
Dhananjay Phadke29566402008-07-21 19:44:04 -0700148 struct netxen_recv_context *recv_ctx;
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -0700149 struct nx_host_rds_ring *rds_ring;
Dhananjay Phadke29566402008-07-21 19:44:04 -0700150 struct netxen_rx_buffer *rx_buf;
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000151 int i, ring;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400152
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000153 recv_ctx = &adapter->recv_ctx;
154 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
155 rds_ring = &recv_ctx->rds_rings[ring];
Dhananjay Phadke438627c2009-03-13 14:52:03 +0000156 for (i = 0; i < rds_ring->num_desc; ++i) {
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000157 rx_buf = &(rds_ring->rx_buf_arr[i]);
158 if (rx_buf->state == NETXEN_BUFFER_FREE)
159 continue;
160 pci_unmap_single(adapter->pdev,
161 rx_buf->dma,
162 rds_ring->dma_size,
163 PCI_DMA_FROMDEVICE);
164 if (rx_buf->skb != NULL)
165 dev_kfree_skb_any(rx_buf->skb);
Dhananjay Phadke29566402008-07-21 19:44:04 -0700166 }
167 }
168}
169
170void netxen_release_tx_buffers(struct netxen_adapter *adapter)
171{
172 struct netxen_cmd_buffer *cmd_buf;
173 struct netxen_skb_frag *buffrag;
174 int i, j;
175
176 cmd_buf = adapter->cmd_buf_arr;
Dhananjay Phadke438627c2009-03-13 14:52:03 +0000177 for (i = 0; i < adapter->num_txd; i++) {
Dhananjay Phadke29566402008-07-21 19:44:04 -0700178 buffrag = cmd_buf->frag_array;
179 if (buffrag->dma) {
180 pci_unmap_single(adapter->pdev, buffrag->dma,
181 buffrag->length, PCI_DMA_TODEVICE);
182 buffrag->dma = 0ULL;
183 }
184 for (j = 0; j < cmd_buf->frag_count; j++) {
185 buffrag++;
186 if (buffrag->dma) {
187 pci_unmap_page(adapter->pdev, buffrag->dma,
188 buffrag->length,
189 PCI_DMA_TODEVICE);
190 buffrag->dma = 0ULL;
191 }
192 }
Dhananjay Phadke29566402008-07-21 19:44:04 -0700193 if (cmd_buf->skb) {
194 dev_kfree_skb_any(cmd_buf->skb);
195 cmd_buf->skb = NULL;
196 }
197 cmd_buf++;
198 }
199}
200
201void netxen_free_sw_resources(struct netxen_adapter *adapter)
202{
203 struct netxen_recv_context *recv_ctx;
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -0700204 struct nx_host_rds_ring *rds_ring;
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000205 int ring;
Dhananjay Phadke29566402008-07-21 19:44:04 -0700206
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000207 recv_ctx = &adapter->recv_ctx;
208 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
209 rds_ring = &recv_ctx->rds_rings[ring];
210 if (rds_ring->rx_buf_arr) {
211 vfree(rds_ring->rx_buf_arr);
212 rds_ring->rx_buf_arr = NULL;
Dhananjay Phadke29566402008-07-21 19:44:04 -0700213 }
214 }
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000215
Dhananjay Phadke29566402008-07-21 19:44:04 -0700216 if (adapter->cmd_buf_arr)
217 vfree(adapter->cmd_buf_arr);
218 return;
219}
220
221int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
222{
223 struct netxen_recv_context *recv_ctx;
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -0700224 struct nx_host_rds_ring *rds_ring;
Dhananjay Phadke29566402008-07-21 19:44:04 -0700225 struct netxen_rx_buffer *rx_buf;
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000226 int ring, i, num_rx_bufs;
Dhananjay Phadke29566402008-07-21 19:44:04 -0700227
228 struct netxen_cmd_buffer *cmd_buf_arr;
229 struct net_device *netdev = adapter->netdev;
230
231 cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
232 if (cmd_buf_arr == NULL) {
233 printk(KERN_ERR "%s: Failed to allocate cmd buffer ring\n",
234 netdev->name);
235 return -ENOMEM;
236 }
237 memset(cmd_buf_arr, 0, TX_RINGSIZE);
238 adapter->cmd_buf_arr = cmd_buf_arr;
239
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000240 recv_ctx = &adapter->recv_ctx;
241 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
242 rds_ring = &recv_ctx->rds_rings[ring];
Dhananjay Phadke438627c2009-03-13 14:52:03 +0000243 switch (ring) {
244 case RCV_RING_NORMAL:
245 rds_ring->num_desc = adapter->num_rxd;
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000246 if (adapter->ahw.cut_through) {
247 rds_ring->dma_size =
248 NX_CT_DEFAULT_RX_BUF_LEN;
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -0700249 rds_ring->skb_size =
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000250 NX_CT_DEFAULT_RX_BUF_LEN;
251 } else {
252 rds_ring->dma_size = RX_DMA_MAP_LEN;
253 rds_ring->skb_size =
254 MAX_RX_BUFFER_LENGTH;
255 }
256 break;
Dhananjay Phadke29566402008-07-21 19:44:04 -0700257
Dhananjay Phadke438627c2009-03-13 14:52:03 +0000258 case RCV_RING_JUMBO:
259 rds_ring->num_desc = adapter->num_jumbo_rxd;
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000260 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
261 rds_ring->dma_size =
262 NX_P3_RX_JUMBO_BUF_MAX_LEN;
263 else
264 rds_ring->dma_size =
265 NX_P2_RX_JUMBO_BUF_MAX_LEN;
266 rds_ring->skb_size =
267 rds_ring->dma_size + NET_IP_ALIGN;
268 break;
Dhananjay Phadke29566402008-07-21 19:44:04 -0700269
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000270 case RCV_RING_LRO:
Dhananjay Phadke438627c2009-03-13 14:52:03 +0000271 rds_ring->num_desc = adapter->num_lro_rxd;
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000272 rds_ring->dma_size = RX_LRO_DMA_MAP_LEN;
273 rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
274 break;
275
276 }
277 rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
278 vmalloc(RCV_BUFFSIZE);
279 if (rds_ring->rx_buf_arr == NULL) {
280 printk(KERN_ERR "%s: Failed to allocate "
281 "rx buffer ring %d\n",
282 netdev->name, ring);
283 /* free whatever was already allocated */
284 goto err_out;
285 }
286 memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE);
287 INIT_LIST_HEAD(&rds_ring->free_list);
288 /*
289 * Now go through all of them, set reference handles
290 * and put them in the queues.
291 */
Dhananjay Phadke438627c2009-03-13 14:52:03 +0000292 num_rx_bufs = rds_ring->num_desc;
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000293 rx_buf = rds_ring->rx_buf_arr;
294 for (i = 0; i < num_rx_bufs; i++) {
295 list_add_tail(&rx_buf->list,
296 &rds_ring->free_list);
297 rx_buf->ref_handle = i;
298 rx_buf->state = NETXEN_BUFFER_FREE;
299 rx_buf++;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400300 }
301 }
Dhananjay Phadke29566402008-07-21 19:44:04 -0700302
303 return 0;
304
305err_out:
306 netxen_free_sw_resources(adapter);
307 return -ENOMEM;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400308}
309
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400310void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
311{
Dhananjay Phadke1e2d0052009-03-09 08:50:56 +0000312 switch (adapter->ahw.port_type) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400313 case NETXEN_NIC_GBE:
Amit S. Kale80922fb2006-12-04 09:18:00 -0800314 adapter->enable_phy_interrupts =
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400315 netxen_niu_gbe_enable_phy_interrupts;
Amit S. Kale80922fb2006-12-04 09:18:00 -0800316 adapter->disable_phy_interrupts =
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400317 netxen_niu_gbe_disable_phy_interrupts;
Amit S. Kale80922fb2006-12-04 09:18:00 -0800318 adapter->macaddr_set = netxen_niu_macaddr_set;
319 adapter->set_mtu = netxen_nic_set_mtu_gb;
320 adapter->set_promisc = netxen_niu_set_promiscuous_mode;
Amit S. Kale80922fb2006-12-04 09:18:00 -0800321 adapter->phy_read = netxen_niu_gbe_phy_read;
322 adapter->phy_write = netxen_niu_gbe_phy_write;
Dhananjay Phadkec9fc8912008-07-21 19:44:07 -0700323 adapter->init_port = netxen_niu_gbe_init_port;
Amit S. Kale80922fb2006-12-04 09:18:00 -0800324 adapter->stop_port = netxen_niu_disable_gbe_port;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400325 break;
326
327 case NETXEN_NIC_XGBE:
Amit S. Kale80922fb2006-12-04 09:18:00 -0800328 adapter->enable_phy_interrupts =
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400329 netxen_niu_xgbe_enable_phy_interrupts;
Amit S. Kale80922fb2006-12-04 09:18:00 -0800330 adapter->disable_phy_interrupts =
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400331 netxen_niu_xgbe_disable_phy_interrupts;
Amit S. Kale80922fb2006-12-04 09:18:00 -0800332 adapter->macaddr_set = netxen_niu_xg_macaddr_set;
333 adapter->set_mtu = netxen_nic_set_mtu_xgb;
334 adapter->init_port = netxen_niu_xg_init_port;
335 adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode;
Amit S. Kale80922fb2006-12-04 09:18:00 -0800336 adapter->stop_port = netxen_niu_disable_xg_port;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400337 break;
338
339 default:
340 break;
341 }
Dhananjay Phadke9ad27642008-08-01 03:14:59 -0700342
343 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
344 adapter->set_mtu = nx_fw_cmd_set_mtu;
345 adapter->set_promisc = netxen_p3_nic_set_promisc;
346 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400347}
348
349/*
350 * netxen_decode_crb_addr(0 - utility to translate from internal Phantom CRB
351 * address to external PCI CRB address.
352 */
Adrian Bunk993fb902007-11-05 18:07:31 +0100353static u32 netxen_decode_crb_addr(u32 addr)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400354{
355 int i;
Linsys Contractor Mithlesh Thukrale0e20a12007-02-28 05:16:40 -0800356 u32 base_addr, offset, pci_base;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400357
358 crb_addr_transform_setup();
359
360 pci_base = NETXEN_ADDR_ERROR;
361 base_addr = addr & 0xfff00000;
362 offset = addr & 0x000fffff;
363
364 for (i = 0; i < NETXEN_MAX_CRB_XFORM; i++) {
365 if (crb_addr_xform[i] == base_addr) {
366 pci_base = i << 20;
367 break;
368 }
369 }
370 if (pci_base == NETXEN_ADDR_ERROR)
371 return pci_base;
372 else
373 return (pci_base + offset);
374}
375
Mithlesh Thukral13ba9c72007-04-20 07:53:05 -0700376static long rom_max_timeout = 100;
377static long rom_lock_timeout = 10000;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400378
Adrian Bunk993fb902007-11-05 18:07:31 +0100379static int rom_lock(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400380{
381 int iter;
382 u32 done = 0;
383 int timeout = 0;
384
385 while (!done) {
386 /* acquire semaphore2 from PCI HW block */
387 netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK),
388 &done);
389 if (done == 1)
390 break;
391 if (timeout >= rom_lock_timeout)
392 return -EIO;
393
394 timeout++;
395 /*
396 * Yield CPU
397 */
398 if (!in_atomic())
399 schedule();
400 else {
401 for (iter = 0; iter < 20; iter++)
402 cpu_relax(); /*This a nop instr on i386 */
403 }
404 }
405 netxen_nic_reg_write(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER);
406 return 0;
407}
408
Adrian Bunk993fb902007-11-05 18:07:31 +0100409static int netxen_wait_rom_done(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400410{
411 long timeout = 0;
412 long done = 0;
413
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800414 cond_resched();
415
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400416 while (done == 0) {
417 done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS);
418 done &= 2;
419 timeout++;
420 if (timeout >= rom_max_timeout) {
421 printk("Timeout reached waiting for rom done");
422 return -EIO;
423 }
424 }
425 return 0;
426}
427
Adrian Bunk993fb902007-11-05 18:07:31 +0100428static void netxen_rom_unlock(struct netxen_adapter *adapter)
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800429{
430 u32 val;
431
432 /* release semaphore2 */
433 netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK), &val);
434
435}
436
Adrian Bunk993fb902007-11-05 18:07:31 +0100437static int do_rom_fast_read(struct netxen_adapter *adapter,
438 int addr, int *valp)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400439{
440 netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400441 netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800442 netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400443 netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
444 if (netxen_wait_rom_done(adapter)) {
445 printk("Error waiting for rom done\n");
446 return -EIO;
447 }
448 /* reset abyte_cnt and dummy_byte_cnt */
449 netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800450 udelay(10);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400451 netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
452
453 *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA);
454 return 0;
455}
456
Adrian Bunk993fb902007-11-05 18:07:31 +0100457static int do_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
458 u8 *bytes, size_t size)
Amit S. Kale27d2ab52007-02-05 07:40:49 -0800459{
460 int addridx;
461 int ret = 0;
462
463 for (addridx = addr; addridx < (addr + size); addridx += 4) {
Al Virof305f782007-12-22 19:44:00 +0000464 int v;
465 ret = do_rom_fast_read(adapter, addridx, &v);
Amit S. Kale27d2ab52007-02-05 07:40:49 -0800466 if (ret != 0)
467 break;
Al Virof305f782007-12-22 19:44:00 +0000468 *(__le32 *)bytes = cpu_to_le32(v);
Amit S. Kale27d2ab52007-02-05 07:40:49 -0800469 bytes += 4;
470 }
471
472 return ret;
473}
474
475int
Jeff Garzik47906542007-11-23 21:23:36 -0500476netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
Amit S. Kale27d2ab52007-02-05 07:40:49 -0800477 u8 *bytes, size_t size)
478{
479 int ret;
480
481 ret = rom_lock(adapter);
482 if (ret < 0)
483 return ret;
484
485 ret = do_rom_fast_read_words(adapter, addr, bytes, size);
486
487 netxen_rom_unlock(adapter);
488 return ret;
489}
490
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400491int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
492{
493 int ret;
494
495 if (rom_lock(adapter) != 0)
496 return -EIO;
497
498 ret = do_rom_fast_read(adapter, addr, valp);
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800499 netxen_rom_unlock(adapter);
500 return ret;
501}
502
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400503#define NETXEN_BOARDTYPE 0x4008
504#define NETXEN_BOARDNUM 0x400c
505#define NETXEN_CHIPNUM 0x4010
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400506
507int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
508{
Dhananjay Phadkedcd56fd2008-06-15 22:59:45 -0700509 int addr, val;
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800510 int i, n, init_delay = 0;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400511 struct crb_addr_pair *buf;
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800512 unsigned offset;
Linsys Contractor Mithlesh Thukrale0e20a12007-02-28 05:16:40 -0800513 u32 off;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400514
515 /* resetall */
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800516 rom_lock(adapter);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400517 netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
Dhananjay Phadke29566402008-07-21 19:44:04 -0700518 0xffffffff);
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800519 netxen_rom_unlock(adapter);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400520
521 if (verbose) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400522 if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0)
523 printk("P2 ROM board type: 0x%08x\n", val);
524 else
525 printk("Could not read board type\n");
526 if (netxen_rom_fast_read(adapter, NETXEN_BOARDNUM, &val) == 0)
527 printk("P2 ROM board num: 0x%08x\n", val);
528 else
529 printk("Could not read board number\n");
530 if (netxen_rom_fast_read(adapter, NETXEN_CHIPNUM, &val) == 0)
531 printk("P2 ROM chip num: 0x%08x\n", val);
532 else
533 printk("Could not read chip number\n");
534 }
535
Dhananjay Phadke29566402008-07-21 19:44:04 -0700536 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
537 if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800538 (n != 0xcafecafe) ||
Dhananjay Phadke29566402008-07-21 19:44:04 -0700539 netxen_rom_fast_read(adapter, 4, &n) != 0) {
540 printk(KERN_ERR "%s: ERROR Reading crb_init area: "
541 "n: %08x\n", netxen_nic_driver_name, n);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400542 return -EIO;
543 }
Dhananjay Phadke29566402008-07-21 19:44:04 -0700544 offset = n & 0xffffU;
545 n = (n >> 16) & 0xffffU;
546 } else {
547 if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
548 !(n & 0x80000000)) {
549 printk(KERN_ERR "%s: ERROR Reading crb_init area: "
550 "n: %08x\n", netxen_nic_driver_name, n);
551 return -EIO;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400552 }
Dhananjay Phadke29566402008-07-21 19:44:04 -0700553 offset = 1;
554 n &= ~0x80000000;
555 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400556
Dhananjay Phadke29566402008-07-21 19:44:04 -0700557 if (n < 1024) {
558 if (verbose)
559 printk(KERN_DEBUG "%s: %d CRB init values found"
560 " in ROM.\n", netxen_nic_driver_name, n);
561 } else {
562 printk(KERN_ERR "%s:n=0x%x Error! NetXen card flash not"
563 " initialized.\n", __func__, n);
564 return -EIO;
565 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400566
Dhananjay Phadke29566402008-07-21 19:44:04 -0700567 buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
568 if (buf == NULL) {
569 printk("%s: netxen_pinit_from_rom: Unable to calloc memory.\n",
570 netxen_nic_driver_name);
571 return -ENOMEM;
572 }
573 for (i = 0; i < n; i++) {
574 if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
Daniel Marjamäki584dbe92009-01-29 08:55:56 +0000575 netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) {
576 kfree(buf);
Dhananjay Phadke29566402008-07-21 19:44:04 -0700577 return -EIO;
Daniel Marjamäki584dbe92009-01-29 08:55:56 +0000578 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400579
Dhananjay Phadke29566402008-07-21 19:44:04 -0700580 buf[i].addr = addr;
581 buf[i].data = val;
582
583 if (verbose)
584 printk(KERN_DEBUG "%s: PCI: 0x%08x == 0x%08x\n",
585 netxen_nic_driver_name,
586 (u32)netxen_decode_crb_addr(addr), val);
587 }
588 for (i = 0; i < n; i++) {
589
590 off = netxen_decode_crb_addr(buf[i].addr);
591 if (off == NETXEN_ADDR_ERROR) {
592 printk(KERN_ERR"CRB init value out of range %x\n",
Amit S. Kale1fcca1a2007-02-05 07:35:26 -0800593 buf[i].addr);
Dhananjay Phadke29566402008-07-21 19:44:04 -0700594 continue;
595 }
596 off += NETXEN_PCI_CRBSPACE;
597 /* skipping cold reboot MAGIC */
598 if (off == NETXEN_CAM_RAM(0x1fc))
599 continue;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400600
Dhananjay Phadke29566402008-07-21 19:44:04 -0700601 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
602 /* do not reset PCI */
603 if (off == (ROMUSB_GLB + 0xbc))
604 continue;
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800605 if (off == (ROMUSB_GLB + 0xa8))
606 continue;
607 if (off == (ROMUSB_GLB + 0xc8)) /* core clock */
608 continue;
609 if (off == (ROMUSB_GLB + 0x24)) /* MN clock */
610 continue;
611 if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */
612 continue;
Dhananjay Phadke29566402008-07-21 19:44:04 -0700613 if (off == (NETXEN_CRB_PEG_NET_1 + 0x18))
614 buf[i].data = 0x1020;
615 /* skip the function enable register */
616 if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION))
617 continue;
618 if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION2))
619 continue;
620 if ((off & 0x0ff00000) == NETXEN_CRB_SMB)
621 continue;
622 }
623
624 if (off == NETXEN_ADDR_ERROR) {
625 printk(KERN_ERR "%s: Err: Unknown addr: 0x%08x\n",
626 netxen_nic_driver_name, buf[i].addr);
627 continue;
628 }
629
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800630 init_delay = 1;
Dhananjay Phadke29566402008-07-21 19:44:04 -0700631 /* After writing this register, HW needs time for CRB */
632 /* to quiet down (else crb_window returns 0xffffffff) */
633 if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800634 init_delay = 1000;
Dhananjay Phadke29566402008-07-21 19:44:04 -0700635 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400636 /* hold xdma in reset also */
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800637 buf[i].data = NETXEN_NIC_XDMA_RESET;
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800638 buf[i].data = 0x8000ff;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400639 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400640 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400641
Dhananjay Phadke29566402008-07-21 19:44:04 -0700642 adapter->hw_write_wx(adapter, off, &buf[i].data, 4);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400643
Dhananjay Phadke27c915a2009-01-14 20:49:00 -0800644 msleep(init_delay);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400645 }
Dhananjay Phadke29566402008-07-21 19:44:04 -0700646 kfree(buf);
647
648 /* disable_peg_cache_all */
649
650 /* unreset_net_cache */
651 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
652 adapter->hw_read_wx(adapter,
653 NETXEN_ROMUSB_GLB_SW_RESET, &val, 4);
654 netxen_crb_writelit_adapter(adapter,
655 NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f));
656 }
657
658 /* p2dn replyCount */
659 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
660 /* disable_peg_cache 0 */
661 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8);
662 /* disable_peg_cache 1 */
663 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8);
664
665 /* peg_clr_all */
666
667 /* peg_clr 0 */
668 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0);
669 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0);
670 /* peg_clr 1 */
671 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0);
672 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0);
673 /* peg_clr 2 */
674 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0);
675 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0);
676 /* peg_clr 3 */
677 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0);
678 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400679 return 0;
680}
681
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800682int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
683{
684 uint64_t addr;
685 uint32_t hi;
686 uint32_t lo;
687
688 adapter->dummy_dma.addr =
Dhananjay Phadke7830b222008-07-21 19:44:00 -0700689 pci_alloc_consistent(adapter->pdev,
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800690 NETXEN_HOST_DUMMY_DMA_SIZE,
691 &adapter->dummy_dma.phys_addr);
692 if (adapter->dummy_dma.addr == NULL) {
693 printk("%s: ERROR: Could not allocate dummy DMA memory\n",
Dhananjay Phadke29566402008-07-21 19:44:04 -0700694 __func__);
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800695 return -ENOMEM;
696 }
697
698 addr = (uint64_t) adapter->dummy_dma.phys_addr;
699 hi = (addr >> 32) & 0xffffffff;
700 lo = addr & 0xffffffff;
701
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700702 adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
703 adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800704
Dhananjay Phadke29566402008-07-21 19:44:04 -0700705 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
706 uint32_t temp = 0;
707 adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, &temp, 4);
708 }
709
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800710 return 0;
711}
712
713void netxen_free_adapter_offload(struct netxen_adapter *adapter)
714{
Dhananjay Phadke15eef1e2008-08-08 00:08:42 -0700715 int i = 100;
Dhananjay Phadke439b4542008-06-15 22:59:46 -0700716
Dhananjay Phadke15eef1e2008-08-08 00:08:42 -0700717 if (!adapter->dummy_dma.addr)
718 return;
719
720 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
Dhananjay Phadke439b4542008-06-15 22:59:46 -0700721 do {
722 if (dma_watchdog_shutdown_request(adapter) == 1)
723 break;
724 msleep(50);
725 if (dma_watchdog_shutdown_poll_result(adapter) == 1)
726 break;
727 } while (--i);
Dhananjay Phadke15eef1e2008-08-08 00:08:42 -0700728 }
Dhananjay Phadke439b4542008-06-15 22:59:46 -0700729
Dhananjay Phadke15eef1e2008-08-08 00:08:42 -0700730 if (i) {
731 pci_free_consistent(adapter->pdev,
732 NETXEN_HOST_DUMMY_DMA_SIZE,
733 adapter->dummy_dma.addr,
734 adapter->dummy_dma.phys_addr);
735 adapter->dummy_dma.addr = NULL;
736 } else {
737 printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n",
738 adapter->netdev->name);
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800739 }
740}
741
Dhananjay Phadke96acb6e2007-07-02 09:37:57 +0530742int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400743{
744 u32 val = 0;
Dhananjay Phadke29566402008-07-21 19:44:04 -0700745 int retries = 60;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400746
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800747 if (!pegtune_val) {
Dhananjay Phadke96acb6e2007-07-02 09:37:57 +0530748 do {
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700749 val = adapter->pci_read_normalize(adapter,
750 CRB_CMDPEG_STATE);
Dhananjay Phadke96acb6e2007-07-02 09:37:57 +0530751
752 if (val == PHAN_INITIALIZE_COMPLETE ||
753 val == PHAN_INITIALIZE_ACK)
754 return 0;
755
Dhananjay Phadke29566402008-07-21 19:44:04 -0700756 msleep(500);
757
Dhananjay Phadke96acb6e2007-07-02 09:37:57 +0530758 } while (--retries);
Dhananjay Phadke29566402008-07-21 19:44:04 -0700759
Dhananjay Phadke96acb6e2007-07-02 09:37:57 +0530760 if (!retries) {
Dhananjay Phadke29566402008-07-21 19:44:04 -0700761 pegtune_val = adapter->pci_read_normalize(adapter,
762 NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
Dhananjay Phadke96acb6e2007-07-02 09:37:57 +0530763 printk(KERN_WARNING "netxen_phantom_init: init failed, "
764 "pegtune_val=%x\n", pegtune_val);
765 return -1;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400766 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400767 }
Dhananjay Phadke96acb6e2007-07-02 09:37:57 +0530768
769 return 0;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400770}
771
Dhananjay Phadke29566402008-07-21 19:44:04 -0700772int netxen_receive_peg_ready(struct netxen_adapter *adapter)
773{
774 u32 val = 0;
775 int retries = 2000;
776
777 do {
778 val = adapter->pci_read_normalize(adapter, CRB_RCVPEG_STATE);
779
780 if (val == PHAN_PEG_RCV_INITIALIZED)
781 return 0;
782
783 msleep(10);
784
785 } while (--retries);
786
787 if (!retries) {
788 printk(KERN_ERR "Receive Peg initialization not "
789 "complete, state: 0x%x.\n", val);
790 return -EIO;
791 }
792
793 return 0;
794}
795
Dhananjay Phadked9e651b2008-07-21 19:44:08 -0700796static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter,
797 struct nx_host_rds_ring *rds_ring, u16 index, u16 cksum)
798{
799 struct netxen_rx_buffer *buffer;
800 struct sk_buff *skb;
801
802 buffer = &rds_ring->rx_buf_arr[index];
803
804 pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
805 PCI_DMA_FROMDEVICE);
806
807 skb = buffer->skb;
808 if (!skb)
809 goto no_skb;
810
811 if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) {
812 adapter->stats.csummed++;
813 skb->ip_summed = CHECKSUM_UNNECESSARY;
814 } else
815 skb->ip_summed = CHECKSUM_NONE;
816
817 skb->dev = adapter->netdev;
818
819 buffer->skb = NULL;
820
821no_skb:
822 buffer->state = NETXEN_BUFFER_FREE;
Dhananjay Phadked9e651b2008-07-21 19:44:08 -0700823 list_add_tail(&buffer->list, &rds_ring->free_list);
824 return skb;
825}
826
Dhananjay Phadke9b3ef552009-03-13 14:52:04 +0000827static void
828netxen_process_rcv(struct netxen_adapter *adapter,
829 int ring, int index, int length, int cksum, int pkt_offset)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400830{
Mithlesh Thukral3176ff32007-04-20 07:52:37 -0700831 struct net_device *netdev = adapter->netdev;
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000832 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400833 struct netxen_rx_buffer *buffer;
834 struct sk_buff *skb;
Dhananjay Phadke9b3ef552009-03-13 14:52:04 +0000835 struct nx_host_rds_ring *rds_ring = &recv_ctx->rds_rings[ring];
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400836
Dhananjay Phadke438627c2009-03-13 14:52:03 +0000837 if (unlikely(index > rds_ring->num_desc))
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800838 return;
Dhananjay Phadke438627c2009-03-13 14:52:03 +0000839
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -0700840 buffer = &rds_ring->rx_buf_arr[index];
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400841
Dhananjay Phadked9e651b2008-07-21 19:44:08 -0700842 skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum);
843 if (!skb)
844 return;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400845
Dhananjay Phadke9b3ef552009-03-13 14:52:04 +0000846 if (length > rds_ring->skb_size)
847 skb_put(skb, rds_ring->skb_size);
848 else
849 skb_put(skb, length);
Dhananjay Phadked9e651b2008-07-21 19:44:08 -0700850
Dhananjay Phadke9b3ef552009-03-13 14:52:04 +0000851
852 if (pkt_offset)
853 skb_pull(skb, pkt_offset);
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800854
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400855 skb->protocol = eth_type_trans(skb, netdev);
856
Dhananjay Phadke0ddc1102009-03-09 08:50:52 +0000857 netif_receive_skb(skb);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400858
Dhananjay Phadke0ddc1102009-03-09 08:50:52 +0000859 adapter->stats.no_rcv++;
860 adapter->stats.rxbytes += length;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400861}
862
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000863int
864netxen_process_rcv_ring(struct netxen_adapter *adapter, int max)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400865{
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000866 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400867 struct status_desc *desc_head = recv_ctx->rcv_status_desc_head;
Dhananjay Phadke0ddc1102009-03-09 08:50:52 +0000868 struct status_desc *desc;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400869 u32 consumer = recv_ctx->status_rx_consumer;
Dhananjay Phadke9b3ef552009-03-13 14:52:04 +0000870 int count = 0;
Dhananjay Phadked9e651b2008-07-21 19:44:08 -0700871 u64 sts_data;
Dhananjay Phadke9b3ef552009-03-13 14:52:04 +0000872 int opcode, ring, index, length, cksum, pkt_offset;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400873
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400874 while (count < max) {
875 desc = &desc_head[consumer];
Dhananjay Phadked9e651b2008-07-21 19:44:08 -0700876 sts_data = le64_to_cpu(desc->status_desc_data);
Dhananjay Phadke0ddc1102009-03-09 08:50:52 +0000877
878 if (!(sts_data & STATUS_OWNER_HOST))
879 break;
880
Dhananjay Phadke9b3ef552009-03-13 14:52:04 +0000881 ring = netxen_get_sts_type(sts_data);
882 if (ring > RCV_RING_JUMBO)
883 continue;
884
Dhananjay Phadked9e651b2008-07-21 19:44:08 -0700885 opcode = netxen_get_sts_opcode(sts_data);
Dhananjay Phadked9e651b2008-07-21 19:44:08 -0700886
Dhananjay Phadke9b3ef552009-03-13 14:52:04 +0000887 index = netxen_get_sts_refhandle(sts_data);
888 length = netxen_get_sts_totallength(sts_data);
889 cksum = netxen_get_sts_status(sts_data);
890 pkt_offset = netxen_get_sts_pkt_offset(sts_data);
891
892 netxen_process_rcv(adapter, ring, index,
893 length, cksum, pkt_offset);
Dhananjay Phadked9e651b2008-07-21 19:44:08 -0700894
Dhananjay Phadke0ddc1102009-03-09 08:50:52 +0000895 desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM);
Dhananjay Phadked9e651b2008-07-21 19:44:08 -0700896
Dhananjay Phadke438627c2009-03-13 14:52:03 +0000897 consumer = get_next_index(consumer, adapter->num_rxd);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400898 count++;
899 }
Dhananjay Phadke0ddc1102009-03-09 08:50:52 +0000900
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -0700901 for (ring = 0; ring < adapter->max_rds_rings; ring++)
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000902 netxen_post_rx_buffers_nodb(adapter, ring);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400903
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400904 if (count) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400905 recv_ctx->status_rx_consumer = consumer;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -0700906 adapter->pci_write_normalize(adapter,
907 recv_ctx->crb_sts_consumer, consumer);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400908 }
909
910 return count;
911}
912
913/* Process Command status ring */
Dhananjay Phadke05aaa022008-03-17 19:59:49 -0700914int netxen_process_cmd_ring(struct netxen_adapter *adapter)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400915{
Dhananjay Phadkeba53e6b2008-03-17 19:59:50 -0700916 u32 last_consumer, consumer;
917 int count = 0, i;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400918 struct netxen_cmd_buffer *buffer;
Dhananjay Phadkeba53e6b2008-03-17 19:59:50 -0700919 struct pci_dev *pdev = adapter->pdev;
920 struct net_device *netdev = adapter->netdev;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400921 struct netxen_skb_frag *frag;
Dhananjay Phadkeba53e6b2008-03-17 19:59:50 -0700922 int done = 0;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400923
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400924 last_consumer = adapter->last_cmd_consumer;
Dhananjay Phadked32cc3d2009-03-09 08:50:53 +0000925 barrier(); /* cmd_consumer can change underneath */
Amit S. Kale9b410112007-02-09 05:45:18 -0800926 consumer = le32_to_cpu(*(adapter->cmd_consumer));
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400927
Dhananjay Phadkeba53e6b2008-03-17 19:59:50 -0700928 while (last_consumer != consumer) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400929 buffer = &adapter->cmd_buf_arr[last_consumer];
dhananjay@netxen.com53a01e02007-12-26 10:23:58 -0800930 if (buffer->skb) {
931 frag = &buffer->frag_array[0];
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400932 pci_unmap_single(pdev, frag->dma, frag->length,
933 PCI_DMA_TODEVICE);
Dhananjay Phadke96acb6e2007-07-02 09:37:57 +0530934 frag->dma = 0ULL;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400935 for (i = 1; i < buffer->frag_count; i++) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400936 frag++; /* Get the next frag */
937 pci_unmap_page(pdev, frag->dma, frag->length,
938 PCI_DMA_TODEVICE);
Dhananjay Phadke96acb6e2007-07-02 09:37:57 +0530939 frag->dma = 0ULL;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400940 }
941
Dhananjay Phadkeba53e6b2008-03-17 19:59:50 -0700942 adapter->stats.xmitfinished++;
dhananjay@netxen.com53a01e02007-12-26 10:23:58 -0800943 dev_kfree_skb_any(buffer->skb);
944 buffer->skb = NULL;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400945 }
946
947 last_consumer = get_next_index(last_consumer,
Dhananjay Phadke438627c2009-03-13 14:52:03 +0000948 adapter->num_txd);
Dhananjay Phadkeba53e6b2008-03-17 19:59:50 -0700949 if (++count >= MAX_STATUS_HANDLE)
950 break;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400951 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400952
Dhananjay Phadkeba53e6b2008-03-17 19:59:50 -0700953 if (count) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400954 adapter->last_cmd_consumer = last_consumer;
Dhananjay Phadkeba53e6b2008-03-17 19:59:50 -0700955 smp_mb();
956 if (netif_queue_stopped(netdev) && netif_running(netdev)) {
957 netif_tx_lock(netdev);
958 netif_wake_queue(netdev);
959 smp_mb();
960 netif_tx_unlock(netdev);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400961 }
962 }
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800963 /*
964 * If everything is freed up to consumer then check if the ring is full
965 * If the ring is full then check if more needs to be freed and
966 * schedule the call back again.
967 *
968 * This happens when there are 2 CPUs. One could be freeing and the
969 * other filling it. If the ring is full when we get out of here and
970 * the card has already interrupted the host then the host can miss the
971 * interrupt.
972 *
973 * There is still a possible race condition and the host could miss an
974 * interrupt. The card has to take care of this.
975 */
Dhananjay Phadked32cc3d2009-03-09 08:50:53 +0000976 barrier(); /* cmd_consumer can change underneath */
Dhananjay Phadkeba53e6b2008-03-17 19:59:50 -0700977 consumer = le32_to_cpu(*(adapter->cmd_consumer));
978 done = (last_consumer == consumer);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400979
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800980 return (done);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400981}
982
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000983void
984netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400985{
Dhananjay Phadke7830b222008-07-21 19:44:00 -0700986 struct pci_dev *pdev = adapter->pdev;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400987 struct sk_buff *skb;
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +0000988 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -0700989 struct nx_host_rds_ring *rds_ring = NULL;
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800990 uint producer;
991 struct rcv_desc *pdesc;
992 struct netxen_rx_buffer *buffer;
993 int count = 0;
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800994 netxen_ctx_msg msg = 0;
995 dma_addr_t dma;
Dhananjay Phadked9e651b2008-07-21 19:44:08 -0700996 struct list_head *head;
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800997
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -0700998 rds_ring = &recv_ctx->rds_rings[ringid];
Amit S. Kaleed25ffa2006-12-04 09:23:25 -0800999
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001000 producer = rds_ring->producer;
Dhananjay Phadked9e651b2008-07-21 19:44:08 -07001001 head = &rds_ring->free_list;
1002
Dhananjay Phadked9e651b2008-07-21 19:44:08 -07001003 while (!list_empty(head)) {
1004
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001005 skb = dev_alloc_skb(rds_ring->skb_size);
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001006 if (unlikely(!skb)) {
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001007 break;
1008 }
1009
Dhananjay Phadke6f703402009-01-14 20:50:00 -08001010 if (!adapter->ahw.cut_through)
1011 skb_reserve(skb, 2);
1012
1013 dma = pci_map_single(pdev, skb->data,
1014 rds_ring->dma_size, PCI_DMA_FROMDEVICE);
1015 if (pci_dma_mapping_error(pdev, dma)) {
1016 dev_kfree_skb_any(skb);
1017 break;
1018 }
1019
1020 count++;
Dhananjay Phadked9e651b2008-07-21 19:44:08 -07001021 buffer = list_entry(head->next, struct netxen_rx_buffer, list);
1022 list_del(&buffer->list);
1023
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001024 buffer->skb = skb;
1025 buffer->state = NETXEN_BUFFER_BUSY;
1026 buffer->dma = dma;
Dhananjay Phadke6f703402009-01-14 20:50:00 -08001027
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001028 /* make a rcv descriptor */
Dhananjay Phadke6f703402009-01-14 20:50:00 -08001029 pdesc = &rds_ring->desc_head[producer];
1030 pdesc->addr_buffer = cpu_to_le64(dma);
Amit S. Kaleed33ebe2006-12-18 05:53:59 -08001031 pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001032 pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
Dhananjay Phadke6f703402009-01-14 20:50:00 -08001033
Dhananjay Phadke438627c2009-03-13 14:52:03 +00001034 producer = get_next_index(producer, rds_ring->num_desc);
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001035 }
Dhananjay Phadke9b3ef552009-03-13 14:52:04 +00001036
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001037 if (count) {
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001038 rds_ring->producer = producer;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001039 adapter->pci_write_normalize(adapter,
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001040 rds_ring->crb_rcv_producer,
Dhananjay Phadke438627c2009-03-13 14:52:03 +00001041 (producer-1) & (rds_ring->num_desc-1));
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001042
1043 if (adapter->fw_major < 4) {
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001044 /*
1045 * Write a doorbell msg to tell phanmon of change in
1046 * receive ring producer
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001047 * Only for firmware version < 4.0.0
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001048 */
1049 netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID);
1050 netxen_set_msg_privid(msg);
1051 netxen_set_msg_count(msg,
Dhananjay Phadke438627c2009-03-13 14:52:03 +00001052 ((producer - 1) &
1053 (rds_ring->num_desc - 1)));
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07001054 netxen_set_msg_ctxid(msg, adapter->portnum);
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001055 netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid));
1056 writel(msg,
1057 DB_NORMALIZE(adapter,
1058 NETXEN_RCV_PRODUCER_OFFSET));
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001059 }
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001060 }
1061}
1062
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +00001063static void
1064netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid)
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001065{
Dhananjay Phadke7830b222008-07-21 19:44:00 -07001066 struct pci_dev *pdev = adapter->pdev;
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001067 struct sk_buff *skb;
Dhananjay Phadkebecf46a2009-03-09 08:50:55 +00001068 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001069 struct nx_host_rds_ring *rds_ring = NULL;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001070 u32 producer;
1071 struct rcv_desc *pdesc;
1072 struct netxen_rx_buffer *buffer;
1073 int count = 0;
Dhananjay Phadked9e651b2008-07-21 19:44:08 -07001074 struct list_head *head;
Dhananjay Phadke6f703402009-01-14 20:50:00 -08001075 dma_addr_t dma;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001076
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001077 rds_ring = &recv_ctx->rds_rings[ringid];
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001078
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001079 producer = rds_ring->producer;
Dhananjay Phadked9e651b2008-07-21 19:44:08 -07001080 head = &rds_ring->free_list;
Dhananjay Phadked9e651b2008-07-21 19:44:08 -07001081 while (!list_empty(head)) {
1082
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001083 skb = dev_alloc_skb(rds_ring->skb_size);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001084 if (unlikely(!skb)) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001085 break;
1086 }
Dhananjay Phadked9e651b2008-07-21 19:44:08 -07001087
Dhananjay Phadke6f703402009-01-14 20:50:00 -08001088 if (!adapter->ahw.cut_through)
1089 skb_reserve(skb, 2);
1090
1091 dma = pci_map_single(pdev, skb->data,
1092 rds_ring->dma_size, PCI_DMA_FROMDEVICE);
1093 if (pci_dma_mapping_error(pdev, dma)) {
1094 dev_kfree_skb_any(skb);
1095 break;
1096 }
1097
1098 count++;
Dhananjay Phadked9e651b2008-07-21 19:44:08 -07001099 buffer = list_entry(head->next, struct netxen_rx_buffer, list);
1100 list_del(&buffer->list);
1101
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001102 buffer->skb = skb;
1103 buffer->state = NETXEN_BUFFER_BUSY;
Dhananjay Phadke6f703402009-01-14 20:50:00 -08001104 buffer->dma = dma;
Amit S. Kaleed25ffa2006-12-04 09:23:25 -08001105
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001106 /* make a rcv descriptor */
Dhananjay Phadke6f703402009-01-14 20:50:00 -08001107 pdesc = &rds_ring->desc_head[producer];
Amit S. Kaleed33ebe2006-12-18 05:53:59 -08001108 pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001109 pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001110 pdesc->addr_buffer = cpu_to_le64(buffer->dma);
Dhananjay Phadke6f703402009-01-14 20:50:00 -08001111
Dhananjay Phadke438627c2009-03-13 14:52:03 +00001112 producer = get_next_index(producer, rds_ring->num_desc);
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001113 }
1114
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001115 if (count) {
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001116 rds_ring->producer = producer;
Dhananjay Phadke3ce06a32008-07-21 19:44:03 -07001117 adapter->pci_write_normalize(adapter,
Dhananjay Phadke48bfd1e2008-07-21 19:44:06 -07001118 rds_ring->crb_rcv_producer,
Dhananjay Phadke438627c2009-03-13 14:52:03 +00001119 (producer - 1) & (rds_ring->num_desc - 1));
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001120 wmb();
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001121 }
1122}
1123
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001124void netxen_nic_clear_stats(struct netxen_adapter *adapter)
1125{
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001126 memset(&adapter->stats, 0, sizeof(adapter->stats));
Mithlesh Thukral3176ff32007-04-20 07:52:37 -07001127 return;
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001128}
1129