qlcnic_main.c 99.3 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

25
MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver");
26 27 28 29 30
MODULE_LICENSE("GPL");
MODULE_VERSION(QLCNIC_LINUX_VERSIONID);
MODULE_FIRMWARE(QLCNIC_UNIFIED_ROMIMAGE_NAME);

char qlcnic_driver_name[] = "qlcnic";
31 32
static const char qlcnic_driver_string[] = "QLogic 1/10 GbE "
	"Converged/Intelligent Ethernet Driver v" QLCNIC_LINUX_VERSIONID;
33

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

39
int qlcnic_use_msi = 1;
40
MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled)");
41
module_param_named(use_msi, qlcnic_use_msi, int, 0444);
42

43
int qlcnic_use_msi_x = 1;
44
MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled)");
45
module_param_named(use_msi_x, qlcnic_use_msi_x, int, 0444);
46

47
int qlcnic_auto_fw_reset = 1;
48
MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled)");
49
module_param_named(auto_fw_reset, qlcnic_auto_fw_reset, int, 0644);
50

51
int qlcnic_load_fw_file;
52
MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file)");
53
module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444);
54

55
static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
B
Bill Pemberton 已提交
56
static void qlcnic_remove(struct pci_dev *pdev);
57 58 59 60 61 62 63 64 65
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

66
static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
67 68
static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);

69
static irqreturn_t qlcnic_tmp_intr(int irq, void *data);
70 71 72
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 已提交
73
static irqreturn_t qlcnic_msix_tx_intr(int irq, void *data);
74 75

static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev);
76 77
static int qlcnic_start_firmware(struct qlcnic_adapter *);

78
static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
79 80
static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
81 82
static int qlcnic_vlan_rx_add(struct net_device *, __be16, u16);
static int qlcnic_vlan_rx_del(struct net_device *, __be16, u16);
83

S
Sony Chacko 已提交
84 85 86 87 88 89 90 91 92 93
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;
}

94 95 96 97 98
/*  PCI Device ID Table  */
#define ENTRY(device) \
	{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
	.class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0}

99
static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
100
	ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X),
S
Sony Chacko 已提交
101
	ENTRY(PCI_DEVICE_ID_QLOGIC_QLE834X),
R
Rajesh Borundia 已提交
102
	ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE834X),
103 104
	ENTRY(PCI_DEVICE_ID_QLOGIC_QLE844X),
	ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE844X),
105 106 107 108 109 110
	{0,}
};

MODULE_DEVICE_TABLE(pci, qlcnic_pci_tbl);


S
Sony Chacko 已提交
111
inline void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *tx_ring)
112 113 114 115 116 117 118 119 120 121 122
{
	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
};

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
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 已提交
149
static const struct qlcnic_board_info qlcnic_boards[] = {
150 151 152 153 154
	{ PCI_VENDOR_ID_QLOGIC,
	  PCI_DEVICE_ID_QLOGIC_QLE844X,
	  0x0,
	  0x0,
	  "8400 series 10GbE Converged Network Adapter (TCP/IP Networking)" },
155 156 157 158 159 160 161 162 163 164 165 166 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
	{ 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 已提交
261 262 263 264
};

#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards)

265 266 267
static const
struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG;

268
int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
269 270 271 272 273
{
	int size = sizeof(struct qlcnic_host_sds_ring) * count;

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

274
	return recv_ctx->sds_rings == NULL;
275 276
}

277
void qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
278 279 280 281 282 283 284
{
	if (recv_ctx->sds_rings != NULL)
		kfree(recv_ctx->sds_rings);

	recv_ctx->sds_rings = NULL;
}

R
Rajesh Borundia 已提交
285
int qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
286 287 288
{
	struct net_device *netdev = adapter->netdev;
	struct pci_dev *pdev = adapter->pdev;
289 290
	u8 mac_addr[ETH_ALEN];
	int ret;
291

292 293 294 295
	ret = qlcnic_get_mac_address(adapter, mac_addr,
				     adapter->ahw->pci_func);
	if (ret)
		return ret;
296

297
	memcpy(netdev->dev_addr, mac_addr, ETH_ALEN);
298 299 300 301
	memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len);

	/* set station address */

302
	if (!is_valid_ether_addr(netdev->dev_addr))
303 304 305 306 307 308
		dev_warn(&pdev->dev, "Bad MAC address %pM.\n",
					netdev->dev_addr);

	return 0;
}

M
Manish Chopra 已提交
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
static void qlcnic_delete_adapter_mac(struct qlcnic_adapter *adapter)
{
	struct qlcnic_mac_list_s *cur;
	struct list_head *head;

	list_for_each(head, &adapter->mac_list) {
		cur = list_entry(head, struct qlcnic_mac_list_s, list);
		if (!memcmp(adapter->mac_addr, cur->mac_addr, ETH_ALEN)) {
			qlcnic_sre_macaddr_change(adapter, cur->mac_addr,
						  0, QLCNIC_MAC_DEL);
			list_del(&cur->list);
			kfree(cur);
			return;
		}
	}
}

326 327 328 329 330
static int qlcnic_set_mac(struct net_device *netdev, void *p)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct sockaddr *addr = p;

331 332 333
	if (qlcnic_sriov_vf_check(adapter))
		return -EINVAL;

334 335 336
	if ((adapter->flags & QLCNIC_MAC_OVERRIDE_DISABLED))
		return -EOPNOTSUPP;

337
	if (!is_valid_ether_addr(addr->sa_data))
S
Sony Chacko 已提交
338
		return -EINVAL;
339

M
Manish Chopra 已提交
340 341 342
	if (!memcmp(adapter->mac_addr, addr->sa_data, ETH_ALEN))
		return 0;

343
	if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
344 345 346 347
		netif_device_detach(netdev);
		qlcnic_napi_disable(adapter);
	}

M
Manish Chopra 已提交
348
	qlcnic_delete_adapter_mac(adapter);
349 350 351 352
	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);

353
	if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
354 355 356 357 358 359
		netif_device_attach(netdev);
		qlcnic_napi_enable(adapter);
	}
	return 0;
}

360 361
static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
			struct net_device *netdev, const unsigned char *addr)
362 363 364 365
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	int err = -EOPNOTSUPP;

366 367
	if (!adapter->fdb_mac_learn)
		return ndo_dflt_fdb_del(ndm, tb, netdev, addr);
368 369

	if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
370 371 372 373 374
		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)) {
375
			err = dev_mc_del(netdev, addr);
376
		} else {
377
			err =  -EINVAL;
378
		}
379 380 381 382 383 384 385 386 387 388 389
	}
	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;

390 391
	if (!adapter->fdb_mac_learn)
		return ndo_dflt_fdb_add(ndm, tb, netdev, addr, flags);
392 393 394 395 396 397 398 399 400

	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;

401 402 403 404 405 406
	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)) {
407
		err = dev_mc_add_excl(netdev, addr);
408
	} else {
409
		err = -EINVAL;
410
	}
411 412 413 414 415 416 417 418 419

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

420 421
	if (!adapter->fdb_mac_learn)
		return ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
422 423 424 425 426 427 428

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

	return idx;
}

429 430 431 432 433 434 435 436
static void qlcnic_82xx_cancel_idc_work(struct qlcnic_adapter *adapter)
{
	while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
		usleep_range(10000, 11000);

	cancel_delayed_work_sync(&adapter->fw_work);
}

437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
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;
}

452 453 454 455 456 457
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,
458
	.ndo_set_rx_mode   = qlcnic_set_multi,
459 460
	.ndo_set_mac_address    = qlcnic_set_mac,
	.ndo_change_mtu	   = qlcnic_change_mtu,
461 462
	.ndo_fix_features  = qlcnic_fix_features,
	.ndo_set_features  = qlcnic_set_features,
463
	.ndo_tx_timeout	   = qlcnic_tx_timeout,
464 465
	.ndo_vlan_rx_add_vid	= qlcnic_vlan_rx_add,
	.ndo_vlan_rx_kill_vid	= qlcnic_vlan_rx_del,
466 467 468
	.ndo_fdb_add		= qlcnic_fdb_add,
	.ndo_fdb_del		= qlcnic_fdb_del,
	.ndo_fdb_dump		= qlcnic_fdb_dump,
469
	.ndo_get_phys_port_id	= qlcnic_get_phys_port_id,
470 471 472
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller = qlcnic_poll_controller,
#endif
473 474 475 476
#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,
477
	.ndo_set_vf_vlan	= qlcnic_sriov_set_vf_vlan,
478
	.ndo_set_vf_spoofchk	= qlcnic_sriov_set_vf_spoofchk,
479
#endif
480 481
};

482 483 484 485
static const struct net_device_ops qlcnic_netdev_failed_ops = {
	.ndo_open	   = qlcnic_open,
};

486
static struct qlcnic_nic_template qlcnic_ops = {
487 488 489 490 491 492
	.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 已提交
493
	.napi_del		= qlcnic_82xx_napi_del,
494
	.config_ipaddr		= qlcnic_82xx_config_ipaddr,
495 496
	.shutdown		= qlcnic_82xx_shutdown,
	.resume			= qlcnic_82xx_resume,
497 498 499 500 501 502 503
	.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
504 505
};

506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
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,
523 524
	.del_rx_ctx			= qlcnic_82xx_fw_cmd_del_rx_ctx,
	.del_tx_ctx			= qlcnic_82xx_fw_cmd_del_tx_ctx,
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
	.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,
540
	.set_mac_filter_count		= qlcnic_82xx_set_mac_filter_count,
541
	.free_mac_list			= qlcnic_82xx_free_mac_list,
542
	.read_phys_port_id		= qlcnic_82xx_read_phys_port_id,
543 544 545
	.io_error_detected		= qlcnic_82xx_io_error_detected,
	.io_slot_reset			= qlcnic_82xx_io_slot_reset,
	.io_resume			= qlcnic_82xx_io_resume,
546 547
};

548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
static void qlcnic_get_multiq_capability(struct qlcnic_adapter *adapter)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	int num_tx_q;

	if (ahw->msix_supported &&
	    (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_MULTI_TX)) {
		num_tx_q = min_t(int, QLCNIC_DEF_NUM_TX_RINGS,
				 num_online_cpus());
		if (num_tx_q > 1) {
			test_and_set_bit(__QLCNIC_MULTI_TX_UNIQUE,
					 &adapter->state);
			adapter->max_drv_tx_rings = num_tx_q;
		}
	} else {
		adapter->max_drv_tx_rings = 1;
	}
}

567
int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
568 569
{
	struct pci_dev *pdev = adapter->pdev;
570
	int max_tx_rings, max_sds_rings, tx_vector;
S
Sony Chacko 已提交
571
	int err = -1, i;
572 573 574 575 576 577 578 579

	if (adapter->flags & QLCNIC_TX_INTR_SHARED) {
		max_tx_rings = 0;
		tx_vector = 0;
	} else {
		max_tx_rings = adapter->max_drv_tx_rings;
		tx_vector = 1;
	}
S
Sony Chacko 已提交
580 581 582 583 584

	if (!adapter->msix_entries) {
		adapter->msix_entries = kcalloc(num_msix,
						sizeof(struct msix_entry),
						GFP_KERNEL);
585
		if (!adapter->msix_entries)
S
Sony Chacko 已提交
586 587
			return -ENOMEM;
	}
588 589 590 591

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

592
	if (adapter->ahw->msix_supported) {
593
 enable_msix:
S
Sony Chacko 已提交
594 595
		for (i = 0; i < num_msix; i++)
			adapter->msix_entries[i].entry = i;
596 597 598
		err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
		if (err == 0) {
			adapter->flags |= QLCNIC_MSIX_ENABLED;
S
Sony Chacko 已提交
599 600 601 602 603 604
			if (qlcnic_83xx_check(adapter)) {
				adapter->ahw->num_msix = num_msix;
				/* subtract mail box and tx ring vectors */
				adapter->max_sds_rings = num_msix -
							 max_tx_rings - 1;
			} else {
605 606
				adapter->ahw->num_msix = num_msix;
				if (qlcnic_check_multi_tx(adapter) &&
607
				    !adapter->ahw->diag_test &&
608 609 610 611 612 613
				    (adapter->max_drv_tx_rings > 1))
					max_sds_rings = num_msix - max_tx_rings;
				else
					max_sds_rings = num_msix;

				adapter->max_sds_rings = max_sds_rings;
S
Sony Chacko 已提交
614
			}
615
			dev_info(&pdev->dev, "using msi-x interrupts\n");
616
			return err;
S
Sony Chacko 已提交
617 618 619 620 621
		} else if (err > 0) {
			dev_info(&pdev->dev,
				 "Unable to allocate %d MSI-X interrupt vectors\n",
				 num_msix);
			if (qlcnic_83xx_check(adapter)) {
622
				if (err < (QLC_83XX_MINIMUM_VECTOR - tx_vector))
S
Sony Chacko 已提交
623
					return err;
624
				err -= (max_tx_rings + 1);
S
Sony Chacko 已提交
625
				num_msix = rounddown_pow_of_two(err);
626
				num_msix += (max_tx_rings + 1);
S
Sony Chacko 已提交
627 628
			} else {
				num_msix = rounddown_pow_of_two(err);
629 630
				if (qlcnic_check_multi_tx(adapter))
					num_msix += max_tx_rings;
S
Sony Chacko 已提交
631 632 633 634
			}

			if (num_msix) {
				dev_info(&pdev->dev,
635
					 "Trying to allocate %d MSI-X interrupt vectors\n",
S
Sony Chacko 已提交
636
					 num_msix);
637
				goto enable_msix;
S
Sony Chacko 已提交
638 639
			}
		} else {
640 641
			dev_info(&pdev->dev,
				 "Unable to allocate %d MSI-X interrupt vectors\n",
S
Sony Chacko 已提交
642
				 num_msix);
643 644
		}
	}
S
Sony Chacko 已提交
645

646 647
	return err;
}
648

