Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] libfc: Add support for FDMI

This patch adds support for Fabric Device Management
Interface as per FC-GS-4 spec. in libfc. Any driver
making use of libfc can enable fdmi state machine
for a given lport.

If lport has enabled FDMI support the lport state
machine will transition into FDMI after completing
the DNS states and before entering the SCR state.
The FDMI state transition is such that if there is an
error, it won't stop the lport state machine from
transitioning and the it will behave as if there was
no FDMI support.

The FDMI HBA attributes are registed with the Management
server via Register HBA (RHBA) command and the port
attributes are reigstered using the Register Port(RPA)
command.

Signed-off-by: Neerav Parikh <neerav.parikh@intel.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Acked-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

authored by

Neerav Parikh and committed by
James Bottomley
d78c317f 1ea2c1da

+751 -3
+224 -3
drivers/scsi/libfc/fc_lport.c
··· 116 116 static void fc_lport_enter_scr(struct fc_lport *); 117 117 static void fc_lport_enter_ready(struct fc_lport *); 118 118 static void fc_lport_enter_logo(struct fc_lport *); 119 + static void fc_lport_enter_fdmi(struct fc_lport *lport); 120 + static void fc_lport_enter_ms(struct fc_lport *, enum fc_lport_state); 119 121 120 122 static const char *fc_lport_state_names[] = { 121 123 [LPORT_ST_DISABLED] = "disabled", ··· 128 126 [LPORT_ST_RSPN_ID] = "RSPN_ID", 129 127 [LPORT_ST_RFT_ID] = "RFT_ID", 130 128 [LPORT_ST_RFF_ID] = "RFF_ID", 129 + [LPORT_ST_FDMI] = "FDMI", 130 + [LPORT_ST_RHBA] = "RHBA", 131 + [LPORT_ST_RPA] = "RPA", 132 + [LPORT_ST_DHBA] = "DHBA", 133 + [LPORT_ST_DPRT] = "DPRT", 131 134 [LPORT_ST_SCR] = "SCR", 132 135 [LPORT_ST_READY] = "Ready", 133 136 [LPORT_ST_LOGO] = "LOGO", ··· 190 183 if (lport->state == LPORT_ST_DNS) { 191 184 lport->dns_rdata = rdata; 192 185 fc_lport_enter_ns(lport, LPORT_ST_RNN_ID); 186 + } else if (lport->state == LPORT_ST_FDMI) { 187 + lport->ms_rdata = rdata; 188 + fc_lport_enter_ms(lport, LPORT_ST_DHBA); 193 189 } else { 194 190 FC_LPORT_DBG(lport, "Received an READY event " 195 191 "on port (%6.6x) for the directory " 196 192 "server, but the lport is not " 197 - "in the DNS state, it's in the " 193 + "in the DNS or FDMI state, it's in the " 198 194 "%d state", rdata->ids.port_id, 199 195 lport->state); 200 196 lport->tt.rport_logoff(rdata); ··· 206 196 case RPORT_EV_LOGO: 207 197 case RPORT_EV_FAILED: 208 198 case RPORT_EV_STOP: 209 - lport->dns_rdata = NULL; 199 + if (rdata->ids.port_id == FC_FID_DIR_SERV) 200 + lport->dns_rdata = NULL; 201 + else if (rdata->ids.port_id == FC_FID_MGMT_SERV) 202 + lport->ms_rdata = NULL; 210 203 break; 211 204 case RPORT_EV_NONE: 212 205 break; ··· 1161 1148 fc_lport_enter_ns(lport, LPORT_ST_RFF_ID); 1162 1149 break; 1163 1150 case LPORT_ST_RFF_ID: 1164 - fc_lport_enter_scr(lport); 1151 + if (lport->fdmi_enabled) 1152 + fc_lport_enter_fdmi(lport); 1153 + else 1154 + fc_lport_enter_scr(lport); 1165 1155 break; 1166 1156 default: 1167 1157 /* should have already been caught by state checks */ ··· 1172 1156 } 1173 1157 else 1174 1158 fc_lport_error(lport, fp); 1159 + out: 1160 + fc_frame_free(fp); 1161 + err: 1162 + mutex_unlock(&lport->lp_mutex); 1163 + } 1164 + 1165 + /** 1166 + * fc_lport_ms_resp() - Handle response to a management server 1167 + * exchange 1168 + * @sp: current sequence in exchange 1169 + * @fp: response frame 1170 + * @lp_arg: Fibre Channel host port instance 1171 + * 1172 + * Locking Note: This function will be called without the lport lock 1173 + * held, but it will lock, call an _enter_* function or fc_lport_error() 1174 + * and then unlock the lport. 1175 + */ 1176 + static void fc_lport_ms_resp(struct fc_seq *sp, struct fc_frame *fp, 1177 + void *lp_arg) 1178 + { 1179 + struct fc_lport *lport = lp_arg; 1180 + struct fc_frame_header *fh; 1181 + struct fc_ct_hdr *ct; 1182 + 1183 + FC_LPORT_DBG(lport, "Received a ms %s\n", fc_els_resp_type(fp)); 1184 + 1185 + if (fp == ERR_PTR(-FC_EX_CLOSED)) 1186 + return; 1187 + 1188 + mutex_lock(&lport->lp_mutex); 1189 + 1190 + if (lport->state < LPORT_ST_RHBA || lport->state > LPORT_ST_DPRT) { 1191 + FC_LPORT_DBG(lport, "Received a management server response, " 1192 + "but in state %s\n", fc_lport_state(lport)); 1193 + if (IS_ERR(fp)) 1194 + goto err; 1195 + goto out; 1196 + } 1197 + 1198 + if (IS_ERR(fp)) { 1199 + fc_lport_error(lport, fp); 1200 + goto err; 1201 + } 1202 + 1203 + fh = fc_frame_header_get(fp); 1204 + ct = fc_frame_payload_get(fp, sizeof(*ct)); 1205 + 1206 + if (fh && ct && fh->fh_type == FC_TYPE_CT && 1207 + ct->ct_fs_type == FC_FST_MGMT && 1208 + ct->ct_fs_subtype == FC_FDMI_SUBTYPE) { 1209 + FC_LPORT_DBG(lport, "Received a management server response, " 1210 + "reason=%d explain=%d\n", 1211 + ct->ct_reason, 1212 + ct->ct_explan); 1213 + 1214 + switch (lport->state) { 1215 + case LPORT_ST_RHBA: 1216 + if (ntohs(ct->ct_cmd) == FC_FS_ACC) 1217 + fc_lport_enter_ms(lport, LPORT_ST_RPA); 1218 + else /* Error Skip RPA */ 1219 + fc_lport_enter_scr(lport); 1220 + break; 1221 + case LPORT_ST_RPA: 1222 + fc_lport_enter_scr(lport); 1223 + break; 1224 + case LPORT_ST_DPRT: 1225 + fc_lport_enter_ms(lport, LPORT_ST_RHBA); 1226 + break; 1227 + case LPORT_ST_DHBA: 1228 + fc_lport_enter_ms(lport, LPORT_ST_DPRT); 1229 + break; 1230 + default: 1231 + /* should have already been caught by state checks */ 1232 + break; 1233 + } 1234 + } else { 1235 + /* Invalid Frame? */ 1236 + fc_lport_error(lport, fp); 1237 + } 1175 1238 out: 1176 1239 fc_frame_free(fp); 1177 1240 err: ··· 1434 1339 } 1435 1340 1436 1341 /** 1342 + * fc_lport_enter_ms() - management server commands 1343 + * @lport: Fibre Channel local port to register 1344 + * 1345 + * Locking Note: The lport lock is expected to be held before calling 1346 + * this routine. 1347 + */ 1348 + static void fc_lport_enter_ms(struct fc_lport *lport, enum fc_lport_state state) 1349 + { 1350 + struct fc_frame *fp; 1351 + enum fc_fdmi_req cmd; 1352 + int size = sizeof(struct fc_ct_hdr); 1353 + size_t len; 1354 + int numattrs; 1355 + 1356 + FC_LPORT_DBG(lport, "Entered %s state from %s state\n", 1357 + fc_lport_state_names[state], 1358 + fc_lport_state(lport)); 1359 + 1360 + fc_lport_state_enter(lport, state); 1361 + 1362 + switch (state) { 1363 + case LPORT_ST_RHBA: 1364 + cmd = FC_FDMI_RHBA; 1365 + /* Number of HBA Attributes */ 1366 + numattrs = 10; 1367 + len = sizeof(struct fc_fdmi_rhba); 1368 + len -= sizeof(struct fc_fdmi_attr_entry); 1369 + len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN); 1370 + len += FC_FDMI_HBA_ATTR_NODENAME_LEN; 1371 + len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN; 1372 + len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN; 1373 + len += FC_FDMI_HBA_ATTR_MODEL_LEN; 1374 + len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN; 1375 + len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN; 1376 + len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN; 1377 + len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN; 1378 + len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN; 1379 + len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN; 1380 + 1381 + size += len; 1382 + break; 1383 + case LPORT_ST_RPA: 1384 + cmd = FC_FDMI_RPA; 1385 + /* Number of Port Attributes */ 1386 + numattrs = 6; 1387 + len = sizeof(struct fc_fdmi_rpa); 1388 + len -= sizeof(struct fc_fdmi_attr_entry); 1389 + len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN); 1390 + len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN; 1391 + len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN; 1392 + len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN; 1393 + len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN; 1394 + len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN; 1395 + len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN; 1396 + 1397 + size += len; 1398 + break; 1399 + case LPORT_ST_DPRT: 1400 + cmd = FC_FDMI_DPRT; 1401 + len = sizeof(struct fc_fdmi_dprt); 1402 + size += len; 1403 + break; 1404 + case LPORT_ST_DHBA: 1405 + cmd = FC_FDMI_DHBA; 1406 + len = sizeof(struct fc_fdmi_dhba); 1407 + size += len; 1408 + break; 1409 + default: 1410 + fc_lport_error(lport, NULL); 1411 + return; 1412 + } 1413 + 1414 + FC_LPORT_DBG(lport, "Cmd=0x%x Len %d size %d\n", 1415 + cmd, (int)len, size); 1416 + fp = fc_frame_alloc(lport, size); 1417 + if (!fp) { 1418 + fc_lport_error(lport, fp); 1419 + return; 1420 + } 1421 + 1422 + if (!lport->tt.elsct_send(lport, FC_FID_MGMT_SERV, fp, cmd, 1423 + fc_lport_ms_resp, 1424 + lport, 3 * lport->r_a_tov)) 1425 + fc_lport_error(lport, fp); 1426 + } 1427 + 1428 + /** 1429 + * fc_rport_enter_fdmi() - Create a fc_rport for the management server 1430 + * @lport: The local port requesting a remote port for the management server 1431 + * 1432 + * Locking Note: The lport lock is expected to be held before calling 1433 + * this routine. 1434 + */ 1435 + static void fc_lport_enter_fdmi(struct fc_lport *lport) 1436 + { 1437 + struct fc_rport_priv *rdata; 1438 + 1439 + FC_LPORT_DBG(lport, "Entered FDMI state from %s state\n", 1440 + fc_lport_state(lport)); 1441 + 1442 + fc_lport_state_enter(lport, LPORT_ST_FDMI); 1443 + 1444 + mutex_lock(&lport->disc.disc_mutex); 1445 + rdata = lport->tt.rport_create(lport, FC_FID_MGMT_SERV); 1446 + mutex_unlock(&lport->disc.disc_mutex); 1447 + if (!rdata) 1448 + goto err; 1449 + 1450 + rdata->ops = &fc_lport_rport_ops; 1451 + lport->tt.rport_login(rdata); 1452 + return; 1453 + 1454 + err: 1455 + fc_lport_error(lport, NULL); 1456 + } 1457 + 1458 + /** 1437 1459 * fc_lport_timeout() - Handler for the retry_work timer 1438 1460 * @work: The work struct of the local port 1439 1461 */ ··· 1582 1370 case LPORT_ST_RFT_ID: 1583 1371 case LPORT_ST_RFF_ID: 1584 1372 fc_lport_enter_ns(lport, lport->state); 1373 + break; 1374 + case LPORT_ST_FDMI: 1375 + fc_lport_enter_fdmi(lport); 1376 + break; 1377 + case LPORT_ST_RHBA: 1378 + case LPORT_ST_RPA: 1379 + case LPORT_ST_DHBA: 1380 + case LPORT_ST_DPRT: 1381 + fc_lport_enter_ms(lport, lport->state); 1585 1382 break; 1586 1383 case LPORT_ST_SCR: 1587 1384 fc_lport_enter_scr(lport);
+213
include/scsi/fc/fc_ms.h
··· 1 + /* * Copyright(c) 2011 Intel Corporation. All rights reserved. 2 + * 3 + * This program is free software; you can redistribute it and/or modify it 4 + * under the terms and conditions of the GNU General Public License, 5 + * version 2, as published by the Free Software Foundation. 6 + * 7 + * This program is distributed in the hope it will be useful, but WITHOUT 8 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 9 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 10 + * more details. 11 + * 12 + * You should have received a copy of the GNU General Public License along with 13 + * this program; if not, write to the Free Software Foundation, Inc., 14 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 15 + * 16 + * Maintained at www.Open-FCoE.org 17 + */ 18 + 19 + #ifndef _FC_MS_H_ 20 + #define _FC_MS_H_ 21 + 22 + #include <linux/types.h> 23 + 24 + /* 25 + * Fibre Channel Services - Management Service (MS) 26 + * From T11.org FC-GS-4 Rev 7.91 February 4, 2004 27 + */ 28 + 29 + /* 30 + * Fabric Device Management Interface 31 + */ 32 + 33 + /* 34 + * Common-transport sub-type for FDMI 35 + */ 36 + #define FC_FDMI_SUBTYPE 0x10 /* fs_ct_hdr.ct_fs_subtype */ 37 + 38 + /* 39 + * Management server FDMI Requests. 40 + */ 41 + enum fc_fdmi_req { 42 + FC_FDMI_GRHL = 0x0100, /* Get Registered HBA List */ 43 + FC_FDMI_GHAT = 0x0101, /* Get HBA Attributes */ 44 + FC_FDMI_GRPL = 0x0102, /* Get Registered Port List */ 45 + FC_FDMI_GPAT = 0x0110, /* Get Port Attributes */ 46 + FC_FDMI_RHBA = 0x0200, /* Register HBA */ 47 + FC_FDMI_RHAT = 0x0201, /* Register HBA Attributes */ 48 + FC_FDMI_RPRT = 0x0210, /* Register Port */ 49 + FC_FDMI_RPA = 0x0211, /* Register Port Attributes */ 50 + FC_FDMI_DHBA = 0x0300, /* Deregister HBA */ 51 + FC_FDMI_DHAT = 0x0301, /* Deregister HBA Attributes */ 52 + FC_FDMI_DPRT = 0x0310, /* Deregister Port */ 53 + FC_FDMI_DPA = 0x0311, /* Deregister Port Attributes */ 54 + }; 55 + 56 + /* 57 + * HBA Attribute Entry Type 58 + */ 59 + enum fc_fdmi_hba_attr_type { 60 + FC_FDMI_HBA_ATTR_NODENAME = 0x0001, 61 + FC_FDMI_HBA_ATTR_MANUFACTURER = 0x0002, 62 + FC_FDMI_HBA_ATTR_SERIALNUMBER = 0x0003, 63 + FC_FDMI_HBA_ATTR_MODEL = 0x0004, 64 + FC_FDMI_HBA_ATTR_MODELDESCRIPTION = 0x0005, 65 + FC_FDMI_HBA_ATTR_HARDWAREVERSION = 0x0006, 66 + FC_FDMI_HBA_ATTR_DRIVERVERSION = 0x0007, 67 + FC_FDMI_HBA_ATTR_OPTIONROMVERSION = 0x0008, 68 + FC_FDMI_HBA_ATTR_FIRMWAREVERSION = 0x0009, 69 + FC_FDMI_HBA_ATTR_OSNAMEVERSION = 0x000A, 70 + FC_FDMI_HBA_ATTR_MAXCTPAYLOAD = 0x000B, 71 + }; 72 + 73 + /* 74 + * HBA Attribute Length 75 + */ 76 + #define FC_FDMI_HBA_ATTR_NODENAME_LEN 8 77 + #define FC_FDMI_HBA_ATTR_MANUFACTURER_LEN 64 78 + #define FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN 64 79 + #define FC_FDMI_HBA_ATTR_MODEL_LEN 256 80 + #define FC_FDMI_HBA_ATTR_MODELDESCR_LEN 256 81 + #define FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN 256 82 + #define FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN 256 83 + #define FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN 256 84 + #define FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN 256 85 + #define FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN 256 86 + #define FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN 4 87 + 88 + /* 89 + * Port Attribute Type 90 + */ 91 + enum fc_fdmi_port_attr_type { 92 + FC_FDMI_PORT_ATTR_FC4TYPES = 0x0001, 93 + FC_FDMI_PORT_ATTR_SUPPORTEDSPEED = 0x0002, 94 + FC_FDMI_PORT_ATTR_CURRENTPORTSPEED = 0x0003, 95 + FC_FDMI_PORT_ATTR_MAXFRAMESIZE = 0x0004, 96 + FC_FDMI_PORT_ATTR_OSDEVICENAME = 0x0005, 97 + FC_FDMI_PORT_ATTR_HOSTNAME = 0x0006, 98 + }; 99 + 100 + /* 101 + * Port Attribute Length 102 + */ 103 + #define FC_FDMI_PORT_ATTR_FC4TYPES_LEN 32 104 + #define FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN 4 105 + #define FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN 4 106 + #define FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN 4 107 + #define FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN 256 108 + #define FC_FDMI_PORT_ATTR_HOSTNAME_LEN 256 109 + 110 + /* 111 + * HBA Attribute ID 112 + */ 113 + struct fc_fdmi_hba_identifier { 114 + __be64 id; 115 + }; 116 + 117 + /* 118 + * Port Name 119 + */ 120 + struct fc_fdmi_port_name { 121 + __be64 portname; 122 + }; 123 + 124 + /* 125 + * Attribute Entry Block for HBA/Port Attributes 126 + */ 127 + #define FC_FDMI_ATTR_ENTRY_HEADER_LEN 4 128 + struct fc_fdmi_attr_entry { 129 + __be16 type; 130 + __be16 len; 131 + __u8 value[1]; 132 + } __attribute__((__packed__)); 133 + 134 + /* 135 + * Common for HBA/Port Attributes 136 + */ 137 + struct fs_fdmi_attrs { 138 + __be32 numattrs; 139 + struct fc_fdmi_attr_entry attr[1]; 140 + } __attribute__((__packed__)); 141 + 142 + /* 143 + * Registered Port List 144 + */ 145 + struct fc_fdmi_rpl { 146 + __be32 numport; 147 + struct fc_fdmi_port_name port[1]; 148 + } __attribute__((__packed__)); 149 + 150 + /* 151 + * Register HBA (RHBA) 152 + */ 153 + struct fc_fdmi_rhba { 154 + struct fc_fdmi_hba_identifier hbaid; 155 + struct fc_fdmi_rpl port; 156 + struct fs_fdmi_attrs hba_attrs; 157 + } __attribute__((__packed__)); 158 + 159 + /* 160 + * Register HBA Attributes (RHAT) 161 + */ 162 + struct fc_fdmi_rhat { 163 + struct fc_fdmi_hba_identifier hbaid; 164 + struct fs_fdmi_attrs hba_attrs; 165 + } __attribute__((__packed__)); 166 + 167 + /* 168 + * Register Port (RPRT) 169 + */ 170 + struct fc_fdmi_rprt { 171 + struct fc_fdmi_hba_identifier hbaid; 172 + struct fc_fdmi_port_name port; 173 + struct fs_fdmi_attrs hba_attrs; 174 + } __attribute__((__packed__)); 175 + 176 + /* 177 + * Register Port Attributes (RPA) 178 + */ 179 + struct fc_fdmi_rpa { 180 + struct fc_fdmi_port_name port; 181 + struct fs_fdmi_attrs hba_attrs; 182 + } __attribute__((__packed__)); 183 + 184 + /* 185 + * Deregister Port (DPRT) 186 + */ 187 + struct fc_fdmi_dprt { 188 + struct fc_fdmi_port_name port; 189 + } __attribute__((__packed__)); 190 + 191 + /* 192 + * Deregister Port Attributes (DPA) 193 + */ 194 + struct fc_fdmi_dpa { 195 + struct fc_fdmi_port_name port; 196 + struct fs_fdmi_attrs hba_attrs; 197 + } __attribute__((__packed__)); 198 + 199 + /* 200 + * Deregister HBA Attributes (DHAT) 201 + */ 202 + struct fc_fdmi_dhat { 203 + struct fc_fdmi_hba_identifier hbaid; 204 + } __attribute__((__packed__)); 205 + 206 + /* 207 + * Deregister HBA (DHBA) 208 + */ 209 + struct fc_fdmi_dhba { 210 + struct fc_fdmi_hba_identifier hbaid; 211 + } __attribute__((__packed__)); 212 + 213 + #endif /* _FC_MS_H_ */
+303
include/scsi/fc_encode.h
··· 20 20 #ifndef _FC_ENCODE_H_ 21 21 #define _FC_ENCODE_H_ 22 22 #include <asm/unaligned.h> 23 + #include <linux/utsname.h> 23 24 24 25 /* 25 26 * F_CTL values for simple requests and responses. ··· 44 43 struct fc_ns_fid fid; 45 44 struct fc_ns_rsnn snn; 46 45 struct fc_ns_rspn spn; 46 + struct fc_fdmi_rhba rhba; 47 + struct fc_fdmi_rpa rpa; 48 + struct fc_fdmi_dprt dprt; 49 + struct fc_fdmi_dhba dhba; 47 50 } payload; 48 51 }; 49 52 ··· 204 199 } 205 200 206 201 /** 202 + * fc_ct_ms_fill() - Fill in a mgmt service request frame 203 + * @lport: local port. 204 + * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. 205 + * @fp: frame to contain payload. 206 + * @op: CT opcode. 207 + * @r_ctl: pointer to FC header R_CTL. 208 + * @fh_type: pointer to FC-4 type. 209 + */ 210 + static inline int fc_ct_ms_fill(struct fc_lport *lport, 211 + u32 fc_id, struct fc_frame *fp, 212 + unsigned int op, enum fc_rctl *r_ctl, 213 + enum fc_fh_type *fh_type) 214 + { 215 + struct fc_ct_req *ct; 216 + size_t len; 217 + struct fc_fdmi_attr_entry *entry; 218 + struct fs_fdmi_attrs *hba_attrs; 219 + int numattrs = 0; 220 + 221 + switch (op) { 222 + case FC_FDMI_RHBA: 223 + numattrs = 10; 224 + len = sizeof(struct fc_fdmi_rhba); 225 + len -= sizeof(struct fc_fdmi_attr_entry); 226 + len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN); 227 + len += FC_FDMI_HBA_ATTR_NODENAME_LEN; 228 + len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN; 229 + len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN; 230 + len += FC_FDMI_HBA_ATTR_MODEL_LEN; 231 + len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN; 232 + len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN; 233 + len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN; 234 + len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN; 235 + len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN; 236 + len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN; 237 + ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, 238 + FC_FDMI_SUBTYPE); 239 + 240 + /* HBA Identifier */ 241 + put_unaligned_be64(lport->wwpn, &ct->payload.rhba.hbaid.id); 242 + /* Number of Ports - always 1 */ 243 + put_unaligned_be32(1, &ct->payload.rhba.port.numport); 244 + /* Port Name */ 245 + put_unaligned_be64(lport->wwpn, 246 + &ct->payload.rhba.port.port[0].portname); 247 + 248 + /* HBA Attributes */ 249 + put_unaligned_be32(numattrs, 250 + &ct->payload.rhba.hba_attrs.numattrs); 251 + hba_attrs = &ct->payload.rhba.hba_attrs; 252 + entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr; 253 + /* NodeName*/ 254 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 255 + len += FC_FDMI_HBA_ATTR_NODENAME_LEN; 256 + put_unaligned_be16(FC_FDMI_HBA_ATTR_NODENAME, 257 + &entry->type); 258 + put_unaligned_be16(len, &entry->len); 259 + put_unaligned_be64(lport->wwnn, 260 + (__be64 *)&entry->value[0]); 261 + 262 + /* Manufacturer */ 263 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 264 + FC_FDMI_HBA_ATTR_NODENAME_LEN); 265 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 266 + len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN; 267 + put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER, 268 + &entry->type); 269 + put_unaligned_be16(len, &entry->len); 270 + strncpy((char *)&entry->value, 271 + fc_host_manufacturer(lport->host), 272 + FC_FDMI_HBA_ATTR_MANUFACTURER_LEN); 273 + 274 + /* SerialNumber */ 275 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 276 + FC_FDMI_HBA_ATTR_MANUFACTURER_LEN); 277 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 278 + len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN; 279 + put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER, 280 + &entry->type); 281 + put_unaligned_be16(len, &entry->len); 282 + strncpy((char *)&entry->value, 283 + fc_host_serial_number(lport->host), 284 + FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN); 285 + 286 + /* Model */ 287 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 288 + FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN); 289 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 290 + len += FC_FDMI_HBA_ATTR_MODEL_LEN; 291 + put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL, 292 + &entry->type); 293 + put_unaligned_be16(len, &entry->len); 294 + strncpy((char *)&entry->value, 295 + fc_host_model(lport->host), 296 + FC_FDMI_HBA_ATTR_MODEL_LEN); 297 + 298 + /* Model Description */ 299 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 300 + FC_FDMI_HBA_ATTR_MODEL_LEN); 301 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 302 + len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN; 303 + put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION, 304 + &entry->type); 305 + put_unaligned_be16(len, &entry->len); 306 + strncpy((char *)&entry->value, 307 + fc_host_model_description(lport->host), 308 + FC_FDMI_HBA_ATTR_MODELDESCR_LEN); 309 + 310 + /* Hardware Version */ 311 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 312 + FC_FDMI_HBA_ATTR_MODELDESCR_LEN); 313 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 314 + len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN; 315 + put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION, 316 + &entry->type); 317 + put_unaligned_be16(len, &entry->len); 318 + strncpy((char *)&entry->value, 319 + fc_host_hardware_version(lport->host), 320 + FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN); 321 + 322 + /* Driver Version */ 323 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 324 + FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN); 325 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 326 + len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN; 327 + put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION, 328 + &entry->type); 329 + put_unaligned_be16(len, &entry->len); 330 + strncpy((char *)&entry->value, 331 + fc_host_driver_version(lport->host), 332 + FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN); 333 + 334 + /* OptionROM Version */ 335 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 336 + FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN); 337 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 338 + len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN; 339 + put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION, 340 + &entry->type); 341 + put_unaligned_be16(len, &entry->len); 342 + strncpy((char *)&entry->value, 343 + fc_host_optionrom_version(lport->host), 344 + FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN); 345 + 346 + /* Firmware Version */ 347 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 348 + FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN); 349 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 350 + len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN; 351 + put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION, 352 + &entry->type); 353 + put_unaligned_be16(len, &entry->len); 354 + strncpy((char *)&entry->value, 355 + fc_host_firmware_version(lport->host), 356 + FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN); 357 + 358 + /* OS Name and Version */ 359 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 360 + FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN); 361 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 362 + len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN; 363 + put_unaligned_be16(FC_FDMI_HBA_ATTR_OSNAMEVERSION, 364 + &entry->type); 365 + put_unaligned_be16(len, &entry->len); 366 + snprintf((char *)&entry->value, 367 + FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN, 368 + "%s v%s", 369 + init_utsname()->sysname, 370 + init_utsname()->release); 371 + break; 372 + case FC_FDMI_RPA: 373 + numattrs = 6; 374 + len = sizeof(struct fc_fdmi_rpa); 375 + len -= sizeof(struct fc_fdmi_attr_entry); 376 + len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN); 377 + len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN; 378 + len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN; 379 + len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN; 380 + len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN; 381 + len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN; 382 + len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN; 383 + ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, 384 + FC_FDMI_SUBTYPE); 385 + 386 + /* Port Name */ 387 + put_unaligned_be64(lport->wwpn, 388 + &ct->payload.rpa.port.portname); 389 + 390 + /* Port Attributes */ 391 + put_unaligned_be32(numattrs, 392 + &ct->payload.rpa.hba_attrs.numattrs); 393 + 394 + hba_attrs = &ct->payload.rpa.hba_attrs; 395 + entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr; 396 + 397 + /* FC4 types */ 398 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 399 + len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN; 400 + put_unaligned_be16(FC_FDMI_PORT_ATTR_FC4TYPES, 401 + &entry->type); 402 + put_unaligned_be16(len, &entry->len); 403 + memcpy(&entry->value, fc_host_supported_fc4s(lport->host), 404 + FC_FDMI_PORT_ATTR_FC4TYPES_LEN); 405 + 406 + /* Supported Speed */ 407 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 408 + FC_FDMI_PORT_ATTR_FC4TYPES_LEN); 409 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 410 + len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN; 411 + put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED, 412 + &entry->type); 413 + put_unaligned_be16(len, &entry->len); 414 + 415 + put_unaligned_be32(fc_host_supported_speeds(lport->host), 416 + &entry->value); 417 + 418 + /* Current Port Speed */ 419 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 420 + FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN); 421 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 422 + len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN; 423 + put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED, 424 + &entry->type); 425 + put_unaligned_be16(len, &entry->len); 426 + put_unaligned_be32(lport->link_speed, 427 + &entry->value); 428 + 429 + /* Max Frame Size */ 430 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 431 + FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN); 432 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 433 + len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN; 434 + put_unaligned_be16(FC_FDMI_PORT_ATTR_MAXFRAMESIZE, 435 + &entry->type); 436 + put_unaligned_be16(len, &entry->len); 437 + put_unaligned_be32(fc_host_maxframe_size(lport->host), 438 + &entry->value); 439 + 440 + /* OS Device Name */ 441 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 442 + FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN); 443 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 444 + len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN; 445 + put_unaligned_be16(FC_FDMI_PORT_ATTR_OSDEVICENAME, 446 + &entry->type); 447 + put_unaligned_be16(len, &entry->len); 448 + /* Use the sysfs device name */ 449 + strncpy((char *)&entry->value, 450 + dev_name(&lport->host->shost_gendev), 451 + strnlen(dev_name(&lport->host->shost_gendev), 452 + FC_FDMI_PORT_ATTR_HOSTNAME_LEN)); 453 + 454 + /* Host Name */ 455 + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 456 + FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN); 457 + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 458 + len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN; 459 + put_unaligned_be16(FC_FDMI_PORT_ATTR_HOSTNAME, 460 + &entry->type); 461 + put_unaligned_be16(len, &entry->len); 462 + if (strlen(fc_host_system_hostname(lport->host))) 463 + strncpy((char *)&entry->value, 464 + fc_host_system_hostname(lport->host), 465 + strnlen(fc_host_system_hostname(lport->host), 466 + FC_FDMI_PORT_ATTR_HOSTNAME_LEN)); 467 + else 468 + strncpy((char *)&entry->value, 469 + init_utsname()->nodename, 470 + FC_FDMI_PORT_ATTR_HOSTNAME_LEN); 471 + break; 472 + case FC_FDMI_DPRT: 473 + len = sizeof(struct fc_fdmi_dprt); 474 + ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, 475 + FC_FDMI_SUBTYPE); 476 + /* Port Name */ 477 + put_unaligned_be64(lport->wwpn, 478 + &ct->payload.dprt.port.portname); 479 + break; 480 + case FC_FDMI_DHBA: 481 + len = sizeof(struct fc_fdmi_dhba); 482 + ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, 483 + FC_FDMI_SUBTYPE); 484 + /* HBA Identifier */ 485 + put_unaligned_be64(lport->wwpn, &ct->payload.dhba.hbaid.id); 486 + break; 487 + default: 488 + return -EINVAL; 489 + } 490 + *r_ctl = FC_RCTL_DD_UNSOL_CTL; 491 + *fh_type = FC_TYPE_CT; 492 + return 0; 493 + } 494 + 495 + /** 207 496 * fc_ct_fill() - Fill in a common transport service request frame 208 497 * @lport: local port. 209 498 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. ··· 514 215 int rc = -EINVAL; 515 216 516 217 switch (fc_id) { 218 + case FC_FID_MGMT_SERV: 219 + rc = fc_ct_ms_fill(lport, fc_id, fp, op, r_ctl, fh_type); 220 + *did = FC_FID_MGMT_SERV; 221 + break; 517 222 case FC_FID_DIR_SERV: 518 223 default: 519 224 rc = fc_ct_ns_fill(lport, fc_id, fp, op, r_ctl, fh_type);
+11
include/scsi/libfc.h
··· 30 30 31 31 #include <scsi/fc/fc_fcp.h> 32 32 #include <scsi/fc/fc_ns.h> 33 + #include <scsi/fc/fc_ms.h> 33 34 #include <scsi/fc/fc_els.h> 34 35 #include <scsi/fc/fc_gs.h> 35 36 ··· 53 52 * @LPORT_ST_RPN_ID: Register port name by ID (RPN_ID) sent 54 53 * @LPORT_ST_RFT_ID: Register Fibre Channel types by ID (RFT_ID) sent 55 54 * @LPORT_ST_RFF_ID: Register FC-4 Features by ID (RFF_ID) sent 55 + * @LPORT_ST_FDMI: Waiting for mgmt server rport to become ready 56 + * @LPORT_ST_RHBA: 56 57 * @LPORT_ST_SCR: State Change Register (SCR) sent 57 58 * @LPORT_ST_READY: Ready for use 58 59 * @LPORT_ST_LOGO: Local port logout (LOGO) sent ··· 69 66 LPORT_ST_RSPN_ID, 70 67 LPORT_ST_RFT_ID, 71 68 LPORT_ST_RFF_ID, 69 + LPORT_ST_FDMI, 70 + LPORT_ST_RHBA, 71 + LPORT_ST_RPA, 72 + LPORT_ST_DHBA, 73 + LPORT_ST_DPRT, 72 74 LPORT_ST_SCR, 73 75 LPORT_ST_READY, 74 76 LPORT_ST_LOGO, ··· 805 797 * @host: The SCSI host associated with a local port 806 798 * @ema_list: Exchange manager anchor list 807 799 * @dns_rdata: The directory server remote port 800 + * @ms_rdata: The management server remote port 808 801 * @ptp_rdata: Point to point remote port 809 802 * @scsi_priv: FCP layer internal data 810 803 * @disc: Discovery context ··· 851 842 struct Scsi_Host *host; 852 843 struct list_head ema_list; 853 844 struct fc_rport_priv *dns_rdata; 845 + struct fc_rport_priv *ms_rdata; 854 846 struct fc_rport_priv *ptp_rdata; 855 847 void *scsi_priv; 856 848 struct fc_disc disc; ··· 887 877 u32 does_npiv:1; 888 878 u32 npiv_enabled:1; 889 879 u32 point_to_multipoint:1; 880 + u32 fdmi_enabled:1; 890 881 u32 mfs; 891 882 u8 max_retry_count; 892 883 u8 max_rport_retry_count;