qlcnic_main.c 107.4 KB
Newer Older
1
/*
S
Sritej Velaga 已提交
2
 * QLogic qlcnic NIC Driver
3
 * Copyright (c) 2009-2013 QLogic Corporation
4
 *
S
Sritej Velaga 已提交
5
 * See LICENSE.qlcnic for copyright and licensing details.
6 7 8 9 10 11
 */

#include <linux/vmalloc.h>
#include <linux/interrupt.h>

#include "qlcnic.h"
12
#include "qlcnic_sriov.h"
13
#include "qlcnic_hw.h"
14

15
#include <linux/swab.h>
16
#include <linux/dma-mapping.h>
S
Sony Chacko 已提交
17
#include <linux/if_vlan.h>
18 19 20
#include <net/ip.h>
#include <linux/ipv6.h>
#include <linux/inetdevice.h>
S
Sucheta Chakraborty 已提交
21
#include <linux/aer.h>
22
#include <linux/log2.h>
23
#include <linux/pci.h>
24
#ifdef CONFIG_QLCNIC_VXLAN
25
#include <net/vxlan.h>
26
#endif
27

28
MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver");
29 30 31 32 33
MODULE_LICENSE("GPL");
MODULE_VERSION(QLCNIC_LINUX_VERSIONID);
MODULE_FIRMWARE(QLCNIC_UNIFIED_ROMIMAGE_NAME);

char qlcnic_driver_name[] = "qlcnic";
34 35
static const char qlcnic_driver_string[] = "QLogic 1/10 GbE "
	"Converged/Intelligent Ethernet Driver v" QLCNIC_LINUX_VERSIONID;
36

37
static int qlcnic_mac_learn;
38
module_param(qlcnic_mac_learn, int, 0444);
39 40
MODULE_PARM_DESC(qlcnic_mac_learn,
		 "Mac Filter (0=learning is disabled, 1=Driver learning is enabled, 2=FDB learning is enabled)");
41

42
int qlcnic_use_msi = 1;
43
MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled)");
44
module_param_named(use_msi, qlcnic_use_msi, int, 0444);
45

46
int qlcnic_use_msi_x = 1;
47
MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled)");
48
module_param_named(use_msi_x, qlcnic_use_msi_x, int, 0444);
49

50
int qlcnic_auto_fw_reset = 1;
51
MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled)");
52
module_param_named(auto_fw_reset, qlcnic_auto_fw_reset, int, 0644);
53

54
int qlcnic_load_fw_file;
55
MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file)");
56
module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444);
57

58
static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
B
Bill Pemberton 已提交
59
static void qlcnic_remove(struct pci_dev *pdev);
60 61 62 63 64 65 66 67 68
static int qlcnic_open(struct net_device *netdev);
static int qlcnic_close(struct net_device *netdev);
static void qlcnic_tx_timeout(struct net_device *netdev);
static void qlcnic_attach_work(struct work_struct *work);
static void qlcnic_fwinit_work(struct work_struct *work);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void qlcnic_poll_controller(struct net_device *netdev);
#endif

69
static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
70 71
static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);

72
static irqreturn_t qlcnic_tmp_intr(int irq, void *data);
73 74 75
static irqreturn_t qlcnic_intr(int irq, void *data);
static irqreturn_t qlcnic_msi_intr(int irq, void *data);
static irqreturn_t qlcnic_msix_intr(int irq, void *data);
S
Sony Chacko 已提交
76
static irqreturn_t qlcnic_msix_tx_intr(int irq, void *data);
77 78

static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev);
79 80
static int qlcnic_start_firmware(struct qlcnic_adapter *);

81
static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
82 83
static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
84 85
static int qlcnic_vlan_rx_add(struct net_device *, __be16, u16);
static int qlcnic_vlan_rx_del(struct net_device *, __be16, u16);
86

87 88 89 90 91 92 93 94 95
static int qlcnic_82xx_setup_intr(struct qlcnic_adapter *);
static void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *, u32);
static irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *);
static pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *);
static int qlcnic_82xx_start_firmware(struct qlcnic_adapter *);
static void qlcnic_82xx_io_resume(struct pci_dev *);
static void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *);
static pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *,
						      pci_channel_state_t);
S
Sony Chacko 已提交
96 97 98 99 100 101 102 103 104 105
static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;

	if (adapter->pdev->device == PCI_DEVICE_ID_QLOGIC_QLE824X)
		return ahw->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX;
	else
		return 1;
}

106 107 108 109 110
/*  PCI Device ID Table  */
#define ENTRY(device) \
	{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
	.class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0}

111
static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
112
	ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X),
S
Sony Chacko 已提交
113
	ENTRY(PCI_DEVICE_ID_QLOGIC_QLE834X),
R
Rajesh Borundia 已提交
114
	ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE834X),
115 116
	ENTRY(PCI_DEVICE_ID_QLOGIC_QLE844X),
	ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE844X),
117 118 119 120 121 122
	{0,}
};

MODULE_DEVICE_TABLE(pci, qlcnic_pci_tbl);


S
Sony Chacko 已提交
123
inline void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *tx_ring)
124 125 126 127 128 129 130 131 132 133 134
{
	writel(tx_ring->producer, tx_ring->crb_cmd_producer);
}

static const u32 msi_tgt_status[8] = {
	ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
	ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
	ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
	ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
};

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
static const u32 qlcnic_reg_tbl[] = {
	0x1B20A8,	/* PEG_HALT_STAT1 */
	0x1B20AC,	/* PEG_HALT_STAT2 */
	0x1B20B0,	/* FW_HEARTBEAT */
	0x1B2100,	/* LOCK ID */
	0x1B2128,	/* FW_CAPABILITIES */
	0x1B2138,	/* drv active */
	0x1B2140,	/* dev state */
	0x1B2144,	/* drv state */
	0x1B2148,	/* drv scratch */
	0x1B214C,	/* dev partition info */
	0x1B2174,	/* drv idc ver */
	0x1B2150,	/* fw version major */
	0x1B2154,	/* fw version minor */
	0x1B2158,	/* fw version sub */
	0x1B219C,	/* npar state */
	0x1B21FC,	/* FW_IMG_VALID */
	0x1B2250,	/* CMD_PEG_STATE */
	0x1B233C,	/* RCV_PEG_STATE */
	0x1B23B4,	/* ASIC TEMP */
	0x1B216C,	/* FW api */
	0x1B2170,	/* drv op mode */
	0x13C010,	/* flash lock */
	0x13C014,	/* flash unlock */
};

S
Sony Chacko 已提交
161
static const struct qlcnic_board_info qlcnic_boards[] = {
162 163 164 165 166
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE844X,
	  0x0,
	  0x0,
	  "8400 series 10GbE Converged Network Adapter (TCP/IP Networking)" },
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE834X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x24e,
	  "8300 Series Dual Port 10GbE Converged Network Adapter "
	  "(TCP/IP Networking)" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE834X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x243,
	  "8300 Series Single Port 10GbE Converged Network Adapter "
	  "(TCP/IP Networking)" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE834X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x24a,
	  "8300 Series Dual Port 10GbE Converged Network Adapter "
	  "(TCP/IP Networking)" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE834X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x246,
	  "8300 Series Dual Port 10GbE Converged Network Adapter "
	  "(TCP/IP Networking)" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE834X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x252,
	  "8300 Series Dual Port 10GbE Converged Network Adapter "
	  "(TCP/IP Networking)" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE834X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x26e,
	  "8300 Series Dual Port 10GbE Converged Network Adapter "
	  "(TCP/IP Networking)" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE834X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x260,
	  "8300 Series Dual Port 10GbE Converged Network Adapter "
	  "(TCP/IP Networking)" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE834X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x266,
	  "8300 Series Single Port 10GbE Converged Network Adapter "
	  "(TCP/IP Networking)" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE834X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x269,
	  "8300 Series Dual Port 10GbE Converged Network Adapter "
	  "(TCP/IP Networking)" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE834X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x271,
	  "8300 Series Dual Port 10GbE Converged Network Adapter "
	  "(TCP/IP Networking)" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE834X,
	  0x0, 0x0, "8300 Series 1/10GbE Controller" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE824X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x203,
	  "8200 Series Single Port 10GbE Converged Network Adapter"
	  "(TCP/IP Networking)" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE824X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x207,
	  "8200 Series Dual Port 10GbE Converged Network Adapter"
	  "(TCP/IP Networking)" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE824X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x20b,
	  "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE824X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x20c,
	  "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE824X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x20f,
	  "3200 Series Single Port 10Gb Intelligent Ethernet Adapter" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE824X,
	  0x103c, 0x3733,
	  "NC523SFP 10Gb 2-port Server Adapter" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE824X,
	  0x103c, 0x3346,
	  "CN1000Q Dual Port Converged Network Adapter" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE824X,
	  PCI_VENDOR_ID_QLOGIC,
	  0x210,
	  "QME8242-k 10GbE Dual Port Mezzanine Card" },
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE824X,
	  0x0, 0x0, "cLOM8214 1/10GbE Controller" },
S
Sony Chacko 已提交
273 274 275 276
};

#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards)

277 278 279
static const
struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG;

280
int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
281 282 283 284 285
{
	int size = sizeof(struct qlcnic_host_sds_ring) * count;

	recv_ctx->sds_rings = kzalloc(size, GFP_KERNEL);

286
	return recv_ctx->sds_rings == NULL;
287 288
}

289
void qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
290 291 292 293 294 295 296
{
	if (recv_ctx->sds_rings != NULL)
		kfree(recv_ctx->sds_rings);

	recv_ctx->sds_rings = NULL;
}

R
Rajesh Borundia 已提交
297
int qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
298 299 300
{
	struct net_device *netdev = adapter->netdev;
	struct pci_dev *pdev = adapter->pdev;
301 302
	u8 mac_addr[ETH_ALEN];
	int ret;
303

304 305 306 307
	ret = qlcnic_get_mac_address(adapter, mac_addr,
				     adapter->ahw->pci_func);
	if (ret)
		return ret;
308

309
	memcpy(netdev->dev_addr, mac_addr, ETH_ALEN);
310 311 312 313
	memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len);

	/* set station address */

314
	if (!is_valid_ether_addr(netdev->dev_addr))
315 316 317 318 319 320
		dev_warn(&pdev->dev, "Bad MAC address %pM.\n",
					netdev->dev_addr);

	return 0;
}

M
Manish Chopra 已提交
321 322
static void qlcnic_delete_adapter_mac(struct qlcnic_adapter *adapter)
{
323
	struct qlcnic_mac_vlan_list *cur;
M
Manish Chopra 已提交
324 325 326
	struct list_head *head;

	list_for_each(head, &adapter->mac_list) {
327
		cur = list_entry(head, struct qlcnic_mac_vlan_list, list);
328
		if (ether_addr_equal_unaligned(adapter->mac_addr, cur->mac_addr)) {
M
Manish Chopra 已提交
329 330 331 332 333 334 335 336 337
			qlcnic_sre_macaddr_change(adapter, cur->mac_addr,
						  0, QLCNIC_MAC_DEL);
			list_del(&cur->list);
			kfree(cur);
			return;
		}
	}
}

338 339 340 341 342
static int qlcnic_set_mac(struct net_device *netdev, void *p)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct sockaddr *addr = p;

343 344 345
	if (qlcnic_sriov_vf_check(adapter))
		return -EINVAL;

346 347 348
	if ((adapter->flags & QLCNIC_MAC_OVERRIDE_DISABLED))
		return -EOPNOTSUPP;

349
	if (!is_valid_ether_addr(addr->sa_data))
S
Sony Chacko 已提交
350
		return -EINVAL;
351

352
	if (ether_addr_equal_unaligned(adapter->mac_addr, addr->sa_data))
M
Manish Chopra 已提交
353 354
		return 0;

355
	if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
356 357 358 359
		netif_device_detach(netdev);
		qlcnic_napi_disable(adapter);
	}

M
Manish Chopra 已提交
360
	qlcnic_delete_adapter_mac(adapter);
361 362 363 364
	memcpy(adapter->mac_addr, addr->sa_data, netdev->addr_len);
	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
	qlcnic_set_multi(adapter->netdev);

365
	if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
366 367 368 369 370 371
		netif_device_attach(netdev);
		qlcnic_napi_enable(adapter);
	}
	return 0;
}

372 373
static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
			struct net_device *netdev, const unsigned char *addr)
374 375 376 377
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	int err = -EOPNOTSUPP;

378 379
	if (!adapter->fdb_mac_learn)
		return ndo_dflt_fdb_del(ndm, tb, netdev, addr);
380 381

	if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
382 383 384 385 386
		if (is_unicast_ether_addr(addr)) {
			err = dev_uc_del(netdev, addr);
			if (!err)
				err = qlcnic_nic_del_mac(adapter, addr);
		} else if (is_multicast_ether_addr(addr)) {
387
			err = dev_mc_del(netdev, addr);
388
		} else {
389
			err =  -EINVAL;
390
		}
391 392 393 394 395 396 397 398 399 400 401
	}
	return err;
}

static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
			struct net_device *netdev,
			const unsigned char *addr, u16 flags)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	int err = 0;

402 403
	if (!adapter->fdb_mac_learn)
		return ndo_dflt_fdb_add(ndm, tb, netdev, addr, flags);
404 405 406 407 408 409 410 411 412

	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
		pr_info("%s: FDB e-switch is not enabled\n", __func__);
		return -EOPNOTSUPP;
	}

	if (ether_addr_equal(addr, adapter->mac_addr))
		return err;

413 414 415 416 417 418
	if (is_unicast_ether_addr(addr)) {
		if (netdev_uc_count(netdev) < adapter->ahw->max_uc_count)
			err = dev_uc_add_excl(netdev, addr);
		else
			err = -ENOMEM;
	} else if (is_multicast_ether_addr(addr)) {
419
		err = dev_mc_add_excl(netdev, addr);
420
	} else {
421
		err = -EINVAL;
422
	}
423 424 425 426 427 428 429 430 431

	return err;
}

static int qlcnic_fdb_dump(struct sk_buff *skb, struct netlink_callback *ncb,
			struct net_device *netdev, int idx)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);

432 433
	if (!adapter->fdb_mac_learn)
		return ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
434 435 436 437 438 439 440

	if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
		idx = ndo_dflt_fdb_dump(skb, ncb, netdev, idx);

	return idx;
}

441 442 443 444 445
static void qlcnic_82xx_cancel_idc_work(struct qlcnic_adapter *adapter)
{
	while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
		usleep_range(10000, 11000);

446 447 448
	if (!adapter->fw_work.work.func)
		return;

449 450 451
	cancel_delayed_work_sync(&adapter->fw_work);
}

452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
static int qlcnic_get_phys_port_id(struct net_device *netdev,
				   struct netdev_phys_port_id *ppid)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct qlcnic_hardware_context *ahw = adapter->ahw;

	if (!(adapter->flags & QLCNIC_HAS_PHYS_PORT_ID))
		return -EOPNOTSUPP;

	ppid->id_len = sizeof(ahw->phys_port_id);
	memcpy(ppid->id, ahw->phys_port_id, ppid->id_len);

	return 0;
}

467
#ifdef CONFIG_QLCNIC_VXLAN
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
static void qlcnic_add_vxlan_port(struct net_device *netdev,
				  sa_family_t sa_family, __be16 port)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct qlcnic_hardware_context *ahw = adapter->ahw;

	/* Adapter supports only one VXLAN port. Use very first port
	 * for enabling offload
	 */
	if (!qlcnic_encap_rx_offload(adapter) || ahw->vxlan_port)
		return;

	ahw->vxlan_port = ntohs(port);
	adapter->flags |= QLCNIC_ADD_VXLAN_PORT;
}

static void qlcnic_del_vxlan_port(struct net_device *netdev,
				  sa_family_t sa_family, __be16 port)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct qlcnic_hardware_context *ahw = adapter->ahw;

	if (!qlcnic_encap_rx_offload(adapter) || !ahw->vxlan_port ||
	    (ahw->vxlan_port != ntohs(port)))
		return;

	adapter->flags |= QLCNIC_DEL_VXLAN_PORT;
}
496
#endif
497

498 499 500 501 502 503
static const struct net_device_ops qlcnic_netdev_ops = {
	.ndo_open	   = qlcnic_open,
	.ndo_stop	   = qlcnic_close,
	.ndo_start_xmit    = qlcnic_xmit_frame,
	.ndo_get_stats	   = qlcnic_get_stats,
	.ndo_validate_addr = eth_validate_addr,
504
	.ndo_set_rx_mode   = qlcnic_set_multi,
505 506
	.ndo_set_mac_address    = qlcnic_set_mac,
	.ndo_change_mtu	   = qlcnic_change_mtu,
507 508
	.ndo_fix_features  = qlcnic_fix_features,
	.ndo_set_features  = qlcnic_set_features,
509
	.ndo_tx_timeout	   = qlcnic_tx_timeout,
510 511
	.ndo_vlan_rx_add_vid	= qlcnic_vlan_rx_add,
	.ndo_vlan_rx_kill_vid	= qlcnic_vlan_rx_del,
512 513 514
	.ndo_fdb_add		= qlcnic_fdb_add,
	.ndo_fdb_del		= qlcnic_fdb_del,
	.ndo_fdb_dump		= qlcnic_fdb_dump,
515
	.ndo_get_phys_port_id	= qlcnic_get_phys_port_id,
516
#ifdef CONFIG_QLCNIC_VXLAN
517 518
	.ndo_add_vxlan_port	= qlcnic_add_vxlan_port,
	.ndo_del_vxlan_port	= qlcnic_del_vxlan_port,
519
#endif
520 521 522
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller = qlcnic_poll_controller,
#endif
523 524 525 526
#ifdef CONFIG_QLCNIC_SRIOV
	.ndo_set_vf_mac		= qlcnic_sriov_set_vf_mac,
	.ndo_set_vf_tx_rate	= qlcnic_sriov_set_vf_tx_rate,
	.ndo_get_vf_config	= qlcnic_sriov_get_vf_config,
527
	.ndo_set_vf_vlan	= qlcnic_sriov_set_vf_vlan,
528
	.ndo_set_vf_spoofchk	= qlcnic_sriov_set_vf_spoofchk,
529
#endif
530 531
};

532 533 534 535
static const struct net_device_ops qlcnic_netdev_failed_ops = {
	.ndo_open	   = qlcnic_open,
};

536
static struct qlcnic_nic_template qlcnic_ops = {
537 538 539 540 541 542
	.config_bridged_mode	= qlcnic_config_bridged_mode,
	.config_led		= qlcnic_82xx_config_led,
	.start_firmware		= qlcnic_82xx_start_firmware,
	.request_reset		= qlcnic_82xx_dev_request_reset,
	.cancel_idc_work	= qlcnic_82xx_cancel_idc_work,
	.napi_add		= qlcnic_82xx_napi_add,
S
Sony Chacko 已提交
543
	.napi_del		= qlcnic_82xx_napi_del,
544
	.config_ipaddr		= qlcnic_82xx_config_ipaddr,
545 546
	.shutdown		= qlcnic_82xx_shutdown,
	.resume			= qlcnic_82xx_resume,
547 548 549 550 551 552 553
	.clear_legacy_intr	= qlcnic_82xx_clear_legacy_intr,
};

struct qlcnic_nic_template qlcnic_vf_ops = {
	.config_bridged_mode	= qlcnicvf_config_bridged_mode,
	.config_led		= qlcnicvf_config_led,
	.start_firmware		= qlcnicvf_start_firmware
554 555
};

