[SRP] add SCSI errors to the logs
[mirror/winof/.git] / ulp / srp / kernel / srp_data_path.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 \r
33 #include <complib/cl_math.h>\r
34 #include <complib/cl_obj.h>\r
35 \r
36 #include "srp_cmd.h"\r
37 #include "srp_data_path.h"\r
38 #include "srp_debug.h"\r
39 #if defined(EVENT_TRACING)\r
40 #ifdef offsetof\r
41 #undef offsetof\r
42 #endif\r
43 #include "srp_data_path.tmh"\r
44 #endif\r
45 #include "srp_descriptors.h"\r
46 #include "srp_rsp.h"\r
47 #include "srp_session.h"\r
48 #include "srp_tsk_mgmt.h"\r
49 \r
50 //#include "srp_aer_req.h"\r
51 //#include "srp_aer_rsp.h"\r
52 \r
53 //#include "srp_cred_req.h"\r
54 //#include "srp_cred_rsp.h"\r
55 \r
56 //#include "srp_i_logout.h"\r
57 //#include "srp_t_logout.h"\r
58 \r
59 // Final address is of the form 0b00ttttttllllllll\r
60 #define BUILD_SCSI_ADDRESS(lun) ((uint64_t)lun << 48)\r
61 \r
62 \r
63 static inline\r
64 void\r
65 __srp_dump_srb_info(srp_send_descriptor_t*              p_send_descriptor)\r
66 {\r
67         \r
68         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
69                 ("Srb Address              = %p\n",\r
70                 p_send_descriptor->p_srb) );\r
71         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
72                 ("Srb DataBuffer Address   = %p\n",\r
73                 p_send_descriptor->p_srb->DataBuffer) );\r
74         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
75                 ("Srb DataTransferLength   = %d\n",\r
76                  p_send_descriptor->p_srb->DataTransferLength) );\r
77 \r
78         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
79                            ("Returning SrbStatus %s(0x%x) for "\r
80                            "Function = %s(0x%x), Path = 0x%x, Target = 0x%x, "\r
81                            "Lun = 0x%x, tag 0x%I64xn",\r
82                            g_srb_status_name[p_send_descriptor->p_srb->SrbStatus],\r
83                            p_send_descriptor->p_srb->SrbStatus,\r
84                            g_srb_function_name[p_send_descriptor->p_srb->Function],\r
85                            p_send_descriptor->p_srb->Function,\r
86                            p_send_descriptor->p_srb->PathId,\r
87                            p_send_descriptor->p_srb->TargetId,\r
88                            p_send_descriptor->p_srb->Lun,\r
89                            get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );\r
90 }\r
91 \r
92 \r
93 static inline\r
94 void\r
95 __srp_process_session_send_completions(\r
96         IN  srp_session_t   *p_session )\r
97 {\r
98         ib_api_status_t status;\r
99         ib_wc_t         *p_wc_done_list = NULL;\r
100         ib_wc_t         *p_wc;\r
101 \r
102         SRP_ENTER( SRP_DBG_DATA );\r
103 \r
104         cl_obj_lock( &p_session->obj );\r
105 \r
106         if ( p_session->connection.state != SRP_CONNECTED )\r
107         {\r
108                 cl_obj_unlock( &p_session->obj );\r
109                 SRP_EXIT( SRP_DBG_DATA );\r
110                 return;\r
111         }\r
112 \r
113         status = p_session->p_hba->ifc.poll_cq(\r
114                 p_session->connection.h_send_cq,\r
115                 &p_session->connection.p_wc_free_list,\r
116                 &p_wc_done_list );\r
117         if ( status != IB_SUCCESS )\r
118         {\r
119                 SRP_PRINT_EXIT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
120                         ("ib_poll_cq() failed!, status 0x%x\n", status) );\r
121 \r
122                 // TODO: Kill session and inform port driver link down scsiportnotification\r
123                 cl_obj_unlock( &p_session->obj );\r
124                 return;\r
125         }\r
126 \r
127         cl_obj_ref( &p_session->obj );\r
128         cl_obj_unlock( &p_session->obj );\r
129 \r
130         while ( (p_wc = p_wc_done_list) != NULL )\r
131         {\r
132                 srp_send_descriptor_t   *p_send_descriptor;\r
133 \r
134                 p_send_descriptor = (srp_send_descriptor_t *)((uintn_t)p_wc->wr_id);\r
135 \r
136                 /* Remove head from list */\r
137                 p_wc_done_list = p_wc->p_next;\r
138                 p_wc->p_next = NULL;\r
139 \r
140                 switch ( p_wc->status)\r
141                 {\r
142                         case IB_WCS_SUCCESS:\r
143                                 break;\r
144                         case IB_WCS_WR_FLUSHED_ERR:\r
145                                 // TODO: Kill session and inform port driver link down scsiportnotification\r
146                                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DATA,\r
147                                         ("Send Completion Status %s Vendore Status = 0x%x, \n",\r
148                                         p_session->p_hba->ifc.get_wc_status_str( p_wc->status ),\r
149                                         (int)p_wc->vendor_specific));\r
150 \r
151                                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DATA,\r
152                                                    ("Send Completion Received for Function = %s(0x%x), "\r
153                                                    "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
154                                                    g_srb_function_name[p_send_descriptor->p_srb->Function],\r
155                                                    p_send_descriptor->p_srb->Function,\r
156                                                    p_send_descriptor->p_srb->PathId,\r
157                                                    p_send_descriptor->p_srb->TargetId,\r
158                                                    p_send_descriptor->p_srb->Lun,\r
159                                                    get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );\r
160                                 break;\r
161                         default:\r
162                                 // TODO: Kill session and inform port driver link down scsiportnotification\r
163                                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
164                                         ("Send Completion Status %s Vendore Status = 0x%x, \n",\r
165                                         p_session->p_hba->ifc.get_wc_status_str( p_wc->status ),\r
166                                         (int)p_wc->vendor_specific));\r
167 \r
168                                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
169                                                    ("Send Completion Received for Function = %s(0x%x), "\r
170                                                    "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
171                                                    g_srb_function_name[p_send_descriptor->p_srb->Function],\r
172                                                    p_send_descriptor->p_srb->Function,\r
173                                                    p_send_descriptor->p_srb->PathId,\r
174                                                    p_send_descriptor->p_srb->TargetId,\r
175                                                    p_send_descriptor->p_srb->Lun,\r
176                                                    get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );\r
177                                 break;\r
178                 }\r
179 \r
180                 /* Put onto head of free list */\r
181                 cl_obj_lock( &p_session->obj );\r
182                 p_wc->p_next = p_session->connection.p_wc_free_list;\r
183                 p_session->connection.p_wc_free_list = p_wc;\r
184                 cl_obj_unlock( &p_session->obj );\r
185 \r
186                 /* Get next completion */\r
187                 p_wc = p_wc_done_list;\r
188         }\r
189 \r
190         /* Re-arm the CQ for more completions */\r
191         status = p_session->p_hba->ifc.rearm_cq(\r
192                 p_session->connection.h_send_cq, FALSE );\r
193         if ( status != IB_SUCCESS)\r
194         {\r
195                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
196                         ("ib_rearm_cq() failed!, status 0x%x\n", status) );\r
197 \r
198                 // TODO: Kill session and inform port driver link down scsiportnotification\r
199         }\r
200 \r
201         cl_obj_deref( &p_session->obj );\r
202 \r
203         SRP_EXIT( SRP_DBG_DATA );\r
204 }\r
205 \r
206 /* srp_send_completion_cb */\r
207 /*!\r
208 Set Timer to Process Send Completions - Usually bad if we get here\r
209 \r
210 @param p_context - context pointer to the owning session\r
211 \r
212 @return - none\r
213 */\r
214 void\r
215 srp_send_completion_cb(\r
216         IN      const   ib_cq_handle_t          h_cq,\r
217         IN                      void                            *p_context )\r
218 {\r
219         srp_session_t   *p_session = (srp_session_t *)p_context;\r
220 \r
221         SRP_ENTER( SRP_DBG_DATA );\r
222 \r
223         UNUSED_PARAM( h_cq );\r
224 \r
225         __srp_process_session_send_completions( p_session );\r
226 \r
227         SRP_EXIT( SRP_DBG_DATA );\r
228 }\r
229 \r
230 static inline\r
231 ib_api_status_t\r
232 __srp_process_recv_completion(\r
233         IN  srp_recv_descriptor_t   *p_recv_descriptor,\r
234         IN  srp_session_t           *p_session )\r
235 {\r
236         ib_api_status_t         status = IB_SUCCESS;\r
237         srp_rsp_t               *p_srp_rsp;\r
238         uint8_t                 response_status;\r
239         srp_send_descriptor_t   *p_send_descriptor;\r
240 \r
241         SRP_ENTER( SRP_DBG_DATA );\r
242 \r
243         p_srp_rsp = (srp_rsp_t *)p_recv_descriptor->p_data_segment;\r
244 \r
245         set_srp_response_from_network_to_host( p_srp_rsp );\r
246 \r
247         response_status = get_srp_response_status( p_srp_rsp );\r
248 \r
249         p_send_descriptor = srp_find_matching_send_descriptor(\r
250                 &p_session->descriptors,\r
251                 get_srp_response_tag( (srp_rsp_t *)p_recv_descriptor->p_data_segment ) );\r
252         if ( p_send_descriptor == NULL )\r
253         {\r
254                 /* Repost the recv descriptor */\r
255                 status = p_session->p_hba->ifc.post_recv(\r
256                         p_session->connection.h_qp, &p_recv_descriptor->wr, NULL );\r
257                 if ( status != IB_SUCCESS )\r
258                 {\r
259                         SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
260                                 ("Failed to post send descriptor. Status = %d.\n", status) );\r
261                         // TODO: Kill session and inform port driver link down scsiportnotification\r
262                 }\r
263 \r
264                 cl_atomic_add( &p_session->connection.request_limit, get_srp_response_request_limit_delta( p_srp_rsp ) );\r
265 \r
266                 SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
267                         ("Matching Send Descriptor Not Found.\n") );\r
268 \r
269                 goto exit;\r
270         }\r
271 \r
272         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
273                            ("Recv Completion Received for Function = %s(0x%x), "\r
274                            "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
275                            g_srb_function_name[p_send_descriptor->p_srb->Function],\r
276                            p_send_descriptor->p_srb->Function,\r
277                            p_send_descriptor->p_srb->PathId,\r
278                            p_send_descriptor->p_srb->TargetId,\r
279                            p_send_descriptor->p_srb->Lun,\r
280                            get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );\r
281 \r
282         switch ( get_srp_iu_buffer_type( (srp_iu_buffer_t *)p_send_descriptor->data_segment ) )\r
283         {\r
284                 case SRP_TSK_MGMT:\r
285                 {\r
286                         srp_tsk_mgmt_t  *p_srp_tsk_mgmt = (srp_tsk_mgmt_t *)p_send_descriptor->data_segment;\r
287 \r
288                         set_srp_tsk_mgmt_from_network_to_host( p_srp_tsk_mgmt );\r
289 \r
290 \r
291                         if(response_status == SCSISTAT_GOOD)\r
292                         {\r
293                                 p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_SUCCESS;\r
294                         }\r
295                         else\r
296                         {\r
297                                 p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_ABORT_FAILED;\r
298                                 SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
299                                            ("Scsi Error  %s (%#x)  Received for Function = %s(0x%x), "\r
300                                            "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
301                                            g_srb_scsi_status_name[response_status],\r
302                                            response_status,\r
303                                            g_srb_function_name[p_send_descriptor->p_srb->Function],\r
304                                            p_send_descriptor->p_srb->Function,\r
305                                            p_send_descriptor->p_srb->PathId,\r
306                                            p_send_descriptor->p_srb->TargetId,\r
307                                            p_send_descriptor->p_srb->Lun,\r
308                                            get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );\r
309                         }\r
310 \r
311                         if ( get_srp_tsk_mgmt_task_management_flags( p_srp_tsk_mgmt ) == TMF_ABORT_TASK )\r
312                         {\r
313                                 /* Repost the recv descriptor */\r
314                                 status = p_session->p_hba->ifc.post_recv(\r
315                                         p_session->connection.h_qp, &p_recv_descriptor->wr, NULL );\r
316                                 if ( status != IB_SUCCESS )\r
317                                 {\r
318                                         SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
319                                                 ("Failed to post recv descriptor. Status = %d.\n", status) );\r
320                                         // TODO: Kill session and inform port driver link down storportnotification\r
321                                 }\r
322 \r
323                                 cl_atomic_add( &p_session->connection.request_limit, get_srp_response_request_limit_delta( p_srp_rsp ) );\r
324                                 __srp_dump_srb_info( p_send_descriptor);\r
325 \r
326                                 StorPortNotification( RequestComplete, p_session->p_hba->p_ext, p_send_descriptor->p_srb );\r
327                         }\r
328                         break;\r
329                 }\r
330 \r
331                 case SRP_CMD:\r
332                         p_send_descriptor->p_srb->ScsiStatus = response_status;\r
333                         if(response_status == SCSISTAT_GOOD)\r
334                         {\r
335                                 p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_SUCCESS;\r
336                         }\r
337                         else\r
338                         {\r
339                                 p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_ABORT_FAILED;\r
340                                 SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
341                                            ("Scsi Error  %s (%#x)  Received for Function = %s(0x%x), "\r
342                                            "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
343                                            g_srb_scsi_status_name[response_status],\r
344                                            response_status,\r
345                                            g_srb_function_name[p_send_descriptor->p_srb->Function],\r
346                                            p_send_descriptor->p_srb->Function,\r
347                                            p_send_descriptor->p_srb->PathId,\r
348                                            p_send_descriptor->p_srb->TargetId,\r
349                                            p_send_descriptor->p_srb->Lun,\r
350                                            get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );\r
351                         }\r
352 \r
353                         if ( get_srp_response_flags( p_srp_rsp ) != 0 )\r
354                         {\r
355                                 uint32_t    resid;\r
356 \r
357                                 if ( (response_status != SCSISTAT_CHECK_CONDITION) && get_srp_response_di_under( p_srp_rsp ) )\r
358                                 {\r
359                                         resid = get_srp_response_data_in_residual_count( p_srp_rsp );\r
360 \r
361                                         SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
362                                                 ("DI Underflow in response: expected %d got %d.\n",\r
363                                                 p_send_descriptor->p_srb->DataTransferLength,\r
364                                                 p_send_descriptor->p_srb->DataTransferLength - resid) );\r
365 \r
366                                         p_send_descriptor->p_srb->DataTransferLength -= resid;\r
367 \r
368                                         if ( p_send_descriptor->p_srb->SrbStatus == SRB_STATUS_SUCCESS )\r
369                                         {\r
370                                                 p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; /* Also for underrun see DDK */\r
371                                         }\r
372                                 }\r
373 \r
374                                 if ( (response_status != SCSISTAT_CHECK_CONDITION) && get_srp_response_do_under( p_srp_rsp ) )\r
375                                 {\r
376                                         resid = get_srp_response_data_out_residual_count( p_srp_rsp );\r
377 \r
378                                         SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
379                                                 ("DI Underflow in response: expected %d got %d.\n",\r
380                                                 p_send_descriptor->p_srb->DataTransferLength,\r
381                                                 p_send_descriptor->p_srb->DataTransferLength - resid) );\r
382 \r
383                                         p_send_descriptor->p_srb->DataTransferLength -= resid;\r
384 \r
385                                         if ( p_send_descriptor->p_srb->SrbStatus == SRB_STATUS_SUCCESS )\r
386                                         {\r
387                                                 p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; /* Also for underrun see DDK */\r
388                                         }\r
389                                 }\r
390 \r
391                                 if ( get_srp_response_sns_valid( p_srp_rsp ) )\r
392                                 {\r
393                                         uint8_t *p_sense_data = get_srp_response_sense_data( p_srp_rsp );\r
394 \r
395                                         /* Copy only as much of the sense data as we can hold. */\r
396                                         cl_memcpy( p_send_descriptor->p_srb->SenseInfoBuffer,\r
397                                                            p_sense_data,\r
398                                                            MIN( get_srp_response_sense_data_list_length( p_srp_rsp ),\r
399                                                                         p_send_descriptor->p_srb->SenseInfoBufferLength ) );\r
400                                         SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
401                                                         ("Sense Data  SENSE_KEY 0x%02x ADDITIONAL_SENSE_CODE"\r
402                                                         "0x%02x ADDITIONAL_SENSE_QUILIFIER 0x%02x.\n",\r
403                                                         p_sense_data[2],p_sense_data[12],p_sense_data[13]) );\r
404                                         \r
405                                         if ( ((p_sense_data[2]&0xf) == 0x0b /*ABORTED_COMMAND*/) &&\r
406                                                 (p_sense_data[12] == 0x08) &&\r
407                                                 (p_sense_data[13] == 0x00) )\r
408 \r
409                                         {\r
410                                                 /* probably a problem with the Vfx FC san like wire pull*/\r
411                                                 /* initiate session recovery */\r
412                                                 SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
413                                                         ("Sense Data indicates FC link connectivity has been lost.\n") );\r
414                                                 StorPortPauseDevice( p_session->p_hba->p_ext,\r
415                                                                                          p_send_descriptor->p_srb->PathId,\r
416                                                                                          p_send_descriptor->p_srb->TargetId,\r
417                                                                                          p_send_descriptor->p_srb->Lun,\r
418                                                                                          5 );\r
419                                         }\r
420                                         \r
421                                 }\r
422 \r
423                                 if ( get_srp_response_di_over( p_srp_rsp ) || get_srp_response_do_over( p_srp_rsp ) )\r
424                                 {\r
425                                         SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
426                                                 ("Overflow error in response.\n") );\r
427                                         if ( p_send_descriptor->p_srb->SrbStatus == SRB_STATUS_SUCCESS )\r
428                                         {\r
429                                                 p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;\r
430                                         }\r
431                                 }\r
432                         }\r
433 \r
434                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
435                                 ("DataBuffer = 0x%I64x.\n", MmGetPhysicalAddress(\r
436                                 p_send_descriptor->p_srb->DataBuffer ).QuadPart) );\r
437 \r
438                         /* Repost the recv descriptor */\r
439                         status = p_session->p_hba->ifc.post_recv(\r
440                                 p_session->connection.h_qp, &p_recv_descriptor->wr, NULL );\r
441                         if ( status != IB_SUCCESS )\r
442                         {\r
443                                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
444                                         ("Failed to post recv descriptor. Status = %d.\n", status) );\r
445                                 // TODO: Kill session and inform port driver link down storportnotification\r
446                         }\r
447 \r
448                         cl_atomic_add( &p_session->connection.request_limit, get_srp_response_request_limit_delta( p_srp_rsp ) );\r
449                         __srp_dump_srb_info( p_send_descriptor);\r
450 \r
451                         StorPortNotification( RequestComplete, p_session->p_hba->p_ext, p_send_descriptor->p_srb );\r
452                         break;\r
453 \r
454                 case SRP_LOGIN_REQ:\r
455                 case SRP_I_LOGOUT:\r
456                 case SRP_CRED_RSP:\r
457                 case SRP_AER_RSP:\r
458                 default:\r
459                         CL_ASSERT ( 0 );\r
460                         break;\r
461         }\r
462 \r
463 exit:\r
464         SRP_EXIT( SRP_DBG_DATA );\r
465 \r
466         return ( status );\r
467 }\r
468 \r
469 static inline\r
470 void\r
471 __srp_process_session_recv_completions(\r
472         IN  srp_session_t   *p_session )\r
473 {\r
474         ib_api_status_t status;\r
475         ib_wc_t         *p_wc_done_list;\r
476         ib_wc_t         *p_wc;\r
477 \r
478         SRP_ENTER( SRP_DBG_DATA );\r
479 \r
480         cl_obj_lock( &p_session->obj );\r
481 \r
482         if ( p_session->connection.state != SRP_CONNECTED )\r
483         {\r
484                 cl_obj_unlock( &p_session->obj );\r
485                 SRP_EXIT( SRP_DBG_DATA );\r
486                 return;\r
487         }\r
488 \r
489         status = p_session->p_hba->ifc.poll_cq(\r
490                 p_session->connection.h_recv_cq,\r
491                 &p_session->connection.p_wc_free_list,\r
492                 &p_wc_done_list );\r
493         if ( status != IB_SUCCESS )\r
494         {\r
495                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
496                         ("ib_poll_cq() failed!, status 0x%x\n", status) );\r
497 \r
498                 // TODO: Kill session and inform port driver link down scsiportnotification\r
499                 SRP_EXIT( SRP_DBG_DATA );\r
500                 cl_obj_unlock( &p_session->obj );\r
501                 return;\r
502         }\r
503 \r
504         cl_obj_ref( &p_session->obj );\r
505         cl_obj_unlock( &p_session->obj );\r
506 \r
507         while ( (p_wc = p_wc_done_list) != NULL )\r
508         {\r
509                 srp_recv_descriptor_t   *p_recv_descriptor;\r
510 \r
511                 /* Remove head from list */\r
512                 p_wc_done_list = p_wc->p_next;\r
513                 p_wc->p_next = NULL;\r
514 \r
515                 p_recv_descriptor = (srp_recv_descriptor_t *)((uintn_t)p_wc->wr_id);\r
516 \r
517                 if ( p_wc->status == IB_WCS_SUCCESS )\r
518                 {\r
519                         status = __srp_process_recv_completion( p_recv_descriptor, p_session );\r
520                         if ( status != IB_SUCCESS )\r
521                         {\r
522                                 // TODO: Kill session and inform port driver link down scsiportnotification\r
523                         }\r
524                 }\r
525                 else\r
526                 {\r
527                         if( p_wc->status != IB_WCS_WR_FLUSHED_ERR )\r
528                         {\r
529                                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
530                                         ("Recv Completion with Error Status %s (vendore specific %#x)\n",\r
531                                         p_session->p_hba->ifc.get_wc_status_str( p_wc->status ),\r
532                                         (int)p_wc->vendor_specific) );\r
533                         }\r
534                         else\r
535                         {\r
536                                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DATA,\r
537                                         ("Recv Completion Flushed in Error Status: %s\n",\r
538                                         p_session->p_hba->ifc.get_wc_status_str( p_wc->status )));\r
539 \r
540                         }\r
541                 }\r
542 \r
543                 /* Put onto head of free list */\r
544                 cl_obj_lock( &p_session->obj );\r
545                 p_wc->p_next = p_session->connection.p_wc_free_list;\r
546                 p_session->connection.p_wc_free_list = p_wc;\r
547                 cl_obj_unlock( &p_session->obj );\r
548 \r
549                 /* Get next completion */\r
550                 p_wc = p_wc_done_list;\r
551         }\r
552 \r
553         /* Re-arm the CQ for more completions */\r
554         status = p_session->p_hba->ifc.rearm_cq(\r
555                 p_session->connection.h_recv_cq, FALSE );\r
556         if ( status != IB_SUCCESS)\r
557         {\r
558                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
559                         ("ib_rearm_cq() failed!, status 0x%x\n", status) );\r
560 \r
561                 // TODO: Kill session and inform port driver link down scsiportnotification\r
562         }\r
563 \r
564         cl_obj_deref( &p_session->obj );\r
565 \r
566         SRP_EXIT( SRP_DBG_DATA );\r
567 }\r
568 \r
569 /* srp_recv_completion_cb */\r
570 /*!\r
571 Set Timer to Process Receive Completions - Responses to our requests\r
572 \r
573 @param p_context - context pointer to the owning session\r
574 \r
575 @return - none\r
576 */\r
577 void\r
578 srp_recv_completion_cb(\r
579         IN      const   ib_cq_handle_t          h_cq,\r
580         IN                      void                            *p_context )\r
581 {\r
582         srp_session_t   *p_session = (srp_session_t *)p_context;\r
583 \r
584         SRP_ENTER( SRP_DBG_DATA );\r
585 \r
586         UNUSED_PARAM( h_cq );\r
587 \r
588         __srp_process_session_recv_completions( p_session );\r
589 \r
590         SRP_EXIT( SRP_DBG_DATA );\r
591 }\r
592 \r
593 /* __srp_build_cmd */\r
594 /*!\r
595 Build the SRP Cmd to be sent to the VFx target\r
596 \r
597 @param p_dev_ext - our context pointer\r
598 @param p_srb     - scsi request to send to target\r
599 \r
600 @return - none\r
601 */\r
602 static inline\r
603 void\r
604 __srp_build_cmd(\r
605         IN      PVOID               p_dev_ext,\r
606         IN OUT  PSCSI_REQUEST_BLOCK p_srb,\r
607         IN      srp_conn_info_t     *p_srp_conn_info )\r
608 {\r
609         srp_send_descriptor_t           *p_send_descriptor = (srp_send_descriptor_t *)p_srb->SrbExtension;\r
610         srp_cmd_t                       *p_srp_cmd = (srp_cmd_t *)p_send_descriptor->data_segment;\r
611         UCHAR                           *p_cdb;\r
612         PSTOR_SCATTER_GATHER_LIST       p_scatter_gather_list = NULL;\r
613         uint8_t                         scatter_gather_count = 0;\r
614         srp_memory_descriptor_t         *p_memory_descriptor = NULL;\r
615         srp_memory_table_descriptor_t   *p_table_descriptor = NULL;\r
616         uint32_t                        i;\r
617         ULONG                           scsi_direction = p_srb->SrbFlags & ( SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT );\r
618         DATA_BUFFER_DESCRIPTOR_FORMAT   format = p_srp_conn_info->descriptor_format & DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS;\r
619         ULONG                                                   length;\r
620         SRP_ENTER( SRP_DBG_DATA );\r
621 \r
622         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
623                            ("Sending I/O to Path = 0x%x, Target = 0x%x, Lun = 0x%x\n",\r
624                            p_srb->PathId,\r
625                            p_srb->TargetId,\r
626                            p_srb->Lun) );\r
627 \r
628         setup_srp_command( p_srp_cmd,\r
629                                            p_send_descriptor->tag,\r
630                                            DBDF_NO_DATA_BUFFER_DESCRIPTOR_PRESENT,\r
631                                            DBDF_NO_DATA_BUFFER_DESCRIPTOR_PRESENT,\r
632                                            0,\r
633                                            0,\r
634                                            BUILD_SCSI_ADDRESS( p_srb->Lun ),\r
635                                            TAV_SIMPLE_TASK,\r
636                                            0 );\r
637 \r
638         p_cdb = get_srp_command_cdb( p_srp_cmd );\r
639         cl_memcpy( p_cdb, p_srb->Cdb, p_srb->CdbLength );\r
640 \r
641         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
642                 ("CDB Length = %d.\n", p_srb->CdbLength) );\r
643 #ifdef DBG\r
644         {\r
645                 char*   cmd;\r
646                 cmd = cl_zalloc(p_srb->CdbLength +1);\r
647                 for ( i = 0; i < p_srb->CdbLength; i++ )\r
648                 {\r
649                         cmd[i] = p_srb->Cdb[i];\r
650                 }\r
651                 cmd[i] = '\0';\r
652                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA, ("CDB = 0x%s\n",cmd) );\r
653         }\r
654 #endif\r
655         \r
656         if ( !format )\r
657         {\r
658                 format = DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR;\r
659         }\r
660 \r
661         if ( scsi_direction )\r
662         {\r
663                 p_scatter_gather_list = StorPortGetScatterGatherList( p_dev_ext, p_srb );\r
664                 CL_ASSERT( p_scatter_gather_list != NULL );\r
665                 scatter_gather_count = (uint8_t)p_scatter_gather_list->NumberOfElements;\r
666         }\r
667 \r
668         /* Cap the length of the inline descriptors to the maximum IU size. */\r
669         if( p_srp_conn_info->max_scatter_gather_entries < scatter_gather_count )\r
670         {\r
671                 scatter_gather_count =\r
672                         (uint8_t)p_srp_conn_info->max_scatter_gather_entries;\r
673         }\r
674 \r
675         if ( scsi_direction == SRB_FLAGS_DATA_IN )\r
676         {\r
677                 set_srp_command_data_in_buffer_desc_fmt( p_srp_cmd, format );\r
678                 set_srp_command_data_in_buffer_desc_count( p_srp_cmd, scatter_gather_count );\r
679                 p_memory_descriptor = get_srp_command_data_in_buffer_desc( p_srp_cmd );\r
680         }\r
681 \r
682         else if ( scsi_direction == SRB_FLAGS_DATA_OUT )\r
683         {\r
684                 set_srp_command_data_out_buffer_desc_fmt( p_srp_cmd, format );\r
685                 set_srp_command_data_out_buffer_desc_count( p_srp_cmd, scatter_gather_count );\r
686                 p_memory_descriptor = get_srp_command_data_out_buffer_desc( p_srp_cmd );\r
687         }\r
688 \r
689         if ( p_memory_descriptor != NULL )\r
690         {\r
691                 PSTOR_SCATTER_GATHER_ELEMENT    p_sg_element;\r
692                 uint32_t                                                totalLength;\r
693                 uint64_t                                                buf_addr;\r
694                 if ( format == DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS )\r
695                 {\r
696                         p_table_descriptor = (srp_memory_table_descriptor_t *)p_memory_descriptor;\r
697                         p_memory_descriptor = ( srp_memory_descriptor_t *)(p_table_descriptor + 1 );\r
698 \r
699                         buf_addr = (StorPortGetPhysicalAddress( p_dev_ext,p_srb, p_memory_descriptor, &length)).QuadPart;\r
700 \r
701                         /* we don't swap rkey - it is already in network order*/\r
702                         p_table_descriptor->descriptor.virtual_address =  cl_hton64( buf_addr );\r
703                         p_table_descriptor->descriptor.memory_handle = p_srp_conn_info->rkey;\r
704 \r
705                         p_table_descriptor->descriptor.data_length =\r
706                                 cl_hton32( sizeof(srp_memory_descriptor_t) *\r
707                                 p_scatter_gather_list->NumberOfElements );\r
708                         \r
709                         for ( i = 0, totalLength = 0, p_sg_element = p_scatter_gather_list->List;\r
710                                   i < p_scatter_gather_list->NumberOfElements;\r
711                                   i++, p_memory_descriptor++, p_sg_element++ )\r
712                         {\r
713                                 buf_addr =  p_srp_conn_info->vaddr + p_sg_element->PhysicalAddress.QuadPart;\r
714                         \r
715                                 p_memory_descriptor->virtual_address = cl_hton64( buf_addr );\r
716                                 p_memory_descriptor->memory_handle   = p_srp_conn_info->rkey;\r
717                                 p_memory_descriptor->data_length     =  cl_hton32( p_sg_element->Length );\r
718                                 totalLength += p_sg_element->Length;\r
719                         }\r
720                         p_table_descriptor->total_length = cl_hton32( totalLength );\r
721                 }\r
722                 else if ( format == DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR )\r
723                 {\r
724                         CL_ASSERT( scatter_gather_count ==\r
725                                 p_scatter_gather_list->NumberOfElements );\r
726                         for ( i = 0, p_sg_element = p_scatter_gather_list->List;\r
727                                   i < scatter_gather_count;     i++, p_memory_descriptor++, p_sg_element++ )\r
728                         {\r
729                                 buf_addr =  p_srp_conn_info->vaddr + p_sg_element->PhysicalAddress.QuadPart;\r
730                                 p_memory_descriptor->virtual_address = cl_hton64( buf_addr );\r
731                                 p_memory_descriptor->memory_handle   = p_srp_conn_info->rkey;\r
732                                 p_memory_descriptor->data_length     = cl_hton32( p_sg_element->Length );\r
733 \r
734                                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
735                                         ("virtual_address[%d] = 0x%I64x.\n",\r
736                                         i, cl_ntoh64(p_memory_descriptor->virtual_address) ) );\r
737                                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
738                                         ("memory_handle[%d]   = 0x%x.\n",\r
739                                         i, cl_ntoh32( p_memory_descriptor->memory_handle) ) );\r
740                                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
741                                         ("data_length[%d]     = %d.\n",\r
742                                         i, cl_ntoh32( p_memory_descriptor->data_length) ) );\r
743                         }\r
744                 }\r
745                 SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
746                         ("scatter/gather count = %d.\n", scatter_gather_count));\r
747         }\r
748 \r
749         p_srp_cmd->logical_unit_number = cl_hton64( p_srp_cmd->logical_unit_number );\r
750 \r
751         //set_srp_command_from_host_to_network( p_srp_cmd );\r
752 \r
753         SRP_EXIT( SRP_DBG_DATA );\r
754 }\r
755 \r
756 /* srp_format_io_request */\r
757 /*!\r
758 Format the SRP Cmd for the VFx target\r
759 \r
760 @param p_dev_ext - our context pointer\r
761 @param p_srb     - scsi request to send to target\r
762 \r
763 @return - TRUE for success, FALSE for failure\r
764 */\r
765 BOOLEAN\r
766 srp_format_io_request(\r
767         IN      PVOID               p_dev_ext,\r
768         IN OUT  PSCSI_REQUEST_BLOCK p_srb  )\r
769 {\r
770         srp_hba_t       *p_hba = ((srp_ext_t *)p_dev_ext)->p_hba;\r
771         BOOLEAN         result = TRUE;\r
772         srp_session_t   *p_srp_session;\r
773 \r
774         SRP_ENTER( SRP_DBG_DATA );\r
775 \r
776         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
777                 ("Device Extension Address = %p\n", p_dev_ext) );\r
778         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
779                 ("Srb Address              = %p\n", p_srb) );\r
780         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
781                 ("Srb DataBuffer Address   = %p\n", p_srb->DataBuffer) );\r
782         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
783                 ("Srb DataTransferLength   = %d\n", p_srb->DataTransferLength) );\r
784 \r
785         cl_obj_lock( &p_hba->obj );\r
786 \r
787         p_srp_session = p_hba->session_list[p_srb->TargetId];\r
788 \r
789         if ( p_srp_session != NULL )\r
790         {\r
791                 srp_conn_info_t srp_conn_info;\r
792 \r
793                 cl_obj_ref( &p_srp_session->obj );\r
794                 cl_obj_unlock( &p_hba->obj );\r
795 \r
796                 srp_conn_info.vaddr = p_srp_session->hca.vaddr;\r
797                 srp_conn_info.lkey  = p_srp_session->hca.lkey;\r
798                 srp_conn_info.rkey  = p_srp_session->hca.rkey;\r
799                 srp_conn_info.descriptor_format = p_srp_session->connection.descriptor_format;\r
800                 srp_conn_info.init_to_targ_iu_sz         = p_srp_session->connection.init_to_targ_iu_sz;\r
801                 srp_conn_info.max_scatter_gather_entries = p_srp_session->connection.max_scatter_gather_entries;\r
802                 srp_conn_info.tag                        = cl_atomic_inc( &p_srp_session->connection.tag );\r
803                 srp_conn_info.signal_send_completion     =\r
804                         ((srp_conn_info.tag % p_srp_session->connection.signaled_send_completion_count) == 0) ? TRUE : FALSE;\r
805 \r
806                 cl_obj_deref( &p_srp_session->obj );\r
807 \r
808                 srp_build_send_descriptor( p_dev_ext, p_srb, &srp_conn_info );\r
809 \r
810                 __srp_build_cmd( p_dev_ext, p_srb, &srp_conn_info );\r
811         }\r
812         else\r
813         {\r
814                 // Handle the error case here\r
815                 SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
816                         ("Cannot Find Session For Target ID = %d\n", p_srb->TargetId) );\r
817                 cl_obj_unlock( &p_hba->obj );\r
818                 p_srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;\r
819                 result = FALSE;\r
820         }\r
821 \r
822 \r
823         SRP_EXIT( SRP_DBG_DATA );\r
824         return ( result );\r
825 }\r
826 \r
827 void\r
828 srp_post_io_request(\r
829         IN      PVOID               p_dev_ext,\r
830         IN OUT  PSCSI_REQUEST_BLOCK p_srb  )\r
831 {\r
832         ib_api_status_t                 status;\r
833         srp_hba_t               *p_hba = ((srp_ext_t *)p_dev_ext)->p_hba;\r
834         srp_send_descriptor_t   *p_send_descriptor = (srp_send_descriptor_t *)p_srb->SrbExtension;\r
835         srp_session_t           *p_srp_session;\r
836 \r
837         SRP_ENTER( SRP_DBG_DATA );\r
838 \r
839         cl_obj_lock( &p_hba->obj );\r
840 \r
841         p_srp_session = p_hba->session_list[p_srb->TargetId];\r
842 \r
843         if ( p_srp_session != NULL )\r
844         {\r
845                 cl_obj_ref( &p_srp_session->obj );\r
846                 cl_obj_unlock( &p_hba->obj );\r
847 \r
848                 status = srp_post_send_descriptor( &p_srp_session->descriptors,\r
849                                                                                    p_send_descriptor,\r
850                                                                                    p_srp_session );\r
851 \r
852                 if ( status == IB_SUCCESS )\r
853                 {\r
854                         cl_atomic_dec( &p_srp_session->connection.request_limit );\r
855 \r
856                         if ( p_srp_session->connection.request_limit < 3 )\r
857                         {\r
858                                 SRP_PRINT( TRACE_LEVEL_WARNING, SRP_DBG_DATA,\r
859                                         ("Calling StorPortBusy.\n") );\r
860                                 StorPortBusy( p_dev_ext, 1 );\r
861                         }\r
862 \r
863                         cl_obj_deref( &p_srp_session->obj );\r
864                         goto exit;\r
865                 }\r
866 \r
867                 cl_obj_deref( &p_srp_session->obj );\r
868         }\r
869         else\r
870         {\r
871                 cl_obj_unlock( &p_hba->obj );\r
872         }\r
873 \r
874         p_srb->SrbStatus = SRB_STATUS_NO_HBA;\r
875         SRP_PRINT( TRACE_LEVEL_ERROR, SRP_DBG_ERROR,\r
876                            ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), Path = 0x%x, "\r
877                            "Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
878                            g_srb_status_name[p_srb->SrbStatus],\r
879                            p_srb->SrbStatus,\r
880                            g_srb_function_name[p_srb->Function],\r
881                            p_srb->Function,\r
882                            p_srb->PathId,\r
883                            p_srb->TargetId,\r
884                            p_srb->Lun,\r
885                            get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );\r
886         StorPortNotification( RequestComplete, p_dev_ext, p_srb );\r
887 \r
888 exit:\r
889         SRP_EXIT( SRP_DBG_DATA );\r
890 }\r
891 \r
892 void\r
893 srp_abort_command(\r
894         IN      PVOID               p_dev_ext,\r
895         IN OUT  PSCSI_REQUEST_BLOCK p_srb  )\r
896 {\r
897         srp_hba_t               *p_hba = ((srp_ext_t *)p_dev_ext)->p_hba;\r
898         srp_session_t           *p_srp_session;\r
899         uint64_t                iu_tag;\r
900         srp_send_descriptor_t   *p_srb_send_descriptor;\r
901         srp_send_descriptor_t   *p_send_descriptor;\r
902         srp_conn_info_t         srp_conn_info;\r
903         srp_tsk_mgmt_t          *p_srp_tsk_mgmt;\r
904 \r
905         SRP_ENTER( SRP_DBG_DATA );\r
906 \r
907         cl_obj_lock( &p_hba->obj );\r
908 \r
909         p_srp_session = p_hba->session_list[p_srb->TargetId];\r
910         if ( p_srp_session == NULL )\r
911         {\r
912                 /* If the session is NULL there is no connection and cannot be aborted */\r
913                 p_srb->SrbStatus = SRB_STATUS_ABORT_FAILED;\r
914                 goto exit;\r
915         }\r
916 \r
917         p_srb_send_descriptor = (srp_send_descriptor_t *)p_srb->NextSrb->SrbExtension;\r
918 \r
919         iu_tag = get_srp_information_unit_tag( (srp_information_unit_t *)p_srb_send_descriptor->data_segment );\r
920 \r
921         p_send_descriptor = srp_find_matching_send_descriptor( &p_srp_session->descriptors, iu_tag );\r
922         if ( p_send_descriptor == NULL )\r
923         {\r
924                 /* Cannot find the command so it must have been completed */\r
925                 p_srb->SrbStatus = SRB_STATUS_ABORT_FAILED;\r
926                 goto exit;\r
927         }\r
928 \r
929         CL_ASSERT( p_srb_send_descriptor == p_send_descriptor );\r
930 \r
931         p_srb->NextSrb->SrbStatus = SRB_STATUS_ABORTED;\r
932 \r
933         /* create and send abort request to the VFx */\r
934 \r
935         srp_conn_info.vaddr = p_srp_session->hca.vaddr;\r
936         srp_conn_info.lkey  = p_srp_session->hca.lkey;\r
937         srp_conn_info.rkey  = p_srp_session->hca.rkey;\r
938 \r
939         srp_conn_info.init_to_targ_iu_sz         = p_srp_session->connection.init_to_targ_iu_sz;\r
940         srp_conn_info.max_scatter_gather_entries = p_srp_session->connection.max_scatter_gather_entries;\r
941         srp_conn_info.tag                        = cl_atomic_inc( &p_srp_session->connection.tag );\r
942         srp_conn_info.signal_send_completion     =\r
943                 ((srp_conn_info.tag % p_srp_session->connection.signaled_send_completion_count) == 0) ? TRUE : FALSE;\r
944 \r
945         srp_build_send_descriptor( p_dev_ext, p_srb, &srp_conn_info );\r
946 \r
947         p_srp_tsk_mgmt = (srp_tsk_mgmt_t *)p_send_descriptor->data_segment;\r
948 \r
949         setup_srp_tsk_mgmt( p_srp_tsk_mgmt,\r
950                                                 p_send_descriptor->tag,\r
951                                                 BUILD_SCSI_ADDRESS( p_srb->Lun ),\r
952                                                 TMF_ABORT_TASK,\r
953                                                 iu_tag );\r
954 \r
955         set_srp_tsk_mgmt_from_host_to_network( p_srp_tsk_mgmt );\r
956 \r
957         srp_post_io_request( p_dev_ext, p_srb );\r
958 \r
959 exit:\r
960         cl_obj_unlock( &p_hba->obj );\r
961         if ( p_srb->SrbStatus == SRB_STATUS_ABORT_FAILED )\r
962         {\r
963                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DATA,\r
964                                    ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), "\r
965                                    "Path = 0x%x, Target = 0x%x, Lun = 0x%x\n",\r
966                                    g_srb_status_name[p_srb->SrbStatus],\r
967                                    p_srb->SrbStatus,\r
968                                    g_srb_function_name[p_srb->Function],\r
969                                    p_srb->Function,\r
970                                    p_srb->PathId,\r
971                                    p_srb->TargetId,\r
972                                    p_srb->Lun) );\r
973                 StorPortNotification( RequestComplete, p_dev_ext, p_srb );\r
974         }\r
975 \r
976         SRP_EXIT( SRP_DBG_DATA );\r
977 }\r
978 \r
979 void\r
980 srp_lun_reset(\r
981         IN      PVOID               p_dev_ext,\r
982         IN OUT  PSCSI_REQUEST_BLOCK p_srb  )\r
983 {\r
984 \r
985         srp_hba_t               *p_hba = ((srp_ext_t *)p_dev_ext)->p_hba;\r
986         srp_session_t           *p_srp_session;\r
987 \r
988         SRP_ENTER( SRP_DBG_DATA );\r
989 \r
990         cl_obj_lock( &p_hba->obj );\r
991 \r
992         p_srp_session = p_hba->session_list[p_srb->TargetId];\r
993         if ( p_srp_session != NULL )\r
994         {\r
995                 srp_send_descriptor_t   *p_send_descriptor;\r
996                 UCHAR                   path_id   = p_srb->PathId;\r
997                 UCHAR                   target_id = p_srb->TargetId;\r
998                 UCHAR                   lun       = p_srb->Lun;\r
999 \r
1000             StorPortPauseDevice( p_dev_ext, p_srb->PathId, p_srb->TargetId, p_srb->Lun, 10 );\r
1001 \r
1002                 while ( (p_send_descriptor = srp_remove_lun_head_send_descriptor( &p_srp_session->descriptors, p_srb->Lun )) != NULL )\r
1003                 {\r
1004                         SRP_PRINT( TRACE_LEVEL_VERBOSE, SRP_DBG_DATA,\r
1005                                            ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), "\r
1006                                            "Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%I64xn",\r
1007                                            g_srb_status_name[SRB_STATUS_BUS_RESET],\r
1008                                            SRB_STATUS_BUS_RESET,\r
1009                                            g_srb_function_name[p_send_descriptor->p_srb->Function],\r
1010                                            p_send_descriptor->p_srb->Function,\r
1011                                            p_send_descriptor->p_srb->PathId,\r
1012                                            p_send_descriptor->p_srb->TargetId,\r
1013                                            p_send_descriptor->p_srb->Lun,\r
1014                                            get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );\r
1015                 }\r
1016 \r
1017                 p_srb->SrbStatus = SRB_STATUS_SUCCESS;\r
1018 \r
1019                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DATA,\r
1020                                    ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), "\r
1021                                    "Path = 0x%x, Target = 0x%x, Lun = 0x%x\n",\r
1022                                    g_srb_status_name[p_srb->SrbStatus],\r
1023                                    p_srb->SrbStatus,\r
1024                                    g_srb_function_name[p_srb->Function],\r
1025                                    p_srb->Function,\r
1026                                    p_srb->PathId,\r
1027                                    p_srb->TargetId,\r
1028                                    p_srb->Lun) );\r
1029 \r
1030                 StorPortNotification( RequestComplete, p_dev_ext, p_srb );\r
1031 \r
1032                 StorPortCompleteRequest( p_dev_ext, path_id, target_id, lun, SRB_STATUS_BUS_RESET );\r
1033 \r
1034                 StorPortResumeDevice( p_dev_ext, path_id, target_id, lun );\r
1035         }\r
1036         else\r
1037         {\r
1038                 // Handle the error case here\r
1039                 p_srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;\r
1040                 SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DATA,\r
1041                                    ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), "\r
1042                                    "Path = 0x%x, Target = 0x%x, Lun = 0x%x\n",\r
1043                                    g_srb_status_name[p_srb->SrbStatus],\r
1044                                    p_srb->SrbStatus,\r
1045                                    g_srb_function_name[p_srb->Function],\r
1046                                    p_srb->Function,\r
1047                                    p_srb->PathId,\r
1048                                    p_srb->TargetId,\r
1049                                    p_srb->Lun) );\r
1050 \r
1051                 StorPortNotification( RequestComplete, p_dev_ext, p_srb );\r
1052         }\r
1053 \r
1054         cl_obj_unlock( &p_hba->obj );\r
1055 \r
1056         SRP_EXIT( SRP_DBG_DATA );\r
1057 }\r