Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ocs_hal_workaround.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 /**
34  * @file
35  * This file contains all HAL runtime workaround code. Based on the asic type,
36  * asic revision, and range of fw revisions, a particular workaround may be enabled.
37  *
38  * A workaround may consist of overriding a particular HAL/SLI4 value that was initialized
39  * during ocs_hal_setup() (for example the MAX_QUEUE overrides for mis-reported queue
40  * sizes). Or if required, elements of the ocs_hal_workaround_t structure may be set to
41  * control specific runtime behavior.
42  *
43  * It is intended that the controls in ocs_hal_workaround_t be defined functionally. So we
44  * would have the driver look like: "if (hal->workaround.enable_xxx) then ...", rather than
45  * what we might previously see as "if this is a BE3, then do xxx"
46  *
47  */
48 
49 #include "ocs_hal.h"
50 
51 #define HAL_FWREV_ZERO (0ull)
52 #define HAL_FWREV_MAX (~0ull)
53 
54 #define SLI4_ASIC_TYPE_ANY 0
55 #define SLI4_ASIC_REV_ANY 0
56 
57 /**
58  * @brief Internal definition of workarounds
59  */
60 
61 typedef enum {
63  HAL_WORKAROUND_MAX_QUEUE, /**< Limits all queues */
64  HAL_WORKAROUND_MAX_RQ, /**< Limits only the RQ */
69  HAL_WORKAROUND_DISABLE_AR_TGT_DIF, /**< Disable of auto-response target DIF */
72  HAL_WORKAROUND_USE_DIF_SEC_XRI, /**< Use secondary xri for multiple data phases */
73  HAL_WORKAROUND_OVERRIDE_FCFI_IN_SRB, /**< FCFI reported in SRB not correct, use "first" registered domain */
74  HAL_WORKAROUND_FW_VERSION_TOO_LOW, /**< The FW version is not the min version supported by this driver */
75  HAL_WORKAROUND_SGLC_MISREPORTED, /**< Chip supports SGL Chaining but SGLC is not set in SLI4_PARAMS */
76  HAL_WORKAROUND_IGNORE_SEND_FRAME_CAPABLE, /**< Don't use SEND_FRAME capable if FW version is too old */
78 
79 /**
80  * @brief Internal workaround structure instance
81  */
82 
83 typedef struct {
86  uint64_t fwrev_low;
87  uint64_t fwrev_high;
88 
90  uint32_t value;
92 
95  HAL_WORKAROUND_TEST, 999},
96 
97  /* Bug: 127585: if_type == 2 returns 0 for total length placed on
98  * FCP_TSEND64_WQE completions. Note, original driver code enables this
99  * workaround for all asic types
100  */
103 
104  /* Bug: unknown, Lancer A0 has mis-reported max queue depth */
107 
108  /* Bug: 143399, BE3 has mis-reported max RQ queue depth */
110  HAL_WORKAROUND_MAX_RQ, 2048},
111 
112  /* Bug: 143399, skyhawk has mis-reported max RQ queue depth */
114  HAL_WORKAROUND_MAX_RQ, 2048},
115 
116  /* Bug: 103487, BE3 before f/w 4.2.314.0 has mis-reported WQE count method */
119 
120  /* Bug: 103487, BE3 before f/w 4.2.314.0 has mis-reported RQE count method */
123 
124  /* Bug: 142968, BE3 UE with RPI == 0xffff */
127 
128  /* Bug: unknown, Skyhawk won't support auto-response on target T10-PI */
131 
134 
135  /* Bug: 160124, Skyhawk quarantine DIF XRIs */
138 
139  /* Bug: 161832, Skyhawk use secondary XRI for multiple data phase TRECV */
142 
143  /* Bug: xxxxxx, FCFI reported in SRB not corrrect */
146 
147  /* Bug: 165642, FW version check for driver */
150 
153 
154  /* Bug 177061, Lancer FW does not set the SGLC bit */
157 
158  /* BZ 181208/183914, enable this workaround for ALL revisions */
161 };
162 
163 /**
164  * @brief Function prototypes
165  */
166 
167 static int32_t ocs_hal_workaround_match(ocs_hal_t *hal, hal_workaround_t *w);
168 
169 /**
170  * @brief Parse the firmware version (name)
171  *
172  * Parse a string of the form a.b.c.d, returning a uint64_t packed as defined
173  * by the HAL_FWREV() macro
174  *
175  * @param fwrev_string pointer to the firmware string
176  *
177  * @return packed firmware revision value
178  */
179 
180 static uint64_t
181 parse_fw_version(const char *fwrev_string)
182 {
183  int v[4] = {0};
184  const char *p;
185  int i;
186 
187  for (p = fwrev_string, i = 0; *p && (i < 4); i ++) {
188  v[i] = ocs_strtoul(p, 0, 0);
189  while(*p && *p != '.') {
190  p ++;
191  }
192  if (*p) {
193  p ++;
194  }
195  }
196 
197  /* Special case for bootleg releases with f/w rev 0.0.9999.0, set to max value */
198  if (v[2] == 9999) {
199  return HAL_FWREV_MAX;
200  } else {
201  return HAL_FWREV(v[0], v[1], v[2], v[3]);
202  }
203 }
204 
205 /**
206  * @brief Test for a workaround match
207  *
208  * Looks at the asic type, asic revision, and fw revision, and returns TRUE if match.
209  *
210  * @param hal Pointer to the HAL structure
211  * @param w Pointer to a workaround structure entry
212  *
213  * @return Return TRUE for a match
214  */
215 
216 static int32_t
218 {
219  return (((w->asic_type == SLI4_ASIC_TYPE_ANY) || (w->asic_type == hal->sli.asic_type)) &&
220  ((w->asic_rev == SLI4_ASIC_REV_ANY) || (w->asic_rev == hal->sli.asic_rev)) &&
221  (w->fwrev_low <= hal->workaround.fwrev) &&
222  ((w->fwrev_high == HAL_FWREV_MAX) || (hal->workaround.fwrev < w->fwrev_high)));
223 }
224 
225 /**
226  * @brief Setup HAL runtime workarounds
227  *
228  * The function is called at the end of ocs_hal_setup() to setup any runtime workarounds
229  * based on the HAL/SLI setup.
230  *
231  * @param hal Pointer to HAL structure
232  *
233  * @return none
234  */
235 
236 void
238 {
239  hal_workaround_t *w;
240  sli4_t *sli4 = &hal->sli;
241  uint32_t i;
242 
243  /* Initialize the workaround settings */
244  ocs_memset(&hal->workaround, 0, sizeof(hal->workaround));
245 
246  /* If hal_war_version is non-null, then its a value that was set by a module parameter
247  * (sorry for the break in abstraction, but workarounds are ... well, workarounds)
248  */
249 
250  if (hal->hal_war_version) {
252  } else {
253  hal->workaround.fwrev = parse_fw_version((char*) sli4->config.fw_name[0]);
254  }
255 
256  /* Walk the workaround list, if a match is found, then handle it */
257  for (i = 0, w = hal_workarounds; i < ARRAY_SIZE(hal_workarounds); i++, w++) {
258  if (ocs_hal_workaround_match(hal, w)) {
259  switch(w->workaround) {
260 
261  case HAL_WORKAROUND_TEST: {
262  ocs_log_debug(hal->os, "Override: test: %d\n", w->value);
263  break;
264  }
265 
267  ocs_log_debug(hal->os, "HAL Workaround: retain TSEND IO length\n");
269  break;
270  }
272  sli4_qtype_e q;
273 
274  ocs_log_debug(hal->os, "HAL Workaround: override max_qentries: %d\n", w->value);
275  for (q = SLI_QTYPE_EQ; q < SLI_QTYPE_MAX; q++) {
276  if (hal->num_qentries[q] > w->value) {
277  hal->num_qentries[q] = w->value;
278  }
279  }
280  break;
281  }
282  case HAL_WORKAROUND_MAX_RQ: {
283  ocs_log_debug(hal->os, "HAL Workaround: override RQ max_qentries: %d\n", w->value);
284  if (hal->num_qentries[SLI_QTYPE_RQ] > w->value) {
285  hal->num_qentries[SLI_QTYPE_RQ] = w->value;
286  }
287  break;
288  }
290  ocs_log_debug(hal->os, "HAL Workaround: set WQE count method=%d\n", w->value);
292  sli_calc_max_qentries(sli4);
293  break;
294  }
296  ocs_log_debug(hal->os, "HAL Workaround: set RQE count method=%d\n", w->value);
298  sli_calc_max_qentries(sli4);
299  break;
300  }
302  ocs_log_debug(hal->os, "HAL Workaround: use unreg'd RPI if rnode->indicator == 0xFFFF\n");
303  hal->workaround.use_unregistered_rpi = TRUE;
304  /*
305  * Allocate an RPI that is never registered, to be used in the case where
306  * a node has been unregistered, and its indicator (RPI) value is set to 0xFFFF
307  */
310  ocs_log_err(hal->os, "sli_resource_alloc unregistered RPI failed\n");
311  hal->workaround.use_unregistered_rpi = FALSE;
312  }
313  break;
315  ocs_log_debug(hal->os, "HAL Workaround: disable AR on T10-PI TSEND\n");
316  hal->workaround.disable_ar_tgt_dif = TRUE;
317  break;
319  ocs_log_debug(hal->os, "HAL Workaround: disable set_dump_loc\n");
320  hal->workaround.disable_dump_loc = TRUE;
321  break;
323  ocs_log_debug(hal->os, "HAL Workaround: use DIF quarantine\n");
324  hal->workaround.use_dif_quarantine = TRUE;
325  break;
327  ocs_log_debug(hal->os, "HAL Workaround: use DIF secondary xri\n");
328  hal->workaround.use_dif_sec_xri = TRUE;
329  break;
331  ocs_log_debug(hal->os, "HAL Workaround: override FCFI in SRB\n");
332  hal->workaround.override_fcfi = TRUE;
333  break;
334 
336  ocs_log_debug(hal->os, "HAL Workaround: fw version is below the minimum for this driver\n");
337  hal->workaround.fw_version_too_low = TRUE;
338  break;
340  ocs_log_debug(hal->os, "HAL Workaround: SGLC misreported - chaining is enabled\n");
341  hal->workaround.sglc_misreported = TRUE;
342  break;
344  ocs_log_debug(hal->os, "HAL Workaround: not SEND_FRAME capable - disabled\n");
345  hal->workaround.ignore_send_frame = TRUE;
346  break;
347  } /* switch(w->workaround) */
348  }
349  }
350 }
hal_workaround_e workaround
sli4_qtype_e
Definition: sli4.h:3423
HAL object.
Definition: ocs_hal.h:902
Internal workaround structure instance.
uint16_t count_method[SLI_QTYPE_MAX]
Definition: sli4.h:3619
#define OCS_MIN_FW_VER_LANCER
int32_t sli_resource_alloc(sli4_t *sli4, sli4_resource_e rtype, uint32_t *rid, uint32_t *index)
Allocate SLI Port resources.
Definition: sli4.c:5851
static hal_workaround_t hal_workarounds[]
hal_workaround_e
Internal definition of workarounds.
#define HAL_FWREV_MAX
sli4_asic_type_e
Definition: sli4.h:3580
void sli_calc_max_qentries(sli4_t *sli4)
Calculate max queue entries.
Definition: sli4.c:3959
#define HAL_FWREV_1(x)
struct sli4_t::@47 config
Definition: sli4.h:3601
sli4_asic_type_e asic_type
#define SLI4_ASIC_REV_ANY
#define SLI4_ASIC_TYPE_ANY
static int32_t ocs_hal_workaround_match(ocs_hal_t *hal, hal_workaround_t *w)
Function prototypes.
void ocs_hal_workaround_setup(struct ocs_hal_s *hal)
Setup HAL runtime workarounds.
char * hal_war_version
Definition: ocs_hal.h:1076
ocs_hal_workaround_t workaround
Definition: ocs_hal.h:1077
uint8_t fw_name[2][16]
Definition: sli4.h:3629
#define OCS_MIN_FW_VER_SKYHAWK
sli4_asic_rev_e asic_rev
sli4_asic_rev_e
Definition: sli4.h:3589
sli4_t sli
Definition: ocs_hal.h:904
uint32_t num_qentries[SLI_QTYPE_MAX]
Definition: ocs_hal.h:954
static uint64_t parse_fw_version(const char *fwrev_string)
Parse the firmware version (name)
#define HAL_FWREV_ZERO
#define HAL_FWREV(a, b, c, d)
pack fw revision values into a single uint64_t
ocs_os_handle_t os
Definition: ocs_hal.h:903