ql4_bsg.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * QLogic iSCSI HBA Driver
  3. * Copyright (c) 2011 QLogic Corporation
  4. *
  5. * See LICENSE.qla4xxx for copyright and licensing details.
  6. */
  7. #include "ql4_def.h"
  8. #include "ql4_glbl.h"
  9. #include "ql4_bsg.h"
  10. static int
  11. qla4xxx_read_flash(struct bsg_job *bsg_job)
  12. {
  13. struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
  14. struct scsi_qla_host *ha = to_qla_host(host);
  15. struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
  16. struct iscsi_bsg_request *bsg_req = bsg_job->request;
  17. uint32_t sg_cnt;
  18. uint32_t offset = 0;
  19. uint32_t length = 0;
  20. dma_addr_t flash_dma;
  21. uint8_t *flash = NULL;
  22. int rval = 0;
  23. bsg_reply->reply_payload_rcv_len = 0;
  24. if (unlikely(pci_channel_offline(ha->pdev)))
  25. return -EINVAL;
  26. if (ha->flash_state != QLFLASH_WAITING)
  27. return -EBUSY;
  28. /* TODO: Add check for adapter online, reset active?? */
  29. sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
  30. bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
  31. if (!sg_cnt)
  32. return -ENOMEM;
  33. if (sg_cnt != bsg_job->reply_payload.sg_cnt) {
  34. ql4_printk(KERN_ERR, ha, "dma mapping resulted in different"
  35. " sg counts, sg_cnt: %x dma_sg_cnt: %x\n",
  36. bsg_job->reply_payload.sg_cnt, sg_cnt);
  37. rval = -EAGAIN;
  38. goto unmap_sg;
  39. }
  40. offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
  41. length = bsg_job->reply_payload.payload_len;
  42. flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma,
  43. GFP_KERNEL);
  44. if (!flash) {
  45. ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
  46. "data\n", __func__);
  47. rval = -ENOMEM;
  48. goto unmap_sg;
  49. }
  50. ha->flash_state = QLFLASH_READING;
  51. if (qla4xxx_get_flash(ha, flash_dma, offset, length))
  52. bsg_reply->result = (DID_ERROR << 16);
  53. else {
  54. sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
  55. bsg_job->reply_payload.sg_cnt,
  56. flash, length);
  57. bsg_reply->result = DID_OK;
  58. bsg_reply->reply_payload_rcv_len = length;
  59. }
  60. if (flash)
  61. dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma);
  62. ha->flash_state = QLFLASH_WAITING;
  63. unmap_sg:
  64. dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
  65. bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
  66. if (!rval)
  67. bsg_job_done(bsg_job, bsg_reply->result,
  68. bsg_reply->reply_payload_rcv_len);
  69. return rval;
  70. }
  71. static int
  72. qla4xxx_update_flash(struct bsg_job *bsg_job)
  73. {
  74. struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
  75. struct scsi_qla_host *ha = to_qla_host(host);
  76. struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
  77. struct iscsi_bsg_request *bsg_req = bsg_job->request;
  78. uint32_t sg_cnt;
  79. uint32_t length = 0;
  80. uint32_t offset = 0;
  81. uint32_t options = 0;
  82. dma_addr_t flash_dma;
  83. uint8_t *flash = NULL;
  84. int rval = 0;
  85. bsg_reply->reply_payload_rcv_len = 0;
  86. if (unlikely(pci_channel_offline(ha->pdev)))
  87. return -EINVAL;
  88. if (ha->flash_state != QLFLASH_WAITING)
  89. return -EBUSY;
  90. sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
  91. bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
  92. if (!sg_cnt)
  93. return -ENOMEM;
  94. if (sg_cnt != bsg_job->request_payload.sg_cnt) {
  95. ql4_printk(KERN_ERR, ha, "dma mapping resulted in different "
  96. "sg counts request_sg_cnt: %x dma_request_sg_cnt: "
  97. "%x\n", bsg_job->request_payload.sg_cnt, sg_cnt);
  98. rval = -EAGAIN;
  99. goto unmap_sg;
  100. }
  101. length = bsg_job->request_payload.payload_len;
  102. offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
  103. options = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
  104. flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma,
  105. GFP_KERNEL);
  106. if (!flash) {
  107. ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
  108. "data\n", __func__);
  109. rval = -ENOMEM;
  110. goto unmap_sg;
  111. }
  112. ha->flash_state = QLFLASH_WRITING;
  113. sg_copy_to_buffer(bsg_job->request_payload.sg_list,
  114. bsg_job->request_payload.sg_cnt, flash, length);
  115. if (qla4xxx_set_flash(ha, flash_dma, offset, length, options))
  116. bsg_reply->result = (DID_ERROR << 16);
  117. else {
  118. bsg_reply->result = DID_OK;
  119. bsg_reply->reply_payload_rcv_len = length;
  120. }
  121. if (flash)
  122. dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma);
  123. ha->flash_state = QLFLASH_WAITING;
  124. unmap_sg:
  125. dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
  126. bsg_job->reply_payload.sg_cnt, DMA_TO_DEVICE);
  127. if (!rval)
  128. bsg_job_done(bsg_job, bsg_reply->result,
  129. bsg_reply->reply_payload_rcv_len);
  130. return rval;
  131. }
  132. /**
  133. * qla4xxx_process_vendor_specific - handle vendor specific bsg request
  134. * @job: iscsi_bsg_job to handle
  135. **/
  136. int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job)
  137. {
  138. struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
  139. struct iscsi_bsg_request *bsg_req = bsg_job->request;
  140. struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
  141. struct scsi_qla_host *ha = to_qla_host(host);
  142. switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) {
  143. case QLISCSI_VND_READ_FLASH:
  144. return qla4xxx_read_flash(bsg_job);
  145. case QLISCSI_VND_UPDATE_FLASH:
  146. return qla4xxx_update_flash(bsg_job);
  147. default:
  148. ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: "
  149. "0x%x\n", __func__, bsg_req->msgcode);
  150. bsg_reply->result = (DID_ERROR << 16);
  151. bsg_reply->reply_payload_rcv_len = 0;
  152. bsg_job_done(bsg_job, bsg_reply->result,
  153. bsg_reply->reply_payload_rcv_len);
  154. return -ENOSYS;
  155. }
  156. }
  157. /**
  158. * qla4xxx_bsg_request - handle bsg request from ISCSI transport
  159. * @job: iscsi_bsg_job to handle
  160. */
  161. int qla4xxx_bsg_request(struct bsg_job *bsg_job)
  162. {
  163. struct iscsi_bsg_request *bsg_req = bsg_job->request;
  164. struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
  165. struct scsi_qla_host *ha = to_qla_host(host);
  166. switch (bsg_req->msgcode) {
  167. case ISCSI_BSG_HST_VENDOR:
  168. return qla4xxx_process_vendor_specific(bsg_job);
  169. default:
  170. ql4_printk(KERN_ERR, ha, "%s: invalid BSG command: 0x%x\n",
  171. __func__, bsg_req->msgcode);
  172. }
  173. return -ENOSYS;
  174. }