Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ocs_gendump.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015, Emulex
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 #include "ocs.h"
34 #include "ocs_gendump.h"
35 
36 #define OCS_XPORT_QUIESCED_TIMEOUT_MSEC 60000
37 
38 int32_t
39 ocs_port_reset(ocs_t *ocs)
40 {
41  int rc = 0;
42 
43  if (ocs_hal_reset(&ocs->hal, OCS_HAL_RESET_FUNCTION)) {
44  ocs_log_err(ocs, "Failed to reset port\n");
45  rc = -1;
46  } else {
47  ocs_log_info(ocs, "Successfully reset port\n");
48 
49  /* now initialize hal so user can read the dump in */
50  if (ocs_hal_init(&ocs->hal)) {
51  ocs_log_err(ocs, "Failed to initialize hal\n");
52  rc = -1;
53  } else {
54  ocs_log_info(ocs, "Successfully initialized hal\n");
55  }
56  }
57 
58  return rc;
59 }
60 
61 /* Reset all the functions associated with a bus/dev */
62 int32_t
63 ocs_adapter_reset(ocs_t *ocs)
64 {
65  ocs_t *other_ocs = NULL;
66  uint8_t bus, dev, func;
67  int rc = 0;
68  uint32_t index = 0;
69 
70  ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
71  while ((other_ocs = ocs_get_instance(index++)) != NULL) {
72  uint8_t other_bus, other_dev, other_func;
73 
74  ocs_get_bus_dev_func(other_ocs, &other_bus, &other_dev, &other_func);
75  if ((bus == other_bus) && (dev == other_dev)) {
76  if (0 != ocs_port_reset(other_ocs)) {
77  rc = -1;
78  }
79  }
80  }
81 
82  return rc;
83 }
84 
85 int32_t
86 ocs_fw_reset(ocs_t *ocs)
87 {
88  ocs_t *other_ocs;
89  uint8_t bus, dev, func;
90  uint8_t other_bus, other_dev, other_func;
91  uint8_t prev_port_state[OCS_MAX_HBA_PORTS] = { 0 };
92  int32_t rc = 0;
93  uint32_t ms_waited = 0;
94  uint32_t index = 0, port_index = 0;
95  ocs_xport_stats_t status;
96 
97  /* Stop FC statistics timers */
99  ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
100 
101  /* Drop link on all ports */
102  while ((other_ocs = ocs_get_instance(index++)) != NULL) {
103  ocs_get_bus_dev_func(other_ocs, &other_bus, &other_dev, &other_func);
104  if ((bus == other_bus) && (dev == other_dev) && (port_index < OCS_MAX_HBA_PORTS)) {
105  /* Check the current link status and save for future use */
106  if (0 == ocs_xport_status(other_ocs->xport, OCS_XPORT_PORT_STATUS, &status)) {
107  if (OCS_XPORT_PORT_ONLINE == status.value) {
108  prev_port_state[port_index] = 1;
109  } else {
110  prev_port_state[port_index] = 0;
111  }
112  }
113  port_index++;
114  }
115  }
116 
117  index = 0;
118  /* Wait until all ports have quiesced */
119  while ((other_ocs = ocs_get_instance(index++)) != NULL) {
120  ocs_get_bus_dev_func(other_ocs, &other_bus, &other_dev, &other_func);
121  if ((bus == other_bus) && (dev == other_dev)) {
122  for (;;) {
123  ocs_xport_status(other_ocs->xport, OCS_XPORT_IS_QUIESCED, &status);
124  if (status.value) {
125  ocs_log_debug(other_ocs, "Port quiesced\n");
126  break;
127  }
128 
129  ocs_delay_usec(10000);
130  ms_waited += 10;
131  if (ms_waited > OCS_XPORT_QUIESCED_TIMEOUT_MSEC) {
132  ocs_log_err(other_ocs, "Timed out waiting for port to quiesce\n");
133  break;
134  }
135  }
136  }
137  }
138 
139  ocs_log_info(ocs, "Resetting firmware\n");
140  if (ocs_hal_reset(&ocs->hal, OCS_HAL_RESET_FIRMWARE)) {
141  ocs_log_err(ocs, "Firmware reset NOT successful\n");
142  return -1;
143  }
144  ocs_log_info(ocs, "Firmware reset successful\n");
145 
146  index = 0;
147  /* Re-attach all the pci functions on this adapter */
148  while ((other_ocs = ocs_get_instance(index++)) != NULL) {
149  ocs_get_bus_dev_func(other_ocs, &other_bus, &other_dev, &other_func);
150  if ((bus == other_bus) && (dev == other_dev)) {
151  if (OCS_HAL_STATE_UNINITIALIZED != other_ocs->hal.state) {
152  other_ocs->hal.state = OCS_HAL_STATE_QUEUES_ALLOCATED;
153  }
154 
155  ocs_device_detach(other_ocs);
156  if (0 != ocs_device_attach(other_ocs)) {
157  ocs_log_err(other_ocs, "Failed to re-attach the device\n");
158  rc = -1;
159  } else {
160  ocs_log_info(other_ocs, "Successfully re-attached the device\n");
161  }
162  }
163  }
164 
165  index = port_index = 0;
166  /* Bring up the links on each port to previous state */
167  while ((other_ocs = ocs_get_instance(index++)) != NULL) {
168  ocs_get_bus_dev_func(other_ocs, &other_bus, &other_dev, &other_func);
169  if ((bus == other_bus) && (dev == other_dev) && (port_index < OCS_MAX_HBA_PORTS)) {
170  if (prev_port_state[port_index]) {
171  ocs_xport_control(other_ocs->xport, OCS_XPORT_PORT_ONLINE);
172  }
173  port_index++;
174  }
175  }
176 
177  return rc;
178 }
179 
180 static uint32_t
181 ocs_fw_dump_present(ocs_t *ocs, uint32_t *ms_waited)
182 {
183  uint32_t dump_present = FW_DUMP_READY_STATUS_NOT_READY;
184 
185  /* Wait for the dump to complete */
186  for (*ms_waited = 0; *ms_waited < SLI4_FW_DUMP_TIMEOUT_MSEC; *ms_waited += 100) {
187 
188  /* First wait for the status register to reflect steady state
189  * values as a result of writing to control/physdev regs
190  */
191  ocs_delay_msec(100);
192 
193  ocs_hal_get(&ocs->hal, OCS_HAL_DUMP_READY, &dump_present);
194  if (dump_present)
195  break;
196 
197  }
198 
199  return dump_present;
200 }
201 
202 int32_t
203 ocs_trigger_dump(ocs_t *ocs, uint8_t dump_level)
204 {
205  uint32_t ms_waited = 0;
206  uint32_t dump_status = FW_DUMP_READY_STATUS_NOT_READY;
207 
208  /* If the chip is in an error state (UE'd), wait for the already triggered dump to complete */
209  if (sli_fw_error_status(&ocs->hal.sli) > 0) {
210  ocs_log_info(ocs, "Waiting for the recovery dump to complete\n");
211  dump_status = ocs_fw_dump_present(ocs, &ms_waited);
212  }
213 
214  if (FW_DUMP_READY_STATUS_NOT_READY == dump_status) {
215  ocs_log_info(ocs, "Initiating the FW dump forcefully\n");
216 
217  if (OCS_HAL_RTN_SUCCESS != ocs_hal_raise_ue(&ocs->hal, dump_level)) {
218  ocs_log_err(ocs, "Failed to trigger the FW dump\n");
220  }
221 
222  ocs_log_info(ocs, "Dump requested, waiting for it to complete\n");
223  dump_status = ocs_fw_dump_present(ocs, &ms_waited);
224  }
225 
226  if (FW_DUMP_READY_STATUS_NOT_READY == dump_status) {
227  ocs_log_err(ocs, "Failed to see the FW dump (%d) after %d msec\n", dump_status, ms_waited);
229  }
230 
231  if (FW_DUMP_READY_STATUS_SKIP_DUMP == dump_status) {
232  ocs_log_info(ocs, "Skipped the FW dump\n");
234  }
235 
236  if (ms_waited) {
237  ocs_log_info(ocs, "FW dump was generated successfully in %d msec\n", ms_waited);
238  } else {
239  ocs_log_info(ocs, "FW dump was already present\n");
240  }
241 
243 }
244 
245 int
246 ocs_gen_dump(ocs_t *ocs)
247 {
248  int rc = 0;
249  uint32_t reset_required;
250 
251  /* Collect the FW dump */
253  if (rc) {
254  return rc;
255  }
256 
257  /* now reset the adapter */
258  ocs_hal_get(&ocs->hal, OCS_HAL_RESET_REQUIRED, &reset_required);
259  ocs_log_info(ocs, "Reset required=%d\n", reset_required);
260  if (reset_required) {
261  if (0 == ocs_fw_reset(ocs)) {
262  ocs_log_info(ocs, "All devices reset\n");
263  } else {
264  ocs_log_err(ocs, "All devices NOT reset\n");
265  }
266  }
267 
268  return rc;
269 }
270 
271 /**
272  * @brief Check the fw dump state
273  *
274  * @return TRUE if the state is set, FALSE otherwise
275  */
276 int32_t
277 ocs_fw_dump_state_check(ocs_t *ocs, uint32_t state)
278 {
279  ocs_t *other_ocs;
280  uint8_t bus, dev, func;
281  uint8_t other_bus, other_dev, other_func;
282  int32_t rc = FALSE;
283  uint32_t index = 0;
284 
285  ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
286  while ((other_ocs = ocs_get_instance(index++)) != NULL) {
287  ocs_get_bus_dev_func(other_ocs, &other_bus, &other_dev, &other_func);
288  if ((bus == other_bus) && (dev == other_dev)) {
289  if ((FW_CHIP_DUMP_STATE_VALID == state) && (0 != other_func)) {
290  /* For CLD, check the dump state only on pci func 0 */
291  continue;
292  }
293 
294  if ((FW_FUNC_DUMP_STATE_VALID == state) && (func != other_func)) {
295  /* For FDD, check the dump state only on the specified pci func */
296  continue;
297  }
298 
299  /* Return the existing dump irrespective of CLD / FDD request */
300  ocs_lock(&other_ocs->fw_dump.lock);
301  if (other_ocs->fw_dump.state) {
302  rc = TRUE;
303  ocs_unlock(&other_ocs->fw_dump.lock);
304  break;
305  }
306  ocs_unlock(&other_ocs->fw_dump.lock);
307  }
308  }
309 
310  return rc;
311 }
#define OCS_XPORT_QUIESCED_TIMEOUT_MSEC
Definition: ocs_gendump.c:36
static uint32_t ocs_fw_dump_present(ocs_t *ocs, uint32_t *ms_waited)
Definition: ocs_gendump.c:181
int32_t sli_fw_error_status(sli4_t *sli4)
Read the SLIPORT_SEMAPHORE and SLIPORT_STATUS registers to check if the port status indicates that a ...
Definition: sli4.c:6283
ocs_hal_rtn_e ocs_hal_init(ocs_hal_t *hal)
Allocate memory structures to prepare for the device operation.
Definition: ocs_hal.c:813
#define OCS_FW_DUMP_STATUS_SKIP
Definition: ocs_gendump.h:50
void ocs_device_stop_stats_timers(ocs_t *ocs)
Definition: ocs_xport.c:1319
#define OCS_FW_DUMP_STATUS_SUCCESS
Definition: ocs_gendump.h:48
int32_t ocs_trigger_dump(ocs_t *ocs, uint8_t dump_level)
Definition: ocs_gendump.c:203
#define OCS_MAX_HBA_PORTS
Definition: ocs_gendump.h:45
int32_t ocs_fw_dump_state_check(ocs_t *ocs, uint32_t state)
Check the fw dump state.
Definition: ocs_gendump.c:277
#define FW_DUMP_READY_STATUS_SKIP_DUMP
Definition: ocs_gendump.h:71
#define FW_FUNC_DUMP_STATE_VALID
Definition: ocs_gendump.h:61
int32_t ocs_device_detach(ocs_t *ocs)
free resources when pci device detach
int32_t ocs_xport_control(ocs_xport_t *xport, ocs_xport_ctrl_e cmd,...)
Perform transport attach function.
Definition: ocs_xport.c:866
ocs_hal_rtn_e ocs_hal_reset(ocs_hal_t *hal, ocs_hal_reset_e reset)
Definition: ocs_hal.c:1670
#define SLI4_FW_DUMP_TIMEOUT_MSEC
Definition: sli4.h:50
uint32_t value
Definition: ocs_xport.h:170
ocs_hal_rtn_e ocs_hal_get(ocs_hal_t *hal, ocs_hal_property_e prop, uint32_t *value)
Definition: ocs_hal.c:1840
int32_t ocs_adapter_reset(ocs_t *ocs)
Definition: ocs_gendump.c:63
ocs_hal_rtn_e ocs_hal_raise_ue(ocs_hal_t *hal, uint8_t dump)
Cause chip to enter an unrecoverable error state.
Definition: ocs_hal.c:8161
int32_t ocs_device_attach(ocs_t *ocs)
Initialize resources when pci devices attach.
#define FW_CHIP_DUMP_STATE_VALID
Definition: ocs_gendump.h:60
ocs_t * ocs_get_instance(uint32_t index)
return pointer to ocs structure given instance index
int32_t ocs_fw_reset(ocs_t *ocs)
Definition: ocs_gendump.c:86
#define FW_CHIP_LEVEL_DUMP
Definition: ocs_gendump.h:55
int32_t ocs_get_bus_dev_func(ocs_t *ocs, uint8_t *bus, uint8_t *dev, uint8_t *func)
int32_t ocs_port_reset(ocs_t *ocs)
Definition: ocs_gendump.c:39
#define OCS_FW_DUMP_STATUS_FAILED
Definition: ocs_gendump.h:51
int32_t ocs_xport_status(ocs_xport_t *xport, ocs_xport_status_e cmd, ocs_xport_stats_t *result)
Return status on a link.
Definition: ocs_xport.c:1073
#define FW_DUMP_READY_STATUS_NOT_READY
Definition: ocs_gendump.h:68
int ocs_gen_dump(ocs_t *ocs)
Definition: ocs_gendump.c:246