556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
static struct qlcnic_hardware_ops qlcnic_hw_ops = {
	.read_crb			= qlcnic_82xx_read_crb,
	.write_crb			= qlcnic_82xx_write_crb,
	.read_reg			= qlcnic_82xx_hw_read_wx_2M,
	.write_reg			= qlcnic_82xx_hw_write_wx_2M,
	.get_mac_address		= qlcnic_82xx_get_mac_address,
	.setup_intr			= qlcnic_82xx_setup_intr,
	.alloc_mbx_args			= qlcnic_82xx_alloc_mbx_args,
	.mbx_cmd			= qlcnic_82xx_issue_cmd,
	.get_func_no			= qlcnic_82xx_get_func_no,
	.api_lock			= qlcnic_82xx_api_lock,
	.api_unlock			= qlcnic_82xx_api_unlock,
	.add_sysfs			= qlcnic_82xx_add_sysfs,
	.remove_sysfs			= qlcnic_82xx_remove_sysfs,
	.process_lb_rcv_ring_diag	= qlcnic_82xx_process_rcv_ring_diag,
	.create_rx_ctx			= qlcnic_82xx_fw_cmd_create_rx_ctx,
	.create_tx_ctx			= qlcnic_82xx_fw_cmd_create_tx_ctx,
573 574
	.del_rx_ctx			= qlcnic_82xx_fw_cmd_del_rx_ctx,
	.del_tx_ctx			= qlcnic_82xx_fw_cmd_del_tx_ctx,
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
	.setup_link_event		= qlcnic_82xx_linkevent_request,
	.get_nic_info			= qlcnic_82xx_get_nic_info,
	.get_pci_info			= qlcnic_82xx_get_pci_info,
	.set_nic_info			= qlcnic_82xx_set_nic_info,
	.change_macvlan			= qlcnic_82xx_sre_macaddr_change,
	.napi_enable			= qlcnic_82xx_napi_enable,
	.napi_disable			= qlcnic_82xx_napi_disable,
	.config_intr_coal		= qlcnic_82xx_config_intr_coalesce,
	.config_rss			= qlcnic_82xx_config_rss,
	.config_hw_lro			= qlcnic_82xx_config_hw_lro,
	.config_loopback		= qlcnic_82xx_set_lb_mode,
	.clear_loopback			= qlcnic_82xx_clear_lb_mode,
	.config_promisc_mode		= qlcnic_82xx_nic_set_promisc,
	.change_l2_filter		= qlcnic_82xx_change_filter,
	.get_board_info			= qlcnic_82xx_get_board_info,
590
	.set_mac_filter_count		= qlcnic_82xx_set_mac_filter_count,
591
	.free_mac_list			= qlcnic_82xx_free_mac_list,
592
	.read_phys_port_id		= qlcnic_82xx_read_phys_port_id,
593 594 595
	.io_error_detected		= qlcnic_82xx_io_error_detected,
	.io_slot_reset			= qlcnic_82xx_io_slot_reset,
	.io_resume			= qlcnic_82xx_io_resume,
596
	.get_beacon_state		= qlcnic_82xx_get_beacon_state,
M
Manish chopra 已提交
597 598 599 600
	.enable_sds_intr		= qlcnic_82xx_enable_sds_intr,
	.disable_sds_intr		= qlcnic_82xx_disable_sds_intr,
	.enable_tx_intr			= qlcnic_82xx_enable_tx_intr,
	.disable_tx_intr		= qlcnic_82xx_disable_tx_intr,
601 602 603 604 605 606
	.get_saved_state		= qlcnic_82xx_get_saved_state,
	.set_saved_state		= qlcnic_82xx_set_saved_state,
	.cache_tmpl_hdr_values		= qlcnic_82xx_cache_tmpl_hdr_values,
	.get_cap_size			= qlcnic_82xx_get_cap_size,
	.set_sys_info			= qlcnic_82xx_set_sys_info,
	.store_cap_mask			= qlcnic_82xx_store_cap_mask,
607 608
};

609
static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter)
610 611 612
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;

613
	if (qlcnic_82xx_check(adapter) &&
614
	    (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_MULTI_TX)) {
615 616
		test_and_set_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state);
		return 0;
617
	} else {
618
		return 1;
619 620 621
	}
}

622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
static int qlcnic_max_rings(struct qlcnic_adapter *adapter, u8 ring_cnt,
			    int queue_type)
{
	int num_rings, max_rings = QLCNIC_MAX_SDS_RINGS;

	if (queue_type == QLCNIC_RX_QUEUE)
		max_rings = adapter->max_sds_rings;
	else if (queue_type == QLCNIC_TX_QUEUE)
		max_rings = adapter->max_tx_rings;

	num_rings = rounddown_pow_of_two(min_t(int, num_online_cpus(),
					      max_rings));

	if (ring_cnt > num_rings)
		return num_rings;
	else
		return ring_cnt;
}

void qlcnic_set_tx_ring_count(struct qlcnic_adapter *adapter, u8 tx_cnt)
{
	/* 83xx adapter does not have max_tx_rings intialized in probe */
	if (adapter->max_tx_rings)
		adapter->drv_tx_rings = qlcnic_max_rings(adapter, tx_cnt,
							 QLCNIC_TX_QUEUE);
	else
		adapter->drv_tx_rings = tx_cnt;
}

void qlcnic_set_sds_ring_count(struct qlcnic_adapter *adapter, u8 rx_cnt)
{
	/* 83xx adapter does not have max_sds_rings intialized in probe */
	if (adapter->max_sds_rings)
		adapter->drv_sds_rings = qlcnic_max_rings(adapter, rx_cnt,
							  QLCNIC_RX_QUEUE);
	else
		adapter->drv_sds_rings = rx_cnt;
}

661
int qlcnic_setup_tss_rss_intr(struct qlcnic_adapter *adapter)
662 663
{
	struct pci_dev *pdev = adapter->pdev;
664 665 666 667 668 669 670 671 672
	int num_msix = 0, err = 0, vector;

	adapter->flags &= ~QLCNIC_TSS_RSS;

	if (adapter->drv_tss_rings > 0)
		num_msix += adapter->drv_tss_rings;
	else
		num_msix += adapter->drv_tx_rings;

673
	if (adapter->drv_rss_rings > 0)
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
		num_msix += adapter->drv_rss_rings;
	else
		num_msix += adapter->drv_sds_rings;

	if (qlcnic_83xx_check(adapter))
		num_msix += 1;

	if (!adapter->msix_entries) {
		adapter->msix_entries = kcalloc(num_msix,
						sizeof(struct msix_entry),
						GFP_KERNEL);
		if (!adapter->msix_entries)
			return -ENOMEM;
	}

	for (vector = 0; vector < num_msix; vector++)
		adapter->msix_entries[vector].entry = vector;

692
restore:
693 694
	err = pci_enable_msix_exact(pdev, adapter->msix_entries, num_msix);
	if (err == -ENOSPC) {
695
		if (!adapter->drv_tss_rings && !adapter->drv_rss_rings)
696
			return err;
697

698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
		netdev_info(adapter->netdev,
			    "Unable to allocate %d MSI-X vectors, Available vectors %d\n",
			    num_msix, err);

		num_msix = adapter->drv_tx_rings + adapter->drv_sds_rings;

		/* Set rings to 0 so we can restore original TSS/RSS count */
		adapter->drv_tss_rings = 0;
		adapter->drv_rss_rings = 0;

		if (qlcnic_83xx_check(adapter))
			num_msix += 1;

		netdev_info(adapter->netdev,
			    "Restoring %d Tx, %d SDS rings for total %d vectors.\n",
			    adapter->drv_tx_rings, adapter->drv_sds_rings,
			    num_msix);

716 717 718
		goto restore;
	} else if (err < 0) {
		return err;
719
	}
S
Sony Chacko 已提交
720

721 722 723 724 725 726 727 728
	adapter->ahw->num_msix = num_msix;
	if (adapter->drv_tss_rings > 0)
		adapter->drv_tx_rings = adapter->drv_tss_rings;

	if (adapter->drv_rss_rings > 0)
		adapter->drv_sds_rings = adapter->drv_rss_rings;

	return 0;
729 730 731 732 733
}

int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
{
	struct pci_dev *pdev = adapter->pdev;
734
	int err, vector;
735

S
Sony Chacko 已提交
736 737 738 739
	if (!adapter->msix_entries) {
		adapter->msix_entries = kcalloc(num_msix,
						sizeof(struct msix_entry),
						GFP_KERNEL);
740
		if (!adapter->msix_entries)
S
Sony Chacko 已提交
741 742
			return -ENOMEM;
	}
743 744 745

	adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED);

746
	if (adapter->ahw->msix_supported) {
747 748 749 750
enable_msix:
		for (vector = 0; vector < num_msix; vector++)
			adapter->msix_entries[vector].entry = vector;

751 752 753 754
		err = pci_enable_msix_range(pdev,
					    adapter->msix_entries, 1, num_msix);

		if (err == num_msix) {
755
			adapter->flags |= QLCNIC_MSIX_ENABLED;
756
			adapter->ahw->num_msix = num_msix;
757
			dev_info(&pdev->dev, "using msi-x interrupts\n");
758
			return 0;
S
Sony Chacko 已提交
759
		} else if (err > 0) {
760 761
			pci_disable_msix(pdev);

S
Sony Chacko 已提交
762
			dev_info(&pdev->dev,
763 764 765 766
				 "Unable to allocate %d MSI-X vectors, Available vectors %d\n",
				 num_msix, err);

			if (qlcnic_82xx_check(adapter)) {
S
Sony Chacko 已提交
767
				num_msix = rounddown_pow_of_two(err);
768
				if (err < QLCNIC_82XX_MINIMUM_VECTOR)
769
					return -ENOSPC;
S
Sony Chacko 已提交
770
			} else {
771 772 773
				num_msix = rounddown_pow_of_two(err - 1);
				num_msix += 1;
				if (err < QLCNIC_83XX_MINIMUM_VECTOR)
774
					return -ENOSPC;
775 776 777 778 779 780 781 782 783 784
			}

			if (qlcnic_82xx_check(adapter) &&
			    !qlcnic_check_multi_tx(adapter)) {
				adapter->drv_sds_rings = num_msix;
				adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
			} else {
				/* Distribute vectors equally */
				adapter->drv_tx_rings = num_msix / 2;
				adapter->drv_sds_rings = adapter->drv_tx_rings;
S
Sony Chacko 已提交
785 786 787 788
			}

			if (num_msix) {
				dev_info(&pdev->dev,
789
					 "Trying to allocate %d MSI-X interrupt vectors\n",
S
Sony Chacko 已提交
790
					 num_msix);
791
				goto enable_msix;
S
Sony Chacko 已提交
792 793
			}
		} else {
794
			dev_info(&pdev->dev,
795 796 797
				 "Unable to allocate %d MSI-X vectors, err=%d\n",
				 num_msix, err);
			return err;
798 799
		}
	}
S
Sony Chacko 已提交
800

801
	return -EIO;
802
}
803

804 805 806 807 808 809 810 811 812 813 814 815 816 817
static int qlcnic_82xx_calculate_msix_vector(struct qlcnic_adapter *adapter)
{
	int num_msix;

	num_msix = adapter->drv_sds_rings;

	if (qlcnic_check_multi_tx(adapter))
		num_msix += adapter->drv_tx_rings;
	else
		num_msix += QLCNIC_SINGLE_RING;

	return num_msix;
}

818
static int qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
819
{
820
	int err = 0;
821
	u32 offset, mask_reg;
822
	const struct qlcnic_legacy_intr_set *legacy_intrp;
823
	struct qlcnic_hardware_context *ahw = adapter->ahw;
824
	struct pci_dev *pdev = adapter->pdev;
825

826
	if (qlcnic_use_msi && !pci_enable_msi(pdev)) {
827
		adapter->flags |= QLCNIC_MSI_ENABLED;
828 829 830
		offset = msi_tgt_status[adapter->ahw->pci_func];
		adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter->ahw,
							    offset);
831 832
		dev_info(&pdev->dev, "using msi interrupts\n");
		adapter->msix_entries[0].vector = pdev->irq;
833
		return err;
834
	}
835

836 837
	if (qlcnic_use_msi || qlcnic_use_msi_x)
		return -EOPNOTSUPP;
838

839
	legacy_intrp = &legacy_intr[adapter->ahw->pci_func];
840
	adapter->ahw->int_vec_bit = legacy_intrp->int_vec_bit;
841 842 843 844 845 846
	offset = legacy_intrp->tgt_status_reg;
	adapter->tgt_status_reg = qlcnic_get_ioaddr(ahw, offset);
	mask_reg = legacy_intrp->tgt_mask_reg;
	adapter->tgt_mask_reg = qlcnic_get_ioaddr(ahw, mask_reg);
	adapter->isr_int_vec = qlcnic_get_ioaddr(ahw, ISR_INT_VECTOR);
	adapter->crb_int_state_reg = qlcnic_get_ioaddr(ahw, ISR_INT_STATE_REG);
847 848
	dev_info(&pdev->dev, "using legacy interrupts\n");
	adapter->msix_entries[0].vector = pdev->irq;
849
	return err;
850 851
}

852
static int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter)
853
{
854
	int num_msix, err = 0;
855

856 857 858 859 860 861 862
	if (adapter->flags & QLCNIC_TSS_RSS) {
		err = qlcnic_setup_tss_rss_intr(adapter);
		if (err < 0)
			return err;
		num_msix = adapter->ahw->num_msix;
	} else {
		num_msix = qlcnic_82xx_calculate_msix_vector(adapter);
863

864 865 866
		err = qlcnic_enable_msix(adapter, num_msix);
		if (err == -ENOMEM)
			return err;
867

868 869
		if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
			qlcnic_disable_multi_tx(adapter);
870
			adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
871

872
			err = qlcnic_enable_msi_legacy(adapter);
873
			if (err)
874 875
				return err;
		}
876 877 878 879 880 881 882 883 884 885 886
	}

	return 0;
}

int qlcnic_82xx_mq_intrpt(struct qlcnic_adapter *adapter, int op_type)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	int err, i;

	if (qlcnic_check_multi_tx(adapter) &&
887
	    !ahw->diag_test &&
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904
	    (adapter->flags & QLCNIC_MSIX_ENABLED)) {
		ahw->intr_tbl = vzalloc(ahw->num_msix *
					sizeof(struct qlcnic_intrpt_config));
		if (!ahw->intr_tbl)
			return -ENOMEM;

		for (i = 0; i < ahw->num_msix; i++) {
			ahw->intr_tbl[i].type = QLCNIC_INTRPT_MSIX;
			ahw->intr_tbl[i].id = i;
			ahw->intr_tbl[i].src = 0;
		}

		err = qlcnic_82xx_config_intrpt(adapter, 1);
		if (err)
			dev_err(&adapter->pdev->dev,
				"Failed to configure Interrupt for %d vector\n",
				ahw->num_msix);
905
		return err;
906
	}
907

908
	return 0;
909
}
S
Sony Chacko 已提交
910

S
Sony Chacko 已提交
911
void qlcnic_teardown_intr(struct qlcnic_adapter *adapter)
912 913 914 915 916
{
	if (adapter->flags & QLCNIC_MSIX_ENABLED)
		pci_disable_msix(adapter->pdev);
	if (adapter->flags & QLCNIC_MSI_ENABLED)
		pci_disable_msi(adapter->pdev);
S
Sony Chacko 已提交
917 918 919 920 921 922 923 924

	kfree(adapter->msix_entries);
	adapter->msix_entries = NULL;

	if (adapter->ahw->intr_tbl) {
		vfree(adapter->ahw->intr_tbl);
		adapter->ahw->intr_tbl = NULL;
	}
925 926
}

927
static void qlcnic_cleanup_pci_map(struct qlcnic_hardware_context *ahw)
928
{
929 930
	if (ahw->pci_base0 != NULL)
		iounmap(ahw->pci_base0);
931 932
}

933 934
static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter)
{
935
	struct qlcnic_hardware_context *ahw = adapter->ahw;
936 937 938 939
	struct qlcnic_pci_info *pci_info;
	int ret;

	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
940
		switch (ahw->port_type) {
941
		case QLCNIC_GBE:
942
			ahw->total_nic_func = QLCNIC_NIU_MAX_GBE_PORTS;
943 944
			break;
		case QLCNIC_XGBE:
945
			ahw->total_nic_func = QLCNIC_NIU_MAX_XG_PORTS;
946 947 948 949 950
			break;
		}
		return 0;
	}

951
	if (ahw->op_mode == QLCNIC_MGMT_FUNC)
952 953
		return 0;

954
	pci_info = kcalloc(ahw->max_vnic_func, sizeof(*pci_info), GFP_KERNEL);
955 956 957 958 959 960 961
	if (!pci_info)
		return -ENOMEM;

	ret = qlcnic_get_pci_info(adapter, pci_info);
	kfree(pci_info);
	return ret;
}
962

963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
static bool qlcnic_port_eswitch_cfg_capability(struct qlcnic_adapter *adapter)
{
	bool ret = false;

	if (qlcnic_84xx_check(adapter)) {
		ret = true;
	} else if (qlcnic_83xx_check(adapter)) {
		if (adapter->ahw->extra_capability[0] &
		    QLCNIC_FW_CAPABILITY_2_PER_PORT_ESWITCH_CFG)
			ret = true;
		else
			ret = false;
	}

	return ret;
}

980
int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
981
{
982
	struct qlcnic_hardware_context *ahw = adapter->ahw;
D
Dan Carpenter 已提交
983
	struct qlcnic_pci_info *pci_info;
984
	int i, id = 0, ret = 0, j = 0;
985
	u16 act_pci_func;
986 987
	u8 pfn;

988
	pci_info = kcalloc(ahw->max_vnic_func, sizeof(*pci_info), GFP_KERNEL);
D
Dan Carpenter 已提交
989 990 991
	if (!pci_info)
		return -ENOMEM;

992 993 994 995
	ret = qlcnic_get_pci_info(adapter, pci_info);
	if (ret)
		goto err_pci_info;

996
	act_pci_func = ahw->total_nic_func;
997

998
	adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
999
				 act_pci_func, GFP_KERNEL);
D
Dan Carpenter 已提交
1000
	if (!adapter->npars) {
1001
		ret = -ENOMEM;
D
Dan Carpenter 已提交
1002 1003
		goto err_pci_info;
	}
1004

1005
	adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) *
1006 1007
				QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL);
	if (!adapter->eswitch) {
1008
		ret = -ENOMEM;
1009
		goto err_npars;
1010 1011
	}

1012
	for (i = 0; i < ahw->max_vnic_func; i++) {
1013
		pfn = pci_info[i].id;
1014

1015
		if (pfn >= ahw->max_vnic_func) {
S
Sony Chacko 已提交
1016
			ret = QL_STATUS_INVALID_PARAM;
1017 1018
			dev_err(&adapter->pdev->dev, "%s: Invalid function 0x%x, max 0x%x\n",
				__func__, pfn, ahw->max_vnic_func);
S
Sony Chacko 已提交
1019 1020
			goto err_eswitch;
		}
1021 1022 1023 1024 1025

		if (!pci_info[i].active ||
		    (pci_info[i].type != QLCNIC_TYPE_NIC))
			continue;

1026
		if (qlcnic_port_eswitch_cfg_capability(adapter)) {
1027 1028
			if (!qlcnic_83xx_set_port_eswitch_status(adapter, pfn,
								 &id))
1029 1030 1031 1032 1033 1034 1035
				adapter->npars[j].eswitch_status = true;
			else
				continue;
		} else {
			adapter->npars[j].eswitch_status = true;
		}

1036 1037 1038 1039 1040 1041
		adapter->npars[j].pci_func = pfn;
		adapter->npars[j].active = (u8)pci_info[i].active;
		adapter->npars[j].type = (u8)pci_info[i].type;
		adapter->npars[j].phy_port = (u8)pci_info[i].default_port;
		adapter->npars[j].min_bw = pci_info[i].tx_min_bw;
		adapter->npars[j].max_bw = pci_info[i].tx_max_bw;
1042

1043
		memcpy(&adapter->npars[j].mac, &pci_info[i].mac, ETH_ALEN);
1044
		j++;
1045 1046
	}

