Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ocs_openiscsi_ini.c
Go to the documentation of this file.
1 /**
2  * Copyright (C) 2013-2015 Emulex
3  * All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License version 2
7  * as published by the Free Software Foundation. The full GNU General
8  * Public License can be found at <http://www.gnu.org/licenses/>.
9  *
10  * Written by: Chris Moore (chris.moore@emulex.com)
11  *
12  * Emulex
13  * 3333 Susan Street
14  * Costa Mesa, CA 92626
15  */
16 
17 
18 /**
19  * @file
20  * This file contains the linkage to functions that implement the separately loadable
21  * back end initiator.
22  *
23  * Load sequence:
24  * - Base driver is loaded.
25  * - Separately loadable module (SLM) back-end initiator is loaded.
26  * - SLM calls ocs_scsi_ini_driver_init().
27  * - SLM enumerates each OCS object, and calls ocs_scsi_ini_new_device().
28  */
29 
30 #include <scsi/scsi.h>
31 #include <scsi/scsi_device.h>
32 #include <scsi/scsi_eh.h>
33 #include <scsi/scsi_host.h>
34 #include <scsi/scsi_tcq.h>
35 #include <scsi/scsi_transport.h>
36 #include <scsi/libiscsi.h>
37 #include <scsi/scsi_transport_iscsi.h>
38 #include <linux/if_ether.h>
39 
40 #include "ocs.h"
41 #include "ocs_ini_template.h"
42 #include "ocs_scsi_ini.h"
43 #include "ocs_iscsi_spec.h"
44 #include "ocs_iscsi_api.h"
45 #include "ocs_session.h"
46 
47 /*!
48  * @defgroup openiscsi_initiator Open-iSCSI Interface Module (ocs_openiscsi)
49  */
50 
51 static struct scsi_transport_template *transport_template;
52 
53 /* forward declarations */
54 int32_t ocs_scsi_cmd_cb(ocs_io_t *, ocs_scsi_io_status_e,
55  ocs_scsi_cmd_resp_t *, uint32_t , void *);
56 static int32_t ocs_lnx_xport_unsol_cb(void *arg, ocs_cxn_t *cxn,
58  uint32_t hdr_len, ocs_hal_rq_buffer_t *data,
59  uint32_t data_len, uint8_t code);
60 static void ocs_lnx_xport_link_state(ocs_t *ocs, ocs_link_state_e link_state);
61 int32_t ocs_scsi_map_sgl(ocs_t *, struct scsi_cmnd *, ocs_scsi_sgl_t *, uint32_t *);
62 static int ocs_conn_update_context(struct iscsi_conn *conn);
64  ocs_hal_abort_type_e abort_type);
65 static int ocs_eh_abort(struct scsi_cmnd *sc);
66 
67 extern struct iscsi_transport ocs_lnx_xport_iscsi;
68 
69 /* Data structures */
70 typedef struct ocs_lnx_iscsi_arg_s {
71  ocs_sem_t sem;
72  uint32_t status;
74 
75 /* defines */
76 #define ocs_scsi_midlayer_result(host_code, scsi_code) (((host_code) << 16) | scsi_code)
77 
78 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
79 #define SCSI_ISCSI_XPORT_ATTR_IS_VISIBLE_V1
80 #else
81 #define SCSI_ISCSI_XPORT_ATTR_IS_VISIBLE_V0
82 #endif
83 
84 /* globals */
85 ocs_scsi_ini_template_t ocs_iscsi_ini_template = {
86  .ocs_scsi_ini_new_domain = ocs_scsi_ini_new_domain,
87  .ocs_scsi_ini_del_domain = ocs_scsi_ini_del_domain,
88  .ocs_scsi_ini_new_sport = ocs_scsi_ini_new_sport,
89  .ocs_scsi_ini_del_sport = ocs_scsi_ini_del_sport,
90  .ocs_scsi_new_target = ocs_scsi_new_target,
91  .ocs_scsi_del_target = ocs_scsi_del_target,
92  .ocs_scsi_ini_ddump = ocs_scsi_ini_ddump,
93 };
94 
95 /**
96  * @ingroup openiscsi_initiator
97  * @brief Host Template.
98  *
99  * @par Description
100  * This structure is passed to the SCSI midlayer to register the
101  * module as a host.
102  */
103 struct scsi_host_template host_template = {
104  .module = THIS_MODULE,
105  .name = "Emulex OCS iSCSI midlayer interface",
106  .proc_name = "ocs",
107  .queuecommand = iscsi_queuecommand,
108 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
109  .change_queue_depth = iscsi_change_queue_depth,
110 #endif
111  .can_queue = ISCSI_DEF_XMIT_CMDS_MAX - 1,
112  .this_id = -1,
113  .sg_tablesize = OCS_DEFAULT_SG_SEG_CNT,
114  .cmd_per_lun = OCS_CMD_PER_LUN, // queue depth for each LUN
115  .eh_abort_handler = ocs_eh_abort,
116  .eh_device_reset_handler= iscsi_eh_device_reset,
117  .eh_target_reset_handler = iscsi_eh_recover_target,
118  .use_clustering = ENABLE_CLUSTERING,
119  .target_alloc = iscsi_target_alloc,
120  .max_sectors = 0xFFFF,
121  .vendor_id = OCS_NL_VENDOR_ID,
122 };
123 
124 static int ocs_eh_abort(struct scsi_cmnd *sc)
125 {
126  struct iscsi_task *task = (struct iscsi_task *)sc->SCp.ptr;
127  ocs_io_t *aborted_io;
128  ocs_hal_io_t *hio;
129  ocs_t *ocs;
130  ocs_iscsi_t *iscsi;
131  int rc;
132  ocs_io_task_t *io_task;
133 
134  io_task = (ocs_io_task_t *)task->dd_data;
135  ocs_assert(io_task, -1);
136 
137  aborted_io = io_task->io;
138  ocs_assert(aborted_io, -1);
139 
140  ocs = aborted_io->ocs;
141  ocs_assert(ocs, -1);
142 
143  iscsi = &ocs->iscsi;
144  ocs_assert(iscsi, -1);
145 
146  hio = aborted_io->hio;
147  ocs_assert(hio, -1);
148 
149  ocs_log_debug(ocs, "EH aborted on IO type=%d, icd=%d\n",
150  hio->type, hio->icd);
151 
152  rc = ocs_scsi_abort_io(iscsi->hal,
153  hio,
155  if (rc) {
156  ocs_log_test(ocs, "ocs scsi abort io failed\n");
157  }
158 
159  return iscsi_eh_abort(sc);
160 }
161 
162 int32_t ocs_ramlog_printf(void *os, const char *fmt, ...)
163 {
164  return 0;
165 }
166 
167 void ocs_print_stack(void)
168 {
169  dump_stack();
170 }
171 
172 
173 /**
174  * @brief Initialize initiator client.
175  *
176  * @par Description
177  * Called by OS initialization code to initialize initiator
178  * client. This is called prior to any PCI device enumeration.
179  * @n @n
180  * Registers with open-iscsi as a transport.
181  *
182  * @param initiator TRUE for initiator mode
183  *
184  * @return Returns 0 on success, or a negative error code value on failure.
185  */
186 int32_t
187 ocs_scsi_ini_driver_init(int32_t initiator)
188 {
189  int rc = 0;
190 
191  transport_template = iscsi_register_transport(&ocs_lnx_xport_iscsi);
192  if (transport_template) {
193  printk(KERN_INFO "%s: Registered transport with open-iscsi\n", __func__);
194  } else {
195  printk(KERN_INFO "%s: Failed to register transport with open-iscsi\n", __func__);
196  rc = -1;
197  }
198 
199  return rc;
200 }
201 
202 /**
203  * @brief initiator client exit
204  *
205  * @par Description
206  * Called by OS driver-wide clean-up/exit code to clean up
207  * initiator client.
208  *
209  * @param initiator TRUE for initiator mode
210  *
211  * @return Returns 0 on success, or a negative error code value on failure.
212  */
213 int32_t
214 ocs_scsi_ini_driver_exit(int32_t initiator)
215 {
216  iscsi_unregister_transport(&ocs_lnx_xport_iscsi);
217  return 0;
218 }
219 
220 /**
221  * @ingroup openiscsi_initiator
222  * @brief Initializes any initiator fields on the ocs structure.
223  *
224  * @par Description
225  * Called by the OS initialization code when a new device is discovered.
226  *
227  * @param ocs Pointer to ocs.
228  *
229  * @return Returns 0 on success, or a non-zero error code value
230  * on failure.
231  */
232 
233 int32_t
235 {
236  struct Scsi_Host *shost = NULL;
237  ocs_iscsi_host_private_t *host_private = NULL;
238  int ret;
239 
240  printk("%s: entry\n", __func__);
241 
242  /* Register with base driver */
243  ret = ocs_scsi_register_ini_templ(ocs, &ocs_iscsi_ini_template);
244  if (ret) {
245  printk("%s: template registration failed\n", __func__);
246  return -ENODEV;
247  }
248  printk("%s: template registration successful\n", __func__);
249 
250  /* Allocate a SCSI Host structure in the midlayer */
251  shost = iscsi_host_alloc(&host_template, sizeof(*host_private), 0);
252  if (!shost) {
253  printk("%s: failed to allocate Scsi_Host struct\n", __func__);
254  return -1;
255  }
256 
257  /* save shost to initiator-client context */
258  ocs->ini_ocs.shost = shost;
259 
260  /* save ocs information to shost LLD-specific space */
261  host_private = iscsi_host_priv(shost);
262  host_private->ocs = ocs;
263 
264  /*
265  * Set initial can_queue value to the max SCSI IOs. This is the maximum
266  * global queue depth (as opposed to the per-LUN queue depth -- .cmd_per_lun
267  * This may need to be adjusted for I+T mode.
268  */
269  shost->can_queue = ocs_scsi_get_property(ocs, OCS_SCSI_MAX_IOS);
270  shost->max_cmd_len = 16; // 16-byte CDBs
271 
272  /* can only accept (from mid-layer) as many SGEs as we've pre-registered */
273  shost->sg_tablesize = ocs_scsi_get_property(ocs, OCS_SCSI_MAX_SGL);
274 
275  /* attach iSCSI Transport template to shost */
276  shost->transportt = transport_template;
277 
278  /* register callback for unsolicited initiator event*/
280  if (ret) {
281  printk("%s: failed to register unsolicited callback\n", __func__);
282  goto ocs_dealloc_iscsi_host;
283  }
284 
285  /* Register to received link state change events */
287  if (ret != 0) {
288  printk("Failed to register a link state callback function\n");
289  }
290 
291  /* get pci_dev structure and add host to SCSI ML */
292  ret = iscsi_host_add(shost, &ocs->ocs_os.pdev->dev);
293  if (ret) {
294  printk("%s: failed iscsi_host_add\n", __func__);
295  goto ocs_dealloc_iscsi_host;
296  }
297 
298  // TODO: How do we determine IPV4 or IPV6?
299  iscsi_create_iface(shost, &ocs_lnx_xport_iscsi, ISCSI_IFACE_TYPE_IPV4, 0, 0);
300 
301  return 0;
302 
303 ocs_dealloc_iscsi_host:
304  iscsi_host_free(shost);
305  ocs->ini_ocs.shost = NULL;
306  return ret;
307 }
308 
309 /**
310  * @ingroup openiscsi_initiator
311  * @brief Tears down initiator members of ocs structure.
312  *
313  * @par Description
314  * Called by the OS code when the device is removed.
315  *
316  * @param ocs Pointer to ocs.
317  *
318  * @return Returns 0.
319  */
320 
321 int32_t
323 {
324  if (ocs->ini_ocs.shost) {
325  printk("%s: Removing scsi%d from SCSI Midlayer\n", __func__, ocs->ini_ocs.shost->host_no);
326  iscsi_host_remove(ocs->ini_ocs.shost);
327  ocs->ini_ocs.shost = NULL;
328  }
329 
330  /* Remove our link state callback registration */
332 
333  /* Unregister from base driver */
334  ocs_scsi_unregister_ini_templ(ocs);
335 
336  printk("%s: template unregistered\n", __func__);
337  return 0;
338 }
339 
340 /**
341  * @ingroup openiscsi_initiator
342  * @brief Accept new domain notification.
343  *
344  * @par Description
345  * Called by the base driver when a new domain is discovered. An initiator-client
346  * will accept this call to prepare for new remote node notifications
347  * arising from ocs_scsi_new_target(). The domain context has the element
348  * <b>ocs_scsi_ini_domain_t ini_domain</b> which is
349  * declared by the initiator-client code and is used for initiator-client private data.
350  * @n @n @b Notes:
351  * - This function will only be called if the base-driver has been enabled for initiator
352  * capability.
353  * - This call is made to initiator-client backends. The ocs_scsi_tgt_new_domain()
354  * function is called to target-server backends.
355  * - For the open-iscsi driver, nothing needs to be done for a new
356  * domain, but this function is left in place as a template for
357  * future use.
358  *
359  * @param domain Pointer to domain.
360  *
361  * @return Returns 0 for success, or a negative error code value for failure.
362  */
363 int32_t ocs_scsi_ini_new_domain(ocs_domain_t *domain)
364 {
365  ocs_assert(domain, -1);
366  ocs_assert(domain->ocs, -1);
367  printk("%s()\n", __func__);
368  return 0;
369 }
370 
371 /**
372  * @ingroup openiscsi_initiator
373  * @brief Accept domain lost notification.
374  *
375  * @par Description
376  * Called by the base driver when a domain goes away. An initiator-client
377  * uses this call to clean up all domain scoped resources.
378  * @n @n @b Notes:
379  * - This function is only called if the base driver has been enabled for initiator
380  * capability.
381  * - This call is made to initiator-client backends. The ocs_scsi_tgt_del_domain()
382  * function is called to target-server backends.
383  * - For the open-iscsi initiator nothing needs to be done when
384  * deleting a domain, but this function is left in place as a
385  * template for future use.
386  *
387  * @param domain Pointer to domain.
388  *
389  * @return Returns 0 for success, or a negative error code value for failure.
390  */
391 void ocs_scsi_ini_del_domain(ocs_domain_t *domain)
392 {
393  ocs_assert(domain);
394  ocs_assert(domain->ocs);
395 }
396 
397 /**
398  * @ingroup openiscsi_initiator
399  * @brief Process creation of a new SPORT.
400  *
401  * @par Description
402  * This function is called by the base driver when a new SPORT
403  * is discovered.
404  * @n @n
405  * For the open-iscsi initiator, no action is taken on creation
406  * of a SPORT, but this function is left here as a template for
407  * future use.
408  *
409  * @param sport The SPORT that has been created.
410  *
411  * @return Returns 0.
412  */
413 int32_t ocs_scsi_ini_new_sport(ocs_sport_t *sport)
414 {
415  printk("New SPORT: %s\n", sport->display_name);
416  return 0;
417 }
418 
419 /**
420  * @ingroup openiscsi_initiator
421  * @brief Process deletion of a SPORT.
422  *
423  * @par Description
424  * This function is called by the base driver when a SPORT
425  * has been deleted.
426  * @n @n
427  * For the open-iscsi initiator, no action is taken on deletion
428  * of a SPORT, but this function is left here as a template for
429  * future use.
430  *
431  * @param sport The SPORT that has been deleted.
432  *
433  * @return Returns 0.
434  */
435 void ocs_scsi_ini_del_sport(ocs_sport_t *sport)
436 {
437  printk("Del SPORT: %s\n", sport->display_name);
438 }
439 
440 /**
441  * @ingroup openiscsi_initiator
442  * @brief Receive notification of a new SCSI target node.
443  *
444  * @par Description
445  * Sent by the base driver to notify the initiator-client of the presence of a new
446  * remote target. The initiator-server may use this call to prepare for
447  * inbound IO from this node.
448  * @n @n @b Note:
449  * This function is only called if the base driver is enabled for initiator capability.
450  *
451  * @param node Pointer to new remote initiator node.
452  *
453  * @return None.
454  *
455  */
456 
457 int32_t ocs_scsi_new_target(ocs_node_t *node)
458 {
459  return 0;
460 }
461 
462 /**
463  * @ingroup openiscsi_initiator
464  * @brief Delete a SCSI target node.
465  *
466  * @par Description
467  * Sent by the base driver to notify the initiator-client that a remote target is now gone.
468  * The initiator-client should terminate and clean up all I/Os associated with the node.
469  * @n @n
470  * The ocs_node_t structure has an element of type ocs_scsi_ini_node_t named
471  * ni_node that is declared and used by a target-server for private
472  * information.
473  * @n @n @b Note:
474  * This function is only called if the base driver is enabled for target capability.
475  *
476  * @param node Pointer node being deleted.
477  * @param reason Reason for deleting the target.
478  *
479  * @return
480  * - OCS_SCSI_CALL_ASYNC if target delete is queued for async completion.
481  * - OCS_SCSI_CALL_COMPLETE if call completed
482  * - error
483  *
484  */
485 int32_t ocs_scsi_del_target(ocs_node_t *node, ocs_scsi_del_target_reason_e reason)
486 {
489  printk("%s()\n", __func__);
490  return OCS_SCSI_CALL_COMPLETE;
491 }
492 
493 /**
494  * @ingroup openiscsi_initiator
495  * @brief Generate driver dump data for debugging.
496  *
497  * @par Description
498  * This function is a placeholder for future use in dumping
499  * driver debug data.
500  *
501  * @param textbuf The structure into which the data is dumped.
502  * @param type The type of data to dump.
503  * @param obj TBD
504  */
506 {
507 }
508 
509 /**
510  * @brief Set scsi_cmnd check condition.
511  *
512  * @par Description
513  * This function is called by the LLD to indicate that the given
514  * scsi_cmnd resulted in a check condition. Sense data will be
515  * filled out independently.
516  *
517  * @param scsi_cmd Command for which to set check condition.
518  *
519  */
520 static void
521 ocs_scsi_cmnd_result_chk_cond(struct scsi_cmnd *scsi_cmd)
522 {
523  scsi_cmd->result = DRIVER_SENSE << 24 |
524  ocs_scsi_midlayer_result(DID_ABORT, SAM_STAT_CHECK_CONDITION);
525 }
526 
527 /**
528  * @brief SCSI IO callback function.
529  *
530  * @par Description
531  * This function is called back by the base driver to indicate
532  * that the given IO has completed.
533  *
534  * @param io Pointer to IO that has completed.
535  * @param status Status of IO.
536  * @param rsp Pointer to response.
537  * @param flags Flags.
538  * @param arg Pointer to argument passed when sending IO.
539  *
540  */
541 int32_t
543  ocs_io_t *io,
544  ocs_scsi_io_status_e status,
545  ocs_scsi_cmd_resp_t *rsp,
546  uint32_t flags,
547  void *arg)
548 {
549  struct scsi_cmnd *scsi_cmd = io->ini_io.scsi_cmd;
550  struct scsi_sense_hdr sshdr;
551  int sense_len;
552  ocs_assert(io, -1);
553  ocs_assert(scsi_cmd, -1);
554 
555  switch (status) {
557  /* success */
558  scsi_cmd->result = ocs_scsi_midlayer_result(DID_OK, rsp->scsi_status);
559  break;
561  if (rsp->scsi_status == 2) {
562  /* set check condition indication in scsi_cmd and copy sense data */
563  sense_len = MIN(rsp->sense_data_length, SCSI_SENSE_BUFFERSIZE);
565  ocs_memcpy(scsi_cmd->sense_buffer, rsp->sense_data, sense_len);
566  scsi_normalize_sense(scsi_cmd->sense_buffer, sense_len, &sshdr);
567 
568  printk("%s: check condition received x%x/x%x/x%x\n",
569  __func__, sshdr.sense_key, sshdr.asc, sshdr.ascq);
570 
571  } else if (rsp->scsi_status == 0 && rsp->residual) {
572  /* residual non-zero but good status; treat as okay */
573  scsi_cmd->result = ocs_scsi_midlayer_result(DID_OK, rsp->scsi_status);
574  } else {
575  /* everything else; send generic error */
576  printk("%s: OCS_SCSI_STATUS_ERROR, scsi_status=%d\n",
577  __func__, rsp->scsi_status);
578  scsi_cmd->result = ocs_scsi_midlayer_result(DID_ERROR, 0);
579  }
580  break;
582  scsi_cmd->result = ocs_scsi_midlayer_result(DID_ERROR, 0);
583  break;
584  default:
585  /* for now, set DID_ERROR */
586  scsi_cmd->result = ocs_scsi_midlayer_result(DID_ERROR, 0);
587  printk("%s: Unhandled status=%d\n", __func__, status);
588  break;
589  }
590 
591  return 0;
592 }
593 
594 /**
595  * @brief Map mid-layer SGLs to ocs SGLs
596  *
597  * @par Description
598  * This function is called by ocs_queuecommand() to map the SGL
599  * received from the mid-layer to an ocs SGL that can be used by
600  * the SCSI API.
601  *
602  * @param ocs The ocs pointer associated with this request.
603  * @param scsi_cmd Command received from mid-layer.
604  * @param sgl Resulting ocs SGL.
605  * @param sgl_cnt [in] - Maximum number of SGLs that @c sgl can
606  * accommodate; [out] - The resulting number of SGL
607  * entries.
608  *
609  */
610 int32_t
612  ocs_t *ocs,
613  struct scsi_cmnd *scsi_cmd,
614  ocs_scsi_sgl_t *sgl,
615  uint32_t *sgl_cnt)
616 {
617  int num_seg = 0;
618  int i = 0;
619  struct scatterlist *sgel = NULL;
620 
621  ocs_assert(scsi_sg_count(scsi_cmd), -1);
622  num_seg = scsi_dma_map(scsi_cmd);
623 
624  if (num_seg > *sgl_cnt) {
625  /* shouldn't happen since we've already given mid-layer the max number */
626  printk("%s: num SGEs=%d requested exceeds max=%d\n",
627  __func__, num_seg, *sgl_cnt);
628  return -1;
629  }
630 
631  /* loop through each scsi_cmd SGE and fill out OCS-specific SGL */
632  for (i = 0, sgel = scsi_sglist(scsi_cmd); i < (num_seg); i++, sgel = sg_next(sgel)) {
633  //scsi_for_each_sg(scsi_cmd, sgel, nseg, i) {
634  sgl[i].addr = sg_dma_address(sgel);
635  sgl[i].len = sg_dma_len(sgel);
636  }
637  *sgl_cnt = i;
638 // printk("%s: number of SGEs mapped=%d\n", __func__, *sgl_cnt);
639 
640  return 0;
641 }
642 
643 /**
644  * @ingroup openiscsi_initiator
645  * @brief Unsolicited event handler.
646  *
647  * @par Description
648  * Called by the iSCSI transport layer to handle unsolicited PDUs
649  * for initiator connections. For open-iSCSI, we don't want the
650  * iSCSI transport layer to receive unsolicited PDUs and push
651  * them through state machines. The Linux iSCSI transport layer
652  * (open-iSCSI) manages these.
653  *
654  * @param arg TBD.
655  * @param cxn TBD.
656  * @param bhs TBD.
657  * @param hdr_len TBD.
658  * @param data TBD.
659  * @param data_len TBD.
660  * @param code TBD.
661  *
662  * @return Returns 0 on success; or a negative error code value
663  * on failure.
664  */
665 static
666 int32_t
668  ocs_cxn_t *cxn,
669  ocs_hal_rq_buffer_t *bhs,
670  uint32_t hdr_len,
671  ocs_hal_rq_buffer_t *data,
672  uint32_t data_len,
673  uint8_t code)
674 {
675  int rc = 0;
676  struct iscsi_hdr *hdr = bhs->dma.virt;
677  ocs_iscsi_t *iscsi = (ocs_iscsi_t *)arg;
678  ocs_ep_t *ocs_ep;
679  ocs_conn_t *ocs_conn;
680  struct iscsi_conn *conn;
681  struct iscsi_task *task;
682  ocs_io_task_t *io_task = NULL;
683  ocs_io_t *io = NULL;
684 
685  ocs_ep = cxn->ini_node.ocs_ep;
686  ocs_assert(ocs_ep, -1);
687  ocs_conn = ocs_ep->ocs_conn;
688  ocs_assert(ocs_conn, -1);
689  conn = ocs_conn->conn;
690  ocs_assert(conn, -1);
691 
692  switch(hdr->opcode & ISCSI_OPCODE_MASK) {
693  case ISCSI_RESP_LOGIN:
694  {
695  struct iscsi_login_rsp *rsp_hdr = (struct iscsi_login_rsp *)hdr;
696 
697  /*
698  * libiscsi will handle most of the LOGIN processing, but we need to set
699  * up the fields in our ocs_cxn_t to show that LOGIN is complete
700  */
701  if ((rsp_hdr->status_class == ISCSI_STATUS_CLS_SUCCESS) &&
702  ((rsp_hdr->flags) & ISCSI_FLAG_LOGIN_TRANSIT) &&
703  (ISCSI_LOGIN_NEXT_STAGE(rsp_hdr->flags) == ISCSI_FULL_FEATURE_PHASE)) {
704  ocs_session_exp_cmd_sn_set(cxn, ocs_be32toh(rsp_hdr->exp_cmdsn));
705  ocs_session_max_cmd_sn_set(cxn, ocs_be32toh(rsp_hdr->max_cmdsn));
707  cxn->cxn_state = CONN_STATE_FULL_FEATURE;
708  }
709 
710  task = conn->login_task;
711  }
712  break;
713  case ISCSI_RESP_TEXT:
714  case ISCSI_RESP_LOGOUT:
715  task = conn->login_task;
716  break;
717  default:
718  task = conn->task;
719  break;
720  }
721 
722  if (task != NULL) {
723  io_task = (ocs_io_task_t*) task->dd_data;
724  if (io_task != NULL) {
725  hdr->itt = io_task->original_itt;
727  io = io_task->io;
728  }
729  }
730 
731  /* Send the PDU to the openiscsi layer to handle the rest */
732  rc = iscsi_complete_pdu(conn, hdr, (data ? data->dma.virt : NULL), data_len);
733  if (rc) {
734  printk("%s: iscsi_complete_pdu failed, rc=%d\n", __func__, rc);
735  }
736 
737  if (io && io->node) {
738  ocs_scsi_io_free(io);
739  }
740 
741  /* return buffer to RX queue */
742  if (!rc) {
743  ocs_iscsi_rx_buffers_free(iscsi, bhs, data);
744  }
745 
746  return rc;
747 }
748 
749 /**
750  * @ingroup openiscsi_initiator
751  * @brief Helper function for marking sessions as failed.
752  *
753  * @par Description
754  * This is a helper function used by ocs_lnx_xport_link_state.
755  * When a link goes down that function iterates over all
756  * sessions on the link and calls this function for each of
757  * them. This function then calls iscsi_session_failure for
758  * each of the sessions to let open-iscsi know that the session
759  * has failed.
760  *
761  *
762  * @param cls_session TBD.
763  */
764 static void ocs_lnx_xport_fail_session(struct iscsi_cls_session *cls_session)
765 {
766  iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED);
767 }
768 
769 /**
770  * @ingroup openiscsi_initiator
771  * @brief Called when the link changes state.
772  *
773  * @param ocs Pointer to the ocs structure.
774  * @param link_state Provides the status of the link.
775  *
776  * @return None.
777  */
778 static void ocs_lnx_xport_link_state(ocs_t *ocs, ocs_link_state_e link_state)
779 {
780  ocs_iscsi_t *iscsi;
781  struct Scsi_Host *shost;
782 
783  iscsi = &ocs->iscsi;
784  shost = ocs->ini_ocs.shost;
785 
786  /* Notify libiscsi of the connection state change */
787  if (link_state == OCS_LINK_STATE_DOWN) {
788  iscsi_host_for_each_session(shost, ocs_lnx_xport_fail_session);
789 
790  }
791 
792 }
793 
794 
795 /**
796  * @ingroup openiscsi_initiator
797  * @brief IO completion handler for iSCSI initiator.
798  *
799  * @par Description
800  * This function is called on receipt of a Initiator Solicited CQE
801  * in response to a SCSI I/O. The CQE indicates that the
802  * SCSI command has completed.
803  * @n @n
804  * This function restores the original ITT in the BHS, then calls
805  * iscsi_complete_scsi_task to let libiscsi do its processing, then
806  * calls ocs_scsi_cmd_cb to let the ocs_scsi layer complete its
807  * processing.
808  *
809  * @param io Pointer to the io that completed.
810  * @param status OCS_SCSI status.
811  * @param rsp SCSI response, including SCSI status.
812  * @param flags Flags (currently unused).
813  * @param arg Argument from the upper layer (currently unused).
814  *
815  * @return Returns 0 on success; or a negative error code value
816  * on failure.
817  */
818 
819 static int32_t ocs_lnx_xport_io_cb (
820  ocs_io_t *io,
821  ocs_scsi_io_status_e status,
822  ocs_scsi_cmd_resp_t *rsp,
823  uint32_t flags,
824  void *arg)
825 {
826  ocs_cxn_t *cxn;
827  ocs_ep_t *ep;
828  struct iscsi_conn *conn;
829  ocs_conn_t *ocs_conn;
830  struct iscsi_hdr *hdr;
831  ocs_io_task_t *io_task;
832  struct iscsi_task *task;
833  int exp_cmdsn;
834  int max_cmdsn;
835  int32_t rc;
836  unsigned long irq_flags;
837  spinlock_t *session_lock_iscsi;
838 
839  ocs_assert(io, -1);
840 
841  cxn = io->node;
842  ocs_assert(cxn, -1);
843 
844  ep = cxn->ini_node.ocs_ep;
845  ocs_assert(ep, -1);
846 
847  ocs_conn = ep->ocs_conn;
848  ocs_assert(ocs_conn, -1);
849 
850  conn = ocs_conn->conn;
851  ocs_assert(conn, -1);
852 
853  io_task = io->ini_io.io_task;
854  ocs_assert(io_task, -1);
855 
856  task = io_task->task;
857  ocs_assert(task, -1);
858 
859 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0)
860  session_lock_iscsi = &task->conn->session->back_lock;
861 #else
862  session_lock_iscsi = &task->conn->session->lock;
863 #endif
864 
865  /*
866  * If this IO was aborted by the upper layer then do no issue a
867  * callback because libiscsi already issued a completion to the
868  * mid layer after calling cleanup_task().
869  */
870  if (io_task->task_state == OCS_IO_TASK_STATE_CLEANUP) {
871  ocs_scsi_io_free(io);
873  return 0;
874  }
875 
876  // hdr = io->bhs.virt;
877  hdr = task->hdr;
878 
879  /* The ITT was modified to match the SLI-4 requirements before
880  * the PDU was sent. Now that the SLI port is done with it we
881  * need to change it back to the tag that libiscsi assigned to
882  * it so that libiscsi can find the task and complete processing
883  * on it.
884  */
885 
886  hdr->itt = io_task->original_itt;
887 
888  exp_cmdsn = ocs_session_exp_cmd_sn_get(cxn);
889  max_cmdsn = (exp_cmdsn + ocs_session_cmd_window_get(cxn) - 1);
890 
891  rc = ocs_scsi_cmd_cb(io, status, rsp, flags, arg);
892 
893  /* Required to hold session lock for this call */
894  spin_lock_irqsave(session_lock_iscsi, irq_flags);
895 
896  iscsi_complete_scsi_task(task, exp_cmdsn, max_cmdsn);
897  spin_unlock_irqrestore(session_lock_iscsi, irq_flags);
898 
900  ocs_scsi_io_free(io);
901  return rc;
902 }
903 
904 
905 /**
906  * @ingroup openiscsi_initiator
907  * @brief Create a new iscsi session.
908  *
909  * @param ep TBD.
910  * @param cmds_max Maximum commands supported.
911  * @param qdepth Maximum queue depth.
912  * @param initial_cmdsn Initial iSCSI CMDSN.
913  *
914  * @return Returns a pointer to the session object; or NULL.
915  */
916 struct iscsi_cls_session *ocs_session_create(struct iscsi_endpoint *ep,
917  u16 cmds_max,
918  u16 qdepth,
919  u32 initial_cmdsn)
920 {
921  struct iscsi_cls_session *cls_session;
922  struct Scsi_Host *shost;
923  struct iscsi_session *sess;
924  ocs_t *ocs;
925  ocs_ep_t *ocs_ep;
926  ocs_session_t *ocs_sess;
927 
928  if (!ep) {
929  return NULL;
930  }
931  ocs_ep = ep->dd_data;
932  ocs_assert(ocs_ep, NULL);
933  ocs_assert(ocs_ep->cxn, NULL);
934  ocs = ocs_ep->cxn->ocs;
935  ocs_assert(ocs, NULL);
936  shost = ocs->ini_ocs.shost;
937 
938  // TODO: check max_cmds and update as necessary
939 
940  cls_session = iscsi_session_setup(&ocs_lnx_xport_iscsi,
941  shost, cmds_max,
942  sizeof(ocs_session_t),
943  sizeof(ocs_io_task_t),
944  initial_cmdsn, ISCSI_MAX_TARGET);
945  if (!cls_session)
946  return NULL;
947  sess = cls_session->dd_data;
948  ocs_sess = sess->dd_data;
949 
950  printk("%s(): cls_session=%p, ocs_sess=%p sess->state=%d\n",
951  __func__, cls_session, ocs_sess, sess->state);
952 
953  return cls_session;
954 }
955 
956 /**
957  * @ingroup openiscsi_initiator
958  * @brief Destroy an iSCSI session.
959  *
960  * @par Description
961  * Destroys iSCSI session instance and releases resources
962  * allocated for it.
963  *
964  * @param cls_session Pointer to the iSCSI session to destroy.
965  *
966  * @return None.
967  */
968 void ocs_session_destroy(struct iscsi_cls_session *cls_session)
969 {
970 
971  iscsi_session_teardown(cls_session);
972 }
973 
974 /**
975  * @ingroup openiscsi_initiator
976  * @brief Create an instance of iSCSI connection.
977  *
978  * @param cls_session TBD.
979  * @param cid TBD.
980  *
981  * @return TBD
982  */
983 struct iscsi_cls_conn *
984 ocs_conn_create(struct iscsi_cls_session *cls_session, u32 cid)
985 {
986  ocs_iscsi_host_private_t *host_private = NULL;
987  ocs_t *ocs = NULL;
988  struct Scsi_Host *shost;
989  struct iscsi_cls_conn *cls_conn;
990  ocs_conn_t *ocs_conn;
991  struct iscsi_conn *conn;
992  struct iscsi_session *sess;
993  ocs_session_t *ocs_sess;
994 
995  shost = iscsi_session_to_shost(cls_session);
996  ocs_assert(shost, NULL);
997  host_private = iscsi_host_priv(shost);
998  ocs = host_private->ocs;
999 
1000  /* create iSCSI cls_conn */
1001  cls_conn = iscsi_conn_setup(cls_session, sizeof(*ocs_conn), cid);
1002  if (!cls_conn)
1003  return NULL;
1004 
1005  /* map OCS connection to iSCSI cls_conn connection */
1006  conn = cls_conn->dd_data;
1007  ocs_conn = conn->dd_data;
1008  ocs_conn->conn = conn;
1009 
1010  /* connection not yet bound to endpoint */
1011  ocs_conn->ocs_ep = NULL;
1012 
1013  /* map OCS session to new OCS connection */
1014  sess = cls_session->dd_data;
1015  ocs_sess = sess->dd_data;
1016  ocs_conn->ocs_sess = ocs_sess;
1017 
1018  return cls_conn;
1019 }
1020 
1021 
1022 /**
1023  * @ingroup openiscsi_initiator
1024  * @brief Binds an iSCSI connection to an endpoint.
1025  *
1026  * @par Description
1027  * This function binds a connection/session pair to a connected
1028  * endpoint.
1029  *
1030  *
1031  * @param cls_session Pointer to iSCSI session.
1032  * @param cls_conn Pointer to iSCSI connection.
1033  * @param transport_fd File descriptor for the endpoint (not
1034  * used)
1035  * @param is_leading Not used.
1036  *
1037  * @return Returns 0 on success; or a negative error code value
1038  * on failure.
1039  */
1040 int ocs_conn_bind(struct iscsi_cls_session *cls_session,
1041  struct iscsi_cls_conn *cls_conn,
1042  u64 transport_fd, int is_leading)
1043 {
1044  struct iscsi_conn *conn = cls_conn->dd_data;
1045  ocs_conn_t *ocs_conn = conn->dd_data;
1046  struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
1047  ocs_iscsi_host_private_t *host_private = iscsi_host_priv(shost);
1048  ocs_t *ocs = host_private->ocs;
1049  ocs_ep_t *ocs_ep;
1050  struct iscsi_endpoint *ep;
1051  ocs_cxn_t *cxn;
1052 
1053  ocs_assert(ocs, -EINVAL);
1054 
1055  /* get iSCSI endpoint from transport_fd */
1056  ep = iscsi_lookup_endpoint(transport_fd);
1057  if (!ep)
1058  return -EINVAL;
1059 
1060  /* get corresponding OCS endpoint */
1061  ocs_ep = ep->dd_data;
1062 
1063  /* bind iSCSI connection to iSCSI session */
1064  if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
1065  return -EINVAL;
1066 
1067  /* map OCS connection (ocs_conn) to OCS endpoint (ocs_ep) */
1068  ocs_conn->ocs_ep = ocs_ep;
1069  ocs_ep->ocs_conn = ocs_conn;
1070 
1071  /* Now that the endpoint is associated with a connection we can map the node to the session */
1072  cxn = ocs_ep->cxn;
1073  cxn->session = ocs_conn->ocs_sess;
1074 
1075  printk("%s: connection bound to endpoint\n", __func__);
1076  return 0;
1077 }
1078 
1079 /**
1080  * @ingroup openiscsi_initiator
1081  * @brief
1082  * @par Description
1083  *
1084  * @param shost TBD.
1085  * @param data TBD.
1086  * @param dt_len TBD.
1087  *
1088  * @return
1089  */
1090 int ocs_iface_set_param(struct Scsi_Host *shost,
1091  void *data, uint32_t dt_len)
1092 {
1093 
1094  return 0;
1095 }
1096 
1097 /**
1098  * @ingroup openiscsi_initiator
1099  * @brief
1100  * @par Description
1101  *
1102  * @param iface TBD.
1103  * @param param_type TBD.
1104  * @param param TBD.
1105  * @param buf TBD.
1106  *
1107  * @return
1108  */
1109 int ocs_iface_get_param(struct iscsi_iface *iface,
1110  enum iscsi_param_type param_type,
1111  int param, char *buf)
1112 {
1113 
1114  return 0;
1115 }
1116 
1117 /**
1118  * @ingroup openiscsi_initiator
1119  * @brief
1120  * @par Description
1121  *
1122  *
1123  * @param ep
1124  * @param param
1125  * @param buf
1126  *
1127  * @return
1128  */
1129 int ocs_ep_get_param(struct iscsi_endpoint *ep,
1130  enum iscsi_param param, char *buf)
1131 {
1132  return 0;
1133 }
1134 
1135 /**
1136  * @ingroup openiscsi_initiator
1137  * @brief
1138  * @par Description
1139  *
1140  *
1141  * @param cls_conn
1142  * @param param
1143  * @param buf
1144  *
1145  * @return
1146  */
1147 int ocs_conn_get_param(struct iscsi_cls_conn *cls_conn,
1148  enum iscsi_param param, char *buf)
1149 {
1150  struct iscsi_conn *conn = cls_conn->dd_data;
1151  ocs_conn_t *ocs_conn;
1152  ocs_cxn_t *cxn;
1153  int len;
1154 
1155 
1156  ocs_assert(conn, -1);
1157  ocs_conn = conn->dd_data;
1158  ocs_assert(ocs_conn, -1);
1159  ocs_assert(ocs_conn->ocs_ep, -1);
1160  cxn = ocs_conn->ocs_ep->cxn;
1161 
1162  switch(param) {
1163  case ISCSI_PARAM_PERSISTENT_PORT:
1164  len = sprintf(buf, "%d\n", cxn->source_port);
1165  break;
1166  case ISCSI_PARAM_PERSISTENT_ADDRESS:
1167  ocs_strcpy(buf, cxn->source_ip);
1168  len = strlen(buf);
1169  break;
1170  default:
1171  len = iscsi_conn_get_param(cls_conn, param, buf);
1172  break;
1173  }
1174 
1175  return len;
1176 }
1177 
1178 /**
1179  * @ingroup openiscsi_initiator
1180  * @brief
1181  * @par Description
1182  *
1183  *
1184  * @param cls_session
1185  * @param param
1186  * @param buf
1187  *
1188  * @return
1189  */
1190 int ocs_session_get_param(struct iscsi_cls_session *cls_session,
1191  enum iscsi_param param, char *buf)
1192 {
1193  int len = 0;
1194 
1195  switch(param) {
1196  default:
1197  return iscsi_session_get_param(cls_session, param, buf);
1198  }
1199 
1200  return len;
1201 
1202 }
1203 
1204 /**
1205  * @ingroup openiscsi_initiator
1206  * @brief
1207  *
1208  * @par Description
1209  * set iSCSI parameter. Return 0 on success, -ENODATA when param is not
1210  * supported, and a -Exx value on other error.
1211  *
1212  * @param cls_conn
1213  * @param param
1214  * @param buf
1215  * @param buflen
1216  *
1217  * @return
1218  */
1219 int ocs_set_param(struct iscsi_cls_conn *cls_conn,
1220  enum iscsi_param param, char *buf, int buflen)
1221 {
1222  struct iscsi_conn *conn = cls_conn->dd_data;
1223  struct iscsi_session *session = conn->session;
1224  ocs_conn_t *ocs_conn;
1225  ocs_cxn_t *cxn;
1226  ocs_session_t *ocs_sess;
1227  int ret;
1228 
1229 
1230 
1231  ocs_assert(conn, -1);
1232  ocs_conn = conn->dd_data;
1233  ocs_assert(ocs_conn, -1);
1234  ocs_assert(ocs_conn->ocs_ep, -1);
1235  cxn = ocs_conn->ocs_ep->cxn;
1236  ocs_sess = cxn->session;
1237 
1238  /* libiscsi will set appropriate session field */
1239  ret = iscsi_set_param(cls_conn, param, buf, buflen);
1240  if (ret)
1241  return ret;
1242 
1243  switch (param) {
1244  case ISCSI_PARAM_FIRST_BURST:
1245  printk("%s(): cxn=%p first_burst=%d\n", __func__, cxn, session->first_burst);
1246  // TODO: be2iscsi does this; verify that we need to limit
1247  if (session->first_burst > 8192)
1248  session->first_burst = 8192;
1249 
1250  ocs_sess->login_options.first_burst = session->first_burst;
1251  break;
1252  case ISCSI_PARAM_MAX_RECV_DLENGTH:
1253  printk("%s(): cxn=%p max_recv_dl=%d\n", __func__, cxn, conn->max_recv_dlength);
1254  // TODO: be2iscsi does this; verify that we need to limit
1255  if (conn->max_recv_dlength > 65536)
1256  conn->max_recv_dlength = 65536;
1257 
1258  /* save in context for next call to ocs_conn_start */
1259  cxn->max_rcv_dsl = conn->max_recv_dlength;
1260  break;
1261  case ISCSI_PARAM_MAX_BURST:
1262  printk("%s(): cxn=%p max_burst=%d\n", __func__, cxn, session->max_burst);
1263  // TODO: be2iscsi does this; verify that we need to limit
1264  if (session->max_burst > 262144)
1265  session->max_burst = 262144;
1266 
1267  /* save in context for next call to ocs_conn_start */
1268  ocs_sess->login_options.max_burst = session->max_burst;
1269  break;
1270  case ISCSI_PARAM_MAX_XMIT_DLENGTH:
1271  printk("%s(): cxn=%p max_xmit_dlen=%d\n",
1272  __func__, cxn, conn->max_xmit_dlength);
1273  // TODO: be2iscsi does this; verify that we need to limit
1274  if ((conn->max_xmit_dlength > OCS_ISCSI_LOGIN_MAX_RECV_DATA_SEG_LEN) ||
1275  (conn->max_xmit_dlength == 0))
1276  conn->max_xmit_dlength = OCS_ISCSI_LOGIN_MAX_RECV_DATA_SEG_LEN;
1277 
1278  /* save in context for next call to ocs_conn_start */
1279  cxn->max_xmit_dsl = conn->max_xmit_dlength;
1280  break;
1281  case ISCSI_PARAM_PERSISTENT_ADDRESS:
1282  ocs_memcpy(cxn->source_ip, conn->persistent_address, 16);
1283  break;
1284  case ISCSI_PARAM_PERSISTENT_PORT:
1285  cxn->source_port = conn->persistent_port;
1286  break;
1287  case ISCSI_PARAM_HDRDGST_EN:
1288  printk("%s(): cxn=%p HdrDigest=%d\n",
1289  __func__, cxn, conn->hdrdgst_en);
1290  cxn->hdr_digest = conn->hdrdgst_en;
1291  break;
1292  case ISCSI_PARAM_DATADGST_EN:
1293  printk("%s(): cxn=%p DataDigest=%d\n",
1294  __func__, cxn, conn->datadgst_en);
1295  cxn->data_digest = conn->datadgst_en;
1296  break;
1297  case ISCSI_PARAM_IMM_DATA_EN:
1298  printk("%s(): cxn=%p immediate_data=%d\n",
1299  __func__, cxn, session->imm_data_en);
1300  ocs_sess->login_options.immediate_data = session->imm_data_en;
1301  break;
1302  default:
1303  break;
1304 
1305  }
1306 
1307  return 0;
1308 }
1309 
1310 /**
1311  * @ingroup openiscsi_initiator
1312  * @brief
1313  * @par Description
1314  *
1315  * @param shost
1316  * @param param
1317  * @param buf
1318  * @param buflen
1319  *
1320  * @return
1321  */
1322 int ocs_set_host_param(struct Scsi_Host *shost,
1323  enum iscsi_host_param param, char *buf, int buflen)
1324 {
1325  int ret;
1326 
1327  ret = iscsi_host_set_param(shost, param, buf, buflen);
1328  if (ret) {
1329  return ret;
1330  }
1331 
1332  return 0;
1333 }
1334 
1335 /**
1336  * @ingroup openiscsi_initiator
1337  * @brief
1338  * @par Description
1339  *
1340  *
1341  * @param shost
1342  * @param param
1343  * @param buf
1344  *
1345  * @return
1346  */
1347 int ocs_get_host_param(struct Scsi_Host *shost,
1348  enum iscsi_host_param param, char *buf)
1349 {
1350  ocs_iscsi_host_private_t *host_private = iscsi_host_priv(shost);
1351  ocs_t *ocs = host_private->ocs;
1352  int status = 0;
1353 
1354  switch (param) {
1355  case ISCSI_HOST_PARAM_HWADDRESS:
1356  status = sysfs_format_mac(buf, ocs_iscsi_mac_get(ocs), ETH_ALEN);
1357  break;
1358  case ISCSI_HOST_PARAM_INITIATOR_NAME:
1359  strcpy(buf, ocs_iscsi_ini_get_name(ocs));
1360  status = strlen(buf);
1361  break;
1362  default:
1363  status = iscsi_host_get_param(shost, param, buf);
1364  break;
1365  }
1366 
1367  return status;
1368 }
1369 
1370 /**
1371  * @ingroup openiscsi_initiator
1372  * @brief
1373  * @par Description
1374  *
1375  *
1376  * @param cls_conn
1377  * @param stats
1378  */
1379 void ocs_conn_get_stats(struct iscsi_cls_conn *cls_conn,
1380  struct iscsi_stats *stats)
1381 {
1382 
1383 }
1384 
1385 /**
1386  * @ingroup openiscsi_initiator
1387  * @brief Set UPDATE CONTEXT options
1388  *
1389  * @par Description
1390  * Set the parameters that libiscsi keeps track of that are
1391  * required by CONTEXT_UPDATE_WQE.
1392  *
1393  * @param iparam
1394  * @param conn
1395  *
1396  * @return None.
1397  */
1399  struct iscsi_conn *conn)
1400 {
1401  struct iscsi_session *session = conn->session;
1402 
1403  iparam->context_upd.lgn_options.session_options.max_burst = session->max_burst;
1404  iparam->context_upd.lgn_options.max_rcv_dsl = conn->max_recv_dlength;
1405  iparam->context_upd.lgn_options.max_send_dsl = conn->max_xmit_dlength;
1406  iparam->context_upd.lgn_options.session_options.first_burst = session->first_burst;
1408  iparam->context_upd.lgn_options.data_digest = conn->datadgst_en;
1409  iparam->context_upd.lgn_options.hdr_digest = conn->hdrdgst_en;
1410  iparam->context_upd.lgn_options.session_options.initial_r2t = session->initial_r2t_en;
1411  iparam->context_upd.lgn_options.session_options.immediate_data = session->imm_data_en;
1412  iparam->context_upd.statsn = (conn->exp_statsn);
1413 
1414 }
1415 
1416 /**
1417  * @ingroup openiscsi_initiator
1418  * @brief Offload of session to chip
1419  *
1420  * @par Description
1421  *
1422  *
1423  * @param cls_conn
1424  *
1425  * @return Returns 0.
1426  */
1427 int ocs_conn_start(struct iscsi_cls_conn *cls_conn)
1428 {
1429  // uint32_t rc;
1430  // ocs_hal_io_param_t iparam;
1431  ocs_conn_t *ocs_conn;
1432  ocs_ep_t *ocs_ep;
1433  ocs_cxn_t *cxn;
1434  ocs_iscsi_t *iscsi;
1435  struct iscsi_conn *conn;
1436  // ocs_lnx_iscsi_arg_t arg;
1437 
1438  conn = cls_conn->dd_data;
1439  ocs_assert(conn, -1);
1440  ocs_conn = conn->dd_data;
1441  ocs_assert(ocs_conn, -1);
1442  ocs_ep = ocs_conn->ocs_ep;
1443  ocs_assert(ocs_ep, -1);
1444  cxn = ocs_ep->cxn;
1445  ocs_assert(cxn, -1);
1446  iscsi = cxn->iscsi;
1447  ocs_assert(iscsi, -1);
1448 
1449 
1451 
1452  iscsi_conn_start(cls_conn);
1453 
1454  return 0;
1455 }
1456 
1457 /**
1458  * @ingroup openiscsi_initiator
1459  * @brief
1460  *
1461  * @par Description
1462  *
1463  * @param conn
1464  *
1465  * @return
1466  */
1467 static
1468 int ocs_conn_update_context(struct iscsi_conn *conn)
1469 {
1470  uint32_t rc = 0;
1471  struct iscsi_session *session;
1472  ocs_conn_t *ocs_conn;
1473  ocs_ep_t *ocs_ep;
1474  ocs_cxn_t *cxn;
1475  ocs_session_t *ocs_session;
1476 
1477  ocs_assert(conn, -1);
1478  ocs_conn = conn->dd_data;
1479  ocs_assert(ocs_conn, -1);
1480  session = conn->session;
1481  ocs_assert(session, -1);
1482  ocs_ep = ocs_conn->ocs_ep;
1483  ocs_assert(ocs_ep, -1);
1484  cxn = ocs_ep->cxn;
1485  ocs_assert(cxn, -1);
1486  ocs_session = cxn->session;
1487  ocs_assert(session, -1);
1488 
1489  // Copy data from the open-iscsi structures to the ocs structures
1490  cxn->data_digest = conn->datadgst_en;
1491  cxn->hdr_digest = conn->hdrdgst_en;
1492  cxn->max_rcv_dsl = conn->max_recv_dlength;
1493  cxn->max_xmit_dsl = conn->max_xmit_dlength;
1494  cxn->stat_sn = conn->exp_statsn;
1495  ocs_session->login_options.max_burst = session->max_burst;
1496  ocs_session->login_options.first_burst = session->first_burst;
1497  ocs_session->login_options.error_recovery_level = session->erl;
1498  ocs_session->login_options.initial_r2t = session->initial_r2t_en;
1499  ocs_session->login_options.immediate_data = session->imm_data_en;
1500 
1502 
1503  return rc;
1504 }
1505 
1506 /**
1507  * @ingroup openiscsi_initiator
1508  * @brief
1509  *
1510  * @par Description
1511  *
1512  * @param addr
1513  * @param hal_ip
1514  * @param port
1515  *
1516  * @return
1517  */
1518 static int
1519 ocs_sockaddr_to_hal_ip(struct sockaddr *addr, ocs_hal_ip_address_t *hal_ip, uint16_t *port)
1520 {
1521  struct sockaddr_in *daddr_in = (struct sockaddr_in *)addr;
1522  struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)addr;
1523  if (addr->sa_family == PF_INET) {
1524  __be32 s_addr = daddr_in->sin_addr.s_addr;
1525  hal_ip->ip_type = OCS_HAL_IP_TYPE_V4;
1526  hal_ip->ip_address[0] = s_addr & 0x000000ff;
1527  hal_ip->ip_address[1] = (s_addr & 0x0000ff00) >> 8;
1528  hal_ip->ip_address[2] = (s_addr & 0x00ff0000) >> 16;
1529  hal_ip->ip_address[3] = (s_addr & 0xff000000) >> 24;
1530  *port = ntohs(daddr_in->sin_port);
1531  } else if (addr->sa_family == PF_INET6) {
1532  hal_ip->ip_type = OCS_HAL_IP_TYPE_V6;
1533  memcpy(hal_ip->ip_address, &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
1534  *port = ntohs(daddr_in6->sin6_port);
1535  } else{
1536  return -1;
1537  }
1538  return 0;
1539 }
1540 
1541 /**
1542  * @ingroup openiscsi_initiator
1543  * @brief Ask the chip to create TCP connection.
1544  *
1545  * @par Description
1546  * This routine first asks the chip to create a connection and then
1547  * allocates an EP.
1548  *
1549  * @param shost Pointer to Scsi_Host structure.
1550  * @param dst_addr The IP address of the target.
1551  * @param non_blocking Blocking or non-blocking call.
1552  *
1553  * @return
1554  * - A pointer to an endpoint on success.
1555  * - A negative error value on error.
1556  */
1557 struct iscsi_endpoint *
1558 ocs_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, int non_blocking)
1559 {
1560  ocs_iscsi_host_private_t *host_private = NULL;
1561  ocs_t *ocs = NULL;
1562  ocs_ep_t *ocs_ep = NULL;
1563  struct iscsi_endpoint *ep;
1564  int ret;
1565  ocs_hal_ip_address_t remote_ip;
1566  uint16_t remote_port = 0;
1567  ocs_cxn_t *cxn = NULL;
1568 
1569  if (shost) {
1570  host_private = iscsi_host_priv(shost);
1571  } else {
1572  ret = -ENXIO;
1573  return ERR_PTR(ret);
1574  }
1575 
1576  ocs = host_private->ocs;
1577  ep = iscsi_create_endpoint(sizeof(ocs_ep_t));
1578  if (!ep) {
1579  ret = -ENOMEM;
1580  return ERR_PTR(ret);
1581  }
1582 
1583  ocs_ep = ep->dd_data;
1584  ocs_ep->openiscsi_ep = ep;
1585  ocs_ep->cxn = NULL;
1586 
1587  /* translate socket address format to hal IP address and port */
1588  ret = ocs_sockaddr_to_hal_ip(dst_addr, &remote_ip, &remote_port);
1589  if (ret) {
1590  printk("%s(): failed to translate IP address\n", __func__);
1591  ret = -EIO;
1592  goto ocs_free_ep;
1593  }
1594 
1595  /* use OCS Transport API to connect */
1596  if (remote_ip.ip_type == OCS_HAL_IP_TYPE_V4) {
1597  printk("%s(): attempt to connect to IPv4 address %d.%d.%d.%d\n",
1598  __func__,
1599  remote_ip.ip_address[0],
1600  remote_ip.ip_address[1],
1601  remote_ip.ip_address[2],
1602  remote_ip.ip_address[3]);
1603  } else {
1604  uint16_t *word = (uint16_t *)remote_ip.ip_address;
1605  printk("%s(): attempt to connect to IPv6 address %x:%x:%x:%x:%x:%x:%x:%x\n",
1606  __func__,
1607  word[0],
1608  word[1],
1609  word[2],
1610  word[3],
1611  word[4],
1612  word[5],
1613  word[6],
1614  word[7]);
1615  }
1616  ret = ocs_xport_control(ocs->xport, OCS_XPORT_CONNECT, &remote_ip, remote_port, &cxn);
1617  if (ret) {
1618  printk("%s(): connection failed, status=%d\n", __func__, ret);
1619  ret = -EIO;
1620  goto ocs_free_ep;
1621  } else {
1622  ocs_assert(cxn, ERR_PTR(-EIO));
1623  printk("%s(): connection success\n", __func__);
1624  cxn->cxn_state = CONN_STATE_NEW_CONN;
1625  }
1626 
1627  ocs_ep->cxn = cxn;
1628  cxn->ini_node.ocs_ep = ocs_ep;
1629  return ep;
1630 
1631 ocs_free_ep:
1632  iscsi_destroy_endpoint(ep);
1633  return ERR_PTR(ret);
1634 }
1635 
1636 
1637 /**
1638  * @ingroup openiscsi_initiator
1639  * @brief Poll to see if a connection is established.
1640  *
1641  * @par Description
1642  * Poll to see if TCP connection is established.
1643  *
1644  * @param ep The endpoint to be polled.
1645  * @param timeout_ms Maximum time to wait (not used).
1646  *
1647  * @return Returns 1 if the endpoint is connected; or 0 if not.
1648  */
1649 int ocs_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
1650 {
1651  ocs_ep_t *ocs_ep;
1652  int ret;
1653 
1654  if (!ep) {
1655  return -1;
1656  }
1657 
1658  ocs_ep = ep->dd_data;
1659  ocs_assert(ocs_ep, -1);
1660 
1661  /* return 1 if connection is valid, 0 otherwise */
1662  ret = (ocs_ep->cxn ? 1 : 0);
1663  return ret;
1664 }
1665 
1666 /**
1667  * @ingroup openiscsi_initiator
1668  * @brief Tears down the TCP connection.
1669  *
1670  * @par Description
1671  * Tears down a TCP connection.
1672  *
1673  * @param ep The endpoint to be disconnected.
1674  *
1675  * @return None.
1676  */
1677 void ocs_ep_disconnect(struct iscsi_endpoint *ep)
1678 {
1679  ocs_ep_t *ocs_ep;
1680  ocs_cxn_t *cxn = NULL;
1681  int32_t ret;
1682  ocs_t *ocs = NULL;
1683  uint32_t reset;
1684 
1685  if (!ep) {
1686  return;
1687  }
1688 
1689  ocs_ep = ep->dd_data;
1690  ocs_assert(ocs_ep);
1691  cxn = ocs_ep->cxn;
1692  ocs = cxn->ocs;
1693 
1694  if (ocs_ep->ocs_conn != NULL) {
1695  iscsi_suspend_queue(ocs_ep->ocs_conn->conn);
1696  reset = 1;
1697  } else {
1698  reset = 0;
1699  }
1700 
1701  /* use OCS Transport API to disconnect */
1702  ret = ocs_xport_control(ocs->xport, OCS_XPORT_DISCONNECT, cxn, reset);
1703  if (ret) {
1704  printk("%s(): disconnect failed, status=%d\n", __func__, ret);
1705  return;
1706  }
1707  // ocs_iscsi_login_cxn_cleanup(cxn) needed ?
1708  // ocs_iscsi_del_target(cxn) needed ?
1709  printk("%s(): disconnect success, ep=%p ocs_ep=%p cxn=%p\n",
1710  __func__, ep, ocs_ep, cxn);
1711 
1712  /* use OCS Transport API to "upload" connection */
1713  ret = ocs_xport_control(ocs->xport, OCS_XPORT_UPLOAD, cxn, reset);
1714  if (ret) {
1715  printk("%s(): upload failed, status=%d\n", __func__, ret);
1716  return;
1717  }
1718  // ocs_iscsi_login_cxn_cleanup(cxn) needed ?
1719  // ocs_iscsi_del_target(cxn) needed ?
1720  printk("%s(): upload success, ep=%p ocs_ep=%p cxn=%p\n",
1721  __func__, ep, ocs_ep, cxn);
1722 
1723  iscsi_destroy_endpoint(ocs_ep->openiscsi_ep);
1724 }
1725 
1726 
1727 /**
1728  * @ingroup openiscsi_initiator
1729  * @brief Completion handler for non-SCSI initiator tasks that complete on
1730  * TCP ACK.
1731  *
1732  * @par Description
1733  * This function is called on receipt of a DMSG_CQE. The CQE indicates that a
1734  * DM_CMD_WQE has been sent with the DM flag set and a TCP ACK has been
1735  * received. We must wait for the response to come up the unsolicited path
1736  * to complete the "task" to libiscsi.
1737  *
1738  * @param io Pointer to the io that completed.
1739  * @param exp_cmdsn TBD.
1740  * @param max_cmdsn TBD.
1741  * @param response TBD.
1742  *
1743  * @return Returns 0 on success; negative error value on
1744  * failure.
1745  */
1746 
1747 int32_t ocs_iscsi_mtask_cb_tcp_ack_wait_rsp(ocs_io_t *io, uint32_t exp_cmdsn,
1748  uint32_t max_cmdsn, uint8_t response)
1749 {
1750  ocs_io_task_t *io_task;
1751  ocs_cxn_t *cxn;
1752  ocs_ep_t *ep;
1753  ocs_conn_t *ocs_conn;
1754  struct iscsi_conn *conn;
1755 
1756  ocs_assert(io, -1);
1757 
1758  cxn = io->node;
1759  ocs_assert(cxn, -1);
1760 
1761  ep = cxn->ini_node.ocs_ep;
1762  ocs_assert(ep, -1);
1763 
1764  ocs_conn = ep->ocs_conn;
1765  ocs_assert(ocs_conn, -1);
1766 
1767  io_task = io->ini_io.io_task;
1768  ocs_assert(io_task, -1);
1769 
1770  conn = ocs_conn->conn;
1771  ocs_assert(conn, -1);
1772 
1773  /*
1774  * If this IO was aborted by the upper layer then do no issue a
1775  * callback because libiscsi already issued a completion to the
1776  * mid layer after calling cleanup_task().
1777  */
1778  if (io_task->task_state == OCS_IO_TASK_STATE_CLEANUP) {
1779  ocs_scsi_io_free(io);
1781  return 0;
1782  }
1783 
1784  return 0;
1785 }
1786 
1787 /**
1788  * @ingroup openiscsi_initiator
1789  * @brief Completion handler for non-SCSI initiator tasks that complete on
1790  * TCP ACK.
1791  *
1792  * @par Description
1793  * This function is called on receipt of a DMSG_CQE. The CQE indicates that a
1794  * DM_CMD_WQE has been sent with the DM flag set and a TCP ACK has been
1795  * received. There is no response coming, so complete the "task" to libiscsi.
1796  *
1797  * @param io Pointer to the io that completed.
1798  * @param exp_cmdsn TBD.
1799  * @param max_cmdsn TBD.
1800  * @param response TBD.
1801  *
1802  * @return Returns 0 on success; negative error value on
1803  * failure.
1804  */
1805 
1806 int32_t ocs_iscsi_mtask_cb_tcp_ack_no_rsp(ocs_io_t *io, uint32_t exp_cmdsn,
1807  uint32_t max_cmdsn, uint8_t response)
1808 {
1809  struct iscsi_hdr *hdr;
1810  ocs_io_task_t *io_task;
1811  ocs_cxn_t *cxn;
1812  ocs_ep_t *ep;
1813  ocs_conn_t *ocs_conn;
1814  struct iscsi_conn *conn;
1815  int rc;
1816 
1817  ocs_assert(io, -1);
1818 
1819  cxn = io->node;
1820  ocs_assert(cxn, -1);
1821 
1822  ep = cxn->ini_node.ocs_ep;
1823  ocs_assert(ep, -1);
1824 
1825  ocs_conn = ep->ocs_conn;
1826  ocs_assert(ocs_conn, -1);
1827 
1828  io_task = io->ini_io.io_task;
1829  ocs_assert(io_task, -1);
1830 
1831  conn = ocs_conn->conn;
1832  ocs_assert(conn, -1);
1833 
1834  /*
1835  * If this IO was aborted by the upper layer then do no issue a
1836  * callback because libiscsi already issued a completion to the
1837  * mid layer after calling cleanup_task().
1838  */
1839  if (io_task->task_state == OCS_IO_TASK_STATE_CLEANUP) {
1840  ocs_scsi_io_free(io);
1842  return 0;
1843  }
1844 
1845  /* Reset the ITT back to the one that libiscsi is expecting to see */
1846  hdr = (struct iscsi_hdr *)io->bhs;
1847  hdr->itt = io_task->original_itt;
1848 
1850  rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
1851  if (rc) {
1852  if (rc == ISCSI_ERR_BAD_OPCODE) {
1853  printk("%s: iscsi_complete_pdu returns BAD_OPCODE %d\n",
1854  __func__, hdr->opcode);
1855  } else {
1856  printk("%s: iscsi_complete_pdu failed, rc=%d\n", __func__, rc);
1857  }
1858  }
1859 
1860  ocs_scsi_io_free(io);
1861  return rc;
1862 }
1863 
1864 /**
1865  * @ingroup openiscsi_initiator
1866  * @brief Completion handler for non-SCSI initiator tasks.
1867  *
1868  * @par Description
1869  * This function is called on receipt of a DMSG_CQE with a response PDU.
1870  * The CQE indicates that a DM_CMD_WQE has been sent without the DM flag set.
1871  * A response is received as part of the completion.
1872  *
1873  * @param io Pointer to the io that completed.
1874  * @param exp_cmdsn TBD.
1875  * @param max_cmdsn TBD.
1876  * @param response TBD.
1877  *
1878  * @return Returns 0 on success; or a negative error value on
1879  * failure.
1880  */
1881 
1882 int32_t ocs_iscsi_mtask_cb_with_rsp(ocs_io_t *io, uint32_t exp_cmdsn,
1883  uint32_t max_cmdsn, uint8_t response)
1884 {
1885  struct iscsi_hdr *hdr;
1886  ocs_io_task_t *io_task;
1887  ocs_cxn_t *cxn;
1888  ocs_ep_t *ep;
1889  ocs_conn_t *ocs_conn;
1890  struct iscsi_conn *conn;
1891  int rc;
1892 
1893  ocs_assert(io, -1);
1894 
1895  cxn = io->node;
1896  if (cxn == NULL) {
1897  return -1;
1898  }
1899 
1900  ep = cxn->ini_node.ocs_ep;
1901  ocs_assert(ep, -1);
1902 
1903  ocs_conn = ep->ocs_conn;
1904  ocs_assert(ocs_conn, -1);
1905 
1906  io_task = io->ini_io.io_task;
1907  ocs_assert(io_task, -1);
1908 
1909  conn = ocs_conn->conn;
1910  ocs_assert(conn, -1);
1911 
1912  /*
1913  * If this IO was aborted by the upper layer then do no issue a
1914  * callback because libiscsi already issued a completion to the
1915  * mid layer after calling cleanup_task().
1916  */
1917  if (io_task->task_state == OCS_IO_TASK_STATE_CLEANUP) {
1918  ocs_scsi_io_free(io);
1920  return 0;
1921  }
1922 
1923  /* Reset the ITT back to the one that libiscsi is expecting to see */
1924  hdr = (struct iscsi_hdr *)io->bhs;
1925  hdr->itt = io_task->original_itt;
1926 
1927 
1928  /*
1929  * For nop-out, the FW does not put the response into the BHS, so we
1930  * end up having to build a fake NOP-IN here to get things to work.
1931  */
1932  if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_CMD_NOOP) {
1933  iscsi_nopin_hdr_t *nop_hdr = (iscsi_nopin_hdr_t *)io->bhs;
1934  nop_hdr->expCmdSN = ocs_htobe32(exp_cmdsn);
1935  nop_hdr->maxCmdSN = ocs_htobe32(max_cmdsn);
1936  nop_hdr->opcode = ISCSI_OP_NOOP_IN;
1937  nop_hdr->ttt = 0xffffffff;
1938  }
1939 
1941  rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
1942  if (rc) {
1943  if (rc == ISCSI_ERR_BAD_OPCODE) {
1944  printk("%s: iscsi_complete_pdu returns BAD_OPCODE %d\n",
1945  __func__, hdr->opcode);
1946  } else {
1947  printk("%s: iscsi_complete_pdu failed, rc=%d\n", __func__, rc);
1948  }
1949  }
1950 
1951  ocs_scsi_io_free(io);
1952  return rc;
1953 }
1954 
1955 
1956 /**
1957  * @ingroup openiscsi_initiator
1958  * @brief Transmit a management task
1959  *
1960  * @par Description
1961  * Transmits a task that does not perform a SCSI I/O.
1962  *
1963  * @param task Task to be transmitted.
1964  *
1965  * @return Returns 0 on success; or a negative error code value
1966  * on failure.
1967  */
1968 static int ocs_xmit_mtask(struct iscsi_task *task)
1969 {
1970  ocs_io_task_t *io_task = task->dd_data;
1971  ocs_io_t *io = io_task->io;
1972  struct iscsi_conn *conn = task->conn;
1973  ocs_t *ocs;
1974  ocs_conn_t *ocs_conn = conn->dd_data;
1975  ocs_cxn_t *cxn;
1976  iscsi_bhs_t *bhs;
1977  ocs_iscsi_pdu_cb_t cb;
1978  bool is_login;
1979  bool set_dm;
1980  int32_t rc;
1981 
1982  ocs_assert(ocs_conn, -EINVAL);
1983  ocs_assert(ocs_conn->ocs_ep, -EINVAL);
1984  cxn = ocs_conn->ocs_ep->cxn;
1985  ocs_assert(cxn, -EINVAL);
1986  ocs = cxn->ocs;
1987 
1988  bhs = (iscsi_bhs_t *)task->hdr;
1989 
1990  is_login = FALSE;
1991  set_dm = TRUE;
1992 
1993  switch (bhs->opcode & ISCSI_OPCODE_MASK) {
1994  case ISCSI_CMD_NOOP: {
1995  iscsi_nopout_hdr_t *nop_hdr = (iscsi_nopout_hdr_t *)task->hdr;
1996 
1997  /*
1998  * If the ttt is all f's then check the ITT to see if we are
1999  * requesting a response.
2000  */
2001  if (nop_hdr->ttt == 0xffffffff) {
2002  if (nop_hdr->itt == 0xffffffff) {
2003  /* no response expected */
2004  set_dm = TRUE;
2006  } else {
2007  /* response expected */
2008  set_dm = FALSE;
2010  }
2011  } else {
2012  /* response to target nop */
2013  set_dm = TRUE;
2015  }
2016  break;
2017  }
2018  case ISCSI_CMD_LOGIN:
2019  /* Login response is handled in the unsolicited path */
2020  set_dm = TRUE;
2021  is_login = TRUE;
2023  break;
2024  case ISCSI_CMD_LOGOUT:
2025  /* Logout response is handled in the unsolicited path */
2026  set_dm = TRUE;
2028  break;
2029  case ISCSI_CMD_TEXT:
2030  /* Text response is handled in the unsolicited path */
2031  set_dm = TRUE;
2033  break;
2034  case ISCSI_CMD_TASK:
2035  /* Task management response is sent as unsolicited */
2036  set_dm = TRUE;
2038  break;
2039  case ISCSI_CMD_SNACK:
2040  set_dm = TRUE;
2042  break;
2043  default:
2044  printk("%s: unhandled opcode=%d\n", __func__, bhs->opcode);
2045  return -1;
2046  }
2047 
2048  rc = ocs_iscsi_unassisted_pdu_send(ocs, io, cxn, (void *)task->hdr,
2049  (void *)task->data, task->data_count,
2050  is_login, set_dm, cb);
2051  if (rc == 0) {
2053  }
2054  return rc;
2055 }
2056 
2057 /**
2058  * @ingroup openiscsi_initiator
2059  * @brief Clean up an iSCSI task.
2060  *
2061  * @par Description
2062  * Issue a completion to the upper layer and free internal resources for the IO.
2063  *
2064  * @param task The iSCSI task to transmit.
2065  */
2066 static void
2067 ocs_task_cleanup(struct iscsi_task *task)
2068 {
2069  ocs_io_task_t *io_task = task->dd_data;
2070  struct scsi_cmnd *scsi_cmnd = task->sc;
2071 
2072  if (io_task->io) {
2073  ocs_scsi_io_free(io_task->io);
2075  io_task->io = NULL;
2076  }
2077 
2078  if (scsi_cmnd != NULL) {
2079  scsi_cmnd->result = DID_NO_CONNECT;
2080  scsi_cmnd->scsi_done(scsi_cmnd);
2081  }
2082 }
2083 
2084 
2085 /**
2086  * @ingroup openiscsi_initiator
2087  * @brief Transmit an iSCSI task.
2088  *
2089  * @par Description
2090  * Transmit an iSCSI task to the target.
2091  * @n @n
2092  * Requests LLD to transfer cmd task. Returns 0 or the the number of bytes
2093  * transferred on success, and -Exyz value on error. When offloading the data
2094  * path, this is called from queuecommand with the session lock, or from the
2095  * iscsi_conn_send_pdu context with the session lock. When not offloading the
2096  * data path, this is called from the scsi work queue without the session lock.
2097  *
2098  * @param task The iSCSI task to transmit.
2099  *
2100  * @return Returns 0 on success; or a non-zero error code value on
2101  * failure.
2102  */
2103 static int ocs_task_xmit(struct iscsi_task *task)
2104 {
2105  ocs_io_task_t *io_task = task->dd_data;
2106  ocs_io_t *io = NULL;
2107  struct iscsi_conn *conn = task->conn;
2108  ocs_conn_t *ocs_conn = conn->dd_data;
2109  ocs_cxn_t *ocs_cxn = ocs_conn->ocs_ep->cxn;
2110  ocs_t *ocs = ocs_cxn->ocs;
2111  struct scsi_cmnd *scsi_cmnd = task->sc;
2112  int num_sg;
2113  unsigned xferlen;
2115  uint32_t sgl_count;
2116  int rc;
2117 
2118  io_task->task = task;
2119  io = io_task->io;
2120  io_task->original_itt = task->hdr->itt;
2121 
2122  if (scsi_cmnd == NULL) {
2123  rc = ocs_xmit_mtask(task);
2124  if (rc) {
2125  ocs_task_cleanup(task);
2126  }
2127  return rc;
2128  }
2129 
2130  /* save mid-layer command and callback function */
2131  ocs_memset(&io->ini_io, 0, sizeof(io->ini_io));
2132  io->ini_io.scsi_cmd = scsi_cmnd;
2133  io->ini_io.done = scsi_cmnd->scsi_done;
2134  io->ini_io.io_task = io_task;
2135 
2136  io_task->scsi_cmnd = scsi_cmnd;
2137 
2138  num_sg = scsi_dma_map(scsi_cmnd);
2139 
2140  if (num_sg < 0) {
2141  printk("%s: scsi_dma_map returned %d\n", __func__, num_sg);
2142  ocs_task_cleanup(task);
2143  return num_sg;
2144  }
2145 
2146  xferlen = scsi_bufflen(scsi_cmnd);
2147 
2148  if (scsi_sg_count(scsi_cmnd)) {
2149  /* map SGL from Mid-layer to OCS SGL */
2150  sgl_count = sizeof(sgl)/sizeof(sgl[0]);
2151  ocs_scsi_map_sgl(ocs, scsi_cmnd, sgl, &sgl_count);
2152 
2153  switch (scsi_cmnd->sc_data_direction) {
2154  case DMA_FROM_DEVICE:
2155  /* read command */
2156  rc = ocs_scsi_send_rd_io(ocs_cxn, io, scsi_cmnd->device->lun,
2157  scsi_cmnd->cmnd, scsi_cmnd->cmd_len, NULL,
2158  sgl, sgl_count, scsi_bufflen(scsi_cmnd),
2159  ocs_lnx_xport_io_cb, NULL);
2160  break;
2161  case DMA_TO_DEVICE:
2162  /* write command */
2163  rc = ocs_scsi_send_wr_io(ocs_cxn, io, scsi_cmnd->device->lun,
2164  scsi_cmnd->cmnd, scsi_cmnd->cmd_len, NULL,
2165  sgl, sgl_count, scsi_bufflen(scsi_cmnd),
2166  ocs_lnx_xport_io_cb, NULL);
2167  break;
2168  default:
2169  rc = -1;
2170  printk("%s: default %d\n", __func__, scsi_cmnd->sc_data_direction);
2171  }
2172  } else {
2173  /* no data transfer */
2174  rc = ocs_scsi_send_nodata_io(ocs_cxn, io, scsi_cmnd->device->lun,
2175  scsi_cmnd->cmnd, scsi_cmnd->cmd_len,
2176  ocs_lnx_xport_io_cb, NULL);
2177  }
2178 
2179  if (rc) {
2180  ocs_task_cleanup(task);
2181  } else {
2183  }
2184  return rc;
2185 
2186 }
2187 
2188 /**
2189  * @ingroup openiscsi_initiator
2190  * @brief
2191  *
2192  * @par Description
2193  * Requests LLD to fail task. Called with session lock and after the connection
2194  * has been suspended and terminated during recovery. If called from abort task,
2195  * then connection is not suspended or terminated but sk_callback_lock is held.
2196  *
2197  * @param task The iSCSI task to be cleaned up.
2198  *
2199  * @return None.
2200  */
2201 void ocs_cleanup_task(struct iscsi_task *task) {
2202  ocs_io_task_t *io_task;
2203  ocs_io_t *io;
2204 
2205  io_task = task->dd_data;
2206  io = io_task->io;
2207 
2208  switch (io_task->task_state) {
2210  ocs_scsi_io_free(io);
2212  io_task->io = NULL;
2213  break;
2216  break;
2219  break;
2220  }
2221 }
2222 
2223 /**
2224  * @ingroup openiscsi_initiator
2225  * @brief Allocate a new PDU.
2226  *
2227  * @par Description
2228  * This function is called by libiscsi to create a new PDU for a
2229  * task. This function calls the SCSI API to allocate an I/O
2230  * object for the task. libiscsi expects us to allocate memory
2231  * for the PDU and point task->hdr to it.
2232  *
2233  * @param task iSCSI task to which the new PDU belongs.
2234  * @param opcode Opcode of the new PDU.
2235  *
2236  * @return Returns 0 on success; or a negative error code value
2237  * on failure.
2238  */
2239 static int ocs_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
2240 {
2241  ocs_io_task_t *io_task;
2242  struct iscsi_conn *conn;
2243  ocs_conn_t *ocs_conn;
2244  ocs_ep_t *ocs_ep;
2245  ocs_io_t *io;
2246  ocs_cxn_t *cxn;
2247  ocs_iscsi_t *ocs_iscsi;
2248  ocs_t *ocs;
2249 
2250  ocs_assert(task, -EINVAL);
2251 
2252  io_task = task->dd_data;
2253  ocs_assert(io_task, -EINVAL);
2254 
2255  conn = task->conn;
2256  ocs_assert(conn, -EINVAL);
2257 
2258  ocs_conn = conn->dd_data;
2259  ocs_assert(ocs_conn, -EINVAL);
2260 
2261  ocs_ep = ocs_conn->ocs_ep;
2262  ocs_assert(ocs_ep, -EINVAL);
2263 
2264  cxn = ocs_ep->cxn;
2265  ocs_assert(cxn, -EINVAL);
2266 
2267  ocs_iscsi = cxn->iscsi;
2268  ocs_assert(ocs_iscsi, -EINVAL);
2269 
2270  ocs = cxn->ocs;
2271  ocs_assert(ocs, -EINVAL);
2272 
2273  /*
2274  * Return error if WQ is full.
2275  * Lets upper layer to requeue request.
2276  */
2277  if (ocs_scsi_check_cxn_wq_full(ocs, cxn))
2278  return -ENOMEM;
2279 
2281  if (!io) {
2282  printk("%s: No io is available", __func__);
2283  // TODO: Queue the request?
2284  return -ENOMEM;
2285  }
2286 
2287  io_task->io = io;
2289  io->ini_io.io_task = io_task;
2290 
2291  /*
2292  * Save libiscsi's itt. We change it because SLI-4 has specific
2293  * requirements about the format of the ITT and will be changing
2294  * it. Later, when we get
2295  * the completion from SLI-4, we'll change it back before we hand
2296  * the PDU back to libiscsi for processing.
2297  */
2298 
2299  /* setup header so Linux iSCSI transport populate */
2300  task->hdr = (struct iscsi_hdr *)io->bhs;
2301  task->hdr_len = 0;
2302  task->hdr_max = OCS_BHS_ALLOC_SIZE;
2303 
2304  return 0;
2305 }
2306 
2307 /**
2308  * @ingroup openiscsi_initiator
2309  * @brief Return sysfs visibility for a parameter.
2310  * @par Description
2311  *
2312  *
2313  * @param param_type Type of parameter to query.
2314  * @param param Parameter to query.
2315  *
2316  * @return Returns a non-zero mode_t if a parameter is visible
2317  * through sysfs; or 0 if the parameter is not visible.
2318  */
2319 #if defined(SCSI_ISCSI_XPORT_ATTR_IS_VISIBLE_V0)
2320 mode_t ocs_attr_is_visible(int param_type, int param)
2321 #endif
2322 #if defined(SCSI_ISCSI_XPORT_ATTR_IS_VISIBLE_V1)
2323 umode_t ocs_attr_is_visible(int param_type, int param)
2324 #endif
2325 {
2326  switch (param_type) {
2327  case ISCSI_NET_PARAM:
2328  switch (param) {
2329  case ISCSI_NET_PARAM_IFACE_ENABLE:
2330  case ISCSI_NET_PARAM_IPV4_ADDR:
2331  case ISCSI_NET_PARAM_IPV4_SUBNET:
2332  case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
2333  case ISCSI_NET_PARAM_IPV4_GW:
2334  case ISCSI_NET_PARAM_IPV6_ADDR:
2335  case ISCSI_NET_PARAM_VLAN_ID:
2336  case ISCSI_NET_PARAM_VLAN_PRIORITY:
2337  case ISCSI_NET_PARAM_VLAN_ENABLED:
2338  return S_IRUGO;
2339  default:
2340  return 0;
2341  }
2342  case ISCSI_HOST_PARAM:
2343  switch (param) {
2344  case ISCSI_HOST_PARAM_HWADDRESS:
2345  case ISCSI_HOST_PARAM_INITIATOR_NAME:
2346  /* TODO : Enable when PORT_SPEED and PORT_STATE
2347  support added in OEM kernel
2348  */
2349 #if 0
2350  case ISCSI_HOST_PARAM_PORT_STATE:
2351  case ISCSI_HOST_PARAM_PORT_SPEED:
2352 #endif
2353  return S_IRUGO;
2354  default:
2355  return 0;
2356  }
2357  case ISCSI_PARAM:
2358  switch (param) {
2359  case ISCSI_PARAM_MAX_RECV_DLENGTH:
2360  case ISCSI_PARAM_MAX_XMIT_DLENGTH:
2361  case ISCSI_PARAM_HDRDGST_EN:
2362  case ISCSI_PARAM_DATADGST_EN:
2363  case ISCSI_PARAM_CONN_ADDRESS:
2364  case ISCSI_PARAM_CONN_PORT:
2365  case ISCSI_PARAM_EXP_STATSN:
2366  case ISCSI_PARAM_PERSISTENT_ADDRESS:
2367  case ISCSI_PARAM_PERSISTENT_PORT:
2368  case ISCSI_PARAM_PING_TMO:
2369  case ISCSI_PARAM_RECV_TMO:
2370  case ISCSI_PARAM_INITIAL_R2T_EN:
2371  case ISCSI_PARAM_MAX_R2T:
2372  case ISCSI_PARAM_IMM_DATA_EN:
2373  case ISCSI_PARAM_FIRST_BURST:
2374  case ISCSI_PARAM_MAX_BURST:
2375  case ISCSI_PARAM_PDU_INORDER_EN:
2376  case ISCSI_PARAM_DATASEQ_INORDER_EN:
2377  case ISCSI_PARAM_ERL:
2378  case ISCSI_PARAM_TARGET_NAME:
2379  case ISCSI_PARAM_TPGT:
2380  case ISCSI_PARAM_USERNAME:
2381  case ISCSI_PARAM_PASSWORD:
2382  case ISCSI_PARAM_USERNAME_IN:
2383  case ISCSI_PARAM_PASSWORD_IN:
2384  case ISCSI_PARAM_FAST_ABORT:
2385  case ISCSI_PARAM_ABORT_TMO:
2386  case ISCSI_PARAM_LU_RESET_TMO:
2387  case ISCSI_PARAM_IFACE_NAME:
2388  case ISCSI_PARAM_INITIATOR_NAME:
2389  return S_IRUGO;
2390  default:
2391  return 0;
2392  }
2393  }
2394 
2395  return 0;
2396 }
2397 
2398 /**
2399  * @ingroup openiscsi_initiator
2400  * @brief iSCSI transport entry points.
2401  *
2402  * @par Description
2403  * This structure defines the hooks that libiscsi uses to
2404  * call various functions in this driver.
2405  *
2406  */
2407 struct iscsi_transport ocs_lnx_xport_iscsi = {
2408  .owner = THIS_MODULE,
2409  .name = "ocs",
2410  .caps = (CAP_RECOVERY_L0 |
2411  CAP_HDRDGST |
2412  CAP_DATADGST |
2413  CAP_TEXT_NEGO |
2414  CAP_MULTI_CONN |
2415  CAP_DIGEST_OFFLOAD |
2416  CAP_DATA_PATH_OFFLOAD),
2417  .create_session = ocs_session_create,
2418  .destroy_session = ocs_session_destroy,
2419  .create_conn = ocs_conn_create,
2420  .bind_conn = ocs_conn_bind,
2421  .destroy_conn = iscsi_conn_teardown,
2422  .attr_is_visible = ocs_attr_is_visible,
2423  .set_iface_param = ocs_iface_set_param,
2424  .get_iface_param = ocs_iface_get_param,
2425  .set_param = ocs_set_param,
2426  .set_host_param = ocs_set_host_param,
2427  .get_conn_param = ocs_conn_get_param,
2428  .get_session_param = ocs_session_get_param,
2429  .get_host_param = ocs_get_host_param,
2430  .start_conn = ocs_conn_start,
2431  .stop_conn = iscsi_conn_stop,
2432  .send_pdu = iscsi_conn_send_pdu,
2433  .xmit_task = ocs_task_xmit,
2434  .cleanup_task = ocs_cleanup_task,
2435  .alloc_pdu = ocs_alloc_pdu,
2436  .get_stats = ocs_conn_get_stats,
2437  .get_ep_param = ocs_ep_get_param,
2438  .ep_connect = ocs_ep_connect,
2439  .ep_poll = ocs_ep_poll,
2440  .ep_disconnect = ocs_ep_disconnect,
2441  .session_recovery_timedout = iscsi_session_recovery_timedout,
2442 };
2443 
2444 /**
2445  * @page openiscsi_init_overview Initiator API and Open iSCSI Interface Module
2446  * - @ref openiscsi_initiator
2447  *
2448  * <div class="overview">
2449  *
2450  * <h2>Overview</h2>
2451  * <img src="elx_iscsi_init.jpg" alt="iSCSI Initiator Interface" title="iSCSI Initiator Interface" align="right"/>
2452  *
2453  * The Emulex Open-iSCSI interface (ocs_openiscsi) module is a separate loadable module
2454  * included in the OneCore Storage SDK package to be used for initiator support with the
2455  * Linux ocs_iscsi_driver
2456  * (see the <a href="../../../ocs_openiscsi/" target="_blank">driver/linux/ocs_openiscsi
2457  * directory</a>).<br><br>
2458  *
2459  * The ocs_openiscsi module acts as an interface adapter between the driver’s Initiator
2460  * API and the Open-iSCSI kernel module (iSCSI transport and libiscsi.ko).
2461  * The ocs_openiscsi module registers with Linux ocs_iscsi_ramd driver as an initiator, then
2462  * registers with Open-iSCSI as a transport. Emulex SLI-4 adapters are then presented to
2463  * the SCSI Mid-layer as available SCSI host devices.<br><br>
2464  *
2465  * The ocs_openiscsi module depends on symbols exported from the Open-iSCSI’s
2466  * libiscsi.ko module (libiscsi) and the Linux ocs_iscsi_ramd driver. As such, the libiscsi
2467  * and Linux ocs_iscsi_ramd driver must be loaded before the ocs_openiscsi module is
2468  * loaded.<br><br>
2469  *
2470  * Once the ocs_openiscsi module is loaded, it calls into the libiscsi to register
2471  * itself as an interface and calls into the Linux ocs_iscsi_ramd driver to register
2472  * itself as an initiator.<br><br>
2473  *
2474  * <h2>Initiator Task Tag (ITT) Handling</h2>
2475  * Open-iSCSI presents its iSCSI transport with complete PDUs to be executed. The ITT is
2476  * set by the libiscsi and is used on a task completion to associate the response PDU with
2477  * the correct task.<br><br>
2478  *
2479  * SLI-4 has its own rules about the contents of the ITT in a PDU. The ITT for SLI-4 must
2480  * contain the WRB index and the SGL_ICD index for the command being submitted. To
2481  * accommodate these requirements, the ocs_openiscsi module must store the ITT when a
2482  * task is submitted, and then restore the ITT before it reports a completion back to the
2483  * libiscsi.ko. The ITT is saved by the ocs_alloc_pdu() function, and then restored by the
2484  * various callback functions.
2485  *
2486  * <h2>ocs_openiscsi Module Load</h2>
2487  * When the ocs_openiscsi module is loaded, it calls iscsi_register_transport. This
2488  * provides the libiscsi with pointers (such as start_conn, ep_connect, and
2489  * get_stats) to the ocs_openiscsi module functions (such as ocs_conn_start(),
2490  * ocs_ep_connect(), and ocs_conn_get_stats()) that are needed to act as a transport. The libiscsi
2491  * can then use those ocs_openiscsi module functions to manage Open-iSCSI connections
2492  * and I/Os.<br><br>
2493  *
2494  * After registering with the libiscsi, the ocs_openiscsi module calls ocs_get_instance() in
2495  * the Linux ocs_iscsi_ramd driver to get information about each device that the driver
2496  * has available. For each of these devices, the ocs_openiscsi module calls
2497  * ocs_scsi_register_ini_templ() in the driver. This function call provides pointers to
2498  * functions that the driver can use to add/delete domains, sports, and targets, and to
2499  * send notifications to the ocs_openiscsi module.<br><br>
2500  *
2501  * Finally, the ocs_openiscsi module completes the registration with the libiscsi by calling
2502  * iscsi_host_add and iscsi_create_iface.
2503  *
2504  * <h2>ocs_openiscsi Module Load</h2>
2505  * The connect process of Open-iSCSI to the Linux ocs_iscsi_ramd driver has four steps:
2506  *
2507  * <ol><li>Create an endpoint.</li>
2508  * <li>Create a session.</li>
2509  * <li>Create a connection structure.</li>
2510  * <li>Bind the three (endpoint, session, and connection structure) together.</li></ol>
2511  *
2512  * <br>For the first step, the Open-iSCSI iSCSI transport calls ocs_ep_connect(). The
2513  * ocs_ep_connect() function calls into the libiscsi to create the endpoint structure, then
2514  * calls ocs_xport_control() into the Linux ocs_iscsi_ramd driver to establish the
2515  * connection.<br><br>
2516  *
2517  * The remaining three steps do not require any interaction with the Linux ocs_iscsi_ramd
2518  * driver. The iSCSI transport calls into the ocs_openiscsi module, which calls into libiscsi
2519  * to create the required structures and bind them.
2520  *
2521  * <h2>Management PDU Processing</h2>
2522  * Open-iSCSI has an interface to send management (non-I/O) PDUs, such as LOGIN and NO-OP.<br><br>
2523  *
2524  * The iSCSI transport calls iscsi_conn_send_pdu, which then calls ocs_alloc_pdu() to
2525  * allocate memory for the transaction. It fills in the PDU structure and calls
2526  * ocs_task_xmit(). Within the task structure, the scsi_cmnd pointer is NULL (the
2527  * distinguishing factor between a management task and an I/O task). The ocs_task_xmit()
2528  * keys off the NULL scsi_cmnd pointer and calls ocs_xmit_mtask() to send the management
2529  * task. The ocs_xmit_mtask() function sets up the correct callback function based on the
2530  * type of PDU, and then calls into ocs_iscsi_unassisted_pdu_send() in the ocs_iscsi_ramd
2531  * driver’s iSCSI API to send the PDU.<br><br>
2532  *
2533  * Depending on the value of the set_dm argument, the callback is called either when the
2534  * PDU is sent or when the response to the PDU is received. The callback function
2535  * performs any required processing on the response; calls iscsi_complete_pdu to notify
2536  * libiscsi that the task is done; and finally calls ocs_scsi_io_free() to free the I/O
2537  * resources.
2538  *
2539  * <h2>IO PDU Processing</h2>
2540  * I/O PDU processing is similar to management PDU processing. The I/O begins in the
2541  * SCSI mid-layer with a call to scsi_dispatch_cmd, which then gets forwarded to
2542  * iscsi_queue_command in libiscsi. A PDU is allocated by calling ocs_alloc_pdu(). The
2543  * libiscsi fills in the PDU details, including the SCSI CDB and data; and then calls
2544  * ocs_task_xmit() to send the task.<br><br>
2545  *
2546  * The ocs_openiscsi module identifies the task as a SCSI command task due to the
2547  * non-NULL scsi_cmd pointer. Based on the sc_data_direction field in the scsi_cmd, the
2548  * ocs_openiscsi module calls ocs_scsi_send_rd_io() or ocs_scsi_send_wr_io(). The
2549  * command callback is set to ocs_lnx_xport_io_cb().<br><br>
2550  *
2551  * When the command completes and ocs_lnx_xport_io_cb() is called, the ocs_openiscsi
2552  * module calls iscsi_complete_scsi_task to inform the libiscsi that the task is complete.
2553  * Next, the ocs_openiscsi module calls ocs_scsi_cmd_cb(), which then calls the scsi_done
2554  * function from the I/O.<br><br>
2555  *
2556  * Finally, the ocs_openiscsi module calls ocs_scsi_io_free to release the I/O resources.
2557  *
2558  * <br>
2559  * </div><!-- overview -->
2560  *
2561  */
int32_t ocs_iscsi_unassisted_pdu_send(ocs_t *ocs, ocs_io_t *io, ocs_cxn_t *cxn, void *bhs, void *data, uint32_t data_size, bool is_login, bool set_dm, ocs_iscsi_pdu_cb_t cb)
static void ocs_session_max_cmd_sn_set(ocs_cxn_t *cxn, uint32_t max_cmd_sn)
Definition: ocs_session.h:174
int32_t ocs_scsi_ini_new_sport(ocs_sport_t *sport)
Process creation of a new SPORT.
int ocs_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t dt_len)
#define OCS_DEFAULT_SG_SEG_CNT
Definition: ocs_scsi_ini.h:34
int ocs_iface_get_param(struct iscsi_iface *iface, enum iscsi_param_type param_type, int param, char *buf)
uint8_t scsi_status
Definition: ocs_scsi.h:92
struct iscsi_task * task
Definition: ocs_scsi_ini.h:66
int ocs_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
Poll to see if a connection is established.
ocs_link_state_e
enum identifying the link state.
Definition: ocs_iscsi_api.h:66
int32_t ocs_iscsi_register_link_state_callback(ocs_t *ocs, ocs_link_state_cb_t cb)
Register to receive link state change notifications.
Definition: ocs_iscsi.c:3324
void ocs_session_destroy(struct iscsi_cls_session *cls_session)
Destroy an iSCSI session.
struct iscsi_cls_session * ocs_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth, u32 initial_cmdsn)
Create a new iscsi session.
int32_t ocs_scsi_ini_new_domain(ocs_domain_t *domain)
Accept new domain notification.
ocs_scsi_ini_template_t ocs_iscsi_ini_template
struct iscsi_endpoint * openiscsi_ep
Definition: ocs_scsi_ini.h:51
int32_t ocs_scsi_ini_driver_init(int32_t initiator)
Initialize initiator client.
int32_t ocs_iscsi_mtask_cb_tcp_ack_wait_rsp(ocs_io_t *io, uint32_t exp_cmdsn, uint32_t max_cmdsn, uint8_t response)
Completion handler for non-SCSI initiator tasks that complete on TCP ACK.
Defines the generic iSCSI basic header segment.
uint8_t ip_address[16]
Definition: ocs_hal.h:261
#define OCS_BHS_ALLOC_SIZE
Definition: ocs_scsi_ini.h:36
uintptr_t addr
Definition: ocs_scsi.h:219
static int32_t ocs_lnx_xport_unsol_cb(void *arg, ocs_cxn_t *cxn, ocs_hal_rq_buffer_t *bhs, uint32_t hdr_len, ocs_hal_rq_buffer_t *data, uint32_t data_len, uint8_t code)
Unsolicited event handler.
static int32_t ocs_lnx_xport_io_cb(ocs_io_t *io, ocs_scsi_io_status_e status, ocs_scsi_cmd_resp_t *rsp, uint32_t flags, void *arg)
IO completion handler for iSCSI initiator.
#define OCS_CMD_PER_LUN
Definition: ocs_scsi_ini.h:35
ocs_scsi_ddump_type_e
Definition: ocs_scsi.h:366
static void ocs_lnx_xport_fail_session(struct iscsi_cls_session *cls_session)
Helper function for marking sessions as failed.
ocs_cxn_t * cxn
Definition: ocs_scsi_ini.h:52
int32_t ocs_ramlog_printf(void *os, const char *fmt,...)
Append formatted printf data to a ramlog buffer.
Definition: ocs_ramlog.c:179
static struct scsi_transport_template * transport_template
uint32_t sense_data_length
Definition: ocs_scsi.h:97
ocs_hal_target_login_options_t lgn_options
Definition: ocs_hal.h:563
#define ISCSI_RESP_TEXT
ocs_hal_abort_type_e
HAL abort types.
Definition: ocs_hal.h:675
static void ocs_session_calc_cmd_window(ocs_cxn_t *cxn)
Definition: ocs_session.h:194
static int ocs_conn_update_context(struct iscsi_conn *conn)
int32_t ocs_iscsi_mtask_cb_with_rsp(ocs_io_t *io, uint32_t exp_cmdsn, uint32_t max_cmdsn, uint8_t response)
Completion handler for non-SCSI initiator tasks.
bool ocs_scsi_check_cxn_wq_full(ocs_t *ocs, ocs_cxn_t *cxn)
Check Connection WQ&#39;s full status.
Definition: ocs_scsi.c:2374
char * ocs_iscsi_ini_get_name(ocs_t *ocs)
Return this initiator&#39;s name.
HAL object.
Definition: ocs_hal.h:724
generic scatter-gather list structure
Definition: ocs_scsi.h:218
void ocs_cleanup_task(struct iscsi_task *task)
int32_t ocs_iscsi_send_context_udpate(ocs_cxn_t *cxn)
Sends the login parameters to the FW.
void ocs_scsi_io_free(ocs_io_t *io)
Free a SCSI IO context.
Definition: ocs_scsi.c:2264
#define CONN_STATE_NEW_CONN
int32_t ocs_iscsi_mtask_cb_tcp_ack_no_rsp(ocs_io_t *io, uint32_t exp_cmdsn, uint32_t max_cmdsn, uint8_t response)
Completion handler for non-SCSI initiator tasks that complete on TCP ACK.
#define ISCSI_CMD_TEXT
defines the parameters for an IO based on the IO type.
Definition: ocs_hal.h:501
int32_t ocs_scsi_map_sgl(ocs_t *, struct scsi_cmnd *, ocs_scsi_sgl_t *, uint32_t *)
Map mid-layer SGLs to ocs SGLs.
int32_t ocs_scsi_send_rd_io(ocs_node_t *node, ocs_io_t *io, uint32_t lun, void *cdb, uint32_t cdb_len, ocs_scsi_dif_info_t *dif_info, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, ocs_scsi_rsp_io_cb_t cb, void *arg)
Initiate initiator read IO.
Definition: ocs_scsi.c:1693
void ocs_print_stack(void)
static void ocs_task_cleanup(struct iscsi_task *task)
Clean up an iSCSI task.
ocs_conn_t * ocs_conn
Definition: ocs_scsi_ini.h:53
int32_t ocs_xport_control(ocs_xport_t *xport, ocs_xport_ctrl_e cmd,...)
Perform transport attach function.
Definition: ocs_xport.c:100
SCSI command response.
Definition: ocs_scsi.h:91
uint8_t * ocs_iscsi_mac_get(ocs_t *ocs)
Gets the MAC address of the iSCSI device.
Definition: ocs_iscsi.c:1323
#define ISCSI_RESP_LOGIN
#define ISCSI_CMD_LOGOUT
static void ocs_scsi_cmnd_result_chk_cond(struct scsi_cmnd *scsi_cmd)
Set scsi_cmnd check condition.
ocs_io_task_state_e task_state
Definition: ocs_scsi_ini.h:63
int ocs_get_host_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf)
int32_t ocs_scsi_ini_del_device(ocs_t *ocs)
Tears down initiator members of ocs structure.
void ocs_scsi_ini_ddump(ocs_textbuf_t *textbuf, ocs_scsi_ddump_type_e type, void *obj)
Generate driver dump data for debugging.
int ocs_scsi_abort_io(ocs_hal_t *hal, ocs_hal_io_t *hio, ocs_hal_abort_type_e abort_type)
Definition: ocs_scsi.c:2342
struct scsi_cmnd * scsi_cmnd
Definition: ocs_scsi_ini.h:65
int ocs_conn_start(struct iscsi_cls_conn *cls_conn)
Offload of session to chip.
#define ISCSI_CMD_NOOP
iSCSI object
Definition: ocs_iscsi.h:293
uint32_t original_itt
Definition: ocs_scsi_ini.h:67
int ocs_conn_get_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf)
static void ocs_lnx_xport_link_state(ocs_t *ocs, ocs_link_state_e link_state)
Called when the link changes state.
ocs_hal_ip_type_e ip_type
Definition: ocs_hal.h:260
Defines a wrapper for the RQ payload buffers so that we can place it back on the proper queue...
Definition: ocs_hal.h:694
HAL IO object.
Definition: ocs_hal.h:471
int32_t ocs_scsi_new_target(ocs_node_t *node)
Receive notification of a new SCSI target node.
static void ocs_session_exp_cmd_sn_set(ocs_cxn_t *cxn, uint32_t exp_cmd_sn)
Definition: ocs_session.h:164
Defines the iSCSI nop-out PDU header.
struct iscsi_endpoint * ocs_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, int non_blocking)
Ask the chip to create TCP connection.
struct ocs_hal_io_param_t::@17 context_upd
static int ocs_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
Allocate a new PDU.
uint8_t * sense_data
Definition: ocs_scsi.h:96
void ocs_iscsi_rx_buffers_free(ocs_iscsi_t *iscsi, ocs_hal_rq_buffer_t *header, ocs_hal_rq_buffer_t *payload)
Add a receive buffer pair to the Receive Queue, if an error is received, then queue the buffer...
Definition: ocs_iscsi.c:4447
static int ocs_xmit_mtask(struct iscsi_task *task)
Transmit a management task.
static uint32_t ocs_session_exp_cmd_sn_get(ocs_cxn_t *cxn)
Definition: ocs_session.h:122
ocs_scsi_del_target_reason_e
Definition: ocs_scsi.h:343
struct scsi_host_template host_template
Host Template.
int ocs_conn_bind(struct iscsi_cls_session *cls_session, struct iscsi_cls_conn *cls_conn, u64 transport_fd, int is_leading)
Binds an iSCSI connection to an endpoint.
int32_t ocs_scsi_send_nodata_io(ocs_node_t *node, ocs_io_t *io, uint32_t lun, void *cdb, uint32_t cdb_len, ocs_scsi_rsp_io_cb_t cb, void *arg)
Initiate initiator SCSI command with no data.
Definition: ocs_scsi.c:1724
uint32_t opcode
int32_t ocs_scsi_cmd_cb(ocs_io_t *, ocs_scsi_io_status_e, ocs_scsi_cmd_resp_t *, uint32_t, void *)
SCSI IO callback function.
int32_t ocs_scsi_ini_driver_exit(int32_t initiator)
initiator client exit
struct iscsi_cls_conn * ocs_conn_create(struct iscsi_cls_session *cls_session, u32 cid)
Create an instance of iSCSI connection.
#define OCS_ISCSI_LOGIN_MAX_RECV_DATA_SEG_LEN
umode_t ocs_attr_is_visible(int param_type, int param)
Return sysfs visibility for a parameter.
structure wrapping an IP address together with it&#39;s type.
Definition: ocs_hal.h:259
#define ISCSI_RESP_LOGOUT
static int ocs_task_xmit(struct iscsi_task *task)
Transmit an iSCSI task.
#define OCS_NL_VENDOR_ID
Definition: ocs_scsi_ini.h:33
void ocs_set_update_ctx_options(ocs_hal_io_param_t *iparam, struct iscsi_conn *conn)
Set UPDATE CONTEXT options.
size_t len
Definition: ocs_scsi.h:221
int ocs_ep_get_param(struct iscsi_endpoint *ep, enum iscsi_param param, char *buf)
static int ocs_eh_abort(struct scsi_cmnd *sc)
uint32_t statsn
Definition: ocs_hal.h:564
ocs_io_t * io
Definition: ocs_scsi_ini.h:64
int32_t ocs_scsi_ini_new_device(ocs_t *ocs)
Initializes any initiator fields on the ocs structure.
int ocs_set_host_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf, int buflen)
int32_t residual
Definition: ocs_scsi.h:98
ocs_dma_t dma
Definition: ocs_hal.h:696
void ocs_scsi_ini_del_sport(ocs_sport_t *sport)
Process deletion of a SPORT.
int32_t ocs_scsi_del_target(ocs_node_t *node, ocs_scsi_del_target_reason_e reason)
Delete a SCSI target node.
static int ocs_sockaddr_to_hal_ip(struct sockaddr *addr, ocs_hal_ip_address_t *hal_ip, uint16_t *port)
struct iscsi_transport ocs_lnx_xport_iscsi
iSCSI transport entry points.
static uint32_t ocs_session_cmd_window_get(ocs_cxn_t *cxn)
Definition: ocs_session.h:138
int ocs_session_get_param(struct iscsi_cls_session *cls_session, enum iscsi_param param, char *buf)
void ocs_iscsi_unregister_link_state_callback(ocs_t *ocs, ocs_link_state_cb_t cb)
Unregister a link state change callback.
Definition: ocs_iscsi.c:3360
#define ocs_assert(cond,...)
Definition: ocs_debug.h:163
#define ISCSI_CMD_LOGIN
#define CONN_STATE_FULL_FEATURE
#define ocs_scsi_midlayer_result(host_code, scsi_code)
int32_t ocs_scsi_send_wr_io(ocs_node_t *node, ocs_io_t *io, uint32_t lun, void *cdb, uint32_t cdb_len, ocs_scsi_dif_info_t *dif_info, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, ocs_scsi_rsp_io_cb_t cb, void *arg)
Initiate initiator write IO.
Definition: ocs_scsi.c:1761
#define OCS_SCSI_CALL_COMPLETE
Definition: ocs_scsi.h:249
int32_t(* ocs_iscsi_pdu_cb_t)(ocs_io_t *io, uint32_t exp_cmdsn, uint32_t max_cmdsn, uint8_t response)
ocs_io_t * ocs_scsi_io_alloc(ocs_node_t *node, ocs_scsi_io_role_e role)
allocate a SCSI IO context.
Definition: ocs_scsi.c:2187
ocs_scsi_io_status_e
Definition: ocs_scsi.h:105
const char const char * fmt
Definition: ocs_ddump.h:54
#define ISCSI_CMD_TASK
Defines the iSCSI nop-in PDU header.
uint32_t ocs_scsi_get_property(ocs_t *ocs, ocs_scsi_property_e prop)
Return SCSI API integer valued property.
Definition: ocs_scsi.c:2048
void ocs_scsi_ini_del_domain(ocs_domain_t *domain)
Accept domain lost notification.
ocs_session_login_options_t session_options
Definition: ocs_hal.h:322
int ocs_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf, int buflen)
void ocs_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
#define ISCSI_CMD_SNACK
void ocs_ep_disconnect(struct iscsi_endpoint *ep)
Tears down the TCP connection.