blob: ce9ef6bc865c1f9b10d8dad73a6e16dbcfa36d5c [file] [log] [blame]
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001/*
Chien Tungfa6c87d2009-12-09 15:21:56 -08002 * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
Glenn Streiff3c2d7742008-02-04 20:20:45 -08003 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 *
32 */
33
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include <linux/netdevice.h>
37#include <linux/etherdevice.h>
38#include <linux/ip.h>
39#include <linux/tcp.h>
40#include <linux/if_arp.h>
41#include <linux/if_vlan.h>
42#include <linux/ethtool.h>
43#include <net/tcp.h>
44
45#include <net/inet_common.h>
46#include <linux/inet.h>
47
48#include "nes.h"
49
50static struct nic_qp_map nic_qp_mapping_0[] = {
51 {16,0,0,1},{24,4,0,0},{28,8,0,0},{32,12,0,0},
52 {20,2,2,1},{26,6,2,0},{30,10,2,0},{34,14,2,0},
53 {18,1,1,1},{25,5,1,0},{29,9,1,0},{33,13,1,0},
54 {22,3,3,1},{27,7,3,0},{31,11,3,0},{35,15,3,0}
55};
56
57static struct nic_qp_map nic_qp_mapping_1[] = {
58 {18,1,1,1},{25,5,1,0},{29,9,1,0},{33,13,1,0},
59 {22,3,3,1},{27,7,3,0},{31,11,3,0},{35,15,3,0}
60};
61
62static struct nic_qp_map nic_qp_mapping_2[] = {
63 {20,2,2,1},{26,6,2,0},{30,10,2,0},{34,14,2,0}
64};
65
66static struct nic_qp_map nic_qp_mapping_3[] = {
67 {22,3,3,1},{27,7,3,0},{31,11,3,0},{35,15,3,0}
68};
69
70static struct nic_qp_map nic_qp_mapping_4[] = {
71 {28,8,0,0},{32,12,0,0}
72};
73
74static struct nic_qp_map nic_qp_mapping_5[] = {
75 {29,9,1,0},{33,13,1,0}
76};
77
78static struct nic_qp_map nic_qp_mapping_6[] = {
79 {30,10,2,0},{34,14,2,0}
80};
81
82static struct nic_qp_map nic_qp_mapping_7[] = {
83 {31,11,3,0},{35,15,3,0}
84};
85
86static struct nic_qp_map *nic_qp_mapping_per_function[] = {
87 nic_qp_mapping_0, nic_qp_mapping_1, nic_qp_mapping_2, nic_qp_mapping_3,
88 nic_qp_mapping_4, nic_qp_mapping_5, nic_qp_mapping_6, nic_qp_mapping_7
89};
90
91static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
92 | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
93static int debug = -1;
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -070094static int nics_per_function = 1;
Glenn Streiff3c2d7742008-02-04 20:20:45 -080095
Glenn Streiff3c2d7742008-02-04 20:20:45 -080096/**
97 * nes_netdev_poll
98 */
99static int nes_netdev_poll(struct napi_struct *napi, int budget)
100{
101 struct nes_vnic *nesvnic = container_of(napi, struct nes_vnic, napi);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800102 struct nes_device *nesdev = nesvnic->nesdev;
103 struct nes_hw_nic_cq *nescq = &nesvnic->nic_cq;
104
105 nesvnic->budget = budget;
106 nescq->cqes_pending = 0;
107 nescq->rx_cqes_completed = 0;
108 nescq->cqe_allocs_pending = 0;
109 nescq->rx_pkts_indicated = 0;
110
111 nes_nic_ce_handler(nesdev, nescq);
112
113 if (nescq->cqes_pending == 0) {
Ben Hutchings288379f2009-01-19 16:43:59 -0800114 napi_complete(napi);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800115 /* clear out completed cqes and arm */
116 nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
117 nescq->cq_number | (nescq->cqe_allocs_pending << 16));
118 nes_read32(nesdev->regs+NES_CQE_ALLOC);
119 } else {
120 /* clear out completed cqes but don't arm */
121 nes_write32(nesdev->regs+NES_CQE_ALLOC,
122 nescq->cq_number | (nescq->cqe_allocs_pending << 16));
123 nes_debug(NES_DBG_NETDEV, "%s: exiting with work pending\n",
124 nesvnic->netdev->name);
125 }
126 return nescq->rx_pkts_indicated;
127}
128
129
130/**
131 * nes_netdev_open - Activate the network interface; ifconfig
132 * ethx up.
133 */
134static int nes_netdev_open(struct net_device *netdev)
135{
136 u32 macaddr_low;
137 u16 macaddr_high;
138 struct nes_vnic *nesvnic = netdev_priv(netdev);
139 struct nes_device *nesdev = nesvnic->nesdev;
140 int ret;
141 int i;
Glenn Streiff11e07042008-02-15 11:41:27 -0600142 struct nes_vnic *first_nesvnic = NULL;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800143 u32 nic_active_bit;
144 u32 nic_active;
Glenn Streiff11e07042008-02-15 11:41:27 -0600145 struct list_head *list_pos, *list_temp;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800146
147 assert(nesdev != NULL);
148
Glenn Streiff11e07042008-02-15 11:41:27 -0600149 if (nesvnic->netdev_open == 1)
150 return 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800151
152 if (netif_msg_ifup(nesvnic))
153 printk(KERN_INFO PFX "%s: enabling interface\n", netdev->name);
154
155 ret = nes_init_nic_qp(nesdev, netdev);
156 if (ret) {
157 return ret;
158 }
159
160 netif_carrier_off(netdev);
161 netif_stop_queue(netdev);
162
163 if ((!nesvnic->of_device_registered) && (nesvnic->rdma_enabled)) {
164 nesvnic->nesibdev = nes_init_ofa_device(netdev);
165 if (nesvnic->nesibdev == NULL) {
166 printk(KERN_ERR PFX "%s: nesvnic->nesibdev alloc failed", netdev->name);
167 } else {
168 nesvnic->nesibdev->nesvnic = nesvnic;
169 ret = nes_register_ofa_device(nesvnic->nesibdev);
170 if (ret) {
171 printk(KERN_ERR PFX "%s: Unable to register RDMA device, ret = %d\n",
172 netdev->name, ret);
173 }
174 }
175 }
176 /* Set packet filters */
177 nic_active_bit = 1 << nesvnic->nic_index;
178 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_ACTIVE);
179 nic_active |= nic_active_bit;
180 nes_write_indexed(nesdev, NES_IDX_NIC_ACTIVE, nic_active);
181 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE);
182 nic_active |= nic_active_bit;
183 nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE, nic_active);
184 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON);
185 nic_active |= nic_active_bit;
186 nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);
187
Glenn Streiff7495ab62008-04-29 13:46:54 -0700188 macaddr_high = ((u16)netdev->dev_addr[0]) << 8;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800189 macaddr_high += (u16)netdev->dev_addr[1];
Glenn Streiff7495ab62008-04-29 13:46:54 -0700190
191 macaddr_low = ((u32)netdev->dev_addr[2]) << 24;
192 macaddr_low += ((u32)netdev->dev_addr[3]) << 16;
193 macaddr_low += ((u32)netdev->dev_addr[4]) << 8;
194 macaddr_low += (u32)netdev->dev_addr[5];
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800195
196 /* Program the various MAC regs */
197 for (i = 0; i < NES_MAX_PORT_COUNT; i++) {
198 if (nesvnic->qp_nic_index[i] == 0xf) {
199 break;
200 }
201 nes_debug(NES_DBG_NETDEV, "i=%d, perfect filter table index= %d, PERF FILTER LOW"
202 " (Addr:%08X) = %08X, HIGH = %08X.\n",
203 i, nesvnic->qp_nic_index[i],
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700204 NES_IDX_PERFECT_FILTER_LOW+
205 (nesvnic->qp_nic_index[i] * 8),
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800206 macaddr_low,
207 (u32)macaddr_high | NES_MAC_ADDR_VALID |
208 ((((u32)nesvnic->nic_index) << 16)));
209 nes_write_indexed(nesdev,
210 NES_IDX_PERFECT_FILTER_LOW + (nesvnic->qp_nic_index[i] * 8),
211 macaddr_low);
212 nes_write_indexed(nesdev,
213 NES_IDX_PERFECT_FILTER_HIGH + (nesvnic->qp_nic_index[i] * 8),
214 (u32)macaddr_high | NES_MAC_ADDR_VALID |
215 ((((u32)nesvnic->nic_index) << 16)));
216 }
217
218
219 nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
220 nesvnic->nic_cq.cq_number);
221 nes_read32(nesdev->regs+NES_CQE_ALLOC);
Glenn Streiff11e07042008-02-15 11:41:27 -0600222 list_for_each_safe(list_pos, list_temp, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]) {
223 first_nesvnic = container_of(list_pos, struct nes_vnic, list);
224 if (first_nesvnic->netdev_open == 1)
225 break;
226 }
227 if (first_nesvnic->netdev_open == 0) {
228 nes_debug(NES_DBG_INIT, "Setting up MAC interrupt mask.\n");
229 nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK + (0x200 * nesdev->mac_index),
230 ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT |
231 NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR));
232 first_nesvnic = nesvnic;
233 }
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800234 if (first_nesvnic->linkup) {
235 /* Enable network packets */
236 nesvnic->linkup = 1;
237 netif_start_queue(netdev);
238 netif_carrier_on(netdev);
239 }
240 napi_enable(&nesvnic->napi);
241 nesvnic->netdev_open = 1;
242
243 return 0;
244}
245
246
247/**
248 * nes_netdev_stop
249 */
250static int nes_netdev_stop(struct net_device *netdev)
251{
252 struct nes_vnic *nesvnic = netdev_priv(netdev);
253 struct nes_device *nesdev = nesvnic->nesdev;
254 u32 nic_active_mask;
255 u32 nic_active;
Glenn Streiff11e07042008-02-15 11:41:27 -0600256 struct nes_vnic *first_nesvnic = NULL;
257 struct list_head *list_pos, *list_temp;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800258
259 nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n",
260 nesvnic, nesdev, netdev, netdev->name);
261 if (nesvnic->netdev_open == 0)
262 return 0;
263
264 if (netif_msg_ifdown(nesvnic))
265 printk(KERN_INFO PFX "%s: disabling interface\n", netdev->name);
266
267 /* Disable network packets */
268 napi_disable(&nesvnic->napi);
269 netif_stop_queue(netdev);
Glenn Streiff11e07042008-02-15 11:41:27 -0600270 list_for_each_safe(list_pos, list_temp, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]) {
271 first_nesvnic = container_of(list_pos, struct nes_vnic, list);
272 if ((first_nesvnic->netdev_open == 1) && (first_nesvnic != nesvnic))
273 break;
274 }
275
Chien Tung068e80d2008-09-26 15:08:10 -0500276 if ((first_nesvnic->netdev_open == 1) && (first_nesvnic != nesvnic) &&
277 (PCI_FUNC(first_nesvnic->nesdev->pcidev->devfn) !=
278 PCI_FUNC(nesvnic->nesdev->pcidev->devfn))) {
279 nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+
280 (0x200*nesdev->mac_index), 0xffffffff);
281 nes_write_indexed(first_nesvnic->nesdev,
282 NES_IDX_MAC_INT_MASK+
283 (0x200*first_nesvnic->nesdev->mac_index),
284 ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT |
285 NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR));
286 } else {
Glenn Streiff11e07042008-02-15 11:41:27 -0600287 nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800288 }
289
290 nic_active_mask = ~((u32)(1 << nesvnic->nic_index));
291 nes_write_indexed(nesdev, NES_IDX_PERFECT_FILTER_HIGH+
292 (nesvnic->perfect_filter_index*8), 0);
293 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_ACTIVE);
294 nic_active &= nic_active_mask;
295 nes_write_indexed(nesdev, NES_IDX_NIC_ACTIVE, nic_active);
296 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
297 nic_active &= nic_active_mask;
298 nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
299 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE);
300 nic_active &= nic_active_mask;
301 nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE, nic_active);
302 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
303 nic_active &= nic_active_mask;
304 nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
305 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON);
306 nic_active &= nic_active_mask;
307 nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);
308
309
310 if (nesvnic->of_device_registered) {
311 nes_destroy_ofa_device(nesvnic->nesibdev);
312 nesvnic->nesibdev = NULL;
313 nesvnic->of_device_registered = 0;
314 }
315 nes_destroy_nic_qp(nesvnic);
316
317 nesvnic->netdev_open = 0;
318
319 return 0;
320}
321
322
323/**
324 * nes_nic_send
325 */
326static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev)
327{
328 struct nes_vnic *nesvnic = netdev_priv(netdev);
329 struct nes_device *nesdev = nesvnic->nesdev;
330 struct nes_hw_nic *nesnic = &nesvnic->nic;
331 struct nes_hw_nic_sq_wqe *nic_sqe;
332 struct tcphdr *tcph;
333 __le16 *wqe_fragment_length;
334 u32 wqe_misc;
335 u16 wqe_fragment_index = 1; /* first fragment (0) is used by copy buffer */
336 u16 skb_fragment_index;
337 dma_addr_t bus_address;
338
339 nic_sqe = &nesnic->sq_vbase[nesnic->sq_head];
340 wqe_fragment_length = (__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
341
342 /* setup the VLAN tag if present */
343 if (vlan_tx_tag_present(skb)) {
344 nes_debug(NES_DBG_NIC_TX, "%s: VLAN packet to send... VLAN = %08X\n",
345 netdev->name, vlan_tx_tag_get(skb));
346 wqe_misc = NES_NIC_SQ_WQE_TAGVALUE_ENABLE;
347 wqe_fragment_length[0] = (__force __le16) vlan_tx_tag_get(skb);
348 } else
349 wqe_misc = 0;
350
351 /* bump past the vlan tag */
352 wqe_fragment_length++;
353 /* wqe_fragment_address = (u64 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX]; */
354
355 if (skb->ip_summed == CHECKSUM_PARTIAL) {
356 tcph = tcp_hdr(skb);
357 if (1) {
358 if (skb_is_gso(skb)) {
359 /* nes_debug(NES_DBG_NIC_TX, "%s: TSO request... seg size = %u\n",
360 netdev->name, skb_is_gso(skb)); */
361 wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE |
362 NES_NIC_SQ_WQE_COMPLETION | (u16)skb_is_gso(skb);
363 set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_LSO_INFO_IDX,
364 ((u32)tcph->doff) |
365 (((u32)(((unsigned char *)tcph) - skb->data)) << 4));
366 } else {
367 wqe_misc |= NES_NIC_SQ_WQE_COMPLETION;
368 }
369 }
370 } else { /* CHECKSUM_HW */
371 wqe_misc |= NES_NIC_SQ_WQE_DISABLE_CHKSUM | NES_NIC_SQ_WQE_COMPLETION;
372 }
373
374 set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX,
375 skb->len);
376 memcpy(&nesnic->first_frag_vbase[nesnic->sq_head].buffer,
377 skb->data, min(((unsigned int)NES_FIRST_FRAG_SIZE), skb_headlen(skb)));
378 wqe_fragment_length[0] = cpu_to_le16(min(((unsigned int)NES_FIRST_FRAG_SIZE),
379 skb_headlen(skb)));
380 wqe_fragment_length[1] = 0;
381 if (skb_headlen(skb) > NES_FIRST_FRAG_SIZE) {
382 if ((skb_shinfo(skb)->nr_frags + 1) > 4) {
383 nes_debug(NES_DBG_NIC_TX, "%s: Packet with %u fragments not sent, skb_headlen=%u\n",
384 netdev->name, skb_shinfo(skb)->nr_frags + 2, skb_headlen(skb));
385 kfree_skb(skb);
386 nesvnic->tx_sw_dropped++;
387 return NETDEV_TX_LOCKED;
388 }
389 set_bit(nesnic->sq_head, nesnic->first_frag_overflow);
390 bus_address = pci_map_single(nesdev->pcidev, skb->data + NES_FIRST_FRAG_SIZE,
391 skb_headlen(skb) - NES_FIRST_FRAG_SIZE, PCI_DMA_TODEVICE);
392 wqe_fragment_length[wqe_fragment_index++] =
393 cpu_to_le16(skb_headlen(skb) - NES_FIRST_FRAG_SIZE);
394 wqe_fragment_length[wqe_fragment_index] = 0;
395 set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,
396 ((u64)(bus_address)));
397 nesnic->tx_skb[nesnic->sq_head] = skb;
398 }
399
400 if (skb_headlen(skb) == skb->len) {
401 if (skb_headlen(skb) <= NES_FIRST_FRAG_SIZE) {
402 nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_2_1_IDX] = 0;
Faisal Latif28699752009-03-06 15:12:11 -0800403 nesnic->tx_skb[nesnic->sq_head] = skb;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800404 }
405 } else {
406 /* Deal with Fragments */
407 nesnic->tx_skb[nesnic->sq_head] = skb;
408 for (skb_fragment_index = 0; skb_fragment_index < skb_shinfo(skb)->nr_frags;
409 skb_fragment_index++) {
410 bus_address = pci_map_page( nesdev->pcidev,
411 skb_shinfo(skb)->frags[skb_fragment_index].page,
412 skb_shinfo(skb)->frags[skb_fragment_index].page_offset,
413 skb_shinfo(skb)->frags[skb_fragment_index].size,
414 PCI_DMA_TODEVICE);
415 wqe_fragment_length[wqe_fragment_index] =
416 cpu_to_le16(skb_shinfo(skb)->frags[skb_fragment_index].size);
417 set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
418 bus_address);
419 wqe_fragment_index++;
420 if (wqe_fragment_index < 5)
421 wqe_fragment_length[wqe_fragment_index] = 0;
422 }
423 }
424
425 set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_MISC_IDX, wqe_misc);
426 nesnic->sq_head++;
427 nesnic->sq_head &= nesnic->sq_size - 1;
428
429 return NETDEV_TX_OK;
430}
431
432
433/**
434 * nes_netdev_start_xmit
435 */
436static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
437{
438 struct nes_vnic *nesvnic = netdev_priv(netdev);
439 struct nes_device *nesdev = nesvnic->nesdev;
440 struct nes_hw_nic *nesnic = &nesvnic->nic;
441 struct nes_hw_nic_sq_wqe *nic_sqe;
442 struct tcphdr *tcph;
443 /* struct udphdr *udph; */
Bob Sharpa06fd262008-09-26 15:08:10 -0500444#define NES_MAX_TSO_FRAGS MAX_SKB_FRAGS
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800445 /* 64K segment plus overflow on each side */
446 dma_addr_t tso_bus_address[NES_MAX_TSO_FRAGS];
447 dma_addr_t bus_address;
448 u32 tso_frag_index;
449 u32 tso_frag_count;
450 u32 tso_wqe_length;
451 u32 curr_tcp_seq;
452 u32 wqe_count=1;
453 u32 send_rc;
454 struct iphdr *iph;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800455 __le16 *wqe_fragment_length;
456 u32 nr_frags;
457 u32 original_first_length;
Glenn Streiff7495ab62008-04-29 13:46:54 -0700458 /* u64 *wqe_fragment_address; */
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800459 /* first fragment (0) is used by copy buffer */
460 u16 wqe_fragment_index=1;
461 u16 hoffset;
462 u16 nhoffset;
463 u16 wqes_needed;
464 u16 wqes_available;
465 u32 old_head;
466 u32 wqe_misc;
467
Glenn Streiff7495ab62008-04-29 13:46:54 -0700468 /*
469 * nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"
470 * " (%u frags), tso_size=%u\n",
471 * netdev->name, skb->len, skb_headlen(skb),
472 * skb_shinfo(skb)->nr_frags, skb_is_gso(skb));
473 */
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800474
475 if (!netif_carrier_ok(netdev))
476 return NETDEV_TX_OK;
477
478 if (netif_queue_stopped(netdev))
479 return NETDEV_TX_BUSY;
480
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800481 /* Check if SQ is full */
482 if ((((nesnic->sq_tail+(nesnic->sq_size*2))-nesnic->sq_head) & (nesnic->sq_size - 1)) == 1) {
483 if (!netif_queue_stopped(netdev)) {
484 netif_stop_queue(netdev);
485 barrier();
486 if ((((((volatile u16)nesnic->sq_tail)+(nesnic->sq_size*2))-nesnic->sq_head) & (nesnic->sq_size - 1)) != 1) {
487 netif_start_queue(netdev);
488 goto sq_no_longer_full;
489 }
490 }
491 nesvnic->sq_full++;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800492 return NETDEV_TX_BUSY;
493 }
494
495sq_no_longer_full:
496 nr_frags = skb_shinfo(skb)->nr_frags;
497 if (skb_headlen(skb) > NES_FIRST_FRAG_SIZE) {
498 nr_frags++;
499 }
500 /* Check if too many fragments */
501 if (unlikely((nr_frags > 4))) {
502 if (skb_is_gso(skb)) {
503 nesvnic->segmented_tso_requests++;
504 nesvnic->tso_requests++;
505 old_head = nesnic->sq_head;
506 /* Basically 4 fragments available per WQE with extended fragments */
507 wqes_needed = nr_frags >> 2;
508 wqes_needed += (nr_frags&3)?1:0;
509 wqes_available = (((nesnic->sq_tail+nesnic->sq_size)-nesnic->sq_head) - 1) &
510 (nesnic->sq_size - 1);
511
512 if (unlikely(wqes_needed > wqes_available)) {
513 if (!netif_queue_stopped(netdev)) {
514 netif_stop_queue(netdev);
515 barrier();
516 wqes_available = (((((volatile u16)nesnic->sq_tail)+nesnic->sq_size)-nesnic->sq_head) - 1) &
517 (nesnic->sq_size - 1);
518 if (wqes_needed <= wqes_available) {
519 netif_start_queue(netdev);
520 goto tso_sq_no_longer_full;
521 }
522 }
523 nesvnic->sq_full++;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800524 nes_debug(NES_DBG_NIC_TX, "%s: HNIC SQ full- TSO request has too many frags!\n",
525 netdev->name);
526 return NETDEV_TX_BUSY;
527 }
528tso_sq_no_longer_full:
529 /* Map all the buffers */
530 for (tso_frag_count=0; tso_frag_count < skb_shinfo(skb)->nr_frags;
531 tso_frag_count++) {
532 tso_bus_address[tso_frag_count] = pci_map_page( nesdev->pcidev,
533 skb_shinfo(skb)->frags[tso_frag_count].page,
534 skb_shinfo(skb)->frags[tso_frag_count].page_offset,
535 skb_shinfo(skb)->frags[tso_frag_count].size,
536 PCI_DMA_TODEVICE);
537 }
538
539 tso_frag_index = 0;
540 curr_tcp_seq = ntohl(tcp_hdr(skb)->seq);
541 hoffset = skb_transport_header(skb) - skb->data;
542 nhoffset = skb_network_header(skb) - skb->data;
543 original_first_length = hoffset + ((((struct tcphdr *)skb_transport_header(skb))->doff)<<2);
544
545 for (wqe_count=0; wqe_count<((u32)wqes_needed); wqe_count++) {
546 tso_wqe_length = 0;
547 nic_sqe = &nesnic->sq_vbase[nesnic->sq_head];
548 wqe_fragment_length =
549 (__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
550 /* setup the VLAN tag if present */
551 if (vlan_tx_tag_present(skb)) {
552 nes_debug(NES_DBG_NIC_TX, "%s: VLAN packet to send... VLAN = %08X\n",
553 netdev->name, vlan_tx_tag_get(skb) );
554 wqe_misc = NES_NIC_SQ_WQE_TAGVALUE_ENABLE;
555 wqe_fragment_length[0] = (__force __le16) vlan_tx_tag_get(skb);
556 } else
557 wqe_misc = 0;
558
559 /* bump past the vlan tag */
560 wqe_fragment_length++;
561
562 /* Assumes header totally fits in allocated buffer and is in first fragment */
563 if (original_first_length > NES_FIRST_FRAG_SIZE) {
564 nes_debug(NES_DBG_NIC_TX, "ERROR: SKB header too big, headlen=%u, FIRST_FRAG_SIZE=%u\n",
565 original_first_length, NES_FIRST_FRAG_SIZE);
566 nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"
567 " (%u frags), tso_size=%u\n",
568 netdev->name,
569 skb->len, skb_headlen(skb),
570 skb_shinfo(skb)->nr_frags, skb_is_gso(skb));
571 }
572 memcpy(&nesnic->first_frag_vbase[nesnic->sq_head].buffer,
573 skb->data, min(((unsigned int)NES_FIRST_FRAG_SIZE),
574 original_first_length));
575 iph = (struct iphdr *)
576 (&nesnic->first_frag_vbase[nesnic->sq_head].buffer[nhoffset]);
577 tcph = (struct tcphdr *)
578 (&nesnic->first_frag_vbase[nesnic->sq_head].buffer[hoffset]);
579 if ((wqe_count+1)!=(u32)wqes_needed) {
580 tcph->fin = 0;
581 tcph->psh = 0;
582 tcph->rst = 0;
583 tcph->urg = 0;
584 }
585 if (wqe_count) {
586 tcph->syn = 0;
587 }
588 tcph->seq = htonl(curr_tcp_seq);
589 wqe_fragment_length[0] = cpu_to_le16(min(((unsigned int)NES_FIRST_FRAG_SIZE),
590 original_first_length));
591
592 wqe_fragment_index = 1;
593 if ((wqe_count==0) && (skb_headlen(skb) > original_first_length)) {
594 set_bit(nesnic->sq_head, nesnic->first_frag_overflow);
595 bus_address = pci_map_single(nesdev->pcidev, skb->data + original_first_length,
596 skb_headlen(skb) - original_first_length, PCI_DMA_TODEVICE);
597 wqe_fragment_length[wqe_fragment_index++] =
598 cpu_to_le16(skb_headlen(skb) - original_first_length);
599 wqe_fragment_length[wqe_fragment_index] = 0;
600 set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,
601 bus_address);
Chien Tung168ac822008-09-26 15:08:10 -0500602 tso_wqe_length += skb_headlen(skb) -
603 original_first_length;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800604 }
605 while (wqe_fragment_index < 5) {
606 wqe_fragment_length[wqe_fragment_index] =
607 cpu_to_le16(skb_shinfo(skb)->frags[tso_frag_index].size);
608 set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
609 (u64)tso_bus_address[tso_frag_index]);
610 wqe_fragment_index++;
611 tso_wqe_length += skb_shinfo(skb)->frags[tso_frag_index++].size;
612 if (wqe_fragment_index < 5)
613 wqe_fragment_length[wqe_fragment_index] = 0;
614 if (tso_frag_index == tso_frag_count)
615 break;
616 }
617 if ((wqe_count+1) == (u32)wqes_needed) {
618 nesnic->tx_skb[nesnic->sq_head] = skb;
619 } else {
620 nesnic->tx_skb[nesnic->sq_head] = NULL;
621 }
622 wqe_misc |= NES_NIC_SQ_WQE_COMPLETION | (u16)skb_is_gso(skb);
623 if ((tso_wqe_length + original_first_length) > skb_is_gso(skb)) {
624 wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE;
625 } else {
626 iph->tot_len = htons(tso_wqe_length + original_first_length - nhoffset);
627 }
628
629 set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_MISC_IDX,
630 wqe_misc);
631 set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_LSO_INFO_IDX,
632 ((u32)tcph->doff) | (((u32)hoffset) << 4));
633
634 set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX,
635 tso_wqe_length + original_first_length);
636 curr_tcp_seq += tso_wqe_length;
637 nesnic->sq_head++;
638 nesnic->sq_head &= nesnic->sq_size-1;
639 }
640 } else {
641 nesvnic->linearized_skbs++;
642 hoffset = skb_transport_header(skb) - skb->data;
643 nhoffset = skb_network_header(skb) - skb->data;
644 skb_linearize(skb);
645 skb_set_transport_header(skb, hoffset);
646 skb_set_network_header(skb, nhoffset);
647 send_rc = nes_nic_send(skb, netdev);
Faisal Latif28699752009-03-06 15:12:11 -0800648 if (send_rc != NETDEV_TX_OK)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800649 return NETDEV_TX_OK;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800650 }
651 } else {
652 send_rc = nes_nic_send(skb, netdev);
Faisal Latif28699752009-03-06 15:12:11 -0800653 if (send_rc != NETDEV_TX_OK)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800654 return NETDEV_TX_OK;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800655 }
656
657 barrier();
658
659 if (wqe_count)
660 nes_write32(nesdev->regs+NES_WQE_ALLOC,
661 (wqe_count << 24) | (1 << 23) | nesvnic->nic.qp_id);
662
663 netdev->trans_start = jiffies;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800664
665 return NETDEV_TX_OK;
666}
667
668
669/**
670 * nes_netdev_get_stats
671 */
672static struct net_device_stats *nes_netdev_get_stats(struct net_device *netdev)
673{
674 struct nes_vnic *nesvnic = netdev_priv(netdev);
675 struct nes_device *nesdev = nesvnic->nesdev;
676 u64 u64temp;
677 u32 u32temp;
678
679 u32temp = nes_read_indexed(nesdev,
680 NES_IDX_ENDNODE0_NSTAT_RX_DISCARD + (nesvnic->nic_index*0x200));
681 nesvnic->netstats.rx_dropped += u32temp;
682 nesvnic->endnode_nstat_rx_discard += u32temp;
683
684 u64temp = (u64)nes_read_indexed(nesdev,
685 NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_LO + (nesvnic->nic_index*0x200));
686 u64temp += ((u64)nes_read_indexed(nesdev,
687 NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_HI + (nesvnic->nic_index*0x200))) << 32;
688
689 nesvnic->endnode_nstat_rx_octets += u64temp;
690 nesvnic->netstats.rx_bytes += u64temp;
691
692 u64temp = (u64)nes_read_indexed(nesdev,
693 NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_LO + (nesvnic->nic_index*0x200));
694 u64temp += ((u64)nes_read_indexed(nesdev,
695 NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_HI + (nesvnic->nic_index*0x200))) << 32;
696
697 nesvnic->endnode_nstat_rx_frames += u64temp;
698 nesvnic->netstats.rx_packets += u64temp;
699
700 u64temp = (u64)nes_read_indexed(nesdev,
701 NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_LO + (nesvnic->nic_index*0x200));
702 u64temp += ((u64)nes_read_indexed(nesdev,
703 NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_HI + (nesvnic->nic_index*0x200))) << 32;
704
705 nesvnic->endnode_nstat_tx_octets += u64temp;
706 nesvnic->netstats.tx_bytes += u64temp;
707
708 u64temp = (u64)nes_read_indexed(nesdev,
709 NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_LO + (nesvnic->nic_index*0x200));
710 u64temp += ((u64)nes_read_indexed(nesdev,
711 NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_HI + (nesvnic->nic_index*0x200))) << 32;
712
713 nesvnic->endnode_nstat_tx_frames += u64temp;
714 nesvnic->netstats.tx_packets += u64temp;
715
716 u32temp = nes_read_indexed(nesdev,
717 NES_IDX_MAC_RX_SHORT_FRAMES + (nesvnic->nesdev->mac_index*0x200));
718 nesvnic->netstats.rx_dropped += u32temp;
719 nesvnic->nesdev->mac_rx_errors += u32temp;
720 nesvnic->nesdev->mac_rx_short_frames += u32temp;
721
722 u32temp = nes_read_indexed(nesdev,
723 NES_IDX_MAC_RX_OVERSIZED_FRAMES + (nesvnic->nesdev->mac_index*0x200));
724 nesvnic->netstats.rx_dropped += u32temp;
725 nesvnic->nesdev->mac_rx_errors += u32temp;
726 nesvnic->nesdev->mac_rx_oversized_frames += u32temp;
727
728 u32temp = nes_read_indexed(nesdev,
729 NES_IDX_MAC_RX_JABBER_FRAMES + (nesvnic->nesdev->mac_index*0x200));
730 nesvnic->netstats.rx_dropped += u32temp;
731 nesvnic->nesdev->mac_rx_errors += u32temp;
732 nesvnic->nesdev->mac_rx_jabber_frames += u32temp;
733
734 u32temp = nes_read_indexed(nesdev,
735 NES_IDX_MAC_RX_SYMBOL_ERR_FRAMES + (nesvnic->nesdev->mac_index*0x200));
736 nesvnic->netstats.rx_dropped += u32temp;
737 nesvnic->nesdev->mac_rx_errors += u32temp;
738 nesvnic->nesdev->mac_rx_symbol_err_frames += u32temp;
739
740 u32temp = nes_read_indexed(nesdev,
741 NES_IDX_MAC_RX_LENGTH_ERR_FRAMES + (nesvnic->nesdev->mac_index*0x200));
742 nesvnic->netstats.rx_length_errors += u32temp;
743 nesvnic->nesdev->mac_rx_errors += u32temp;
744
745 u32temp = nes_read_indexed(nesdev,
746 NES_IDX_MAC_RX_CRC_ERR_FRAMES + (nesvnic->nesdev->mac_index*0x200));
747 nesvnic->nesdev->mac_rx_errors += u32temp;
748 nesvnic->nesdev->mac_rx_crc_errors += u32temp;
749 nesvnic->netstats.rx_crc_errors += u32temp;
750
751 u32temp = nes_read_indexed(nesdev,
752 NES_IDX_MAC_TX_ERRORS + (nesvnic->nesdev->mac_index*0x200));
753 nesvnic->nesdev->mac_tx_errors += u32temp;
754 nesvnic->netstats.tx_errors += u32temp;
755
756 return &nesvnic->netstats;
757}
758
759
760/**
761 * nes_netdev_tx_timeout
762 */
763static void nes_netdev_tx_timeout(struct net_device *netdev)
764{
765 struct nes_vnic *nesvnic = netdev_priv(netdev);
766
767 if (netif_msg_timer(nesvnic))
768 nes_debug(NES_DBG_NIC_TX, "%s: tx timeout\n", netdev->name);
769}
770
771
772/**
773 * nes_netdev_set_mac_address
774 */
775static int nes_netdev_set_mac_address(struct net_device *netdev, void *p)
776{
777 struct nes_vnic *nesvnic = netdev_priv(netdev);
778 struct nes_device *nesdev = nesvnic->nesdev;
779 struct sockaddr *mac_addr = p;
780 int i;
781 u32 macaddr_low;
782 u16 macaddr_high;
783
784 if (!is_valid_ether_addr(mac_addr->sa_data))
785 return -EADDRNOTAVAIL;
786
787 memcpy(netdev->dev_addr, mac_addr->sa_data, netdev->addr_len);
Johannes Berge1749612008-10-27 15:59:26 -0700788 printk(PFX "%s: Address length = %d, Address = %pM\n",
789 __func__, netdev->addr_len, mac_addr->sa_data);
Glenn Streiff7495ab62008-04-29 13:46:54 -0700790 macaddr_high = ((u16)netdev->dev_addr[0]) << 8;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800791 macaddr_high += (u16)netdev->dev_addr[1];
Glenn Streiff7495ab62008-04-29 13:46:54 -0700792 macaddr_low = ((u32)netdev->dev_addr[2]) << 24;
793 macaddr_low += ((u32)netdev->dev_addr[3]) << 16;
794 macaddr_low += ((u32)netdev->dev_addr[4]) << 8;
795 macaddr_low += (u32)netdev->dev_addr[5];
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800796
797 for (i = 0; i < NES_MAX_PORT_COUNT; i++) {
798 if (nesvnic->qp_nic_index[i] == 0xf) {
799 break;
800 }
801 nes_write_indexed(nesdev,
802 NES_IDX_PERFECT_FILTER_LOW + (nesvnic->qp_nic_index[i] * 8),
803 macaddr_low);
804 nes_write_indexed(nesdev,
805 NES_IDX_PERFECT_FILTER_HIGH + (nesvnic->qp_nic_index[i] * 8),
806 (u32)macaddr_high | NES_MAC_ADDR_VALID |
807 ((((u32)nesvnic->nic_index) << 16)));
808 }
809 return 0;
810}
811
812
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000813static void set_allmulti(struct nes_device *nesdev, u32 nic_active_bit)
814{
815 u32 nic_active;
816
817 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
818 nic_active |= nic_active_bit;
819 nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
820 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
821 nic_active &= ~nic_active_bit;
822 nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
823}
824
825#define get_addr(addrs, index) ((addrs) + (index) * ETH_ALEN)
826
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800827/**
828 * nes_netdev_set_multicast_list
829 */
Roland Dreier1a855fbf2008-04-16 21:01:09 -0700830static void nes_netdev_set_multicast_list(struct net_device *netdev)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800831{
832 struct nes_vnic *nesvnic = netdev_priv(netdev);
833 struct nes_device *nesdev = nesvnic->nesdev;
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700834 struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800835 u32 nic_active_bit;
836 u32 nic_active;
837 u32 perfect_filter_register_address;
838 u32 macaddr_low;
839 u16 macaddr_high;
840 u8 mc_all_on = 0;
841 u8 mc_index;
842 int mc_nic_index = -1;
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700843 u8 pft_entries_preallocated = max(nesadapter->adapter_fcn_count *
844 nics_per_function, 4);
845 u8 max_pft_entries_avaiable = NES_PFT_SIZE - pft_entries_preallocated;
846 unsigned long flags;
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000847 int mc_count = netdev_mc_count(netdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800848
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700849 spin_lock_irqsave(&nesadapter->resource_lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800850 nic_active_bit = 1 << nesvnic->nic_index;
851
852 if (netdev->flags & IFF_PROMISC) {
853 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
854 nic_active |= nic_active_bit;
855 nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
856 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
857 nic_active |= nic_active_bit;
858 nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
859 mc_all_on = 1;
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700860 } else if ((netdev->flags & IFF_ALLMULTI) ||
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800861 (nesvnic->nic_index > 3)) {
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000862 set_allmulti(nesdev, nic_active_bit);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800863 mc_all_on = 1;
864 } else {
865 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
866 nic_active &= ~nic_active_bit;
867 nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
868 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
869 nic_active &= ~nic_active_bit;
870 nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
871 }
872
873 nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n",
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000874 mc_count, !!(netdev->flags & IFF_PROMISC),
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700875 !!(netdev->flags & IFF_ALLMULTI));
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800876 if (!mc_all_on) {
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000877 char *addrs;
878 int i;
Jiri Pirko22bedad32010-04-01 21:22:57 +0000879 struct netdev_hw_addr *ha;
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000880
881 addrs = kmalloc(ETH_ALEN * mc_count, GFP_ATOMIC);
882 if (!addrs) {
883 set_allmulti(nesdev, nic_active_bit);
884 goto unlock;
885 }
886 i = 0;
Jiri Pirko22bedad32010-04-01 21:22:57 +0000887 netdev_for_each_mc_addr(ha, netdev)
888 memcpy(get_addr(addrs, i++), ha->addr, ETH_ALEN);
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000889
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700890 perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW +
891 pft_entries_preallocated * 0x8;
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000892 for (i = 0, mc_index = 0; mc_index < max_pft_entries_avaiable;
893 mc_index++) {
894 while (i < mc_count && nesvnic->mcrq_mcast_filter &&
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700895 ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic,
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000896 get_addr(addrs, i++))) == 0));
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800897 if (mc_nic_index < 0)
898 mc_nic_index = nesvnic->nic_index;
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700899 while (nesadapter->pft_mcast_map[mc_index] < 16 &&
900 nesadapter->pft_mcast_map[mc_index] !=
901 nesvnic->nic_index &&
902 mc_index < max_pft_entries_avaiable) {
903 nes_debug(NES_DBG_NIC_RX,
904 "mc_index=%d skipping nic_index=%d,\
905 used for=%d \n", mc_index,
906 nesvnic->nic_index,
907 nesadapter->pft_mcast_map[mc_index]);
908 mc_index++;
909 }
910 if (mc_index >= max_pft_entries_avaiable)
911 break;
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000912 if (i < mc_count) {
913 char *addr = get_addr(addrs, i++);
914
Johannes Berge1749612008-10-27 15:59:26 -0700915 nes_debug(NES_DBG_NIC_RX, "Assigning MC Address %pM to register 0x%04X nic_idx=%d\n",
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000916 addr,
Roland Dreier2bd01c52008-04-23 11:52:18 -0700917 perfect_filter_register_address+(mc_index * 8),
918 mc_nic_index);
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000919 macaddr_high = ((u16) addr[0]) << 8;
920 macaddr_high += (u16) addr[1];
921 macaddr_low = ((u32) addr[2]) << 24;
922 macaddr_low += ((u32) addr[3]) << 16;
923 macaddr_low += ((u32) addr[4]) << 8;
924 macaddr_low += (u32) addr[5];
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800925 nes_write_indexed(nesdev,
926 perfect_filter_register_address+(mc_index * 8),
927 macaddr_low);
928 nes_write_indexed(nesdev,
929 perfect_filter_register_address+4+(mc_index * 8),
930 (u32)macaddr_high | NES_MAC_ADDR_VALID |
931 ((((u32)(1<<mc_nic_index)) << 16)));
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700932 nesadapter->pft_mcast_map[mc_index] =
933 nesvnic->nic_index;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800934 } else {
935 nes_debug(NES_DBG_NIC_RX, "Clearing MC Address at register 0x%04X\n",
936 perfect_filter_register_address+(mc_index * 8));
937 nes_write_indexed(nesdev,
938 perfect_filter_register_address+4+(mc_index * 8),
939 0);
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700940 nesadapter->pft_mcast_map[mc_index] = 255;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800941 }
942 }
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000943 kfree(addrs);
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700944 /* PFT is not large enough */
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000945 if (i < mc_count)
946 set_allmulti(nesdev, nic_active_bit);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800947 }
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700948
Jiri Pirkofbf219f2010-02-24 05:11:08 +0000949unlock:
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -0700950 spin_unlock_irqrestore(&nesadapter->resource_lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800951}
952
953
954/**
955 * nes_netdev_change_mtu
956 */
Glenn Streiff7495ab62008-04-29 13:46:54 -0700957static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800958{
959 struct nes_vnic *nesvnic = netdev_priv(netdev);
Glenn Streiff7495ab62008-04-29 13:46:54 -0700960 struct nes_device *nesdev = nesvnic->nesdev;
961 int ret = 0;
962 u8 jumbomode = 0;
Bob Sharpe0e31af2008-09-26 15:08:10 -0500963 u32 nic_active;
964 u32 nic_active_bit;
965 u32 uc_all_active;
966 u32 mc_all_active;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800967
Glenn Streiff7495ab62008-04-29 13:46:54 -0700968 if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu))
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800969 return -EINVAL;
970
Glenn Streiff7495ab62008-04-29 13:46:54 -0700971 netdev->mtu = new_mtu;
Chien Tungedd2fd62008-02-15 21:00:36 -0600972 nesvnic->max_frame_size = new_mtu + VLAN_ETH_HLEN;
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800973
974 if (netdev->mtu > 1500) {
975 jumbomode=1;
976 }
Glenn Streiff7495ab62008-04-29 13:46:54 -0700977 nes_nic_init_timer_defaults(nesdev, jumbomode);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800978
979 if (netif_running(netdev)) {
Bob Sharpe0e31af2008-09-26 15:08:10 -0500980 nic_active_bit = 1 << nesvnic->nic_index;
981 mc_all_active = nes_read_indexed(nesdev,
982 NES_IDX_NIC_MULTICAST_ALL) & nic_active_bit;
983 uc_all_active = nes_read_indexed(nesdev,
984 NES_IDX_NIC_UNICAST_ALL) & nic_active_bit;
985
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800986 nes_netdev_stop(netdev);
987 nes_netdev_open(netdev);
Bob Sharpe0e31af2008-09-26 15:08:10 -0500988
989 nic_active = nes_read_indexed(nesdev,
990 NES_IDX_NIC_MULTICAST_ALL);
991 nic_active |= mc_all_active;
992 nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL,
993 nic_active);
994
995 nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
996 nic_active |= uc_all_active;
997 nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
Glenn Streiff3c2d7742008-02-04 20:20:45 -0800998 }
999
1000 return ret;
1001}
1002
Faisal Latif37dab412008-04-29 13:46:54 -07001003static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001004 "Link Change Interrupts",
1005 "Linearized SKBs",
1006 "T/GSO Requests",
1007 "Pause Frames Sent",
1008 "Pause Frames Received",
1009 "Internal Routing Errors",
1010 "SQ SW Dropped SKBs",
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001011 "SQ Full",
1012 "Segmented TSO Requests",
1013 "Rx Symbol Errors",
1014 "Rx Jabber Errors",
1015 "Rx Oversized Frames",
1016 "Rx Short Frames",
1017 "Endnode Rx Discards",
1018 "Endnode Rx Octets",
1019 "Endnode Rx Frames",
1020 "Endnode Tx Octets",
1021 "Endnode Tx Frames",
1022 "mh detected",
1023 "mh pauses",
1024 "Retransmission Count",
1025 "CM Connects",
1026 "CM Accepts",
1027 "Disconnects",
1028 "Connected Events",
1029 "Connect Requests",
1030 "CM Rejects",
1031 "ModifyQP Timeouts",
1032 "CreateQPs",
1033 "SW DestroyQPs",
1034 "DestroyQPs",
1035 "CM Closes",
1036 "CM Packets Sent",
1037 "CM Packets Bounced",
1038 "CM Packets Created",
1039 "CM Packets Rcvd",
1040 "CM Packets Dropped",
1041 "CM Packets Retrans",
1042 "CM Listens Created",
1043 "CM Listens Destroyed",
1044 "CM Backlog Drops",
1045 "CM Loopbacks",
1046 "CM Nodes Created",
1047 "CM Nodes Destroyed",
1048 "CM Accel Drops",
1049 "CM Resets Received",
1050 "Timer Inits",
1051 "CQ Depth 1",
1052 "CQ Depth 4",
1053 "CQ Depth 16",
1054 "CQ Depth 24",
1055 "CQ Depth 32",
1056 "CQ Depth 128",
1057 "CQ Depth 256",
Faisal Latif37dab412008-04-29 13:46:54 -07001058 "LRO aggregated",
1059 "LRO flushed",
1060 "LRO no_desc",
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001061};
1062
Faisal Latif37dab412008-04-29 13:46:54 -07001063#define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001064
1065/**
1066 * nes_netdev_get_rx_csum
1067 */
1068static u32 nes_netdev_get_rx_csum (struct net_device *netdev)
1069{
1070 struct nes_vnic *nesvnic = netdev_priv(netdev);
1071
1072 if (nesvnic->rx_checksum_disabled)
1073 return 0;
1074 else
1075 return 1;
1076}
1077
1078
1079/**
1080 * nes_netdev_set_rc_csum
1081 */
1082static int nes_netdev_set_rx_csum(struct net_device *netdev, u32 enable)
1083{
1084 struct nes_vnic *nesvnic = netdev_priv(netdev);
1085
1086 if (enable)
1087 nesvnic->rx_checksum_disabled = 0;
1088 else
1089 nesvnic->rx_checksum_disabled = 1;
1090 return 0;
1091}
1092
1093
1094/**
Ben Hutchings15f0a392009-10-01 11:58:24 +00001095 * nes_netdev_get_sset_count
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001096 */
Ben Hutchings15f0a392009-10-01 11:58:24 +00001097static int nes_netdev_get_sset_count(struct net_device *netdev, int stringset)
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001098{
Ben Hutchings15f0a392009-10-01 11:58:24 +00001099 if (stringset == ETH_SS_STATS)
1100 return NES_ETHTOOL_STAT_COUNT;
1101 else
1102 return -EINVAL;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001103}
1104
1105
1106/**
1107 * nes_netdev_get_strings
1108 */
1109static void nes_netdev_get_strings(struct net_device *netdev, u32 stringset,
1110 u8 *ethtool_strings)
1111{
1112 if (stringset == ETH_SS_STATS)
1113 memcpy(ethtool_strings,
1114 &nes_ethtool_stringset,
1115 sizeof(nes_ethtool_stringset));
1116}
1117
1118
1119/**
1120 * nes_netdev_get_ethtool_stats
1121 */
1122static void nes_netdev_get_ethtool_stats(struct net_device *netdev,
1123 struct ethtool_stats *target_ethtool_stats, u64 *target_stat_values)
1124{
1125 u64 u64temp;
1126 struct nes_vnic *nesvnic = netdev_priv(netdev);
1127 struct nes_device *nesdev = nesvnic->nesdev;
1128 u32 nic_count;
1129 u32 u32temp;
Faisal Latif28699752009-03-06 15:12:11 -08001130 u32 index = 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001131
1132 target_ethtool_stats->n_stats = NES_ETHTOOL_STAT_COUNT;
Faisal Latif28699752009-03-06 15:12:11 -08001133 target_stat_values[index] = nesvnic->nesdev->link_status_interrupts;
1134 target_stat_values[++index] = nesvnic->linearized_skbs;
1135 target_stat_values[++index] = nesvnic->tso_requests;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001136
1137 u32temp = nes_read_indexed(nesdev,
1138 NES_IDX_MAC_TX_PAUSE_FRAMES + (nesvnic->nesdev->mac_index*0x200));
1139 nesvnic->nesdev->mac_pause_frames_sent += u32temp;
Faisal Latif28699752009-03-06 15:12:11 -08001140 target_stat_values[++index] = nesvnic->nesdev->mac_pause_frames_sent;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001141
1142 u32temp = nes_read_indexed(nesdev,
1143 NES_IDX_MAC_RX_PAUSE_FRAMES + (nesvnic->nesdev->mac_index*0x200));
1144 nesvnic->nesdev->mac_pause_frames_received += u32temp;
1145
1146 u32temp = nes_read_indexed(nesdev,
1147 NES_IDX_PORT_RX_DISCARDS + (nesvnic->nesdev->mac_index*0x40));
1148 nesvnic->nesdev->port_rx_discards += u32temp;
1149 nesvnic->netstats.rx_dropped += u32temp;
1150
1151 u32temp = nes_read_indexed(nesdev,
1152 NES_IDX_PORT_TX_DISCARDS + (nesvnic->nesdev->mac_index*0x40));
1153 nesvnic->nesdev->port_tx_discards += u32temp;
1154 nesvnic->netstats.tx_dropped += u32temp;
1155
1156 for (nic_count = 0; nic_count < NES_MAX_PORT_COUNT; nic_count++) {
1157 if (nesvnic->qp_nic_index[nic_count] == 0xf)
1158 break;
1159
1160 u32temp = nes_read_indexed(nesdev,
1161 NES_IDX_ENDNODE0_NSTAT_RX_DISCARD +
1162 (nesvnic->qp_nic_index[nic_count]*0x200));
1163 nesvnic->netstats.rx_dropped += u32temp;
1164 nesvnic->endnode_nstat_rx_discard += u32temp;
1165
1166 u64temp = (u64)nes_read_indexed(nesdev,
1167 NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_LO +
1168 (nesvnic->qp_nic_index[nic_count]*0x200));
1169 u64temp += ((u64)nes_read_indexed(nesdev,
1170 NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_HI +
1171 (nesvnic->qp_nic_index[nic_count]*0x200))) << 32;
1172
1173 nesvnic->endnode_nstat_rx_octets += u64temp;
1174 nesvnic->netstats.rx_bytes += u64temp;
1175
1176 u64temp = (u64)nes_read_indexed(nesdev,
1177 NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_LO +
1178 (nesvnic->qp_nic_index[nic_count]*0x200));
1179 u64temp += ((u64)nes_read_indexed(nesdev,
1180 NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_HI +
1181 (nesvnic->qp_nic_index[nic_count]*0x200))) << 32;
1182
1183 nesvnic->endnode_nstat_rx_frames += u64temp;
1184 nesvnic->netstats.rx_packets += u64temp;
1185
1186 u64temp = (u64)nes_read_indexed(nesdev,
1187 NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_LO +
1188 (nesvnic->qp_nic_index[nic_count]*0x200));
1189 u64temp += ((u64)nes_read_indexed(nesdev,
1190 NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_HI +
1191 (nesvnic->qp_nic_index[nic_count]*0x200))) << 32;
1192
1193 nesvnic->endnode_nstat_tx_octets += u64temp;
1194 nesvnic->netstats.tx_bytes += u64temp;
1195
1196 u64temp = (u64)nes_read_indexed(nesdev,
1197 NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_LO +
1198 (nesvnic->qp_nic_index[nic_count]*0x200));
1199 u64temp += ((u64)nes_read_indexed(nesdev,
1200 NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_HI +
1201 (nesvnic->qp_nic_index[nic_count]*0x200))) << 32;
1202
1203 nesvnic->endnode_nstat_tx_frames += u64temp;
1204 nesvnic->netstats.tx_packets += u64temp;
1205
1206 u32temp = nes_read_indexed(nesdev,
1207 NES_IDX_IPV4_TCP_REXMITS + (nesvnic->qp_nic_index[nic_count]*0x200));
1208 nesvnic->endnode_ipv4_tcp_retransmits += u32temp;
1209 }
1210
Faisal Latif28699752009-03-06 15:12:11 -08001211 target_stat_values[++index] = nesvnic->nesdev->mac_pause_frames_received;
1212 target_stat_values[++index] = nesdev->nesadapter->nic_rx_eth_route_err;
1213 target_stat_values[++index] = nesvnic->tx_sw_dropped;
1214 target_stat_values[++index] = nesvnic->sq_full;
1215 target_stat_values[++index] = nesvnic->segmented_tso_requests;
1216 target_stat_values[++index] = nesvnic->nesdev->mac_rx_symbol_err_frames;
1217 target_stat_values[++index] = nesvnic->nesdev->mac_rx_jabber_frames;
1218 target_stat_values[++index] = nesvnic->nesdev->mac_rx_oversized_frames;
1219 target_stat_values[++index] = nesvnic->nesdev->mac_rx_short_frames;
1220 target_stat_values[++index] = nesvnic->endnode_nstat_rx_discard;
1221 target_stat_values[++index] = nesvnic->endnode_nstat_rx_octets;
1222 target_stat_values[++index] = nesvnic->endnode_nstat_rx_frames;
1223 target_stat_values[++index] = nesvnic->endnode_nstat_tx_octets;
1224 target_stat_values[++index] = nesvnic->endnode_nstat_tx_frames;
1225 target_stat_values[++index] = mh_detected;
1226 target_stat_values[++index] = mh_pauses_sent;
1227 target_stat_values[++index] = nesvnic->endnode_ipv4_tcp_retransmits;
1228 target_stat_values[++index] = atomic_read(&cm_connects);
1229 target_stat_values[++index] = atomic_read(&cm_accepts);
1230 target_stat_values[++index] = atomic_read(&cm_disconnects);
1231 target_stat_values[++index] = atomic_read(&cm_connecteds);
1232 target_stat_values[++index] = atomic_read(&cm_connect_reqs);
1233 target_stat_values[++index] = atomic_read(&cm_rejects);
1234 target_stat_values[++index] = atomic_read(&mod_qp_timouts);
1235 target_stat_values[++index] = atomic_read(&qps_created);
1236 target_stat_values[++index] = atomic_read(&sw_qps_destroyed);
1237 target_stat_values[++index] = atomic_read(&qps_destroyed);
1238 target_stat_values[++index] = atomic_read(&cm_closes);
1239 target_stat_values[++index] = cm_packets_sent;
1240 target_stat_values[++index] = cm_packets_bounced;
1241 target_stat_values[++index] = cm_packets_created;
1242 target_stat_values[++index] = cm_packets_received;
1243 target_stat_values[++index] = cm_packets_dropped;
1244 target_stat_values[++index] = cm_packets_retrans;
Faisal Latif6e10d2e2010-02-12 19:55:03 +00001245 target_stat_values[++index] = atomic_read(&cm_listens_created);
1246 target_stat_values[++index] = atomic_read(&cm_listens_destroyed);
Faisal Latif28699752009-03-06 15:12:11 -08001247 target_stat_values[++index] = cm_backlog_drops;
1248 target_stat_values[++index] = atomic_read(&cm_loopbacks);
1249 target_stat_values[++index] = atomic_read(&cm_nodes_created);
1250 target_stat_values[++index] = atomic_read(&cm_nodes_destroyed);
1251 target_stat_values[++index] = atomic_read(&cm_accel_dropped_pkts);
1252 target_stat_values[++index] = atomic_read(&cm_resets_recvd);
1253 target_stat_values[++index] = int_mod_timer_init;
1254 target_stat_values[++index] = int_mod_cq_depth_1;
1255 target_stat_values[++index] = int_mod_cq_depth_4;
1256 target_stat_values[++index] = int_mod_cq_depth_16;
1257 target_stat_values[++index] = int_mod_cq_depth_24;
1258 target_stat_values[++index] = int_mod_cq_depth_32;
1259 target_stat_values[++index] = int_mod_cq_depth_128;
1260 target_stat_values[++index] = int_mod_cq_depth_256;
1261 target_stat_values[++index] = nesvnic->lro_mgr.stats.aggregated;
1262 target_stat_values[++index] = nesvnic->lro_mgr.stats.flushed;
1263 target_stat_values[++index] = nesvnic->lro_mgr.stats.no_desc;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001264
1265}
1266
1267
1268/**
1269 * nes_netdev_get_drvinfo
1270 */
1271static void nes_netdev_get_drvinfo(struct net_device *netdev,
1272 struct ethtool_drvinfo *drvinfo)
1273{
1274 struct nes_vnic *nesvnic = netdev_priv(netdev);
Chien Tung0c93ae32008-09-26 15:08:10 -05001275 struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001276
1277 strcpy(drvinfo->driver, DRV_NAME);
1278 strcpy(drvinfo->bus_info, pci_name(nesvnic->nesdev->pcidev));
Chien Tung0c93ae32008-09-26 15:08:10 -05001279 sprintf(drvinfo->fw_version, "%u.%u", nesadapter->firmware_version>>16,
1280 nesadapter->firmware_version & 0x000000ff);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001281 strcpy(drvinfo->version, DRV_VERSION);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001282 drvinfo->testinfo_len = 0;
1283 drvinfo->eedump_len = 0;
1284 drvinfo->regdump_len = 0;
1285}
1286
1287
1288/**
1289 * nes_netdev_set_coalesce
1290 */
1291static int nes_netdev_set_coalesce(struct net_device *netdev,
1292 struct ethtool_coalesce *et_coalesce)
1293{
1294 struct nes_vnic *nesvnic = netdev_priv(netdev);
Glenn Streiff7495ab62008-04-29 13:46:54 -07001295 struct nes_device *nesdev = nesvnic->nesdev;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001296 struct nes_adapter *nesadapter = nesdev->nesadapter;
1297 struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
1298 unsigned long flags;
1299
Glenn Streiff7495ab62008-04-29 13:46:54 -07001300 spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001301 if (et_coalesce->rx_max_coalesced_frames_low) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07001302 shared_timer->threshold_low = et_coalesce->rx_max_coalesced_frames_low;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001303 }
1304 if (et_coalesce->rx_max_coalesced_frames_irq) {
1305 shared_timer->threshold_target = et_coalesce->rx_max_coalesced_frames_irq;
1306 }
1307 if (et_coalesce->rx_max_coalesced_frames_high) {
1308 shared_timer->threshold_high = et_coalesce->rx_max_coalesced_frames_high;
1309 }
1310 if (et_coalesce->rx_coalesce_usecs_low) {
1311 shared_timer->timer_in_use_min = et_coalesce->rx_coalesce_usecs_low;
1312 }
1313 if (et_coalesce->rx_coalesce_usecs_high) {
1314 shared_timer->timer_in_use_max = et_coalesce->rx_coalesce_usecs_high;
1315 }
1316 spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
1317
1318 /* using this to drive total interrupt moderation */
1319 nesadapter->et_rx_coalesce_usecs_irq = et_coalesce->rx_coalesce_usecs_irq;
1320 if (et_coalesce->use_adaptive_rx_coalesce) {
1321 nesadapter->et_use_adaptive_rx_coalesce = 1;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001322 nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001323 nesadapter->et_rx_coalesce_usecs_irq = 0;
1324 if (et_coalesce->pkt_rate_low) {
Glenn Streiff7495ab62008-04-29 13:46:54 -07001325 nesadapter->et_pkt_rate_low = et_coalesce->pkt_rate_low;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001326 }
1327 } else {
1328 nesadapter->et_use_adaptive_rx_coalesce = 0;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001329 nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001330 if (nesadapter->et_rx_coalesce_usecs_irq) {
1331 nes_write32(nesdev->regs+NES_PERIODIC_CONTROL,
1332 0x80000000 | ((u32)(nesadapter->et_rx_coalesce_usecs_irq*8)));
1333 }
1334 }
1335 return 0;
1336}
1337
1338
1339/**
1340 * nes_netdev_get_coalesce
1341 */
1342static int nes_netdev_get_coalesce(struct net_device *netdev,
1343 struct ethtool_coalesce *et_coalesce)
1344{
1345 struct nes_vnic *nesvnic = netdev_priv(netdev);
Glenn Streiff7495ab62008-04-29 13:46:54 -07001346 struct nes_device *nesdev = nesvnic->nesdev;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001347 struct nes_adapter *nesadapter = nesdev->nesadapter;
1348 struct ethtool_coalesce temp_et_coalesce;
1349 struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
1350 unsigned long flags;
1351
1352 memset(&temp_et_coalesce, 0, sizeof(temp_et_coalesce));
Glenn Streiff7495ab62008-04-29 13:46:54 -07001353 temp_et_coalesce.rx_coalesce_usecs_irq = nesadapter->et_rx_coalesce_usecs_irq;
1354 temp_et_coalesce.use_adaptive_rx_coalesce = nesadapter->et_use_adaptive_rx_coalesce;
1355 temp_et_coalesce.rate_sample_interval = nesadapter->et_rate_sample_interval;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001356 temp_et_coalesce.pkt_rate_low = nesadapter->et_pkt_rate_low;
1357 spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
Glenn Streiff7495ab62008-04-29 13:46:54 -07001358 temp_et_coalesce.rx_max_coalesced_frames_low = shared_timer->threshold_low;
1359 temp_et_coalesce.rx_max_coalesced_frames_irq = shared_timer->threshold_target;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001360 temp_et_coalesce.rx_max_coalesced_frames_high = shared_timer->threshold_high;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001361 temp_et_coalesce.rx_coalesce_usecs_low = shared_timer->timer_in_use_min;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001362 temp_et_coalesce.rx_coalesce_usecs_high = shared_timer->timer_in_use_max;
1363 if (nesadapter->et_use_adaptive_rx_coalesce) {
1364 temp_et_coalesce.rx_coalesce_usecs_irq = shared_timer->timer_in_use;
1365 }
1366 spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
Glenn Streiff7495ab62008-04-29 13:46:54 -07001367 memcpy(et_coalesce, &temp_et_coalesce, sizeof(*et_coalesce));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001368 return 0;
1369}
1370
1371
1372/**
1373 * nes_netdev_get_pauseparam
1374 */
1375static void nes_netdev_get_pauseparam(struct net_device *netdev,
1376 struct ethtool_pauseparam *et_pauseparam)
1377{
1378 struct nes_vnic *nesvnic = netdev_priv(netdev);
1379
1380 et_pauseparam->autoneg = 0;
1381 et_pauseparam->rx_pause = (nesvnic->nesdev->disable_rx_flow_control == 0) ? 1:0;
1382 et_pauseparam->tx_pause = (nesvnic->nesdev->disable_tx_flow_control == 0) ? 1:0;
1383}
1384
1385
1386/**
1387 * nes_netdev_set_pauseparam
1388 */
1389static int nes_netdev_set_pauseparam(struct net_device *netdev,
1390 struct ethtool_pauseparam *et_pauseparam)
1391{
1392 struct nes_vnic *nesvnic = netdev_priv(netdev);
1393 struct nes_device *nesdev = nesvnic->nesdev;
1394 u32 u32temp;
1395
1396 if (et_pauseparam->autoneg) {
1397 /* TODO: should return unsupported */
1398 return 0;
1399 }
1400 if ((et_pauseparam->tx_pause == 1) && (nesdev->disable_tx_flow_control == 1)) {
1401 u32temp = nes_read_indexed(nesdev,
1402 NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200));
1403 u32temp |= NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE;
1404 nes_write_indexed(nesdev,
1405 NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE + (nesdev->mac_index*0x200), u32temp);
1406 nesdev->disable_tx_flow_control = 0;
1407 } else if ((et_pauseparam->tx_pause == 0) && (nesdev->disable_tx_flow_control == 0)) {
1408 u32temp = nes_read_indexed(nesdev,
1409 NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200));
1410 u32temp &= ~NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE;
1411 nes_write_indexed(nesdev,
1412 NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE + (nesdev->mac_index*0x200), u32temp);
1413 nesdev->disable_tx_flow_control = 1;
1414 }
1415 if ((et_pauseparam->rx_pause == 1) && (nesdev->disable_rx_flow_control == 1)) {
1416 u32temp = nes_read_indexed(nesdev,
1417 NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40));
1418 u32temp &= ~NES_IDX_MPP_DEBUG_PORT_DISABLE_PAUSE;
1419 nes_write_indexed(nesdev,
1420 NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40), u32temp);
1421 nesdev->disable_rx_flow_control = 0;
1422 } else if ((et_pauseparam->rx_pause == 0) && (nesdev->disable_rx_flow_control == 0)) {
1423 u32temp = nes_read_indexed(nesdev,
1424 NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40));
1425 u32temp |= NES_IDX_MPP_DEBUG_PORT_DISABLE_PAUSE;
1426 nes_write_indexed(nesdev,
1427 NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40), u32temp);
1428 nesdev->disable_rx_flow_control = 1;
1429 }
1430
1431 return 0;
1432}
1433
1434
1435/**
1436 * nes_netdev_get_settings
1437 */
1438static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd *et_cmd)
1439{
1440 struct nes_vnic *nesvnic = netdev_priv(netdev);
1441 struct nes_device *nesdev = nesvnic->nesdev;
1442 struct nes_adapter *nesadapter = nesdev->nesadapter;
Chien Tung43035652009-04-08 14:27:56 -07001443 u32 mac_index = nesdev->mac_index;
1444 u8 phy_type = nesadapter->phy_type[mac_index];
1445 u8 phy_index = nesadapter->phy_index[mac_index];
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001446 u16 phy_data;
1447
1448 et_cmd->duplex = DUPLEX_FULL;
Glenn Streiff7495ab62008-04-29 13:46:54 -07001449 et_cmd->port = PORT_MII;
Chien Tung43035652009-04-08 14:27:56 -07001450 et_cmd->maxtxpkt = 511;
1451 et_cmd->maxrxpkt = 511;
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001452
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001453 if (nesadapter->OneG_Mode) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001454 et_cmd->speed = SPEED_1000;
Chien Tung43035652009-04-08 14:27:56 -07001455 if (phy_type == NES_PHY_TYPE_PUMA_1G) {
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001456 et_cmd->supported = SUPPORTED_1000baseT_Full;
1457 et_cmd->advertising = ADVERTISED_1000baseT_Full;
1458 et_cmd->autoneg = AUTONEG_DISABLE;
1459 et_cmd->transceiver = XCVR_INTERNAL;
Chien Tung43035652009-04-08 14:27:56 -07001460 et_cmd->phy_address = mac_index;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001461 } else {
Chien Tung43035652009-04-08 14:27:56 -07001462 et_cmd->supported = SUPPORTED_1000baseT_Full
1463 | SUPPORTED_Autoneg;
1464 et_cmd->advertising = ADVERTISED_1000baseT_Full
1465 | ADVERTISED_Autoneg;
1466 nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001467 if (phy_data & 0x1000)
1468 et_cmd->autoneg = AUTONEG_ENABLE;
1469 else
1470 et_cmd->autoneg = AUTONEG_DISABLE;
1471 et_cmd->transceiver = XCVR_EXTERNAL;
Chien Tung43035652009-04-08 14:27:56 -07001472 et_cmd->phy_address = phy_index;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001473 }
Chien Tung43035652009-04-08 14:27:56 -07001474 return 0;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001475 }
Chien Tung09124e12010-02-23 17:52:10 +00001476 if ((phy_type == NES_PHY_TYPE_ARGUS) ||
1477 (phy_type == NES_PHY_TYPE_SFP_D) ||
1478 (phy_type == NES_PHY_TYPE_KR)) {
Chien Tung43035652009-04-08 14:27:56 -07001479 et_cmd->transceiver = XCVR_EXTERNAL;
1480 et_cmd->port = PORT_FIBRE;
1481 et_cmd->supported = SUPPORTED_FIBRE;
1482 et_cmd->advertising = ADVERTISED_FIBRE;
1483 et_cmd->phy_address = phy_index;
1484 } else {
1485 et_cmd->transceiver = XCVR_INTERNAL;
1486 et_cmd->supported = SUPPORTED_10000baseT_Full;
1487 et_cmd->advertising = ADVERTISED_10000baseT_Full;
1488 et_cmd->phy_address = mac_index;
1489 }
1490 et_cmd->speed = SPEED_10000;
1491 et_cmd->autoneg = AUTONEG_DISABLE;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001492 return 0;
1493}
1494
1495
1496/**
1497 * nes_netdev_set_settings
1498 */
1499static int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd *et_cmd)
1500{
1501 struct nes_vnic *nesvnic = netdev_priv(netdev);
1502 struct nes_device *nesdev = nesvnic->nesdev;
1503 struct nes_adapter *nesadapter = nesdev->nesadapter;
1504 u16 phy_data;
1505
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001506 if ((nesadapter->OneG_Mode) &&
1507 (nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_PUMA_1G)) {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001508 nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
1509 &phy_data);
1510 if (et_cmd->autoneg) {
1511 /* Turn on Full duplex, Autoneg, and restart autonegotiation */
1512 phy_data |= 0x1300;
1513 } else {
Glenn Streiff7495ab62008-04-29 13:46:54 -07001514 /* Turn off autoneg */
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001515 phy_data &= ~0x1000;
1516 }
1517 nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
1518 phy_data);
1519 }
1520
1521 return 0;
1522}
1523
1524
Stephen Hemminger0fc0b732009-09-02 01:03:33 -07001525static const struct ethtool_ops nes_ethtool_ops = {
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001526 .get_link = ethtool_op_get_link,
1527 .get_settings = nes_netdev_get_settings,
1528 .set_settings = nes_netdev_set_settings,
1529 .get_tx_csum = ethtool_op_get_tx_csum,
1530 .get_rx_csum = nes_netdev_get_rx_csum,
1531 .get_sg = ethtool_op_get_sg,
1532 .get_strings = nes_netdev_get_strings,
Ben Hutchings15f0a392009-10-01 11:58:24 +00001533 .get_sset_count = nes_netdev_get_sset_count,
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001534 .get_ethtool_stats = nes_netdev_get_ethtool_stats,
1535 .get_drvinfo = nes_netdev_get_drvinfo,
1536 .get_coalesce = nes_netdev_get_coalesce,
1537 .set_coalesce = nes_netdev_set_coalesce,
1538 .get_pauseparam = nes_netdev_get_pauseparam,
1539 .set_pauseparam = nes_netdev_set_pauseparam,
1540 .set_tx_csum = ethtool_op_set_tx_csum,
1541 .set_rx_csum = nes_netdev_set_rx_csum,
1542 .set_sg = ethtool_op_set_sg,
1543 .get_tso = ethtool_op_get_tso,
1544 .set_tso = ethtool_op_set_tso,
Faisal Latif37dab412008-04-29 13:46:54 -07001545 .get_flags = ethtool_op_get_flags,
1546 .set_flags = ethtool_op_set_flags,
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001547};
1548
1549
1550static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
1551{
1552 struct nes_vnic *nesvnic = netdev_priv(netdev);
1553 struct nes_device *nesdev = nesvnic->nesdev;
Chien Tungedd2fd62008-02-15 21:00:36 -06001554 struct nes_adapter *nesadapter = nesdev->nesadapter;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001555 u32 u32temp;
Chien Tungedd2fd62008-02-15 21:00:36 -06001556 unsigned long flags;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001557
Chien Tungedd2fd62008-02-15 21:00:36 -06001558 spin_lock_irqsave(&nesadapter->phy_lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001559 nesvnic->vlan_grp = grp;
1560
Chien Tungedd2fd62008-02-15 21:00:36 -06001561 nes_debug(NES_DBG_NETDEV, "%s: %s\n", __func__, netdev->name);
1562
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001563 /* Enable/Disable VLAN Stripping */
1564 u32temp = nes_read_indexed(nesdev, NES_IDX_PCIX_DIAG);
1565 if (grp)
1566 u32temp &= 0xfdffffff;
1567 else
1568 u32temp |= 0x02000000;
1569
1570 nes_write_indexed(nesdev, NES_IDX_PCIX_DIAG, u32temp);
Chien Tungedd2fd62008-02-15 21:00:36 -06001571 spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001572}
1573
Stephen Hemmingerd0929552009-03-20 19:35:31 +00001574static const struct net_device_ops nes_netdev_ops = {
1575 .ndo_open = nes_netdev_open,
1576 .ndo_stop = nes_netdev_stop,
1577 .ndo_start_xmit = nes_netdev_start_xmit,
1578 .ndo_get_stats = nes_netdev_get_stats,
1579 .ndo_tx_timeout = nes_netdev_tx_timeout,
1580 .ndo_set_mac_address = nes_netdev_set_mac_address,
1581 .ndo_set_multicast_list = nes_netdev_set_multicast_list,
1582 .ndo_change_mtu = nes_netdev_change_mtu,
Stephen Hemmingerd0929552009-03-20 19:35:31 +00001583 .ndo_validate_addr = eth_validate_addr,
1584 .ndo_vlan_rx_register = nes_netdev_vlan_rx_register,
1585};
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001586
1587/**
1588 * nes_netdev_init - initialize network device
1589 */
1590struct net_device *nes_netdev_init(struct nes_device *nesdev,
1591 void __iomem *mmio_addr)
1592{
1593 u64 u64temp;
Linus Torvalds13220a92009-03-26 15:54:36 -07001594 struct nes_vnic *nesvnic;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001595 struct net_device *netdev;
1596 struct nic_qp_map *curr_qp_map;
Chien Tung09124e12010-02-23 17:52:10 +00001597 u8 phy_type = nesdev->nesadapter->phy_type[nesdev->mac_index];
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001598
1599 netdev = alloc_etherdev(sizeof(struct nes_vnic));
1600 if (!netdev) {
1601 printk(KERN_ERR PFX "nesvnic etherdev alloc failed");
1602 return NULL;
1603 }
Linus Torvalds13220a92009-03-26 15:54:36 -07001604 nesvnic = netdev_priv(netdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001605
1606 nes_debug(NES_DBG_INIT, "netdev = %p, %s\n", netdev, netdev->name);
1607
1608 SET_NETDEV_DEV(netdev, &nesdev->pcidev->dev);
1609
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001610 netdev->watchdog_timeo = NES_TX_TIMEOUT;
1611 netdev->irq = nesdev->pcidev->irq;
1612 netdev->mtu = ETH_DATA_LEN;
1613 netdev->hard_header_len = ETH_HLEN;
1614 netdev->addr_len = ETH_ALEN;
1615 netdev->type = ARPHRD_ETHER;
1616 netdev->features = NETIF_F_HIGHDMA;
Stephen Hemmingerd0929552009-03-20 19:35:31 +00001617 netdev->netdev_ops = &nes_netdev_ops;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001618 netdev->ethtool_ops = &nes_ethtool_ops;
1619 netif_napi_add(netdev, &nesvnic->napi, nes_netdev_poll, 128);
1620 nes_debug(NES_DBG_INIT, "Enabling VLAN Insert/Delete.\n");
1621 netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001622
1623 /* Fill in the port structure */
1624 nesvnic->netdev = netdev;
1625 nesvnic->nesdev = nesdev;
1626 nesvnic->msg_enable = netif_msg_init(debug, default_msg);
1627 nesvnic->netdev_index = nesdev->netdev_count;
1628 nesvnic->perfect_filter_index = nesdev->nesadapter->netdev_count;
Chien Tungedd2fd62008-02-15 21:00:36 -06001629 nesvnic->max_frame_size = netdev->mtu + netdev->hard_header_len + VLAN_HLEN;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001630
1631 curr_qp_map = nic_qp_mapping_per_function[PCI_FUNC(nesdev->pcidev->devfn)];
1632 nesvnic->nic.qp_id = curr_qp_map[nesdev->netdev_count].qpid;
1633 nesvnic->nic_index = curr_qp_map[nesdev->netdev_count].nic_index;
1634 nesvnic->logical_port = curr_qp_map[nesdev->netdev_count].logical_port;
1635
1636 /* Setup the burned in MAC address */
1637 u64temp = (u64)nesdev->nesadapter->mac_addr_low;
1638 u64temp += ((u64)nesdev->nesadapter->mac_addr_high) << 32;
1639 u64temp += nesvnic->nic_index;
1640 netdev->dev_addr[0] = (u8)(u64temp>>40);
1641 netdev->dev_addr[1] = (u8)(u64temp>>32);
1642 netdev->dev_addr[2] = (u8)(u64temp>>24);
1643 netdev->dev_addr[3] = (u8)(u64temp>>16);
1644 netdev->dev_addr[4] = (u8)(u64temp>>8);
1645 netdev->dev_addr[5] = (u8)u64temp;
1646 memcpy(netdev->perm_addr, netdev->dev_addr, 6);
1647
1648 if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV)) {
1649 netdev->features |= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
1650 netdev->features |= NETIF_F_GSO | NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
1651 } else {
1652 netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
1653 }
1654
1655 nes_debug(NES_DBG_INIT, "nesvnic = %p, reported features = 0x%lX, QPid = %d,"
1656 " nic_index = %d, logical_port = %d, mac_index = %d.\n",
1657 nesvnic, (unsigned long)netdev->features, nesvnic->nic.qp_id,
1658 nesvnic->nic_index, nesvnic->logical_port, nesdev->mac_index);
1659
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -07001660 if (nesvnic->nesdev->nesadapter->port_count == 1 &&
1661 nesvnic->nesdev->nesadapter->adapter_fcn_count == 1) {
1662
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001663 nesvnic->qp_nic_index[0] = nesvnic->nic_index;
1664 nesvnic->qp_nic_index[1] = nesvnic->nic_index + 1;
1665 if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT) {
1666 nesvnic->qp_nic_index[2] = 0xf;
1667 nesvnic->qp_nic_index[3] = 0xf;
1668 } else {
1669 nesvnic->qp_nic_index[2] = nesvnic->nic_index + 2;
1670 nesvnic->qp_nic_index[3] = nesvnic->nic_index + 3;
1671 }
1672 } else {
Vadim Makhervaks7e36d3d2008-10-03 12:21:18 -07001673 if (nesvnic->nesdev->nesadapter->port_count == 2 ||
1674 (nesvnic->nesdev->nesadapter->port_count == 1 &&
1675 nesvnic->nesdev->nesadapter->adapter_fcn_count == 2)) {
1676 nesvnic->qp_nic_index[0] = nesvnic->nic_index;
1677 nesvnic->qp_nic_index[1] = nesvnic->nic_index
1678 + 2;
1679 nesvnic->qp_nic_index[2] = 0xf;
1680 nesvnic->qp_nic_index[3] = 0xf;
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001681 } else {
1682 nesvnic->qp_nic_index[0] = nesvnic->nic_index;
1683 nesvnic->qp_nic_index[1] = 0xf;
1684 nesvnic->qp_nic_index[2] = 0xf;
1685 nesvnic->qp_nic_index[3] = 0xf;
1686 }
1687 }
1688 nesvnic->next_qp_nic_index = 0;
1689
1690 if (nesdev->netdev_count == 0) {
1691 nesvnic->rdma_enabled = 1;
1692 } else {
1693 nesvnic->rdma_enabled = 0;
1694 }
1695 nesvnic->nic_cq.cq_number = nesvnic->nic.qp_id;
1696 spin_lock_init(&nesvnic->tx_lock);
1697 nesdev->netdev[nesdev->netdev_count] = netdev;
1698
1699 nes_debug(NES_DBG_INIT, "Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n",
1700 nesvnic, nesdev->mac_index);
1701 list_add_tail(&nesvnic->list, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]);
1702
1703 if ((nesdev->netdev_count == 0) &&
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001704 ((PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index) ||
Chien Tung09124e12010-02-23 17:52:10 +00001705 ((phy_type == NES_PHY_TYPE_PUMA_1G) &&
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001706 (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) ||
1707 ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) {
Chien Tunga72042c2010-03-03 19:13:26 +00001708 u32 u32temp;
1709 u32 link_mask;
1710 u32 link_val;
1711
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001712 u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001713 (0x200 * (nesdev->mac_index & 1)));
Chien Tung09124e12010-02-23 17:52:10 +00001714 if (phy_type != NES_PHY_TYPE_PUMA_1G) {
Eric Schneider0e1de5d2008-04-29 13:46:54 -07001715 u32temp |= 0x00200000;
1716 nes_write_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
1717 (0x200 * (nesdev->mac_index & 1)), u32temp);
1718 }
1719
Chien Tunga72042c2010-03-03 19:13:26 +00001720 /* Check and set linkup here. This is for back to back */
1721 /* configuration where second port won't get link interrupt */
1722 switch (phy_type) {
1723 case NES_PHY_TYPE_PUMA_1G:
1724 if (nesdev->mac_index < 2) {
1725 link_mask = 0x01010000;
1726 link_val = 0x01010000;
1727 } else {
1728 link_mask = 0x02020000;
1729 link_val = 0x02020000;
1730 }
1731 break;
1732 default:
1733 link_mask = 0x0f1f0000;
1734 link_val = 0x0f0f0000;
1735 break;
1736 }
1737
1738 u32temp = nes_read_indexed(nesdev,
1739 NES_IDX_PHY_PCS_CONTROL_STATUS0 +
1740 (0x200 * (nesdev->mac_index & 1)));
1741 if ((u32temp & link_mask) == link_val)
1742 nesvnic->linkup = 1;
1743
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001744 /* clear the MAC interrupt status, assumes direct logical to physical mapping */
Glenn Streiff11e07042008-02-15 11:41:27 -06001745 u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index));
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001746 nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp);
Glenn Streiff11e07042008-02-15 11:41:27 -06001747 nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index), u32temp);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001748
Chien Tung09124e12010-02-23 17:52:10 +00001749 nes_init_phy(nesdev);
Glenn Streiff3c2d7742008-02-04 20:20:45 -08001750 }
1751
1752 return netdev;
1753}
1754
1755
1756/**
1757 * nes_netdev_destroy - destroy network device structure
1758 */
1759void nes_netdev_destroy(struct net_device *netdev)
1760{
1761 struct nes_vnic *nesvnic = netdev_priv(netdev);
1762
1763 /* make sure 'stop' method is called by Linux stack */
1764 /* nes_netdev_stop(netdev); */
1765
1766 list_del(&nesvnic->list);
1767
1768 if (nesvnic->of_device_registered) {
1769 nes_destroy_ofa_device(nesvnic->nesibdev);
1770 }
1771
1772 free_netdev(netdev);
1773}
1774
1775
1776/**
1777 * nes_nic_cm_xmit -- CM calls this to send out pkts
1778 */
1779int nes_nic_cm_xmit(struct sk_buff *skb, struct net_device *netdev)
1780{
1781 int ret;
1782
1783 skb->dev = netdev;
1784 ret = dev_queue_xmit(skb);
1785 if (ret) {
1786 nes_debug(NES_DBG_CM, "Bad return code from dev_queue_xmit %d\n", ret);
1787 }
1788
1789 return ret;
1790}