1047 1048 1049 1050
	/* Update eSwitch status for adapters without per port eSwitch
	 * configuration capability
	 */
	if (!qlcnic_port_eswitch_cfg_capability(adapter)) {
1051 1052
		for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
			adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE;
S
Sony Chacko 已提交
1053
	}
1054

D
Dan Carpenter 已提交
1055
	kfree(pci_info);
1056 1057 1058
	return 0;

err_eswitch:
1059 1060
	kfree(adapter->eswitch);
	adapter->eswitch = NULL;
1061
err_npars:
1062
	kfree(adapter->npars);
1063
	adapter->npars = NULL;
D
Dan Carpenter 已提交
1064 1065
err_pci_info:
	kfree(pci_info);
1066 1067 1068 1069

	return ret;
}

1070 1071 1072 1073
static int
qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
{
	u8 id;
1074
	int ret;
1075
	u32 data = QLCNIC_MGMT_FUNC;
1076
	struct qlcnic_hardware_context *ahw = adapter->ahw;
1077 1078 1079 1080 1081

	ret = qlcnic_api_lock(adapter);
	if (ret)
		goto err_lock;

1082 1083 1084 1085
	id = ahw->pci_func;
	data = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE);
	data = (data & ~QLC_DEV_SET_DRV(0xf, id)) |
	       QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, id);
1086
	QLC_SHARED_REG_WR32(adapter, QLCNIC_DRV_OP_MODE, data);
1087 1088 1089 1090 1091
	qlcnic_api_unlock(adapter);
err_lock:
	return ret;
}

S
Sony Chacko 已提交
1092 1093
static void qlcnic_check_vf(struct qlcnic_adapter *adapter,
			    const struct pci_device_id *ent)
1094 1095 1096 1097
{
	u32 op_mode, priv_level;

	/* Determine FW API version */
S
Sony Chacko 已提交
1098 1099
	adapter->ahw->fw_hal_version = QLC_SHARED_REG_RD32(adapter,
							   QLCNIC_FW_API);
1100 1101

	/* Find PCI function number */
S
Sony Chacko 已提交
1102
	qlcnic_get_func_no(adapter);
1103 1104

	/* Determine function privilege level */
S
Sony Chacko 已提交
1105
	op_mode = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE);
1106
	if (op_mode == QLC_DEV_DRV_DEFAULT)
1107
		priv_level = QLCNIC_MGMT_FUNC;
1108
	else
A
Anirban Chakraborty 已提交
1109
		priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
1110

1111
	if (priv_level == QLCNIC_NON_PRIV_FUNC) {
1112
		adapter->ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
1113 1114
		dev_info(&adapter->pdev->dev,
			"HAL Version: %d Non Privileged function\n",
1115
			 adapter->ahw->fw_hal_version);
1116
		adapter->nic_ops = &qlcnic_vf_ops;
1117 1118
	} else
		adapter->nic_ops = &qlcnic_ops;
1119 1120
}

1121
#define QLCNIC_82XX_BAR0_LENGTH 0x00200000UL
S
Sony Chacko 已提交
1122
#define QLCNIC_83XX_BAR0_LENGTH 0x4000
1123 1124 1125 1126 1127 1128
static void qlcnic_get_bar_length(u32 dev_id, ulong *bar)
{
	switch (dev_id) {
	case PCI_DEVICE_ID_QLOGIC_QLE824X:
		*bar = QLCNIC_82XX_BAR0_LENGTH;
		break;
S
Sony Chacko 已提交
1129
	case PCI_DEVICE_ID_QLOGIC_QLE834X:
1130
	case PCI_DEVICE_ID_QLOGIC_QLE844X:
R
Rajesh Borundia 已提交
1131
	case PCI_DEVICE_ID_QLOGIC_VF_QLE834X:
1132
	case PCI_DEVICE_ID_QLOGIC_VF_QLE844X:
S
Sony Chacko 已提交
1133 1134
		*bar = QLCNIC_83XX_BAR0_LENGTH;
		break;
1135 1136 1137 1138 1139 1140 1141
	default:
		*bar = 0;
	}
}

static int qlcnic_setup_pci_map(struct pci_dev *pdev,
				struct qlcnic_hardware_context *ahw)
1142
{
1143
	u32 offset;
1144
	void __iomem *mem_ptr0 = NULL;
1145
	unsigned long mem_len, pci_len0 = 0, bar0_len;
1146 1147 1148 1149

	/* remap phys address */
	mem_len = pci_resource_len(pdev, 0);

1150 1151
	qlcnic_get_bar_length(pdev->device, &bar0_len);
	if (mem_len >= bar0_len) {
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162

		mem_ptr0 = pci_ioremap_bar(pdev, 0);
		if (mem_ptr0 == NULL) {
			dev_err(&pdev->dev, "failed to map PCI bar 0\n");
			return -EIO;
		}
		pci_len0 = mem_len;
	} else {
		return -EIO;
	}

R
Rajesh Borundia 已提交
1163
	dev_info(&pdev->dev, "%dKB memory map\n", (int)(mem_len >> 10));
1164

1165 1166 1167 1168
	ahw->pci_base0 = mem_ptr0;
	ahw->pci_len0 = pci_len0;
	offset = QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(ahw->pci_func));
	qlcnic_get_ioaddr(ahw, offset);
1169 1170 1171 1172

	return 0;
}

M
Manish Chopra 已提交
1173 1174
static bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter,
					 int index)
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
{
	struct pci_dev *pdev = adapter->pdev;
	unsigned short subsystem_vendor;
	bool ret = true;

	subsystem_vendor = pdev->subsystem_vendor;

	if (pdev->device == PCI_DEVICE_ID_QLOGIC_QLE824X ||
	    pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X) {
		if (qlcnic_boards[index].sub_vendor == subsystem_vendor &&
		    qlcnic_boards[index].sub_device == pdev->subsystem_device)
			ret = true;
		else
			ret = false;
	}

	return ret;
}

S
Sony Chacko 已提交
1194
static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name)
1195 1196 1197 1198 1199 1200
{
	struct pci_dev *pdev = adapter->pdev;
	int i, found = 0;

	for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) {
		if (qlcnic_boards[i].vendor == pdev->vendor &&
1201 1202 1203 1204
		    qlcnic_boards[i].device == pdev->device &&
		    qlcnic_validate_subsystem_id(adapter, i)) {
			found = 1;
			break;
1205 1206 1207 1208
		}
	}

	if (!found)
1209
		sprintf(name, "%pM Gigabit Ethernet", adapter->mac_addr);
1210 1211 1212
	else
		sprintf(name, "%pM: %s" , adapter->mac_addr,
			qlcnic_boards[i].short_name);
1213 1214 1215 1216 1217
}

static void
qlcnic_check_options(struct qlcnic_adapter *adapter)
{
1218
	int err;
1219
	u32 fw_major, fw_minor, fw_build, prev_fw_version;
1220
	struct pci_dev *pdev = adapter->pdev;
1221 1222
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	struct qlcnic_fw_dump *fw_dump = &ahw->fw_dump;
1223 1224

	prev_fw_version = adapter->fw_version;
1225

1226 1227 1228
	fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
	fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
	fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
1229 1230 1231

	adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);

1232 1233 1234 1235 1236 1237
	err = qlcnic_get_board_info(adapter);
	if (err) {
		dev_err(&pdev->dev, "Error getting board config info.\n");
		return;
	}
	if (ahw->op_mode != QLCNIC_NON_PRIV_FUNC) {
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
		if (fw_dump->tmpl_hdr == NULL ||
				adapter->fw_version > prev_fw_version) {
			if (fw_dump->tmpl_hdr)
				vfree(fw_dump->tmpl_hdr);
			if (!qlcnic_fw_cmd_get_minidump_temp(adapter))
				dev_info(&pdev->dev,
					"Supports FW dump capability\n");
		}
	}

S
Sony Chacko 已提交
1248 1249 1250
	dev_info(&pdev->dev, "Driver v%s, firmware v%d.%d.%d\n",
		 QLCNIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build);

A
Anirban Chakraborty 已提交
1251
	if (adapter->ahw->port_type == QLCNIC_XGBE) {
S
Sony Chacko 已提交
1252 1253 1254 1255 1256 1257 1258 1259
		if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
			adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF;
			adapter->max_rxd = MAX_RCV_DESCRIPTORS_VF;
		} else {
			adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;
			adapter->max_rxd = MAX_RCV_DESCRIPTORS_10G;
		}

1260
		adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
S
Sony Chacko 已提交
1261 1262
		adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;

A
Anirban Chakraborty 已提交
1263
	} else if (adapter->ahw->port_type == QLCNIC_GBE) {
1264 1265
		adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
		adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
S
Sony Chacko 已提交
1266 1267
		adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
		adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;
1268 1269
	}

1270
	adapter->ahw->msix_supported = !!qlcnic_use_msi_x;
1271 1272 1273

	adapter->num_txd = MAX_CMD_DESCRIPTORS;

1274
	adapter->max_rds_rings = MAX_RDS_RINGS;
1275 1276
}

1277 1278 1279 1280
static int
qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
{
	struct qlcnic_info nic_info;
1281
	int err = 0;
1282

1283
	memset(&nic_info, 0, sizeof(struct qlcnic_info));
A
Anirban Chakraborty 已提交
1284
	err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw->pci_func);
1285 1286 1287
	if (err)
		return err;

1288 1289 1290 1291 1292
	adapter->ahw->physical_port = (u8)nic_info.phys_port;
	adapter->ahw->switch_mode = nic_info.switch_mode;
	adapter->ahw->max_tx_ques = nic_info.max_tx_ques;
	adapter->ahw->max_rx_ques = nic_info.max_rx_ques;
	adapter->ahw->capabilities = nic_info.capabilities;
1293 1294 1295

	if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
		u32 temp;
1296 1297 1298
		temp = QLCRD32(adapter, CRB_FW_CAPABILITIES_2, &err);
		if (err == -EIO)
			return err;
1299
		adapter->ahw->extra_capability[0] = temp;
1300 1301
	} else {
		adapter->ahw->extra_capability[0] = 0;
1302
	}
1303

1304 1305
	adapter->ahw->max_mac_filters = nic_info.max_mac_filters;
	adapter->ahw->max_mtu = nic_info.max_mtu;
1306

1307
	if (adapter->ahw->capabilities & BIT_6) {
1308
		adapter->flags |= QLCNIC_ESWITCH_ENABLED;
1309 1310 1311 1312 1313 1314 1315 1316
		adapter->ahw->nic_mode = QLCNIC_VNIC_MODE;
		adapter->max_tx_rings = QLCNIC_MAX_HW_VNIC_TX_RINGS;
		adapter->max_sds_rings = QLCNIC_MAX_VNIC_SDS_RINGS;

		dev_info(&adapter->pdev->dev, "vNIC mode enabled.\n");
	} else {
		adapter->ahw->nic_mode = QLCNIC_DEFAULT_MODE;
		adapter->max_tx_rings = QLCNIC_MAX_HW_TX_RINGS;
1317
		adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
1318
		adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
1319
	}
1320 1321 1322 1323

	return err;
}

1324 1325
void qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
			    struct qlcnic_esw_func_cfg *esw_cfg)
1326 1327 1328 1329 1330 1331
{
	if (esw_cfg->discard_tagged)
		adapter->flags &= ~QLCNIC_TAGGING_ENABLED;
	else
		adapter->flags |= QLCNIC_TAGGING_ENABLED;

1332 1333 1334 1335 1336 1337 1338
	if (esw_cfg->vlan_id) {
		adapter->rx_pvid = esw_cfg->vlan_id;
		adapter->tx_pvid = esw_cfg->vlan_id;
	} else {
		adapter->rx_pvid = 0;
		adapter->tx_pvid = 0;
	}
1339 1340
}

1341
static int
1342
qlcnic_vlan_rx_add(struct net_device *netdev, __be16 proto, u16 vid)
1343 1344
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356
	int err;

	if (qlcnic_sriov_vf_check(adapter)) {
		err = qlcnic_sriov_cfg_vf_guest_vlan(adapter, vid, 1);
		if (err) {
			netdev_err(netdev,
				   "Cannot add VLAN filter for VLAN id %d, err=%d",
				   vid, err);
			return err;
		}
	}

1357
	set_bit(vid, adapter->vlans);
1358
	return 0;
1359 1360
}

1361
static int
1362
qlcnic_vlan_rx_del(struct net_device *netdev, __be16 proto, u16 vid)
1363 1364
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375
	int err;

	if (qlcnic_sriov_vf_check(adapter)) {
		err = qlcnic_sriov_cfg_vf_guest_vlan(adapter, vid, 0);
		if (err) {
			netdev_err(netdev,
				   "Cannot delete VLAN filter for VLAN id %d, err=%d",
				   vid, err);
			return err;
		}
	}
1376 1377 1378

	qlcnic_restore_indev_addr(netdev, NETDEV_DOWN);
	clear_bit(vid, adapter->vlans);
1379
	return 0;
1380 1381
}

1382 1383
void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
				      struct qlcnic_esw_func_cfg *esw_cfg)
1384
{
1385 1386
	adapter->flags &= ~(QLCNIC_MACSPOOF | QLCNIC_MAC_OVERRIDE_DISABLED |
				QLCNIC_PROMISC_DISABLED);
1387 1388 1389

	if (esw_cfg->mac_anti_spoof)
		adapter->flags |= QLCNIC_MACSPOOF;
S
Sony Chacko 已提交
1390

1391 1392 1393
	if (!esw_cfg->mac_override)
		adapter->flags |= QLCNIC_MAC_OVERRIDE_DISABLED;

1394 1395
	if (!esw_cfg->promisc_mode)
		adapter->flags |= QLCNIC_PROMISC_DISABLED;
1396 1397
}

1398
int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
1399 1400 1401 1402 1403 1404
{
	struct qlcnic_esw_func_cfg esw_cfg;

	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
		return 0;

A
Anirban Chakraborty 已提交
1405
	esw_cfg.pci_func = adapter->ahw->pci_func;
1406 1407
	if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg))
			return -EIO;
1408
	qlcnic_set_vlan_config(adapter, &esw_cfg);
1409
	qlcnic_set_eswitch_port_features(adapter, &esw_cfg);
1410
	qlcnic_set_netdev_features(adapter, &esw_cfg);
1411 1412 1413 1414

	return 0;
}

1415 1416
void qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
				struct qlcnic_esw_func_cfg *esw_cfg)
1417 1418
{
	struct net_device *netdev = adapter->netdev;
S
Sony Chacko 已提交
1419 1420 1421

	if (qlcnic_83xx_check(adapter))
		return;
1422

1423 1424 1425 1426
	adapter->offload_flags = esw_cfg->offload_flags;
	adapter->flags |= QLCNIC_APP_CHANGED_FLAGS;
	netdev_update_features(netdev);
	adapter->flags &= ~QLCNIC_APP_CHANGED_FLAGS;
1427 1428
}

1429 1430 1431 1432 1433 1434
static int
qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
{
	u32 op_mode, priv_level;
	int err = 0;

1435 1436 1437 1438
	err = qlcnic_initialize_nic(adapter);
	if (err)
		return err;

1439 1440 1441
	if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED)
		return 0;

S
Sony Chacko 已提交
1442
	op_mode = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE);
A
Anirban Chakraborty 已提交
1443
	priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
1444 1445 1446 1447

	if (op_mode == QLC_DEV_DRV_DEFAULT)
		priv_level = QLCNIC_MGMT_FUNC;
	else
A
Anirban Chakraborty 已提交
1448
		priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
1449

1450
	if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
1451
		if (priv_level == QLCNIC_MGMT_FUNC) {
1452
			adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
1453 1454 1455 1456 1457 1458 1459
			err = qlcnic_init_pci_info(adapter);
			if (err)
				return err;
			/* Set privilege level for other functions */
			qlcnic_set_function_modes(adapter);
			dev_info(&adapter->pdev->dev,
				"HAL Version: %d, Management function\n",
1460
				 adapter->ahw->fw_hal_version);
1461
		} else if (priv_level == QLCNIC_PRIV_FUNC) {
1462
			adapter->ahw->op_mode = QLCNIC_PRIV_FUNC;
1463 1464
			dev_info(&adapter->pdev->dev,
				"HAL Version: %d, Privileged function\n",
1465
				 adapter->ahw->fw_hal_version);
1466
		}
1467 1468
	} else {
		adapter->ahw->nic_mode = QLCNIC_DEFAULT_MODE;
1469
	}
1470 1471 1472 1473 1474 1475

	adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;

	return err;
}

1476
int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
1477 1478 1479 1480 1481
{
	struct qlcnic_esw_func_cfg esw_cfg;
	struct qlcnic_npar_info *npar;
	u8 i;

1482
	if (adapter->need_fw_reset)
1483 1484
		return 0;

1485
	for (i = 0; i < adapter->ahw->total_nic_func; i++) {
1486 1487 1488
		if (!adapter->npars[i].eswitch_status)
			continue;

1489
		memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg));
1490
		esw_cfg.pci_func = adapter->npars[i].pci_func;
1491
		esw_cfg.mac_override = BIT_0;
1492
		esw_cfg.promisc_mode = BIT_0;
1493 1494 1495 1496 1497
		if (qlcnic_82xx_check(adapter)) {
			esw_cfg.offload_flags = BIT_0;
			if (QLCNIC_IS_TSO_CAPABLE(adapter))
				esw_cfg.offload_flags |= (BIT_1 | BIT_2);
		}
1498 1499 1500 1501
		if (qlcnic_config_switch_port(adapter, &esw_cfg))
			return -EIO;
		npar = &adapter->npars[i];
		npar->pvid = esw_cfg.vlan_id;
1502
		npar->mac_override = esw_cfg.mac_override;
1503 1504 1505 1506 1507 1508 1509 1510 1511
		npar->mac_anti_spoof = esw_cfg.mac_anti_spoof;
		npar->discard_tagged = esw_cfg.discard_tagged;
		npar->promisc_mode = esw_cfg.promisc_mode;
		npar->offload_flags = esw_cfg.offload_flags;
	}

	return 0;
}

S
Sony Chacko 已提交
1512

1513 1514 1515 1516 1517 1518 1519 1520
static int
qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter,
			struct qlcnic_npar_info *npar, int pci_func)
{
	struct qlcnic_esw_func_cfg esw_cfg;
	esw_cfg.op_mode = QLCNIC_PORT_DEFAULTS;
	esw_cfg.pci_func = pci_func;
	esw_cfg.vlan_id = npar->pvid;
1521
	esw_cfg.mac_override = npar->mac_override;
1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535
	esw_cfg.discard_tagged = npar->discard_tagged;
	esw_cfg.mac_anti_spoof = npar->mac_anti_spoof;
	esw_cfg.offload_flags = npar->offload_flags;
	esw_cfg.promisc_mode = npar->promisc_mode;
	if (qlcnic_config_switch_port(adapter, &esw_cfg))
		return -EIO;

	esw_cfg.op_mode = QLCNIC_ADD_VLAN;
	if (qlcnic_config_switch_port(adapter, &esw_cfg))
		return -EIO;

	return 0;
}

