blob: c08fa20dd5f07a2679905bbaf27668f6cf3ef741 [file] [log] [blame]
Jitendra Kalsaria577ae392013-02-04 12:33:07 +00001/*
2 * QLogic qlcnic NIC Driver
3 * Copyright (c) 2009-2013 QLogic Corporation
4 *
5 * See LICENSE.qlcnic for copyright and licensing details.
6 */
7
Sony Chacko7f966452013-01-01 03:20:19 +00008#include "qlcnic.h"
9#include <linux/if_vlan.h>
10#include <linux/ipv6.h>
11#include <linux/ethtool.h>
12#include <linux/interrupt.h>
13
14#define QLCNIC_MAX_TX_QUEUES 1
Sony Chacko7f966452013-01-01 03:20:19 +000015#define RSS_HASHTYPE_IP_TCP 0x3
16
17/* status descriptor mailbox data
Shahed Shaikha96227e2013-03-08 09:53:49 +000018 * @phy_addr_{low|high}: physical address of buffer
Sony Chacko7f966452013-01-01 03:20:19 +000019 * @sds_ring_size: buffer size
20 * @intrpt_id: interrupt id
21 * @intrpt_val: source of interrupt
22 */
23struct qlcnic_sds_mbx {
Shahed Shaikha96227e2013-03-08 09:53:49 +000024 u32 phy_addr_low;
25 u32 phy_addr_high;
26 u32 rsvd1[4];
27#if defined(__LITTLE_ENDIAN)
Sony Chacko7f966452013-01-01 03:20:19 +000028 u16 sds_ring_size;
Shahed Shaikha96227e2013-03-08 09:53:49 +000029 u16 rsvd2;
30 u16 rsvd3[2];
Sony Chacko7f966452013-01-01 03:20:19 +000031 u16 intrpt_id;
32 u8 intrpt_val;
Shahed Shaikha96227e2013-03-08 09:53:49 +000033 u8 rsvd4;
34#elif defined(__BIG_ENDIAN)
35 u16 rsvd2;
36 u16 sds_ring_size;
37 u16 rsvd3[2];
38 u8 rsvd4;
39 u8 intrpt_val;
40 u16 intrpt_id;
41#endif
42 u32 rsvd5;
Sony Chacko7f966452013-01-01 03:20:19 +000043} __packed;
44
45/* receive descriptor buffer data
Shahed Shaikha96227e2013-03-08 09:53:49 +000046 * phy_addr_reg_{low|high}: physical address of regular buffer
47 * phy_addr_jmb_{low|high}: physical address of jumbo buffer
Sony Chacko7f966452013-01-01 03:20:19 +000048 * reg_ring_sz: size of regular buffer
49 * reg_ring_len: no. of entries in regular buffer
50 * jmb_ring_len: no. of entries in jumbo buffer
51 * jmb_ring_sz: size of jumbo buffer
52 */
53struct qlcnic_rds_mbx {
Shahed Shaikha96227e2013-03-08 09:53:49 +000054 u32 phy_addr_reg_low;
55 u32 phy_addr_reg_high;
56 u32 phy_addr_jmb_low;
57 u32 phy_addr_jmb_high;
58#if defined(__LITTLE_ENDIAN)
Sony Chacko7f966452013-01-01 03:20:19 +000059 u16 reg_ring_sz;
60 u16 reg_ring_len;
61 u16 jmb_ring_sz;
62 u16 jmb_ring_len;
Shahed Shaikha96227e2013-03-08 09:53:49 +000063#elif defined(__BIG_ENDIAN)
64 u16 reg_ring_len;
65 u16 reg_ring_sz;
66 u16 jmb_ring_len;
67 u16 jmb_ring_sz;
68#endif
Sony Chacko7f966452013-01-01 03:20:19 +000069} __packed;
70
71/* host producers for regular and jumbo rings */
72struct __host_producer_mbx {
73 u32 reg_buf;
74 u32 jmb_buf;
75} __packed;
76
77/* Receive context mailbox data outbox registers
78 * @state: state of the context
79 * @vport_id: virtual port id
80 * @context_id: receive context id
81 * @num_pci_func: number of pci functions of the port
82 * @phy_port: physical port id
83 */
84struct qlcnic_rcv_mbx_out {
Shahed Shaikha96227e2013-03-08 09:53:49 +000085#if defined(__LITTLE_ENDIAN)
Sony Chacko7f966452013-01-01 03:20:19 +000086 u8 rcv_num;
87 u8 sts_num;
88 u16 ctx_id;
89 u8 state;
90 u8 num_pci_func;
91 u8 phy_port;
92 u8 vport_id;
Shahed Shaikha96227e2013-03-08 09:53:49 +000093#elif defined(__BIG_ENDIAN)
94 u16 ctx_id;
95 u8 sts_num;
96 u8 rcv_num;
97 u8 vport_id;
98 u8 phy_port;
99 u8 num_pci_func;
100 u8 state;
101#endif
Sony Chacko7f966452013-01-01 03:20:19 +0000102 u32 host_csmr[QLCNIC_MAX_RING_SETS];
103 struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
104} __packed;
105
106struct qlcnic_add_rings_mbx_out {
Shahed Shaikha96227e2013-03-08 09:53:49 +0000107#if defined(__LITTLE_ENDIAN)
Sony Chacko7f966452013-01-01 03:20:19 +0000108 u8 rcv_num;
109 u8 sts_num;
Shahed Shaikha96227e2013-03-08 09:53:49 +0000110 u16 ctx_id;
111#elif defined(__BIG_ENDIAN)
112 u16 ctx_id;
113 u8 sts_num;
114 u8 rcv_num;
115#endif
Sony Chacko7f966452013-01-01 03:20:19 +0000116 u32 host_csmr[QLCNIC_MAX_RING_SETS];
117 struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
118} __packed;
119
120/* Transmit context mailbox inbox registers
Shahed Shaikha96227e2013-03-08 09:53:49 +0000121 * @phys_addr_{low|high}: DMA address of the transmit buffer
122 * @cnsmr_index_{low|high}: host consumer index
Sony Chacko7f966452013-01-01 03:20:19 +0000123 * @size: legth of transmit buffer ring
124 * @intr_id: interrput id
125 * @src: src of interrupt
126 */
127struct qlcnic_tx_mbx {
Shahed Shaikha96227e2013-03-08 09:53:49 +0000128 u32 phys_addr_low;
129 u32 phys_addr_high;
130 u32 cnsmr_index_low;
131 u32 cnsmr_index_high;
132#if defined(__LITTLE_ENDIAN)
Sony Chacko7f966452013-01-01 03:20:19 +0000133 u16 size;
134 u16 intr_id;
135 u8 src;
136 u8 rsvd[3];
Shahed Shaikha96227e2013-03-08 09:53:49 +0000137#elif defined(__BIG_ENDIAN)
138 u16 intr_id;
139 u16 size;
140 u8 rsvd[3];
141 u8 src;
142#endif
Sony Chacko7f966452013-01-01 03:20:19 +0000143} __packed;
144
145/* Transmit context mailbox outbox registers
146 * @host_prod: host producer index
147 * @ctx_id: transmit context id
148 * @state: state of the transmit context
149 */
Shahed Shaikha96227e2013-03-08 09:53:49 +0000150
Sony Chacko7f966452013-01-01 03:20:19 +0000151struct qlcnic_tx_mbx_out {
152 u32 host_prod;
Shahed Shaikha96227e2013-03-08 09:53:49 +0000153#if defined(__LITTLE_ENDIAN)
Sony Chacko7f966452013-01-01 03:20:19 +0000154 u16 ctx_id;
155 u8 state;
156 u8 rsvd;
Shahed Shaikha96227e2013-03-08 09:53:49 +0000157#elif defined(__BIG_ENDIAN)
158 u8 rsvd;
159 u8 state;
160 u16 ctx_id;
161#endif
Sony Chacko7f966452013-01-01 03:20:19 +0000162} __packed;
163
164static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
165 {QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1},
166 {QLCNIC_CMD_CONFIG_INTRPT, 18, 34},
167 {QLCNIC_CMD_CREATE_RX_CTX, 136, 27},
168 {QLCNIC_CMD_DESTROY_RX_CTX, 2, 1},
169 {QLCNIC_CMD_CREATE_TX_CTX, 54, 18},
170 {QLCNIC_CMD_DESTROY_TX_CTX, 2, 1},
171 {QLCNIC_CMD_CONFIGURE_MAC_LEARNING, 2, 1},
172 {QLCNIC_CMD_INTRPT_TEST, 22, 12},
173 {QLCNIC_CMD_SET_MTU, 3, 1},
174 {QLCNIC_CMD_READ_PHY, 4, 2},
175 {QLCNIC_CMD_WRITE_PHY, 5, 1},
176 {QLCNIC_CMD_READ_HW_REG, 4, 1},
177 {QLCNIC_CMD_GET_FLOW_CTL, 4, 2},
178 {QLCNIC_CMD_SET_FLOW_CTL, 4, 1},
179 {QLCNIC_CMD_READ_MAX_MTU, 4, 2},
180 {QLCNIC_CMD_READ_MAX_LRO, 4, 2},
181 {QLCNIC_CMD_MAC_ADDRESS, 4, 3},
182 {QLCNIC_CMD_GET_PCI_INFO, 1, 66},
183 {QLCNIC_CMD_GET_NIC_INFO, 2, 19},
184 {QLCNIC_CMD_SET_NIC_INFO, 32, 1},
185 {QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3},
186 {QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1},
187 {QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3},
188 {QLCNIC_CMD_SET_PORTMIRRORING, 4, 1},
189 {QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1},
190 {QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3},
191 {QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1},
192 {QLCNIC_CMD_CONFIG_PORT, 4, 1},
193 {QLCNIC_CMD_TEMP_SIZE, 1, 4},
194 {QLCNIC_CMD_GET_TEMP_HDR, 5, 5},
195 {QLCNIC_CMD_GET_LINK_EVENT, 2, 1},
196 {QLCNIC_CMD_CONFIG_MAC_VLAN, 4, 3},
197 {QLCNIC_CMD_CONFIG_INTR_COAL, 6, 1},
198 {QLCNIC_CMD_CONFIGURE_RSS, 14, 1},
199 {QLCNIC_CMD_CONFIGURE_LED, 2, 1},
200 {QLCNIC_CMD_CONFIGURE_MAC_RX_MODE, 2, 1},
201 {QLCNIC_CMD_CONFIGURE_HW_LRO, 2, 1},
202 {QLCNIC_CMD_GET_STATISTICS, 2, 80},
203 {QLCNIC_CMD_SET_PORT_CONFIG, 2, 1},
204 {QLCNIC_CMD_GET_PORT_CONFIG, 2, 2},
205 {QLCNIC_CMD_GET_LINK_STATUS, 2, 4},
206 {QLCNIC_CMD_IDC_ACK, 5, 1},
207 {QLCNIC_CMD_INIT_NIC_FUNC, 2, 1},
208 {QLCNIC_CMD_STOP_NIC_FUNC, 2, 1},
209 {QLCNIC_CMD_SET_LED_CONFIG, 5, 1},
210 {QLCNIC_CMD_GET_LED_CONFIG, 1, 5},
211 {QLCNIC_CMD_ADD_RCV_RINGS, 130, 26},
212};
213
214static const u32 qlcnic_83xx_ext_reg_tbl[] = {
215 0x38CC, /* Global Reset */
216 0x38F0, /* Wildcard */
217 0x38FC, /* Informant */
218 0x3038, /* Host MBX ctrl */
219 0x303C, /* FW MBX ctrl */
220 0x355C, /* BOOT LOADER ADDRESS REG */
221 0x3560, /* BOOT LOADER SIZE REG */
222 0x3564, /* FW IMAGE ADDR REG */
223 0x1000, /* MBX intr enable */
224 0x1200, /* Default Intr mask */
225 0x1204, /* Default Interrupt ID */
226 0x3780, /* QLC_83XX_IDC_MAJ_VERSION */
227 0x3784, /* QLC_83XX_IDC_DEV_STATE */
228 0x3788, /* QLC_83XX_IDC_DRV_PRESENCE */
229 0x378C, /* QLC_83XX_IDC_DRV_ACK */
230 0x3790, /* QLC_83XX_IDC_CTRL */
231 0x3794, /* QLC_83XX_IDC_DRV_AUDIT */
232 0x3798, /* QLC_83XX_IDC_MIN_VERSION */
233 0x379C, /* QLC_83XX_RECOVER_DRV_LOCK */
234 0x37A0, /* QLC_83XX_IDC_PF_0 */
235 0x37A4, /* QLC_83XX_IDC_PF_1 */
236 0x37A8, /* QLC_83XX_IDC_PF_2 */
237 0x37AC, /* QLC_83XX_IDC_PF_3 */
238 0x37B0, /* QLC_83XX_IDC_PF_4 */
239 0x37B4, /* QLC_83XX_IDC_PF_5 */
240 0x37B8, /* QLC_83XX_IDC_PF_6 */
241 0x37BC, /* QLC_83XX_IDC_PF_7 */
242 0x37C0, /* QLC_83XX_IDC_PF_8 */
243 0x37C4, /* QLC_83XX_IDC_PF_9 */
244 0x37C8, /* QLC_83XX_IDC_PF_10 */
245 0x37CC, /* QLC_83XX_IDC_PF_11 */
246 0x37D0, /* QLC_83XX_IDC_PF_12 */
247 0x37D4, /* QLC_83XX_IDC_PF_13 */
248 0x37D8, /* QLC_83XX_IDC_PF_14 */
249 0x37DC, /* QLC_83XX_IDC_PF_15 */
250 0x37E0, /* QLC_83XX_IDC_DEV_PARTITION_INFO_1 */
251 0x37E4, /* QLC_83XX_IDC_DEV_PARTITION_INFO_2 */
252 0x37F0, /* QLC_83XX_DRV_OP_MODE */
253 0x37F4, /* QLC_83XX_VNIC_STATE */
254 0x3868, /* QLC_83XX_DRV_LOCK */
255 0x386C, /* QLC_83XX_DRV_UNLOCK */
256 0x3504, /* QLC_83XX_DRV_LOCK_ID */
257 0x34A4, /* QLC_83XX_ASIC_TEMP */
258};
259
260static const u32 qlcnic_83xx_reg_tbl[] = {
261 0x34A8, /* PEG_HALT_STAT1 */
262 0x34AC, /* PEG_HALT_STAT2 */
263 0x34B0, /* FW_HEARTBEAT */
264 0x3500, /* FLASH LOCK_ID */
265 0x3528, /* FW_CAPABILITIES */
266 0x3538, /* Driver active, DRV_REG0 */
267 0x3540, /* Device state, DRV_REG1 */
268 0x3544, /* Driver state, DRV_REG2 */
269 0x3548, /* Driver scratch, DRV_REG3 */
270 0x354C, /* Device partiton info, DRV_REG4 */
271 0x3524, /* Driver IDC ver, DRV_REG5 */
272 0x3550, /* FW_VER_MAJOR */
273 0x3554, /* FW_VER_MINOR */
274 0x3558, /* FW_VER_SUB */
275 0x359C, /* NPAR STATE */
276 0x35FC, /* FW_IMG_VALID */
277 0x3650, /* CMD_PEG_STATE */
278 0x373C, /* RCV_PEG_STATE */
279 0x37B4, /* ASIC TEMP */
280 0x356C, /* FW API */
281 0x3570, /* DRV OP MODE */
282 0x3850, /* FLASH LOCK */
283 0x3854, /* FLASH UNLOCK */
284};
285
286static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
287 .read_crb = qlcnic_83xx_read_crb,
288 .write_crb = qlcnic_83xx_write_crb,
289 .read_reg = qlcnic_83xx_rd_reg_indirect,
290 .write_reg = qlcnic_83xx_wrt_reg_indirect,
291 .get_mac_address = qlcnic_83xx_get_mac_address,
292 .setup_intr = qlcnic_83xx_setup_intr,
293 .alloc_mbx_args = qlcnic_83xx_alloc_mbx_args,
294 .mbx_cmd = qlcnic_83xx_mbx_op,
295 .get_func_no = qlcnic_83xx_get_func_no,
296 .api_lock = qlcnic_83xx_cam_lock,
297 .api_unlock = qlcnic_83xx_cam_unlock,
Sony Chacko319ecf12013-01-01 03:20:22 +0000298 .add_sysfs = qlcnic_83xx_add_sysfs,
299 .remove_sysfs = qlcnic_83xx_remove_sysfs,
Sony Chacko4be41e92013-01-01 03:20:20 +0000300 .process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag,
Sony Chacko7f966452013-01-01 03:20:19 +0000301 .create_rx_ctx = qlcnic_83xx_create_rx_ctx,
302 .create_tx_ctx = qlcnic_83xx_create_tx_ctx,
303 .setup_link_event = qlcnic_83xx_setup_link_event,
304 .get_nic_info = qlcnic_83xx_get_nic_info,
305 .get_pci_info = qlcnic_83xx_get_pci_info,
306 .set_nic_info = qlcnic_83xx_set_nic_info,
307 .change_macvlan = qlcnic_83xx_sre_macaddr_change,
Sony Chacko4be41e92013-01-01 03:20:20 +0000308 .napi_enable = qlcnic_83xx_napi_enable,
309 .napi_disable = qlcnic_83xx_napi_disable,
Sony Chacko7f966452013-01-01 03:20:19 +0000310 .config_intr_coal = qlcnic_83xx_config_intr_coal,
311 .config_rss = qlcnic_83xx_config_rss,
312 .config_hw_lro = qlcnic_83xx_config_hw_lro,
Sony Chacko7f966452013-01-01 03:20:19 +0000313 .config_promisc_mode = qlcnic_83xx_nic_set_promisc,
314 .change_l2_filter = qlcnic_83xx_change_l2_filter,
315 .get_board_info = qlcnic_83xx_get_port_info,
316};
317
318static struct qlcnic_nic_template qlcnic_83xx_ops = {
319 .config_bridged_mode = qlcnic_config_bridged_mode,
320 .config_led = qlcnic_config_led,
Sony Chacko629263a2013-01-01 04:11:55 +0000321 .request_reset = qlcnic_83xx_idc_request_reset,
322 .cancel_idc_work = qlcnic_83xx_idc_exit,
Sony Chacko4be41e92013-01-01 03:20:20 +0000323 .napi_add = qlcnic_83xx_napi_add,
324 .napi_del = qlcnic_83xx_napi_del,
Sony Chacko7f966452013-01-01 03:20:19 +0000325 .config_ipaddr = qlcnic_83xx_config_ipaddr,
326 .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr,
327};
328
329void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw)
330{
331 ahw->hw_ops = &qlcnic_83xx_hw_ops;
332 ahw->reg_tbl = (u32 *)qlcnic_83xx_reg_tbl;
333 ahw->ext_reg_tbl = (u32 *)qlcnic_83xx_ext_reg_tbl;
334}
335
336int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *adapter)
337{
338 u32 fw_major, fw_minor, fw_build;
339 struct pci_dev *pdev = adapter->pdev;
340
341 fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
342 fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
343 fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
344 adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
345
346 dev_info(&pdev->dev, "Driver v%s, firmware version %d.%d.%d\n",
347 QLCNIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build);
348
349 return adapter->fw_version;
350}
351
352static int __qlcnic_set_win_base(struct qlcnic_adapter *adapter, u32 addr)
353{
354 void __iomem *base;
355 u32 val;
356
357 base = adapter->ahw->pci_base0 +
358 QLC_83XX_CRB_WIN_FUNC(adapter->ahw->pci_func);
359 writel(addr, base);
360 val = readl(base);
361 if (val != addr)
362 return -EIO;
363
364 return 0;
365}
366
367int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *adapter, ulong addr)
368{
369 int ret;
370 struct qlcnic_hardware_context *ahw = adapter->ahw;
371
372 ret = __qlcnic_set_win_base(adapter, (u32) addr);
373 if (!ret) {
374 return QLCRDX(ahw, QLCNIC_WILDCARD);
375 } else {
376 dev_err(&adapter->pdev->dev,
377 "%s failed, addr = 0x%x\n", __func__, (int)addr);
378 return -EIO;
379 }
380}
381
382int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
383 u32 data)
384{
385 int err;
386 struct qlcnic_hardware_context *ahw = adapter->ahw;
387
388 err = __qlcnic_set_win_base(adapter, (u32) addr);
389 if (!err) {
390 QLCWRX(ahw, QLCNIC_WILDCARD, data);
391 return 0;
392 } else {
393 dev_err(&adapter->pdev->dev,
394 "%s failed, addr = 0x%x data = 0x%x\n",
395 __func__, (int)addr, data);
396 return err;
397 }
398}
399
400int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
401{
402 int err, i, num_msix;
403 struct qlcnic_hardware_context *ahw = adapter->ahw;
404
405 if (!num_intr)
406 num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;
407 num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
408 num_intr));
409 /* account for AEN interrupt MSI-X based interrupts */
410 num_msix += 1;
411 num_msix += adapter->max_drv_tx_rings;
412 err = qlcnic_enable_msix(adapter, num_msix);
413 if (err == -ENOMEM)
414 return err;
415 if (adapter->flags & QLCNIC_MSIX_ENABLED)
416 num_msix = adapter->ahw->num_msix;
417 else
418 num_msix = 1;
419 /* setup interrupt mapping table for fw */
420 ahw->intr_tbl = vzalloc(num_msix *
421 sizeof(struct qlcnic_intrpt_config));
422 if (!ahw->intr_tbl)
423 return -ENOMEM;
424 if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
425 /* MSI-X enablement failed, use legacy interrupt */
426 adapter->tgt_status_reg = ahw->pci_base0 + QLC_83XX_INTX_PTR;
427 adapter->tgt_mask_reg = ahw->pci_base0 + QLC_83XX_INTX_MASK;
428 adapter->isr_int_vec = ahw->pci_base0 + QLC_83XX_INTX_TRGR;
429 adapter->msix_entries[0].vector = adapter->pdev->irq;
430 dev_info(&adapter->pdev->dev, "using legacy interrupt\n");
431 }
432
433 for (i = 0; i < num_msix; i++) {
434 if (adapter->flags & QLCNIC_MSIX_ENABLED)
435 ahw->intr_tbl[i].type = QLCNIC_INTRPT_MSIX;
436 else
437 ahw->intr_tbl[i].type = QLCNIC_INTRPT_INTX;
438 ahw->intr_tbl[i].id = i;
439 ahw->intr_tbl[i].src = 0;
440 }
441 return 0;
442}
443
Himanshu Madhaniac166702013-02-18 12:06:15 +0000444inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter)
445{
446 writel(0, adapter->tgt_mask_reg);
447}
448
449/* Enable MSI-x and INT-x interrupts */
450void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter,
451 struct qlcnic_host_sds_ring *sds_ring)
Sony Chacko7f966452013-01-01 03:20:19 +0000452{
453 writel(0, sds_ring->crb_intr_mask);
Himanshu Madhaniac166702013-02-18 12:06:15 +0000454}
455
456/* Disable MSI-x and INT-x interrupts */
457void qlcnic_83xx_disable_intr(struct qlcnic_adapter *adapter,
458 struct qlcnic_host_sds_ring *sds_ring)
459{
460 writel(1, sds_ring->crb_intr_mask);
461}
462
463inline void qlcnic_83xx_enable_legacy_msix_mbx_intr(struct qlcnic_adapter
464 *adapter)
465{
466 u32 mask;
467
468 /* Mailbox in MSI-x mode and Legacy Interrupt share the same
469 * source register. We could be here before contexts are created
470 * and sds_ring->crb_intr_mask has not been initialized, calculate
471 * BAR offset for Interrupt Source Register
472 */
473 mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
474 writel(0, adapter->ahw->pci_base0 + mask);
475}
476
477inline void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *adapter)
478{
479 u32 mask;
480
481 mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
482 writel(1, adapter->ahw->pci_base0 + mask);
Sony Chacko7f966452013-01-01 03:20:19 +0000483}
484
485static inline void qlcnic_83xx_get_mbx_data(struct qlcnic_adapter *adapter,
486 struct qlcnic_cmd_args *cmd)
487{
488 int i;
489 for (i = 0; i < cmd->rsp.num; i++)
490 cmd->rsp.arg[i] = readl(QLCNIC_MBX_FW(adapter->ahw, i));
491}
492
493irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
494{
495 u32 intr_val;
496 struct qlcnic_hardware_context *ahw = adapter->ahw;
497 int retries = 0;
498
499 intr_val = readl(adapter->tgt_status_reg);
500
501 if (!QLC_83XX_VALID_INTX_BIT31(intr_val))
502 return IRQ_NONE;
503
504 if (QLC_83XX_INTX_FUNC(intr_val) != adapter->ahw->pci_func) {
505 adapter->stats.spurious_intr++;
506 return IRQ_NONE;
507 }
Himanshu Madhaniac166702013-02-18 12:06:15 +0000508 /* The barrier is required to ensure writes to the registers */
509 wmb();
510
Sony Chacko7f966452013-01-01 03:20:19 +0000511 /* clear the interrupt trigger control register */
512 writel(0, adapter->isr_int_vec);
Himanshu Madhaniac166702013-02-18 12:06:15 +0000513 intr_val = readl(adapter->isr_int_vec);
Sony Chacko7f966452013-01-01 03:20:19 +0000514 do {
515 intr_val = readl(adapter->tgt_status_reg);
516 if (QLC_83XX_INTX_FUNC(intr_val) != ahw->pci_func)
517 break;
518 retries++;
519 } while (QLC_83XX_VALID_INTX_BIT30(intr_val) &&
520 (retries < QLC_83XX_LEGACY_INTX_MAX_RETRY));
521
Himanshu Madhaniac166702013-02-18 12:06:15 +0000522 return IRQ_HANDLED;
523}
524
525static void qlcnic_83xx_poll_process_aen(struct qlcnic_adapter *adapter)
526{
527 u32 resp, event;
528 unsigned long flags;
529
530 spin_lock_irqsave(&adapter->ahw->mbx_lock, flags);
531
532 resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL);
533 if (!(resp & QLCNIC_SET_OWNER))
534 goto out;
535
536 event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
537 if (event & QLCNIC_MBX_ASYNC_EVENT)
538 qlcnic_83xx_process_aen(adapter);
539out:
540 qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
541 spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
542}
543
544irqreturn_t qlcnic_83xx_intr(int irq, void *data)
545{
546 struct qlcnic_adapter *adapter = data;
547 struct qlcnic_host_sds_ring *sds_ring;
548 struct qlcnic_hardware_context *ahw = adapter->ahw;
549
550 if (qlcnic_83xx_clear_legacy_intr(adapter) == IRQ_NONE)
Sony Chacko7f966452013-01-01 03:20:19 +0000551 return IRQ_NONE;
Himanshu Madhaniac166702013-02-18 12:06:15 +0000552
553 qlcnic_83xx_poll_process_aen(adapter);
554
555 if (ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
556 ahw->diag_cnt++;
557 qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
558 return IRQ_HANDLED;
Sony Chacko7f966452013-01-01 03:20:19 +0000559 }
560
Himanshu Madhaniac166702013-02-18 12:06:15 +0000561 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
562 qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
563 } else {
564 sds_ring = &adapter->recv_ctx->sds_rings[0];
565 napi_schedule(&sds_ring->napi);
566 }
Sony Chacko7f966452013-01-01 03:20:19 +0000567
568 return IRQ_HANDLED;
569}
570
571irqreturn_t qlcnic_83xx_tmp_intr(int irq, void *data)
572{
573 struct qlcnic_host_sds_ring *sds_ring = data;
574 struct qlcnic_adapter *adapter = sds_ring->adapter;
575
576 if (adapter->flags & QLCNIC_MSIX_ENABLED)
577 goto done;
578
579 if (adapter->nic_ops->clear_legacy_intr(adapter) == IRQ_NONE)
580 return IRQ_NONE;
581
582done:
583 adapter->ahw->diag_cnt++;
584 qlcnic_83xx_enable_intr(adapter, sds_ring);
585
586 return IRQ_HANDLED;
587}
588
589void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
590{
Himanshu Madhaniac166702013-02-18 12:06:15 +0000591 u32 val = 0, num_msix = adapter->ahw->num_msix - 1;
Sony Chacko7f966452013-01-01 03:20:19 +0000592
Himanshu Madhaniac166702013-02-18 12:06:15 +0000593 if (adapter->flags & QLCNIC_MSIX_ENABLED)
594 num_msix = adapter->ahw->num_msix - 1;
595 else
596 num_msix = 0;
Sony Chacko7f966452013-01-01 03:20:19 +0000597
598 QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val);
Himanshu Madhaniac166702013-02-18 12:06:15 +0000599
600 qlcnic_83xx_disable_mbx_intr(adapter);
601
602 msleep(20);
603 synchronize_irq(adapter->msix_entries[num_msix].vector);
604 free_irq(adapter->msix_entries[num_msix].vector, adapter);
Sony Chacko7f966452013-01-01 03:20:19 +0000605}
606
607int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
608{
609 irq_handler_t handler;
610 u32 val;
611 char name[32];
612 int err = 0;
613 unsigned long flags = 0;
614
615 if (!(adapter->flags & QLCNIC_MSI_ENABLED) &&
616 !(adapter->flags & QLCNIC_MSIX_ENABLED))
617 flags |= IRQF_SHARED;
618
619 if (adapter->flags & QLCNIC_MSIX_ENABLED) {
620 handler = qlcnic_83xx_handle_aen;
621 val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector;
622 snprintf(name, (IFNAMSIZ + 4),
Himanshu Madhaniac166702013-02-18 12:06:15 +0000623 "%s[%s]", "qlcnic", "aen");
Sony Chacko7f966452013-01-01 03:20:19 +0000624 err = request_irq(val, handler, flags, name, adapter);
625 if (err) {
626 dev_err(&adapter->pdev->dev,
627 "failed to register MBX interrupt\n");
628 return err;
629 }
Himanshu Madhaniac166702013-02-18 12:06:15 +0000630 } else {
631 handler = qlcnic_83xx_intr;
632 val = adapter->msix_entries[0].vector;
633 err = request_irq(val, handler, flags, "qlcnic", adapter);
634 if (err) {
635 dev_err(&adapter->pdev->dev,
636 "failed to register INTx interrupt\n");
637 return err;
638 }
639 qlcnic_83xx_clear_legacy_intr_mask(adapter);
Sony Chacko7f966452013-01-01 03:20:19 +0000640 }
641
642 /* Enable mailbox interrupt */
643 qlcnic_83xx_enable_mbx_intrpt(adapter);
Sony Chacko7f966452013-01-01 03:20:19 +0000644
645 return err;
646}
647
648void qlcnic_83xx_get_func_no(struct qlcnic_adapter *adapter)
649{
650 u32 val = QLCRDX(adapter->ahw, QLCNIC_INFORMANT);
651 adapter->ahw->pci_func = val & 0xf;
652}
653
654int qlcnic_83xx_cam_lock(struct qlcnic_adapter *adapter)
655{
656 void __iomem *addr;
657 u32 val, limit = 0;
658
659 struct qlcnic_hardware_context *ahw = adapter->ahw;
660
661 addr = ahw->pci_base0 + QLC_83XX_SEM_LOCK_FUNC(ahw->pci_func);
662 do {
663 val = readl(addr);
664 if (val) {
665 /* write the function number to register */
666 QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER,
667 ahw->pci_func);
668 return 0;
669 }
670 usleep_range(1000, 2000);
671 } while (++limit <= QLCNIC_PCIE_SEM_TIMEOUT);
672
673 return -EIO;
674}
675
676void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *adapter)
677{
678 void __iomem *addr;
679 u32 val;
680 struct qlcnic_hardware_context *ahw = adapter->ahw;
681
682 addr = ahw->pci_base0 + QLC_83XX_SEM_UNLOCK_FUNC(ahw->pci_func);
683 val = readl(addr);
684}
685
686void qlcnic_83xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
687 loff_t offset, size_t size)
688{
689 int ret;
690 u32 data;
691
692 if (qlcnic_api_lock(adapter)) {
693 dev_err(&adapter->pdev->dev,
694 "%s: failed to acquire lock. addr offset 0x%x\n",
695 __func__, (u32)offset);
696 return;
697 }
698
699 ret = qlcnic_83xx_rd_reg_indirect(adapter, (u32) offset);
700 qlcnic_api_unlock(adapter);
701
702 if (ret == -EIO) {
703 dev_err(&adapter->pdev->dev,
704 "%s: failed. addr offset 0x%x\n",
705 __func__, (u32)offset);
706 return;
707 }
708 data = ret;
709 memcpy(buf, &data, size);
710}
711
712void qlcnic_83xx_write_crb(struct qlcnic_adapter *adapter, char *buf,
713 loff_t offset, size_t size)
714{
715 u32 data;
716
717 memcpy(&data, buf, size);
718 qlcnic_83xx_wrt_reg_indirect(adapter, (u32) offset, data);
719}
720
721int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
722{
723 int status;
724
725 status = qlcnic_83xx_get_port_config(adapter);
726 if (status) {
727 dev_err(&adapter->pdev->dev,
728 "Get Port Info failed\n");
729 } else {
730 if (QLC_83XX_SFP_10G_CAPABLE(adapter->ahw->port_config))
731 adapter->ahw->port_type = QLCNIC_XGBE;
732 else
733 adapter->ahw->port_type = QLCNIC_GBE;
Sony Chacko629263a2013-01-01 04:11:55 +0000734
Sony Chacko7f966452013-01-01 03:20:19 +0000735 if (QLC_83XX_AUTONEG(adapter->ahw->port_config))
736 adapter->ahw->link_autoneg = AUTONEG_ENABLE;
737 }
738 return status;
739}
740
741void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *adapter)
742{
743 u32 val;
744
745 if (adapter->flags & QLCNIC_MSIX_ENABLED)
746 val = BIT_2 | ((adapter->ahw->num_msix - 1) << 8);
747 else
748 val = BIT_2;
Sony Chacko629263a2013-01-01 04:11:55 +0000749
Sony Chacko7f966452013-01-01 03:20:19 +0000750 QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val);
Himanshu Madhaniac166702013-02-18 12:06:15 +0000751 qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
Sony Chacko7f966452013-01-01 03:20:19 +0000752}
753
754void qlcnic_83xx_check_vf(struct qlcnic_adapter *adapter,
755 const struct pci_device_id *ent)
756{
757 u32 op_mode, priv_level;
758 struct qlcnic_hardware_context *ahw = adapter->ahw;
759
Sony Chacko7f966452013-01-01 03:20:19 +0000760 ahw->fw_hal_version = 2;
Sony Chacko7f966452013-01-01 03:20:19 +0000761 qlcnic_get_func_no(adapter);
762
763 /* Determine function privilege level */
764 op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
765 if (op_mode == QLC_83XX_DEFAULT_OPMODE)
766 priv_level = QLCNIC_MGMT_FUNC;
767 else
768 priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode,
769 ahw->pci_func);
770
771 if (priv_level == QLCNIC_NON_PRIV_FUNC) {
772 ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
773 dev_info(&adapter->pdev->dev,
774 "HAL Version: %d Non Privileged function\n",
775 ahw->fw_hal_version);
776 adapter->nic_ops = &qlcnic_vf_ops;
777 } else {
778 adapter->nic_ops = &qlcnic_83xx_ops;
779 }
780}
781
782static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
783 u32 data[]);
784static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter,
785 u32 data[]);
786
787static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
788 struct qlcnic_cmd_args *cmd)
789{
790 int i;
791
792 dev_info(&adapter->pdev->dev,
793 "Host MBX regs(%d)\n", cmd->req.num);
794 for (i = 0; i < cmd->req.num; i++) {
795 if (i && !(i % 8))
796 pr_info("\n");
797 pr_info("%08x ", cmd->req.arg[i]);
798 }
799 pr_info("\n");
800 dev_info(&adapter->pdev->dev,
801 "FW MBX regs(%d)\n", cmd->rsp.num);
802 for (i = 0; i < cmd->rsp.num; i++) {
803 if (i && !(i % 8))
804 pr_info("\n");
805 pr_info("%08x ", cmd->rsp.arg[i]);
806 }
807 pr_info("\n");
808}
809
Jitendra Kalsaria65ab9992013-02-09 09:29:55 +0000810/* Mailbox response for mac rcode */
811static u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *adapter)
812{
813 u32 fw_data;
814 u8 mac_cmd_rcode;
815
816 fw_data = readl(QLCNIC_MBX_FW(adapter->ahw, 2));
817 mac_cmd_rcode = (u8)fw_data;
818 if (mac_cmd_rcode == QLC_83XX_NO_NIC_RESOURCE ||
819 mac_cmd_rcode == QLC_83XX_MAC_PRESENT ||
820 mac_cmd_rcode == QLC_83XX_MAC_ABSENT)
821 return QLCNIC_RCODE_SUCCESS;
822 return 1;
823}
824
Sony Chacko7f966452013-01-01 03:20:19 +0000825static u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter)
826{
827 u32 data;
828 unsigned long wait_time = 0;
829 struct qlcnic_hardware_context *ahw = adapter->ahw;
830 /* wait for mailbox completion */
831 do {
832 data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
833 if (++wait_time > QLCNIC_MBX_TIMEOUT) {
834 data = QLCNIC_RCODE_TIMEOUT;
835 break;
836 }
837 mdelay(1);
838 } while (!data);
839 return data;
840}
841
842int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter,
843 struct qlcnic_cmd_args *cmd)
844{
845 int i;
846 u16 opcode;
Jitendra Kalsaria65ab9992013-02-09 09:29:55 +0000847 u8 mbx_err_code;
Himanshu Madhaniac166702013-02-18 12:06:15 +0000848 unsigned long flags;
Jitendra Kalsaria483202d2013-02-09 09:29:50 +0000849 u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd;
Sony Chacko7f966452013-01-01 03:20:19 +0000850 struct qlcnic_hardware_context *ahw = adapter->ahw;
851
852 opcode = LSW(cmd->req.arg[0]);
Sony Chacko629263a2013-01-01 04:11:55 +0000853 if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) {
854 dev_info(&adapter->pdev->dev,
855 "Mailbox cmd attempted, 0x%x\n", opcode);
856 dev_info(&adapter->pdev->dev, "Mailbox detached\n");
857 return 0;
858 }
859
Himanshu Madhaniac166702013-02-18 12:06:15 +0000860 spin_lock_irqsave(&adapter->ahw->mbx_lock, flags);
Sony Chacko7f966452013-01-01 03:20:19 +0000861 mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
862
863 if (mbx_val) {
864 QLCDB(adapter, DRV,
865 "Mailbox cmd attempted, 0x%x\n", opcode);
866 QLCDB(adapter, DRV,
867 "Mailbox not available, 0x%x, collect FW dump\n",
868 mbx_val);
869 cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
Himanshu Madhaniac166702013-02-18 12:06:15 +0000870 spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
Sony Chacko7f966452013-01-01 03:20:19 +0000871 return cmd->rsp.arg[0];
872 }
873
874 /* Fill in mailbox registers */
875 mbx_cmd = cmd->req.arg[0];
876 writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
877 for (i = 1; i < cmd->req.num; i++)
878 writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i));
879
880 /* Signal FW about the impending command */
881 QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
882poll:
883 rsp = qlcnic_83xx_mbx_poll(adapter);
Sony Chacko7f966452013-01-01 03:20:19 +0000884 if (rsp != QLCNIC_RCODE_TIMEOUT) {
Jitendra Kalsaria65ab9992013-02-09 09:29:55 +0000885 /* Get the FW response data */
886 fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
Jitendra Kalsaria483202d2013-02-09 09:29:50 +0000887 if (fw_data & QLCNIC_MBX_ASYNC_EVENT) {
888 qlcnic_83xx_process_aen(adapter);
Sony Chacko7f966452013-01-01 03:20:19 +0000889 mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
890 if (mbx_val)
891 goto poll;
Jitendra Kalsaria65ab9992013-02-09 09:29:55 +0000892 }
893 mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
894 rsp_num = QLCNIC_MBX_NUM_REGS(fw_data);
895 opcode = QLCNIC_MBX_RSP(fw_data);
896 qlcnic_83xx_get_mbx_data(adapter, cmd);
897
898 switch (mbx_err_code) {
899 case QLCNIC_MBX_RSP_OK:
900 case QLCNIC_MBX_PORT_RSP_OK:
Sony Chacko7f966452013-01-01 03:20:19 +0000901 rsp = QLCNIC_RCODE_SUCCESS;
Jitendra Kalsaria65ab9992013-02-09 09:29:55 +0000902 break;
903 default:
Sony Chacko7f966452013-01-01 03:20:19 +0000904 if (opcode == QLCNIC_CMD_CONFIG_MAC_VLAN) {
Jitendra Kalsaria65ab9992013-02-09 09:29:55 +0000905 rsp = qlcnic_83xx_mac_rcode(adapter);
906 if (!rsp)
Sony Chacko7f966452013-01-01 03:20:19 +0000907 goto out;
Sony Chacko7f966452013-01-01 03:20:19 +0000908 }
Jitendra Kalsaria65ab9992013-02-09 09:29:55 +0000909 dev_err(&adapter->pdev->dev,
910 "MBX command 0x%x failed with err:0x%x\n",
911 opcode, mbx_err_code);
Sony Chacko7f966452013-01-01 03:20:19 +0000912 rsp = mbx_err_code;
913 qlcnic_dump_mbx(adapter, cmd);
Jitendra Kalsaria65ab9992013-02-09 09:29:55 +0000914 break;
Sony Chacko7f966452013-01-01 03:20:19 +0000915 }
Jitendra Kalsaria65ab9992013-02-09 09:29:55 +0000916 goto out;
Sony Chacko7f966452013-01-01 03:20:19 +0000917 }
Jitendra Kalsaria65ab9992013-02-09 09:29:55 +0000918
919 dev_err(&adapter->pdev->dev, "MBX command 0x%x timed out\n",
920 QLCNIC_MBX_RSP(mbx_cmd));
921 rsp = QLCNIC_RCODE_TIMEOUT;
Sony Chacko7f966452013-01-01 03:20:19 +0000922out:
923 /* clear fw mbx control register */
924 QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
Himanshu Madhaniac166702013-02-18 12:06:15 +0000925 spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
Sony Chacko7f966452013-01-01 03:20:19 +0000926 return rsp;
927}
928
929int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
930 struct qlcnic_adapter *adapter, u32 type)
931{
932 int i, size;
933 u32 temp;
934 const struct qlcnic_mailbox_metadata *mbx_tbl;
935
936 mbx_tbl = qlcnic_83xx_mbx_tbl;
937 size = ARRAY_SIZE(qlcnic_83xx_mbx_tbl);
938 for (i = 0; i < size; i++) {
939 if (type == mbx_tbl[i].cmd) {
940 mbx->req.num = mbx_tbl[i].in_args;
941 mbx->rsp.num = mbx_tbl[i].out_args;
942 mbx->req.arg = kcalloc(mbx->req.num, sizeof(u32),
943 GFP_ATOMIC);
944 if (!mbx->req.arg)
945 return -ENOMEM;
946 mbx->rsp.arg = kcalloc(mbx->rsp.num, sizeof(u32),
947 GFP_ATOMIC);
948 if (!mbx->rsp.arg) {
949 kfree(mbx->req.arg);
950 mbx->req.arg = NULL;
951 return -ENOMEM;
952 }
953 memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num);
954 memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
955 temp = adapter->ahw->fw_hal_version << 29;
956 mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp);
957 break;
958 }
959 }
960 return 0;
961}
962
963void qlcnic_83xx_idc_aen_work(struct work_struct *work)
964{
965 struct qlcnic_adapter *adapter;
966 struct qlcnic_cmd_args cmd;
967 int i, err = 0;
968
969 adapter = container_of(work, struct qlcnic_adapter, idc_aen_work.work);
970 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_IDC_ACK);
971
972 for (i = 1; i < QLC_83XX_MBX_AEN_CNT; i++)
973 cmd.req.arg[i] = adapter->ahw->mbox_aen[i];
974
975 err = qlcnic_issue_cmd(adapter, &cmd);
976 if (err)
977 dev_info(&adapter->pdev->dev,
978 "%s: Mailbox IDC ACK failed.\n", __func__);
979 qlcnic_free_mbx_args(&cmd);
980}
981
982static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter,
983 u32 data[])
984{
985 dev_dbg(&adapter->pdev->dev, "Completion AEN:0x%x.\n",
986 QLCNIC_MBX_RSP(data[0]));
Sony Chacko629263a2013-01-01 04:11:55 +0000987 clear_bit(QLC_83XX_IDC_COMP_AEN, &adapter->ahw->idc.status);
Sony Chacko7f966452013-01-01 03:20:19 +0000988 return;
989}
990
991void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
992{
Jitendra Kalsaria483202d2013-02-09 09:29:50 +0000993 u32 event[QLC_83XX_MBX_AEN_CNT];
Sony Chacko7f966452013-01-01 03:20:19 +0000994 int i;
995 struct qlcnic_hardware_context *ahw = adapter->ahw;
996
Sony Chacko7f966452013-01-01 03:20:19 +0000997 for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
998 event[i] = readl(QLCNIC_MBX_FW(ahw, i));
999
1000 switch (QLCNIC_MBX_RSP(event[0])) {
1001
1002 case QLCNIC_MBX_LINK_EVENT:
1003 qlcnic_83xx_handle_link_aen(adapter, event);
1004 break;
1005 case QLCNIC_MBX_COMP_EVENT:
1006 qlcnic_83xx_handle_idc_comp_aen(adapter, event);
1007 break;
1008 case QLCNIC_MBX_REQUEST_EVENT:
1009 for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
1010 adapter->ahw->mbox_aen[i] = QLCNIC_MBX_RSP(event[i]);
1011 queue_delayed_work(adapter->qlcnic_wq,
1012 &adapter->idc_aen_work, 0);
1013 break;
1014 case QLCNIC_MBX_TIME_EXTEND_EVENT:
1015 break;
1016 case QLCNIC_MBX_SFP_INSERT_EVENT:
1017 dev_info(&adapter->pdev->dev, "SFP+ Insert AEN:0x%x.\n",
1018 QLCNIC_MBX_RSP(event[0]));
1019 break;
1020 case QLCNIC_MBX_SFP_REMOVE_EVENT:
1021 dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n",
1022 QLCNIC_MBX_RSP(event[0]));
1023 break;
1024 default:
1025 dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n",
1026 QLCNIC_MBX_RSP(event[0]));
1027 break;
1028 }
1029
1030 QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
Sony Chacko7f966452013-01-01 03:20:19 +00001031}
1032
1033static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter)
1034{
1035 int index, i, err, sds_mbx_size;
1036 u32 *buf, intrpt_id, intr_mask;
1037 u16 context_id;
1038 u8 num_sds;
1039 struct qlcnic_cmd_args cmd;
1040 struct qlcnic_host_sds_ring *sds;
1041 struct qlcnic_sds_mbx sds_mbx;
1042 struct qlcnic_add_rings_mbx_out *mbx_out;
1043 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1044 struct qlcnic_hardware_context *ahw = adapter->ahw;
1045
1046 sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
1047 context_id = recv_ctx->context_id;
1048 num_sds = (adapter->max_sds_rings - QLCNIC_MAX_RING_SETS);
1049 ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
1050 QLCNIC_CMD_ADD_RCV_RINGS);
1051 cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16);
1052
1053 /* set up status rings, mbx 2-81 */
1054 index = 2;
1055 for (i = 8; i < adapter->max_sds_rings; i++) {
1056 memset(&sds_mbx, 0, sds_mbx_size);
1057 sds = &recv_ctx->sds_rings[i];
1058 sds->consumer = 0;
1059 memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
Shahed Shaikha96227e2013-03-08 09:53:49 +00001060 sds_mbx.phy_addr_low = LSD(sds->phys_addr);
1061 sds_mbx.phy_addr_high = MSD(sds->phys_addr);
Sony Chacko7f966452013-01-01 03:20:19 +00001062 sds_mbx.sds_ring_size = sds->num_desc;
1063
1064 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1065 intrpt_id = ahw->intr_tbl[i].id;
1066 else
1067 intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
1068
1069 if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
1070 sds_mbx.intrpt_id = intrpt_id;
1071 else
1072 sds_mbx.intrpt_id = 0xffff;
1073 sds_mbx.intrpt_val = 0;
1074 buf = &cmd.req.arg[index];
1075 memcpy(buf, &sds_mbx, sds_mbx_size);
1076 index += sds_mbx_size / sizeof(u32);
1077 }
1078
1079 /* send the mailbox command */
1080 err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
1081 if (err) {
1082 dev_err(&adapter->pdev->dev,
1083 "Failed to add rings %d\n", err);
1084 goto out;
1085 }
1086
1087 mbx_out = (struct qlcnic_add_rings_mbx_out *)&cmd.rsp.arg[1];
1088 index = 0;
1089 /* status descriptor ring */
1090 for (i = 8; i < adapter->max_sds_rings; i++) {
1091 sds = &recv_ctx->sds_rings[i];
1092 sds->crb_sts_consumer = ahw->pci_base0 +
1093 mbx_out->host_csmr[index];
1094 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1095 intr_mask = ahw->intr_tbl[i].src;
1096 else
1097 intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
1098
1099 sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
1100 index++;
1101 }
1102out:
1103 qlcnic_free_mbx_args(&cmd);
1104 return err;
1105}
1106
1107int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
1108{
1109 int i, err, index, sds_mbx_size, rds_mbx_size;
1110 u8 num_sds, num_rds;
1111 u32 *buf, intrpt_id, intr_mask, cap = 0;
1112 struct qlcnic_host_sds_ring *sds;
1113 struct qlcnic_host_rds_ring *rds;
1114 struct qlcnic_sds_mbx sds_mbx;
1115 struct qlcnic_rds_mbx rds_mbx;
1116 struct qlcnic_cmd_args cmd;
1117 struct qlcnic_rcv_mbx_out *mbx_out;
1118 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1119 struct qlcnic_hardware_context *ahw = adapter->ahw;
1120 num_rds = adapter->max_rds_rings;
1121
1122 if (adapter->max_sds_rings <= QLCNIC_MAX_RING_SETS)
1123 num_sds = adapter->max_sds_rings;
1124 else
1125 num_sds = QLCNIC_MAX_RING_SETS;
1126
1127 sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
1128 rds_mbx_size = sizeof(struct qlcnic_rds_mbx);
1129 cap = QLCNIC_CAP0_LEGACY_CONTEXT;
1130
1131 if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
1132 cap |= QLC_83XX_FW_CAP_LRO_MSS;
1133
1134 /* set mailbox hdr and capabilities */
1135 qlcnic_alloc_mbx_args(&cmd, adapter,
1136 QLCNIC_CMD_CREATE_RX_CTX);
1137 cmd.req.arg[1] = cap;
1138 cmd.req.arg[5] = 1 | (num_rds << 5) | (num_sds << 8) |
1139 (QLC_83XX_HOST_RDS_MODE_UNIQUE << 16);
1140 /* set up status rings, mbx 8-57/87 */
1141 index = QLC_83XX_HOST_SDS_MBX_IDX;
1142 for (i = 0; i < num_sds; i++) {
1143 memset(&sds_mbx, 0, sds_mbx_size);
1144 sds = &recv_ctx->sds_rings[i];
1145 sds->consumer = 0;
1146 memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
Shahed Shaikha96227e2013-03-08 09:53:49 +00001147 sds_mbx.phy_addr_low = LSD(sds->phys_addr);
1148 sds_mbx.phy_addr_high = MSD(sds->phys_addr);
Sony Chacko7f966452013-01-01 03:20:19 +00001149 sds_mbx.sds_ring_size = sds->num_desc;
1150 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1151 intrpt_id = ahw->intr_tbl[i].id;
1152 else
1153 intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
1154 if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
1155 sds_mbx.intrpt_id = intrpt_id;
1156 else
1157 sds_mbx.intrpt_id = 0xffff;
1158 sds_mbx.intrpt_val = 0;
1159 buf = &cmd.req.arg[index];
1160 memcpy(buf, &sds_mbx, sds_mbx_size);
1161 index += sds_mbx_size / sizeof(u32);
1162 }
1163 /* set up receive rings, mbx 88-111/135 */
1164 index = QLCNIC_HOST_RDS_MBX_IDX;
1165 rds = &recv_ctx->rds_rings[0];
1166 rds->producer = 0;
1167 memset(&rds_mbx, 0, rds_mbx_size);
Shahed Shaikha96227e2013-03-08 09:53:49 +00001168 rds_mbx.phy_addr_reg_low = LSD(rds->phys_addr);
1169 rds_mbx.phy_addr_reg_high = MSD(rds->phys_addr);
Sony Chacko7f966452013-01-01 03:20:19 +00001170 rds_mbx.reg_ring_sz = rds->dma_size;
1171 rds_mbx.reg_ring_len = rds->num_desc;
1172 /* Jumbo ring */
1173 rds = &recv_ctx->rds_rings[1];
1174 rds->producer = 0;
Shahed Shaikha96227e2013-03-08 09:53:49 +00001175 rds_mbx.phy_addr_jmb_low = LSD(rds->phys_addr);
1176 rds_mbx.phy_addr_jmb_high = MSD(rds->phys_addr);
Sony Chacko7f966452013-01-01 03:20:19 +00001177 rds_mbx.jmb_ring_sz = rds->dma_size;
1178 rds_mbx.jmb_ring_len = rds->num_desc;
1179 buf = &cmd.req.arg[index];
1180 memcpy(buf, &rds_mbx, rds_mbx_size);
1181
1182 /* send the mailbox command */
1183 err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
1184 if (err) {
1185 dev_err(&adapter->pdev->dev,
1186 "Failed to create Rx ctx in firmware%d\n", err);
1187 goto out;
1188 }
1189 mbx_out = (struct qlcnic_rcv_mbx_out *)&cmd.rsp.arg[1];
1190 recv_ctx->context_id = mbx_out->ctx_id;
1191 recv_ctx->state = mbx_out->state;
1192 recv_ctx->virt_port = mbx_out->vport_id;
1193 dev_info(&adapter->pdev->dev, "Rx Context[%d] Created, state:0x%x\n",
1194 recv_ctx->context_id, recv_ctx->state);
1195 /* Receive descriptor ring */
1196 /* Standard ring */
1197 rds = &recv_ctx->rds_rings[0];
1198 rds->crb_rcv_producer = ahw->pci_base0 +
1199 mbx_out->host_prod[0].reg_buf;
1200 /* Jumbo ring */
1201 rds = &recv_ctx->rds_rings[1];
1202 rds->crb_rcv_producer = ahw->pci_base0 +
1203 mbx_out->host_prod[0].jmb_buf;
1204 /* status descriptor ring */
1205 for (i = 0; i < num_sds; i++) {
1206 sds = &recv_ctx->sds_rings[i];
1207 sds->crb_sts_consumer = ahw->pci_base0 +
1208 mbx_out->host_csmr[i];
1209 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1210 intr_mask = ahw->intr_tbl[i].src;
1211 else
1212 intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
1213 sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
1214 }
1215
1216 if (adapter->max_sds_rings > QLCNIC_MAX_RING_SETS)
1217 err = qlcnic_83xx_add_rings(adapter);
1218out:
1219 qlcnic_free_mbx_args(&cmd);
1220 return err;
1221}
1222
1223int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
1224 struct qlcnic_host_tx_ring *tx, int ring)
1225{
1226 int err;
1227 u16 msix_id;
1228 u32 *buf, intr_mask;
1229 struct qlcnic_cmd_args cmd;
1230 struct qlcnic_tx_mbx mbx;
1231 struct qlcnic_tx_mbx_out *mbx_out;
1232 struct qlcnic_hardware_context *ahw = adapter->ahw;
1233
1234 /* Reset host resources */
1235 tx->producer = 0;
1236 tx->sw_consumer = 0;
1237 *(tx->hw_consumer) = 0;
1238
1239 memset(&mbx, 0, sizeof(struct qlcnic_tx_mbx));
1240
1241 /* setup mailbox inbox registerss */
Shahed Shaikha96227e2013-03-08 09:53:49 +00001242 mbx.phys_addr_low = LSD(tx->phys_addr);
1243 mbx.phys_addr_high = MSD(tx->phys_addr);
1244 mbx.cnsmr_index_low = LSD(tx->hw_cons_phys_addr);
1245 mbx.cnsmr_index_high = MSD(tx->hw_cons_phys_addr);
Sony Chacko7f966452013-01-01 03:20:19 +00001246 mbx.size = tx->num_desc;
1247 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1248 msix_id = ahw->intr_tbl[adapter->max_sds_rings + ring].id;
1249 else
1250 msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
1251 if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
1252 mbx.intr_id = msix_id;
1253 else
1254 mbx.intr_id = 0xffff;
1255 mbx.src = 0;
1256
1257 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
1258 cmd.req.arg[1] = QLCNIC_CAP0_LEGACY_CONTEXT;
1259 cmd.req.arg[5] = QLCNIC_MAX_TX_QUEUES;
1260 buf = &cmd.req.arg[6];
1261 memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx));
1262 /* send the mailbox command*/
1263 err = qlcnic_issue_cmd(adapter, &cmd);
1264 if (err) {
1265 dev_err(&adapter->pdev->dev,
1266 "Failed to create Tx ctx in firmware 0x%x\n", err);
1267 goto out;
1268 }
1269 mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2];
1270 tx->crb_cmd_producer = ahw->pci_base0 + mbx_out->host_prod;
1271 tx->ctx_id = mbx_out->ctx_id;
1272 if (adapter->flags & QLCNIC_MSIX_ENABLED) {
1273 intr_mask = ahw->intr_tbl[adapter->max_sds_rings + ring].src;
1274 tx->crb_intr_mask = ahw->pci_base0 + intr_mask;
1275 }
1276 dev_info(&adapter->pdev->dev, "Tx Context[0x%x] Created, state:0x%x\n",
1277 tx->ctx_id, mbx_out->state);
1278out:
1279 qlcnic_free_mbx_args(&cmd);
1280 return err;
1281}
1282
Jitendra Kalsariaba4468db2013-02-09 09:29:51 +00001283static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test)
1284{
1285 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1286 struct qlcnic_host_sds_ring *sds_ring;
1287 struct qlcnic_host_rds_ring *rds_ring;
1288 u8 ring;
1289 int ret;
1290
1291 netif_device_detach(netdev);
1292
1293 if (netif_running(netdev))
1294 __qlcnic_down(adapter, netdev);
1295
1296 qlcnic_detach(adapter);
1297
1298 adapter->max_sds_rings = 1;
1299 adapter->ahw->diag_test = test;
1300 adapter->ahw->linkup = 0;
1301
1302 ret = qlcnic_attach(adapter);
1303 if (ret) {
1304 netif_device_attach(netdev);
1305 return ret;
1306 }
1307
1308 ret = qlcnic_fw_create_ctx(adapter);
1309 if (ret) {
1310 qlcnic_detach(adapter);
1311 netif_device_attach(netdev);
1312 return ret;
1313 }
1314
1315 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
1316 rds_ring = &adapter->recv_ctx->rds_rings[ring];
1317 qlcnic_post_rx_buffers(adapter, rds_ring, ring);
1318 }
1319
1320 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
1321 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
1322 sds_ring = &adapter->recv_ctx->sds_rings[ring];
1323 qlcnic_83xx_enable_intr(adapter, sds_ring);
1324 }
1325 }
1326
1327 if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
1328 /* disable and free mailbox interrupt */
1329 qlcnic_83xx_free_mbx_intr(adapter);
1330 adapter->ahw->loopback_state = 0;
1331 adapter->ahw->hw_ops->setup_link_event(adapter, 1);
1332 }
1333
1334 set_bit(__QLCNIC_DEV_UP, &adapter->state);
1335 return 0;
1336}
1337
1338static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
1339 int max_sds_rings)
1340{
1341 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1342 struct qlcnic_host_sds_ring *sds_ring;
1343 int ring, err;
1344
1345 clear_bit(__QLCNIC_DEV_UP, &adapter->state);
1346 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
1347 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
1348 sds_ring = &adapter->recv_ctx->sds_rings[ring];
Himanshu Madhaniac166702013-02-18 12:06:15 +00001349 qlcnic_83xx_disable_intr(adapter, sds_ring);
Jitendra Kalsariaba4468db2013-02-09 09:29:51 +00001350 }
1351 }
1352
1353 qlcnic_fw_destroy_ctx(adapter);
1354 qlcnic_detach(adapter);
1355
1356 if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
1357 err = qlcnic_83xx_setup_mbx_intr(adapter);
1358 if (err) {
1359 dev_err(&adapter->pdev->dev,
1360 "%s: failed to setup mbx interrupt\n",
1361 __func__);
1362 goto out;
1363 }
1364 }
1365 adapter->ahw->diag_test = 0;
1366 adapter->max_sds_rings = max_sds_rings;
1367
1368 if (qlcnic_attach(adapter))
1369 goto out;
1370
1371 if (netif_running(netdev))
1372 __qlcnic_up(adapter, netdev);
1373out:
1374 netif_device_attach(netdev);
1375}
1376
Sony Chacko319ecf12013-01-01 03:20:22 +00001377int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state,
1378 u32 beacon)
1379{
1380 struct qlcnic_cmd_args cmd;
1381 u32 mbx_in;
1382 int i, status = 0;
1383
1384 if (state) {
1385 /* Get LED configuration */
1386 qlcnic_alloc_mbx_args(&cmd, adapter,
1387 QLCNIC_CMD_GET_LED_CONFIG);
1388 status = qlcnic_issue_cmd(adapter, &cmd);
1389 if (status) {
1390 dev_err(&adapter->pdev->dev,
1391 "Get led config failed.\n");
1392 goto mbx_err;
1393 } else {
1394 for (i = 0; i < 4; i++)
1395 adapter->ahw->mbox_reg[i] = cmd.rsp.arg[i+1];
1396 }
1397 qlcnic_free_mbx_args(&cmd);
1398 /* Set LED Configuration */
1399 mbx_in = (LSW(QLC_83XX_LED_CONFIG) << 16) |
1400 LSW(QLC_83XX_LED_CONFIG);
1401 qlcnic_alloc_mbx_args(&cmd, adapter,
1402 QLCNIC_CMD_SET_LED_CONFIG);
1403 cmd.req.arg[1] = mbx_in;
1404 cmd.req.arg[2] = mbx_in;
1405 cmd.req.arg[3] = mbx_in;
1406 if (beacon)
1407 cmd.req.arg[4] = QLC_83XX_ENABLE_BEACON;
1408 status = qlcnic_issue_cmd(adapter, &cmd);
1409 if (status) {
1410 dev_err(&adapter->pdev->dev,
1411 "Set led config failed.\n");
1412 }
1413mbx_err:
1414 qlcnic_free_mbx_args(&cmd);
1415 return status;
1416
1417 } else {
1418 /* Restoring default LED configuration */
1419 qlcnic_alloc_mbx_args(&cmd, adapter,
1420 QLCNIC_CMD_SET_LED_CONFIG);
1421 cmd.req.arg[1] = adapter->ahw->mbox_reg[0];
1422 cmd.req.arg[2] = adapter->ahw->mbox_reg[1];
1423 cmd.req.arg[3] = adapter->ahw->mbox_reg[2];
1424 if (beacon)
1425 cmd.req.arg[4] = adapter->ahw->mbox_reg[3];
1426 status = qlcnic_issue_cmd(adapter, &cmd);
1427 if (status)
1428 dev_err(&adapter->pdev->dev,
1429 "Restoring led config failed.\n");
1430 qlcnic_free_mbx_args(&cmd);
1431 return status;
1432 }
1433}
1434
Himanshu Madhanid16951d2013-03-08 09:53:50 +00001435int qlcnic_83xx_set_led(struct net_device *netdev,
1436 enum ethtool_phys_id_state state)
1437{
1438 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1439 int err = -EIO, active = 1;
1440
1441 if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
1442 netdev_warn(netdev,
1443 "LED test is not supported in non-privileged mode\n");
1444 return -EOPNOTSUPP;
1445 }
1446
1447 switch (state) {
1448 case ETHTOOL_ID_ACTIVE:
1449 if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
1450 return -EBUSY;
1451
1452 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
1453 break;
1454
1455 err = qlcnic_83xx_config_led(adapter, active, 0);
1456 if (err)
1457 netdev_err(netdev, "Failed to set LED blink state\n");
1458 break;
1459 case ETHTOOL_ID_INACTIVE:
1460 active = 0;
1461
1462 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
1463 break;
1464
1465 err = qlcnic_83xx_config_led(adapter, active, 0);
1466 if (err)
1467 netdev_err(netdev, "Failed to reset LED blink state\n");
1468 break;
1469
1470 default:
1471 return -EINVAL;
1472 }
1473
1474 if (!active || err)
1475 clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
1476
1477 return err;
1478}
1479
Sony Chacko7f966452013-01-01 03:20:19 +00001480void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter,
1481 int enable)
1482{
1483 struct qlcnic_cmd_args cmd;
1484 int status;
1485
1486 if (enable) {
1487 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INIT_NIC_FUNC);
Himanshu Madhanid5fcff02013-02-09 09:29:48 +00001488 cmd.req.arg[1] = BIT_0 | BIT_31;
Sony Chacko7f966452013-01-01 03:20:19 +00001489 } else {
1490 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_STOP_NIC_FUNC);
Himanshu Madhanid5fcff02013-02-09 09:29:48 +00001491 cmd.req.arg[1] = BIT_0 | BIT_31;
Sony Chacko7f966452013-01-01 03:20:19 +00001492 }
1493 status = qlcnic_issue_cmd(adapter, &cmd);
1494 if (status)
1495 dev_err(&adapter->pdev->dev,
1496 "Failed to %s in NIC IDC function event.\n",
1497 (enable ? "register" : "unregister"));
1498
1499 qlcnic_free_mbx_args(&cmd);
1500}
1501
1502int qlcnic_83xx_set_port_config(struct qlcnic_adapter *adapter)
1503{
1504 struct qlcnic_cmd_args cmd;
1505 int err;
1506
1507 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORT_CONFIG);
1508 cmd.req.arg[1] = adapter->ahw->port_config;
1509 err = qlcnic_issue_cmd(adapter, &cmd);
1510 if (err)
1511 dev_info(&adapter->pdev->dev, "Set Port Config failed.\n");
1512 qlcnic_free_mbx_args(&cmd);
1513 return err;
1514}
1515
1516int qlcnic_83xx_get_port_config(struct qlcnic_adapter *adapter)
1517{
1518 struct qlcnic_cmd_args cmd;
1519 int err;
1520
1521 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PORT_CONFIG);
1522 err = qlcnic_issue_cmd(adapter, &cmd);
1523 if (err)
1524 dev_info(&adapter->pdev->dev, "Get Port config failed\n");
1525 else
1526 adapter->ahw->port_config = cmd.rsp.arg[1];
1527 qlcnic_free_mbx_args(&cmd);
1528 return err;
1529}
1530
1531int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *adapter, int enable)
1532{
1533 int err;
1534 u32 temp;
1535 struct qlcnic_cmd_args cmd;
1536
1537 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_EVENT);
1538 temp = adapter->recv_ctx->context_id << 16;
1539 cmd.req.arg[1] = (enable ? 1 : 0) | BIT_8 | temp;
1540 err = qlcnic_issue_cmd(adapter, &cmd);
1541 if (err)
1542 dev_info(&adapter->pdev->dev,
1543 "Setup linkevent mailbox failed\n");
1544 qlcnic_free_mbx_args(&cmd);
1545 return err;
1546}
1547
1548int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
1549{
1550 int err;
1551 u32 temp;
1552 struct qlcnic_cmd_args cmd;
1553
1554 if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
1555 return -EIO;
1556
1557 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_MAC_RX_MODE);
1558 temp = adapter->recv_ctx->context_id << 16;
1559 cmd.req.arg[1] = (mode ? 1 : 0) | temp;
1560 err = qlcnic_issue_cmd(adapter, &cmd);
1561 if (err)
1562 dev_info(&adapter->pdev->dev,
1563 "Promiscous mode config failed\n");
1564 qlcnic_free_mbx_args(&cmd);
1565
1566 return err;
1567}
1568
Jitendra Kalsariaba4468db2013-02-09 09:29:51 +00001569int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
1570{
1571 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1572 struct qlcnic_hardware_context *ahw = adapter->ahw;
1573 int ret = 0, loop = 0, max_sds_rings = adapter->max_sds_rings;
1574
1575 QLCDB(adapter, DRV, "%s loopback test in progress\n",
1576 mode == QLCNIC_ILB_MODE ? "internal" : "external");
1577 if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
1578 dev_warn(&adapter->pdev->dev,
1579 "Loopback test not supported for non privilege function\n");
1580 return ret;
1581 }
1582
1583 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
1584 return -EBUSY;
1585
1586 ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
1587 if (ret)
1588 goto fail_diag_alloc;
1589
1590 ret = qlcnic_83xx_set_lb_mode(adapter, mode);
1591 if (ret)
1592 goto free_diag_res;
1593
1594 /* Poll for link up event before running traffic */
1595 do {
1596 msleep(500);
1597 qlcnic_83xx_process_aen(adapter);
1598 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
1599 dev_info(&adapter->pdev->dev,
1600 "Firmware didn't sent link up event to loopback request\n");
1601 ret = -QLCNIC_FW_NOT_RESPOND;
1602 qlcnic_83xx_clear_lb_mode(adapter, mode);
1603 goto free_diag_res;
1604 }
1605 } while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
1606
1607 ret = qlcnic_do_lb_test(adapter, mode);
1608
1609 qlcnic_83xx_clear_lb_mode(adapter, mode);
1610
1611free_diag_res:
1612 qlcnic_83xx_diag_free_res(netdev, max_sds_rings);
1613
1614fail_diag_alloc:
1615 adapter->max_sds_rings = max_sds_rings;
1616 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1617 return ret;
1618}
1619
Sony Chacko7f966452013-01-01 03:20:19 +00001620int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
1621{
1622 struct qlcnic_hardware_context *ahw = adapter->ahw;
Sony Chacko629263a2013-01-01 04:11:55 +00001623 int status = 0, loop = 0;
Sony Chacko7f966452013-01-01 03:20:19 +00001624 u32 config;
1625
1626 status = qlcnic_83xx_get_port_config(adapter);
1627 if (status)
1628 return status;
1629
1630 config = ahw->port_config;
Sony Chacko629263a2013-01-01 04:11:55 +00001631 set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
Sony Chacko7f966452013-01-01 03:20:19 +00001632
1633 if (mode == QLCNIC_ILB_MODE)
1634 ahw->port_config |= QLC_83XX_CFG_LOOPBACK_HSS;
1635 if (mode == QLCNIC_ELB_MODE)
1636 ahw->port_config |= QLC_83XX_CFG_LOOPBACK_EXT;
1637
1638 status = qlcnic_83xx_set_port_config(adapter);
1639 if (status) {
1640 dev_err(&adapter->pdev->dev,
1641 "Failed to Set Loopback Mode = 0x%x.\n",
1642 ahw->port_config);
1643 ahw->port_config = config;
Sony Chacko629263a2013-01-01 04:11:55 +00001644 clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
Sony Chacko7f966452013-01-01 03:20:19 +00001645 return status;
1646 }
1647
Jitendra Kalsaria9a05f922013-02-09 09:29:53 +00001648 /* Wait for Link and IDC Completion AEN */
Sony Chacko629263a2013-01-01 04:11:55 +00001649 do {
1650 msleep(300);
Jitendra Kalsaria9a05f922013-02-09 09:29:53 +00001651 qlcnic_83xx_process_aen(adapter);
Sony Chacko629263a2013-01-01 04:11:55 +00001652 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
1653 dev_err(&adapter->pdev->dev,
1654 "FW did not generate IDC completion AEN\n");
1655 clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
Jitendra Kalsaria9a05f922013-02-09 09:29:53 +00001656 qlcnic_83xx_clear_lb_mode(adapter, mode);
Sony Chacko629263a2013-01-01 04:11:55 +00001657 return -EIO;
1658 }
1659 } while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status));
1660
Sony Chacko7f966452013-01-01 03:20:19 +00001661 qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0,
1662 QLCNIC_MAC_ADD);
1663 return status;
1664}
1665
1666int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
1667{
1668 struct qlcnic_hardware_context *ahw = adapter->ahw;
Sony Chacko629263a2013-01-01 04:11:55 +00001669 int status = 0, loop = 0;
Sony Chacko7f966452013-01-01 03:20:19 +00001670 u32 config = ahw->port_config;
1671
Sony Chacko629263a2013-01-01 04:11:55 +00001672 set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
Sony Chacko7f966452013-01-01 03:20:19 +00001673 if (mode == QLCNIC_ILB_MODE)
1674 ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_HSS;
1675 if (mode == QLCNIC_ELB_MODE)
1676 ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_EXT;
1677
1678 status = qlcnic_83xx_set_port_config(adapter);
1679 if (status) {
1680 dev_err(&adapter->pdev->dev,
1681 "Failed to Clear Loopback Mode = 0x%x.\n",
1682 ahw->port_config);
1683 ahw->port_config = config;
Sony Chacko629263a2013-01-01 04:11:55 +00001684 clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
Sony Chacko7f966452013-01-01 03:20:19 +00001685 return status;
1686 }
1687
Jitendra Kalsaria9a05f922013-02-09 09:29:53 +00001688 /* Wait for Link and IDC Completion AEN */
Sony Chacko629263a2013-01-01 04:11:55 +00001689 do {
1690 msleep(300);
Jitendra Kalsaria9a05f922013-02-09 09:29:53 +00001691 qlcnic_83xx_process_aen(adapter);
Sony Chacko629263a2013-01-01 04:11:55 +00001692 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
1693 dev_err(&adapter->pdev->dev,
1694 "Firmware didn't sent IDC completion AEN\n");
1695 clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
1696 return -EIO;
1697 }
1698 } while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status));
1699
Sony Chacko7f966452013-01-01 03:20:19 +00001700 qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0,
1701 QLCNIC_MAC_DEL);
1702 return status;
1703}
1704
1705void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip,
1706 int mode)
1707{
1708 int err;
Manish chopra283c1c62013-01-30 12:47:15 +00001709 u32 temp, temp_ip;
Sony Chacko7f966452013-01-01 03:20:19 +00001710 struct qlcnic_cmd_args cmd;
1711
1712 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_IP_ADDR);
1713 if (mode == QLCNIC_IP_UP) {
1714 temp = adapter->recv_ctx->context_id << 16;
1715 cmd.req.arg[1] = 1 | temp;
1716 } else {
1717 temp = adapter->recv_ctx->context_id << 16;
1718 cmd.req.arg[1] = 2 | temp;
1719 }
Sony Chacko7f966452013-01-01 03:20:19 +00001720
Manish chopra283c1c62013-01-30 12:47:15 +00001721 /*
1722 * Adapter needs IP address in network byte order.
1723 * But hardware mailbox registers go through writel(), hence IP address
1724 * gets swapped on big endian architecture.
1725 * To negate swapping of writel() on big endian architecture
1726 * use swab32(value).
1727 */
1728
1729 temp_ip = swab32(ntohl(ip));
1730 memcpy(&cmd.req.arg[2], &temp_ip, sizeof(u32));
Sony Chacko7f966452013-01-01 03:20:19 +00001731 err = qlcnic_issue_cmd(adapter, &cmd);
1732 if (err != QLCNIC_RCODE_SUCCESS)
1733 dev_err(&adapter->netdev->dev,
1734 "could not notify %s IP 0x%x request\n",
1735 (mode == QLCNIC_IP_UP) ? "Add" : "Remove", ip);
1736 qlcnic_free_mbx_args(&cmd);
1737}
1738
1739int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *adapter, int mode)
1740{
1741 int err;
1742 u32 temp, arg1;
1743 struct qlcnic_cmd_args cmd;
Manish chopra283c1c62013-01-30 12:47:15 +00001744 int lro_bit_mask;
1745
1746 lro_bit_mask = (mode ? (BIT_0 | BIT_1 | BIT_2 | BIT_3) : 0);
Sony Chacko7f966452013-01-01 03:20:19 +00001747
1748 if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
1749 return 0;
1750
1751 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_HW_LRO);
1752 temp = adapter->recv_ctx->context_id << 16;
Manish chopra283c1c62013-01-30 12:47:15 +00001753 arg1 = lro_bit_mask | temp;
Sony Chacko7f966452013-01-01 03:20:19 +00001754 cmd.req.arg[1] = arg1;
1755
1756 err = qlcnic_issue_cmd(adapter, &cmd);
1757 if (err)
1758 dev_info(&adapter->pdev->dev, "LRO config failed\n");
1759 qlcnic_free_mbx_args(&cmd);
1760
1761 return err;
1762}
1763
1764int qlcnic_83xx_config_rss(struct qlcnic_adapter *adapter, int enable)
1765{
1766 int err;
1767 u32 word;
1768 struct qlcnic_cmd_args cmd;
1769 const u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
1770 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
1771 0x255b0ec26d5a56daULL };
1772
1773 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_RSS);
1774
1775 /*
1776 * RSS request:
1777 * bits 3-0: Rsvd
1778 * 5-4: hash_type_ipv4
1779 * 7-6: hash_type_ipv6
1780 * 8: enable
1781 * 9: use indirection table
1782 * 16-31: indirection table mask
1783 */
1784 word = ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) |
1785 ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) |
1786 ((u32)(enable & 0x1) << 8) |
1787 ((0x7ULL) << 16);
1788 cmd.req.arg[1] = (adapter->recv_ctx->context_id);
1789 cmd.req.arg[2] = word;
1790 memcpy(&cmd.req.arg[4], key, sizeof(key));
1791
1792 err = qlcnic_issue_cmd(adapter, &cmd);
1793
1794 if (err)
1795 dev_info(&adapter->pdev->dev, "RSS config failed\n");
1796 qlcnic_free_mbx_args(&cmd);
1797
1798 return err;
1799
1800}
1801
1802int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
1803 __le16 vlan_id, u8 op)
1804{
1805 int err;
1806 u32 *buf;
1807 struct qlcnic_cmd_args cmd;
1808 struct qlcnic_macvlan_mbx mv;
1809
1810 if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
1811 return -EIO;
1812
1813 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
1814 if (err)
1815 return err;
1816 cmd.req.arg[1] = op | (1 << 8) |
1817 (adapter->recv_ctx->context_id << 16);
1818
1819 mv.vlan = le16_to_cpu(vlan_id);
Shahed Shaikha96227e2013-03-08 09:53:49 +00001820 mv.mac_addr0 = addr[0];
1821 mv.mac_addr1 = addr[1];
1822 mv.mac_addr2 = addr[2];
1823 mv.mac_addr3 = addr[3];
1824 mv.mac_addr4 = addr[4];
1825 mv.mac_addr5 = addr[5];
Sony Chacko7f966452013-01-01 03:20:19 +00001826 buf = &cmd.req.arg[2];
1827 memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
1828 err = qlcnic_issue_cmd(adapter, &cmd);
1829 if (err)
1830 dev_err(&adapter->pdev->dev,
1831 "MAC-VLAN %s to CAM failed, err=%d.\n",
1832 ((op == 1) ? "add " : "delete "), err);
1833 qlcnic_free_mbx_args(&cmd);
1834 return err;
1835}
1836
1837void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *adapter, u64 *addr,
1838 __le16 vlan_id)
1839{
1840 u8 mac[ETH_ALEN];
1841 memcpy(&mac, addr, ETH_ALEN);
1842 qlcnic_83xx_sre_macaddr_change(adapter, mac, vlan_id, QLCNIC_MAC_ADD);
1843}
1844
1845void qlcnic_83xx_configure_mac(struct qlcnic_adapter *adapter, u8 *mac,
1846 u8 type, struct qlcnic_cmd_args *cmd)
1847{
1848 switch (type) {
1849 case QLCNIC_SET_STATION_MAC:
1850 case QLCNIC_SET_FAC_DEF_MAC:
1851 memcpy(&cmd->req.arg[2], mac, sizeof(u32));
1852 memcpy(&cmd->req.arg[3], &mac[4], sizeof(u16));
1853 break;
1854 }
1855 cmd->req.arg[1] = type;
1856}
1857
1858int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
1859{
1860 int err, i;
1861 struct qlcnic_cmd_args cmd;
1862 u32 mac_low, mac_high;
1863
1864 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS);
1865 qlcnic_83xx_configure_mac(adapter, mac, QLCNIC_GET_CURRENT_MAC, &cmd);
1866 err = qlcnic_issue_cmd(adapter, &cmd);
1867
1868 if (err == QLCNIC_RCODE_SUCCESS) {
1869 mac_low = cmd.rsp.arg[1];
1870 mac_high = cmd.rsp.arg[2];
1871
1872 for (i = 0; i < 2; i++)
1873 mac[i] = (u8) (mac_high >> ((1 - i) * 8));
1874 for (i = 2; i < 6; i++)
1875 mac[i] = (u8) (mac_low >> ((5 - i) * 8));
1876 } else {
1877 dev_err(&adapter->pdev->dev, "Failed to get mac address%d\n",
1878 err);
1879 err = -EIO;
1880 }
1881 qlcnic_free_mbx_args(&cmd);
1882 return err;
1883}
1884
1885void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter)
1886{
1887 int err;
1888 u32 temp;
1889 struct qlcnic_cmd_args cmd;
1890 struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
1891
1892 if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
1893 return;
1894
1895 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
1896 cmd.req.arg[1] = 1 | (adapter->recv_ctx->context_id << 16);
1897 cmd.req.arg[3] = coal->flag;
1898 temp = coal->rx_time_us << 16;
1899 cmd.req.arg[2] = coal->rx_packets | temp;
1900 err = qlcnic_issue_cmd(adapter, &cmd);
1901 if (err != QLCNIC_RCODE_SUCCESS)
1902 dev_info(&adapter->pdev->dev,
1903 "Failed to send interrupt coalescence parameters\n");
1904 qlcnic_free_mbx_args(&cmd);
1905}
1906
1907static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
1908 u32 data[])
1909{
1910 u8 link_status, duplex;
1911 /* link speed */
1912 link_status = LSB(data[3]) & 1;
1913 adapter->ahw->link_speed = MSW(data[2]);
1914 adapter->ahw->link_autoneg = MSB(MSW(data[3]));
1915 adapter->ahw->module_type = MSB(LSW(data[3]));
1916 duplex = LSB(MSW(data[3]));
1917 if (duplex)
1918 adapter->ahw->link_duplex = DUPLEX_FULL;
1919 else
1920 adapter->ahw->link_duplex = DUPLEX_HALF;
1921 adapter->ahw->has_link_events = 1;
1922 qlcnic_advert_link_change(adapter, link_status);
1923}
1924
1925irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
1926{
1927 struct qlcnic_adapter *adapter = data;
Jitendra Kalsaria483202d2013-02-09 09:29:50 +00001928 unsigned long flags;
1929 u32 mask, resp, event;
1930
1931 spin_lock_irqsave(&adapter->ahw->mbx_lock, flags);
1932 resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL);
1933 if (!(resp & QLCNIC_SET_OWNER))
1934 goto out;
Himanshu Madhaniac166702013-02-18 12:06:15 +00001935
Jitendra Kalsaria483202d2013-02-09 09:29:50 +00001936 event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
1937 if (event & QLCNIC_MBX_ASYNC_EVENT)
1938 qlcnic_83xx_process_aen(adapter);
1939out:
1940 mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
1941 writel(0, adapter->ahw->pci_base0 + mask);
1942 spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
1943
Sony Chacko7f966452013-01-01 03:20:19 +00001944 return IRQ_HANDLED;
1945}
1946
1947int qlcnic_enable_eswitch(struct qlcnic_adapter *adapter, u8 port, u8 enable)
1948{
1949 int err = -EIO;
1950 struct qlcnic_cmd_args cmd;
1951
1952 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
1953 dev_err(&adapter->pdev->dev,
1954 "%s: Error, invoked by non management func\n",
1955 __func__);
1956 return err;
1957 }
1958
1959 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH);
1960 cmd.req.arg[1] = (port & 0xf) | BIT_4;
1961 err = qlcnic_issue_cmd(adapter, &cmd);
1962
1963 if (err != QLCNIC_RCODE_SUCCESS) {
1964 dev_err(&adapter->pdev->dev, "Failed to enable eswitch%d\n",
1965 err);
1966 err = -EIO;
1967 }
1968 qlcnic_free_mbx_args(&cmd);
1969
1970 return err;
1971
1972}
1973
1974int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *adapter,
1975 struct qlcnic_info *nic)
1976{
1977 int i, err = -EIO;
1978 struct qlcnic_cmd_args cmd;
1979
1980 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
1981 dev_err(&adapter->pdev->dev,
1982 "%s: Error, invoked by non management func\n",
1983 __func__);
1984 return err;
1985 }
1986
1987 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
1988 cmd.req.arg[1] = (nic->pci_func << 16);
1989 cmd.req.arg[2] = 0x1 << 16;
1990 cmd.req.arg[3] = nic->phys_port | (nic->switch_mode << 16);
1991 cmd.req.arg[4] = nic->capabilities;
1992 cmd.req.arg[5] = (nic->max_mac_filters & 0xFF) | ((nic->max_mtu) << 16);
1993 cmd.req.arg[6] = (nic->max_tx_ques) | ((nic->max_rx_ques) << 16);
1994 cmd.req.arg[7] = (nic->min_tx_bw) | ((nic->max_tx_bw) << 16);
1995 for (i = 8; i < 32; i++)
1996 cmd.req.arg[i] = 0;
1997
1998 err = qlcnic_issue_cmd(adapter, &cmd);
1999
2000 if (err != QLCNIC_RCODE_SUCCESS) {
2001 dev_err(&adapter->pdev->dev, "Failed to set nic info%d\n",
2002 err);
2003 err = -EIO;
2004 }
2005
2006 qlcnic_free_mbx_args(&cmd);
2007
2008 return err;
2009}
2010
2011int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
2012 struct qlcnic_info *npar_info, u8 func_id)
2013{
2014 int err;
2015 u32 temp;
2016 u8 op = 0;
2017 struct qlcnic_cmd_args cmd;
2018
2019 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
2020 if (func_id != adapter->ahw->pci_func) {
2021 temp = func_id << 16;
2022 cmd.req.arg[1] = op | BIT_31 | temp;
2023 } else {
2024 cmd.req.arg[1] = adapter->ahw->pci_func << 16;
2025 }
2026 err = qlcnic_issue_cmd(adapter, &cmd);
2027 if (err) {
2028 dev_info(&adapter->pdev->dev,
2029 "Failed to get nic info %d\n", err);
2030 goto out;
2031 }
2032
2033 npar_info->op_type = cmd.rsp.arg[1];
2034 npar_info->pci_func = cmd.rsp.arg[2] & 0xFFFF;
2035 npar_info->op_mode = (cmd.rsp.arg[2] & 0xFFFF0000) >> 16;
2036 npar_info->phys_port = cmd.rsp.arg[3] & 0xFFFF;
2037 npar_info->switch_mode = (cmd.rsp.arg[3] & 0xFFFF0000) >> 16;
2038 npar_info->capabilities = cmd.rsp.arg[4];
2039 npar_info->max_mac_filters = cmd.rsp.arg[5] & 0xFF;
2040 npar_info->max_mtu = (cmd.rsp.arg[5] & 0xFFFF0000) >> 16;
2041 npar_info->max_tx_ques = cmd.rsp.arg[6] & 0xFFFF;
2042 npar_info->max_rx_ques = (cmd.rsp.arg[6] & 0xFFFF0000) >> 16;
2043 npar_info->min_tx_bw = cmd.rsp.arg[7] & 0xFFFF;
2044 npar_info->max_tx_bw = (cmd.rsp.arg[7] & 0xFFFF0000) >> 16;
2045 if (cmd.rsp.arg[8] & 0x1)
2046 npar_info->max_bw_reg_offset = (cmd.rsp.arg[8] & 0x7FFE) >> 1;
2047 if (cmd.rsp.arg[8] & 0x10000) {
2048 temp = (cmd.rsp.arg[8] & 0x7FFE0000) >> 17;
2049 npar_info->max_linkspeed_reg_offset = temp;
2050 }
2051
2052out:
2053 qlcnic_free_mbx_args(&cmd);
2054 return err;
2055}
2056
2057int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
2058 struct qlcnic_pci_info *pci_info)
2059{
2060 int i, err = 0, j = 0;
2061 u32 temp;
2062 struct qlcnic_cmd_args cmd;
2063
2064 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
2065 err = qlcnic_issue_cmd(adapter, &cmd);
2066
2067 adapter->ahw->act_pci_func = 0;
2068 if (err == QLCNIC_RCODE_SUCCESS) {
2069 pci_info->func_count = cmd.rsp.arg[1] & 0xFF;
2070 dev_info(&adapter->pdev->dev,
2071 "%s: total functions = %d\n",
2072 __func__, pci_info->func_count);
2073 for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) {
2074 pci_info->id = cmd.rsp.arg[i] & 0xFFFF;
2075 pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
2076 i++;
2077 pci_info->type = cmd.rsp.arg[i] & 0xFFFF;
2078 if (pci_info->type == QLCNIC_TYPE_NIC)
2079 adapter->ahw->act_pci_func++;
2080 temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
2081 pci_info->default_port = temp;
2082 i++;
2083 pci_info->tx_min_bw = cmd.rsp.arg[i] & 0xFFFF;
2084 temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
2085 pci_info->tx_max_bw = temp;
2086 i = i + 2;
2087 memcpy(pci_info->mac, &cmd.rsp.arg[i], ETH_ALEN - 2);
2088 i++;
2089 memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2);
2090 i = i + 3;
2091
2092 dev_info(&adapter->pdev->dev, "%s:\n"
2093 "\tid = %d active = %d type = %d\n"
2094 "\tport = %d min bw = %d max bw = %d\n"
2095 "\tmac_addr = %pM\n", __func__,
2096 pci_info->id, pci_info->active, pci_info->type,
2097 pci_info->default_port, pci_info->tx_min_bw,
2098 pci_info->tx_max_bw, pci_info->mac);
2099 }
2100 } else {
2101 dev_err(&adapter->pdev->dev, "Failed to get PCI Info%d\n",
2102 err);
2103 err = -EIO;
2104 }
2105
2106 qlcnic_free_mbx_args(&cmd);
2107
2108 return err;
2109}
2110
2111int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type)
2112{
2113 int i, index, err;
2114 bool type;
2115 u8 max_ints;
2116 u32 val, temp;
2117 struct qlcnic_cmd_args cmd;
2118
Sucheta Chakraborty7dd90cf2013-02-18 12:06:14 +00002119 max_ints = adapter->ahw->num_msix - 1;
Sony Chacko7f966452013-01-01 03:20:19 +00002120 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT);
2121 cmd.req.arg[1] = max_ints;
2122 for (i = 0, index = 2; i < max_ints; i++) {
2123 type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL;
2124 val = type | (adapter->ahw->intr_tbl[i].type << 4);
2125 if (adapter->ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX)
2126 val |= (adapter->ahw->intr_tbl[i].id << 16);
2127 cmd.req.arg[index++] = val;
2128 }
2129 err = qlcnic_issue_cmd(adapter, &cmd);
2130 if (err) {
2131 dev_err(&adapter->pdev->dev,
2132 "Failed to configure interrupts 0x%x\n", err);
2133 goto out;
2134 }
2135
2136 max_ints = cmd.rsp.arg[1];
2137 for (i = 0, index = 2; i < max_ints; i++, index += 2) {
2138 val = cmd.rsp.arg[index];
2139 if (LSB(val)) {
2140 dev_info(&adapter->pdev->dev,
2141 "Can't configure interrupt %d\n",
2142 adapter->ahw->intr_tbl[i].id);
2143 continue;
2144 }
2145 if (op_type) {
2146 adapter->ahw->intr_tbl[i].id = MSW(val);
2147 adapter->ahw->intr_tbl[i].enabled = 1;
2148 temp = cmd.rsp.arg[index + 1];
2149 adapter->ahw->intr_tbl[i].src = temp;
2150 } else {
2151 adapter->ahw->intr_tbl[i].id = i;
2152 adapter->ahw->intr_tbl[i].enabled = 0;
2153 adapter->ahw->intr_tbl[i].src = 0;
2154 }
2155 }
2156out:
2157 qlcnic_free_mbx_args(&cmd);
2158 return err;
2159}
Sony Chackod865ebb2013-01-01 03:20:23 +00002160
2161int qlcnic_83xx_lock_flash(struct qlcnic_adapter *adapter)
2162{
2163 int id, timeout = 0;
2164 u32 status = 0;
2165
2166 while (status == 0) {
2167 status = QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_LOCK);
2168 if (status)
2169 break;
2170
2171 if (++timeout >= QLC_83XX_FLASH_LOCK_TIMEOUT) {
2172 id = QLC_SHARED_REG_RD32(adapter,
2173 QLCNIC_FLASH_LOCK_OWNER);
2174 dev_err(&adapter->pdev->dev,
2175 "%s: failed, lock held by %d\n", __func__, id);
2176 return -EIO;
2177 }
2178 usleep_range(1000, 2000);
2179 }
2180
2181 QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, adapter->portnum);
2182 return 0;
2183}
2184
2185void qlcnic_83xx_unlock_flash(struct qlcnic_adapter *adapter)
2186{
2187 QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_UNLOCK);
2188 QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, 0xFF);
2189}
2190
Sony Chacko629263a2013-01-01 04:11:55 +00002191int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *adapter,
2192 u32 flash_addr, u8 *p_data,
2193 int count)
Sony Chackod865ebb2013-01-01 03:20:23 +00002194{
2195 int i, ret;
2196 u32 word, range, flash_offset, addr = flash_addr;
2197 ulong indirect_add, direct_window;
2198
2199 flash_offset = addr & (QLCNIC_FLASH_SECTOR_SIZE - 1);
2200 if (addr & 0x3) {
2201 dev_err(&adapter->pdev->dev, "Illegal addr = 0x%x\n", addr);
2202 return -EIO;
2203 }
2204
2205 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_DIRECT_WINDOW,
2206 (addr));
2207
2208 range = flash_offset + (count * sizeof(u32));
2209 /* Check if data is spread across multiple sectors */
2210 if (range > (QLCNIC_FLASH_SECTOR_SIZE - 1)) {
2211
2212 /* Multi sector read */
2213 for (i = 0; i < count; i++) {
2214 indirect_add = QLC_83XX_FLASH_DIRECT_DATA(addr);
2215 ret = qlcnic_83xx_rd_reg_indirect(adapter,
2216 indirect_add);
2217 if (ret == -EIO)
2218 return -EIO;
2219
2220 word = ret;
2221 *(u32 *)p_data = word;
2222 p_data = p_data + 4;
2223 addr = addr + 4;
2224 flash_offset = flash_offset + 4;
2225
2226 if (flash_offset > (QLCNIC_FLASH_SECTOR_SIZE - 1)) {
2227 direct_window = QLC_83XX_FLASH_DIRECT_WINDOW;
2228 /* This write is needed once for each sector */
2229 qlcnic_83xx_wrt_reg_indirect(adapter,
2230 direct_window,
2231 (addr));
2232 flash_offset = 0;
2233 }
2234 }
2235 } else {
2236 /* Single sector read */
2237 for (i = 0; i < count; i++) {
2238 indirect_add = QLC_83XX_FLASH_DIRECT_DATA(addr);
2239 ret = qlcnic_83xx_rd_reg_indirect(adapter,
2240 indirect_add);
2241 if (ret == -EIO)
2242 return -EIO;
2243
2244 word = ret;
2245 *(u32 *)p_data = word;
2246 p_data = p_data + 4;
2247 addr = addr + 4;
2248 }
2249 }
2250
2251 return 0;
2252}
2253
2254static int qlcnic_83xx_poll_flash_status_reg(struct qlcnic_adapter *adapter)
2255{
2256 u32 status;
2257 int retries = QLC_83XX_FLASH_READ_RETRY_COUNT;
2258
2259 do {
2260 status = qlcnic_83xx_rd_reg_indirect(adapter,
2261 QLC_83XX_FLASH_STATUS);
2262 if ((status & QLC_83XX_FLASH_STATUS_READY) ==
2263 QLC_83XX_FLASH_STATUS_READY)
2264 break;
2265
2266 msleep(QLC_83XX_FLASH_STATUS_REG_POLL_DELAY);
2267 } while (--retries);
2268
2269 if (!retries)
2270 return -EIO;
2271
2272 return 0;
2273}
2274
2275static int qlcnic_83xx_enable_flash_write_op(struct qlcnic_adapter *adapter)
2276{
2277 int ret;
2278 u32 cmd;
2279 cmd = adapter->ahw->fdt.write_statusreg_cmd;
2280 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2281 (QLC_83XX_FLASH_FDT_WRITE_DEF_SIG | cmd));
2282 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
2283 adapter->ahw->fdt.write_enable_bits);
2284 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2285 QLC_83XX_FLASH_SECOND_ERASE_MS_VAL);
2286 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2287 if (ret)
2288 return -EIO;
2289
2290 return 0;
2291}
2292
2293static int qlcnic_83xx_disable_flash_write_op(struct qlcnic_adapter *adapter)
2294{
2295 int ret;
2296
2297 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2298 (QLC_83XX_FLASH_FDT_WRITE_DEF_SIG |
2299 adapter->ahw->fdt.write_statusreg_cmd));
2300 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
2301 adapter->ahw->fdt.write_disable_bits);
2302 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2303 QLC_83XX_FLASH_SECOND_ERASE_MS_VAL);
2304 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2305 if (ret)
2306 return -EIO;
2307
2308 return 0;
2309}
2310
2311int qlcnic_83xx_read_flash_mfg_id(struct qlcnic_adapter *adapter)
2312{
2313 int ret, mfg_id;
2314
2315 if (qlcnic_83xx_lock_flash(adapter))
2316 return -EIO;
2317
2318 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2319 QLC_83XX_FLASH_FDT_READ_MFG_ID_VAL);
2320 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2321 QLC_83XX_FLASH_READ_CTRL);
2322 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2323 if (ret) {
2324 qlcnic_83xx_unlock_flash(adapter);
2325 return -EIO;
2326 }
2327
2328 mfg_id = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_RDDATA);
2329 if (mfg_id == -EIO)
2330 return -EIO;
2331
2332 adapter->flash_mfg_id = (mfg_id & 0xFF);
2333 qlcnic_83xx_unlock_flash(adapter);
2334
2335 return 0;
2336}
2337
2338int qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *adapter)
2339{
2340 int count, fdt_size, ret = 0;
2341
2342 fdt_size = sizeof(struct qlcnic_fdt);
2343 count = fdt_size / sizeof(u32);
2344
2345 if (qlcnic_83xx_lock_flash(adapter))
2346 return -EIO;
2347
2348 memset(&adapter->ahw->fdt, 0, fdt_size);
2349 ret = qlcnic_83xx_lockless_flash_read32(adapter, QLCNIC_FDT_LOCATION,
2350 (u8 *)&adapter->ahw->fdt,
2351 count);
2352
2353 qlcnic_83xx_unlock_flash(adapter);
2354 return ret;
2355}
2356
2357int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,
2358 u32 sector_start_addr)
2359{
2360 u32 reversed_addr, addr1, addr2, cmd;
2361 int ret = -EIO;
2362
2363 if (qlcnic_83xx_lock_flash(adapter) != 0)
2364 return -EIO;
2365
2366 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
2367 ret = qlcnic_83xx_enable_flash_write_op(adapter);
2368 if (ret) {
2369 qlcnic_83xx_unlock_flash(adapter);
2370 dev_err(&adapter->pdev->dev,
2371 "%s failed at %d\n",
2372 __func__, __LINE__);
2373 return ret;
2374 }
2375 }
2376
2377 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2378 if (ret) {
2379 qlcnic_83xx_unlock_flash(adapter);
2380 dev_err(&adapter->pdev->dev,
2381 "%s: failed at %d\n", __func__, __LINE__);
2382 return -EIO;
2383 }
2384
2385 addr1 = (sector_start_addr & 0xFF) << 16;
2386 addr2 = (sector_start_addr & 0xFF0000) >> 16;
2387 reversed_addr = addr1 | addr2;
2388
2389 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
2390 reversed_addr);
2391 cmd = QLC_83XX_FLASH_FDT_ERASE_DEF_SIG | adapter->ahw->fdt.erase_cmd;
2392 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id)
2393 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, cmd);
2394 else
2395 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2396 QLC_83XX_FLASH_OEM_ERASE_SIG);
2397 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2398 QLC_83XX_FLASH_LAST_ERASE_MS_VAL);
2399
2400 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2401 if (ret) {
2402 qlcnic_83xx_unlock_flash(adapter);
2403 dev_err(&adapter->pdev->dev,
2404 "%s: failed at %d\n", __func__, __LINE__);
2405 return -EIO;
2406 }
2407
2408 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
2409 ret = qlcnic_83xx_disable_flash_write_op(adapter);
2410 if (ret) {
2411 qlcnic_83xx_unlock_flash(adapter);
2412 dev_err(&adapter->pdev->dev,
2413 "%s: failed at %d\n", __func__, __LINE__);
2414 return ret;
2415 }
2416 }
2417
2418 qlcnic_83xx_unlock_flash(adapter);
2419
2420 return 0;
2421}
2422
2423int qlcnic_83xx_flash_write32(struct qlcnic_adapter *adapter, u32 addr,
2424 u32 *p_data)
2425{
2426 int ret = -EIO;
2427 u32 addr1 = 0x00800000 | (addr >> 2);
2428
2429 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, addr1);
2430 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data);
2431 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2432 QLC_83XX_FLASH_LAST_ERASE_MS_VAL);
2433 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2434 if (ret) {
2435 dev_err(&adapter->pdev->dev,
2436 "%s: failed at %d\n", __func__, __LINE__);
2437 return -EIO;
2438 }
2439
2440 return 0;
2441}
2442
2443int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
2444 u32 *p_data, int count)
2445{
2446 u32 temp;
2447 int ret = -EIO;
2448
2449 if ((count < QLC_83XX_FLASH_BULK_WRITE_MIN) ||
2450 (count > QLC_83XX_FLASH_BULK_WRITE_MAX)) {
2451 dev_err(&adapter->pdev->dev,
2452 "%s: Invalid word count\n", __func__);
2453 return -EIO;
2454 }
2455
2456 temp = qlcnic_83xx_rd_reg_indirect(adapter,
2457 QLC_83XX_FLASH_SPI_CONTROL);
2458 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_SPI_CONTROL,
2459 (temp | QLC_83XX_FLASH_SPI_CTRL));
2460 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2461 QLC_83XX_FLASH_ADDR_TEMP_VAL);
2462
2463 /* First DWORD write */
2464 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data++);
2465 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2466 QLC_83XX_FLASH_FIRST_MS_PATTERN);
2467 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2468 if (ret) {
2469 dev_err(&adapter->pdev->dev,
2470 "%s: failed at %d\n", __func__, __LINE__);
2471 return -EIO;
2472 }
2473
2474 count--;
2475 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2476 QLC_83XX_FLASH_ADDR_SECOND_TEMP_VAL);
2477 /* Second to N-1 DWORD writes */
2478 while (count != 1) {
2479 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
2480 *p_data++);
2481 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2482 QLC_83XX_FLASH_SECOND_MS_PATTERN);
2483 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2484 if (ret) {
2485 dev_err(&adapter->pdev->dev,
2486 "%s: failed at %d\n", __func__, __LINE__);
2487 return -EIO;
2488 }
2489 count--;
2490 }
2491
2492 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2493 QLC_83XX_FLASH_ADDR_TEMP_VAL |
2494 (addr >> 2));
2495 /* Last DWORD write */
2496 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data++);
2497 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2498 QLC_83XX_FLASH_LAST_MS_PATTERN);
2499 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2500 if (ret) {
2501 dev_err(&adapter->pdev->dev,
2502 "%s: failed at %d\n", __func__, __LINE__);
2503 return -EIO;
2504 }
2505
2506 ret = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_SPI_STATUS);
2507 if ((ret & QLC_83XX_FLASH_SPI_CTRL) == QLC_83XX_FLASH_SPI_CTRL) {
2508 dev_err(&adapter->pdev->dev, "%s: failed at %d\n",
2509 __func__, __LINE__);
2510 /* Operation failed, clear error bit */
2511 temp = qlcnic_83xx_rd_reg_indirect(adapter,
2512 QLC_83XX_FLASH_SPI_CONTROL);
2513 qlcnic_83xx_wrt_reg_indirect(adapter,
2514 QLC_83XX_FLASH_SPI_CONTROL,
2515 (temp | QLC_83XX_FLASH_SPI_CTRL));
2516 }
2517
2518 return 0;
2519}
Sony Chacko629263a2013-01-01 04:11:55 +00002520
2521static void qlcnic_83xx_recover_driver_lock(struct qlcnic_adapter *adapter)
2522{
2523 u32 val, id;
2524
2525 val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK);
2526
2527 /* Check if recovery need to be performed by the calling function */
2528 if ((val & QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK) == 0) {
2529 val = val & ~0x3F;
2530 val = val | ((adapter->portnum << 2) |
2531 QLC_83XX_NEED_DRV_LOCK_RECOVERY);
2532 QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
2533 dev_info(&adapter->pdev->dev,
2534 "%s: lock recovery initiated\n", __func__);
2535 msleep(QLC_83XX_DRV_LOCK_RECOVERY_DELAY);
2536 val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK);
2537 id = ((val >> 2) & 0xF);
2538 if (id == adapter->portnum) {
2539 val = val & ~QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK;
2540 val = val | QLC_83XX_DRV_LOCK_RECOVERY_IN_PROGRESS;
2541 QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
2542 /* Force release the lock */
2543 QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK);
2544 /* Clear recovery bits */
2545 val = val & ~0x3F;
2546 QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
2547 dev_info(&adapter->pdev->dev,
2548 "%s: lock recovery completed\n", __func__);
2549 } else {
2550 dev_info(&adapter->pdev->dev,
2551 "%s: func %d to resume lock recovery process\n",
2552 __func__, id);
2553 }
2554 } else {
2555 dev_info(&adapter->pdev->dev,
2556 "%s: lock recovery initiated by other functions\n",
2557 __func__);
2558 }
2559}
2560
2561int qlcnic_83xx_lock_driver(struct qlcnic_adapter *adapter)
2562{
2563 u32 lock_alive_counter, val, id, i = 0, status = 0, temp = 0;
2564 int max_attempt = 0;
2565
2566 while (status == 0) {
2567 status = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK);
2568 if (status)
2569 break;
2570
2571 msleep(QLC_83XX_DRV_LOCK_WAIT_DELAY);
2572 i++;
2573
2574 if (i == 1)
2575 temp = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
2576
2577 if (i == QLC_83XX_DRV_LOCK_WAIT_COUNTER) {
2578 val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
2579 if (val == temp) {
2580 id = val & 0xFF;
2581 dev_info(&adapter->pdev->dev,
2582 "%s: lock to be recovered from %d\n",
2583 __func__, id);
2584 qlcnic_83xx_recover_driver_lock(adapter);
2585 i = 0;
2586 max_attempt++;
2587 } else {
2588 dev_err(&adapter->pdev->dev,
2589 "%s: failed to get lock\n", __func__);
2590 return -EIO;
2591 }
2592 }
2593
2594 /* Force exit from while loop after few attempts */
2595 if (max_attempt == QLC_83XX_MAX_DRV_LOCK_RECOVERY_ATTEMPT) {
2596 dev_err(&adapter->pdev->dev,
2597 "%s: failed to get lock\n", __func__);
2598 return -EIO;
2599 }
2600 }
2601
2602 val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
2603 lock_alive_counter = val >> 8;
2604 lock_alive_counter++;
2605 val = lock_alive_counter << 8 | adapter->portnum;
2606 QLCWRX(adapter->ahw, QLC_83XX_DRV_LOCK_ID, val);
2607
2608 return 0;
2609}
2610
2611void qlcnic_83xx_unlock_driver(struct qlcnic_adapter *adapter)
2612{
2613 u32 val, lock_alive_counter, id;
2614
2615 val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
2616 id = val & 0xFF;
2617 lock_alive_counter = val >> 8;
2618
2619 if (id != adapter->portnum)
2620 dev_err(&adapter->pdev->dev,
2621 "%s:Warning func %d is unlocking lock owned by %d\n",
2622 __func__, adapter->portnum, id);
2623
2624 val = (lock_alive_counter << 8) | 0xFF;
2625 QLCWRX(adapter->ahw, QLC_83XX_DRV_LOCK_ID, val);
2626 QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK);
2627}
2628
2629int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *adapter, u64 addr,
2630 u32 *data, u32 count)
2631{
2632 int i, j, ret = 0;
2633 u32 temp;
2634
2635 /* Check alignment */
2636 if (addr & 0xF)
2637 return -EIO;
2638
2639 mutex_lock(&adapter->ahw->mem_lock);
2640 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_ADDR_HI, 0);
2641
2642 for (i = 0; i < count; i++, addr += 16) {
2643 if (!((ADDR_IN_RANGE(addr, QLCNIC_ADDR_QDR_NET,
2644 QLCNIC_ADDR_QDR_NET_MAX)) ||
2645 (ADDR_IN_RANGE(addr, QLCNIC_ADDR_DDR_NET,
2646 QLCNIC_ADDR_DDR_NET_MAX)))) {
2647 mutex_unlock(&adapter->ahw->mem_lock);
2648 return -EIO;
2649 }
2650
2651 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_ADDR_LO, addr);
2652 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_LO,
2653 *data++);
2654 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_HI,
2655 *data++);
2656 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_ULO,
2657 *data++);
2658 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_UHI,
2659 *data++);
2660 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_CTRL,
2661 QLCNIC_TA_WRITE_ENABLE);
2662 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_CTRL,
2663 QLCNIC_TA_WRITE_START);
2664
2665 for (j = 0; j < MAX_CTL_CHECK; j++) {
2666 temp = qlcnic_83xx_rd_reg_indirect(adapter,
2667 QLCNIC_MS_CTRL);
2668 if ((temp & TA_CTL_BUSY) == 0)
2669 break;
2670 }
2671
2672 /* Status check failure */
2673 if (j >= MAX_CTL_CHECK) {
2674 printk_ratelimited(KERN_WARNING
2675 "MS memory write failed\n");
2676 mutex_unlock(&adapter->ahw->mem_lock);
2677 return -EIO;
2678 }
2679 }
2680
2681 mutex_unlock(&adapter->ahw->mem_lock);
2682
2683 return ret;
2684}
Sony Chacko81d0aeb2013-01-01 03:20:25 +00002685
2686int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
2687 u8 *p_data, int count)
2688{
2689 int i, ret;
2690 u32 word, addr = flash_addr;
2691 ulong indirect_addr;
2692
2693 if (qlcnic_83xx_lock_flash(adapter) != 0)
2694 return -EIO;
2695
2696 if (addr & 0x3) {
2697 dev_err(&adapter->pdev->dev, "Illegal addr = 0x%x\n", addr);
2698 qlcnic_83xx_unlock_flash(adapter);
2699 return -EIO;
2700 }
2701
2702 for (i = 0; i < count; i++) {
2703 if (qlcnic_83xx_wrt_reg_indirect(adapter,
2704 QLC_83XX_FLASH_DIRECT_WINDOW,
2705 (addr))) {
2706 qlcnic_83xx_unlock_flash(adapter);
2707 return -EIO;
2708 }
2709
2710 indirect_addr = QLC_83XX_FLASH_DIRECT_DATA(addr);
2711 ret = qlcnic_83xx_rd_reg_indirect(adapter,
2712 indirect_addr);
2713 if (ret == -EIO)
2714 return -EIO;
2715 word = ret;
Manish chopra1403f432013-01-30 12:47:13 +00002716 *(u32 *)p_data = word;
Sony Chacko81d0aeb2013-01-01 03:20:25 +00002717 p_data = p_data + 4;
2718 addr = addr + 4;
2719 }
2720
2721 qlcnic_83xx_unlock_flash(adapter);
2722
2723 return 0;
2724}
Sony Chacko7e38d042013-01-01 03:20:28 +00002725
2726int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
2727{
2728 int err;
2729 u32 config = 0, state;
2730 struct qlcnic_cmd_args cmd;
2731 struct qlcnic_hardware_context *ahw = adapter->ahw;
2732
2733 state = readl(ahw->pci_base0 + QLC_83XX_LINK_STATE(ahw->pci_func));
2734 if (!QLC_83xx_FUNC_VAL(state, ahw->pci_func)) {
2735 dev_info(&adapter->pdev->dev, "link state down\n");
2736 return config;
2737 }
2738 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS);
2739 err = qlcnic_issue_cmd(adapter, &cmd);
2740 if (err) {
2741 dev_info(&adapter->pdev->dev,
2742 "Get Link Status Command failed: 0x%x\n", err);
2743 goto out;
2744 } else {
2745 config = cmd.rsp.arg[1];
2746 switch (QLC_83XX_CURRENT_LINK_SPEED(config)) {
2747 case QLC_83XX_10M_LINK:
2748 ahw->link_speed = SPEED_10;
2749 break;
2750 case QLC_83XX_100M_LINK:
2751 ahw->link_speed = SPEED_100;
2752 break;
2753 case QLC_83XX_1G_LINK:
2754 ahw->link_speed = SPEED_1000;
2755 break;
2756 case QLC_83XX_10G_LINK:
2757 ahw->link_speed = SPEED_10000;
2758 break;
2759 default:
2760 ahw->link_speed = 0;
2761 break;
2762 }
2763 config = cmd.rsp.arg[3];
2764 if (config & 1)
2765 err = 1;
2766 }
2767out:
2768 qlcnic_free_mbx_args(&cmd);
2769 return config;
2770}
2771
2772int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter)
2773{
2774 u32 config = 0;
2775 int status = 0;
2776 struct qlcnic_hardware_context *ahw = adapter->ahw;
2777
2778 /* Get port configuration info */
2779 status = qlcnic_83xx_get_port_info(adapter);
2780 /* Get Link Status related info */
2781 config = qlcnic_83xx_test_link(adapter);
2782 ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config);
2783 /* hard code until there is a way to get it from flash */
2784 ahw->board_type = QLCNIC_BRDTYPE_83XX_10G;
2785 return status;
2786}
2787
2788int qlcnic_83xx_set_settings(struct qlcnic_adapter *adapter,
2789 struct ethtool_cmd *ecmd)
2790{
2791 int status = 0;
2792 u32 config = adapter->ahw->port_config;
2793
2794 if (ecmd->autoneg)
2795 adapter->ahw->port_config |= BIT_15;
2796
2797 switch (ethtool_cmd_speed(ecmd)) {
2798 case SPEED_10:
2799 adapter->ahw->port_config |= BIT_8;
2800 break;
2801 case SPEED_100:
2802 adapter->ahw->port_config |= BIT_9;
2803 break;
2804 case SPEED_1000:
2805 adapter->ahw->port_config |= BIT_10;
2806 break;
2807 case SPEED_10000:
2808 adapter->ahw->port_config |= BIT_11;
2809 break;
2810 default:
2811 return -EINVAL;
2812 }
2813
2814 status = qlcnic_83xx_set_port_config(adapter);
2815 if (status) {
2816 dev_info(&adapter->pdev->dev,
2817 "Faild to Set Link Speed and autoneg.\n");
2818 adapter->ahw->port_config = config;
2819 }
2820 return status;
2821}
2822
2823static inline u64 *qlcnic_83xx_copy_stats(struct qlcnic_cmd_args *cmd,
2824 u64 *data, int index)
2825{
2826 u32 low, hi;
2827 u64 val;
2828
2829 low = cmd->rsp.arg[index];
2830 hi = cmd->rsp.arg[index + 1];
2831 val = (((u64) low) | (((u64) hi) << 32));
2832 *data++ = val;
2833 return data;
2834}
2835
2836static u64 *qlcnic_83xx_fill_stats(struct qlcnic_adapter *adapter,
2837 struct qlcnic_cmd_args *cmd, u64 *data,
2838 int type, int *ret)
2839{
2840 int err, k, total_regs;
2841
2842 *ret = 0;
2843 err = qlcnic_issue_cmd(adapter, cmd);
2844 if (err != QLCNIC_RCODE_SUCCESS) {
2845 dev_info(&adapter->pdev->dev,
2846 "Error in get statistics mailbox command\n");
2847 *ret = -EIO;
2848 return data;
2849 }
2850 total_regs = cmd->rsp.num;
2851 switch (type) {
2852 case QLC_83XX_STAT_MAC:
2853 /* fill in MAC tx counters */
2854 for (k = 2; k < 28; k += 2)
2855 data = qlcnic_83xx_copy_stats(cmd, data, k);
2856 /* skip 24 bytes of reserved area */
2857 /* fill in MAC rx counters */
2858 for (k += 6; k < 60; k += 2)
2859 data = qlcnic_83xx_copy_stats(cmd, data, k);
2860 /* skip 24 bytes of reserved area */
2861 /* fill in MAC rx frame stats */
2862 for (k += 6; k < 80; k += 2)
2863 data = qlcnic_83xx_copy_stats(cmd, data, k);
2864 break;
2865 case QLC_83XX_STAT_RX:
2866 for (k = 2; k < 8; k += 2)
2867 data = qlcnic_83xx_copy_stats(cmd, data, k);
2868 /* skip 8 bytes of reserved data */
2869 for (k += 2; k < 24; k += 2)
2870 data = qlcnic_83xx_copy_stats(cmd, data, k);
2871 /* skip 8 bytes containing RE1FBQ error data */
2872 for (k += 2; k < total_regs; k += 2)
2873 data = qlcnic_83xx_copy_stats(cmd, data, k);
2874 break;
2875 case QLC_83XX_STAT_TX:
2876 for (k = 2; k < 10; k += 2)
2877 data = qlcnic_83xx_copy_stats(cmd, data, k);
2878 /* skip 8 bytes of reserved data */
2879 for (k += 2; k < total_regs; k += 2)
2880 data = qlcnic_83xx_copy_stats(cmd, data, k);
2881 break;
2882 default:
2883 dev_warn(&adapter->pdev->dev, "Unknown get statistics mode\n");
2884 *ret = -EIO;
2885 }
2886 return data;
2887}
2888
2889void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data)
2890{
2891 struct qlcnic_cmd_args cmd;
2892 int ret = 0;
2893
2894 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_STATISTICS);
2895 /* Get Tx stats */
2896 cmd.req.arg[1] = BIT_1 | (adapter->tx_ring->ctx_id << 16);
2897 cmd.rsp.num = QLC_83XX_TX_STAT_REGS;
2898 data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
2899 QLC_83XX_STAT_TX, &ret);
2900 if (ret) {
2901 dev_info(&adapter->pdev->dev, "Error getting MAC stats\n");
2902 goto out;
2903 }
2904 /* Get MAC stats */
2905 cmd.req.arg[1] = BIT_2 | (adapter->portnum << 16);
2906 cmd.rsp.num = QLC_83XX_MAC_STAT_REGS;
2907 memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num);
2908 data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
2909 QLC_83XX_STAT_MAC, &ret);
2910 if (ret) {
2911 dev_info(&adapter->pdev->dev,
2912 "Error getting Rx stats\n");
2913 goto out;
2914 }
2915 /* Get Rx stats */
2916 cmd.req.arg[1] = adapter->recv_ctx->context_id << 16;
2917 cmd.rsp.num = QLC_83XX_RX_STAT_REGS;
2918 memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num);
2919 data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
2920 QLC_83XX_STAT_RX, &ret);
2921 if (ret)
2922 dev_info(&adapter->pdev->dev,
2923 "Error getting Tx stats\n");
2924out:
2925 qlcnic_free_mbx_args(&cmd);
2926}
2927
2928int qlcnic_83xx_reg_test(struct qlcnic_adapter *adapter)
2929{
2930 u32 major, minor, sub;
2931
2932 major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
2933 minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
2934 sub = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
2935
2936 if (adapter->fw_version != QLCNIC_VERSION_CODE(major, minor, sub)) {
2937 dev_info(&adapter->pdev->dev, "%s: Reg test failed\n",
2938 __func__);
2939 return 1;
2940 }
2941 return 0;
2942}
2943
2944int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *adapter)
2945{
2946 return (ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl) *
2947 sizeof(adapter->ahw->ext_reg_tbl)) +
2948 (ARRAY_SIZE(qlcnic_83xx_reg_tbl) +
2949 sizeof(adapter->ahw->reg_tbl));
2950}
2951
2952int qlcnic_83xx_get_registers(struct qlcnic_adapter *adapter, u32 *regs_buff)
2953{
2954 int i, j = 0;
2955
2956 for (i = QLCNIC_DEV_INFO_SIZE + 1;
2957 j < ARRAY_SIZE(qlcnic_83xx_reg_tbl); i++, j++)
2958 regs_buff[i] = QLC_SHARED_REG_RD32(adapter, j);
2959
2960 for (j = 0; j < ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl); j++)
2961 regs_buff[i++] = QLCRDX(adapter->ahw, j);
2962 return i;
2963}
2964
Jitendra Kalsaria58ead412013-02-09 09:29:52 +00002965int qlcnic_83xx_interrupt_test(struct net_device *netdev)
Sony Chacko7e38d042013-01-01 03:20:28 +00002966{
Jitendra Kalsaria58ead412013-02-09 09:29:52 +00002967 struct qlcnic_adapter *adapter = netdev_priv(netdev);
2968 struct qlcnic_hardware_context *ahw = adapter->ahw;
2969 struct qlcnic_cmd_args cmd;
Sony Chacko7e38d042013-01-01 03:20:28 +00002970 u32 data;
2971 u16 intrpt_id, id;
Jitendra Kalsaria58ead412013-02-09 09:29:52 +00002972 u8 val;
2973 int ret, max_sds_rings = adapter->max_sds_rings;
2974
2975 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
2976 return -EIO;
2977
2978 ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
2979 if (ret)
2980 goto fail_diag_irq;
2981
2982 ahw->diag_cnt = 0;
2983 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
Sony Chacko7e38d042013-01-01 03:20:28 +00002984
2985 if (adapter->flags & QLCNIC_MSIX_ENABLED)
Jitendra Kalsaria58ead412013-02-09 09:29:52 +00002986 intrpt_id = ahw->intr_tbl[0].id;
Sony Chacko7e38d042013-01-01 03:20:28 +00002987 else
Jitendra Kalsaria58ead412013-02-09 09:29:52 +00002988 intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
Sony Chacko7e38d042013-01-01 03:20:28 +00002989
Jitendra Kalsaria58ead412013-02-09 09:29:52 +00002990 cmd.req.arg[1] = 1;
2991 cmd.req.arg[2] = intrpt_id;
2992 cmd.req.arg[3] = BIT_0;
Sony Chacko7e38d042013-01-01 03:20:28 +00002993
Jitendra Kalsaria58ead412013-02-09 09:29:52 +00002994 ret = qlcnic_issue_cmd(adapter, &cmd);
2995 data = cmd.rsp.arg[2];
Sony Chacko7e38d042013-01-01 03:20:28 +00002996 id = LSW(data);
2997 val = LSB(MSW(data));
2998 if (id != intrpt_id)
2999 dev_info(&adapter->pdev->dev,
3000 "Interrupt generated: 0x%x, requested:0x%x\n",
3001 id, intrpt_id);
3002 if (val)
Jitendra Kalsaria58ead412013-02-09 09:29:52 +00003003 dev_err(&adapter->pdev->dev,
Sony Chacko7e38d042013-01-01 03:20:28 +00003004 "Interrupt test error: 0x%x\n", val);
Jitendra Kalsaria58ead412013-02-09 09:29:52 +00003005 if (ret)
3006 goto done;
Sony Chacko7e38d042013-01-01 03:20:28 +00003007
Jitendra Kalsaria58ead412013-02-09 09:29:52 +00003008 msleep(20);
3009 ret = !ahw->diag_cnt;
3010
3011done:
3012 qlcnic_free_mbx_args(&cmd);
3013 qlcnic_83xx_diag_free_res(netdev, max_sds_rings);
3014
3015fail_diag_irq:
3016 adapter->max_sds_rings = max_sds_rings;
3017 clear_bit(__QLCNIC_RESETTING, &adapter->state);
Sony Chacko7e38d042013-01-01 03:20:28 +00003018 return ret;
3019}
3020
3021void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *adapter,
3022 struct ethtool_pauseparam *pause)
3023{
3024 struct qlcnic_hardware_context *ahw = adapter->ahw;
3025 int status = 0;
3026 u32 config;
3027
3028 status = qlcnic_83xx_get_port_config(adapter);
3029 if (status) {
3030 dev_err(&adapter->pdev->dev,
3031 "%s: Get Pause Config failed\n", __func__);
3032 return;
3033 }
3034 config = ahw->port_config;
3035 if (config & QLC_83XX_CFG_STD_PAUSE) {
3036 if (config & QLC_83XX_CFG_STD_TX_PAUSE)
3037 pause->tx_pause = 1;
3038 if (config & QLC_83XX_CFG_STD_RX_PAUSE)
3039 pause->rx_pause = 1;
3040 }
3041
3042 if (QLC_83XX_AUTONEG(config))
3043 pause->autoneg = 1;
3044}
3045
3046int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *adapter,
3047 struct ethtool_pauseparam *pause)
3048{
3049 struct qlcnic_hardware_context *ahw = adapter->ahw;
3050 int status = 0;
3051 u32 config;
3052
3053 status = qlcnic_83xx_get_port_config(adapter);
3054 if (status) {
3055 dev_err(&adapter->pdev->dev,
3056 "%s: Get Pause Config failed.\n", __func__);
3057 return status;
3058 }
3059 config = ahw->port_config;
3060
3061 if (ahw->port_type == QLCNIC_GBE) {
3062 if (pause->autoneg)
3063 ahw->port_config |= QLC_83XX_ENABLE_AUTONEG;
3064 if (!pause->autoneg)
3065 ahw->port_config &= ~QLC_83XX_ENABLE_AUTONEG;
3066 } else if ((ahw->port_type == QLCNIC_XGBE) && (pause->autoneg)) {
3067 return -EOPNOTSUPP;
3068 }
3069
3070 if (!(config & QLC_83XX_CFG_STD_PAUSE))
3071 ahw->port_config |= QLC_83XX_CFG_STD_PAUSE;
3072
3073 if (pause->rx_pause && pause->tx_pause) {
3074 ahw->port_config |= QLC_83XX_CFG_STD_TX_RX_PAUSE;
3075 } else if (pause->rx_pause && !pause->tx_pause) {
3076 ahw->port_config &= ~QLC_83XX_CFG_STD_TX_PAUSE;
3077 ahw->port_config |= QLC_83XX_CFG_STD_RX_PAUSE;
3078 } else if (pause->tx_pause && !pause->rx_pause) {
3079 ahw->port_config &= ~QLC_83XX_CFG_STD_RX_PAUSE;
3080 ahw->port_config |= QLC_83XX_CFG_STD_TX_PAUSE;
3081 } else if (!pause->rx_pause && !pause->tx_pause) {
3082 ahw->port_config &= ~QLC_83XX_CFG_STD_TX_RX_PAUSE;
3083 }
3084 status = qlcnic_83xx_set_port_config(adapter);
3085 if (status) {
3086 dev_err(&adapter->pdev->dev,
3087 "%s: Set Pause Config failed.\n", __func__);
3088 ahw->port_config = config;
3089 }
3090 return status;
3091}
3092
3093static int qlcnic_83xx_read_flash_status_reg(struct qlcnic_adapter *adapter)
3094{
3095 int ret;
3096
3097 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
3098 QLC_83XX_FLASH_OEM_READ_SIG);
3099 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
3100 QLC_83XX_FLASH_READ_CTRL);
3101 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
3102 if (ret)
3103 return -EIO;
3104
3105 ret = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_RDDATA);
3106 return ret & 0xFF;
3107}
3108
3109int qlcnic_83xx_flash_test(struct qlcnic_adapter *adapter)
3110{
3111 int status;
3112
3113 status = qlcnic_83xx_read_flash_status_reg(adapter);
3114 if (status == -EIO) {
3115 dev_info(&adapter->pdev->dev, "%s: EEPROM test failed.\n",
3116 __func__);
3117 return 1;
3118 }
3119 return 0;
3120}