649
static int qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
650
{
651
	int err = 0;
652
	u32 offset, mask_reg;
653
	const struct qlcnic_legacy_intr_set *legacy_intrp;
654
	struct qlcnic_hardware_context *ahw = adapter->ahw;
655
	struct pci_dev *pdev = adapter->pdev;
656

657
	if (qlcnic_use_msi && !pci_enable_msi(pdev)) {
658
		adapter->flags |= QLCNIC_MSI_ENABLED;
659 660 661
		offset = msi_tgt_status[adapter->ahw->pci_func];
		adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter->ahw,
							    offset);
662 663
		dev_info(&pdev->dev, "using msi interrupts\n");
		adapter->msix_entries[0].vector = pdev->irq;
664
		return err;
665
	}
666

667 668
	if (qlcnic_use_msi || qlcnic_use_msi_x)
		return -EOPNOTSUPP;
669

670
	legacy_intrp = &legacy_intr[adapter->ahw->pci_func];
671
	adapter->ahw->int_vec_bit = legacy_intrp->int_vec_bit;
672 673 674 675 676 677
	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);
678 679
	dev_info(&pdev->dev, "using legacy interrupts\n");
	adapter->msix_entries[0].vector = pdev->irq;
680
	return err;
681 682
}

683
int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr, int txq)
684
{
685
	struct qlcnic_hardware_context *ahw = adapter->ahw;
686
	int num_msix, err = 0;
687

688 689 690
	if (!num_intr)
		num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;

691
	if (ahw->msix_supported) {
692
		num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
693
						num_intr));
694 695 696
		if (qlcnic_check_multi_tx(adapter)) {
			if (txq)
				adapter->max_drv_tx_rings = txq;
697
			num_msix += adapter->max_drv_tx_rings;
698
		}
699
	} else {
700
		num_msix = 1;
701
	}
702

703
	err = qlcnic_enable_msix(adapter, num_msix);
704
	if (err == -ENOMEM)
705
		return err;
706

707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
	if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
		qlcnic_disable_multi_tx(adapter);

		err = qlcnic_enable_msi_legacy(adapter);
		if (!err)
			return err;
	}

	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) &&
724
	    !ahw->diag_test &&
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
	    (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);
742
		return err;
743
	}
744

745
	return 0;
746
}
S
Sony Chacko 已提交
747

S
Sony Chacko 已提交
748
void qlcnic_teardown_intr(struct qlcnic_adapter *adapter)
749 750 751 752 753
{
	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 已提交
754 755 756 757 758 759 760 761

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

	if (adapter->ahw->intr_tbl) {
		vfree(adapter->ahw->intr_tbl);
		adapter->ahw->intr_tbl = NULL;
	}
762 763
}

764
static void qlcnic_cleanup_pci_map(struct qlcnic_hardware_context *ahw)
765
{
766 767
	if (ahw->pci_base0 != NULL)
		iounmap(ahw->pci_base0);
768 769
}

770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter)
{
	struct qlcnic_pci_info *pci_info;
	int ret;

	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
		switch (adapter->ahw->port_type) {
		case QLCNIC_GBE:
			adapter->ahw->act_pci_func = QLCNIC_NIU_MAX_GBE_PORTS;
			break;
		case QLCNIC_XGBE:
			adapter->ahw->act_pci_func = QLCNIC_NIU_MAX_XG_PORTS;
			break;
		}
		return 0;
	}

	if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
		return 0;

	pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
	if (!pci_info)
		return -ENOMEM;

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

799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
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;
}

816
int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
817
{
D
Dan Carpenter 已提交
818
	struct qlcnic_pci_info *pci_info;
819 820
	int i, ret = 0, j = 0;
	u16 act_pci_func;
821 822
	u8 pfn;

D
Dan Carpenter 已提交
823 824 825 826
	pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
	if (!pci_info)
		return -ENOMEM;

827 828 829 830 831 832
	ret = qlcnic_get_pci_info(adapter, pci_info);
	if (ret)
		goto err_pci_info;

	act_pci_func = adapter->ahw->act_pci_func;

833
	adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
834
				 act_pci_func, GFP_KERNEL);
D
Dan Carpenter 已提交
835
	if (!adapter->npars) {
836
		ret = -ENOMEM;
D
Dan Carpenter 已提交
837 838
		goto err_pci_info;
	}
839

840
	adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) *
841 842
				QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL);
	if (!adapter->eswitch) {
843
		ret = -ENOMEM;
844
		goto err_npars;
845 846
	}

847 848
	for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
		pfn = pci_info[i].id;
849

850
		if (pfn >= QLCNIC_MAX_PCI_FUNC) {
S
Sony Chacko 已提交
851 852 853
			ret = QL_STATUS_INVALID_PARAM;
			goto err_eswitch;
		}
854 855 856 857 858

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

859 860 861 862 863 864 865 866 867
		if (qlcnic_port_eswitch_cfg_capability(adapter)) {
			if (!qlcnic_83xx_enable_port_eswitch(adapter, pfn))
				adapter->npars[j].eswitch_status = true;
			else
				continue;
		} else {
			adapter->npars[j].eswitch_status = true;
		}

868 869 870 871 872 873
		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;
874

875
		j++;
876 877
	}

878 879 880 881 882
	if (qlcnic_82xx_check(adapter)) {
		for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
			adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE;
	} else if (!qlcnic_port_eswitch_cfg_capability(adapter)) {
		for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
S
Sony Chacko 已提交
883 884
			qlcnic_enable_eswitch(adapter, i, 1);
	}
885

D
Dan Carpenter 已提交
886
	kfree(pci_info);
887 888 889
	return 0;

err_eswitch:
890 891
	kfree(adapter->eswitch);
	adapter->eswitch = NULL;
892
err_npars:
893
	kfree(adapter->npars);
894
	adapter->npars = NULL;
D
Dan Carpenter 已提交
895 896
err_pci_info:
	kfree(pci_info);
897 898 899 900

	return ret;
}

901 902 903 904
static int
qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
{
	u8 id;
905
	int ret;
906
	u32 data = QLCNIC_MGMT_FUNC;
907
	struct qlcnic_hardware_context *ahw = adapter->ahw;
908 909 910 911 912

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

913 914 915 916
	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);
917
	QLC_SHARED_REG_WR32(adapter, QLCNIC_DRV_OP_MODE, data);
918 919 920 921 922
	qlcnic_api_unlock(adapter);
err_lock:
	return ret;
}

S
Sony Chacko 已提交
923 924
static void qlcnic_check_vf(struct qlcnic_adapter *adapter,
			    const struct pci_device_id *ent)
925 926 927 928
{
	u32 op_mode, priv_level;

	/* Determine FW API version */
S
Sony Chacko 已提交
929 930
	adapter->ahw->fw_hal_version = QLC_SHARED_REG_RD32(adapter,
							   QLCNIC_FW_API);
931 932

	/* Find PCI function number */
S
Sony Chacko 已提交
933
	qlcnic_get_func_no(adapter);
934 935

	/* Determine function privilege level */
S
Sony Chacko 已提交
936
	op_mode = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE);
937
	if (op_mode == QLC_DEV_DRV_DEFAULT)
938
		priv_level = QLCNIC_MGMT_FUNC;
939
	else
A
Anirban Chakraborty 已提交
940
		priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
941

942
	if (priv_level == QLCNIC_NON_PRIV_FUNC) {
943
		adapter->ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
944 945
		dev_info(&adapter->pdev->dev,
			"HAL Version: %d Non Privileged function\n",
946
			 adapter->ahw->fw_hal_version);
947
		adapter->nic_ops = &qlcnic_vf_ops;
948 949
	} else
		adapter->nic_ops = &qlcnic_ops;
950 951
}

952
#define QLCNIC_82XX_BAR0_LENGTH 0x00200000UL
S
Sony Chacko 已提交
953
#define QLCNIC_83XX_BAR0_LENGTH 0x4000
954 955 956 957 958 959
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 已提交
960
	case PCI_DEVICE_ID_QLOGIC_QLE834X:
961
	case PCI_DEVICE_ID_QLOGIC_QLE844X:
R
Rajesh Borundia 已提交
962
	case PCI_DEVICE_ID_QLOGIC_VF_QLE834X:
963
	case PCI_DEVICE_ID_QLOGIC_VF_QLE844X:
S
Sony Chacko 已提交
964 965
		*bar = QLCNIC_83XX_BAR0_LENGTH;
		break;
966 967 968 969 970 971 972
	default:
		*bar = 0;
	}
}

static int qlcnic_setup_pci_map(struct pci_dev *pdev,
				struct qlcnic_hardware_context *ahw)
973
{
974
	u32 offset;
975
	void __iomem *mem_ptr0 = NULL;
976
	unsigned long mem_len, pci_len0 = 0, bar0_len;
977 978 979 980

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

981 982
	qlcnic_get_bar_length(pdev->device, &bar0_len);
	if (mem_len >= bar0_len) {
983 984 985 986 987 988 989 990 991 992 993

		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 已提交
994
	dev_info(&pdev->dev, "%dKB memory map\n", (int)(mem_len >> 10));
995

996 997 998 999
	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);
1000 1001 1002 1003

	return 0;
}

M
Manish Chopra 已提交
1004 1005
static bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter,
					 int index)
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
{
	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 已提交
1025
static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name)
1026 1027 1028 1029 1030 1031
{
	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 &&
1032 1033 1034 1035
		    qlcnic_boards[i].device == pdev->device &&
		    qlcnic_validate_subsystem_id(adapter, i)) {
			found = 1;
			break;
1036 1037 1038 1039
		}
	}

	if (!found)
1040
		sprintf(name, "%pM Gigabit Ethernet", adapter->mac_addr);
1041 1042 1043
	else
		sprintf(name, "%pM: %s" , adapter->mac_addr,
			qlcnic_boards[i].short_name);
1044 1045 1046 1047 1048
}

static void
qlcnic_check_options(struct qlcnic_adapter *adapter)
{
1049
	int err;
1050
	u32 fw_major, fw_minor, fw_build, prev_fw_version;
1051
	struct pci_dev *pdev = adapter->pdev;
1052 1053
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	struct qlcnic_fw_dump *fw_dump = &ahw->fw_dump;
1054 1055

	prev_fw_version = adapter->fw_version;
1056

1057 1058 1059
	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);
1060 1061 1062

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

1063 1064 1065 1066 1067 1068
	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) {
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
		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 已提交
1079 1080 1081
	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 已提交
1082
	if (adapter->ahw->port_type == QLCNIC_XGBE) {
S
Sony Chacko 已提交
1083 1084 1085 1086 1087 1088 1089 1090
		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;
		}

1091
		adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
S
Sony Chacko 已提交
1092 1093
		adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;

A
Anirban Chakraborty 已提交
1094
	} else if (adapter->ahw->port_type == QLCNIC_GBE) {
1095 1096
		adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
		adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
S
Sony Chacko 已提交
1097 1098
		adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
		adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;
1099 1100
	}

1101
	adapter->ahw->msix_supported = !!qlcnic_use_msi_x;
1102 1103 1104

	adapter->num_txd = MAX_CMD_DESCRIPTORS;

1105
	adapter->max_rds_rings = MAX_RDS_RINGS;
1106 1107
}

1108 1109 1110 1111
static int
qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
{
	struct qlcnic_info nic_info;
1112
	int err = 0;
1113

1114
	memset(&nic_info, 0, sizeof(struct qlcnic_info));
A
Anirban Chakraborty 已提交
1115
	err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw->pci_func);
1116 1117 1118
	if (err)
		return err;

1119 1120 1121 1122 1123
	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;
1124 1125 1126

	if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
		u32 temp;
1127 1128 1129
		temp = QLCRD32(adapter, CRB_FW_CAPABILITIES_2, &err);
		if (err == -EIO)
			return err;
