1004b26b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2577ae39dSJitendra Kalsaria /*
3577ae39dSJitendra Kalsaria * QLogic qlcnic NIC Driver
4577ae39dSJitendra Kalsaria * Copyright (c) 2009-2013 QLogic Corporation
5577ae39dSJitendra Kalsaria */
6577ae39dSJitendra Kalsaria
7f8468331SRajesh Borundia #include "qlcnic_sriov.h"
8629263acSSony Chacko #include "qlcnic.h"
9629263acSSony Chacko #include "qlcnic_hw.h"
10629263acSSony Chacko
1181d0aeb0SSony Chacko /* Reset template definitions */
1281d0aeb0SSony Chacko #define QLC_83XX_RESTART_TEMPLATE_SIZE 0x2000
1381d0aeb0SSony Chacko #define QLC_83XX_RESET_TEMPLATE_ADDR 0x4F0000
1481d0aeb0SSony Chacko #define QLC_83XX_RESET_SEQ_VERSION 0x0101
1581d0aeb0SSony Chacko
1681d0aeb0SSony Chacko #define QLC_83XX_OPCODE_NOP 0x0000
1781d0aeb0SSony Chacko #define QLC_83XX_OPCODE_WRITE_LIST 0x0001
1881d0aeb0SSony Chacko #define QLC_83XX_OPCODE_READ_WRITE_LIST 0x0002
1981d0aeb0SSony Chacko #define QLC_83XX_OPCODE_POLL_LIST 0x0004
2081d0aeb0SSony Chacko #define QLC_83XX_OPCODE_POLL_WRITE_LIST 0x0008
2181d0aeb0SSony Chacko #define QLC_83XX_OPCODE_READ_MODIFY_WRITE 0x0010
2281d0aeb0SSony Chacko #define QLC_83XX_OPCODE_SEQ_PAUSE 0x0020
2381d0aeb0SSony Chacko #define QLC_83XX_OPCODE_SEQ_END 0x0040
2481d0aeb0SSony Chacko #define QLC_83XX_OPCODE_TMPL_END 0x0080
2581d0aeb0SSony Chacko #define QLC_83XX_OPCODE_POLL_READ_LIST 0x0100
2681d0aeb0SSony Chacko
27c0d79cd0SManish Chopra /* EPORT control registers */
28c0d79cd0SManish Chopra #define QLC_83XX_RESET_CONTROL 0x28084E50
29c0d79cd0SManish Chopra #define QLC_83XX_RESET_REG 0x28084E60
30c0d79cd0SManish Chopra #define QLC_83XX_RESET_PORT0 0x28084E70
31c0d79cd0SManish Chopra #define QLC_83XX_RESET_PORT1 0x28084E80
32c0d79cd0SManish Chopra #define QLC_83XX_RESET_PORT2 0x28084E90
33c0d79cd0SManish Chopra #define QLC_83XX_RESET_PORT3 0x28084EA0
34c0d79cd0SManish Chopra #define QLC_83XX_RESET_SRESHIM 0x28084EB0
35c0d79cd0SManish Chopra #define QLC_83XX_RESET_EPGSHIM 0x28084EC0
36c0d79cd0SManish Chopra #define QLC_83XX_RESET_ETHERPCS 0x28084ED0
37c0d79cd0SManish Chopra
38629263acSSony Chacko static int qlcnic_83xx_init_default_driver(struct qlcnic_adapter *adapter);
39629263acSSony Chacko static int qlcnic_83xx_check_heartbeat(struct qlcnic_adapter *p_dev);
40629263acSSony Chacko static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter);
4121041400Sstephen hemminger static int qlcnic_83xx_check_hw_status(struct qlcnic_adapter *p_dev);
4221041400Sstephen hemminger static int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *);
4321041400Sstephen hemminger static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *);
44629263acSSony Chacko
4581d0aeb0SSony Chacko /* Template header */
4681d0aeb0SSony Chacko struct qlc_83xx_reset_hdr {
47a96227e6SShahed Shaikh #if defined(__LITTLE_ENDIAN)
4881d0aeb0SSony Chacko u16 version;
4981d0aeb0SSony Chacko u16 signature;
5081d0aeb0SSony Chacko u16 size;
5181d0aeb0SSony Chacko u16 entries;
5281d0aeb0SSony Chacko u16 hdr_size;
5381d0aeb0SSony Chacko u16 checksum;
5481d0aeb0SSony Chacko u16 init_offset;
5581d0aeb0SSony Chacko u16 start_offset;
56a96227e6SShahed Shaikh #elif defined(__BIG_ENDIAN)
57a96227e6SShahed Shaikh u16 signature;
58a96227e6SShahed Shaikh u16 version;
59a96227e6SShahed Shaikh u16 entries;
60a96227e6SShahed Shaikh u16 size;
61a96227e6SShahed Shaikh u16 checksum;
62a96227e6SShahed Shaikh u16 hdr_size;
63a96227e6SShahed Shaikh u16 start_offset;
64a96227e6SShahed Shaikh u16 init_offset;
65a96227e6SShahed Shaikh #endif
6681d0aeb0SSony Chacko } __packed;
6781d0aeb0SSony Chacko
6881d0aeb0SSony Chacko /* Command entry header. */
6981d0aeb0SSony Chacko struct qlc_83xx_entry_hdr {
70a96227e6SShahed Shaikh #if defined(__LITTLE_ENDIAN)
7181d0aeb0SSony Chacko u16 cmd;
7281d0aeb0SSony Chacko u16 size;
7381d0aeb0SSony Chacko u16 count;
7481d0aeb0SSony Chacko u16 delay;
75a96227e6SShahed Shaikh #elif defined(__BIG_ENDIAN)
76a96227e6SShahed Shaikh u16 size;
77a96227e6SShahed Shaikh u16 cmd;
78a96227e6SShahed Shaikh u16 delay;
79a96227e6SShahed Shaikh u16 count;
80a96227e6SShahed Shaikh #endif
8181d0aeb0SSony Chacko } __packed;
8281d0aeb0SSony Chacko
8381d0aeb0SSony Chacko /* Generic poll command */
8481d0aeb0SSony Chacko struct qlc_83xx_poll {
8581d0aeb0SSony Chacko u32 mask;
8681d0aeb0SSony Chacko u32 status;
8781d0aeb0SSony Chacko } __packed;
8881d0aeb0SSony Chacko
8981d0aeb0SSony Chacko /* Read modify write command */
9081d0aeb0SSony Chacko struct qlc_83xx_rmw {
9181d0aeb0SSony Chacko u32 mask;
9281d0aeb0SSony Chacko u32 xor_value;
9381d0aeb0SSony Chacko u32 or_value;
94a96227e6SShahed Shaikh #if defined(__LITTLE_ENDIAN)
9581d0aeb0SSony Chacko u8 shl;
9681d0aeb0SSony Chacko u8 shr;
9781d0aeb0SSony Chacko u8 index_a;
9881d0aeb0SSony Chacko u8 rsvd;
99a96227e6SShahed Shaikh #elif defined(__BIG_ENDIAN)
100a96227e6SShahed Shaikh u8 rsvd;
101a96227e6SShahed Shaikh u8 index_a;
102a96227e6SShahed Shaikh u8 shr;
103a96227e6SShahed Shaikh u8 shl;
104a96227e6SShahed Shaikh #endif
10581d0aeb0SSony Chacko } __packed;
10681d0aeb0SSony Chacko
10781d0aeb0SSony Chacko /* Generic command with 2 DWORD */
10881d0aeb0SSony Chacko struct qlc_83xx_entry {
10981d0aeb0SSony Chacko u32 arg1;
11081d0aeb0SSony Chacko u32 arg2;
11181d0aeb0SSony Chacko } __packed;
11281d0aeb0SSony Chacko
11381d0aeb0SSony Chacko /* Generic command with 4 DWORD */
11481d0aeb0SSony Chacko struct qlc_83xx_quad_entry {
11581d0aeb0SSony Chacko u32 dr_addr;
11681d0aeb0SSony Chacko u32 dr_value;
11781d0aeb0SSony Chacko u32 ar_addr;
11881d0aeb0SSony Chacko u32 ar_value;
11981d0aeb0SSony Chacko } __packed;
120629263acSSony Chacko static const char *const qlc_83xx_idc_states[] = {
121629263acSSony Chacko "Unknown",
122629263acSSony Chacko "Cold",
123629263acSSony Chacko "Init",
124629263acSSony Chacko "Ready",
125629263acSSony Chacko "Need Reset",
126629263acSSony Chacko "Need Quiesce",
127629263acSSony Chacko "Failed",
128629263acSSony Chacko "Quiesce"
129629263acSSony Chacko };
130629263acSSony Chacko
131629263acSSony Chacko static int
qlcnic_83xx_idc_check_driver_presence_reg(struct qlcnic_adapter * adapter)132629263acSSony Chacko qlcnic_83xx_idc_check_driver_presence_reg(struct qlcnic_adapter *adapter)
133629263acSSony Chacko {
134629263acSSony Chacko u32 val;
135629263acSSony Chacko
136629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
137629263acSSony Chacko if ((val & 0xFFFF))
138629263acSSony Chacko return 1;
139629263acSSony Chacko else
140629263acSSony Chacko return 0;
141629263acSSony Chacko }
142629263acSSony Chacko
qlcnic_83xx_idc_log_state_history(struct qlcnic_adapter * adapter)143629263acSSony Chacko static void qlcnic_83xx_idc_log_state_history(struct qlcnic_adapter *adapter)
144629263acSSony Chacko {
145629263acSSony Chacko u32 cur, prev;
146629263acSSony Chacko cur = adapter->ahw->idc.curr_state;
147629263acSSony Chacko prev = adapter->ahw->idc.prev_state;
148629263acSSony Chacko
149629263acSSony Chacko dev_info(&adapter->pdev->dev,
150629263acSSony Chacko "current state = %s, prev state = %s\n",
151629263acSSony Chacko adapter->ahw->idc.name[cur],
152629263acSSony Chacko adapter->ahw->idc.name[prev]);
153629263acSSony Chacko }
154629263acSSony Chacko
qlcnic_83xx_idc_update_audit_reg(struct qlcnic_adapter * adapter,u8 mode,int lock)155629263acSSony Chacko static int qlcnic_83xx_idc_update_audit_reg(struct qlcnic_adapter *adapter,
156629263acSSony Chacko u8 mode, int lock)
157629263acSSony Chacko {
158629263acSSony Chacko u32 val;
159629263acSSony Chacko int seconds;
160629263acSSony Chacko
161629263acSSony Chacko if (lock) {
162629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter))
163629263acSSony Chacko return -EBUSY;
164629263acSSony Chacko }
165629263acSSony Chacko
166f036e4f4SRajesh Borundia val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT);
167f036e4f4SRajesh Borundia val |= (adapter->portnum & 0xf);
168629263acSSony Chacko val |= mode << 7;
169629263acSSony Chacko if (mode)
170629263acSSony Chacko seconds = jiffies / HZ - adapter->ahw->idc.sec_counter;
171629263acSSony Chacko else
172629263acSSony Chacko seconds = jiffies / HZ;
173629263acSSony Chacko
174629263acSSony Chacko val |= seconds << 8;
175629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT, val);
176629263acSSony Chacko adapter->ahw->idc.sec_counter = jiffies / HZ;
177629263acSSony Chacko
178629263acSSony Chacko if (lock)
179629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
180629263acSSony Chacko
181629263acSSony Chacko return 0;
182629263acSSony Chacko }
183629263acSSony Chacko
qlcnic_83xx_idc_update_minor_version(struct qlcnic_adapter * adapter)184629263acSSony Chacko static void qlcnic_83xx_idc_update_minor_version(struct qlcnic_adapter *adapter)
185629263acSSony Chacko {
186629263acSSony Chacko u32 val;
187629263acSSony Chacko
188629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MIN_VERSION);
189629263acSSony Chacko val = val & ~(0x3 << (adapter->portnum * 2));
190629263acSSony Chacko val = val | (QLC_83XX_IDC_MINOR_VERSION << (adapter->portnum * 2));
191629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_MIN_VERSION, val);
192629263acSSony Chacko }
193629263acSSony Chacko
qlcnic_83xx_idc_update_major_version(struct qlcnic_adapter * adapter,int lock)194629263acSSony Chacko static int qlcnic_83xx_idc_update_major_version(struct qlcnic_adapter *adapter,
195629263acSSony Chacko int lock)
196629263acSSony Chacko {
197629263acSSony Chacko u32 val;
198629263acSSony Chacko
199629263acSSony Chacko if (lock) {
200629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter))
201629263acSSony Chacko return -EBUSY;
202629263acSSony Chacko }
203629263acSSony Chacko
204629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION);
205629263acSSony Chacko val = val & ~0xFF;
206629263acSSony Chacko val = val | QLC_83XX_IDC_MAJOR_VERSION;
207629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION, val);
208629263acSSony Chacko
209629263acSSony Chacko if (lock)
210629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
211629263acSSony Chacko
212629263acSSony Chacko return 0;
213629263acSSony Chacko }
214629263acSSony Chacko
215629263acSSony Chacko static int
qlcnic_83xx_idc_update_drv_presence_reg(struct qlcnic_adapter * adapter,int status,int lock)216629263acSSony Chacko qlcnic_83xx_idc_update_drv_presence_reg(struct qlcnic_adapter *adapter,
217629263acSSony Chacko int status, int lock)
218629263acSSony Chacko {
219629263acSSony Chacko u32 val;
220629263acSSony Chacko
221629263acSSony Chacko if (lock) {
222629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter))
223629263acSSony Chacko return -EBUSY;
224629263acSSony Chacko }
225629263acSSony Chacko
226629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
227629263acSSony Chacko
228629263acSSony Chacko if (status)
229629263acSSony Chacko val = val | (1 << adapter->portnum);
230629263acSSony Chacko else
231629263acSSony Chacko val = val & ~(1 << adapter->portnum);
232629263acSSony Chacko
233629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val);
234629263acSSony Chacko qlcnic_83xx_idc_update_minor_version(adapter);
235629263acSSony Chacko
236629263acSSony Chacko if (lock)
237629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
238629263acSSony Chacko
239629263acSSony Chacko return 0;
240629263acSSony Chacko }
241629263acSSony Chacko
qlcnic_83xx_idc_check_major_version(struct qlcnic_adapter * adapter)242629263acSSony Chacko static int qlcnic_83xx_idc_check_major_version(struct qlcnic_adapter *adapter)
243629263acSSony Chacko {
244629263acSSony Chacko u32 val;
245629263acSSony Chacko u8 version;
246629263acSSony Chacko
247629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION);
248629263acSSony Chacko version = val & 0xFF;
249629263acSSony Chacko
250629263acSSony Chacko if (version != QLC_83XX_IDC_MAJOR_VERSION) {
251629263acSSony Chacko dev_info(&adapter->pdev->dev,
252629263acSSony Chacko "%s:mismatch. version 0x%x, expected version 0x%x\n",
253629263acSSony Chacko __func__, version, QLC_83XX_IDC_MAJOR_VERSION);
254629263acSSony Chacko return -EIO;
255629263acSSony Chacko }
256629263acSSony Chacko
257629263acSSony Chacko return 0;
258629263acSSony Chacko }
259629263acSSony Chacko
qlcnic_83xx_idc_clear_registers(struct qlcnic_adapter * adapter,int lock)260629263acSSony Chacko static int qlcnic_83xx_idc_clear_registers(struct qlcnic_adapter *adapter,
261629263acSSony Chacko int lock)
262629263acSSony Chacko {
263629263acSSony Chacko u32 val;
264629263acSSony Chacko
265629263acSSony Chacko if (lock) {
266629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter))
267629263acSSony Chacko return -EBUSY;
268629263acSSony Chacko }
269629263acSSony Chacko
270629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_ACK, 0);
271dbedd44eSJoe Perches /* Clear graceful reset bit */
272629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
273629263acSSony Chacko val &= ~QLC_83XX_IDC_GRACEFULL_RESET;
274629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
275629263acSSony Chacko
276629263acSSony Chacko if (lock)
277629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
278629263acSSony Chacko
279629263acSSony Chacko return 0;
280629263acSSony Chacko }
281629263acSSony Chacko
qlcnic_83xx_idc_update_drv_ack_reg(struct qlcnic_adapter * adapter,int flag,int lock)282629263acSSony Chacko static int qlcnic_83xx_idc_update_drv_ack_reg(struct qlcnic_adapter *adapter,
283629263acSSony Chacko int flag, int lock)
284629263acSSony Chacko {
285629263acSSony Chacko u32 val;
286629263acSSony Chacko
287629263acSSony Chacko if (lock) {
288629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter))
289629263acSSony Chacko return -EBUSY;
290629263acSSony Chacko }
291629263acSSony Chacko
292629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_ACK);
293629263acSSony Chacko if (flag)
294629263acSSony Chacko val = val | (1 << adapter->portnum);
295629263acSSony Chacko else
296629263acSSony Chacko val = val & ~(1 << adapter->portnum);
297629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_ACK, val);
298629263acSSony Chacko
299629263acSSony Chacko if (lock)
300629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
301629263acSSony Chacko
302629263acSSony Chacko return 0;
303629263acSSony Chacko }
304629263acSSony Chacko
qlcnic_83xx_idc_check_timeout(struct qlcnic_adapter * adapter,int time_limit)305629263acSSony Chacko static int qlcnic_83xx_idc_check_timeout(struct qlcnic_adapter *adapter,
306629263acSSony Chacko int time_limit)
307629263acSSony Chacko {
308629263acSSony Chacko u64 seconds;
309629263acSSony Chacko
310629263acSSony Chacko seconds = jiffies / HZ - adapter->ahw->idc.sec_counter;
311629263acSSony Chacko if (seconds <= time_limit)
312629263acSSony Chacko return 0;
313629263acSSony Chacko else
314629263acSSony Chacko return -EBUSY;
315629263acSSony Chacko }
316629263acSSony Chacko
317629263acSSony Chacko /**
318629263acSSony Chacko * qlcnic_83xx_idc_check_reset_ack_reg
319629263acSSony Chacko *
320629263acSSony Chacko * @adapter: adapter structure
321629263acSSony Chacko *
322629263acSSony Chacko * Check ACK wait limit and clear the functions which failed to ACK
323629263acSSony Chacko *
324629263acSSony Chacko * Return 0 if all functions have acknowledged the reset request.
325629263acSSony Chacko **/
qlcnic_83xx_idc_check_reset_ack_reg(struct qlcnic_adapter * adapter)326629263acSSony Chacko static int qlcnic_83xx_idc_check_reset_ack_reg(struct qlcnic_adapter *adapter)
327629263acSSony Chacko {
328629263acSSony Chacko int timeout;
329629263acSSony Chacko u32 ack, presence, val;
330629263acSSony Chacko
331629263acSSony Chacko timeout = QLC_83XX_IDC_RESET_TIMEOUT_SECS;
332629263acSSony Chacko ack = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_ACK);
333629263acSSony Chacko presence = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
334629263acSSony Chacko dev_info(&adapter->pdev->dev,
335629263acSSony Chacko "%s: ack = 0x%x, presence = 0x%x\n", __func__, ack, presence);
336629263acSSony Chacko if (!((ack & presence) == presence)) {
337629263acSSony Chacko if (qlcnic_83xx_idc_check_timeout(adapter, timeout)) {
338629263acSSony Chacko /* Clear functions which failed to ACK */
339629263acSSony Chacko dev_info(&adapter->pdev->dev,
340629263acSSony Chacko "%s: ACK wait exceeds time limit\n", __func__);
341629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
342629263acSSony Chacko val = val & ~(ack ^ presence);
343629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter))
344629263acSSony Chacko return -EBUSY;
345629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val);
346629263acSSony Chacko dev_info(&adapter->pdev->dev,
347629263acSSony Chacko "%s: updated drv presence reg = 0x%x\n",
348629263acSSony Chacko __func__, val);
349629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
350629263acSSony Chacko return 0;
351629263acSSony Chacko
352629263acSSony Chacko } else {
353629263acSSony Chacko return 1;
354629263acSSony Chacko }
355629263acSSony Chacko } else {
356629263acSSony Chacko dev_info(&adapter->pdev->dev,
357629263acSSony Chacko "%s: Reset ACK received from all functions\n",
358629263acSSony Chacko __func__);
359629263acSSony Chacko return 0;
360629263acSSony Chacko }
361629263acSSony Chacko }
362629263acSSony Chacko
363629263acSSony Chacko /**
364629263acSSony Chacko * qlcnic_83xx_idc_tx_soft_reset
365629263acSSony Chacko *
366629263acSSony Chacko * @adapter: adapter structure
367629263acSSony Chacko *
368629263acSSony Chacko * Handle context deletion and recreation request from transmit routine
369629263acSSony Chacko *
370629263acSSony Chacko * Returns -EBUSY or Success (0)
371629263acSSony Chacko *
372629263acSSony Chacko **/
qlcnic_83xx_idc_tx_soft_reset(struct qlcnic_adapter * adapter)373629263acSSony Chacko static int qlcnic_83xx_idc_tx_soft_reset(struct qlcnic_adapter *adapter)
374629263acSSony Chacko {
375629263acSSony Chacko struct net_device *netdev = adapter->netdev;
376629263acSSony Chacko
377629263acSSony Chacko if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
378629263acSSony Chacko return -EBUSY;
379629263acSSony Chacko
380629263acSSony Chacko netif_device_detach(netdev);
381629263acSSony Chacko qlcnic_down(adapter, netdev);
382629263acSSony Chacko qlcnic_up(adapter, netdev);
383629263acSSony Chacko netif_device_attach(netdev);
384629263acSSony Chacko clear_bit(__QLCNIC_RESETTING, &adapter->state);
38595b3890aSHimanshu Madhani netdev_info(adapter->netdev, "%s: soft reset complete.\n", __func__);
386629263acSSony Chacko
387629263acSSony Chacko return 0;
388629263acSSony Chacko }
389629263acSSony Chacko
390629263acSSony Chacko /**
391629263acSSony Chacko * qlcnic_83xx_idc_detach_driver
392629263acSSony Chacko *
393629263acSSony Chacko * @adapter: adapter structure
394629263acSSony Chacko * Detach net interface, stop TX and cleanup resources before the HW reset.
395629263acSSony Chacko * Returns: None
396629263acSSony Chacko *
397629263acSSony Chacko **/
qlcnic_83xx_idc_detach_driver(struct qlcnic_adapter * adapter)398629263acSSony Chacko static void qlcnic_83xx_idc_detach_driver(struct qlcnic_adapter *adapter)
399629263acSSony Chacko {
400629263acSSony Chacko int i;
401629263acSSony Chacko struct net_device *netdev = adapter->netdev;
402629263acSSony Chacko
403629263acSSony Chacko netif_device_detach(netdev);
404068a8d19SManish Chopra qlcnic_83xx_detach_mailbox_work(adapter);
405f036e4f4SRajesh Borundia
406629263acSSony Chacko /* Disable mailbox interrupt */
407f036e4f4SRajesh Borundia qlcnic_83xx_disable_mbx_intr(adapter);
408629263acSSony Chacko qlcnic_down(adapter, netdev);
409629263acSSony Chacko for (i = 0; i < adapter->ahw->num_msix; i++) {
410629263acSSony Chacko adapter->ahw->intr_tbl[i].id = i;
411629263acSSony Chacko adapter->ahw->intr_tbl[i].enabled = 0;
412629263acSSony Chacko adapter->ahw->intr_tbl[i].src = 0;
413629263acSSony Chacko }
414f036e4f4SRajesh Borundia
415f036e4f4SRajesh Borundia if (qlcnic_sriov_pf_check(adapter))
416f036e4f4SRajesh Borundia qlcnic_sriov_pf_reset(adapter);
417629263acSSony Chacko }
418629263acSSony Chacko
419629263acSSony Chacko /**
420629263acSSony Chacko * qlcnic_83xx_idc_attach_driver
421629263acSSony Chacko *
422629263acSSony Chacko * @adapter: adapter structure
423629263acSSony Chacko *
424629263acSSony Chacko * Re-attach and re-enable net interface
425629263acSSony Chacko * Returns: None
426629263acSSony Chacko *
427629263acSSony Chacko **/
qlcnic_83xx_idc_attach_driver(struct qlcnic_adapter * adapter)428629263acSSony Chacko static void qlcnic_83xx_idc_attach_driver(struct qlcnic_adapter *adapter)
429629263acSSony Chacko {
430629263acSSony Chacko struct net_device *netdev = adapter->netdev;
431629263acSSony Chacko
432629263acSSony Chacko if (netif_running(netdev)) {
433629263acSSony Chacko if (qlcnic_up(adapter, netdev))
434629263acSSony Chacko goto done;
435629263acSSony Chacko qlcnic_restore_indev_addr(netdev, NETDEV_UP);
436629263acSSony Chacko }
437629263acSSony Chacko done:
438629263acSSony Chacko netif_device_attach(netdev);
439629263acSSony Chacko }
440629263acSSony Chacko
qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter * adapter,int lock)441629263acSSony Chacko static int qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter *adapter,
442629263acSSony Chacko int lock)
443629263acSSony Chacko {
444629263acSSony Chacko if (lock) {
445629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter))
446629263acSSony Chacko return -EBUSY;
447629263acSSony Chacko }
448629263acSSony Chacko
449629263acSSony Chacko qlcnic_83xx_idc_clear_registers(adapter, 0);
450629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_FAILED);
451629263acSSony Chacko if (lock)
452629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
453629263acSSony Chacko
454629263acSSony Chacko qlcnic_83xx_idc_log_state_history(adapter);
455629263acSSony Chacko dev_info(&adapter->pdev->dev, "Device will enter failed state\n");
456629263acSSony Chacko
457629263acSSony Chacko return 0;
458629263acSSony Chacko }
459629263acSSony Chacko
qlcnic_83xx_idc_enter_init_state(struct qlcnic_adapter * adapter,int lock)460629263acSSony Chacko static int qlcnic_83xx_idc_enter_init_state(struct qlcnic_adapter *adapter,
461629263acSSony Chacko int lock)
462629263acSSony Chacko {
463629263acSSony Chacko if (lock) {
464629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter))
465629263acSSony Chacko return -EBUSY;
466629263acSSony Chacko }
467629263acSSony Chacko
468629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_INIT);
469629263acSSony Chacko
470629263acSSony Chacko if (lock)
471629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
472629263acSSony Chacko
473629263acSSony Chacko return 0;
474629263acSSony Chacko }
475629263acSSony Chacko
qlcnic_83xx_idc_enter_need_quiesce(struct qlcnic_adapter * adapter,int lock)476629263acSSony Chacko static int qlcnic_83xx_idc_enter_need_quiesce(struct qlcnic_adapter *adapter,
477629263acSSony Chacko int lock)
478629263acSSony Chacko {
479629263acSSony Chacko if (lock) {
480629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter))
481629263acSSony Chacko return -EBUSY;
482629263acSSony Chacko }
483629263acSSony Chacko
484629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,
485629263acSSony Chacko QLC_83XX_IDC_DEV_NEED_QUISCENT);
486629263acSSony Chacko
487629263acSSony Chacko if (lock)
488629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
489629263acSSony Chacko
490629263acSSony Chacko return 0;
491629263acSSony Chacko }
492629263acSSony Chacko
493629263acSSony Chacko static int
qlcnic_83xx_idc_enter_need_reset_state(struct qlcnic_adapter * adapter,int lock)494629263acSSony Chacko qlcnic_83xx_idc_enter_need_reset_state(struct qlcnic_adapter *adapter, int lock)
495629263acSSony Chacko {
496629263acSSony Chacko if (lock) {
497629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter))
498629263acSSony Chacko return -EBUSY;
499629263acSSony Chacko }
500629263acSSony Chacko
501629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,
502629263acSSony Chacko QLC_83XX_IDC_DEV_NEED_RESET);
503629263acSSony Chacko
504629263acSSony Chacko if (lock)
505629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
506629263acSSony Chacko
507629263acSSony Chacko return 0;
508629263acSSony Chacko }
509629263acSSony Chacko
qlcnic_83xx_idc_enter_ready_state(struct qlcnic_adapter * adapter,int lock)510629263acSSony Chacko static int qlcnic_83xx_idc_enter_ready_state(struct qlcnic_adapter *adapter,
511629263acSSony Chacko int lock)
512629263acSSony Chacko {
513629263acSSony Chacko if (lock) {
514629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter))
515629263acSSony Chacko return -EBUSY;
516629263acSSony Chacko }
517629263acSSony Chacko
518629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_READY);
519629263acSSony Chacko if (lock)
520629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
521629263acSSony Chacko
522629263acSSony Chacko return 0;
523629263acSSony Chacko }
524629263acSSony Chacko
525629263acSSony Chacko /**
526629263acSSony Chacko * qlcnic_83xx_idc_find_reset_owner_id
527629263acSSony Chacko *
528629263acSSony Chacko * @adapter: adapter structure
529629263acSSony Chacko *
530629263acSSony Chacko * NIC gets precedence over ISCSI and ISCSI has precedence over FCOE.
531629263acSSony Chacko * Within the same class, function with lowest PCI ID assumes ownership
532629263acSSony Chacko *
533629263acSSony Chacko * Returns: reset owner id or failure indication (-EIO)
534629263acSSony Chacko *
535629263acSSony Chacko **/
qlcnic_83xx_idc_find_reset_owner_id(struct qlcnic_adapter * adapter)536629263acSSony Chacko static int qlcnic_83xx_idc_find_reset_owner_id(struct qlcnic_adapter *adapter)
537629263acSSony Chacko {
538629263acSSony Chacko u32 reg, reg1, reg2, i, j, owner, class;
539629263acSSony Chacko
540629263acSSony Chacko reg1 = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_PARTITION_INFO_1);
541629263acSSony Chacko reg2 = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_PARTITION_INFO_2);
542629263acSSony Chacko owner = QLCNIC_TYPE_NIC;
543629263acSSony Chacko i = 0;
544629263acSSony Chacko j = 0;
545629263acSSony Chacko reg = reg1;
546629263acSSony Chacko
547629263acSSony Chacko do {
548629263acSSony Chacko class = (((reg & (0xF << j * 4)) >> j * 4) & 0x3);
549629263acSSony Chacko if (class == owner)
550629263acSSony Chacko break;
551629263acSSony Chacko if (i == (QLC_83XX_IDC_MAX_FUNC_PER_PARTITION_INFO - 1)) {
552629263acSSony Chacko reg = reg2;
553629263acSSony Chacko j = 0;
554629263acSSony Chacko } else {
555629263acSSony Chacko j++;
556629263acSSony Chacko }
557629263acSSony Chacko
558629263acSSony Chacko if (i == (QLC_83XX_IDC_MAX_CNA_FUNCTIONS - 1)) {
559629263acSSony Chacko if (owner == QLCNIC_TYPE_NIC)
560629263acSSony Chacko owner = QLCNIC_TYPE_ISCSI;
561629263acSSony Chacko else if (owner == QLCNIC_TYPE_ISCSI)
562629263acSSony Chacko owner = QLCNIC_TYPE_FCOE;
563629263acSSony Chacko else if (owner == QLCNIC_TYPE_FCOE)
564629263acSSony Chacko return -EIO;
565629263acSSony Chacko reg = reg1;
566629263acSSony Chacko j = 0;
567629263acSSony Chacko i = 0;
568629263acSSony Chacko }
569629263acSSony Chacko } while (i++ < QLC_83XX_IDC_MAX_CNA_FUNCTIONS);
570629263acSSony Chacko
571629263acSSony Chacko return i;
572629263acSSony Chacko }
573629263acSSony Chacko
qlcnic_83xx_idc_restart_hw(struct qlcnic_adapter * adapter,int lock)574629263acSSony Chacko static int qlcnic_83xx_idc_restart_hw(struct qlcnic_adapter *adapter, int lock)
575629263acSSony Chacko {
576629263acSSony Chacko int ret = 0;
577629263acSSony Chacko
578629263acSSony Chacko ret = qlcnic_83xx_restart_hw(adapter);
579629263acSSony Chacko
580629263acSSony Chacko if (ret) {
581629263acSSony Chacko qlcnic_83xx_idc_enter_failed_state(adapter, lock);
582629263acSSony Chacko } else {
583629263acSSony Chacko qlcnic_83xx_idc_clear_registers(adapter, lock);
584629263acSSony Chacko ret = qlcnic_83xx_idc_enter_ready_state(adapter, lock);
585629263acSSony Chacko }
586629263acSSony Chacko
587629263acSSony Chacko return ret;
588629263acSSony Chacko }
589629263acSSony Chacko
qlcnic_83xx_idc_check_fan_failure(struct qlcnic_adapter * adapter)590629263acSSony Chacko static int qlcnic_83xx_idc_check_fan_failure(struct qlcnic_adapter *adapter)
591629263acSSony Chacko {
592629263acSSony Chacko u32 status;
593629263acSSony Chacko
594629263acSSony Chacko status = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS1);
595629263acSSony Chacko
596629263acSSony Chacko if (status & QLCNIC_RCODE_FATAL_ERROR) {
597629263acSSony Chacko dev_err(&adapter->pdev->dev,
598629263acSSony Chacko "peg halt status1=0x%x\n", status);
599629263acSSony Chacko if (QLCNIC_FWERROR_CODE(status) == QLCNIC_FWERROR_FAN_FAILURE) {
600629263acSSony Chacko dev_err(&adapter->pdev->dev,
601629263acSSony Chacko "On board active cooling fan failed. "
602629263acSSony Chacko "Device has been halted.\n");
603629263acSSony Chacko dev_err(&adapter->pdev->dev,
604629263acSSony Chacko "Replace the adapter.\n");
605629263acSSony Chacko return -EIO;
606629263acSSony Chacko }
607629263acSSony Chacko }
608629263acSSony Chacko
609629263acSSony Chacko return 0;
610629263acSSony Chacko }
611629263acSSony Chacko
qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter * adapter)612486a5bc7SRajesh Borundia int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
613629263acSSony Chacko {
614f036e4f4SRajesh Borundia int err;
615f036e4f4SRajesh Borundia
616068a8d19SManish Chopra qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox);
617068a8d19SManish Chopra qlcnic_83xx_enable_mbx_interrupt(adapter);
618068a8d19SManish Chopra
6199b0fff2aSSucheta Chakraborty qlcnic_83xx_initialize_nic(adapter, 1);
620d5fcff04SHimanshu Madhani
621f036e4f4SRajesh Borundia err = qlcnic_sriov_pf_reinit(adapter);
622f036e4f4SRajesh Borundia if (err)
623f036e4f4SRajesh Borundia return err;
624f036e4f4SRajesh Borundia
625e5c4e6c6SManish Chopra qlcnic_83xx_enable_mbx_interrupt(adapter);
626629263acSSony Chacko
627629263acSSony Chacko if (qlcnic_83xx_configure_opmode(adapter)) {
628629263acSSony Chacko qlcnic_83xx_idc_enter_failed_state(adapter, 1);
629629263acSSony Chacko return -EIO;
630629263acSSony Chacko }
631629263acSSony Chacko
632629263acSSony Chacko if (adapter->nic_ops->init_driver(adapter)) {
633629263acSSony Chacko qlcnic_83xx_idc_enter_failed_state(adapter, 1);
634629263acSSony Chacko return -EIO;
635629263acSSony Chacko }
636629263acSSony Chacko
63724866d15SHimanshu Madhani if (adapter->portnum == 0)
6388af3f33dSPratik Pujar qlcnic_set_drv_version(adapter);
63914d385b9SSucheta Chakraborty
6401de899d3SSucheta Chakraborty qlcnic_dcb_get_info(adapter->dcb);
641629263acSSony Chacko qlcnic_83xx_idc_attach_driver(adapter);
642629263acSSony Chacko
643629263acSSony Chacko return 0;
644629263acSSony Chacko }
645629263acSSony Chacko
qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter * adapter)646629263acSSony Chacko static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)
647629263acSSony Chacko {
648536faa61SSony Chacko struct qlcnic_hardware_context *ahw = adapter->ahw;
649536faa61SSony Chacko
650629263acSSony Chacko qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1);
651629263acSSony Chacko qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
652629263acSSony Chacko set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
653536faa61SSony Chacko
654536faa61SSony Chacko ahw->idc.quiesce_req = 0;
655536faa61SSony Chacko ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;
656536faa61SSony Chacko ahw->idc.err_code = 0;
657536faa61SSony Chacko ahw->idc.collect_dump = 0;
658536faa61SSony Chacko ahw->reset_context = 0;
659536faa61SSony Chacko adapter->tx_timeo_cnt = 0;
660099907faSSony Chacko ahw->idc.delay_reset = 0;
661536faa61SSony Chacko
662536faa61SSony Chacko clear_bit(__QLCNIC_RESETTING, &adapter->state);
663629263acSSony Chacko }
664629263acSSony Chacko
665629263acSSony Chacko /**
666629263acSSony Chacko * qlcnic_83xx_idc_ready_state_entry
667629263acSSony Chacko *
668629263acSSony Chacko * @adapter: adapter structure
669629263acSSony Chacko *
670629263acSSony Chacko * Perform ready state initialization, this routine will get invoked only
671629263acSSony Chacko * once from READY state.
672629263acSSony Chacko *
673629263acSSony Chacko * Returns: Error code or Success(0)
674629263acSSony Chacko *
675629263acSSony Chacko **/
qlcnic_83xx_idc_ready_state_entry(struct qlcnic_adapter * adapter)676629263acSSony Chacko int qlcnic_83xx_idc_ready_state_entry(struct qlcnic_adapter *adapter)
677629263acSSony Chacko {
678629263acSSony Chacko struct qlcnic_hardware_context *ahw = adapter->ahw;
679629263acSSony Chacko
680629263acSSony Chacko if (ahw->idc.prev_state != QLC_83XX_IDC_DEV_READY) {
681629263acSSony Chacko qlcnic_83xx_idc_update_idc_params(adapter);
682629263acSSony Chacko /* Re-attach the device if required */
683629263acSSony Chacko if ((ahw->idc.prev_state == QLC_83XX_IDC_DEV_NEED_RESET) ||
684629263acSSony Chacko (ahw->idc.prev_state == QLC_83XX_IDC_DEV_INIT)) {
685629263acSSony Chacko if (qlcnic_83xx_idc_reattach_driver(adapter))
686629263acSSony Chacko return -EIO;
687629263acSSony Chacko }
688629263acSSony Chacko }
689629263acSSony Chacko
690629263acSSony Chacko return 0;
691629263acSSony Chacko }
692629263acSSony Chacko
693d71170fbSSony Chacko /**
694d71170fbSSony Chacko * qlcnic_83xx_idc_vnic_pf_entry
695d71170fbSSony Chacko *
696d71170fbSSony Chacko * @adapter: adapter structure
697d71170fbSSony Chacko *
698d71170fbSSony Chacko * Ensure vNIC mode privileged function starts only after vNIC mode is
699d71170fbSSony Chacko * enabled by management function.
700d71170fbSSony Chacko * If vNIC mode is ready, start initialization.
701d71170fbSSony Chacko *
702d71170fbSSony Chacko * Returns: -EIO or 0
703d71170fbSSony Chacko *
704d71170fbSSony Chacko **/
qlcnic_83xx_idc_vnic_pf_entry(struct qlcnic_adapter * adapter)705d71170fbSSony Chacko int qlcnic_83xx_idc_vnic_pf_entry(struct qlcnic_adapter *adapter)
706d71170fbSSony Chacko {
707d71170fbSSony Chacko u32 state;
708d71170fbSSony Chacko struct qlcnic_hardware_context *ahw = adapter->ahw;
709d71170fbSSony Chacko
710d71170fbSSony Chacko /* Privileged function waits till mgmt function enables VNIC mode */
711d71170fbSSony Chacko state = QLCRDX(adapter->ahw, QLC_83XX_VNIC_STATE);
712d71170fbSSony Chacko if (state != QLCNIC_DEV_NPAR_OPER) {
713d71170fbSSony Chacko if (!ahw->idc.vnic_wait_limit--) {
714d71170fbSSony Chacko qlcnic_83xx_idc_enter_failed_state(adapter, 1);
715d71170fbSSony Chacko return -EIO;
716d71170fbSSony Chacko }
717d71170fbSSony Chacko dev_info(&adapter->pdev->dev, "vNIC mode disabled\n");
718d71170fbSSony Chacko return -EIO;
719d71170fbSSony Chacko
720d71170fbSSony Chacko } else {
721d71170fbSSony Chacko /* Perform one time initialization from ready state */
722d71170fbSSony Chacko if (ahw->idc.vnic_state != QLCNIC_DEV_NPAR_OPER) {
723d71170fbSSony Chacko qlcnic_83xx_idc_update_idc_params(adapter);
724d71170fbSSony Chacko
725d71170fbSSony Chacko /* If the previous state is UNKNOWN, device will be
726d71170fbSSony Chacko already attached properly by Init routine*/
727d71170fbSSony Chacko if (ahw->idc.prev_state != QLC_83XX_IDC_DEV_UNKNOWN) {
728d71170fbSSony Chacko if (qlcnic_83xx_idc_reattach_driver(adapter))
729d71170fbSSony Chacko return -EIO;
730d71170fbSSony Chacko }
731d71170fbSSony Chacko adapter->ahw->idc.vnic_state = QLCNIC_DEV_NPAR_OPER;
732d71170fbSSony Chacko dev_info(&adapter->pdev->dev, "vNIC mode enabled\n");
733d71170fbSSony Chacko }
734d71170fbSSony Chacko }
735d71170fbSSony Chacko
736d71170fbSSony Chacko return 0;
737d71170fbSSony Chacko }
738d71170fbSSony Chacko
qlcnic_83xx_idc_unknown_state(struct qlcnic_adapter * adapter)739629263acSSony Chacko static int qlcnic_83xx_idc_unknown_state(struct qlcnic_adapter *adapter)
740629263acSSony Chacko {
741629263acSSony Chacko adapter->ahw->idc.err_code = -EIO;
742629263acSSony Chacko dev_err(&adapter->pdev->dev,
743629263acSSony Chacko "%s: Device in unknown state\n", __func__);
74430fa15f6SManish Chopra clear_bit(__QLCNIC_RESETTING, &adapter->state);
745629263acSSony Chacko return 0;
746629263acSSony Chacko }
747629263acSSony Chacko
748629263acSSony Chacko /**
7499f2e6fb6SYang Shen * qlcnic_83xx_idc_cold_state_handler
750629263acSSony Chacko *
751629263acSSony Chacko * @adapter: adapter structure
752629263acSSony Chacko *
753629263acSSony Chacko * If HW is up and running device will enter READY state.
754629263acSSony Chacko * If firmware image from host needs to be loaded, device is
755629263acSSony Chacko * forced to start with the file firmware image.
756629263acSSony Chacko *
757629263acSSony Chacko * Returns: Error code or Success(0)
758629263acSSony Chacko *
759629263acSSony Chacko **/
qlcnic_83xx_idc_cold_state_handler(struct qlcnic_adapter * adapter)760629263acSSony Chacko static int qlcnic_83xx_idc_cold_state_handler(struct qlcnic_adapter *adapter)
761629263acSSony Chacko {
762629263acSSony Chacko qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 0);
763629263acSSony Chacko qlcnic_83xx_idc_update_audit_reg(adapter, 1, 0);
764629263acSSony Chacko
765629263acSSony Chacko if (qlcnic_load_fw_file) {
766629263acSSony Chacko qlcnic_83xx_idc_restart_hw(adapter, 0);
767629263acSSony Chacko } else {
768629263acSSony Chacko if (qlcnic_83xx_check_hw_status(adapter)) {
769629263acSSony Chacko qlcnic_83xx_idc_enter_failed_state(adapter, 0);
770629263acSSony Chacko return -EIO;
771629263acSSony Chacko } else {
772629263acSSony Chacko qlcnic_83xx_idc_enter_ready_state(adapter, 0);
773629263acSSony Chacko }
774629263acSSony Chacko }
775629263acSSony Chacko return 0;
776629263acSSony Chacko }
777629263acSSony Chacko
778629263acSSony Chacko /**
779629263acSSony Chacko * qlcnic_83xx_idc_init_state
780629263acSSony Chacko *
781629263acSSony Chacko * @adapter: adapter structure
782629263acSSony Chacko *
783629263acSSony Chacko * Reset owner will restart the device from this state.
784629263acSSony Chacko * Device will enter failed state if it remains
785629263acSSony Chacko * in this state for more than DEV_INIT time limit.
786629263acSSony Chacko *
787629263acSSony Chacko * Returns: Error code or Success(0)
788629263acSSony Chacko *
789629263acSSony Chacko **/
qlcnic_83xx_idc_init_state(struct qlcnic_adapter * adapter)790629263acSSony Chacko static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter)
791629263acSSony Chacko {
792629263acSSony Chacko int timeout, ret = 0;
793629263acSSony Chacko u32 owner;
794629263acSSony Chacko
795629263acSSony Chacko timeout = QLC_83XX_IDC_INIT_TIMEOUT_SECS;
796629263acSSony Chacko if (adapter->ahw->idc.prev_state == QLC_83XX_IDC_DEV_NEED_RESET) {
797629263acSSony Chacko owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
798629263acSSony Chacko if (adapter->ahw->pci_func == owner)
799629263acSSony Chacko ret = qlcnic_83xx_idc_restart_hw(adapter, 1);
800629263acSSony Chacko } else {
801629263acSSony Chacko ret = qlcnic_83xx_idc_check_timeout(adapter, timeout);
802629263acSSony Chacko }
803629263acSSony Chacko
804629263acSSony Chacko return ret;
805629263acSSony Chacko }
806629263acSSony Chacko
807629263acSSony Chacko /**
808629263acSSony Chacko * qlcnic_83xx_idc_ready_state
809629263acSSony Chacko *
810629263acSSony Chacko * @adapter: adapter structure
811629263acSSony Chacko *
812629263acSSony Chacko * Perform IDC protocol specicifed actions after monitoring device state and
813629263acSSony Chacko * events.
814629263acSSony Chacko *
815629263acSSony Chacko * Returns: Error code or Success(0)
816629263acSSony Chacko *
817629263acSSony Chacko **/
qlcnic_83xx_idc_ready_state(struct qlcnic_adapter * adapter)818629263acSSony Chacko static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
819629263acSSony Chacko {
820629263acSSony Chacko struct qlcnic_hardware_context *ahw = adapter->ahw;
821068a8d19SManish Chopra struct qlcnic_mailbox *mbx = ahw->mailbox;
822629263acSSony Chacko int ret = 0;
823068a8d19SManish Chopra u32 val;
824629263acSSony Chacko
825629263acSSony Chacko /* Perform NIC configuration based ready state entry actions */
826629263acSSony Chacko if (ahw->idc.state_entry(adapter))
827629263acSSony Chacko return -EIO;
828629263acSSony Chacko
829629263acSSony Chacko if (qlcnic_check_temp(adapter)) {
830629263acSSony Chacko if (ahw->temp == QLCNIC_TEMP_PANIC) {
831629263acSSony Chacko qlcnic_83xx_idc_check_fan_failure(adapter);
832629263acSSony Chacko dev_err(&adapter->pdev->dev,
833629263acSSony Chacko "Error: device temperature %d above limits\n",
834629263acSSony Chacko adapter->ahw->temp);
835068a8d19SManish Chopra clear_bit(QLC_83XX_MBX_READY, &mbx->status);
836629263acSSony Chacko set_bit(__QLCNIC_RESETTING, &adapter->state);
837629263acSSony Chacko qlcnic_83xx_idc_detach_driver(adapter);
838629263acSSony Chacko qlcnic_83xx_idc_enter_failed_state(adapter, 1);
839629263acSSony Chacko return -EIO;
840629263acSSony Chacko }
841629263acSSony Chacko }
842629263acSSony Chacko
843629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
844629263acSSony Chacko ret = qlcnic_83xx_check_heartbeat(adapter);
845629263acSSony Chacko if (ret) {
846629263acSSony Chacko adapter->flags |= QLCNIC_FW_HANG;
847629263acSSony Chacko if (!(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {
848068a8d19SManish Chopra clear_bit(QLC_83XX_MBX_READY, &mbx->status);
849629263acSSony Chacko set_bit(__QLCNIC_RESETTING, &adapter->state);
850629263acSSony Chacko qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
851891e71b1SPratik Pujar } else {
85230fa15f6SManish Chopra netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
85330fa15f6SManish Chopra __func__);
85430fa15f6SManish Chopra qlcnic_83xx_idc_enter_failed_state(adapter, 1);
855629263acSSony Chacko }
856629263acSSony Chacko return -EIO;
857629263acSSony Chacko }
858629263acSSony Chacko
859629263acSSony Chacko if ((val & QLC_83XX_IDC_GRACEFULL_RESET) || ahw->idc.collect_dump) {
860068a8d19SManish Chopra clear_bit(QLC_83XX_MBX_READY, &mbx->status);
861068a8d19SManish Chopra
862629263acSSony Chacko /* Move to need reset state and prepare for reset */
863629263acSSony Chacko qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
864629263acSSony Chacko return ret;
865629263acSSony Chacko }
866629263acSSony Chacko
867629263acSSony Chacko /* Check for soft reset request */
868629263acSSony Chacko if (ahw->reset_context &&
869629263acSSony Chacko !(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {
870536faa61SSony Chacko adapter->ahw->reset_context = 0;
871629263acSSony Chacko qlcnic_83xx_idc_tx_soft_reset(adapter);
872629263acSSony Chacko return ret;
873629263acSSony Chacko }
874629263acSSony Chacko
875629263acSSony Chacko /* Move to need quiesce state if requested */
876629263acSSony Chacko if (adapter->ahw->idc.quiesce_req) {
877629263acSSony Chacko qlcnic_83xx_idc_enter_need_quiesce(adapter, 1);
878629263acSSony Chacko qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
879629263acSSony Chacko return ret;
880629263acSSony Chacko }
881629263acSSony Chacko
882629263acSSony Chacko return ret;
883629263acSSony Chacko }
884629263acSSony Chacko
885629263acSSony Chacko /**
886629263acSSony Chacko * qlcnic_83xx_idc_need_reset_state
887629263acSSony Chacko *
888629263acSSony Chacko * @adapter: adapter structure
889629263acSSony Chacko *
890629263acSSony Chacko * Device will remain in this state until:
891dbedd44eSJoe Perches * Reset request ACK's are received from all the functions
892629263acSSony Chacko * Wait time exceeds max time limit
893629263acSSony Chacko *
894629263acSSony Chacko * Returns: Error code or Success(0)
895629263acSSony Chacko *
896629263acSSony Chacko **/
qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter * adapter)897629263acSSony Chacko static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter)
898629263acSSony Chacko {
899068a8d19SManish Chopra struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
900629263acSSony Chacko int ret = 0;
901629263acSSony Chacko
902629263acSSony Chacko if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) {
903629263acSSony Chacko qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
904629263acSSony Chacko set_bit(__QLCNIC_RESETTING, &adapter->state);
905068a8d19SManish Chopra clear_bit(QLC_83XX_MBX_READY, &mbx->status);
90634e8c406SHimanshu Madhani if (adapter->ahw->nic_mode == QLCNIC_VNIC_MODE)
907d71170fbSSony Chacko qlcnic_83xx_disable_vnic_mode(adapter, 1);
908099907faSSony Chacko
909099907faSSony Chacko if (qlcnic_check_diag_status(adapter)) {
910099907faSSony Chacko dev_info(&adapter->pdev->dev,
911099907faSSony Chacko "%s: Wait for diag completion\n", __func__);
912099907faSSony Chacko adapter->ahw->idc.delay_reset = 1;
913099907faSSony Chacko return 0;
914099907faSSony Chacko } else {
915099907faSSony Chacko qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);
916629263acSSony Chacko qlcnic_83xx_idc_detach_driver(adapter);
917629263acSSony Chacko }
918099907faSSony Chacko }
919629263acSSony Chacko
920099907faSSony Chacko if (qlcnic_check_diag_status(adapter)) {
921099907faSSony Chacko dev_info(&adapter->pdev->dev,
922099907faSSony Chacko "%s: Wait for diag completion\n", __func__);
923099907faSSony Chacko return -1;
924099907faSSony Chacko } else {
925099907faSSony Chacko if (adapter->ahw->idc.delay_reset) {
926099907faSSony Chacko qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);
927099907faSSony Chacko qlcnic_83xx_idc_detach_driver(adapter);
928099907faSSony Chacko adapter->ahw->idc.delay_reset = 0;
929099907faSSony Chacko }
930099907faSSony Chacko
931099907faSSony Chacko /* Check for ACK from other functions */
932629263acSSony Chacko ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter);
933629263acSSony Chacko if (ret) {
934629263acSSony Chacko dev_info(&adapter->pdev->dev,
935629263acSSony Chacko "%s: Waiting for reset ACK\n", __func__);
936099907faSSony Chacko return -1;
937099907faSSony Chacko }
938629263acSSony Chacko }
939629263acSSony Chacko
940629263acSSony Chacko /* Transit to INIT state and restart the HW */
941629263acSSony Chacko qlcnic_83xx_idc_enter_init_state(adapter, 1);
942629263acSSony Chacko
943629263acSSony Chacko return ret;
944629263acSSony Chacko }
945629263acSSony Chacko
qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter * adapter)946629263acSSony Chacko static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter)
947629263acSSony Chacko {
948629263acSSony Chacko dev_err(&adapter->pdev->dev, "%s: TBD\n", __func__);
949629263acSSony Chacko return 0;
950629263acSSony Chacko }
951629263acSSony Chacko
qlcnic_83xx_idc_failed_state(struct qlcnic_adapter * adapter)95230fa15f6SManish Chopra static void qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
953629263acSSony Chacko {
95430fa15f6SManish Chopra struct qlcnic_hardware_context *ahw = adapter->ahw;
95530fa15f6SManish Chopra u32 val, owner;
956629263acSSony Chacko
95730fa15f6SManish Chopra val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
95830fa15f6SManish Chopra if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
95930fa15f6SManish Chopra owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
96030fa15f6SManish Chopra if (ahw->pci_func == owner) {
96130fa15f6SManish Chopra qlcnic_83xx_stop_hw(adapter);
96230fa15f6SManish Chopra qlcnic_dump_fw(adapter);
96330fa15f6SManish Chopra }
96430fa15f6SManish Chopra }
96530fa15f6SManish Chopra
96630fa15f6SManish Chopra netdev_warn(adapter->netdev, "%s: Reboot will be required to recover the adapter!!\n",
96730fa15f6SManish Chopra __func__);
96830fa15f6SManish Chopra clear_bit(__QLCNIC_RESETTING, &adapter->state);
96930fa15f6SManish Chopra ahw->idc.err_code = -EIO;
97030fa15f6SManish Chopra
97130fa15f6SManish Chopra return;
972629263acSSony Chacko }
973629263acSSony Chacko
qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter * adapter)974629263acSSony Chacko static int qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter *adapter)
975629263acSSony Chacko {
976629263acSSony Chacko dev_info(&adapter->pdev->dev, "%s: TBD\n", __func__);
977629263acSSony Chacko return 0;
978629263acSSony Chacko }
979629263acSSony Chacko
qlcnic_83xx_idc_check_state_validity(struct qlcnic_adapter * adapter,u32 state)980629263acSSony Chacko static int qlcnic_83xx_idc_check_state_validity(struct qlcnic_adapter *adapter,
981629263acSSony Chacko u32 state)
982629263acSSony Chacko {
983629263acSSony Chacko u32 cur, prev, next;
984629263acSSony Chacko
985629263acSSony Chacko cur = adapter->ahw->idc.curr_state;
986629263acSSony Chacko prev = adapter->ahw->idc.prev_state;
987629263acSSony Chacko next = state;
988629263acSSony Chacko
989629263acSSony Chacko if ((next < QLC_83XX_IDC_DEV_COLD) ||
990629263acSSony Chacko (next > QLC_83XX_IDC_DEV_QUISCENT)) {
991629263acSSony Chacko dev_err(&adapter->pdev->dev,
992629263acSSony Chacko "%s: curr %d, prev %d, next state %d is invalid\n",
993629263acSSony Chacko __func__, cur, prev, state);
994629263acSSony Chacko return 1;
995629263acSSony Chacko }
996629263acSSony Chacko
997629263acSSony Chacko if ((cur == QLC_83XX_IDC_DEV_UNKNOWN) &&
998629263acSSony Chacko (prev == QLC_83XX_IDC_DEV_UNKNOWN)) {
999629263acSSony Chacko if ((next != QLC_83XX_IDC_DEV_COLD) &&
1000629263acSSony Chacko (next != QLC_83XX_IDC_DEV_READY)) {
1001629263acSSony Chacko dev_err(&adapter->pdev->dev,
1002629263acSSony Chacko "%s: failed, cur %d prev %d next %d\n",
1003629263acSSony Chacko __func__, cur, prev, next);
1004629263acSSony Chacko return 1;
1005629263acSSony Chacko }
1006629263acSSony Chacko }
1007629263acSSony Chacko
1008629263acSSony Chacko if (next == QLC_83XX_IDC_DEV_INIT) {
1009629263acSSony Chacko if ((prev != QLC_83XX_IDC_DEV_INIT) &&
1010629263acSSony Chacko (prev != QLC_83XX_IDC_DEV_COLD) &&
1011629263acSSony Chacko (prev != QLC_83XX_IDC_DEV_NEED_RESET)) {
1012629263acSSony Chacko dev_err(&adapter->pdev->dev,
1013629263acSSony Chacko "%s: failed, cur %d prev %d next %d\n",
1014629263acSSony Chacko __func__, cur, prev, next);
1015629263acSSony Chacko return 1;
1016629263acSSony Chacko }
1017629263acSSony Chacko }
1018629263acSSony Chacko
1019629263acSSony Chacko return 0;
1020629263acSSony Chacko }
1021629263acSSony Chacko
10222b3d7b75SShahed Shaikh #define QLC_83XX_ENCAP_TYPE_VXLAN BIT_1
10232b3d7b75SShahed Shaikh #define QLC_83XX_MATCH_ENCAP_ID BIT_2
10242b3d7b75SShahed Shaikh #define QLC_83XX_SET_VXLAN_UDP_DPORT BIT_3
10252b3d7b75SShahed Shaikh #define QLC_83XX_VXLAN_UDP_DPORT(PORT) ((PORT & 0xffff) << 16)
10262b3d7b75SShahed Shaikh
10272b3d7b75SShahed Shaikh #define QLCNIC_ENABLE_INGRESS_ENCAP_PARSING 1
10282b3d7b75SShahed Shaikh #define QLCNIC_DISABLE_INGRESS_ENCAP_PARSING 0
10292b3d7b75SShahed Shaikh
qlcnic_set_vxlan_port(struct qlcnic_adapter * adapter,u16 port)103078c6bc2bSJakub Kicinski int qlcnic_set_vxlan_port(struct qlcnic_adapter *adapter, u16 port)
10312b3d7b75SShahed Shaikh {
10322b3d7b75SShahed Shaikh struct qlcnic_cmd_args cmd;
10332b3d7b75SShahed Shaikh int ret = 0;
10342b3d7b75SShahed Shaikh
10352b3d7b75SShahed Shaikh memset(&cmd, 0, sizeof(cmd));
10362b3d7b75SShahed Shaikh
10372b3d7b75SShahed Shaikh ret = qlcnic_alloc_mbx_args(&cmd, adapter,
10382b3d7b75SShahed Shaikh QLCNIC_CMD_INIT_NIC_FUNC);
10392b3d7b75SShahed Shaikh if (ret)
10402b3d7b75SShahed Shaikh return ret;
10412b3d7b75SShahed Shaikh
10422b3d7b75SShahed Shaikh cmd.req.arg[1] = QLC_83XX_MULTI_TENANCY_INFO;
10432b3d7b75SShahed Shaikh cmd.req.arg[2] = QLC_83XX_ENCAP_TYPE_VXLAN |
10442b3d7b75SShahed Shaikh QLC_83XX_SET_VXLAN_UDP_DPORT |
10452b3d7b75SShahed Shaikh QLC_83XX_VXLAN_UDP_DPORT(port);
10462b3d7b75SShahed Shaikh
10472b3d7b75SShahed Shaikh ret = qlcnic_issue_cmd(adapter, &cmd);
10482b3d7b75SShahed Shaikh if (ret)
10492b3d7b75SShahed Shaikh netdev_err(adapter->netdev,
10502b3d7b75SShahed Shaikh "Failed to set VXLAN port %d in adapter\n",
10512b3d7b75SShahed Shaikh port);
10522b3d7b75SShahed Shaikh
10532b3d7b75SShahed Shaikh qlcnic_free_mbx_args(&cmd);
10542b3d7b75SShahed Shaikh
10552b3d7b75SShahed Shaikh return ret;
10562b3d7b75SShahed Shaikh }
10572b3d7b75SShahed Shaikh
qlcnic_set_vxlan_parsing(struct qlcnic_adapter * adapter,u16 port)105878c6bc2bSJakub Kicinski int qlcnic_set_vxlan_parsing(struct qlcnic_adapter *adapter, u16 port)
10592b3d7b75SShahed Shaikh {
10602b3d7b75SShahed Shaikh struct qlcnic_cmd_args cmd;
10612b3d7b75SShahed Shaikh int ret = 0;
10622b3d7b75SShahed Shaikh
10632b3d7b75SShahed Shaikh memset(&cmd, 0, sizeof(cmd));
10642b3d7b75SShahed Shaikh
10652b3d7b75SShahed Shaikh ret = qlcnic_alloc_mbx_args(&cmd, adapter,
10662b3d7b75SShahed Shaikh QLCNIC_CMD_SET_INGRESS_ENCAP);
10672b3d7b75SShahed Shaikh if (ret)
10682b3d7b75SShahed Shaikh return ret;
10692b3d7b75SShahed Shaikh
107078c6bc2bSJakub Kicinski cmd.req.arg[1] = port ? QLCNIC_ENABLE_INGRESS_ENCAP_PARSING :
10712b3d7b75SShahed Shaikh QLCNIC_DISABLE_INGRESS_ENCAP_PARSING;
10722b3d7b75SShahed Shaikh
10732b3d7b75SShahed Shaikh ret = qlcnic_issue_cmd(adapter, &cmd);
10742b3d7b75SShahed Shaikh if (ret)
10752b3d7b75SShahed Shaikh netdev_err(adapter->netdev,
10762b3d7b75SShahed Shaikh "Failed to %s VXLAN parsing for port %d\n",
107778c6bc2bSJakub Kicinski port ? "enable" : "disable", port);
10782b3d7b75SShahed Shaikh else
10792b3d7b75SShahed Shaikh netdev_info(adapter->netdev,
10802b3d7b75SShahed Shaikh "%s VXLAN parsing for port %d\n",
108178c6bc2bSJakub Kicinski port ? "Enabled" : "Disabled", port);
10822b3d7b75SShahed Shaikh
10832b3d7b75SShahed Shaikh qlcnic_free_mbx_args(&cmd);
10842b3d7b75SShahed Shaikh
10852b3d7b75SShahed Shaikh return ret;
10862b3d7b75SShahed Shaikh }
10872b3d7b75SShahed Shaikh
qlcnic_83xx_periodic_tasks(struct qlcnic_adapter * adapter)1088629263acSSony Chacko static void qlcnic_83xx_periodic_tasks(struct qlcnic_adapter *adapter)
1089629263acSSony Chacko {
1090629263acSSony Chacko if (adapter->fhash.fnum)
1091629263acSSony Chacko qlcnic_prune_lb_filters(adapter);
1092629263acSSony Chacko }
1093629263acSSony Chacko
1094629263acSSony Chacko /**
1095629263acSSony Chacko * qlcnic_83xx_idc_poll_dev_state
1096629263acSSony Chacko *
1097629263acSSony Chacko * @work: kernel work queue structure used to schedule the function
1098629263acSSony Chacko *
1099629263acSSony Chacko * Poll device state periodically and perform state specific
1100629263acSSony Chacko * actions defined by Inter Driver Communication (IDC) protocol.
1101629263acSSony Chacko *
1102629263acSSony Chacko * Returns: None
1103629263acSSony Chacko *
1104629263acSSony Chacko **/
qlcnic_83xx_idc_poll_dev_state(struct work_struct * work)1105629263acSSony Chacko void qlcnic_83xx_idc_poll_dev_state(struct work_struct *work)
1106629263acSSony Chacko {
1107629263acSSony Chacko struct qlcnic_adapter *adapter;
1108629263acSSony Chacko u32 state;
1109629263acSSony Chacko
1110629263acSSony Chacko adapter = container_of(work, struct qlcnic_adapter, fw_work.work);
1111629263acSSony Chacko state = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE);
1112629263acSSony Chacko
1113629263acSSony Chacko if (qlcnic_83xx_idc_check_state_validity(adapter, state)) {
1114629263acSSony Chacko qlcnic_83xx_idc_log_state_history(adapter);
1115629263acSSony Chacko adapter->ahw->idc.curr_state = QLC_83XX_IDC_DEV_UNKNOWN;
1116629263acSSony Chacko } else {
1117629263acSSony Chacko adapter->ahw->idc.curr_state = state;
1118629263acSSony Chacko }
1119629263acSSony Chacko
1120629263acSSony Chacko switch (adapter->ahw->idc.curr_state) {
1121629263acSSony Chacko case QLC_83XX_IDC_DEV_READY:
1122629263acSSony Chacko qlcnic_83xx_idc_ready_state(adapter);
1123629263acSSony Chacko break;
1124629263acSSony Chacko case QLC_83XX_IDC_DEV_NEED_RESET:
1125629263acSSony Chacko qlcnic_83xx_idc_need_reset_state(adapter);
1126629263acSSony Chacko break;
1127629263acSSony Chacko case QLC_83XX_IDC_DEV_NEED_QUISCENT:
1128629263acSSony Chacko qlcnic_83xx_idc_need_quiesce_state(adapter);
1129629263acSSony Chacko break;
1130629263acSSony Chacko case QLC_83XX_IDC_DEV_FAILED:
1131629263acSSony Chacko qlcnic_83xx_idc_failed_state(adapter);
1132629263acSSony Chacko return;
1133629263acSSony Chacko case QLC_83XX_IDC_DEV_INIT:
1134629263acSSony Chacko qlcnic_83xx_idc_init_state(adapter);
1135629263acSSony Chacko break;
1136629263acSSony Chacko case QLC_83XX_IDC_DEV_QUISCENT:
1137629263acSSony Chacko qlcnic_83xx_idc_quiesce_state(adapter);
1138629263acSSony Chacko break;
1139629263acSSony Chacko default:
1140629263acSSony Chacko qlcnic_83xx_idc_unknown_state(adapter);
1141629263acSSony Chacko return;
1142629263acSSony Chacko }
1143629263acSSony Chacko adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state;
1144629263acSSony Chacko qlcnic_83xx_periodic_tasks(adapter);
1145629263acSSony Chacko
1146629263acSSony Chacko /* Re-schedule the function */
1147629263acSSony Chacko if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status))
1148629263acSSony Chacko qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
1149629263acSSony Chacko adapter->ahw->idc.delay);
1150629263acSSony Chacko }
1151629263acSSony Chacko
qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter * adapter)1152629263acSSony Chacko static void qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter *adapter)
1153629263acSSony Chacko {
1154629263acSSony Chacko u32 idc_params, val;
1155629263acSSony Chacko
11564324414fSSony Chacko if (qlcnic_83xx_flash_read32(adapter, QLC_83XX_IDC_FLASH_PARAM_ADDR,
1157629263acSSony Chacko (u8 *)&idc_params, 1)) {
1158629263acSSony Chacko dev_info(&adapter->pdev->dev,
1159629263acSSony Chacko "%s:failed to get IDC params from flash\n", __func__);
1160629263acSSony Chacko adapter->dev_init_timeo = QLC_83XX_IDC_INIT_TIMEOUT_SECS;
1161629263acSSony Chacko adapter->reset_ack_timeo = QLC_83XX_IDC_RESET_TIMEOUT_SECS;
1162629263acSSony Chacko } else {
1163629263acSSony Chacko adapter->dev_init_timeo = idc_params & 0xFFFF;
1164629263acSSony Chacko adapter->reset_ack_timeo = ((idc_params >> 16) & 0xFFFF);
1165629263acSSony Chacko }
1166629263acSSony Chacko
1167629263acSSony Chacko adapter->ahw->idc.curr_state = QLC_83XX_IDC_DEV_UNKNOWN;
1168629263acSSony Chacko adapter->ahw->idc.prev_state = QLC_83XX_IDC_DEV_UNKNOWN;
1169629263acSSony Chacko adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;
1170629263acSSony Chacko adapter->ahw->idc.err_code = 0;
1171629263acSSony Chacko adapter->ahw->idc.collect_dump = 0;
1172629263acSSony Chacko adapter->ahw->idc.name = (char **)qlc_83xx_idc_states;
1173629263acSSony Chacko
1174629263acSSony Chacko clear_bit(__QLCNIC_RESETTING, &adapter->state);
1175629263acSSony Chacko set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
1176629263acSSony Chacko
1177629263acSSony Chacko /* Check if reset recovery is disabled */
1178629263acSSony Chacko if (!qlcnic_auto_fw_reset) {
1179629263acSSony Chacko /* Propagate do not reset request to other functions */
1180629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1181629263acSSony Chacko val = val | QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY;
1182629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
1183629263acSSony Chacko }
1184629263acSSony Chacko }
1185629263acSSony Chacko
1186629263acSSony Chacko static int
qlcnic_83xx_idc_first_to_load_function_handler(struct qlcnic_adapter * adapter)1187629263acSSony Chacko qlcnic_83xx_idc_first_to_load_function_handler(struct qlcnic_adapter *adapter)
1188629263acSSony Chacko {
1189629263acSSony Chacko u32 state, val;
1190629263acSSony Chacko
1191629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter))
1192629263acSSony Chacko return -EIO;
1193629263acSSony Chacko
1194629263acSSony Chacko /* Clear driver lock register */
1195629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, 0);
1196629263acSSony Chacko if (qlcnic_83xx_idc_update_major_version(adapter, 0)) {
1197629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
1198629263acSSony Chacko return -EIO;
1199629263acSSony Chacko }
1200629263acSSony Chacko
1201629263acSSony Chacko state = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE);
1202629263acSSony Chacko if (qlcnic_83xx_idc_check_state_validity(adapter, state)) {
1203629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
1204629263acSSony Chacko return -EIO;
1205629263acSSony Chacko }
1206629263acSSony Chacko
1207629263acSSony Chacko if (state != QLC_83XX_IDC_DEV_COLD && qlcnic_load_fw_file) {
1208629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,
1209629263acSSony Chacko QLC_83XX_IDC_DEV_COLD);
1210629263acSSony Chacko state = QLC_83XX_IDC_DEV_COLD;
1211629263acSSony Chacko }
1212629263acSSony Chacko
1213629263acSSony Chacko adapter->ahw->idc.curr_state = state;
1214629263acSSony Chacko /* First to load function should cold boot the device */
1215629263acSSony Chacko if (state == QLC_83XX_IDC_DEV_COLD)
1216629263acSSony Chacko qlcnic_83xx_idc_cold_state_handler(adapter);
1217629263acSSony Chacko
1218629263acSSony Chacko /* Check if reset recovery is enabled */
1219629263acSSony Chacko if (qlcnic_auto_fw_reset) {
1220629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1221629263acSSony Chacko val = val & ~QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY;
1222629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
1223629263acSSony Chacko }
1224629263acSSony Chacko
1225629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
1226629263acSSony Chacko
1227629263acSSony Chacko return 0;
1228629263acSSony Chacko }
1229629263acSSony Chacko
qlcnic_83xx_idc_init(struct qlcnic_adapter * adapter)1230486a5bc7SRajesh Borundia int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter)
1231629263acSSony Chacko {
123281d0aeb0SSony Chacko int ret = -EIO;
123381d0aeb0SSony Chacko
1234629263acSSony Chacko qlcnic_83xx_setup_idc_parameters(adapter);
1235629263acSSony Chacko
123681d0aeb0SSony Chacko if (qlcnic_83xx_get_reset_instruction_template(adapter))
123781d0aeb0SSony Chacko return ret;
123881d0aeb0SSony Chacko
1239629263acSSony Chacko if (!qlcnic_83xx_idc_check_driver_presence_reg(adapter)) {
1240629263acSSony Chacko if (qlcnic_83xx_idc_first_to_load_function_handler(adapter))
1241629263acSSony Chacko return -EIO;
1242629263acSSony Chacko } else {
1243629263acSSony Chacko if (qlcnic_83xx_idc_check_major_version(adapter))
1244629263acSSony Chacko return -EIO;
1245629263acSSony Chacko }
1246629263acSSony Chacko
1247629263acSSony Chacko qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
1248629263acSSony Chacko
1249629263acSSony Chacko return 0;
1250629263acSSony Chacko }
1251629263acSSony Chacko
qlcnic_83xx_idc_exit(struct qlcnic_adapter * adapter)1252629263acSSony Chacko void qlcnic_83xx_idc_exit(struct qlcnic_adapter *adapter)
1253629263acSSony Chacko {
1254629263acSSony Chacko int id;
1255629263acSSony Chacko u32 val;
1256629263acSSony Chacko
1257629263acSSony Chacko while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
1258629263acSSony Chacko usleep_range(10000, 11000);
1259629263acSSony Chacko
1260629263acSSony Chacko id = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
1261629263acSSony Chacko id = id & 0xFF;
1262629263acSSony Chacko
1263629263acSSony Chacko if (id == adapter->portnum) {
1264629263acSSony Chacko dev_err(&adapter->pdev->dev,
1265629263acSSony Chacko "%s: wait for lock recovery.. %d\n", __func__, id);
1266629263acSSony Chacko msleep(20);
1267629263acSSony Chacko id = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
1268629263acSSony Chacko id = id & 0xFF;
1269629263acSSony Chacko }
1270629263acSSony Chacko
1271629263acSSony Chacko /* Clear driver presence bit */
1272629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
1273629263acSSony Chacko val = val & ~(1 << adapter->portnum);
1274629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val);
1275629263acSSony Chacko clear_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
1276629263acSSony Chacko clear_bit(__QLCNIC_RESETTING, &adapter->state);
1277629263acSSony Chacko
1278629263acSSony Chacko cancel_delayed_work_sync(&adapter->fw_work);
1279629263acSSony Chacko }
1280629263acSSony Chacko
qlcnic_83xx_idc_request_reset(struct qlcnic_adapter * adapter,u32 key)1281629263acSSony Chacko void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key)
1282629263acSSony Chacko {
1283629263acSSony Chacko u32 val;
1284629263acSSony Chacko
1285068a8d19SManish Chopra if (qlcnic_sriov_vf_check(adapter))
1286068a8d19SManish Chopra return;
1287068a8d19SManish Chopra
1288629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter)) {
1289629263acSSony Chacko dev_err(&adapter->pdev->dev,
1290629263acSSony Chacko "%s:failed, please retry\n", __func__);
1291629263acSSony Chacko return;
1292629263acSSony Chacko }
1293629263acSSony Chacko
1294629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
129530fa15f6SManish Chopra if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
129630fa15f6SManish Chopra netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
129730fa15f6SManish Chopra __func__);
129830fa15f6SManish Chopra qlcnic_83xx_idc_enter_failed_state(adapter, 0);
1299629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
1300629263acSSony Chacko return;
1301629263acSSony Chacko }
1302629263acSSony Chacko
1303629263acSSony Chacko if (key == QLCNIC_FORCE_FW_RESET) {
1304629263acSSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1305629263acSSony Chacko val = val | QLC_83XX_IDC_GRACEFULL_RESET;
1306629263acSSony Chacko QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
1307629263acSSony Chacko } else if (key == QLCNIC_FORCE_FW_DUMP_KEY) {
1308629263acSSony Chacko adapter->ahw->idc.collect_dump = 1;
1309629263acSSony Chacko }
1310629263acSSony Chacko
1311629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
1312629263acSSony Chacko return;
1313629263acSSony Chacko }
1314629263acSSony Chacko
qlcnic_83xx_copy_bootloader(struct qlcnic_adapter * adapter)1315629263acSSony Chacko static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)
1316629263acSSony Chacko {
1317629263acSSony Chacko u8 *p_cache;
1318629263acSSony Chacko u32 src, size;
1319629263acSSony Chacko u64 dest;
1320629263acSSony Chacko int ret = -EIO;
1321629263acSSony Chacko
1322629263acSSony Chacko src = QLC_83XX_BOOTLOADER_FLASH_ADDR;
1323629263acSSony Chacko dest = QLCRDX(adapter->ahw, QLCNIC_BOOTLOADER_ADDR);
1324629263acSSony Chacko size = QLCRDX(adapter->ahw, QLCNIC_BOOTLOADER_SIZE);
1325629263acSSony Chacko
1326629263acSSony Chacko /* alignment check */
1327629263acSSony Chacko if (size & 0xF)
1328629263acSSony Chacko size = (size + 16) & ~0xF;
1329629263acSSony Chacko
13303fc38e26SManish Chopra p_cache = vzalloc(size);
1331b2adaca9SJoe Perches if (p_cache == NULL)
1332629263acSSony Chacko return -ENOMEM;
1333b2adaca9SJoe Perches
1334629263acSSony Chacko ret = qlcnic_83xx_lockless_flash_read32(adapter, src, p_cache,
1335629263acSSony Chacko size / sizeof(u32));
1336629263acSSony Chacko if (ret) {
13373fc38e26SManish Chopra vfree(p_cache);
1338629263acSSony Chacko return ret;
1339629263acSSony Chacko }
1340629263acSSony Chacko /* 16 byte write to MS memory */
13418d37ba02SShahed Shaikh ret = qlcnic_ms_mem_write128(adapter, dest, (u32 *)p_cache,
1342629263acSSony Chacko size / 16);
1343629263acSSony Chacko if (ret) {
13443fc38e26SManish Chopra vfree(p_cache);
1345629263acSSony Chacko return ret;
1346629263acSSony Chacko }
13473fc38e26SManish Chopra vfree(p_cache);
1348629263acSSony Chacko
1349629263acSSony Chacko return ret;
1350629263acSSony Chacko }
1351629263acSSony Chacko
qlcnic_83xx_copy_fw_file(struct qlcnic_adapter * adapter)1352629263acSSony Chacko static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
1353629263acSSony Chacko {
13547000078aSPratik Pujar struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;
13557000078aSPratik Pujar const struct firmware *fw = fw_info->fw;
13563d8623e6SShahed Shaikh u32 dest, *p_cache, *temp;
13573d8623e6SShahed Shaikh __le32 *temp_le;
1358629263acSSony Chacko u8 data[16];
1359629263acSSony Chacko size_t size;
1360666eb96dSColin Ian King int i, ret;
13617000078aSPratik Pujar u64 addr;
1362629263acSSony Chacko
13630e90ad9bSShahed Shaikh temp = vzalloc(fw->size);
13643d8623e6SShahed Shaikh if (!temp) {
13653d8623e6SShahed Shaikh release_firmware(fw);
13663d8623e6SShahed Shaikh fw_info->fw = NULL;
13673d8623e6SShahed Shaikh return -ENOMEM;
13683d8623e6SShahed Shaikh }
13693d8623e6SShahed Shaikh
13703d8623e6SShahed Shaikh temp_le = (__le32 *)fw->data;
13713d8623e6SShahed Shaikh
13723d8623e6SShahed Shaikh /* FW image in file is in little endian, swap the data to nullify
13733d8623e6SShahed Shaikh * the effect of writel() operation on big endian platform.
13743d8623e6SShahed Shaikh */
13753d8623e6SShahed Shaikh for (i = 0; i < fw->size / sizeof(u32); i++)
13763d8623e6SShahed Shaikh temp[i] = __le32_to_cpu(temp_le[i]);
13773d8623e6SShahed Shaikh
1378629263acSSony Chacko dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR);
13797000078aSPratik Pujar size = (fw->size & ~0xF);
13803d8623e6SShahed Shaikh p_cache = temp;
1381629263acSSony Chacko addr = (u64)dest;
1382629263acSSony Chacko
13838d37ba02SShahed Shaikh ret = qlcnic_ms_mem_write128(adapter, addr,
13844e2e865dSJoe Perches p_cache, size / 16);
1385629263acSSony Chacko if (ret) {
1386629263acSSony Chacko dev_err(&adapter->pdev->dev, "MS memory write failed\n");
13873d8623e6SShahed Shaikh goto exit;
1388629263acSSony Chacko }
1389629263acSSony Chacko
1390629263acSSony Chacko /* alignment check */
13917000078aSPratik Pujar if (fw->size & 0xF) {
1392629263acSSony Chacko addr = dest + size;
13937000078aSPratik Pujar for (i = 0; i < (fw->size & 0xF); i++)
139415f1bb1fSShahed Shaikh data[i] = ((u8 *)temp)[size + i];
1395629263acSSony Chacko for (; i < 16; i++)
1396629263acSSony Chacko data[i] = 0;
13978d37ba02SShahed Shaikh ret = qlcnic_ms_mem_write128(adapter, addr,
1398629263acSSony Chacko (u32 *)data, 1);
1399629263acSSony Chacko if (ret) {
1400629263acSSony Chacko dev_err(&adapter->pdev->dev,
1401629263acSSony Chacko "MS memory write failed\n");
14023d8623e6SShahed Shaikh goto exit;
1403629263acSSony Chacko }
1404629263acSSony Chacko }
1405629263acSSony Chacko
14063d8623e6SShahed Shaikh exit:
14073d8623e6SShahed Shaikh release_firmware(fw);
14083d8623e6SShahed Shaikh fw_info->fw = NULL;
14090e90ad9bSShahed Shaikh vfree(temp);
14103d8623e6SShahed Shaikh
14113d8623e6SShahed Shaikh return ret;
1412629263acSSony Chacko }
1413629263acSSony Chacko
qlcnic_83xx_dump_pause_control_regs(struct qlcnic_adapter * adapter)1414629263acSSony Chacko static void qlcnic_83xx_dump_pause_control_regs(struct qlcnic_adapter *adapter)
1415629263acSSony Chacko {
1416629263acSSony Chacko int i, j;
1417629263acSSony Chacko u32 val = 0, val1 = 0, reg = 0;
14184bd8e738SHimanshu Madhani int err = 0;
1419629263acSSony Chacko
14204bd8e738SHimanshu Madhani val = QLCRD32(adapter, QLC_83XX_SRE_SHIM_REG, &err);
14214bd8e738SHimanshu Madhani if (err == -EIO)
14224bd8e738SHimanshu Madhani return;
1423629263acSSony Chacko dev_info(&adapter->pdev->dev, "SRE-Shim Ctrl:0x%x\n", val);
1424629263acSSony Chacko
1425629263acSSony Chacko for (j = 0; j < 2; j++) {
1426629263acSSony Chacko if (j == 0) {
1427629263acSSony Chacko dev_info(&adapter->pdev->dev,
1428629263acSSony Chacko "Port 0 RxB Pause Threshold Regs[TC7..TC0]:");
1429629263acSSony Chacko reg = QLC_83XX_PORT0_THRESHOLD;
1430629263acSSony Chacko } else if (j == 1) {
1431629263acSSony Chacko dev_info(&adapter->pdev->dev,
1432629263acSSony Chacko "Port 1 RxB Pause Threshold Regs[TC7..TC0]:");
1433629263acSSony Chacko reg = QLC_83XX_PORT1_THRESHOLD;
1434629263acSSony Chacko }
1435629263acSSony Chacko for (i = 0; i < 8; i++) {
14364bd8e738SHimanshu Madhani val = QLCRD32(adapter, reg + (i * 0x4), &err);
14374bd8e738SHimanshu Madhani if (err == -EIO)
14384bd8e738SHimanshu Madhani return;
1439629263acSSony Chacko dev_info(&adapter->pdev->dev, "0x%x ", val);
1440629263acSSony Chacko }
1441629263acSSony Chacko dev_info(&adapter->pdev->dev, "\n");
1442629263acSSony Chacko }
1443629263acSSony Chacko
1444629263acSSony Chacko for (j = 0; j < 2; j++) {
1445629263acSSony Chacko if (j == 0) {
1446629263acSSony Chacko dev_info(&adapter->pdev->dev,
1447629263acSSony Chacko "Port 0 RxB TC Max Cell Registers[4..1]:");
1448629263acSSony Chacko reg = QLC_83XX_PORT0_TC_MC_REG;
1449629263acSSony Chacko } else if (j == 1) {
1450629263acSSony Chacko dev_info(&adapter->pdev->dev,
1451629263acSSony Chacko "Port 1 RxB TC Max Cell Registers[4..1]:");
1452629263acSSony Chacko reg = QLC_83XX_PORT1_TC_MC_REG;
1453629263acSSony Chacko }
1454629263acSSony Chacko for (i = 0; i < 4; i++) {
14554bd8e738SHimanshu Madhani val = QLCRD32(adapter, reg + (i * 0x4), &err);
14564bd8e738SHimanshu Madhani if (err == -EIO)
14574bd8e738SHimanshu Madhani return;
1458629263acSSony Chacko dev_info(&adapter->pdev->dev, "0x%x ", val);
1459629263acSSony Chacko }
1460629263acSSony Chacko dev_info(&adapter->pdev->dev, "\n");
1461629263acSSony Chacko }
1462629263acSSony Chacko
1463629263acSSony Chacko for (j = 0; j < 2; j++) {
1464629263acSSony Chacko if (j == 0) {
1465629263acSSony Chacko dev_info(&adapter->pdev->dev,
1466629263acSSony Chacko "Port 0 RxB Rx TC Stats[TC7..TC0]:");
1467629263acSSony Chacko reg = QLC_83XX_PORT0_TC_STATS;
1468629263acSSony Chacko } else if (j == 1) {
1469629263acSSony Chacko dev_info(&adapter->pdev->dev,
1470629263acSSony Chacko "Port 1 RxB Rx TC Stats[TC7..TC0]:");
1471629263acSSony Chacko reg = QLC_83XX_PORT1_TC_STATS;
1472629263acSSony Chacko }
1473629263acSSony Chacko for (i = 7; i >= 0; i--) {
14744bd8e738SHimanshu Madhani val = QLCRD32(adapter, reg, &err);
14754bd8e738SHimanshu Madhani if (err == -EIO)
14764bd8e738SHimanshu Madhani return;
1477629263acSSony Chacko val &= ~(0x7 << 29); /* Reset bits 29 to 31 */
1478629263acSSony Chacko QLCWR32(adapter, reg, (val | (i << 29)));
14794bd8e738SHimanshu Madhani val = QLCRD32(adapter, reg, &err);
14804bd8e738SHimanshu Madhani if (err == -EIO)
14814bd8e738SHimanshu Madhani return;
1482629263acSSony Chacko dev_info(&adapter->pdev->dev, "0x%x ", val);
1483629263acSSony Chacko }
1484629263acSSony Chacko dev_info(&adapter->pdev->dev, "\n");
1485629263acSSony Chacko }
1486629263acSSony Chacko
14874bd8e738SHimanshu Madhani val = QLCRD32(adapter, QLC_83XX_PORT2_IFB_THRESHOLD, &err);
14884bd8e738SHimanshu Madhani if (err == -EIO)
14894bd8e738SHimanshu Madhani return;
14904bd8e738SHimanshu Madhani val1 = QLCRD32(adapter, QLC_83XX_PORT3_IFB_THRESHOLD, &err);
14914bd8e738SHimanshu Madhani if (err == -EIO)
14924bd8e738SHimanshu Madhani return;
1493629263acSSony Chacko dev_info(&adapter->pdev->dev,
1494629263acSSony Chacko "IFB-Pause Thresholds: Port 2:0x%x, Port 3:0x%x\n",
1495629263acSSony Chacko val, val1);
1496629263acSSony Chacko }
1497629263acSSony Chacko
149881d0aeb0SSony Chacko
qlcnic_83xx_disable_pause_frames(struct qlcnic_adapter * adapter)1499629263acSSony Chacko static void qlcnic_83xx_disable_pause_frames(struct qlcnic_adapter *adapter)
1500629263acSSony Chacko {
1501629263acSSony Chacko u32 reg = 0, i, j;
1502629263acSSony Chacko
1503629263acSSony Chacko if (qlcnic_83xx_lock_driver(adapter)) {
1504629263acSSony Chacko dev_err(&adapter->pdev->dev,
1505629263acSSony Chacko "%s:failed to acquire driver lock\n", __func__);
1506629263acSSony Chacko return;
1507629263acSSony Chacko }
1508629263acSSony Chacko
1509629263acSSony Chacko qlcnic_83xx_dump_pause_control_regs(adapter);
1510629263acSSony Chacko QLCWR32(adapter, QLC_83XX_SRE_SHIM_REG, 0x0);
1511629263acSSony Chacko
1512629263acSSony Chacko for (j = 0; j < 2; j++) {
1513629263acSSony Chacko if (j == 0)
1514629263acSSony Chacko reg = QLC_83XX_PORT0_THRESHOLD;
1515629263acSSony Chacko else if (j == 1)
1516629263acSSony Chacko reg = QLC_83XX_PORT1_THRESHOLD;
1517629263acSSony Chacko
1518629263acSSony Chacko for (i = 0; i < 8; i++)
1519629263acSSony Chacko QLCWR32(adapter, reg + (i * 0x4), 0x0);
1520629263acSSony Chacko }
1521629263acSSony Chacko
1522629263acSSony Chacko for (j = 0; j < 2; j++) {
1523629263acSSony Chacko if (j == 0)
1524629263acSSony Chacko reg = QLC_83XX_PORT0_TC_MC_REG;
1525629263acSSony Chacko else if (j == 1)
1526629263acSSony Chacko reg = QLC_83XX_PORT1_TC_MC_REG;
1527629263acSSony Chacko
1528629263acSSony Chacko for (i = 0; i < 4; i++)
1529629263acSSony Chacko QLCWR32(adapter, reg + (i * 0x4), 0x03FF03FF);
1530629263acSSony Chacko }
1531629263acSSony Chacko
1532629263acSSony Chacko QLCWR32(adapter, QLC_83XX_PORT2_IFB_THRESHOLD, 0);
1533629263acSSony Chacko QLCWR32(adapter, QLC_83XX_PORT3_IFB_THRESHOLD, 0);
1534629263acSSony Chacko dev_info(&adapter->pdev->dev,
1535629263acSSony Chacko "Disabled pause frames successfully on all ports\n");
1536629263acSSony Chacko qlcnic_83xx_unlock_driver(adapter);
1537629263acSSony Chacko }
1538629263acSSony Chacko
qlcnic_83xx_take_eport_out_of_reset(struct qlcnic_adapter * adapter)1539c0d79cd0SManish Chopra static void qlcnic_83xx_take_eport_out_of_reset(struct qlcnic_adapter *adapter)
1540c0d79cd0SManish Chopra {
1541c0d79cd0SManish Chopra QLCWR32(adapter, QLC_83XX_RESET_REG, 0);
1542c0d79cd0SManish Chopra QLCWR32(adapter, QLC_83XX_RESET_PORT0, 0);
1543c0d79cd0SManish Chopra QLCWR32(adapter, QLC_83XX_RESET_PORT1, 0);
1544c0d79cd0SManish Chopra QLCWR32(adapter, QLC_83XX_RESET_PORT2, 0);
1545c0d79cd0SManish Chopra QLCWR32(adapter, QLC_83XX_RESET_PORT3, 0);
1546c0d79cd0SManish Chopra QLCWR32(adapter, QLC_83XX_RESET_SRESHIM, 0);
1547c0d79cd0SManish Chopra QLCWR32(adapter, QLC_83XX_RESET_EPGSHIM, 0);
1548c0d79cd0SManish Chopra QLCWR32(adapter, QLC_83XX_RESET_ETHERPCS, 0);
1549c0d79cd0SManish Chopra QLCWR32(adapter, QLC_83XX_RESET_CONTROL, 1);
1550c0d79cd0SManish Chopra }
1551c0d79cd0SManish Chopra
qlcnic_83xx_check_heartbeat(struct qlcnic_adapter * p_dev)1552629263acSSony Chacko static int qlcnic_83xx_check_heartbeat(struct qlcnic_adapter *p_dev)
1553629263acSSony Chacko {
1554629263acSSony Chacko u32 heartbeat, peg_status;
15554bd8e738SHimanshu Madhani int retries, ret = -EIO, err = 0;
1556629263acSSony Chacko
1557629263acSSony Chacko retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT;
1558629263acSSony Chacko p_dev->heartbeat = QLC_SHARED_REG_RD32(p_dev,
1559629263acSSony Chacko QLCNIC_PEG_ALIVE_COUNTER);
1560629263acSSony Chacko
1561629263acSSony Chacko do {
1562629263acSSony Chacko msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);
1563629263acSSony Chacko heartbeat = QLC_SHARED_REG_RD32(p_dev,
1564629263acSSony Chacko QLCNIC_PEG_ALIVE_COUNTER);
1565629263acSSony Chacko if (heartbeat != p_dev->heartbeat) {
1566629263acSSony Chacko ret = QLCNIC_RCODE_SUCCESS;
1567629263acSSony Chacko break;
1568629263acSSony Chacko }
1569629263acSSony Chacko } while (--retries);
1570629263acSSony Chacko
1571629263acSSony Chacko if (ret) {
1572629263acSSony Chacko dev_err(&p_dev->pdev->dev, "firmware hang detected\n");
1573c0d79cd0SManish Chopra qlcnic_83xx_take_eport_out_of_reset(p_dev);
1574629263acSSony Chacko qlcnic_83xx_disable_pause_frames(p_dev);
1575629263acSSony Chacko peg_status = QLC_SHARED_REG_RD32(p_dev,
1576629263acSSony Chacko QLCNIC_PEG_HALT_STATUS1);
1577629263acSSony Chacko dev_info(&p_dev->pdev->dev, "Dumping HW/FW registers\n"
1578629263acSSony Chacko "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n"
1579629263acSSony Chacko "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n"
1580629263acSSony Chacko "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n"
1581629263acSSony Chacko "PEG_NET_4_PC: 0x%x\n", peg_status,
1582629263acSSony Chacko QLC_SHARED_REG_RD32(p_dev, QLCNIC_PEG_HALT_STATUS2),
15834bd8e738SHimanshu Madhani QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_0, &err),
15844bd8e738SHimanshu Madhani QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_1, &err),
15854bd8e738SHimanshu Madhani QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_2, &err),
15864bd8e738SHimanshu Madhani QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_3, &err),
15874bd8e738SHimanshu Madhani QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_4, &err));
1588629263acSSony Chacko
1589629263acSSony Chacko if (QLCNIC_FWERROR_CODE(peg_status) == 0x67)
1590629263acSSony Chacko dev_err(&p_dev->pdev->dev,
1591629263acSSony Chacko "Device is being reset err code 0x00006700.\n");
1592629263acSSony Chacko }
1593629263acSSony Chacko
1594629263acSSony Chacko return ret;
1595629263acSSony Chacko }
1596629263acSSony Chacko
qlcnic_83xx_check_cmd_peg_status(struct qlcnic_adapter * p_dev)1597629263acSSony Chacko static int qlcnic_83xx_check_cmd_peg_status(struct qlcnic_adapter *p_dev)
1598629263acSSony Chacko {
1599629263acSSony Chacko int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT;
1600629263acSSony Chacko u32 val;
1601629263acSSony Chacko
1602629263acSSony Chacko do {
1603629263acSSony Chacko val = QLC_SHARED_REG_RD32(p_dev, QLCNIC_CMDPEG_STATE);
1604629263acSSony Chacko if (val == QLC_83XX_CMDPEG_COMPLETE)
1605629263acSSony Chacko return 0;
1606629263acSSony Chacko msleep(QLCNIC_CMDPEG_CHECK_DELAY);
1607629263acSSony Chacko } while (--retries);
1608629263acSSony Chacko
1609629263acSSony Chacko dev_err(&p_dev->pdev->dev, "%s: failed, state = 0x%x\n", __func__, val);
1610629263acSSony Chacko return -EIO;
1611629263acSSony Chacko }
1612629263acSSony Chacko
qlcnic_83xx_check_hw_status(struct qlcnic_adapter * p_dev)161321041400Sstephen hemminger static int qlcnic_83xx_check_hw_status(struct qlcnic_adapter *p_dev)
1614629263acSSony Chacko {
1615629263acSSony Chacko int err;
1616629263acSSony Chacko
1617629263acSSony Chacko err = qlcnic_83xx_check_cmd_peg_status(p_dev);
1618629263acSSony Chacko if (err)
1619629263acSSony Chacko return err;
1620629263acSSony Chacko
1621629263acSSony Chacko err = qlcnic_83xx_check_heartbeat(p_dev);
1622629263acSSony Chacko if (err)
1623629263acSSony Chacko return err;
1624629263acSSony Chacko
1625629263acSSony Chacko return err;
1626629263acSSony Chacko }
1627629263acSSony Chacko
qlcnic_83xx_poll_reg(struct qlcnic_adapter * p_dev,u32 addr,int duration,u32 mask,u32 status)162881d0aeb0SSony Chacko static int qlcnic_83xx_poll_reg(struct qlcnic_adapter *p_dev, u32 addr,
162981d0aeb0SSony Chacko int duration, u32 mask, u32 status)
163081d0aeb0SSony Chacko {
16314bd8e738SHimanshu Madhani int timeout_error, err = 0;
163281d0aeb0SSony Chacko u32 value;
163381d0aeb0SSony Chacko u8 retries;
163481d0aeb0SSony Chacko
16354bd8e738SHimanshu Madhani value = QLCRD32(p_dev, addr, &err);
16364bd8e738SHimanshu Madhani if (err == -EIO)
16374bd8e738SHimanshu Madhani return err;
163881d0aeb0SSony Chacko retries = duration / 10;
163981d0aeb0SSony Chacko
164081d0aeb0SSony Chacko do {
164181d0aeb0SSony Chacko if ((value & mask) != status) {
164281d0aeb0SSony Chacko timeout_error = 1;
164381d0aeb0SSony Chacko msleep(duration / 10);
16444bd8e738SHimanshu Madhani value = QLCRD32(p_dev, addr, &err);
16454bd8e738SHimanshu Madhani if (err == -EIO)
16464bd8e738SHimanshu Madhani return err;
164781d0aeb0SSony Chacko } else {
164881d0aeb0SSony Chacko timeout_error = 0;
164981d0aeb0SSony Chacko break;
165081d0aeb0SSony Chacko }
165181d0aeb0SSony Chacko } while (retries--);
165281d0aeb0SSony Chacko
165381d0aeb0SSony Chacko if (timeout_error) {
165481d0aeb0SSony Chacko p_dev->ahw->reset.seq_error++;
165581d0aeb0SSony Chacko dev_err(&p_dev->pdev->dev,
165681d0aeb0SSony Chacko "%s: Timeout Err, entry_num = %d\n",
165781d0aeb0SSony Chacko __func__, p_dev->ahw->reset.seq_index);
165881d0aeb0SSony Chacko dev_err(&p_dev->pdev->dev,
165981d0aeb0SSony Chacko "0x%08x 0x%08x 0x%08x\n",
166081d0aeb0SSony Chacko value, mask, status);
166181d0aeb0SSony Chacko }
166281d0aeb0SSony Chacko
166381d0aeb0SSony Chacko return timeout_error;
166481d0aeb0SSony Chacko }
166581d0aeb0SSony Chacko
qlcnic_83xx_reset_template_checksum(struct qlcnic_adapter * p_dev)166681d0aeb0SSony Chacko static int qlcnic_83xx_reset_template_checksum(struct qlcnic_adapter *p_dev)
166781d0aeb0SSony Chacko {
166881d0aeb0SSony Chacko u32 sum = 0;
166981d0aeb0SSony Chacko u16 *buff = (u16 *)p_dev->ahw->reset.buff;
167081d0aeb0SSony Chacko int count = p_dev->ahw->reset.hdr->size / sizeof(u16);
167181d0aeb0SSony Chacko
167281d0aeb0SSony Chacko while (count-- > 0)
167381d0aeb0SSony Chacko sum += *buff++;
167481d0aeb0SSony Chacko
167581d0aeb0SSony Chacko while (sum >> 16)
167681d0aeb0SSony Chacko sum = (sum & 0xFFFF) + (sum >> 16);
167781d0aeb0SSony Chacko
167881d0aeb0SSony Chacko if (~sum) {
167981d0aeb0SSony Chacko return 0;
168081d0aeb0SSony Chacko } else {
168181d0aeb0SSony Chacko dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);
168281d0aeb0SSony Chacko return -1;
168381d0aeb0SSony Chacko }
168481d0aeb0SSony Chacko }
168581d0aeb0SSony Chacko
qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter * p_dev)168621041400Sstephen hemminger static int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev)
168781d0aeb0SSony Chacko {
168881d0aeb0SSony Chacko struct qlcnic_hardware_context *ahw = p_dev->ahw;
1689486a5bc7SRajesh Borundia u32 addr, count, prev_ver, curr_ver;
1690486a5bc7SRajesh Borundia u8 *p_buff;
1691486a5bc7SRajesh Borundia
1692486a5bc7SRajesh Borundia if (ahw->reset.buff != NULL) {
1693486a5bc7SRajesh Borundia prev_ver = p_dev->fw_version;
1694486a5bc7SRajesh Borundia curr_ver = qlcnic_83xx_get_fw_version(p_dev);
1695486a5bc7SRajesh Borundia if (curr_ver > prev_ver)
1696486a5bc7SRajesh Borundia kfree(ahw->reset.buff);
1697486a5bc7SRajesh Borundia else
1698486a5bc7SRajesh Borundia return 0;
1699486a5bc7SRajesh Borundia }
170081d0aeb0SSony Chacko
170181d0aeb0SSony Chacko ahw->reset.seq_error = 0;
170281d0aeb0SSony Chacko ahw->reset.buff = kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL);
1703bcaeb886SXu Wang if (ahw->reset.buff == NULL)
170481d0aeb0SSony Chacko return -ENOMEM;
1705b2adaca9SJoe Perches
170681d0aeb0SSony Chacko p_buff = p_dev->ahw->reset.buff;
170781d0aeb0SSony Chacko addr = QLC_83XX_RESET_TEMPLATE_ADDR;
170881d0aeb0SSony Chacko count = sizeof(struct qlc_83xx_reset_hdr) / sizeof(u32);
170981d0aeb0SSony Chacko
171081d0aeb0SSony Chacko /* Copy template header from flash */
171181d0aeb0SSony Chacko if (qlcnic_83xx_flash_read32(p_dev, addr, p_buff, count)) {
171281d0aeb0SSony Chacko dev_err(&p_dev->pdev->dev, "%s: flash read failed\n", __func__);
171381d0aeb0SSony Chacko return -EIO;
171481d0aeb0SSony Chacko }
171581d0aeb0SSony Chacko ahw->reset.hdr = (struct qlc_83xx_reset_hdr *)ahw->reset.buff;
171681d0aeb0SSony Chacko addr = QLC_83XX_RESET_TEMPLATE_ADDR + ahw->reset.hdr->hdr_size;
171781d0aeb0SSony Chacko p_buff = ahw->reset.buff + ahw->reset.hdr->hdr_size;
171881d0aeb0SSony Chacko count = (ahw->reset.hdr->size - ahw->reset.hdr->hdr_size) / sizeof(u32);
171981d0aeb0SSony Chacko
172081d0aeb0SSony Chacko /* Copy rest of the template */
172181d0aeb0SSony Chacko if (qlcnic_83xx_flash_read32(p_dev, addr, p_buff, count)) {
172281d0aeb0SSony Chacko dev_err(&p_dev->pdev->dev, "%s: flash read failed\n", __func__);
172381d0aeb0SSony Chacko return -EIO;
172481d0aeb0SSony Chacko }
172581d0aeb0SSony Chacko
172681d0aeb0SSony Chacko if (qlcnic_83xx_reset_template_checksum(p_dev))
172781d0aeb0SSony Chacko return -EIO;
172881d0aeb0SSony Chacko /* Get Stop, Start and Init command offsets */
172981d0aeb0SSony Chacko ahw->reset.init_offset = ahw->reset.buff + ahw->reset.hdr->init_offset;
173081d0aeb0SSony Chacko ahw->reset.start_offset = ahw->reset.buff +
173181d0aeb0SSony Chacko ahw->reset.hdr->start_offset;
173281d0aeb0SSony Chacko ahw->reset.stop_offset = ahw->reset.buff + ahw->reset.hdr->hdr_size;
173381d0aeb0SSony Chacko return 0;
173481d0aeb0SSony Chacko }
173581d0aeb0SSony Chacko
173681d0aeb0SSony Chacko /* Read Write HW register command */
qlcnic_83xx_read_write_crb_reg(struct qlcnic_adapter * p_dev,u32 raddr,u32 waddr)173781d0aeb0SSony Chacko static void qlcnic_83xx_read_write_crb_reg(struct qlcnic_adapter *p_dev,
173881d0aeb0SSony Chacko u32 raddr, u32 waddr)
173981d0aeb0SSony Chacko {
17404bd8e738SHimanshu Madhani int err = 0;
17414bd8e738SHimanshu Madhani u32 value;
174281d0aeb0SSony Chacko
17434bd8e738SHimanshu Madhani value = QLCRD32(p_dev, raddr, &err);
17444bd8e738SHimanshu Madhani if (err == -EIO)
17454bd8e738SHimanshu Madhani return;
174681d0aeb0SSony Chacko qlcnic_83xx_wrt_reg_indirect(p_dev, waddr, value);
174781d0aeb0SSony Chacko }
174881d0aeb0SSony Chacko
174981d0aeb0SSony Chacko /* Read Modify Write HW register command */
qlcnic_83xx_rmw_crb_reg(struct qlcnic_adapter * p_dev,u32 raddr,u32 waddr,struct qlc_83xx_rmw * p_rmw_hdr)175081d0aeb0SSony Chacko static void qlcnic_83xx_rmw_crb_reg(struct qlcnic_adapter *p_dev,
175181d0aeb0SSony Chacko u32 raddr, u32 waddr,
175281d0aeb0SSony Chacko struct qlc_83xx_rmw *p_rmw_hdr)
175381d0aeb0SSony Chacko {
17544bd8e738SHimanshu Madhani int err = 0;
17554bd8e738SHimanshu Madhani u32 value;
175681d0aeb0SSony Chacko
17574bd8e738SHimanshu Madhani if (p_rmw_hdr->index_a) {
175881d0aeb0SSony Chacko value = p_dev->ahw->reset.array[p_rmw_hdr->index_a];
17594bd8e738SHimanshu Madhani } else {
17604bd8e738SHimanshu Madhani value = QLCRD32(p_dev, raddr, &err);
17614bd8e738SHimanshu Madhani if (err == -EIO)
17624bd8e738SHimanshu Madhani return;
17634bd8e738SHimanshu Madhani }
176481d0aeb0SSony Chacko
176581d0aeb0SSony Chacko value &= p_rmw_hdr->mask;
176681d0aeb0SSony Chacko value <<= p_rmw_hdr->shl;
176781d0aeb0SSony Chacko value >>= p_rmw_hdr->shr;
176881d0aeb0SSony Chacko value |= p_rmw_hdr->or_value;
176981d0aeb0SSony Chacko value ^= p_rmw_hdr->xor_value;
177081d0aeb0SSony Chacko qlcnic_83xx_wrt_reg_indirect(p_dev, waddr, value);
177181d0aeb0SSony Chacko }
177281d0aeb0SSony Chacko
177381d0aeb0SSony Chacko /* Write HW register command */
qlcnic_83xx_write_list(struct qlcnic_adapter * p_dev,struct qlc_83xx_entry_hdr * p_hdr)177481d0aeb0SSony Chacko static void qlcnic_83xx_write_list(struct qlcnic_adapter *p_dev,
177581d0aeb0SSony Chacko struct qlc_83xx_entry_hdr *p_hdr)
177681d0aeb0SSony Chacko {
177781d0aeb0SSony Chacko int i;
177881d0aeb0SSony Chacko struct qlc_83xx_entry *entry;
177981d0aeb0SSony Chacko
178081d0aeb0SSony Chacko entry = (struct qlc_83xx_entry *)((char *)p_hdr +
178181d0aeb0SSony Chacko sizeof(struct qlc_83xx_entry_hdr));
178281d0aeb0SSony Chacko
178381d0aeb0SSony Chacko for (i = 0; i < p_hdr->count; i++, entry++) {
178481d0aeb0SSony Chacko qlcnic_83xx_wrt_reg_indirect(p_dev, entry->arg1,
178581d0aeb0SSony Chacko entry->arg2);
178681d0aeb0SSony Chacko if (p_hdr->delay)
178781d0aeb0SSony Chacko udelay((u32)(p_hdr->delay));
178881d0aeb0SSony Chacko }
178981d0aeb0SSony Chacko }
179081d0aeb0SSony Chacko
179181d0aeb0SSony Chacko /* Read and Write instruction */
qlcnic_83xx_read_write_list(struct qlcnic_adapter * p_dev,struct qlc_83xx_entry_hdr * p_hdr)179281d0aeb0SSony Chacko static void qlcnic_83xx_read_write_list(struct qlcnic_adapter *p_dev,
179381d0aeb0SSony Chacko struct qlc_83xx_entry_hdr *p_hdr)
179481d0aeb0SSony Chacko {
179581d0aeb0SSony Chacko int i;
179681d0aeb0SSony Chacko struct qlc_83xx_entry *entry;
179781d0aeb0SSony Chacko
179881d0aeb0SSony Chacko entry = (struct qlc_83xx_entry *)((char *)p_hdr +
179981d0aeb0SSony Chacko sizeof(struct qlc_83xx_entry_hdr));
180081d0aeb0SSony Chacko
180181d0aeb0SSony Chacko for (i = 0; i < p_hdr->count; i++, entry++) {
180281d0aeb0SSony Chacko qlcnic_83xx_read_write_crb_reg(p_dev, entry->arg1,
180381d0aeb0SSony Chacko entry->arg2);
180481d0aeb0SSony Chacko if (p_hdr->delay)
180581d0aeb0SSony Chacko udelay((u32)(p_hdr->delay));
180681d0aeb0SSony Chacko }
180781d0aeb0SSony Chacko }
180881d0aeb0SSony Chacko
180981d0aeb0SSony Chacko /* Poll HW register command */
qlcnic_83xx_poll_list(struct qlcnic_adapter * p_dev,struct qlc_83xx_entry_hdr * p_hdr)181081d0aeb0SSony Chacko static void qlcnic_83xx_poll_list(struct qlcnic_adapter *p_dev,
181181d0aeb0SSony Chacko struct qlc_83xx_entry_hdr *p_hdr)
181281d0aeb0SSony Chacko {
181381d0aeb0SSony Chacko long delay;
181481d0aeb0SSony Chacko struct qlc_83xx_entry *entry;
181581d0aeb0SSony Chacko struct qlc_83xx_poll *poll;
18164bd8e738SHimanshu Madhani int i, err = 0;
181781d0aeb0SSony Chacko unsigned long arg1, arg2;
181881d0aeb0SSony Chacko
181981d0aeb0SSony Chacko poll = (struct qlc_83xx_poll *)((char *)p_hdr +
182081d0aeb0SSony Chacko sizeof(struct qlc_83xx_entry_hdr));
182181d0aeb0SSony Chacko
182281d0aeb0SSony Chacko entry = (struct qlc_83xx_entry *)((char *)poll +
182381d0aeb0SSony Chacko sizeof(struct qlc_83xx_poll));
182481d0aeb0SSony Chacko delay = (long)p_hdr->delay;
182581d0aeb0SSony Chacko
182681d0aeb0SSony Chacko if (!delay) {
182781d0aeb0SSony Chacko for (i = 0; i < p_hdr->count; i++, entry++)
182881d0aeb0SSony Chacko qlcnic_83xx_poll_reg(p_dev, entry->arg1,
182981d0aeb0SSony Chacko delay, poll->mask,
183081d0aeb0SSony Chacko poll->status);
183181d0aeb0SSony Chacko } else {
183281d0aeb0SSony Chacko for (i = 0; i < p_hdr->count; i++, entry++) {
183381d0aeb0SSony Chacko arg1 = entry->arg1;
183481d0aeb0SSony Chacko arg2 = entry->arg2;
183581d0aeb0SSony Chacko if (delay) {
183681d0aeb0SSony Chacko if (qlcnic_83xx_poll_reg(p_dev,
183781d0aeb0SSony Chacko arg1, delay,
183881d0aeb0SSony Chacko poll->mask,
183981d0aeb0SSony Chacko poll->status)){
18404bd8e738SHimanshu Madhani QLCRD32(p_dev, arg1, &err);
18414bd8e738SHimanshu Madhani if (err == -EIO)
18424bd8e738SHimanshu Madhani return;
18434bd8e738SHimanshu Madhani QLCRD32(p_dev, arg2, &err);
18444bd8e738SHimanshu Madhani if (err == -EIO)
18454bd8e738SHimanshu Madhani return;
184681d0aeb0SSony Chacko }
184781d0aeb0SSony Chacko }
184881d0aeb0SSony Chacko }
184981d0aeb0SSony Chacko }
185081d0aeb0SSony Chacko }
185181d0aeb0SSony Chacko
185281d0aeb0SSony Chacko /* Poll and write HW register command */
qlcnic_83xx_poll_write_list(struct qlcnic_adapter * p_dev,struct qlc_83xx_entry_hdr * p_hdr)185381d0aeb0SSony Chacko static void qlcnic_83xx_poll_write_list(struct qlcnic_adapter *p_dev,
185481d0aeb0SSony Chacko struct qlc_83xx_entry_hdr *p_hdr)
185581d0aeb0SSony Chacko {
185681d0aeb0SSony Chacko int i;
185781d0aeb0SSony Chacko long delay;
185881d0aeb0SSony Chacko struct qlc_83xx_quad_entry *entry;
185981d0aeb0SSony Chacko struct qlc_83xx_poll *poll;
186081d0aeb0SSony Chacko
186181d0aeb0SSony Chacko poll = (struct qlc_83xx_poll *)((char *)p_hdr +
186281d0aeb0SSony Chacko sizeof(struct qlc_83xx_entry_hdr));
186381d0aeb0SSony Chacko entry = (struct qlc_83xx_quad_entry *)((char *)poll +
186481d0aeb0SSony Chacko sizeof(struct qlc_83xx_poll));
186581d0aeb0SSony Chacko delay = (long)p_hdr->delay;
186681d0aeb0SSony Chacko
186781d0aeb0SSony Chacko for (i = 0; i < p_hdr->count; i++, entry++) {
186881d0aeb0SSony Chacko qlcnic_83xx_wrt_reg_indirect(p_dev, entry->dr_addr,
186981d0aeb0SSony Chacko entry->dr_value);
187081d0aeb0SSony Chacko qlcnic_83xx_wrt_reg_indirect(p_dev, entry->ar_addr,
187181d0aeb0SSony Chacko entry->ar_value);
187281d0aeb0SSony Chacko if (delay)
187381d0aeb0SSony Chacko qlcnic_83xx_poll_reg(p_dev, entry->ar_addr, delay,
187481d0aeb0SSony Chacko poll->mask, poll->status);
187581d0aeb0SSony Chacko }
187681d0aeb0SSony Chacko }
187781d0aeb0SSony Chacko
187881d0aeb0SSony Chacko /* Read Modify Write register command */
qlcnic_83xx_read_modify_write(struct qlcnic_adapter * p_dev,struct qlc_83xx_entry_hdr * p_hdr)187981d0aeb0SSony Chacko static void qlcnic_83xx_read_modify_write(struct qlcnic_adapter *p_dev,
188081d0aeb0SSony Chacko struct qlc_83xx_entry_hdr *p_hdr)
188181d0aeb0SSony Chacko {
188281d0aeb0SSony Chacko int i;
188381d0aeb0SSony Chacko struct qlc_83xx_entry *entry;
188481d0aeb0SSony Chacko struct qlc_83xx_rmw *rmw_hdr;
188581d0aeb0SSony Chacko
188681d0aeb0SSony Chacko rmw_hdr = (struct qlc_83xx_rmw *)((char *)p_hdr +
188781d0aeb0SSony Chacko sizeof(struct qlc_83xx_entry_hdr));
188881d0aeb0SSony Chacko
188981d0aeb0SSony Chacko entry = (struct qlc_83xx_entry *)((char *)rmw_hdr +
189081d0aeb0SSony Chacko sizeof(struct qlc_83xx_rmw));
189181d0aeb0SSony Chacko
189281d0aeb0SSony Chacko for (i = 0; i < p_hdr->count; i++, entry++) {
189381d0aeb0SSony Chacko qlcnic_83xx_rmw_crb_reg(p_dev, entry->arg1,
189481d0aeb0SSony Chacko entry->arg2, rmw_hdr);
189581d0aeb0SSony Chacko if (p_hdr->delay)
189681d0aeb0SSony Chacko udelay((u32)(p_hdr->delay));
189781d0aeb0SSony Chacko }
189881d0aeb0SSony Chacko }
189981d0aeb0SSony Chacko
qlcnic_83xx_pause(struct qlc_83xx_entry_hdr * p_hdr)190081d0aeb0SSony Chacko static void qlcnic_83xx_pause(struct qlc_83xx_entry_hdr *p_hdr)
190181d0aeb0SSony Chacko {
190281d0aeb0SSony Chacko if (p_hdr->delay)
190381d0aeb0SSony Chacko mdelay((u32)((long)p_hdr->delay));
190481d0aeb0SSony Chacko }
190581d0aeb0SSony Chacko
190681d0aeb0SSony Chacko /* Read and poll register command */
qlcnic_83xx_poll_read_list(struct qlcnic_adapter * p_dev,struct qlc_83xx_entry_hdr * p_hdr)190781d0aeb0SSony Chacko static void qlcnic_83xx_poll_read_list(struct qlcnic_adapter *p_dev,
190881d0aeb0SSony Chacko struct qlc_83xx_entry_hdr *p_hdr)
190981d0aeb0SSony Chacko {
191081d0aeb0SSony Chacko long delay;
19114bd8e738SHimanshu Madhani int index, i, j, err;
191281d0aeb0SSony Chacko struct qlc_83xx_quad_entry *entry;
191381d0aeb0SSony Chacko struct qlc_83xx_poll *poll;
191481d0aeb0SSony Chacko unsigned long addr;
191581d0aeb0SSony Chacko
191681d0aeb0SSony Chacko poll = (struct qlc_83xx_poll *)((char *)p_hdr +
191781d0aeb0SSony Chacko sizeof(struct qlc_83xx_entry_hdr));
191881d0aeb0SSony Chacko
191981d0aeb0SSony Chacko entry = (struct qlc_83xx_quad_entry *)((char *)poll +
192081d0aeb0SSony Chacko sizeof(struct qlc_83xx_poll));
192181d0aeb0SSony Chacko delay = (long)p_hdr->delay;
192281d0aeb0SSony Chacko
192381d0aeb0SSony Chacko for (i = 0; i < p_hdr->count; i++, entry++) {
192481d0aeb0SSony Chacko qlcnic_83xx_wrt_reg_indirect(p_dev, entry->ar_addr,
192581d0aeb0SSony Chacko entry->ar_value);
192681d0aeb0SSony Chacko if (delay) {
192781d0aeb0SSony Chacko if (!qlcnic_83xx_poll_reg(p_dev, entry->ar_addr, delay,
192881d0aeb0SSony Chacko poll->mask, poll->status)){
192981d0aeb0SSony Chacko index = p_dev->ahw->reset.array_index;
193081d0aeb0SSony Chacko addr = entry->dr_addr;
19314bd8e738SHimanshu Madhani j = QLCRD32(p_dev, addr, &err);
19324bd8e738SHimanshu Madhani if (err == -EIO)
19334bd8e738SHimanshu Madhani return;
19344bd8e738SHimanshu Madhani
193581d0aeb0SSony Chacko p_dev->ahw->reset.array[index++] = j;
193681d0aeb0SSony Chacko
193781d0aeb0SSony Chacko if (index == QLC_83XX_MAX_RESET_SEQ_ENTRIES)
193881d0aeb0SSony Chacko p_dev->ahw->reset.array_index = 1;
193981d0aeb0SSony Chacko }
194081d0aeb0SSony Chacko }
194181d0aeb0SSony Chacko }
194281d0aeb0SSony Chacko }
194381d0aeb0SSony Chacko
qlcnic_83xx_seq_end(struct qlcnic_adapter * p_dev)194481d0aeb0SSony Chacko static inline void qlcnic_83xx_seq_end(struct qlcnic_adapter *p_dev)
194581d0aeb0SSony Chacko {
194681d0aeb0SSony Chacko p_dev->ahw->reset.seq_end = 1;
194781d0aeb0SSony Chacko }
194881d0aeb0SSony Chacko
qlcnic_83xx_template_end(struct qlcnic_adapter * p_dev)194981d0aeb0SSony Chacko static void qlcnic_83xx_template_end(struct qlcnic_adapter *p_dev)
195081d0aeb0SSony Chacko {
195181d0aeb0SSony Chacko p_dev->ahw->reset.template_end = 1;
195281d0aeb0SSony Chacko if (p_dev->ahw->reset.seq_error == 0)
195381d0aeb0SSony Chacko dev_err(&p_dev->pdev->dev,
195481d0aeb0SSony Chacko "HW restart process completed successfully.\n");
195581d0aeb0SSony Chacko else
195681d0aeb0SSony Chacko dev_err(&p_dev->pdev->dev,
195781d0aeb0SSony Chacko "HW restart completed with timeout errors.\n");
195881d0aeb0SSony Chacko }
195981d0aeb0SSony Chacko
196081d0aeb0SSony Chacko /**
196181d0aeb0SSony Chacko * qlcnic_83xx_exec_template_cmd
196281d0aeb0SSony Chacko *
196381d0aeb0SSony Chacko * @p_dev: adapter structure
196481d0aeb0SSony Chacko * @p_buff: Poiter to instruction template
196581d0aeb0SSony Chacko *
196681d0aeb0SSony Chacko * Template provides instructions to stop, restart and initalize firmware.
196781d0aeb0SSony Chacko * These instructions are abstracted as a series of read, write and
196881d0aeb0SSony Chacko * poll operations on hardware registers. Register information and operation
196981d0aeb0SSony Chacko * specifics are not exposed to the driver. Driver reads the template from
197081d0aeb0SSony Chacko * flash and executes the instructions located at pre-defined offsets.
197181d0aeb0SSony Chacko *
197281d0aeb0SSony Chacko * Returns: None
197381d0aeb0SSony Chacko * */
qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter * p_dev,char * p_buff)197481d0aeb0SSony Chacko static void qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter *p_dev,
197581d0aeb0SSony Chacko char *p_buff)
197681d0aeb0SSony Chacko {
197781d0aeb0SSony Chacko int index, entries;
197881d0aeb0SSony Chacko struct qlc_83xx_entry_hdr *p_hdr;
197981d0aeb0SSony Chacko char *entry = p_buff;
198081d0aeb0SSony Chacko
198181d0aeb0SSony Chacko p_dev->ahw->reset.seq_end = 0;
198281d0aeb0SSony Chacko p_dev->ahw->reset.template_end = 0;
198381d0aeb0SSony Chacko entries = p_dev->ahw->reset.hdr->entries;
198481d0aeb0SSony Chacko index = p_dev->ahw->reset.seq_index;
198581d0aeb0SSony Chacko
198681d0aeb0SSony Chacko for (; (!p_dev->ahw->reset.seq_end) && (index < entries); index++) {
198781d0aeb0SSony Chacko p_hdr = (struct qlc_83xx_entry_hdr *)entry;
198881d0aeb0SSony Chacko
198981d0aeb0SSony Chacko switch (p_hdr->cmd) {
199081d0aeb0SSony Chacko case QLC_83XX_OPCODE_NOP:
199181d0aeb0SSony Chacko break;
199281d0aeb0SSony Chacko case QLC_83XX_OPCODE_WRITE_LIST:
199381d0aeb0SSony Chacko qlcnic_83xx_write_list(p_dev, p_hdr);
199481d0aeb0SSony Chacko break;
199581d0aeb0SSony Chacko case QLC_83XX_OPCODE_READ_WRITE_LIST:
199681d0aeb0SSony Chacko qlcnic_83xx_read_write_list(p_dev, p_hdr);
199781d0aeb0SSony Chacko break;
199881d0aeb0SSony Chacko case QLC_83XX_OPCODE_POLL_LIST:
199981d0aeb0SSony Chacko qlcnic_83xx_poll_list(p_dev, p_hdr);
200081d0aeb0SSony Chacko break;
200181d0aeb0SSony Chacko case QLC_83XX_OPCODE_POLL_WRITE_LIST:
200281d0aeb0SSony Chacko qlcnic_83xx_poll_write_list(p_dev, p_hdr);
200381d0aeb0SSony Chacko break;
200481d0aeb0SSony Chacko case QLC_83XX_OPCODE_READ_MODIFY_WRITE:
200581d0aeb0SSony Chacko qlcnic_83xx_read_modify_write(p_dev, p_hdr);
200681d0aeb0SSony Chacko break;
200781d0aeb0SSony Chacko case QLC_83XX_OPCODE_SEQ_PAUSE:
200881d0aeb0SSony Chacko qlcnic_83xx_pause(p_hdr);
200981d0aeb0SSony Chacko break;
201081d0aeb0SSony Chacko case QLC_83XX_OPCODE_SEQ_END:
201181d0aeb0SSony Chacko qlcnic_83xx_seq_end(p_dev);
201281d0aeb0SSony Chacko break;
201381d0aeb0SSony Chacko case QLC_83XX_OPCODE_TMPL_END:
201481d0aeb0SSony Chacko qlcnic_83xx_template_end(p_dev);
201581d0aeb0SSony Chacko break;
201681d0aeb0SSony Chacko case QLC_83XX_OPCODE_POLL_READ_LIST:
201781d0aeb0SSony Chacko qlcnic_83xx_poll_read_list(p_dev, p_hdr);
201881d0aeb0SSony Chacko break;
201981d0aeb0SSony Chacko default:
202081d0aeb0SSony Chacko dev_err(&p_dev->pdev->dev,
202181d0aeb0SSony Chacko "%s: Unknown opcode 0x%04x in template %d\n",
202281d0aeb0SSony Chacko __func__, p_hdr->cmd, index);
202381d0aeb0SSony Chacko break;
202481d0aeb0SSony Chacko }
202581d0aeb0SSony Chacko entry += p_hdr->size;
202622e98449SManish Chopra cond_resched();
202781d0aeb0SSony Chacko }
202881d0aeb0SSony Chacko p_dev->ahw->reset.seq_index = index;
202981d0aeb0SSony Chacko }
203081d0aeb0SSony Chacko
qlcnic_83xx_stop_hw(struct qlcnic_adapter * p_dev)203121041400Sstephen hemminger static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
203281d0aeb0SSony Chacko {
203381d0aeb0SSony Chacko p_dev->ahw->reset.seq_index = 0;
203481d0aeb0SSony Chacko
203581d0aeb0SSony Chacko qlcnic_83xx_exec_template_cmd(p_dev, p_dev->ahw->reset.stop_offset);
203681d0aeb0SSony Chacko if (p_dev->ahw->reset.seq_end != 1)
203781d0aeb0SSony Chacko dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);
203881d0aeb0SSony Chacko }
203981d0aeb0SSony Chacko
qlcnic_83xx_start_hw(struct qlcnic_adapter * p_dev)204081d0aeb0SSony Chacko static void qlcnic_83xx_start_hw(struct qlcnic_adapter *p_dev)
204181d0aeb0SSony Chacko {
204281d0aeb0SSony Chacko qlcnic_83xx_exec_template_cmd(p_dev, p_dev->ahw->reset.start_offset);
204381d0aeb0SSony Chacko if (p_dev->ahw->reset.template_end != 1)
204481d0aeb0SSony Chacko dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);
204581d0aeb0SSony Chacko }
204681d0aeb0SSony Chacko
qlcnic_83xx_init_hw(struct qlcnic_adapter * p_dev)204781d0aeb0SSony Chacko static void qlcnic_83xx_init_hw(struct qlcnic_adapter *p_dev)
204881d0aeb0SSony Chacko {
204981d0aeb0SSony Chacko qlcnic_83xx_exec_template_cmd(p_dev, p_dev->ahw->reset.init_offset);
205081d0aeb0SSony Chacko if (p_dev->ahw->reset.seq_end != 1)
205181d0aeb0SSony Chacko dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);
205281d0aeb0SSony Chacko }
205381d0aeb0SSony Chacko
20543ced0a88SShahed Shaikh /* POST FW related definations*/
20553ced0a88SShahed Shaikh #define QLC_83XX_POST_SIGNATURE_REG 0x41602014
20563ced0a88SShahed Shaikh #define QLC_83XX_POST_MODE_REG 0x41602018
20573ced0a88SShahed Shaikh #define QLC_83XX_POST_FAST_MODE 0
20583ced0a88SShahed Shaikh #define QLC_83XX_POST_MEDIUM_MODE 1
20593ced0a88SShahed Shaikh #define QLC_83XX_POST_SLOW_MODE 2
20603ced0a88SShahed Shaikh
20613ced0a88SShahed Shaikh /* POST Timeout values in milliseconds */
20623ced0a88SShahed Shaikh #define QLC_83XX_POST_FAST_MODE_TIMEOUT 690
20633ced0a88SShahed Shaikh #define QLC_83XX_POST_MED_MODE_TIMEOUT 2930
20643ced0a88SShahed Shaikh #define QLC_83XX_POST_SLOW_MODE_TIMEOUT 7500
20653ced0a88SShahed Shaikh
20663ced0a88SShahed Shaikh /* POST result values */
20673ced0a88SShahed Shaikh #define QLC_83XX_POST_PASS 0xfffffff0
20683ced0a88SShahed Shaikh #define QLC_83XX_POST_ASIC_STRESS_TEST_FAIL 0xffffffff
20693ced0a88SShahed Shaikh #define QLC_83XX_POST_DDR_TEST_FAIL 0xfffffffe
20703ced0a88SShahed Shaikh #define QLC_83XX_POST_ASIC_MEMORY_TEST_FAIL 0xfffffffc
20713ced0a88SShahed Shaikh #define QLC_83XX_POST_FLASH_TEST_FAIL 0xfffffff8
20723ced0a88SShahed Shaikh
qlcnic_83xx_run_post(struct qlcnic_adapter * adapter)20733ced0a88SShahed Shaikh static int qlcnic_83xx_run_post(struct qlcnic_adapter *adapter)
20743ced0a88SShahed Shaikh {
20753ced0a88SShahed Shaikh struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;
20763ced0a88SShahed Shaikh struct device *dev = &adapter->pdev->dev;
20773ced0a88SShahed Shaikh int timeout, count, ret = 0;
20783ced0a88SShahed Shaikh u32 signature;
20793ced0a88SShahed Shaikh
20803ced0a88SShahed Shaikh /* Set timeout values with extra 2 seconds of buffer */
20813ced0a88SShahed Shaikh switch (adapter->ahw->post_mode) {
20823ced0a88SShahed Shaikh case QLC_83XX_POST_FAST_MODE:
20833ced0a88SShahed Shaikh timeout = QLC_83XX_POST_FAST_MODE_TIMEOUT + 2000;
20843ced0a88SShahed Shaikh break;
20853ced0a88SShahed Shaikh case QLC_83XX_POST_MEDIUM_MODE:
20863ced0a88SShahed Shaikh timeout = QLC_83XX_POST_MED_MODE_TIMEOUT + 2000;
20873ced0a88SShahed Shaikh break;
20883ced0a88SShahed Shaikh case QLC_83XX_POST_SLOW_MODE:
20893ced0a88SShahed Shaikh timeout = QLC_83XX_POST_SLOW_MODE_TIMEOUT + 2000;
20903ced0a88SShahed Shaikh break;
20913ced0a88SShahed Shaikh default:
20923ced0a88SShahed Shaikh return -EINVAL;
20933ced0a88SShahed Shaikh }
20943ced0a88SShahed Shaikh
20953ced0a88SShahed Shaikh strncpy(fw_info->fw_file_name, QLC_83XX_POST_FW_FILE_NAME,
20963ced0a88SShahed Shaikh QLC_FW_FILE_NAME_LEN);
20973ced0a88SShahed Shaikh
20983ced0a88SShahed Shaikh ret = request_firmware(&fw_info->fw, fw_info->fw_file_name, dev);
20993ced0a88SShahed Shaikh if (ret) {
21003ced0a88SShahed Shaikh dev_err(dev, "POST firmware can not be loaded, skipping POST\n");
21013ced0a88SShahed Shaikh return 0;
21023ced0a88SShahed Shaikh }
21033ced0a88SShahed Shaikh
21043ced0a88SShahed Shaikh ret = qlcnic_83xx_copy_fw_file(adapter);
21053ced0a88SShahed Shaikh if (ret)
21063ced0a88SShahed Shaikh return ret;
21073ced0a88SShahed Shaikh
21083ced0a88SShahed Shaikh /* clear QLC_83XX_POST_SIGNATURE_REG register */
21093ced0a88SShahed Shaikh qlcnic_ind_wr(adapter, QLC_83XX_POST_SIGNATURE_REG, 0);
21103ced0a88SShahed Shaikh
21113ced0a88SShahed Shaikh /* Set POST mode */
21123ced0a88SShahed Shaikh qlcnic_ind_wr(adapter, QLC_83XX_POST_MODE_REG,
21133ced0a88SShahed Shaikh adapter->ahw->post_mode);
21143ced0a88SShahed Shaikh
21153ced0a88SShahed Shaikh QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,
21163ced0a88SShahed Shaikh QLC_83XX_BOOT_FROM_FILE);
21173ced0a88SShahed Shaikh
21183ced0a88SShahed Shaikh qlcnic_83xx_start_hw(adapter);
21193ced0a88SShahed Shaikh
21203ced0a88SShahed Shaikh count = 0;
21213ced0a88SShahed Shaikh do {
21223ced0a88SShahed Shaikh msleep(100);
21233ced0a88SShahed Shaikh count += 100;
21243ced0a88SShahed Shaikh
21253ced0a88SShahed Shaikh signature = qlcnic_ind_rd(adapter, QLC_83XX_POST_SIGNATURE_REG);
21263ced0a88SShahed Shaikh if (signature == QLC_83XX_POST_PASS)
21273ced0a88SShahed Shaikh break;
21283ced0a88SShahed Shaikh } while (timeout > count);
21293ced0a88SShahed Shaikh
21303ced0a88SShahed Shaikh if (timeout <= count) {
21313ced0a88SShahed Shaikh dev_err(dev, "POST timed out, signature = 0x%08x\n", signature);
21323ced0a88SShahed Shaikh return -EIO;
21333ced0a88SShahed Shaikh }
21343ced0a88SShahed Shaikh
21353ced0a88SShahed Shaikh switch (signature) {
21363ced0a88SShahed Shaikh case QLC_83XX_POST_PASS:
21373ced0a88SShahed Shaikh dev_info(dev, "POST passed, Signature = 0x%08x\n", signature);
21383ced0a88SShahed Shaikh break;
21393ced0a88SShahed Shaikh case QLC_83XX_POST_ASIC_STRESS_TEST_FAIL:
21403ced0a88SShahed Shaikh dev_err(dev, "POST failed, Test case : ASIC STRESS TEST, Signature = 0x%08x\n",
21413ced0a88SShahed Shaikh signature);
21423ced0a88SShahed Shaikh ret = -EIO;
21433ced0a88SShahed Shaikh break;
21443ced0a88SShahed Shaikh case QLC_83XX_POST_DDR_TEST_FAIL:
21453ced0a88SShahed Shaikh dev_err(dev, "POST failed, Test case : DDT TEST, Signature = 0x%08x\n",
21463ced0a88SShahed Shaikh signature);
21473ced0a88SShahed Shaikh ret = -EIO;
21483ced0a88SShahed Shaikh break;
21493ced0a88SShahed Shaikh case QLC_83XX_POST_ASIC_MEMORY_TEST_FAIL:
21503ced0a88SShahed Shaikh dev_err(dev, "POST failed, Test case : ASIC MEMORY TEST, Signature = 0x%08x\n",
21513ced0a88SShahed Shaikh signature);
21523ced0a88SShahed Shaikh ret = -EIO;
21533ced0a88SShahed Shaikh break;
21543ced0a88SShahed Shaikh case QLC_83XX_POST_FLASH_TEST_FAIL:
21553ced0a88SShahed Shaikh dev_err(dev, "POST failed, Test case : FLASH TEST, Signature = 0x%08x\n",
21563ced0a88SShahed Shaikh signature);
21573ced0a88SShahed Shaikh ret = -EIO;
21583ced0a88SShahed Shaikh break;
21593ced0a88SShahed Shaikh default:
21603ced0a88SShahed Shaikh dev_err(dev, "POST failed, Test case : INVALID, Signature = 0x%08x\n",
21613ced0a88SShahed Shaikh signature);
21623ced0a88SShahed Shaikh ret = -EIO;
21633ced0a88SShahed Shaikh break;
21643ced0a88SShahed Shaikh }
21653ced0a88SShahed Shaikh
21663ced0a88SShahed Shaikh return ret;
21673ced0a88SShahed Shaikh }
21683ced0a88SShahed Shaikh
qlcnic_83xx_load_fw_image_from_host(struct qlcnic_adapter * adapter)2169629263acSSony Chacko static int qlcnic_83xx_load_fw_image_from_host(struct qlcnic_adapter *adapter)
2170629263acSSony Chacko {
21717000078aSPratik Pujar struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;
2172629263acSSony Chacko int err = -EIO;
2173629263acSSony Chacko
21747000078aSPratik Pujar if (request_firmware(&fw_info->fw, fw_info->fw_file_name,
2175fef349ceSPratik Pujar &(adapter->pdev->dev))) {
2176629263acSSony Chacko dev_err(&adapter->pdev->dev,
2177629263acSSony Chacko "No file FW image, loading flash FW image.\n");
2178629263acSSony Chacko QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,
2179629263acSSony Chacko QLC_83XX_BOOT_FROM_FLASH);
2180629263acSSony Chacko } else {
2181629263acSSony Chacko if (qlcnic_83xx_copy_fw_file(adapter))
2182629263acSSony Chacko return err;
2183629263acSSony Chacko QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,
2184629263acSSony Chacko QLC_83XX_BOOT_FROM_FILE);
2185629263acSSony Chacko }
2186629263acSSony Chacko
2187629263acSSony Chacko return 0;
2188629263acSSony Chacko }
2189629263acSSony Chacko
qlcnic_83xx_restart_hw(struct qlcnic_adapter * adapter)2190629263acSSony Chacko static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)
2191629263acSSony Chacko {
21924e60ac46SSony Chacko u32 val;
2193629263acSSony Chacko int err = -EIO;
2194629263acSSony Chacko
219581d0aeb0SSony Chacko qlcnic_83xx_stop_hw(adapter);
21964e60ac46SSony Chacko
21974e60ac46SSony Chacko /* Collect FW register dump if required */
21984e60ac46SSony Chacko val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
21994e60ac46SSony Chacko if (!(val & QLC_83XX_IDC_GRACEFULL_RESET))
22004e60ac46SSony Chacko qlcnic_dump_fw(adapter);
220130fa15f6SManish Chopra
220230fa15f6SManish Chopra if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
220330fa15f6SManish Chopra netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
220430fa15f6SManish Chopra __func__);
220530fa15f6SManish Chopra qlcnic_83xx_idc_enter_failed_state(adapter, 1);
220630fa15f6SManish Chopra return err;
220730fa15f6SManish Chopra }
220830fa15f6SManish Chopra
220981d0aeb0SSony Chacko qlcnic_83xx_init_hw(adapter);
221081d0aeb0SSony Chacko
2211629263acSSony Chacko if (qlcnic_83xx_copy_bootloader(adapter))
2212629263acSSony Chacko return err;
22133ced0a88SShahed Shaikh
22143ced0a88SShahed Shaikh /* Check if POST needs to be run */
22153ced0a88SShahed Shaikh if (adapter->ahw->run_post) {
22163ced0a88SShahed Shaikh err = qlcnic_83xx_run_post(adapter);
22173ced0a88SShahed Shaikh if (err)
22183ced0a88SShahed Shaikh return err;
22193ced0a88SShahed Shaikh
22203ced0a88SShahed Shaikh /* No need to run POST in next reset sequence */
22213ced0a88SShahed Shaikh adapter->ahw->run_post = false;
22223ced0a88SShahed Shaikh
22233ced0a88SShahed Shaikh /* Again reset the adapter to load regular firmware */
22243ced0a88SShahed Shaikh qlcnic_83xx_stop_hw(adapter);
22253ced0a88SShahed Shaikh qlcnic_83xx_init_hw(adapter);
22263ced0a88SShahed Shaikh
22273ced0a88SShahed Shaikh err = qlcnic_83xx_copy_bootloader(adapter);
22283ced0a88SShahed Shaikh if (err)
22293ced0a88SShahed Shaikh return err;
22303ced0a88SShahed Shaikh }
22313ced0a88SShahed Shaikh
2232629263acSSony Chacko /* Boot either flash image or firmware image from host file system */
22333ced0a88SShahed Shaikh if (qlcnic_load_fw_file == 1) {
22343beb9be1SZhang Changzhong err = qlcnic_83xx_load_fw_image_from_host(adapter);
22353beb9be1SZhang Changzhong if (err)
2236629263acSSony Chacko return err;
2237629263acSSony Chacko } else {
2238629263acSSony Chacko QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,
2239629263acSSony Chacko QLC_83XX_BOOT_FROM_FLASH);
2240629263acSSony Chacko }
2241629263acSSony Chacko
224281d0aeb0SSony Chacko qlcnic_83xx_start_hw(adapter);
2243629263acSSony Chacko if (qlcnic_83xx_check_hw_status(adapter))
2244629263acSSony Chacko return -EIO;
2245629263acSSony Chacko
2246629263acSSony Chacko return 0;
2247629263acSSony Chacko }
2248629263acSSony Chacko
qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter * adapter)224921041400Sstephen hemminger static int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
2250629263acSSony Chacko {
2251629263acSSony Chacko int err;
2252629263acSSony Chacko struct qlcnic_info nic_info;
2253629263acSSony Chacko struct qlcnic_hardware_context *ahw = adapter->ahw;
2254629263acSSony Chacko
2255629263acSSony Chacko memset(&nic_info, 0, sizeof(struct qlcnic_info));
2256629263acSSony Chacko err = qlcnic_get_nic_info(adapter, &nic_info, ahw->pci_func);
2257629263acSSony Chacko if (err)
2258629263acSSony Chacko return -EIO;
2259629263acSSony Chacko
2260629263acSSony Chacko ahw->physical_port = (u8) nic_info.phys_port;
2261629263acSSony Chacko ahw->switch_mode = nic_info.switch_mode;
2262629263acSSony Chacko ahw->max_tx_ques = nic_info.max_tx_ques;
2263629263acSSony Chacko ahw->max_rx_ques = nic_info.max_rx_ques;
2264629263acSSony Chacko ahw->capabilities = nic_info.capabilities;
2265629263acSSony Chacko ahw->max_mac_filters = nic_info.max_mac_filters;
2266629263acSSony Chacko ahw->max_mtu = nic_info.max_mtu;
2267629263acSSony Chacko
226835dafcb0SSony Chacko /* eSwitch capability indicates vNIC mode.
226935dafcb0SSony Chacko * vNIC and SRIOV are mutually exclusive operational modes.
227035dafcb0SSony Chacko * If SR-IOV capability is detected, SR-IOV physical function
227135dafcb0SSony Chacko * will get initialized in default mode.
227235dafcb0SSony Chacko * SR-IOV virtual function initialization follows a
227335dafcb0SSony Chacko * different code path and opmode.
227435dafcb0SSony Chacko * SRIOV mode has precedence over vNIC mode.
227502feda17SRajesh Borundia */
227635dafcb0SSony Chacko if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state))
227735dafcb0SSony Chacko return QLC_83XX_DEFAULT_OPMODE;
227802feda17SRajesh Borundia
227935dafcb0SSony Chacko if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
228034e8c406SHimanshu Madhani return QLCNIC_VNIC_MODE;
2281629263acSSony Chacko
228235dafcb0SSony Chacko return QLC_83XX_DEFAULT_OPMODE;
2283629263acSSony Chacko }
2284629263acSSony Chacko
qlcnic_83xx_configure_opmode(struct qlcnic_adapter * adapter)228502feda17SRajesh Borundia int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
2286629263acSSony Chacko {
228735dafcb0SSony Chacko struct qlcnic_hardware_context *ahw = adapter->ahw;
22887b546842SShahed Shaikh u16 max_sds_rings, max_tx_rings;
2289629263acSSony Chacko int ret;
2290629263acSSony Chacko
2291629263acSSony Chacko ret = qlcnic_83xx_get_nic_configuration(adapter);
2292629263acSSony Chacko if (ret == -EIO)
2293629263acSSony Chacko return -EIO;
2294629263acSSony Chacko
229534e8c406SHimanshu Madhani if (ret == QLCNIC_VNIC_MODE) {
229634e8c406SHimanshu Madhani ahw->nic_mode = QLCNIC_VNIC_MODE;
229734e8c406SHimanshu Madhani
2298d71170fbSSony Chacko if (qlcnic_83xx_config_vnic_opmode(adapter))
2299d71170fbSSony Chacko return -EIO;
230035dafcb0SSony Chacko
23017b546842SShahed Shaikh max_sds_rings = QLCNIC_MAX_VNIC_SDS_RINGS;
23027b546842SShahed Shaikh max_tx_rings = QLCNIC_MAX_VNIC_TX_RINGS;
230335dafcb0SSony Chacko } else if (ret == QLC_83XX_DEFAULT_OPMODE) {
230434e8c406SHimanshu Madhani ahw->nic_mode = QLCNIC_DEFAULT_MODE;
230535dafcb0SSony Chacko adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
230635dafcb0SSony Chacko ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
23077b546842SShahed Shaikh max_sds_rings = QLCNIC_MAX_SDS_RINGS;
23087b546842SShahed Shaikh max_tx_rings = QLCNIC_MAX_TX_RINGS;
230935dafcb0SSony Chacko } else {
2310c65762fcSSucheta Chakraborty dev_err(&adapter->pdev->dev, "%s: Invalid opmode %d\n",
2311c65762fcSSucheta Chakraborty __func__, ret);
2312629263acSSony Chacko return -EIO;
2313629263acSSony Chacko }
2314629263acSSony Chacko
23157b546842SShahed Shaikh adapter->max_sds_rings = min(ahw->max_rx_ques, max_sds_rings);
23167b546842SShahed Shaikh adapter->max_tx_rings = min(ahw->max_tx_ques, max_tx_rings);
23177b546842SShahed Shaikh
2318629263acSSony Chacko return 0;
2319629263acSSony Chacko }
2320629263acSSony Chacko
qlcnic_83xx_config_buff_descriptors(struct qlcnic_adapter * adapter)2321629263acSSony Chacko static void qlcnic_83xx_config_buff_descriptors(struct qlcnic_adapter *adapter)
2322629263acSSony Chacko {
2323629263acSSony Chacko struct qlcnic_hardware_context *ahw = adapter->ahw;
2324629263acSSony Chacko
2325629263acSSony Chacko if (ahw->port_type == QLCNIC_XGBE) {
2326629263acSSony Chacko adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;
2327629263acSSony Chacko adapter->max_rxd = MAX_RCV_DESCRIPTORS_10G;
2328629263acSSony Chacko adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
2329629263acSSony Chacko adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
2330629263acSSony Chacko
2331629263acSSony Chacko } else if (ahw->port_type == QLCNIC_GBE) {
2332629263acSSony Chacko adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
2333629263acSSony Chacko adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
2334629263acSSony Chacko adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
2335629263acSSony Chacko adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;
2336629263acSSony Chacko }
2337629263acSSony Chacko adapter->num_txd = MAX_CMD_DESCRIPTORS;
2338629263acSSony Chacko adapter->max_rds_rings = MAX_RDS_RINGS;
2339629263acSSony Chacko }
2340629263acSSony Chacko
qlcnic_83xx_init_default_driver(struct qlcnic_adapter * adapter)2341629263acSSony Chacko static int qlcnic_83xx_init_default_driver(struct qlcnic_adapter *adapter)
2342629263acSSony Chacko {
2343629263acSSony Chacko int err = -EIO;
2344629263acSSony Chacko
23454e60ac46SSony Chacko qlcnic_83xx_get_minidump_template(adapter);
2346629263acSSony Chacko if (qlcnic_83xx_get_port_info(adapter))
2347629263acSSony Chacko return err;
2348629263acSSony Chacko
2349629263acSSony Chacko qlcnic_83xx_config_buff_descriptors(adapter);
2350629263acSSony Chacko adapter->ahw->msix_supported = !!qlcnic_use_msi_x;
2351629263acSSony Chacko adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
2352629263acSSony Chacko
2353629263acSSony Chacko dev_info(&adapter->pdev->dev, "HAL Version: %d\n",
2354629263acSSony Chacko adapter->ahw->fw_hal_version);
2355629263acSSony Chacko
2356629263acSSony Chacko return 0;
2357629263acSSony Chacko }
2358629263acSSony Chacko
2359629263acSSony Chacko #define IS_QLC_83XX_USED(a, b, c) (((1 << a->portnum) & b) || ((c >> 6) & 0x1))
qlcnic_83xx_clear_function_resources(struct qlcnic_adapter * adapter)2360629263acSSony Chacko static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter)
2361629263acSSony Chacko {
2362629263acSSony Chacko struct qlcnic_cmd_args cmd;
2363629263acSSony Chacko u32 presence_mask, audit_mask;
2364629263acSSony Chacko int status;
2365629263acSSony Chacko
2366629263acSSony Chacko presence_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
2367629263acSSony Chacko audit_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT);
2368629263acSSony Chacko
2369629263acSSony Chacko if (IS_QLC_83XX_USED(adapter, presence_mask, audit_mask)) {
2370b6b4316cSShahed Shaikh status = qlcnic_alloc_mbx_args(&cmd, adapter,
2371b6b4316cSShahed Shaikh QLCNIC_CMD_STOP_NIC_FUNC);
2372b6b4316cSShahed Shaikh if (status)
2373b6b4316cSShahed Shaikh return;
2374b6b4316cSShahed Shaikh
2375629263acSSony Chacko cmd.req.arg[1] = BIT_31;
2376629263acSSony Chacko status = qlcnic_issue_cmd(adapter, &cmd);
2377629263acSSony Chacko if (status)
2378629263acSSony Chacko dev_err(&adapter->pdev->dev,
2379629263acSSony Chacko "Failed to clean up the function resources\n");
2380629263acSSony Chacko qlcnic_free_mbx_args(&cmd);
2381629263acSSony Chacko }
2382629263acSSony Chacko }
2383629263acSSony Chacko
qlcnic_83xx_get_fw_info(struct qlcnic_adapter * adapter)23847000078aSPratik Pujar static int qlcnic_83xx_get_fw_info(struct qlcnic_adapter *adapter)
23857000078aSPratik Pujar {
23867000078aSPratik Pujar struct qlcnic_hardware_context *ahw = adapter->ahw;
23877000078aSPratik Pujar struct pci_dev *pdev = adapter->pdev;
23887000078aSPratik Pujar struct qlc_83xx_fw_info *fw_info;
23897000078aSPratik Pujar int err = 0;
23907000078aSPratik Pujar
23917000078aSPratik Pujar ahw->fw_info = kzalloc(sizeof(*fw_info), GFP_KERNEL);
23927000078aSPratik Pujar if (!ahw->fw_info) {
23937000078aSPratik Pujar err = -ENOMEM;
23947000078aSPratik Pujar } else {
23957000078aSPratik Pujar fw_info = ahw->fw_info;
23967000078aSPratik Pujar switch (pdev->device) {
23977000078aSPratik Pujar case PCI_DEVICE_ID_QLOGIC_QLE834X:
239840e2b8edSShahed Shaikh case PCI_DEVICE_ID_QLOGIC_QLE8830:
23997000078aSPratik Pujar strncpy(fw_info->fw_file_name, QLC_83XX_FW_FILE_NAME,
24007000078aSPratik Pujar QLC_FW_FILE_NAME_LEN);
24017000078aSPratik Pujar break;
24027000078aSPratik Pujar case PCI_DEVICE_ID_QLOGIC_QLE844X:
24037000078aSPratik Pujar strncpy(fw_info->fw_file_name, QLC_84XX_FW_FILE_NAME,
24047000078aSPratik Pujar QLC_FW_FILE_NAME_LEN);
24057000078aSPratik Pujar break;
24067000078aSPratik Pujar default:
24077000078aSPratik Pujar dev_err(&pdev->dev, "%s: Invalid device id\n",
24087000078aSPratik Pujar __func__);
24097000078aSPratik Pujar err = -EINVAL;
24107000078aSPratik Pujar break;
24117000078aSPratik Pujar }
24127000078aSPratik Pujar }
24137000078aSPratik Pujar
24147000078aSPratik Pujar return err;
24157000078aSPratik Pujar }
24167000078aSPratik Pujar
qlcnic_83xx_init_rings(struct qlcnic_adapter * adapter)241734e8c406SHimanshu Madhani static void qlcnic_83xx_init_rings(struct qlcnic_adapter *adapter)
241834e8c406SHimanshu Madhani {
241918afc102SHimanshu Madhani u8 rx_cnt = QLCNIC_DEF_SDS_RINGS;
242018afc102SHimanshu Madhani u8 tx_cnt = QLCNIC_DEF_TX_RINGS;
242118afc102SHimanshu Madhani
242234e8c406SHimanshu Madhani adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS;
242334e8c406SHimanshu Madhani adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
242434e8c406SHimanshu Madhani
242518afc102SHimanshu Madhani if (!adapter->ahw->msix_supported) {
242618afc102SHimanshu Madhani rx_cnt = QLCNIC_SINGLE_RING;
242718afc102SHimanshu Madhani tx_cnt = QLCNIC_SINGLE_RING;
242818afc102SHimanshu Madhani }
242934e8c406SHimanshu Madhani
243034e8c406SHimanshu Madhani /* compute and set drv sds rings */
243118afc102SHimanshu Madhani qlcnic_set_tx_ring_count(adapter, tx_cnt);
243218afc102SHimanshu Madhani qlcnic_set_sds_ring_count(adapter, rx_cnt);
243334e8c406SHimanshu Madhani }
24347000078aSPratik Pujar
qlcnic_83xx_init(struct qlcnic_adapter * adapter)2435a72dc199SChristophe JAILLET int qlcnic_83xx_init(struct qlcnic_adapter *adapter)
2436629263acSSony Chacko {
2437629263acSSony Chacko struct qlcnic_hardware_context *ahw = adapter->ahw;
2438068a8d19SManish Chopra int err = 0;
2439629263acSSony Chacko
244072ebe349SSucheta Chakraborty adapter->rx_mac_learn = false;
2441068a8d19SManish Chopra ahw->msix_supported = !!qlcnic_use_msi_x;
244234e8c406SHimanshu Madhani
24433ced0a88SShahed Shaikh /* Check if POST needs to be run */
24443ced0a88SShahed Shaikh switch (qlcnic_load_fw_file) {
24453ced0a88SShahed Shaikh case 2:
24463ced0a88SShahed Shaikh ahw->post_mode = QLC_83XX_POST_FAST_MODE;
24473ced0a88SShahed Shaikh ahw->run_post = true;
24483ced0a88SShahed Shaikh break;
24493ced0a88SShahed Shaikh case 3:
24503ced0a88SShahed Shaikh ahw->post_mode = QLC_83XX_POST_MEDIUM_MODE;
24513ced0a88SShahed Shaikh ahw->run_post = true;
24523ced0a88SShahed Shaikh break;
24533ced0a88SShahed Shaikh case 4:
24543ced0a88SShahed Shaikh ahw->post_mode = QLC_83XX_POST_SLOW_MODE;
24553ced0a88SShahed Shaikh ahw->run_post = true;
24563ced0a88SShahed Shaikh break;
24573ced0a88SShahed Shaikh default:
24583ced0a88SShahed Shaikh ahw->run_post = false;
24593ced0a88SShahed Shaikh break;
24603ced0a88SShahed Shaikh }
24613ced0a88SShahed Shaikh
246234e8c406SHimanshu Madhani qlcnic_83xx_init_rings(adapter);
246334e8c406SHimanshu Madhani
2464068a8d19SManish Chopra err = qlcnic_83xx_init_mailbox_work(adapter);
2465068a8d19SManish Chopra if (err)
2466068a8d19SManish Chopra goto exit;
2467f8468331SRajesh Borundia
2468068a8d19SManish Chopra if (qlcnic_sriov_vf_check(adapter)) {
2469a72dc199SChristophe JAILLET err = qlcnic_sriov_vf_init(adapter);
2470068a8d19SManish Chopra if (err)
2471068a8d19SManish Chopra goto detach_mbx;
2472068a8d19SManish Chopra else
2473068a8d19SManish Chopra return err;
2474068a8d19SManish Chopra }
2475629263acSSony Chacko
247678ea2d97SSucheta Chakraborty if (qlcnic_83xx_read_flash_descriptor_table(adapter) ||
247778ea2d97SSucheta Chakraborty qlcnic_83xx_read_flash_mfg_id(adapter)) {
247878ea2d97SSucheta Chakraborty dev_err(&adapter->pdev->dev, "Failed reading flash mfg id\n");
247978ea2d97SSucheta Chakraborty err = -ENOTRECOVERABLE;
248078ea2d97SSucheta Chakraborty goto detach_mbx;
248178ea2d97SSucheta Chakraborty }
248278ea2d97SSucheta Chakraborty
2483068a8d19SManish Chopra err = qlcnic_83xx_check_hw_status(adapter);
2484068a8d19SManish Chopra if (err)
2485068a8d19SManish Chopra goto detach_mbx;
2486629263acSSony Chacko
24877000078aSPratik Pujar err = qlcnic_83xx_get_fw_info(adapter);
2488b5acb255SManish Chopra if (err)
2489b5acb255SManish Chopra goto detach_mbx;
2490b5acb255SManish Chopra
24917000078aSPratik Pujar err = qlcnic_83xx_idc_init(adapter);
24927000078aSPratik Pujar if (err)
249378ea2d97SSucheta Chakraborty goto detach_mbx;
24947000078aSPratik Pujar
249534e8c406SHimanshu Madhani err = qlcnic_setup_intr(adapter);
2496068a8d19SManish Chopra if (err) {
2497068a8d19SManish Chopra dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
2498068a8d19SManish Chopra goto disable_intr;
2499068a8d19SManish Chopra }
2500068a8d19SManish Chopra
2501463518a0SSucheta Chakraborty INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);
2502463518a0SSucheta Chakraborty
2503068a8d19SManish Chopra err = qlcnic_83xx_setup_mbx_intr(adapter);
2504068a8d19SManish Chopra if (err)
2505068a8d19SManish Chopra goto disable_mbx_intr;
2506068a8d19SManish Chopra
2507629263acSSony Chacko qlcnic_83xx_clear_function_resources(adapter);
2508*13a7c896SDaniil Tatianin
2509*13a7c896SDaniil Tatianin err = qlcnic_dcb_enable(adapter->dcb);
2510*13a7c896SDaniil Tatianin if (err) {
2511*13a7c896SDaniil Tatianin qlcnic_dcb_free(adapter->dcb);
2512*13a7c896SDaniil Tatianin goto disable_mbx_intr;
2513*13a7c896SDaniil Tatianin }
2514*13a7c896SDaniil Tatianin
25159b0fff2aSSucheta Chakraborty qlcnic_83xx_initialize_nic(adapter, 1);
25164d52e1e8SSucheta Chakraborty qlcnic_dcb_get_info(adapter->dcb);
2517d5fcff04SHimanshu Madhani
2518629263acSSony Chacko /* Configure default, SR-IOV or Virtual NIC mode of operation */
2519068a8d19SManish Chopra err = qlcnic_83xx_configure_opmode(adapter);
2520068a8d19SManish Chopra if (err)
2521068a8d19SManish Chopra goto disable_mbx_intr;
2522629263acSSony Chacko
252334e8c406SHimanshu Madhani
2524629263acSSony Chacko /* Perform operating mode specific initialization */
2525068a8d19SManish Chopra err = adapter->nic_ops->init_driver(adapter);
2526068a8d19SManish Chopra if (err)
2527068a8d19SManish Chopra goto disable_mbx_intr;
2528629263acSSony Chacko
2529629263acSSony Chacko /* Periodically monitor device status */
2530629263acSSony Chacko qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work);
2531068a8d19SManish Chopra return 0;
2532629263acSSony Chacko
2533068a8d19SManish Chopra disable_mbx_intr:
2534068a8d19SManish Chopra qlcnic_83xx_free_mbx_intr(adapter);
2535068a8d19SManish Chopra
2536068a8d19SManish Chopra disable_intr:
2537068a8d19SManish Chopra qlcnic_teardown_intr(adapter);
2538068a8d19SManish Chopra
2539068a8d19SManish Chopra detach_mbx:
2540068a8d19SManish Chopra qlcnic_83xx_detach_mailbox_work(adapter);
2541068a8d19SManish Chopra qlcnic_83xx_free_mailbox(ahw->mailbox);
254278ea2d97SSucheta Chakraborty ahw->mailbox = NULL;
2543068a8d19SManish Chopra exit:
2544068a8d19SManish Chopra return err;
2545629263acSSony Chacko }
25469ce226faSPratik Pujar
qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter * adapter)25479ce226faSPratik Pujar void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *adapter)
25489ce226faSPratik Pujar {
25499ce226faSPratik Pujar struct qlcnic_hardware_context *ahw = adapter->ahw;
25509ce226faSPratik Pujar struct qlc_83xx_idc *idc = &ahw->idc;
25519ce226faSPratik Pujar
25529ce226faSPratik Pujar clear_bit(QLC_83XX_MBX_READY, &idc->status);
25539ce226faSPratik Pujar cancel_delayed_work_sync(&adapter->fw_work);
25549ce226faSPratik Pujar
255534e8c406SHimanshu Madhani if (ahw->nic_mode == QLCNIC_VNIC_MODE)
25569ce226faSPratik Pujar qlcnic_83xx_disable_vnic_mode(adapter, 1);
25579ce226faSPratik Pujar
25589ce226faSPratik Pujar qlcnic_83xx_idc_detach_driver(adapter);
25599b0fff2aSSucheta Chakraborty qlcnic_83xx_initialize_nic(adapter, 0);
25609ce226faSPratik Pujar
25619ce226faSPratik Pujar cancel_delayed_work_sync(&adapter->idc_aen_work);
25629ce226faSPratik Pujar }
25639ce226faSPratik Pujar
qlcnic_83xx_aer_reset(struct qlcnic_adapter * adapter)25649ce226faSPratik Pujar int qlcnic_83xx_aer_reset(struct qlcnic_adapter *adapter)
25659ce226faSPratik Pujar {
25669ce226faSPratik Pujar struct qlcnic_hardware_context *ahw = adapter->ahw;
25679ce226faSPratik Pujar struct qlc_83xx_idc *idc = &ahw->idc;
25689ce226faSPratik Pujar int ret = 0;
25699ce226faSPratik Pujar u32 owner;
25709ce226faSPratik Pujar
25719ce226faSPratik Pujar /* Mark the previous IDC state as NEED_RESET so
25729ce226faSPratik Pujar * that state_entry() will perform the reattachment
25739ce226faSPratik Pujar * and bringup the device
25749ce226faSPratik Pujar */
25759ce226faSPratik Pujar idc->prev_state = QLC_83XX_IDC_DEV_NEED_RESET;
25769ce226faSPratik Pujar owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
25779ce226faSPratik Pujar if (ahw->pci_func == owner) {
25789ce226faSPratik Pujar ret = qlcnic_83xx_restart_hw(adapter);
25799ce226faSPratik Pujar if (ret < 0)
25809ce226faSPratik Pujar return ret;
25819ce226faSPratik Pujar qlcnic_83xx_idc_clear_registers(adapter, 0);
25829ce226faSPratik Pujar }
25839ce226faSPratik Pujar
25849ce226faSPratik Pujar ret = idc->state_entry(adapter);
25859ce226faSPratik Pujar return ret;
25869ce226faSPratik Pujar }
25879ce226faSPratik Pujar
qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter * adapter)25889ce226faSPratik Pujar void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *adapter)
25899ce226faSPratik Pujar {
25909ce226faSPratik Pujar struct qlcnic_hardware_context *ahw = adapter->ahw;
25919ce226faSPratik Pujar struct qlc_83xx_idc *idc = &ahw->idc;
25929ce226faSPratik Pujar u32 owner;
25939ce226faSPratik Pujar
25949ce226faSPratik Pujar idc->prev_state = QLC_83XX_IDC_DEV_READY;
25959ce226faSPratik Pujar owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
25969ce226faSPratik Pujar if (ahw->pci_func == owner)
25979ce226faSPratik Pujar qlcnic_83xx_idc_enter_ready_state(adapter, 0);
25989ce226faSPratik Pujar
25999ce226faSPratik Pujar qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state, 0);
26009ce226faSPratik Pujar }
2601