1536
int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
1537
{
1538
	int i, err;
1539 1540
	struct qlcnic_npar_info *npar;
	struct qlcnic_info nic_info;
1541
	u8 pci_func;
1542

1543 1544 1545
	if (qlcnic_82xx_check(adapter))
		if (!adapter->need_fw_reset)
			return 0;
1546

1547
	/* Set the NPAR config data after FW reset */
1548
	for (i = 0; i < adapter->ahw->total_nic_func; i++) {
1549
		npar = &adapter->npars[i];
1550
		pci_func = npar->pci_func;
1551 1552 1553
		if (!adapter->npars[i].eswitch_status)
			continue;

1554
		memset(&nic_info, 0, sizeof(struct qlcnic_info));
S
Sony Chacko 已提交
1555
		err = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
1556 1557 1558 1559 1560 1561 1562
		if (err)
			return err;
		nic_info.min_tx_bw = npar->min_bw;
		nic_info.max_tx_bw = npar->max_bw;
		err = qlcnic_set_nic_info(adapter, &nic_info);
		if (err)
			return err;
1563

1564 1565
		if (npar->enable_pm) {
			err = qlcnic_config_port_mirroring(adapter,
1566 1567
							   npar->dest_npar, 1,
							   pci_func);
1568 1569
			if (err)
				return err;
1570
		}
1571
		err = qlcnic_reset_eswitch_config(adapter, npar, pci_func);
1572 1573
		if (err)
			return err;
1574
	}
1575
	return 0;
1576 1577
}

A
Amit Kumar Salecha 已提交
1578 1579 1580 1581 1582
static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter)
{
	u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO;
	u32 npar_state;

1583
	if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
A
Amit Kumar Salecha 已提交
1584 1585
		return 0;

1586 1587
	npar_state = QLC_SHARED_REG_RD32(adapter,
					 QLCNIC_CRB_DEV_NPAR_STATE);
A
Amit Kumar Salecha 已提交
1588 1589
	while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) {
		msleep(1000);
1590 1591
		npar_state = QLC_SHARED_REG_RD32(adapter,
						 QLCNIC_CRB_DEV_NPAR_STATE);
A
Amit Kumar Salecha 已提交
1592 1593 1594
	}
	if (!npar_opt_timeo) {
		dev_err(&adapter->pdev->dev,
1595
			"Waiting for NPAR state to operational timeout\n");
A
Amit Kumar Salecha 已提交
1596 1597 1598 1599 1600
		return -EIO;
	}
	return 0;
}

1601 1602 1603 1604 1605 1606
static int
qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter)
{
	int err;

	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
1607
	    adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622
		return 0;

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

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

	qlcnic_dev_set_npar_ready(adapter);

	return err;
}

1623
static int qlcnic_82xx_start_firmware(struct qlcnic_adapter *adapter)
1624
{
1625
	int err;
1626

1627 1628 1629 1630
	err = qlcnic_can_start_firmware(adapter);
	if (err < 0)
		return err;
	else if (!err)
1631
		goto check_fw_status;
1632

1633
	if (qlcnic_load_fw_file)
1634
		qlcnic_request_firmware(adapter);
S
schacko 已提交
1635
	else {
S
Sony Chacko 已提交
1636 1637
		err = qlcnic_check_flash_fw_ver(adapter);
		if (err)
S
schacko 已提交
1638 1639
			goto err_out;

1640
		adapter->ahw->fw_type = QLCNIC_FLASH_ROMIMAGE;
S
schacko 已提交
1641
	}
1642 1643 1644

	err = qlcnic_need_fw_reset(adapter);
	if (err == 0)
1645
		goto check_fw_status;
1646

1647 1648 1649
	err = qlcnic_pinit_from_rom(adapter);
	if (err)
		goto err_out;
1650 1651 1652 1653 1654 1655

	err = qlcnic_load_firmware(adapter);
	if (err)
		goto err_out;

	qlcnic_release_firmware(adapter);
1656
	QLCWR32(adapter, CRB_DRIVER_VERSION, QLCNIC_DRIVER_VERSION);
1657

1658 1659
check_fw_status:
	err = qlcnic_check_fw_status(adapter);
1660 1661 1662
	if (err)
		goto err_out;

1663
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
1664
	qlcnic_idc_debug_info(adapter, 1);
1665 1666 1667 1668 1669 1670
	err = qlcnic_check_eswitch_mode(adapter);
	if (err) {
		dev_err(&adapter->pdev->dev,
			"Memory allocation failed for eswitch\n");
		goto err_out;
	}
1671 1672 1673 1674 1675
	err = qlcnic_set_mgmt_operations(adapter);
	if (err)
		goto err_out;

	qlcnic_check_options(adapter);
1676 1677
	adapter->need_fw_reset = 0;

1678 1679
	qlcnic_release_firmware(adapter);
	return 0;
1680 1681

err_out:
1682
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
1683
	dev_err(&adapter->pdev->dev, "Device state set to failed\n");
1684

1685 1686 1687 1688 1689 1690 1691 1692 1693
	qlcnic_release_firmware(adapter);
	return err;
}

static int
qlcnic_request_irq(struct qlcnic_adapter *adapter)
{
	irq_handler_t handler;
	struct qlcnic_host_sds_ring *sds_ring;
S
Sony Chacko 已提交
1694
	struct qlcnic_host_tx_ring *tx_ring;
1695
	int err, ring, num_sds_rings;
1696 1697 1698

	unsigned long flags = 0;
	struct net_device *netdev = adapter->netdev;
A
Anirban Chakraborty 已提交
1699
	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1700

1701
	if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
S
Sony Chacko 已提交
1702 1703
		if (qlcnic_82xx_check(adapter))
			handler = qlcnic_tmp_intr;
1704 1705
		else
			handler = qlcnic_83xx_tmp_intr;
1706 1707 1708 1709 1710 1711 1712 1713 1714 1715
		if (!QLCNIC_IS_MSI_FAMILY(adapter))
			flags |= IRQF_SHARED;

	} else {
		if (adapter->flags & QLCNIC_MSIX_ENABLED)
			handler = qlcnic_msix_intr;
		else if (adapter->flags & QLCNIC_MSI_ENABLED)
			handler = qlcnic_msi_intr;
		else {
			flags |= IRQF_SHARED;
1716 1717 1718 1719
			if (qlcnic_82xx_check(adapter))
				handler = qlcnic_intr;
			else
				handler = qlcnic_83xx_intr;
1720
		}
1721 1722 1723
	}
	adapter->irq = netdev->irq;

S
Sony Chacko 已提交
1724
	if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) {
1725 1726 1727
		if (qlcnic_82xx_check(adapter) ||
		    (qlcnic_83xx_check(adapter) &&
		     (adapter->flags & QLCNIC_MSIX_ENABLED))) {
1728
			num_sds_rings = adapter->drv_sds_rings;
1729
			for (ring = 0; ring < num_sds_rings; ring++) {
1730
				sds_ring = &recv_ctx->sds_rings[ring];
1731
				if (qlcnic_82xx_check(adapter) &&
1732
				    !qlcnic_check_multi_tx(adapter) &&
1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
				    (ring == (num_sds_rings - 1))) {
					if (!(adapter->flags &
					      QLCNIC_MSIX_ENABLED))
						snprintf(sds_ring->name,
							 sizeof(sds_ring->name),
							 "qlcnic");
					else
						snprintf(sds_ring->name,
							 sizeof(sds_ring->name),
							 "%s-tx-0-rx-%d",
							 netdev->name, ring);
				} else {
1745 1746
					snprintf(sds_ring->name,
						 sizeof(sds_ring->name),
1747
						 "%s-rx-%d",
1748
						 netdev->name, ring);
1749
				}
1750 1751 1752 1753 1754
				err = request_irq(sds_ring->irq, handler, flags,
						  sds_ring->name, sds_ring);
				if (err)
					return err;
			}
S
Sony Chacko 已提交
1755
		}
1756 1757 1758 1759 1760
		if ((qlcnic_82xx_check(adapter) &&
		     qlcnic_check_multi_tx(adapter)) ||
		    (qlcnic_83xx_check(adapter) &&
		     (adapter->flags & QLCNIC_MSIX_ENABLED) &&
		     !(adapter->flags & QLCNIC_TX_INTR_SHARED))) {
S
Sony Chacko 已提交
1761
			handler = qlcnic_msix_tx_intr;
1762
			for (ring = 0; ring < adapter->drv_tx_rings;
S
Sony Chacko 已提交
1763 1764
			     ring++) {
				tx_ring = &adapter->tx_ring[ring];
1765
				snprintf(tx_ring->name, sizeof(tx_ring->name),
1766
					 "%s-tx-%d", netdev->name, ring);
S
Sony Chacko 已提交
1767 1768 1769 1770 1771 1772
				err = request_irq(tx_ring->irq, handler, flags,
						  tx_ring->name, tx_ring);
				if (err)
					return err;
			}
		}
1773 1774 1775 1776 1777 1778 1779 1780 1781
	}
	return 0;
}

static void
qlcnic_free_irq(struct qlcnic_adapter *adapter)
{
	int ring;
	struct qlcnic_host_sds_ring *sds_ring;
S
Sony Chacko 已提交
1782
	struct qlcnic_host_tx_ring *tx_ring;
1783

A
Anirban Chakraborty 已提交
1784
	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1785

S
Sony Chacko 已提交
1786
	if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) {
1787 1788 1789
		if (qlcnic_82xx_check(adapter) ||
		    (qlcnic_83xx_check(adapter) &&
		     (adapter->flags & QLCNIC_MSIX_ENABLED))) {
1790
			for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
1791 1792 1793
				sds_ring = &recv_ctx->sds_rings[ring];
				free_irq(sds_ring->irq, sds_ring);
			}
S
Sony Chacko 已提交
1794
		}
1795 1796 1797 1798
		if ((qlcnic_83xx_check(adapter) &&
		     !(adapter->flags & QLCNIC_TX_INTR_SHARED)) ||
		    (qlcnic_82xx_check(adapter) &&
		     qlcnic_check_multi_tx(adapter))) {
1799
			for (ring = 0; ring < adapter->drv_tx_rings;
S
Sony Chacko 已提交
1800 1801 1802 1803 1804 1805
			     ring++) {
				tx_ring = &adapter->tx_ring[ring];
				if (tx_ring->irq)
					free_irq(tx_ring->irq, tx_ring);
			}
		}
1806 1807 1808
	}
}

1809 1810 1811 1812 1813
static void qlcnic_get_lro_mss_capability(struct qlcnic_adapter *adapter)
{
	u32 capab = 0;

	if (qlcnic_82xx_check(adapter)) {
1814
		if (adapter->ahw->extra_capability[0] &
1815 1816 1817 1818 1819 1820 1821 1822 1823
		    QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG)
			adapter->flags |= QLCNIC_FW_LRO_MSS_CAP;
	} else {
		capab = adapter->ahw->capabilities;
		if (QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(capab))
			adapter->flags |= QLCNIC_FW_LRO_MSS_CAP;
	}
}

1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850
static int qlcnic_config_def_intr_coalesce(struct qlcnic_adapter *adapter)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	int err;

	/* Initialize interrupt coalesce parameters */
	ahw->coal.flag = QLCNIC_INTR_DEFAULT;

	if (qlcnic_83xx_check(adapter)) {
		ahw->coal.type = QLCNIC_INTR_COAL_TYPE_RX_TX;
		ahw->coal.tx_time_us = QLCNIC_DEF_INTR_COALESCE_TX_TIME_US;
		ahw->coal.tx_packets = QLCNIC_DEF_INTR_COALESCE_TX_PACKETS;
		ahw->coal.rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
		ahw->coal.rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;

		err = qlcnic_83xx_set_rx_tx_intr_coal(adapter);
	} else {
		ahw->coal.type = QLCNIC_INTR_COAL_TYPE_RX;
		ahw->coal.rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
		ahw->coal.rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;

		err = qlcnic_82xx_set_rx_coalesce(adapter);
	}

	return err;
}

S
Sony Chacko 已提交
1851
int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
1852
{
1853 1854 1855
	int ring;
	struct qlcnic_host_rds_ring *rds_ring;

1856 1857 1858
	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
		return -EIO;

1859 1860
	if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
		return 0;
1861

1862 1863
	if (qlcnic_set_eswitch_port_config(adapter))
		return -EIO;
1864

1865
	qlcnic_get_lro_mss_capability(adapter);
1866

1867 1868 1869 1870
	if (qlcnic_fw_create_ctx(adapter))
		return -EIO;

	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
A
Anirban Chakraborty 已提交
1871
		rds_ring = &adapter->recv_ctx->rds_rings[ring];
S
Sony Chacko 已提交
1872
		qlcnic_post_rx_buffers(adapter, rds_ring, ring);
1873 1874
	}

1875 1876 1877
	qlcnic_set_multi(netdev);
	qlcnic_fw_cmd_set_mtu(adapter, netdev->mtu);

A
Anirban Chakraborty 已提交
1878
	adapter->ahw->linkup = 0;
1879

1880
	if (adapter->drv_sds_rings > 1)
1881 1882
		qlcnic_config_rss(adapter, 1);

1883
	qlcnic_config_def_intr_coalesce(adapter);
1884

1885
	if (netdev->features & NETIF_F_LRO)
1886 1887
		qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED);

1888
	set_bit(__QLCNIC_DEV_UP, &adapter->state);
1889 1890 1891 1892
	qlcnic_napi_enable(adapter);

	qlcnic_linkevent_request(adapter, 1);

1893
	adapter->ahw->reset_context = 0;
R
Rajesh Borundia 已提交
1894
	netif_tx_start_all_queues(netdev);
1895 1896 1897
	return 0;
}

1898
int qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909
{
	int err = 0;

	rtnl_lock();
	if (netif_running(netdev))
		err = __qlcnic_up(adapter, netdev);
	rtnl_unlock();

	return err;
}

S
Sony Chacko 已提交
1910
void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
1911
{
1912 1913
	int ring;

1914 1915 1916 1917 1918 1919 1920 1921
	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
		return;

	if (!test_and_clear_bit(__QLCNIC_DEV_UP, &adapter->state))
		return;

	smp_mb();
	netif_carrier_off(netdev);
1922
	adapter->ahw->linkup = 0;
1923 1924 1925 1926
	netif_tx_disable(netdev);

	qlcnic_free_mac_list(adapter);

1927 1928 1929
	if (adapter->fhash.fnum)
		qlcnic_delete_lb_filters(adapter);

1930
	qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE);
1931 1932
	if (qlcnic_sriov_vf_check(adapter))
		qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
1933 1934 1935

	qlcnic_napi_disable(adapter);

1936
	qlcnic_fw_destroy_ctx(adapter);
1937
	adapter->flags &= ~QLCNIC_FW_LRO_MSS_CAP;
1938 1939

	qlcnic_reset_rx_buffers_list(adapter);
1940

1941
	for (ring = 0; ring < adapter->drv_tx_rings; ring++)
1942
		qlcnic_release_tx_buffers(adapter, &adapter->tx_ring[ring]);
1943 1944 1945 1946
}

/* Usage: During suspend and firmware recovery module */

1947
void qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
1948 1949 1950 1951 1952 1953 1954 1955
{
	rtnl_lock();
	if (netif_running(netdev))
		__qlcnic_down(adapter, netdev);
	rtnl_unlock();

}

S
Sony Chacko 已提交
1956
int
1957 1958 1959 1960
qlcnic_attach(struct qlcnic_adapter *adapter)
{
	struct net_device *netdev = adapter->netdev;
	struct pci_dev *pdev = adapter->pdev;
1961
	int err;
1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972

	if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC)
		return 0;

	err = qlcnic_napi_add(adapter, netdev);
	if (err)
		return err;

	err = qlcnic_alloc_sw_resources(adapter);
	if (err) {
		dev_err(&pdev->dev, "Error in setting sw resources\n");
1973
		goto err_out_napi_del;
1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984
	}

	err = qlcnic_alloc_hw_resources(adapter);
	if (err) {
		dev_err(&pdev->dev, "Error in setting hw resources\n");
		goto err_out_free_sw;
	}

	err = qlcnic_request_irq(adapter);
	if (err) {
		dev_err(&pdev->dev, "failed to setup interrupt\n");
1985
		goto err_out_free_hw;
1986 1987 1988 1989
	}

	qlcnic_create_sysfs_entries(adapter);

1990
#ifdef CONFIG_QLCNIC_VXLAN
1991 1992
	if (qlcnic_encap_rx_offload(adapter))
		vxlan_get_rx_port(netdev);
1993
#endif
1994

1995 1996 1997
	adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC;
	return 0;

1998
err_out_free_hw:
1999 2000 2001
	qlcnic_free_hw_resources(adapter);
err_out_free_sw:
	qlcnic_free_sw_resources(adapter);
2002 2003
err_out_napi_del:
	qlcnic_napi_del(adapter);
2004 2005 2006
	return err;
}

S
Sony Chacko 已提交
2007
void qlcnic_detach(struct qlcnic_adapter *adapter)
2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022
{
	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
		return;

	qlcnic_remove_sysfs_entries(adapter);

	qlcnic_free_hw_resources(adapter);
	qlcnic_release_rx_buffers(adapter);
	qlcnic_free_irq(adapter);
	qlcnic_napi_del(adapter);
	qlcnic_free_sw_resources(adapter);

	adapter->is_up = 0;
}

2023
void qlcnic_diag_free_res(struct net_device *netdev, int drv_sds_rings)
2024 2025 2026
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct qlcnic_host_sds_ring *sds_ring;
2027
	int drv_tx_rings = adapter->drv_tx_rings;
2028 2029
	int ring;

2030
	clear_bit(__QLCNIC_DEV_UP, &adapter->state);
2031
	if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
2032
		for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
A
Anirban Chakraborty 已提交
2033
			sds_ring = &adapter->recv_ctx->sds_rings[ring];
M
Manish chopra 已提交
2034
			qlcnic_disable_sds_intr(adapter, sds_ring);
2035
		}
2036 2037
	}

2038 2039
	qlcnic_fw_destroy_ctx(adapter);

2040 2041
	qlcnic_detach(adapter);

2042
	adapter->ahw->diag_test = 0;
2043 2044
	adapter->drv_sds_rings = drv_sds_rings;
	adapter->drv_tx_rings = drv_tx_rings;
2045 2046

	if (qlcnic_attach(adapter))
2047
		goto out;
2048 2049 2050

	if (netif_running(netdev))
		__qlcnic_up(adapter, netdev);
2051
out:
2052 2053 2054
	netif_device_attach(netdev);
}

A
Anirban Chakraborty 已提交
2055 2056
static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
{
2057
	struct qlcnic_hardware_context *ahw = adapter->ahw;
A
Anirban Chakraborty 已提交
2058
	int err = 0;
2059

A
Anirban Chakraborty 已提交
2060 2061 2062 2063
	adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context),
				GFP_KERNEL);
	if (!adapter->recv_ctx) {
		err = -ENOMEM;
A
Anirban Chakraborty 已提交
2064
		goto err_out;
A
Anirban Chakraborty 已提交
2065
	}
2066

2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078
	if (qlcnic_83xx_check(adapter)) {
		ahw->coal.type = QLCNIC_INTR_COAL_TYPE_RX_TX;
		ahw->coal.tx_time_us = QLCNIC_DEF_INTR_COALESCE_TX_TIME_US;
		ahw->coal.tx_packets = QLCNIC_DEF_INTR_COALESCE_TX_PACKETS;
		ahw->coal.rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
		ahw->coal.rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;
	} else {
		ahw->coal.type = QLCNIC_INTR_COAL_TYPE_RX;
		ahw->coal.rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
		ahw->coal.rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;
	}

S
Sony Chacko 已提交
2079 2080
	/* clear stats */
	memset(&adapter->stats, 0, sizeof(adapter->stats));
A
Anirban Chakraborty 已提交
2081 2082 2083 2084 2085 2086 2087 2088 2089
err_out:
	return err;
}

static void qlcnic_free_adapter_resources(struct qlcnic_adapter *adapter)
{
	kfree(adapter->recv_ctx);
	adapter->recv_ctx = NULL;

A
Anirban Chakraborty 已提交
2090 2091 2092 2093
	if (adapter->ahw->fw_dump.tmpl_hdr) {
		vfree(adapter->ahw->fw_dump.tmpl_hdr);
		adapter->ahw->fw_dump.tmpl_hdr = NULL;
	}
S
Sony Chacko 已提交
2094

2095
	kfree(adapter->ahw->reset.buff);
S
Sony Chacko 已提交
2096
	adapter->ahw->fw_dump.tmpl_hdr = NULL;
A
Anirban Chakraborty 已提交
2097 2098
}