1130
		adapter->ahw->extra_capability[0] = temp;
1131
	}
1132 1133
	adapter->ahw->max_mac_filters = nic_info.max_mac_filters;
	adapter->ahw->max_mtu = nic_info.max_mtu;
1134

S
Sony Chacko 已提交
1135 1136 1137 1138
	/* Disable NPAR for 83XX */
	if (qlcnic_83xx_check(adapter))
		return err;

1139
	if (adapter->ahw->capabilities & BIT_6)
1140 1141 1142 1143 1144 1145 1146
		adapter->flags |= QLCNIC_ESWITCH_ENABLED;
	else
		adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;

	return err;
}

1147 1148
void qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
			    struct qlcnic_esw_func_cfg *esw_cfg)
1149 1150 1151 1152 1153 1154
{
	if (esw_cfg->discard_tagged)
		adapter->flags &= ~QLCNIC_TAGGING_ENABLED;
	else
		adapter->flags |= QLCNIC_TAGGING_ENABLED;

1155 1156 1157 1158 1159 1160 1161
	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;
	}
1162 1163
}

1164
static int
1165
qlcnic_vlan_rx_add(struct net_device *netdev, __be16 proto, u16 vid)
1166 1167
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
	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;
		}
	}

1180
	set_bit(vid, adapter->vlans);
1181
	return 0;
1182 1183
}

1184
static int
1185
qlcnic_vlan_rx_del(struct net_device *netdev, __be16 proto, u16 vid)
1186 1187
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
	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;
		}
	}
1199 1200 1201

	qlcnic_restore_indev_addr(netdev, NETDEV_DOWN);
	clear_bit(vid, adapter->vlans);
1202
	return 0;
1203 1204
}

1205 1206
void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
				      struct qlcnic_esw_func_cfg *esw_cfg)
1207
{
1208 1209
	adapter->flags &= ~(QLCNIC_MACSPOOF | QLCNIC_MAC_OVERRIDE_DISABLED |
				QLCNIC_PROMISC_DISABLED);
1210 1211 1212

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

1214 1215 1216
	if (!esw_cfg->mac_override)
		adapter->flags |= QLCNIC_MAC_OVERRIDE_DISABLED;

1217 1218
	if (!esw_cfg->promisc_mode)
		adapter->flags |= QLCNIC_PROMISC_DISABLED;
1219 1220
}

1221
int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
1222 1223 1224 1225 1226 1227
{
	struct qlcnic_esw_func_cfg esw_cfg;

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

A
Anirban Chakraborty 已提交
1228
	esw_cfg.pci_func = adapter->ahw->pci_func;
1229 1230
	if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg))
			return -EIO;
1231
	qlcnic_set_vlan_config(adapter, &esw_cfg);
1232
	qlcnic_set_eswitch_port_features(adapter, &esw_cfg);
1233
	qlcnic_set_netdev_features(adapter, &esw_cfg);
1234 1235 1236 1237

	return 0;
}

1238 1239
void qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
				struct qlcnic_esw_func_cfg *esw_cfg)
1240 1241
{
	struct net_device *netdev = adapter->netdev;
S
Sony Chacko 已提交
1242 1243 1244

	if (qlcnic_83xx_check(adapter))
		return;
1245

1246 1247 1248 1249
	adapter->offload_flags = esw_cfg->offload_flags;
	adapter->flags |= QLCNIC_APP_CHANGED_FLAGS;
	netdev_update_features(netdev);
	adapter->flags &= ~QLCNIC_APP_CHANGED_FLAGS;
1250 1251
}

1252 1253 1254 1255 1256 1257
static int
qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
{
	u32 op_mode, priv_level;
	int err = 0;

1258 1259 1260 1261
	err = qlcnic_initialize_nic(adapter);
	if (err)
		return err;

1262 1263 1264
	if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED)
		return 0;

S
Sony Chacko 已提交
1265
	op_mode = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE);
A
Anirban Chakraborty 已提交
1266
	priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
1267 1268 1269 1270

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

1273
	if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
1274
		if (priv_level == QLCNIC_MGMT_FUNC) {
1275
			adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
1276 1277 1278 1279 1280 1281 1282
			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",
1283
				 adapter->ahw->fw_hal_version);
1284
		} else if (priv_level == QLCNIC_PRIV_FUNC) {
1285
			adapter->ahw->op_mode = QLCNIC_PRIV_FUNC;
1286 1287
			dev_info(&adapter->pdev->dev,
				"HAL Version: %d, Privileged function\n",
1288
				 adapter->ahw->fw_hal_version);
1289
		}
1290
	}
1291 1292 1293 1294 1295 1296

	adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;

	return err;
}

1297
int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
1298 1299 1300 1301 1302
{
	struct qlcnic_esw_func_cfg esw_cfg;
	struct qlcnic_npar_info *npar;
	u8 i;

1303
	if (adapter->need_fw_reset)
1304 1305
		return 0;

1306
	for (i = 0; i < adapter->ahw->act_pci_func; i++) {
1307 1308 1309
		if (!adapter->npars[i].eswitch_status)
			continue;

1310
		memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg));
1311
		esw_cfg.pci_func = adapter->npars[i].pci_func;
1312
		esw_cfg.mac_override = BIT_0;
1313
		esw_cfg.promisc_mode = BIT_0;
1314 1315 1316 1317 1318
		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);
		}
1319 1320 1321 1322
		if (qlcnic_config_switch_port(adapter, &esw_cfg))
			return -EIO;
		npar = &adapter->npars[i];
		npar->pvid = esw_cfg.vlan_id;
1323
		npar->mac_override = esw_cfg.mac_override;
1324 1325 1326 1327 1328 1329 1330 1331 1332
		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 已提交
1333

1334 1335 1336 1337 1338 1339 1340 1341
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;
1342
	esw_cfg.mac_override = npar->mac_override;
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356
	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;
}

1357
int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
1358
{
1359
	int i, err;
1360 1361
	struct qlcnic_npar_info *npar;
	struct qlcnic_info nic_info;
1362
	u8 pci_func;
1363

1364 1365 1366
	if (qlcnic_82xx_check(adapter))
		if (!adapter->need_fw_reset)
			return 0;
1367

1368
	/* Set the NPAR config data after FW reset */
1369
	for (i = 0; i < adapter->ahw->act_pci_func; i++) {
1370
		npar = &adapter->npars[i];
1371
		pci_func = npar->pci_func;
1372 1373 1374
		if (!adapter->npars[i].eswitch_status)
			continue;

1375
		memset(&nic_info, 0, sizeof(struct qlcnic_info));
S
Sony Chacko 已提交
1376
		err = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
1377 1378 1379 1380 1381 1382 1383
		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;
1384

1385 1386
		if (npar->enable_pm) {
			err = qlcnic_config_port_mirroring(adapter,
1387 1388
							   npar->dest_npar, 1,
							   pci_func);
1389 1390
			if (err)
				return err;
1391
		}
1392
		err = qlcnic_reset_eswitch_config(adapter, npar, pci_func);
1393 1394
		if (err)
			return err;
1395
	}
1396
	return 0;
1397 1398
}

A
Amit Kumar Salecha 已提交
1399 1400 1401 1402 1403
static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter)
{
	u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO;
	u32 npar_state;

1404
	if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
A
Amit Kumar Salecha 已提交
1405 1406
		return 0;

1407 1408
	npar_state = QLC_SHARED_REG_RD32(adapter,
					 QLCNIC_CRB_DEV_NPAR_STATE);
A
Amit Kumar Salecha 已提交
1409 1410
	while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) {
		msleep(1000);
1411 1412
		npar_state = QLC_SHARED_REG_RD32(adapter,
						 QLCNIC_CRB_DEV_NPAR_STATE);
A
Amit Kumar Salecha 已提交
1413 1414 1415
	}
	if (!npar_opt_timeo) {
		dev_err(&adapter->pdev->dev,
1416
			"Waiting for NPAR state to operational timeout\n");
A
Amit Kumar Salecha 已提交
1417 1418 1419 1420 1421
		return -EIO;
	}
	return 0;
}

1422 1423 1424 1425 1426 1427
static int
qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter)
{
	int err;

	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
1428
	    adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443
		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;
}

1444
int qlcnic_82xx_start_firmware(struct qlcnic_adapter *adapter)
1445
{
1446
	int err;
1447

1448 1449 1450 1451
	err = qlcnic_can_start_firmware(adapter);
	if (err < 0)
		return err;
	else if (!err)
1452
		goto check_fw_status;
1453

1454
	if (qlcnic_load_fw_file)
1455
		qlcnic_request_firmware(adapter);
S
schacko 已提交
1456
	else {
S
Sony Chacko 已提交
1457 1458
		err = qlcnic_check_flash_fw_ver(adapter);
		if (err)
S
schacko 已提交
1459 1460
			goto err_out;

1461
		adapter->ahw->fw_type = QLCNIC_FLASH_ROMIMAGE;
S
schacko 已提交
1462
	}
1463 1464 1465

	err = qlcnic_need_fw_reset(adapter);
	if (err == 0)
1466
		goto check_fw_status;
1467

1468 1469 1470
	err = qlcnic_pinit_from_rom(adapter);
	if (err)
		goto err_out;
1471 1472 1473 1474 1475 1476

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

	qlcnic_release_firmware(adapter);
1477
	QLCWR32(adapter, CRB_DRIVER_VERSION, QLCNIC_DRIVER_VERSION);
1478

1479 1480
check_fw_status:
	err = qlcnic_check_fw_status(adapter);
1481 1482 1483
	if (err)
		goto err_out;

1484
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
1485
	qlcnic_idc_debug_info(adapter, 1);
1486 1487 1488 1489 1490 1491
	err = qlcnic_check_eswitch_mode(adapter);
	if (err) {
		dev_err(&adapter->pdev->dev,
			"Memory allocation failed for eswitch\n");
		goto err_out;
	}
1492 1493 1494 1495 1496
	err = qlcnic_set_mgmt_operations(adapter);
	if (err)
		goto err_out;

	qlcnic_check_options(adapter);
1497 1498
	adapter->need_fw_reset = 0;

1499 1500
	qlcnic_release_firmware(adapter);
	return 0;
1501 1502

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

1506 1507 1508 1509 1510 1511 1512 1513 1514
	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 已提交
1515
	struct qlcnic_host_tx_ring *tx_ring;
1516
	int err, ring, num_sds_rings;
1517 1518 1519

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

1522
	if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
S
Sony Chacko 已提交
1523 1524
		if (qlcnic_82xx_check(adapter))
			handler = qlcnic_tmp_intr;
1525 1526
		else
			handler = qlcnic_83xx_tmp_intr;
1527 1528 1529 1530 1531 1532 1533 1534 1535 1536
		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;
1537 1538 1539 1540
			if (qlcnic_82xx_check(adapter))
				handler = qlcnic_intr;
			else
				handler = qlcnic_83xx_intr;
1541
		}
1542 1543 1544
	}
	adapter->irq = netdev->irq;

S
Sony Chacko 已提交
1545
	if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) {
1546 1547 1548
		if (qlcnic_82xx_check(adapter) ||
		    (qlcnic_83xx_check(adapter) &&
		     (adapter->flags & QLCNIC_MSIX_ENABLED))) {
1549 1550
			num_sds_rings = adapter->max_sds_rings;
			for (ring = 0; ring < num_sds_rings; ring++) {
1551
				sds_ring = &recv_ctx->sds_rings[ring];
1552
				if (qlcnic_82xx_check(adapter) &&
1553
				    !qlcnic_check_multi_tx(adapter) &&
1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565
				    (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 {
1566 1567
					snprintf(sds_ring->name,
						 sizeof(sds_ring->name),
1568
						 "%s-rx-%d",
1569
						 netdev->name, ring);
1570
				}
1571 1572 1573 1574 1575
				err = request_irq(sds_ring->irq, handler, flags,
						  sds_ring->name, sds_ring);
				if (err)
					return err;
			}
S
Sony Chacko 已提交
1576
		}
1577 1578 1579 1580 1581
		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 已提交
1582 1583 1584 1585
			handler = qlcnic_msix_tx_intr;
			for (ring = 0; ring < adapter->max_drv_tx_rings;
			     ring++) {
				tx_ring = &adapter->tx_ring[ring];
1586
				snprintf(tx_ring->name, sizeof(tx_ring->name),
1587
					 "%s-tx-%d", netdev->name, ring);
S
Sony Chacko 已提交
1588 1589 1590 1591 1592 1593
				err = request_irq(tx_ring->irq, handler, flags,
						  tx_ring->name, tx_ring);
				if (err)
					return err;
			}
		}
1594 1595 1596 1597 1598 1599 1600 1601 1602
	}
	return 0;
}

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

A
Anirban Chakraborty 已提交
1605
	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1606

