blob: 1e5e66facabd263268b94355a0ab8e198b9b5a77 [file] [log] [blame]
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001/*
2 * Copyright (C) 2009 - QLogic Corporation.
3 * All rights reserved.
4 *
5 * 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.
9 *
10 * 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.
14 *
15 * 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.
19 *
20 * The full GNU General Public License is included in this distribution
21 * in the file called "COPYING".
22 *
23 */
24
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090025#include <linux/slab.h>
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000026#include <linux/vmalloc.h>
27#include <linux/interrupt.h>
28
29#include "qlcnic.h"
30
31#include <linux/dma-mapping.h>
32#include <linux/if_vlan.h>
33#include <net/ip.h>
34#include <linux/ipv6.h>
35#include <linux/inetdevice.h>
36#include <linux/sysfs.h>
37
38MODULE_DESCRIPTION("QLogic 10 GbE Converged Ethernet Driver");
39MODULE_LICENSE("GPL");
40MODULE_VERSION(QLCNIC_LINUX_VERSIONID);
41MODULE_FIRMWARE(QLCNIC_UNIFIED_ROMIMAGE_NAME);
42
43char qlcnic_driver_name[] = "qlcnic";
44static const char qlcnic_driver_string[] = "QLogic Converged Ethernet Driver v"
45 QLCNIC_LINUX_VERSIONID;
46
47static int port_mode = QLCNIC_PORT_MODE_AUTO_NEG;
48
49/* Default to restricted 1G auto-neg mode */
50static int wol_port_mode = 5;
51
52static int use_msi = 1;
53module_param(use_msi, int, 0644);
54MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled");
55
56static int use_msi_x = 1;
57module_param(use_msi_x, int, 0644);
58MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled");
59
60static int auto_fw_reset = AUTO_FW_RESET_ENABLED;
61module_param(auto_fw_reset, int, 0644);
62MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled");
63
Amit Kumar Salecha4d5bdb32010-05-17 01:22:11 +000064static int load_fw_file;
65module_param(load_fw_file, int, 0644);
66MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file");
67
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +000068static int qlcnic_config_npars;
69module_param(qlcnic_config_npars, int, 0644);
70MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled");
71
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000072static int __devinit qlcnic_probe(struct pci_dev *pdev,
73 const struct pci_device_id *ent);
74static void __devexit qlcnic_remove(struct pci_dev *pdev);
75static int qlcnic_open(struct net_device *netdev);
76static int qlcnic_close(struct net_device *netdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000077static void qlcnic_tx_timeout(struct net_device *netdev);
78static void qlcnic_tx_timeout_task(struct work_struct *work);
79static void qlcnic_attach_work(struct work_struct *work);
80static void qlcnic_fwinit_work(struct work_struct *work);
81static void qlcnic_fw_poll_work(struct work_struct *work);
82static void qlcnic_schedule_work(struct qlcnic_adapter *adapter,
83 work_func_t func, int delay);
84static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter);
85static int qlcnic_poll(struct napi_struct *napi, int budget);
86#ifdef CONFIG_NET_POLL_CONTROLLER
87static void qlcnic_poll_controller(struct net_device *netdev);
88#endif
89
90static void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter);
91static void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter);
92static void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
93static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
94
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +000095static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000096static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter);
97static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
98
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +000099static irqreturn_t qlcnic_tmp_intr(int irq, void *data);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000100static irqreturn_t qlcnic_intr(int irq, void *data);
101static irqreturn_t qlcnic_msi_intr(int irq, void *data);
102static irqreturn_t qlcnic_msix_intr(int irq, void *data);
103
104static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev);
105static void qlcnic_config_indev_addr(struct net_device *dev, unsigned long);
106
107/* PCI Device ID Table */
108#define ENTRY(device) \
109 {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
110 .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0}
111
112#define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020
113
Amit Kumar Salecha6a902882010-02-01 05:24:54 +0000114static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000115 ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X),
116 {0,}
117};
118
119MODULE_DEVICE_TABLE(pci, qlcnic_pci_tbl);
120
121
122void
123qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
124 struct qlcnic_host_tx_ring *tx_ring)
125{
126 writel(tx_ring->producer, tx_ring->crb_cmd_producer);
127
128 if (qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH) {
129 netif_stop_queue(adapter->netdev);
130 smp_mb();
Sucheta Chakraborty8bfe8b92010-03-08 00:14:46 +0000131 adapter->stats.xmit_off++;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000132 }
133}
134
135static const u32 msi_tgt_status[8] = {
136 ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
137 ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
138 ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
139 ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
140};
141
142static const
143struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG;
144
145static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
146{
147 writel(0, sds_ring->crb_intr_mask);
148}
149
150static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
151{
152 struct qlcnic_adapter *adapter = sds_ring->adapter;
153
154 writel(0x1, sds_ring->crb_intr_mask);
155
156 if (!QLCNIC_IS_MSI_FAMILY(adapter))
157 writel(0xfbff, adapter->tgt_mask_reg);
158}
159
160static int
161qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
162{
163 int size = sizeof(struct qlcnic_host_sds_ring) * count;
164
165 recv_ctx->sds_rings = kzalloc(size, GFP_KERNEL);
166
167 return (recv_ctx->sds_rings == NULL);
168}
169
170static void
171qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
172{
173 if (recv_ctx->sds_rings != NULL)
174 kfree(recv_ctx->sds_rings);
175
176 recv_ctx->sds_rings = NULL;
177}
178
179static int
180qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
181{
182 int ring;
183 struct qlcnic_host_sds_ring *sds_ring;
184 struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
185
186 if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
187 return -ENOMEM;
188
189 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
190 sds_ring = &recv_ctx->sds_rings[ring];
191 netif_napi_add(netdev, &sds_ring->napi,
192 qlcnic_poll, QLCNIC_NETDEV_WEIGHT);
193 }
194
195 return 0;
196}
197
198static void
199qlcnic_napi_del(struct qlcnic_adapter *adapter)
200{
201 int ring;
202 struct qlcnic_host_sds_ring *sds_ring;
203 struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
204
205 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
206 sds_ring = &recv_ctx->sds_rings[ring];
207 netif_napi_del(&sds_ring->napi);
208 }
209
210 qlcnic_free_sds_rings(&adapter->recv_ctx);
211}
212
213static void
214qlcnic_napi_enable(struct qlcnic_adapter *adapter)
215{
216 int ring;
217 struct qlcnic_host_sds_ring *sds_ring;
218 struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
219
Amit Kumar Salecha780ab792010-04-22 02:51:41 +0000220 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
221 return;
222
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000223 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
224 sds_ring = &recv_ctx->sds_rings[ring];
225 napi_enable(&sds_ring->napi);
226 qlcnic_enable_int(sds_ring);
227 }
228}
229
230static void
231qlcnic_napi_disable(struct qlcnic_adapter *adapter)
232{
233 int ring;
234 struct qlcnic_host_sds_ring *sds_ring;
235 struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
236
Amit Kumar Salecha780ab792010-04-22 02:51:41 +0000237 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
238 return;
239
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000240 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
241 sds_ring = &recv_ctx->sds_rings[ring];
242 qlcnic_disable_int(sds_ring);
243 napi_synchronize(&sds_ring->napi);
244 napi_disable(&sds_ring->napi);
245 }
246}
247
248static void qlcnic_clear_stats(struct qlcnic_adapter *adapter)
249{
250 memset(&adapter->stats, 0, sizeof(adapter->stats));
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000251}
252
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000253static void qlcnic_set_port_mode(struct qlcnic_adapter *adapter)
254{
255 u32 val, data;
256
257 val = adapter->ahw.board_type;
258 if ((val == QLCNIC_BRDTYPE_P3_HMEZ) ||
259 (val == QLCNIC_BRDTYPE_P3_XG_LOM)) {
260 if (port_mode == QLCNIC_PORT_MODE_802_3_AP) {
261 data = QLCNIC_PORT_MODE_802_3_AP;
262 QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
263 } else if (port_mode == QLCNIC_PORT_MODE_XG) {
264 data = QLCNIC_PORT_MODE_XG;
265 QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
266 } else if (port_mode == QLCNIC_PORT_MODE_AUTO_NEG_1G) {
267 data = QLCNIC_PORT_MODE_AUTO_NEG_1G;
268 QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
269 } else if (port_mode == QLCNIC_PORT_MODE_AUTO_NEG_XG) {
270 data = QLCNIC_PORT_MODE_AUTO_NEG_XG;
271 QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
272 } else {
273 data = QLCNIC_PORT_MODE_AUTO_NEG;
274 QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
275 }
276
277 if ((wol_port_mode != QLCNIC_PORT_MODE_802_3_AP) &&
278 (wol_port_mode != QLCNIC_PORT_MODE_XG) &&
279 (wol_port_mode != QLCNIC_PORT_MODE_AUTO_NEG_1G) &&
280 (wol_port_mode != QLCNIC_PORT_MODE_AUTO_NEG_XG)) {
281 wol_port_mode = QLCNIC_PORT_MODE_AUTO_NEG;
282 }
283 QLCWR32(adapter, QLCNIC_WOL_PORT_MODE, wol_port_mode);
284 }
285}
286
287static void qlcnic_set_msix_bit(struct pci_dev *pdev, int enable)
288{
289 u32 control;
290 int pos;
291
292 pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
293 if (pos) {
294 pci_read_config_dword(pdev, pos, &control);
295 if (enable)
296 control |= PCI_MSIX_FLAGS_ENABLE;
297 else
298 control = 0;
299 pci_write_config_dword(pdev, pos, control);
300 }
301}
302
303static void qlcnic_init_msix_entries(struct qlcnic_adapter *adapter, int count)
304{
305 int i;
306
307 for (i = 0; i < count; i++)
308 adapter->msix_entries[i].entry = i;
309}
310
311static int
312qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
313{
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000314 u8 mac_addr[ETH_ALEN];
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000315 struct net_device *netdev = adapter->netdev;
316 struct pci_dev *pdev = adapter->pdev;
317
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000318 if (adapter->nic_ops->get_mac_addr(adapter, mac_addr) != 0)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000319 return -EIO;
320
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000321 memcpy(netdev->dev_addr, mac_addr, ETH_ALEN);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000322 memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
323 memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len);
324
325 /* set station address */
326
327 if (!is_valid_ether_addr(netdev->perm_addr))
328 dev_warn(&pdev->dev, "Bad MAC address %pM.\n",
329 netdev->dev_addr);
330
331 return 0;
332}
333
334static int qlcnic_set_mac(struct net_device *netdev, void *p)
335{
336 struct qlcnic_adapter *adapter = netdev_priv(netdev);
337 struct sockaddr *addr = p;
338
339 if (!is_valid_ether_addr(addr->sa_data))
340 return -EINVAL;
341
342 if (netif_running(netdev)) {
343 netif_device_detach(netdev);
344 qlcnic_napi_disable(adapter);
345 }
346
347 memcpy(adapter->mac_addr, addr->sa_data, netdev->addr_len);
348 memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
349 qlcnic_set_multi(adapter->netdev);
350
351 if (netif_running(netdev)) {
352 netif_device_attach(netdev);
353 qlcnic_napi_enable(adapter);
354 }
355 return 0;
356}
357
358static const struct net_device_ops qlcnic_netdev_ops = {
359 .ndo_open = qlcnic_open,
360 .ndo_stop = qlcnic_close,
361 .ndo_start_xmit = qlcnic_xmit_frame,
362 .ndo_get_stats = qlcnic_get_stats,
363 .ndo_validate_addr = eth_validate_addr,
364 .ndo_set_multicast_list = qlcnic_set_multi,
365 .ndo_set_mac_address = qlcnic_set_mac,
366 .ndo_change_mtu = qlcnic_change_mtu,
367 .ndo_tx_timeout = qlcnic_tx_timeout,
368#ifdef CONFIG_NET_POLL_CONTROLLER
369 .ndo_poll_controller = qlcnic_poll_controller,
370#endif
371};
372
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000373static struct qlcnic_nic_template qlcnic_ops = {
374 .get_mac_addr = qlcnic_get_mac_addr,
375 .config_bridged_mode = qlcnic_config_bridged_mode,
376 .config_led = qlcnic_config_led,
377 .set_ilb_mode = qlcnic_set_ilb_mode,
378 .clear_ilb_mode = qlcnic_clear_ilb_mode
379};
380
381static struct qlcnic_nic_template qlcnic_pf_ops = {
382 .get_mac_addr = qlcnic_get_mac_address,
383 .config_bridged_mode = qlcnic_config_bridged_mode,
384 .config_led = qlcnic_config_led,
385 .set_ilb_mode = qlcnic_set_ilb_mode,
386 .clear_ilb_mode = qlcnic_clear_ilb_mode
387};
388
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000389static void
390qlcnic_setup_intr(struct qlcnic_adapter *adapter)
391{
392 const struct qlcnic_legacy_intr_set *legacy_intrp;
393 struct pci_dev *pdev = adapter->pdev;
394 int err, num_msix;
395
396 if (adapter->rss_supported) {
397 num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ?
398 MSIX_ENTRIES_PER_ADAPTER : 2;
399 } else
400 num_msix = 1;
401
402 adapter->max_sds_rings = 1;
403
404 adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED);
405
406 legacy_intrp = &legacy_intr[adapter->ahw.pci_func];
407
408 adapter->int_vec_bit = legacy_intrp->int_vec_bit;
409 adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter,
410 legacy_intrp->tgt_status_reg);
411 adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter,
412 legacy_intrp->tgt_mask_reg);
413 adapter->isr_int_vec = qlcnic_get_ioaddr(adapter, ISR_INT_VECTOR);
414
415 adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter,
416 ISR_INT_STATE_REG);
417
418 qlcnic_set_msix_bit(pdev, 0);
419
420 if (adapter->msix_supported) {
421
422 qlcnic_init_msix_entries(adapter, num_msix);
423 err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
424 if (err == 0) {
425 adapter->flags |= QLCNIC_MSIX_ENABLED;
426 qlcnic_set_msix_bit(pdev, 1);
427
428 if (adapter->rss_supported)
429 adapter->max_sds_rings = num_msix;
430
431 dev_info(&pdev->dev, "using msi-x interrupts\n");
432 return;
433 }
434
435 if (err > 0)
436 pci_disable_msix(pdev);
437
438 /* fall through for msi */
439 }
440
441 if (use_msi && !pci_enable_msi(pdev)) {
442 adapter->flags |= QLCNIC_MSI_ENABLED;
443 adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter,
444 msi_tgt_status[adapter->ahw.pci_func]);
445 dev_info(&pdev->dev, "using msi interrupts\n");
446 adapter->msix_entries[0].vector = pdev->irq;
447 return;
448 }
449
450 dev_info(&pdev->dev, "using legacy interrupts\n");
451 adapter->msix_entries[0].vector = pdev->irq;
452}
453
454static void
455qlcnic_teardown_intr(struct qlcnic_adapter *adapter)
456{
457 if (adapter->flags & QLCNIC_MSIX_ENABLED)
458 pci_disable_msix(adapter->pdev);
459 if (adapter->flags & QLCNIC_MSI_ENABLED)
460 pci_disable_msi(adapter->pdev);
461}
462
463static void
464qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
465{
466 if (adapter->ahw.pci_base0 != NULL)
467 iounmap(adapter->ahw.pci_base0);
468}
469
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000470/* Use api lock to access this function */
471static int
472qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
473{
474 u8 id;
475 u32 ref_count;
476 int i, ret = 1;
477 u32 data = QLCNIC_MGMT_FUNC;
478 void __iomem *priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
479
480 /* If other drivers are not in use set their privilege level */
481 ref_count = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
482 ret = qlcnic_api_lock(adapter);
483 if (ret)
484 goto err_lock;
485 if (QLC_DEV_CLR_REF_CNT(ref_count, adapter->ahw.pci_func))
486 goto err_npar;
487
488 for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
489 id = adapter->npars[i].id;
490 if (adapter->npars[i].type != QLCNIC_TYPE_NIC ||
491 id == adapter->ahw.pci_func)
492 continue;
493 data |= (qlcnic_config_npars & QLC_DEV_SET_DRV(0xf, id));
494 }
495 writel(data, priv_op);
496
497err_npar:
498 qlcnic_api_unlock(adapter);
499err_lock:
500 return ret;
501}
502
503static u8
504qlcnic_set_mgmt_driver(struct qlcnic_adapter *adapter)
505{
506 u8 i, ret = 0;
507
508 if (qlcnic_get_pci_info(adapter))
509 return ret;
510 /* Set the eswitch */
511 for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) {
512 if (!qlcnic_get_eswitch_capabilities(adapter, i,
513 &adapter->eswitch[i])) {
514 ret++;
515 qlcnic_toggle_eswitch(adapter, i, ret);
516 }
517 }
518 return ret;
519}
520
521static u32
522qlcnic_get_driver_mode(struct qlcnic_adapter *adapter)
523{
524 void __iomem *msix_base_addr;
525 void __iomem *priv_op;
526 u32 func;
527 u32 msix_base;
528 u32 op_mode, priv_level;
529
530 /* Determine FW API version */
531 adapter->fw_hal_version = readl(adapter->ahw.pci_base0 + QLCNIC_FW_API);
532 if (adapter->fw_hal_version == ~0) {
533 adapter->nic_ops = &qlcnic_ops;
534 adapter->fw_hal_version = QLCNIC_FW_BASE;
535 adapter->ahw.pci_func = PCI_FUNC(adapter->pdev->devfn);
536 dev_info(&adapter->pdev->dev,
537 "FW does not support nic partion\n");
538 return adapter->fw_hal_version;
539 }
540
541 /* Find PCI function number */
542 pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func);
543 msix_base_addr = adapter->ahw.pci_base0 + QLCNIC_MSIX_BASE;
544 msix_base = readl(msix_base_addr);
545 func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
546 adapter->ahw.pci_func = func;
547
548 /* Determine function privilege level */
549 priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
550 op_mode = readl(priv_op);
551 if (op_mode == QLC_DEV_DRV_DEFAULT) {
552 priv_level = QLCNIC_MGMT_FUNC;
553 if (qlcnic_api_lock(adapter))
554 return 0;
555 op_mode = (op_mode & ~QLC_DEV_SET_DRV(0xf, func)) |
556 (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, func));
557 writel(op_mode, priv_op);
558 qlcnic_api_unlock(adapter);
559
560 } else
561 priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
562
563 switch (priv_level) {
564 case QLCNIC_MGMT_FUNC:
565 adapter->op_mode = QLCNIC_MGMT_FUNC;
566 adapter->nic_ops = &qlcnic_pf_ops;
567 /* Set privilege level for other functions */
568 if (qlcnic_config_npars)
569 qlcnic_set_function_modes(adapter);
570 dev_info(&adapter->pdev->dev,
571 "HAL Version: %d, Management function\n",
572 adapter->fw_hal_version);
573 break;
574 case QLCNIC_PRIV_FUNC:
575 adapter->op_mode = QLCNIC_PRIV_FUNC;
576 dev_info(&adapter->pdev->dev,
577 "HAL Version: %d, Privileged function\n",
578 adapter->fw_hal_version);
579 adapter->nic_ops = &qlcnic_pf_ops;
580 break;
581 default:
582 dev_info(&adapter->pdev->dev, "Unknown function mode: %d\n",
583 priv_level);
584 return 0;
585 }
586 return adapter->fw_hal_version;
587}
588
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000589static int
590qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
591{
592 void __iomem *mem_ptr0 = NULL;
593 resource_size_t mem_base;
594 unsigned long mem_len, pci_len0 = 0;
595
596 struct pci_dev *pdev = adapter->pdev;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000597
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000598 /* remap phys address */
599 mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
600 mem_len = pci_resource_len(pdev, 0);
601
602 if (mem_len == QLCNIC_PCI_2MB_SIZE) {
603
604 mem_ptr0 = pci_ioremap_bar(pdev, 0);
605 if (mem_ptr0 == NULL) {
606 dev_err(&pdev->dev, "failed to map PCI bar 0\n");
607 return -EIO;
608 }
609 pci_len0 = mem_len;
610 } else {
611 return -EIO;
612 }
613
614 dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
615
616 adapter->ahw.pci_base0 = mem_ptr0;
617 adapter->ahw.pci_len0 = pci_len0;
618
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000619 if (!qlcnic_get_driver_mode(adapter)) {
620 iounmap(adapter->ahw.pci_base0);
621 return -EIO;
622 }
623
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000624 adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter,
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000625 QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(adapter->ahw.pci_func)));
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000626
627 return 0;
628}
629
630static void get_brd_name(struct qlcnic_adapter *adapter, char *name)
631{
632 struct pci_dev *pdev = adapter->pdev;
633 int i, found = 0;
634
635 for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) {
636 if (qlcnic_boards[i].vendor == pdev->vendor &&
637 qlcnic_boards[i].device == pdev->device &&
638 qlcnic_boards[i].sub_vendor == pdev->subsystem_vendor &&
639 qlcnic_boards[i].sub_device == pdev->subsystem_device) {
Sucheta Chakraborty02f6e462010-05-17 01:22:09 +0000640 sprintf(name, "%pM: %s" ,
641 adapter->mac_addr,
642 qlcnic_boards[i].short_name);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000643 found = 1;
644 break;
645 }
646
647 }
648
649 if (!found)
650 name = "Unknown";
651}
652
653static void
654qlcnic_check_options(struct qlcnic_adapter *adapter)
655{
656 u32 fw_major, fw_minor, fw_build;
657 char brd_name[QLCNIC_MAX_BOARD_NAME_LEN];
658 char serial_num[32];
659 int i, offset, val;
660 int *ptr32;
661 struct pci_dev *pdev = adapter->pdev;
662
663 adapter->driver_mismatch = 0;
664
665 ptr32 = (int *)&serial_num;
666 offset = QLCNIC_FW_SERIAL_NUM_OFFSET;
667 for (i = 0; i < 8; i++) {
668 if (qlcnic_rom_fast_read(adapter, offset, &val) == -1) {
669 dev_err(&pdev->dev, "error reading board info\n");
670 adapter->driver_mismatch = 1;
671 return;
672 }
673 ptr32[i] = cpu_to_le32(val);
674 offset += sizeof(u32);
675 }
676
677 fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
678 fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
679 fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB);
680
681 adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
682
683 if (adapter->portnum == 0) {
684 get_brd_name(adapter, brd_name);
685
686 pr_info("%s: %s Board Chip rev 0x%x\n",
687 module_name(THIS_MODULE),
688 brd_name, adapter->ahw.revision_id);
689 }
690
Amit Kumar Salecha251a84c2010-05-13 03:07:46 +0000691 dev_info(&pdev->dev, "firmware v%d.%d.%d\n",
692 fw_major, fw_minor, fw_build);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000693
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000694 if (adapter->fw_hal_version == QLCNIC_FW_NPAR)
695 qlcnic_get_nic_info(adapter, adapter->ahw.pci_func);
696 else
697 adapter->capabilities = QLCRD32(adapter, CRB_FW_CAPABILITIES_1);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000698
699 adapter->flags &= ~QLCNIC_LRO_ENABLED;
700
701 if (adapter->ahw.port_type == QLCNIC_XGBE) {
702 adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;
703 adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
704 } else if (adapter->ahw.port_type == QLCNIC_GBE) {
705 adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
706 adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
707 }
708
709 adapter->msix_supported = !!use_msi_x;
710 adapter->rss_supported = !!use_msi_x;
711
712 adapter->num_txd = MAX_CMD_DESCRIPTORS;
713
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000714 adapter->max_rds_rings = 2;
715}
716
717static int
718qlcnic_start_firmware(struct qlcnic_adapter *adapter)
719{
720 int val, err, first_boot;
721
Sucheta Chakrabortyaa5e18c2010-04-01 19:01:32 +0000722 err = qlcnic_can_start_firmware(adapter);
723 if (err < 0)
724 return err;
725 else if (!err)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000726 goto wait_init;
727
728 first_boot = QLCRD32(adapter, QLCNIC_CAM_RAM(0x1fc));
729 if (first_boot == 0x55555555)
730 /* This is the first boot after power up */
731 QLCWR32(adapter, QLCNIC_CAM_RAM(0x1fc), QLCNIC_BDINFO_MAGIC);
732
Amit Kumar Salecha4d5bdb32010-05-17 01:22:11 +0000733 if (load_fw_file)
734 qlcnic_request_firmware(adapter);
735 else
736 adapter->fw_type = QLCNIC_FLASH_ROMIMAGE;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000737
738 err = qlcnic_need_fw_reset(adapter);
739 if (err < 0)
740 goto err_out;
741 if (err == 0)
742 goto wait_init;
743
744 if (first_boot != 0x55555555) {
745 QLCWR32(adapter, CRB_CMDPEG_STATE, 0);
746 qlcnic_pinit_from_rom(adapter);
747 msleep(1);
748 }
749
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000750 QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0);
751 QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0);
752
753 qlcnic_set_port_mode(adapter);
754
755 err = qlcnic_load_firmware(adapter);
756 if (err)
757 goto err_out;
758
759 qlcnic_release_firmware(adapter);
760
761 val = (_QLCNIC_LINUX_MAJOR << 16)
762 | ((_QLCNIC_LINUX_MINOR << 8))
763 | (_QLCNIC_LINUX_SUBVERSION);
764 QLCWR32(adapter, CRB_DRIVER_VERSION, val);
765
766wait_init:
767 /* Handshake with the card before we register the devices. */
768 err = qlcnic_phantom_init(adapter);
769 if (err)
770 goto err_out;
771
772 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +0000773 qlcnic_idc_debug_info(adapter, 1);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000774
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000775 qlcnic_check_options(adapter);
776
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000777 if (adapter->fw_hal_version != QLCNIC_FW_BASE &&
778 adapter->op_mode == QLCNIC_MGMT_FUNC)
779 qlcnic_set_mgmt_driver(adapter);
780
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000781 adapter->need_fw_reset = 0;
782
Amit Kumar Salechaa7fc9482010-05-17 01:22:14 +0000783 qlcnic_release_firmware(adapter);
784 return 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000785
786err_out:
Amit Kumar Salechaa7fc9482010-05-17 01:22:14 +0000787 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
788 dev_err(&adapter->pdev->dev, "Device state set to failed\n");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000789 qlcnic_release_firmware(adapter);
790 return err;
791}
792
793static int
794qlcnic_request_irq(struct qlcnic_adapter *adapter)
795{
796 irq_handler_t handler;
797 struct qlcnic_host_sds_ring *sds_ring;
798 int err, ring;
799
800 unsigned long flags = 0;
801 struct net_device *netdev = adapter->netdev;
802 struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
803
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +0000804 if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
805 handler = qlcnic_tmp_intr;
806 if (!QLCNIC_IS_MSI_FAMILY(adapter))
807 flags |= IRQF_SHARED;
808
809 } else {
810 if (adapter->flags & QLCNIC_MSIX_ENABLED)
811 handler = qlcnic_msix_intr;
812 else if (adapter->flags & QLCNIC_MSI_ENABLED)
813 handler = qlcnic_msi_intr;
814 else {
815 flags |= IRQF_SHARED;
816 handler = qlcnic_intr;
817 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000818 }
819 adapter->irq = netdev->irq;
820
821 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
822 sds_ring = &recv_ctx->sds_rings[ring];
823 sprintf(sds_ring->name, "%s[%d]", netdev->name, ring);
824 err = request_irq(sds_ring->irq, handler,
825 flags, sds_ring->name, sds_ring);
826 if (err)
827 return err;
828 }
829
830 return 0;
831}
832
833static void
834qlcnic_free_irq(struct qlcnic_adapter *adapter)
835{
836 int ring;
837 struct qlcnic_host_sds_ring *sds_ring;
838
839 struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
840
841 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
842 sds_ring = &recv_ctx->sds_rings[ring];
843 free_irq(sds_ring->irq, sds_ring);
844 }
845}
846
847static void
848qlcnic_init_coalesce_defaults(struct qlcnic_adapter *adapter)
849{
850 adapter->coal.flags = QLCNIC_INTR_DEFAULT;
851 adapter->coal.normal.data.rx_time_us =
852 QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
853 adapter->coal.normal.data.rx_packets =
854 QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
855 adapter->coal.normal.data.tx_time_us =
856 QLCNIC_DEFAULT_INTR_COALESCE_TX_TIME_US;
857 adapter->coal.normal.data.tx_packets =
858 QLCNIC_DEFAULT_INTR_COALESCE_TX_PACKETS;
859}
860
861static int
862__qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
863{
864 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
865 return -EIO;
866
867 qlcnic_set_multi(netdev);
868 qlcnic_fw_cmd_set_mtu(adapter, netdev->mtu);
869
870 adapter->ahw.linkup = 0;
871
872 if (adapter->max_sds_rings > 1)
873 qlcnic_config_rss(adapter, 1);
874
875 qlcnic_config_intr_coalesce(adapter);
876
877 if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
878 qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED);
879
880 qlcnic_napi_enable(adapter);
881
882 qlcnic_linkevent_request(adapter, 1);
883
884 set_bit(__QLCNIC_DEV_UP, &adapter->state);
885 return 0;
886}
887
888/* Usage: During resume and firmware recovery module.*/
889
890static int
891qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
892{
893 int err = 0;
894
895 rtnl_lock();
896 if (netif_running(netdev))
897 err = __qlcnic_up(adapter, netdev);
898 rtnl_unlock();
899
900 return err;
901}
902
903static void
904__qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
905{
906 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
907 return;
908
909 if (!test_and_clear_bit(__QLCNIC_DEV_UP, &adapter->state))
910 return;
911
912 smp_mb();
913 spin_lock(&adapter->tx_clean_lock);
914 netif_carrier_off(netdev);
915 netif_tx_disable(netdev);
916
917 qlcnic_free_mac_list(adapter);
918
919 qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE);
920
921 qlcnic_napi_disable(adapter);
922
923 qlcnic_release_tx_buffers(adapter);
924 spin_unlock(&adapter->tx_clean_lock);
925}
926
927/* Usage: During suspend and firmware recovery module */
928
929static void
930qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
931{
932 rtnl_lock();
933 if (netif_running(netdev))
934 __qlcnic_down(adapter, netdev);
935 rtnl_unlock();
936
937}
938
939static int
940qlcnic_attach(struct qlcnic_adapter *adapter)
941{
942 struct net_device *netdev = adapter->netdev;
943 struct pci_dev *pdev = adapter->pdev;
944 int err, ring;
945 struct qlcnic_host_rds_ring *rds_ring;
946
947 if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC)
948 return 0;
949
950 err = qlcnic_init_firmware(adapter);
951 if (err)
952 return err;
953
954 err = qlcnic_napi_add(adapter, netdev);
955 if (err)
956 return err;
957
958 err = qlcnic_alloc_sw_resources(adapter);
959 if (err) {
960 dev_err(&pdev->dev, "Error in setting sw resources\n");
961 return err;
962 }
963
964 err = qlcnic_alloc_hw_resources(adapter);
965 if (err) {
966 dev_err(&pdev->dev, "Error in setting hw resources\n");
967 goto err_out_free_sw;
968 }
969
970
971 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
972 rds_ring = &adapter->recv_ctx.rds_rings[ring];
973 qlcnic_post_rx_buffers(adapter, ring, rds_ring);
974 }
975
976 err = qlcnic_request_irq(adapter);
977 if (err) {
978 dev_err(&pdev->dev, "failed to setup interrupt\n");
979 goto err_out_free_rxbuf;
980 }
981
982 qlcnic_init_coalesce_defaults(adapter);
983
984 qlcnic_create_sysfs_entries(adapter);
985
986 adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC;
987 return 0;
988
989err_out_free_rxbuf:
990 qlcnic_release_rx_buffers(adapter);
991 qlcnic_free_hw_resources(adapter);
992err_out_free_sw:
993 qlcnic_free_sw_resources(adapter);
994 return err;
995}
996
997static void
998qlcnic_detach(struct qlcnic_adapter *adapter)
999{
1000 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1001 return;
1002
1003 qlcnic_remove_sysfs_entries(adapter);
1004
1005 qlcnic_free_hw_resources(adapter);
1006 qlcnic_release_rx_buffers(adapter);
1007 qlcnic_free_irq(adapter);
1008 qlcnic_napi_del(adapter);
1009 qlcnic_free_sw_resources(adapter);
1010
1011 adapter->is_up = 0;
1012}
1013
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001014void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
1015{
1016 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1017 struct qlcnic_host_sds_ring *sds_ring;
1018 int ring;
1019
Sucheta Chakraborty78ad3892010-05-17 01:22:12 +00001020 clear_bit(__QLCNIC_DEV_UP, &adapter->state);
Amit Kumar Salechacdaff182010-02-01 05:25:00 +00001021 if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
1022 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
1023 sds_ring = &adapter->recv_ctx.sds_rings[ring];
1024 qlcnic_disable_int(sds_ring);
1025 }
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001026 }
1027
1028 qlcnic_detach(adapter);
1029
1030 adapter->diag_test = 0;
1031 adapter->max_sds_rings = max_sds_rings;
1032
1033 if (qlcnic_attach(adapter))
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00001034 goto out;
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001035
1036 if (netif_running(netdev))
1037 __qlcnic_up(adapter, netdev);
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00001038out:
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001039 netif_device_attach(netdev);
1040}
1041
1042int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
1043{
1044 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1045 struct qlcnic_host_sds_ring *sds_ring;
1046 int ring;
1047 int ret;
1048
1049 netif_device_detach(netdev);
1050
1051 if (netif_running(netdev))
1052 __qlcnic_down(adapter, netdev);
1053
1054 qlcnic_detach(adapter);
1055
1056 adapter->max_sds_rings = 1;
1057 adapter->diag_test = test;
1058
1059 ret = qlcnic_attach(adapter);
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00001060 if (ret) {
1061 netif_device_attach(netdev);
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001062 return ret;
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00001063 }
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001064
Amit Kumar Salechacdaff182010-02-01 05:25:00 +00001065 if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
1066 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
1067 sds_ring = &adapter->recv_ctx.sds_rings[ring];
1068 qlcnic_enable_int(sds_ring);
1069 }
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001070 }
Sucheta Chakraborty78ad3892010-05-17 01:22:12 +00001071 set_bit(__QLCNIC_DEV_UP, &adapter->state);
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001072
1073 return 0;
1074}
1075
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001076int
1077qlcnic_reset_context(struct qlcnic_adapter *adapter)
1078{
1079 int err = 0;
1080 struct net_device *netdev = adapter->netdev;
1081
1082 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
1083 return -EBUSY;
1084
1085 if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) {
1086
1087 netif_device_detach(netdev);
1088
1089 if (netif_running(netdev))
1090 __qlcnic_down(adapter, netdev);
1091
1092 qlcnic_detach(adapter);
1093
1094 if (netif_running(netdev)) {
1095 err = qlcnic_attach(adapter);
1096 if (!err)
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00001097 __qlcnic_up(adapter, netdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001098 }
1099
1100 netif_device_attach(netdev);
1101 }
1102
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001103 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1104 return err;
1105}
1106
1107static int
1108qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
Amit Kumar Salecha1bb09fb2010-05-14 03:07:46 -07001109 struct net_device *netdev, u8 pci_using_dac)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001110{
1111 int err;
1112 struct pci_dev *pdev = adapter->pdev;
1113
1114 adapter->rx_csum = 1;
1115 adapter->mc_enabled = 0;
1116 adapter->max_mc_count = 38;
1117
1118 netdev->netdev_ops = &qlcnic_netdev_ops;
1119 netdev->watchdog_timeo = 2*HZ;
1120
1121 qlcnic_change_mtu(netdev, netdev->mtu);
1122
1123 SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
1124
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001125 netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
1126 NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001127
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001128 netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
1129 NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001130
Amit Kumar Salecha1bb09fb2010-05-14 03:07:46 -07001131 if (pci_using_dac) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001132 netdev->features |= NETIF_F_HIGHDMA;
1133 netdev->vlan_features |= NETIF_F_HIGHDMA;
1134 }
1135
1136 if (adapter->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX)
1137 netdev->features |= (NETIF_F_HW_VLAN_TX);
1138
1139 if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
1140 netdev->features |= NETIF_F_LRO;
1141
1142 netdev->irq = adapter->msix_entries[0].vector;
1143
1144 INIT_WORK(&adapter->tx_timeout_task, qlcnic_tx_timeout_task);
1145
1146 if (qlcnic_read_mac_addr(adapter))
1147 dev_warn(&pdev->dev, "failed to read mac addr\n");
1148
1149 netif_carrier_off(netdev);
1150 netif_stop_queue(netdev);
1151
1152 err = register_netdev(netdev);
1153 if (err) {
1154 dev_err(&pdev->dev, "failed to register net device\n");
1155 return err;
1156 }
1157
1158 return 0;
1159}
1160
Amit Kumar Salecha1bb09fb2010-05-14 03:07:46 -07001161static int qlcnic_set_dma_mask(struct pci_dev *pdev, u8 *pci_using_dac)
1162{
1163 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
1164 !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
1165 *pci_using_dac = 1;
1166 else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) &&
1167 !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
1168 *pci_using_dac = 0;
1169 else {
1170 dev_err(&pdev->dev, "Unable to set DMA mask, aborting\n");
1171 return -EIO;
1172 }
1173
1174 return 0;
1175}
1176
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001177static int __devinit
1178qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1179{
1180 struct net_device *netdev = NULL;
1181 struct qlcnic_adapter *adapter = NULL;
1182 int err;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001183 uint8_t revision_id;
Amit Kumar Salecha1bb09fb2010-05-14 03:07:46 -07001184 uint8_t pci_using_dac;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001185
1186 err = pci_enable_device(pdev);
1187 if (err)
1188 return err;
1189
1190 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
1191 err = -ENODEV;
1192 goto err_out_disable_pdev;
1193 }
1194
Amit Kumar Salecha1bb09fb2010-05-14 03:07:46 -07001195 err = qlcnic_set_dma_mask(pdev, &pci_using_dac);
1196 if (err)
1197 goto err_out_disable_pdev;
1198
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001199 err = pci_request_regions(pdev, qlcnic_driver_name);
1200 if (err)
1201 goto err_out_disable_pdev;
1202
1203 pci_set_master(pdev);
1204
1205 netdev = alloc_etherdev(sizeof(struct qlcnic_adapter));
1206 if (!netdev) {
1207 dev_err(&pdev->dev, "failed to allocate net_device\n");
1208 err = -ENOMEM;
1209 goto err_out_free_res;
1210 }
1211
1212 SET_NETDEV_DEV(netdev, &pdev->dev);
1213
1214 adapter = netdev_priv(netdev);
1215 adapter->netdev = netdev;
1216 adapter->pdev = pdev;
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +00001217 adapter->dev_rst_time = jiffies;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001218
1219 revision_id = pdev->revision;
1220 adapter->ahw.revision_id = revision_id;
1221
1222 rwlock_init(&adapter->ahw.crb_lock);
1223 mutex_init(&adapter->ahw.mem_lock);
1224
1225 spin_lock_init(&adapter->tx_clean_lock);
1226 INIT_LIST_HEAD(&adapter->mac_list);
1227
1228 err = qlcnic_setup_pci_map(adapter);
1229 if (err)
1230 goto err_out_free_netdev;
1231
1232 /* This will be reset for mezz cards */
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001233 adapter->portnum = adapter->ahw.pci_func;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001234
1235 err = qlcnic_get_board_info(adapter);
1236 if (err) {
1237 dev_err(&pdev->dev, "Error getting board config info.\n");
1238 goto err_out_iounmap;
1239 }
1240
Sucheta Chakraborty02f6e462010-05-17 01:22:09 +00001241 if (qlcnic_read_mac_addr(adapter))
1242 dev_warn(&pdev->dev, "failed to read mac addr\n");
1243
Sucheta Chakrabortyb3a24642010-05-13 03:07:48 +00001244 if (qlcnic_setup_idc_param(adapter))
1245 goto err_out_iounmap;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001246
1247 err = qlcnic_start_firmware(adapter);
Amit Kumar Salechaa7fc9482010-05-17 01:22:14 +00001248 if (err) {
1249 dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001250 goto err_out_decr_ref;
Amit Kumar Salechaa7fc9482010-05-17 01:22:14 +00001251 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001252
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001253 qlcnic_clear_stats(adapter);
1254
1255 qlcnic_setup_intr(adapter);
1256
Amit Kumar Salecha1bb09fb2010-05-14 03:07:46 -07001257 err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001258 if (err)
1259 goto err_out_disable_msi;
1260
1261 pci_set_drvdata(pdev, adapter);
1262
1263 qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
1264
1265 switch (adapter->ahw.port_type) {
1266 case QLCNIC_GBE:
1267 dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
1268 adapter->netdev->name);
1269 break;
1270 case QLCNIC_XGBE:
1271 dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
1272 adapter->netdev->name);
1273 break;
1274 }
1275
1276 qlcnic_create_diag_entries(adapter);
1277
1278 return 0;
1279
1280err_out_disable_msi:
1281 qlcnic_teardown_intr(adapter);
1282
1283err_out_decr_ref:
1284 qlcnic_clr_all_drv_state(adapter);
1285
1286err_out_iounmap:
1287 qlcnic_cleanup_pci_map(adapter);
1288
1289err_out_free_netdev:
1290 free_netdev(netdev);
1291
1292err_out_free_res:
1293 pci_release_regions(pdev);
1294
1295err_out_disable_pdev:
1296 pci_set_drvdata(pdev, NULL);
1297 pci_disable_device(pdev);
1298 return err;
1299}
1300
1301static void __devexit qlcnic_remove(struct pci_dev *pdev)
1302{
1303 struct qlcnic_adapter *adapter;
1304 struct net_device *netdev;
1305
1306 adapter = pci_get_drvdata(pdev);
1307 if (adapter == NULL)
1308 return;
1309
1310 netdev = adapter->netdev;
1311
1312 qlcnic_cancel_fw_work(adapter);
1313
1314 unregister_netdev(netdev);
1315
1316 cancel_work_sync(&adapter->tx_timeout_task);
1317
1318 qlcnic_detach(adapter);
1319
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001320 if (adapter->npars != NULL)
1321 kfree(adapter->npars);
1322 if (adapter->eswitch != NULL)
1323 kfree(adapter->eswitch);
1324
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001325 qlcnic_clr_all_drv_state(adapter);
1326
1327 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1328
1329 qlcnic_teardown_intr(adapter);
1330
1331 qlcnic_remove_diag_entries(adapter);
1332
1333 qlcnic_cleanup_pci_map(adapter);
1334
1335 qlcnic_release_firmware(adapter);
1336
1337 pci_release_regions(pdev);
1338 pci_disable_device(pdev);
1339 pci_set_drvdata(pdev, NULL);
1340
1341 free_netdev(netdev);
1342}
1343static int __qlcnic_shutdown(struct pci_dev *pdev)
1344{
1345 struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
1346 struct net_device *netdev = adapter->netdev;
1347 int retval;
1348
1349 netif_device_detach(netdev);
1350
1351 qlcnic_cancel_fw_work(adapter);
1352
1353 if (netif_running(netdev))
1354 qlcnic_down(adapter, netdev);
1355
1356 cancel_work_sync(&adapter->tx_timeout_task);
1357
1358 qlcnic_detach(adapter);
1359
1360 qlcnic_clr_all_drv_state(adapter);
1361
1362 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1363
1364 retval = pci_save_state(pdev);
1365 if (retval)
1366 return retval;
1367
1368 if (qlcnic_wol_supported(adapter)) {
1369 pci_enable_wake(pdev, PCI_D3cold, 1);
1370 pci_enable_wake(pdev, PCI_D3hot, 1);
1371 }
1372
1373 return 0;
1374}
1375
1376static void qlcnic_shutdown(struct pci_dev *pdev)
1377{
1378 if (__qlcnic_shutdown(pdev))
1379 return;
1380
1381 pci_disable_device(pdev);
1382}
1383
1384#ifdef CONFIG_PM
1385static int
1386qlcnic_suspend(struct pci_dev *pdev, pm_message_t state)
1387{
1388 int retval;
1389
1390 retval = __qlcnic_shutdown(pdev);
1391 if (retval)
1392 return retval;
1393
1394 pci_set_power_state(pdev, pci_choose_state(pdev, state));
1395 return 0;
1396}
1397
1398static int
1399qlcnic_resume(struct pci_dev *pdev)
1400{
1401 struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
1402 struct net_device *netdev = adapter->netdev;
1403 int err;
1404
1405 err = pci_enable_device(pdev);
1406 if (err)
1407 return err;
1408
1409 pci_set_power_state(pdev, PCI_D0);
1410 pci_set_master(pdev);
1411 pci_restore_state(pdev);
1412
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001413 err = qlcnic_start_firmware(adapter);
1414 if (err) {
1415 dev_err(&pdev->dev, "failed to start firmware\n");
1416 return err;
1417 }
1418
1419 if (netif_running(netdev)) {
1420 err = qlcnic_attach(adapter);
1421 if (err)
1422 goto err_out;
1423
1424 err = qlcnic_up(adapter, netdev);
1425 if (err)
1426 goto err_out_detach;
1427
1428
1429 qlcnic_config_indev_addr(netdev, NETDEV_UP);
1430 }
1431
1432 netif_device_attach(netdev);
1433 qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
1434 return 0;
1435
1436err_out_detach:
1437 qlcnic_detach(adapter);
1438err_out:
1439 qlcnic_clr_all_drv_state(adapter);
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00001440 netif_device_attach(netdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001441 return err;
1442}
1443#endif
1444
1445static int qlcnic_open(struct net_device *netdev)
1446{
1447 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1448 int err;
1449
1450 if (adapter->driver_mismatch)
1451 return -EIO;
1452
1453 err = qlcnic_attach(adapter);
1454 if (err)
1455 return err;
1456
1457 err = __qlcnic_up(adapter, netdev);
1458 if (err)
1459 goto err_out;
1460
1461 netif_start_queue(netdev);
1462
1463 return 0;
1464
1465err_out:
1466 qlcnic_detach(adapter);
1467 return err;
1468}
1469
1470/*
1471 * qlcnic_close - Disables a network interface entry point
1472 */
1473static int qlcnic_close(struct net_device *netdev)
1474{
1475 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1476
1477 __qlcnic_down(adapter, netdev);
1478 return 0;
1479}
1480
1481static void
1482qlcnic_tso_check(struct net_device *netdev,
1483 struct qlcnic_host_tx_ring *tx_ring,
1484 struct cmd_desc_type0 *first_desc,
1485 struct sk_buff *skb)
1486{
1487 u8 opcode = TX_ETHER_PKT;
1488 __be16 protocol = skb->protocol;
1489 u16 flags = 0, vid = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001490 int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0;
1491 struct cmd_desc_type0 *hwdesc;
1492 struct vlan_ethhdr *vh;
Sucheta Chakraborty8bfe8b92010-03-08 00:14:46 +00001493 struct qlcnic_adapter *adapter = netdev_priv(netdev);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001494 u32 producer = tx_ring->producer;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001495
1496 if (protocol == cpu_to_be16(ETH_P_8021Q)) {
1497
1498 vh = (struct vlan_ethhdr *)skb->data;
1499 protocol = vh->h_vlan_encapsulated_proto;
1500 flags = FLAGS_VLAN_TAGGED;
1501
1502 } else if (vlan_tx_tag_present(skb)) {
1503
1504 flags = FLAGS_VLAN_OOB;
1505 vid = vlan_tx_tag_get(skb);
1506 qlcnic_set_tx_vlan_tci(first_desc, vid);
1507 vlan_oob = 1;
1508 }
1509
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001510 if (*(skb->data) & BIT_0) {
1511 flags |= BIT_0;
1512 memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
1513 }
1514
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001515 if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
1516 skb_shinfo(skb)->gso_size > 0) {
1517
1518 hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
1519
1520 first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
1521 first_desc->total_hdr_length = hdr_len;
1522 if (vlan_oob) {
1523 first_desc->total_hdr_length += VLAN_HLEN;
1524 first_desc->tcp_hdr_offset = VLAN_HLEN;
1525 first_desc->ip_hdr_offset = VLAN_HLEN;
1526 /* Only in case of TSO on vlan device */
1527 flags |= FLAGS_VLAN_TAGGED;
1528 }
1529
1530 opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ?
1531 TX_TCP_LSO6 : TX_TCP_LSO;
1532 tso = 1;
1533
1534 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
1535 u8 l4proto;
1536
1537 if (protocol == cpu_to_be16(ETH_P_IP)) {
1538 l4proto = ip_hdr(skb)->protocol;
1539
1540 if (l4proto == IPPROTO_TCP)
1541 opcode = TX_TCP_PKT;
1542 else if (l4proto == IPPROTO_UDP)
1543 opcode = TX_UDP_PKT;
1544 } else if (protocol == cpu_to_be16(ETH_P_IPV6)) {
1545 l4proto = ipv6_hdr(skb)->nexthdr;
1546
1547 if (l4proto == IPPROTO_TCP)
1548 opcode = TX_TCPV6_PKT;
1549 else if (l4proto == IPPROTO_UDP)
1550 opcode = TX_UDPV6_PKT;
1551 }
1552 }
1553
1554 first_desc->tcp_hdr_offset += skb_transport_offset(skb);
1555 first_desc->ip_hdr_offset += skb_network_offset(skb);
1556 qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
1557
1558 if (!tso)
1559 return;
1560
1561 /* For LSO, we need to copy the MAC/IP/TCP headers into
1562 * the descriptor ring
1563 */
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001564 copied = 0;
1565 offset = 2;
1566
1567 if (vlan_oob) {
1568 /* Create a TSO vlan header template for firmware */
1569
1570 hwdesc = &tx_ring->desc_head[producer];
1571 tx_ring->cmd_buf_arr[producer].skb = NULL;
1572
1573 copy_len = min((int)sizeof(struct cmd_desc_type0) - offset,
1574 hdr_len + VLAN_HLEN);
1575
1576 vh = (struct vlan_ethhdr *)((char *)hwdesc + 2);
1577 skb_copy_from_linear_data(skb, vh, 12);
1578 vh->h_vlan_proto = htons(ETH_P_8021Q);
1579 vh->h_vlan_TCI = htons(vid);
1580 skb_copy_from_linear_data_offset(skb, 12,
1581 (char *)vh + 16, copy_len - 16);
1582
1583 copied = copy_len - VLAN_HLEN;
1584 offset = 0;
1585
1586 producer = get_next_index(producer, tx_ring->num_desc);
1587 }
1588
1589 while (copied < hdr_len) {
1590
1591 copy_len = min((int)sizeof(struct cmd_desc_type0) - offset,
1592 (hdr_len - copied));
1593
1594 hwdesc = &tx_ring->desc_head[producer];
1595 tx_ring->cmd_buf_arr[producer].skb = NULL;
1596
1597 skb_copy_from_linear_data_offset(skb, copied,
1598 (char *)hwdesc + offset, copy_len);
1599
1600 copied += copy_len;
1601 offset = 0;
1602
1603 producer = get_next_index(producer, tx_ring->num_desc);
1604 }
1605
1606 tx_ring->producer = producer;
1607 barrier();
Sucheta Chakraborty8bfe8b92010-03-08 00:14:46 +00001608 adapter->stats.lso_frames++;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001609}
1610
1611static int
1612qlcnic_map_tx_skb(struct pci_dev *pdev,
1613 struct sk_buff *skb, struct qlcnic_cmd_buffer *pbuf)
1614{
1615 struct qlcnic_skb_frag *nf;
1616 struct skb_frag_struct *frag;
1617 int i, nr_frags;
1618 dma_addr_t map;
1619
1620 nr_frags = skb_shinfo(skb)->nr_frags;
1621 nf = &pbuf->frag_array[0];
1622
1623 map = pci_map_single(pdev, skb->data,
1624 skb_headlen(skb), PCI_DMA_TODEVICE);
1625 if (pci_dma_mapping_error(pdev, map))
1626 goto out_err;
1627
1628 nf->dma = map;
1629 nf->length = skb_headlen(skb);
1630
1631 for (i = 0; i < nr_frags; i++) {
1632 frag = &skb_shinfo(skb)->frags[i];
1633 nf = &pbuf->frag_array[i+1];
1634
1635 map = pci_map_page(pdev, frag->page, frag->page_offset,
1636 frag->size, PCI_DMA_TODEVICE);
1637 if (pci_dma_mapping_error(pdev, map))
1638 goto unwind;
1639
1640 nf->dma = map;
1641 nf->length = frag->size;
1642 }
1643
1644 return 0;
1645
1646unwind:
1647 while (--i >= 0) {
1648 nf = &pbuf->frag_array[i+1];
1649 pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
1650 }
1651
1652 nf = &pbuf->frag_array[0];
1653 pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
1654
1655out_err:
1656 return -ENOMEM;
1657}
1658
1659static inline void
1660qlcnic_clear_cmddesc(u64 *desc)
1661{
1662 desc[0] = 0ULL;
1663 desc[2] = 0ULL;
1664}
1665
Amit Kumar Salechacdaff182010-02-01 05:25:00 +00001666netdev_tx_t
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001667qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1668{
1669 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1670 struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
1671 struct qlcnic_cmd_buffer *pbuf;
1672 struct qlcnic_skb_frag *buffrag;
1673 struct cmd_desc_type0 *hwdesc, *first_desc;
1674 struct pci_dev *pdev;
1675 int i, k;
1676
1677 u32 producer;
1678 int frag_count, no_of_desc;
1679 u32 num_txd = tx_ring->num_desc;
1680
Amit Kumar Salecha780ab792010-04-22 02:51:41 +00001681 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
1682 netif_stop_queue(netdev);
1683 return NETDEV_TX_BUSY;
1684 }
1685
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001686 frag_count = skb_shinfo(skb)->nr_frags + 1;
1687
1688 /* 4 fragments per cmd des */
1689 no_of_desc = (frag_count + 3) >> 2;
1690
1691 if (unlikely(no_of_desc + 2 > qlcnic_tx_avail(tx_ring))) {
1692 netif_stop_queue(netdev);
Sucheta Chakraborty8bfe8b92010-03-08 00:14:46 +00001693 adapter->stats.xmit_off++;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001694 return NETDEV_TX_BUSY;
1695 }
1696
1697 producer = tx_ring->producer;
1698 pbuf = &tx_ring->cmd_buf_arr[producer];
1699
1700 pdev = adapter->pdev;
1701
Amit Kumar Salecha8ae6df92010-04-22 02:51:35 +00001702 if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
1703 adapter->stats.tx_dma_map_error++;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001704 goto drop_packet;
Amit Kumar Salecha8ae6df92010-04-22 02:51:35 +00001705 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001706
1707 pbuf->skb = skb;
1708 pbuf->frag_count = frag_count;
1709
1710 first_desc = hwdesc = &tx_ring->desc_head[producer];
1711 qlcnic_clear_cmddesc((u64 *)hwdesc);
1712
1713 qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
1714 qlcnic_set_tx_port(first_desc, adapter->portnum);
1715
1716 for (i = 0; i < frag_count; i++) {
1717
1718 k = i % 4;
1719
1720 if ((k == 0) && (i > 0)) {
1721 /* move to next desc.*/
1722 producer = get_next_index(producer, num_txd);
1723 hwdesc = &tx_ring->desc_head[producer];
1724 qlcnic_clear_cmddesc((u64 *)hwdesc);
1725 tx_ring->cmd_buf_arr[producer].skb = NULL;
1726 }
1727
1728 buffrag = &pbuf->frag_array[i];
1729
1730 hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length);
1731 switch (k) {
1732 case 0:
1733 hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
1734 break;
1735 case 1:
1736 hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma);
1737 break;
1738 case 2:
1739 hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma);
1740 break;
1741 case 3:
1742 hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma);
1743 break;
1744 }
1745 }
1746
1747 tx_ring->producer = get_next_index(producer, num_txd);
1748
1749 qlcnic_tso_check(netdev, tx_ring, first_desc, skb);
1750
1751 qlcnic_update_cmd_producer(adapter, tx_ring);
1752
1753 adapter->stats.txbytes += skb->len;
1754 adapter->stats.xmitcalled++;
1755
1756 return NETDEV_TX_OK;
1757
1758drop_packet:
1759 adapter->stats.txdropped++;
1760 dev_kfree_skb_any(skb);
1761 return NETDEV_TX_OK;
1762}
1763
1764static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
1765{
1766 struct net_device *netdev = adapter->netdev;
1767 u32 temp, temp_state, temp_val;
1768 int rv = 0;
1769
1770 temp = QLCRD32(adapter, CRB_TEMP_STATE);
1771
1772 temp_state = qlcnic_get_temp_state(temp);
1773 temp_val = qlcnic_get_temp_val(temp);
1774
1775 if (temp_state == QLCNIC_TEMP_PANIC) {
1776 dev_err(&netdev->dev,
1777 "Device temperature %d degrees C exceeds"
1778 " maximum allowed. Hardware has been shut down.\n",
1779 temp_val);
1780 rv = 1;
1781 } else if (temp_state == QLCNIC_TEMP_WARN) {
1782 if (adapter->temp == QLCNIC_TEMP_NORMAL) {
1783 dev_err(&netdev->dev,
1784 "Device temperature %d degrees C "
1785 "exceeds operating range."
1786 " Immediate action needed.\n",
1787 temp_val);
1788 }
1789 } else {
1790 if (adapter->temp == QLCNIC_TEMP_WARN) {
1791 dev_info(&netdev->dev,
1792 "Device temperature is now %d degrees C"
1793 " in normal range.\n", temp_val);
1794 }
1795 }
1796 adapter->temp = temp_state;
1797 return rv;
1798}
1799
1800void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
1801{
1802 struct net_device *netdev = adapter->netdev;
1803
1804 if (adapter->ahw.linkup && !linkup) {
1805 dev_info(&netdev->dev, "NIC Link is down\n");
1806 adapter->ahw.linkup = 0;
1807 if (netif_running(netdev)) {
1808 netif_carrier_off(netdev);
1809 netif_stop_queue(netdev);
1810 }
1811 } else if (!adapter->ahw.linkup && linkup) {
1812 dev_info(&netdev->dev, "NIC Link is up\n");
1813 adapter->ahw.linkup = 1;
1814 if (netif_running(netdev)) {
1815 netif_carrier_on(netdev);
1816 netif_wake_queue(netdev);
1817 }
1818 }
1819}
1820
1821static void qlcnic_tx_timeout(struct net_device *netdev)
1822{
1823 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1824
1825 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
1826 return;
1827
1828 dev_err(&netdev->dev, "transmit timeout, resetting.\n");
1829 schedule_work(&adapter->tx_timeout_task);
1830}
1831
1832static void qlcnic_tx_timeout_task(struct work_struct *work)
1833{
1834 struct qlcnic_adapter *adapter =
1835 container_of(work, struct qlcnic_adapter, tx_timeout_task);
1836
1837 if (!netif_running(adapter->netdev))
1838 return;
1839
1840 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
1841 return;
1842
1843 if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS)
1844 goto request_reset;
1845
1846 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1847 if (!qlcnic_reset_context(adapter)) {
1848 adapter->netdev->trans_start = jiffies;
1849 return;
1850
1851 /* context reset failed, fall through for fw reset */
1852 }
1853
1854request_reset:
1855 adapter->need_fw_reset = 1;
1856 clear_bit(__QLCNIC_RESETTING, &adapter->state);
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00001857 QLCDB(adapter, DRV, "Resetting adapter\n");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001858}
1859
1860static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
1861{
1862 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1863 struct net_device_stats *stats = &netdev->stats;
1864
1865 memset(stats, 0, sizeof(*stats));
1866
1867 stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
1868 stats->tx_packets = adapter->stats.xmitfinished;
Sucheta Chakraborty7e382592010-05-17 01:22:10 +00001869 stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001870 stats->tx_bytes = adapter->stats.txbytes;
1871 stats->rx_dropped = adapter->stats.rxdropped;
1872 stats->tx_dropped = adapter->stats.txdropped;
1873
1874 return stats;
1875}
1876
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001877static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001878{
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001879 u32 status;
1880
1881 status = readl(adapter->isr_int_vec);
1882
1883 if (!(status & adapter->int_vec_bit))
1884 return IRQ_NONE;
1885
1886 /* check interrupt state machine, to be sure */
1887 status = readl(adapter->crb_int_state_reg);
1888 if (!ISR_LEGACY_INT_TRIGGERED(status))
1889 return IRQ_NONE;
1890
1891 writel(0xffffffff, adapter->tgt_status_reg);
1892 /* read twice to ensure write is flushed */
1893 readl(adapter->isr_int_vec);
1894 readl(adapter->isr_int_vec);
1895
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001896 return IRQ_HANDLED;
1897}
1898
1899static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
1900{
1901 struct qlcnic_host_sds_ring *sds_ring = data;
1902 struct qlcnic_adapter *adapter = sds_ring->adapter;
1903
1904 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1905 goto done;
1906 else if (adapter->flags & QLCNIC_MSI_ENABLED) {
1907 writel(0xffffffff, adapter->tgt_status_reg);
1908 goto done;
1909 }
1910
1911 if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
1912 return IRQ_NONE;
1913
1914done:
1915 adapter->diag_cnt++;
1916 qlcnic_enable_int(sds_ring);
1917 return IRQ_HANDLED;
1918}
1919
1920static irqreturn_t qlcnic_intr(int irq, void *data)
1921{
1922 struct qlcnic_host_sds_ring *sds_ring = data;
1923 struct qlcnic_adapter *adapter = sds_ring->adapter;
1924
1925 if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
1926 return IRQ_NONE;
1927
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001928 napi_schedule(&sds_ring->napi);
1929
1930 return IRQ_HANDLED;
1931}
1932
1933static irqreturn_t qlcnic_msi_intr(int irq, void *data)
1934{
1935 struct qlcnic_host_sds_ring *sds_ring = data;
1936 struct qlcnic_adapter *adapter = sds_ring->adapter;
1937
1938 /* clear interrupt */
1939 writel(0xffffffff, adapter->tgt_status_reg);
1940
1941 napi_schedule(&sds_ring->napi);
1942 return IRQ_HANDLED;
1943}
1944
1945static irqreturn_t qlcnic_msix_intr(int irq, void *data)
1946{
1947 struct qlcnic_host_sds_ring *sds_ring = data;
1948
1949 napi_schedule(&sds_ring->napi);
1950 return IRQ_HANDLED;
1951}
1952
1953static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter)
1954{
1955 u32 sw_consumer, hw_consumer;
1956 int count = 0, i;
1957 struct qlcnic_cmd_buffer *buffer;
1958 struct pci_dev *pdev = adapter->pdev;
1959 struct net_device *netdev = adapter->netdev;
1960 struct qlcnic_skb_frag *frag;
1961 int done;
1962 struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
1963
1964 if (!spin_trylock(&adapter->tx_clean_lock))
1965 return 1;
1966
1967 sw_consumer = tx_ring->sw_consumer;
1968 hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
1969
1970 while (sw_consumer != hw_consumer) {
1971 buffer = &tx_ring->cmd_buf_arr[sw_consumer];
1972 if (buffer->skb) {
1973 frag = &buffer->frag_array[0];
1974 pci_unmap_single(pdev, frag->dma, frag->length,
1975 PCI_DMA_TODEVICE);
1976 frag->dma = 0ULL;
1977 for (i = 1; i < buffer->frag_count; i++) {
1978 frag++;
1979 pci_unmap_page(pdev, frag->dma, frag->length,
1980 PCI_DMA_TODEVICE);
1981 frag->dma = 0ULL;
1982 }
1983
1984 adapter->stats.xmitfinished++;
1985 dev_kfree_skb_any(buffer->skb);
1986 buffer->skb = NULL;
1987 }
1988
1989 sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
1990 if (++count >= MAX_STATUS_HANDLE)
1991 break;
1992 }
1993
1994 if (count && netif_running(netdev)) {
1995 tx_ring->sw_consumer = sw_consumer;
1996
1997 smp_mb();
1998
1999 if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
2000 __netif_tx_lock(tx_ring->txq, smp_processor_id());
2001 if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
2002 netif_wake_queue(netdev);
2003 adapter->tx_timeo_cnt = 0;
Sucheta Chakraborty8bfe8b92010-03-08 00:14:46 +00002004 adapter->stats.xmit_on++;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002005 }
2006 __netif_tx_unlock(tx_ring->txq);
2007 }
2008 }
2009 /*
2010 * If everything is freed up to consumer then check if the ring is full
2011 * If the ring is full then check if more needs to be freed and
2012 * schedule the call back again.
2013 *
2014 * This happens when there are 2 CPUs. One could be freeing and the
2015 * other filling it. If the ring is full when we get out of here and
2016 * the card has already interrupted the host then the host can miss the
2017 * interrupt.
2018 *
2019 * There is still a possible race condition and the host could miss an
2020 * interrupt. The card has to take care of this.
2021 */
2022 hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
2023 done = (sw_consumer == hw_consumer);
2024 spin_unlock(&adapter->tx_clean_lock);
2025
2026 return done;
2027}
2028
2029static int qlcnic_poll(struct napi_struct *napi, int budget)
2030{
2031 struct qlcnic_host_sds_ring *sds_ring =
2032 container_of(napi, struct qlcnic_host_sds_ring, napi);
2033
2034 struct qlcnic_adapter *adapter = sds_ring->adapter;
2035
2036 int tx_complete;
2037 int work_done;
2038
2039 tx_complete = qlcnic_process_cmd_ring(adapter);
2040
2041 work_done = qlcnic_process_rcv_ring(sds_ring, budget);
2042
2043 if ((work_done < budget) && tx_complete) {
2044 napi_complete(&sds_ring->napi);
2045 if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
2046 qlcnic_enable_int(sds_ring);
2047 }
2048
2049 return work_done;
2050}
2051
2052#ifdef CONFIG_NET_POLL_CONTROLLER
2053static void qlcnic_poll_controller(struct net_device *netdev)
2054{
2055 struct qlcnic_adapter *adapter = netdev_priv(netdev);
2056 disable_irq(adapter->irq);
2057 qlcnic_intr(adapter->irq, adapter);
2058 enable_irq(adapter->irq);
2059}
2060#endif
2061
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +00002062static void
2063qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding)
2064{
2065 u32 val;
2066
2067 val = adapter->portnum & 0xf;
2068 val |= encoding << 7;
2069 val |= (jiffies - adapter->dev_rst_time) << 8;
2070
2071 QLCWR32(adapter, QLCNIC_CRB_DRV_SCRATCH, val);
2072 adapter->dev_rst_time = jiffies;
2073}
2074
Amit Kumar Salechaade91f82010-04-22 02:51:39 +00002075static int
2076qlcnic_set_drv_state(struct qlcnic_adapter *adapter, u8 state)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002077{
2078 u32 val;
2079
2080 WARN_ON(state != QLCNIC_DEV_NEED_RESET &&
2081 state != QLCNIC_DEV_NEED_QUISCENT);
2082
2083 if (qlcnic_api_lock(adapter))
Amit Kumar Salechaade91f82010-04-22 02:51:39 +00002084 return -EIO;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002085
2086 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
2087
2088 if (state == QLCNIC_DEV_NEED_RESET)
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002089 QLC_DEV_SET_RST_RDY(val, adapter->portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002090 else if (state == QLCNIC_DEV_NEED_QUISCENT)
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002091 QLC_DEV_SET_QSCNT_RDY(val, adapter->portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002092
2093 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2094
2095 qlcnic_api_unlock(adapter);
Amit Kumar Salechaade91f82010-04-22 02:51:39 +00002096
2097 return 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002098}
2099
Amit Kumar Salecha1b95a832010-02-01 05:24:56 +00002100static int
2101qlcnic_clr_drv_state(struct qlcnic_adapter *adapter)
2102{
2103 u32 val;
2104
2105 if (qlcnic_api_lock(adapter))
2106 return -EBUSY;
2107
2108 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002109 QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum);
Amit Kumar Salecha1b95a832010-02-01 05:24:56 +00002110 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2111
2112 qlcnic_api_unlock(adapter);
2113
2114 return 0;
2115}
2116
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002117static void
2118qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter)
2119{
2120 u32 val;
2121
2122 if (qlcnic_api_lock(adapter))
2123 goto err;
2124
2125 val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002126 QLC_DEV_CLR_REF_CNT(val, adapter->portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002127 QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val);
2128
2129 if (!(val & 0x11111111))
2130 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_COLD);
2131
2132 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002133 QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002134 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2135
2136 qlcnic_api_unlock(adapter);
2137err:
2138 adapter->fw_fail_cnt = 0;
2139 clear_bit(__QLCNIC_START_FW, &adapter->state);
2140 clear_bit(__QLCNIC_RESETTING, &adapter->state);
2141}
2142
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002143/* Grab api lock, before checking state */
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002144static int
2145qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
2146{
2147 int act, state;
2148
2149 state = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
2150 act = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
2151
2152 if (((state & 0x11111111) == (act & 0x11111111)) ||
2153 ((act & 0x11111111) == ((state >> 1) & 0x11111111)))
2154 return 0;
2155 else
2156 return 1;
2157}
2158
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002159static int qlcnic_check_idc_ver(struct qlcnic_adapter *adapter)
2160{
2161 u32 val = QLCRD32(adapter, QLCNIC_CRB_DRV_IDC_VER);
2162
2163 if (val != QLCNIC_DRV_IDC_VER) {
2164 dev_warn(&adapter->pdev->dev, "IDC Version mismatch, driver's"
2165 " idc ver = %x; reqd = %x\n", QLCNIC_DRV_IDC_VER, val);
2166 }
2167
2168 return 0;
2169}
2170
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002171static int
2172qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
2173{
2174 u32 val, prev_state;
Sucheta Chakrabortyaa5e18c2010-04-01 19:01:32 +00002175 u8 dev_init_timeo = adapter->dev_init_timeo;
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002176 u8 portnum = adapter->portnum;
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002177 u8 ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002178
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002179 if (test_and_clear_bit(__QLCNIC_START_FW, &adapter->state))
2180 return 1;
2181
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002182 if (qlcnic_api_lock(adapter))
2183 return -1;
2184
2185 val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002186 if (!(val & (1 << (portnum * 4)))) {
2187 QLC_DEV_SET_REF_CNT(val, portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002188 QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002189 }
2190
2191 prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002192 QLCDB(adapter, HW, "Device state = %u\n", prev_state);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002193
2194 switch (prev_state) {
2195 case QLCNIC_DEV_COLD:
Amit Kumar Salechabbd8c6a2010-04-22 02:51:36 +00002196 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002197 QLCWR32(adapter, QLCNIC_CRB_DRV_IDC_VER, QLCNIC_DRV_IDC_VER);
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +00002198 qlcnic_idc_debug_info(adapter, 0);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002199 qlcnic_api_unlock(adapter);
2200 return 1;
2201
2202 case QLCNIC_DEV_READY:
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002203 ret = qlcnic_check_idc_ver(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002204 qlcnic_api_unlock(adapter);
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002205 return ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002206
2207 case QLCNIC_DEV_NEED_RESET:
2208 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002209 QLC_DEV_SET_RST_RDY(val, portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002210 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2211 break;
2212
2213 case QLCNIC_DEV_NEED_QUISCENT:
2214 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002215 QLC_DEV_SET_QSCNT_RDY(val, portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002216 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2217 break;
2218
2219 case QLCNIC_DEV_FAILED:
Amit Kumar Salechaa7fc9482010-05-17 01:22:14 +00002220 dev_err(&adapter->pdev->dev, "Device in failed state.\n");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002221 qlcnic_api_unlock(adapter);
2222 return -1;
Amit Kumar Salechabbd8c6a2010-04-22 02:51:36 +00002223
2224 case QLCNIC_DEV_INITIALIZING:
2225 case QLCNIC_DEV_QUISCENT:
2226 break;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002227 }
2228
2229 qlcnic_api_unlock(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002230
Sucheta Chakrabortyaa5e18c2010-04-01 19:01:32 +00002231 do {
2232 msleep(1000);
Sucheta Chakrabortya5e463d2010-05-13 03:07:49 +00002233 prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
2234
2235 if (prev_state == QLCNIC_DEV_QUISCENT)
2236 continue;
2237 } while ((prev_state != QLCNIC_DEV_READY) && --dev_init_timeo);
Sucheta Chakrabortyaa5e18c2010-04-01 19:01:32 +00002238
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002239 if (!dev_init_timeo) {
2240 dev_err(&adapter->pdev->dev,
2241 "Waiting for device to initialize timeout\n");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002242 return -1;
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002243 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002244
2245 if (qlcnic_api_lock(adapter))
2246 return -1;
2247
2248 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002249 QLC_DEV_CLR_RST_QSCNT(val, portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002250 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2251
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002252 ret = qlcnic_check_idc_ver(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002253 qlcnic_api_unlock(adapter);
2254
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002255 return ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002256}
2257
2258static void
2259qlcnic_fwinit_work(struct work_struct *work)
2260{
2261 struct qlcnic_adapter *adapter = container_of(work,
2262 struct qlcnic_adapter, fw_work.work);
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002263 u32 dev_state = 0xf;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002264
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002265 if (qlcnic_api_lock(adapter))
2266 goto err_ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002267
Sucheta Chakrabortya5e463d2010-05-13 03:07:49 +00002268 dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
2269 if (dev_state == QLCNIC_DEV_QUISCENT) {
2270 qlcnic_api_unlock(adapter);
2271 qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
2272 FW_POLL_DELAY * 2);
2273 return;
2274 }
2275
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002276 if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
2277 dev_err(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n",
2278 adapter->reset_ack_timeo);
2279 goto skip_ack_check;
2280 }
2281
2282 if (!qlcnic_check_drv_state(adapter)) {
2283skip_ack_check:
2284 dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
Sucheta Chakrabortya5e463d2010-05-13 03:07:49 +00002285
2286 if (dev_state == QLCNIC_DEV_NEED_QUISCENT) {
2287 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
2288 QLCNIC_DEV_QUISCENT);
2289 qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
2290 FW_POLL_DELAY * 2);
2291 QLCDB(adapter, DRV, "Quiscing the driver\n");
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +00002292 qlcnic_idc_debug_info(adapter, 0);
2293
Sucheta Chakrabortya5e463d2010-05-13 03:07:49 +00002294 qlcnic_api_unlock(adapter);
2295 return;
2296 }
2297
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002298 if (dev_state == QLCNIC_DEV_NEED_RESET) {
2299 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
2300 QLCNIC_DEV_INITIALIZING);
2301 set_bit(__QLCNIC_START_FW, &adapter->state);
2302 QLCDB(adapter, DRV, "Restarting fw\n");
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +00002303 qlcnic_idc_debug_info(adapter, 0);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002304 }
2305
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002306 qlcnic_api_unlock(adapter);
2307
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002308 if (!qlcnic_start_firmware(adapter)) {
2309 qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
2310 return;
2311 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002312 goto err_ret;
2313 }
2314
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002315 qlcnic_api_unlock(adapter);
Sucheta Chakrabortyaa5e18c2010-04-01 19:01:32 +00002316
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002317 dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002318 QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002319
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002320 switch (dev_state) {
Sucheta Chakrabortya5e463d2010-05-13 03:07:49 +00002321 case QLCNIC_DEV_QUISCENT:
2322 case QLCNIC_DEV_NEED_QUISCENT:
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002323 case QLCNIC_DEV_NEED_RESET:
2324 qlcnic_schedule_work(adapter,
2325 qlcnic_fwinit_work, FW_POLL_DELAY);
2326 return;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002327 case QLCNIC_DEV_FAILED:
2328 break;
2329
2330 default:
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002331 if (!qlcnic_start_firmware(adapter)) {
2332 qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
2333 return;
2334 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002335 }
2336
2337err_ret:
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002338 dev_err(&adapter->pdev->dev, "Fwinit work failed state=%u "
2339 "fw_wait_cnt=%u\n", dev_state, adapter->fw_wait_cnt);
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00002340 netif_device_attach(adapter->netdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002341 qlcnic_clr_all_drv_state(adapter);
2342}
2343
2344static void
2345qlcnic_detach_work(struct work_struct *work)
2346{
2347 struct qlcnic_adapter *adapter = container_of(work,
2348 struct qlcnic_adapter, fw_work.work);
2349 struct net_device *netdev = adapter->netdev;
2350 u32 status;
2351
2352 netif_device_detach(netdev);
2353
2354 qlcnic_down(adapter, netdev);
2355
Amit Kumar Salechace668442010-02-01 05:24:57 +00002356 rtnl_lock();
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002357 qlcnic_detach(adapter);
Amit Kumar Salechace668442010-02-01 05:24:57 +00002358 rtnl_unlock();
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002359
2360 status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
2361
2362 if (status & QLCNIC_RCODE_FATAL_ERROR)
2363 goto err_ret;
2364
2365 if (adapter->temp == QLCNIC_TEMP_PANIC)
2366 goto err_ret;
2367
Amit Kumar Salechaade91f82010-04-22 02:51:39 +00002368 if (qlcnic_set_drv_state(adapter, adapter->dev_state))
2369 goto err_ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002370
2371 adapter->fw_wait_cnt = 0;
2372
2373 qlcnic_schedule_work(adapter, qlcnic_fwinit_work, FW_POLL_DELAY);
2374
2375 return;
2376
2377err_ret:
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002378 dev_err(&adapter->pdev->dev, "detach failed; status=%d temp=%d\n",
2379 status, adapter->temp);
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00002380 netif_device_attach(netdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002381 qlcnic_clr_all_drv_state(adapter);
2382
2383}
2384
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002385/*Transit to RESET state from READY state only */
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002386static void
2387qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
2388{
2389 u32 state;
2390
2391 if (qlcnic_api_lock(adapter))
2392 return;
2393
2394 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
2395
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002396 if (state == QLCNIC_DEV_READY) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002397 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET);
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002398 QLCDB(adapter, DRV, "NEED_RESET state set\n");
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +00002399 qlcnic_idc_debug_info(adapter, 0);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002400 }
2401
2402 qlcnic_api_unlock(adapter);
2403}
2404
2405static void
2406qlcnic_schedule_work(struct qlcnic_adapter *adapter,
2407 work_func_t func, int delay)
2408{
2409 INIT_DELAYED_WORK(&adapter->fw_work, func);
2410 schedule_delayed_work(&adapter->fw_work, round_jiffies_relative(delay));
2411}
2412
2413static void
2414qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter)
2415{
2416 while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
2417 msleep(10);
2418
2419 cancel_delayed_work_sync(&adapter->fw_work);
2420}
2421
2422static void
2423qlcnic_attach_work(struct work_struct *work)
2424{
2425 struct qlcnic_adapter *adapter = container_of(work,
2426 struct qlcnic_adapter, fw_work.work);
2427 struct net_device *netdev = adapter->netdev;
2428 int err;
2429
2430 if (netif_running(netdev)) {
2431 err = qlcnic_attach(adapter);
2432 if (err)
2433 goto done;
2434
2435 err = qlcnic_up(adapter, netdev);
2436 if (err) {
2437 qlcnic_detach(adapter);
2438 goto done;
2439 }
2440
2441 qlcnic_config_indev_addr(netdev, NETDEV_UP);
2442 }
2443
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002444done:
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00002445 netif_device_attach(netdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002446 adapter->fw_fail_cnt = 0;
2447 clear_bit(__QLCNIC_RESETTING, &adapter->state);
Amit Kumar Salecha1b95a832010-02-01 05:24:56 +00002448
2449 if (!qlcnic_clr_drv_state(adapter))
2450 qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
2451 FW_POLL_DELAY);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002452}
2453
2454static int
2455qlcnic_check_health(struct qlcnic_adapter *adapter)
2456{
2457 u32 state = 0, heartbit;
2458 struct net_device *netdev = adapter->netdev;
2459
2460 if (qlcnic_check_temp(adapter))
2461 goto detach;
2462
Amit Kumar Salecha2372a5f2010-05-13 03:07:42 +00002463 if (adapter->need_fw_reset)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002464 qlcnic_dev_request_reset(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002465
2466 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
2467 if (state == QLCNIC_DEV_NEED_RESET || state == QLCNIC_DEV_NEED_QUISCENT)
2468 adapter->need_fw_reset = 1;
2469
2470 heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
2471 if (heartbit != adapter->heartbit) {
2472 adapter->heartbit = heartbit;
2473 adapter->fw_fail_cnt = 0;
2474 if (adapter->need_fw_reset)
2475 goto detach;
2476 return 0;
2477 }
2478
2479 if (++adapter->fw_fail_cnt < FW_FAIL_THRESH)
2480 return 0;
2481
2482 qlcnic_dev_request_reset(adapter);
2483
2484 clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
2485
2486 dev_info(&netdev->dev, "firmware hang detected\n");
2487
2488detach:
2489 adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state :
2490 QLCNIC_DEV_NEED_RESET;
2491
2492 if ((auto_fw_reset == AUTO_FW_RESET_ENABLED) &&
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002493 !test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) {
2494
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002495 qlcnic_schedule_work(adapter, qlcnic_detach_work, 0);
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002496 QLCDB(adapter, DRV, "fw recovery scheduled.\n");
2497 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002498
2499 return 1;
2500}
2501
2502static void
2503qlcnic_fw_poll_work(struct work_struct *work)
2504{
2505 struct qlcnic_adapter *adapter = container_of(work,
2506 struct qlcnic_adapter, fw_work.work);
2507
2508 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
2509 goto reschedule;
2510
2511
2512 if (qlcnic_check_health(adapter))
2513 return;
2514
2515reschedule:
2516 qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
2517}
2518
2519static ssize_t
2520qlcnic_store_bridged_mode(struct device *dev,
2521 struct device_attribute *attr, const char *buf, size_t len)
2522{
2523 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
2524 unsigned long new;
2525 int ret = -EINVAL;
2526
2527 if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG))
2528 goto err_out;
2529
2530 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
2531 goto err_out;
2532
2533 if (strict_strtoul(buf, 2, &new))
2534 goto err_out;
2535
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00002536 if (!adapter->nic_ops->config_bridged_mode(adapter, !!new))
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002537 ret = len;
2538
2539err_out:
2540 return ret;
2541}
2542
2543static ssize_t
2544qlcnic_show_bridged_mode(struct device *dev,
2545 struct device_attribute *attr, char *buf)
2546{
2547 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
2548 int bridged_mode = 0;
2549
2550 if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
2551 bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
2552
2553 return sprintf(buf, "%d\n", bridged_mode);
2554}
2555
2556static struct device_attribute dev_attr_bridged_mode = {
2557 .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
2558 .show = qlcnic_show_bridged_mode,
2559 .store = qlcnic_store_bridged_mode,
2560};
2561
2562static ssize_t
2563qlcnic_store_diag_mode(struct device *dev,
2564 struct device_attribute *attr, const char *buf, size_t len)
2565{
2566 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
2567 unsigned long new;
2568
2569 if (strict_strtoul(buf, 2, &new))
2570 return -EINVAL;
2571
2572 if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
2573 adapter->flags ^= QLCNIC_DIAG_ENABLED;
2574
2575 return len;
2576}
2577
2578static ssize_t
2579qlcnic_show_diag_mode(struct device *dev,
2580 struct device_attribute *attr, char *buf)
2581{
2582 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
2583
2584 return sprintf(buf, "%d\n",
2585 !!(adapter->flags & QLCNIC_DIAG_ENABLED));
2586}
2587
2588static struct device_attribute dev_attr_diag_mode = {
2589 .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)},
2590 .show = qlcnic_show_diag_mode,
2591 .store = qlcnic_store_diag_mode,
2592};
2593
2594static int
2595qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
2596 loff_t offset, size_t size)
2597{
Dhananjay Phadke897e8c72010-04-01 19:01:29 +00002598 size_t crb_size = 4;
2599
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002600 if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
2601 return -EIO;
2602
Dhananjay Phadke897e8c72010-04-01 19:01:29 +00002603 if (offset < QLCNIC_PCI_CRBSPACE) {
2604 if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
2605 QLCNIC_PCI_CAMQM_END))
2606 crb_size = 8;
2607 else
2608 return -EINVAL;
2609 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002610
Dhananjay Phadke897e8c72010-04-01 19:01:29 +00002611 if ((size != crb_size) || (offset & (crb_size-1)))
2612 return -EINVAL;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002613
2614 return 0;
2615}
2616
2617static ssize_t
Chris Wright2c3c8be2010-05-12 18:28:57 -07002618qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
2619 struct bin_attribute *attr,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002620 char *buf, loff_t offset, size_t size)
2621{
2622 struct device *dev = container_of(kobj, struct device, kobj);
2623 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
2624 u32 data;
Dhananjay Phadke897e8c72010-04-01 19:01:29 +00002625 u64 qmdata;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002626 int ret;
2627
2628 ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
2629 if (ret != 0)
2630 return ret;
2631
Dhananjay Phadke897e8c72010-04-01 19:01:29 +00002632 if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
2633 qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
2634 memcpy(buf, &qmdata, size);
2635 } else {
2636 data = QLCRD32(adapter, offset);
2637 memcpy(buf, &data, size);
2638 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002639 return size;
2640}
2641
2642static ssize_t
Chris Wright2c3c8be2010-05-12 18:28:57 -07002643qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
2644 struct bin_attribute *attr,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002645 char *buf, loff_t offset, size_t size)
2646{
2647 struct device *dev = container_of(kobj, struct device, kobj);
2648 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
2649 u32 data;
Dhananjay Phadke897e8c72010-04-01 19:01:29 +00002650 u64 qmdata;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002651 int ret;
2652
2653 ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
2654 if (ret != 0)
2655 return ret;
2656
Dhananjay Phadke897e8c72010-04-01 19:01:29 +00002657 if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
2658 memcpy(&qmdata, buf, size);
2659 qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
2660 } else {
2661 memcpy(&data, buf, size);
2662 QLCWR32(adapter, offset, data);
2663 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002664 return size;
2665}
2666
2667static int
2668qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
2669 loff_t offset, size_t size)
2670{
2671 if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
2672 return -EIO;
2673
2674 if ((size != 8) || (offset & 0x7))
2675 return -EIO;
2676
2677 return 0;
2678}
2679
2680static ssize_t
Chris Wright2c3c8be2010-05-12 18:28:57 -07002681qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
2682 struct bin_attribute *attr,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002683 char *buf, loff_t offset, size_t size)
2684{
2685 struct device *dev = container_of(kobj, struct device, kobj);
2686 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
2687 u64 data;
2688 int ret;
2689
2690 ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
2691 if (ret != 0)
2692 return ret;
2693
2694 if (qlcnic_pci_mem_read_2M(adapter, offset, &data))
2695 return -EIO;
2696
2697 memcpy(buf, &data, size);
2698
2699 return size;
2700}
2701
2702static ssize_t
Chris Wright2c3c8be2010-05-12 18:28:57 -07002703qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
2704 struct bin_attribute *attr,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002705 char *buf, loff_t offset, size_t size)
2706{
2707 struct device *dev = container_of(kobj, struct device, kobj);
2708 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
2709 u64 data;
2710 int ret;
2711
2712 ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
2713 if (ret != 0)
2714 return ret;
2715
2716 memcpy(&data, buf, size);
2717
2718 if (qlcnic_pci_mem_write_2M(adapter, offset, data))
2719 return -EIO;
2720
2721 return size;
2722}
2723
2724
2725static struct bin_attribute bin_attr_crb = {
2726 .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)},
2727 .size = 0,
2728 .read = qlcnic_sysfs_read_crb,
2729 .write = qlcnic_sysfs_write_crb,
2730};
2731
2732static struct bin_attribute bin_attr_mem = {
2733 .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)},
2734 .size = 0,
2735 .read = qlcnic_sysfs_read_mem,
2736 .write = qlcnic_sysfs_write_mem,
2737};
2738
2739static void
2740qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
2741{
2742 struct device *dev = &adapter->pdev->dev;
2743
2744 if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
2745 if (device_create_file(dev, &dev_attr_bridged_mode))
2746 dev_warn(dev,
2747 "failed to create bridged_mode sysfs entry\n");
2748}
2749
2750static void
2751qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
2752{
2753 struct device *dev = &adapter->pdev->dev;
2754
2755 if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
2756 device_remove_file(dev, &dev_attr_bridged_mode);
2757}
2758
2759static void
2760qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
2761{
2762 struct device *dev = &adapter->pdev->dev;
2763
2764 if (device_create_file(dev, &dev_attr_diag_mode))
2765 dev_info(dev, "failed to create diag_mode sysfs entry\n");
2766 if (device_create_bin_file(dev, &bin_attr_crb))
2767 dev_info(dev, "failed to create crb sysfs entry\n");
2768 if (device_create_bin_file(dev, &bin_attr_mem))
2769 dev_info(dev, "failed to create mem sysfs entry\n");
2770}
2771
2772
2773static void
2774qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
2775{
2776 struct device *dev = &adapter->pdev->dev;
2777
2778 device_remove_file(dev, &dev_attr_diag_mode);
2779 device_remove_bin_file(dev, &bin_attr_crb);
2780 device_remove_bin_file(dev, &bin_attr_mem);
2781}
2782
2783#ifdef CONFIG_INET
2784
2785#define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops)
2786
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002787static void
2788qlcnic_config_indev_addr(struct net_device *dev, unsigned long event)
2789{
2790 struct in_device *indev;
2791 struct qlcnic_adapter *adapter = netdev_priv(dev);
2792
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002793 indev = in_dev_get(dev);
2794 if (!indev)
2795 return;
2796
2797 for_ifa(indev) {
2798 switch (event) {
2799 case NETDEV_UP:
2800 qlcnic_config_ipaddr(adapter,
2801 ifa->ifa_address, QLCNIC_IP_UP);
2802 break;
2803 case NETDEV_DOWN:
2804 qlcnic_config_ipaddr(adapter,
2805 ifa->ifa_address, QLCNIC_IP_DOWN);
2806 break;
2807 default:
2808 break;
2809 }
2810 } endfor_ifa(indev);
2811
2812 in_dev_put(indev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002813}
2814
2815static int qlcnic_netdev_event(struct notifier_block *this,
2816 unsigned long event, void *ptr)
2817{
2818 struct qlcnic_adapter *adapter;
2819 struct net_device *dev = (struct net_device *)ptr;
2820
2821recheck:
2822 if (dev == NULL)
2823 goto done;
2824
2825 if (dev->priv_flags & IFF_802_1Q_VLAN) {
2826 dev = vlan_dev_real_dev(dev);
2827 goto recheck;
2828 }
2829
2830 if (!is_qlcnic_netdev(dev))
2831 goto done;
2832
2833 adapter = netdev_priv(dev);
2834
2835 if (!adapter)
2836 goto done;
2837
2838 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
2839 goto done;
2840
2841 qlcnic_config_indev_addr(dev, event);
2842done:
2843 return NOTIFY_DONE;
2844}
2845
2846static int
2847qlcnic_inetaddr_event(struct notifier_block *this,
2848 unsigned long event, void *ptr)
2849{
2850 struct qlcnic_adapter *adapter;
2851 struct net_device *dev;
2852
2853 struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
2854
2855 dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
2856
2857recheck:
2858 if (dev == NULL || !netif_running(dev))
2859 goto done;
2860
2861 if (dev->priv_flags & IFF_802_1Q_VLAN) {
2862 dev = vlan_dev_real_dev(dev);
2863 goto recheck;
2864 }
2865
2866 if (!is_qlcnic_netdev(dev))
2867 goto done;
2868
2869 adapter = netdev_priv(dev);
2870
Amit Kumar Salecha251a84c2010-05-13 03:07:46 +00002871 if (!adapter)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002872 goto done;
2873
2874 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
2875 goto done;
2876
2877 switch (event) {
2878 case NETDEV_UP:
2879 qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_UP);
2880 break;
2881 case NETDEV_DOWN:
2882 qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_DOWN);
2883 break;
2884 default:
2885 break;
2886 }
2887
2888done:
2889 return NOTIFY_DONE;
2890}
2891
2892static struct notifier_block qlcnic_netdev_cb = {
2893 .notifier_call = qlcnic_netdev_event,
2894};
2895
2896static struct notifier_block qlcnic_inetaddr_cb = {
2897 .notifier_call = qlcnic_inetaddr_event,
2898};
2899#else
2900static void
2901qlcnic_config_indev_addr(struct net_device *dev, unsigned long event)
2902{ }
2903#endif
2904
2905static struct pci_driver qlcnic_driver = {
2906 .name = qlcnic_driver_name,
2907 .id_table = qlcnic_pci_tbl,
2908 .probe = qlcnic_probe,
2909 .remove = __devexit_p(qlcnic_remove),
2910#ifdef CONFIG_PM
2911 .suspend = qlcnic_suspend,
2912 .resume = qlcnic_resume,
2913#endif
2914 .shutdown = qlcnic_shutdown
2915};
2916
2917static int __init qlcnic_init_module(void)
2918{
2919
2920 printk(KERN_INFO "%s\n", qlcnic_driver_string);
2921
2922#ifdef CONFIG_INET
2923 register_netdevice_notifier(&qlcnic_netdev_cb);
2924 register_inetaddr_notifier(&qlcnic_inetaddr_cb);
2925#endif
2926
2927
2928 return pci_register_driver(&qlcnic_driver);
2929}
2930
2931module_init(qlcnic_init_module);
2932
2933static void __exit qlcnic_exit_module(void)
2934{
2935
2936 pci_unregister_driver(&qlcnic_driver);
2937
2938#ifdef CONFIG_INET
2939 unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
2940 unregister_netdevice_notifier(&qlcnic_netdev_cb);
2941#endif
2942}
2943
2944module_exit(qlcnic_exit_module);