Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sli4.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 \defgroup sli SLI-4 base APIs
35  */
36 
37 /**
38  * @file
39  * Implementation of common SLI-4 functions
40  * All common (i.e. transport independent) SLI-4 functions are implemented
41  * here.
42  */
43 
44 #include "ocs.h"
45 #include "ocs_hal.h"
46 #include "sli4.h"
47 #include "sli4_iscsi.h"
48 #include "ocs_iscsi_spec.h"
49 
50 #if defined(OCS_INCLUDE_DEBUG)
51 #include "ocs_debug.h"
52 #endif
53 
54 static int32_t sli_fw_init(sli4_t *);
55 static int32_t sli_fw_term(sli4_t *);
56 static int32_t sli_sliport_control(sli4_t *sli4, uint32_t endian);
57 static int32_t sli_cmd_fw_deinitialize(sli4_t *, void *, size_t);
58 static int32_t sli_cmd_fw_initialize(sli4_t *, void *, size_t);
59 static int32_t sli_queue_doorbell(sli4_t *, sli4_queue_t *);
60 static uint8_t sli_queue_entry_is_valid(sli4_queue_t *, uint8_t *, uint8_t);
61 
62 const uint8_t sli4_fw_initialize[] = {
63  0xff, 0x12, 0x34, 0xff,
64  0xff, 0x56, 0x78, 0xff,
65 };
66 
67 const uint8_t sli4_fw_deinitialize[] = {
68  0xff, 0xaa, 0xbb, 0xff,
69  0xff, 0xcc, 0xdd, 0xff,
70 };
71 
72 /*
73  * @brief convert queue type enum (SLI_QTYPE_*) into string
74  */
75 const char *SLI_QNAME[] = {
76  "Event Queue",
77  "Completion Queue",
78  "Mailbox Queue",
79  "Work Queue",
80  "Receive Queue",
81  "Undefined"
82 };
83 
84 typedef struct {
85  uint32_t rev_id;
86  uint32_t family; /* generation */
90 
95  { 0x00, 4, SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_A0}, // not documented
101  { 0x10, 0x0b, SLI4_ASIC_TYPE_LANCER, SLI4_ASIC_REV_B0},
102  { 0x30, 0x0b, SLI4_ASIC_TYPE_LANCER, SLI4_ASIC_REV_D0},
104 };
105 
106 /**
107  * @brief Define the mapping of registers to their BAR and offset
108  *
109  * Although SLI-4 defines a common set of registers, their locations (both BAR
110  * and offset) depend on the interface type. This array maps a register enum
111  * to an array of BAR / offset pairs indexed by the interface type. For
112  * example, to access the bootstrap mailbox register on an interface type 0
113  * device, code can refer to the offset using
114  *
115  * regmap[SLI4_REG_BMBX][0].offset
116  *
117  * @note A value of -1 for either the register set (rset) or offset (off)
118  * indicates an invalid mapping.
119  */
121  // SLI4_REG_BMBX
122  {
123  { 2, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG },
124  },
125  // SLI4_REG_EQCQ_DOORBELL
126  {
129  },
130  // SLI4_REG_FCOE_RQ_DOORBELL
131  {
133  { 0, SLI4_RQ_DOORBELL_REG }, { -1, -1 },
134  },
135  // SLI4_REG_IO_WQ_DOORBELL
136  {
138  },
139  // SLI4_REG_MQ_DOORBELL
140  {
143  },
144  // SLI4_REG_PHYSDEV_CONTROL
145  {
146  { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 },
147  },
148  // SLI4_REG_SLIPORT_CONTROL
149  {
150  { -1, -1 }, { -1, -1 }, { 0, SLI4_SLIPORT_CONTROL_REG }, { -1, -1 },
151  },
152  // SLI4_REG_SLIPORT_ERROR1
153  {
154  { -1, -1 }, { -1, -1 }, { 0, SLI4_SLIPORT_ERROR1 }, { -1, -1 },
155  },
156  // SLI4_REG_SLIPORT_ERROR2
157  {
158  { -1, -1 }, { -1, -1 }, { 0, SLI4_SLIPORT_ERROR2 }, { -1, -1 },
159  },
160  // SLI4_REG_SLIPORT_SEMAPHORE
161  {
165  },
166  // SLI4_REG_SLIPORT_STATUS
167  {
168  { -1, -1 }, { -1, -1 }, { 0, SLI4_PORT_STATUS_REG_23 }, { 0, SLI4_PORT_STATUS_REG_23 },
169  },
170  // SLI4_REG_UERR_MASK_HI
171  {
172  { 0, SLI4_UERR_MASK_HIGH_REG }, { 0, 0x1000 + SLI4_UERR_MASK_HIGH_REG },
173  { -1, -1 }, { -1, -1 },
174  },
175  // SLI4_REG_UERR_MASK_LO
176  {
177  { 0, SLI4_UERR_MASK_LOW_REG }, { 0, 0x1000 + SLI4_UERR_MASK_LOW_REG },
178  { -1, -1 }, { -1, -1 },
179  },
180  // SLI4_REG_UERR_STATUS_HI
181  {
183  { -1, -1 }, { -1, -1 },
184  },
185  // SLI4_REG_UERR_STATUS_LO
186  {
187  { 0, SLI4_UERR_STATUS_LOW_REG }, { 0, 0x1000 + SLI4_UERR_STATUS_LOW_REG },
188  { -1, -1 }, { -1, -1 },
189  },
190  // SLI4_REG_ONLINE0
191  {
192  { 0, SLI4_ONLINE0_REG }, { -1, -1 }, { -1, -1 }, { -1, -1 },
193  },
194  // SLI4_REG_ONLINE1
195  {
196  { 0, SLI4_ONLINE1_REG }, { -1, -1 }, { -1, -1 }, { -1, -1 },
197  },
198 };
199 
200 /**
201  * @ingroup sli
202  * @brief Read the given SLI register.
203  *
204  * @param sli Pointer to SLI context.
205  * @param reg Register name enum.
206  *
207  * @return Returns register value.
208  */
209 uint32_t
211 {
212  const sli4_reg_t *r = &(regmap[reg][sli->if_type]);
213 
214  // sanity check
215  if ((UINT32_MAX == r->rset) || (UINT32_MAX == r->off)) {
216  ocs_log_err(sli->os, "regname %d not defined for if_type %d\n", reg, sli->if_type);
217  return UINT32_MAX;
218  }
219 
220  return ocs_reg_read32(sli->os, r->rset, r->off);
221 }
222 
223 /**
224  * @ingroup sli
225  * @brief Write the value to the given SLI register.
226  *
227  * @param sli Pointer to SLI context.
228  * @param reg Register name enum.
229  * @param val Value to write.
230  *
231  * @return None.
232  */
233 void
234 sli_reg_write(sli4_t *sli, sli4_regname_e reg, uint32_t val)
235 {
236  const sli4_reg_t *r = &(regmap[reg][sli->if_type]);
237 
238  // sanity check
239  if ((UINT32_MAX == r->rset) || (UINT32_MAX == r->off)) {
240  ocs_log_err(NULL, "regname %d not defined for if_type %d\n", reg, sli->if_type);
241  return;
242  }
243 
244  ocs_reg_write32(sli->os, r->rset, r->off, val);
245 }
246 
247 /**
248  * @brief Check if the SLI_INTF register is valid.
249  *
250  * @param val 32-bit SLI_INTF register value.
251  *
252  * @return Returns 0 if valid, or non-zero otherwise.
253  */
254 static uint8_t
255 sli_intf_valid_check(uint32_t val)
256 {
258 }
259 
260 /**
261  * @brief Retrieve the SLI revision level.
262  *
263  * @param val 32-bit SLI_INTF register value.
264  *
265  * @return Returns SLI revision level.
266  */
267 static uint8_t
269 {
271 }
272 
273 static uint8_t
274 sli_intf_sli_family(uint32_t val)
275 {
277 }
278 
279 /**
280  * @brief Retrieve SLI interface type.
281  *
282  * @param val 32-bit SLI_INTF register value.
283  *
284  * @return Returns SLI interface type.
285  */
286 static uint8_t
287 sli_intf_if_type(uint32_t val)
288 {
290 }
291 
292 /**
293  * @brief Retrieve PCI revision ID.
294  *
295  * @param val 32-bit PCI CLASS_REVISION register value.
296  *
297  * @return Returns PCI revision ID.
298  */
299 static uint8_t
300 sli_pci_rev_id(uint32_t val)
301 {
302  return ((val >> SLI4_PCI_REV_ID_SHIFT) & SLI4_PCI_REV_ID_MASK);
303 }
304 
305 /**
306  * @brief Retrieve SLI ASIC revision.
307  *
308  * @param val 32-bit SLI_ASIC_ID register value.
309  *
310  * @return Returns SLI ASIC revision in hex.
311  */
312 static uint8_t
313 sli_asic_revision(uint32_t val)
314 {
315  uint32_t rev;
316  uint32_t spin;
317 
318  rev = 0xa + ((val >> SLI4_ASIC_VER_SHIFT) & SLI4_ASIC_VER_MASK);
319  spin = ((val >> SLI4_ASIC_REV_SHIFT) & SLI4_ASIC_REV_MASK);
320 
321  return (rev << 4) | spin;
322 }
323 
324 /**
325  * @brief Retrieve SLI ASIC generation.
326  *
327  * @param val 32-bit SLI_ASIC_ID register value.
328  *
329  * @return Returns SLI ASIC generation.
330  */
331 static uint8_t
332 sli_asic_gen(uint32_t val)
333 {
334  return ((val >> SLI4_ASIC_GEN_SHIFT) & SLI4_ASIC_GEN_MASK);
335 }
336 
337 /**
338  * @brief Wait for the bootstrap mailbox to report "ready".
339  *
340  * @param sli4 SLI context pointer.
341  * @param msec Number of milliseconds to wait.
342  *
343  * @return Returns 0 if BMBX is ready, or non-zero otherwise (i.e. timed out).
344  */
345 static int32_t
346 sli_bmbx_wait(sli4_t *sli4, uint32_t msec)
347 {
348  uint32_t val = 0;
349 
350  do {
351  ocs_delay_usec(1000); // 1 ms
352  val = sli_reg_read(sli4, SLI4_REG_BMBX);
353  msec--;
354  } while(msec && !(val & SLI4_BMBX_RDY));
355 
356  return(!(val & SLI4_BMBX_RDY));
357 }
358 
359 int32_t
361 {
362  uint32_t val = 0;
363  sli_reg_write(sli4, SLI4_REG_ONLINE0, val);
364  sli_reg_write(sli4, SLI4_REG_ONLINE1, val);
365  return 0;
366 }
367 
368 /**
369  * @brief Write bootstrap mailbox.
370  *
371  * @param sli4 SLI context pointer.
372  *
373  * @return Returns 0 if command was successful, or non-zero otherwise.
374  */
375 static int32_t
377 {
378  uint32_t val = 0;
379 
380  // write buffer location to bootstrap mailbox register
381  ocs_dma_sync(&sli4->bmbx, OCS_DMASYNC_PREWRITE);
382  val = SLI4_BMBX_WRITE_HI(sli4->bmbx.phys);
383  sli_reg_write(sli4, SLI4_REG_BMBX, val);
384 
385  if (sli_bmbx_wait(sli4, sli4->config.bmbx_timeout_msecs)) {
386  ocs_log_crit(NULL, "BMBX WRITE_HI failed\n");
387  return -1;
388  }
389  val = SLI4_BMBX_WRITE_LO(sli4->bmbx.phys);
390  sli_reg_write(sli4, SLI4_REG_BMBX, val);
391 
392  // wait for SLI port to set ready bit
393  return sli_bmbx_wait(sli4, sli4->config.bmbx_timeout_msecs * 2);
394 }
395 
396 /**
397  * @ingroup sli
398  * @brief Submit a command to the bootstrap mailbox and check the status.
399  *
400  * @param sli4 SLI context pointer.
401  *
402  * @return Returns 0 if command succeeded, or non-zero otherwise.
403  */
404 int32_t
406 {
407  void *cqe = (uint8_t *)sli4->bmbx.virt + SLI4_BMBX_SIZE;
408 
409  if (sli_fw_error_status(sli4)) {
410  return -1;
411  }
412 
413 #if defined(OCS_INCLUDE_DEBUG)
414  // Mailbox diagnostic logging
415  {
416  sli4_mqe_hdr_t *hdr = (sli4_mqe_hdr_t*)sli4->bmbx.virt;
417  uint32_t bytes;
418 
419  /* The FW Initiialize doesn't follow the model... */
420  if (hdr->embedded) {
421  bytes = (hdr->payload_length + sizeof(sli4_mqe_hdr_t));
422  if (bytes > SLI4_BMBX_SIZE) bytes = SLI4_BMBX_SIZE;
423  } else {
424  bytes = (sizeof(sli4_mqe_hdr_t) + (hdr->sge_count * 12));
425  }
426 
428  sli4->os,
429  (hdr->embedded ? "Embedded Mailbox Command" :
430  "non-Embedded Mailbox Command"),
431  sli4->bmbx.virt,
432  bytes);
433  }
434 #endif
435  if (sli_bmbx_write(sli4)) {
436  ocs_log_crit(NULL, "bootstrap mailbox write fail phys=%#lx reg=%#x\n",
437  sli4->bmbx.phys,
438  sli_reg_read(sli4, SLI4_REG_BMBX));
439  return -1;
440  }
441 
442  // check completion queue entry status
443  ocs_dma_sync(&sli4->bmbx, OCS_DMASYNC_POSTREAD);
444  if (((sli4_mcqe_t *)cqe)->val) {
445  return sli_cqe_mq(cqe);
446  } else {
447  ocs_log_test(NULL, "invalid or wrong type\n");
448  return -1;
449  }
450 }
451 
452 /* -----------------------------------------------------------------
453  * Messages
454  */
455 
456 /**
457  * @brief Write a FW_DEINITIALIZE command to the provided buffer.
458  *
459  * @param sli4 SLI context pointer.
460  * @param buf Virtual pointer to destination buffer.
461  * @param size Buffer size in bytes.
462  *
463  * @return Returns the number of bytes written.
464  */
465 static int32_t
466 sli_cmd_fw_deinitialize(sli4_t *sli4, void *buf, size_t size)
467 {
468  // TODO assert sizeof(sli4_fw_initialize) <= size
469  ocs_memset(buf, 0, size);
470  ocs_memcpy(buf, sli4_fw_deinitialize, sizeof(sli4_fw_deinitialize));
471 
472  return sizeof(sli4_fw_deinitialize);
473 }
474 
475 /**
476  * @brief Write a FW_INITIALIZE command to the provided buffer.
477  *
478  * @param sli4 SLI context pointer.
479  * @param buf Virtual pointer to destination buffer.
480  * @param size Buffer size in bytes.
481  *
482  * @return Returns number of bytes written.
483  */
484 static int32_t
485 sli_cmd_fw_initialize(sli4_t *sli4, void *buf, size_t size)
486 {
487  // TODO assert sizeof(sli4_fw_initialize) <= size
488  ocs_memset(buf, 0, size);
489  ocs_memcpy(buf, sli4_fw_initialize, sizeof(sli4_fw_initialize));
490 
491  return sizeof(sli4_fw_initialize);
492 }
493 
494 /**
495  * @ingroup sli
496  * @brief Write a MQE header in the provided buffer.
497  *
498  * @param sli4 SLI context pointer.
499  * @param buf Virtual pointer to destination buffer.
500  * @param size Buffer size in bytes.
501  * @param tag Command tag.
502  * @param length Length in bytes of attached command.
503  * @param dma DMA buffer for non-embedded commands.
504  *
505  * @return Returns the number of bytes written.
506  */
507 int32_t
508 sli_cmd_mailbox_queue_entry(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint32_t length, ocs_dma_t *dma)
509 {
510  sli4_mqe_hdr_t *mqe_hdr = buf;
511  uint32_t *sgl;
512  uint32_t sgl_offset = 0;
513 
514  ocs_memset(buf, 0, size);
515 
516  if (NULL == dma) {
517  if (length > size - sizeof(sli4_mqe_hdr_t)) {
518  ocs_log_test(NULL, "length(%d) > payload(%ld)\n",
519  length,
520  size - sizeof(sli4_mqe_hdr_t));
521  return -1;
522  }
523 
524  mqe_hdr->embedded = 1;
525  mqe_hdr->payload_length = length;
526  } else {
527  mqe_hdr->sge_count = 1;
528  mqe_hdr->payload_length = dma->size;
529 
530  /* Fill in the SGL */
531  sgl = (uint32_t*)(((uint8_t*)buf) + sizeof(sli4_mqe_hdr_t));
532  sgl[0] = ocs_addr32_lo(dma->phys);
533  sgl[1] = ocs_addr32_hi(dma->phys);
534  sgl[2] = dma->size;
535  sgl_offset = 12;
536  }
537 
538  mqe_hdr->tag[0] = tag & 0xFFFFFFFF;
539  mqe_hdr->tag[1] = tag >> 32;
540 
541  return sizeof(sli4_mqe_hdr_t) + sgl_offset;
542 }
543 
544 
545 static int32_t
546 sli_sliport_control(sli4_t *sli4, uint32_t endian)
547 {
548  uint32_t iter;
549  uint32_t val;
550 
551  /* Initialize port, endian */
553 
554  for (iter = 0; iter < 1000; iter ++) {
555  ocs_delay_usec(1000); // 1 ms
557  if (SLI4_PORT_STATUS_ERROR(val)) {
558  ocs_log_crit(NULL, "initialize port failed\n");
559  return -1;
560  }
561  if (SLI4_PORT_STATUS_READY(val))
562  break;
563  }
564  return 0;
565 }
566 
567 /**
568  * @brief Write a COMMON_GET_FW_VERSION command to the provided buffer.
569  *
570  * @param sli4 SLI context pointer.
571  * @param buf Virtual pointer to destination buffer.
572  * @param size Buffer size in bytes.
573  *
574  * @return Returns the number of bytes written.
575  */
576 static int32_t
577 sli_cmd_common_get_fw_version(sli4_t *sli4, void *buf, size_t size)
578 {
580  uint32_t cmd_off = 0;
581  uint32_t payload_size;
582 
583  /* Payload length must accomodate both request and response */
584  payload_size = max(sizeof(sli4_req_common_get_fw_version_t),
586 
587  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, 0,
588  payload_size,
589  NULL);
590 
591  req = (sli4_req_common_get_fw_version_t*)((uint8_t*)buf + cmd_off);
594  req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
595  return cmd_off + sizeof(sli4_req_common_get_fw_version_t);
596 }
597 
598 /**
599  * @brief Write a COMMON_QUERY_FW_CONFIG command to the provided buffer.
600  *
601  * @param sli4 SLI context pointer.
602  * @param buf Virtual pointer to destination buffer.
603  * @param size Buffer size in bytes.
604  *
605  * @return Returns the number of bytes written.
606  */
607 static int32_t
608 sli_cmd_common_query_fw_config(sli4_t *sli4, void *buf, size_t size)
609 {
611  uint32_t cmd_off = 0;
612  uint32_t payload_size;
613 
614  /* Payload length must accomodate both request and response */
615  payload_size = max(sizeof(sli4_req_common_query_fw_config_t),
617 
618  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, 0,
619  payload_size,
620  NULL);
621 
622  fw_config = (sli4_req_common_query_fw_config_t*)((uint8_t*)buf + cmd_off);
624  fw_config->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
625  fw_config->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
626  return cmd_off + sizeof(sli4_req_common_query_fw_config_t);
627 }
628 
629 
630 /**
631  * @brief Write a COMMON_GET_VPD_DATA command to the provided buffer.
632  *
633  * @param sli4 SLI context pointer.
634  * @param buf Virtual pointer to destination buffer.
635  * @param size Buffer size in bytes.
636  *
637  * @return Returns the number of bytes written.
638  */
639 static int32_t
640 sli_cmd_get_vpd_data(sli4_t *sli4, void *buf, size_t size)
641 {
643  uint32_t cmd_off = 0;
644  uint32_t payload_size;
645 
646  /* Payload length must accomodate both request and response */
647  payload_size = max(sizeof(sli4_req_common_get_vpd_data_t),
648  sizeof(sli4_res_hdr_t) + sli4->vpd.data.size);
649 
650  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, 0,
651  payload_size,
652  &sli4->vpd.data);
653 
654  get_vpd = (sli4_req_common_get_vpd_data_t*)sli4->vpd.data.virt;
657  get_vpd->hdr.request_length = sli4->vpd.data.size - sizeof(sli4_req_hdr_t);
658  return cmd_off + sizeof(sli4_req_common_get_vpd_data_t);
659 }
660 
661 
662 /**
663  * @brief Write a COMMON_GET_CNTL_ATTRIBUTES command to the provided buffer.
664  *
665  * @param sli4 SLI context pointer.
666  * @param buf Virtual pointer to destination buffer.
667  * @param size Buffer size in bytes.
668  *
669  * @return Returns the number of bytes written.
670  */
671 static int32_t
672 sli_cmd_common_get_cntl_attributes(sli4_t *sli4, void *buf, size_t size)
673 {
675  uint32_t cmd_off = 0;
676  uint32_t payload_size;
677 
678  /* Payload length must accomodate both request and response */
679  payload_size = max(sizeof(sli4_req_common_get_cntl_attributes_t),
681 
682  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, 0, payload_size,
683  &sli4->cntl_attr);
684 
685  get_cntl = (sli4_req_common_get_cntl_attributes_t *)sli4->cntl_attr.virt;
686  ocs_memset(get_cntl, 0, payload_size);
687 
689  get_cntl->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
690  get_cntl->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
691 
692  return(cmd_off);
693 }
694 
695 
696 /**
697  * @brief Write a COMMON_GET_CNTL_ADDL_ATTRIBUTES command to the provided buffer
698  *
699  * @param sli4 SLI context pointer
700  * @param buf virtual pointer to destination buffer
701  * @param size buffer size in bytes
702  *
703  * @return number of bytes written
704  */
705 static int32_t
706 sli_cmd_common_get_cntl_addl_attributes(sli4_t *sli4, void *buf, size_t size)
707 {
709  uint32_t cmd_off = 0;
710  uint32_t payload_size;
711 
712  /* Payload length must accomodate both request and response */
713  payload_size = max(sizeof(sli4_req_common_get_cntl_addl_attributes_t),
715 
716  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, 0, payload_size,
717  &sli4->cntl_attr);
718 
719  get_cntl_addl = (sli4_req_common_get_cntl_addl_attributes_t *)sli4->cntl_attr.virt;
720  ocs_memset(get_cntl_addl, 0, payload_size);
721 
723  get_cntl_addl->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
724  get_cntl_addl->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
725 
726  return(cmd_off);
727 }
728 
729 
730 /**
731  * @brief write a COMMON_FUNCTION_RESET command.
732  *
733  * @param sli4 SLI context.
734  * @param buf Destination buffer for the command.
735  * @param size Buffer size in bytes.
736  * @param tag Command tag.
737  *
738  * @return Returns the number of bytes written.
739  */
740 static int32_t
741 sli_cmd_common_function_reset(sli4_t *sli4, void *buf, size_t size, uint64_t tag)
742 {
743  sli4_req_common_function_reset_t *reset = NULL;
744  uint32_t cmd_off = 0;
745  uint32_t payload_size;
746 
747  /* Payload length must accomodate both request and response */
748  payload_size = max(sizeof(sli4_req_common_function_reset_t),
750 
751  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag, payload_size,
752  NULL);
753  reset = (sli4_req_common_function_reset_t *)((uint8_t *)buf + cmd_off);
754 
757 
758  return(cmd_off + sizeof(sli4_req_common_function_reset_t));
759 }
760 
761 
762 /**
763  * @brief Write a COMMON_CREATE_CQ command.
764  *
765  * @param sli4 SLI context.
766  * @param buf Destination buffer for the command.
767  * @param size Buffer size in bytes.
768  * @param tag Command tag.
769  * @param qmem DMA memory for the queue.
770  * @param eq_id Associated EQ_ID.
771  * @param ignored This parameter carries the ULP which is only used for WQ and RQs.
772  *
773  * @note This creates a Version 0 message.
774  *
775  * @return Returns the number of bytes written.
776  */
777 static int32_t
778 sli_cmd_common_create_cq(sli4_t *sli4, void *buf, size_t size, uint64_t tag,
779  ocs_dma_t *qmem, uint16_t eq_id, uint16_t ignored)
780 {
781  sli4_req_common_create_cq_v0_t *cqv0 = NULL;
782  sli4_req_common_create_cq_v2_t *cqv2 = NULL;
783  uint32_t cmd_off = 0;
784  uint32_t p;
785  uintptr_t addr;
786  uint32_t if_type = sli4->if_type;
787  uint32_t payload_size;
788 
789  /* Payload length must accomodate both request and response */
790  payload_size = max(sizeof(sli4_req_common_create_cq_v0_t),
792 
793  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag, payload_size,
794  NULL);
795 
796  /* note, there are places that follow that assume certain element locations are the
797  * same between the V0 and V2 forms
798  */
799  cqv0 = (sli4_req_common_create_cq_v0_t *)((uint8_t *)buf + cmd_off);
800  cqv2 = (sli4_req_common_create_cq_v2_t *)((uint8_t *)buf + cmd_off);
801 
805  sizeof(sli4_req_hdr_t);
806  switch (if_type)
807  {
808  case 0:
809  cqv0->hdr.version = 0;
810 
811  /* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */
812  cqv0->num_pages = qmem->size / 4096;
813  switch (cqv0->num_pages) {
814  case 1:
815  cqv0->cqecnt = SLI4_CQ_CNT_256;
816  break;
817  case 2:
818  cqv0->cqecnt = SLI4_CQ_CNT_512;
819  break;
820  case 4:
821  cqv0->cqecnt = SLI4_CQ_CNT_1024;
822  break;
823  default:
824  ocs_log_err(NULL, "num_pages %d not valid\n", cqv0->num_pages);
825  return -1;
826  }
827  cqv0->evt = TRUE;
828  cqv0->valid = TRUE;
829  /* TODO cq->nodelay = ???; */
830  /* TODO cq->clswm = ???; */
831  cqv0->arm = FALSE;
832  cqv0->eq_id = eq_id;
833  break;
834  case 2:
835  cqv2->hdr.version = 2;
836 
837  /* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */
838  cqv2->num_pages = qmem->size / 4096;
839  switch (cqv2->num_pages) {
840  case 1:
841  cqv2->cqecnt = SLI4_CQ_CNT_256;
842  break;
843  case 2:
844  cqv2->cqecnt = SLI4_CQ_CNT_512;
845  break;
846  case 4:
847  cqv2->cqecnt = SLI4_CQ_CNT_1024;
848  break;
849  default:
850  ocs_log_err(NULL, "num_pages %d not valid\n", cqv2->num_pages);
851  return -1;
852  }
853  cqv2->evt = TRUE;
854  cqv2->valid = TRUE;
855  /* TODO cq->nodelay = ???; */
856  /* TODO cq->clswm = ???; */
857  cqv2->arm = FALSE;
858  cqv2->eq_id = eq_id;
859 
860  // V2 variables
861  cqv2->page_size = 1;
862  cqv2->autovalid = 0;
863 
864  break;
865  }
866 
867  for (p = 0, addr = qmem->phys;
868  p < cqv0->num_pages;
869  p++, addr += 4096) {
870  cqv0->page_physical_address[p].low = ocs_addr32_lo(addr);
871  cqv0->page_physical_address[p].high = ocs_addr32_hi(addr);
872  }
873 
874  return(cmd_off + sizeof(sli4_req_common_create_cq_v0_t));
875 }
876 
877 /**
878  * @brief write a COMMON_DESTROY_CQ command.
879  *
880  * @param sli4 SLI context.
881  * @param buf Destination buffer for the command.
882  * @param size Buffer size in bytes.
883  * @param tag Command tag.
884  * @param cq_id CQ ID.
885  *
886  * @note This creates a Version 0 message.
887  *
888  * @return Returns the number of bytes written.
889  */
890 static int32_t
891 sli_cmd_common_destroy_cq(sli4_t *sli4, void *buf, size_t size, uint64_t tag,
892  uint16_t cq_id)
893 {
894  sli4_req_common_destroy_cq_t *cq = NULL;
895  uint32_t cmd_off = 0;
896 
897  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
898  /* Payload length must accomodate both request and response */
899  max(sizeof(sli4_req_common_destroy_cq_t),
900  sizeof(sli4_res_hdr_t)),
901  NULL);
902  cq = (sli4_req_common_destroy_cq_t *)((uint8_t *)buf + cmd_off);
903 
904 
908  sizeof(sli4_req_hdr_t);
909  cq->cq_id = cq_id;
910 
911  return(cmd_off + sizeof(sli4_req_common_destroy_cq_t));
912 }
913 
914 /**
915  * @brief write a COMMON_CREATE_EQ command.
916  *
917  * @param sli4 SLI context.
918  * @param buf Destination buffer for the command.
919  * @param size Buffer size in bytes.
920  * @param tag Command tag.
921  * @param qmem DMA memory for the queue.
922  * @param ignored1 Ignored (used for consistency among queue creation functions).
923  * @param ignored2 Ignored (used for consistency among queue creation functions).
924  *
925  * @note
926  * - Other queue creation routines use the last parameter to pass in
927  * the associated Q_ID and ULP. EQ doesn't have an associated queue or ULP,
928  * so these parameters are ignored.
929  * - This creates a Version 0 message.
930  *
931  * @return Returns the number of bytes written.
932  */
933 static int32_t
934 sli_cmd_common_create_eq(sli4_t *sli4, void *buf, size_t size, uint64_t tag,
935  ocs_dma_t *qmem, uint16_t ignored1, uint16_t ignored2)
936 {
937  sli4_req_common_create_eq_t *eq = NULL;
938  uint32_t cmd_off = 0;
939  uint32_t p;
940  uintptr_t addr;
941  uint32_t payload_size;
942 
943  /* Payload length must accomodate both request and response */
944  payload_size = max(sizeof(sli4_req_common_create_eq_t),
946 
947  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag, payload_size,
948  NULL);
949 
950  eq = (sli4_req_common_create_eq_t *)((uint8_t *)buf + cmd_off);
951 
955  sizeof(sli4_req_hdr_t);
956  /* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */
957  eq->num_pages = qmem->size / 4096;
958  switch (eq->num_pages) {
959  case 1:
960  eq->eqesz = SLI4_EQE_SIZE_4;
961  eq->count = SLI4_EQ_CNT_1024;
962  break;
963  case 2:
964  eq->eqesz = SLI4_EQE_SIZE_4;
965  eq->count = SLI4_EQ_CNT_2048;
966  break;
967  case 4:
968  eq->eqesz = SLI4_EQE_SIZE_4;
969  eq->count = SLI4_EQ_CNT_4096;
970  break;
971  default:
972  ocs_log_err(NULL, "num_pages %d not valid\n", eq->num_pages);
973  return -1;
974  }
975  eq->valid = TRUE;
976  eq->arm = FALSE;
977  eq->delay_multiplier = 32;
978 
979  for (p = 0, addr = qmem->phys;
980  p < eq->num_pages;
981  p++, addr += 4096) {
982  eq->page_address[p].low = ocs_addr32_lo(addr);
983  eq->page_address[p].high = ocs_addr32_hi(addr);
984  }
985 
986  return(cmd_off + sizeof(sli4_req_common_create_eq_t));
987 }
988 
989 /**
990  * @brief Write a COMMON_MODIFY_EQ_DELAY command
991  *
992  * @param sli4 SLI context
993  * @param buf Destination buffer for the command.
994  * @param size Buffer size, in bytes.
995  * @param q Queue object array.
996  * @param num_q Queue object array count.
997  * @param shift Phase shift for staggering interrupts.
998  * @param delay_mult Delay multiplier for limiting interrupt frequency.
999  *
1000  * @return Returns the number of bytes written.
1001  */
1002 static int32_t
1003 sli_cmd_common_modify_eq_delay(sli4_t *sli4, void *buf, size_t size, sli4_queue_t *q, int num_q, uint32_t shift,
1004  uint32_t delay_mult)
1005 {
1006  sli4_req_common_modify_eq_delay_t *modify_delay = NULL;
1007  uint32_t cmd_off = 0;
1008  int i;
1009 
1010  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, 0,
1011  /* Payload length must accomodate both request and response */
1012  max(sizeof(sli4_req_common_modify_eq_delay_t), sizeof(sli4_res_hdr_t)),
1013  NULL);
1014 
1015  modify_delay = (sli4_req_common_modify_eq_delay_t *)((uint8_t *)buf + cmd_off);
1016 
1017  modify_delay->hdr.opcode = SLI4_OPC_COMMON_MODIFY_EQ_DELAY;
1018  modify_delay->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
1019  modify_delay->hdr.request_length = sizeof(sli4_req_common_modify_eq_delay_t) -
1020  sizeof(sli4_req_hdr_t);
1021 
1022  modify_delay->num_eq = num_q;
1023 
1024  for (i = 0; i<num_q; i++) {
1025  modify_delay->eq_delay_record[i].eq_id = q[i].id;
1026  modify_delay->eq_delay_record[i].phase = shift;
1027  modify_delay->eq_delay_record[i].delay_multiplier = delay_mult;
1028  }
1029 
1030  return(cmd_off + sizeof(sli4_req_common_modify_eq_delay_t));
1031 }
1032 
1033 /**
1034  * @brief Write a COMMON_DESTROY_EQ command.
1035  *
1036  * @param sli4 SLI context.
1037  * @param buf Destination buffer for the command.
1038  * @param size Buffer size in bytes.
1039  * @param tag Command tag.
1040  * @param eq_id EQ ID.
1041  *
1042  * @note This creates a Version 0 message.
1043  *
1044  * @return Returns the number of bytes written.
1045  */
1046 static int32_t
1047 sli_cmd_common_destroy_eq(sli4_t *sli4, void *buf, size_t size, uint64_t tag,
1048  uint16_t eq_id)
1049 {
1050  sli4_req_common_destroy_eq_t *eq = NULL;
1051  uint32_t cmd_off = 0;
1052 
1053  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1054  /* Payload length must accomodate both request and response */
1055  max(sizeof(sli4_req_common_destroy_eq_t),
1056  sizeof(sli4_res_hdr_t)),
1057  NULL);
1058  eq = (sli4_req_common_destroy_eq_t *)((uint8_t *)buf + cmd_off);
1059 
1063  sizeof(sli4_req_hdr_t);
1064  eq->eq_id = eq_id;
1065 
1066  return(cmd_off + sizeof(sli4_req_common_destroy_eq_t));
1067 }
1068 
1069 /**
1070  * @brief Write a COMMON_CREATE_MQ_EXT command.
1071  *
1072  * @param sli4 SLI context.
1073  * @param buf Destination buffer for the command.
1074  * @param size Buffer size in bytes.
1075  * @param tag Command tag.
1076  * @param qmem DMA memory for the queue.
1077  * @param cq_id Associated CQ_ID.
1078  * @param ignored This parameter carries the ULP which is only used for WQ and RQs.
1079  *
1080  * @note This creates a Version 0 message.
1081  *
1082  * @return Returns the number of bytes written.
1083  */
1084 static int32_t
1085 sli_cmd_common_create_mq_ext(sli4_t *sli4, void *buf, size_t size, uint64_t tag,
1086  ocs_dma_t *qmem, uint16_t cq_id, uint16_t ignored)
1087 {
1089  uint32_t cmd_off = 0;
1090  uint32_t p;
1091  uintptr_t addr;
1092  uint32_t payload_size;
1093 
1094  /* Payload length must accomodate both request and response */
1095  payload_size = max(sizeof(sli4_req_common_create_mq_ext_t),
1097 
1098  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag, payload_size,
1099  NULL);
1100 
1101  mq = (sli4_req_common_create_mq_ext_t *)((uint8_t *)buf + cmd_off);
1102 
1106  sizeof(sli4_req_hdr_t);
1107  /* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.12) */
1108  mq->num_pages = qmem->size / 4096;
1109  switch (mq->num_pages) {
1110  case 1:
1112  break;
1113  case 2:
1115  break;
1116  case 4:
1118  break;
1119  case 8:
1121  break;
1122  default:
1123  ocs_log_err(NULL, "num_pages %d not valid\n", mq->num_pages);
1124  return -1;
1125  }
1126 
1128 
1129  /* Use version 0 */
1130  mq->cq_id_v0 = cq_id;
1131  mq->val = TRUE;
1132 
1133  for (p = 0, addr = qmem->phys;
1134  p < mq->num_pages;
1135  p++, addr += 4096) {
1136  mq->page_physical_address[p].low = ocs_addr32_lo(addr);
1137  mq->page_physical_address[p].high = ocs_addr32_hi(addr);
1138  }
1139 
1140  return(cmd_off + sizeof(sli4_req_common_create_mq_ext_t));
1141 }
1142 
1143 /**
1144  * @brief Write a COMMON_DESTROY_MQ command.
1145  *
1146  * @param sli4 SLI context.
1147  * @param buf Destination buffer for the command.
1148  * @param size Buffer size, in bytes.
1149  * @param tag Command tag.
1150  * @param mq_id MQ ID.
1151  *
1152  * @note This creates a Version 0 message.
1153  *
1154  * @return Returns the number of bytes written.
1155  */
1156 static int32_t
1157 sli_cmd_common_destroy_mq(sli4_t *sli4, void *buf, size_t size, uint64_t tag,
1158  uint16_t mq_id)
1159 {
1160  sli4_req_common_destroy_mq_t *mq = NULL;
1161  uint32_t cmd_off = 0;
1162 
1163  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1164  /* Payload length must accomodate both request and response */
1165  max(sizeof(sli4_req_common_destroy_mq_t),
1166  sizeof(sli4_res_hdr_t)),
1167  NULL);
1168 
1169  mq = (sli4_req_common_destroy_mq_t *)((uint8_t *)buf + cmd_off);
1170 
1174  sizeof(sli4_req_hdr_t);
1175  mq->mq_id = mq_id;
1176 
1177  return(cmd_off + sizeof(sli4_req_common_destroy_mq_t));
1178 }
1179 
1180 
1181 /**
1182  * @ingroup sli
1183  * @brief Write a COMMON_TCP_UPLOAD command.
1184  *
1185  * @param sli4 SLI context.
1186  * @param buf Destination buffer for the command.
1187  * @param size Buffer size in bytes.
1188  * @param tag Command tag.
1189  * @param wq_id The work queue id assigned to the connection.
1190  * @param graceful If true, a graceful upload is done, otherwise an abort without
1191  * reset is sent.
1192  *
1193  * @return Returns the number of bytes written.
1194  */
1195 int32_t
1196 sli_cmd_common_tcp_upload(sli4_t *sli4, void *buf, size_t size, uint64_t tag,
1197  uint16_t wq_id, uint8_t graceful)
1198 {
1199  sli4_req_common_tcp_upload_t *req = NULL;
1200  uint32_t cmd_off = 0;
1201 
1202  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1203  /* Payload length must accomodate both request and response */
1204  max(sizeof(sli4_req_common_tcp_upload_t),
1205  sizeof(sli4_res_hdr_t)),
1206  NULL);
1207 
1208  req = (sli4_req_common_tcp_upload_t *)((uint8_t *)buf + cmd_off);
1209 
1213  sizeof(sli4_req_hdr_t);
1214 
1215  req->wq_id = wq_id;
1216  req->upload_type = (graceful ? 1 : 3);
1217  req->reset_seq = 0;
1218 
1219  return(cmd_off + sizeof(sli4_req_common_destroy_mq_t));
1220 }
1221 
1222 
1223 /**
1224  * @ingroup sli
1225  * @brief Write a COMMON_NOP command.
1226  *
1227  * @param sli4 SLI context.
1228  * @param buf Destination buffer for the command.
1229  * @param size Buffer size in bytes.
1230  * @param tag Command tag.
1231  * @param context NOP context value (passed to response, except on FC/FCoE).
1232  *
1233  * @return Returns the number of bytes written.
1234  */
1235 int32_t
1236 sli_cmd_common_nop(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint64_t context)
1237 {
1238  sli4_req_common_nop_t *nop = NULL;
1239  uint32_t cmd_off = 0;
1240 
1241  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1242  /* Payload length must accomodate both request and response */
1243  max(sizeof(sli4_req_common_nop_t), sizeof(sli4_res_common_nop_t)),
1244  NULL);
1245 
1246  nop = (sli4_req_common_nop_t *)((uint8_t *)buf + cmd_off);
1247 
1250  nop->hdr.request_length = 8;
1251 
1252  ocs_memcpy(&nop->context, &context, sizeof(context));
1253 
1254  return(cmd_off + sizeof(sli4_req_common_nop_t));
1255 }
1256 
1257 /**
1258  * @ingroup sli
1259  * @brief Write a COMMON_READ_TRANSCEIVER_DATA command.
1260  *
1261  * @param sli4 SLI context.
1262  * @param buf Destination buffer for the command.
1263  * @param size Buffer size in bytes.
1264  * @param tag Command tag.
1265  * @param page_num The page of SFP data to retrieve (0xa0 or 0xa2).
1266  * @param port The port from which to retrieve SFP data.
1267  * @param dma DMA buffer for non-embedded commands.
1268  *
1269  * @return Returns the number of bytes written.
1270  */
1271 static int32_t
1272 sli_cmd_common_read_transceiver_data(sli4_t *sli4, void *buf, size_t size,
1273  uint64_t tag, uint32_t page_num,
1274  uint32_t port, ocs_dma_t *dma)
1275 {
1277  uint32_t cmd_off = 0;
1278  uint32_t pl_size;
1279 
1280  /* Payload length must accomodate both request and response */
1281  if (dma == NULL) {
1282  pl_size = max(sizeof(sli4_req_common_read_transceiver_data_t),
1284  } else {
1285  pl_size = dma->size;
1286  }
1287 
1288  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag, pl_size, dma);
1289 
1290  if (dma == NULL) {
1291  req = (sli4_req_common_read_transceiver_data_t*)((uint8_t *)buf + cmd_off);
1292  } else {
1293  req = (sli4_req_common_read_transceiver_data_t*)dma->virt;
1294  }
1295 
1298  req->hdr.domain = 0;
1299  req->hdr.port_number = 0;
1300  req->hdr.timeout = 0;
1301  req->hdr.version = 0;
1302  req->hdr.request_length = pl_size - sizeof(sli4_req_hdr_t);
1303 
1304  req->page_num = page_num;
1305  req->port = port;
1306 
1307  return(cmd_off + sizeof(sli4_req_common_read_transceiver_data_t));
1308 }
1309 
1310 /**
1311  * @ingroup sli
1312  * @brief Write a COMMON_COMMON_GET_BE_CONFIGURATION_AND_RESOURCES command
1313  *
1314  * @param sli4 SLI context.
1315  * @param buf Destination buffer for the command.
1316  * @param size bBuffer size in bytes.
1317  * @param tag Command tag.
1318  *
1319  * @return Returns the number of bytes written.
1320  */
1321 static int32_t
1322 sli_cmd_common_get_be_configuration_and_resources(sli4_t *sli4, void *buf, size_t size, uint64_t tag)
1323 {
1325  uint32_t cmd_off = 0;
1326  uint32_t payload_size;
1327 
1328  /* Payload length must accomodate both request and response */
1329  payload_size = max(sizeof(sli4_req_common_get_be_configuration_and_resources_t),
1330  size - sizeof(sli4_mqe_hdr_t));
1331 
1332  /* Note: We cheat and use the VPD buffer */
1333  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1334  payload_size,
1335  &sli4->vpd.data);
1336 
1338  sli4->vpd.data.virt;
1339 
1342  req->hdr.request_length = sli4->vpd.data.size - sizeof(sli4_req_hdr_t);
1343  req->hdr.version = 1;
1344 
1345  return(cmd_off + sizeof(sli4_req_common_get_be_configuration_and_resources_t));
1346 }
1347 
1348 
1349 /**
1350  * @ingroup sli
1351  * @brief Write a COMMON_COMMON_SET_BE_CONFIGURATION_AND_RESOURCES command.
1352  *
1353  * @param sli4 SLI context.
1354  * @param buf Destination buffer for the command.
1355  * @param size Buffer size in bytes.
1356  * @param tag Command tag.
1357  * @param mac_addr Pointer to the 6 byte MAC address.
1358  *
1359  * @return Returns the number of bytes written.
1360  */
1361 int32_t
1362 sli_cmd_common_set_be_configuration_and_resources(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint8_t *mac_addr)
1363 {
1365  uint32_t cmd_off = 0;
1366  uint32_t payload_size;
1367 
1368  /* Payload length must accomodate both request and response */
1369  payload_size = max(sizeof(sli4_req_common_set_be_configuration_and_resources_t),
1370  sizeof(sli4_mqe_hdr_t));
1371 
1372  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1373  payload_size,
1374  NULL);
1375 
1377  ((uint8_t *)buf + cmd_off);
1378 
1381  req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
1382  req->hdr.version = 1;
1383  req->resource_desc_cnt = 1;
1384  req->resource_type = 0x2; /* iSCSI */
1385  req->pf_num = sli4->pf_num;
1386  req->vf_domain = 0xFF;
1387  req->valid_fields = 0;
1388  req->session_count = UINT16_MAX;
1389  req->icd_count = UINT16_MAX;
1390  req->cq_count = UINT16_MAX;
1391  req->iscsi_mac_address_0 = mac_addr[0];
1392  req->iscsi_mac_address_1 = mac_addr[1];
1393  req->iscsi_mac_address_2 = mac_addr[2];
1394  req->iscsi_mac_address_3 = mac_addr[3];
1395  req->iscsi_mac_address_4 = mac_addr[4];
1396  req->iscsi_mac_address_5 = mac_addr[5];
1397  req->mcc_queue_count = UINT8_MAX;
1398  req->bw_percent = UINT8_MAX;
1399  req->vlan_id = UINT16_MAX;
1400 
1401  return(cmd_off + sizeof(sli4_req_common_set_be_configuration_and_resources_t));
1402 }
1403 
1404 /**
1405  * @ingroup sli
1406  * @brief Write a COMMON_COMMON_GET_FUNCTION_CONFIG command.
1407  *
1408  * @param sli4 SLI context.
1409  * @param buf Destination buffer for the command.
1410  * @param size Buffer size in bytes.
1411  * @param tag Command tag.
1412  *
1413  * @return Returns the number of bytes written.
1414  */
1415 int32_t
1416 sli_cmd_common_get_function_config(sli4_t *sli4, void *buf, size_t size, uint64_t tag)
1417 {
1419  uint32_t cmd_off = 0;
1420  uint32_t payload_size;
1421 
1422  /* Payload length must accomodate both request and response */
1423  payload_size = max(sizeof(sli4_req_common_get_function_config_t),
1425 
1426  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1427  payload_size,
1428  NULL);
1429 
1431  ((uint8_t*)buf + cmd_off);
1432 
1435  req->hdr.request_length = sli4->vpd.data.size - sizeof(sli4_req_hdr_t);
1436  req->hdr.version = 1;
1437 
1438  return(cmd_off + sizeof(sli4_req_common_get_function_config_t));
1439 }
1440 
1441 /**
1442  * @ingroup sli
1443  * @brief Write a COMMON_COMMON_GET_PROFILE_CONFIG command.
1444  *
1445  * @param sli4 SLI context.
1446  * @param buf Destination buffer for the command.
1447  * @param size Buffer size in bytes.
1448  * @param tag Command tag.
1449  * @param dma DMA capable memory used to retrieve profile.
1450  *
1451  * @return Returns the number of bytes written.
1452  */
1453 int32_t
1454 sli_cmd_common_get_profile_config(sli4_t *sli4, void *buf, size_t size, uint64_t tag, ocs_dma_t *dma)
1455 {
1457  uint32_t cmd_off = 0;
1458  uint32_t payload_size;
1459 
1460  if (dma == NULL) {
1461  payload_size = max(sizeof(sli4_req_common_get_profile_list_t),
1463  } else {
1464  payload_size = dma->size;
1465  }
1466 
1467  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1468  payload_size,
1469  dma);
1470 
1471  if (dma == NULL) {
1472  req = (sli4_req_common_get_profile_config_t*)((uint8_t *)buf + cmd_off);
1473  } else {
1474  ocs_memset(dma->virt, 0, dma->size);
1475  req = (sli4_req_common_get_profile_config_t *)dma->virt;
1476  }
1477 
1478 
1479 
1482  req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
1483  req->hdr.version = 1;
1484 
1485  return(cmd_off + sizeof(sli4_req_common_get_profile_config_t));
1486 }
1487 
1488 /**
1489  * @ingroup sli
1490  * @brief Write a COMMON_COMMON_SET_PROFILE_CONFIG command.
1491  *
1492  * @param sli4 SLI context
1493  * @param buf Destination buffer for the command.
1494  * @param size Buffer size in bytes.
1495  * @param tag Command tag.
1496  * @param dma DMA capable memory containing profile.
1497  * @param profile_id Profile ID to configure.
1498  * @param descriptor_count Number of descriptors in DMA buffer.
1499  * @param isap Set Active Profile value to use.
1500  *
1501  * @return Returns the number of bytes written.
1502  */
1503 int32_t
1504 sli_cmd_common_set_profile_config(sli4_t *sli4, void *buf, size_t size, uint64_t tag, ocs_dma_t *dma,
1505  uint8_t profile_id, uint32_t descriptor_count, uint8_t isap)
1506 {
1508  uint32_t cmd_off = 0;
1509  uint32_t payload_size;
1510 
1511  if (dma == NULL) {
1512  payload_size = max(sizeof(sli4_req_common_set_profile_config_t),
1514  } else {
1515  payload_size = dma->size;
1516  }
1517 
1518  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1519  payload_size,
1520  dma);
1521 
1522  if (dma == NULL) {
1523  req = (sli4_req_common_set_profile_config_t*)((uint8_t *)buf + cmd_off);
1524  } else {
1525  ocs_memset(dma->virt, 0, dma->size);
1526  req = (sli4_req_common_set_profile_config_t *)dma->virt;
1527  }
1528 
1531  req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
1532  req->hdr.version = 1;
1533  req->profile_id = profile_id;
1534  req->desc_count = descriptor_count;
1535  req->isap = isap;
1536 
1537  return(cmd_off + sizeof(sli4_req_common_set_profile_config_t));
1538 }
1539 
1540 
1541 /**
1542  * @ingroup sli
1543  * @brief Write a COMMON_COMMON_GET_PROFILE_LIST command.
1544  *
1545  * @param sli4 SLI context.
1546  * @param buf Destination buffer for the command.
1547  * @param size Buffer size in bytes.
1548  * @param tag Command tag.
1549  * @param start_profile_index First profile index to return.
1550  * @param dma Buffer into which the list will be written.
1551  *
1552  * @return Returns the number of bytes written.
1553  */
1554 int32_t
1555 sli_cmd_common_get_profile_list(sli4_t *sli4, void *buf, size_t size, uint64_t tag,
1556  uint32_t start_profile_index, ocs_dma_t *dma)
1557 {
1559  uint32_t cmd_off = 0;
1560  uint32_t payload_size;
1561 
1562  if (dma == NULL) {
1563  payload_size = max(sizeof(sli4_req_common_get_profile_list_t),
1565  } else {
1566  payload_size = dma->size;
1567  }
1568 
1569  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1570  payload_size,
1571  dma);
1572 
1573  if (dma == NULL) {
1574  req = (sli4_req_common_get_profile_list_t*)((uint8_t *)buf + cmd_off);
1575  } else {
1576  ocs_memset(dma->virt, 0, dma->size);
1577  req = (sli4_req_common_get_profile_list_t *)dma->virt;
1578  }
1579 
1580 
1583  req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
1584  req->hdr.version = 0;
1585 
1586  req->start_profile_index = start_profile_index;
1587 
1588  return(cmd_off + sizeof(sli4_req_common_get_profile_list_t));
1589 }
1590 
1591 /**
1592  * @ingroup sli
1593  * @brief Write a COMMON_COMMON_GET_ACTIVE_PROFILE command.
1594  *
1595  * @param sli4 SLI context.
1596  * @param buf Destination buffer for the command.
1597  * @param size Buffer size in bytes.
1598  * @param tag Command tag.
1599  *
1600  * @return Returns the number of bytes written.
1601  */
1602 int32_t
1603 sli_cmd_common_get_active_profile(sli4_t *sli4, void *buf, size_t size, uint64_t tag)
1604 {
1606  uint32_t cmd_off = 0;
1607  uint32_t payload_size;
1608 
1609  /* Payload length must accomodate both request and response */
1610  payload_size = max(sizeof(sli4_req_common_get_active_profile_t),
1612 
1613  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1614  payload_size,
1615  NULL);
1616 
1618  ((uint8_t*)buf + cmd_off);
1619 
1622  req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
1623  req->hdr.version = 0;
1624 
1625  return(cmd_off + sizeof(sli4_req_common_get_active_profile_t));
1626 }
1627 
1628 /**
1629  * @ingroup sli
1630  * @brief Write a COMMON_COMMON_SET_ACTIVE_PROFILE command.
1631  *
1632  * @param sli4 SLI context.
1633  * @param buf Destination buffer for the command.
1634  * @param size Buffer size in bytes.
1635  * @param tag Command tag.
1636  * @param fd If non-zero, set profile to factory default.
1637  * @param active_profile_id ID of new active profile.
1638  *
1639  * @return Returns the number of bytes written.
1640  */
1641 int32_t
1642 sli_cmd_common_set_active_profile(sli4_t *sli4, void *buf, size_t size, uint64_t tag,
1643  uint32_t fd, uint32_t active_profile_id)
1644 {
1646  uint32_t cmd_off = 0;
1647  uint32_t payload_size;
1648 
1649  /* Payload length must accomodate both request and response */
1650  payload_size = max(sizeof(sli4_req_common_set_active_profile_t),
1652 
1653  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1654  payload_size,
1655  NULL);
1656 
1658  ((uint8_t*)buf + cmd_off);
1659 
1662  req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
1663  req->hdr.version = 0;
1664  req->fd = fd;
1665  req->active_profile_id = active_profile_id;
1666 
1667  return(cmd_off + sizeof(sli4_req_common_set_active_profile_t));
1668 }
1669 
1670 /**
1671  * @ingroup sli
1672  * @brief Write a COMMON_COMMON_GET_RECONFIG_LINK_INFO command.
1673  *
1674  * @param sli4 SLI context.
1675  * @param buf Destination buffer for the command.
1676  * @param size Buffer size in bytes.
1677  * @param tag Command tag.
1678  * @param dma Buffer to store the link configuration mode from the physical device.
1679  *
1680  * @return Returns the number of bytes written.
1681  */
1682 int32_t
1683 sli_cmd_common_get_reconfig_link_info(sli4_t *sli4, void *buf, size_t size, uint64_t tag, ocs_dma_t *dma)
1684 {
1686  uint32_t cmd_off = 0;
1687  uint32_t payload_size;
1688 
1689  if (dma != NULL) {
1690  payload_size = dma->size;
1691  } else {
1692  payload_size = sizeof(sli4_req_common_get_reconfig_link_info_t);
1693  }
1694 
1695  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1696  payload_size,
1697  dma);
1698 
1699  if (dma != NULL) {
1700  req = dma->virt;
1701  ocs_memset(req, 0, dma->size);
1702  } else {
1703  req = (sli4_req_common_get_reconfig_link_info_t *)((uint8_t *)buf + cmd_off);
1704  }
1705 
1708  req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
1709  req->hdr.version = 0;
1710 
1711  return(cmd_off + sizeof(sli4_req_common_get_reconfig_link_info_t));
1712 }
1713 
1714 /**
1715  * @ingroup sli
1716  * @brief Write a COMMON_COMMON_SET_RECONFIG_LINK_ID command.
1717  *
1718  * @param sli4 SLI context.
1719  * @param buf Destination buffer for the command.
1720  * @param size Buffer size in bytes.
1721  * @param tag Command tag.
1722  * @param dma Buffer to assign the link configuration mode that is to become active from the physical device.
1723  * @param fd If non-zero, set link config to factory default.
1724  * @param active_link_config_id ID of new active profile.
1725  *
1726  * @return Returns the number of bytes written.
1727  */
1728 int32_t
1729 sli_cmd_common_set_reconfig_link_id(sli4_t *sli4, void *buf, size_t size, uint64_t tag,
1730  ocs_dma_t *dma, uint32_t fd,
1731  uint32_t active_link_config_id)
1732 {
1734  uint32_t cmd_off = 0;
1735  uint32_t payload_size;
1736 
1737  if (dma != NULL) {
1738  payload_size = dma->size;
1739  } else {
1740  payload_size = sizeof(sli4_req_common_set_reconfig_link_id_t);
1741  }
1742 
1743  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, tag,
1744  payload_size,
1745  dma);
1746 
1747  if (dma != NULL) {
1748  req = dma->virt;
1749  ocs_memset(req, 0, dma->size);
1750  } else {
1751  req = (sli4_req_common_set_reconfig_link_id_t *)((uint8_t *)buf + cmd_off);
1752  }
1753 
1756  req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
1757  req->hdr.version = 0;
1758  req->fd = fd;
1759  req->next_link_config_id = active_link_config_id;
1760 
1761  return(cmd_off + sizeof(sli4_req_common_set_reconfig_link_id_t));
1762 }
1763 
1764 /**
1765  * @ingroup sli
1766  * @brief Write a COMMON_SET_FEATURES command.
1767  *
1768  * @param sli4 SLI context.
1769  * @param buf Destination buffer for the command.
1770  * @param size Buffer size, in bytes.
1771  * @param feature The feature to set.
1772  * @param param_len The length of the parameter (must be a multiple of 4 bytes).
1773  * @param parameter Pointer to the parameter value.
1774  *
1775  * @return Returns the number of bytes written.
1776  */
1777 int32_t
1778 sli_cmd_common_set_features(sli4_t *sli4, void *buf, size_t size,
1779  uint32_t feature,
1780  uint32_t param_len,
1781  void* parameter)
1782 {
1783  sli4_req_common_set_features_t *cmd = NULL;
1784  uint32_t cmd_off = 0;
1785  uint32_t payload_size;
1786 
1787  /* Payload length must accomodate both request and response */
1788  payload_size = max(sizeof(sli4_req_common_set_features_t),
1789  sizeof(sli4_mqe_hdr_t));
1790 
1791  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, 0,
1792  payload_size,
1793  NULL);
1794 
1795  cmd = (sli4_req_common_set_features_t *)((uint8_t*)buf + cmd_off);
1796 
1800  cmd->hdr.timeout = 0;
1801  cmd->hdr.version = 0;
1802 
1803  cmd->feature = feature;
1804  cmd->param_len = param_len;
1805  ocs_memcpy(cmd->params, parameter, param_len);
1806 
1807  return (cmd_off + sizeof(sli4_req_common_set_features_t));
1808 }
1809 
1810 
1811 /**
1812  * @ingroup sli
1813  * @brief Check mailbox/queue completion entry.
1814  *
1815  * @param buf Pointer to MCQE.
1816  *
1817  * @return Returns status field (0 success, non-zero otherwise).
1818  */
1819 int32_t
1820 sli_cqe_mq(void *buf)
1821 {
1822  sli4_mcqe_t *mcqe = buf;
1823 
1824  /*
1825  * TODO: Firmware/documentation issue: the "consumed" and "complete"
1826  * bits should both be set upon completion; Lancer currently doesn't
1827  * seem to do this. Code simply checks for completion right now.
1828  */
1829  if (!mcqe->cmp /*XXX || !mcqe->con */) {
1830 #if 0
1831  ocs_log_debug(NULL, "command not finished (cmpl=%#x ext=%#x con=%d cmp=%d ae=%d val=%d)\n",
1832  mcqe->completion_status,
1833  mcqe->extended_status,
1834  mcqe->con,
1835  mcqe->cmp,
1836  mcqe->ae,
1837  mcqe->val);
1838  return -1;
1839 #endif
1840  return -2;
1841  }
1842 
1843  if (mcqe->completion_status) {
1844  ocs_log_test(NULL, "bad status (cmpl=%#x ext=%#x con=%d cmp=%d ae=%d val=%d)\n",
1845  mcqe->completion_status,
1846  mcqe->extended_status,
1847  mcqe->con,
1848  mcqe->cmp,
1849  mcqe->ae,
1850  mcqe->val);
1851  }
1852 
1853  return mcqe->completion_status;
1854 }
1855 
1856 /**
1857  * @ingroup sli
1858  * @brief Check asynchronous event completion entry.
1859  *
1860  * @param sli4 SLI context.
1861  * @param buf Pointer to ACQE.
1862  *
1863  * @return Returns status field (0 success, non-zero otherwise).
1864  */
1865 int32_t
1866 sli_cqe_async(sli4_t *sli4, void *buf)
1867 {
1868  sli4_acqe_t *acqe = buf;
1869  int32_t rc = -1;
1870 
1871  if (!sli4 || !buf) {
1872  ocs_log_err(NULL, "bad parameter sli4=%p buf=%p\n", sli4, buf);
1873  return -1;
1874  }
1875 
1876  switch (acqe->event_code) {
1878  rc = sli_iscsi_process_link_state(sli4, buf);
1879  break;
1881  ocs_log_debug(NULL, "ACQE FCOE FIP\n");
1882  break;
1884  rc = sli_iscsi_process_iscsi(sli4, buf);
1885  break;
1887  ocs_log_debug(NULL, "ACQE GRP5\n");
1888  break;
1889  default:
1890  ocs_log_test(NULL, "ACQE unknown=%#x\n", acqe->event_code);
1891  }
1892 
1893  return rc;
1894 }
1895 
1896 /**
1897  * @brief Issue a COMMON_FUNCTION_RESET command.
1898  *
1899  * @param sli4 SLI context.
1900  *
1901  * @return Returns 0 success, or non-zero otherwise.
1902  */
1903 static int32_t
1905 {
1907 
1908  if (sli_cmd_common_function_reset(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 0)) {
1909  if (sli_bmbx_command(sli4)) {
1910  ocs_log_crit(NULL, "bootstrap mailbox write fail (COMMON_FUNCTION_RESET)\n");
1911  return -1;
1912  }
1914  (((uint8_t *)sli4->bmbx.virt) + sizeof(sli4_mqe_hdr_t));
1915  if (parms->hdr.status) {
1916  ocs_log_crit(NULL, "bad status COMMON_FUNCTION_RESET\n");
1917  return -1;
1918  }
1919  } else {
1920  ocs_log_crit(NULL, "bad COMMON_FUNCTION_RESET write\n");
1921  return -1;
1922  }
1923 
1924  return 0;
1925 }
1926 
1927 /**
1928  * @brief Issue a ISCSI_CFG_REMOVE_SGL_PAGES command.
1929  *
1930  * @param sli4 SLI context.
1931  *
1932  * @return Returns 0 success, or non-zero otherwise.
1933  */
1934 static int32_t
1936 {
1937  sli4_res_hdr_t *hdr;
1938 
1939  if (sli_cmd_iscsi_remove_sgl_pages(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 0)) {
1940  if (sli_bmbx_command(sli4)) {
1941  ocs_log_crit(NULL, "bootstrap mailbox write fail (CFG_REMOVE_SGL_PAGES)\n");
1942  return -1;
1943  }
1944  hdr = (sli4_res_hdr_t *)
1945  (((uint8_t *)sli4->bmbx.virt) + sizeof(sli4_mqe_hdr_t));
1946  if (hdr->status) {
1947  ocs_log_err(NULL, "bad status CFG_REMOVE_SGL_PAGES\n");
1948  return -1;
1949  }
1950  } else {
1951  ocs_log_err(NULL, "bad CFG_REMOVE_SGL_PAGES write\n");
1952  return -1;
1953  }
1954 
1955  return 0;
1956 }
1957 
1958 
1959 /**
1960  * @brief Initialize the firmware.
1961  *
1962  * @par Description
1963  * Based on SLI-4 Architecture Specification 2.4.1
1964  *
1965  * @param sli4 SLI context.
1966  *
1967  * @return Returns 0 success, or non-zero otherwise.
1968  */
1969 static int32_t
1971 {
1972  uint32_t val = 0;
1973  uint32_t iter = 1000/*XXX*/;
1974 
1975  /*
1976  * Is firmware ready for operation? Check needed depends on IF_TYPE
1977  */
1978  if (0 == sli4->if_type) {
1979  do {
1980  ocs_delay_usec(1000); // 1 ms
1982  iter--;
1984  SLI4_PORT_SEMAPHORE_PORT(val)) &&
1986  (iter > 0)
1987  );
1988 
1989  /* Force the check below to fail on error */
1990  if (SLI4_PORT_SEMAPHORE_IN_ERR(val)) {
1991  iter = 0;
1992  }
1993  } else if ((1 == sli4->if_type) || (2 == sli4->if_type)) {
1994  do {
1995  ocs_delay_usec(1000); // 1 ms
1997  iter--;
1998  } while (!SLI4_PORT_STATUS_READY(val) && (iter > 0));
1999  }
2000 
2001  if (0 == iter) {
2002  /*XXX*/ocs_log_crit(NULL, "FW status is NOT ready\n");
2003  return -1;
2004  }
2005 
2006  /*
2007  * Reset port to a known state
2008  */
2009  switch (sli4->if_type) {
2010 //TODO: might be nice to if IF_TYPE_0,1,2,... defined
2011  case 0:
2012  case 1:
2013  /* No SLIPORT_CONTROL register so use command sequence instead */
2014  if (sli_bmbx_wait(sli4, sli4->config.bmbx_timeout_msecs)) {
2015  ocs_log_crit(NULL, "bootstrap mailbox not ready\n");
2016  return -1;
2017  }
2018 
2019  if (sli_cmd_fw_initialize(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
2020  if (sli_bmbx_command(sli4)) {
2021  ocs_log_crit(NULL, "bootstrap mailbox write fail (FW_INIT)\n");
2022  return -1;
2023  }
2024  } else {
2025  ocs_log_crit(NULL, "bad FW_INIT write\n");
2026  return -1;
2027  }
2028 
2029  if (sli_common_function_reset(sli4)) {
2030  ocs_log_err(NULL, "bad COM_FUNC_RESET write\n");
2031  return -1;
2032  }
2033  break;
2034  case 2: {
2036  return -1;
2037  break;
2038  }
2039 
2040  default:
2041  ocs_log_err(NULL, "if_type %d not supported\n", sli4->if_type);
2042  return -1;
2043  }
2044 
2045  return 0;
2046 }
2047 
2048 /**
2049  * @brief Terminate the firmware.
2050  *
2051  * @param sli4 SLI context.
2052  *
2053  * @return Returns 0 success, or non-zero otherwise.
2054  */
2055 static int32_t
2057 {
2058 
2059  if (sli4->if_type <= 1) {
2060  /* No SLIPORT_CONTROL register so use command sequence instead */
2061  if (sli_bmbx_wait(sli4, sli4->config.bmbx_timeout_msecs)) {
2062  ocs_log_crit(NULL, "bootstrap mailbox not ready\n");
2063  return -1;
2064  }
2065 
2066  if (sli_iscsi_remove_sgl_pages(sli4)) {
2067  ocs_log_err(NULL, "Failed to remove SGL pages\n");
2068  }
2069 
2070  if (sli_common_function_reset(sli4)) {
2071  ocs_log_err(NULL, "bad COM_FUNC_RESET write\n");
2072  return -1;
2073  }
2074 
2075  if (sli_cmd_fw_deinitialize(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
2076  if (sli_bmbx_command(sli4)) {
2077  ocs_log_crit(NULL, "bootstrap mailbox write fail (FW_DEINIT)\n");
2078  return -1;
2079  }
2080  } else {
2081  ocs_log_err(NULL, "bad FW_DEINIT write\n");
2082  return -1;
2083  }
2084  } else {
2085  // type 2 etc. use SLIPORT_CONTROL to initialize port
2087  }
2088  return 0;
2089 }
2090 
2091 /**
2092  * @brief Write the doorbell register associated with the queue object
2093  *
2094  * @param sli4 SLI context.
2095  * @param q Queue object.
2096  *
2097  * @return Returns 0 success, or non-zero otherwise.
2098  */
2099 static int32_t
2101 {
2102  uint32_t val = 0;
2103 
2104  switch (q->type) {
2105  case SLI_QTYPE_EQ:
2106  val = sli_eq_doorbell(q->n_posted, q->id, FALSE);
2107  ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
2108  q->db_ring_cnt++;
2109  break;
2110  case SLI_QTYPE_CQ:
2111  val = sli_cq_doorbell(q->n_posted, q->id, FALSE);
2112  ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
2113  q->db_ring_cnt++;
2114  break;
2115  case SLI_QTYPE_MQ:
2116  val = SLI4_MQ_DOORBELL(q->n_posted, q->id);
2117  ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
2118  q->db_ring_cnt++;
2119  break;
2120  case SLI_QTYPE_RQ:
2121  {
2122  uint32_t n_posted = q->n_posted;
2123  /*
2124  * FC/FCoE has different rules for Receive Queues. The host
2125  * should only update the doorbell of the RQ-pair containing
2126  * the headers since the header / payload RQs are treated
2127  * as a matched unit.
2128  */
2129  /*
2130  * Some RQ cannot be incremented one entry at a time. Instead,
2131  * the driver collects a number of entries and updates the
2132  * RQ in batches.
2133  */
2134  if (q->u.flag.rq_batch) {
2135  if (((q->index + q->n_posted) % SLI4_QUEUE_RQ_BATCH)) {
2136  break;
2137  }
2138  n_posted = SLI4_QUEUE_RQ_BATCH;
2139  }
2140 
2141  val = SLI4_RQ_DOORBELL(n_posted, q->id);
2142  ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
2143  q->db_ring_cnt++;
2144  break;
2145  }
2146  case SLI_QTYPE_WQ:
2147  val = SLI4_WQ_DOORBELL(q->n_posted, q->index, q->id);
2148  ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
2149  q->db_ring_cnt++;
2150  break;
2151  default:
2152  ocs_log_err(sli4->os, "bad queue type %d\n", q->type);
2153  return -1;
2154  }
2155 
2156  return 0;
2157 }
2158 
2159 /**
2160  * @brief Issue a GET_FW_VERSION mailbox command and store the results.
2161  *
2162  * @param sli4 SLI context.
2163  *
2164  * @return Returns 0 success, or non-zero otherwise.
2165  */
2166 static int32_t
2168 {
2169  if (sli_cmd_common_get_fw_version(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
2172  (((uint8_t *)sli4->bmbx.virt) + sizeof(sli4_mqe_hdr_t));
2173 
2174  if (sli_bmbx_command(sli4)) {
2175  ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_CONFIG)\n");
2176  return -1;
2177  }
2178  if (rsp->hdr.status) {
2179  ocs_log_err(sli4->os, "COMMON_GET_FW_VERSION bad status %#x\n",
2180  rsp->hdr.status);
2181  return -1;
2182  }
2183 
2184  ocs_log_debug(sli4->os, "FW_VERSION running FW %s\n",
2185  rsp->fw_ver);
2186  ocs_log_debug(sli4->os, "FW_VERSION flash FW %s\n",
2187  rsp->flash_fw_ver);
2188  } else {
2189  ocs_log_err(sli4->os, "bad GET_FW_VERSION write\n");
2190  return -1;
2191  }
2192  return 0;
2193 }
2194 
2195 /**
2196  * @brief Issue a READ_TRANSCEIVER_DATA mailbox command and store the results.
2197  *
2198  * @param sli4 SLI context.
2199  *
2200  * @return Returns 0 success, or non-zero otherwise.
2201  */
2202 static int32_t
2204 {
2205  ocs_dma_t page_buffer;
2206  int port = sli4->physical_port;
2207  ocs_log_debug(sli4->os, "Getting transceiver data for port %d\n", port);
2208 
2209  if (ocs_dma_alloc(sli4->os, &page_buffer, sizeof(sli4_res_common_read_transceiver_data_t), 4)) {
2210  return -1;
2211  }
2212 
2213  /* Get page A0 */
2214  if (sli_cmd_common_read_transceiver_data(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 0, 0xa0, port, &page_buffer)) {
2216  (sli4_res_common_read_transceiver_data_t *) page_buffer.virt;
2217 
2218  if (sli_bmbx_command(sli4)) {
2219  ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_TRANSCEIVER_DATA)\n");
2220  goto free_and_return_failure;
2221  }
2222  if (rsp->hdr.status) {
2223  ocs_log_err(sli4->os, "COMMON_READ_TRANSCEIVER_DATA bad status %#x/%#x\n",
2224  rsp->hdr.status, rsp->hdr.additional_status);
2225  goto free_and_return_failure;
2226  }
2227 
2228  memcpy(sli4->sfp_a0, page_buffer.virt, sizeof(sli4->sfp_a0));
2229  } else {
2230  ocs_log_err(sli4->os, "bad READ_TRANSCEIVER_DATA write\n");
2231  goto free_and_return_failure;
2232  }
2233 
2234  /* Get page A2 */
2235  if (sli_cmd_common_read_transceiver_data(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 0, 0xa2, port, &page_buffer)) {
2237  (sli4_res_common_read_transceiver_data_t *) page_buffer.virt;
2238 
2239  if (sli_bmbx_command(sli4)) {
2240  ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_TRANSCEIVER_DATA)\n");
2241  goto free_and_return_failure;
2242  }
2243  if (rsp->hdr.status) {
2244  ocs_log_err(sli4->os, "COMMON_READ_TRANSCEIVER_DATA bad status %#x/%#x\n",
2245  rsp->hdr.status, rsp->hdr.additional_status);
2246  goto free_and_return_failure;
2247  }
2248 
2249  memcpy(sli4->sfp_a2, page_buffer.virt, sizeof(sli4->sfp_a2));
2250  } else {
2251  ocs_log_err(sli4->os, "bad READ_TRANSCEIVER_DATA write\n");
2252  goto free_and_return_failure;
2253  }
2254 
2255  ocs_dma_free(sli4->os, &page_buffer);
2256  return 0;
2257 
2258 free_and_return_failure:
2259  ocs_dma_free(sli4->os, &page_buffer);
2260  return -1;
2261 }
2262 
2263 
2264 /**
2265  * @brief Issue a FW_CONFIG mailbox command and store the results.
2266  *
2267  * @param sli4 SLI context.
2268  *
2269  * @return Returns 0 success, or non-zero otherwise.
2270  */
2271 static int32_t
2273 {
2274  /*
2275  * Read the device configuration
2276  *
2277  * Note: Only ulp0 fields contain values
2278  */
2279  if (sli_cmd_common_query_fw_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
2282  (((uint8_t *)sli4->bmbx.virt) + sizeof(sli4_mqe_hdr_t));
2283 
2284  if (sli_bmbx_command(sli4)) {
2285  ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_CONFIG)\n");
2286  return -1;
2287  }
2288  if (fw_config->hdr.status) {
2289  ocs_log_err(sli4->os, "COMMON_QUERY_FW_CONFIG bad status %#x\n",
2290  fw_config->hdr.status);
2291  return -1;
2292  }
2293 
2294  sli4->features.dual_ulp_capable = ((fw_config->function_mode & SLI4_FUNCTION_MODE_DUA_MODE) == 0 ? 0 : 1);
2295  sli4->features.is_ulp_iscsi[0] = ((fw_config->ulp0_mode &
2297  SLI4_ULP_MODE_ISCSI_TGT)) == 0 ? 0 : 1);
2298  sli4->features.is_ulp_iscsi[1] = ((fw_config->ulp1_mode &
2300  SLI4_ULP_MODE_ISCSI_TGT)) == 0 ? 0 : 1);
2301 
2302  sli4->physical_port = fw_config->physical_port;
2303 
2304  if (sli4->features.dual_ulp_capable &&
2305  sli4->features.is_ulp_iscsi[0] &&
2306  sli4->features.is_ulp_iscsi[1]) {
2307  /* ICD fields are the same between ULPs */
2308  sli4->icd_base = fw_config->ulp0_iscsi_icd_base;
2309  sli4->icd_count = fw_config->ulp0_iscsi_icd_total;
2310  sli4->config.max_ios = fw_config->ulp0_iscsi_icd_total;
2311  sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp0_toe_wq_total + fw_config->ulp1_toe_wq_total;
2312  sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp0_toe_defrq_total + fw_config->ulp1_toe_defrq_total;
2313  } else if (sli4->features.is_ulp_iscsi[0]) {
2314  sli4->icd_base = fw_config->ulp0_iscsi_icd_base;
2315  sli4->icd_count = fw_config->ulp0_iscsi_icd_total;
2316  sli4->config.max_ios = fw_config->ulp0_iscsi_icd_total;
2317  sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp0_toe_wq_total;
2318  sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp0_toe_defrq_total;
2319  } else {
2320  sli4->icd_base = fw_config->ulp1_iscsi_icd_base;
2321  sli4->icd_count = fw_config->ulp1_iscsi_icd_total;
2322  sli4->config.max_ios = fw_config->ulp1_iscsi_icd_total;
2323  sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp1_toe_wq_total;
2324  sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp1_toe_defrq_total;
2325  }
2326 
2327  /*
2328  * READ_FW_CONFIG doesn't give the max number of EQ, CQ or MQ.
2329  * Dummy up a "max" count here.
2330  */
2334 
2335  if (sli4->features.sgl_chaining_capable) {
2336  sli4->icd_chain_base = fw_config->ulp0_iscsi_chain_icd_base;
2337  sli4->icd_chain_count = fw_config->ulp0_iscsi_chain_icd_total;
2338  sli4->config.max_qcount[SLI_QTYPE_EQ] = fw_config->ulp0_eq_total;
2339  sli4->config.max_qcount[SLI_QTYPE_CQ] = fw_config->ulp0_cq_total;
2340  }
2341  } else {
2342  ocs_log_err(sli4->os, "bad READ_CONFIG write\n");
2343  return -1;
2344  }
2345  return 0;
2346 }
2347 
2348 
2349 /**
2350  * @brief Issue a mailbox command and find the MAC address.
2351  *
2352  * @param sli4 SLI context.
2353  *
2354  * @return Returns 0 success, or non-zero otherwise.
2355  */
2356 static int32_t
2358 {
2359  uint32_t desc_cnt;
2360  uint32_t desc_len;
2361  uint32_t desc_type;
2362  uint32_t desc_pf;
2363  uint32_t indx;
2364 
2365  if (sli4->is_skyhawk) {
2366  if (sli_cmd_common_get_function_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 0)) {
2367  /* Note: No offset of sizeof(sli4_mqe_hdr_t) because we used a DMA buffer */
2370  (((uint8_t *)sli4->bmbx.virt) + sizeof(sli4_mqe_hdr_t));
2371  uint32_t *dword;
2372 
2373  if (sli_bmbx_command(sli4)) {
2374  ocs_log_crit(sli4->os, "bootstrap mailbox write fail (GET_FUNCTION_CONFIG)\n");
2375  return -1;
2376  }
2377  if (rsp->hdr.status) {
2378  ocs_log_err(sli4->os, "GET_FUNCTION_CONFIG bad status %#x\n",
2379  rsp->hdr.status);
2380  return -1;
2381  }
2382 
2383  /*
2384  * parse the results looking for the iSCSI descriptor.
2385  *
2386  * Note: Each descriptor is fixed at 64 bytes (16 dwords) + resource
2387  * type
2388  */
2389  desc_cnt = rsp->desc_count;
2390  dword = rsp->desc;
2391  for (indx = 0; indx < desc_cnt; indx++) {
2392  desc_len = (dword[0] >> 8) & 0xff;
2393  desc_type = dword[0] & 0xff;
2394  desc_pf = (dword[1] >> 16) & 0xff;
2395  if (desc_type == 0x52 &&
2396  desc_pf == sli4->pf_num) {
2397  /* This is the iSCSI descriptor */
2398  sli4->mac_addr[0] = (dword[3] >> 16) & 0xff;
2399  sli4->mac_addr[1] = (dword[3] >> 24) & 0xff;
2400  sli4->mac_addr[2] = dword[4] & 0xff;
2401  sli4->mac_addr[3] = (dword[4] >> 8) & 0xff;
2402  sli4->mac_addr[4] = (dword[4] >> 16) & 0xff;
2403  sli4->mac_addr[5] = (dword[4] >> 24) & 0xff;
2404 
2405  ocs_log_debug(sli4->os, "EEPROM MAC Addr %02x:%02x:%02x:%02x:%02x:%02x\n",
2406  sli4->mac_addr[0],
2407  sli4->mac_addr[1],
2408  sli4->mac_addr[2],
2409  sli4->mac_addr[3],
2410  sli4->mac_addr[4],
2411  sli4->mac_addr[5]);
2412  break;
2413  }
2414  dword += desc_len / 4;
2415  }
2416  } else {
2417  ocs_log_err(sli4->os, "bad GET_FUNCTION_CONFIG write\n");
2418  return -1;
2419  }
2420  } else {
2422  /* Note: No offset of sizeof(sli4_mqe_hdr_t) because we used a DMA buffer */
2423  sli4_res_hdr_t *hdr = sli4->vpd.data.virt;
2424  uint32_t *dword = sli4->vpd.data.virt;
2425 
2426  if (sli_bmbx_command(sli4)) {
2427  ocs_log_crit(sli4->os, "bootstrap mailbox write fail (GET_BE_CONFIG)\n");
2428  return -1;
2429  }
2430  if (hdr->status) {
2431  ocs_log_err(sli4->os, "GET_BE_CONFIG bad status %#x\n",
2432  hdr->status);
2433  return -1;
2434  }
2435 
2436  /*
2437  * parse the results looking for the iSCSI descriptor.
2438  *
2439  * Note: Each descriptor is fixed at 64 bytes (16 dwords) + resource
2440  * type
2441  */
2442  desc_cnt = dword[4];
2443  for (indx = 0; indx < desc_cnt; indx++) {
2444  if (dword[5 + (17 * indx)] == 0x2 &&
2445  (dword[6 + (17 * indx)] & 0xff) == sli4->pf_num) {
2446  /* This is the iSCSI descriptor */
2447  sli4->mac_addr[0] = (dword[9 + (17 * indx)] >> 16) & 0xff;
2448  sli4->mac_addr[1] = (dword[9 + (17 * indx)] >> 24) & 0xff;
2449  sli4->mac_addr[2] = dword[10 + (17 * indx)] & 0xff;
2450  sli4->mac_addr[3] = (dword[10 + (17 * indx)] >> 8) & 0xff;
2451  sli4->mac_addr[4] = (dword[10 + (17 * indx)] >> 16) & 0xff;
2452  sli4->mac_addr[5] = (dword[10 + (17 * indx)] >> 24) & 0xff;
2453 
2454  ocs_log_debug(sli4->os, "EEPROM MAC Addr %02x:%02x:%02x:%02x:%02x:%02x\n",
2455  sli4->mac_addr[0],
2456  sli4->mac_addr[1],
2457  sli4->mac_addr[2],
2458  sli4->mac_addr[3],
2459  sli4->mac_addr[4],
2460  sli4->mac_addr[5]);
2461  break;
2462  }
2463  }
2464  ocs_memset(sli4->vpd.data.virt, 0, sli4->vpd.data.size);
2465  } else {
2466  ocs_log_err(sli4->os, "bad GET_BE_CONFIG write\n");
2467  return -1;
2468  }
2469  }
2470  return 0;
2471 }
2472 
2473 
2474 /**
2475  * @brief Retrieve all of the defines interface IDs and store the default
2476  * interface.
2477  *
2478  * @param sli4 SLI context.
2479  *
2480  * @return Returns 0 success, non-zero otherwise.
2481  */
2482 static int32_t
2484 {
2486 
2487  get_all_if = (sli4_res_iscsi_ntwk_get_all_if_id_t *)
2488  (((uint8_t *)sli4->bmbx.virt) + sizeof(sli4_mqe_hdr_t));
2489 
2490  /* Get all the interface IDs */
2491  if (sli_cmd_iscsi_common_get_all_if_id(sli4, sli4->bmbx.virt,
2492  SLI4_BMBX_SIZE, 0)) {
2493  if (sli_bmbx_command(sli4)) {
2494  ocs_log_crit(sli4->os, "bootstrap mailbox write fail (GET_ALL_IF_ID)\n");
2495  return -1;
2496  }
2497  if (get_all_if->hdr.status) {
2498  ocs_log_err(sli4->os, "GET_ALL_IF_ID bad status %#x\n",
2499  get_all_if->hdr.status);
2500  return -1;
2501  }
2502 
2503  if (get_all_if->iface_count > 0) {
2504  sli4->iface_default = get_all_if->iface[0];
2505  ocs_log_debug(sli4->os, "Default interface handle %d\n", sli4->iface_default);
2506  }
2507  } else {
2508  ocs_log_err(sli4->os, "bad GET_IF_ID call\n");
2509  sli_teardown(sli4);
2510  return -1;
2511  }
2512  return 0;
2513 }
2514 
2515 
2516 /****************************************************************************
2517  * Public functions
2518  */
2519 
2520 /**
2521  * @ingroup sli
2522  * @brief Setup the SLI context.
2523  *
2524  * @param sli4 SLI context.
2525  * @param os Device abstraction.
2526  * @param port_type Protocol type of port (e.g. FC, NIC, ...).
2527  *
2528  * @return Returns 0 on success, or non-zero otherwise.
2529  */
2530 int32_t
2531 sli_setup(sli4_t *sli4, ocs_os_handle_t os, sli4_port_type_e port_type)
2532 {
2533  uint32_t sli_intf = UINT32_MAX;
2534  uint32_t sli_asic_id;
2535  uint8_t revision;
2536  uint8_t generation;
2537  uint32_t pci_class_rev = 0;
2538  uint32_t rev_id = 0;
2539  uint32_t family = 0;
2540  uint32_t i;
2541  sli4_asic_entry_t *asic;
2542 
2543  ocs_memset(sli4, 0, sizeof(sli4_t));
2544 
2545  sli4->os = os;
2546  sli4->port_type = port_type;
2547  sli4->config.bmbx_timeout_msecs = 3000; /* 3 sec default */
2548 
2549  /*
2550  * Read the SLI_INTF register to discover the register layout
2551  * and other capability information
2552  */
2553  sli_intf = ocs_config_read32(os, SLI4_INTF_REG);
2554 
2555  if (sli_intf_valid_check(sli_intf)) {
2556  ocs_log_err(os, "SLI_INTF is not valid\n");
2557  return -1;
2558  }
2559 
2560  /* driver only support SLI-4 */
2561  sli4->sli_rev = sli_intf_sli_revision(sli_intf);
2562  if (4 != sli4->sli_rev) {
2563  ocs_log_err(os, "Unsupported SLI revision (intf=%#x)\n",
2564  sli_intf);
2565  return -1;
2566  }
2567 
2568  sli4->sli_family = sli_intf_sli_family(sli_intf);
2569  sli4->if_type = sli_intf_if_type(sli_intf);
2570 
2571  /*
2572  * set the ASIC type and revision
2573  */
2574  pci_class_rev = ocs_config_read32(os, SLI4_PCI_CLASS_REVISION);
2575  rev_id = sli_pci_rev_id(pci_class_rev);
2576  family = sli4->sli_family;
2577  if (family == 0xf) {
2578  uint32_t asic_id = ocs_config_read32(os, SLI4_ASIC_ID_REG);
2579  family = sli_asic_gen(asic_id);
2580  }
2581 
2582  for (i = 0, asic = sli4_asic_table; i < ARRAY_SIZE(sli4_asic_table); i++, asic++) {
2583  if ((rev_id == asic->rev_id) && (family == asic->family)) {
2584  sli4->asic_type = asic->type;
2585  sli4->asic_rev = asic->rev;
2586  }
2587  }
2588  /* Fail if no matching asic type/rev was found */
2589  if( (sli4->asic_type == 0) || (sli4->asic_rev == 0)) {
2590  ocs_log_err(os, "no matching asic type/rev found\n");
2591  return -1;
2592  }
2593 
2594  /* Use the family to determine if this is a BE3 or a skyhawk */
2595  ocs_log_debug(sli4->os, "SLI if_type = 0x%x, Family 0x%x\n",
2596  sli4->if_type, sli4->sli_family);
2599 
2600  if (sli4->sli_family == 0xf) {
2601  sli_asic_id = ocs_config_read32(os, SLI4_ASIC_ID_REG);
2602  revision = sli_asic_revision(sli_asic_id);
2603  generation = sli_asic_gen(sli_asic_id);
2604 
2605  ocs_log_debug(sli4->os, "SLI ASIC revision = 0x%x, generation 0x%x\n",
2606  revision, generation);
2607 
2608  if (generation == SLI4_ASIC_GEN_BE3) {
2609  ocs_log_debug(os, "Using BE3 message handlers\n");
2610  } else if (generation == SLI4_ASIC_GEN_SKYHAWK) {
2611  ocs_log_debug(os, "Using Skyhawk message handlers\n");
2612  sli4->is_skyhawk = TRUE;
2613  sli4->features.tcp_offload_nrs = TRUE;
2616  } else {
2617  ocs_log_err(os, "Unhandled generation (asic_id=%#x)\n",
2618  sli_asic_id);
2619  return -1;
2620  }
2621  } else if (sli4->sli_family == 0x2) {
2622  ocs_log_debug(os, "Using Skyhawk message handlers\n");
2623  sli4->is_skyhawk = TRUE;
2624  sli4->features.tcp_offload_nrs = TRUE;
2627  } else {
2628  ocs_log_debug(os, "Using BE3 message handlers\n");
2629  }
2630 
2631  /* Configure the number of SGEs and the post_sgl registration version */
2632  sli4->config.num_sges_per_icd = 32;
2633  sli4->config.post_sgl_ver = (sli4->is_skyhawk ? 1 : 0);
2634 
2635  /*
2636  * The bootstrap mailbox is equivalent to a MQ with a single 256 byte
2637  * entry, a CQ with a single 16 byte entry, and no event queue.
2638  * Alignment must be 16 bytes as the low order address bits in the
2639  * address register are also control / status.
2640  */
2641  if (ocs_dma_alloc(sli4->os, &sli4->bmbx, SLI4_BMBX_SIZE +
2642  sizeof(sli4_mcqe_t), 16)) {
2643  ocs_log_err(os, "bootstrap mailbox allocation failed\n");
2644  return -1;
2645  }
2646 
2647  if (sli4->bmbx.phys & SLI4_BMBX_MASK_LO) {
2648  ocs_log_err(os, "bad alignment for bootstrap mailbox\n");
2649  return -1;
2650  }
2651 
2652  ocs_log_debug(os, "bmbx v=%p p=%#lx s=%zd\n", sli4->bmbx.virt, sli4->bmbx.phys,
2653  sli4->bmbx.size);
2654 
2655  // TODO 4096 is arbitrary. What should this value actually be?
2656  if (ocs_dma_alloc(sli4->os, &sli4->vpd.data, 4096/*TODO*/, 4096)) {
2657  /* Note that failure isn't fatal in this specific case */
2658  sli4->vpd.data.size = 0;
2659  ocs_log_test(os, "VPD buffer allocation failed\n");
2660  }
2661 
2662  if (ocs_dma_alloc(sli4->os, &sli4->cntl_attr, sizeof(sli4_res_common_get_cntl_attributes_t), 16)) {
2663  /* Note that failure isn't fatal in this specific case */
2664  sli4->cntl_attr.size = 0;
2665  ocs_log_test(os, "CNTL Attribute buffer allocation failed\n");
2666  }
2667 
2668  if (sli_fw_init(sli4)) {
2669  ocs_log_err(sli4->os, "FW initialization failed\n");
2670  sli_teardown(sli4);
2671  return -1;
2672  }
2673 
2674  if (sli_get_fw_version(sli4)) {
2675  ocs_log_err(sli4->os, "get FW version failed\n");
2676  sli_teardown(sli4);
2677  return -1;
2678  }
2679 
2680  if (sli4->get_sli4_parameters(sli4)) {
2681  ocs_log_err(sli4->os, "get SLI4 parameters failed\n");
2682  sli_teardown(sli4);
2683  return -1;
2684  }
2685 
2686  if (sli_query_fw_config(sli4)) {
2687  ocs_log_err(sli4->os, "FW config failed\n");
2688  sli_teardown(sli4);
2689  return -1;
2690  }
2691 
2692  if (sli_read_transceiver_data(sli4)) {
2693  ocs_log_test(sli4->os, "Read transceiver data failed\n");
2694  // Don't fail the setup if we can't read transceiver data
2695 
2696  }
2697 
2698  if (sli_get_all_if_ids(sli4)) {
2699  ocs_log_err(sli4->os, "Get IF Ids/Info failed\n");
2700  sli_teardown(sli4);
2701  return -1;
2702  }
2703 
2704  if (sli_cmd_common_get_cntl_attributes(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
2705  sli4_res_common_get_cntl_attributes_t *get_cntl = sli4->cntl_attr.virt;
2706 
2707  if (sli_bmbx_command(sli4)) {
2708  ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_CNTL_ATTRIBUTES)\n");
2709  sli_teardown(sli4);
2710  return -1;
2711  }
2712  if (get_cntl->hdr.status) {
2713  ocs_log_err(sli4->os, "COMMON_GET_CNTL_ATTRIBUTES bad status %#x\n",
2714  get_cntl->hdr.status);
2715  sli_teardown(sli4);
2716  return -1;
2717  }
2718 
2719  sli4->pf_num = get_cntl->pci_function_number;
2720 
2721  ocs_memcpy(sli4->config.fw_version,
2722  get_cntl->firmware_version_string,
2723  32);
2724  ocs_memcpy(sli4->config.fw_on_flash_version,
2725  get_cntl->fw_on_flash_version_string,
2726  32);
2727 
2728  ocs_memcpy(sli4->config.modeldesc, get_cntl->controller_description, sizeof(sli4->config.modeldesc));
2729 
2730  ocs_log_debug(sli4->os, "FW1:%s (pf_num %d) \n",
2731  (char*)sli4->config.fw_version,
2732  sli4->pf_num);
2733 
2734  ocs_log_debug(sli4->os, "HW1: Device id %08x, rev %08x\n",
2735  get_cntl->pci_device_id,
2736  get_cntl->asic_revision);
2737  } else {
2738  ocs_log_err(sli4->os, "bad COMMON_GET_CNTL_ATTRIBUTES write\n");
2739  sli_teardown(sli4);
2740  return -1;
2741  }
2742 
2744  sli4_res_common_get_cntl_addl_attributes_t *get_cntl_addl = sli4->cntl_attr.virt;
2745 
2746  if (sli_bmbx_command(sli4)) {
2747  ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_CNTL_ADDL_ATTRIBUTES)\n");
2748  sli_teardown(sli4);
2749  return -1;
2750  }
2751  if (get_cntl_addl->hdr.status) {
2752  ocs_log_err(sli4->os, "COMMON_GET_CNTL_ADDL_ATTRIBUTES bad status %#x\n",
2753  get_cntl_addl->hdr.status);
2754  sli_teardown(sli4);
2755  return -1;
2756  }
2757 
2758  ocs_memcpy(sli4->config.ipl_name, get_cntl_addl->ipl_file_name, sizeof(sli4->config.ipl_name));
2759 
2760  ocs_log_debug(sli4->os, "IPL:%s (pf_num %d) \n",
2761  (char*)sli4->config.ipl_name,
2762  sli4->pf_num);
2763 
2764  } else {
2765  ocs_log_err(sli4->os, "bad COMMON_GET_CNTL_ADDL_ATTRIBUTES write\n");
2766  sli_teardown(sli4);
2767  return -1;
2768  }
2769 
2770  /* must be before call to sli_cmd_get_vpd_data() since sli4->vpd is "borrowed" */
2771  if (sli_query_fw_mac_addr(sli4)) {
2772  ocs_log_test(sli4->os, "Failed to read EEPROM MAC address\n");
2773  }
2774 
2775  if (sli_cmd_get_vpd_data(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
2776  /* Note: No offset of sizeof(sli4_mqe_hdr_t) because we used a DMA buffer */
2777  sli4_res_hdr_t *rsp_hdr = sli4->vpd.data.virt;
2778 
2779  if (sli_bmbx_command(sli4)) {
2780  ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_NVPARMS)\n");
2781  sli_teardown(sli4);
2782  return -1;
2783  }
2784  if (rsp_hdr->status) {
2785  ocs_log_err(sli4->os, "COMMON_GET_VPD bad status %#x\n",
2786  rsp_hdr->status);
2787  sli_teardown(sli4);
2788  return -1;
2789  }
2790  /* save the response length */
2791  sli4->vpd.length = rsp_hdr->response_length;
2792 
2793  } else {
2794  ocs_log_err(sli4->os, "bad COMMON_GET_VPD_DATA call\n");
2795  sli_teardown(sli4);
2796  return -1;
2797  }
2798 
2799  return 0;
2800 }
2801 
2802 int32_t
2804 {
2805  return 0;
2806 }
2807 
2808 int32_t
2810 {
2811  if (sli_fw_init(sli4)) {
2812  ocs_log_crit(sli4->os, "FW initialization failed\n");
2813  return -1;
2814  }
2815 
2816  ocs_memset(&sli4->config, 0, sizeof(sli4->config));
2817 
2818  return 0;
2819 }
2820 
2821 int32_t
2823 {
2824  uint32_t val;
2825  uint32_t iter = 3000;
2826  uint32_t not_ready = TRUE;
2827 
2828 
2829  /* BE3 / Skyhawk use PCICFG_SOFT_RESET_CSR */
2830  val = ocs_config_read32(sli4->os, SLI4_PCI_SOFT_RESET_CSR);
2831  val |= SLI4_PCI_SOFT_RESET_MASK;
2832  ocs_config_write32(sli4->os, SLI4_PCI_SOFT_RESET_CSR, val);
2833 
2834  do {
2835  ocs_delay_usec(10000); // 10 ms
2837  iter--;
2839  SLI4_PORT_SEMAPHORE_PORT(val)) &&
2841  } while (not_ready && (iter > 0));
2842 
2843 
2844 
2845  if (not_ready) {
2846  ocs_log_crit(sli4->os, "Failed to become ready after firmware reset\n");
2847  return -1;
2848  } else {
2849  return 0;
2850  }
2851 
2852 }
2853 
2854 
2855 
2856 /**
2857  * @ingroup sli
2858  * @brief Tear down a SLI context.
2859  *
2860  * @param sli4 SLI context.
2861  *
2862  * @return Returns 0 on success, or non-zero otherwise.
2863  */
2864 int32_t
2866 {
2867  uint32_t i;
2868 
2869  if (sli_fw_term(sli4)) {
2870  ocs_log_crit(sli4->os, "FW deinitialization failed\n");
2871  }
2872 
2873  if (sli4->num_sgl_pages > 0) {
2874  for (i = 0; i < sli4->num_sgl_pages; i++) {
2875  ocs_dma_free(sli4->os, &sli4->sgl_pages[i]);
2876  ocs_memset(&sli4->sgl_pages[i], 0, sizeof(ocs_dma_t));
2877  }
2878  ocs_free(sli4->os, sli4->sgl_pages, sizeof(ocs_dma_t) * sli4->num_sgl_pages);
2879  }
2880 
2881  ocs_dma_free(sli4->os, &sli4->vpd.data);
2882  ocs_memset(&sli4->vpd.data, 0, sizeof(ocs_dma_t));
2883 
2884  ocs_dma_free(sli4->os, &sli4->cntl_attr);
2885  ocs_memset(&sli4->cntl_attr, 0, sizeof(ocs_dma_t));
2886 
2887  ocs_dma_free(sli4->os, &sli4->bmbx);
2888  ocs_memset(&sli4->bmbx, 0, sizeof(ocs_dma_t));
2889 
2890  return 0;
2891 }
2892 
2893 /**
2894  * @ingroup sli
2895  * @brief Register a callback for the given event.
2896  *
2897  * @param sli4 SLI context.
2898  * @param which Event of interest.
2899  * @param func Function to call when the event occurs.
2900  * @param arg Argument passed to the callback function.
2901  *
2902  * @return Returns 0 on success, or non-zero otherwise.
2903  */
2904 int32_t
2905 sli_callback(sli4_t *sli4, sli4_callback_e which, void *func, void *arg)
2906 {
2907 
2908  if (!sli4 || !func || (which >= SLI4_CB_MAX)) {
2909  ocs_log_err(NULL, "bad parameter sli4=%p which=%#x func=%p\n",
2910  sli4, which, func);
2911  return -1;
2912  }
2913 
2914  switch (which) {
2915  case SLI4_CB_LINK:
2916  sli4->link = func;
2917  sli4->link_arg = arg;
2918  break;
2919  case SLI4_CB_ISCSI_ASYNC:
2920  sli4->iscsi_async = func;
2921  sli4->iscsi_async_arg = arg;
2922  break;
2923  default:
2924  ocs_log_test(sli4->os, "unknown callback %#x\n", which);
2925  return -1;
2926  }
2927 
2928  return 0;
2929 }
2930 
2931 /**
2932  * @ingroup sli
2933  * @brief Initialize a queue object.
2934  *
2935  * @par Description
2936  * This initializes the sli4_queue_t object members including the underlying
2937  * DMA memory.
2938  *
2939  * @param sli4 SLI context.
2940  * @param q Pointer to queue object.
2941  * @param qtype Type of queue to create.
2942  * @param version Queue version (e.g. V0, V1, ...).
2943  * @param size Size of each entry.
2944  * @param n_entries Number of entries to allocate.
2945  * @param align Starting memory address alignment.
2946  *
2947  * @note Checks to see if using the existing DMA memory (if any) is possible. If not,
2948  * frees existing memory an reallocates.
2949  *
2950  * @return Returns 0 on success, non-zero otherwise
2951  */
2952 int32_t
2953 __sli_queue_init(sli4_t *sli4, sli4_queue_t *q, uint32_t qtype, uint32_t version,
2954  size_t size, uint32_t n_entries, uint32_t align)
2955 {
2956 
2957  if ((size != q->size) || (n_entries != q->length)) {
2958  if (q->dma.size) {
2959  ocs_dma_free(sli4->os, &q->dma);
2960  ocs_memset(&q->dma, 0, sizeof(ocs_dma_t));
2961  }
2962 
2963  ocs_memset(q, 0, sizeof(sli4_queue_t));
2964 
2965  if (ocs_dma_alloc(sli4->os, &q->dma, size * n_entries, align)) {
2966  ocs_log_err(sli4->os, "%s allocation failed\n", SLI_QNAME[qtype]);
2967  return -1;
2968  }
2969 
2970  ocs_memset(q->dma.virt, 0, size * n_entries);
2971 
2972  ocs_lock_init(sli4->os, &q->lock, "%s lock[%d]", SLI_QNAME[qtype], ocs_instance(sli4->os));
2973 
2974  q->type = qtype;
2975  q->size = size;
2976  q->length = n_entries;
2977  q->version = version;
2978  q->proc_limit = n_entries / 2; /* Limit to half the queue size per interrupt */
2979 
2980  switch(q->type) {
2981  case SLI_QTYPE_EQ:
2982  q->posted_limit = q->length / 2;
2983  break;
2984  default:
2985  if ((sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) ||
2986  (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_VF)) {
2987  /* For Skyhawk, ring the doorbell more often */
2988  q->posted_limit = 8;
2989  } else {
2990  q->posted_limit = 64;
2991  }
2992  break;
2993  }
2994  }
2995 
2996  return 0;
2997 }
2998 
2999 /**
3000  * @ingroup sli
3001  * @brief Issue command to create queue.
3002  *
3003  * @param sli4 SLI context.
3004  * @param q Pointer to queue object.
3005  *
3006  * @return Returns 0 on success, or non-zero otherwise.
3007  */
3008 int32_t
3010 {
3011  sli4_res_common_create_queue_t *res_q = NULL;
3012  char queue_name[3] = "XX";
3013 
3014  if (sli_bmbx_command(sli4)){
3015  ocs_log_crit(sli4->os, "bootstrap mailbox write fail %s\n",
3016  SLI_QNAME[q->type]);
3017  ocs_dma_free(sli4->os, &q->dma);
3018  ocs_memset(&q->dma, 0, sizeof(ocs_dma_t));
3019  return -1;
3020  }
3021  res_q = (void *)((uint8_t *)sli4->bmbx.virt + sizeof(sli4_mqe_hdr_t));
3022 
3023  if (res_q->hdr.status) {
3024  ocs_log_err(sli4->os, "bad create %s status=%#x addl=%#x\n",
3025  SLI_QNAME[q->type],
3026  res_q->hdr.status, res_q->hdr.additional_status);
3027  ocs_dma_free(sli4->os, &q->dma);
3028  ocs_memset(&q->dma, 0, sizeof(ocs_dma_t));
3029  return -1;
3030  } else {
3031  q->id = res_q->q_id;
3032  q->doorbell_offset = res_q->db_offset;
3033  q->doorbell_rset = res_q->db_rs;
3034 
3035  switch (q->type) {
3036  case SLI_QTYPE_EQ:
3037  ocs_memcpy(queue_name, "EQ", 3);
3038 
3039  /* No doorbell information in response for EQs */
3040  q->doorbell_offset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].off;
3041  q->doorbell_rset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].rset;
3042  break;
3043  case SLI_QTYPE_CQ:
3044  ocs_memcpy(queue_name, "CQ", 3);
3045 
3046  /* No doorbell information in response for CQs */
3047  q->doorbell_offset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].off;
3048  q->doorbell_rset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].rset;
3049  break;
3050  case SLI_QTYPE_MQ:
3051  ocs_memcpy(queue_name, "MQ", 3);
3052 
3053  /* No doorbell information in response for MQs */
3054  q->doorbell_offset = regmap[SLI4_REG_MQ_DOORBELL][sli4->if_type].off;
3055  q->doorbell_rset = regmap[SLI4_REG_MQ_DOORBELL][sli4->if_type].rset;
3056  break;
3057  case SLI_QTYPE_RQ:
3058  ocs_memcpy(queue_name, "RQ", 3);
3059 
3060  /* set the doorbell for non-skyhawks */
3061  if (!sli4->features.dual_ulp_capable) {
3064  }
3065  break;
3066  case SLI_QTYPE_WQ:
3067  ocs_memcpy(queue_name, "WQ", 3);
3068 
3069  /* set the doorbell for non-skyhawks */
3070  if (!sli4->features.dual_ulp_capable) {
3071  q->doorbell_offset = regmap[SLI4_REG_IO_WQ_DOORBELL][sli4->if_type].off;
3072  q->doorbell_rset = regmap[SLI4_REG_IO_WQ_DOORBELL][sli4->if_type].rset;
3073  }
3074  break;
3075  default:
3076  break;
3077  }
3078 
3079  snprintf(q->name, sizeof(q->name), "%s-%d", queue_name, q->id);
3080  }
3081 
3082  return 0;
3083 }
3084 
3085 /**
3086  * @ingroup sli
3087  * @brief Modify the delay timer for all the EQs
3088  *
3089  * @param sli4 SLI context.
3090  * @param eq Array of EQs.
3091  * @param num_eq Count of EQs.
3092  * @param shift Phase shift for staggering interrupts.
3093  * @param delay_mult Delay multiplier for limiting interrupt frequency.
3094  *
3095  * @return Returns 0 on success, or -1 otherwise.
3096  */
3097 int32_t
3098 sli_eq_modify_delay(sli4_t *sli4, sli4_queue_t *eq, uint32_t num_eq, uint32_t shift, uint32_t delay_mult)
3099 {
3100 
3101  sli4_res_hdr_t *hdr;
3102  sli_cmd_common_modify_eq_delay(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, eq, num_eq, shift, delay_mult);
3103 
3104  if (sli_bmbx_command(sli4)) {
3105  ocs_log_crit(sli4->os, "bootstrap mailbox write fail (MODIFY EQ DELAY)\n");
3106  return -1;
3107  }
3108  hdr = (sli4_res_hdr_t *)
3109  (((uint8_t *)sli4->bmbx.virt) + sizeof(sli4_mqe_hdr_t));
3110  if (hdr->status) {
3111  ocs_log_test(NULL, "bad status MODIFY EQ DELAY\n");
3112  return -1;
3113  }
3114 
3115  return 0;
3116 }
3117 
3118 /**
3119  * @ingroup sli
3120  * @brief Allocate a queue.
3121  *
3122  * @par Description
3123  * Allocates DMA memory and configures the requested queue type.
3124  *
3125  * @param sli4 SLI context.
3126  * @param qtype Type of queue to create.
3127  * @param q Pointer to queue object.
3128  * @param n_entries Number of entries to allocate.
3129  * @param assoc Associated queue (e.g. the EQ for a CQ, the CQ for a MQ, ...).
3130  * @param ulp ULP to bind, which is only used for WQ and RQs.
3131  *
3132  * @return Returns 0 on success, -1 otherwise
3133  */
3134 int32_t
3135 sli_queue_alloc(sli4_t *sli4, uint32_t qtype, sli4_queue_t *q, uint32_t n_entries,
3136  sli4_queue_t *assoc, uint16_t ulp)
3137 {
3138  uint32_t size = 0;
3139  uint32_t align = 0;
3140  uint32_t version = 0;
3141  sli4_create_q_fn_t create = NULL;
3142 
3143  if (!sli4 || !q) {
3144  ocs_log_err(NULL, "bad parameter sli4=%p q=%p\n", sli4, q);
3145  return -1;
3146  }
3147 
3148  switch (qtype) {
3149  case SLI_QTYPE_EQ:
3150  size = sizeof(uint32_t);
3151  align = 4096;
3152  create = sli_cmd_common_create_eq;
3153  break;
3154  case SLI_QTYPE_CQ:
3155  size = 16;
3156  align = 4096;
3157  create = sli_cmd_common_create_cq;
3158  break;
3159  case SLI_QTYPE_MQ:
3160  /* Validate the number of entries */
3161  switch (n_entries) {
3162  case 16:
3163  case 32:
3164  case 64:
3165  case 128:
3166  break;
3167  default:
3168  ocs_log_err(sli4->os, "illegal n_entries value %d for MQ\n", n_entries);
3169  return -1;
3170  }
3171  assoc->u.flag.is_mq = TRUE;
3172  size = 256;
3173  align = 4096;
3175  break;
3176  case SLI_QTYPE_WQ:
3177  size = 64;
3178  align = 4096;
3179  create = sli_cmd_iscsi_wq_create;
3180  break;
3181  default:
3182  ocs_log_err(sli4->os, "unknown queue type %d\n", qtype);
3183  return -1;
3184  }
3185 
3186  if (__sli_queue_init(sli4, q, qtype, version, size, n_entries, align)) {
3187  ocs_log_err(sli4->os, "%s allocation failed\n", SLI_QNAME[qtype]);
3188  return -1;
3189  }
3190 
3191  if (create(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 0, &q->dma,
3192  assoc ? assoc->id : 0, ulp)) {
3193  if (__sli_create_queue(sli4, q)) {
3194  ocs_log_err(sli4->os, "create %s failed\n", SLI_QNAME[qtype]);
3195  return -1;
3196  }
3197  q->ulp = ulp;
3198  } else {
3199  ocs_log_err(sli4->os, "cannot create %s\n", SLI_QNAME[qtype]);
3200  return -1;
3201  }
3202  return 0;
3203 }
3204 
3205 /**
3206  * @ingroup sli
3207  * @brief Free a queue.
3208  *
3209  * @par
3210  * Frees DMA memory and de-registers the requested queue.
3211  *
3212  * @param sli4 SLI context.
3213  * @param q Pointer to queue object.
3214  *
3215  * @return Returns 0 on success, or -1 otherwise.
3216  */
3217 int32_t
3219 {
3220  sli4_destroy_q_fn_t destroy = NULL;
3221  int32_t rc = -1;
3222 
3223  if (!sli4 || !q) {
3224  ocs_log_err(NULL, "bad parameter sli4=%p q=%p\n", sli4, q);
3225  return -1;
3226  }
3227 
3228  switch (q->type) {
3229  case SLI_QTYPE_EQ:
3230  destroy = sli_cmd_common_destroy_eq;
3231  break;
3232  case SLI_QTYPE_CQ:
3233  destroy = sli_cmd_common_destroy_cq;
3234  break;
3235  case SLI_QTYPE_MQ:
3236  destroy = sli_cmd_common_destroy_mq;
3237  break;
3238  case SLI_QTYPE_WQ:
3239  destroy = sli_cmd_iscsi_wq_destroy;
3240  break;
3241  case SLI_QTYPE_RQ:
3242  destroy = sli_cmd_iscsi_defq_destroy;
3243  break;
3244  default:
3245  ocs_log_test(sli4->os, "bad queue type %d\n",
3246  q->type);
3247  return -1;
3248  }
3249 
3250  if (sli_fw_error_status(sli4) == 0) {
3251  // Destroy the queue if the operation is defined
3252  if (destroy && destroy(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 0, q->id)) {
3253  sli4_res_hdr_t *res = NULL;
3254 
3255  if (sli_bmbx_command(sli4)){
3256  ocs_log_crit(sli4->os, "bootstrap mailbox write fail destroy %s\n",
3257  SLI_QNAME[q->type]);
3258  } else {
3259  res = (void *)((uint8_t *)sli4->bmbx.virt + sizeof(sli4_mqe_hdr_t));
3260 
3261  if (res->status) {
3262  ocs_log_test(sli4->os, "bad destroy %s status=%#x addl=%#x\n",
3263  SLI_QNAME[q->type],
3264  res->status, res->additional_status);
3265  } else {
3266  rc = 0;
3267  }
3268  }
3269  }
3270  }
3271 
3272  ocs_lock_free(&q->lock);
3273 
3274  if (ocs_dma_free(sli4->os, &q->dma)) {
3275  ocs_log_test(sli4->os, "%s queue ID %d free failed\n", SLI_QNAME[q->type], q->id);
3276  rc = -1;
3277  }
3278  ocs_memset(&q->dma, 0, sizeof(ocs_dma_t));
3279 
3280  return rc;
3281 }
3282 
3283 
3284 /**
3285  * @ingroup sli
3286  * @brief Zero all queue entries and reset the indexes.
3287  *
3288  * @param sli4 SLI context.
3289  * @param q Pointer to queue object.
3290  *
3291  * @return Returns 0 if successful.
3292  */
3293 int32_t
3295 {
3296 
3297  ocs_lock(&q->lock);
3298 
3299  q->index = 0;
3300  q->n_posted = 0;
3301  q->cxn_cnt = 0;
3302 
3303  if (SLI_QTYPE_MQ == q->type) {
3304  q->u.r_idx = 0;
3305  }
3306 
3307  ocs_memset(q->dma.virt, 0, (q->size * (uint64_t)q->length));
3308 
3309  ocs_unlock(&q->lock);
3310 
3311  return 0;
3312 }
3313 
3314 /**
3315  * @ingroup sli
3316  * @brief Check if the given queue is empty.
3317  *
3318  * @par Description
3319  * If the valid bit of the current entry is unset, the queue is empty.
3320  *
3321  * @param sli4 SLI context.
3322  * @param q Pointer to queue object.
3323  *
3324  * @return Returns TRUE if empty, or FALSE otherwise.
3325  */
3326 int32_t
3328 {
3329  int32_t rc = TRUE;
3330  uint8_t *qe = q->dma.virt;
3331 
3332  ocs_lock(&q->lock);
3333 
3334  ocs_dma_sync(&q->dma, OCS_DMASYNC_POSTREAD);
3335 
3336  qe += q->index * q->size;
3337 
3338  rc = !sli_queue_entry_is_valid(q, qe, FALSE);
3339 
3340  ocs_unlock(&q->lock);
3341 
3342  return rc;
3343 }
3344 
3345 /**
3346  * @ingroup sli
3347  * @brief Arm or dis-arm a queue.
3348  *
3349  * @param sli4 SLI context.
3350  * @param q Pointer to queue object.
3351  * @param arm If TRUE, arm the queue.
3352  *
3353  * @return Returns 0 on success, or non-zero otherwise.
3354  */
3355 int32_t
3356 sli_queue_arm(sli4_t *sli4, sli4_queue_t *q, uint8_t arm)
3357 {
3358  uint32_t val = 0;
3359 
3360  ocs_lock(&q->lock);
3361 
3362  switch (q->type) {
3363  case SLI_QTYPE_EQ:
3364  val = sli_eq_doorbell(q->n_posted, q->id, arm);
3365  ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
3366  q->n_posted = 0;
3367  break;
3368  case SLI_QTYPE_CQ:
3369  val = sli_cq_doorbell(q->n_posted, q->id, arm);
3370  ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
3371  q->n_posted = 0;
3372  break;
3373  default:
3374  ocs_log_test(sli4->os, "should only be used for EQ/CQ, not %s\n",
3375  SLI_QNAME[q->type]);
3376  }
3377 
3378  ocs_unlock(&q->lock);
3379 
3380  return 0;
3381 }
3382 
3383 /**
3384  * @ingroup sli
3385  * @brief Write an entry to the queue object
3386  *
3387  * @par Description
3388  * @b Note: Assumes the q->lock will be locked and released by the caller.
3389  *
3390  * @param sli4 SLI context.
3391  * @param q Pointer to queue object.
3392  * @param entry Pointer to entry contents.
3393  *
3394  * @return Returns queue index on success, or a negative error otherwise.
3395  */
3396 int32_t
3397 _sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
3398 {
3399  int32_t rc = 0;
3400  uint8_t *qe = q->dma.virt;
3401  int32_t qindex;
3402 #if defined(OCS_INCLUDE_DEBUG)
3403  char desc[32];
3404 #endif
3405 
3406  qindex = q->index;
3407  qe += q->index * q->size;
3408 
3409  if (entry) {
3410 #if defined(OCS_INCLUDE_DEBUG)
3411  switch(q->type) {
3412  case SLI_QTYPE_WQ:
3413  snprintf(desc, sizeof(desc), "%s entry %d", q->name, q->index);
3414  ocs_dump32(OCS_DEBUG_ENABLE_WQ_DUMP, sli4->os, desc, entry, q->size);
3415  break;
3416 
3417  case SLI_QTYPE_MQ:
3418  {
3419  sli4_mqe_hdr_t *hdr = (sli4_mqe_hdr_t *)entry;
3420 
3421  snprintf(desc, sizeof(desc), "mqe outbound entry %d", q->index);
3423  sli4->os,
3424  desc,
3425  entry,
3426  hdr->payload_length + sizeof(sli4_mqe_hdr_t));
3427  }
3428  break;
3429 
3430  default:
3431  break;
3432  }
3433 #endif
3434  ocs_memcpy(qe, entry, q->size);
3435  q->n_posted = 1;
3436  }
3437 
3438  ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
3439 
3440  rc = sli_queue_doorbell(sli4, q);
3441 
3442  q->index = (q->index + q->n_posted) & (q->length - 1);
3443  q->n_posted = 0;
3444 
3445  if (rc < 0) {
3446  /* failure */
3447  return rc;
3448  } else if (rc > 0) {
3449  /* failure - but we need to return a negative value on failure */
3450  return -rc;
3451  } else {
3452  /* success */
3453  return qindex;
3454  }
3455 }
3456 
3457 
3458 /**
3459  * @ingroup sli
3460  * @brief Write an entry to the queue object.
3461  *
3462  * @param sli4 SLI context.
3463  * @param q Pointer to queue object.
3464  * @param entry Pointer to entry contents.
3465  *
3466  * @return Returns queue index on success, or negative error otherwise.
3467  */
3468 int32_t
3469 sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
3470 {
3471  int32_t rc;
3472  ocs_lock(&q->lock);
3473  rc = _sli_queue_write(sli4, q, entry);
3474  ocs_unlock(&q->lock);
3475  return rc;
3476 }
3477 
3478 /**
3479  * @ingroup sli
3480  * @brief Processes a solicited IO completion. Moves the WRB to the free list.
3481  *
3482  * @param sli4 SLI context.
3483  * @param q Pointer to queue object.
3484  * @param wqe_index The wqe index that completed.
3485  *
3486  * @return Returns pointer to the IO or NULL if not found.
3487  */
3488 void*
3489 sli_queue_iscsi_wqe_complete(sli4_t *sli4, sli4_queue_t *q, uint8_t wqe_index)
3490 {
3491  void *rval = NULL;
3492  sli4_wqe_context_t *ctx;
3493 
3494  ocs_lock(&q->lock);
3495 
3496  if (wqe_index < q->length) {
3497  ctx = &q->u.wq.wqe_context[wqe_index];
3498 
3499  if (ctx->io != NULL) {
3500  ((ocs_hal_io_t*)ctx->io)->wq_ctx = NULL;
3501  }
3502  rval = ctx->io;
3503  ctx->io = NULL;
3504  ocs_list_remove(&q->u.wq.wqe_busy, ctx);
3505  ocs_list_add_tail(&q->u.wq.wqe_free, ctx);
3506  q->u.wq.wqe_free_cnt++;
3507  } else {
3508  ocs_log_test(sli4->os, "WQE index %d is out of range\n", wqe_index);
3509  }
3510  ocs_unlock(&q->lock);
3511  return rval;
3512 }
3513 
3514 
3515 /**
3516  * @ingroup sli
3517  * @brief Processes a TCP ACK completion.
3518  *
3519  * @par Description
3520  * According to the manual, you may not receive a TCP acknowledgement for every
3521  * message, we need to complete every request that was submitted prior to the
3522  * indicated WQE index as well. So loop through the busy list and complete all
3523  * the entries waiting for TCP ACKs up through the index we received.
3524  *
3525  * @param sli4 SLI context.
3526  * @param q Pointer to queue object.
3527  * @param wqe_index The wqe index that ACK'd.
3528  *
3529  * @return Returns 0 on success, or non-zero value otherwise.
3530  */
3531 int32_t
3532 sli_queue_iscsi_tcp_ack(sli4_t *sli4, sli4_queue_t *q, uint8_t wqe_index)
3533 {
3534  sli4_wqe_context_t *ctx;
3535  sli4_wqe_context_t *ctx_next;
3536  ocs_hal_io_t *io;
3537  uint16_t wrb_index;
3538  uint8_t tcp_ack_status;
3539  uint32_t cmpl_cnt = 0;
3540 
3541  ocs_lock(&q->lock);
3542  ctx = ocs_list_get_head(&q->u.wq.wqe_busy);
3543  while (ctx != NULL) {
3544  ctx_next = ocs_list_next(&q->u.wq.wqe_busy, ctx);
3545  if (ctx->wait_tcp_ack) {
3546  cmpl_cnt++;
3547  io = ctx->io;
3548  if (io != NULL) {
3549  io->wq_ctx = NULL;
3550  }
3551 
3552  ctx->io = NULL;
3553  wrb_index = ctx->wrb_index;
3554  tcp_ack_status = ctx->tcp_ack_status;
3555 
3556  ocs_list_remove(&q->u.wq.wqe_busy, ctx);
3557  ocs_list_add_tail(&q->u.wq.wqe_free, ctx);
3558  q->u.wq.wqe_free_cnt++;
3559 
3560  if (NULL != io) {
3561  io_cb_t *done = io->done;
3562  void *arg = io->arg;
3563 
3564  io->done = NULL;
3565  if (NULL != done) {
3566  ocs_unlock(&q->lock);
3567  done(io,
3568  io->node,
3569  tcp_ack_status,
3570  NULL,
3571  arg);
3572  ocs_lock(&q->lock);
3573  }
3574  } else {
3575  ocs_log_test(sli4->os, "IO at index %d for WQ id %d was not found\n",
3576  wrb_index, q->id);
3577  }
3578 
3579  /* Stop once we find the index we are looking for */
3580  if (wrb_index == wqe_index) {
3581  break;
3582  }
3583  }
3584  ctx = ctx_next;
3585  }
3586  ocs_unlock(&q->lock);
3587 
3588  /* We should always have at least one completion */
3589  return (cmpl_cnt > 0);
3590 }
3591 
3592 
3593 /**
3594  * @ingroup sli
3595  * @brief Returns the IO tied to a specific ICD index.
3596  *
3597  * @param sli4 SLI context.
3598  * @param q Pointer to queue object.
3599  * @param icd_index The icd index that completed.
3600  *
3601  * @return Returns pointer to the IO or NULL if not found.
3602  */
3603 void*
3604 sli_queue_iscsi_icd_lookup(sli4_t *sli4, sli4_queue_t *q, uint16_t icd_index)
3605 {
3606  void *rval = NULL;
3607  sli4_wqe_context_t *ctx;
3608  ocs_hal_io_t *io;
3609 
3610  ocs_lock(&q->lock);
3611 
3612  /* This is an error case, so just walk the busy list and find the icd */
3613  ctx = ocs_list_get_head(&q->u.wq.wqe_busy);
3614  while (ctx != NULL) {
3615  io = ctx->io;
3616  if (io != NULL &&
3617  io->icd == icd_index) {
3618  rval = ctx->io;
3619  break;
3620  }
3621  ctx = ocs_list_next(&q->u.wq.wqe_busy, ctx);
3622  }
3623  ocs_unlock(&q->lock);
3624 
3625  if (rval == NULL) {
3626  ocs_log_test(sli4->os, "ICD index %d is not on the WQ %d busy list\n",
3627  icd_index, q->id);
3628  }
3629  return rval;
3630 }
3631 
3632 
3633 
3634 /**
3635  * @ingroup sli
3636  * @brief Processes a target command invalidation IO completion. Moves the WRB
3637  * to the free list.
3638  *
3639  * @param sli4 SLI context.
3640  * @param q Pointer to queue object.
3641  * @param icd_index The icd index that completed.
3642  * @param wait_for_tcp_ack Returns a boolean whether we must wait for a TCP
3643  * acknowledgement before completing the IO. (i.e. the HAL must not
3644  * issue this completion to the caller because it may still be active
3645  * in the FW).
3646  * @param tcp_ack_status The status to send for the IO once the TCP ACK is received.
3647  *
3648  * @return Returns pointer to the IO or NULL if not found.
3649  */
3650 void*
3651 sli_queue_iscsi_icd_invalid(sli4_t *sli4, sli4_queue_t *q, uint16_t icd_index,
3652  uint8_t *wait_for_tcp_ack,
3653  uint8_t tcp_ack_status)
3654 {
3655  void *rval = NULL;
3656  sli4_wqe_context_t *ctx;
3657  ocs_hal_io_t *io;
3658 
3659  ocs_lock(&q->lock);
3660 
3661  *wait_for_tcp_ack = FALSE;
3662  /* This is an error case, so just walk the busy list and find the icd */
3663  ctx = ocs_list_get_head(&q->u.wq.wqe_busy);
3664  while (ctx != NULL) {
3665  io = ctx->io;
3666  if (io != NULL &&
3667  io->icd == icd_index) {
3668  io->wq_ctx = NULL;
3669  rval = ctx->io;
3670  *wait_for_tcp_ack = ctx->wait_tcp_ack;
3671  ctx->tcp_ack_status = tcp_ack_status;
3672 
3673  if (ctx->wait_tcp_ack == 0) {
3674  ctx->io = NULL;
3675  ocs_list_remove(&q->u.wq.wqe_busy, ctx);
3676  ocs_list_add_tail(&q->u.wq.wqe_free, ctx);
3677  q->u.wq.wqe_free_cnt++;
3678  }
3679  break;
3680  }
3681  ctx = ocs_list_next(&q->u.wq.wqe_busy, ctx);
3682  }
3683  ocs_unlock(&q->lock);
3684 
3685  if (rval == NULL) {
3686  ocs_log_test(sli4->os, "ICD index %d is not on the WQ %d busy list\n",
3687  icd_index, q->id);
3688  }
3689  return rval;
3690 }
3691 
3692 /**
3693  * @ingroup sli
3694  * @brief Return the number of free WRB entries.
3695  *
3696  * @param sli4 SLI context.
3697  * @param q Pointer to queue object.
3698  *
3699  * @return Returns number of free WRBs.
3700  */
3701 uint32_t
3703 {
3704  return q->u.wq.wqe_free_cnt;
3705 }
3706 
3707 
3708 /**
3709  * @ingroup sli
3710  * @brief Moves any WQE entries from the busy back to the free list when a
3711  * connection is uploaded.
3712  *
3713  * @param hal Pointer to the HAL context.
3714  * @param sli4 SLI context.
3715  * @param q Pointer to queue object.
3716  */
3717 void
3719 {
3720  sli4_wqe_context_t *ctx;
3721  ocs_hal_io_t *io;
3722  uint16_t wrb_index;
3723 
3724  ocs_lock(&q->lock);
3725 
3726  ctx = ocs_list_get_head(&q->u.wq.wqe_busy);
3727  while (ctx != NULL) {
3728  io = ctx->io;
3729  ctx->io = NULL;
3730  wrb_index = ctx->wrb_index;
3731 
3732  ocs_list_remove(&q->u.wq.wqe_busy, ctx);
3733  ocs_list_add_tail(&q->u.wq.wqe_free, ctx);
3734  q->u.wq.wqe_free_cnt++;
3735  ctx = ocs_list_get_head(&q->u.wq.wqe_busy);
3736  if (NULL != io) {
3737  io_cb_t *done = io->done;
3738  void *arg = io->arg;
3739 
3740  io->done = NULL;
3741  io->wq_ctx = NULL;
3742  if (NULL != done) {
3743  ocs_unlock(&q->lock);
3744  ocs_log_test(sli4->os, "IO HAL type 0x%x with ICD 0x%x active on freed connection at wrb_index %d\n",
3745  io->type, io->icd, wrb_index);
3746 
3747  done(io,
3748  io->node,
3750  NULL,
3751  arg);
3752  ocs_lock(&q->lock);
3753  }
3754  } else {
3755  ocs_log_test(sli4->os, "IO at index %d for WQ id %d was not found\n",
3756  wrb_index, q->id);
3757  }
3758  }
3759  ocs_unlock(&q->lock);
3760 
3761 
3762 }
3763 
3764 
3765 /**
3766  * @brief Check if the current queue entry is valid.
3767  *
3768  * @param q Pointer to queue object.
3769  * @param qe Pointer to queue entry.
3770  * @param clear Boolean to clear valid bit.
3771  *
3772  * @return Returns TRUE if entry is valid, or FALSE otherwise.
3773  */
3774 static uint8_t
3775 sli_queue_entry_is_valid(sli4_queue_t *q, uint8_t *qe, uint8_t clear)
3776 {
3777  uint8_t valid = FALSE;
3778 
3779  switch (q->type) {
3780  case SLI_QTYPE_EQ:
3781  valid = ((sli4_eqe_t *)qe)->vld;
3782  if (valid && clear) {
3783  ((sli4_eqe_t *)qe)->vld = 0;
3784  }
3785  break;
3786  case SLI_QTYPE_CQ:
3787  /*
3788  * For both MCQE and WCQE/RCQE, the valid bit
3789  * is bit 31 of dword 3 (0 based)
3790  */
3791  valid = (qe[15] & 0x80) != 0;
3792  if (valid & clear) {
3793  qe[15] &= ~0x80;
3794  }
3795  break;
3796  case SLI_QTYPE_MQ:
3797  valid = q->index != q->u.r_idx;
3798  break;
3799  case SLI_QTYPE_RQ:
3800  valid = TRUE;
3801  clear = FALSE;
3802  break;
3803  default:
3804  ocs_log_test(NULL, "doesn't handle type=%#x\n", q->type);
3805  }
3806 
3807  if (clear) {
3808  ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
3809  }
3810 
3811  return valid;
3812 }
3813 
3814 /**
3815  * @ingroup sli
3816  * @brief Read an entry from the queue object.
3817  *
3818  * @param sli4 SLI context.
3819  * @param q Pointer to queue object.
3820  * @param entry Destination pointer for queue entry contents.
3821  *
3822  * @return Returns 0 on success, or non-zero otherwise.
3823  */
3824 int32_t
3825 sli_queue_read(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
3826 {
3827  int32_t rc = 0;
3828  uint8_t *qe = q->dma.virt;
3829  uint32_t *qindex = NULL;
3830 #if defined(OCS_INCLUDE_DEBUG)
3831  char desc[32];
3832 #endif
3833 
3834  ocs_lock(&q->lock);
3835 
3836  ocs_dma_sync(&q->dma, OCS_DMASYNC_POSTREAD);
3837 
3838  if (SLI_QTYPE_MQ == q->type) {
3839  qindex = &q->u.r_idx;
3840  } else {
3841  qindex = &q->index;
3842  }
3843 
3844  qe += *qindex * q->size;
3845 
3846  if (!sli_queue_entry_is_valid(q, qe, TRUE)) {
3847  ocs_unlock(&q->lock);
3848  return -1;
3849  }
3850 
3851  if (entry) {
3852  ocs_memcpy(entry, qe, q->size);
3853 #if defined(OCS_INCLUDE_DEBUG)
3854  switch(q->type) {
3855  case SLI_QTYPE_CQ:
3856  snprintf(desc, sizeof(desc), "%s entry %d", q->name, *qindex);
3857  ocs_dump32(OCS_DEBUG_ENABLE_CQ_DUMP, sli4->os, desc, entry, q->size);
3858  break;
3859  case SLI_QTYPE_MQ:
3860  {
3861  sli4_mqe_hdr_t *hdr = (sli4_mqe_hdr_t *)entry;
3862 
3863  snprintf(desc, sizeof(desc), "mq Compl entry %d", *qindex);
3865  sli4->os,
3866  desc,
3867  entry,
3868  hdr->payload_length + sizeof(sli4_mqe_hdr_t));
3869  }
3870  break;
3871  default:
3872  break;
3873  }
3874 #endif
3875  }
3876 
3877  switch (q->type) {
3878  case SLI_QTYPE_EQ:
3879  case SLI_QTYPE_CQ:
3880  case SLI_QTYPE_MQ:
3881  *qindex = (*qindex + 1) & (q->length - 1);
3882  if (SLI_QTYPE_MQ != q->type) {
3883  q->n_posted++;
3884  }
3885  break;
3886  default:
3887  /* reads don't update the index */
3888  break;
3889  }
3890 
3891  ocs_unlock(&q->lock);
3892 
3893  return rc;
3894 }
3895 
3896 int32_t
3898 {
3899 
3900  if (q) {
3901  return q->index;
3902  } else {
3903  return -1;
3904  }
3905 }
3906 
3907 int32_t
3908 _sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
3909 {
3910  int32_t rc = 0;
3911  uint8_t *qe = q->dma.virt;
3912 
3913  if (index >= q->length) {
3914  return -1;
3915  }
3916 
3917  qe += index * q->size;
3918 
3919  if (entry) {
3920  ocs_memcpy(qe, entry, q->size);
3921  }
3922 
3923  ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
3924 
3925  return rc;
3926 }
3927 
3928 int32_t
3929 sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
3930 {
3931  int32_t rc;
3932 
3933  ocs_lock(&q->lock);
3934  rc = _sli_queue_poke(sli4, q, index, entry);
3935  ocs_unlock(&q->lock);
3936 
3937  return rc;
3938 }
3939 
3940 int32_t
3941 _sli_queue_peek(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
3942 {
3943  int32_t rc = 0;
3944  uint8_t *qe = q->dma.virt;
3945 
3946  if (index >= q->length) {
3947  return -1;
3948  }
3949 
3950  qe += index * q->size;
3951 
3952  if (entry) {
3953  ocs_memcpy(entry, qe, q->size);
3954  }
3955 
3956  return rc;
3957 }
3958 
3959 int32_t
3960 sli_queue_peek(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
3961 {
3962  int32_t rc;
3963 
3964  ocs_lock(&q->lock);
3965  rc = _sli_queue_peek(sli4, q, index, entry);
3966  ocs_unlock(&q->lock);
3967 
3968  return rc;
3969 }
3970 
3971 /**
3972  * @ingroup sli
3973  * @brief Parse an EQ entry to retrieve the CQ_ID for this event.
3974  *
3975  * @param sli4 SLI context.
3976  * @param buf Pointer to EQ entry.
3977  * @param cq_id CQ_ID for this entry.
3978  *
3979  * @return Returns 0 on success, or non-zero otherwise.
3980  */
3981 int32_t
3982 sli_eq_parse(sli4_t *sli4, uint8_t *buf, uint16_t *cq_id)
3983 {
3984  sli4_eqe_t *eqe = (void *)buf;
3985 
3986  if (!sli4 || !buf || !cq_id) {
3987  ocs_log_err(NULL, "bad parameters sli4=%p buf=%p cq_id=%p\n",
3988  sli4, buf, cq_id);
3989  return -1;
3990  }
3991 
3992  *cq_id = eqe->resource_id;
3993 
3994  return 0;
3995 }
3996 
3997 /**
3998  * @ingroup sli
3999  * @brief Parse a CQ entry to retrieve event type and associated queue.
4000  *
4001  * @param sli4 SLI context.
4002  * @param cq CQ to process.
4003  * @param cqe Pointer to the CQ entry.
4004  * @param fields Returns the fields of the CQE to the caller.
4005  *
4006  * @return Returns 0 on success, nor on-zero otherwise.
4007  */
4008 int32_t
4009 sli_cq_parse(sli4_t *sli4, sli4_queue_t *cq, uint8_t *cqe,
4010  sli4_qentry_fields_t *fields)
4011 {
4012  int32_t rc = 0;
4013 
4014  if (!sli4 || !cq || !cqe || !fields) {
4015  ocs_log_err(NULL, "bad parameters sli4=%p cq=%p cqe=%p fields=%p\n",
4016  sli4, cq, cqe, fields);
4017  return -1;
4018  }
4019 
4020  if (cq->u.flag.is_mq) {
4021  sli4_mcqe_t *mcqe = (void *)cqe;
4022 
4023  if (mcqe->ae) {
4024  fields->ctype = SLI_CQENTRY_ASYNC;
4025  } else {
4026  fields->ctype = SLI_CQENTRY_MQ;
4027  rc = sli_cqe_mq(mcqe);
4028  }
4029  } else {
4030  rc = sli_iscsi_cqe_parse(sli4, cq, cqe, fields);
4031  }
4032 
4033  return rc;
4034 }
4035 
4036 void
4037 sli_interrupt_set(sli4_t *sli, uint8_t enable)
4038 {
4039  uint32_t val;
4040 
4041  val = ocs_reg_read32(sli->os, 0, PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);
4042 
4043  /* If enabling, then make sure the global interrupt enable bit is set. */
4044  if (enable &&
4047  ocs_reg_write32(sli->os, 0, PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET, val);
4048  }
4049 
4050  /* If disabling, then make sure the global interrupt enable bit is cleared. */
4051  if (!enable &&
4052  (val & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK)) {
4053  val &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
4054  ocs_reg_write32(sli->os, 0, PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET, val);
4055  }
4056 }
4057 
4058 /**
4059  * @ingroup sli
4060  * @brief Read the SLIPORT_SEMAPHORE and SLIPORT_STATUS registers to check if
4061  * the port status indicates that a FW error has occurred.
4062  *
4063  * @param sli4 SLI context.
4064  *
4065  * @return
4066  * - 0 if call completed correctly and no FW error occurred.
4067  * - > 0 which indicates that a FW error has occurred.
4068  * - -1 if call failed.
4069  */
4071 {
4072  uint32_t sliport_semaphore;
4073  int32_t rc = 0;
4074 
4075  sliport_semaphore = sli_reg_read(sli4, SLI4_REG_SLIPORT_SEMAPHORE);
4076  if (UINT32_MAX == sliport_semaphore) {
4077  ocs_log_test(sli4->os, "error reading SLIPORT_SEMAPHORE register\n");
4078  return -1;
4079  }
4080  rc = (SLI4_PORT_SEMAPHORE_IN_ERR(sliport_semaphore) ? 1 : 0);
4081 
4082  if (rc == 0) {
4083  if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type ||
4084  (SLI4_IF_TYPE_BE3_SKH_VF == sli4->if_type)) {
4085  uint32_t uerr_mask_lo, uerr_mask_hi;
4086  uint32_t uerr_status_lo, uerr_status_hi;
4087 
4088  uerr_mask_lo = sli_reg_read(sli4, SLI4_REG_UERR_MASK_LO);
4089  uerr_mask_hi = sli_reg_read(sli4, SLI4_REG_UERR_MASK_HI);
4090  uerr_status_lo = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_LO);
4091  uerr_status_hi = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_HI);
4092  if ((uerr_mask_lo & uerr_status_lo) != 0 ||
4093  (uerr_mask_hi & uerr_status_hi) != 0) {
4094  rc = 1;
4095  }
4096  } else if ((SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type)) {
4097  uint32_t sliport_status;
4098 
4099  sliport_status = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
4100  rc = (SLI4_PORT_STATUS_ERROR(sliport_status) ? 1 : 0);
4101  }
4102  }
4103  return rc;
4104 }
4105 
4106 /* vim: set noexpandtab textwidth=120: */
This structure contains the type and associated fields for a CQE completion.
Definition: sli4.h:2017
uint8_t is_skyhawk
Definition: sli4.h:2208
Mailbox Completion Queue Entry.
Definition: sli4.h:1773
int32_t(* link)(void *, void *)
Definition: sli4.h:2255
sli4_req_hdr_t hdr
Definition: sli4.h:871
static int32_t sli_cmd_common_get_cntl_attributes(sli4_t *sli4, void *buf, size_t size)
Write a COMMON_GET_CNTL_ATTRIBUTES command to the provided buffer.
Definition: sli4.c:672
#define SLI4_OPC_COMMON_GET_ACTIVE_PROFILE
Definition: sli4.h:545
ocs_os_handle_t os
Definition: sli4.h:2202
char ipl_name[16]
Definition: sli4.h:2245
uint32_t physical_port
Definition: sli4.h:2204
sli4_port_type_e port_type
Definition: sli4.h:2203
#define SLI4_ULP_MODE_ISCSI_TGT
Definition: sli4.h:766
uint32_t ae
Definition: sli4.h:1781
sli4_wqe_context_t * wq_ctx
Definition: ocs_hal.h:495
static int32_t sli_cmd_common_destroy_eq(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint16_t eq_id)
Write a COMMON_DESTROY_EQ command.
Definition: sli4.c:1047
void * sli_queue_iscsi_icd_lookup(sli4_t *sli4, sli4_queue_t *q, uint16_t icd_index)
Returns the IO tied to a specific ICD index.
Definition: sli4.c:3604
#define SLI4_ASIC_REV_MASK
Definition: sli4.h:103
#define SLI4_PCI_REV_ID_SHIFT
Definition: sli4.h:69
#define SLI4_IO_WQ_DOORBELL_REG
WQ_DOORBELL - WQ Doorbell Register.
Definition: sli4.h:265
uint32_t con
Definition: sli4.h:1781
#define SLI4_INTF_VALID
Definition: sli4.h:84
#define SLI4_OPC_COMMON_GET_BE_CONFIGURATION_AND_RESOURCES
Definition: sli4.h:532
Generic Common Create EQ/CQ/MQ/WQ/RQ Queue completion.
Definition: sli4.h:914
static int32_t sli_cmd_fw_initialize(sli4_t *, void *, size_t)
Write a FW_INITIALIZE command to the provided buffer.
Definition: sli4.c:485
int32_t sli_raise_ue(sli4_t *sli4)
Definition: sli4.c:360
static int32_t sli_cmd_common_destroy_cq(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint16_t cq_id)
write a COMMON_DESTROY_CQ command.
Definition: sli4.c:891
uint32_t length
Definition: sli4.h:2265
#define SLI4_ACQE_EVENT_CODE_LINK_STATE
Definition: sli4.h:1813
uint32_t additional_status
Definition: sli4.h:606
static uint32_t sli_eq_doorbell(uint16_t n_popped, uint16_t id, uint8_t arm)
Definition: sli4.h:170
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:4070
uint32_t uint32_t response_length
Definition: sli4.h:606
int32_t sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
Definition: sli4.c:3929
#define SLI4_PCI_SOFT_RESET_MASK
Definition: sli4.h:75
#define SLI4_QUEUE_RQ_BATCH
Definition: sli4.h:2090
uint32_t icd_chain_count
Definition: sli4.h:2217
uint32_t family
Definition: sli4.c:86
uint32_t num_sgl_pages
Definition: sli4.h:2267
struct sli4_req_common_create_mq_ext_t::@31 page_physical_address[8]
int32_t sli_cmd_common_tcp_upload(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint16_t wq_id, uint8_t graceful)
Write a COMMON_TCP_UPLOAD command.
Definition: sli4.c:1196
#define SLI4_OPC_COMMON_DESTROY_EQ
Definition: sli4.h:523
static int32_t sli_get_all_if_ids(sli4_t *sli4)
Retrieve all of the defines interface IDs and store the default interface.
Definition: sli4.c:2483
#define SLI4_OPC_COMMON_SET_BE_CONFIGURATION_AND_RESOURCES
Definition: sli4.h:533
int32_t sli_cmd_mailbox_queue_entry(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint32_t length, ocs_dma_t *dma)
Write a MQE header in the provided buffer.
Definition: sli4.c:508
uint16_t size
Definition: sli4.h:2051
mailbox queue Element header
Definition: sli4.h:564
uint32_t sli_family
Definition: sli4.h:2226
#define OCS_DEBUG_ENABLE_MQ_DUMP
Definition: ocs_debug.h:155
sli4_req_hdr_t hdr
Definition: sli4.h:836
COMMON_CREATE_MQ_EXT.
Definition: sli4.h:1003
uint32_t extended_status
Definition: sli4.h:1775
#define SLI4_UERR_MASK_HIGH_REG
Definition: sli4.h:238
static int32_t sli_bmbx_write(sli4_t *sli4)
Write bootstrap mailbox.
Definition: sli4.c:376
#define SLI4_OPC_COMMON_QUERY_FW_CONFIG
Definition: sli4.h:517
uint32_t domain
Definition: sli4.h:584
int32_t sli_eq_modify_delay(sli4_t *sli4, sli4_queue_t *eq, uint32_t num_eq, uint32_t shift, uint32_t delay_mult)
Modify the delay timer for all the EQs.
Definition: sli4.c:3098
int32_t sli_queue_peek(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
Definition: sli4.c:3960
Event Queue Entry.
Definition: sli4.h:1757
Common TCP_UPLOAD.
Definition: sli4.h:1081
get_sli4_parameters_t * get_sli4_parameters
Definition: sli4.h:2271
COMMON_QUERY_FW_CONFIG.
Definition: sli4.h:756
struct sli4_queue_t::@33::@35 wq
int32_t sli_cmd_common_set_features(sli4_t *sli4, void *buf, size_t size, uint32_t feature, uint32_t param_len, void *parameter)
Write a COMMON_SET_FEATURES command.
Definition: sli4.c:1778
#define SLI4_ACQE_EVENT_CODE_GRP_5
Definition: sli4.h:1816
#define SLI4_EQ_CNT_2048
Definition: sli4.h:979
int32_t sli_fw_reset(sli4_t *sli4)
Definition: sli4.c:2822
#define SLI4_MQE_SIZE_16
Definition: sli4.h:1033
uint32_t cmp
Definition: sli4.h:1781
uint8_t dual_ulp_capable
Definition: sli4.h:2234
int32_t sli_setup(sli4_t *sli4, ocs_os_handle_t os, sli4_port_type_e port_type)
Setup the SLI context.
Definition: sli4.c:2531
#define SLI4_OPC_COMMON_GET_PROFILE_LIST
Definition: sli4.h:544
#define SLI4_MQ_DOORBELL_REG
MQ_DOORBELL - MQ Doorbell Register.
Definition: sli4.h:243
COMMON_GET_BE_CONFIGURATION_AND_RESOURCES (v1)
Definition: sli4.h:1148
static uint8_t sli_pci_rev_id(uint32_t val)
Retrieve PCI revision ID.
Definition: sli4.c:300
int32_t sli_cmd_common_get_profile_config(sli4_t *sli4, void *buf, size_t size, uint64_t tag, ocs_dma_t *dma)
Write a COMMON_COMMON_GET_PROFILE_CONFIG command.
Definition: sli4.c:1454
COMMON_NOP.
Definition: sli4.h:1098
static uint8_t sli_intf_sli_family(uint32_t val)
Definition: sli4.c:274
uint8_t tcp_offload_nrs
Definition: sli4.h:2229
int32_t sli_cmd_common_get_active_profile(sli4_t *sli4, void *buf, size_t size, uint64_t tag)
Write a COMMON_COMMON_GET_ACTIVE_PROFILE command.
Definition: sli4.c:1603
int32_t sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
Write an entry to the queue object.
Definition: sli4.c:3469
#define SLI4_OPC_COMMON_TCP_UPLOAD
Definition: sli4.h:527
uint32_t rset
Definition: sli4.h:1853
uint32_t posted_limit
Definition: sli4.h:2064
static void * ocs_list_get_head(ocs_list_t *list)
Return the first item in the list.
Definition: ocs_list.h:292
struct sli4_queue_t::@33::@34 flag
#define SLI4_OPC_COMMON_GET_RECONFIG_LINK_INFO
Definition: sli4.h:553
uint8_t fw_on_flash_version[32]
Definition: sli4.h:2244
Common Destroy CQ.
Definition: sli4.h:930
uint8_t tcp_ack_status
Definition: sli4.h:2039
static uint8_t sli_intf_sli_revision(uint32_t val)
Retrieve the SLI revision level.
Definition: sli4.c:268
ocs_dma_t data
Definition: sli4.h:2264
#define SLI4_FUNCTION_MODE_DUA_MODE
Definition: sli4.h:763
#define SLI_USER_EQ_COUNT
Definition: sli4.h:1867
int32_t sli_cmd_common_set_profile_config(sli4_t *sli4, void *buf, size_t size, uint64_t tag, ocs_dma_t *dma, uint8_t profile_id, uint32_t descriptor_count, uint8_t isap)
Write a COMMON_COMMON_SET_PROFILE_CONFIG command.
Definition: sli4.c:1504
#define SLI4_OPC_COMMON_GET_CNTL_ADDL_ATTRIBUTES
Definition: sli4.h:535
#define SLI4_OPC_COMMON_SET_RECONFIG_LINK_ID
Definition: sli4.h:554
sli4_qentry_e ctype
Definition: sli4.h:2018
#define SLI4_OPC_COMMON_SET_ACTIVE_PROFILE
Definition: sli4.h:546
uint32_t index
Definition: sli4.h:2050
#define SLI4_INTF_SLI_FAMILY_SHIFT
Definition: sli4.h:87
static uint8_t sli_asic_gen(uint32_t val)
Retrieve SLI ASIC generation.
Definition: sli4.c:332
#define SLI4_ASYNC_EVT_ISCSI_EVENTS
Definition: sli4.h:1059
static int32_t sli_cmd_common_create_cq(sli4_t *sli4, void *buf, size_t size, uint64_t tag, ocs_dma_t *qmem, uint16_t eq_id, uint16_t ignored)
Write a COMMON_CREATE_CQ command.
Definition: sli4.c:778
#define SLI4_OPC_COMMON_GET_PROFILE_CONFIG
Definition: sli4.h:542
sli4_asic_entry_t sli4_asic_table[]
Definition: sli4.c:91
static int32_t sli_cmd_common_destroy_mq(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint16_t mq_id)
Write a COMMON_DESTROY_MQ command.
Definition: sli4.c:1157
#define SLI4_INTF_IF_TYPE_MASK
Definition: sli4.h:86
#define SLI4_BMBX_WRITE_HI(r)
Definition: sli4.h:121
int32_t sli_queue_is_empty(sli4_t *sli4, sli4_queue_t *q)
Check if the given queue is empty.
Definition: sli4.c:3327
COMMON_GET_CNTL_ATTRIBUTES.
Definition: sli4.h:637
static int32_t sli_query_fw_config(sli4_t *sli4)
Issue a FW_CONFIG mailbox command and store the results.
Definition: sli4.c:2272
#define SLI4_SLIPORT_ERROR2
SLI4_SLIPORT_ERROR2 - SLI Port Error register.
Definition: sli4.h:164
static int32_t sli_cmd_get_vpd_data(sli4_t *sli4, void *buf, size_t size)
Write a COMMON_GET_VPD_DATA command to the provided buffer.
Definition: sli4.c:640
#define SLI4_OPC_COMMON_DESTROY_MQ
Definition: sli4.h:526
#define SLI4_MQE_SIZE_64
Definition: sli4.h:1035
static int32_t sli_cmd_common_modify_eq_delay(sli4_t *sli4, void *buf, size_t size, sli4_queue_t *q, int num_q, uint32_t shift, uint32_t delay_mult)
Write a COMMON_MODIFY_EQ_DELAY command.
Definition: sli4.c:1003
uint32_t max_ios
Definition: sli4.h:2247
int32_t __sli_queue_init(sli4_t *sli4, sli4_queue_t *q, uint32_t qtype, uint32_t version, size_t size, uint32_t n_entries, uint32_t align)
Initialize a queue object.
Definition: sli4.c:2953
#define SLI_USER_MQ_COUNT
Definition: sli4.h:1866
#define SLI4_PCI_SOFT_RESET_CSR
Definition: sli4.h:74
#define SLI4_IF_TYPE_BE3_SKH_VF
Definition: sli4.h:93
struct sli4_t::@37 features
uint16_t icd
Definition: ocs_hal.h:474
sli4_req_hdr_t hdr
Definition: sli4.h:931
char name[8]
Definition: sli4.h:2061
#define SLI4_PORT_STATUS_REG_23
SLIPORT_STATUS - SLI Port Status Register.
Definition: sli4.h:329
int32_t sli_iscsi_process_iscsi(sli4_t *sli4, void *acqe)
Process an asynchronous iSCSI event entry.
Definition: sli4_iscsi.c:2032
int32_t sli_cqe_mq(void *buf)
Check mailbox/queue completion entry.
Definition: sli4.c:1820
sli4_req_hdr_t hdr
Definition: sli4.h:989
Common Destroy MQ.
Definition: sli4.h:1068
#define SLI4_SLIPORT_ERROR1
SLI4_SLIPORT_ERROR1 - SLI Port Error register.
Definition: sli4.h:159
struct sli4_req_common_modify_eq_delay_t::@27 eq_delay_record[8]
int32_t sli_cmd_common_get_reconfig_link_info(sli4_t *sli4, void *buf, size_t size, uint64_t tag, ocs_dma_t *dma)
Write a COMMON_COMMON_GET_RECONFIG_LINK_INFO command.
Definition: sli4.c:1683
uint32_t resource_id
Definition: sli4.h:1759
sli_wqe_handlers_t sli_be3_iscsi_wqe_handlers
int32_t sli_queue_read(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
Read an entry from the queue object.
Definition: sli4.c:3825
#define SLI4_INTF_IF_TYPE_SHIFT
Definition: sli4.h:85
int32_t sli_teardown(sli4_t *sli4)
Tear down a SLI context.
Definition: sli4.c:2865
#define SLI4_OPC_COMMON_FUNCTION_RESET
Definition: sli4.h:518
uint32_t icd_count
Definition: sli4.h:2215
uint32_t context[2]
Definition: sli4.h:1101
sli4_req_hdr_t hdr
Definition: sli4.h:1069
#define SLI4_PCI_REV_ID_MASK
Definition: sli4.h:70
sli4_asic_type_e type
Definition: sli4.c:87
#define SLI4_MQ_DOORBELL(n, i)
Definition: sli4.h:247
#define SLI4_ASIC_ID_REG
ASIC_ID - SLI ASIC Type and Revision Register.
Definition: sli4.h:101
ocs_dma_t * sgl_pages
Definition: sli4.h:2268
sli4_asic_type_e
Definition: sli4.h:2163
#define SLI4_CQ_CNT_512
Definition: sli4.h:908
uint32_t sli_rev
Definition: sli4.h:2225
static void * ocs_list_remove(ocs_list_t *list, void *item)
Remove an item from the list.
Definition: ocs_list.h:385
union sli4_queue_t::@33 u
int32_t sli_cmd_iscsi_wq_create(sli4_t *sli4, void *buf, size_t size, uint64_t tag, ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp)
write a ISCSI_WQ_CREATE command
Definition: sli4_iscsi.c:1409
uint32_t status
Definition: sli4.h:606
uint32_t bmbx_timeout_msecs
Definition: sli4.h:2249
uint32_t completion_status
Definition: sli4.h:1775
COMMON_MODIFY_EQ_DELAY.
Definition: sli4.h:816
#define SLI4_ULP_MODE_ISCSI_INI
Definition: sli4.h:765
uint32_t sli_reg_read(sli4_t *sli, sli4_regname_e reg)
Read the given SLI register.
Definition: sli4.c:210
uint16_t ulp
Definition: sli4.h:2055
static int32_t sli_cmd_common_function_reset(sli4_t *sli4, void *buf, size_t size, uint64_t tag)
write a COMMON_FUNCTION_RESET command.
Definition: sli4.c:741
int32_t(* sli4_create_q_fn_t)(sli4_t *, void *, size_t, uint64_t, ocs_dma_t *, uint16_t, uint16_t)
Common Create Queue function prototype.
Definition: sli4.h:2409
Common Destroy EQ.
Definition: sli4.h:988
#define SLI4_INTF_VALID_MASK
Definition: sli4.h:83
uint32_t val
Definition: sli4.h:1781
int32_t sli_cmd_iscsi_remove_sgl_pages(sli4_t *sli4, void *buf, size_t size, uint64_t tag)
write a COMMON_ISCSI_CFG_REMOVE_SGL_PAGES command
Definition: sli4_iscsi.c:1794
uint32_t doorbell_offset
Definition: sli4.h:2057
uint32_t uint32_t db_offset
Definition: sli4.h:917
uint32_t opcode
Definition: sli4.h:584
static int32_t sli_iscsi_remove_sgl_pages(sli4_t *sli4)
Issue a ISCSI_CFG_REMOVE_SGL_PAGES command.
Definition: sli4.c:1935
int32_t sli_cqe_async(sli4_t *sli4, void *buf)
Check asynchronous event completion entry.
Definition: sli4.c:1866
sli4_regname_e
Register name enums.
Definition: sli4.h:1821
Definition: sli4.h:2201
static uint8_t sli_queue_entry_is_valid(sli4_queue_t *, uint8_t *, uint8_t)
Check if the current queue entry is valid.
Definition: sli4.c:3775
#define SLI4_ASIC_VER_SHIFT
Definition: sli4.h:104
#define SLI4_BMBX_SIZE
Definition: sli4.h:128
ocs_lock_t lock
Definition: sli4.h:2049
static int32_t sli_common_function_reset(sli4_t *sli4)
Issue a COMMON_FUNCTION_RESET command.
Definition: sli4.c:1904
#define SLI4_OPC_COMMON_MODIFY_EQ_DELAY
Definition: sli4.h:524
static uint8_t sli_asic_revision(uint32_t val)
Retrieve SLI ASIC revision.
Definition: sli4.c:313
#define SLI4_ONLINE1_REG
Definition: sli4.h:231
int32_t sli_iscsi_process_link_state(sli4_t *sli4, void *acqe)
Process an asynchronous Link State event entry.
Definition: sli4_iscsi.c:1947
#define SLI4_BMBX_REG
BMBX - Bootstrap Mailbox Register.
Definition: sli4.h:115
Definition: sli4.c:84
#define SLI4_SUBSYSTEM_COMMON
Definition: sli4.h:507
uint32_t event_code
Definition: sli4.h:1802
#define SLI4_INTF_SLI_FAMILY_MASK
Definition: sli4.h:88
#define SLI4_CQ_CNT_256
Definition: sli4.h:907
COMMON_GET_FW_VERSION.
Definition: sli4.h:740
#define SLI4_RQ_DOORBELL_REG
RQ_DOORBELL - RQ Doorbell Register.
Definition: sli4.h:254
static int32_t sli_cmd_common_get_cntl_addl_attributes(sli4_t *sli4, void *buf, size_t size)
Write a COMMON_GET_CNTL_ADDL_ATTRIBUTES command to the provided buffer.
Definition: sli4.c:706
void ocs_dump32(uint32_t mask, ocs_os_handle_t os, const char *label, void *buf, uint32_t buf_length)
Dump 32 bit hex/ascii data.
Definition: ocs_dump32.c:72
#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET
Definition: sli4.h:54
int32_t sli_cmd_common_nop(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint64_t context)
Write a COMMON_NOP command.
Definition: sli4.c:1236
int32_t sli_cmd_iscsi_defq_destroy(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint16_t rq_id)
write a ISCSI_DEFQ_DESTROY command
Definition: sli4_iscsi.c:1910
COMMON_FUNCTION_RESET.
Definition: sli4.h:623
uint8_t post_sgl_ver
Definition: sli4.h:2242
int32_t(* iscsi_async)(void *, void *)
Definition: sli4.h:2258
#define SLI4_ASIC_GEN_SHIFT
Definition: sli4.h:106
#define SLI4_OPC_COMMON_NOP
Definition: sli4.h:528
#define SLI4_MAX_IF_TYPES
Definition: sli4.h:96
uint32_t proc_limit
Definition: sli4.h:2063
COMMON_GET_CNTL_ATTRIBUTES.
Definition: sli4.h:700
io_cb_t * done
Definition: ocs_hal.h:493
void * sli_queue_iscsi_icd_invalid(sli4_t *sli4, sli4_queue_t *q, uint16_t icd_index, uint8_t *wait_for_tcp_ack, uint8_t tcp_ack_status)
Processes a target command invalidation IO completion. Moves the WRB to the free list.
Definition: sli4.c:3651
COMMON_SET_PROFILE_CONFIG.
Definition: sli4.h:1494
void * link_arg
Definition: sli4.h:2256
static int32_t sli_cmd_common_create_mq_ext(sli4_t *sli4, void *buf, size_t size, uint64_t tag, ocs_dma_t *qmem, uint16_t cq_id, uint16_t ignored)
Write a COMMON_CREATE_MQ_EXT command.
Definition: sli4.c:1085
uint32_t port_number
Definition: sli4.h:584
sli4_req_hdr_t hdr
Definition: sli4.h:946
const uint8_t sli4_fw_initialize[]
FW_INITIALIZE - initialize a SLI port.
Definition: sli4.c:62
int32_t sli_eq_parse(sli4_t *sli4, uint8_t *buf, uint16_t *cq_id)
Parse an EQ entry to retrieve the CQ_ID for this event.
Definition: sli4.c:3982
Asynchronous Completion Queue Entry.
Definition: sli4.h:1798
struct sli4_t::@39 vpd
uint32_t embedded
Definition: sli4.h:566
uint8_t type
Definition: sli4.h:2059
sli_wqe_handlers_t sli_skh_iscsi_wqe_handlers
#define SLI4_OPC_COMMON_GET_VPD_DATA
Definition: sli4.h:534
int32_t sli_queue_free(sli4_t *sli4, sli4_queue_t *q)
Free a queue.
Definition: sli4.c:3218
COMMON_GET_VPD_DATA.
Definition: sli4.h:1370
#define SLI4_EQ_CNT_4096
Definition: sli4.h:980
uint8_t fw_version[32]
Definition: sli4.h:2243
static int32_t sli_cmd_common_query_fw_config(sli4_t *sli4, void *buf, size_t size)
Write a COMMON_QUERY_FW_CONFIG command to the provided buffer.
Definition: sli4.c:608
int32_t sli_cmd_common_get_function_config(sli4_t *sli4, void *buf, size_t size, uint64_t tag)
Write a COMMON_COMMON_GET_FUNCTION_CONFIG command.
Definition: sli4.c:1416
int32_t sli_cmd_iscsi_wq_destroy(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint16_t wq_id)
write a ISCSI_WQ_DESTROY command
Definition: sli4_iscsi.c:1466
#define SLI4_PORT_STATUS_READY(r)
Definition: sli4.h:335
int32_t _sli_queue_peek(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
Definition: sli4.c:3941
sli4_asic_type_e asic_type
Definition: sli4.h:2273
const char * SLI_QNAME[]
Definition: sli4.c:75
COMMON_GET_FUNCTION_CONFIG.
Definition: sli4.h:1457
#define OCS_DEBUG_ENABLE_CQ_DUMP
Definition: ocs_debug.h:156
#define SLI4_OPC_COMMON_GET_FW_VERSION
Definition: sli4.h:516
static uint8_t sli_intf_valid_check(uint32_t val)
Check if the SLI_INTF register is valid.
Definition: sli4.c:255
HAL IO object.
Definition: ocs_hal.h:471
struct sli4_req_common_create_eq_t::@30 page_address[8]
uint16_t wrb_index
Definition: sli4.h:2037
This structure is used to track the WQEs for iSCSI.
Definition: sli4.h:2034
uint32_t version
Definition: sli4.h:590
#define SLI4_UERR_STATUS_HIGH_REG
Definition: sli4.h:236
sli4_asic_rev_e rev
Definition: sli4.c:88
uint16_t length
Definition: sli4.h:2052
#define SLI4_OPC_COMMON_DESTROY_CQ
Definition: sli4.h:521
COMMON_GET_PROFILE_CONFIG.
Definition: sli4.h:1474
uint32_t if_type
Definition: sli4.h:2206
uint16_t id
Definition: sli4.h:2054
static int32_t sli_cmd_common_create_eq(sli4_t *sli4, void *buf, size_t size, uint64_t tag, ocs_dma_t *qmem, uint16_t ignored1, uint16_t ignored2)
write a COMMON_CREATE_EQ command.
Definition: sli4.c:934
static int32_t sli_queue_doorbell(sli4_t *, sli4_queue_t *)
Write the doorbell register associated with the queue object.
Definition: sli4.c:2100
uint32_t delay_multiplier
Definition: sli4.h:961
static int32_t sli_get_fw_version(sli4_t *sli4)
Issue a GET_FW_VERSION mailbox command and store the results.
Definition: sli4.c:2167
uint32_t ocs_instance(void *os)
Return the instance index of an opaque ocs structure.
Definition: ocs_driver.c:160
ocs_cxn_t * node
Definition: ocs_hal.h:475
int32_t sli_skh_get_sli4_parameters(sli4_t *sli4)
Issue the GET_SLI4_PARAMETERS IOCTL and populate the results.
#define SLI4_BMBX_RDY
Definition: sli4.h:118
struct sli4_req_common_create_cq_v0_t::@28 page_physical_address[4]
uint32_t subsystem
Definition: sli4.h:584
int32_t sli_queue_arm(sli4_t *sli4, sli4_queue_t *q, uint8_t arm)
Arm or dis-arm a queue.
Definition: sli4.c:3356
uint16_t n_posted
Definition: sli4.h:2053
#define SLI4_OPC_COMMON_CREATE_EQ
Definition: sli4.h:522
struct sli4_t::@38 config
int32_t sli_reset(sli4_t *sli4)
Definition: sli4.c:2809
sli4_callback_e
Definition: sli4.h:2092
uint16_t doorbell_rset
Definition: sli4.h:2058
#define SLI4_BMBX_WRITE_LO(r)
Definition: sli4.h:124
#define SLI4_EQ_CNT_1024
Definition: sli4.h:978
#define SLI4_PORT_SEMAPHORE_PORT(r)
Definition: sli4.h:291
static int32_t sli_fw_init(sli4_t *)
Initialize the firmware.
Definition: sli4.c:1970
int32_t sli_cmd_iscsi_common_get_all_if_id(sli4_t *sli4, void *buf, size_t size, uint64_t tag)
write a COMMON_ISCSI_NTWK_GET_ALL_IF_ID command
Definition: sli4_iscsi.c:591
#define SLI4_ASIC_GEN_SKYHAWK
Definition: sli4.h:110
#define SLI4_MQE_SIZE_128
Definition: sli4.h:1036
#define SLI4_OPC_COMMON_GET_FUNCTION_CONFIG
Definition: sli4.h:541
#define SLI4_OPC_COMMON_SET_FEATURES
Definition: sli4.h:552
#define SLI4_OPC_COMMON_CREATE_CQ
Definition: sli4.h:520
static void ocs_list_add_tail(ocs_list_t *list, void *item)
Add an item to the tail of the list.
Definition: ocs_list.h:263
COMMON_GET_PROFILE_LIST.
Definition: sli4.h:1537
COMMON_GET_ACTIVE_PROFILE.
Definition: sli4.h:1560
#define SLI4_PORT_SEMAPHORE_IN_ERR(r)
Definition: sli4.h:320
#define SLI4_RQ_DOORBELL(n, i)
Definition: sli4.h:258
#define SLI4_SLIPORT_CONTROL_REG
SLIPORT_CONTROL - SLI Port Control Register.
Definition: sli4.h:149
This structure is used to track the SLI4 queues.
Definition: sli4.h:2046
uint32_t r_idx
Definition: sli4.h:2069
static int32_t sli_bmbx_wait(sli4_t *sli4, uint32_t msec)
Wait for the bootstrap mailbox to report &quot;ready&quot;.
Definition: sli4.c:346
static int32_t sli_cmd_common_get_fw_version(sli4_t *sli4, void *buf, size_t size)
Write a COMMON_GET_FW_VERSION command to the provided buffer.
Definition: sli4.c:577
int32_t sli_iscsi_cqe_parse(sli4_t *sli4, sli4_queue_t *cq, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse a iSCSI work queue CQ entry.
Definition: sli4_iscsi.c:2120
ocs_dma_t cntl_attr
Definition: sli4.h:2261
int32_t sli_cmd_common_set_active_profile(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint32_t fd, uint32_t active_profile_id)
Write a COMMON_COMMON_SET_ACTIVE_PROFILE command.
Definition: sli4.c:1642
void sli_reg_write(sli4_t *sli, sli4_regname_e reg, uint32_t val)
Write the value to the given SLI register.
Definition: sli4.c:234
#define SLI4_INTF_REG
SLI_INTF - SLI Interface Definition Register.
Definition: sli4.h:81
sli4_res_hdr_t hdr
Definition: sli4.h:915
#define SLI4_PCI_CLASS_REVISION
Definition: sli4.h:68
#define SLI4_ONLINE0_REG
Definition: sli4.h:230
int32_t sli_cq_parse(sli4_t *sli4, sli4_queue_t *cq, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse a CQ entry to retrieve event type and associated queue.
Definition: sli4.c:4009
int32_t __sli_create_queue(sli4_t *sli4, sli4_queue_t *q)
Issue command to create queue.
Definition: sli4.c:3009
static void * ocs_list_next(ocs_list_t *list, void *item)
Get the next item on the list.
Definition: ocs_list.h:339
#define SLI4_INTF_SLI_REVISION_SHIFT
Definition: sli4.h:89
#define SLI4_ASIC_VER_MASK
Definition: sli4.h:105
#define SLI4_PORT_STATUS_ERROR(r)
Definition: sli4.h:336
void sli_queue_iscsi_cleanup(void *hal, sli4_t *sli4, sli4_queue_t *q)
Moves any WQE entries from the busy back to the free list when a connection is uploaded.
Definition: sli4.c:3718
uint8_t version
Definition: sli4.h:2060
int32_t sli_queue_iscsi_tcp_ack(sli4_t *sli4, sli4_queue_t *q, uint8_t wqe_index)
Processes a TCP ACK completion.
Definition: sli4.c:3532
uint32_t rev_id
Definition: sli4.c:85
int32_t _sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
Definition: sli4.c:3908
ocs_dma_t bmbx
Definition: sli4.h:2262
COMMON_CREATE_CQ_V2.
Definition: sli4.h:870
uint8_t mac_addr[6]
Definition: sli4.h:2210
#define SLI4_OPC_COMMON_CREATE_MQ_EXT
Definition: sli4.h:525
#define SLI4_IF_TYPE_BE3_SKH_PF
Definition: sli4.h:92
uint8_t pf_num
Definition: sli4.h:2209
int32_t sli_queue_reset(sli4_t *sli4, sli4_queue_t *q)
Zero all queue entries and reset the indexes.
Definition: sli4.c:3294
#define SLI4_UERR_STATUS_LOW_REG
Definition: sli4.h:235
#define SLI4_EQCQ_DOORBELL_REG
EQCQ_DOORBELL - EQ and CQ Doorbell Register.
Definition: sli4.h:133
#define SLI4_PORT_SEMAPHORE_STATUS_POST_READY
Definition: sli4.h:316
#define SLI4_MQE_SIZE_32
Definition: sli4.h:1034
#define SLI4_ASIC_GEN_MASK
Definition: sli4.h:107
static int32_t sli_query_fw_mac_addr(sli4_t *sli4)
Issue a mailbox command and find the MAC address.
Definition: sli4.c:2357
char modeldesc[64]
Definition: sli4.h:2246
#define SLI4_OPC_COMMON_SET_PROFILE_CONFIG
Definition: sli4.h:543
int32_t sli_queue_alloc(sli4_t *sli4, uint32_t qtype, sli4_queue_t *q, uint32_t n_entries, sli4_queue_t *assoc, uint16_t ulp)
Allocate a queue.
Definition: sli4.c:3135
#define SLI4_ACQE_EVENT_CODE_FCOE_FIP
Definition: sli4.h:1814
int32_t sli_be3_get_sli4_parameters(sli4_t *sli4)
Note: GET_SLI4_PARAMETERS IOCTL is not supported on BE3, so we just return constant values...
COMMON_CREATE_CQ_V0.
Definition: sli4.h:835
int32_t sli_bmbx_command(sli4_t *sli4)
Submit a command to the bootstrap mailbox and check the status.
Definition: sli4.c:405
static uint8_t sli_intf_if_type(uint32_t val)
Retrieve SLI interface type.
Definition: sli4.c:287
uint32_t timeout
Definition: sli4.h:588
int32_t(* sli4_destroy_q_fn_t)(sli4_t *, void *, size_t, uint64_t, uint16_t)
Common Destroy Queue function prototype.
Definition: sli4.h:2415
uint32_t icd_chain_base
Definition: sli4.h:2216
int32_t sli_cmd_common_set_be_configuration_and_resources(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint8_t *mac_addr)
Write a COMMON_COMMON_SET_BE_CONFIGURATION_AND_RESOURCES command.
Definition: sli4.c:1362
uint32_t sli_queue_iscsi_free_cnt(sli4_t *sli4, sli4_queue_t *q)
Return the number of free WRB entries.
Definition: sli4.c:3702
#define SLI4_OPC_COMMON_GET_CNTL_ATTRIBUTES
Definition: sli4.h:515
int32_t sli_cmd_common_get_profile_list(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint32_t start_profile_index, ocs_dma_t *dma)
Write a COMMON_COMMON_GET_PROFILE_LIST command.
Definition: sli4.c:1555
uint32_t sfp_a0[64]
Definition: sli4.h:2211
#define SLI4_EQE_SIZE_4
Definition: sli4.h:982
uint16_t cxn_cnt
Definition: sli4.h:2056
int32_t sli_callback(sli4_t *sli4, sli4_callback_e which, void *func, void *arg)
Register a callback for the given event.
Definition: sli4.c:2905
static int32_t sli_cmd_fw_deinitialize(sli4_t *, void *, size_t)
Write a FW_DEINITIALIZE command to the provided buffer.
Definition: sli4.c:466
uint16_t num_sges_per_icd
Definition: sli4.h:2241
static int32_t sli_fw_term(sli4_t *)
Terminate the firmware.
Definition: sli4.c:2056
static int32_t sli_read_transceiver_data(sli4_t *sli4)
Issue a READ_TRANSCEIVER_DATA mailbox command and store the results.
Definition: sli4.c:2203
int32_t io_cb_t(struct ocs_hal_io_s *io, ocs_cxn_t *cxn, int32_t status, ocs_ini_cmpl_fields_t *ini_fields, void *ul_arg)
IO Completion function prototype.
Definition: ocs_hal.h:432
#define SLI4_ASIC_REV_SHIFT
Definition: sli4.h:102
static int32_t sli_sliport_control(sli4_t *sli4, uint32_t endian)
Definition: sli4.c:546
uint32_t off
Definition: sli4.h:1854
uint32_t icd_base
Definition: sli4.h:2214
uint16_t max_qcount[SLI_QTYPE_MAX]
Definition: sli4.h:2239
void * iscsi_async_arg
Definition: sli4.h:2259
uint32_t db_ring_cnt
Definition: sli4.h:2062
#define SLI4_UERR_MASK_LOW_REG
Definition: sli4.h:237
uint16_t type
Definition: ocs_hal.h:477
uint32_t request_length
Definition: sli4.h:589
#define SLI4_INTF_SLI_REVISION_MASK
Definition: sli4.h:90
Generic Command Request header.
Definition: sli4.h:582
void sli_interrupt_set(sli4_t *sli, uint8_t enable)
Definition: sli4.c:4037
uint32_t payload_length
Definition: sli4.h:571
#define SLI4_ASIC_GEN_BE3
Definition: sli4.h:109
struct sli_wqe_handlers * wqe_handlers
Definition: sli4.h:2270
#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK
Definition: sli4.h:62
Generic Command Response header.
Definition: sli4.h:600
#define SLI4_PORT_SEMAPHORE_REG_23
Definition: sli4.h:288
COMMON_SET_ACTIVE_PROFILE.
Definition: sli4.h:1579
void * sli_queue_iscsi_wqe_complete(sli4_t *sli4, sli4_queue_t *q, uint8_t wqe_index)
Processes a solicited IO completion. Moves the WRB to the free list.
Definition: sli4.c:3489
sli4_req_hdr_t hdr
Definition: sli4.h:1099
#define SLI4_INTF_VALID_SHIFT
Definition: sli4.h:82
const uint8_t sli4_fw_deinitialize[]
FW_DEINITIALIZE - deinitialize a SLI port.
Definition: sli4.c:67
#define SLI4_PORT_SEMAPHORE_REG_01
SLIPORT_SEMAPHORE - SLI Port Host and Port Status Register.
Definition: sli4.h:286
uint32_t sge_count
Definition: sli4.h:566
uint8_t sgl_chaining_capable
Definition: sli4.h:2233
int32_t sli_cmd_common_set_reconfig_link_id(sli4_t *sli4, void *buf, size_t size, uint64_t tag, ocs_dma_t *dma, uint32_t fd, uint32_t active_link_config_id)
Write a COMMON_COMMON_SET_RECONFIG_LINK_ID command.
Definition: sli4.c:1729
static int32_t sli_cmd_common_read_transceiver_data(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint32_t page_num, uint32_t port, ocs_dma_t *dma)
Write a COMMON_READ_TRANSCEIVER_DATA command.
Definition: sli4.c:1272
#define SLI4_BMBX_MASK_LO
Definition: sli4.h:117
COMMON_CREATE_EQ.
Definition: sli4.h:945
sli4_asic_rev_e
Definition: sli4.h:2170
uint8_t is_ulp_iscsi[2]
Definition: sli4.h:2235
uint8_t wait_tcp_ack
Definition: sli4.h:2038
int32_t sli_queue_index(sli4_t *sli4, sli4_queue_t *q)
Definition: sli4.c:3897
int32_t _sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
Write an entry to the queue object.
Definition: sli4.c:3397
sli4_req_hdr_t hdr
Definition: sli4.h:1082
int32_t sli_init(sli4_t *sli4)
Definition: sli4.c:2803
sli4_asic_rev_e asic_rev
Definition: sli4.h:2274
#define SLI4_SLIPORT_CONTROL_LITTLE_ENDIAN
Definition: sli4.h:151
uint32_t sfp_a2[64]
Definition: sli4.h:2212
#define SLI4_WQ_DOORBELL(n, x, i)
Definition: sli4.h:271
static uint32_t sli_cq_doorbell(uint16_t n_popped, uint16_t id, uint8_t arm)
Definition: sli4.h:200
static int32_t sli_cmd_common_get_be_configuration_and_resources(sli4_t *sli4, void *buf, size_t size, uint64_t tag)
Write a COMMON_COMMON_GET_BE_CONFIGURATION_AND_RESOURCES command.
Definition: sli4.c:1322
sli4_port_type_e
Definition: sli4.h:2156
#define SLI4_CQ_CNT_1024
Definition: sli4.h:909
#define SLI4_OPC_COMMON_READ_TRANSCEIVER_DATA
Definition: sli4.h:531
ocs_dma_t dma
Definition: sli4.h:2048
#define SLI4_IF_TYPE_LANCER_FC_ETH
Definition: sli4.h:94
#define OCS_DEBUG_ENABLE_WQ_DUMP
Definition: ocs_debug.h:157
#define SLI4_SLIPORT_CONTROL_IP
Definition: sli4.h:153
uint8_t fw_on_flash_version_string[32]
Definition: sli4.h:662
uint32_t tag[2]
Definition: sli4.h:572
uint32_t iface_default
Definition: sli4.h:2205
#define SLI4_ACQE_EVENT_CODE_ISCSI
Definition: sli4.h:1815
const sli4_reg_t regmap[SLI4_REG_MAX][SLI4_MAX_IF_TYPES]
Define the mapping of registers to their BAR and offset.
Definition: sli4.c:120
void * arg
Definition: ocs_hal.h:494
COMMON_SET_BE_CONFIGURATION_AND_RESOURCES (v1)
Definition: sli4.h:1162