S
Sony Chacko 已提交
1607
	if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) {
1608 1609 1610 1611 1612 1613 1614
		if (qlcnic_82xx_check(adapter) ||
		    (qlcnic_83xx_check(adapter) &&
		     (adapter->flags & QLCNIC_MSIX_ENABLED))) {
			for (ring = 0; ring < adapter->max_sds_rings; ring++) {
				sds_ring = &recv_ctx->sds_rings[ring];
				free_irq(sds_ring->irq, sds_ring);
			}
S
Sony Chacko 已提交
1615
		}
1616 1617 1618 1619
		if ((qlcnic_83xx_check(adapter) &&
		     !(adapter->flags & QLCNIC_TX_INTR_SHARED)) ||
		    (qlcnic_82xx_check(adapter) &&
		     qlcnic_check_multi_tx(adapter))) {
S
Sony Chacko 已提交
1620 1621 1622 1623 1624 1625 1626
			for (ring = 0; ring < adapter->max_drv_tx_rings;
			     ring++) {
				tx_ring = &adapter->tx_ring[ring];
				if (tx_ring->irq)
					free_irq(tx_ring->irq, tx_ring);
			}
		}
1627 1628 1629
	}
}

1630 1631 1632 1633 1634
static void qlcnic_get_lro_mss_capability(struct qlcnic_adapter *adapter)
{
	u32 capab = 0;

	if (qlcnic_82xx_check(adapter)) {
1635
		if (adapter->ahw->extra_capability[0] &
1636 1637 1638 1639 1640 1641 1642 1643 1644
		    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;
	}
}

S
Sony Chacko 已提交
1645
int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
1646
{
1647 1648 1649
	int ring;
	struct qlcnic_host_rds_ring *rds_ring;

1650 1651 1652
	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
		return -EIO;

1653 1654
	if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
		return 0;
1655

1656 1657
	if (qlcnic_set_eswitch_port_config(adapter))
		return -EIO;
1658

1659
	qlcnic_get_lro_mss_capability(adapter);
1660

1661 1662 1663 1664
	if (qlcnic_fw_create_ctx(adapter))
		return -EIO;

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

1669 1670 1671
	qlcnic_set_multi(netdev);
	qlcnic_fw_cmd_set_mtu(adapter, netdev->mtu);

A
Anirban Chakraborty 已提交
1672
	adapter->ahw->linkup = 0;
1673 1674 1675 1676 1677 1678

	if (adapter->max_sds_rings > 1)
		qlcnic_config_rss(adapter, 1);

	qlcnic_config_intr_coalesce(adapter);

1679
	if (netdev->features & NETIF_F_LRO)
1680 1681
		qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED);

1682
	set_bit(__QLCNIC_DEV_UP, &adapter->state);
1683 1684 1685 1686
	qlcnic_napi_enable(adapter);

	qlcnic_linkevent_request(adapter, 1);

1687
	adapter->ahw->reset_context = 0;
1688 1689 1690
	return 0;
}

1691
int qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702
{
	int err = 0;

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

	return err;
}

S
Sony Chacko 已提交
1703
void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
1704
{
1705 1706
	int ring;

1707 1708 1709 1710 1711 1712
	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
		return;

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

1713 1714
	if (qlcnic_sriov_vf_check(adapter))
		qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
1715 1716
	smp_mb();
	netif_carrier_off(netdev);
1717
	adapter->ahw->linkup = 0;
1718 1719 1720 1721
	netif_tx_disable(netdev);

	qlcnic_free_mac_list(adapter);

1722 1723 1724
	if (adapter->fhash.fnum)
		qlcnic_delete_lb_filters(adapter);

1725 1726 1727 1728
	qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE);

	qlcnic_napi_disable(adapter);

1729
	qlcnic_fw_destroy_ctx(adapter);
1730
	adapter->flags &= ~QLCNIC_FW_LRO_MSS_CAP;
1731 1732

	qlcnic_reset_rx_buffers_list(adapter);
1733 1734 1735

	for (ring = 0; ring < adapter->max_drv_tx_rings; ring++)
		qlcnic_release_tx_buffers(adapter, &adapter->tx_ring[ring]);
1736 1737 1738 1739
}

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

1740
void qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
1741 1742 1743 1744 1745 1746 1747 1748
{
	rtnl_lock();
	if (netif_running(netdev))
		__qlcnic_down(adapter, netdev);
	rtnl_unlock();

}

S
Sony Chacko 已提交
1749
int
1750 1751 1752 1753
qlcnic_attach(struct qlcnic_adapter *adapter)
{
	struct net_device *netdev = adapter->netdev;
	struct pci_dev *pdev = adapter->pdev;
1754
	int err;
1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765

	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");
1766
		goto err_out_napi_del;
1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777
	}

	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");
1778
		goto err_out_free_hw;
1779 1780 1781 1782 1783 1784 1785
	}

	qlcnic_create_sysfs_entries(adapter);

	adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC;
	return 0;

1786
err_out_free_hw:
1787 1788 1789
	qlcnic_free_hw_resources(adapter);
err_out_free_sw:
	qlcnic_free_sw_resources(adapter);
1790 1791
err_out_napi_del:
	qlcnic_napi_del(adapter);
1792 1793 1794
	return err;
}

S
Sony Chacko 已提交
1795
void qlcnic_detach(struct qlcnic_adapter *adapter)
1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810
{
	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;
}

1811 1812 1813 1814
void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct qlcnic_host_sds_ring *sds_ring;
1815
	int max_tx_rings = adapter->max_drv_tx_rings;
1816 1817
	int ring;

1818
	clear_bit(__QLCNIC_DEV_UP, &adapter->state);
1819
	if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
1820
		for (ring = 0; ring < adapter->max_sds_rings; ring++) {
A
Anirban Chakraborty 已提交
1821
			sds_ring = &adapter->recv_ctx->sds_rings[ring];
1822
			qlcnic_disable_int(sds_ring);
1823
		}
1824 1825
	}

1826 1827
	qlcnic_fw_destroy_ctx(adapter);

1828 1829
	qlcnic_detach(adapter);

1830
	adapter->ahw->diag_test = 0;
1831
	adapter->max_sds_rings = max_sds_rings;
1832
	adapter->max_drv_tx_rings = max_tx_rings;
1833 1834

	if (qlcnic_attach(adapter))
1835
		goto out;
1836 1837 1838

	if (netif_running(netdev))
		__qlcnic_up(adapter, netdev);
1839
out:
1840 1841 1842
	netif_device_attach(netdev);
}

A
Anirban Chakraborty 已提交
1843 1844
static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
{
1845
	struct qlcnic_hardware_context *ahw = adapter->ahw;
A
Anirban Chakraborty 已提交
1846
	int err = 0;
1847

A
Anirban Chakraborty 已提交
1848 1849 1850 1851
	adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context),
				GFP_KERNEL);
	if (!adapter->recv_ctx) {
		err = -ENOMEM;
A
Anirban Chakraborty 已提交
1852
		goto err_out;
A
Anirban Chakraborty 已提交
1853
	}
A
Anirban Chakraborty 已提交
1854
	/* Initialize interrupt coalesce parameters */
1855 1856 1857 1858 1859 1860 1861 1862
	ahw->coal.flag = QLCNIC_INTR_DEFAULT;
	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;
	if (qlcnic_83xx_check(adapter)) {
		ahw->coal.tx_time_us = QLCNIC_DEF_INTR_COALESCE_TX_TIME_US;
		ahw->coal.tx_packets = QLCNIC_DEF_INTR_COALESCE_TX_PACKETS;
	}
S
Sony Chacko 已提交
1863 1864
	/* clear stats */
	memset(&adapter->stats, 0, sizeof(adapter->stats));
A
Anirban Chakraborty 已提交
1865 1866 1867 1868 1869 1870 1871 1872 1873
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 已提交
1874 1875 1876 1877
	if (adapter->ahw->fw_dump.tmpl_hdr) {
		vfree(adapter->ahw->fw_dump.tmpl_hdr);
		adapter->ahw->fw_dump.tmpl_hdr = NULL;
	}
S
Sony Chacko 已提交
1878

1879
	kfree(adapter->ahw->reset.buff);
S
Sony Chacko 已提交
1880
	adapter->ahw->fw_dump.tmpl_hdr = NULL;
A
Anirban Chakraborty 已提交
1881 1882
}

1883 1884 1885 1886
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;
1887
	struct qlcnic_host_rds_ring *rds_ring;
1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898
	int ring;
	int ret;

	netif_device_detach(netdev);

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

	qlcnic_detach(adapter);

	adapter->max_sds_rings = 1;
1899
	adapter->ahw->diag_test = test;
S
Sony Chacko 已提交
1900
	adapter->ahw->linkup = 0;
1901
	adapter->max_drv_tx_rings = 1;
1902 1903

	ret = qlcnic_attach(adapter);
1904 1905
	if (ret) {
		netif_device_attach(netdev);
1906
		return ret;
1907
	}
1908

1909 1910 1911
	ret = qlcnic_fw_create_ctx(adapter);
	if (ret) {
		qlcnic_detach(adapter);
1912
		netif_device_attach(netdev);
1913 1914 1915 1916
		return ret;
	}

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

1921
	if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
1922
		for (ring = 0; ring < adapter->max_sds_rings; ring++) {
A
Anirban Chakraborty 已提交
1923
			sds_ring = &adapter->recv_ctx->sds_rings[ring];
1924
			qlcnic_enable_int(sds_ring);
1925
		}
1926
	}
1927

1928
	if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
1929 1930 1931 1932
		adapter->ahw->loopback_state = 0;
		qlcnic_linkevent_request(adapter, 1);
	}

1933
	set_bit(__QLCNIC_DEV_UP, &adapter->state);
1934 1935 1936 1937

	return 0;
}

1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955
/* 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);
S
Sony Chacko 已提交
1956
	dev_err(&adapter->pdev->dev, "%s:\n", __func__);
1957 1958 1959
	return 0;
}

1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979
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 已提交
1980
			if (!err) {
1981
				__qlcnic_up(adapter, netdev);
A
Anirban Chakraborty 已提交
1982 1983
				qlcnic_restore_indev_addr(netdev, NETDEV_UP);
			}
1984 1985 1986 1987 1988 1989 1990 1991 1992
		}

		netif_device_attach(netdev);
	}

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

1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008
void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	u16 act_pci_fn = ahw->act_pci_func;
	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 已提交
2009
int
S
Sony Chacko 已提交
2010 2011
qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
		    int pci_using_dac)
2012 2013 2014 2015
{
	int err;
	struct pci_dev *pdev = adapter->pdev;

S
Sony Chacko 已提交
2016
	adapter->rx_csum = 1;
2017
	adapter->ahw->mc_enabled = 0;
2018
	qlcnic_set_mac_filter_count(adapter);
2019 2020

	netdev->netdev_ops	   = &qlcnic_netdev_ops;
S
Sony Chacko 已提交
2021
	netdev->watchdog_timeo     = QLCNIC_WATCHDOG_TIMEOUTVALUE * HZ;
2022 2023 2024

	qlcnic_change_mtu(netdev, netdev->mtu);

2025 2026 2027 2028
	if (qlcnic_sriov_vf_check(adapter))
		SET_ETHTOOL_OPS(netdev, &qlcnic_sriov_vf_ethtool_ops);
	else
		SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
2029

2030
	netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
S
Sony Chacko 已提交
2031
			     NETIF_F_IPV6_CSUM | NETIF_F_GRO |
2032
			     NETIF_F_HW_VLAN_CTAG_RX);
S
Sony Chacko 已提交
2033 2034
	netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
				  NETIF_F_IPV6_CSUM);
2035

S
Sony Chacko 已提交
2036 2037 2038 2039
	if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
		netdev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
		netdev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
	}
2040

S
Sony Chacko 已提交
2041 2042 2043 2044
	if (pci_using_dac) {
		netdev->features |= NETIF_F_HIGHDMA;
		netdev->vlan_features |= NETIF_F_HIGHDMA;
	}
2045

S
Sony Chacko 已提交
2046
	if (qlcnic_vlan_tx_check(adapter))
2047
		netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX);
2048

2049 2050 2051
	if (qlcnic_sriov_vf_check(adapter))
		netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;

S
Sony Chacko 已提交
2052 2053
	if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
		netdev->features |= NETIF_F_LRO;
2054

2055
	netdev->hw_features = netdev->features;
2056
	netdev->priv_flags |= IFF_UNICAST_FLT;
2057 2058
	netdev->irq = adapter->msix_entries[0].vector;

2059 2060 2061
	err = qlcnic_set_real_num_queues(adapter, netdev);
	if (err)
		return err;
2062

2063 2064 2065 2066 2067 2068
	err = register_netdev(netdev);
	if (err) {
		dev_err(&pdev->dev, "failed to register net device\n");
		return err;
	}

2069 2070
	qlcnic_dcb_init_dcbnl_ops(adapter);

2071 2072 2073
	return 0;
}

S
Sony Chacko 已提交
2074
static int qlcnic_set_dma_mask(struct pci_dev *pdev, int *pci_using_dac)
2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089
{
	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 已提交
2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108
void qlcnic_free_tx_rings(struct qlcnic_adapter *adapter)
{
	int ring;
	struct qlcnic_host_tx_ring *tx_ring;

	for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
		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)
{
2109
	int ring, vector, index;
S
Sony Chacko 已提交
2110 2111 2112
	struct qlcnic_host_tx_ring *tx_ring;
	struct qlcnic_cmd_buffer *cmd_buf_arr;

2113 2114 2115
	tx_ring = kcalloc(adapter->max_drv_tx_rings,
			  sizeof(struct qlcnic_host_tx_ring), GFP_KERNEL);
	if (tx_ring == NULL)
S
Sony Chacko 已提交
2116
		return -ENOMEM;
2117

S
Sony Chacko 已提交
2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132
	adapter->tx_ring = tx_ring;

	for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
		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;
	}

2133 2134
	if (qlcnic_83xx_check(adapter) ||
	    (qlcnic_82xx_check(adapter) && qlcnic_check_multi_tx(adapter))) {
S
Sony Chacko 已提交
2135 2136 2137 2138 2139 2140 2141 2142 2143 2144
		for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
			tx_ring = &adapter->tx_ring[ring];
			tx_ring->adapter = adapter;
			if (adapter->flags & QLCNIC_MSIX_ENABLED) {
				index = adapter->max_sds_rings + ring;
				vector = adapter->msix_entries[index].vector;
				tx_ring->irq = vector;
			}
		}
	}
2145

S
Sony Chacko 已提交
2146 2147 2148
	return 0;
}

2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163
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;

	if ((ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) &&
	    (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_SET_DRV_VER))
		qlcnic_fw_cmd_set_drv_version(adapter, fw_cmd);
}

2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174
static int qlcnic_register_dcb(struct qlcnic_adapter *adapter)
{
	return __qlcnic_register_dcb(adapter);
}

void qlcnic_clear_dcb_ops(struct qlcnic_adapter *adapter)
{
	kfree(adapter->dcb);
	adapter->dcb = NULL;
}

B
Bill Pemberton 已提交
2175
static int
2176 2177 2178 2179
qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct net_device *netdev = NULL;
	struct qlcnic_adapter *adapter = NULL;
2180
	struct qlcnic_hardware_context *ahw;
S
Sony Chacko 已提交
2181
	int err, pci_using_dac = -1;
2182
	char board_name[QLCNIC_MAX_BOARD_NAME_LEN + 19]; /* MAC + ": " + name */