2099 2100 2101 2102
int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct qlcnic_host_sds_ring *sds_ring;
2103
	struct qlcnic_host_rds_ring *rds_ring;
2104 2105 2106 2107 2108 2109 2110 2111 2112 2113
	int ring;
	int ret;

	netif_device_detach(netdev);

	if (netif_running(netdev))
		__qlcnic_down(adapter, netdev);

	qlcnic_detach(adapter);

2114
	adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
2115
	adapter->ahw->diag_test = test;
S
Sony Chacko 已提交
2116
	adapter->ahw->linkup = 0;
2117 2118

	ret = qlcnic_attach(adapter);
2119 2120
	if (ret) {
		netif_device_attach(netdev);
2121
		return ret;
2122
	}
2123

2124 2125 2126
	ret = qlcnic_fw_create_ctx(adapter);
	if (ret) {
		qlcnic_detach(adapter);
2127
		netif_device_attach(netdev);
2128 2129 2130 2131
		return ret;
	}

	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
A
Anirban Chakraborty 已提交
2132
		rds_ring = &adapter->recv_ctx->rds_rings[ring];
S
Sony Chacko 已提交
2133
		qlcnic_post_rx_buffers(adapter, rds_ring, ring);
2134 2135
	}

2136
	if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
2137
		for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
A
Anirban Chakraborty 已提交
2138
			sds_ring = &adapter->recv_ctx->sds_rings[ring];
M
Manish chopra 已提交
2139
			qlcnic_enable_sds_intr(adapter, sds_ring);
2140
		}
2141
	}
2142

2143
	if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
2144 2145 2146 2147
		adapter->ahw->loopback_state = 0;
		qlcnic_linkevent_request(adapter, 1);
	}

2148
	set_bit(__QLCNIC_DEV_UP, &adapter->state);
2149 2150 2151 2152

	return 0;
}

2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170
/* Reset context in hardware only */
static int
qlcnic_reset_hw_context(struct qlcnic_adapter *adapter)
{
	struct net_device *netdev = adapter->netdev;

	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
		return -EBUSY;

	netif_device_detach(netdev);

	qlcnic_down(adapter, netdev);

	qlcnic_up(adapter, netdev);

	netif_device_attach(netdev);

	clear_bit(__QLCNIC_RESETTING, &adapter->state);
2171
	netdev_info(adapter->netdev, "%s: soft reset complete\n", __func__);
2172 2173 2174
	return 0;
}

2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194
int
qlcnic_reset_context(struct qlcnic_adapter *adapter)
{
	int err = 0;
	struct net_device *netdev = adapter->netdev;

	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
		return -EBUSY;

	if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) {

		netif_device_detach(netdev);

		if (netif_running(netdev))
			__qlcnic_down(adapter, netdev);

		qlcnic_detach(adapter);

		if (netif_running(netdev)) {
			err = qlcnic_attach(adapter);
A
Anirban Chakraborty 已提交
2195
			if (!err) {
2196
				__qlcnic_up(adapter, netdev);
A
Anirban Chakraborty 已提交
2197 2198
				qlcnic_restore_indev_addr(netdev, NETDEV_UP);
			}
2199 2200 2201 2202 2203 2204 2205 2206 2207
		}

		netif_device_attach(netdev);
	}

	clear_bit(__QLCNIC_RESETTING, &adapter->state);
	return err;
}

2208
static void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
2209 2210
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
2211
	u16 act_pci_fn = ahw->total_nic_func;
2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223
	u16 count;

	ahw->max_mc_count = QLCNIC_MAX_MC_COUNT;
	if (act_pci_fn <= 2)
		count = (QLCNIC_MAX_UC_COUNT - QLCNIC_MAX_MC_COUNT) /
			 act_pci_fn;
	else
		count = (QLCNIC_LB_MAX_FILTERS - QLCNIC_MAX_MC_COUNT) /
			 act_pci_fn;
	ahw->max_uc_count = count;
}

R
Rajesh Borundia 已提交
2224
int
S
Sony Chacko 已提交
2225 2226
qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
		    int pci_using_dac)
2227 2228 2229 2230
{
	int err;
	struct pci_dev *pdev = adapter->pdev;

S
Sony Chacko 已提交
2231
	adapter->rx_csum = 1;
2232
	adapter->ahw->mc_enabled = 0;
2233
	qlcnic_set_mac_filter_count(adapter);
2234 2235

	netdev->netdev_ops	   = &qlcnic_netdev_ops;
S
Sony Chacko 已提交
2236
	netdev->watchdog_timeo     = QLCNIC_WATCHDOG_TIMEOUTVALUE * HZ;
2237 2238 2239

	qlcnic_change_mtu(netdev, netdev->mtu);

2240 2241 2242 2243
	if (qlcnic_sriov_vf_check(adapter))
		SET_ETHTOOL_OPS(netdev, &qlcnic_sriov_vf_ethtool_ops);
	else
		SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
2244

2245
	netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
S
Sony Chacko 已提交
2246
			     NETIF_F_IPV6_CSUM | NETIF_F_GRO |
2247
			     NETIF_F_HW_VLAN_CTAG_RX);
S
Sony Chacko 已提交
2248 2249
	netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
				  NETIF_F_IPV6_CSUM);
2250

S
Sony Chacko 已提交
2251 2252 2253 2254
	if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
		netdev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
		netdev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
	}
2255

S
Sony Chacko 已提交
2256 2257 2258 2259
	if (pci_using_dac) {
		netdev->features |= NETIF_F_HIGHDMA;
		netdev->vlan_features |= NETIF_F_HIGHDMA;
	}
2260

S
Sony Chacko 已提交
2261
	if (qlcnic_vlan_tx_check(adapter))
2262
		netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX);
2263

2264 2265 2266
	if (qlcnic_sriov_vf_check(adapter))
		netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;

S
Sony Chacko 已提交
2267 2268
	if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
		netdev->features |= NETIF_F_LRO;
2269

2270 2271 2272 2273 2274 2275 2276 2277 2278 2279
	if (qlcnic_encap_tx_offload(adapter)) {
		netdev->features |= NETIF_F_GSO_UDP_TUNNEL;

		/* encapsulation Tx offload supported by Adapter */
		netdev->hw_enc_features = NETIF_F_IP_CSUM        |
					  NETIF_F_GSO_UDP_TUNNEL |
					  NETIF_F_TSO            |
					  NETIF_F_TSO6;
	}

2280 2281 2282
	if (qlcnic_encap_rx_offload(adapter))
		netdev->hw_enc_features |= NETIF_F_RXCSUM;

2283
	netdev->hw_features = netdev->features;
2284
	netdev->priv_flags |= IFF_UNICAST_FLT;
2285 2286
	netdev->irq = adapter->msix_entries[0].vector;

2287 2288 2289
	err = qlcnic_set_real_num_queues(adapter, netdev);
	if (err)
		return err;
2290

2291 2292 2293 2294 2295 2296
	err = register_netdev(netdev);
	if (err) {
		dev_err(&pdev->dev, "failed to register net device\n");
		return err;
	}

2297
	qlcnic_dcb_init_dcbnl_ops(adapter->dcb);
2298

2299 2300 2301
	return 0;
}

S
Sony Chacko 已提交
2302
static int qlcnic_set_dma_mask(struct pci_dev *pdev, int *pci_using_dac)
2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317
{
	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
			!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
		*pci_using_dac = 1;
	else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) &&
			!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
		*pci_using_dac = 0;
	else {
		dev_err(&pdev->dev, "Unable to set DMA mask, aborting\n");
		return -EIO;
	}

	return 0;
}

S
Sony Chacko 已提交
2318 2319 2320 2321 2322
void qlcnic_free_tx_rings(struct qlcnic_adapter *adapter)
{
	int ring;
	struct qlcnic_host_tx_ring *tx_ring;

2323
	for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
S
Sony Chacko 已提交
2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336
		tx_ring = &adapter->tx_ring[ring];
		if (tx_ring && tx_ring->cmd_buf_arr != NULL) {
			vfree(tx_ring->cmd_buf_arr);
			tx_ring->cmd_buf_arr = NULL;
		}
	}
	if (adapter->tx_ring != NULL)
		kfree(adapter->tx_ring);
}

int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter,
			  struct net_device *netdev)
{
2337
	int ring, vector, index;
S
Sony Chacko 已提交
2338 2339 2340
	struct qlcnic_host_tx_ring *tx_ring;
	struct qlcnic_cmd_buffer *cmd_buf_arr;

2341
	tx_ring = kcalloc(adapter->drv_tx_rings,
2342 2343
			  sizeof(struct qlcnic_host_tx_ring), GFP_KERNEL);
	if (tx_ring == NULL)
S
Sony Chacko 已提交
2344
		return -ENOMEM;
2345

S
Sony Chacko 已提交
2346 2347
	adapter->tx_ring = tx_ring;

2348
	for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
S
Sony Chacko 已提交
2349 2350 2351 2352 2353 2354 2355 2356 2357 2358
		tx_ring = &adapter->tx_ring[ring];
		tx_ring->num_desc = adapter->num_txd;
		tx_ring->txq = netdev_get_tx_queue(netdev, ring);
		cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring));
		if (cmd_buf_arr == NULL) {
			qlcnic_free_tx_rings(adapter);
			return -ENOMEM;
		}
		memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
		tx_ring->cmd_buf_arr = cmd_buf_arr;
2359
		spin_lock_init(&tx_ring->tx_clean_lock);
S
Sony Chacko 已提交
2360 2361
	}

2362 2363
	if (qlcnic_83xx_check(adapter) ||
	    (qlcnic_82xx_check(adapter) && qlcnic_check_multi_tx(adapter))) {
2364
		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
S
Sony Chacko 已提交
2365 2366 2367
			tx_ring = &adapter->tx_ring[ring];
			tx_ring->adapter = adapter;
			if (adapter->flags & QLCNIC_MSIX_ENABLED) {
2368
				index = adapter->drv_sds_rings + ring;
S
Sony Chacko 已提交
2369 2370 2371 2372 2373
				vector = adapter->msix_entries[index].vector;
				tx_ring->irq = vector;
			}
		}
	}
2374

S
Sony Chacko 已提交
2375 2376 2377
	return 0;
}

2378 2379 2380 2381 2382 2383 2384 2385 2386 2387
void qlcnic_set_drv_version(struct qlcnic_adapter *adapter)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	u32 fw_cmd = 0;

	if (qlcnic_82xx_check(adapter))
		fw_cmd = QLCNIC_CMD_82XX_SET_DRV_VER;
	else if (qlcnic_83xx_check(adapter))
		fw_cmd = QLCNIC_CMD_83XX_SET_DRV_VER;

2388
	if (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_SET_DRV_VER)
2389 2390 2391
		qlcnic_fw_cmd_set_drv_version(adapter, fw_cmd);
}

B
Bill Pemberton 已提交
2392
static int
2393 2394 2395 2396
qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct net_device *netdev = NULL;
	struct qlcnic_adapter *adapter = NULL;
2397
	struct qlcnic_hardware_context *ahw;
S
Sony Chacko 已提交
2398
	int err, pci_using_dac = -1;
2399
	char board_name[QLCNIC_MAX_BOARD_NAME_LEN + 19]; /* MAC + ": " + name */
2400 2401 2402 2403 2404 2405 2406 2407 2408 2409

	err = pci_enable_device(pdev);
	if (err)
		return err;

	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
		err = -ENODEV;
		goto err_out_disable_pdev;
	}

2410 2411 2412 2413
	err = qlcnic_set_dma_mask(pdev, &pci_using_dac);
	if (err)
		goto err_out_disable_pdev;

2414 2415 2416 2417 2418
	err = pci_request_regions(pdev, qlcnic_driver_name);
	if (err)
		goto err_out_disable_pdev;

	pci_set_master(pdev);
S
Sucheta Chakraborty 已提交
2419
	pci_enable_pcie_error_reporting(pdev);
2420

2421
	ahw = kzalloc(sizeof(struct qlcnic_hardware_context), GFP_KERNEL);
2422 2423
	if (!ahw) {
		err = -ENOMEM;
2424
		goto err_out_free_res;
2425
	}
2426

R
Rajesh Borundia 已提交
2427 2428
	switch (ent->device) {
	case PCI_DEVICE_ID_QLOGIC_QLE824X:
2429
		ahw->hw_ops = &qlcnic_hw_ops;
R
Rajesh Borundia 已提交
2430 2431 2432
		ahw->reg_tbl = (u32 *) qlcnic_reg_tbl;
		break;
	case PCI_DEVICE_ID_QLOGIC_QLE834X:
2433
	case PCI_DEVICE_ID_QLOGIC_QLE844X:
S
Sony Chacko 已提交
2434
		qlcnic_83xx_register_map(ahw);
R
Rajesh Borundia 已提交
2435 2436
		break;
	case PCI_DEVICE_ID_QLOGIC_VF_QLE834X:
2437
	case PCI_DEVICE_ID_QLOGIC_VF_QLE844X:
R
Rajesh Borundia 已提交
2438 2439 2440
		qlcnic_sriov_vf_register_map(ahw);
		break;
	default:
S
Sony Chacko 已提交
2441
		goto err_out_free_hw_res;
2442 2443 2444 2445 2446 2447
	}

	err = qlcnic_setup_pci_map(pdev, ahw);
	if (err)
		goto err_out_free_hw_res;

2448 2449
	netdev = alloc_etherdev_mq(sizeof(struct qlcnic_adapter),
				   QLCNIC_MAX_TX_RINGS);
2450 2451
	if (!netdev) {
		err = -ENOMEM;
2452
		goto err_out_iounmap;
2453 2454 2455 2456 2457 2458 2459
	}

	SET_NETDEV_DEV(netdev, &pdev->dev);

	adapter = netdev_priv(netdev);
	adapter->netdev  = netdev;
	adapter->pdev    = pdev;
S
Sony Chacko 已提交
2460 2461 2462 2463
	adapter->ahw = ahw;

	adapter->qlcnic_wq = create_singlethread_workqueue("qlcnic");
	if (adapter->qlcnic_wq == NULL) {
2464
		err = -ENOMEM;
S
Sony Chacko 已提交
2465 2466 2467
		dev_err(&pdev->dev, "Failed to create workqueue\n");
		goto err_out_free_netdev;
	}
2468

2469 2470
	err = qlcnic_alloc_adapter_resources(adapter);
	if (err)
2471
		goto err_out_free_wq;
A
Anirban Chakraborty 已提交
2472 2473

	adapter->dev_rst_time = jiffies;
2474 2475
	ahw->revision_id = pdev->revision;
	ahw->max_vnic_func = qlcnic_get_vnic_func_count(adapter);
2476 2477 2478 2479
	if (qlcnic_mac_learn == FDB_MAC_LEARN)
		adapter->fdb_mac_learn = true;
	else if (qlcnic_mac_learn == DRV_MAC_LEARN)
		adapter->drv_mac_learn = true;
2480

A
Anirban Chakraborty 已提交
2481 2482
	rwlock_init(&adapter->ahw->crb_lock);
	mutex_init(&adapter->ahw->mem_lock);
2483 2484 2485

	INIT_LIST_HEAD(&adapter->mac_list);

2486 2487
	qlcnic_register_dcb(adapter);

2488
	if (qlcnic_82xx_check(adapter)) {
S
Sony Chacko 已提交
2489
		qlcnic_check_vf(adapter, ent);
2490 2491 2492
		adapter->portnum = adapter->ahw->pci_func;
		err = qlcnic_start_firmware(adapter);
		if (err) {
2493 2494 2495
			dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n"
				"\t\tIf reboot doesn't help, try flashing the card\n");
			goto err_out_maintenance_mode;
2496
		}
2497

2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510
		/* compute and set default and max tx/sds rings */
		if (adapter->ahw->msix_supported) {
			if (qlcnic_check_multi_tx_capability(adapter) == 1)
				qlcnic_set_tx_ring_count(adapter,
							 QLCNIC_SINGLE_RING);
			else
				qlcnic_set_tx_ring_count(adapter,
							 QLCNIC_DEF_TX_RINGS);
			qlcnic_set_sds_ring_count(adapter,
						  QLCNIC_DEF_SDS_RINGS);
		} else {
			qlcnic_set_tx_ring_count(adapter, QLCNIC_SINGLE_RING);
			qlcnic_set_sds_ring_count(adapter, QLCNIC_SINGLE_RING);
2511 2512
		}

2513 2514 2515
		err = qlcnic_setup_idc_param(adapter);
		if (err)
			goto err_out_free_hw;
2516

2517
		adapter->flags |= QLCNIC_NEED_FLR;
2518

S
Sony Chacko 已提交
2519 2520 2521
	} else if (qlcnic_83xx_check(adapter)) {
		qlcnic_83xx_check_vf(adapter, ent);
		adapter->portnum = adapter->ahw->pci_func;
R
Rajesh Borundia 已提交
2522
		err = qlcnic_83xx_init(adapter, pci_using_dac);
2523
		if (err) {
2524 2525
			switch (err) {
			case -ENOTRECOVERABLE:
2526 2527
				dev_err(&pdev->dev, "Adapter initialization failed due to a faulty hardware\n");
				dev_err(&pdev->dev, "Please replace the adapter with new one and return the faulty adapter for repair\n");
2528 2529 2530 2531
				goto err_out_free_hw;
			case -ENOMEM:
				dev_err(&pdev->dev, "Adapter initialization failed. Please reboot\n");
				goto err_out_free_hw;
2532 2533 2534
			case -EOPNOTSUPP:
				dev_err(&pdev->dev, "Adapter initialization failed\n");
				goto err_out_free_hw;
2535
			default:
2536
				dev_err(&pdev->dev, "Adapter initialization failed. Driver will load in maintenance mode to recover the adapter using the application\n");
2537 2538
				goto err_out_maintenance_mode;
			}
2539
		}
2540

R
Rajesh Borundia 已提交
2541 2542
		if (qlcnic_sriov_vf_check(adapter))
			return 0;
S
Sony Chacko 已提交
2543 2544 2545 2546
	} else {
		dev_err(&pdev->dev,
			"%s: failed. Please Reboot\n", __func__);
		goto err_out_free_hw;
2547
	}
2548

R
Rajesh Borundia 已提交
2549 2550 2551
	if (qlcnic_read_mac_addr(adapter))
		dev_warn(&pdev->dev, "failed to read mac addr\n");

2552 2553
	qlcnic_read_phys_port_id(adapter);

R
Rajesh Borundia 已提交
2554
	if (adapter->portnum == 0) {
S
Sony Chacko 已提交
2555
		qlcnic_get_board_name(adapter, board_name);
S
Sony Chacko 已提交
2556

R
Rajesh Borundia 已提交
2557
		pr_info("%s: %s Board Chip rev 0x%x\n",
S
Sony Chacko 已提交
2558 2559
			module_name(THIS_MODULE),
			board_name, adapter->ahw->revision_id);
R
Rajesh Borundia 已提交
2560
	}
2561 2562 2563 2564

	if (qlcnic_83xx_check(adapter) && !qlcnic_use_msi_x &&
	    !!qlcnic_use_msi)
		dev_warn(&pdev->dev,
2565
			 "Device does not support MSI interrupts\n");
2566

2567
	if (qlcnic_82xx_check(adapter)) {
2568 2569
		qlcnic_dcb_enable(adapter->dcb);
		qlcnic_dcb_get_info(adapter->dcb);
2570
		err = qlcnic_setup_intr(adapter);
2571

2572 2573
		if (err) {
			dev_err(&pdev->dev, "Failed to setup interrupt\n");
S
Sony Chacko 已提交
2574
			goto err_out_disable_msi;
2575
		}
S
Sony Chacko 已提交
2576
	}
