zfcp_fc.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * zfcp device driver
  3. *
  4. * Fibre Channel related definitions and inline functions for the zfcp
  5. * device driver
  6. *
  7. * Copyright IBM Corporation 2009
  8. */
  9. #ifndef ZFCP_FC_H
  10. #define ZFCP_FC_H
  11. #include <scsi/fc/fc_els.h>
  12. #include <scsi/fc/fc_fcp.h>
  13. #include <scsi/scsi_cmnd.h>
  14. #include <scsi/scsi_tcq.h>
  15. /**
  16. * struct zfcp_fc_els_adisc - everything required in zfcp for issuing ELS ADISC
  17. * @els: data required for issuing els fsf command
  18. * @req: scatterlist entry for ELS ADISC request
  19. * @resp: scatterlist entry for ELS ADISC response
  20. * @adisc_req: ELS ADISC request data
  21. * @adisc_resp: ELS ADISC response data
  22. */
  23. struct zfcp_fc_els_adisc {
  24. struct zfcp_send_els els;
  25. struct scatterlist req;
  26. struct scatterlist resp;
  27. struct fc_els_adisc adisc_req;
  28. struct fc_els_adisc adisc_resp;
  29. };
  30. /**
  31. * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd
  32. * @fcp: fcp_cmnd to setup
  33. * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB
  34. */
  35. static inline
  36. void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi)
  37. {
  38. char tag[2];
  39. int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun);
  40. if (scsi_populate_tag_msg(scsi, tag)) {
  41. switch (tag[0]) {
  42. case MSG_ORDERED_TAG:
  43. fcp->fc_pri_ta |= FCP_PTA_ORDERED;
  44. break;
  45. case MSG_SIMPLE_TAG:
  46. fcp->fc_pri_ta |= FCP_PTA_SIMPLE;
  47. break;
  48. };
  49. } else
  50. fcp->fc_pri_ta = FCP_PTA_SIMPLE;
  51. if (scsi->sc_data_direction == DMA_FROM_DEVICE)
  52. fcp->fc_flags |= FCP_CFL_RDDATA;
  53. if (scsi->sc_data_direction == DMA_TO_DEVICE)
  54. fcp->fc_flags |= FCP_CFL_WRDATA;
  55. memcpy(fcp->fc_cdb, scsi->cmnd, scsi->cmd_len);
  56. fcp->fc_dl = scsi_bufflen(scsi);
  57. }
  58. /**
  59. * zfcp_fc_fcp_tm - setup FCP command as task management command
  60. * @fcp: fcp_cmnd to setup
  61. * @dev: scsi_device where to send the task management command
  62. * @tm: task management flags to setup tm command
  63. */
  64. static inline
  65. void zfcp_fc_fcp_tm(struct fcp_cmnd *fcp, struct scsi_device *dev, u8 tm_flags)
  66. {
  67. int_to_scsilun(dev->lun, (struct scsi_lun *) &fcp->fc_lun);
  68. fcp->fc_tm_flags |= tm_flags;
  69. }
  70. /**
  71. * zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly
  72. * @fcp_rsp: FCP RSP IU to evaluate
  73. * @scsi: SCSI command where to update status and sense buffer
  74. */
  75. static inline
  76. void zfcp_fc_eval_fcp_rsp(struct fcp_resp_with_ext *fcp_rsp,
  77. struct scsi_cmnd *scsi)
  78. {
  79. struct fcp_resp_rsp_info *rsp_info;
  80. char *sense;
  81. u32 sense_len, resid;
  82. u8 rsp_flags;
  83. set_msg_byte(scsi, COMMAND_COMPLETE);
  84. scsi->result |= fcp_rsp->resp.fr_status;
  85. rsp_flags = fcp_rsp->resp.fr_flags;
  86. if (unlikely(rsp_flags & FCP_RSP_LEN_VAL)) {
  87. rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
  88. if (rsp_info->rsp_code == FCP_TMF_CMPL)
  89. set_host_byte(scsi, DID_OK);
  90. else {
  91. set_host_byte(scsi, DID_ERROR);
  92. return;
  93. }
  94. }
  95. if (unlikely(rsp_flags & FCP_SNS_LEN_VAL)) {
  96. sense = (char *) &fcp_rsp[1];
  97. if (rsp_flags & FCP_RSP_LEN_VAL)
  98. sense += fcp_rsp->ext.fr_sns_len;
  99. sense_len = min(fcp_rsp->ext.fr_sns_len,
  100. (u32) SCSI_SENSE_BUFFERSIZE);
  101. memcpy(scsi->sense_buffer, sense, sense_len);
  102. }
  103. if (unlikely(rsp_flags & FCP_RESID_UNDER)) {
  104. resid = fcp_rsp->ext.fr_resid;
  105. scsi_set_resid(scsi, resid);
  106. if (scsi_bufflen(scsi) - resid < scsi->underflow &&
  107. !(rsp_flags & FCP_SNS_LEN_VAL) &&
  108. fcp_rsp->resp.fr_status == SAM_STAT_GOOD)
  109. set_host_byte(scsi, DID_ERROR);
  110. }
  111. }
  112. #endif