2183

R
Rajesh Borundia 已提交
2184 2185 2186
	if (pdev->is_virtfn)
		return -ENODEV;

2187 2188 2189 2190 2191 2192 2193 2194 2195
	err = pci_enable_device(pdev);
	if (err)
		return err;

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

2196 2197 2198 2199
	err = qlcnic_set_dma_mask(pdev, &pci_using_dac);
	if (err)
		goto err_out_disable_pdev;

2200 2201 2202 2203 2204
	err = pci_request_regions(pdev, qlcnic_driver_name);
	if (err)
		goto err_out_disable_pdev;

	pci_set_master(pdev);
S
Sucheta Chakraborty 已提交
2205
	pci_enable_pcie_error_reporting(pdev);
2206

2207
	ahw = kzalloc(sizeof(struct qlcnic_hardware_context), GFP_KERNEL);
2208 2209
	if (!ahw) {
		err = -ENOMEM;
2210
		goto err_out_free_res;
2211
	}
2212

R
Rajesh Borundia 已提交
2213 2214
	switch (ent->device) {
	case PCI_DEVICE_ID_QLOGIC_QLE824X:
2215
		ahw->hw_ops = &qlcnic_hw_ops;
R
Rajesh Borundia 已提交
2216 2217 2218
		ahw->reg_tbl = (u32 *) qlcnic_reg_tbl;
		break;
	case PCI_DEVICE_ID_QLOGIC_QLE834X:
2219
	case PCI_DEVICE_ID_QLOGIC_QLE844X:
S
Sony Chacko 已提交
2220
		qlcnic_83xx_register_map(ahw);
R
Rajesh Borundia 已提交
2221 2222
		break;
	case PCI_DEVICE_ID_QLOGIC_VF_QLE834X:
2223
	case PCI_DEVICE_ID_QLOGIC_VF_QLE844X:
R
Rajesh Borundia 已提交
2224 2225 2226
		qlcnic_sriov_vf_register_map(ahw);
		break;
	default:
S
Sony Chacko 已提交
2227
		goto err_out_free_hw_res;
2228 2229 2230 2231 2232 2233
	}

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

2234 2235
	netdev = alloc_etherdev_mq(sizeof(struct qlcnic_adapter),
				   QLCNIC_MAX_TX_RINGS);
2236 2237
	if (!netdev) {
		err = -ENOMEM;
2238
		goto err_out_iounmap;
2239 2240 2241 2242 2243 2244 2245
	}

	SET_NETDEV_DEV(netdev, &pdev->dev);

	adapter = netdev_priv(netdev);
	adapter->netdev  = netdev;
	adapter->pdev    = pdev;
S
Sony Chacko 已提交
2246 2247 2248 2249
	adapter->ahw = ahw;

	adapter->qlcnic_wq = create_singlethread_workqueue("qlcnic");
	if (adapter->qlcnic_wq == NULL) {
2250
		err = -ENOMEM;
S
Sony Chacko 已提交
2251 2252 2253
		dev_err(&pdev->dev, "Failed to create workqueue\n");
		goto err_out_free_netdev;
	}
2254

2255 2256
	err = qlcnic_alloc_adapter_resources(adapter);
	if (err)
A
Anirban Chakraborty 已提交
2257 2258 2259
		goto err_out_free_netdev;

	adapter->dev_rst_time = jiffies;
2260
	adapter->ahw->revision_id = pdev->revision;
2261 2262 2263 2264
	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;
2265

A
Anirban Chakraborty 已提交
2266 2267
	rwlock_init(&adapter->ahw->crb_lock);
	mutex_init(&adapter->ahw->mem_lock);
2268 2269 2270

	INIT_LIST_HEAD(&adapter->mac_list);

2271 2272
	qlcnic_register_dcb(adapter);

2273
	if (qlcnic_82xx_check(adapter)) {
S
Sony Chacko 已提交
2274
		qlcnic_check_vf(adapter, ent);
2275 2276 2277 2278 2279 2280
		adapter->portnum = adapter->ahw->pci_func;
		err = qlcnic_start_firmware(adapter);
		if (err) {
			dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n");
			goto err_out_free_hw;
		}
2281

2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295
		qlcnic_get_multiq_capability(adapter);

		if ((adapter->ahw->act_pci_func > 2) &&
		    qlcnic_check_multi_tx(adapter)) {
			adapter->max_drv_tx_rings = QLCNIC_DEF_NUM_TX_RINGS;
			dev_info(&adapter->pdev->dev,
				 "vNIC mode enabled, Set max TX rings = %d\n",
				 adapter->max_drv_tx_rings);
		}

		if (!qlcnic_check_multi_tx(adapter)) {
			clear_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state);
			adapter->max_drv_tx_rings = 1;
		}
2296 2297 2298
		err = qlcnic_setup_idc_param(adapter);
		if (err)
			goto err_out_free_hw;
2299

2300
		adapter->flags |= QLCNIC_NEED_FLR;
2301 2302 2303 2304

		if (adapter->dcb && qlcnic_dcb_attach(adapter))
			qlcnic_clear_dcb_ops(adapter);

S
Sony Chacko 已提交
2305
	} else if (qlcnic_83xx_check(adapter)) {
2306
		adapter->max_drv_tx_rings = 1;
S
Sony Chacko 已提交
2307 2308
		qlcnic_83xx_check_vf(adapter, ent);
		adapter->portnum = adapter->ahw->pci_func;
R
Rajesh Borundia 已提交
2309
		err = qlcnic_83xx_init(adapter, pci_using_dac);
2310 2311 2312 2313
		if (err) {
			dev_err(&pdev->dev, "%s: failed\n", __func__);
			goto err_out_free_hw;
		}
R
Rajesh Borundia 已提交
2314 2315
		if (qlcnic_sriov_vf_check(adapter))
			return 0;
S
Sony Chacko 已提交
2316 2317 2318 2319
	} else {
		dev_err(&pdev->dev,
			"%s: failed. Please Reboot\n", __func__);
		goto err_out_free_hw;
2320
	}
2321

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

2325 2326
	qlcnic_read_phys_port_id(adapter);

R
Rajesh Borundia 已提交
2327
	if (adapter->portnum == 0) {
S
Sony Chacko 已提交
2328
		qlcnic_get_board_name(adapter, board_name);
S
Sony Chacko 已提交
2329

R
Rajesh Borundia 已提交
2330
		pr_info("%s: %s Board Chip rev 0x%x\n",
S
Sony Chacko 已提交
2331 2332
			module_name(THIS_MODULE),
			board_name, adapter->ahw->revision_id);
R
Rajesh Borundia 已提交
2333
	}
2334 2335 2336 2337

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

2340
	if (qlcnic_82xx_check(adapter)) {
2341
		err = qlcnic_setup_intr(adapter, 0, 0);
2342 2343
		if (err) {
			dev_err(&pdev->dev, "Failed to setup interrupt\n");
S
Sony Chacko 已提交
2344
			goto err_out_disable_msi;
2345
		}
S
Sony Chacko 已提交
2346
	}
2347

2348 2349 2350 2351
	err = qlcnic_get_act_pci_func(adapter);
	if (err)
		goto err_out_disable_mbx_intr;

2352
	err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac);
2353
	if (err)
2354
		goto err_out_disable_mbx_intr;
2355

2356 2357
	if (adapter->portnum == 0)
		qlcnic_set_drv_version(adapter);
2358

2359 2360
	pci_set_drvdata(pdev, adapter);

2361 2362 2363
	if (qlcnic_82xx_check(adapter))
		qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
				     FW_POLL_DELAY);
2364

A
Anirban Chakraborty 已提交
2365
	switch (adapter->ahw->port_type) {
2366 2367 2368 2369 2370 2371 2372 2373 2374 2375
	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;
	}

2376
	if (adapter->drv_mac_learn)
2377 2378
		qlcnic_alloc_lb_filters_mem(adapter);

2379
	qlcnic_add_sysfs(adapter);
2380 2381 2382

	return 0;

2383
err_out_disable_mbx_intr:
2384
	if (qlcnic_83xx_check(adapter))
S
Sony Chacko 已提交
2385
		qlcnic_83xx_free_mbx_intr(adapter);
2386

2387 2388
err_out_disable_msi:
	qlcnic_teardown_intr(adapter);
2389
	qlcnic_cancel_idc_work(adapter);
2390
	qlcnic_clr_all_drv_state(adapter, 0);
2391

A
Anirban Chakraborty 已提交
2392 2393 2394
err_out_free_hw:
	qlcnic_free_adapter_resources(adapter);

2395 2396 2397
err_out_free_netdev:
	free_netdev(netdev);

2398
err_out_iounmap:
2399
	qlcnic_cleanup_pci_map(ahw);
2400 2401 2402 2403

err_out_free_hw_res:
	kfree(ahw);

2404 2405 2406 2407 2408 2409 2410 2411 2412
err_out_free_res:
	pci_release_regions(pdev);

err_out_disable_pdev:
	pci_set_drvdata(pdev, NULL);
	pci_disable_device(pdev);
	return err;
}

B
Bill Pemberton 已提交
2413
static void qlcnic_remove(struct pci_dev *pdev)
2414 2415 2416
{
	struct qlcnic_adapter *adapter;
	struct net_device *netdev;
S
Sony Chacko 已提交
2417
	struct qlcnic_hardware_context *ahw;
2418 2419 2420 2421 2422 2423

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

	netdev = adapter->netdev;
2424
	qlcnic_sriov_pf_disable(adapter);
2425

S
Sony Chacko 已提交
2426 2427
	qlcnic_cancel_idc_work(adapter);
	ahw = adapter->ahw;
2428

2429 2430
	qlcnic_dcb_free(adapter);

2431
	unregister_netdev(netdev);
2432
	qlcnic_sriov_cleanup(adapter);
2433

S
Sony Chacko 已提交
2434
	if (qlcnic_83xx_check(adapter)) {
2435 2436
		qlcnic_83xx_register_nic_idc_func(adapter, 0);
		cancel_delayed_work_sync(&adapter->idc_aen_work);
2437 2438 2439
		qlcnic_83xx_free_mbx_intr(adapter);
		qlcnic_83xx_detach_mailbox_work(adapter);
		qlcnic_83xx_free_mailbox(ahw->mailbox);
2440
		kfree(ahw->fw_info);
S
Sony Chacko 已提交
2441 2442
	}

2443 2444
	qlcnic_detach(adapter);

2445 2446 2447 2448 2449
	if (adapter->npars != NULL)
		kfree(adapter->npars);
	if (adapter->eswitch != NULL)
		kfree(adapter->eswitch);

2450 2451
	if (qlcnic_82xx_check(adapter))
		qlcnic_clr_all_drv_state(adapter, 0);
2452 2453 2454

	clear_bit(__QLCNIC_RESETTING, &adapter->state);

2455 2456
	qlcnic_free_lb_filters_mem(adapter);

2457 2458
	qlcnic_teardown_intr(adapter);

S
Sony Chacko 已提交
2459
	qlcnic_remove_sysfs(adapter);
2460

2461
	qlcnic_cleanup_pci_map(adapter->ahw);
2462 2463 2464

	qlcnic_release_firmware(adapter);

S
Sucheta Chakraborty 已提交
2465
	pci_disable_pcie_error_reporting(pdev);
2466 2467 2468 2469
	pci_release_regions(pdev);
	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);