2577

2578 2579 2580 2581
	err = qlcnic_get_act_pci_func(adapter);
	if (err)
		goto err_out_disable_mbx_intr;

2582
	err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac);
2583
	if (err)
2584
		goto err_out_disable_mbx_intr;
2585

2586 2587
	if (adapter->portnum == 0)
		qlcnic_set_drv_version(adapter);
2588

2589 2590
	pci_set_drvdata(pdev, adapter);

2591 2592 2593
	if (qlcnic_82xx_check(adapter))
		qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
				     FW_POLL_DELAY);
2594

A
Anirban Chakraborty 已提交
2595
	switch (adapter->ahw->port_type) {
2596 2597 2598 2599 2600 2601 2602 2603 2604 2605
	case QLCNIC_GBE:
		dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
				adapter->netdev->name);
		break;
	case QLCNIC_XGBE:
		dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
				adapter->netdev->name);
		break;
	}

2606
	if (adapter->drv_mac_learn)
2607 2608
		qlcnic_alloc_lb_filters_mem(adapter);

2609
	qlcnic_add_sysfs(adapter);
2610
	qlcnic_register_hwmon_dev(adapter);
2611 2612
	return 0;

2613
err_out_disable_mbx_intr:
2614
	if (qlcnic_83xx_check(adapter))
S
Sony Chacko 已提交
2615
		qlcnic_83xx_free_mbx_intr(adapter);
2616

2617 2618
err_out_disable_msi:
	qlcnic_teardown_intr(adapter);
2619
	qlcnic_cancel_idc_work(adapter);
2620
	qlcnic_clr_all_drv_state(adapter, 0);
2621

A
Anirban Chakraborty 已提交
2622 2623 2624
err_out_free_hw:
	qlcnic_free_adapter_resources(adapter);

2625 2626 2627
err_out_free_wq:
	destroy_workqueue(adapter->qlcnic_wq);

2628 2629 2630
err_out_free_netdev:
	free_netdev(netdev);

2631
err_out_iounmap:
2632
	qlcnic_cleanup_pci_map(ahw);
2633 2634 2635 2636

err_out_free_hw_res:
	kfree(ahw);

2637 2638 2639 2640 2641 2642
err_out_free_res:
	pci_release_regions(pdev);

err_out_disable_pdev:
	pci_disable_device(pdev);
	return err;
2643 2644

err_out_maintenance_mode:
2645
	set_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state);
2646 2647
	netdev->netdev_ops = &qlcnic_netdev_failed_ops;
	SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_failed_ops);
2648 2649 2650 2651 2652 2653 2654
	ahw->port_type = QLCNIC_XGBE;

	if (qlcnic_83xx_check(adapter))
		adapter->tgt_status_reg = NULL;
	else
		ahw->board_type = QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS;

2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666
	err = register_netdev(netdev);

	if (err) {
		dev_err(&pdev->dev, "Failed to register net device\n");
		qlcnic_clr_all_drv_state(adapter, 0);
		goto err_out_free_hw;
	}

	pci_set_drvdata(pdev, adapter);
	qlcnic_add_sysfs(adapter);

	return 0;
2667 2668
}

B
Bill Pemberton 已提交
2669
static void qlcnic_remove(struct pci_dev *pdev)
2670 2671 2672
{
	struct qlcnic_adapter *adapter;
	struct net_device *netdev;
S
Sony Chacko 已提交
2673
	struct qlcnic_hardware_context *ahw;
2674 2675 2676 2677 2678 2679 2680

	adapter = pci_get_drvdata(pdev);
	if (adapter == NULL)
		return;

	netdev = adapter->netdev;

S
Sony Chacko 已提交
2681
	qlcnic_cancel_idc_work(adapter);
2682
	qlcnic_sriov_pf_disable(adapter);
S
Sony Chacko 已提交
2683
	ahw = adapter->ahw;
2684 2685

	unregister_netdev(netdev);
2686
	qlcnic_sriov_cleanup(adapter);
2687

S
Sony Chacko 已提交
2688
	if (qlcnic_83xx_check(adapter)) {
2689
		qlcnic_83xx_initialize_nic(adapter, 0);
2690
		cancel_delayed_work_sync(&adapter->idc_aen_work);
2691 2692 2693
		qlcnic_83xx_free_mbx_intr(adapter);
		qlcnic_83xx_detach_mailbox_work(adapter);
		qlcnic_83xx_free_mailbox(ahw->mailbox);
2694
		kfree(ahw->fw_info);
S
Sony Chacko 已提交
2695 2696
	}

2697 2698
	qlcnic_dcb_free(adapter->dcb);

2699 2700
	qlcnic_detach(adapter);

2701 2702 2703 2704 2705
	if (adapter->npars != NULL)
		kfree(adapter->npars);
	if (adapter->eswitch != NULL)
		kfree(adapter->eswitch);

2706 2707
	if (qlcnic_82xx_check(adapter))
		qlcnic_clr_all_drv_state(adapter, 0);
2708 2709 2710

	clear_bit(__QLCNIC_RESETTING, &adapter->state);

2711 2712
	qlcnic_free_lb_filters_mem(adapter);

2713 2714
	qlcnic_teardown_intr(adapter);

S
Sony Chacko 已提交
2715
	qlcnic_remove_sysfs(adapter);
2716

2717 2718
	qlcnic_unregister_hwmon_dev(adapter);

2719
	qlcnic_cleanup_pci_map(adapter->ahw);
2720 2721 2722

	qlcnic_release_firmware(adapter);

S
Sucheta Chakraborty 已提交
2723
	pci_disable_pcie_error_reporting(pdev);
2724 2725 2726
	pci_release_regions(pdev);
	pci_disable_device(pdev);

S
Sony Chacko 已提交
2727 2728 2729 2730
	if (adapter->qlcnic_wq) {
		destroy_workqueue(adapter->qlcnic_wq);
		adapter->qlcnic_wq = NULL;
	}
2731

A
Anirban Chakraborty 已提交
2732
	qlcnic_free_adapter_resources(adapter);
S
Sony Chacko 已提交
2733
	kfree(ahw);
2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745
	free_netdev(netdev);
}

static void qlcnic_shutdown(struct pci_dev *pdev)
{
	if (__qlcnic_shutdown(pdev))
		return;

	pci_disable_device(pdev);
}

#ifdef CONFIG_PM
2746
static int qlcnic_suspend(struct pci_dev *pdev, pm_message_t state)
2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757
{
	int retval;

	retval = __qlcnic_shutdown(pdev);
	if (retval)
		return retval;

	pci_set_power_state(pdev, pci_choose_state(pdev, state));
	return 0;
}

2758
static int qlcnic_resume(struct pci_dev *pdev)
2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770
{
	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
	int err;

	err = pci_enable_device(pdev);
	if (err)
		return err;

	pci_set_power_state(pdev, PCI_D0);
	pci_set_master(pdev);
	pci_restore_state(pdev);

2771
	return  __qlcnic_resume(adapter);
2772 2773 2774 2775 2776 2777 2778 2779
}
#endif

static int qlcnic_open(struct net_device *netdev)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	int err;

2780 2781 2782
	if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
		netdev_err(netdev, "%s: Device is in non-operational state\n",
			   __func__);
2783 2784 2785 2786

		return -EIO;
	}

2787 2788
	netif_carrier_off(netdev);

2789 2790 2791 2792 2793 2794
	err = qlcnic_attach(adapter);
	if (err)
		return err;

	err = __qlcnic_up(adapter, netdev);
	if (err)
R
Rajesh Borundia 已提交
2795
		qlcnic_detach(adapter);
2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807

	return err;
}

/*
 * qlcnic_close - Disables a network interface entry point
 */
static int qlcnic_close(struct net_device *netdev)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);

	__qlcnic_down(adapter, netdev);
S
Sony Chacko 已提交
2808

2809 2810 2811
	return 0;
}

2812
void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
2813 2814 2815
{
	void *head;
	int i;
S
Sony Chacko 已提交
2816 2817 2818
	struct net_device *netdev = adapter->netdev;
	u32 filter_size = 0;
	u16 act_pci_func = 0;
2819

2820
	if (adapter->fhash.fmax && adapter->fhash.fhead)
2821 2822
		return;

2823
	act_pci_func = adapter->ahw->total_nic_func;
2824
	spin_lock_init(&adapter->mac_learn_lock);
2825
	spin_lock_init(&adapter->rx_mac_learn_lock);
2826

S
Sony Chacko 已提交
2827 2828 2829 2830 2831 2832 2833 2834 2835
	if (qlcnic_82xx_check(adapter)) {
		filter_size = QLCNIC_LB_MAX_FILTERS;
		adapter->fhash.fbucket_size = QLCNIC_LB_BUCKET_SIZE;
	} else {
		filter_size = QLC_83XX_LB_MAX_FILTERS;
		adapter->fhash.fbucket_size = QLC_83XX_LB_BUCKET_SIZE;
	}

	head = kcalloc(adapter->fhash.fbucket_size,
2836
		       sizeof(struct hlist_head), GFP_ATOMIC);
S
Sony Chacko 已提交
2837

2838 2839 2840
	if (!head)
		return;

S
Sony Chacko 已提交
2841
	adapter->fhash.fmax = (filter_size / act_pci_func);
2842
	adapter->fhash.fhead = head;
2843

S
Sony Chacko 已提交
2844 2845 2846 2847
	netdev_info(netdev, "active nic func = %d, mac filter size=%d\n",
		    act_pci_func, adapter->fhash.fmax);

	for (i = 0; i < adapter->fhash.fbucket_size; i++)
2848
		INIT_HLIST_HEAD(&adapter->fhash.fhead[i]);
2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862

	adapter->rx_fhash.fbucket_size = adapter->fhash.fbucket_size;

	head = kcalloc(adapter->rx_fhash.fbucket_size,
		       sizeof(struct hlist_head), GFP_ATOMIC);

	if (!head)
		return;

	adapter->rx_fhash.fmax = (filter_size / act_pci_func);
	adapter->rx_fhash.fhead = head;

	for (i = 0; i < adapter->rx_fhash.fbucket_size; i++)
		INIT_HLIST_HEAD(&adapter->rx_fhash.fhead[i]);
2863 2864 2865 2866 2867 2868 2869 2870 2871
}

static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
{
	if (adapter->fhash.fmax && adapter->fhash.fhead)
		kfree(adapter->fhash.fhead);

	adapter->fhash.fhead = NULL;
	adapter->fhash.fmax = 0;
2872 2873 2874 2875 2876 2877

	if (adapter->rx_fhash.fmax && adapter->rx_fhash.fhead)
		kfree(adapter->rx_fhash.fhead);

	adapter->rx_fhash.fmax = 0;
	adapter->rx_fhash.fhead = NULL;
2878 2879
}

2880
int qlcnic_check_temp(struct qlcnic_adapter *adapter)
2881 2882
{
	struct net_device *netdev = adapter->netdev;
2883
	u32 temp_state, temp_val, temp = 0;
2884 2885
	int rv = 0;

S
Sony Chacko 已提交
2886 2887 2888
	if (qlcnic_83xx_check(adapter))
		temp = QLCRDX(adapter->ahw, QLC_83XX_ASIC_TEMP);

2889
	if (qlcnic_82xx_check(adapter))
2890
		temp = QLC_SHARED_REG_RD32(adapter, QLCNIC_ASIC_TEMP);
2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901

	temp_state = qlcnic_get_temp_state(temp);
	temp_val = qlcnic_get_temp_val(temp);

	if (temp_state == QLCNIC_TEMP_PANIC) {
		dev_err(&netdev->dev,
		       "Device temperature %d degrees C exceeds"
		       " maximum allowed. Hardware has been shut down.\n",
		       temp_val);
		rv = 1;
	} else if (temp_state == QLCNIC_TEMP_WARN) {
2902
		if (adapter->ahw->temp == QLCNIC_TEMP_NORMAL) {
2903 2904 2905 2906 2907 2908 2909
			dev_err(&netdev->dev,
			       "Device temperature %d degrees C "
			       "exceeds operating range."
			       " Immediate action needed.\n",
			       temp_val);
		}
	} else {
2910
		if (adapter->ahw->temp == QLCNIC_TEMP_WARN) {
2911 2912 2913 2914 2915
			dev_info(&netdev->dev,
			       "Device temperature is now %d degrees C"
			       " in normal range.\n", temp_val);
		}
	}
2916
	adapter->ahw->temp = temp_state;
2917 2918 2919
	return rv;
}

2920
static inline void dump_tx_ring_desc(struct qlcnic_host_tx_ring *tx_ring)
2921
{
2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936
	int i;
	struct cmd_desc_type0 *tx_desc_info;

	for (i = 0; i < tx_ring->num_desc; i++) {
		tx_desc_info = &tx_ring->desc_head[i];
		pr_info("TX Desc: %d\n", i);
		print_hex_dump(KERN_INFO, "TX: ", DUMP_PREFIX_OFFSET, 16, 1,
			       &tx_ring->desc_head[i],
			       sizeof(struct cmd_desc_type0), true);
	}
}

static void qlcnic_dump_tx_rings(struct qlcnic_adapter *adapter)
{
	struct net_device *netdev = adapter->netdev;
2937 2938
	struct qlcnic_host_tx_ring *tx_ring;
	int ring;
2939

2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971
	if (!netdev || !netif_running(netdev))
		return;

	for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
		tx_ring = &adapter->tx_ring[ring];
		netdev_info(netdev, "Tx ring=%d Context Id=0x%x\n",
			    ring, tx_ring->ctx_id);
		netdev_info(netdev,
			    "xmit_finished=%llu, xmit_called=%llu, xmit_on=%llu, xmit_off=%llu\n",
			    tx_ring->tx_stats.xmit_finished,
			    tx_ring->tx_stats.xmit_called,
			    tx_ring->tx_stats.xmit_on,
			    tx_ring->tx_stats.xmit_off);
		netdev_info(netdev,
			    "crb_intr_mask=%d, hw_producer=%d, sw_producer=%d sw_consumer=%d, hw_consumer=%d\n",
			    readl(tx_ring->crb_intr_mask),
			    readl(tx_ring->crb_cmd_producer),
			    tx_ring->producer, tx_ring->sw_consumer,
			    le32_to_cpu(*(tx_ring->hw_consumer)));

		netdev_info(netdev, "Total desc=%d, Available desc=%d\n",
			    tx_ring->num_desc, qlcnic_tx_avail(tx_ring));

		if (netif_msg_tx_done(adapter->ahw))
			dump_tx_ring_desc(tx_ring);
	}
}

static void qlcnic_tx_timeout(struct net_device *netdev)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);

2972 2973 2974
	if (test_bit(__QLCNIC_RESETTING, &adapter->state))
		return;

2975 2976 2977 2978 2979 2980 2981 2982 2983
	if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) {
		netdev_info(netdev, "Tx timeout, reset the adapter.\n");
		if (qlcnic_82xx_check(adapter))
			adapter->need_fw_reset = 1;
		else if (qlcnic_83xx_check(adapter))
			qlcnic_83xx_idc_request_reset(adapter,
						      QLCNIC_FORCE_FW_DUMP_KEY);
	} else {
		netdev_info(netdev, "Tx timeout, reset adapter context.\n");
2984
		qlcnic_dump_tx_rings(adapter);
2985
		adapter->ahw->reset_context = 1;
2986
	}
2987 2988 2989 2990 2991 2992 2993
}

static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct net_device_stats *stats = &netdev->stats;

M
Manish Chopra 已提交
2994 2995 2996
	if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
		qlcnic_update_stats(adapter);

2997 2998
	stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
	stats->tx_packets = adapter->stats.xmitfinished;
2999
	stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
3000 3001 3002 3003 3004 3005 3006
	stats->tx_bytes = adapter->stats.txbytes;
	stats->rx_dropped = adapter->stats.rxdropped;
	stats->tx_dropped = adapter->stats.txdropped;

	return stats;
}

3007
static irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
3008 3009 3010 3011 3012
{
	u32 status;

	status = readl(adapter->isr_int_vec);

3013
	if (!(status & adapter->ahw->int_vec_bit))
3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025
		return IRQ_NONE;

	/* check interrupt state machine, to be sure */
	status = readl(adapter->crb_int_state_reg);
	if (!ISR_LEGACY_INT_TRIGGERED(status))
		return IRQ_NONE;

	writel(0xffffffff, adapter->tgt_status_reg);
	/* read twice to ensure write is flushed */
	readl(adapter->isr_int_vec);
	readl(adapter->isr_int_vec);

3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044
	return IRQ_HANDLED;
}

static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
{
	struct qlcnic_host_sds_ring *sds_ring = data;
	struct qlcnic_adapter *adapter = sds_ring->adapter;

	if (adapter->flags & QLCNIC_MSIX_ENABLED)
		goto done;
	else if (adapter->flags & QLCNIC_MSI_ENABLED) {
		writel(0xffffffff, adapter->tgt_status_reg);
		goto done;
	}

	if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
		return IRQ_NONE;

done:
3045
	adapter->ahw->diag_cnt++;
M
Manish chopra 已提交
3046
	qlcnic_enable_sds_intr(adapter, sds_ring);
3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057
	return IRQ_HANDLED;
}

static irqreturn_t qlcnic_intr(int irq, void *data)
{
	struct qlcnic_host_sds_ring *sds_ring = data;
	struct qlcnic_adapter *adapter = sds_ring->adapter;

	if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
		return IRQ_NONE;

3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082
	napi_schedule(&sds_ring->napi);

	return IRQ_HANDLED;
}

static irqreturn_t qlcnic_msi_intr(int irq, void *data)
{
	struct qlcnic_host_sds_ring *sds_ring = data;
	struct qlcnic_adapter *adapter = sds_ring->adapter;

	/* clear interrupt */
	writel(0xffffffff, adapter->tgt_status_reg);

	napi_schedule(&sds_ring->napi);
	return IRQ_HANDLED;
}

static irqreturn_t qlcnic_msix_intr(int irq, void *data)
{
	struct qlcnic_host_sds_ring *sds_ring = data;

	napi_schedule(&sds_ring->napi);
	return IRQ_HANDLED;
}

S
Sony Chacko 已提交
3083 3084 3085 3086 3087 3088 3089 3090
static irqreturn_t qlcnic_msix_tx_intr(int irq, void *data)
{
	struct qlcnic_host_tx_ring *tx_ring = data;

	napi_schedule(&tx_ring->napi);
	return IRQ_HANDLED;
}

3091 3092 3093 3094
#ifdef CONFIG_NET_POLL_CONTROLLER
static void qlcnic_poll_controller(struct net_device *netdev)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
3095 3096 3097 3098 3099 3100 3101 3102 3103
	struct qlcnic_host_sds_ring *sds_ring;
	struct qlcnic_recv_context *recv_ctx;
	struct qlcnic_host_tx_ring *tx_ring;
	int ring;

	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
		return;

	recv_ctx = adapter->recv_ctx;
Y
Yinglin Luan 已提交
3104

3105
	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
Y
Yinglin Luan 已提交
3106
		sds_ring = &recv_ctx->sds_rings[ring];
3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125
		qlcnic_disable_sds_intr(adapter, sds_ring);
		napi_schedule(&sds_ring->napi);
	}

	if (adapter->flags & QLCNIC_MSIX_ENABLED) {
		/* Only Multi-Tx queue capable devices need to
		 * schedule NAPI for TX rings
		 */
		if ((qlcnic_83xx_check(adapter) &&
		     (adapter->flags & QLCNIC_TX_INTR_SHARED)) ||
		    (qlcnic_82xx_check(adapter) &&
		     !qlcnic_check_multi_tx(adapter)))
			return;

		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
			tx_ring = &adapter->tx_ring[ring];
			qlcnic_disable_tx_intr(adapter, tx_ring);
			napi_schedule(&tx_ring->napi);
		}
