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