S
Sony Chacko 已提交
2470 2471 2472 2473
	if (adapter->qlcnic_wq) {
		destroy_workqueue(adapter->qlcnic_wq);
		adapter->qlcnic_wq = NULL;
	}
2474

A
Anirban Chakraborty 已提交
2475
	qlcnic_free_adapter_resources(adapter);
S
Sony Chacko 已提交
2476
	kfree(ahw);
2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488
	free_netdev(netdev);
}

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

	pci_disable_device(pdev);
}

#ifdef CONFIG_PM
2489
static int qlcnic_suspend(struct pci_dev *pdev, pm_message_t state)
2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500
{
	int retval;

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

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

2501
static int qlcnic_resume(struct pci_dev *pdev)
2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513
{
	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);

2514
	return  __qlcnic_resume(adapter);
2515 2516 2517 2518 2519 2520 2521 2522
}
#endif

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

2523 2524
	netif_carrier_off(netdev);

2525 2526 2527 2528 2529 2530 2531 2532
	err = qlcnic_attach(adapter);
	if (err)
		return err;

	err = __qlcnic_up(adapter, netdev);
	if (err)
		goto err_out;

2533
	netif_tx_start_all_queues(netdev);
2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549

	return 0;

err_out:
	qlcnic_detach(adapter);
	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 已提交
2550

2551 2552 2553
	return 0;
}

2554
void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
2555 2556 2557
{
	void *head;
	int i;
S
Sony Chacko 已提交
2558 2559 2560
	struct net_device *netdev = adapter->netdev;
	u32 filter_size = 0;
	u16 act_pci_func = 0;
2561

2562
	if (adapter->fhash.fmax && adapter->fhash.fhead)
2563 2564
		return;

S
Sony Chacko 已提交
2565
	act_pci_func = adapter->ahw->act_pci_func;
2566
	spin_lock_init(&adapter->mac_learn_lock);
2567
	spin_lock_init(&adapter->rx_mac_learn_lock);
2568

S
Sony Chacko 已提交
2569 2570 2571 2572 2573 2574 2575 2576 2577
	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,
2578
		       sizeof(struct hlist_head), GFP_ATOMIC);
S
Sony Chacko 已提交
2579

2580 2581 2582
	if (!head)
		return;

S
Sony Chacko 已提交
2583
	adapter->fhash.fmax = (filter_size / act_pci_func);
2584
	adapter->fhash.fhead = head;
2585

S
Sony Chacko 已提交
2586 2587 2588 2589
	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++)
2590
		INIT_HLIST_HEAD(&adapter->fhash.fhead[i]);
2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604

	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]);
2605 2606 2607 2608 2609 2610 2611 2612 2613
}

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;
2614 2615 2616 2617 2618 2619

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

	adapter->rx_fhash.fmax = 0;
	adapter->rx_fhash.fhead = NULL;
2620 2621
}

2622
int qlcnic_check_temp(struct qlcnic_adapter *adapter)
2623 2624
{
	struct net_device *netdev = adapter->netdev;
2625
	u32 temp_state, temp_val, temp = 0;
2626 2627
	int rv = 0;

S
Sony Chacko 已提交
2628 2629 2630
	if (qlcnic_83xx_check(adapter))
		temp = QLCRDX(adapter->ahw, QLC_83XX_ASIC_TEMP);

2631
	if (qlcnic_82xx_check(adapter))
2632
		temp = QLC_SHARED_REG_RD32(adapter, QLCNIC_ASIC_TEMP);
2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643

	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) {
2644
		if (adapter->ahw->temp == QLCNIC_TEMP_NORMAL) {
2645 2646 2647 2648 2649 2650 2651
			dev_err(&netdev->dev,
			       "Device temperature %d degrees C "
			       "exceeds operating range."
			       " Immediate action needed.\n",
			       temp_val);
		}
	} else {
2652
		if (adapter->ahw->temp == QLCNIC_TEMP_WARN) {
2653 2654 2655 2656 2657
			dev_info(&netdev->dev,
			       "Device temperature is now %d degrees C"
			       " in normal range.\n", temp_val);
		}
	}
2658
	adapter->ahw->temp = temp_state;
2659 2660 2661 2662 2663 2664
	return rv;
}

static void qlcnic_tx_timeout(struct net_device *netdev)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
2665 2666
	struct qlcnic_host_tx_ring *tx_ring;
	int ring;
2667 2668 2669 2670

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

2671 2672 2673 2674 2675 2676 2677 2678 2679
	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");
2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698
		if (qlcnic_82xx_check(adapter)) {
			for (ring = 0; ring < adapter->max_drv_tx_rings;
			     ring++) {
				tx_ring = &adapter->tx_ring[ring];
				dev_info(&netdev->dev, "ring=%d\n", ring);
				dev_info(&netdev->dev, "crb_intr_mask=%d\n",
					 readl(tx_ring->crb_intr_mask));
				dev_info(&netdev->dev, "producer=%d\n",
					 readl(tx_ring->crb_cmd_producer));
				dev_info(&netdev->dev, "sw_consumer = %d\n",
					 tx_ring->sw_consumer);
				dev_info(&netdev->dev, "hw_consumer = %d\n",
					 le32_to_cpu(*(tx_ring->hw_consumer)));
				dev_info(&netdev->dev, "xmit-on=%llu\n",
					 tx_ring->xmit_on);
				dev_info(&netdev->dev, "xmit-off=%llu\n",
					 tx_ring->xmit_off);
			}
		}
2699
		adapter->ahw->reset_context = 1;
2700
	}
2701 2702 2703 2704 2705 2706 2707 2708 2709
}

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;

	stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
	stats->tx_packets = adapter->stats.xmitfinished;
2710
	stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
2711 2712 2713 2714 2715 2716 2717
	stats->tx_bytes = adapter->stats.txbytes;
	stats->rx_dropped = adapter->stats.rxdropped;
	stats->tx_dropped = adapter->stats.txdropped;

	return stats;
}

2718
irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
2719 2720 2721 2722 2723
{
	u32 status;

	status = readl(adapter->isr_int_vec);

2724
	if (!(status & adapter->ahw->int_vec_bit))
2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736
		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);

2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755
	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:
2756
	adapter->ahw->diag_cnt++;
2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768
	qlcnic_enable_int(sds_ring);
	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;

2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793
	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 已提交
2794 2795 2796 2797 2798 2799 2800 2801
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;
}

2802 2803 2804
#ifdef CONFIG_NET_POLL_CONTROLLER
static void qlcnic_poll_controller(struct net_device *netdev)
{
Y
Yinglin Luan 已提交
2805 2806
	int ring;
	struct qlcnic_host_sds_ring *sds_ring;
2807
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
A
Anirban Chakraborty 已提交
2808
	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
Y
Yinglin Luan 已提交
2809

2810
	disable_irq(adapter->irq);
Y
Yinglin Luan 已提交
2811 2812 2813 2814
	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
		sds_ring = &recv_ctx->sds_rings[ring];
		qlcnic_intr(adapter->irq, sds_ring);
	}
2815 2816 2817 2818
	enable_irq(adapter->irq);
}
#endif

2819 2820 2821 2822 2823 2824 2825 2826 2827
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;

2828
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_SCRATCH, val);
2829 2830 2831
	adapter->dev_rst_time = jiffies;
}

2832 2833
static int
qlcnic_set_drv_state(struct qlcnic_adapter *adapter, u8 state)
2834 2835 2836 2837 2838 2839 2840
{
	u32  val;

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

	if (qlcnic_api_lock(adapter))
2841
		return -EIO;
2842

2843
	val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
2844 2845

	if (state == QLCNIC_DEV_NEED_RESET)
2846
		QLC_DEV_SET_RST_RDY(val, adapter->portnum);
2847
	else if (state == QLCNIC_DEV_NEED_QUISCENT)
2848
		QLC_DEV_SET_QSCNT_RDY(val, adapter->portnum);
2849

2850
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2851 2852

	qlcnic_api_unlock(adapter);
2853 2854

	return 0;
2855 2856
}

2857 2858 2859 2860 2861 2862 2863 2864
static int
qlcnic_clr_drv_state(struct qlcnic_adapter *adapter)
{
	u32  val;

	if (qlcnic_api_lock(adapter))
		return -EBUSY;

2865
	val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
2866
	QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum);
2867
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2868 2869 2870 2871 2872 2873

	qlcnic_api_unlock(adapter);

	return 0;
}

2874
void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
2875 2876 2877 2878 2879 2880
{
	u32  val;

	if (qlcnic_api_lock(adapter))
		goto err;

2881
	val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
2882
	QLC_DEV_CLR_REF_CNT(val, adapter->portnum);
2883
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
2884

2885
	if (failed) {
2886 2887
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE,
				    QLCNIC_DEV_FAILED);
2888 2889 2890
		dev_info(&adapter->pdev->dev,
				"Device state set to Failed. Please Reboot\n");
	} else if (!(val & 0x11111111))
2891 2892
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE,
				    QLCNIC_DEV_COLD);
2893

2894
	val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
2895
	QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum);
2896
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2897 2898 2899 2900

	qlcnic_api_unlock(adapter);
err:
	adapter->fw_fail_cnt = 0;
S
Sritej Velaga 已提交
2901
	adapter->flags &= ~QLCNIC_FW_HANG;
2902 2903 2904 2905
	clear_bit(__QLCNIC_START_FW, &adapter->state);
	clear_bit(__QLCNIC_RESETTING, &adapter->state);
}

2906
/* Grab api lock, before checking state */
2907 2908 2909
static int
qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
{
2910
	int act, state, active_mask;
2911
	struct qlcnic_hardware_context *ahw = adapter->ahw;
2912

2913 2914
	state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
	act = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
2915

2916
	if (adapter->flags & QLCNIC_FW_RESET_OWNER) {
2917
		active_mask = (~(1 << (ahw->pci_func * 4)));
2918 2919 2920
		act = act & active_mask;
	}

2921 2922 2923 2924 2925 2926 2927
	if (((state & 0x11111111) == (act & 0x11111111)) ||
			((act & 0x11111111) == ((state >> 1) & 0x11111111)))
		return 0;
	else
		return 1;
}

S
Sucheta Chakraborty 已提交
2928 2929
static int qlcnic_check_idc_ver(struct qlcnic_adapter *adapter)
{
2930
	u32 val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_IDC_VER);
S
Sucheta Chakraborty 已提交
2931 2932 2933 2934 2935 2936 2937 2938 2939

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

2940 2941 2942 2943
static int
qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
{
	u32 val, prev_state;
2944
	u8 dev_init_timeo = adapter->dev_init_timeo;
2945
	u8 portnum = adapter->portnum;
S
Sucheta Chakraborty 已提交
2946
	u8 ret;
2947

2948 2949 2950
	if (test_and_clear_bit(__QLCNIC_START_FW, &adapter->state))
		return 1;

2951 2952 2953
	if (qlcnic_api_lock(adapter))
		return -1;

2954
	val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
2955 2956
	if (!(val & (1 << (portnum * 4)))) {
		QLC_DEV_SET_REF_CNT(val, portnum);
2957
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
2958 2959
	}

2960
	prev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
2961
	QLCDB(adapter, HW, "Device state = %u\n", prev_state);
2962 2963 2964

	switch (prev_state) {
	case QLCNIC_DEV_COLD:
2965 2966 2967 2968
		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);
2969
		qlcnic_idc_debug_info(adapter, 0);
2970 2971 2972 2973
		qlcnic_api_unlock(adapter);
		return 1;

	case QLCNIC_DEV_READY:
S
Sucheta Chakraborty 已提交
2974
		ret = qlcnic_check_idc_ver(adapter);
2975
		qlcnic_api_unlock(adapter);
S
Sucheta Chakraborty 已提交
2976
		return ret;
2977 2978

	case QLCNIC_DEV_NEED_RESET:
2979
		val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
2980
		QLC_DEV_SET_RST_RDY(val, portnum);
2981
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2982 2983 2984
		break;

	case QLCNIC_DEV_NEED_QUISCENT:
2985
		val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
2986
		QLC_DEV_SET_QSCNT_RDY(val, portnum);
2987
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2988 2989 2990
		break;

	case QLCNIC_DEV_FAILED:
2991
		dev_err(&adapter->pdev->dev, "Device in failed state.\n");
2992 2993
		qlcnic_api_unlock(adapter);
		return -1;
2994 2995 2996 2997

	case QLCNIC_DEV_INITIALIZING:
	case QLCNIC_DEV_QUISCENT:
		break;
2998 2999 3000
	}

	qlcnic_api_unlock(adapter);