Y
Yinglin Luan 已提交
3126
	}
3127 3128 3129
}
#endif

3130 3131 3132 3133 3134 3135 3136 3137 3138
static void
qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding)
{
	u32 val;

	val = adapter->portnum & 0xf;
	val |= encoding << 7;
	val |= (jiffies - adapter->dev_rst_time) << 8;

3139
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_SCRATCH, val);
3140 3141 3142
	adapter->dev_rst_time = jiffies;
}

3143 3144
static int
qlcnic_set_drv_state(struct qlcnic_adapter *adapter, u8 state)
3145 3146 3147 3148 3149 3150 3151
{
	u32  val;

	WARN_ON(state != QLCNIC_DEV_NEED_RESET &&
			state != QLCNIC_DEV_NEED_QUISCENT);

	if (qlcnic_api_lock(adapter))
3152
		return -EIO;
3153

3154
	val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
3155 3156

	if (state == QLCNIC_DEV_NEED_RESET)
3157
		QLC_DEV_SET_RST_RDY(val, adapter->portnum);
3158
	else if (state == QLCNIC_DEV_NEED_QUISCENT)
3159
		QLC_DEV_SET_QSCNT_RDY(val, adapter->portnum);
3160

3161
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val);
3162 3163

	qlcnic_api_unlock(adapter);
3164 3165

	return 0;
3166 3167
}

3168 3169 3170 3171 3172 3173 3174 3175
static int
qlcnic_clr_drv_state(struct qlcnic_adapter *adapter)
{
	u32  val;

	if (qlcnic_api_lock(adapter))
		return -EBUSY;

3176
	val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
3177
	QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum);
3178
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val);
3179 3180 3181 3182 3183 3184

	qlcnic_api_unlock(adapter);

	return 0;
}

3185
void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
3186 3187 3188 3189 3190 3191
{
	u32  val;

	if (qlcnic_api_lock(adapter))
		goto err;

3192
	val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
3193
	QLC_DEV_CLR_REF_CNT(val, adapter->portnum);
3194
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
3195

3196
	if (failed) {
3197 3198
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE,
				    QLCNIC_DEV_FAILED);
3199 3200 3201
		dev_info(&adapter->pdev->dev,
				"Device state set to Failed. Please Reboot\n");
	} else if (!(val & 0x11111111))
3202 3203
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE,
				    QLCNIC_DEV_COLD);
3204

3205
	val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
3206
	QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum);
3207
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val);
3208 3209 3210 3211

	qlcnic_api_unlock(adapter);
err:
	adapter->fw_fail_cnt = 0;
S
Sritej Velaga 已提交
3212
	adapter->flags &= ~QLCNIC_FW_HANG;
3213 3214 3215 3216
	clear_bit(__QLCNIC_START_FW, &adapter->state);
	clear_bit(__QLCNIC_RESETTING, &adapter->state);
}

3217
/* Grab api lock, before checking state */
3218 3219 3220
static int
qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
{
3221
	int act, state, active_mask;
3222
	struct qlcnic_hardware_context *ahw = adapter->ahw;
3223

3224 3225
	state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
	act = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
3226

3227
	if (adapter->flags & QLCNIC_FW_RESET_OWNER) {
3228
		active_mask = (~(1 << (ahw->pci_func * 4)));
3229 3230 3231
		act = act & active_mask;
	}

3232 3233 3234 3235 3236 3237 3238
	if (((state & 0x11111111) == (act & 0x11111111)) ||
			((act & 0x11111111) == ((state >> 1) & 0x11111111)))
		return 0;
	else
		return 1;
}

S
Sucheta Chakraborty 已提交
3239 3240
static int qlcnic_check_idc_ver(struct qlcnic_adapter *adapter)
{
3241
	u32 val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_IDC_VER);
S
Sucheta Chakraborty 已提交
3242 3243 3244 3245 3246 3247 3248 3249 3250

	if (val != QLCNIC_DRV_IDC_VER) {
		dev_warn(&adapter->pdev->dev, "IDC Version mismatch, driver's"
			" idc ver = %x; reqd = %x\n", QLCNIC_DRV_IDC_VER, val);
	}

	return 0;
}

3251 3252 3253 3254
static int
qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
{
	u32 val, prev_state;
3255
	u8 dev_init_timeo = adapter->dev_init_timeo;
3256
	u8 portnum = adapter->portnum;
S
Sucheta Chakraborty 已提交
3257
	u8 ret;
3258

3259 3260 3261
	if (test_and_clear_bit(__QLCNIC_START_FW, &adapter->state))
		return 1;

3262 3263 3264
	if (qlcnic_api_lock(adapter))
		return -1;

3265
	val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
3266 3267
	if (!(val & (1 << (portnum * 4)))) {
		QLC_DEV_SET_REF_CNT(val, portnum);
3268
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
3269 3270
	}

3271
	prev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3272
	QLCDB(adapter, HW, "Device state = %u\n", prev_state);
3273 3274 3275

	switch (prev_state) {
	case QLCNIC_DEV_COLD:
3276 3277 3278 3279
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE,
				    QLCNIC_DEV_INITIALIZING);
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_IDC_VER,
				    QLCNIC_DRV_IDC_VER);
3280
		qlcnic_idc_debug_info(adapter, 0);
3281 3282 3283 3284
		qlcnic_api_unlock(adapter);
		return 1;

	case QLCNIC_DEV_READY:
S
Sucheta Chakraborty 已提交
3285
		ret = qlcnic_check_idc_ver(adapter);
3286
		qlcnic_api_unlock(adapter);
S
Sucheta Chakraborty 已提交
3287
		return ret;
3288 3289

	case QLCNIC_DEV_NEED_RESET:
3290
		val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
3291
		QLC_DEV_SET_RST_RDY(val, portnum);
3292
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val);
3293 3294 3295
		break;

	case QLCNIC_DEV_NEED_QUISCENT:
3296
		val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
3297
		QLC_DEV_SET_QSCNT_RDY(val, portnum);
3298
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val);
3299 3300 3301
		break;

	case QLCNIC_DEV_FAILED:
3302
		dev_err(&adapter->pdev->dev, "Device in failed state.\n");
3303 3304
		qlcnic_api_unlock(adapter);
		return -1;
3305 3306 3307 3308

	case QLCNIC_DEV_INITIALIZING:
	case QLCNIC_DEV_QUISCENT:
		break;
3309 3310 3311
	}

	qlcnic_api_unlock(adapter);
3312 3313

	do {
3314
		msleep(1000);
3315
		prev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3316 3317 3318 3319

		if (prev_state == QLCNIC_DEV_QUISCENT)
			continue;
	} while ((prev_state != QLCNIC_DEV_READY) && --dev_init_timeo);
3320

3321 3322 3323
	if (!dev_init_timeo) {
		dev_err(&adapter->pdev->dev,
			"Waiting for device to initialize timeout\n");
3324
		return -1;
3325
	}
3326 3327 3328 3329

	if (qlcnic_api_lock(adapter))
		return -1;

3330
	val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
3331
	QLC_DEV_CLR_RST_QSCNT(val, portnum);
3332
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val);
3333

S
Sucheta Chakraborty 已提交
3334
	ret = qlcnic_check_idc_ver(adapter);
3335 3336
	qlcnic_api_unlock(adapter);

S
Sucheta Chakraborty 已提交
3337
	return ret;
3338 3339 3340 3341 3342 3343 3344
}

static void
qlcnic_fwinit_work(struct work_struct *work)
{
	struct qlcnic_adapter *adapter = container_of(work,
			struct qlcnic_adapter, fw_work.work);
3345
	u32 dev_state = 0xf;
S
Sritej Velaga 已提交
3346
	u32 val;
3347

3348 3349
	if (qlcnic_api_lock(adapter))
		goto err_ret;
3350

3351
	dev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3352 3353
	if (dev_state == QLCNIC_DEV_QUISCENT ||
	    dev_state == QLCNIC_DEV_NEED_QUISCENT) {
3354 3355 3356 3357 3358 3359
		qlcnic_api_unlock(adapter);
		qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
						FW_POLL_DELAY * 2);
		return;
	}

3360
	if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
3361 3362
		qlcnic_api_unlock(adapter);
		goto wait_npar;
3363 3364
	}

3365 3366 3367 3368 3369 3370 3371
	if (dev_state == QLCNIC_DEV_INITIALIZING ||
	    dev_state == QLCNIC_DEV_READY) {
		dev_info(&adapter->pdev->dev, "Detected state change from "
				"DEV_NEED_RESET, skipping ack check\n");
		goto skip_ack_check;
	}

3372
	if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
3373
		dev_info(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n",
3374 3375 3376 3377 3378 3379
					adapter->reset_ack_timeo);
		goto skip_ack_check;
	}

	if (!qlcnic_check_drv_state(adapter)) {
skip_ack_check:
3380
		dev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3381

3382
		if (dev_state == QLCNIC_DEV_NEED_RESET) {
3383 3384
			QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE,
					    QLCNIC_DEV_INITIALIZING);
3385 3386
			set_bit(__QLCNIC_START_FW, &adapter->state);
			QLCDB(adapter, DRV, "Restarting fw\n");
3387
			qlcnic_idc_debug_info(adapter, 0);
3388 3389
			val = QLC_SHARED_REG_RD32(adapter,
						  QLCNIC_CRB_DRV_STATE);
S
Sritej Velaga 已提交
3390
			QLC_DEV_SET_RST_RDY(val, adapter->portnum);
3391 3392
			QLC_SHARED_REG_WR32(adapter,
					    QLCNIC_CRB_DRV_STATE, val);
3393 3394
		}

3395 3396
		qlcnic_api_unlock(adapter);

3397
		rtnl_lock();
3398
		if (qlcnic_check_fw_dump_state(adapter) &&
S
Sritej Velaga 已提交
3399
		    (adapter->flags & QLCNIC_FW_RESET_OWNER)) {
3400 3401
			QLCDB(adapter, DRV, "Take FW dump\n");
			qlcnic_dump_fw(adapter);
S
Sritej Velaga 已提交
3402
			adapter->flags |= QLCNIC_FW_HANG;
3403
		}
3404
		rtnl_unlock();
S
Sritej Velaga 已提交
3405 3406

		adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
3407
		if (!adapter->nic_ops->start_firmware(adapter)) {
3408
			qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
3409
			adapter->fw_wait_cnt = 0;
3410 3411 3412 3413 3414
			return;
		}
		goto err_ret;
	}

3415
	qlcnic_api_unlock(adapter);
3416

3417
wait_npar:
3418
	dev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3419
	QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
3420

3421
	switch (dev_state) {
3422
	case QLCNIC_DEV_READY:
3423
		if (!qlcnic_start_firmware(adapter)) {
3424
			qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
3425
			adapter->fw_wait_cnt = 0;
3426 3427
			return;
		}
3428 3429 3430 3431 3432 3433
	case QLCNIC_DEV_FAILED:
		break;
	default:
		qlcnic_schedule_work(adapter,
			qlcnic_fwinit_work, FW_POLL_DELAY);
		return;
3434 3435 3436
	}

err_ret:
3437 3438
	dev_err(&adapter->pdev->dev, "Fwinit work failed state=%u "
		"fw_wait_cnt=%u\n", dev_state, adapter->fw_wait_cnt);
3439
	netif_device_attach(adapter->netdev);
3440
	qlcnic_clr_all_drv_state(adapter, 0);
3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452
}

static void
qlcnic_detach_work(struct work_struct *work)
{
	struct qlcnic_adapter *adapter = container_of(work,
			struct qlcnic_adapter, fw_work.work);
	struct net_device *netdev = adapter->netdev;
	u32 status;

	netif_device_detach(netdev);

3453 3454 3455 3456 3457 3458
	/* Dont grab rtnl lock during Quiscent mode */
	if (adapter->dev_state == QLCNIC_DEV_NEED_QUISCENT) {
		if (netif_running(netdev))
			__qlcnic_down(adapter, netdev);
	} else
		qlcnic_down(adapter, netdev);
3459

3460
	status = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS1);
3461

S
Sony Chacko 已提交
3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474
	if (status & QLCNIC_RCODE_FATAL_ERROR) {
		dev_err(&adapter->pdev->dev,
			"Detaching the device: peg halt status1=0x%x\n",
					status);

		if (QLCNIC_FWERROR_CODE(status) == QLCNIC_FWERROR_FAN_FAILURE) {
			dev_err(&adapter->pdev->dev,
			"On board active cooling fan failed. "
				"Device has been halted.\n");
			dev_err(&adapter->pdev->dev,
				"Replace the adapter.\n");
		}

3475
		goto err_ret;
S
Sony Chacko 已提交
3476
	}
3477

3478
	if (adapter->ahw->temp == QLCNIC_TEMP_PANIC) {
S
Sony Chacko 已提交
3479
		dev_err(&adapter->pdev->dev, "Detaching the device: temp=%d\n",
3480
			adapter->ahw->temp);
3481
		goto err_ret;
S
Sony Chacko 已提交
3482 3483
	}

3484 3485
	/* Dont ack if this instance is the reset owner */
	if (!(adapter->flags & QLCNIC_FW_RESET_OWNER)) {
S
Sony Chacko 已提交
3486 3487 3488 3489
		if (qlcnic_set_drv_state(adapter, adapter->dev_state)) {
			dev_err(&adapter->pdev->dev,
				"Failed to set driver state,"
					"detaching the device.\n");
3490
			goto err_ret;
S
Sony Chacko 已提交
3491
		}
3492
	}
3493 3494 3495 3496 3497 3498 3499 3500

	adapter->fw_wait_cnt = 0;

	qlcnic_schedule_work(adapter, qlcnic_fwinit_work, FW_POLL_DELAY);

	return;

err_ret:
3501
	netif_device_attach(netdev);
3502
	qlcnic_clr_all_drv_state(adapter, 1);
3503 3504
}

3505 3506 3507 3508 3509 3510
/*Transit NPAR state to NON Operational */
static void
qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter)
{
	u32 state;

3511
	state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
3512 3513 3514 3515 3516
	if (state == QLCNIC_DEV_NPAR_NON_OPER)
		return;

	if (qlcnic_api_lock(adapter))
		return;
3517 3518
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
			    QLCNIC_DEV_NPAR_NON_OPER);
3519 3520 3521
	qlcnic_api_unlock(adapter);
}

3522 3523
static void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *adapter,
					  u32 key)
3524
{
3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536
	u32 state, xg_val = 0, gb_val = 0;

	qlcnic_xg_set_xg0_mask(xg_val);
	qlcnic_xg_set_xg1_mask(xg_val);
	QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, xg_val);
	qlcnic_gb_set_gb0_mask(gb_val);
	qlcnic_gb_set_gb1_mask(gb_val);
	qlcnic_gb_set_gb2_mask(gb_val);
	qlcnic_gb_set_gb3_mask(gb_val);
	QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, gb_val);
	dev_info(&adapter->pdev->dev, "Pause control frames disabled"
				" on all ports\n");
3537
	adapter->need_fw_reset = 1;
S
Sony Chacko 已提交
3538

3539 3540 3541
	if (qlcnic_api_lock(adapter))
		return;

S
Sony Chacko 已提交
3542
	state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3543 3544 3545

	if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
		netdev_err(adapter->netdev, "%s: Device is in non-operational state\n",
3546 3547 3548 3549 3550
			   __func__);
		qlcnic_api_unlock(adapter);

		return;
	}
3551

3552
	if (state == QLCNIC_DEV_READY) {
S
Sony Chacko 已提交
3553 3554
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE,
				    QLCNIC_DEV_NEED_RESET);
3555
		adapter->flags |= QLCNIC_FW_RESET_OWNER;
3556
		QLCDB(adapter, DRV, "NEED_RESET state set\n");
3557
		qlcnic_idc_debug_info(adapter, 0);
3558 3559
	}

S
Sony Chacko 已提交
3560 3561
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
			    QLCNIC_DEV_NPAR_NON_OPER);
3562 3563 3564
	qlcnic_api_unlock(adapter);
}

3565 3566 3567 3568 3569 3570 3571
/* Transit to NPAR READY state from NPAR NOT READY state */
static void
qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
{
	if (qlcnic_api_lock(adapter))
		return;

3572 3573
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
			    QLCNIC_DEV_NPAR_OPER);
3574
	QLCDB(adapter, DRV, "NPAR operational state set\n");
3575 3576 3577 3578

	qlcnic_api_unlock(adapter);
}

S
Sony Chacko 已提交
3579 3580
void qlcnic_schedule_work(struct qlcnic_adapter *adapter,
			  work_func_t func, int delay)
3581
{
S
Sucheta Chakraborty 已提交
3582 3583 3584
	if (test_bit(__QLCNIC_AER, &adapter->state))
		return;

3585
	INIT_DELAYED_WORK(&adapter->fw_work, func);
S
Sony Chacko 已提交
3586 3587
	queue_delayed_work(adapter->qlcnic_wq, &adapter->fw_work,
			   round_jiffies_relative(delay));
3588 3589 3590 3591 3592 3593 3594 3595
}

static void
qlcnic_attach_work(struct work_struct *work)
{
	struct qlcnic_adapter *adapter = container_of(work,
				struct qlcnic_adapter, fw_work.work);
	struct net_device *netdev = adapter->netdev;
3596
	u32 npar_state;
3597

3598
	if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
3599 3600
		npar_state = QLC_SHARED_REG_RD32(adapter,
						 QLCNIC_CRB_DEV_NPAR_STATE);
3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611
		if (adapter->fw_wait_cnt++ > QLCNIC_DEV_NPAR_OPER_TIMEO)
			qlcnic_clr_all_drv_state(adapter, 0);
		else if (npar_state != QLCNIC_DEV_NPAR_OPER)
			qlcnic_schedule_work(adapter, qlcnic_attach_work,
							FW_POLL_DELAY);
		else
			goto attach;
		QLCDB(adapter, DRV, "Waiting for NPAR state to operational\n");
		return;
	}
attach:
3612
	qlcnic_dcb_get_info(adapter->dcb);
3613

3614
	if (netif_running(netdev)) {
3615
		if (qlcnic_up(adapter, netdev))
3616 3617
			goto done;

A
Amit Kumar Salecha 已提交
3618
		qlcnic_restore_indev_addr(netdev, NETDEV_UP);
3619 3620 3621
	}

done:
3622
	netif_device_attach(netdev);
3623
	adapter->fw_fail_cnt = 0;
S
Sritej Velaga 已提交
3624
	adapter->flags &= ~QLCNIC_FW_HANG;
3625
	clear_bit(__QLCNIC_RESETTING, &adapter->state);
3626 3627
	if (adapter->portnum == 0)
		qlcnic_set_drv_version(adapter);
3628 3629 3630 3631

	if (!qlcnic_clr_drv_state(adapter))
		qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
							FW_POLL_DELAY);
3632 3633 3634 3635 3636
}

