1 /*- 2 * Copyright (c) 2018 Microsemi Corporation. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 /* $FreeBSD$ */ 28 29 #include "smartpqi_includes.h" 30 31 /* 32 * Process internal RAID response in the case of success. 33 */ 34 void pqisrc_process_internal_raid_response_success(pqisrc_softstate_t *softs, 35 rcb_t *rcb) 36 { 37 DBG_FUNC("IN"); 38 39 rcb->status = REQUEST_SUCCESS; 40 rcb->req_pending = false; 41 42 DBG_FUNC("OUT"); 43 } 44 45 /* 46 * Process internal RAID response in the case of failure. 47 */ 48 void pqisrc_process_internal_raid_response_error(pqisrc_softstate_t *softs, 49 rcb_t *rcb, uint16_t err_idx) 50 { 51 raid_path_error_info_elem_t error_info; 52 53 DBG_FUNC("IN"); 54 55 rcb->error_info = (char *) (softs->err_buf_dma_mem.virt_addr) + 56 (err_idx * PQI_ERROR_BUFFER_ELEMENT_LENGTH); 57 rcb->status = REQUEST_SUCCESS; 58 memcpy(&error_info, rcb->error_info, sizeof(error_info)); 59 60 DBG_INFO("error_status 0x%x data_in_result 0x%x data_out_result 0x%x\n", 61 error_info.status, error_info.data_in_result, error_info.data_out_result); 62 63 if (error_info.status != 0) 64 rcb->status = REQUEST_FAILED; 65 if (error_info.data_in_result != PQI_RAID_DATA_IN_OUT_GOOD) 66 rcb->status = REQUEST_FAILED; 67 if (error_info.data_out_result != PQI_RAID_DATA_IN_OUT_GOOD) 68 rcb->status = REQUEST_FAILED; 69 70 rcb->req_pending = false; 71 72 DBG_FUNC("OUT"); 73 } 74 75 /* 76 * Process the AIO/RAID IO in the case of success. 77 */ 78 void pqisrc_process_io_response_success(pqisrc_softstate_t *softs, 79 rcb_t *rcb) 80 { 81 DBG_FUNC("IN"); 82 83 os_io_response_success(rcb); 84 85 DBG_FUNC("OUT"); 86 } 87 88 /* 89 * Process the error info for AIO in the case of failure. 90 */ 91 void pqisrc_process_aio_response_error(pqisrc_softstate_t *softs, 92 rcb_t *rcb, uint16_t err_idx) 93 { 94 aio_path_error_info_elem_t *err_info = NULL; 95 96 DBG_FUNC("IN"); 97 98 err_info = (aio_path_error_info_elem_t*) 99 softs->err_buf_dma_mem.virt_addr + 100 err_idx; 101 102 if(err_info == NULL) { 103 DBG_ERR("err_info structure is NULL err_idx :%x", err_idx); 104 return; 105 } 106 107 os_aio_response_error(rcb, err_info); 108 109 DBG_FUNC("OUT"); 110 } 111 112 /* 113 * Process the error info for RAID IO in the case of failure. 114 */ 115 void pqisrc_process_raid_response_error(pqisrc_softstate_t *softs, 116 rcb_t *rcb, uint16_t err_idx) 117 { 118 raid_path_error_info_elem_t *err_info = NULL; 119 120 DBG_FUNC("IN"); 121 122 err_info = (raid_path_error_info_elem_t*) 123 softs->err_buf_dma_mem.virt_addr + 124 err_idx; 125 126 if(err_info == NULL) { 127 DBG_ERR("err_info structure is NULL err_idx :%x", err_idx); 128 return; 129 } 130 131 os_raid_response_error(rcb, err_info); 132 133 DBG_FUNC("OUT"); 134 } 135 136 /* 137 * Process the Task Management function response. 138 */ 139 int pqisrc_process_task_management_response(pqisrc_softstate_t *softs, 140 pqi_tmf_resp_t *tmf_resp) 141 { 142 int ret = REQUEST_SUCCESS; 143 uint32_t tag = (uint32_t)tmf_resp->req_id; 144 rcb_t *rcb = &softs->rcb[tag]; 145 146 ASSERT(rcb->tag == tag); 147 148 DBG_FUNC("IN\n"); 149 150 switch (tmf_resp->resp_code) { 151 case SOP_TASK_MANAGEMENT_FUNCTION_COMPLETE: 152 case SOP_TASK_MANAGEMENT_FUNCTION_SUCCEEDED: 153 ret = REQUEST_SUCCESS; 154 break; 155 default: 156 DBG_ERR("TMF Failed, Response code : 0x%x\n", tmf_resp->resp_code); 157 ret = REQUEST_FAILED; 158 break; 159 } 160 161 rcb->status = ret; 162 rcb->req_pending = false; 163 164 DBG_FUNC("OUT"); 165 return ret; 166 } 167 168 /* 169 * Function used to process the response from the adapter 170 * which is invoked by IRQ handler. 171 */ 172 void 173 pqisrc_process_response_queue(pqisrc_softstate_t *softs, int oq_id) 174 { 175 ob_queue_t *ob_q; 176 struct pqi_io_response *response; 177 uint32_t oq_pi, oq_ci; 178 179 DBG_FUNC("IN"); 180 181 OS_ATOMIC64_INC(softs, num_intrs); 182 183 ob_q = &softs->op_ob_q[oq_id - 1]; /* zero for event Q */ 184 oq_ci = ob_q->ci_local; 185 oq_pi = *(ob_q->pi_virt_addr); 186 187 DBG_INFO("ci : %d pi : %d qid : %d\n", oq_ci, oq_pi, ob_q->q_id); 188 189 while (1) { 190 rcb_t *rcb = NULL; 191 uint32_t tag = 0; 192 uint32_t offset; 193 194 if (oq_pi == oq_ci) 195 break; 196 /* Get the response */ 197 offset = oq_ci * ob_q->elem_size; 198 response = (struct pqi_io_response *)(ob_q->array_virt_addr + 199 offset); 200 tag = response->request_id; 201 rcb = &softs->rcb[tag]; 202 /* Make sure we are processing a valid response. */ 203 ASSERT(rcb->tag == tag && rcb->req_pending); 204 rcb->req_pending = false; 205 206 DBG_INFO("response.header.iu_type : %x \n", response->header.iu_type); 207 208 switch (response->header.iu_type) { 209 case PQI_RESPONSE_IU_RAID_PATH_IO_SUCCESS: 210 case PQI_RESPONSE_IU_AIO_PATH_IO_SUCCESS: 211 rcb->success_cmp_callback(softs, rcb); 212 break; 213 case PQI_RESPONSE_IU_RAID_PATH_IO_ERROR: 214 case PQI_RESPONSE_IU_AIO_PATH_IO_ERROR: 215 rcb->error_cmp_callback(softs, rcb, LE_16(response->error_index)); 216 break; 217 case PQI_RESPONSE_IU_GENERAL_MANAGEMENT: 218 rcb->req_pending = false; 219 break; 220 case PQI_RESPONSE_IU_TASK_MANAGEMENT: 221 rcb->status = pqisrc_process_task_management_response(softs, (void *)response); 222 break; 223 224 default: 225 DBG_ERR("Invalid Response IU 0x%x\n",response->header.iu_type); 226 break; 227 } 228 229 oq_ci = (oq_ci + 1) % ob_q->num_elem; 230 } 231 232 ob_q->ci_local = oq_ci; 233 PCI_MEM_PUT32(softs, ob_q->ci_register_abs, 234 ob_q->ci_register_offset, ob_q->ci_local ); 235 DBG_FUNC("OUT"); 236 } 237