Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ocs_elxu.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015, Emulex
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 /**
34  * @file
35  * Elxutility interface code
36  */
37 
38 
39 #include "ocs.h"
40 #include "ocs_ioctl.h"
41 
42 /**
43  * @brief Defines the structure of a FC SLI_CONFIG mailbox command.
44  */
45 // TODO - FC specific - should be native mailbox commands
46 typedef struct {
47  unsigned reserved:8;
48  unsigned command:8;
49  unsigned status:16;
50 
51  unsigned emb:1;
52  unsigned :2;
53  unsigned pcmd_count:5;
54  unsigned :24;
55 
56  uint32_t payload_length;
57 
58  uint32_t tag_lo;
59  uint32_t tag_hi;
60  unsigned :32;
62 
63 /**
64  * @brief Defines the common mailbox header structure.
65  */
66 typedef struct {
67  uint32_t opcode:8;
68  uint32_t subsystem:8;
69  uint32_t :16;
70 
71  union {
72  struct {
73  uint32_t timeout; // (out) timeout (in) status/add'l status
74  } out;
75  struct {
76  uint32_t status:8;
77  uint32_t additional_status:8;
78  uint32_t :16;
79  } in;
80  } word1;
81 
82  uint32_t request_length;
83 
86 
87 static int32_t __ocs_ioctl_mbox_cb(ocs_hal_t *hal, int32_t status, ocs_command_ctx_t *ctx);
88 
89 /**
90  * @brief Converts a FC SLI_CONFIG command to the iSCSI format
91  *
92  * @param mcmd the IOCTL comand received
93  * @param ctx the iSCSI SLI command context
94  * @param dma for non-embedded mailbox commands, this field provides the DMA
95  * memory for the command.
96  */
97 static void
99 {
100  mbox_sli_config_t *sli_config = (mbox_sli_config_t *)mcmd->payload;
101  void *ioctl_cmd = (((uint8_t*)mcmd->payload) + sizeof(mbox_sli_config_t));
102  sli4_mqe_hdr_t *mqe_hdr = (sli4_mqe_hdr_t *)ctx->cmd;
103  uint32_t *sgl;
104 
105  ocs_memset(ctx->cmd, 0, ARRAY_SIZE(ctx->cmd));
106 
107  mqe_hdr->payload_length = sli_config->payload_length;
108  if (sli_config->emb) {
109  mqe_hdr->embedded = 1;
110 
111  /* Copy the IOCTL command into the mailbox cmd */
112  ocs_memcpy(ctx->cmd + sizeof(sli4_mqe_hdr_t),
113  ioctl_cmd, sli_config->payload_length);
114  } else {
115  mqe_hdr->sge_count = 1;
116  /* Fill in the SGL */
117  sgl = (uint32_t*)(ctx->cmd + sizeof(sli4_mqe_hdr_t));
118  sgl[0] = ocs_addr32_lo(dma->phys);
119  sgl[1] = ocs_addr32_hi(dma->phys);
120  sgl[2] = dma->size;
121  }
122 }
123 
124 /**
125  * @brief Converts an iSCSI result back into the FC SLI_CONFIG format
126  *
127  * @param mcmd the IOCTL comand received
128  * @param ctx the iSCSI SLI command context
129  * @param status the command status
130  */
131 static void
133 {
134  mbox_sli_config_t *sli_config = (mbox_sli_config_t *)mcmd->payload;
135  void *ioctl_cmd = (((uint8_t*)mcmd->payload) + sizeof(mbox_sli_config_t));
136 
137  sli_config->status = status;
138  if (sli_config->emb) {
139  /* Copy the IOCTL command into the mailbox cmd */
140  ocs_memcpy(ioctl_cmd,
141  ctx->cmd + sizeof(sli4_mqe_hdr_t), sli_config->payload_length);
142  }
143 }
144 
145 
146 int32_t
147 ocs_elxu(ocs_t *ocs, ocs_ioctl_elxu_mbox_t *mcmd)
148 {
149  int32_t rc = 0;
150  mbox_sli_config_t *sli_config = NULL;
151  ocs_dma_t dma = { 0 };
152  ocs_sem_t waitsem;
153  ocs_command_ctx_t *ctx;
154  ocs_hal_t *hal = &ocs->hal;
155  void *ioctl_cmd = (((uint8_t*)mcmd->payload) + sizeof(mbox_sli_config_t));
156 
157  uint32_t max_bytes;
158  // sanity checks
159  if ((ELXU_BSD_MAGIC != mcmd->magic) ||
160  (sizeof(*mcmd) != mcmd->size)) {
161  ocs_log_test(ocs, "malformed command m=%08x s=%08x\n",
162  mcmd->magic, mcmd->size);
163  return EINVAL;
164  }
165 
166  ctx = ocs_hal_command_get_ctx(hal);
167  if (!ctx) {
168  ocs_log_err(hal->os, "no buffer for command\n");
169  return ENOMEM;
170  }
171 
172  sli_config = (mbox_sli_config_t *)mcmd->payload;
173 
174  if (sli_config->emb) {
175  mbox_common_t *req = (mbox_common_t *)ioctl_cmd;
176 
177  switch (req->opcode) {
179  if (mcmd->out_bytes) {
181 
182  if (ocs_dma_alloc(ocs, &dma, mcmd->out_bytes, 4096)) {
183  ocs_log_err(ocs, "COMMON_READ_OBJECT - %" PRId64 "allocation failed\n",
184  mcmd->out_bytes);
185  ocs_hal_command_free_ctx(hal, ctx);
186  return ENXIO;
187  }
188 
189  memset(dma.virt, 0, mcmd->out_bytes);
190 
193  rdobj->host_buffer_descriptor[0].u.data.buffer_address_low = ocs_addr32_lo(dma.phys);
194  rdobj->host_buffer_descriptor[0].u.data.buffer_address_high = ocs_addr32_hi(dma.phys);
195 
196  }
197  break;
199  {
201 
202  if (ocs_dma_alloc(ocs, &dma, wrobj->desired_write_length, 4096)) {
203  ocs_log_err(ocs, "COMMON_WRITE_OBJECT - %d allocation failed\n",
204  wrobj->desired_write_length);
205  ocs_hal_command_free_ctx(hal, ctx);
206  return ENXIO;
207  }
208  // setup the descriptor
211  wrobj->host_buffer_descriptor[0].u.data.buffer_address_low = ocs_addr32_lo(dma.phys);
212  wrobj->host_buffer_descriptor[0].u.data.buffer_address_high = ocs_addr32_hi(dma.phys);
213 
214  // copy the data into the DMA buffer
215  if (ocs_copy_from_user(dma.virt, (void *)mcmd->in_addr, mcmd->in_bytes)) {
216  ocs_log_test(ocs, "copy_from_user() failed\n");
217  ocs_hal_command_free_ctx(hal, ctx);
218  return EFAULT;
219  }
220 
221  }
222  break;
224  break;
226  if (mcmd->out_bytes) {
229  if (ocs_dma_alloc(ocs, &dma, mcmd->out_bytes, 4096)) {
230  ocs_log_err(ocs, "COMMON_READ_OBJECT_LIST - %" PRId64 "lld allocation failed\n",
231  mcmd->out_bytes);
232  ocs_hal_command_free_ctx(hal, ctx);
233  return ENXIO;
234  }
235 
236  ocs_memset(dma.virt, 0, mcmd->out_bytes);
237 
240  rdobj->host_buffer_descriptor[0].u.data.buffer_address_low = ocs_addr32_lo(dma.phys);
241  rdobj->host_buffer_descriptor[0].u.data.buffer_address_high = ocs_addr32_hi(dma.phys);
242 
243  }
244  break;
250  break;
251 
252  default:
253  ocs_log_test(ocs, "in=%p (%" PRId64 ") out=%p (%" PRId64 ")\n",
254  (void *)mcmd->in_addr, mcmd->in_bytes,
255  (void *)mcmd->out_addr, mcmd->out_bytes);
256  ocs_log_test(ocs, "unknown (opc=%#x)\n",
257  req->opcode);
258  break;
259  }
260  } else {
261  max_bytes = max(mcmd->in_bytes, mcmd->out_bytes);
262  if (ocs_dma_alloc(ocs, &dma, max_bytes, 4096)) {
263  ocs_log_err(ocs, "non-embedded - %u allocation failed\n", max_bytes);
264  ocs_hal_command_free_ctx(hal, ctx);
265  return ENXIO;
266  }
267 
268  if (ocs_copy_from_user(dma.virt, (void *)mcmd->in_addr, mcmd->in_bytes)) {
269  ocs_log_test(ocs, "copy_from_user failed\n");
270  ocs_hal_command_free_ctx(hal, ctx);
271  return ENXIO;
272  }
273  }
274 
275  ocs_sem_init(&waitsem, 0, "waitsem");
276 
277  /* TODO - Mbox command should be in native format */
278  ocs_elxu_convert_cmd_to_iscsi(mcmd, ctx, &dma);
279 
280  ctx->upper_arg = mcmd;
281  ctx->cb_arg = &waitsem;
282  ctx->cb = __ocs_ioctl_mbox_cb;
283 
284  if (ocs_hal_command_queue(hal, ctx)) {
285  ocs_log_err(hal->os, "Error posting mailbox command\n");
286  ocs_hal_command_free_ctx(hal, ctx);
287  return ENXIO;
288  }
289 
290  if (ocs_sem_p(&waitsem, OCS_SEM_FOREVER) == 0) {
291  if (mcmd->out_bytes && dma.virt) {
292  if (ocs_copy_to_user((void *)mcmd->out_addr, dma.virt, mcmd->out_bytes)) {
293  ocs_log_test(ocs, "copy_to_user failed\n");
294  rc = -ENXIO;
295  }
296  }
297  } else {
298  ocs_log_test(ocs, "hal command was interrupted\n");
299  rc = -ENXIO;
300  }
301 
302  ocs_dma_free(ocs, &dma);
303  ocs_hal_command_free_ctx(hal, ctx);
304 
305  return rc;
306 }
307 
308 
309 static int32_t
311 {
312  ocs_sem_t *sem = ctx->cb_arg;
313  ocs_ioctl_elxu_mbox_t *mcmd = ctx->upper_arg;
314 
315  // TODO - Use native format
316  /* Convert the response back to FC format */
317  ocs_elxu_convert_status_to_fc(mcmd, ctx, status);
318 
319  ocs_sem_v(sem);
320 
321  return 0;
322 
323 }
uint32_t tag_hi
Definition: ocs_elxu.c:59
uint32_t payload_length
Definition: ocs_elxu.c:56
void * upper_arg
Definition: ocs_hal.h:388
ocs_os_handle_t os
Definition: ocs_hal.h:725
uint32_t opcode
Definition: ocs_elxu.c:67
sli4_bde_t host_buffer_descriptor[0]
Definition: sli4.h:1718
Defines the structure of a FC SLI_CONFIG mailbox command.
Definition: ocs_elxu.c:46
#define SLI4_OPC_COMMON_SET_BE_CONFIGURATION_AND_RESOURCES
Definition: sli4.h:533
mailbox queue Element header
Definition: sli4.h:564
ocs_hal_rtn_e ocs_hal_command_queue(ocs_hal_t *hal, ocs_command_ctx_t *ctx)
Issue a SLI command.
Definition: ocs_hal.c:2164
uint32_t buffer_length
Definition: sli4.h:351
#define SLI4_OPC_COMMON_SET_PHYSICAL_LINK_CONFIG
Definition: sli4.h:519
static void ocs_elxu_convert_cmd_to_iscsi(ocs_ioctl_elxu_mbox_t *mcmd, ocs_command_ctx_t *ctx, ocs_dma_t *dma)
Converts a FC SLI_CONFIG command to the iSCSI format.
Definition: ocs_elxu.c:98
ocs_command_ctx_t * ocs_hal_command_get_ctx(ocs_hal_t *hal)
Issue a SLI command.
Definition: ocs_hal.c:2065
int32_t ocs_elxu(ocs_t *ocs, ocs_ioctl_elxu_mbox_t *mcmd)
Definition: ocs_elxu.c:147
sli4_bde_t host_buffer_descriptor[0]
Definition: sli4.h:1668
HAL object.
Definition: ocs_hal.h:724
IOCTL_CMD_IOCTL_ELXU_MBOX ioctl structure.
Definition: ocs_ioctl.h:89
unsigned status
Definition: ocs_elxu.c:49
struct sli4_bde_t::@23::@24 data
HAL command context.
Definition: ocs_hal.h:360
void ocs_hal_command_free_ctx(ocs_hal_t *hal, ocs_command_ctx_t *ctx)
Issue a SLI command.
Definition: ocs_hal.c:2089
unsigned emb
Definition: ocs_elxu.c:51
COMMON_READ_OBJECT.
Definition: sli4.h:1659
uint32_t tag_lo
Definition: ocs_elxu.c:58
#define SLI4_OPC_COMMON_WRITE_OBJECT
Definition: sli4.h:548
static int32_t __ocs_ioctl_mbox_cb(ocs_hal_t *hal, int32_t status, ocs_command_ctx_t *ctx)
Definition: ocs_elxu.c:310
uint32_t embedded
Definition: sli4.h:566
uint8_t payload[256]
Definition: ocs_ioctl.h:92
uint32_t timeout
Definition: ocs_elxu.c:73
uint32_t request_length
Definition: ocs_elxu.c:82
COMMON_READ_OBJECT_LIST.
Definition: sli4.h:1709
sli4_bde_t host_buffer_descriptor[0]
Definition: sli4.h:1686
#define SLI4_OPC_COMMON_READ_OBJECT
Definition: sli4.h:547
int32_t(* cb)(struct ocs_hal_s *, int32_t, struct ocs_command_ctx_s *)
Definition: ocs_hal.h:373
#define SLI4_OPC_COMMON_READ_OBJECT_LIST
Definition: sli4.h:550
#define ELXU_BSD_MAGIC
Definition: ocs_ioctl.h:80
#define SLI4_OPC_COMMON_ISCSI_SET_TCP_PARAMETERS
Definition: sli4.h:558
uint8_t cmd[SLI4_BMBX_SIZE]
Definition: ocs_hal.h:370
COMMON_WRITE_OBJECT.
Definition: sli4.h:1677
union sli4_bde_t::@23 u
Defines the common mailbox header structure.
Definition: ocs_elxu.c:66
uint32_t bde_type
Definition: sli4.h:351
#define SLI4_BDE_TYPE_BDE_64
Definition: sli4.h:372
#define SLI4_OPC_COMMON_ISCSI_GET_CONNECTION_INFO
Definition: sli4.h:559
uint32_t payload_length
Definition: sli4.h:571
uint32_t actual_response_length
Definition: ocs_elxu.c:84
static void ocs_elxu_convert_status_to_fc(ocs_ioctl_elxu_mbox_t *mcmd, ocs_command_ctx_t *ctx, int32_t status)
Converts an iSCSI result back into the FC SLI_CONFIG format.
Definition: ocs_elxu.c:132
uint32_t sge_count
Definition: sli4.h:566
#define SLI4_OPC_COMMON_DELETE_OBJECT
Definition: sli4.h:549
#define SLI4_OPC_COMMON_READ_TRANSCEIVER_DATA
Definition: sli4.h:531