81cb0e96710e4662e156292f7d03275bf80066cd
[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                 ASSERT( p_descriptor->ds[0].length <= p_connection->init_to_targ_iu_sz );\r
389 \r
390                 srp_add_send_descriptor( p_descriptors, p_descriptor );\r
391 \r
392                 status = p_ifc->post_send(\r
393                         p_connection->h_qp, &p_descriptor->wr, NULL );\r
394                 if ( status != IB_SUCCESS )\r
395                 {\r
396                         /* Remove From Sent List */\r
397                         srp_remove_send_descriptor( p_descriptors, p_descriptor );\r
398                         SRP_TRACE( SRP_DBG_ERROR,\r
399                                                 ("Failed to post send descriptor. ib_post_send status = 0x%x tag = 0x%"PRIx64"\n",\r
400                                                 status,\r
401                                                 get_srp_command_tag( (srp_cmd_t *)p_descriptor->data_segment )) );\r
402                 }\r
403         }\r
404         else\r
405         {\r
406                 SRP_TRACE( SRP_DBG_ERROR,\r
407                         ("Attempting to post to an unconnected session.\n") );\r
408         }\r
409 \r
410         SRP_EXIT( SRP_DBG_FUNC );\r
411 \r
412         return ( status );\r
413 }\r
414 \r
415 /* srp_find_matching_send_descriptor */\r
416 /*!\r
417 Given a received response find the matching send descriptor\r
418 which originated the request to the VFx and remove it from\r
419 the sent descriptor list\r
420 \r
421 @param p_descriptors - pointer to the descriptors structure\r
422 @param tag           - tag of descriptor to find\r
423 \r
424 @return - pointer to send descriptor or NULL if not found\r
425 */\r
426 srp_send_descriptor_t*\r
427 srp_find_matching_send_descriptor(\r
428         IN      srp_descriptors_t   *p_descriptors,\r
429         IN      uint64_t            tag )\r
430 {\r
431         srp_send_descriptor_t   *p_send_descriptor;\r
432 \r
433         SRP_ENTER( SRP_DBG_FUNC );\r
434 \r
435         cl_spinlock_acquire( &p_descriptors->sent_list_lock );\r
436 \r
437         p_send_descriptor = (srp_send_descriptor_t *)cl_qlist_head( &p_descriptors->sent_descriptors );\r
438         CL_ASSERT( &p_descriptors->sent_descriptors == p_send_descriptor->list_item.p_list );\r
439 \r
440         SRP_TRACE( SRP_DBG_VERBOSE, ("rsp tag = 0x%"PRIx64".\n", tag) );\r
441 \r
442         while ( p_send_descriptor != (srp_send_descriptor_t *)cl_qlist_end( &p_descriptors->sent_descriptors ) )\r
443         {\r
444                 SRP_TRACE( SRP_DBG_VERBOSE, ("cmd tag = 0x%"PRIx64".\n",\r
445                         get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment )) );\r
446 \r
447                 if ( get_srp_command_tag( (srp_cmd_t *)p_send_descriptor->data_segment ) == tag )\r
448                 {\r
449                         CL_ASSERT( &p_descriptors->sent_descriptors == p_send_descriptor->list_item.p_list );\r
450                         cl_qlist_remove_item( &p_descriptors->sent_descriptors, &p_send_descriptor->list_item );\r
451                         goto exit;\r
452                 }\r
453 \r
454                 p_send_descriptor = (srp_send_descriptor_t *)cl_qlist_next( &p_send_descriptor->list_item );\r
455         }\r
456 \r
457         /* This is not an error. The request may have been aborted */\r
458         p_send_descriptor = NULL;\r
459 \r
460 exit:\r
461         cl_spinlock_release( &p_descriptors->sent_list_lock );\r
462 \r
463         SRP_EXIT( SRP_DBG_FUNC );\r
464 \r
465         return ( p_send_descriptor );\r
466 }\r
467 \r
468 /* srp_build_send_descriptor */\r
469 /*!\r
470 Initializes a send descriptor's fields\r
471 \r
472 @param p_dev_ext       - our context pointer\r
473 @param p_srb           - scsi request to send to target\r
474 @param p_srp_conn_info - information about our connection to the VFx\r
475 \r
476 @return - none\r
477 */\r
478 void\r
479 srp_build_send_descriptor(\r
480         IN      PVOID               p_dev_ext,\r
481         IN OUT  PSCSI_REQUEST_BLOCK p_srb,\r
482         IN      p_srp_conn_info_t   p_srp_conn_info )\r
483 {\r
484         srp_send_descriptor_t   *p_send_descriptor = (srp_send_descriptor_t *)p_srb->SrbExtension;\r
485         STOR_PHYSICAL_ADDRESS   physical_address;\r
486         ULONG                   length;\r
487 \r
488         SRP_ENTER( SRP_DBG_FUNC );\r
489 \r
490         cl_memclr( p_send_descriptor, (sizeof ( srp_send_descriptor_t ) - SRP_MAX_IU_SIZE) );\r
491 \r
492         physical_address = StorPortGetPhysicalAddress( p_dev_ext, p_srb, p_send_descriptor->data_segment, &length );\r
493 \r
494         p_send_descriptor->wr.wr_id = (uint64_t)((uintn_t)p_send_descriptor);\r
495         p_send_descriptor->wr.wr_type = WR_SEND;\r
496         p_send_descriptor->wr.send_opt = (p_srp_conn_info->signal_send_completion == TRUE) ? IB_SEND_OPT_SIGNALED : 0;\r
497         p_send_descriptor->wr.num_ds = 1;\r
498         p_send_descriptor->wr.ds_array = p_send_descriptor->ds;\r
499         p_send_descriptor->tag = p_srp_conn_info->tag;\r
500         p_send_descriptor->p_srb = p_srb;\r
501         p_send_descriptor->ds[0].vaddr = p_srp_conn_info->vaddr + physical_address.QuadPart;\r
502         p_send_descriptor->ds[0].length =  p_srp_conn_info->init_to_targ_iu_sz;\r
503         p_send_descriptor->ds[0].lkey =   p_srp_conn_info->lkey;\r
504 \r
505         SRP_TRACE( SRP_DBG_VERBOSE, ("hca vaddr        = 0x%"PRIx64".\n", p_srp_conn_info->vaddr));\r
506         SRP_TRACE( SRP_DBG_VERBOSE, ("physical_address = 0x%"PRIx64".\n", physical_address.QuadPart));\r
507         SRP_TRACE( SRP_DBG_VERBOSE, ("IU  vaddr        = 0x%"PRIx64".\n", p_send_descriptor->ds[0].vaddr));\r
508         SRP_TRACE( SRP_DBG_VERBOSE, ("length           = %d.\n",          p_send_descriptor->ds[0].length));\r
509         SRP_TRACE( SRP_DBG_VERBOSE, ("lkey             = 0x%x.\n",        p_send_descriptor->ds[0].lkey));\r
510 \r
511         SRP_EXIT( SRP_DBG_FUNC );\r
512 }\r