1 /*- 2 * Copyright 2016-2021 Microchip Technology, Inc. and/or its subsidiaries. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 27 #include "smartpqi_includes.h" 28 29 /* 30 * Process internal RAID response in the case of success. 31 */ 32 void 33 pqisrc_process_internal_raid_response_success(pqisrc_softstate_t *softs,rcb_t *rcb) 34 { 35 DBG_FUNC("IN"); 36 37 rcb->status = REQUEST_SUCCESS; 38 rcb->req_pending = false; 39 40 DBG_FUNC("OUT"); 41 } 42 43 /* 44 * Process internal RAID response in the case of failure. 45 */ 46 void 47 pqisrc_process_internal_raid_response_error(pqisrc_softstate_t *softs, 48 rcb_t *rcb, uint16_t err_idx) 49 { 50 raid_path_error_info_elem_t error_info; 51 52 DBG_FUNC("IN"); 53 54 rcb->error_info = (char *) (softs->err_buf_dma_mem.virt_addr) + 55 (err_idx * PQI_ERROR_BUFFER_ELEMENT_LENGTH); 56 57 memcpy(&error_info, rcb->error_info, sizeof(error_info)); 58 59 DBG_INFO("error_status 0x%x data_in_result 0x%x data_out_result 0x%x\n", 60 error_info.status, error_info.data_in_result, error_info.data_out_result); 61 62 rcb->status = REQUEST_FAILED; 63 64 switch (error_info.data_out_result) { 65 case PQI_RAID_DATA_IN_OUT_GOOD: 66 if (error_info.status == PQI_RAID_DATA_IN_OUT_GOOD) 67 rcb->status = REQUEST_SUCCESS; 68 break; 69 case PQI_RAID_DATA_IN_OUT_UNDERFLOW: 70 if (error_info.status == PQI_RAID_DATA_IN_OUT_GOOD || 71 error_info.status == PQI_RAID_STATUS_CHECK_CONDITION) 72 rcb->status = REQUEST_SUCCESS; 73 break; 74 } 75 76 rcb->req_pending = false; 77 78 DBG_FUNC("OUT"); 79 } 80 81 /* 82 * Process the AIO/RAID IO in the case of success. 83 */ 84 void 85 pqisrc_process_io_response_success(pqisrc_softstate_t *softs, rcb_t *rcb) 86 { 87 DBG_FUNC("IN"); 88 89 os_io_response_success(rcb); 90 91 DBG_FUNC("OUT"); 92 } 93 94 static void 95 pqisrc_extract_sense_data(sense_data_u_t *sense_data, uint8_t *key, uint8_t *asc, uint8_t *ascq) 96 { 97 if (sense_data->fixed_format.response_code == SCSI_SENSE_RESPONSE_70 || 98 sense_data->fixed_format.response_code == SCSI_SENSE_RESPONSE_71) 99 { 100 sense_data_fixed_t *fixed = &sense_data->fixed_format; 101 102 *key = fixed->sense_key; 103 *asc = fixed->sense_code; 104 *ascq = fixed->sense_qual; 105 } 106 else if (sense_data->descriptor_format.response_code == SCSI_SENSE_RESPONSE_72 || 107 sense_data->descriptor_format.response_code == SCSI_SENSE_RESPONSE_73) 108 { 109 sense_data_descriptor_t *desc = &sense_data->descriptor_format; 110 111 *key = desc->sense_key; 112 *asc = desc->sense_code; 113 *ascq = desc->sense_qual; 114 } 115 else 116 { 117 *key = 0xFF; 118 *asc = 0xFF; 119 *ascq = 0xFF; 120 } 121 } 122 123 static void 124 pqisrc_show_sense_data_simple(pqisrc_softstate_t *softs, rcb_t *rcb, sense_data_u_t *sense_data) 125 { 126 uint8_t opcode = rcb->cdbp ? rcb->cdbp[0] : 0xFF; 127 char *path = io_path_to_ascii(rcb->path); 128 uint8_t key, asc, ascq; 129 pqisrc_extract_sense_data(sense_data, &key, &asc, &ascq); 130 131 DBG_NOTE("[ERR INFO] BTL: %d:%d:%d op=0x%x path=%s K:C:Q: %x:%x:%x\n", 132 rcb->dvp->bus, rcb->dvp->target, rcb->dvp->lun, 133 opcode, path, key, asc, ascq); 134 } 135 136 void 137 pqisrc_show_sense_data_full(pqisrc_softstate_t *softs, rcb_t *rcb, sense_data_u_t *sense_data) 138 { 139 pqisrc_print_buffer(softs, "sense data", sense_data, 32, 0); 140 141 pqisrc_show_sense_data_simple(softs, rcb, sense_data); 142 143 /* add more detail here as needed */ 144 } 145 146 147 /* 148 * Process the error info for AIO in the case of failure. 149 */ 150 void 151 pqisrc_process_aio_response_error(pqisrc_softstate_t *softs, 152 rcb_t *rcb, uint16_t err_idx) 153 { 154 aio_path_error_info_elem_t *err_info = NULL; 155 156 DBG_FUNC("IN"); 157 158 err_info = (aio_path_error_info_elem_t*) 159 softs->err_buf_dma_mem.virt_addr + 160 err_idx; 161 162 if(err_info == NULL) { 163 DBG_ERR("err_info structure is NULL err_idx :%x", err_idx); 164 return; 165 } 166 167 os_aio_response_error(rcb, err_info); 168 169 DBG_FUNC("OUT"); 170 } 171 172 /* 173 * Process the error info for RAID IO in the case of failure. 174 */ 175 void 176 pqisrc_process_raid_response_error(pqisrc_softstate_t *softs, 177 rcb_t *rcb, uint16_t err_idx) 178 { 179 raid_path_error_info_elem_t *err_info = NULL; 180 181 DBG_FUNC("IN"); 182 183 err_info = (raid_path_error_info_elem_t*) 184 softs->err_buf_dma_mem.virt_addr + 185 err_idx; 186 187 if(err_info == NULL) { 188 DBG_ERR("err_info structure is NULL err_idx :%x", err_idx); 189 return; 190 } 191 192 os_raid_response_error(rcb, err_info); 193 194 DBG_FUNC("OUT"); 195 } 196 197 /* 198 * Process the Task Management function response. 199 */ 200 int 201 pqisrc_process_task_management_response(pqisrc_softstate_t *softs, 202 pqi_tmf_resp_t *tmf_resp) 203 { 204 int ret = REQUEST_SUCCESS; 205 uint32_t tag = (uint32_t)tmf_resp->req_id; 206 rcb_t *rcb = &softs->rcb[tag]; 207 208 ASSERT(rcb->tag == tag); 209 210 DBG_FUNC("IN\n"); 211 212 switch (tmf_resp->resp_code) { 213 case SOP_TASK_MANAGEMENT_FUNCTION_COMPLETE: 214 case SOP_TASK_MANAGEMENT_FUNCTION_SUCCEEDED: 215 ret = REQUEST_SUCCESS; 216 break; 217 default: 218 DBG_WARN("TMF Failed, Response code : 0x%x\n", tmf_resp->resp_code); 219 ret = REQUEST_FAILED; 220 break; 221 } 222 223 rcb->status = ret; 224 rcb->req_pending = false; 225 226 DBG_FUNC("OUT"); 227 return ret; 228 } 229 230 static int 231 pqisrc_process_vendor_general_response(pqi_vendor_general_response_t *response) 232 { 233 234 int ret = REQUEST_SUCCESS; 235 236 switch(response->status) { 237 case PQI_VENDOR_RESPONSE_IU_SUCCESS: 238 break; 239 case PQI_VENDOR_RESPONSE_IU_UNSUCCESS: 240 case PQI_VENDOR_RESPONSE_IU_INVALID_PARAM: 241 case PQI_VENDOR_RESPONSE_IU_INSUFF_RESRC: 242 ret = REQUEST_FAILED; 243 break; 244 } 245 246 return ret; 247 } 248 249 /* 250 * Function used to process the response from the adapter 251 * which is invoked by IRQ handler. 252 */ 253 void 254 pqisrc_process_response_queue(pqisrc_softstate_t *softs, int oq_id) 255 { 256 ob_queue_t *ob_q; 257 struct pqi_io_response *response; 258 uint32_t oq_pi, oq_ci; 259 pqi_scsi_dev_t *dvp = NULL; 260 261 DBG_FUNC("IN"); 262 263 ob_q = &softs->op_ob_q[oq_id - 1]; /* zero for event Q */ 264 oq_ci = ob_q->ci_local; 265 oq_pi = *(ob_q->pi_virt_addr); 266 267 DBG_INFO("ci : %d pi : %d qid : %d\n", oq_ci, oq_pi, ob_q->q_id); 268 269 while (1) { 270 rcb_t *rcb = NULL; 271 uint32_t tag = 0; 272 uint32_t offset; 273 boolean_t os_scsi_cmd = false; 274 275 if (oq_pi == oq_ci) 276 break; 277 /* Get the response */ 278 offset = oq_ci * ob_q->elem_size; 279 response = (struct pqi_io_response *)(ob_q->array_virt_addr + 280 offset); 281 tag = response->request_id; 282 rcb = &softs->rcb[tag]; 283 /* Make sure we are processing a valid response. */ 284 if ((rcb->tag != tag) || (rcb->req_pending == false)) { 285 DBG_ERR("No such request pending with tag : %x", tag); 286 oq_ci = (oq_ci + 1) % ob_q->num_elem; 287 break; 288 } 289 /* Timedout request has been completed. This should not hit, 290 * if timeout is set as TIMEOUT_INFINITE while calling 291 * pqisrc_wait_on_condition(softs,rcb,timeout). 292 */ 293 if (rcb->timedout) { 294 DBG_WARN("timed out request completing from firmware, driver already completed it with failure , free the tag %d\n", tag); 295 oq_ci = (oq_ci + 1) % ob_q->num_elem; 296 os_reset_rcb(rcb); 297 pqisrc_put_tag(&softs->taglist, tag); 298 break; 299 } 300 301 if (IS_OS_SCSICMD(rcb)) { 302 dvp = rcb->dvp; 303 if (dvp) 304 os_scsi_cmd = true; 305 else 306 DBG_WARN("Received IO completion for the Null device!!!\n"); 307 } 308 309 310 DBG_INFO("response.header.iu_type : %x \n", response->header.iu_type); 311 312 switch (response->header.iu_type) { 313 case PQI_RESPONSE_IU_RAID_PATH_IO_SUCCESS: 314 case PQI_RESPONSE_IU_AIO_PATH_IO_SUCCESS: 315 rcb->success_cmp_callback(softs, rcb); 316 if (os_scsi_cmd) 317 pqisrc_decrement_device_active_io(softs, dvp); 318 319 break; 320 case PQI_RESPONSE_IU_RAID_PATH_IO_ERROR: 321 case PQI_RESPONSE_IU_AIO_PATH_IO_ERROR: 322 rcb->error_cmp_callback(softs, rcb, LE_16(response->error_index)); 323 if (os_scsi_cmd) 324 pqisrc_decrement_device_active_io(softs, dvp); 325 break; 326 case PQI_RESPONSE_IU_GENERAL_MANAGEMENT: 327 rcb->req_pending = false; 328 break; 329 case PQI_RESPONSE_IU_VENDOR_GENERAL: 330 rcb->req_pending = false; 331 rcb->status = pqisrc_process_vendor_general_response( 332 (pqi_vendor_general_response_t *)response); 333 break; 334 case PQI_RESPONSE_IU_TASK_MANAGEMENT: 335 rcb->status = pqisrc_process_task_management_response(softs, (void *)response); 336 break; 337 338 default: 339 DBG_ERR("Invalid Response IU 0x%x\n",response->header.iu_type); 340 break; 341 } 342 343 oq_ci = (oq_ci + 1) % ob_q->num_elem; 344 } 345 346 ob_q->ci_local = oq_ci; 347 PCI_MEM_PUT32(softs, ob_q->ci_register_abs, 348 ob_q->ci_register_offset, ob_q->ci_local ); 349 DBG_FUNC("OUT"); 350 } 351