Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / net / infiniband / ib_srp.c
1 /*
2  * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  *   Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  *   Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 FILE_LICENCE ( BSD2 );
32
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <ipxe/interface.h>
36 #include <ipxe/uri.h>
37 #include <ipxe/open.h>
38 #include <ipxe/base16.h>
39 #include <ipxe/acpi.h>
40 #include <ipxe/srp.h>
41 #include <ipxe/infiniband.h>
42 #include <ipxe/ib_cmrc.h>
43 #include <ipxe/ib_srp.h>
44
45 /**
46  * @file
47  *
48  * SCSI RDMA Protocol over Infiniband
49  *
50  */
51
52 /* Disambiguate the various possible EINVALs */
53 #define EINVAL_BYTE_STRING_LEN __einfo_error ( EINFO_EINVAL_BYTE_STRING_LEN )
54 #define EINFO_EINVAL_BYTE_STRING_LEN __einfo_uniqify \
55         ( EINFO_EINVAL, 0x01, "Invalid byte string length" )
56 #define EINVAL_INTEGER __einfo_error ( EINFO_EINVAL_INTEGER )
57 #define EINFO_EINVAL_INTEGER __einfo_uniqify \
58         ( EINFO_EINVAL, 0x03, "Invalid integer" )
59 #define EINVAL_RP_TOO_SHORT __einfo_error ( EINFO_EINVAL_RP_TOO_SHORT )
60 #define EINFO_EINVAL_RP_TOO_SHORT __einfo_uniqify \
61         ( EINFO_EINVAL, 0x04, "Root path too short" )
62
63 /******************************************************************************
64  *
65  * IB SRP devices
66  *
67  ******************************************************************************
68  */
69
70 /** An Infiniband SRP device */
71 struct ib_srp_device {
72         /** Reference count */
73         struct refcnt refcnt;
74
75         /** SRP transport interface */
76         struct interface srp;
77         /** CMRC interface */
78         struct interface cmrc;
79
80         /** Infiniband device */
81         struct ib_device *ibdev;
82
83         /** Destination GID (for boot firmware table) */
84         union ib_gid dgid;
85         /** Service ID (for boot firmware table) */
86         union ib_guid service_id;
87 };
88
89 /**
90  * Free IB SRP device
91  *
92  * @v refcnt            Reference count
93  */
94 static void ib_srp_free ( struct refcnt *refcnt ) {
95         struct ib_srp_device *ib_srp =
96                 container_of ( refcnt, struct ib_srp_device, refcnt );
97
98         ibdev_put ( ib_srp->ibdev );
99         free ( ib_srp );
100 }
101
102 /**
103  * Close IB SRP device
104  *
105  * @v ib_srp            IB SRP device
106  * @v rc                Reason for close
107  */
108 static void ib_srp_close ( struct ib_srp_device *ib_srp, int rc ) {
109
110         /* Shut down interfaces */
111         intf_shutdown ( &ib_srp->cmrc, rc );
112         intf_shutdown ( &ib_srp->srp, rc );
113 }
114
115 /**
116  * Describe IB SRP device in an ACPI table
117  *
118  * @v srpdev            SRP device
119  * @v acpi              ACPI table
120  * @v len               Length of ACPI table
121  * @ret rc              Return status code
122  */
123 static int ib_srp_describe ( struct ib_srp_device *ib_srp,
124                              struct acpi_description_header *acpi,
125                              size_t len ) {
126         struct ib_device *ibdev = ib_srp->ibdev;
127         struct sbft_table *sbft =
128                 container_of ( acpi, struct sbft_table, acpi );
129         struct sbft_ib_subtable *ib_sbft;
130         size_t used;
131
132         /* Sanity check */
133         if ( acpi->signature != SBFT_SIG )
134                 return -EINVAL;
135
136         /* Append IB subtable to existing table */
137         used = le32_to_cpu ( sbft->acpi.length );
138         sbft->ib_offset = cpu_to_le16 ( used );
139         ib_sbft = ( ( ( void * ) sbft ) + used );
140         used += sizeof ( *ib_sbft );
141         if ( used > len )
142                 return -ENOBUFS;
143         sbft->acpi.length = cpu_to_le32 ( used );
144
145         /* Populate subtable */
146         memcpy ( &ib_sbft->sgid, &ibdev->gid, sizeof ( ib_sbft->sgid ) );
147         memcpy ( &ib_sbft->dgid, &ib_srp->dgid, sizeof ( ib_sbft->dgid ) );
148         memcpy ( &ib_sbft->service_id, &ib_srp->service_id,
149                  sizeof ( ib_sbft->service_id ) );
150         ib_sbft->pkey = cpu_to_le16 ( ibdev->pkey );
151
152         return 0;
153 }
154
155 /** IB SRP CMRC interface operations */
156 static struct interface_operation ib_srp_cmrc_op[] = {
157         INTF_OP ( intf_close, struct ib_srp_device *, ib_srp_close ),
158 };
159
160 /** IB SRP CMRC interface descriptor */
161 static struct interface_descriptor ib_srp_cmrc_desc =
162         INTF_DESC_PASSTHRU ( struct ib_srp_device, cmrc, ib_srp_cmrc_op, srp );
163
164 /** IB SRP SRP interface operations */
165 static struct interface_operation ib_srp_srp_op[] = {
166         INTF_OP ( acpi_describe, struct ib_srp_device *, ib_srp_describe ),
167         INTF_OP ( intf_close, struct ib_srp_device *, ib_srp_close ),
168 };
169
170 /** IB SRP SRP interface descriptor */
171 static struct interface_descriptor ib_srp_srp_desc =
172         INTF_DESC_PASSTHRU ( struct ib_srp_device, srp, ib_srp_srp_op, cmrc );
173
174 /**
175  * Open IB SRP device
176  *
177  * @v block             Block control interface
178  * @v ibdev             Infiniband device
179  * @v dgid              Destination GID
180  * @v service_id        Service ID
181  * @v initiator         Initiator port ID
182  * @v target            Target port ID
183  * @v lun               SCSI LUN
184  * @ret rc              Return status code
185  */
186 static int ib_srp_open ( struct interface *block, struct ib_device *ibdev,
187                          union ib_gid *dgid, union ib_guid *service_id,
188                          union srp_port_id *initiator,
189                          union srp_port_id *target, struct scsi_lun *lun ) {
190         struct ib_srp_device *ib_srp;
191         int rc;
192
193         /* Allocate and initialise structure */
194         ib_srp = zalloc ( sizeof ( *ib_srp ) );
195         if ( ! ib_srp ) {
196                 rc = -ENOMEM;
197                 goto err_zalloc;
198         }
199         ref_init ( &ib_srp->refcnt, ib_srp_free );
200         intf_init ( &ib_srp->srp, &ib_srp_srp_desc, &ib_srp->refcnt );
201         intf_init ( &ib_srp->cmrc, &ib_srp_cmrc_desc, &ib_srp->refcnt );
202         ib_srp->ibdev = ibdev_get ( ibdev );
203         DBGC ( ib_srp, "IBSRP %p for " IB_GID_FMT " " IB_GUID_FMT "\n",
204                ib_srp, IB_GID_ARGS ( dgid ), IB_GUID_ARGS ( service_id ) );
205
206         /* Preserve parameters required for boot firmware table */
207         memcpy ( &ib_srp->dgid, dgid, sizeof ( ib_srp->dgid ) );
208         memcpy ( &ib_srp->service_id, service_id,
209                  sizeof ( ib_srp->service_id ) );
210
211         /* Open CMRC socket */
212         if ( ( rc = ib_cmrc_open ( &ib_srp->cmrc, ibdev, dgid,
213                                    service_id ) ) != 0 ) {
214                 DBGC ( ib_srp, "IBSRP %p could not open CMRC socket: %s\n",
215                        ib_srp, strerror ( rc ) );
216                 goto err_cmrc_open;
217         }
218
219         /* Attach SRP device to parent interface */
220         if ( ( rc = srp_open ( block, &ib_srp->srp, initiator, target,
221                                ibdev->rdma_key, lun ) ) != 0 ) {
222                 DBGC ( ib_srp, "IBSRP %p could not create SRP device: %s\n",
223                        ib_srp, strerror ( rc ) );
224                 goto err_srp_open;
225         }
226
227         /* Mortalise self and return */
228         ref_put ( &ib_srp->refcnt );
229         return 0;
230
231  err_srp_open:
232  err_cmrc_open:
233         ib_srp_close ( ib_srp, rc );
234         ref_put ( &ib_srp->refcnt );
235  err_zalloc:
236         return rc;
237 }
238
239 /******************************************************************************
240  *
241  * IB SRP URIs
242  *
243  ******************************************************************************
244  */
245
246 /** IB SRP parse flags */
247 enum ib_srp_parse_flags {
248         IB_SRP_PARSE_REQUIRED = 0x0000,
249         IB_SRP_PARSE_OPTIONAL = 0x8000,
250         IB_SRP_PARSE_FLAG_MASK = 0xf000,
251 };
252
253 /** IB SRP root path parameters */
254 struct ib_srp_root_path {
255         /** Source GID */
256         union ib_gid sgid;
257         /** Initiator port ID */
258         union ib_srp_initiator_port_id initiator;
259         /** Destination GID */
260         union ib_gid dgid;
261         /** Partition key */
262         uint16_t pkey;
263         /** Service ID */
264         union ib_guid service_id;
265         /** SCSI LUN */
266         struct scsi_lun lun;
267         /** Target port ID */
268         union ib_srp_target_port_id target;
269 };
270
271 /**
272  * Parse IB SRP root path byte-string value
273  *
274  * @v rp_comp           Root path component string
275  * @v default_value     Default value to use if component string is empty
276  * @ret value           Value
277  */
278 static int ib_srp_parse_byte_string ( const char *rp_comp, uint8_t *bytes,
279                                       unsigned int size_flags ) {
280         size_t size = ( size_flags & ~IB_SRP_PARSE_FLAG_MASK );
281         size_t rp_comp_len = strlen ( rp_comp );
282         int decoded_size;
283
284         /* Allow optional components to be empty */
285         if ( ( rp_comp_len == 0 ) &&
286              ( size_flags & IB_SRP_PARSE_OPTIONAL ) )
287                 return 0;
288
289         /* Check string length */
290         if ( rp_comp_len != ( 2 * size ) )
291                 return -EINVAL_BYTE_STRING_LEN;
292
293         /* Parse byte string */
294         decoded_size = base16_decode ( rp_comp, bytes );
295         if ( decoded_size < 0 )
296                 return decoded_size;
297
298         return 0;
299 }
300
301 /**
302  * Parse IB SRP root path integer value
303  *
304  * @v rp_comp           Root path component string
305  * @v default_value     Default value to use if component string is empty
306  * @ret value           Value
307  */
308 static int ib_srp_parse_integer ( const char *rp_comp, int default_value ) {
309         int value;
310         char *end;
311
312         value = strtoul ( rp_comp, &end, 16 );
313         if ( *end )
314                 return -EINVAL_INTEGER;
315
316         if ( end == rp_comp )
317                 return default_value;
318
319         return value;
320 }
321
322 /**
323  * Parse IB SRP root path source GID
324  *
325  * @v rp_comp           Root path component string
326  * @v rp                IB SRP root path
327  * @ret rc              Return status code
328  */
329 static int ib_srp_parse_sgid ( const char *rp_comp,
330                                struct ib_srp_root_path *rp ) {
331         struct ib_device *ibdev;
332
333         /* Default to the GID of the last opened Infiniband device */
334         if ( ( ibdev = last_opened_ibdev() ) != NULL )
335                 memcpy ( &rp->sgid, &ibdev->gid, sizeof ( rp->sgid ) );
336
337         return ib_srp_parse_byte_string ( rp_comp, rp->sgid.bytes,
338                                           ( sizeof ( rp->sgid ) |
339                                             IB_SRP_PARSE_OPTIONAL ) );
340 }
341
342 /**
343  * Parse IB SRP root path initiator identifier extension
344  *
345  * @v rp_comp           Root path component string
346  * @v rp                IB SRP root path
347  * @ret rc              Return status code
348  */
349 static int ib_srp_parse_initiator_id_ext ( const char *rp_comp,
350                                            struct ib_srp_root_path *rp ) {
351         union ib_srp_initiator_port_id *port_id = &rp->initiator;
352
353         return ib_srp_parse_byte_string ( rp_comp, port_id->ib.id_ext.bytes,
354                                           ( sizeof ( port_id->ib.id_ext ) |
355                                             IB_SRP_PARSE_OPTIONAL ) );
356 }
357
358 /**
359  * Parse IB SRP root path initiator HCA GUID
360  *
361  * @v rp_comp           Root path component string
362  * @v rp                IB SRP root path
363  * @ret rc              Return status code
364  */
365 static int ib_srp_parse_initiator_hca_guid ( const char *rp_comp,
366                                              struct ib_srp_root_path *rp ) {
367         union ib_srp_initiator_port_id *port_id = &rp->initiator;
368
369         /* Default to the GUID portion of the source GID */
370         memcpy ( &port_id->ib.hca_guid, &rp->sgid.s.guid,
371                  sizeof ( port_id->ib.hca_guid ) );
372
373         return ib_srp_parse_byte_string ( rp_comp, port_id->ib.hca_guid.bytes,
374                                           ( sizeof ( port_id->ib.hca_guid ) |
375                                             IB_SRP_PARSE_OPTIONAL ) );
376 }
377
378 /**
379  * Parse IB SRP root path destination GID
380  *
381  * @v rp_comp           Root path component string
382  * @v rp                IB SRP root path
383  * @ret rc              Return status code
384  */
385 static int ib_srp_parse_dgid ( const char *rp_comp,
386                                struct ib_srp_root_path *rp ) {
387         return ib_srp_parse_byte_string ( rp_comp, rp->dgid.bytes,
388                                           ( sizeof ( rp->dgid ) |
389                                             IB_SRP_PARSE_REQUIRED ) );
390 }
391
392 /**
393  * Parse IB SRP root path partition key
394  *
395  * @v rp_comp           Root path component string
396  * @v rp                IB SRP root path
397  * @ret rc              Return status code
398  */
399 static int ib_srp_parse_pkey ( const char *rp_comp,
400                                struct ib_srp_root_path *rp ) {
401         int pkey;
402
403         if ( ( pkey = ib_srp_parse_integer ( rp_comp, IB_PKEY_DEFAULT ) ) < 0 )
404                 return pkey;
405         rp->pkey = pkey;
406         return 0;
407 }
408
409 /**
410  * Parse IB SRP root path service ID
411  *
412  * @v rp_comp           Root path component string
413  * @v rp                IB SRP root path
414  * @ret rc              Return status code
415  */
416 static int ib_srp_parse_service_id ( const char *rp_comp,
417                                      struct ib_srp_root_path *rp ) {
418         return ib_srp_parse_byte_string ( rp_comp, rp->service_id.bytes,
419                                           ( sizeof ( rp->service_id ) |
420                                             IB_SRP_PARSE_REQUIRED ) );
421 }
422
423 /**
424  * Parse IB SRP root path LUN
425  *
426  * @v rp_comp           Root path component string
427  * @v rp                IB SRP root path
428  * @ret rc              Return status code
429  */
430 static int ib_srp_parse_lun ( const char *rp_comp,
431                               struct ib_srp_root_path *rp ) {
432         return scsi_parse_lun ( rp_comp, &rp->lun );
433 }
434
435 /**
436  * Parse IB SRP root path target identifier extension
437  *
438  * @v rp_comp           Root path component string
439  * @v rp                IB SRP root path
440  * @ret rc              Return status code
441  */
442 static int ib_srp_parse_target_id_ext ( const char *rp_comp,
443                                         struct ib_srp_root_path *rp ) {
444         union ib_srp_target_port_id *port_id = &rp->target;
445
446         return ib_srp_parse_byte_string ( rp_comp, port_id->ib.id_ext.bytes,
447                                           ( sizeof ( port_id->ib.id_ext ) |
448                                             IB_SRP_PARSE_REQUIRED ) );
449 }
450
451 /**
452  * Parse IB SRP root path target I/O controller GUID
453  *
454  * @v rp_comp           Root path component string
455  * @v rp                IB SRP root path
456  * @ret rc              Return status code
457  */
458 static int ib_srp_parse_target_ioc_guid ( const char *rp_comp,
459                                           struct ib_srp_root_path *rp ) {
460         union ib_srp_target_port_id *port_id = &rp->target;
461
462         return ib_srp_parse_byte_string ( rp_comp, port_id->ib.ioc_guid.bytes,
463                                           ( sizeof ( port_id->ib.ioc_guid ) |
464                                             IB_SRP_PARSE_REQUIRED ) );
465 }
466
467 /** IB SRP root path component parser */
468 struct ib_srp_root_path_parser {
469         /**
470          * Parse IB SRP root path component
471          *
472          * @v rp_comp           Root path component string
473          * @v rp                IB SRP root path
474          * @ret rc              Return status code
475          */
476         int ( * parse ) ( const char *rp_comp, struct ib_srp_root_path *rp );
477 };
478
479 /** IB SRP root path components */
480 static struct ib_srp_root_path_parser ib_srp_rp_parser[] = {
481         { ib_srp_parse_sgid },
482         { ib_srp_parse_initiator_id_ext },
483         { ib_srp_parse_initiator_hca_guid },
484         { ib_srp_parse_dgid },
485         { ib_srp_parse_pkey },
486         { ib_srp_parse_service_id },
487         { ib_srp_parse_lun },
488         { ib_srp_parse_target_id_ext },
489         { ib_srp_parse_target_ioc_guid },
490 };
491
492 /** Number of IB SRP root path components */
493 #define IB_SRP_NUM_RP_COMPONENTS \
494         ( sizeof ( ib_srp_rp_parser ) / sizeof ( ib_srp_rp_parser[0] ) )
495
496 /**
497  * Parse IB SRP root path
498  *
499  * @v rp_string         Root path string
500  * @v rp                IB SRP root path
501  * @ret rc              Return status code
502  */
503 static int ib_srp_parse_root_path ( const char *rp_string,
504                                     struct ib_srp_root_path *rp ) {
505         struct ib_srp_root_path_parser *parser;
506         char rp_string_copy[ strlen ( rp_string ) + 1 ];
507         char *rp_comp[IB_SRP_NUM_RP_COMPONENTS];
508         char *rp_string_tmp = rp_string_copy;
509         unsigned int i = 0;
510         int rc;
511
512         /* Split root path into component parts */
513         strcpy ( rp_string_copy, rp_string );
514         while ( 1 ) {
515                 rp_comp[i++] = rp_string_tmp;
516                 if ( i == IB_SRP_NUM_RP_COMPONENTS )
517                         break;
518                 for ( ; *rp_string_tmp != ':' ; rp_string_tmp++ ) {
519                         if ( ! *rp_string_tmp ) {
520                                 DBG ( "IBSRP root path \"%s\" too short\n",
521                                       rp_string );
522                                 return -EINVAL_RP_TOO_SHORT;
523                         }
524                 }
525                 *(rp_string_tmp++) = '\0';
526         }
527
528         /* Parse root path components */
529         for ( i = 0 ; i < IB_SRP_NUM_RP_COMPONENTS ; i++ ) {
530                 parser = &ib_srp_rp_parser[i];
531                 if ( ( rc = parser->parse ( rp_comp[i], rp ) ) != 0 ) {
532                         DBG ( "IBSRP could not parse \"%s\" in root path "
533                               "\"%s\": %s\n", rp_comp[i], rp_string,
534                               strerror ( rc ) );
535                         return rc;
536                 }
537         }
538
539         return 0;
540 }
541
542 /**
543  * Open IB SRP URI
544  *
545  * @v parent            Parent interface
546  * @v uri               URI
547  * @ret rc              Return status code
548  */
549 static int ib_srp_open_uri ( struct interface *parent, struct uri *uri ) {
550         struct ib_srp_root_path rp;
551         struct ib_device *ibdev;
552         int rc;
553
554         /* Parse URI */
555         if ( ! uri->opaque )
556                 return -EINVAL;
557         memset ( &rp, 0, sizeof ( rp ) );
558         if ( ( rc = ib_srp_parse_root_path ( uri->opaque, &rp ) ) != 0 )
559                 return rc;
560
561         /* Identify Infiniband device */
562         ibdev = find_ibdev ( &rp.sgid );
563         if ( ! ibdev ) {
564                 DBG ( "IBSRP could not identify Infiniband device\n" );
565                 return -ENODEV;
566         }
567
568         /* Open IB SRP device */
569         if ( ( rc = ib_srp_open ( parent, ibdev, &rp.dgid, &rp.service_id,
570                                   &rp.initiator.srp, &rp.target.srp,
571                                   &rp.lun ) ) != 0 )
572                 return rc;
573
574         return 0;
575 }
576
577 /** IB SRP URI opener */
578 struct uri_opener ib_srp_uri_opener __uri_opener = {
579         .scheme = "ib_srp",
580         .open = ib_srp_open_uri,
581 };