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