removed Revison keyword since ID keyword exists, deleted unused files
[mirror/winof/.git] / ulp / srp / kernel / srp_descriptors.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 "srp_connection.h"\r
34 #include "srp_cmd.h"\r
35 #include "srp_data_path.h"\r
36 #include "srp_descriptors.h"\r
37 #include "srp_rsp.h"\r
38 #include "srp_session.h"\r
39 #include "srp_tsk_mgmt.h"\r
40 \r
41 /* __srp_create_recv_descriptors */\r
42 /*!\r
43 Creates the receive descriptors and posts them to the receive queue\r
44 \r
45 @param p_descriptors    - pointer to the work requests structure\r
46 @param h_pd             - protection domain used for registration of memory\r
47 @param h_qp             - queue pair used to post work requests\r
48 \r
49 @return - result of operations\r
50 */\r
51 static ib_api_status_t\r
52 __srp_create_recv_descriptors(\r
53         IN      OUT                     srp_descriptors_t                       *p_descriptors,\r
54         IN                              ib_al_ifc_t* const                      p_ifc,\r
55         IN                              ib_pd_handle_t                          h_pd,\r
56         IN                              ib_qp_handle_t                          h_qp )\r
57 {\r
58         ib_api_status_t         status = IB_SUCCESS;\r
59         srp_recv_descriptor_t   *p_descriptor;\r
60         uint8_t                 *p_data_segment;\r
61         ib_mr_create_t          mr_create;\r
62         uint32_t                i;\r
63 \r
64         SRP_ENTER( SRP_DBG_PNP );\r
65 \r
66         /* Create the array of recv descriptors */\r
67         p_descriptors->p_recv_descriptors_array =\r
68                 (srp_recv_descriptor_t *)cl_zalloc( p_descriptors->recv_descriptor_count * sizeof(srp_recv_descriptor_t) );\r
69         if ( p_descriptors->p_recv_descriptors_array == NULL )\r
70         {\r
71                 SRP_TRACE( SRP_DBG_ERROR,\r
72                         ("Failed to allocate %d recv descriptors.\n",  p_descriptors->recv_descriptor_count) );\r
73                 status = IB_INSUFFICIENT_MEMORY;\r
74                 goto exit;\r
75         }\r
76 \r
77         /* Create the array of recv data segments */\r
78         p_descriptors->p_recv_data_segments_array =\r
79                 cl_zalloc( p_descriptors->recv_descriptor_count * p_descriptors->recv_data_segment_size );\r
80         if ( p_descriptors->p_recv_data_segments_array == NULL )\r
81         {\r
82                 SRP_TRACE( SRP_DBG_ERROR,\r
83                         ("Failed to allocate %d recv data segments of %d length.\n",\r
84                         p_descriptors->recv_descriptor_count,\r
85                         p_descriptors->recv_data_segment_size) );\r
86 \r
87                 cl_free( p_descriptors->p_recv_descriptors_array );\r
88                 p_descriptors->p_recv_descriptors_array = NULL;\r
89                 status = IB_INSUFFICIENT_MEMORY;\r
90                 goto exit;\r
91         }\r
92 \r
93         /* Register the data segments array memory */\r
94         mr_create.vaddr = p_descriptors->p_recv_data_segments_array;\r
95         mr_create.length = p_descriptors->recv_descriptor_count * p_descriptors->recv_data_segment_size;\r
96         mr_create.access_ctrl = IB_AC_LOCAL_WRITE;\r
97 \r
98         status = p_ifc->reg_mem( h_pd,\r
99                                                  &mr_create,\r
100                                                  &p_descriptors->recv_lkey,\r
101                                                  &p_descriptors->recv_rkey,\r
102                                                  &p_descriptors->h_recv_mr );\r
103         if ( status != IB_SUCCESS )\r
104         {\r
105                 SRP_TRACE( SRP_DBG_ERROR,\r
106                         ("Failed to register recv data segments. Status = %d.\n", status) );\r
107 \r
108                 cl_free( p_descriptors->p_recv_data_segments_array );\r
109                 p_descriptors->p_recv_data_segments_array = NULL;\r
110 \r
111                 cl_free( p_descriptors->p_recv_descriptors_array );\r
112                 p_descriptors->p_recv_descriptors_array = NULL;\r
113                 goto exit;\r
114         }\r
115 \r
116         /* Initialize them and post to receive queue */\r
117         p_descriptor = p_descriptors->p_recv_descriptors_array;\r
118         p_data_segment = p_descriptors->p_recv_data_segments_array;\r
119 \r
120         for ( i = 0; i < p_descriptors->recv_descriptor_count; i++ )\r
121         {\r
122                 p_descriptor->wr.p_next = NULL;\r
123                 p_descriptor->wr.wr_id = (uint64_t)((void* __ptr64)p_descriptor);\r
124                 p_descriptor->wr.num_ds = 1;\r
125                 p_descriptor->wr.ds_array = p_descriptor->ds;\r
126 \r
127                 p_descriptor->ds[0].vaddr = (uint64_t)((void* __ptr64)p_data_segment);\r
128                 p_descriptor->ds[0].length = p_descriptors->recv_data_segment_size;\r
129                 p_descriptor->ds[0].lkey = p_descriptors->recv_lkey;\r
130 \r
131                 p_descriptors->p_recv_descriptors_array[i].p_data_segment = p_data_segment;\r
132 \r
133                 status = p_ifc->post_recv( h_qp, &p_descriptor->wr, NULL );\r
134                 if ( status != IB_SUCCESS )\r
135                 {\r
136                         SRP_TRACE( SRP_DBG_ERROR,\r
137                                 ("Failed to post send descriptor. Status = %d.\n", status) );\r
138                         goto exit;\r
139                 }\r
140 \r
141                 p_descriptor++;\r
142                 p_data_segment += p_descriptors->recv_data_segment_size;\r
143         }\r
144 \r
145 exit:\r
146         SRP_EXIT( SRP_DBG_PNP );\r
147 \r
148         return ( status );\r
149 }\r
150 \r
151 /* srp_init_descriptors */\r
152 /*!\r
153 Orchestrates creation of receive descriptor buffers and sent list\r
154 \r
155 @param p_descriptors          - pointer to the descriptors structure\r
156 @param recv descriptor_count  - number of receive descriptors to create\r
157 @param recv data_segment_size - size of each receive descriptor's data area\r
158 @param h_pd                   - protection domain used for registration of memory\r
159 @param h_qp                   - queue pair used to post work requests\r
160 \r
161 @return - result of operations\r
162 */\r
163 ib_api_status_t\r
164 srp_init_descriptors(\r
165         IN      OUT                     srp_descriptors_t                       *p_descriptors,\r
166         IN                              uint32_t                                        recv_descriptor_count,\r
167         IN                              uint32_t                                        recv_data_segment_size,\r
168         IN                              ib_al_ifc_t* const                      p_ifc,\r
169         IN                              ib_pd_handle_t                          h_pd,\r
170         IN                              ib_qp_handle_t                          h_qp )\r
171 {\r
172         ib_api_status_t status;\r
173 \r
174         SRP_ENTER( SRP_DBG_PNP );\r
175 \r
176         CL_ASSERT( p_descriptors != NULL );\r
177 \r
178         cl_memclr( p_descriptors, sizeof(*p_descriptors) );\r
179 \r
180         cl_spinlock_init ( &p_descriptors->sent_list_lock );\r
181         cl_qlist_init( &p_descriptors->sent_descriptors );\r
182 \r
183         p_descriptors->initialized = TRUE;\r
184 \r
185         p_descriptors->recv_descriptor_count = recv_descriptor_count;\r
186         p_descriptors->recv_data_segment_size = recv_data_segment_size;\r
187 \r
188         status = __srp_create_recv_descriptors( p_descriptors, p_ifc, h_pd, h_qp );\r
189         if ( status != IB_SUCCESS )\r
190         {\r
191                 srp_destroy_descriptors( p_descriptors );\r
192         }\r
193 \r
194         SRP_EXIT( SRP_DBG_PNP );\r
195 \r
196         return ( status );\r
197 }\r
198 \r
199 /* srp_destroy_descriptors */\r
200 /*!\r
201 Destroys the receive work request buffers\r
202 \r
203 @param p_descriptors - pointer to the descriptors structure\r
204 \r
205 @return - result of operations\r
206 */\r
207 ib_api_status_t\r
208 srp_destroy_descriptors(\r
209         IN OUT  srp_descriptors_t   *p_descriptors )\r
210 {\r
211         SRP_ENTER( SRP_DBG_PNP );\r
212 \r
213         if ( p_descriptors->initialized == TRUE )\r
214         {\r
215                 cl_spinlock_destroy ( &p_descriptors->sent_list_lock );\r
216 \r
217                 if ( p_descriptors->p_recv_data_segments_array != NULL )\r
218                 {\r
219                         cl_free( p_descriptors->p_recv_data_segments_array );\r
220                 }\r
221 \r
222                 if ( p_descriptors->p_recv_descriptors_array != NULL )\r
223                 {\r
224                         cl_free( p_descriptors->p_recv_descriptors_array );\r
225                 }\r
226 \r
227                 cl_memclr( p_descriptors, sizeof( *p_descriptors ) );\r
228         }\r
229 \r
230         SRP_EXIT( SRP_DBG_PNP );\r
231 \r
232         return IB_SUCCESS;\r
233 }\r
234 \r
235 /* srp_add_send_descriptor */\r
236 /*!\r
237 Puts send descriptor at tail of the sent list\r
238 \r
239 @param p_descriptors - pointer to the descriptors structure\r
240 @param p_descriptor  - pointer to the descriptor to add\r
241 \r
242 @return - none\r
243 */\r
244 inline\r
245 void\r
246 srp_add_send_descriptor(\r
247         IN  srp_descriptors_t       *p_descriptors,\r
248         IN  srp_send_descriptor_t   *p_descriptor )\r
249 {\r
250         SRP_ENTER( SRP_DBG_FUNC );\r
251 \r
252         cl_spinlock_acquire ( &p_descriptors->sent_list_lock );\r
253 \r
254         cl_qlist_insert_tail( &p_descriptors->sent_descriptors, &p_descriptor->list_item );\r
255         CL_ASSERT( &p_descriptors->sent_descriptors == p_descriptor->list_item.p_list );\r
256 \r
257         cl_spinlock_release ( &p_descriptors->sent_list_lock );\r
258 \r
259         SRP_EXIT( SRP_DBG_FUNC );\r
260 }\r
261 \r
262 /* srp_remove_send_descriptor */\r
263 /*!\r
264 Removes send descriptor from the sent list\r
265 \r
266 @param p_descriptors - pointer to the descriptors structure\r
267 @param p_descriptor  - pointer to the descriptor to add\r
268 \r
269 @return - none\r
270 */\r
271 inline\r
272 void\r
273 srp_remove_send_descriptor(\r
274         IN  srp_descriptors_t       *p_descriptors,\r
275         IN  srp_send_descriptor_t   *p_descriptor )\r
276 {\r
277         SRP_ENTER( SRP_DBG_FUNC );\r
278 \r
279         cl_spinlock_acquire ( &p_descriptors->sent_list_lock );\r
280 \r
281         CL_ASSERT( &p_descriptors->sent_descriptors == p_descriptor->list_item.p_list );\r
282         cl_qlist_remove_item( &p_descriptors->sent_descriptors, &p_descriptor->list_item );\r
283 \r
284         cl_spinlock_release ( &p_descriptors->sent_list_lock );\r
285 \r
286         SRP_EXIT( SRP_DBG_FUNC );\r
287 }\r
288 \r
289 /* srp_remove_lun_head_send_descriptor */\r
290 /*!\r
291 Removes and returns the send descriptor from the head of the sent list for the lun specified\r
292 \r
293 @param p_descriptors - pointer to the descriptors structure\r
294 @param lun           - lun for which to remove head send descriptor\r
295 \r
296 @return - srp_send_descriptor at head of sent list or NULL if empty\r
297 */\r
298 srp_send_descriptor_t*\r
299 srp_remove_lun_head_send_descriptor(\r
300         IN      srp_descriptors_t       *p_descriptors,\r
301         IN      UCHAR                   lun )\r
302 {\r
303         srp_send_descriptor_t   *p_descriptor;\r
304 \r
305         SRP_ENTER( SRP_DBG_FUNC );\r
306 \r
307         cl_spinlock_acquire ( &p_descriptors->sent_list_lock );\r
308 \r
309         p_descriptor = (srp_send_descriptor_t *)cl_qlist_head( &p_descriptors->sent_descriptors );\r
310         CL_ASSERT( &p_descriptors->sent_descriptors == p_descriptor->list_item.p_list );\r
311 \r
312         while ( p_descriptor != (srp_send_descriptor_t *)cl_qlist_end( &p_descriptors->sent_descriptors ) )\r
313         {\r
314                 if ( p_descriptor->p_srb->Lun == lun )\r
315                 {\r
316                         CL_ASSERT( &p_descriptors->sent_descriptors == p_descriptor->list_item.p_list );\r
317                         cl_qlist_remove_item( &p_descriptors->sent_descriptors, &p_descriptor->list_item );\r
318                         break;\r
319                 }\r
320 \r
321                 p_descriptor = (srp_send_descriptor_t *)cl_qlist_next( &p_descriptor->list_item );\r
322                 CL_ASSERT( &p_descriptors->sent_descriptors == p_descriptor->list_item.p_list );\r
323         }\r
324 \r
325         if ( p_descriptor == (srp_send_descriptor_t *)cl_qlist_end( &p_descriptors->sent_descriptors ) )\r
326         {\r
327                 p_descriptor = NULL;\r
328         }\r
329 \r
330         cl_spinlock_release ( &p_descriptors->sent_list_lock );\r
331 \r
332         SRP_EXIT( SRP_DBG_FUNC );\r
333 \r
334         return ( p_descriptor );\r
335 }\r
336 \r
337 /* srp_post_send_descriptor */\r
338 /*!\r
339 Posts send descriptor across the connection specified and\r
340 if successful add it to the sent descriptors list\r
341 \r
342 @param p_descriptors - pointer to the descriptors structure\r
343 @param p_descriptor  - pointer to the descriptor to send\r
344 @param p_session     - pointer to the session used to send\r
345 \r
346 @return - result of post operation, or IB_ERROR if not connected\r
347 */\r
348 ib_api_status_t\r
349 srp_post_send_descriptor(\r
350         IN                              srp_descriptors_t                       *p_descriptors,\r
351         IN                              srp_send_descriptor_t           *p_descriptor,\r
352         IN                              srp_session_t                           *p_session )\r
353 {\r
354         ib_api_status_t         status = IB_ERROR;\r
355         srp_connection_t        *p_connection;\r
356         ib_al_ifc_t                     *p_ifc;\r
357 \r
358         SRP_ENTER( SRP_DBG_FUNC );\r
359 \r
360         p_connection = &p_session->connection;\r
361         p_ifc = &p_session->hca.p_hba->ifc;\r
362 \r
363         if ( p_connection->state == SRP_CONNECTED )\r
364         {\r
365                 SRP_TRACE( SRP_DBG_VERBOSE, ("wr_id    = 0x%"PRIx64".\n", p_descriptor->wr.wr_id) );\r
366                 SRP_TRACE( SRP_DBG_VERBOSE, ("wr_type  = 0x%x.\n", p_descriptor->wr.wr_type) );\r
367                 SRP_TRACE( SRP_DBG_VERBOSE, ("send_opt = 0x%x.\n", p_descriptor->wr.send_opt) );\r
368                 SRP_TRACE( SRP_DBG_VERBOSE, ("num_ds   = 0x%x.\n", p_descriptor->wr.num_ds) );\r
369 \r
370                 SRP_TRACE( SRP_DBG_VERBOSE,\r
371                                    ("Posting  I/O for Function = %s(0x%x), Path = 0x%x, Target = 0x%x, Lun = 0x%x, tag 0x%"PRIx64"\n",\r
372                                    g_srb_function_name[p_descriptor->p_srb->Function],\r
373                                    p_descriptor->p_srb->Function,\r
374                                    p_descriptor->p_srb->PathId,\r
375                                    p_descriptor->p_srb->TargetId,\r
376                                    p_descriptor->p_srb->Lun,\r
377                                    get_srp_command_tag( (srp_cmd_t *)p_descriptor->data_segment )) );\r
378 \r
379                 if ( get_srp_iu_buffer_type( (srp_iu_buffer_t *)p_descriptor->data_segment ) == SRP_CMD )\r
380                 {\r
381                         p_descriptor->ds[0].length = get_srp_command_length( (srp_cmd_t *)p_descriptor->data_segment );\r
382                 }\r
383                 else /* task type */\r
384                 {\r
385                         p_descriptor->ds[0].length = get_srp_tsk_mgmt_length( (srp_tsk_mgmt_t *)p_descriptor->data_segment );\r
386                 }\r
387 \r
388                 srp_add_send_descriptor( p_descriptors, p_descriptor );\r
389 \r
390                 status = p_ifc->post_send(\r
391                         p_connection->h_qp, &p_descriptor->wr, NULL );\r
392                 if ( status != IB_SUCCESS )\r
393                 {\r
394                         /* Remove From Sent List */\r
395                         srp_remove_send_descriptor( p_descriptors, p_descriptor );\r
396                         SRP_TRACE( SRP_DBG_ERROR,\r
397                                                 ("Failed to post send descriptor. ib_post_send status = 0x%x tag = 0x%"PRIx64"\n",\r
398                                                 status,\r
399                                                 get_srp_command_tag( (srp_cmd_t *)p_descriptor->data_segment )) );\r
400                 }\r
401         }\r
402         else\r
403         {\r
404                 SRP_TRACE( SRP_DBG_ERROR,\r
405                         ("Attempting to post to an unconnected session.\n") );\r
406         }\r
407 \r
408         SRP_EXIT( SRP_DBG_FUNC );\r
409 \r
410         return ( status );\r
411 }\r
412 \r
413 /* srp_find_matching_send_descriptor */\r
414 /*!\r
415 Given a received response find the matching send descriptor\r
416 which originated the request to the VFx and remove it from\r
417 the sent descriptor list\r
418 \r
419 @param p_descriptors - pointer to the descriptors structure\r
420 @param tag           - tag of descriptor to find\r
421 \r
422 @return - pointer to send descriptor or NULL if not found\r
423 */\r
424 srp_send_descriptor_t*\r
425 srp_find_matching_send_descriptor(\r
426         IN      srp_descriptors_t   *p_descriptors,\r
427         IN      uint64_t            tag )\r
428 {\r
429         srp_send_descriptor_t   *p_send_descriptor;\r
430 \r
431         SRP_ENTER( SRP_DBG_FUNC );\r
432 \r
433         cl_spinlock_acquire( &p_descriptors->sent_list_lock );\r
434 \r
435         p_send_descriptor = (srp_send_descriptor_t *)cl_qlist_head( &p_descriptors->sent_descriptors );\r
436         CL_ASSERT( &p_descriptors->sent_descriptors == p_send_descriptor->list_item.p_list );\r
437 \r
438         SRP_TRACE( SRP_DBG_VERBOSE, ("rsp tag = 0x%"PRIx64".\n", tag) );\r
439 \r
440         while ( p_send_descriptor != (srp_send_descriptor_t *)cl_qlist_end( &p_descriptors->sent_descriptors ) )\r
441         {\r
442                 SRP_TRACE( SRP_DBG_VERBOSE, ("cmd tag = 0x%"PRIx64".\n",\r
443                         get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );\r
444 \r
445                 if ( get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment ) == tag )\r
446                 {\r
447                         CL_ASSERT( &p_descriptors->sent_descriptors == p_send_descriptor->list_item.p_list );\r
448                         cl_qlist_remove_item( &p_descriptors->sent_descriptors, &p_send_descriptor->list_item );\r
449                         goto exit;\r
450                 }\r
451 \r
452                 p_send_descriptor = (srp_send_descriptor_t *)cl_qlist_next( &p_send_descriptor->list_item );\r
453         }\r
454 \r
455         /* This is not an error. The request may have been aborted */\r
456         p_send_descriptor = NULL;\r
457 \r
458 exit:\r
459         cl_spinlock_release( &p_descriptors->sent_list_lock );\r
460 \r
461         SRP_EXIT( SRP_DBG_FUNC );\r
462 \r
463         return ( p_send_descriptor );\r
464 }\r
465 \r
466 /* srp_build_send_descriptor */\r
467 /*!\r
468 Initializes a send descriptor's fields\r
469 \r
470 @param p_dev_ext       - our context pointer\r
471 @param p_srb           - scsi request to send to target\r
472 @param p_srp_conn_info - information about our connection to the VFx\r
473 \r
474 @return - none\r
475 */\r
476 void\r
477 srp_build_send_descriptor(\r
478         IN      PVOID               p_dev_ext,\r
479         IN OUT  PSCSI_REQUEST_BLOCK p_srb,\r
480         IN      p_srp_conn_info_t   p_srp_conn_info )\r
481 {\r
482         srp_send_descriptor_t   *p_send_descriptor = (srp_send_descriptor_t *)p_srb->SrbExtension;\r
483         STOR_PHYSICAL_ADDRESS   physical_address;\r
484         ULONG                   length;\r
485 \r
486         SRP_ENTER( SRP_DBG_FUNC );\r
487 \r
488         cl_memclr( p_send_descriptor, (sizeof ( srp_send_descriptor_t ) - SRP_MAX_IU_SIZE) );\r
489 \r
490         physical_address = StorPortGetPhysicalAddress( p_dev_ext, p_srb, p_send_descriptor->data_segment, &length );\r
491 \r
492         p_send_descriptor->wr.wr_id = (uint64_t)((uintn_t)p_send_descriptor);\r
493         p_send_descriptor->wr.wr_type = WR_SEND;\r
494         p_send_descriptor->wr.send_opt = (p_srp_conn_info->signal_send_completion == TRUE) ? IB_SEND_OPT_SIGNALED : 0;\r
495         p_send_descriptor->wr.num_ds = 1;\r
496         p_send_descriptor->wr.ds_array = p_send_descriptor->ds;\r
497         p_send_descriptor->tag = p_srp_conn_info->tag;\r
498         p_send_descriptor->p_srb = p_srb;\r
499         p_send_descriptor->ds[0].vaddr = p_srp_conn_info->vaddr + physical_address.QuadPart;\r
500         p_send_descriptor->ds[0].length =  p_srp_conn_info->init_to_targ_iu_sz;\r
501         p_send_descriptor->ds[0].lkey =   p_srp_conn_info->lkey;\r
502 \r
503         SRP_TRACE( SRP_DBG_VERBOSE, ("hca vaddr        = 0x%"PRIx64".\n", p_srp_conn_info->vaddr));\r
504         SRP_TRACE( SRP_DBG_VERBOSE, ("physical_address = 0x%"PRIx64".\n", physical_address.QuadPart));\r
505         SRP_TRACE( SRP_DBG_VERBOSE, ("IU  vaddr        = 0x%"PRIx64".\n", p_send_descriptor->ds[0].vaddr));\r
506         SRP_TRACE( SRP_DBG_VERBOSE, ("length           = %d.\n",          p_send_descriptor->ds[0].length));\r
507         SRP_TRACE( SRP_DBG_VERBOSE, ("lkey             = 0x%x.\n",        p_send_descriptor->ds[0].lkey));\r
508 \r
509         SRP_EXIT( SRP_DBG_FUNC );\r
510 }\r