iPXE
mlx_pci_gw.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Mellanox Technologies Ltd.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19 
20 FILE_LICENCE ( GPL2_OR_LATER );
21 
22 #include "../../include/public/mlx_pci_gw.h"
23 #include "../../include/public/mlx_bail.h"
24 #include "../../include/public/mlx_pci.h"
25 #include "../../include/public/mlx_logging.h"
26 
27 /* Lock/unlock GW on each VSEC access */
28 #undef VSEC_DEBUG
29 
30 static
33  IN mlx_utils *utils,
34  IN mlx_uint8 cap_pointer,
35  OUT mlx_boolean *bool
36  )
37 {
40  mlx_uint8 id = 0;
42  1, &id);
43  MLX_CHECK_STATUS(utils, status, read_err,"failed to read capability id");
44  *bool = ( id == PCI_GW_CAPABILITY_ID );
45 read_err:
46  return status;
47 }
48 
49 static
52  IN mlx_utils *utils
53  )
54 {
56  mlx_uint32 cap_offset = utils->pci_gw.pci_cmd_offset;
57  mlx_uint32 semaphore = 0;
58  mlx_uint32 counter = 0;
59  mlx_uint32 get_semaphore_try = 0;
60  mlx_uint32 get_ownership_try = 0;
61 
62  for( ; get_ownership_try < PCI_GW_GET_OWNERSHIP_TRIES; get_ownership_try ++){
63  for( ; get_semaphore_try <= PCI_GW_SEMPHORE_TRIES ; get_semaphore_try++){
65  1, &semaphore);
66  MLX_CHECK_STATUS(utils, status, read_err,"failed to read semaphore");
67  if( semaphore == 0 ){
68  break;
69  }
71  }
72  if( semaphore != 0 ){
74  goto semaphore_err;
75  }
76 
78  1, &counter);
79  MLX_CHECK_STATUS(utils, status, read_err, "failed to read counter");
80 
82  1, &counter);
83  MLX_CHECK_STATUS(utils, status, write_err,"failed to write semaphore");
84 
86  1, &semaphore);
87  MLX_CHECK_STATUS(utils, status, read_err,"failed to read semaphore");
88  if( counter == semaphore ){
89  break;
90  }
91  }
92  if( counter != semaphore ){
94  }
95 write_err:
96 read_err:
97 semaphore_err:
98  return status;
99 }
100 
101 static
104  IN mlx_utils *utils
105  )
106 {
108  mlx_uint32 cap_offset = utils->pci_gw.pci_cmd_offset;
109  mlx_uint32 value = 0;
110 
112  1, &value);
113  MLX_CHECK_STATUS(utils, status, write_err,"failed to write semaphore");
114 write_err:
115  return status;
116 }
117 
118 static
121  IN mlx_utils *utils,
122  IN mlx_pci_gw_space space
123  )
124 {
126  mlx_uint32 cap_offset = utils->pci_gw.pci_cmd_offset;;
127  mlx_uint8 space_status = 0;
128 
129  /* set nodnic*/
130  status = mlx_pci_write(utils, MlxPciWidthUint16, cap_offset + PCI_GW_CAPABILITY_SPACE_OFFSET, 1, &space);
131  MLX_CHECK_STATUS(utils, status, read_error,"failed to write capability space");
132 
133  status = mlx_pci_read(utils, MlxPciWidthUint8, cap_offset + PCI_GW_CAPABILITY_STATUS_OFFSET, 1, &space_status);
134  MLX_CHECK_STATUS(utils, status, read_error,"failed to read capability status");
135  if( (space_status & 0x20) == 0){
136  status = MLX_FAILED;
137  goto space_unsupported;
138  }
139 read_error:
140 space_unsupported:
141  return status;
142 }
143 
144 static
147  IN mlx_utils *utils,
149  )
150 {
152  mlx_uint32 try = 0;
153  mlx_uint32 cap_offset = utils->pci_gw.pci_cmd_offset;
154  mlx_uint32 flag = 0;
155 
156  for(; try < PCI_GW_READ_FLAG_TRIES ; try ++ ) {
158  MLX_CHECK_STATUS(utils, status, read_error, "failed to read capability flag");
159  if( ((flag & 0x80000000) != 0) == value ){
160  goto flag_valid;
161  }
163  }
164  status = MLX_FAILED;
165 flag_valid:
166 read_error:
167  return status;
168 }
169 static
172  IN mlx_utils *utils,
173  OUT mlx_uint32 *cap_offset
174  )
175 {
177  mlx_uint8 cap_pointer = 0;
178  mlx_boolean is_capability = FALSE;
179 
180  if( cap_offset == NULL || utils == NULL){
182  goto bad_param;
183  }
184 
185  //get first capability pointer
187  1, &cap_pointer);
188  MLX_CHECK_STATUS(utils, status, read_err,
189  "failed to read capability pointer");
190 
191  //search the right capability
192  while( cap_pointer != 0 ){
193  status = mlx_pci_gw_check_capability_id(utils, cap_pointer, &is_capability);
194  MLX_CHECK_STATUS(utils, status, check_err
195  ,"failed to check capability id");
196 
197  if( is_capability == TRUE ){
198  *cap_offset = cap_pointer;
199  break;
200  }
201 
202  status = mlx_pci_read(utils, MlxPciWidthUint8, cap_pointer +
204  1, &cap_pointer);
205  MLX_CHECK_STATUS(utils, status, read_err,
206  "failed to read capability pointer");
207  }
208  if( is_capability != TRUE ){
210  }
211 check_err:
212 read_err:
213 bad_param:
214  return status;
215 }
216 
219  IN mlx_utils *utils
220  )
221 {
223  mlx_pci_gw *pci_gw = NULL;
224 
225  if( utils == NULL){
227  goto bad_param;
228  }
229 
230  pci_gw = &utils->pci_gw;
231 
233  MLX_CHECK_STATUS(utils, status, cap_err,
234  "mlx_pci_gw_search_capability failed");
235 
236 #if ! defined ( VSEC_DEBUG )
238  MLX_CHECK_STATUS(utils, status, ownership_err,"failed to get ownership");
239 ownership_err:
240 #endif
241 cap_err:
242 bad_param:
243  return status;
244 }
245 
248  IN mlx_utils *utils __attribute__ ((unused))
249  )
250 {
251 #if ! defined ( VSEC_DEBUG )
253 #endif
254  return MLX_SUCCESS;
255 }
256 
259  IN mlx_utils *utils,
260  IN mlx_pci_gw_space space,
263  )
264 {
266  mlx_pci_gw *pci_gw = NULL;
267  mlx_uint32 cap_offset = 0;
268 
269  if (utils == NULL || buffer == NULL || utils->pci_gw.pci_cmd_offset == 0) {
271  goto bad_param;
272  }
273 
274  mlx_utils_acquire_lock(utils);
275 
276  pci_gw = &utils->pci_gw;
277  cap_offset = pci_gw->pci_cmd_offset;
278 
279 #if ! defined ( VSEC_DEBUG )
280  if (pci_gw->space != space) {
281  status = mlx_pci_gw_set_space(utils, space);
282  MLX_CHECK_STATUS(utils, status, space_error,"failed to set space");
283  pci_gw->space = space;
284  }
285 #else
287  MLX_CHECK_STATUS(utils, status, ownership_err,"failed to get ownership");
288 
289  status = mlx_pci_gw_set_space(utils, space);
290  MLX_CHECK_STATUS(utils, status, space_error,"failed to set space");
291  pci_gw->space = space;
292 #endif
293 
295  MLX_CHECK_STATUS(utils, status, read_error,"failed to write capability address");
296 
297 #if defined ( DEVICE_CX3 )
298  /* WA for PCI issue (race) */
299  mlx_utils_delay_in_us ( 10 );
300 #endif
301 
303  MLX_CHECK_STATUS(utils, status, read_error, "flag failed to change");
304 
306  MLX_CHECK_STATUS(utils, status, read_error,"failed to read capability data");
307 
308 #if defined ( VSEC_DEBUG )
310  MLX_CHECK_STATUS(utils, status, free_err,
311  "mlx_pci_gw_free_ownership failed");
312 free_err:
313  mlx_utils_release_lock(utils);
314  return status;
315 #endif
316 read_error:
317 space_error:
318 #if defined ( VSEC_DEBUG )
320 ownership_err:
321 #endif
323 bad_param:
324  return status;
325 }
326 
329  IN mlx_utils *utils,
330  IN mlx_pci_gw_space space,
333  )
334 {
336  mlx_pci_gw *pci_gw = NULL;
337  mlx_uint32 cap_offset = 0;
338  mlx_uint32 fixed_address = address | PCI_GW_WRITE_FLAG;
339 
340  if (utils == NULL || utils->pci_gw.pci_cmd_offset == 0) {
342  goto bad_param;
343  }
344 
345  mlx_utils_acquire_lock(utils);
346 
347  pci_gw = &utils->pci_gw;
348  cap_offset = pci_gw->pci_cmd_offset;
349 
350 #if ! defined ( VSEC_DEBUG )
351  if (pci_gw->space != space) {
352  status = mlx_pci_gw_set_space(utils, space);
353  MLX_CHECK_STATUS(utils, status, space_error,"failed to set space");
354  pci_gw->space = space;
355  }
356 #else
358  MLX_CHECK_STATUS(utils, status, ownership_err,"failed to get ownership");
359 
360  status = mlx_pci_gw_set_space(utils, space);
361  MLX_CHECK_STATUS(utils, status, space_error,"failed to set space");
362  pci_gw->space = space;
363 #endif
365  MLX_CHECK_STATUS(utils, status, read_error,"failed to write capability data");
366 
367  status = mlx_pci_write(utils, MlxPciWidthUint32, cap_offset + PCI_GW_CAPABILITY_ADDRESS_OFFSET, 1, &fixed_address);
368  MLX_CHECK_STATUS(utils, status, read_error,"failed to write capability address");
369 
371  MLX_CHECK_STATUS(utils, status, read_error, "flag failed to change");
372 #if defined ( VSEC_DEBUG )
374  MLX_CHECK_STATUS(utils, status, free_err,
375  "mlx_pci_gw_free_ownership failed");
376 free_err:
378  return status;
379 #endif
380 read_error:
381 space_error:
382 #if defined ( VSEC_DEBUG )
384 ownership_err:
385 #endif
387 bad_param:
388  return status;
389 }
390 
391 
392 
uint8_t mlx_boolean
#define PCI_GW_FIRST_CAPABILITY_POINTER_OFFSET
Definition: mlx_pci_gw.h:27
#define MLX_INVALID_PARAMETER
mlx_uint32 pci_cmd_offset
Definition: mlx_utils.h:34
mlx_status mlx_pci_gw_write(IN mlx_utils *utils, IN mlx_pci_gw_space space, IN mlx_uint32 address, IN mlx_pci_gw_buffer buffer)
Definition: mlx_pci_gw.c:328
#define PCI_GW_CAPABILITY_FLAG_OFFSET
Definition: mlx_pci_gw.h:38
#define PCI_GW_READ_FLAG_TRIES
Definition: mlx_pci_gw.h:43
uint64_t address
Base address.
Definition: ena.h:24
#define PCI_GW_CAPABILITY_DATA_OFFSET
Definition: mlx_pci_gw.h:39
mlx_status mlx_utils_release_lock(IN OUT mlx_utils *utils)
Definition: mlx_utils.c:108
mlx_pci_gw_space space
Definition: mlx_utils.h:35
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition: netvsc.h:16
mlx_status mlx_utils_delay_in_us(IN mlx_uint32 usecs)
Definition: mlx_utils.c:65
mlx_status mlx_pci_read(IN mlx_utils *utils, IN mlx_pci_width width, IN mlx_uint32 offset, IN mlx_uintn count, OUT mlx_void *buffer)
Definition: mlx_pci.c:58
mlx_status mlx_pci_write(IN mlx_utils *utils, IN mlx_pci_width width, IN mlx_uint32 offset, IN mlx_uintn count, IN mlx_void *buffer)
Definition: mlx_pci.c:77
#define PCI_GW_CAPABILITY_ID
Definition: mlx_pci_gw.h:29
#define PCI_GW_CAPABILITY_SPACE_OFFSET
Definition: mlx_pci_gw.h:33
static mlx_status mlx_pci_gw_wait_for_flag_value(IN mlx_utils *utils, IN mlx_boolean value)
Definition: mlx_pci_gw.c:146
uint8_t status
Status.
Definition: ena.h:16
uint32_t mlx_uint32
static mlx_status mlx_pci_gw_set_space(IN mlx_utils *utils, IN mlx_pci_gw_space space)
Definition: mlx_pci_gw.c:120
FILE_LICENCE(GPL2_OR_LATER)
#define OUT
Definition: mlx_utils.h:29
#define MLX_NOT_FOUND
static mlx_status mlx_pci_gw_search_capability(IN mlx_utils *utils, OUT mlx_uint32 *cap_offset)
Definition: mlx_pci_gw.c:171
#define PCI_GW_CAPABILITY_COUNTER_OFFSET
Definition: mlx_pci_gw.h:35
A 16-bit general register.
Definition: registers.h:24
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
mlx_status mlx_pci_gw_teardown(IN mlx_utils *utils)
Definition: mlx_pci_gw.c:247
#define MLX_SUCCESS
#define PCI_GW_WRITE_FLAG
Definition: mlx_pci_gw.h:45
mlx_status mlx_pci_gw_init(IN mlx_utils *utils)
Definition: mlx_pci_gw.c:218
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
mlx_status mlx_pci_gw_read(IN mlx_utils *utils, IN mlx_pci_gw_space space, IN mlx_uint32 address, OUT mlx_pci_gw_buffer *buffer)
Definition: mlx_pci_gw.c:258
#define PCI_GW_SEMPHORE_TRIES
Definition: mlx_pci_gw.h:41
#define MLX_FAILED
#define TRUE
Definition: tlan.h:46
static mlx_status mlx_pci_gw_check_capability_id(IN mlx_utils *utils, IN mlx_uint8 cap_pointer, OUT mlx_boolean *bool)
Definition: mlx_pci_gw.c:32
#define PCI_GW_CAPABILITY_ID_OFFSET
Definition: mlx_pci_gw.h:31
#define IN
Definition: mlx_utils.h:28
static mlx_status mlx_pci_gw_free_ownership(IN mlx_utils *utils)
Definition: mlx_pci_gw.c:103
uint8_t mlx_uint8
mlx_status mlx_utils_acquire_lock(IN OUT mlx_utils *utils)
Definition: mlx_utils.c:100
uint8_t unused[32]
Unused.
Definition: eltorito.h:15
#define PCI_GW_CAPABILITY_STATUS_OFFSET
Definition: mlx_pci_gw.h:34
#define PCI_GW_CAPABILITY_ADDRESS_OFFSET
Definition: mlx_pci_gw.h:37
#define PCI_GW_CAPABILITY_SEMAPHORE_OFFSET
Definition: mlx_pci_gw.h:36
#define PCI_GW_GET_OWNERSHIP_TRIES
Definition: mlx_pci_gw.h:42
#define FALSE
Definition: tlan.h:45
int mlx_status
static mlx_status mlx_pci_gw_get_ownership(IN mlx_utils *utils)
Definition: mlx_pci_gw.c:51
#define MLX_CHECK_STATUS(id, status, label, message)
Definition: mlx_bail.h:37
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define PCI_GW_CAPABILITY_NEXT_POINTER_OFFSET
Definition: mlx_pci_gw.h:32
mlx_uint32 mlx_pci_gw_buffer
Definition: mlx_pci_gw.h:52
uint16_t flag
Flag number.
Definition: hyperv.h:14
mlx_uint16 mlx_pci_gw_space
Definition: mlx_utils.h:31