aboutsummaryrefslogtreecommitdiffstats
path: root/include/scsi/fc_encode.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/scsi/fc_encode.h')
-rw-r--r--include/scsi/fc_encode.h303
1 files changed, 303 insertions, 0 deletions
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
index 73bc43329f86..35fd4744f3e9 100644
--- a/include/scsi/fc_encode.h
+++ b/include/scsi/fc_encode.h
@@ -20,6 +20,7 @@
20#ifndef _FC_ENCODE_H_ 20#ifndef _FC_ENCODE_H_
21#define _FC_ENCODE_H_ 21#define _FC_ENCODE_H_
22#include <asm/unaligned.h> 22#include <asm/unaligned.h>
23#include <linux/utsname.h>
23 24
24/* 25/*
25 * F_CTL values for simple requests and responses. 26 * F_CTL values for simple requests and responses.
@@ -43,6 +44,10 @@ struct fc_ct_req {
43 struct fc_ns_fid fid; 44 struct fc_ns_fid fid;
44 struct fc_ns_rsnn snn; 45 struct fc_ns_rsnn snn;
45 struct fc_ns_rspn spn; 46 struct fc_ns_rspn spn;
47 struct fc_fdmi_rhba rhba;
48 struct fc_fdmi_rpa rpa;
49 struct fc_fdmi_dprt dprt;
50 struct fc_fdmi_dhba dhba;
46 } payload; 51 } payload;
47}; 52};
48 53
@@ -199,6 +204,300 @@ static inline int fc_ct_ns_fill(struct fc_lport *lport,
199} 204}
200 205
201/** 206/**
207 * fc_ct_ms_fill() - Fill in a mgmt service request frame
208 * @lport: local port.
209 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
210 * @fp: frame to contain payload.
211 * @op: CT opcode.
212 * @r_ctl: pointer to FC header R_CTL.
213 * @fh_type: pointer to FC-4 type.
214 */
215static inline int fc_ct_ms_fill(struct fc_lport *lport,
216 u32 fc_id, struct fc_frame *fp,
217 unsigned int op, enum fc_rctl *r_ctl,
218 enum fc_fh_type *fh_type)
219{
220 struct fc_ct_req *ct;
221 size_t len;
222 struct fc_fdmi_attr_entry *entry;
223 struct fs_fdmi_attrs *hba_attrs;
224 int numattrs = 0;
225
226 switch (op) {
227 case FC_FDMI_RHBA:
228 numattrs = 10;
229 len = sizeof(struct fc_fdmi_rhba);
230 len -= sizeof(struct fc_fdmi_attr_entry);
231 len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
232 len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
233 len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;
234 len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;
235 len += FC_FDMI_HBA_ATTR_MODEL_LEN;
236 len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;
237 len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;
238 len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;
239 len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
240 len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
241 len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
242 ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
243 FC_FDMI_SUBTYPE);
244
245 /* HBA Identifier */
246 put_unaligned_be64(lport->wwpn, &ct->payload.rhba.hbaid.id);
247 /* Number of Ports - always 1 */
248 put_unaligned_be32(1, &ct->payload.rhba.port.numport);
249 /* Port Name */
250 put_unaligned_be64(lport->wwpn,
251 &ct->payload.rhba.port.port[0].portname);
252
253 /* HBA Attributes */
254 put_unaligned_be32(numattrs,
255 &ct->payload.rhba.hba_attrs.numattrs);
256 hba_attrs = &ct->payload.rhba.hba_attrs;
257 entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr;
258 /* NodeName*/
259 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
260 len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
261 put_unaligned_be16(FC_FDMI_HBA_ATTR_NODENAME,
262 &entry->type);
263 put_unaligned_be16(len, &entry->len);
264 put_unaligned_be64(lport->wwnn,
265 (__be64 *)&entry->value[0]);
266
267 /* Manufacturer */
268 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
269 FC_FDMI_HBA_ATTR_NODENAME_LEN);
270 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
271 len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;
272 put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER,
273 &entry->type);
274 put_unaligned_be16(len, &entry->len);
275 strncpy((char *)&entry->value,
276 fc_host_manufacturer(lport->host),
277 FC_FDMI_HBA_ATTR_MANUFACTURER_LEN);
278
279 /* SerialNumber */
280 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
281 FC_FDMI_HBA_ATTR_MANUFACTURER_LEN);
282 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
283 len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;
284 put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER,
285 &entry->type);
286 put_unaligned_be16(len, &entry->len);
287 strncpy((char *)&entry->value,
288 fc_host_serial_number(lport->host),
289 FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN);
290
291 /* Model */
292 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
293 FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN);
294 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
295 len += FC_FDMI_HBA_ATTR_MODEL_LEN;
296 put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL,
297 &entry->type);
298 put_unaligned_be16(len, &entry->len);
299 strncpy((char *)&entry->value,
300 fc_host_model(lport->host),
301 FC_FDMI_HBA_ATTR_MODEL_LEN);
302
303 /* Model Description */
304 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
305 FC_FDMI_HBA_ATTR_MODEL_LEN);
306 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
307 len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;
308 put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION,
309 &entry->type);
310 put_unaligned_be16(len, &entry->len);
311 strncpy((char *)&entry->value,
312 fc_host_model_description(lport->host),
313 FC_FDMI_HBA_ATTR_MODELDESCR_LEN);
314
315 /* Hardware Version */
316 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
317 FC_FDMI_HBA_ATTR_MODELDESCR_LEN);
318 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
319 len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;
320 put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION,
321 &entry->type);
322 put_unaligned_be16(len, &entry->len);
323 strncpy((char *)&entry->value,
324 fc_host_hardware_version(lport->host),
325 FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN);
326
327 /* Driver Version */
328 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
329 FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN);
330 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
331 len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;
332 put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION,
333 &entry->type);
334 put_unaligned_be16(len, &entry->len);
335 strncpy((char *)&entry->value,
336 fc_host_driver_version(lport->host),
337 FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN);
338
339 /* OptionROM Version */
340 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
341 FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN);
342 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
343 len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
344 put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION,
345 &entry->type);
346 put_unaligned_be16(len, &entry->len);
347 strncpy((char *)&entry->value,
348 fc_host_optionrom_version(lport->host),
349 FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
350
351 /* Firmware Version */
352 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
353 FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
354 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
355 len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
356 put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION,
357 &entry->type);
358 put_unaligned_be16(len, &entry->len);
359 strncpy((char *)&entry->value,
360 fc_host_firmware_version(lport->host),
361 FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN);
362
363 /* OS Name and Version */
364 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
365 FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN);
366 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
367 len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
368 put_unaligned_be16(FC_FDMI_HBA_ATTR_OSNAMEVERSION,
369 &entry->type);
370 put_unaligned_be16(len, &entry->len);
371 snprintf((char *)&entry->value,
372 FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN,
373 "%s v%s",
374 init_utsname()->sysname,
375 init_utsname()->release);
376 break;
377 case FC_FDMI_RPA:
378 numattrs = 6;
379 len = sizeof(struct fc_fdmi_rpa);
380 len -= sizeof(struct fc_fdmi_attr_entry);
381 len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
382 len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
383 len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;
384 len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;
385 len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
386 len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
387 len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
388 ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
389 FC_FDMI_SUBTYPE);
390
391 /* Port Name */
392 put_unaligned_be64(lport->wwpn,
393 &ct->payload.rpa.port.portname);
394
395 /* Port Attributes */
396 put_unaligned_be32(numattrs,
397 &ct->payload.rpa.hba_attrs.numattrs);
398
399 hba_attrs = &ct->payload.rpa.hba_attrs;
400 entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr;
401
402 /* FC4 types */
403 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
404 len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
405 put_unaligned_be16(FC_FDMI_PORT_ATTR_FC4TYPES,
406 &entry->type);
407 put_unaligned_be16(len, &entry->len);
408 memcpy(&entry->value, fc_host_supported_fc4s(lport->host),
409 FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
410
411 /* Supported Speed */
412 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
413 FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
414 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
415 len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;
416 put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
417 &entry->type);
418 put_unaligned_be16(len, &entry->len);
419
420 put_unaligned_be32(fc_host_supported_speeds(lport->host),
421 &entry->value);
422
423 /* Current Port Speed */
424 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
425 FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN);
426 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
427 len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;
428 put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
429 &entry->type);
430 put_unaligned_be16(len, &entry->len);
431 put_unaligned_be32(lport->link_speed,
432 &entry->value);
433
434 /* Max Frame Size */
435 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
436 FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
437 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
438 len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
439 put_unaligned_be16(FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
440 &entry->type);
441 put_unaligned_be16(len, &entry->len);
442 put_unaligned_be32(fc_host_maxframe_size(lport->host),
443 &entry->value);
444
445 /* OS Device Name */
446 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
447 FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN);
448 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
449 len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
450 put_unaligned_be16(FC_FDMI_PORT_ATTR_OSDEVICENAME,
451 &entry->type);
452 put_unaligned_be16(len, &entry->len);
453 /* Use the sysfs device name */
454 strncpy((char *)&entry->value,
455 dev_name(&lport->host->shost_gendev),
456 strnlen(dev_name(&lport->host->shost_gendev),
457 FC_FDMI_PORT_ATTR_HOSTNAME_LEN));
458
459 /* Host Name */
460 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
461 FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN);
462 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
463 len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
464 put_unaligned_be16(FC_FDMI_PORT_ATTR_HOSTNAME,
465 &entry->type);
466 put_unaligned_be16(len, &entry->len);
467 if (strlen(fc_host_system_hostname(lport->host)))
468 strncpy((char *)&entry->value,
469 fc_host_system_hostname(lport->host),
470 strnlen(fc_host_system_hostname(lport->host),
471 FC_FDMI_PORT_ATTR_HOSTNAME_LEN));
472 else
473 strncpy((char *)&entry->value,
474 init_utsname()->nodename,
475 FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
476 break;
477 case FC_FDMI_DPRT:
478 len = sizeof(struct fc_fdmi_dprt);
479 ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
480 FC_FDMI_SUBTYPE);
481 /* Port Name */
482 put_unaligned_be64(lport->wwpn,
483 &ct->payload.dprt.port.portname);
484 break;
485 case FC_FDMI_DHBA:
486 len = sizeof(struct fc_fdmi_dhba);
487 ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
488 FC_FDMI_SUBTYPE);
489 /* HBA Identifier */
490 put_unaligned_be64(lport->wwpn, &ct->payload.dhba.hbaid.id);
491 break;
492 default:
493 return -EINVAL;
494 }
495 *r_ctl = FC_RCTL_DD_UNSOL_CTL;
496 *fh_type = FC_TYPE_CT;
497 return 0;
498}
499
500/**
202 * fc_ct_fill() - Fill in a common transport service request frame 501 * fc_ct_fill() - Fill in a common transport service request frame
203 * @lport: local port. 502 * @lport: local port.
204 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. 503 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
@@ -215,6 +514,10 @@ static inline int fc_ct_fill(struct fc_lport *lport,
215 int rc = -EINVAL; 514 int rc = -EINVAL;
216 515
217 switch (fc_id) { 516 switch (fc_id) {
517 case FC_FID_MGMT_SERV:
518 rc = fc_ct_ms_fill(lport, fc_id, fp, op, r_ctl, fh_type);
519 *did = FC_FID_MGMT_SERV;
520 break;
218 case FC_FID_DIR_SERV: 521 case FC_FID_DIR_SERV:
219 default: 522 default:
220 rc = fc_ct_ns_fill(lport, fc_id, fp, op, r_ctl, fh_type); 523 rc = fc_ct_ns_fill(lport, fc_id, fp, op, r_ctl, fh_type);