2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
4 * This software is available to you under the OpenIB.org BSD license
\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
11 * - Redistributions of source code must retain the above
\r
12 * copyright notice, this list of conditions and the following
\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
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
33 #include <complib/cl_math.h>
\r
34 #include <complib/cl_obj.h>
\r
36 #include "srp_cmd.h"
\r
37 #include "srp_data_path.h"
\r
38 #include "srp_debug.h"
\r
39 #include "srp_descriptors.h"
\r
40 #include "srp_rsp.h"
\r
41 #include "srp_session.h"
\r
42 #include "srp_tsk_mgmt.h"
\r
44 //#include "srp_aer_req.h"
\r
45 //#include "srp_aer_rsp.h"
\r
47 //#include "srp_cred_req.h"
\r
48 //#include "srp_cred_rsp.h"
\r
50 //#include "srp_i_logout.h"
\r
51 //#include "srp_t_logout.h"
\r
53 // Final address is of the form 0b00ttttttllllllll
\r
54 #define BUILD_SCSI_ADDRESS(target, lun) ((((uint64_t)(target & 0x3f)<<8)+(uint64_t)lun) << 48)
\r
58 __srp_process_session_send_completions(
\r
59 IN srp_session_t *p_session )
\r
61 ib_api_status_t status;
\r
62 ib_wc_t *p_wc_done_list = NULL;
\r
65 SRP_ENTER( SRP_DBG_FUNC );
\r
67 cl_obj_lock( &p_session->obj );
\r
69 if ( p_session->connection.state != SRP_CONNECTED )
\r
71 cl_obj_unlock( &p_session->obj );
\r
72 SRP_EXIT( SRP_DBG_FUNC );
\r
76 status = p_session->p_hba->ifc.poll_cq(
\r
77 p_session->connection.h_send_cq,
\r
78 &p_session->connection.p_wc_free_list,
\r
80 if ( status != IB_SUCCESS )
\r
82 SRP_TRACE_EXIT( SRP_DBG_ERROR,
\r
83 ("ib_poll_cq() failed!, status 0x%x\n", status) );
\r
85 // TODO: Kill session and inform port driver link down scsiportnotification
\r
86 cl_obj_unlock( &p_session->obj );
\r
90 cl_obj_ref( &p_session->obj );
\r
91 cl_obj_unlock( &p_session->obj );
\r
93 while ( (p_wc = p_wc_done_list) != NULL )
\r
95 /* Remove head from list */
\r
96 p_wc_done_list = p_wc->p_next;
\r
97 p_wc->p_next = NULL;
\r
99 if ( p_wc->status != IB_WCS_SUCCESS )
\r
101 srp_send_descriptor_t *p_send_descriptor;
\r
103 p_send_descriptor = (srp_send_descriptor_t *)((uintn_t)p_wc->wr_id);
\r
105 // TODO: Kill session and inform port driver link down scsiportnotification
\r
106 SRP_TRACE( SRP_DBG_ERROR,
\r
107 ("Send failed!, status 0x%x\n", p_wc->status) );
\r
109 SRP_TRACE( SRP_DBG_VERBOSE,
\r
110 ("Send Completion Received for Function = %s(0x%x), Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%"PRIx64"\n",
\r
111 g_srb_function_name[p_send_descriptor->p_srb->Function],
\r
112 p_send_descriptor->p_srb->Function,
\r
113 p_send_descriptor->p_srb->PathId,
\r
114 p_send_descriptor->p_srb->TargetId,
\r
115 p_send_descriptor->p_srb->Lun,
\r
116 get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );
\r
119 /* Put onto head of free list */
\r
120 cl_obj_lock( &p_session->obj );
\r
121 p_wc->p_next = p_session->connection.p_wc_free_list;
\r
122 p_session->connection.p_wc_free_list = p_wc;
\r
123 cl_obj_unlock( &p_session->obj );
\r
125 /* Get next completion */
\r
126 p_wc = p_wc_done_list;
\r
129 /* Re-arm the CQ for more completions */
\r
130 status = p_session->p_hba->ifc.rearm_cq(
\r
131 p_session->connection.h_send_cq, FALSE );
\r
132 if ( status != IB_SUCCESS)
\r
134 SRP_TRACE( SRP_DBG_ERROR,
\r
135 ("ib_rearm_cq() failed!, status 0x%x\n", status) );
\r
137 // TODO: Kill session and inform port driver link down scsiportnotification
\r
140 cl_obj_deref( &p_session->obj );
\r
142 SRP_EXIT( SRP_DBG_FUNC );
\r
145 /* srp_send_completion_cb */
\r
147 Set Timer to Process Send Completions - Usually bad if we get here
\r
149 @param p_context - context pointer to the owning session
\r
154 srp_send_completion_cb(
\r
155 IN const ib_cq_handle_t h_cq,
\r
156 IN void *p_context )
\r
158 srp_session_t *p_session = (srp_session_t *)p_context;
\r
160 SRP_ENTER( SRP_DBG_FUNC );
\r
162 UNUSED_PARAM( h_cq );
\r
164 __srp_process_session_send_completions( p_session );
\r
166 SRP_EXIT( SRP_DBG_FUNC );
\r
171 __srp_process_recv_completion(
\r
172 IN srp_recv_descriptor_t *p_recv_descriptor,
\r
173 IN srp_session_t *p_session )
\r
175 ib_api_status_t status = IB_SUCCESS;
\r
176 srp_rsp_t *p_srp_rsp;
\r
177 uint8_t response_status;
\r
178 srp_send_descriptor_t *p_send_descriptor;
\r
180 SRP_ENTER( SRP_DBG_FUNC );
\r
182 p_srp_rsp = (srp_rsp_t *)p_recv_descriptor->p_data_segment;
\r
184 set_srp_response_from_network_to_host( p_srp_rsp );
\r
186 response_status = get_srp_response_status( p_srp_rsp );
\r
188 p_send_descriptor = srp_find_matching_send_descriptor(
\r
189 &p_session->descriptors,
\r
190 get_srp_response_tag( (srp_rsp_t *)p_recv_descriptor->p_data_segment ) );
\r
191 if ( p_send_descriptor == NULL )
\r
193 /* Repost the recv descriptor */
\r
194 status = p_session->p_hba->ifc.post_recv(
\r
195 p_session->connection.h_qp, &p_recv_descriptor->wr, NULL );
\r
196 if ( status != IB_SUCCESS )
\r
198 SRP_TRACE( SRP_DBG_ERROR,
\r
199 ("Failed to post send descriptor. Status = %d.\n", status) );
\r
200 // TODO: Kill session and inform port driver link down scsiportnotification
\r
203 cl_atomic_add( &p_session->connection.request_limit, get_srp_response_request_limit_delta( p_srp_rsp ) );
\r
205 SRP_TRACE( SRP_DBG_WARN, ("Matching Send Descriptor Not Found.\n") );
\r
210 SRP_TRACE( SRP_DBG_VERBOSE,
\r
211 ("Recv Completion Received for Function = %s(0x%x), Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%"PRIx64"\n",
\r
212 g_srb_function_name[p_send_descriptor->p_srb->Function],
\r
213 p_send_descriptor->p_srb->Function,
\r
214 p_send_descriptor->p_srb->PathId,
\r
215 p_send_descriptor->p_srb->TargetId,
\r
216 p_send_descriptor->p_srb->Lun,
\r
217 get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );
\r
219 switch ( get_srp_iu_buffer_type( (srp_iu_buffer_t *)p_send_descriptor->data_segment ) )
\r
223 srp_tsk_mgmt_t *p_srp_tsk_mgmt = (srp_tsk_mgmt_t *)p_send_descriptor->data_segment;
\r
225 set_srp_tsk_mgmt_from_network_to_host( p_srp_tsk_mgmt );
\r
227 p_send_descriptor->p_srb->SrbStatus =
\r
228 (response_status == SCSISTAT_GOOD) ? SRB_STATUS_SUCCESS : SRB_STATUS_ABORT_FAILED;
\r
230 if ( get_srp_tsk_mgmt_task_management_flags( p_srp_tsk_mgmt ) == TMF_ABORT_TASK )
\r
232 /* Repost the recv descriptor */
\r
233 status = p_session->p_hba->ifc.post_recv(
\r
234 p_session->connection.h_qp, &p_recv_descriptor->wr, NULL );
\r
235 if ( status != IB_SUCCESS )
\r
237 SRP_TRACE( SRP_DBG_ERROR,
\r
238 ("Failed to post recv descriptor. Status = %d.\n", status) );
\r
239 // TODO: Kill session and inform port driver link down storportnotification
\r
242 cl_atomic_add( &p_session->connection.request_limit, get_srp_response_request_limit_delta( p_srp_rsp ) );
\r
244 SRP_TRACE( SRP_DBG_VERBOSE,
\r
245 ("Srb Status = %s(0x%x)\n",
\r
246 g_srb_status_name[p_send_descriptor->p_srb->SrbStatus],
\r
247 p_send_descriptor->p_srb->SrbStatus) );
\r
249 SRP_TRACE( SRP_DBG_VERBOSE, ("Device Extension Address = %p\n", p_session->p_hba->p_ext) );
\r
250 SRP_TRACE( SRP_DBG_VERBOSE, ("Srb Address = %p\n", p_send_descriptor->p_srb) );
\r
251 SRP_TRACE( SRP_DBG_VERBOSE, ("Srb DataBuffer Address = %p\n", p_send_descriptor->p_srb->DataBuffer) );
\r
252 SRP_TRACE( SRP_DBG_VERBOSE, ("Srb DataTransferLength = %d\n", p_send_descriptor->p_srb->DataTransferLength) );
\r
254 SRP_TRACE( SRP_DBG_VERBOSE,
\r
255 ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%"PRIx64"\n",
\r
256 g_srb_status_name[p_send_descriptor->p_srb->SrbStatus],
\r
257 p_send_descriptor->p_srb->SrbStatus,
\r
258 g_srb_function_name[p_send_descriptor->p_srb->Function],
\r
259 p_send_descriptor->p_srb->Function,
\r
260 p_send_descriptor->p_srb->PathId,
\r
261 p_send_descriptor->p_srb->TargetId,
\r
262 p_send_descriptor->p_srb->Lun,
\r
263 get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );
\r
265 StorPortNotification( RequestComplete, p_session->p_hba->p_ext, p_send_descriptor->p_srb );
\r
271 p_send_descriptor->p_srb->ScsiStatus = response_status;
\r
272 p_send_descriptor->p_srb->SrbStatus =
\r
273 (response_status == SCSISTAT_GOOD) ? SRB_STATUS_SUCCESS : SRB_STATUS_ERROR;
\r
275 if ( get_srp_response_flags( p_srp_rsp ) != 0 )
\r
279 if ( (response_status != SCSISTAT_CHECK_CONDITION) && get_srp_response_di_under( p_srp_rsp ) )
\r
281 resid = get_srp_response_data_in_residual_count( p_srp_rsp );
\r
283 SRP_TRACE( SRP_DBG_WARN,
\r
284 ("DI Underflow in response: expected %d got %d.\n",
\r
285 p_send_descriptor->p_srb->DataTransferLength,
\r
286 p_send_descriptor->p_srb->DataTransferLength - resid) );
\r
288 p_send_descriptor->p_srb->DataTransferLength -= resid;
\r
290 if ( p_send_descriptor->p_srb->SrbStatus == SRB_STATUS_SUCCESS )
\r
292 p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; /* Also for underrun see DDK */
\r
296 if ( (response_status != SCSISTAT_CHECK_CONDITION) && get_srp_response_do_under( p_srp_rsp ) )
\r
298 resid = get_srp_response_data_out_residual_count( p_srp_rsp );
\r
300 SRP_TRACE( SRP_DBG_WARN,
\r
301 ("DI Underflow in response: expected %d got %d.\n",
\r
302 p_send_descriptor->p_srb->DataTransferLength,
\r
303 p_send_descriptor->p_srb->DataTransferLength - resid) );
\r
305 p_send_descriptor->p_srb->DataTransferLength -= resid;
\r
307 if ( p_send_descriptor->p_srb->SrbStatus == SRB_STATUS_SUCCESS )
\r
309 p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; /* Also for underrun see DDK */
\r
313 if ( get_srp_response_sns_valid( p_srp_rsp ) )
\r
315 uint8_t *p_sense_data = get_srp_response_sense_data( p_srp_rsp );
\r
317 /* Copy only as much of the sense data as we can hold. */
\r
318 cl_memcpy( p_send_descriptor->p_srb->SenseInfoBuffer,
\r
320 MIN( get_srp_response_sense_data_list_length( p_srp_rsp ),
\r
321 p_send_descriptor->p_srb->SenseInfoBufferLength ) );
\r
323 if ( ((p_sense_data[2]&0xf) == 0x0b /*ABORTED_COMMAND*/) &&
\r
324 (p_sense_data[12] == 0x08) &&
\r
325 (p_sense_data[13] == 0x00) )
\r
328 /* probably a problem with the Vfx FC san like wire pull*/
\r
329 /* initiate session recovery */
\r
330 SRP_TRACE( SRP_DBG_WARN,
\r
331 ("Sense Data indicates FC link connectivity has been lost.\n") );
\r
332 StorPortPauseDevice( p_session->p_hba->p_ext,
\r
333 p_send_descriptor->p_srb->PathId,
\r
334 p_send_descriptor->p_srb->TargetId,
\r
335 p_send_descriptor->p_srb->Lun,
\r
340 if ( get_srp_response_di_over( p_srp_rsp ) || get_srp_response_do_over( p_srp_rsp ) )
\r
342 SRP_TRACE( SRP_DBG_WARN,
\r
343 ("Overflow error in response.\n") );
\r
344 if ( p_send_descriptor->p_srb->SrbStatus == SRB_STATUS_SUCCESS )
\r
346 p_send_descriptor->p_srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
\r
351 SRP_TRACE( SRP_DBG_VERBOSE, ("DataBuffer = 0x%"PRIx64".\n",
\r
352 MmGetPhysicalAddress( p_send_descriptor->p_srb->DataBuffer ).QuadPart) );
\r
354 /* Repost the recv descriptor */
\r
355 status = p_session->p_hba->ifc.post_recv(
\r
356 p_session->connection.h_qp, &p_recv_descriptor->wr, NULL );
\r
357 if ( status != IB_SUCCESS )
\r
359 SRP_TRACE( SRP_DBG_ERROR,
\r
360 ("Failed to post recv descriptor. Status = %d.\n", status) );
\r
361 // TODO: Kill session and inform port driver link down storportnotification
\r
364 cl_atomic_add( &p_session->connection.request_limit, get_srp_response_request_limit_delta( p_srp_rsp ) );
\r
366 SRP_TRACE( SRP_DBG_VERBOSE,
\r
367 ("Srb Status = %s(0x%x)\n",
\r
368 g_srb_status_name[p_send_descriptor->p_srb->SrbStatus],
\r
369 p_send_descriptor->p_srb->SrbStatus) );
\r
371 SRP_TRACE( SRP_DBG_VERBOSE, ("Device Extension Address = %p\n", p_session->p_hba->p_ext) );
\r
372 SRP_TRACE( SRP_DBG_VERBOSE, ("Srb Address = %p\n", p_send_descriptor->p_srb) );
\r
373 SRP_TRACE( SRP_DBG_VERBOSE, ("Srb DataBuffer Address = %p\n", p_send_descriptor->p_srb->DataBuffer) );
\r
374 SRP_TRACE( SRP_DBG_VERBOSE, ("Srb DataTransferLength = %d\n", p_send_descriptor->p_srb->DataTransferLength) );
\r
376 SRP_TRACE( SRP_DBG_VERBOSE,
\r
377 ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%"PRIx64"\n",
\r
378 g_srb_status_name[p_send_descriptor->p_srb->SrbStatus],
\r
379 p_send_descriptor->p_srb->SrbStatus,
\r
380 g_srb_function_name[p_send_descriptor->p_srb->Function],
\r
381 p_send_descriptor->p_srb->Function,
\r
382 p_send_descriptor->p_srb->PathId,
\r
383 p_send_descriptor->p_srb->TargetId,
\r
384 p_send_descriptor->p_srb->Lun,
\r
385 get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );
\r
387 StorPortNotification( RequestComplete, p_session->p_hba->p_ext, p_send_descriptor->p_srb );
\r
390 case SRP_LOGIN_REQ:
\r
400 SRP_EXIT( SRP_DBG_FUNC );
\r
407 __srp_process_session_recv_completions(
\r
408 IN srp_session_t *p_session )
\r
410 ib_api_status_t status;
\r
411 ib_wc_t *p_wc_done_list;
\r
414 SRP_ENTER( SRP_DBG_FUNC );
\r
416 cl_obj_lock( &p_session->obj );
\r
418 if ( p_session->connection.state != SRP_CONNECTED )
\r
420 cl_obj_unlock( &p_session->obj );
\r
421 SRP_EXIT( SRP_DBG_FUNC );
\r
425 status = p_session->p_hba->ifc.poll_cq(
\r
426 p_session->connection.h_recv_cq,
\r
427 &p_session->connection.p_wc_free_list,
\r
429 if ( status != IB_SUCCESS )
\r
431 SRP_TRACE( SRP_DBG_ERROR,
\r
432 ("ib_poll_cq() failed!, status 0x%x\n", status) );
\r
434 // TODO: Kill session and inform port driver link down scsiportnotification
\r
435 SRP_EXIT( SRP_DBG_FUNC );
\r
436 cl_obj_unlock( &p_session->obj );
\r
440 cl_obj_ref( &p_session->obj );
\r
441 cl_obj_unlock( &p_session->obj );
\r
443 while ( (p_wc = p_wc_done_list) != NULL )
\r
445 srp_recv_descriptor_t *p_recv_descriptor;
\r
447 /* Remove head from list */
\r
448 p_wc_done_list = p_wc->p_next;
\r
449 p_wc->p_next = NULL;
\r
451 p_recv_descriptor = (srp_recv_descriptor_t *)((uintn_t)p_wc->wr_id);
\r
453 if ( p_wc->status == IB_WCS_SUCCESS )
\r
455 status = __srp_process_recv_completion( p_recv_descriptor, p_session );
\r
456 if ( status != IB_SUCCESS )
\r
458 // TODO: Kill session and inform port driver link down scsiportnotification
\r
463 SRP_TRACE( SRP_DBG_ERROR,
\r
464 ("Recv failed!, status 0x%x\n", p_wc->status) );
\r
467 /* Put onto head of free list */
\r
468 cl_obj_lock( &p_session->obj );
\r
469 p_wc->p_next = p_session->connection.p_wc_free_list;
\r
470 p_session->connection.p_wc_free_list = p_wc;
\r
471 cl_obj_unlock( &p_session->obj );
\r
473 /* Get next completion */
\r
474 p_wc = p_wc_done_list;
\r
477 /* Re-arm the CQ for more completions */
\r
478 status = p_session->p_hba->ifc.rearm_cq(
\r
479 p_session->connection.h_recv_cq, FALSE );
\r
480 if ( status != IB_SUCCESS)
\r
482 SRP_TRACE( SRP_DBG_ERROR,
\r
483 ("ib_rearm_cq() failed!, status 0x%x\n", status) );
\r
485 // TODO: Kill session and inform port driver link down scsiportnotification
\r
488 cl_obj_deref( &p_session->obj );
\r
490 SRP_EXIT( SRP_DBG_FUNC );
\r
493 /* srp_recv_completion_cb */
\r
495 Set Timer to Process Receive Completions - Responses to our requests
\r
497 @param p_context - context pointer to the owning session
\r
502 srp_recv_completion_cb(
\r
503 IN const ib_cq_handle_t h_cq,
\r
504 IN void *p_context )
\r
506 srp_session_t *p_session = (srp_session_t *)p_context;
\r
508 SRP_ENTER( SRP_DBG_FUNC );
\r
510 UNUSED_PARAM( h_cq );
\r
512 __srp_process_session_recv_completions( p_session );
\r
514 SRP_EXIT( SRP_DBG_FUNC );
\r
517 /* __srp_build_cmd */
\r
519 Build the SRP Cmd to be sent to the VFx target
\r
521 @param p_dev_ext - our context pointer
\r
522 @param p_srb - scsi request to send to target
\r
529 IN PVOID p_dev_ext,
\r
530 IN OUT PSCSI_REQUEST_BLOCK p_srb,
\r
531 IN srp_conn_info_t *p_srp_conn_info )
\r
533 srp_send_descriptor_t *p_send_descriptor = (srp_send_descriptor_t *)p_srb->SrbExtension;
\r
534 srp_cmd_t *p_srp_cmd = (srp_cmd_t *)p_send_descriptor->data_segment;
\r
536 PSTOR_SCATTER_GATHER_LIST p_scatter_gather_list = NULL;
\r
537 uint8_t scatter_gather_count = 0;
\r
538 srp_memory_descriptor_t *p_memory_descriptor = NULL;
\r
539 srp_memory_table_descriptor_t *p_table_descriptor = NULL;
\r
541 ULONG scsi_direction = p_srb->SrbFlags & ( SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT );
\r
542 DATA_BUFFER_DESCRIPTOR_FORMAT format = p_srp_conn_info->descriptor_format & DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS;
\r
544 SRP_ENTER( SRP_DBG_FUNC );
\r
546 SRP_TRACE( SRP_DBG_VERBOSE,
\r
547 ("Sending I/O to Path = 0x%x, Target = 0x%x, Lun = 0x%x\n",
\r
552 setup_srp_command( p_srp_cmd,
\r
553 p_send_descriptor->tag,
\r
554 DBDF_NO_DATA_BUFFER_DESCRIPTOR_PRESENT,
\r
555 DBDF_NO_DATA_BUFFER_DESCRIPTOR_PRESENT,
\r
558 BUILD_SCSI_ADDRESS( p_srb->TargetId, p_srb->Lun ),
\r
562 p_cdb = get_srp_command_cdb( p_srp_cmd );
\r
563 cl_memcpy( p_cdb, p_srb->Cdb, p_srb->CdbLength );
\r
565 SRP_TRACE( SRP_DBG_VERBOSE, ("CDB Length = %d.\n", p_srb->CdbLength) );
\r
566 SRP_TRACE( SRP_DBG_VERBOSE, ("CDB = 0x") );
\r
567 for ( i = 0; i < p_srb->CdbLength; i++ )
\r
569 SRP_TRACE( SRP_DBG_VERBOSE, ("%0.2x", p_srb->Cdb[i]) );
\r
571 SRP_TRACE( SRP_DBG_VERBOSE, ("\n.") );
\r
575 format = DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR;
\r
578 if ( scsi_direction )
\r
580 p_scatter_gather_list = StorPortGetScatterGatherList( p_dev_ext, p_srb );
\r
581 CL_ASSERT( p_scatter_gather_list != NULL );
\r
582 scatter_gather_count = (uint8_t)p_scatter_gather_list->NumberOfElements;
\r
585 /* Cap the length of the inline descriptors to the maximum IU size. */
\r
586 if( p_srp_conn_info->max_scatter_gather_entries < scatter_gather_count )
\r
588 scatter_gather_count =
\r
589 (uint8_t)p_srp_conn_info->max_scatter_gather_entries;
\r
592 if ( scsi_direction == SRB_FLAGS_DATA_IN )
\r
594 set_srp_command_data_in_buffer_desc_fmt( p_srp_cmd, format );
\r
595 set_srp_command_data_in_buffer_desc_count( p_srp_cmd, scatter_gather_count );
\r
596 p_memory_descriptor = get_srp_command_data_in_buffer_desc( p_srp_cmd );
\r
599 else if ( scsi_direction == SRB_FLAGS_DATA_OUT )
\r
601 set_srp_command_data_out_buffer_desc_fmt( p_srp_cmd, format );
\r
602 set_srp_command_data_out_buffer_desc_count( p_srp_cmd, scatter_gather_count );
\r
603 p_memory_descriptor = get_srp_command_data_out_buffer_desc( p_srp_cmd );
\r
606 if ( p_memory_descriptor != NULL )
\r
608 PSTOR_SCATTER_GATHER_ELEMENT p_sg_element;
\r
609 uint32_t totalLength;
\r
611 if ( format == DBDF_INDIRECT_DATA_BUFFER_DESCRIPTORS )
\r
613 p_table_descriptor = (srp_memory_table_descriptor_t *)p_memory_descriptor;
\r
614 p_memory_descriptor = ( srp_memory_descriptor_t *)(p_table_descriptor + 1 );
\r
616 buf_addr = (StorPortGetPhysicalAddress( p_dev_ext,p_srb, p_memory_descriptor, &length)).QuadPart;
\r
618 /* we don't swap rkey - it is already in network order*/
\r
619 p_table_descriptor->descriptor.virtual_address = cl_hton64( buf_addr );
\r
620 p_table_descriptor->descriptor.memory_handle = p_srp_conn_info->rkey;
\r
622 p_table_descriptor->descriptor.data_length =
\r
623 cl_hton32( sizeof(srp_memory_descriptor_t) *
\r
624 p_scatter_gather_list->NumberOfElements );
\r
626 for ( i = 0, totalLength = 0, p_sg_element = p_scatter_gather_list->List;
\r
627 i < p_scatter_gather_list->NumberOfElements;
\r
628 i++, p_memory_descriptor++, p_sg_element++ )
\r
630 buf_addr = p_srp_conn_info->vaddr + p_sg_element->PhysicalAddress.QuadPart;
\r
632 p_memory_descriptor->virtual_address = cl_hton64( buf_addr );
\r
633 p_memory_descriptor->memory_handle = p_srp_conn_info->rkey;
\r
634 p_memory_descriptor->data_length = cl_hton32( p_sg_element->Length );
\r
635 totalLength += p_sg_element->Length;
\r
637 p_table_descriptor->total_length = cl_hton32( totalLength );
\r
639 else if ( format == DBDF_DIRECT_DATA_BUFFER_DESCRIPTOR )
\r
641 CL_ASSERT( scatter_gather_count ==
\r
642 p_scatter_gather_list->NumberOfElements );
\r
643 for ( i = 0, p_sg_element = p_scatter_gather_list->List;
\r
644 i < scatter_gather_count; i++, p_memory_descriptor++, p_sg_element++ )
\r
646 buf_addr = p_srp_conn_info->vaddr + p_sg_element->PhysicalAddress.QuadPart;
\r
647 p_memory_descriptor->virtual_address = cl_hton64( buf_addr );
\r
648 p_memory_descriptor->memory_handle = p_srp_conn_info->rkey;
\r
649 p_memory_descriptor->data_length = cl_hton32( p_sg_element->Length );
\r
651 SRP_TRACE( SRP_DBG_VERBOSE, ("virtual_address[%d] = 0x%"PRIx64".\n", i, cl_ntoh64(p_memory_descriptor->virtual_address) ) );
\r
652 SRP_TRACE( SRP_DBG_VERBOSE, ("memory_handle[%d] = 0x%x.\n", i, cl_ntoh32( p_memory_descriptor->memory_handle) ) );
\r
653 SRP_TRACE( SRP_DBG_VERBOSE, ("data_length[%d] = %d.\n", i, cl_ntoh32( p_memory_descriptor->data_length) ) );
\r
656 SRP_TRACE( SRP_DBG_VERBOSE, ("scatter/gather count = %d.\n", scatter_gather_count));
\r
659 p_srp_cmd->logical_unit_number = cl_hton64( p_srp_cmd->logical_unit_number );
\r
661 //set_srp_command_from_host_to_network( p_srp_cmd );
\r
663 SRP_EXIT( SRP_DBG_FUNC );
\r
666 /* srp_format_io_request */
\r
668 Format the SRP Cmd for the VFx target
\r
670 @param p_dev_ext - our context pointer
\r
671 @param p_srb - scsi request to send to target
\r
673 @return - TRUE for success, FALSE for failure
\r
676 srp_format_io_request(
\r
677 IN PVOID p_dev_ext,
\r
678 IN OUT PSCSI_REQUEST_BLOCK p_srb )
\r
680 srp_hba_t *p_hba = ((srp_ext_t *)p_dev_ext)->p_hba;
\r
681 BOOLEAN result = TRUE;
\r
682 srp_session_t *p_srp_session;
\r
684 SRP_ENTER( SRP_DBG_FUNC );
\r
686 SRP_TRACE( SRP_DBG_VERBOSE, ("Device Extension Address = %p\n", p_dev_ext) );
\r
687 SRP_TRACE( SRP_DBG_VERBOSE, ("Srb Address = %p\n", p_srb) );
\r
688 SRP_TRACE( SRP_DBG_VERBOSE, ("Srb DataBuffer Address = %p\n", p_srb->DataBuffer) );
\r
689 SRP_TRACE( SRP_DBG_VERBOSE, ("Srb DataTransferLength = %d\n", p_srb->DataTransferLength) );
\r
691 cl_obj_lock( &p_hba->obj );
\r
693 p_srp_session = p_hba->session_list[p_srb->TargetId];
\r
695 if ( p_srp_session != NULL )
\r
697 srp_conn_info_t srp_conn_info;
\r
699 cl_obj_ref( &p_srp_session->obj );
\r
700 cl_obj_unlock( &p_hba->obj );
\r
702 srp_conn_info.vaddr = p_srp_session->hca.vaddr;
\r
703 srp_conn_info.lkey = p_srp_session->hca.lkey;
\r
704 srp_conn_info.rkey = p_srp_session->hca.rkey;
\r
705 srp_conn_info.descriptor_format = p_srp_session->connection.descriptor_format;
\r
706 srp_conn_info.init_to_targ_iu_sz = p_srp_session->connection.init_to_targ_iu_sz;
\r
707 srp_conn_info.max_scatter_gather_entries = p_srp_session->connection.max_scatter_gather_entries;
\r
708 srp_conn_info.tag = cl_atomic_inc( &p_srp_session->connection.tag );
\r
709 srp_conn_info.signal_send_completion =
\r
710 ((srp_conn_info.tag % p_srp_session->connection.signaled_send_completion_count) == 0) ? TRUE : FALSE;
\r
712 cl_obj_deref( &p_srp_session->obj );
\r
714 srp_build_send_descriptor( p_dev_ext, p_srb, &srp_conn_info );
\r
716 __srp_build_cmd( p_dev_ext, p_srb, &srp_conn_info );
\r
720 // Handle the error case here
\r
721 SRP_TRACE( SRP_DBG_ERROR, ("Cannot Find Session For Target ID = %d\n", p_srb->TargetId) );
\r
722 cl_obj_unlock( &p_hba->obj );
\r
723 p_srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
\r
728 SRP_EXIT( SRP_DBG_FUNC );
\r
733 srp_post_io_request(
\r
734 IN PVOID p_dev_ext,
\r
735 IN OUT PSCSI_REQUEST_BLOCK p_srb )
\r
737 ib_api_status_t status;
\r
738 srp_hba_t *p_hba = ((srp_ext_t *)p_dev_ext)->p_hba;
\r
739 srp_send_descriptor_t *p_send_descriptor = (srp_send_descriptor_t *)p_srb->SrbExtension;
\r
740 srp_session_t *p_srp_session;
\r
742 SRP_ENTER( SRP_DBG_FUNC );
\r
744 cl_obj_lock( &p_hba->obj );
\r
746 p_srp_session = p_hba->session_list[p_srb->TargetId];
\r
748 if ( p_srp_session != NULL )
\r
750 cl_obj_ref( &p_srp_session->obj );
\r
751 cl_obj_unlock( &p_hba->obj );
\r
753 status = srp_post_send_descriptor( &p_srp_session->descriptors,
\r
757 if ( status == IB_SUCCESS )
\r
759 cl_atomic_dec( &p_srp_session->connection.request_limit );
\r
761 if ( p_srp_session->connection.request_limit < 3 )
\r
763 SRP_TRACE( SRP_DBG_WARN, ("Calling StorPortBusy.\n") );
\r
764 StorPortBusy( p_dev_ext, 1 );
\r
767 cl_obj_deref( &p_srp_session->obj );
\r
771 cl_obj_deref( &p_srp_session->obj );
\r
775 cl_obj_unlock( &p_hba->obj );
\r
778 p_srb->SrbStatus = SRB_STATUS_NO_HBA;
\r
779 SRP_TRACE( SRP_DBG_ERROR,
\r
780 ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%"PRIx64"\n",
\r
781 g_srb_status_name[p_srb->SrbStatus],
\r
783 g_srb_function_name[p_srb->Function],
\r
788 get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );
\r
789 StorPortNotification( RequestComplete, p_dev_ext, p_srb );
\r
792 SRP_EXIT( SRP_DBG_FUNC );
\r
797 IN PVOID p_dev_ext,
\r
798 IN OUT PSCSI_REQUEST_BLOCK p_srb )
\r
800 srp_hba_t *p_hba = ((srp_ext_t *)p_dev_ext)->p_hba;
\r
801 srp_session_t *p_srp_session;
\r
803 srp_send_descriptor_t *p_srb_send_descriptor;
\r
804 srp_send_descriptor_t *p_send_descriptor;
\r
805 srp_conn_info_t srp_conn_info;
\r
806 srp_tsk_mgmt_t *p_srp_tsk_mgmt;
\r
808 SRP_ENTER( SRP_DBG_FUNC );
\r
810 cl_obj_lock( &p_hba->obj );
\r
812 p_srp_session = p_hba->session_list[p_srb->TargetId];
\r
813 if ( p_srp_session == NULL )
\r
815 /* If the session is NULL there is no connection and cannot be aborted */
\r
816 p_srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
\r
820 p_srb_send_descriptor = (srp_send_descriptor_t *)p_srb->NextSrb->SrbExtension;
\r
822 iu_tag = get_srp_information_unit_tag( (srp_information_unit_t *)p_srb_send_descriptor->data_segment );
\r
824 p_send_descriptor = srp_find_matching_send_descriptor( &p_srp_session->descriptors, iu_tag );
\r
825 if ( p_send_descriptor == NULL )
\r
827 /* Cannot find the command so it must have been completed */
\r
828 p_srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
\r
832 CL_ASSERT( p_srb_send_descriptor == p_send_descriptor );
\r
834 p_srb->NextSrb->SrbStatus = SRB_STATUS_ABORTED;
\r
836 /* create and send abort request to the VFx */
\r
838 srp_conn_info.vaddr = p_srp_session->hca.vaddr;
\r
839 srp_conn_info.lkey = p_srp_session->hca.lkey;
\r
840 srp_conn_info.rkey = p_srp_session->hca.rkey;
\r
842 srp_conn_info.init_to_targ_iu_sz = p_srp_session->connection.init_to_targ_iu_sz;
\r
843 srp_conn_info.max_scatter_gather_entries = p_srp_session->connection.max_scatter_gather_entries;
\r
844 srp_conn_info.tag = cl_atomic_inc( &p_srp_session->connection.tag );
\r
845 srp_conn_info.signal_send_completion =
\r
846 ((srp_conn_info.tag % p_srp_session->connection.signaled_send_completion_count) == 0) ? TRUE : FALSE;
\r
848 srp_build_send_descriptor( p_dev_ext, p_srb, &srp_conn_info );
\r
850 p_srp_tsk_mgmt = (srp_tsk_mgmt_t *)p_send_descriptor->data_segment;
\r
852 setup_srp_tsk_mgmt( p_srp_tsk_mgmt,
\r
853 p_send_descriptor->tag,
\r
854 BUILD_SCSI_ADDRESS( p_srb->TargetId, p_srb->Lun ),
\r
858 set_srp_tsk_mgmt_from_host_to_network( p_srp_tsk_mgmt );
\r
860 srp_post_io_request( p_dev_ext, p_srb );
\r
863 cl_obj_unlock( &p_hba->obj );
\r
864 if ( p_srb->SrbStatus == SRB_STATUS_ABORT_FAILED )
\r
866 SRP_TRACE( SRP_DBG_DEBUG,
\r
867 ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), Path = 0x%x, Target = 0x%x, Lun = 0x%x\n",
\r
868 g_srb_status_name[p_srb->SrbStatus],
\r
870 g_srb_function_name[p_srb->Function],
\r
875 StorPortNotification( RequestComplete, p_dev_ext, p_srb );
\r
878 SRP_EXIT( SRP_DBG_FUNC );
\r
883 IN PVOID p_dev_ext,
\r
884 IN OUT PSCSI_REQUEST_BLOCK p_srb )
\r
887 srp_hba_t *p_hba = ((srp_ext_t *)p_dev_ext)->p_hba;
\r
888 srp_session_t *p_srp_session;
\r
890 SRP_ENTER( SRP_DBG_FUNC );
\r
892 cl_obj_lock( &p_hba->obj );
\r
894 p_srp_session = p_hba->session_list[p_srb->TargetId];
\r
895 if ( p_srp_session != NULL )
\r
897 srp_send_descriptor_t *p_send_descriptor;
\r
898 UCHAR path_id = p_srb->PathId;
\r
899 UCHAR target_id = p_srb->TargetId;
\r
900 UCHAR lun = p_srb->Lun;
\r
902 StorPortPauseDevice( p_dev_ext, p_srb->PathId, p_srb->TargetId, p_srb->Lun, 10 );
\r
904 while ( (p_send_descriptor = srp_remove_lun_head_send_descriptor( &p_srp_session->descriptors, p_srb->Lun )) != NULL )
\r
906 SRP_TRACE( SRP_DBG_VERBOSE,
\r
907 ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%"PRIx64"\n",
\r
908 g_srb_status_name[SRB_STATUS_BUS_RESET],
\r
909 SRB_STATUS_BUS_RESET,
\r
910 g_srb_function_name[p_send_descriptor->p_srb->Function],
\r
911 p_send_descriptor->p_srb->Function,
\r
912 p_send_descriptor->p_srb->PathId,
\r
913 p_send_descriptor->p_srb->TargetId,
\r
914 p_send_descriptor->p_srb->Lun,
\r
915 get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );
\r
918 p_srb->SrbStatus = SRB_STATUS_SUCCESS;
\r
920 SRP_TRACE( SRP_DBG_DEBUG,
\r
921 ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), Path = 0x%x, Target = 0x%x, Lun = 0x%x\n",
\r
922 g_srb_status_name[p_srb->SrbStatus],
\r
924 g_srb_function_name[p_srb->Function],
\r
930 StorPortNotification( RequestComplete, p_dev_ext, p_srb );
\r
932 StorPortCompleteRequest( p_dev_ext, path_id, target_id, lun, SRB_STATUS_BUS_RESET );
\r
934 StorPortResumeDevice( p_dev_ext, path_id, target_id, lun );
\r
938 // Handle the error case here
\r
939 p_srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
\r
940 SRP_TRACE( SRP_DBG_DEBUG,
\r
941 ("Returning SrbStatus %s(0x%x) for Function = %s(0x%x), Path = 0x%x, Target = 0x%x, Lun = 0x%x\n",
\r
942 g_srb_status_name[p_srb->SrbStatus],
\r
944 g_srb_function_name[p_srb->Function],
\r
950 StorPortNotification( RequestComplete, p_dev_ext, p_srb );
\r
953 cl_obj_unlock( &p_hba->obj );
\r
955 SRP_EXIT( SRP_DBG_FUNC );
\r