3001 3002

	do {
3003
		msleep(1000);
3004
		prev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3005 3006 3007 3008

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

3010 3011 3012
	if (!dev_init_timeo) {
		dev_err(&adapter->pdev->dev,
			"Waiting for device to initialize timeout\n");
3013
		return -1;
3014
	}
3015 3016 3017 3018

	if (qlcnic_api_lock(adapter))
		return -1;

3019
	val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE);
3020
	QLC_DEV_CLR_RST_QSCNT(val, portnum);
3021
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val);
3022

S
Sucheta Chakraborty 已提交
3023
	ret = qlcnic_check_idc_ver(adapter);
3024 3025
	qlcnic_api_unlock(adapter);

S
Sucheta Chakraborty 已提交
3026
	return ret;
3027 3028 3029 3030 3031 3032 3033
}

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

3037 3038
	if (qlcnic_api_lock(adapter))
		goto err_ret;
3039

3040
	dev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3041 3042
	if (dev_state == QLCNIC_DEV_QUISCENT ||
	    dev_state == QLCNIC_DEV_NEED_QUISCENT) {
3043 3044 3045 3046 3047 3048
		qlcnic_api_unlock(adapter);
		qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
						FW_POLL_DELAY * 2);
		return;
	}

3049
	if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
3050 3051
		qlcnic_api_unlock(adapter);
		goto wait_npar;
3052 3053
	}

3054 3055 3056 3057 3058 3059 3060
	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;
	}

3061
	if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
3062
		dev_info(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n",
3063 3064 3065 3066 3067 3068
					adapter->reset_ack_timeo);
		goto skip_ack_check;
	}

	if (!qlcnic_check_drv_state(adapter)) {
skip_ack_check:
3069
		dev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3070

3071
		if (dev_state == QLCNIC_DEV_NEED_RESET) {
3072 3073
			QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE,
					    QLCNIC_DEV_INITIALIZING);
3074 3075
			set_bit(__QLCNIC_START_FW, &adapter->state);
			QLCDB(adapter, DRV, "Restarting fw\n");
3076
			qlcnic_idc_debug_info(adapter, 0);
3077 3078
			val = QLC_SHARED_REG_RD32(adapter,
						  QLCNIC_CRB_DRV_STATE);
S
Sritej Velaga 已提交
3079
			QLC_DEV_SET_RST_RDY(val, adapter->portnum);
3080 3081
			QLC_SHARED_REG_WR32(adapter,
					    QLCNIC_CRB_DRV_STATE, val);
3082 3083
		}

3084 3085
		qlcnic_api_unlock(adapter);

3086
		rtnl_lock();
3087
		if (qlcnic_check_fw_dump_state(adapter) &&
S
Sritej Velaga 已提交
3088
		    (adapter->flags & QLCNIC_FW_RESET_OWNER)) {
3089 3090
			QLCDB(adapter, DRV, "Take FW dump\n");
			qlcnic_dump_fw(adapter);
S
Sritej Velaga 已提交
3091
			adapter->flags |= QLCNIC_FW_HANG;
3092
		}
3093
		rtnl_unlock();
S
Sritej Velaga 已提交
3094 3095

		adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
3096
		if (!adapter->nic_ops->start_firmware(adapter)) {
3097
			qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
3098
			adapter->fw_wait_cnt = 0;
3099 3100 3101 3102 3103
			return;
		}
		goto err_ret;
	}

3104
	qlcnic_api_unlock(adapter);
3105

3106
wait_npar:
3107
	dev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3108
	QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
3109

3110
	switch (dev_state) {
3111
	case QLCNIC_DEV_READY:
3112
		if (!qlcnic_start_firmware(adapter)) {
3113
			qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
3114
			adapter->fw_wait_cnt = 0;
3115 3116
			return;
		}
3117 3118 3119 3120 3121 3122
	case QLCNIC_DEV_FAILED:
		break;
	default:
		qlcnic_schedule_work(adapter,
			qlcnic_fwinit_work, FW_POLL_DELAY);
		return;
3123 3124 3125
	}

err_ret:
3126 3127
	dev_err(&adapter->pdev->dev, "Fwinit work failed state=%u "
		"fw_wait_cnt=%u\n", dev_state, adapter->fw_wait_cnt);
3128
	netif_device_attach(adapter->netdev);
3129
	qlcnic_clr_all_drv_state(adapter, 0);
3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141
}

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

3142 3143 3144 3145 3146 3147
	/* 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);
3148

3149
	status = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS1);
3150

S
Sony Chacko 已提交
3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163
	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");
		}

3164
		goto err_ret;
S
Sony Chacko 已提交
3165
	}
3166

3167
	if (adapter->ahw->temp == QLCNIC_TEMP_PANIC) {
S
Sony Chacko 已提交
3168
		dev_err(&adapter->pdev->dev, "Detaching the device: temp=%d\n",
3169
			adapter->ahw->temp);
3170
		goto err_ret;
S
Sony Chacko 已提交
3171 3172
	}

3173 3174
	/* Dont ack if this instance is the reset owner */
	if (!(adapter->flags & QLCNIC_FW_RESET_OWNER)) {
S
Sony Chacko 已提交
3175 3176 3177 3178
		if (qlcnic_set_drv_state(adapter, adapter->dev_state)) {
			dev_err(&adapter->pdev->dev,
				"Failed to set driver state,"
					"detaching the device.\n");
3179
			goto err_ret;
S
Sony Chacko 已提交
3180
		}
3181
	}
3182 3183 3184 3185 3186 3187 3188 3189

	adapter->fw_wait_cnt = 0;

	qlcnic_schedule_work(adapter, qlcnic_fwinit_work, FW_POLL_DELAY);

	return;

err_ret:
3190
	netif_device_attach(netdev);
3191
	qlcnic_clr_all_drv_state(adapter, 1);
3192 3193
}

3194 3195 3196 3197 3198 3199
/*Transit NPAR state to NON Operational */
static void
qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter)
{
	u32 state;

3200
	state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
3201 3202 3203 3204 3205
	if (state == QLCNIC_DEV_NPAR_NON_OPER)
		return;

	if (qlcnic_api_lock(adapter))
		return;
3206 3207
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
			    QLCNIC_DEV_NPAR_NON_OPER);
3208 3209 3210
	qlcnic_api_unlock(adapter);
}

3211
void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *adapter, u32 key)
3212
{
3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224
	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");
3225
	adapter->need_fw_reset = 1;
S
Sony Chacko 已提交
3226

3227 3228 3229
	if (qlcnic_api_lock(adapter))
		return;

S
Sony Chacko 已提交
3230
	state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3231

3232
	if (state == QLCNIC_DEV_READY) {
S
Sony Chacko 已提交
3233 3234
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE,
				    QLCNIC_DEV_NEED_RESET);
3235
		adapter->flags |= QLCNIC_FW_RESET_OWNER;
3236
		QLCDB(adapter, DRV, "NEED_RESET state set\n");
3237
		qlcnic_idc_debug_info(adapter, 0);
3238 3239
	}

S
Sony Chacko 已提交
3240 3241
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
			    QLCNIC_DEV_NPAR_NON_OPER);
3242 3243 3244
	qlcnic_api_unlock(adapter);
}

