linux/include/scsi/fc_encode.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * Copyright(c) 2008 Intel Corporation. All rights reserved.
   4 *
   5 * Maintained at www.Open-FCoE.org
   6 */
   7
   8#ifndef _FC_ENCODE_H_
   9#define _FC_ENCODE_H_
  10#include <asm/unaligned.h>
  11#include <linux/utsname.h>
  12
  13/*
  14 * F_CTL values for simple requests and responses.
  15 */
  16#define FC_FCTL_REQ     (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT)
  17#define FC_FCTL_RESP    (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \
  18                        FC_FC_END_SEQ | FC_FC_SEQ_INIT)
  19
  20struct fc_ns_rft {
  21        struct fc_ns_fid fid;   /* port ID object */
  22        struct fc_ns_fts fts;   /* FC4-types object */
  23};
  24
  25struct fc_ct_req {
  26        struct fc_ct_hdr hdr;
  27        union {
  28                struct fc_ns_gid_ft gid;
  29                struct fc_ns_rn_id  rn;
  30                struct fc_ns_rft rft;
  31                struct fc_ns_rff_id rff;
  32                struct fc_ns_fid fid;
  33                struct fc_ns_rsnn snn;
  34                struct fc_ns_rspn spn;
  35                struct fc_fdmi_rhba rhba;
  36                struct fc_fdmi_rpa  rpa;
  37                struct fc_fdmi_dprt dprt;
  38                struct fc_fdmi_dhba dhba;
  39        } payload;
  40};
  41
  42static inline void __fc_fill_fc_hdr(struct fc_frame_header *fh,
  43                                    enum fc_rctl r_ctl,
  44                                    u32 did, u32 sid, enum fc_fh_type type,
  45                                    u32 f_ctl, u32 parm_offset)
  46{
  47        WARN_ON(r_ctl == 0);
  48        fh->fh_r_ctl = r_ctl;
  49        hton24(fh->fh_d_id, did);
  50        hton24(fh->fh_s_id, sid);
  51        fh->fh_type = type;
  52        hton24(fh->fh_f_ctl, f_ctl);
  53        fh->fh_cs_ctl = 0;
  54        fh->fh_df_ctl = 0;
  55        fh->fh_parm_offset = htonl(parm_offset);
  56}
  57
  58/**
  59 * fill FC header fields in specified fc_frame
  60 */
  61static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl,
  62                                  u32 did, u32 sid, enum fc_fh_type type,
  63                                  u32 f_ctl, u32 parm_offset)
  64{
  65        struct fc_frame_header *fh;
  66
  67        fh = fc_frame_header_get(fp);
  68        __fc_fill_fc_hdr(fh, r_ctl, did, sid, type, f_ctl, parm_offset);
  69}
  70
  71/**
  72 * fc_adisc_fill() - Fill in adisc request frame
  73 * @lport: local port.
  74 * @fp: fc frame where payload will be placed.
  75 */
  76static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp)
  77{
  78        struct fc_els_adisc *adisc;
  79
  80        adisc = fc_frame_payload_get(fp, sizeof(*adisc));
  81        memset(adisc, 0, sizeof(*adisc));
  82        adisc->adisc_cmd = ELS_ADISC;
  83        put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn);
  84        put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn);
  85        hton24(adisc->adisc_port_id, lport->port_id);
  86}
  87
  88/**
  89 * fc_ct_hdr_fill- fills ct header and reset ct payload
  90 * returns pointer to ct request.
  91 */
  92static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp,
  93                                               unsigned int op, size_t req_size,
  94                                               enum fc_ct_fs_type fs_type,
  95                                               u8 subtype)
  96{
  97        struct fc_ct_req *ct;
  98        size_t ct_plen;
  99
 100        ct_plen  = sizeof(struct fc_ct_hdr) + req_size;
 101        ct = fc_frame_payload_get(fp, ct_plen);
 102        memset(ct, 0, ct_plen);
 103        ct->hdr.ct_rev = FC_CT_REV;
 104        ct->hdr.ct_fs_type = fs_type;
 105        ct->hdr.ct_fs_subtype = subtype;
 106        ct->hdr.ct_cmd = htons((u16) op);
 107        return ct;
 108}
 109
 110/**
 111 * fc_ct_ns_fill() - Fill in a name service request frame
 112 * @lport: local port.
 113 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
 114 * @fp: frame to contain payload.
 115 * @op: CT opcode.
 116 * @r_ctl: pointer to FC header R_CTL.
 117 * @fh_type: pointer to FC-4 type.
 118 */
 119static inline int fc_ct_ns_fill(struct fc_lport *lport,
 120                      u32 fc_id, struct fc_frame *fp,
 121                      unsigned int op, enum fc_rctl *r_ctl,
 122                      enum fc_fh_type *fh_type)
 123{
 124        struct fc_ct_req *ct;
 125        size_t len;
 126
 127        switch (op) {
 128        case FC_NS_GPN_FT:
 129                ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_gid_ft),
 130                                    FC_FST_DIR, FC_NS_SUBTYPE);
 131                ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
 132                break;
 133
 134        case FC_NS_GPN_ID:
 135                ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_fid),
 136                                    FC_FST_DIR, FC_NS_SUBTYPE);
 137                ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
 138                hton24(ct->payload.fid.fp_fid, fc_id);
 139                break;
 140
 141        case FC_NS_RFT_ID:
 142                ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft),
 143                                    FC_FST_DIR, FC_NS_SUBTYPE);
 144                hton24(ct->payload.rft.fid.fp_fid, lport->port_id);
 145                ct->payload.rft.fts = lport->fcts;
 146                break;
 147
 148        case FC_NS_RFF_ID:
 149                ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rff_id),
 150                                    FC_FST_DIR, FC_NS_SUBTYPE);
 151                hton24(ct->payload.rff.fr_fid.fp_fid, lport->port_id);
 152                ct->payload.rff.fr_type = FC_TYPE_FCP;
 153                if (lport->service_params & FCP_SPPF_INIT_FCN)
 154                        ct->payload.rff.fr_feat = FCP_FEAT_INIT;
 155                if (lport->service_params & FCP_SPPF_TARG_FCN)
 156                        ct->payload.rff.fr_feat |= FCP_FEAT_TARG;
 157                break;
 158
 159        case FC_NS_RNN_ID:
 160                ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id),
 161                                    FC_FST_DIR, FC_NS_SUBTYPE);
 162                hton24(ct->payload.rn.fr_fid.fp_fid, lport->port_id);
 163                put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn);
 164                break;
 165
 166        case FC_NS_RSPN_ID:
 167                len = strnlen(fc_host_symbolic_name(lport->host), 255);
 168                ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rspn) + len,
 169                                    FC_FST_DIR, FC_NS_SUBTYPE);
 170                hton24(ct->payload.spn.fr_fid.fp_fid, lport->port_id);
 171                strncpy(ct->payload.spn.fr_name,
 172                        fc_host_symbolic_name(lport->host), len);
 173                ct->payload.spn.fr_name_len = len;
 174                break;
 175
 176        case FC_NS_RSNN_NN:
 177                len = strnlen(fc_host_symbolic_name(lport->host), 255);
 178                ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rsnn) + len,
 179                                    FC_FST_DIR, FC_NS_SUBTYPE);
 180                put_unaligned_be64(lport->wwnn, &ct->payload.snn.fr_wwn);
 181                strncpy(ct->payload.snn.fr_name,
 182                        fc_host_symbolic_name(lport->host), len);
 183                ct->payload.snn.fr_name_len = len;
 184                break;
 185
 186        default:
 187                return -EINVAL;
 188        }
 189        *r_ctl = FC_RCTL_DD_UNSOL_CTL;
 190        *fh_type = FC_TYPE_CT;
 191        return 0;
 192}
 193
 194/**
 195 * fc_ct_ms_fill() - Fill in a mgmt service request frame
 196 * @lport: local port.
 197 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
 198 * @fp: frame to contain payload.
 199 * @op: CT opcode.
 200 * @r_ctl: pointer to FC header R_CTL.
 201 * @fh_type: pointer to FC-4 type.
 202 */
 203static inline int fc_ct_ms_fill(struct fc_lport *lport,
 204                      u32 fc_id, struct fc_frame *fp,
 205                      unsigned int op, enum fc_rctl *r_ctl,
 206                      enum fc_fh_type *fh_type)
 207{
 208        struct fc_ct_req *ct;
 209        size_t len;
 210        struct fc_fdmi_attr_entry *entry;
 211        struct fs_fdmi_attrs *hba_attrs;
 212        int numattrs = 0;
 213
 214        switch (op) {
 215        case FC_FDMI_RHBA:
 216                numattrs = 10;
 217                len = sizeof(struct fc_fdmi_rhba);
 218                len -= sizeof(struct fc_fdmi_attr_entry);
 219                len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
 220                len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
 221                len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;
 222                len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;
 223                len += FC_FDMI_HBA_ATTR_MODEL_LEN;
 224                len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;
 225                len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;
 226                len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;
 227                len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
 228                len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
 229                len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
 230                ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
 231                                    FC_FDMI_SUBTYPE);
 232
 233                /* HBA Identifier */
 234                put_unaligned_be64(lport->wwpn, &ct->payload.rhba.hbaid.id);
 235                /* Number of Ports - always 1 */
 236                put_unaligned_be32(1, &ct->payload.rhba.port.numport);
 237                /* Port Name */
 238                put_unaligned_be64(lport->wwpn,
 239                                   &ct->payload.rhba.port.port[0].portname);
 240
 241                /* HBA Attributes */
 242                put_unaligned_be32(numattrs,
 243                                   &ct->payload.rhba.hba_attrs.numattrs);
 244                hba_attrs = &ct->payload.rhba.hba_attrs;
 245                entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr;
 246                /* NodeName*/
 247                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 248                len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
 249                put_unaligned_be16(FC_FDMI_HBA_ATTR_NODENAME,
 250                                   &entry->type);
 251                put_unaligned_be16(len, &entry->len);
 252                put_unaligned_be64(lport->wwnn,
 253                                   (__be64 *)&entry->value[0]);
 254
 255                /* Manufacturer */
 256                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 257                                        FC_FDMI_HBA_ATTR_NODENAME_LEN);
 258                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 259                len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;
 260                put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER,
 261                                   &entry->type);
 262                put_unaligned_be16(len, &entry->len);
 263                strncpy((char *)&entry->value,
 264                        fc_host_manufacturer(lport->host),
 265                        FC_FDMI_HBA_ATTR_MANUFACTURER_LEN);
 266
 267                /* SerialNumber */
 268                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 269                                        FC_FDMI_HBA_ATTR_MANUFACTURER_LEN);
 270                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 271                len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;
 272                put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER,
 273                                   &entry->type);
 274                put_unaligned_be16(len, &entry->len);
 275                strncpy((char *)&entry->value,
 276                        fc_host_serial_number(lport->host),
 277                        FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN);
 278
 279                /* Model */
 280                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 281                                        FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN);
 282                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 283                len += FC_FDMI_HBA_ATTR_MODEL_LEN;
 284                put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL,
 285                                   &entry->type);
 286                put_unaligned_be16(len, &entry->len);
 287                strncpy((char *)&entry->value,
 288                        fc_host_model(lport->host),
 289                        FC_FDMI_HBA_ATTR_MODEL_LEN);
 290
 291                /* Model Description */
 292                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 293                                        FC_FDMI_HBA_ATTR_MODEL_LEN);
 294                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 295                len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;
 296                put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION,
 297                                   &entry->type);
 298                put_unaligned_be16(len, &entry->len);
 299                strncpy((char *)&entry->value,
 300                        fc_host_model_description(lport->host),
 301                        FC_FDMI_HBA_ATTR_MODELDESCR_LEN);
 302
 303                /* Hardware Version */
 304                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 305                                        FC_FDMI_HBA_ATTR_MODELDESCR_LEN);
 306                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 307                len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;
 308                put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION,
 309                                   &entry->type);
 310                put_unaligned_be16(len, &entry->len);
 311                strncpy((char *)&entry->value,
 312                        fc_host_hardware_version(lport->host),
 313                        FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN);
 314
 315                /* Driver Version */
 316                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 317                                        FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN);
 318                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 319                len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;
 320                put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION,
 321                                   &entry->type);
 322                put_unaligned_be16(len, &entry->len);
 323                strncpy((char *)&entry->value,
 324                        fc_host_driver_version(lport->host),
 325                        FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN);
 326
 327                /* OptionROM Version */
 328                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 329                                        FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN);
 330                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 331                len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
 332                put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION,
 333                                   &entry->type);
 334                put_unaligned_be16(len, &entry->len);
 335                strncpy((char *)&entry->value,
 336                        fc_host_optionrom_version(lport->host),
 337                        FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
 338
 339                /* Firmware Version */
 340                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 341                                        FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
 342                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 343                len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
 344                put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION,
 345                                   &entry->type);
 346                put_unaligned_be16(len, &entry->len);
 347                strncpy((char *)&entry->value,
 348                        fc_host_firmware_version(lport->host),
 349                        FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN);
 350
 351                /* OS Name and Version */
 352                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 353                                        FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN);
 354                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 355                len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
 356                put_unaligned_be16(FC_FDMI_HBA_ATTR_OSNAMEVERSION,
 357                                   &entry->type);
 358                put_unaligned_be16(len, &entry->len);
 359                snprintf((char *)&entry->value,
 360                        FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN,
 361                        "%s v%s",
 362                        init_utsname()->sysname,
 363                        init_utsname()->release);
 364                break;
 365        case FC_FDMI_RPA:
 366                numattrs = 6;
 367                len = sizeof(struct fc_fdmi_rpa);
 368                len -= sizeof(struct fc_fdmi_attr_entry);
 369                len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
 370                len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
 371                len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;
 372                len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;
 373                len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
 374                len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
 375                len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
 376                ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
 377                                    FC_FDMI_SUBTYPE);
 378
 379                /* Port Name */
 380                put_unaligned_be64(lport->wwpn,
 381                                   &ct->payload.rpa.port.portname);
 382
 383                /* Port Attributes */
 384                put_unaligned_be32(numattrs,
 385                                   &ct->payload.rpa.hba_attrs.numattrs);
 386
 387                hba_attrs = &ct->payload.rpa.hba_attrs;
 388                entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr;
 389
 390                /* FC4 types */
 391                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 392                len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
 393                put_unaligned_be16(FC_FDMI_PORT_ATTR_FC4TYPES,
 394                                   &entry->type);
 395                put_unaligned_be16(len, &entry->len);
 396                memcpy(&entry->value, fc_host_supported_fc4s(lport->host),
 397                       FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
 398
 399                /* Supported Speed */
 400                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 401                                        FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
 402                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 403                len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;
 404                put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
 405                                   &entry->type);
 406                put_unaligned_be16(len, &entry->len);
 407
 408                put_unaligned_be32(fc_host_supported_speeds(lport->host),
 409                                   &entry->value);
 410
 411                /* Current Port Speed */
 412                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 413                                        FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN);
 414                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 415                len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;
 416                put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
 417                                   &entry->type);
 418                put_unaligned_be16(len, &entry->len);
 419                put_unaligned_be32(lport->link_speed,
 420                                   &entry->value);
 421
 422                /* Max Frame Size */
 423                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 424                                        FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
 425                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 426                len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
 427                put_unaligned_be16(FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
 428                                   &entry->type);
 429                put_unaligned_be16(len, &entry->len);
 430                put_unaligned_be32(fc_host_maxframe_size(lport->host),
 431                                   &entry->value);
 432
 433                /* OS Device Name */
 434                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 435                                        FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN);
 436                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 437                len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
 438                put_unaligned_be16(FC_FDMI_PORT_ATTR_OSDEVICENAME,
 439                                   &entry->type);
 440                put_unaligned_be16(len, &entry->len);
 441                /* Use the sysfs device name */
 442                strncpy((char *)&entry->value,
 443                        dev_name(&lport->host->shost_gendev),
 444                        strnlen(dev_name(&lport->host->shost_gendev),
 445                                FC_FDMI_PORT_ATTR_HOSTNAME_LEN));
 446
 447                /* Host Name */
 448                entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
 449                                        FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN);
 450                len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
 451                len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
 452                put_unaligned_be16(FC_FDMI_PORT_ATTR_HOSTNAME,
 453                                   &entry->type);
 454                put_unaligned_be16(len, &entry->len);
 455                if (strlen(fc_host_system_hostname(lport->host)))
 456                        strncpy((char *)&entry->value,
 457                                fc_host_system_hostname(lport->host),
 458                                strnlen(fc_host_system_hostname(lport->host),
 459                                        FC_FDMI_PORT_ATTR_HOSTNAME_LEN));
 460                else
 461                        strncpy((char *)&entry->value,
 462                                init_utsname()->nodename,
 463                                FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
 464                break;
 465        case FC_FDMI_DPRT:
 466                len = sizeof(struct fc_fdmi_dprt);
 467                ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
 468                                    FC_FDMI_SUBTYPE);
 469                /* Port Name */
 470                put_unaligned_be64(lport->wwpn,
 471                                   &ct->payload.dprt.port.portname);
 472                break;
 473        case FC_FDMI_DHBA:
 474                len = sizeof(struct fc_fdmi_dhba);
 475                ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
 476                                    FC_FDMI_SUBTYPE);
 477                /* HBA Identifier */
 478                put_unaligned_be64(lport->wwpn, &ct->payload.dhba.hbaid.id);
 479                break;
 480        default:
 481                return -EINVAL;
 482        }
 483        *r_ctl = FC_RCTL_DD_UNSOL_CTL;
 484        *fh_type = FC_TYPE_CT;
 485        return 0;
 486}
 487
 488/**
 489 * fc_ct_fill() - Fill in a common transport service request frame
 490 * @lport: local port.
 491 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
 492 * @fp: frame to contain payload.
 493 * @op: CT opcode.
 494 * @r_ctl: pointer to FC header R_CTL.
 495 * @fh_type: pointer to FC-4 type.
 496 */
 497static inline int fc_ct_fill(struct fc_lport *lport,
 498                      u32 fc_id, struct fc_frame *fp,
 499                      unsigned int op, enum fc_rctl *r_ctl,
 500                      enum fc_fh_type *fh_type, u32 *did)
 501{
 502        int rc = -EINVAL;
 503
 504        switch (fc_id) {
 505        case FC_FID_MGMT_SERV:
 506                rc = fc_ct_ms_fill(lport, fc_id, fp, op, r_ctl, fh_type);
 507                *did = FC_FID_MGMT_SERV;
 508                break;
 509        case FC_FID_DIR_SERV:
 510        default:
 511                rc = fc_ct_ns_fill(lport, fc_id, fp, op, r_ctl, fh_type);
 512                *did = FC_FID_DIR_SERV;
 513                break;
 514        }
 515
 516        return rc;
 517}
 518/**
 519 * fc_plogi_fill - Fill in plogi request frame
 520 */
 521static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp,
 522                                 unsigned int op)
 523{
 524        struct fc_els_flogi *plogi;
 525        struct fc_els_csp *csp;
 526        struct fc_els_cssp *cp;
 527
 528        plogi = fc_frame_payload_get(fp, sizeof(*plogi));
 529        memset(plogi, 0, sizeof(*plogi));
 530        plogi->fl_cmd = (u8) op;
 531        put_unaligned_be64(lport->wwpn, &plogi->fl_wwpn);
 532        put_unaligned_be64(lport->wwnn, &plogi->fl_wwnn);
 533
 534        csp = &plogi->fl_csp;
 535        csp->sp_hi_ver = 0x20;
 536        csp->sp_lo_ver = 0x20;
 537        csp->sp_bb_cred = htons(10);    /* this gets set by gateway */
 538        csp->sp_bb_data = htons((u16) lport->mfs);
 539        cp = &plogi->fl_cssp[3 - 1];    /* class 3 parameters */
 540        cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
 541        csp->sp_features = htons(FC_SP_FT_CIRO);
 542        csp->sp_tot_seq = htons(255);   /* seq. we accept */
 543        csp->sp_rel_off = htons(0x1f);
 544        csp->sp_e_d_tov = htonl(lport->e_d_tov);
 545
 546        cp->cp_rdfs = htons((u16) lport->mfs);
 547        cp->cp_con_seq = htons(255);
 548        cp->cp_open_seq = 1;
 549}
 550
 551/**
 552 * fc_flogi_fill - Fill in a flogi request frame.
 553 */
 554static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp)
 555{
 556        struct fc_els_csp *sp;
 557        struct fc_els_cssp *cp;
 558        struct fc_els_flogi *flogi;
 559
 560        flogi = fc_frame_payload_get(fp, sizeof(*flogi));
 561        memset(flogi, 0, sizeof(*flogi));
 562        flogi->fl_cmd = (u8) ELS_FLOGI;
 563        put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn);
 564        put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn);
 565        sp = &flogi->fl_csp;
 566        sp->sp_hi_ver = 0x20;
 567        sp->sp_lo_ver = 0x20;
 568        sp->sp_bb_cred = htons(10);     /* this gets set by gateway */
 569        sp->sp_bb_data = htons((u16) lport->mfs);
 570        cp = &flogi->fl_cssp[3 - 1];    /* class 3 parameters */
 571        cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
 572        if (lport->does_npiv)
 573                sp->sp_features = htons(FC_SP_FT_NPIV);
 574}
 575
 576/**
 577 * fc_fdisc_fill - Fill in a fdisc request frame.
 578 */
 579static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp)
 580{
 581        struct fc_els_csp *sp;
 582        struct fc_els_cssp *cp;
 583        struct fc_els_flogi *fdisc;
 584
 585        fdisc = fc_frame_payload_get(fp, sizeof(*fdisc));
 586        memset(fdisc, 0, sizeof(*fdisc));
 587        fdisc->fl_cmd = (u8) ELS_FDISC;
 588        put_unaligned_be64(lport->wwpn, &fdisc->fl_wwpn);
 589        put_unaligned_be64(lport->wwnn, &fdisc->fl_wwnn);
 590        sp = &fdisc->fl_csp;
 591        sp->sp_hi_ver = 0x20;
 592        sp->sp_lo_ver = 0x20;
 593        sp->sp_bb_cred = htons(10);     /* this gets set by gateway */
 594        sp->sp_bb_data = htons((u16) lport->mfs);
 595        cp = &fdisc->fl_cssp[3 - 1];    /* class 3 parameters */
 596        cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
 597}
 598
 599/**
 600 * fc_logo_fill - Fill in a logo request frame.
 601 */
 602static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp)
 603{
 604        struct fc_els_logo *logo;
 605
 606        logo = fc_frame_payload_get(fp, sizeof(*logo));
 607        memset(logo, 0, sizeof(*logo));
 608        logo->fl_cmd = ELS_LOGO;
 609        hton24(logo->fl_n_port_id, lport->port_id);
 610        logo->fl_n_port_wwn = htonll(lport->wwpn);
 611}
 612
 613/**
 614 * fc_rtv_fill - Fill in RTV (read timeout value) request frame.
 615 */
 616static inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp)
 617{
 618        struct fc_els_rtv *rtv;
 619
 620        rtv = fc_frame_payload_get(fp, sizeof(*rtv));
 621        memset(rtv, 0, sizeof(*rtv));
 622        rtv->rtv_cmd = ELS_RTV;
 623}
 624
 625/**
 626 * fc_rec_fill - Fill in rec request frame
 627 */
 628static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp)
 629{
 630        struct fc_els_rec *rec;
 631        struct fc_exch *ep = fc_seq_exch(fr_seq(fp));
 632
 633        rec = fc_frame_payload_get(fp, sizeof(*rec));
 634        memset(rec, 0, sizeof(*rec));
 635        rec->rec_cmd = ELS_REC;
 636        hton24(rec->rec_s_id, lport->port_id);
 637        rec->rec_ox_id = htons(ep->oxid);
 638        rec->rec_rx_id = htons(ep->rxid);
 639}
 640
 641/**
 642 * fc_prli_fill - Fill in prli request frame
 643 */
 644static inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp)
 645{
 646        struct {
 647                struct fc_els_prli prli;
 648                struct fc_els_spp spp;
 649        } *pp;
 650
 651        pp = fc_frame_payload_get(fp, sizeof(*pp));
 652        memset(pp, 0, sizeof(*pp));
 653        pp->prli.prli_cmd = ELS_PRLI;
 654        pp->prli.prli_spp_len = sizeof(struct fc_els_spp);
 655        pp->prli.prli_len = htons(sizeof(*pp));
 656        pp->spp.spp_type = FC_TYPE_FCP;
 657        pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR;
 658        pp->spp.spp_params = htonl(lport->service_params);
 659}
 660
 661/**
 662 * fc_scr_fill - Fill in a scr request frame.
 663 */
 664static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp)
 665{
 666        struct fc_els_scr *scr;
 667
 668        scr = fc_frame_payload_get(fp, sizeof(*scr));
 669        memset(scr, 0, sizeof(*scr));
 670        scr->scr_cmd = ELS_SCR;
 671        scr->scr_reg_func = ELS_SCRF_FULL;
 672}
 673
 674/**
 675 * fc_els_fill - Fill in an ELS  request frame
 676 */
 677static inline int fc_els_fill(struct fc_lport *lport,
 678                       u32 did,
 679                       struct fc_frame *fp, unsigned int op,
 680                       enum fc_rctl *r_ctl, enum fc_fh_type *fh_type)
 681{
 682        switch (op) {
 683        case ELS_ADISC:
 684                fc_adisc_fill(lport, fp);
 685                break;
 686
 687        case ELS_PLOGI:
 688                fc_plogi_fill(lport, fp, ELS_PLOGI);
 689                break;
 690
 691        case ELS_FLOGI:
 692                fc_flogi_fill(lport, fp);
 693                break;
 694
 695        case ELS_FDISC:
 696                fc_fdisc_fill(lport, fp);
 697                break;
 698
 699        case ELS_LOGO:
 700                fc_logo_fill(lport, fp);
 701                break;
 702
 703        case ELS_RTV:
 704                fc_rtv_fill(lport, fp);
 705                break;
 706
 707        case ELS_REC:
 708                fc_rec_fill(lport, fp);
 709                break;
 710
 711        case ELS_PRLI:
 712                fc_prli_fill(lport, fp);
 713                break;
 714
 715        case ELS_SCR:
 716                fc_scr_fill(lport, fp);
 717                break;
 718
 719        default:
 720                return -EINVAL;
 721        }
 722
 723        *r_ctl = FC_RCTL_ELS_REQ;
 724        *fh_type = FC_TYPE_ELS;
 725        return 0;
 726}
 727#endif /* _FC_ENCODE_H_ */
 728