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