blob: 70d325c19dcfc2c50e25cdd0ec78b225f45cc8b5 [file] [log] [blame]
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001/*
Sritej Velaga40839129f2010-12-02 20:41:56 +00002 * QLogic qlcnic NIC Driver
3 * Copyright (c) 2009-2010 QLogic Corporation
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00004 *
Sritej Velaga40839129f2010-12-02 20:41:56 +00005 * See LICENSE.qlcnic for copyright and licensing details.
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00006 */
7
Tejun Heo5a0e3ad2010-03-24 17:04:11 +09008#include <linux/slab.h>
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00009#include <linux/vmalloc.h>
10#include <linux/interrupt.h>
11
12#include "qlcnic.h"
13
Sucheta Chakraborty7e56cac2010-10-04 04:20:13 +000014#include <linux/swab.h>
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000015#include <linux/dma-mapping.h>
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000016#include <net/ip.h>
17#include <linux/ipv6.h>
18#include <linux/inetdevice.h>
19#include <linux/sysfs.h>
Sucheta Chakraborty451724c2010-07-13 20:33:34 +000020#include <linux/aer.h>
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +000021#include <linux/log2.h>
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000022
Sritej Velaga7f9a0c32010-06-17 02:56:39 +000023MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000024MODULE_LICENSE("GPL");
25MODULE_VERSION(QLCNIC_LINUX_VERSIONID);
26MODULE_FIRMWARE(QLCNIC_UNIFIED_ROMIMAGE_NAME);
27
28char qlcnic_driver_name[] = "qlcnic";
Sritej Velaga7f9a0c32010-06-17 02:56:39 +000029static const char qlcnic_driver_string[] = "QLogic 1/10 GbE "
30 "Converged/Intelligent Ethernet Driver v" QLCNIC_LINUX_VERSIONID;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000031
Amit Kumar Salechaf7ec8042010-10-07 23:46:05 +000032static struct workqueue_struct *qlcnic_wq;
Amit Kumar Salechab5e54922010-08-31 17:17:51 +000033static int qlcnic_mac_learn;
amit salechab11a25a2011-01-10 00:15:23 +000034module_param(qlcnic_mac_learn, int, 0444);
Amit Kumar Salechab5e54922010-08-31 17:17:51 +000035MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
36
Sony Chacko099f7aa2012-12-04 03:33:58 +000037static int qlcnic_use_msi = 1;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000038MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled");
Sony Chacko099f7aa2012-12-04 03:33:58 +000039module_param_named(use_msi, qlcnic_use_msi, int, 0444);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000040
Sony Chacko099f7aa2012-12-04 03:33:58 +000041static int qlcnic_use_msi_x = 1;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000042MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled");
Sony Chacko099f7aa2012-12-04 03:33:58 +000043module_param_named(use_msi_x, qlcnic_use_msi_x, int, 0444);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000044
Sony Chacko099f7aa2012-12-04 03:33:58 +000045static int qlcnic_auto_fw_reset = 1;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000046MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled");
Sony Chacko099f7aa2012-12-04 03:33:58 +000047module_param_named(auto_fw_reset, qlcnic_auto_fw_reset, int, 0644);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000048
Sony Chacko099f7aa2012-12-04 03:33:58 +000049static int qlcnic_load_fw_file;
Amit Kumar Salecha4d5bdb32010-05-17 01:22:11 +000050MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file");
Sony Chacko099f7aa2012-12-04 03:33:58 +000051module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444);
Amit Kumar Salecha4d5bdb32010-05-17 01:22:11 +000052
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +000053static int qlcnic_config_npars;
amit salechab11a25a2011-01-10 00:15:23 +000054module_param(qlcnic_config_npars, int, 0444);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +000055MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled");
56
Greg Kroah-Hartman1dd06ae2012-12-06 14:30:56 +000057static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
Bill Pemberton6bb58bb2012-12-03 09:23:25 -050058static void qlcnic_remove(struct pci_dev *pdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000059static int qlcnic_open(struct net_device *netdev);
60static int qlcnic_close(struct net_device *netdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000061static void qlcnic_tx_timeout(struct net_device *netdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000062static void qlcnic_attach_work(struct work_struct *work);
63static void qlcnic_fwinit_work(struct work_struct *work);
64static void qlcnic_fw_poll_work(struct work_struct *work);
65static void qlcnic_schedule_work(struct qlcnic_adapter *adapter,
66 work_func_t func, int delay);
67static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000068#ifdef CONFIG_NET_POLL_CONTROLLER
69static void qlcnic_poll_controller(struct net_device *netdev);
70#endif
71
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +000072static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
Amit Kumar Salecha21854f02010-08-19 05:08:29 +000073static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000074static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
75
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +000076static irqreturn_t qlcnic_tmp_intr(int irq, void *data);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000077static irqreturn_t qlcnic_intr(int irq, void *data);
78static irqreturn_t qlcnic_msi_intr(int irq, void *data);
79static irqreturn_t qlcnic_msix_intr(int irq, void *data);
80
81static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev);
Amit Kumar Salechaaec1e842010-09-16 19:14:41 +000082static void qlcnic_restore_indev_addr(struct net_device *dev, unsigned long);
Anirban Chakraborty9f26f542010-06-01 11:33:09 +000083static int qlcnic_start_firmware(struct qlcnic_adapter *);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000084
Amit Kumar Salechab5e54922010-08-31 17:17:51 +000085static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
Anirban Chakraborty9f26f542010-06-01 11:33:09 +000086static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
Anirban Chakraborty9f26f542010-06-01 11:33:09 +000087static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
Rajesh Borundia0325d692010-08-19 05:08:26 +000088static void qlcnic_set_netdev_features(struct qlcnic_adapter *,
89 struct qlcnic_esw_func_cfg *);
Jiri Pirko8e586132011-12-08 19:52:37 -050090static int qlcnic_vlan_rx_add(struct net_device *, u16);
91static int qlcnic_vlan_rx_del(struct net_device *, u16);
Anirban Chakrabortyb9796a12011-04-01 14:28:15 +000092
Sony Chackobff57d82012-12-04 03:33:56 +000093#define QLCNIC_IS_TSO_CAPABLE(adapter) \
94 ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
95
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000096/* PCI Device ID Table */
97#define ENTRY(device) \
98 {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
99 .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0}
100
101#define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020
102
Amit Kumar Salecha6a902882010-02-01 05:24:54 +0000103static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000104 ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X),
105 {0,}
106};
107
108MODULE_DEVICE_TABLE(pci, qlcnic_pci_tbl);
109
110
Sony Chacko5ad6ff92012-11-17 21:04:38 +0000111inline void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *tx_ring)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000112{
113 writel(tx_ring->producer, tx_ring->crb_cmd_producer);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000114}
115
116static const u32 msi_tgt_status[8] = {
117 ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
118 ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
119 ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
120 ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
121};
122
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000123static const u32 qlcnic_reg_tbl[] = {
124 0x1B20A8, /* PEG_HALT_STAT1 */
125 0x1B20AC, /* PEG_HALT_STAT2 */
126 0x1B20B0, /* FW_HEARTBEAT */
127 0x1B2100, /* LOCK ID */
128 0x1B2128, /* FW_CAPABILITIES */
129 0x1B2138, /* drv active */
130 0x1B2140, /* dev state */
131 0x1B2144, /* drv state */
132 0x1B2148, /* drv scratch */
133 0x1B214C, /* dev partition info */
134 0x1B2174, /* drv idc ver */
135 0x1B2150, /* fw version major */
136 0x1B2154, /* fw version minor */
137 0x1B2158, /* fw version sub */
138 0x1B219C, /* npar state */
139 0x1B21FC, /* FW_IMG_VALID */
140 0x1B2250, /* CMD_PEG_STATE */
141 0x1B233C, /* RCV_PEG_STATE */
142 0x1B23B4, /* ASIC TEMP */
143 0x1B216C, /* FW api */
144 0x1B2170, /* drv op mode */
145 0x13C010, /* flash lock */
146 0x13C014, /* flash unlock */
147};
148
Sony Chacko22999792012-12-04 03:33:55 +0000149static const struct qlcnic_board_info qlcnic_boards[] = {
150 {0x1077, 0x8020, 0x1077, 0x203,
151 "8200 Series Single Port 10GbE Converged Network Adapter"
152 "(TCP/IP Networking)"},
153 {0x1077, 0x8020, 0x1077, 0x207,
154 "8200 Series Dual Port 10GbE Converged Network Adapter"
155 "(TCP/IP Networking)"},
156 {0x1077, 0x8020, 0x1077, 0x20b,
157 "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"},
158 {0x1077, 0x8020, 0x1077, 0x20c,
159 "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"},
160 {0x1077, 0x8020, 0x1077, 0x20f,
161 "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"},
162 {0x1077, 0x8020, 0x103c, 0x3733,
163 "NC523SFP 10Gb 2-port Server Adapter"},
164 {0x1077, 0x8020, 0x103c, 0x3346,
165 "CN1000Q Dual Port Converged Network Adapter"},
166 {0x1077, 0x8020, 0x1077, 0x210,
167 "QME8242-k 10GbE Dual Port Mezzanine Card"},
168 {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
169};
170
171#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards)
172
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000173static const
174struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG;
175
Sony Chackoc70001a2012-11-28 04:34:26 +0000176int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000177{
178 int size = sizeof(struct qlcnic_host_sds_ring) * count;
179
180 recv_ctx->sds_rings = kzalloc(size, GFP_KERNEL);
181
Eric Dumazet807540b2010-09-23 05:40:09 +0000182 return recv_ctx->sds_rings == NULL;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000183}
184
Sony Chackoc70001a2012-11-28 04:34:26 +0000185void qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000186{
187 if (recv_ctx->sds_rings != NULL)
188 kfree(recv_ctx->sds_rings);
189
190 recv_ctx->sds_rings = NULL;
191}
192
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000193static void qlcnic_set_msix_bit(struct pci_dev *pdev, int enable)
194{
195 u32 control;
196 int pos;
197
198 pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
199 if (pos) {
200 pci_read_config_dword(pdev, pos, &control);
201 if (enable)
202 control |= PCI_MSIX_FLAGS_ENABLE;
203 else
204 control = 0;
205 pci_write_config_dword(pdev, pos, control);
206 }
207}
208
209static void qlcnic_init_msix_entries(struct qlcnic_adapter *adapter, int count)
210{
211 int i;
212
213 for (i = 0; i < count; i++)
214 adapter->msix_entries[i].entry = i;
215}
216
217static int
218qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
219{
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000220 u8 mac_addr[ETH_ALEN];
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000221 struct net_device *netdev = adapter->netdev;
222 struct pci_dev *pdev = adapter->pdev;
223
Rajesh Borundiada48e6c2010-08-31 17:17:46 +0000224 if (qlcnic_get_mac_address(adapter, mac_addr) != 0)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000225 return -EIO;
226
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000227 memcpy(netdev->dev_addr, mac_addr, ETH_ALEN);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000228 memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
229 memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len);
230
231 /* set station address */
232
233 if (!is_valid_ether_addr(netdev->perm_addr))
234 dev_warn(&pdev->dev, "Bad MAC address %pM.\n",
235 netdev->dev_addr);
236
237 return 0;
238}
239
240static int qlcnic_set_mac(struct net_device *netdev, void *p)
241{
242 struct qlcnic_adapter *adapter = netdev_priv(netdev);
243 struct sockaddr *addr = p;
244
Rajesh Borundia73733732010-08-31 17:17:50 +0000245 if ((adapter->flags & QLCNIC_MAC_OVERRIDE_DISABLED))
246 return -EOPNOTSUPP;
247
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000248 if (!is_valid_ether_addr(addr->sa_data))
Danny Kukawka504f9b52012-02-21 02:07:49 +0000249 return -EADDRNOTAVAIL;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000250
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000251 if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000252 netif_device_detach(netdev);
253 qlcnic_napi_disable(adapter);
254 }
255
256 memcpy(adapter->mac_addr, addr->sa_data, netdev->addr_len);
257 memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
258 qlcnic_set_multi(adapter->netdev);
259
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000260 if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000261 netif_device_attach(netdev);
262 qlcnic_napi_enable(adapter);
263 }
264 return 0;
265}
266
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000267static void qlcnic_82xx_cancel_idc_work(struct qlcnic_adapter *adapter)
268{
269 while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
270 usleep_range(10000, 11000);
271
272 cancel_delayed_work_sync(&adapter->fw_work);
273}
274
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000275static const struct net_device_ops qlcnic_netdev_ops = {
276 .ndo_open = qlcnic_open,
277 .ndo_stop = qlcnic_close,
278 .ndo_start_xmit = qlcnic_xmit_frame,
279 .ndo_get_stats = qlcnic_get_stats,
280 .ndo_validate_addr = eth_validate_addr,
Jiri Pirkoafc4b132011-08-16 06:29:01 +0000281 .ndo_set_rx_mode = qlcnic_set_multi,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000282 .ndo_set_mac_address = qlcnic_set_mac,
283 .ndo_change_mtu = qlcnic_change_mtu,
Michał Mirosław135d84a2011-04-19 03:03:57 +0000284 .ndo_fix_features = qlcnic_fix_features,
285 .ndo_set_features = qlcnic_set_features,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000286 .ndo_tx_timeout = qlcnic_tx_timeout,
Anirban Chakrabortyb9796a12011-04-01 14:28:15 +0000287 .ndo_vlan_rx_add_vid = qlcnic_vlan_rx_add,
288 .ndo_vlan_rx_kill_vid = qlcnic_vlan_rx_del,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000289#ifdef CONFIG_NET_POLL_CONTROLLER
290 .ndo_poll_controller = qlcnic_poll_controller,
291#endif
292};
293
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +0000294static const struct net_device_ops qlcnic_netdev_failed_ops = {
295 .ndo_open = qlcnic_open,
296};
297
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000298static struct qlcnic_nic_template qlcnic_ops = {
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000299 .config_bridged_mode = qlcnic_config_bridged_mode,
300 .config_led = qlcnic_82xx_config_led,
301 .start_firmware = qlcnic_82xx_start_firmware,
302 .request_reset = qlcnic_82xx_dev_request_reset,
303 .cancel_idc_work = qlcnic_82xx_cancel_idc_work,
304 .napi_add = qlcnic_82xx_napi_add,
305 .config_ipaddr = qlcnic_82xx_config_ipaddr,
306 .clear_legacy_intr = qlcnic_82xx_clear_legacy_intr,
Anirban Chakraborty9f26f542010-06-01 11:33:09 +0000307};
308
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000309struct qlcnic_nic_template qlcnic_vf_ops = {
310 .config_bridged_mode = qlcnicvf_config_bridged_mode,
311 .config_led = qlcnicvf_config_led,
312 .start_firmware = qlcnicvf_start_firmware
313};
314
315static struct qlcnic_hardware_ops qlcnic_hw_ops = {
316 .read_crb = qlcnic_82xx_read_crb,
317 .write_crb = qlcnic_82xx_write_crb,
318 .read_reg = qlcnic_82xx_hw_read_wx_2M,
319 .write_reg = qlcnic_82xx_hw_write_wx_2M,
320 .get_mac_address = qlcnic_82xx_get_mac_address,
321 .setup_intr = qlcnic_82xx_setup_intr,
322 .alloc_mbx_args = qlcnic_82xx_alloc_mbx_args,
323 .mbx_cmd = qlcnic_82xx_issue_cmd,
324 .get_func_no = qlcnic_82xx_get_func_no,
325 .api_lock = qlcnic_82xx_api_lock,
326 .api_unlock = qlcnic_82xx_api_unlock,
327 .add_sysfs = qlcnic_82xx_add_sysfs,
328 .remove_sysfs = qlcnic_82xx_remove_sysfs,
329 .process_lb_rcv_ring_diag = qlcnic_82xx_process_rcv_ring_diag,
330 .create_rx_ctx = qlcnic_82xx_fw_cmd_create_rx_ctx,
331 .create_tx_ctx = qlcnic_82xx_fw_cmd_create_tx_ctx,
332 .setup_link_event = qlcnic_82xx_linkevent_request,
333 .get_nic_info = qlcnic_82xx_get_nic_info,
334 .get_pci_info = qlcnic_82xx_get_pci_info,
335 .set_nic_info = qlcnic_82xx_set_nic_info,
336 .change_macvlan = qlcnic_82xx_sre_macaddr_change,
337 .napi_enable = qlcnic_82xx_napi_enable,
338 .napi_disable = qlcnic_82xx_napi_disable,
339 .config_intr_coal = qlcnic_82xx_config_intr_coalesce,
340 .config_rss = qlcnic_82xx_config_rss,
341 .config_hw_lro = qlcnic_82xx_config_hw_lro,
342 .config_loopback = qlcnic_82xx_set_lb_mode,
343 .clear_loopback = qlcnic_82xx_clear_lb_mode,
344 .config_promisc_mode = qlcnic_82xx_nic_set_promisc,
345 .change_l2_filter = qlcnic_82xx_change_filter,
346 .get_board_info = qlcnic_82xx_get_board_info,
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000347};
348
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +0000349static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
350{
351 struct pci_dev *pdev = adapter->pdev;
352 int err = -1;
353
354 adapter->max_sds_rings = 1;
355 adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED);
356 qlcnic_set_msix_bit(pdev, 0);
357
Sony Chacko79788452012-12-04 03:33:53 +0000358 if (adapter->ahw->msix_supported) {
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +0000359 enable_msix:
360 qlcnic_init_msix_entries(adapter, num_msix);
361 err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
362 if (err == 0) {
363 adapter->flags |= QLCNIC_MSIX_ENABLED;
364 qlcnic_set_msix_bit(pdev, 1);
365
366 adapter->max_sds_rings = num_msix;
367
368 dev_info(&pdev->dev, "using msi-x interrupts\n");
369 return err;
370 }
371 if (err > 0) {
372 num_msix = rounddown_pow_of_two(err);
373 if (num_msix)
374 goto enable_msix;
375 }
376 }
377 return err;
378}
379
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +0000380static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000381{
Sony Chacko15087c22012-12-04 03:33:54 +0000382 u32 offset, mask_reg;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000383 const struct qlcnic_legacy_intr_set *legacy_intrp;
Sony Chacko15087c22012-12-04 03:33:54 +0000384 struct qlcnic_hardware_context *ahw = adapter->ahw;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000385 struct pci_dev *pdev = adapter->pdev;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000386
Sony Chacko099f7aa2012-12-04 03:33:58 +0000387 if (qlcnic_use_msi && !pci_enable_msi(pdev)) {
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +0000388 adapter->flags |= QLCNIC_MSI_ENABLED;
Sony Chacko15087c22012-12-04 03:33:54 +0000389 offset = msi_tgt_status[adapter->ahw->pci_func];
390 adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter->ahw,
391 offset);
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +0000392 dev_info(&pdev->dev, "using msi interrupts\n");
393 adapter->msix_entries[0].vector = pdev->irq;
394 return;
395 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000396
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000397 legacy_intrp = &legacy_intr[adapter->ahw->pci_func];
Sony Chacko79788452012-12-04 03:33:53 +0000398 adapter->ahw->int_vec_bit = legacy_intrp->int_vec_bit;
Sony Chacko15087c22012-12-04 03:33:54 +0000399 offset = legacy_intrp->tgt_status_reg;
400 adapter->tgt_status_reg = qlcnic_get_ioaddr(ahw, offset);
401 mask_reg = legacy_intrp->tgt_mask_reg;
402 adapter->tgt_mask_reg = qlcnic_get_ioaddr(ahw, mask_reg);
403 adapter->isr_int_vec = qlcnic_get_ioaddr(ahw, ISR_INT_VECTOR);
404 adapter->crb_int_state_reg = qlcnic_get_ioaddr(ahw, ISR_INT_STATE_REG);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000405 dev_info(&pdev->dev, "using legacy interrupts\n");
406 adapter->msix_entries[0].vector = pdev->irq;
407}
408
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000409int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +0000410{
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000411 int num_msix, err;
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +0000412
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000413 if (!num_intr)
414 num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;
415
416 if (adapter->ahw->msix_supported)
Sucheta Chakraborty5f6ec292011-06-22 02:52:20 +0000417 num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000418 num_intr));
419 else
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +0000420 num_msix = 1;
421
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000422 err = qlcnic_enable_msix(adapter, num_msix);
423 if (err == -ENOMEM || !err)
424 return err;
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +0000425
426 qlcnic_enable_msi_legacy(adapter);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000427 return 0;
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +0000428}
429
430static void
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000431qlcnic_teardown_intr(struct qlcnic_adapter *adapter)
432{
433 if (adapter->flags & QLCNIC_MSIX_ENABLED)
434 pci_disable_msix(adapter->pdev);
435 if (adapter->flags & QLCNIC_MSI_ENABLED)
436 pci_disable_msi(adapter->pdev);
437}
438
439static void
440qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
441{
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000442 if (adapter->ahw->pci_base0 != NULL)
443 iounmap(adapter->ahw->pci_base0);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000444}
445
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000446static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter)
447{
448 struct qlcnic_pci_info *pci_info;
449 int ret;
450
451 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
452 switch (adapter->ahw->port_type) {
453 case QLCNIC_GBE:
454 adapter->ahw->act_pci_func = QLCNIC_NIU_MAX_GBE_PORTS;
455 break;
456 case QLCNIC_XGBE:
457 adapter->ahw->act_pci_func = QLCNIC_NIU_MAX_XG_PORTS;
458 break;
459 }
460 return 0;
461 }
462
463 if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
464 return 0;
465
466 pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
467 if (!pci_info)
468 return -ENOMEM;
469
470 ret = qlcnic_get_pci_info(adapter, pci_info);
471 kfree(pci_info);
472 return ret;
473}
Sony Chackobff57d82012-12-04 03:33:56 +0000474static int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000475{
Dan Carpentere88db3b2010-08-09 21:49:36 +0000476 struct qlcnic_pci_info *pci_info;
Sony Chackobff57d82012-12-04 03:33:56 +0000477 int i, ret = 0, j = 0;
478 u16 act_pci_func;
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000479 u8 pfn;
480
Dan Carpentere88db3b2010-08-09 21:49:36 +0000481 pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
482 if (!pci_info)
483 return -ENOMEM;
484
Sony Chackobff57d82012-12-04 03:33:56 +0000485 ret = qlcnic_get_pci_info(adapter, pci_info);
486 if (ret)
487 goto err_pci_info;
488
489 act_pci_func = adapter->ahw->act_pci_func;
490
Dan Carpenterca315ac2010-08-09 21:47:56 +0000491 adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
Sony Chackobff57d82012-12-04 03:33:56 +0000492 act_pci_func, GFP_KERNEL);
Dan Carpentere88db3b2010-08-09 21:49:36 +0000493 if (!adapter->npars) {
Julia Lawall900853a2010-08-16 10:23:51 +0000494 ret = -ENOMEM;
Dan Carpentere88db3b2010-08-09 21:49:36 +0000495 goto err_pci_info;
496 }
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000497
Dan Carpenterca315ac2010-08-09 21:47:56 +0000498 adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) *
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000499 QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL);
500 if (!adapter->eswitch) {
Julia Lawall900853a2010-08-16 10:23:51 +0000501 ret = -ENOMEM;
Dan Carpenterca315ac2010-08-09 21:47:56 +0000502 goto err_npars;
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000503 }
504
Dan Carpenterca315ac2010-08-09 21:47:56 +0000505 for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
506 pfn = pci_info[i].id;
Sony Chackobff57d82012-12-04 03:33:56 +0000507
Dan Carpenter0f6efff92012-06-14 08:34:24 +0000508 if (pfn >= QLCNIC_MAX_PCI_FUNC) {
Sony Chackof848d6d2011-04-01 14:27:59 +0000509 ret = QL_STATUS_INVALID_PARAM;
510 goto err_eswitch;
511 }
Sony Chackobff57d82012-12-04 03:33:56 +0000512
513 if (!pci_info[i].active ||
514 (pci_info[i].type != QLCNIC_TYPE_NIC))
515 continue;
516
517 adapter->npars[j].pci_func = pfn;
518 adapter->npars[j].active = (u8)pci_info[i].active;
519 adapter->npars[j].type = (u8)pci_info[i].type;
520 adapter->npars[j].phy_port = (u8)pci_info[i].default_port;
521 adapter->npars[j].min_bw = pci_info[i].tx_min_bw;
522 adapter->npars[j].max_bw = pci_info[i].tx_max_bw;
523 j++;
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000524 }
525
Dan Carpenterca315ac2010-08-09 21:47:56 +0000526 for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
527 adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE;
528
Dan Carpentere88db3b2010-08-09 21:49:36 +0000529 kfree(pci_info);
Dan Carpenterca315ac2010-08-09 21:47:56 +0000530 return 0;
531
532err_eswitch:
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000533 kfree(adapter->eswitch);
534 adapter->eswitch = NULL;
Dan Carpenterca315ac2010-08-09 21:47:56 +0000535err_npars:
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000536 kfree(adapter->npars);
Dan Carpenterca315ac2010-08-09 21:47:56 +0000537 adapter->npars = NULL;
Dan Carpentere88db3b2010-08-09 21:49:36 +0000538err_pci_info:
539 kfree(pci_info);
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000540
541 return ret;
542}
543
544static int
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000545qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
546{
547 u8 id;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000548 int i, ret = 1;
549 u32 data = QLCNIC_MGMT_FUNC;
Sony Chackobff57d82012-12-04 03:33:56 +0000550 struct qlcnic_hardware_context *ahw = adapter->ahw;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000551
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000552 ret = qlcnic_api_lock(adapter);
553 if (ret)
554 goto err_lock;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000555
Anirban Chakraborty0e33c662010-06-16 09:07:27 +0000556 if (qlcnic_config_npars) {
Sony Chackobff57d82012-12-04 03:33:56 +0000557 for (i = 0; i < ahw->act_pci_func; i++) {
558 id = adapter->npars[i].pci_func;
559 if (id == ahw->pci_func)
Anirban Chakraborty0e33c662010-06-16 09:07:27 +0000560 continue;
561 data |= (qlcnic_config_npars &
562 QLC_DEV_SET_DRV(0xf, id));
563 }
564 } else {
Sony Chackobff57d82012-12-04 03:33:56 +0000565 data = QLCRD32(adapter, QLCNIC_DRV_OP_MODE);
566 data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) |
Anirban Chakraborty0e33c662010-06-16 09:07:27 +0000567 (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC,
Sony Chackobff57d82012-12-04 03:33:56 +0000568 ahw->pci_func));
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000569 }
Sony Chackobff57d82012-12-04 03:33:56 +0000570 QLCWR32(adapter, QLCNIC_DRV_OP_MODE, data);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000571 qlcnic_api_unlock(adapter);
572err_lock:
573 return ret;
574}
575
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000576static void
577qlcnic_check_vf(struct qlcnic_adapter *adapter)
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000578{
579 void __iomem *msix_base_addr;
580 void __iomem *priv_op;
581 u32 func;
582 u32 msix_base;
583 u32 op_mode, priv_level;
584
585 /* Determine FW API version */
Sony Chacko79788452012-12-04 03:33:53 +0000586 adapter->ahw->fw_hal_version = readl(adapter->ahw->pci_base0 +
587 QLCNIC_FW_API);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000588
589 /* Find PCI function number */
590 pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000591 msix_base_addr = adapter->ahw->pci_base0 + QLCNIC_MSIX_BASE;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000592 msix_base = readl(msix_base_addr);
593 func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000594 adapter->ahw->pci_func = func;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000595
596 /* Determine function privilege level */
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000597 priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000598 op_mode = readl(priv_op);
Anirban Chakraborty0e33c662010-06-16 09:07:27 +0000599 if (op_mode == QLC_DEV_DRV_DEFAULT)
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000600 priv_level = QLCNIC_MGMT_FUNC;
Anirban Chakraborty0e33c662010-06-16 09:07:27 +0000601 else
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000602 priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000603
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000604 if (priv_level == QLCNIC_NON_PRIV_FUNC) {
Sony Chacko79788452012-12-04 03:33:53 +0000605 adapter->ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
Anirban Chakraborty9f26f542010-06-01 11:33:09 +0000606 dev_info(&adapter->pdev->dev,
607 "HAL Version: %d Non Privileged function\n",
Sony Chacko79788452012-12-04 03:33:53 +0000608 adapter->ahw->fw_hal_version);
Anirban Chakraborty9f26f542010-06-01 11:33:09 +0000609 adapter->nic_ops = &qlcnic_vf_ops;
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000610 } else
611 adapter->nic_ops = &qlcnic_ops;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000612}
613
Sony Chacko15087c22012-12-04 03:33:54 +0000614#define QLCNIC_82XX_BAR0_LENGTH 0x00200000UL
615static void qlcnic_get_bar_length(u32 dev_id, ulong *bar)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000616{
Sony Chacko15087c22012-12-04 03:33:54 +0000617 switch (dev_id) {
618 case PCI_DEVICE_ID_QLOGIC_QLE824X:
619 *bar = QLCNIC_82XX_BAR0_LENGTH;
620 break;
621 default:
622 *bar = 0;
623 }
624}
625
626static int qlcnic_setup_pci_map(struct pci_dev *pdev,
627 struct qlcnic_hardware_context *ahw)
628{
629 u32 offset;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000630 void __iomem *mem_ptr0 = NULL;
Sony Chacko15087c22012-12-04 03:33:54 +0000631 unsigned long mem_len, pci_len0 = 0, bar0_len;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000632
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000633 /* remap phys address */
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000634 mem_len = pci_resource_len(pdev, 0);
635
Sony Chacko15087c22012-12-04 03:33:54 +0000636 qlcnic_get_bar_length(pdev->device, &bar0_len);
637 if (mem_len >= bar0_len) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000638
639 mem_ptr0 = pci_ioremap_bar(pdev, 0);
640 if (mem_ptr0 == NULL) {
641 dev_err(&pdev->dev, "failed to map PCI bar 0\n");
642 return -EIO;
643 }
644 pci_len0 = mem_len;
645 } else {
646 return -EIO;
647 }
648
649 dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000650
Sony Chacko15087c22012-12-04 03:33:54 +0000651 ahw->pci_base0 = mem_ptr0;
652 ahw->pci_len0 = pci_len0;
653 offset = QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(ahw->pci_func));
654 qlcnic_get_ioaddr(ahw, offset);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000655
656 return 0;
657}
658
Sony Chacko22999792012-12-04 03:33:55 +0000659static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000660{
661 struct pci_dev *pdev = adapter->pdev;
662 int i, found = 0;
663
664 for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) {
665 if (qlcnic_boards[i].vendor == pdev->vendor &&
666 qlcnic_boards[i].device == pdev->device &&
667 qlcnic_boards[i].sub_vendor == pdev->subsystem_vendor &&
668 qlcnic_boards[i].sub_device == pdev->subsystem_device) {
Sucheta Chakraborty02f6e462010-05-17 01:22:09 +0000669 sprintf(name, "%pM: %s" ,
670 adapter->mac_addr,
671 qlcnic_boards[i].short_name);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000672 found = 1;
673 break;
674 }
675
676 }
677
678 if (!found)
Sritej Velaga7f9a0c32010-06-17 02:56:39 +0000679 sprintf(name, "%pM Gigabit Ethernet", adapter->mac_addr);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000680}
681
682static void
683qlcnic_check_options(struct qlcnic_adapter *adapter)
684{
Sritej Velaga031a4a22011-07-29 13:30:28 +0000685 u32 fw_major, fw_minor, fw_build, prev_fw_version;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000686 struct pci_dev *pdev = adapter->pdev;
Sritej Velaga031a4a22011-07-29 13:30:28 +0000687 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
688
689 prev_fw_version = adapter->fw_version;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000690
691 fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
692 fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
693 fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB);
694
695 adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
696
Sony Chacko79788452012-12-04 03:33:53 +0000697 if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC) {
Sritej Velaga031a4a22011-07-29 13:30:28 +0000698 if (fw_dump->tmpl_hdr == NULL ||
699 adapter->fw_version > prev_fw_version) {
700 if (fw_dump->tmpl_hdr)
701 vfree(fw_dump->tmpl_hdr);
702 if (!qlcnic_fw_cmd_get_minidump_temp(adapter))
703 dev_info(&pdev->dev,
704 "Supports FW dump capability\n");
705 }
706 }
707
Amit Kumar Salecha251a84c2010-05-13 03:07:46 +0000708 dev_info(&pdev->dev, "firmware v%d.%d.%d\n",
709 fw_major, fw_minor, fw_build);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000710 if (adapter->ahw->port_type == QLCNIC_XGBE) {
Sony Chacko90d19002010-10-26 17:53:08 +0000711 if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
712 adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF;
713 adapter->max_rxd = MAX_RCV_DESCRIPTORS_VF;
714 } else {
715 adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;
716 adapter->max_rxd = MAX_RCV_DESCRIPTORS_10G;
717 }
718
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000719 adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
Sony Chacko90d19002010-10-26 17:53:08 +0000720 adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
721
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000722 } else if (adapter->ahw->port_type == QLCNIC_GBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000723 adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
724 adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
Sony Chacko90d19002010-10-26 17:53:08 +0000725 adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
726 adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000727 }
728
Sony Chacko099f7aa2012-12-04 03:33:58 +0000729 adapter->ahw->msix_supported = !!qlcnic_use_msi_x;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000730
731 adapter->num_txd = MAX_CMD_DESCRIPTORS;
732
Sony Chacko251b0362010-08-19 05:08:24 +0000733 adapter->max_rds_rings = MAX_RDS_RINGS;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000734}
735
Rajesh Borundia174240a2010-08-31 17:17:47 +0000736static int
737qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
738{
739 int err;
740 struct qlcnic_info nic_info;
741
Sony Chackobff57d82012-12-04 03:33:56 +0000742 memset(&nic_info, 0, sizeof(struct qlcnic_info));
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000743 err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw->pci_func);
Rajesh Borundia174240a2010-08-31 17:17:47 +0000744 if (err)
745 return err;
746
Sony Chacko79788452012-12-04 03:33:53 +0000747 adapter->ahw->physical_port = (u8)nic_info.phys_port;
748 adapter->ahw->switch_mode = nic_info.switch_mode;
749 adapter->ahw->max_tx_ques = nic_info.max_tx_ques;
750 adapter->ahw->max_rx_ques = nic_info.max_rx_ques;
751 adapter->ahw->capabilities = nic_info.capabilities;
752 adapter->ahw->max_mac_filters = nic_info.max_mac_filters;
753 adapter->ahw->max_mtu = nic_info.max_mtu;
Rajesh Borundia174240a2010-08-31 17:17:47 +0000754
Sony Chacko79788452012-12-04 03:33:53 +0000755 if (adapter->ahw->capabilities & BIT_6)
Rajesh Borundia174240a2010-08-31 17:17:47 +0000756 adapter->flags |= QLCNIC_ESWITCH_ENABLED;
757 else
758 adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
759
760 return err;
761}
762
Sony Chackoec079a02012-11-28 04:34:28 +0000763void qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
764 struct qlcnic_esw_func_cfg *esw_cfg)
Amit Kumar Salecha8cf61f82010-08-25 04:03:03 +0000765{
766 if (esw_cfg->discard_tagged)
767 adapter->flags &= ~QLCNIC_TAGGING_ENABLED;
768 else
769 adapter->flags |= QLCNIC_TAGGING_ENABLED;
770
771 if (esw_cfg->vlan_id)
772 adapter->pvid = esw_cfg->vlan_id;
773 else
774 adapter->pvid = 0;
775}
776
Jiri Pirko8e586132011-12-08 19:52:37 -0500777static int
Anirban Chakrabortyb9796a12011-04-01 14:28:15 +0000778qlcnic_vlan_rx_add(struct net_device *netdev, u16 vid)
779{
780 struct qlcnic_adapter *adapter = netdev_priv(netdev);
781 set_bit(vid, adapter->vlans);
Jiri Pirko8e586132011-12-08 19:52:37 -0500782 return 0;
Anirban Chakrabortyb9796a12011-04-01 14:28:15 +0000783}
784
Jiri Pirko8e586132011-12-08 19:52:37 -0500785static int
Anirban Chakrabortyb9796a12011-04-01 14:28:15 +0000786qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid)
787{
788 struct qlcnic_adapter *adapter = netdev_priv(netdev);
789
790 qlcnic_restore_indev_addr(netdev, NETDEV_DOWN);
791 clear_bit(vid, adapter->vlans);
Jiri Pirko8e586132011-12-08 19:52:37 -0500792 return 0;
Anirban Chakrabortyb9796a12011-04-01 14:28:15 +0000793}
794
Sony Chackoec079a02012-11-28 04:34:28 +0000795void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
796 struct qlcnic_esw_func_cfg *esw_cfg)
Rajesh Borundia0325d692010-08-19 05:08:26 +0000797{
Rajesh Borundiaee07c1a2010-10-07 23:46:09 +0000798 adapter->flags &= ~(QLCNIC_MACSPOOF | QLCNIC_MAC_OVERRIDE_DISABLED |
799 QLCNIC_PROMISC_DISABLED);
Rajesh Borundia7613c872010-08-31 17:17:48 +0000800
801 if (esw_cfg->mac_anti_spoof)
802 adapter->flags |= QLCNIC_MACSPOOF;
Sony Chackofe4d4342010-08-19 05:08:27 +0000803
Rajesh Borundia73733732010-08-31 17:17:50 +0000804 if (!esw_cfg->mac_override)
805 adapter->flags |= QLCNIC_MAC_OVERRIDE_DISABLED;
806
Rajesh Borundiaee07c1a2010-10-07 23:46:09 +0000807 if (!esw_cfg->promisc_mode)
808 adapter->flags |= QLCNIC_PROMISC_DISABLED;
809
Rajesh Borundia0325d692010-08-19 05:08:26 +0000810 qlcnic_set_netdev_features(adapter, esw_cfg);
811}
812
Sony Chackoec079a02012-11-28 04:34:28 +0000813static int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
Rajesh Borundia0325d692010-08-19 05:08:26 +0000814{
815 struct qlcnic_esw_func_cfg esw_cfg;
816
817 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
818 return 0;
819
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000820 esw_cfg.pci_func = adapter->ahw->pci_func;
Rajesh Borundia0325d692010-08-19 05:08:26 +0000821 if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg))
822 return -EIO;
Amit Kumar Salecha8cf61f82010-08-25 04:03:03 +0000823 qlcnic_set_vlan_config(adapter, &esw_cfg);
Rajesh Borundia0325d692010-08-19 05:08:26 +0000824 qlcnic_set_eswitch_port_features(adapter, &esw_cfg);
825
826 return 0;
827}
828
829static void
830qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
831 struct qlcnic_esw_func_cfg *esw_cfg)
832{
833 struct net_device *netdev = adapter->netdev;
Michał Mirosławc8f44af2011-11-15 15:29:55 +0000834 netdev_features_t features, vlan_features;
Rajesh Borundia0325d692010-08-19 05:08:26 +0000835
Michał Mirosław135d84a2011-04-19 03:03:57 +0000836 features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
Rajesh Borundia0325d692010-08-19 05:08:26 +0000837 NETIF_F_IPV6_CSUM | NETIF_F_GRO);
838 vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM |
Anirban Chakrabortyb9796a12011-04-01 14:28:15 +0000839 NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER);
Rajesh Borundia0325d692010-08-19 05:08:26 +0000840
Sony Chacko79788452012-12-04 03:33:53 +0000841 if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
Rajesh Borundia0325d692010-08-19 05:08:26 +0000842 features |= (NETIF_F_TSO | NETIF_F_TSO6);
843 vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
844 }
Rajesh Borundiab56421d2011-04-01 14:28:31 +0000845
846 if (netdev->features & NETIF_F_LRO)
Rajesh Borundia0325d692010-08-19 05:08:26 +0000847 features |= NETIF_F_LRO;
848
849 if (esw_cfg->offload_flags & BIT_0) {
850 netdev->features |= features;
Rajesh Borundia0325d692010-08-19 05:08:26 +0000851 if (!(esw_cfg->offload_flags & BIT_1))
852 netdev->features &= ~NETIF_F_TSO;
853 if (!(esw_cfg->offload_flags & BIT_2))
854 netdev->features &= ~NETIF_F_TSO6;
855 } else {
856 netdev->features &= ~features;
Rajesh Borundia0325d692010-08-19 05:08:26 +0000857 }
858
859 netdev->vlan_features = (features & vlan_features);
860}
861
862static int
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000863qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
864{
865 void __iomem *priv_op;
866 u32 op_mode, priv_level;
867 int err = 0;
868
Rajesh Borundia174240a2010-08-31 17:17:47 +0000869 err = qlcnic_initialize_nic(adapter);
870 if (err)
871 return err;
872
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000873 if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED)
874 return 0;
875
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000876 priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000877 op_mode = readl(priv_op);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000878 priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000879
880 if (op_mode == QLC_DEV_DRV_DEFAULT)
881 priv_level = QLCNIC_MGMT_FUNC;
882 else
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000883 priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000884
Rajesh Borundia174240a2010-08-31 17:17:47 +0000885 if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000886 if (priv_level == QLCNIC_MGMT_FUNC) {
Sony Chacko79788452012-12-04 03:33:53 +0000887 adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000888 err = qlcnic_init_pci_info(adapter);
889 if (err)
890 return err;
891 /* Set privilege level for other functions */
892 qlcnic_set_function_modes(adapter);
893 dev_info(&adapter->pdev->dev,
894 "HAL Version: %d, Management function\n",
Sony Chacko79788452012-12-04 03:33:53 +0000895 adapter->ahw->fw_hal_version);
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000896 } else if (priv_level == QLCNIC_PRIV_FUNC) {
Sony Chacko79788452012-12-04 03:33:53 +0000897 adapter->ahw->op_mode = QLCNIC_PRIV_FUNC;
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000898 dev_info(&adapter->pdev->dev,
899 "HAL Version: %d, Privileged function\n",
Sony Chacko79788452012-12-04 03:33:53 +0000900 adapter->ahw->fw_hal_version);
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000901 }
Rajesh Borundia174240a2010-08-31 17:17:47 +0000902 }
Anirban Chakraborty0866d962010-08-26 14:02:52 +0000903
904 adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
905
906 return err;
907}
908
Sony Chackobff57d82012-12-04 03:33:56 +0000909static int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
Rajesh Borundia0325d692010-08-19 05:08:26 +0000910{
911 struct qlcnic_esw_func_cfg esw_cfg;
912 struct qlcnic_npar_info *npar;
913 u8 i;
914
Rajesh Borundia174240a2010-08-31 17:17:47 +0000915 if (adapter->need_fw_reset)
Rajesh Borundia0325d692010-08-19 05:08:26 +0000916 return 0;
917
Sony Chackobff57d82012-12-04 03:33:56 +0000918 for (i = 0; i < adapter->ahw->act_pci_func; i++) {
Rajesh Borundia0325d692010-08-19 05:08:26 +0000919 memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg));
Sony Chackobff57d82012-12-04 03:33:56 +0000920 esw_cfg.pci_func = adapter->npars[i].pci_func;
Rajesh Borundia73733732010-08-31 17:17:50 +0000921 esw_cfg.mac_override = BIT_0;
Rajesh Borundiaee07c1a2010-10-07 23:46:09 +0000922 esw_cfg.promisc_mode = BIT_0;
Sony Chackobff57d82012-12-04 03:33:56 +0000923 if (qlcnic_82xx_check(adapter)) {
924 esw_cfg.offload_flags = BIT_0;
925 if (QLCNIC_IS_TSO_CAPABLE(adapter))
926 esw_cfg.offload_flags |= (BIT_1 | BIT_2);
927 }
Rajesh Borundia0325d692010-08-19 05:08:26 +0000928 if (qlcnic_config_switch_port(adapter, &esw_cfg))
929 return -EIO;
930 npar = &adapter->npars[i];
931 npar->pvid = esw_cfg.vlan_id;
Rajesh Borundia73733732010-08-31 17:17:50 +0000932 npar->mac_override = esw_cfg.mac_override;
Rajesh Borundia0325d692010-08-19 05:08:26 +0000933 npar->mac_anti_spoof = esw_cfg.mac_anti_spoof;
934 npar->discard_tagged = esw_cfg.discard_tagged;
935 npar->promisc_mode = esw_cfg.promisc_mode;
936 npar->offload_flags = esw_cfg.offload_flags;
937 }
938
939 return 0;
940}
941
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000942static int
Rajesh Borundia4e8acb02010-08-19 05:08:25 +0000943qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter,
944 struct qlcnic_npar_info *npar, int pci_func)
945{
946 struct qlcnic_esw_func_cfg esw_cfg;
947 esw_cfg.op_mode = QLCNIC_PORT_DEFAULTS;
948 esw_cfg.pci_func = pci_func;
949 esw_cfg.vlan_id = npar->pvid;
Rajesh Borundia73733732010-08-31 17:17:50 +0000950 esw_cfg.mac_override = npar->mac_override;
Rajesh Borundia4e8acb02010-08-19 05:08:25 +0000951 esw_cfg.discard_tagged = npar->discard_tagged;
952 esw_cfg.mac_anti_spoof = npar->mac_anti_spoof;
953 esw_cfg.offload_flags = npar->offload_flags;
954 esw_cfg.promisc_mode = npar->promisc_mode;
955 if (qlcnic_config_switch_port(adapter, &esw_cfg))
956 return -EIO;
957
958 esw_cfg.op_mode = QLCNIC_ADD_VLAN;
959 if (qlcnic_config_switch_port(adapter, &esw_cfg))
960 return -EIO;
961
962 return 0;
963}
964
Sony Chackobff57d82012-12-04 03:33:56 +0000965static int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
Anirban Chakrabortycea89752010-07-13 20:33:35 +0000966{
Rajesh Borundia4e8acb02010-08-19 05:08:25 +0000967 int i, err;
Anirban Chakrabortycea89752010-07-13 20:33:35 +0000968 struct qlcnic_npar_info *npar;
969 struct qlcnic_info nic_info;
Sony Chackobff57d82012-12-04 03:33:56 +0000970 u8 pci_func;
Anirban Chakrabortycea89752010-07-13 20:33:35 +0000971
Sony Chackobff57d82012-12-04 03:33:56 +0000972 if (qlcnic_82xx_check(adapter))
973 if (!adapter->need_fw_reset)
974 return 0;
Anirban Chakrabortycea89752010-07-13 20:33:35 +0000975
Rajesh Borundia4e8acb02010-08-19 05:08:25 +0000976 /* Set the NPAR config data after FW reset */
Sony Chackobff57d82012-12-04 03:33:56 +0000977 for (i = 0; i < adapter->ahw->act_pci_func; i++) {
Rajesh Borundia4e8acb02010-08-19 05:08:25 +0000978 npar = &adapter->npars[i];
Sony Chackobff57d82012-12-04 03:33:56 +0000979 pci_func = npar->pci_func;
980 memset(&nic_info, 0, sizeof(struct qlcnic_info));
981 err = qlcnic_get_nic_info(adapter,
982 &nic_info, pci_func);
Rajesh Borundia4e8acb02010-08-19 05:08:25 +0000983 if (err)
984 return err;
985 nic_info.min_tx_bw = npar->min_bw;
986 nic_info.max_tx_bw = npar->max_bw;
987 err = qlcnic_set_nic_info(adapter, &nic_info);
988 if (err)
989 return err;
Anirban Chakrabortycea89752010-07-13 20:33:35 +0000990
Rajesh Borundia4e8acb02010-08-19 05:08:25 +0000991 if (npar->enable_pm) {
992 err = qlcnic_config_port_mirroring(adapter,
Sony Chackobff57d82012-12-04 03:33:56 +0000993 npar->dest_npar, 1,
994 pci_func);
Rajesh Borundia4e8acb02010-08-19 05:08:25 +0000995 if (err)
996 return err;
Anirban Chakrabortycea89752010-07-13 20:33:35 +0000997 }
Sony Chackobff57d82012-12-04 03:33:56 +0000998 err = qlcnic_reset_eswitch_config(adapter, npar, pci_func);
Rajesh Borundia4e8acb02010-08-19 05:08:25 +0000999 if (err)
1000 return err;
Anirban Chakrabortycea89752010-07-13 20:33:35 +00001001 }
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001002 return 0;
Anirban Chakrabortycea89752010-07-13 20:33:35 +00001003}
1004
Amit Kumar Salecha78f84e12010-08-19 05:08:28 +00001005static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter)
1006{
1007 u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO;
1008 u32 npar_state;
1009
Sony Chacko79788452012-12-04 03:33:53 +00001010 if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
Amit Kumar Salecha78f84e12010-08-19 05:08:28 +00001011 return 0;
1012
1013 npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
1014 while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) {
1015 msleep(1000);
1016 npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
1017 }
1018 if (!npar_opt_timeo) {
1019 dev_err(&adapter->pdev->dev,
1020 "Waiting for NPAR state to opertional timeout\n");
1021 return -EIO;
1022 }
1023 return 0;
1024}
1025
Anirban Chakrabortycea89752010-07-13 20:33:35 +00001026static int
Rajesh Borundia174240a2010-08-31 17:17:47 +00001027qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter)
1028{
1029 int err;
1030
1031 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
Sony Chacko79788452012-12-04 03:33:53 +00001032 adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
Rajesh Borundia174240a2010-08-31 17:17:47 +00001033 return 0;
1034
1035 err = qlcnic_set_default_offload_settings(adapter);
1036 if (err)
1037 return err;
1038
1039 err = qlcnic_reset_npar_config(adapter);
1040 if (err)
1041 return err;
1042
1043 qlcnic_dev_set_npar_ready(adapter);
1044
1045 return err;
1046}
1047
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001048int qlcnic_82xx_start_firmware(struct qlcnic_adapter *adapter)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001049{
Sony Chackod4066832010-08-19 05:08:31 +00001050 int err;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001051
Sucheta Chakrabortyaa5e18c2010-04-01 19:01:32 +00001052 err = qlcnic_can_start_firmware(adapter);
1053 if (err < 0)
1054 return err;
1055 else if (!err)
Sony Chackod4066832010-08-19 05:08:31 +00001056 goto check_fw_status;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001057
Sony Chacko099f7aa2012-12-04 03:33:58 +00001058 if (qlcnic_load_fw_file)
Amit Kumar Salecha4d5bdb32010-05-17 01:22:11 +00001059 qlcnic_request_firmware(adapter);
schacko8f891382010-06-17 02:56:40 +00001060 else {
Sony Chacko8cfdce02010-08-26 14:02:41 +00001061 err = qlcnic_check_flash_fw_ver(adapter);
1062 if (err)
schacko8f891382010-06-17 02:56:40 +00001063 goto err_out;
1064
Sony Chacko79788452012-12-04 03:33:53 +00001065 adapter->ahw->fw_type = QLCNIC_FLASH_ROMIMAGE;
schacko8f891382010-06-17 02:56:40 +00001066 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001067
1068 err = qlcnic_need_fw_reset(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001069 if (err == 0)
Sony Chacko4e708122010-08-31 17:17:44 +00001070 goto check_fw_status;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001071
Sony Chackod4066832010-08-19 05:08:31 +00001072 err = qlcnic_pinit_from_rom(adapter);
1073 if (err)
1074 goto err_out;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001075
1076 err = qlcnic_load_firmware(adapter);
1077 if (err)
1078 goto err_out;
1079
1080 qlcnic_release_firmware(adapter);
Sony Chackod4066832010-08-19 05:08:31 +00001081 QLCWR32(adapter, CRB_DRIVER_VERSION, QLCNIC_DRIVER_VERSION);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001082
Sony Chackod4066832010-08-19 05:08:31 +00001083check_fw_status:
1084 err = qlcnic_check_fw_status(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001085 if (err)
1086 goto err_out;
1087
1088 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +00001089 qlcnic_idc_debug_info(adapter, 1);
Amit Kumar Salechab18971d2010-08-25 04:03:04 +00001090
Anirban Chakraborty0866d962010-08-26 14:02:52 +00001091 err = qlcnic_check_eswitch_mode(adapter);
1092 if (err) {
1093 dev_err(&adapter->pdev->dev,
1094 "Memory allocation failed for eswitch\n");
1095 goto err_out;
1096 }
Rajesh Borundia174240a2010-08-31 17:17:47 +00001097 err = qlcnic_set_mgmt_operations(adapter);
1098 if (err)
1099 goto err_out;
1100
1101 qlcnic_check_options(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001102 adapter->need_fw_reset = 0;
1103
Amit Kumar Salechaa7fc9482010-05-17 01:22:14 +00001104 qlcnic_release_firmware(adapter);
1105 return 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001106
1107err_out:
Amit Kumar Salechaa7fc9482010-05-17 01:22:14 +00001108 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
1109 dev_err(&adapter->pdev->dev, "Device state set to failed\n");
Anirban Chakraborty0866d962010-08-26 14:02:52 +00001110
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001111 qlcnic_release_firmware(adapter);
1112 return err;
1113}
1114
1115static int
1116qlcnic_request_irq(struct qlcnic_adapter *adapter)
1117{
1118 irq_handler_t handler;
1119 struct qlcnic_host_sds_ring *sds_ring;
1120 int err, ring;
1121
1122 unsigned long flags = 0;
1123 struct net_device *netdev = adapter->netdev;
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001124 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001125
Sony Chacko79788452012-12-04 03:33:53 +00001126 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001127 handler = qlcnic_tmp_intr;
1128 if (!QLCNIC_IS_MSI_FAMILY(adapter))
1129 flags |= IRQF_SHARED;
1130
1131 } else {
1132 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1133 handler = qlcnic_msix_intr;
1134 else if (adapter->flags & QLCNIC_MSI_ENABLED)
1135 handler = qlcnic_msi_intr;
1136 else {
1137 flags |= IRQF_SHARED;
1138 handler = qlcnic_intr;
1139 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001140 }
1141 adapter->irq = netdev->irq;
1142
1143 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
1144 sds_ring = &recv_ctx->sds_rings[ring];
1145 sprintf(sds_ring->name, "%s[%d]", netdev->name, ring);
1146 err = request_irq(sds_ring->irq, handler,
1147 flags, sds_ring->name, sds_ring);
1148 if (err)
1149 return err;
1150 }
1151
1152 return 0;
1153}
1154
1155static void
1156qlcnic_free_irq(struct qlcnic_adapter *adapter)
1157{
1158 int ring;
1159 struct qlcnic_host_sds_ring *sds_ring;
1160
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001161 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001162
1163 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
1164 sds_ring = &recv_ctx->sds_rings[ring];
1165 free_irq(sds_ring->irq, sds_ring);
1166 }
1167}
1168
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001169static int
1170__qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
1171{
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001172 int ring;
Rajesh Borundiacae82d42012-06-06 07:35:06 +00001173 u32 capab2;
1174
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001175 struct qlcnic_host_rds_ring *rds_ring;
1176
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001177 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1178 return -EIO;
1179
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001180 if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
1181 return 0;
Rajesh Borundia0325d692010-08-19 05:08:26 +00001182 if (qlcnic_set_eswitch_port_config(adapter))
1183 return -EIO;
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001184
Sony Chacko79788452012-12-04 03:33:53 +00001185 if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
Rajesh Borundiacae82d42012-06-06 07:35:06 +00001186 capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2);
1187 if (capab2 & QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG)
1188 adapter->flags |= QLCNIC_FW_LRO_MSS_CAP;
1189 }
1190
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001191 if (qlcnic_fw_create_ctx(adapter))
1192 return -EIO;
1193
1194 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001195 rds_ring = &adapter->recv_ctx->rds_rings[ring];
1196 qlcnic_post_rx_buffers(adapter, rds_ring);
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001197 }
1198
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001199 qlcnic_set_multi(netdev);
1200 qlcnic_fw_cmd_set_mtu(adapter, netdev->mtu);
1201
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001202 adapter->ahw->linkup = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001203
1204 if (adapter->max_sds_rings > 1)
1205 qlcnic_config_rss(adapter, 1);
1206
1207 qlcnic_config_intr_coalesce(adapter);
1208
Sucheta Chakraborty24763d82010-08-17 00:34:25 +00001209 if (netdev->features & NETIF_F_LRO)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001210 qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED);
1211
1212 qlcnic_napi_enable(adapter);
1213
1214 qlcnic_linkevent_request(adapter, 1);
1215
Sony Chacko79788452012-12-04 03:33:53 +00001216 adapter->ahw->reset_context = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001217 set_bit(__QLCNIC_DEV_UP, &adapter->state);
1218 return 0;
1219}
1220
1221/* Usage: During resume and firmware recovery module.*/
1222
1223static int
1224qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
1225{
1226 int err = 0;
1227
1228 rtnl_lock();
1229 if (netif_running(netdev))
1230 err = __qlcnic_up(adapter, netdev);
1231 rtnl_unlock();
1232
1233 return err;
1234}
1235
1236static void
1237__qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
1238{
1239 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1240 return;
1241
1242 if (!test_and_clear_bit(__QLCNIC_DEV_UP, &adapter->state))
1243 return;
1244
1245 smp_mb();
1246 spin_lock(&adapter->tx_clean_lock);
1247 netif_carrier_off(netdev);
1248 netif_tx_disable(netdev);
1249
1250 qlcnic_free_mac_list(adapter);
1251
Amit Kumar Salechab5e54922010-08-31 17:17:51 +00001252 if (adapter->fhash.fnum)
1253 qlcnic_delete_lb_filters(adapter);
1254
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001255 qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE);
1256
1257 qlcnic_napi_disable(adapter);
1258
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001259 qlcnic_fw_destroy_ctx(adapter);
Rajesh Borundiacae82d42012-06-06 07:35:06 +00001260 adapter->flags &= ~QLCNIC_FW_LRO_MSS_CAP;
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001261
1262 qlcnic_reset_rx_buffers_list(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001263 qlcnic_release_tx_buffers(adapter);
1264 spin_unlock(&adapter->tx_clean_lock);
1265}
1266
1267/* Usage: During suspend and firmware recovery module */
1268
1269static void
1270qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
1271{
1272 rtnl_lock();
1273 if (netif_running(netdev))
1274 __qlcnic_down(adapter, netdev);
1275 rtnl_unlock();
1276
1277}
1278
1279static int
1280qlcnic_attach(struct qlcnic_adapter *adapter)
1281{
1282 struct net_device *netdev = adapter->netdev;
1283 struct pci_dev *pdev = adapter->pdev;
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001284 int err;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001285
1286 if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC)
1287 return 0;
1288
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001289 err = qlcnic_napi_add(adapter, netdev);
1290 if (err)
1291 return err;
1292
1293 err = qlcnic_alloc_sw_resources(adapter);
1294 if (err) {
1295 dev_err(&pdev->dev, "Error in setting sw resources\n");
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001296 goto err_out_napi_del;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001297 }
1298
1299 err = qlcnic_alloc_hw_resources(adapter);
1300 if (err) {
1301 dev_err(&pdev->dev, "Error in setting hw resources\n");
1302 goto err_out_free_sw;
1303 }
1304
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001305 err = qlcnic_request_irq(adapter);
1306 if (err) {
1307 dev_err(&pdev->dev, "failed to setup interrupt\n");
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001308 goto err_out_free_hw;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001309 }
1310
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001311 qlcnic_create_sysfs_entries(adapter);
1312
1313 adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC;
1314 return 0;
1315
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001316err_out_free_hw:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001317 qlcnic_free_hw_resources(adapter);
1318err_out_free_sw:
1319 qlcnic_free_sw_resources(adapter);
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001320err_out_napi_del:
1321 qlcnic_napi_del(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001322 return err;
1323}
1324
1325static void
1326qlcnic_detach(struct qlcnic_adapter *adapter)
1327{
1328 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1329 return;
1330
1331 qlcnic_remove_sysfs_entries(adapter);
1332
1333 qlcnic_free_hw_resources(adapter);
1334 qlcnic_release_rx_buffers(adapter);
1335 qlcnic_free_irq(adapter);
1336 qlcnic_napi_del(adapter);
1337 qlcnic_free_sw_resources(adapter);
1338
1339 adapter->is_up = 0;
1340}
1341
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001342void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
1343{
1344 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1345 struct qlcnic_host_sds_ring *sds_ring;
1346 int ring;
1347
Sucheta Chakraborty78ad3892010-05-17 01:22:12 +00001348 clear_bit(__QLCNIC_DEV_UP, &adapter->state);
Sony Chacko79788452012-12-04 03:33:53 +00001349 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
Amit Kumar Salechacdaff182010-02-01 05:25:00 +00001350 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001351 sds_ring = &adapter->recv_ctx->sds_rings[ring];
Amit Kumar Salechacdaff182010-02-01 05:25:00 +00001352 qlcnic_disable_int(sds_ring);
1353 }
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001354 }
1355
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001356 qlcnic_fw_destroy_ctx(adapter);
1357
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001358 qlcnic_detach(adapter);
1359
Sony Chacko79788452012-12-04 03:33:53 +00001360 adapter->ahw->diag_test = 0;
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001361 adapter->max_sds_rings = max_sds_rings;
1362
1363 if (qlcnic_attach(adapter))
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00001364 goto out;
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001365
1366 if (netif_running(netdev))
1367 __qlcnic_up(adapter, netdev);
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00001368out:
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001369 netif_device_attach(netdev);
1370}
1371
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001372static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
1373{
1374 int err = 0;
1375 adapter->ahw = kzalloc(sizeof(struct qlcnic_hardware_context),
1376 GFP_KERNEL);
1377 if (!adapter->ahw) {
1378 dev_err(&adapter->pdev->dev,
1379 "Failed to allocate recv ctx resources for adapter\n");
1380 err = -ENOMEM;
1381 goto err_out;
1382 }
1383 adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context),
1384 GFP_KERNEL);
1385 if (!adapter->recv_ctx) {
1386 dev_err(&adapter->pdev->dev,
1387 "Failed to allocate recv ctx resources for adapter\n");
1388 kfree(adapter->ahw);
1389 adapter->ahw = NULL;
1390 err = -ENOMEM;
Anirban Chakraborty8816d002011-04-01 14:28:21 +00001391 goto err_out;
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001392 }
Anirban Chakraborty8816d002011-04-01 14:28:21 +00001393 /* Initialize interrupt coalesce parameters */
1394 adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
1395 adapter->ahw->coal.rx_time_us = QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
1396 adapter->ahw->coal.rx_packets = QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001397err_out:
1398 return err;
1399}
1400
1401static void qlcnic_free_adapter_resources(struct qlcnic_adapter *adapter)
1402{
1403 kfree(adapter->recv_ctx);
1404 adapter->recv_ctx = NULL;
1405
Anirban Chakraborty18f2f612011-05-12 12:48:33 +00001406 if (adapter->ahw->fw_dump.tmpl_hdr) {
1407 vfree(adapter->ahw->fw_dump.tmpl_hdr);
1408 adapter->ahw->fw_dump.tmpl_hdr = NULL;
1409 }
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001410 kfree(adapter->ahw);
1411 adapter->ahw = NULL;
1412}
1413
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001414int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
1415{
1416 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1417 struct qlcnic_host_sds_ring *sds_ring;
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001418 struct qlcnic_host_rds_ring *rds_ring;
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001419 int ring;
1420 int ret;
1421
1422 netif_device_detach(netdev);
1423
1424 if (netif_running(netdev))
1425 __qlcnic_down(adapter, netdev);
1426
1427 qlcnic_detach(adapter);
1428
1429 adapter->max_sds_rings = 1;
Sony Chacko79788452012-12-04 03:33:53 +00001430 adapter->ahw->diag_test = test;
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001431
1432 ret = qlcnic_attach(adapter);
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00001433 if (ret) {
1434 netif_device_attach(netdev);
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001435 return ret;
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00001436 }
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001437
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001438 ret = qlcnic_fw_create_ctx(adapter);
1439 if (ret) {
1440 qlcnic_detach(adapter);
Sony Chacko57e46242010-07-24 18:32:18 +00001441 netif_device_attach(netdev);
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001442 return ret;
1443 }
1444
1445 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001446 rds_ring = &adapter->recv_ctx->rds_rings[ring];
1447 qlcnic_post_rx_buffers(adapter, rds_ring);
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001448 }
1449
Sony Chacko79788452012-12-04 03:33:53 +00001450 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
Amit Kumar Salechacdaff182010-02-01 05:25:00 +00001451 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001452 sds_ring = &adapter->recv_ctx->sds_rings[ring];
Amit Kumar Salechacdaff182010-02-01 05:25:00 +00001453 qlcnic_enable_int(sds_ring);
1454 }
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001455 }
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +00001456
Sony Chacko79788452012-12-04 03:33:53 +00001457 if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +00001458 adapter->ahw->loopback_state = 0;
1459 qlcnic_linkevent_request(adapter, 1);
1460 }
1461
Sucheta Chakraborty78ad3892010-05-17 01:22:12 +00001462 set_bit(__QLCNIC_DEV_UP, &adapter->state);
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00001463
1464 return 0;
1465}
1466
Amit Kumar Salecha68bf1c62010-06-22 03:19:03 +00001467/* Reset context in hardware only */
1468static int
1469qlcnic_reset_hw_context(struct qlcnic_adapter *adapter)
1470{
1471 struct net_device *netdev = adapter->netdev;
1472
1473 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
1474 return -EBUSY;
1475
1476 netif_device_detach(netdev);
1477
1478 qlcnic_down(adapter, netdev);
1479
1480 qlcnic_up(adapter, netdev);
1481
1482 netif_device_attach(netdev);
1483
1484 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1485 return 0;
1486}
1487
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001488int
1489qlcnic_reset_context(struct qlcnic_adapter *adapter)
1490{
1491 int err = 0;
1492 struct net_device *netdev = adapter->netdev;
1493
1494 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
1495 return -EBUSY;
1496
1497 if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) {
1498
1499 netif_device_detach(netdev);
1500
1501 if (netif_running(netdev))
1502 __qlcnic_down(adapter, netdev);
1503
1504 qlcnic_detach(adapter);
1505
1506 if (netif_running(netdev)) {
1507 err = qlcnic_attach(adapter);
Anirban Chakraborty1d5c88e2012-03-23 06:32:34 +00001508 if (!err) {
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00001509 __qlcnic_up(adapter, netdev);
Anirban Chakraborty1d5c88e2012-03-23 06:32:34 +00001510 qlcnic_restore_indev_addr(netdev, NETDEV_UP);
1511 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001512 }
1513
1514 netif_device_attach(netdev);
1515 }
1516
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001517 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1518 return err;
1519}
1520
1521static int
Sony Chacko5ad6ff92012-11-17 21:04:38 +00001522qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
1523 int pci_using_dac)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001524{
1525 int err;
1526 struct pci_dev *pdev = adapter->pdev;
1527
Sony Chacko79788452012-12-04 03:33:53 +00001528 adapter->ahw->mc_enabled = 0;
1529 adapter->ahw->max_mc_count = 38;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001530
1531 netdev->netdev_ops = &qlcnic_netdev_ops;
Rajesh K Borundiaef71ff82010-06-17 02:56:41 +00001532 netdev->watchdog_timeo = 5*HZ;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001533
1534 qlcnic_change_mtu(netdev, netdev->mtu);
1535
1536 SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
1537
Michał Mirosław135d84a2011-04-19 03:03:57 +00001538 netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
1539 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
Anirban Chakrabortyac8d0c42010-07-09 13:14:58 +00001540
Sony Chacko79788452012-12-04 03:33:53 +00001541 if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
Michał Mirosław135d84a2011-04-19 03:03:57 +00001542 netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
Sony Chacko5ad6ff92012-11-17 21:04:38 +00001543 if (pci_using_dac == 1)
Michał Mirosław135d84a2011-04-19 03:03:57 +00001544 netdev->hw_features |= NETIF_F_HIGHDMA;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001545
Michał Mirosław135d84a2011-04-19 03:03:57 +00001546 netdev->vlan_features = netdev->hw_features;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001547
Sony Chacko79788452012-12-04 03:33:53 +00001548 if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX)
Michał Mirosław135d84a2011-04-19 03:03:57 +00001549 netdev->hw_features |= NETIF_F_HW_VLAN_TX;
Sony Chacko79788452012-12-04 03:33:53 +00001550 if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
Michał Mirosław135d84a2011-04-19 03:03:57 +00001551 netdev->hw_features |= NETIF_F_LRO;
1552
1553 netdev->features |= netdev->hw_features |
1554 NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
1555
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001556 netdev->irq = adapter->msix_entries[0].vector;
1557
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001558 err = register_netdev(netdev);
1559 if (err) {
1560 dev_err(&pdev->dev, "failed to register net device\n");
1561 return err;
1562 }
1563
1564 return 0;
1565}
1566
Sony Chacko5ad6ff92012-11-17 21:04:38 +00001567static int qlcnic_set_dma_mask(struct pci_dev *pdev, int *pci_using_dac)
Amit Kumar Salecha1bb09fb2010-05-14 03:07:46 -07001568{
1569 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
1570 !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
1571 *pci_using_dac = 1;
1572 else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) &&
1573 !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
1574 *pci_using_dac = 0;
1575 else {
1576 dev_err(&pdev->dev, "Unable to set DMA mask, aborting\n");
1577 return -EIO;
1578 }
1579
1580 return 0;
1581}
1582
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +00001583static int
1584qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count)
1585{
1586 adapter->msix_entries = kcalloc(count, sizeof(struct msix_entry),
1587 GFP_KERNEL);
1588
1589 if (adapter->msix_entries)
1590 return 0;
1591
1592 dev_err(&adapter->pdev->dev, "failed allocating msix_entries\n");
1593 return -ENOMEM;
1594}
1595
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001596static int __devinit
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001597qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1598{
1599 struct net_device *netdev = NULL;
1600 struct qlcnic_adapter *adapter = NULL;
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001601 struct qlcnic_hardware_context *ahw;
Sony Chacko5ad6ff92012-11-17 21:04:38 +00001602 int err, pci_using_dac = -1;
Sony Chacko22999792012-12-04 03:33:55 +00001603 char board_name[QLCNIC_MAX_BOARD_NAME_LEN];
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001604
1605 err = pci_enable_device(pdev);
1606 if (err)
1607 return err;
1608
1609 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
1610 err = -ENODEV;
1611 goto err_out_disable_pdev;
1612 }
1613
Amit Kumar Salecha1bb09fb2010-05-14 03:07:46 -07001614 err = qlcnic_set_dma_mask(pdev, &pci_using_dac);
1615 if (err)
1616 goto err_out_disable_pdev;
1617
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001618 err = pci_request_regions(pdev, qlcnic_driver_name);
1619 if (err)
1620 goto err_out_disable_pdev;
1621
1622 pci_set_master(pdev);
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00001623 pci_enable_pcie_error_reporting(pdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001624
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001625 ahw = kzalloc(sizeof(struct qlcnic_hardware_context), GFP_KERNEL);
1626 if (!ahw)
1627 goto err_out_free_res;
1628
1629 if (ent->device == PCI_DEVICE_ID_QLOGIC_QLE824X) {
1630 ahw->hw_ops = &qlcnic_hw_ops;
1631 ahw->reg_tbl = (u32 *)qlcnic_reg_tbl;
1632 }
1633
1634 err = qlcnic_setup_pci_map(pdev, ahw);
1635 if (err)
1636 goto err_out_free_hw_res;
1637
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001638 netdev = alloc_etherdev(sizeof(struct qlcnic_adapter));
1639 if (!netdev) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001640 err = -ENOMEM;
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001641 goto err_out_iounmap;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001642 }
1643
1644 SET_NETDEV_DEV(netdev, &pdev->dev);
1645
1646 adapter = netdev_priv(netdev);
1647 adapter->netdev = netdev;
1648 adapter->pdev = pdev;
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001649
Peter Senna Tschudin2dfc9672012-10-05 12:10:50 +00001650 err = qlcnic_alloc_adapter_resources(adapter);
1651 if (err)
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001652 goto err_out_free_netdev;
1653
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +00001654 adapter->dev_rst_time = jiffies;
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001655 adapter->ahw->revision_id = pdev->revision;
Sucheta Chakrabortye5dcf6d2011-07-14 03:16:52 +00001656 adapter->mac_learn = qlcnic_mac_learn;
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001657 adapter->max_drv_tx_rings = 1;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001658
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001659 rwlock_init(&adapter->ahw->crb_lock);
1660 mutex_init(&adapter->ahw->mem_lock);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001661
1662 spin_lock_init(&adapter->tx_clean_lock);
1663 INIT_LIST_HEAD(&adapter->mac_list);
1664
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001665 if (qlcnic_82xx_check(adapter)) {
1666 qlcnic_check_vf(adapter);
1667 adapter->portnum = adapter->ahw->pci_func;
1668 err = qlcnic_start_firmware(adapter);
1669 if (err) {
1670 dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n");
1671 goto err_out_free_hw;
1672 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001673
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001674 err = qlcnic_setup_idc_param(adapter);
1675 if (err)
1676 goto err_out_free_hw;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001677
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001678 adapter->flags |= QLCNIC_NEED_FLR;
Amit Kumar Salechaa7fc9482010-05-17 01:22:14 +00001679 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001680
Rajesh Borundiada48e6c2010-08-31 17:17:46 +00001681 if (qlcnic_read_mac_addr(adapter))
1682 dev_warn(&pdev->dev, "failed to read mac addr\n");
1683
1684 if (adapter->portnum == 0) {
Sony Chacko22999792012-12-04 03:33:55 +00001685 qlcnic_get_board_name(adapter, board_name);
Rajesh Borundiada48e6c2010-08-31 17:17:46 +00001686 pr_info("%s: %s Board Chip rev 0x%x\n",
Sony Chacko22999792012-12-04 03:33:55 +00001687 module_name(THIS_MODULE),
1688 board_name, adapter->ahw->revision_id);
Rajesh Borundiada48e6c2010-08-31 17:17:46 +00001689 }
Sony Chacko79788452012-12-04 03:33:53 +00001690 err = qlcnic_alloc_msix_entries(adapter, adapter->ahw->max_rx_ques);
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +00001691 if (err)
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001692 goto err_out_disable_msi;
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +00001693
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001694 err = qlcnic_setup_intr(adapter, 0);
1695 if (err)
1696 goto err_out_disable_msi;
1697
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001698
Amit Kumar Salecha1bb09fb2010-05-14 03:07:46 -07001699 err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001700 if (err)
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001701 goto err_out_disable_mbx_intr;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001702
1703 pci_set_drvdata(pdev, adapter);
1704
Sony Chacko97ee45e2012-12-04 03:33:52 +00001705 if (qlcnic_82xx_check(adapter))
1706 qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
1707 FW_POLL_DELAY);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001708
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001709 switch (adapter->ahw->port_type) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001710 case QLCNIC_GBE:
1711 dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
1712 adapter->netdev->name);
1713 break;
1714 case QLCNIC_XGBE:
1715 dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
1716 adapter->netdev->name);
1717 break;
1718 }
1719
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001720 if (qlcnic_get_act_pci_func(adapter))
1721 goto err_out_disable_mbx_intr;
1722
Sucheta Chakrabortye5dcf6d2011-07-14 03:16:52 +00001723 if (adapter->mac_learn)
1724 qlcnic_alloc_lb_filters_mem(adapter);
1725
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001726 qlcnic_add_sysfs(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001727
1728 return 0;
1729
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001730err_out_disable_mbx_intr:
1731
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001732err_out_disable_msi:
1733 qlcnic_teardown_intr(adapter);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001734 qlcnic_cancel_idc_work(adapter);
Amit Kumar Salecha21854f02010-08-19 05:08:29 +00001735 qlcnic_clr_all_drv_state(adapter, 0);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001736
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001737err_out_free_hw:
1738 qlcnic_free_adapter_resources(adapter);
1739
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001740err_out_free_netdev:
1741 free_netdev(netdev);
1742
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001743err_out_iounmap:
1744 qlcnic_cleanup_pci_map(adapter);
1745
1746err_out_free_hw_res:
1747 kfree(ahw);
1748
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001749err_out_free_res:
1750 pci_release_regions(pdev);
1751
1752err_out_disable_pdev:
1753 pci_set_drvdata(pdev, NULL);
1754 pci_disable_device(pdev);
1755 return err;
1756}
1757
Bill Pemberton6bb58bb2012-12-03 09:23:25 -05001758static void qlcnic_remove(struct pci_dev *pdev)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001759{
1760 struct qlcnic_adapter *adapter;
1761 struct net_device *netdev;
1762
1763 adapter = pci_get_drvdata(pdev);
1764 if (adapter == NULL)
1765 return;
1766
1767 netdev = adapter->netdev;
1768
1769 qlcnic_cancel_fw_work(adapter);
1770
1771 unregister_netdev(netdev);
1772
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001773 qlcnic_detach(adapter);
1774
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001775 if (adapter->npars != NULL)
1776 kfree(adapter->npars);
1777 if (adapter->eswitch != NULL)
1778 kfree(adapter->eswitch);
1779
Sony Chacko97ee45e2012-12-04 03:33:52 +00001780 if (qlcnic_82xx_check(adapter))
1781 qlcnic_clr_all_drv_state(adapter, 0);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001782
1783 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1784
Amit Kumar Salechab5e54922010-08-31 17:17:51 +00001785 qlcnic_free_lb_filters_mem(adapter);
1786
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001787 qlcnic_teardown_intr(adapter);
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +00001788 kfree(adapter->msix_entries);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001789
1790 qlcnic_remove_diag_entries(adapter);
1791
1792 qlcnic_cleanup_pci_map(adapter);
1793
1794 qlcnic_release_firmware(adapter);
1795
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00001796 pci_disable_pcie_error_reporting(pdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001797 pci_release_regions(pdev);
1798 pci_disable_device(pdev);
1799 pci_set_drvdata(pdev, NULL);
1800
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001801 qlcnic_free_adapter_resources(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001802 free_netdev(netdev);
1803}
1804static int __qlcnic_shutdown(struct pci_dev *pdev)
1805{
1806 struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
1807 struct net_device *netdev = adapter->netdev;
1808 int retval;
1809
1810 netif_device_detach(netdev);
1811
1812 qlcnic_cancel_fw_work(adapter);
1813
1814 if (netif_running(netdev))
1815 qlcnic_down(adapter, netdev);
1816
Sony Chacko97ee45e2012-12-04 03:33:52 +00001817 if (qlcnic_82xx_check(adapter))
1818 qlcnic_clr_all_drv_state(adapter, 0);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001819
1820 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1821
1822 retval = pci_save_state(pdev);
1823 if (retval)
1824 return retval;
1825
Sony Chacko97ee45e2012-12-04 03:33:52 +00001826 if (qlcnic_82xx_check(adapter)) {
1827 if (qlcnic_wol_supported(adapter)) {
1828 pci_enable_wake(pdev, PCI_D3cold, 1);
1829 pci_enable_wake(pdev, PCI_D3hot, 1);
1830 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001831 }
1832
1833 return 0;
1834}
1835
1836static void qlcnic_shutdown(struct pci_dev *pdev)
1837{
1838 if (__qlcnic_shutdown(pdev))
1839 return;
1840
1841 pci_disable_device(pdev);
1842}
1843
1844#ifdef CONFIG_PM
1845static int
1846qlcnic_suspend(struct pci_dev *pdev, pm_message_t state)
1847{
1848 int retval;
1849
1850 retval = __qlcnic_shutdown(pdev);
1851 if (retval)
1852 return retval;
1853
1854 pci_set_power_state(pdev, pci_choose_state(pdev, state));
1855 return 0;
1856}
1857
1858static int
1859qlcnic_resume(struct pci_dev *pdev)
1860{
1861 struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
1862 struct net_device *netdev = adapter->netdev;
1863 int err;
1864
1865 err = pci_enable_device(pdev);
1866 if (err)
1867 return err;
1868
1869 pci_set_power_state(pdev, PCI_D0);
1870 pci_set_master(pdev);
1871 pci_restore_state(pdev);
1872
Anirban Chakraborty9f26f542010-06-01 11:33:09 +00001873 err = adapter->nic_ops->start_firmware(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001874 if (err) {
1875 dev_err(&pdev->dev, "failed to start firmware\n");
1876 return err;
1877 }
1878
1879 if (netif_running(netdev)) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001880 err = qlcnic_up(adapter, netdev);
1881 if (err)
Amit Kumar Salecha52486a32010-06-22 03:19:02 +00001882 goto done;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001883
Amit Kumar Salechaaec1e842010-09-16 19:14:41 +00001884 qlcnic_restore_indev_addr(netdev, NETDEV_UP);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001885 }
Amit Kumar Salecha52486a32010-06-22 03:19:02 +00001886done:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001887 netif_device_attach(netdev);
1888 qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
1889 return 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001890}
1891#endif
1892
1893static int qlcnic_open(struct net_device *netdev)
1894{
1895 struct qlcnic_adapter *adapter = netdev_priv(netdev);
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00001896 u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001897 int err;
1898
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00001899 if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) {
1900 netdev_err(netdev, "Device in FAILED state\n");
1901 return -EIO;
1902 }
1903
Amit Kumar Salechac55ad8e2011-06-22 02:52:21 +00001904 netif_carrier_off(netdev);
1905
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001906 err = qlcnic_attach(adapter);
1907 if (err)
1908 return err;
1909
1910 err = __qlcnic_up(adapter, netdev);
1911 if (err)
1912 goto err_out;
1913
1914 netif_start_queue(netdev);
1915
1916 return 0;
1917
1918err_out:
1919 qlcnic_detach(adapter);
1920 return err;
1921}
1922
1923/*
1924 * qlcnic_close - Disables a network interface entry point
1925 */
1926static int qlcnic_close(struct net_device *netdev)
1927{
1928 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1929
1930 __qlcnic_down(adapter, netdev);
1931 return 0;
1932}
1933
Sucheta Chakrabortye5dcf6d2011-07-14 03:16:52 +00001934void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
Amit Kumar Salechab5e54922010-08-31 17:17:51 +00001935{
1936 void *head;
1937 int i;
1938
Sucheta Chakrabortye5dcf6d2011-07-14 03:16:52 +00001939 if (adapter->fhash.fmax && adapter->fhash.fhead)
Amit Kumar Salechab5e54922010-08-31 17:17:51 +00001940 return;
1941
1942 spin_lock_init(&adapter->mac_learn_lock);
1943
1944 head = kcalloc(QLCNIC_LB_MAX_FILTERS, sizeof(struct hlist_head),
1945 GFP_KERNEL);
1946 if (!head)
1947 return;
1948
1949 adapter->fhash.fmax = QLCNIC_LB_MAX_FILTERS;
Joe Perches43d620c2011-06-16 19:08:06 +00001950 adapter->fhash.fhead = head;
Amit Kumar Salechab5e54922010-08-31 17:17:51 +00001951
1952 for (i = 0; i < adapter->fhash.fmax; i++)
1953 INIT_HLIST_HEAD(&adapter->fhash.fhead[i]);
1954}
1955
1956static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
1957{
1958 if (adapter->fhash.fmax && adapter->fhash.fhead)
1959 kfree(adapter->fhash.fhead);
1960
1961 adapter->fhash.fhead = NULL;
1962 adapter->fhash.fmax = 0;
1963}
1964
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001965static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
1966{
1967 struct net_device *netdev = adapter->netdev;
Sony Chacko97ee45e2012-12-04 03:33:52 +00001968 u32 temp_state, temp_val, temp = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001969 int rv = 0;
1970
Sony Chacko97ee45e2012-12-04 03:33:52 +00001971 if (qlcnic_82xx_check(adapter))
1972 temp = QLCRD32(adapter, CRB_TEMP_STATE);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001973
1974 temp_state = qlcnic_get_temp_state(temp);
1975 temp_val = qlcnic_get_temp_val(temp);
1976
1977 if (temp_state == QLCNIC_TEMP_PANIC) {
1978 dev_err(&netdev->dev,
1979 "Device temperature %d degrees C exceeds"
1980 " maximum allowed. Hardware has been shut down.\n",
1981 temp_val);
1982 rv = 1;
1983 } else if (temp_state == QLCNIC_TEMP_WARN) {
Sony Chacko79788452012-12-04 03:33:53 +00001984 if (adapter->ahw->temp == QLCNIC_TEMP_NORMAL) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001985 dev_err(&netdev->dev,
1986 "Device temperature %d degrees C "
1987 "exceeds operating range."
1988 " Immediate action needed.\n",
1989 temp_val);
1990 }
1991 } else {
Sony Chacko79788452012-12-04 03:33:53 +00001992 if (adapter->ahw->temp == QLCNIC_TEMP_WARN) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001993 dev_info(&netdev->dev,
1994 "Device temperature is now %d degrees C"
1995 " in normal range.\n", temp_val);
1996 }
1997 }
Sony Chacko79788452012-12-04 03:33:53 +00001998 adapter->ahw->temp = temp_state;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001999 return rv;
2000}
2001
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002002static void qlcnic_tx_timeout(struct net_device *netdev)
2003{
2004 struct qlcnic_adapter *adapter = netdev_priv(netdev);
2005
2006 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
2007 return;
2008
2009 dev_err(&netdev->dev, "transmit timeout, resetting.\n");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002010
2011 if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS)
Amit Kumar Salecha68bf1c62010-06-22 03:19:03 +00002012 adapter->need_fw_reset = 1;
2013 else
Sony Chacko79788452012-12-04 03:33:53 +00002014 adapter->ahw->reset_context = 1;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002015}
2016
2017static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
2018{
2019 struct qlcnic_adapter *adapter = netdev_priv(netdev);
2020 struct net_device_stats *stats = &netdev->stats;
2021
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002022 stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
2023 stats->tx_packets = adapter->stats.xmitfinished;
Sucheta Chakraborty7e382592010-05-17 01:22:10 +00002024 stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002025 stats->tx_bytes = adapter->stats.txbytes;
2026 stats->rx_dropped = adapter->stats.rxdropped;
2027 stats->tx_dropped = adapter->stats.txdropped;
2028
2029 return stats;
2030}
2031
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00002032irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002033{
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002034 u32 status;
2035
2036 status = readl(adapter->isr_int_vec);
2037
Sony Chacko79788452012-12-04 03:33:53 +00002038 if (!(status & adapter->ahw->int_vec_bit))
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002039 return IRQ_NONE;
2040
2041 /* check interrupt state machine, to be sure */
2042 status = readl(adapter->crb_int_state_reg);
2043 if (!ISR_LEGACY_INT_TRIGGERED(status))
2044 return IRQ_NONE;
2045
2046 writel(0xffffffff, adapter->tgt_status_reg);
2047 /* read twice to ensure write is flushed */
2048 readl(adapter->isr_int_vec);
2049 readl(adapter->isr_int_vec);
2050
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00002051 return IRQ_HANDLED;
2052}
2053
2054static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
2055{
2056 struct qlcnic_host_sds_ring *sds_ring = data;
2057 struct qlcnic_adapter *adapter = sds_ring->adapter;
2058
2059 if (adapter->flags & QLCNIC_MSIX_ENABLED)
2060 goto done;
2061 else if (adapter->flags & QLCNIC_MSI_ENABLED) {
2062 writel(0xffffffff, adapter->tgt_status_reg);
2063 goto done;
2064 }
2065
2066 if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
2067 return IRQ_NONE;
2068
2069done:
Sony Chacko79788452012-12-04 03:33:53 +00002070 adapter->ahw->diag_cnt++;
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +00002071 qlcnic_enable_int(sds_ring);
2072 return IRQ_HANDLED;
2073}
2074
2075static irqreturn_t qlcnic_intr(int irq, void *data)
2076{
2077 struct qlcnic_host_sds_ring *sds_ring = data;
2078 struct qlcnic_adapter *adapter = sds_ring->adapter;
2079
2080 if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
2081 return IRQ_NONE;
2082
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002083 napi_schedule(&sds_ring->napi);
2084
2085 return IRQ_HANDLED;
2086}
2087
2088static irqreturn_t qlcnic_msi_intr(int irq, void *data)
2089{
2090 struct qlcnic_host_sds_ring *sds_ring = data;
2091 struct qlcnic_adapter *adapter = sds_ring->adapter;
2092
2093 /* clear interrupt */
2094 writel(0xffffffff, adapter->tgt_status_reg);
2095
2096 napi_schedule(&sds_ring->napi);
2097 return IRQ_HANDLED;
2098}
2099
2100static irqreturn_t qlcnic_msix_intr(int irq, void *data)
2101{
2102 struct qlcnic_host_sds_ring *sds_ring = data;
2103
2104 napi_schedule(&sds_ring->napi);
2105 return IRQ_HANDLED;
2106}
2107
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002108#ifdef CONFIG_NET_POLL_CONTROLLER
2109static void qlcnic_poll_controller(struct net_device *netdev)
2110{
Yinglin Luanbf827912010-08-22 21:57:56 +00002111 int ring;
2112 struct qlcnic_host_sds_ring *sds_ring;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002113 struct qlcnic_adapter *adapter = netdev_priv(netdev);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00002114 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
Yinglin Luanbf827912010-08-22 21:57:56 +00002115
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002116 disable_irq(adapter->irq);
Yinglin Luanbf827912010-08-22 21:57:56 +00002117 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
2118 sds_ring = &recv_ctx->sds_rings[ring];
2119 qlcnic_intr(adapter->irq, sds_ring);
2120 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002121 enable_irq(adapter->irq);
2122}
2123#endif
2124
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +00002125static void
2126qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding)
2127{
2128 u32 val;
2129
2130 val = adapter->portnum & 0xf;
2131 val |= encoding << 7;
2132 val |= (jiffies - adapter->dev_rst_time) << 8;
2133
2134 QLCWR32(adapter, QLCNIC_CRB_DRV_SCRATCH, val);
2135 adapter->dev_rst_time = jiffies;
2136}
2137
Amit Kumar Salechaade91f82010-04-22 02:51:39 +00002138static int
2139qlcnic_set_drv_state(struct qlcnic_adapter *adapter, u8 state)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002140{
2141 u32 val;
2142
2143 WARN_ON(state != QLCNIC_DEV_NEED_RESET &&
2144 state != QLCNIC_DEV_NEED_QUISCENT);
2145
2146 if (qlcnic_api_lock(adapter))
Amit Kumar Salechaade91f82010-04-22 02:51:39 +00002147 return -EIO;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002148
2149 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
2150
2151 if (state == QLCNIC_DEV_NEED_RESET)
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002152 QLC_DEV_SET_RST_RDY(val, adapter->portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002153 else if (state == QLCNIC_DEV_NEED_QUISCENT)
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002154 QLC_DEV_SET_QSCNT_RDY(val, adapter->portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002155
2156 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2157
2158 qlcnic_api_unlock(adapter);
Amit Kumar Salechaade91f82010-04-22 02:51:39 +00002159
2160 return 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002161}
2162
Amit Kumar Salecha1b95a832010-02-01 05:24:56 +00002163static int
2164qlcnic_clr_drv_state(struct qlcnic_adapter *adapter)
2165{
2166 u32 val;
2167
2168 if (qlcnic_api_lock(adapter))
2169 return -EBUSY;
2170
2171 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002172 QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum);
Amit Kumar Salecha1b95a832010-02-01 05:24:56 +00002173 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2174
2175 qlcnic_api_unlock(adapter);
2176
2177 return 0;
2178}
2179
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002180static void
Amit Kumar Salecha21854f02010-08-19 05:08:29 +00002181qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002182{
2183 u32 val;
2184
2185 if (qlcnic_api_lock(adapter))
2186 goto err;
2187
Amit Kumar Salecha31018e02010-08-25 04:03:05 +00002188 val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002189 QLC_DEV_CLR_REF_CNT(val, adapter->portnum);
Amit Kumar Salecha31018e02010-08-25 04:03:05 +00002190 QLCWR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002191
Amit Kumar Salecha21854f02010-08-19 05:08:29 +00002192 if (failed) {
2193 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
2194 dev_info(&adapter->pdev->dev,
2195 "Device state set to Failed. Please Reboot\n");
2196 } else if (!(val & 0x11111111))
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002197 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_COLD);
2198
2199 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002200 QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002201 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2202
2203 qlcnic_api_unlock(adapter);
2204err:
2205 adapter->fw_fail_cnt = 0;
Sritej Velaga032a13c2011-07-29 13:30:27 +00002206 adapter->flags &= ~QLCNIC_FW_HANG;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002207 clear_bit(__QLCNIC_START_FW, &adapter->state);
2208 clear_bit(__QLCNIC_RESETTING, &adapter->state);
2209}
2210
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002211/* Grab api lock, before checking state */
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002212static int
2213qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
2214{
Sritej Velaga602ca6f2011-06-22 02:52:17 +00002215 int act, state, active_mask;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002216
2217 state = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
Amit Kumar Salecha31018e02010-08-25 04:03:05 +00002218 act = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002219
Sritej Velaga602ca6f2011-06-22 02:52:17 +00002220 if (adapter->flags & QLCNIC_FW_RESET_OWNER) {
2221 active_mask = (~(1 << (adapter->ahw->pci_func * 4)));
2222 act = act & active_mask;
2223 }
2224
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002225 if (((state & 0x11111111) == (act & 0x11111111)) ||
2226 ((act & 0x11111111) == ((state >> 1) & 0x11111111)))
2227 return 0;
2228 else
2229 return 1;
2230}
2231
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002232static int qlcnic_check_idc_ver(struct qlcnic_adapter *adapter)
2233{
2234 u32 val = QLCRD32(adapter, QLCNIC_CRB_DRV_IDC_VER);
2235
2236 if (val != QLCNIC_DRV_IDC_VER) {
2237 dev_warn(&adapter->pdev->dev, "IDC Version mismatch, driver's"
2238 " idc ver = %x; reqd = %x\n", QLCNIC_DRV_IDC_VER, val);
2239 }
2240
2241 return 0;
2242}
2243
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002244static int
2245qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
2246{
2247 u32 val, prev_state;
Sucheta Chakrabortyaa5e18c2010-04-01 19:01:32 +00002248 u8 dev_init_timeo = adapter->dev_init_timeo;
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002249 u8 portnum = adapter->portnum;
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002250 u8 ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002251
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002252 if (test_and_clear_bit(__QLCNIC_START_FW, &adapter->state))
2253 return 1;
2254
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002255 if (qlcnic_api_lock(adapter))
2256 return -1;
2257
Amit Kumar Salecha31018e02010-08-25 04:03:05 +00002258 val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002259 if (!(val & (1 << (portnum * 4)))) {
2260 QLC_DEV_SET_REF_CNT(val, portnum);
Amit Kumar Salecha31018e02010-08-25 04:03:05 +00002261 QLCWR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002262 }
2263
2264 prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002265 QLCDB(adapter, HW, "Device state = %u\n", prev_state);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002266
2267 switch (prev_state) {
2268 case QLCNIC_DEV_COLD:
Amit Kumar Salechabbd8c6a2010-04-22 02:51:36 +00002269 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002270 QLCWR32(adapter, QLCNIC_CRB_DRV_IDC_VER, QLCNIC_DRV_IDC_VER);
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +00002271 qlcnic_idc_debug_info(adapter, 0);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002272 qlcnic_api_unlock(adapter);
2273 return 1;
2274
2275 case QLCNIC_DEV_READY:
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002276 ret = qlcnic_check_idc_ver(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002277 qlcnic_api_unlock(adapter);
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002278 return ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002279
2280 case QLCNIC_DEV_NEED_RESET:
2281 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002282 QLC_DEV_SET_RST_RDY(val, portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002283 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2284 break;
2285
2286 case QLCNIC_DEV_NEED_QUISCENT:
2287 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002288 QLC_DEV_SET_QSCNT_RDY(val, portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002289 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2290 break;
2291
2292 case QLCNIC_DEV_FAILED:
Amit Kumar Salechaa7fc9482010-05-17 01:22:14 +00002293 dev_err(&adapter->pdev->dev, "Device in failed state.\n");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002294 qlcnic_api_unlock(adapter);
2295 return -1;
Amit Kumar Salechabbd8c6a2010-04-22 02:51:36 +00002296
2297 case QLCNIC_DEV_INITIALIZING:
2298 case QLCNIC_DEV_QUISCENT:
2299 break;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002300 }
2301
2302 qlcnic_api_unlock(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002303
Sucheta Chakrabortyaa5e18c2010-04-01 19:01:32 +00002304 do {
2305 msleep(1000);
Sucheta Chakrabortya5e463d2010-05-13 03:07:49 +00002306 prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
2307
2308 if (prev_state == QLCNIC_DEV_QUISCENT)
2309 continue;
2310 } while ((prev_state != QLCNIC_DEV_READY) && --dev_init_timeo);
Sucheta Chakrabortyaa5e18c2010-04-01 19:01:32 +00002311
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002312 if (!dev_init_timeo) {
2313 dev_err(&adapter->pdev->dev,
2314 "Waiting for device to initialize timeout\n");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002315 return -1;
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002316 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002317
2318 if (qlcnic_api_lock(adapter))
2319 return -1;
2320
2321 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
Amit Kumar Salecha6d2a4722010-04-22 02:51:38 +00002322 QLC_DEV_CLR_RST_QSCNT(val, portnum);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002323 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
2324
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002325 ret = qlcnic_check_idc_ver(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002326 qlcnic_api_unlock(adapter);
2327
Sucheta Chakraborty96f81182010-05-13 03:07:47 +00002328 return ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002329}
2330
2331static void
2332qlcnic_fwinit_work(struct work_struct *work)
2333{
2334 struct qlcnic_adapter *adapter = container_of(work,
2335 struct qlcnic_adapter, fw_work.work);
Amit Kumar Salecha3c4b23b2010-08-17 00:34:20 +00002336 u32 dev_state = 0xf;
Sritej Velaga7b749ff2011-07-14 03:16:50 +00002337 u32 val;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002338
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002339 if (qlcnic_api_lock(adapter))
2340 goto err_ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002341
Sucheta Chakrabortya5e463d2010-05-13 03:07:49 +00002342 dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
Amit Kumar Salechab8c17622010-10-07 23:46:06 +00002343 if (dev_state == QLCNIC_DEV_QUISCENT ||
2344 dev_state == QLCNIC_DEV_NEED_QUISCENT) {
Sucheta Chakrabortya5e463d2010-05-13 03:07:49 +00002345 qlcnic_api_unlock(adapter);
2346 qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
2347 FW_POLL_DELAY * 2);
2348 return;
2349 }
2350
Sony Chacko79788452012-12-04 03:33:53 +00002351 if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
Amit Kumar Salecha3c4b23b2010-08-17 00:34:20 +00002352 qlcnic_api_unlock(adapter);
2353 goto wait_npar;
Anirban Chakraborty9f26f542010-06-01 11:33:09 +00002354 }
2355
Sritej Velaga16e3cf72011-10-28 12:57:11 +00002356 if (dev_state == QLCNIC_DEV_INITIALIZING ||
2357 dev_state == QLCNIC_DEV_READY) {
2358 dev_info(&adapter->pdev->dev, "Detected state change from "
2359 "DEV_NEED_RESET, skipping ack check\n");
2360 goto skip_ack_check;
2361 }
2362
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002363 if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
Sritej Velaga16e3cf72011-10-28 12:57:11 +00002364 dev_info(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n",
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002365 adapter->reset_ack_timeo);
2366 goto skip_ack_check;
2367 }
2368
2369 if (!qlcnic_check_drv_state(adapter)) {
2370skip_ack_check:
2371 dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
Sucheta Chakrabortya5e463d2010-05-13 03:07:49 +00002372
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002373 if (dev_state == QLCNIC_DEV_NEED_RESET) {
2374 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
2375 QLCNIC_DEV_INITIALIZING);
2376 set_bit(__QLCNIC_START_FW, &adapter->state);
2377 QLCDB(adapter, DRV, "Restarting fw\n");
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +00002378 qlcnic_idc_debug_info(adapter, 0);
Sritej Velaga7b749ff2011-07-14 03:16:50 +00002379 val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
2380 QLC_DEV_SET_RST_RDY(val, adapter->portnum);
2381 QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002382 }
2383
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002384 qlcnic_api_unlock(adapter);
2385
Anirban Chakraborty287e38a2011-06-22 02:52:18 +00002386 rtnl_lock();
Sritej Velaga7b749ff2011-07-14 03:16:50 +00002387 if (adapter->ahw->fw_dump.enable &&
2388 (adapter->flags & QLCNIC_FW_RESET_OWNER)) {
Anirban Chakraborty9d6a6442011-06-22 02:52:22 +00002389 QLCDB(adapter, DRV, "Take FW dump\n");
2390 qlcnic_dump_fw(adapter);
Sritej Velaga032a13c2011-07-29 13:30:27 +00002391 adapter->flags |= QLCNIC_FW_HANG;
Anirban Chakraborty9d6a6442011-06-22 02:52:22 +00002392 }
Anirban Chakraborty287e38a2011-06-22 02:52:18 +00002393 rtnl_unlock();
Sritej Velaga7b749ff2011-07-14 03:16:50 +00002394
2395 adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
Anirban Chakraborty9f26f542010-06-01 11:33:09 +00002396 if (!adapter->nic_ops->start_firmware(adapter)) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002397 qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
Amit Kumar Salechab18971d2010-08-25 04:03:04 +00002398 adapter->fw_wait_cnt = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002399 return;
2400 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002401 goto err_ret;
2402 }
2403
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002404 qlcnic_api_unlock(adapter);
Sucheta Chakrabortyaa5e18c2010-04-01 19:01:32 +00002405
Anirban Chakraborty9f26f542010-06-01 11:33:09 +00002406wait_npar:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002407 dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002408 QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002409
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002410 switch (dev_state) {
Amit Kumar Salecha3c4b23b2010-08-17 00:34:20 +00002411 case QLCNIC_DEV_READY:
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00002412 if (!qlcnic_start_firmware(adapter)) {
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002413 qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
Amit Kumar Salechab18971d2010-08-25 04:03:04 +00002414 adapter->fw_wait_cnt = 0;
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002415 return;
2416 }
Amit Kumar Salecha3c4b23b2010-08-17 00:34:20 +00002417 case QLCNIC_DEV_FAILED:
2418 break;
2419 default:
2420 qlcnic_schedule_work(adapter,
2421 qlcnic_fwinit_work, FW_POLL_DELAY);
2422 return;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002423 }
2424
2425err_ret:
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002426 dev_err(&adapter->pdev->dev, "Fwinit work failed state=%u "
2427 "fw_wait_cnt=%u\n", dev_state, adapter->fw_wait_cnt);
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00002428 netif_device_attach(adapter->netdev);
Amit Kumar Salecha21854f02010-08-19 05:08:29 +00002429 qlcnic_clr_all_drv_state(adapter, 0);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002430}
2431
2432static void
2433qlcnic_detach_work(struct work_struct *work)
2434{
2435 struct qlcnic_adapter *adapter = container_of(work,
2436 struct qlcnic_adapter, fw_work.work);
2437 struct net_device *netdev = adapter->netdev;
2438 u32 status;
2439
2440 netif_device_detach(netdev);
2441
Amit Kumar Salechab8c17622010-10-07 23:46:06 +00002442 /* Dont grab rtnl lock during Quiscent mode */
2443 if (adapter->dev_state == QLCNIC_DEV_NEED_QUISCENT) {
2444 if (netif_running(netdev))
2445 __qlcnic_down(adapter, netdev);
2446 } else
2447 qlcnic_down(adapter, netdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002448
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002449 status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
2450
Sony Chacko44f65b22011-08-29 12:50:26 +00002451 if (status & QLCNIC_RCODE_FATAL_ERROR) {
2452 dev_err(&adapter->pdev->dev,
2453 "Detaching the device: peg halt status1=0x%x\n",
2454 status);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002455
Sony Chacko44f65b22011-08-29 12:50:26 +00002456 if (QLCNIC_FWERROR_CODE(status) == QLCNIC_FWERROR_FAN_FAILURE) {
2457 dev_err(&adapter->pdev->dev,
2458 "On board active cooling fan failed. "
2459 "Device has been halted.\n");
2460 dev_err(&adapter->pdev->dev,
2461 "Replace the adapter.\n");
2462 }
2463
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002464 goto err_ret;
Sony Chacko44f65b22011-08-29 12:50:26 +00002465 }
2466
Sony Chacko79788452012-12-04 03:33:53 +00002467 if (adapter->ahw->temp == QLCNIC_TEMP_PANIC) {
Sony Chacko44f65b22011-08-29 12:50:26 +00002468 dev_err(&adapter->pdev->dev, "Detaching the device: temp=%d\n",
Sony Chacko79788452012-12-04 03:33:53 +00002469 adapter->ahw->temp);
Sony Chacko44f65b22011-08-29 12:50:26 +00002470 goto err_ret;
2471 }
2472
Sritej Velaga602ca6f2011-06-22 02:52:17 +00002473 /* Dont ack if this instance is the reset owner */
2474 if (!(adapter->flags & QLCNIC_FW_RESET_OWNER)) {
Sony Chacko44f65b22011-08-29 12:50:26 +00002475 if (qlcnic_set_drv_state(adapter, adapter->dev_state)) {
2476 dev_err(&adapter->pdev->dev,
2477 "Failed to set driver state,"
2478 "detaching the device.\n");
Sritej Velaga602ca6f2011-06-22 02:52:17 +00002479 goto err_ret;
Sony Chacko44f65b22011-08-29 12:50:26 +00002480 }
Sritej Velaga602ca6f2011-06-22 02:52:17 +00002481 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002482
2483 adapter->fw_wait_cnt = 0;
2484
2485 qlcnic_schedule_work(adapter, qlcnic_fwinit_work, FW_POLL_DELAY);
2486
2487 return;
2488
2489err_ret:
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00002490 netif_device_attach(netdev);
Amit Kumar Salecha21854f02010-08-19 05:08:29 +00002491 qlcnic_clr_all_drv_state(adapter, 1);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002492}
2493
Amit Kumar Salecha3c4b23b2010-08-17 00:34:20 +00002494/*Transit NPAR state to NON Operational */
2495static void
2496qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter)
2497{
2498 u32 state;
2499
2500 state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
2501 if (state == QLCNIC_DEV_NPAR_NON_OPER)
2502 return;
2503
2504 if (qlcnic_api_lock(adapter))
2505 return;
2506 QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
2507 qlcnic_api_unlock(adapter);
2508}
2509
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00002510void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *adapter, u32 key)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002511{
Sritej Velaga646779f2012-02-03 13:45:41 +00002512 u32 state, xg_val = 0, gb_val = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002513
Sritej Velaga646779f2012-02-03 13:45:41 +00002514 qlcnic_xg_set_xg0_mask(xg_val);
2515 qlcnic_xg_set_xg1_mask(xg_val);
2516 QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, xg_val);
2517 qlcnic_gb_set_gb0_mask(gb_val);
2518 qlcnic_gb_set_gb1_mask(gb_val);
2519 qlcnic_gb_set_gb2_mask(gb_val);
2520 qlcnic_gb_set_gb3_mask(gb_val);
2521 QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, gb_val);
2522 dev_info(&adapter->pdev->dev, "Pause control frames disabled"
2523 " on all ports\n");
Anirban Chakrabortycea89752010-07-13 20:33:35 +00002524 adapter->need_fw_reset = 1;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002525 if (qlcnic_api_lock(adapter))
2526 return;
2527
2528 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00002529 if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) {
2530 netdev_err(adapter->netdev,
2531 "Device is in FAILED state, Please Reboot\n");
2532 qlcnic_api_unlock(adapter);
2533 return;
2534 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002535
Amit Kumar Salechaf73dfc52010-04-22 02:51:37 +00002536 if (state == QLCNIC_DEV_READY) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002537 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET);
Sritej Velaga602ca6f2011-06-22 02:52:17 +00002538 adapter->flags |= QLCNIC_FW_RESET_OWNER;
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002539 QLCDB(adapter, DRV, "NEED_RESET state set\n");
Sucheta Chakraborty6df900e2010-05-13 03:07:50 +00002540 qlcnic_idc_debug_info(adapter, 0);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002541 }
2542
Amit Kumar Salecha3c4b23b2010-08-17 00:34:20 +00002543 QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002544 qlcnic_api_unlock(adapter);
2545}
2546
Anirban Chakraborty9f26f542010-06-01 11:33:09 +00002547/* Transit to NPAR READY state from NPAR NOT READY state */
2548static void
2549qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
2550{
Anirban Chakraborty9f26f542010-06-01 11:33:09 +00002551 if (qlcnic_api_lock(adapter))
2552 return;
2553
Amit Kumar Salecha3c4b23b2010-08-17 00:34:20 +00002554 QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_OPER);
2555 QLCDB(adapter, DRV, "NPAR operational state set\n");
Anirban Chakraborty9f26f542010-06-01 11:33:09 +00002556
2557 qlcnic_api_unlock(adapter);
2558}
2559
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002560static void
2561qlcnic_schedule_work(struct qlcnic_adapter *adapter,
2562 work_func_t func, int delay)
2563{
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00002564 if (test_bit(__QLCNIC_AER, &adapter->state))
2565 return;
2566
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002567 INIT_DELAYED_WORK(&adapter->fw_work, func);
Amit Kumar Salechaf7ec8042010-10-07 23:46:05 +00002568 queue_delayed_work(qlcnic_wq, &adapter->fw_work,
2569 round_jiffies_relative(delay));
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002570}
2571
2572static void
2573qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter)
2574{
2575 while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
2576 msleep(10);
2577
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00002578 if (!adapter->fw_work.work.func)
2579 return;
2580
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002581 cancel_delayed_work_sync(&adapter->fw_work);
2582}
2583
2584static void
2585qlcnic_attach_work(struct work_struct *work)
2586{
2587 struct qlcnic_adapter *adapter = container_of(work,
2588 struct qlcnic_adapter, fw_work.work);
2589 struct net_device *netdev = adapter->netdev;
Amit Kumar Salechab18971d2010-08-25 04:03:04 +00002590 u32 npar_state;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002591
Sony Chacko79788452012-12-04 03:33:53 +00002592 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
Amit Kumar Salechab18971d2010-08-25 04:03:04 +00002593 npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
2594 if (adapter->fw_wait_cnt++ > QLCNIC_DEV_NPAR_OPER_TIMEO)
2595 qlcnic_clr_all_drv_state(adapter, 0);
2596 else if (npar_state != QLCNIC_DEV_NPAR_OPER)
2597 qlcnic_schedule_work(adapter, qlcnic_attach_work,
2598 FW_POLL_DELAY);
2599 else
2600 goto attach;
2601 QLCDB(adapter, DRV, "Waiting for NPAR state to operational\n");
2602 return;
2603 }
2604attach:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002605 if (netif_running(netdev)) {
Amit Kumar Salecha52486a32010-06-22 03:19:02 +00002606 if (qlcnic_up(adapter, netdev))
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002607 goto done;
2608
Amit Kumar Salechaaec1e842010-09-16 19:14:41 +00002609 qlcnic_restore_indev_addr(netdev, NETDEV_UP);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002610 }
2611
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002612done:
Amit Kumar Salecha34ce3622010-04-01 19:01:34 +00002613 netif_device_attach(netdev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002614 adapter->fw_fail_cnt = 0;
Sritej Velaga032a13c2011-07-29 13:30:27 +00002615 adapter->flags &= ~QLCNIC_FW_HANG;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002616 clear_bit(__QLCNIC_RESETTING, &adapter->state);
Amit Kumar Salecha1b95a832010-02-01 05:24:56 +00002617
2618 if (!qlcnic_clr_drv_state(adapter))
2619 qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
2620 FW_POLL_DELAY);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002621}
2622
2623static int
2624qlcnic_check_health(struct qlcnic_adapter *adapter)
2625{
Sony Chacko4e708122010-08-31 17:17:44 +00002626 u32 state = 0, heartbeat;
Ameen Rahman853d4bc2011-09-13 08:06:17 +00002627 u32 peg_status;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002628
2629 if (qlcnic_check_temp(adapter))
2630 goto detach;
2631
Amit Kumar Salecha2372a5f2010-05-13 03:07:42 +00002632 if (adapter->need_fw_reset)
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00002633 qlcnic_dev_request_reset(adapter, 0);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002634
2635 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
Amit Kumar Salechab8c17622010-10-07 23:46:06 +00002636 if (state == QLCNIC_DEV_NEED_RESET) {
Amit Kumar Salecha3c4b23b2010-08-17 00:34:20 +00002637 qlcnic_set_npar_non_operational(adapter);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002638 adapter->need_fw_reset = 1;
Amit Kumar Salechab8c17622010-10-07 23:46:06 +00002639 } else if (state == QLCNIC_DEV_NEED_QUISCENT)
2640 goto detach;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002641
Sony Chacko4e708122010-08-31 17:17:44 +00002642 heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
2643 if (heartbeat != adapter->heartbeat) {
2644 adapter->heartbeat = heartbeat;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002645 adapter->fw_fail_cnt = 0;
2646 if (adapter->need_fw_reset)
2647 goto detach;
Amit Kumar Salecha68bf1c62010-06-22 03:19:03 +00002648
Sony Chacko099f7aa2012-12-04 03:33:58 +00002649 if (adapter->ahw->reset_context && qlcnic_auto_fw_reset) {
Amit Kumar Salecha68bf1c62010-06-22 03:19:03 +00002650 qlcnic_reset_hw_context(adapter);
2651 adapter->netdev->trans_start = jiffies;
2652 }
2653
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002654 return 0;
2655 }
2656
2657 if (++adapter->fw_fail_cnt < FW_FAIL_THRESH)
2658 return 0;
2659
Sritej Velaga032a13c2011-07-29 13:30:27 +00002660 adapter->flags |= QLCNIC_FW_HANG;
2661
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00002662 qlcnic_dev_request_reset(adapter, 0);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002663
Sony Chacko099f7aa2012-12-04 03:33:58 +00002664 if (qlcnic_auto_fw_reset)
Amit Kumar Salecha0df170b2010-07-13 20:33:32 +00002665 clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002666
Ameen Rahman853d4bc2011-09-13 08:06:17 +00002667 dev_err(&adapter->pdev->dev, "firmware hang detected\n");
2668 dev_err(&adapter->pdev->dev, "Dumping hw/fw registers\n"
Sritej Velagac76ecb72011-07-29 13:30:29 +00002669 "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n"
2670 "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n"
2671 "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n"
2672 "PEG_NET_4_PC: 0x%x\n",
2673 QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1),
2674 QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS2),
2675 QLCRD32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x3c),
2676 QLCRD32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x3c),
2677 QLCRD32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c),
2678 QLCRD32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c),
2679 QLCRD32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c));
Ameen Rahman853d4bc2011-09-13 08:06:17 +00002680 peg_status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
Sritej Velaga97048a12012-02-03 13:45:43 +00002681 if (QLCNIC_FWERROR_CODE(peg_status) == 0x67)
Ameen Rahman853d4bc2011-09-13 08:06:17 +00002682 dev_err(&adapter->pdev->dev,
2683 "Firmware aborted with error code 0x00006700. "
2684 "Device is being reset.\n");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002685detach:
2686 adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state :
2687 QLCNIC_DEV_NEED_RESET;
2688
Sony Chacko099f7aa2012-12-04 03:33:58 +00002689 if (qlcnic_auto_fw_reset && !test_and_set_bit(__QLCNIC_RESETTING,
2690 &adapter->state)) {
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002691
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002692 qlcnic_schedule_work(adapter, qlcnic_detach_work, 0);
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00002693 QLCDB(adapter, DRV, "fw recovery scheduled.\n");
2694 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002695
2696 return 1;
2697}
2698
2699static void
2700qlcnic_fw_poll_work(struct work_struct *work)
2701{
2702 struct qlcnic_adapter *adapter = container_of(work,
2703 struct qlcnic_adapter, fw_work.work);
2704
2705 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
2706 goto reschedule;
2707
2708
2709 if (qlcnic_check_health(adapter))
2710 return;
2711
Amit Kumar Salechab5e54922010-08-31 17:17:51 +00002712 if (adapter->fhash.fnum)
2713 qlcnic_prune_lb_filters(adapter);
2714
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002715reschedule:
2716 qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
2717}
2718
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00002719static int qlcnic_is_first_func(struct pci_dev *pdev)
2720{
2721 struct pci_dev *oth_pdev;
2722 int val = pdev->devfn;
2723
2724 while (val-- > 0) {
2725 oth_pdev = pci_get_domain_bus_and_slot(pci_domain_nr
2726 (pdev->bus), pdev->bus->number,
2727 PCI_DEVFN(PCI_SLOT(pdev->devfn), val));
Amit Kumar Salechabfc978f2010-07-18 14:51:59 -07002728 if (!oth_pdev)
2729 continue;
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00002730
Amit Kumar Salechabfc978f2010-07-18 14:51:59 -07002731 if (oth_pdev->current_state != PCI_D3cold) {
2732 pci_dev_put(oth_pdev);
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00002733 return 0;
Amit Kumar Salechabfc978f2010-07-18 14:51:59 -07002734 }
2735 pci_dev_put(oth_pdev);
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00002736 }
2737 return 1;
2738}
2739
2740static int qlcnic_attach_func(struct pci_dev *pdev)
2741{
2742 int err, first_func;
2743 struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
2744 struct net_device *netdev = adapter->netdev;
2745
2746 pdev->error_state = pci_channel_io_normal;
2747
2748 err = pci_enable_device(pdev);
2749 if (err)
2750 return err;
2751
2752 pci_set_power_state(pdev, PCI_D0);
2753 pci_set_master(pdev);
2754 pci_restore_state(pdev);
2755
2756 first_func = qlcnic_is_first_func(pdev);
2757
2758 if (qlcnic_api_lock(adapter))
2759 return -EINVAL;
2760
Sony Chacko79788452012-12-04 03:33:53 +00002761 if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00002762 adapter->need_fw_reset = 1;
2763 set_bit(__QLCNIC_START_FW, &adapter->state);
2764 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
2765 QLCDB(adapter, DRV, "Restarting fw\n");
2766 }
2767 qlcnic_api_unlock(adapter);
2768
2769 err = adapter->nic_ops->start_firmware(adapter);
2770 if (err)
2771 return err;
2772
2773 qlcnic_clr_drv_state(adapter);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00002774 qlcnic_setup_intr(adapter, 0);
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00002775
2776 if (netif_running(netdev)) {
2777 err = qlcnic_attach(adapter);
2778 if (err) {
Amit Kumar Salecha21854f02010-08-19 05:08:29 +00002779 qlcnic_clr_all_drv_state(adapter, 1);
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00002780 clear_bit(__QLCNIC_AER, &adapter->state);
2781 netif_device_attach(netdev);
2782 return err;
2783 }
2784
2785 err = qlcnic_up(adapter, netdev);
2786 if (err)
2787 goto done;
2788
Amit Kumar Salechaaec1e842010-09-16 19:14:41 +00002789 qlcnic_restore_indev_addr(netdev, NETDEV_UP);
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00002790 }
2791 done:
2792 netif_device_attach(netdev);
2793 return err;
2794}
2795
2796static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev,
2797 pci_channel_state_t state)
2798{
2799 struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
2800 struct net_device *netdev = adapter->netdev;
2801
2802 if (state == pci_channel_io_perm_failure)
2803 return PCI_ERS_RESULT_DISCONNECT;
2804
2805 if (state == pci_channel_io_normal)
2806 return PCI_ERS_RESULT_RECOVERED;
2807
2808 set_bit(__QLCNIC_AER, &adapter->state);
2809 netif_device_detach(netdev);
2810
2811 cancel_delayed_work_sync(&adapter->fw_work);
2812
2813 if (netif_running(netdev))
2814 qlcnic_down(adapter, netdev);
2815
2816 qlcnic_detach(adapter);
2817 qlcnic_teardown_intr(adapter);
2818
2819 clear_bit(__QLCNIC_RESETTING, &adapter->state);
2820
2821 pci_save_state(pdev);
2822 pci_disable_device(pdev);
2823
2824 return PCI_ERS_RESULT_NEED_RESET;
2825}
2826
2827static pci_ers_result_t qlcnic_io_slot_reset(struct pci_dev *pdev)
2828{
2829 return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT :
2830 PCI_ERS_RESULT_RECOVERED;
2831}
2832
2833static void qlcnic_io_resume(struct pci_dev *pdev)
2834{
2835 struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
2836
2837 pci_cleanup_aer_uncorrect_error_status(pdev);
2838
2839 if (QLCRD32(adapter, QLCNIC_CRB_DEV_STATE) == QLCNIC_DEV_READY &&
2840 test_and_clear_bit(__QLCNIC_AER, &adapter->state))
2841 qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
2842 FW_POLL_DELAY);
2843}
2844
Anirban Chakraborty87eb7432010-06-03 07:50:56 +00002845static int
2846qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
2847{
2848 int err;
2849
2850 err = qlcnic_can_start_firmware(adapter);
2851 if (err)
2852 return err;
2853
Amit Kumar Salecha78f84e12010-08-19 05:08:28 +00002854 err = qlcnic_check_npar_opertional(adapter);
2855 if (err)
2856 return err;
Amit Kumar Salecha3c4b23b2010-08-17 00:34:20 +00002857
Rajesh Borundia174240a2010-08-31 17:17:47 +00002858 err = qlcnic_initialize_nic(adapter);
2859 if (err)
2860 return err;
2861
Anirban Chakraborty87eb7432010-06-03 07:50:56 +00002862 qlcnic_check_options(adapter);
2863
Rajesh Borundia73733732010-08-31 17:17:50 +00002864 err = qlcnic_set_eswitch_port_config(adapter);
2865 if (err)
2866 return err;
2867
Anirban Chakraborty87eb7432010-06-03 07:50:56 +00002868 adapter->need_fw_reset = 0;
2869
2870 return err;
2871}
2872
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +00002873int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val)
2874{
Sony Chacko099f7aa2012-12-04 03:33:58 +00002875 if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +00002876 netdev_info(netdev, "no msix or msi support, hence no rss\n");
2877 return -EINVAL;
2878 }
2879
2880 if ((val > max_hw) || (val < 2) || !is_power_of_2(val)) {
2881 netdev_info(netdev, "rss_ring valid range [2 - %x] in "
2882 " powers of 2\n", max_hw);
2883 return -EINVAL;
2884 }
2885 return 0;
2886
2887}
2888
2889int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data)
2890{
2891 struct net_device *netdev = adapter->netdev;
2892 int err = 0;
2893
2894 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
2895 return -EBUSY;
2896
2897 netif_device_detach(netdev);
2898 if (netif_running(netdev))
2899 __qlcnic_down(adapter, netdev);
2900 qlcnic_detach(adapter);
2901 qlcnic_teardown_intr(adapter);
2902
2903 if (qlcnic_enable_msix(adapter, data)) {
2904 netdev_info(netdev, "failed setting max_rss; rss disabled\n");
2905 qlcnic_enable_msi_legacy(adapter);
2906 }
2907
2908 if (netif_running(netdev)) {
2909 err = qlcnic_attach(adapter);
2910 if (err)
2911 goto done;
2912 err = __qlcnic_up(adapter, netdev);
2913 if (err)
2914 goto done;
2915 qlcnic_restore_indev_addr(netdev, NETDEV_UP);
2916 }
2917 done:
2918 netif_device_attach(netdev);
2919 clear_bit(__QLCNIC_RESETTING, &adapter->state);
2920 return err;
2921}
2922
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002923#ifdef CONFIG_INET
2924
2925#define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops)
2926
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002927static void
Amit Kumar Salechaaec1e842010-09-16 19:14:41 +00002928qlcnic_config_indev_addr(struct qlcnic_adapter *adapter,
2929 struct net_device *dev, unsigned long event)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002930{
2931 struct in_device *indev;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002932
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002933 indev = in_dev_get(dev);
2934 if (!indev)
2935 return;
2936
2937 for_ifa(indev) {
2938 switch (event) {
2939 case NETDEV_UP:
2940 qlcnic_config_ipaddr(adapter,
2941 ifa->ifa_address, QLCNIC_IP_UP);
2942 break;
2943 case NETDEV_DOWN:
2944 qlcnic_config_ipaddr(adapter,
2945 ifa->ifa_address, QLCNIC_IP_DOWN);
2946 break;
2947 default:
2948 break;
2949 }
2950 } endfor_ifa(indev);
2951
2952 in_dev_put(indev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002953}
2954
Amit Kumar Salechaaec1e842010-09-16 19:14:41 +00002955static void
2956qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event)
2957{
2958 struct qlcnic_adapter *adapter = netdev_priv(netdev);
2959 struct net_device *dev;
2960 u16 vid;
2961
2962 qlcnic_config_indev_addr(adapter, netdev, event);
2963
Anirban Chakrabortyb9796a12011-04-01 14:28:15 +00002964 for_each_set_bit(vid, adapter->vlans, VLAN_N_VID) {
Jiri Pirko223bb152011-07-20 04:54:44 +00002965 dev = __vlan_find_dev_deep(netdev, vid);
Amit Kumar Salechaaec1e842010-09-16 19:14:41 +00002966 if (!dev)
2967 continue;
Amit Kumar Salechaaec1e842010-09-16 19:14:41 +00002968 qlcnic_config_indev_addr(adapter, dev, event);
2969 }
2970}
2971
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002972static int qlcnic_netdev_event(struct notifier_block *this,
2973 unsigned long event, void *ptr)
2974{
2975 struct qlcnic_adapter *adapter;
2976 struct net_device *dev = (struct net_device *)ptr;
2977
2978recheck:
2979 if (dev == NULL)
2980 goto done;
2981
2982 if (dev->priv_flags & IFF_802_1Q_VLAN) {
2983 dev = vlan_dev_real_dev(dev);
2984 goto recheck;
2985 }
2986
2987 if (!is_qlcnic_netdev(dev))
2988 goto done;
2989
2990 adapter = netdev_priv(dev);
2991
2992 if (!adapter)
2993 goto done;
2994
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00002995 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002996 goto done;
2997
Amit Kumar Salechaaec1e842010-09-16 19:14:41 +00002998 qlcnic_config_indev_addr(adapter, dev, event);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00002999done:
3000 return NOTIFY_DONE;
3001}
3002
3003static int
3004qlcnic_inetaddr_event(struct notifier_block *this,
3005 unsigned long event, void *ptr)
3006{
3007 struct qlcnic_adapter *adapter;
3008 struct net_device *dev;
3009
3010 struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
3011
3012 dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
3013
3014recheck:
Amit Kumar Salechaaec1e842010-09-16 19:14:41 +00003015 if (dev == NULL)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003016 goto done;
3017
3018 if (dev->priv_flags & IFF_802_1Q_VLAN) {
3019 dev = vlan_dev_real_dev(dev);
3020 goto recheck;
3021 }
3022
3023 if (!is_qlcnic_netdev(dev))
3024 goto done;
3025
3026 adapter = netdev_priv(dev);
3027
Amit Kumar Salecha251a84c2010-05-13 03:07:46 +00003028 if (!adapter)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003029 goto done;
3030
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00003031 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003032 goto done;
3033
3034 switch (event) {
3035 case NETDEV_UP:
3036 qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_UP);
3037 break;
3038 case NETDEV_DOWN:
3039 qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_DOWN);
3040 break;
3041 default:
3042 break;
3043 }
3044
3045done:
3046 return NOTIFY_DONE;
3047}
3048
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003049static struct notifier_block qlcnic_netdev_cb = {
3050 .notifier_call = qlcnic_netdev_event,
3051};
3052
3053static struct notifier_block qlcnic_inetaddr_cb = {
3054 .notifier_call = qlcnic_inetaddr_event,
3055};
3056#else
3057static void
Amit Kumar Salechaaec1e842010-09-16 19:14:41 +00003058qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003059{ }
3060#endif
Shahed Shaikh63507592012-11-23 23:56:52 +00003061static struct pci_error_handlers qlcnic_err_handler = {
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00003062 .error_detected = qlcnic_io_error_detected,
3063 .slot_reset = qlcnic_io_slot_reset,
3064 .resume = qlcnic_io_resume,
3065};
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003066
3067static struct pci_driver qlcnic_driver = {
3068 .name = qlcnic_driver_name,
3069 .id_table = qlcnic_pci_tbl,
3070 .probe = qlcnic_probe,
Bill Pemberton6bb58bb2012-12-03 09:23:25 -05003071 .remove = qlcnic_remove,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003072#ifdef CONFIG_PM
3073 .suspend = qlcnic_suspend,
3074 .resume = qlcnic_resume,
3075#endif
Sucheta Chakraborty451724c2010-07-13 20:33:34 +00003076 .shutdown = qlcnic_shutdown,
3077 .err_handler = &qlcnic_err_handler
3078
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003079};
3080
3081static int __init qlcnic_init_module(void)
3082{
Amit Kumar Salecha0cf3a142010-07-13 20:33:33 +00003083 int ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003084
3085 printk(KERN_INFO "%s\n", qlcnic_driver_string);
3086
Amit Kumar Salechaf7ec8042010-10-07 23:46:05 +00003087 qlcnic_wq = create_singlethread_workqueue("qlcnic");
3088 if (qlcnic_wq == NULL) {
3089 printk(KERN_ERR "qlcnic: cannot create workqueue\n");
3090 return -ENOMEM;
3091 }
3092
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003093#ifdef CONFIG_INET
3094 register_netdevice_notifier(&qlcnic_netdev_cb);
3095 register_inetaddr_notifier(&qlcnic_inetaddr_cb);
3096#endif
3097
Amit Kumar Salecha0cf3a142010-07-13 20:33:33 +00003098 ret = pci_register_driver(&qlcnic_driver);
3099 if (ret) {
3100#ifdef CONFIG_INET
3101 unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
3102 unregister_netdevice_notifier(&qlcnic_netdev_cb);
3103#endif
Amit Kumar Salechaf7ec8042010-10-07 23:46:05 +00003104 destroy_workqueue(qlcnic_wq);
Amit Kumar Salecha0cf3a142010-07-13 20:33:33 +00003105 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003106
Amit Kumar Salecha0cf3a142010-07-13 20:33:33 +00003107 return ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003108}
3109
3110module_init(qlcnic_init_module);
3111
3112static void __exit qlcnic_exit_module(void)
3113{
3114
3115 pci_unregister_driver(&qlcnic_driver);
3116
3117#ifdef CONFIG_INET
3118 unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
3119 unregister_netdevice_notifier(&qlcnic_netdev_cb);
3120#endif
Amit Kumar Salechaf7ec8042010-10-07 23:46:05 +00003121 destroy_workqueue(qlcnic_wq);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00003122}
3123
3124module_exit(qlcnic_exit_module);