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_os.h"
50 #include "ocs_hal.h"
51 
52 #define HAL_FWREV_ZERO (0)
53 #define HAL_FWREV_MAX UINT32_MAX
54 
55 #define SLI4_ASIC_TYPE_ANY 0
56 #define SLI4_ASIC_REV_ANY 0
57 
58 /**
59  * @brief Internal definition of workarounds
60  */
61 
62 typedef enum {
69 
70 /**
71  * @brief Internal workaround structure instance
72  */
73 
74 typedef struct {
77  uint32_t fwrev_low;
78  uint32_t fwrev_high;
79 
81  uint32_t value;
83 
85 
87  HAL_WORKAROUND_TEST, 999},
88 
89  /* Bug 136289 - Subtract 2 from the advertised CQ so that we can */
92 
93  /* Bug 142785 - use v1 of TGT_OFFLOAD and iSCSI_CLEANUP */
96 
97  /* Bug 160410 - for Skyhawk 10.0 FW force non-DIF operation */
100 
103 };
104 
105 /**
106  * @brief Parse the firmware version (name)
107  *
108  * Parse a string of the form a.b.c.d, returning a uint32_t packed as defined
109  * by the HAL_FWREV() macro
110  *
111  * @param fwrev_string pointer to the firmware string
112  *
113  * @return packed firmware revision value
114  */
115 
116 static uint32_t
117 parse_fw_version(const char *fwrev_string)
118 {
119  int v[4] = {0};
120  const char *p;
121  int i;
122 
123  for (p = fwrev_string, i = 0; *p && (i < 4); i ++) {
124  v[i] = ocs_strtoul(p, 0, 0);
125  while(*p && *p != '.') {
126  p ++;
127  }
128  if (*p) {
129  p ++;
130  }
131  }
132 
133  /* Special case for bootleg releases with f/w rev 0.0.9999.0, set to max value */
134  if (v[2] == 9999) {
135  return HAL_FWREV_MAX;
136  } else {
137  return HAL_FWREV(v[0], v[1], v[2], v[3]);
138  }
139 }
140 
141 /**
142  * @brief Test for a workaround match
143  *
144  * Looks at the asic type, asic revision, and fw revision, and returns TRUE if match.
145  *
146  * @param hal Pointer to the HAL structure
147  * @param w Pointer to a workaround structure entry
148  *
149  * @return Return TRUE for a match
150  */
151 
152 static int32_t
154 {
155  return (((w->asic_type == SLI4_ASIC_TYPE_ANY) || (w->asic_type == hal->sli.asic_type)) &&
156  ((w->asic_rev == SLI4_ASIC_REV_ANY) || (w->asic_rev == hal->sli.asic_rev)) &&
157  (w->fwrev_low <= hal->workaround.fwrev) &&
158  ((w->fwrev_high == HAL_FWREV_MAX) || (hal->workaround.fwrev < w->fwrev_high)));
159 }
160 
161 /**
162  * @brief Setup HAL runtime workarounds
163  *
164  * The function is called at the end of ocs_hal_setup() to setup any runtime workarounds
165  * based on the HAL/SLI setup.
166  *
167  * @param hal Pointer to HAL structure
168  *
169  * @return none
170  */
171 
172 void
173 ocs_hal_workaround_setup(struct ocs_hal_s *hal)
174 {
175  hal_workaround_t *w;
176  sli4_t *sli4 = &hal->sli;
177  uint32_t i;
178 
179  /* If hal_war_version is non-null, then its a value that was set by a module parameter */
180  if (hal->hal_war_version != NULL) {
181  hal->workaround.fwrev = parse_fw_version(hal->hal_war_version);
182  } else {
183  hal->workaround.fwrev = parse_fw_version((char*) sli4->config.fw_version);
184  }
185 
186  /* Walk the workaround list, if a match is found, then handle it */
187  for (i = 0, w= hal_workarounds; i < ARRAY_SIZE(hal_workarounds); i++, w++) {
188  if (ocs_hal_workaround_match(hal, w)) {
189  switch(w->workaround) {
190 
191  case HAL_WORKAROUND_TEST: {
192  ocs_log_debug(hal->os, "Override: test: %d\n", w->value);
193  break;
194  }
195 
197  ocs_log_debug(hal->os, "Override: n_cq: decr by %d\n", w->value);
198  hal->config.n_cq -= w->value;
199  break;
200  }
202  ocs_log_debug(hal->os, "Override: Use version 1 of ISCSI_CLEANUP and TGT_OFFLOAD\n");
203  hal->use_v1_multi_protocol = w->value;
204  break;
205  }
207  ocs_log_debug(hal->os, "Override: Force non-DIF for Skyhawk 10.0 FW\n");
208  sli4->features.t10_dif_capable = 0;
209  break;
210  }
212  ocs_log_debug(hal->os, "HAL Workaround: fw version is below the minimum for this driver\n");
213  hal->workaround.fw_version_too_low = TRUE;
214  break;
215  }
216  }
217  }
218  }
219 }
hal_workaround_e workaround
Internal workaround structure instance.
sli4_t sli
Definition: ocs_hal.h:726
HAL object.
Definition: ocs_hal.h:724
struct sli4_t::@37 features
static hal_workaround_t hal_workarounds[]
hal_workaround_e
Internal definition of workarounds.
#define HAL_FWREV_MAX
sli4_asic_type_e
Definition: sli4.h:2163
#define HAL_FWREV_1(x)
Definition: sli4.h:2201
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)
Test for a workaround match.
uint8_t fw_version[32]
Definition: sli4.h:2243
sli4_asic_type_e asic_type
Definition: sli4.h:2273
void ocs_hal_workaround_setup(struct ocs_hal_s *hal)
Setup HAL runtime workarounds.
struct sli4_t::@38 config
static uint32_t parse_fw_version(const char *fwrev_string)
Parse the firmware version (name)
uint8_t t10_dif_capable
Definition: sli4.h:2230
ocs_hal_workaround_t workaround
Definition: ocs_hal.h:828
#define OCS_MIN_FW_VER
sli4_asic_rev_e asic_rev
sli4_asic_rev_e
Definition: sli4.h:2170
sli4_asic_rev_e asic_rev
Definition: sli4.h:2274
#define HAL_FWREV_ZERO
#define HAL_FWREV(a, b, c, d)
pack fw revision values into a single uint32_t