3245 3246 3247 3248 3249 3250 3251
/* 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;

3252 3253
	QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
			    QLCNIC_DEV_NPAR_OPER);
3254
	QLCDB(adapter, DRV, "NPAR operational state set\n");
3255 3256 3257 3258

	qlcnic_api_unlock(adapter);
}

S
Sony Chacko 已提交
3259 3260
void qlcnic_schedule_work(struct qlcnic_adapter *adapter,
			  work_func_t func, int delay)
3261
{
S
Sucheta Chakraborty 已提交
3262 3263 3264
	if (test_bit(__QLCNIC_AER, &adapter->state))
		return;

3265
	INIT_DELAYED_WORK(&adapter->fw_work, func);
S
Sony Chacko 已提交
3266 3267
	queue_delayed_work(adapter->qlcnic_wq, &adapter->fw_work,
			   round_jiffies_relative(delay));
3268 3269 3270 3271 3272 3273 3274 3275
}

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;
3276
	u32 npar_state;
3277

3278
	if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
3279 3280
		npar_state = QLC_SHARED_REG_RD32(adapter,
						 QLCNIC_CRB_DEV_NPAR_STATE);
3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291
		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:
3292 3293
	qlcnic_dcb_get_info(adapter);

3294
	if (netif_running(netdev)) {
3295
		if (qlcnic_up(adapter, netdev))
3296 3297
			goto done;

A
Amit Kumar Salecha 已提交
3298
		qlcnic_restore_indev_addr(netdev, NETDEV_UP);
3299 3300 3301
	}

done:
3302
	netif_device_attach(netdev);
3303
	adapter->fw_fail_cnt = 0;
S
Sritej Velaga 已提交
3304
	adapter->flags &= ~QLCNIC_FW_HANG;
3305
	clear_bit(__QLCNIC_RESETTING, &adapter->state);
3306 3307
	if (adapter->portnum == 0)
		qlcnic_set_drv_version(adapter);
3308 3309 3310 3311

	if (!qlcnic_clr_drv_state(adapter))
		qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
							FW_POLL_DELAY);
3312 3313 3314 3315 3316
}

static int
qlcnic_check_health(struct qlcnic_adapter *adapter)
{
3317
	u32 state = 0, heartbeat;
3318
	u32 peg_status;
3319
	int err = 0;
3320 3321 3322 3323

	if (qlcnic_check_temp(adapter))
		goto detach;

A
Amit Kumar Salecha 已提交
3324
	if (adapter->need_fw_reset)
3325
		qlcnic_dev_request_reset(adapter, 0);
3326

3327
	state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
3328
	if (state == QLCNIC_DEV_NEED_RESET) {
3329
		qlcnic_set_npar_non_operational(adapter);
3330
		adapter->need_fw_reset = 1;
3331 3332
	} else if (state == QLCNIC_DEV_NEED_QUISCENT)
		goto detach;
3333

3334
	heartbeat = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
3335 3336
	if (heartbeat != adapter->heartbeat) {
		adapter->heartbeat = heartbeat;
3337 3338 3339
		adapter->fw_fail_cnt = 0;
		if (adapter->need_fw_reset)
			goto detach;
3340

3341
		if (adapter->ahw->reset_context && qlcnic_auto_fw_reset)
3342 3343
			qlcnic_reset_hw_context(adapter);

3344 3345 3346 3347 3348 3349
		return 0;
	}

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

S
Sritej Velaga 已提交
3350 3351
	adapter->flags |= QLCNIC_FW_HANG;

3352
	qlcnic_dev_request_reset(adapter, 0);
3353

3354
	if (qlcnic_auto_fw_reset)
3355
		clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
3356

3357
	dev_err(&adapter->pdev->dev, "firmware hang detected\n");
3358
	peg_status = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS1);
3359
	dev_err(&adapter->pdev->dev, "Dumping hw/fw registers\n"
S
Sritej Velaga 已提交
3360 3361 3362 3363
			"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",
3364 3365
			peg_status,
			QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS2),
3366 3367 3368 3369 3370
			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));
3371
	if (QLCNIC_FWERROR_CODE(peg_status) == 0x67)
3372 3373 3374
		dev_err(&adapter->pdev->dev,
			"Firmware aborted with error code 0x00006700. "
				"Device is being reset.\n");
3375 3376 3377 3378
detach:
	adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state :
		QLCNIC_DEV_NEED_RESET;

3379 3380
	if (qlcnic_auto_fw_reset && !test_and_set_bit(__QLCNIC_RESETTING,
						      &adapter->state)) {
3381

3382
		qlcnic_schedule_work(adapter, qlcnic_detach_work, 0);
3383 3384
		QLCDB(adapter, DRV, "fw recovery scheduled.\n");
	}
3385 3386 3387 3388

	return 1;
}

3389
void qlcnic_fw_poll_work(struct work_struct *work)
3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400
{
	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;

3401 3402 3403
	if (adapter->fhash.fnum)
		qlcnic_prune_lb_filters(adapter);

3404 3405 3406 3407
reschedule:
	qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
}

S
Sucheta Chakraborty 已提交
3408 3409 3410 3411 3412 3413 3414 3415 3416
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));
3417 3418
		if (!oth_pdev)
			continue;
S
Sucheta Chakraborty 已提交
3419

3420 3421
		if (oth_pdev->current_state != PCI_D3cold) {
			pci_dev_put(oth_pdev);
S
Sucheta Chakraborty 已提交
3422
			return 0;
3423 3424
		}
		pci_dev_put(oth_pdev);
S
Sucheta Chakraborty 已提交
3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448
	}
	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;

3449
	if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
S
Sucheta Chakraborty 已提交
3450 3451
		adapter->need_fw_reset = 1;
		set_bit(__QLCNIC_START_FW, &adapter->state);
3452 3453
		QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE,
				    QLCNIC_DEV_INITIALIZING);
S
Sucheta Chakraborty 已提交
3454 3455 3456 3457
		QLCDB(adapter, DRV, "Restarting fw\n");
	}
	qlcnic_api_unlock(adapter);

S
Sony Chacko 已提交
3458
	err = qlcnic_start_firmware(adapter);
S
Sucheta Chakraborty 已提交
3459 3460 3461 3462
	if (err)
		return err;

	qlcnic_clr_drv_state(adapter);
S
Sony Chacko 已提交
3463 3464
	kfree(adapter->msix_entries);
	adapter->msix_entries = NULL;
3465
	err = qlcnic_setup_intr(adapter, 0, 0);
S
Sony Chacko 已提交
3466

3467 3468 3469 3470 3471 3472
	if (err) {
		kfree(adapter->msix_entries);
		netdev_err(netdev, "failed to setup interrupt\n");
		return err;
	}

S
Sucheta Chakraborty 已提交
3473 3474 3475
	if (netif_running(netdev)) {
		err = qlcnic_attach(adapter);
		if (err) {
3476
			qlcnic_clr_all_drv_state(adapter, 1);
S
Sucheta Chakraborty 已提交
3477 3478 3479 3480 3481 3482 3483 3484 3485
			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 已提交
3486
		qlcnic_restore_indev_addr(netdev, NETDEV_UP);
S
Sucheta Chakraborty 已提交
3487 3488 3489 3490 3491 3492
	}
 done:
	netif_device_attach(netdev);
	return err;
}

3493 3494
pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *pdev,
					       pci_channel_state_t state)
S
Sucheta Chakraborty 已提交
3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523
{
	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;
}

3524
pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *pdev)
S
Sucheta Chakraborty 已提交
3525 3526 3527 3528 3529
{
	return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT :
				PCI_ERS_RESULT_RECOVERED;
}

3530
void qlcnic_82xx_io_resume(struct pci_dev *pdev)
S
Sucheta Chakraborty 已提交
3531
{
3532
	u32 state;
S
Sucheta Chakraborty 已提交
3533 3534 3535
	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);

	pci_cleanup_aer_uncorrect_error_status(pdev);
3536 3537 3538
	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 已提交
3539
		qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
3540
				     FW_POLL_DELAY);
S
Sucheta Chakraborty 已提交
3541 3542
}

3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581
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");
}


3582 3583 3584 3585 3586 3587 3588 3589 3590
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 已提交
3591 3592 3593
	err = qlcnic_check_npar_opertional(adapter);
	if (err)
		return err;
3594

3595 3596 3597 3598
	err = qlcnic_initialize_nic(adapter);
	if (err)
		return err;

3599 3600
	qlcnic_check_options(adapter);

3601 3602 3603 3604
	err = qlcnic_set_eswitch_port_config(adapter);
	if (err)
		return err;

3605 3606 3607 3608 3609
	adapter->need_fw_reset = 0;

	return err;
}

3610
int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *adapter, u32 txq)
3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652
{
	struct net_device *netdev = adapter->netdev;
	u8 max_hw = QLCNIC_MAX_TX_RINGS;
	u32 max_allowed;

	if (!qlcnic_82xx_check(adapter)) {
		netdev_err(netdev, "No Multi TX-Q support\n");
		return -EINVAL;
	}

	if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
		netdev_err(netdev, "No Multi TX-Q support in INT-x mode\n");
		return -EINVAL;
	}

	if (!qlcnic_check_multi_tx(adapter)) {
		netdev_err(netdev, "No Multi TX-Q support\n");
		return -EINVAL;
	}

	if (txq > QLCNIC_MAX_TX_RINGS) {
		netdev_err(netdev, "Invalid ring count\n");
		return -EINVAL;
	}

	max_allowed = rounddown_pow_of_two(min_t(int, max_hw,
						 num_online_cpus()));
	if ((txq > max_allowed) || !is_power_of_2(txq)) {
		if (!is_power_of_2(txq))
			netdev_err(netdev,
				   "TX queue should be a power of 2\n");
		if (txq > num_online_cpus())
			netdev_err(netdev,
				   "Tx queue should not be higher than [%u], number of online CPUs in the system\n",
				   num_online_cpus());
		netdev_err(netdev, "Unable to configure %u Tx rings\n", txq);
		return -EINVAL;
	}

	return 0;
}

3653
int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter,
3654
				__u32 val)
3655
{
3656 3657
	struct net_device *netdev = adapter->netdev;
	u8 max_hw = adapter->ahw->max_rx_ques;
S
Sony Chacko 已提交
3658 3659
	u32 max_allowed;

3660 3661 3662 3663 3664 3665
	if (qlcnic_82xx_check(adapter) && !qlcnic_use_msi_x &&
	    !qlcnic_use_msi) {
		netdev_err(netdev, "No RSS support in INT-x mode\n");
		return -EINVAL;
	}

3666
	if (val > QLCNIC_MAX_SDS_RINGS) {
3667
		netdev_err(netdev, "RSS value should not be higher than %u\n",
3668
			   QLCNIC_MAX_SDS_RINGS);
3669
		return -EINVAL;
3670 3671
	}

S
Sony Chacko 已提交
3672 3673 3674
	max_allowed = rounddown_pow_of_two(min_t(int, max_hw,
						 num_online_cpus()));
	if ((val > max_allowed) || (val < 2) || !is_power_of_2(val)) {
3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692
		if (!is_power_of_2(val))
			netdev_err(netdev, "RSS value should be a power of 2\n");

		if (val < 2)
			netdev_err(netdev, "RSS value should not be lower than 2\n");

		if (val > max_hw)
			netdev_err(netdev,
				   "RSS value should not be higher than[%u], the max RSS rings supported by the adapter\n",
				   max_hw);

		if (val > num_online_cpus())
			netdev_err(netdev,
				   "RSS value should not be higher than[%u], number of online CPUs in the system\n",
				   num_online_cpus());

		netdev_err(netdev, "Unable to configure %u RSS rings\n", val);

3693 3694 3695 3696 3697
		return -EINVAL;
	}
	return 0;
}

3698
int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, int txq)
3699
{
S
Sony Chacko 已提交
3700
	int err;
3701
	struct net_device *netdev = adapter->netdev;
3702
	int num_msix;
3703

S
Sony Chacko 已提交
3704 3705 3706
	if (test_bit(__QLCNIC_RESETTING, &adapter->state))
		return -EBUSY;

3707 3708 3709 3710 3711 3712
	if (qlcnic_82xx_check(adapter) && !qlcnic_use_msi_x &&
	    !qlcnic_use_msi) {
		netdev_err(netdev, "No RSS support in INT-x mode\n");
		return -EINVAL;
	}

3713 3714 3715
	netif_device_detach(netdev);
	if (netif_running(netdev))
		__qlcnic_down(adapter, netdev);
S
Sony Chacko 已提交
3716

3717 3718
	qlcnic_detach(adapter);

3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729
	if (qlcnic_82xx_check(adapter)) {
		if (txq != 0)
			adapter->max_drv_tx_rings = txq;

		if (qlcnic_check_multi_tx(adapter) &&
		    (txq > adapter->max_drv_tx_rings))
			num_msix = adapter->max_drv_tx_rings;
		else
			num_msix = data;
	}

3730
	if (qlcnic_83xx_check(adapter)) {
S
Sony Chacko 已提交
3731
		qlcnic_83xx_free_mbx_intr(adapter);
3732 3733
		qlcnic_83xx_enable_mbx_poll(adapter);
	}
S
Sony Chacko 已提交
3734

3735 3736
	netif_set_real_num_tx_queues(netdev, adapter->max_drv_tx_rings);

3737
	qlcnic_teardown_intr(adapter);
3738 3739

	err = qlcnic_setup_intr(adapter, data, txq);
3740 3741 3742 3743 3744
	if (err) {
		kfree(adapter->msix_entries);
		netdev_err(netdev, "failed to setup interrupt\n");
		return err;
	}
3745

S
Sony Chacko 已提交
3746
	if (qlcnic_83xx_check(adapter)) {
3747 3748
		/* register for NIC IDC AEN Events */
		qlcnic_83xx_register_nic_idc_func(adapter, 1);
S
Sony Chacko 已提交
3749
		err = qlcnic_83xx_setup_mbx_intr(adapter);
3750
		qlcnic_83xx_disable_mbx_poll(adapter);
S
Sony Chacko 已提交
3751 3752 3753 3754 3755
		if (err) {
			dev_err(&adapter->pdev->dev,
				"failed to setup mbx interrupt\n");
			goto done;
		}
3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766
	}

	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);
	}
3767
done:
3768 3769 3770 3771 3772
	netif_device_attach(netdev);
	clear_bit(__QLCNIC_RESETTING, &adapter->state);
	return err;
}

3773 3774 3775 3776 3777
#ifdef CONFIG_INET

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

static void
A
Amit Kumar Salecha 已提交
3778 3779
qlcnic_config_indev_addr(struct qlcnic_adapter *adapter,
			struct net_device *dev, unsigned long event)
3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804
{
	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 已提交
3805
void qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event)
A
Amit Kumar Salecha 已提交
3806 3807 3808 3809 3810 3811 3812
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct net_device *dev;
	u16 vid;

	qlcnic_config_indev_addr(adapter, netdev, event);

3813
	rcu_read_lock();
3814
	for_each_set_bit(vid, adapter->vlans, VLAN_N_VID) {
3815
		dev = __vlan_find_dev_deep(netdev, htons(ETH_P_8021Q), vid);
A
Amit Kumar Salecha 已提交
3816 3817 3818 3819
		if (!dev)
			continue;
		qlcnic_config_indev_addr(adapter, dev, event);
	}
3820
	rcu_read_unlock();
A
Amit Kumar Salecha 已提交
3821 3822
}

3823 3824 3825 3826
static int qlcnic_netdev_event(struct notifier_block *this,
				 unsigned long event, void *ptr)
{
	struct qlcnic_adapter *adapter;
3827
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845

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;

3846
	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
3847 3848
		goto done;

A
Amit Kumar Salecha 已提交
3849
	qlcnic_config_indev_addr(adapter, dev, event);
3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865
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 已提交
3866
	if (dev == NULL)
3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878
		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 已提交
3879
	if (!adapter)
3880 3881
		goto done;

3882
	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
3883 3884 3885 3886 3887
		goto done;

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

3889 3890 3891
		break;
	case NETDEV_DOWN:
		qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_DOWN);
S
Sony Chacko 已提交
3892

3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909
		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 已提交
3910
void qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event)
3911 3912
{ }
#endif
3913
static const struct pci_error_handlers qlcnic_err_handler = {
S
Sucheta Chakraborty 已提交
3914 3915 3916 3917
	.error_detected = qlcnic_io_error_detected,
	.slot_reset = qlcnic_io_slot_reset,
	.resume = qlcnic_io_resume,
};
3918 3919 3920 3921 3922

static struct pci_driver qlcnic_driver = {
	.name = qlcnic_driver_name,
	.id_table = qlcnic_pci_tbl,
	.probe = qlcnic_probe,
B
Bill Pemberton 已提交
3923
	.remove = qlcnic_remove,
3924 3925 3926 3927
#ifdef CONFIG_PM
	.suspend = qlcnic_suspend,
	.resume = qlcnic_resume,
#endif
S
Sucheta Chakraborty 已提交
3928
	.shutdown = qlcnic_shutdown,
3929 3930 3931 3932
	.err_handler = &qlcnic_err_handler,
#ifdef CONFIG_QLCNIC_SRIOV
	.sriov_configure = qlcnic_pci_sriov_configure,
#endif
S
Sucheta Chakraborty 已提交
3933

3934 3935 3936 3937
};

static int __init qlcnic_init_module(void)
{
3938
	int ret;
3939 3940 3941 3942 3943 3944 3945 3946

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

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

3947 3948 3949 3950 3951 3952 3953
	ret = pci_register_driver(&qlcnic_driver);
	if (ret) {
#ifdef CONFIG_INET
		unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
		unregister_netdevice_notifier(&qlcnic_netdev_cb);
#endif
	}
3954

3955
	return ret;
3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970
}

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