"Fossies" - the Fresh Open Source Software Archive

Member "open-fcoe-3.19/libhbalinux/rport.c" (15 Apr 2015, 5428 Bytes) of package /linux/misc/open-fcoe-3.19.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rport.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (c) 2008, Intel Corporation.
    3  *
    4  * This program is free software; you can redistribute it and/or modify it
    5  * under the terms and conditions of the GNU Lesser General Public License,
    6  * version 2.1, as published by the Free Software Foundation.
    7  *
    8  * This program is distributed in the hope it will be useful, but WITHOUT
    9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   11  * for more details.
   12  *
   13  * You should have received a copy of the GNU Lesser General Public License
   14  * along with this program; if not, write to the Free Software Foundation, Inc.,
   15  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
   16  *
   17  */
   18 
   19 #include "utils.h"
   20 #include "api_lib.h"
   21 #include "adapt_impl.h"
   22 
   23 static int sys_read_port_state(const char *, const char *, u_int32_t *);
   24 static int sys_read_classes(const char *, const char *, u_int32_t *);
   25 
   26 static struct sa_table rports_table;          /* table of discovered ports */
   27 
   28 /*
   29  * Handle a single remote port from the /sys directory entry.
   30  * The return value is 0 unless an error is detected which should stop the
   31  * directory read.
   32  */
   33 static int
   34 sysfs_get_rport(struct dirent *dp, void *arg)
   35 {
   36     struct port_info *rp;
   37     HBA_PORTATTRIBUTES *rpa;
   38     int rc;
   39     u_int32_t hba;
   40     u_int32_t port;
   41     u_int32_t rp_index;
   42     char *rport_dir;
   43     char buf[256];
   44 
   45     /*
   46      * Parse name into bus number, channel number, and remote port number.
   47      */
   48     hba = ~0;
   49     port = ~0;
   50     rp_index = ~0;
   51     rc = sscanf(dp->d_name, SYSFS_RPORT_DIR, &hba, &port, &rp_index);
   52     if (rc != 3) {
   53         fprintf(stderr,
   54             "%s: remote port %s didn't parse."
   55             " rc %d h 0x%x p 0x%x rp 0x%x\n", __func__,
   56             dp->d_name, rc, hba, port, rp_index);
   57         return 0;
   58     }
   59 
   60     /*
   61      * Allocate a remote port.
   62      */
   63     rp = malloc(sizeof(*rp));
   64     if (rp == NULL) {
   65         fprintf(stderr, "%s: malloc for remote port %s failed,"
   66             " errno=0x%x\n", __func__, dp->d_name, errno);
   67         return ENOMEM;
   68     }
   69     memset(rp, 0, sizeof(*rp));
   70     rp->ap_kern_hba = hba;
   71     rp->ap_index = port;
   72     rp->ap_disc_index = rp_index;
   73     rpa = &rp->ap_attr;
   74 
   75     snprintf(rpa->OSDeviceName, sizeof(rpa->OSDeviceName), "%s/%s",
   76         SYSFS_RPORT_ROOT, dp->d_name);
   77     rport_dir = rpa->OSDeviceName;
   78     rc = 0;
   79     rc |= sys_read_wwn(rport_dir, "node_name", &rpa->NodeWWN);
   80     rc |= sys_read_wwn(rport_dir, "port_name", &rpa->PortWWN);
   81     rc |= sa_sys_read_u32(rport_dir, "port_id", &rpa->PortFcId);
   82     rc |= sa_sys_read_u32(rport_dir, "scsi_target_id", &rp->ap_scsi_target);
   83     sa_sys_read_line(rport_dir, "maxframe_size", buf, sizeof(buf));
   84     sscanf(buf, "%d", &rpa->PortMaxFrameSize);
   85     rc |= sys_read_port_state(rport_dir, "port_state", &rpa->PortState);
   86     rc |= sys_read_classes(rport_dir, "supported_classes",
   87                    &rpa->PortSupportedClassofService);
   88     if (rc != 0 || sa_table_append(&rports_table, rp) < 0) {
   89         if (rc != 0)
   90             fprintf(stderr,
   91                 "%s: errors (%x) from /sys reads in %s\n",
   92                 __func__, rc, dp->d_name);
   93         else
   94             fprintf(stderr,
   95                 "%s: sa_table_append error on rport %s\n",
   96                 __func__, dp->d_name);
   97         free(rp);
   98     }
   99     return 0;
  100 }
  101 
  102 /*
  103  * Get remote port information from /sys.
  104  */
  105 static void
  106 sysfs_find_rports(void)
  107 {
  108     sa_dir_read(SYSFS_RPORT_ROOT, sysfs_get_rport, NULL);
  109 }
  110 
  111 /*
  112  * Read port state as formatted by scsi_transport_fc.c in the linux kernel.
  113  */
  114 static int
  115 sys_read_port_state(const char *dir, const char *file, u_int32_t *statep)
  116 {
  117     char buf[256];
  118     int rc;
  119 
  120     rc = sa_sys_read_line(dir, file, buf, sizeof(buf));
  121     if (rc == 0) {
  122         rc = sa_enum_encode(port_states_table, buf, statep);
  123         if (rc != 0)
  124             fprintf(stderr,
  125                 "%s: parse error. file %s/%s line '%s'\n",
  126                 __func__, dir, file, buf);
  127     }
  128     return rc;
  129 }
  130 
  131 /*
  132  * Read class list as formatted by scsi_transport_fc.c in the linux kernel.
  133  * Format is expected to be "Class 3[, Class 4]..."
  134  * Actually accepts "[Class ]3[,[ ][Class ]4]..." (i.e., "Class" and spaces
  135  * are optional).
  136  */
  137 static int
  138 sys_read_classes(const char *dir, const char *file, u_int32_t *classp)
  139 {
  140     char buf[256];
  141     int rc;
  142     u_int32_t val;
  143     char *cp;
  144     char *ep;
  145 
  146     *classp = 0;
  147     rc = sa_sys_read_line(dir, file, buf, sizeof(buf));
  148     if (rc == 0 && strstr(buf, "unspecified") == NULL) {
  149         for (cp = buf; *cp != '\0'; cp = ep) {
  150             if (strncmp(cp, "Class ", 6) == 0)
  151                 cp += 6;
  152             val = strtoul(cp, &ep, 10);
  153             *classp |= 1 << val;
  154             if (*ep == '\0')
  155                 break;
  156             if (*ep == ',') {
  157                 ep++;
  158                 if (*ep == ' ')
  159                     ep++;
  160             } else {
  161                 fprintf(stderr, "%s: parse error. file %s/%s "
  162                        "line '%s' ep '%c'\n", __func__,
  163                     dir, file, buf, *ep);
  164                 rc = -1;
  165                 break;
  166             }
  167         }
  168     }
  169     return rc;
  170 }
  171 
  172 /*
  173  * Get all discovered ports for a particular port using /sys.
  174  */
  175 void
  176 get_rport_info(struct port_info *pp)
  177 {
  178     struct port_info *rp;
  179     int rp_count = 0;
  180     int ri;
  181 
  182     if (rports_table.st_size == 0)
  183         sysfs_find_rports();
  184 
  185     for (ri = 0; ri < rports_table.st_size; ri++) {
  186         rp = sa_table_lookup(&rports_table, ri);
  187         if (rp != NULL) {
  188             if (rp->ap_kern_hba == pp->ap_kern_hba &&
  189                 rp->ap_index == pp->ap_index &&
  190                 rp->ap_adapt == NULL) {
  191                 rp->ap_adapt = pp->ap_adapt;
  192                 if (sa_table_lookup(&pp->ap_rports,
  193                             rp->ap_disc_index)) {
  194                     fprintf(stderr,
  195                         "%s: discovered port exists. "
  196                            "hba %x port %x rport %x\n",
  197                            __func__, pp->ap_kern_hba,
  198                            pp->ap_index, rp->ap_disc_index);
  199                 }
  200                 sa_table_insert(&pp->ap_rports,
  201                         rp->ap_disc_index, rp);
  202             }
  203             rp_count++;
  204         }
  205     }
  206 }
  207