diff options
Diffstat (limited to 'include/scsi/fc_encode.h')
-rw-r--r-- | include/scsi/fc_encode.h | 303 |
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 | */ | ||
215 | static 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); |