static int
qlcnic_check_health(struct qlcnic_adapter *adapter)
{
3637 3638
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	struct qlcnic_fw_dump *fw_dump = &ahw->fw_dump;
3639
	u32 state = 0, heartbeat;
3640
	u32 peg_status;
3641
	int err = 0;
3642 3643 3644 3645

	if (qlcnic_check_temp(adapter))
		goto detach;

A
Amit Kumar Salecha 已提交
3646
	if (adapter->need_fw_reset)
3647
		qlcnic_dev_request_reset(adapter, 0);
3648

3649
	state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3650
	if (state == QLCNIC_DEV_NEED_RESET) {
3651
		qlcnic_set_npar_non_operational(adapter);
3652
		adapter->need_fw_reset = 1;
3653 3654
	} else if (state == QLCNIC_DEV_NEED_QUISCENT)
		goto detach;
3655

3656
	heartbeat = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
3657 3658
	if (heartbeat != adapter->heartbeat) {
		adapter->heartbeat = heartbeat;
3659 3660 3661
		adapter->fw_fail_cnt = 0;
		if (adapter->need_fw_reset)
			goto detach;
3662

3663
		if (ahw->reset_context && qlcnic_auto_fw_reset)
3664 3665
			qlcnic_reset_hw_context(adapter);

3666 3667 3668 3669 3670 3671
		return 0;
	}

	if (++adapter->fw_fail_cnt < FW_FAIL_THRESH)
		return 0;

S
Sritej Velaga 已提交
3672 3673
	adapter->flags |= QLCNIC_FW_HANG;

3674
	qlcnic_dev_request_reset(adapter, 0);
3675

3676
	if (qlcnic_auto_fw_reset)
3677
		clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
3678

3679
	dev_err(&adapter->pdev->dev, "firmware hang detected\n");
3680
	peg_status = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS1);
3681
	dev_err(&adapter->pdev->dev, "Dumping hw/fw registers\n"
S
Sritej Velaga 已提交
3682 3683 3684 3685
			"PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n"
			"PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n"
			"PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n"
			"PEG_NET_4_PC: 0x%x\n",
3686 3687
			peg_status,
			QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS2),
3688 3689 3690 3691 3692
			QLCRD32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x3c, &err),
			QLCRD32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x3c, &err),
			QLCRD32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c, &err),
			QLCRD32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c, &err),
			QLCRD32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c, &err));
3693
	if (QLCNIC_FWERROR_CODE(peg_status) == 0x67)
3694 3695 3696
		dev_err(&adapter->pdev->dev,
			"Firmware aborted with error code 0x00006700. "
				"Device is being reset.\n");
3697 3698 3699 3700
detach:
	adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state :
		QLCNIC_DEV_NEED_RESET;

3701 3702
	if (qlcnic_auto_fw_reset && !test_and_set_bit(__QLCNIC_RESETTING,
						      &adapter->state)) {
3703

3704
		qlcnic_schedule_work(adapter, qlcnic_detach_work, 0);
3705
		QLCDB(adapter, DRV, "fw recovery scheduled.\n");
3706 3707 3708
	} else if (!qlcnic_auto_fw_reset && fw_dump->enable &&
		   adapter->flags & QLCNIC_FW_RESET_OWNER) {
		qlcnic_dump_fw(adapter);
3709
	}
3710 3711 3712 3713

	return 1;
}

3714
void qlcnic_fw_poll_work(struct work_struct *work)
3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725
{
	struct qlcnic_adapter *adapter = container_of(work,
				struct qlcnic_adapter, fw_work.work);

	if (test_bit(__QLCNIC_RESETTING, &adapter->state))
		goto reschedule;


	if (qlcnic_check_health(adapter))
		return;

3726 3727 3728
	if (adapter->fhash.fnum)
		qlcnic_prune_lb_filters(adapter);

3729 3730 3731 3732
reschedule:
	qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
}

S
Sucheta Chakraborty 已提交
3733 3734 3735 3736 3737 3738 3739 3740 3741
static int qlcnic_is_first_func(struct pci_dev *pdev)
{
	struct pci_dev *oth_pdev;
	int val = pdev->devfn;

	while (val-- > 0) {
		oth_pdev = pci_get_domain_bus_and_slot(pci_domain_nr
			(pdev->bus), pdev->bus->number,
			PCI_DEVFN(PCI_SLOT(pdev->devfn), val));
3742 3743
		if (!oth_pdev)
			continue;
S
Sucheta Chakraborty 已提交
3744

3745 3746
		if (oth_pdev->current_state != PCI_D3cold) {
			pci_dev_put(oth_pdev);
S
Sucheta Chakraborty 已提交
3747
			return 0;
3748 3749
		}
		pci_dev_put(oth_pdev);
S
Sucheta Chakraborty 已提交
3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773
	}
	return 1;
}

static int qlcnic_attach_func(struct pci_dev *pdev)
{
	int err, first_func;
	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
	struct net_device *netdev = adapter->netdev;

	pdev->error_state = pci_channel_io_normal;

	err = pci_enable_device(pdev);
	if (err)
		return err;

	pci_set_master(pdev);
	pci_restore_state(pdev);

	first_func = qlcnic_is_first_func(pdev);

	if (qlcnic_api_lock(adapter))
		return -EINVAL;

3774
	if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
S
Sucheta Chakraborty 已提交
3775 3776
		adapter->need_fw_reset = 1;
		set_bit(__QLCNIC_START_FW, &adapter->state);
3777 3778
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE,
				    QLCNIC_DEV_INITIALIZING);
S
Sucheta Chakraborty 已提交
3779 3780 3781 3782
		QLCDB(adapter, DRV, "Restarting fw\n");
	}
	qlcnic_api_unlock(adapter);

S
Sony Chacko 已提交
3783
	err = qlcnic_start_firmware(adapter);
S
Sucheta Chakraborty 已提交
3784 3785 3786 3787
	if (err)
		return err;

	qlcnic_clr_drv_state(adapter);
S
Sony Chacko 已提交
3788 3789
	kfree(adapter->msix_entries);
	adapter->msix_entries = NULL;
3790
	err = qlcnic_setup_intr(adapter);
S
Sony Chacko 已提交
3791

3792 3793 3794 3795 3796 3797
	if (err) {
		kfree(adapter->msix_entries);
		netdev_err(netdev, "failed to setup interrupt\n");
		return err;
	}

S
Sucheta Chakraborty 已提交
3798 3799 3800
	if (netif_running(netdev)) {
		err = qlcnic_attach(adapter);
		if (err) {
3801
			qlcnic_clr_all_drv_state(adapter, 1);
S
Sucheta Chakraborty 已提交
3802 3803 3804 3805 3806 3807 3808 3809 3810
			clear_bit(__QLCNIC_AER, &adapter->state);
			netif_device_attach(netdev);
			return err;
		}

		err = qlcnic_up(adapter, netdev);
		if (err)
			goto done;

A
Amit Kumar Salecha 已提交
3811
		qlcnic_restore_indev_addr(netdev, NETDEV_UP);
S
Sucheta Chakraborty 已提交
3812 3813 3814 3815 3816 3817
	}
 done:
	netif_device_attach(netdev);
	return err;
}

3818 3819
static pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *pdev,
						      pci_channel_state_t state)
S
Sucheta Chakraborty 已提交
3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848
{
	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
	struct net_device *netdev = adapter->netdev;

	if (state == pci_channel_io_perm_failure)
		return PCI_ERS_RESULT_DISCONNECT;

	if (state == pci_channel_io_normal)
		return PCI_ERS_RESULT_RECOVERED;

	set_bit(__QLCNIC_AER, &adapter->state);
	netif_device_detach(netdev);

	cancel_delayed_work_sync(&adapter->fw_work);

	if (netif_running(netdev))
		qlcnic_down(adapter, netdev);

	qlcnic_detach(adapter);
	qlcnic_teardown_intr(adapter);

	clear_bit(__QLCNIC_RESETTING, &adapter->state);

	pci_save_state(pdev);
	pci_disable_device(pdev);

	return PCI_ERS_RESULT_NEED_RESET;
}

3849
static pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *pdev)
S
Sucheta Chakraborty 已提交
3850 3851 3852 3853 3854
{
	return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT :
				PCI_ERS_RESULT_RECOVERED;
}

3855
static void qlcnic_82xx_io_resume(struct pci_dev *pdev)
S
Sucheta Chakraborty 已提交
3856
{
3857
	u32 state;
S
Sucheta Chakraborty 已提交
3858 3859 3860
	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);

	pci_cleanup_aer_uncorrect_error_status(pdev);
3861 3862 3863
	state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
	if (state == QLCNIC_DEV_READY && test_and_clear_bit(__QLCNIC_AER,
							    &adapter->state))
S
Sucheta Chakraborty 已提交
3864
		qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
3865
				     FW_POLL_DELAY);
S
Sucheta Chakraborty 已提交
3866 3867
}

3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906
static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev,
						 pci_channel_state_t state)
{
	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
	struct qlcnic_hardware_ops *hw_ops = adapter->ahw->hw_ops;

	if (hw_ops->io_error_detected) {
		return hw_ops->io_error_detected(pdev, state);
	} else {
		dev_err(&pdev->dev, "AER error_detected handler not registered.\n");
		return PCI_ERS_RESULT_DISCONNECT;
	}
}

static pci_ers_result_t qlcnic_io_slot_reset(struct pci_dev *pdev)
{
	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
	struct qlcnic_hardware_ops *hw_ops = adapter->ahw->hw_ops;

	if (hw_ops->io_slot_reset) {
		return hw_ops->io_slot_reset(pdev);
	} else {
		dev_err(&pdev->dev, "AER slot_reset handler not registered.\n");
		return PCI_ERS_RESULT_DISCONNECT;
	}
}

static void qlcnic_io_resume(struct pci_dev *pdev)
{
	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
	struct qlcnic_hardware_ops *hw_ops = adapter->ahw->hw_ops;

	if (hw_ops->io_resume)
		hw_ops->io_resume(pdev);
	else
		dev_err(&pdev->dev, "AER resume handler not registered.\n");
}


3907 3908 3909 3910 3911 3912 3913 3914 3915
static int
qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
{
	int err;

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

A
Amit Kumar Salecha 已提交
3916 3917 3918
	err = qlcnic_check_npar_opertional(adapter);
	if (err)
		return err;
3919

3920 3921 3922 3923
	err = qlcnic_initialize_nic(adapter);
	if (err)
		return err;

3924 3925
	qlcnic_check_options(adapter);

3926 3927 3928 3929
	err = qlcnic_set_eswitch_port_config(adapter);
	if (err)
		return err;

3930 3931 3932 3933 3934
	adapter->need_fw_reset = 0;

	return err;
}

3935 3936
int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt,
			  int queue_type)
3937 3938
{
	struct net_device *netdev = adapter->netdev;
3939 3940 3941 3942 3943 3944 3945 3946 3947
	u8 max_hw_rings = 0;
	char buf[8];
	int cur_rings;

	if (queue_type == QLCNIC_RX_QUEUE) {
		max_hw_rings = adapter->max_sds_rings;
		cur_rings = adapter->drv_sds_rings;
		strcpy(buf, "SDS");
	} else if (queue_type == QLCNIC_TX_QUEUE) {
3948
		max_hw_rings = adapter->max_tx_rings;
3949 3950
		cur_rings = adapter->drv_tx_rings;
		strcpy(buf, "Tx");
3951 3952
	}

3953
	if (!QLCNIC_IS_MSI_FAMILY(adapter)) {
3954
		netdev_err(netdev, "No RSS/TSS support in INT-x mode\n");
3955 3956 3957
		return -EINVAL;
	}

3958 3959
	if (adapter->flags & QLCNIC_MSI_ENABLED) {
		netdev_err(netdev, "No RSS/TSS support in MSI mode\n");
3960 3961 3962
		return -EINVAL;
	}

3963 3964 3965
	if (!is_power_of_2(ring_cnt)) {
		netdev_err(netdev, "%s rings value should be a power of 2\n",
			   buf);
3966 3967 3968
		return -EINVAL;
	}

3969 3970 3971 3972
	if (qlcnic_82xx_check(adapter) && (queue_type == QLCNIC_TX_QUEUE) &&
	    !qlcnic_check_multi_tx(adapter)) {
			netdev_err(netdev, "No Multi Tx queue support\n");
			return -EINVAL;
3973 3974
	}

3975 3976 3977 3978
	if (ring_cnt > num_online_cpus()) {
		netdev_err(netdev,
			   "%s value[%u] should not be higher than, number of online CPUs\n",
			   buf, num_online_cpus());
3979 3980
		return -EINVAL;
	}
3981

3982 3983 3984
	return 0;
}

3985
int qlcnic_setup_rings(struct qlcnic_adapter *adapter)
3986 3987
{
	struct net_device *netdev = adapter->netdev;
3988
	int err;
3989

S
Sony Chacko 已提交
3990 3991 3992
	if (test_bit(__QLCNIC_RESETTING, &adapter->state))
		return -EBUSY;

3993 3994 3995
	netif_device_detach(netdev);
	if (netif_running(netdev))
		__qlcnic_down(adapter, netdev);
S
Sony Chacko 已提交
3996

3997 3998
	qlcnic_detach(adapter);

3999
	if (qlcnic_83xx_check(adapter)) {
S
Sony Chacko 已提交
4000
		qlcnic_83xx_free_mbx_intr(adapter);
4001 4002
		qlcnic_83xx_enable_mbx_poll(adapter);
	}
S
Sony Chacko 已提交
4003

4004
	qlcnic_teardown_intr(adapter);
4005

4006
	err = qlcnic_setup_intr(adapter);
4007 4008 4009 4010 4011
	if (err) {
		kfree(adapter->msix_entries);
		netdev_err(netdev, "failed to setup interrupt\n");
		return err;
	}
4012

4013 4014
	netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings);

S
Sony Chacko 已提交
4015
	if (qlcnic_83xx_check(adapter)) {
4016
		qlcnic_83xx_initialize_nic(adapter, 1);
S
Sony Chacko 已提交
4017
		err = qlcnic_83xx_setup_mbx_intr(adapter);
4018
		qlcnic_83xx_disable_mbx_poll(adapter);
S
Sony Chacko 已提交
4019 4020 4021 4022 4023
		if (err) {
			dev_err(&adapter->pdev->dev,
				"failed to setup mbx interrupt\n");
			goto done;
		}
4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034
	}

	if (netif_running(netdev)) {
		err = qlcnic_attach(adapter);
		if (err)
			goto done;
		err = __qlcnic_up(adapter, netdev);
		if (err)
			goto done;
		qlcnic_restore_indev_addr(netdev, NETDEV_UP);
	}
4035
done:
4036 4037 4038 4039 4040
	netif_device_attach(netdev);
	clear_bit(__QLCNIC_RESETTING, &adapter->state);
	return err;
}

4041 4042 4043 4044 4045
#ifdef CONFIG_INET

#define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops)

static void
A
Amit Kumar Salecha 已提交
4046 4047
qlcnic_config_indev_addr(struct qlcnic_adapter *adapter,
			struct net_device *dev, unsigned long event)
4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072
{
	struct in_device *indev;

	indev = in_dev_get(dev);
	if (!indev)
		return;

	for_ifa(indev) {
		switch (event) {
		case NETDEV_UP:
			qlcnic_config_ipaddr(adapter,
					ifa->ifa_address, QLCNIC_IP_UP);
			break;
		case NETDEV_DOWN:
			qlcnic_config_ipaddr(adapter,
					ifa->ifa_address, QLCNIC_IP_DOWN);
			break;
		default:
			break;
		}
	} endfor_ifa(indev);

	in_dev_put(indev);
}

S
Sony Chacko 已提交
4073
void qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event)
A
Amit Kumar Salecha 已提交
4074 4075 4076 4077 4078 4079 4080
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct net_device *dev;
	u16 vid;

	qlcnic_config_indev_addr(adapter, netdev, event);

4081
	rcu_read_lock();
4082
	for_each_set_bit(vid, adapter->vlans, VLAN_N_VID) {
4083
		dev = __vlan_find_dev_deep(netdev, htons(ETH_P_8021Q), vid);
A
Amit Kumar Salecha 已提交
4084 4085 4086 4087
		if (!dev)
			continue;
		qlcnic_config_indev_addr(adapter, dev, event);
	}
4088
	rcu_read_unlock();
A
Amit Kumar Salecha 已提交
4089 4090
}

4091 4092 4093 4094
static int qlcnic_netdev_event(struct notifier_block *this,
				 unsigned long event, void *ptr)
{
	struct qlcnic_adapter *adapter;
4095
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113

recheck:
	if (dev == NULL)
		goto done;

	if (dev->priv_flags & IFF_802_1Q_VLAN) {
		dev = vlan_dev_real_dev(dev);
		goto recheck;
	}

	if (!is_qlcnic_netdev(dev))
		goto done;

	adapter = netdev_priv(dev);

	if (!adapter)
		goto done;

4114
	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
4115 4116
		goto done;

A
Amit Kumar Salecha 已提交
4117
	qlcnic_config_indev_addr(adapter, dev, event);
4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133
done:
	return NOTIFY_DONE;
}

static int
qlcnic_inetaddr_event(struct notifier_block *this,
		unsigned long event, void *ptr)
{
	struct qlcnic_adapter *adapter;
	struct net_device *dev;

	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;

	dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;

recheck:
A
Amit Kumar Salecha 已提交
4134
	if (dev == NULL)
4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146
		goto done;

	if (dev->priv_flags & IFF_802_1Q_VLAN) {
		dev = vlan_dev_real_dev(dev);
		goto recheck;
	}

	if (!is_qlcnic_netdev(dev))
		goto done;

	adapter = netdev_priv(dev);

A
Amit Kumar Salecha 已提交
4147
	if (!adapter)
4148 4149
		goto done;

4150
	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
4151 4152 4153 4154 4155
		goto done;

	switch (event) {
	case NETDEV_UP:
		qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_UP);
S
Sony Chacko 已提交
4156

4157 4158 4159
		break;
	case NETDEV_DOWN:
		qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_DOWN);
S
Sony Chacko 已提交
4160

4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177
		break;
	default:
		break;
	}

done:
	return NOTIFY_DONE;
}

static struct notifier_block	qlcnic_netdev_cb = {
	.notifier_call = qlcnic_netdev_event,
};

static struct notifier_block qlcnic_inetaddr_cb = {
	.notifier_call = qlcnic_inetaddr_event,
};
#else
S
Sony Chacko 已提交
4178
void qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event)
4179 4180
{ }
#endif
4181
static const struct pci_error_handlers qlcnic_err_handler = {
S
Sucheta Chakraborty 已提交
4182 4183 4184 4185
	.error_detected = qlcnic_io_error_detected,
	.slot_reset = qlcnic_io_slot_reset,
	.resume = qlcnic_io_resume,
};
4186 4187 4188 4189 4190

static struct pci_driver qlcnic_driver = {
	.name = qlcnic_driver_name,
	.id_table = qlcnic_pci_tbl,
	.probe = qlcnic_probe,
B
Bill Pemberton 已提交
4191
	.remove = qlcnic_remove,
4192 4193 4194 4195
#ifdef CONFIG_PM
	.suspend = qlcnic_suspend,
	.resume = qlcnic_resume,
#endif
S
Sucheta Chakraborty 已提交
4196
	.shutdown = qlcnic_shutdown,
4197 4198 4199 4200
	.err_handler = &qlcnic_err_handler,
#ifdef CONFIG_QLCNIC_SRIOV
	.sriov_configure = qlcnic_pci_sriov_configure,
#endif
S
Sucheta Chakraborty 已提交
4201

4202 4203 4204 4205
};

static int __init qlcnic_init_module(void)
{
4206
	int ret;
4207 4208 4209 4210 4211 4212 4213 4214

	printk(KERN_INFO "%s\n", qlcnic_driver_string);

#ifdef CONFIG_INET
	register_netdevice_notifier(&qlcnic_netdev_cb);
	register_inetaddr_notifier(&qlcnic_inetaddr_cb);
#endif

4215 4216 4217 4218 4219 4220 4221
	ret = pci_register_driver(&qlcnic_driver);
	if (ret) {
#ifdef CONFIG_INET
		unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
		unregister_netdevice_notifier(&qlcnic_netdev_cb);
#endif
	}
4222

4223
	return ret;
4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238
}

module_init(qlcnic_init_module);

static void __exit qlcnic_exit_module(void)
{
	pci_unregister_driver(&qlcnic_driver);

#ifdef CONFIG_INET
	unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
	unregister_netdevice_notifier(&qlcnic_netdev_cb);
#endif
}

module_exit(qlcnic_exit_module);