]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/smartpqi/smartpqi_response.c
MFV r368464:
[FreeBSD/FreeBSD.git] / sys / dev / smartpqi / smartpqi_response.c
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 }