2
* Copyright (c) 2008, Intel Corporation.
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.
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
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.
21
#include "adapt_impl.h"
23
#ifndef HBA_STATUS_ERROR_ILLEGAL_FCID
24
#define HBA_STATUS_ERROR_ILLEGAL_FCID 33 /* defined after HBA-API 2.2 */
26
#define SEND_CT_TIMEOUT (3 * 1000) /* timeout in milliseconds */
29
* The following are temporary settings until we can find a way to
30
* collect these information.
32
#define HBA_ROM_VERSION ""
33
#define HBA_FW_VERSION ""
34
#define HBA_VENDOR_SPECIFIC_ID 0
37
* Convert fc_port_type values to ascii string name.
38
* (This table is copied from scsi_transport_fc.c).
41
enum fc_port_type value;
43
} port_types_table[] = {
44
{ FC_PORTTYPE_UNKNOWN, "Unknown" },
45
{ FC_PORTTYPE_OTHER, "Other" },
46
{ FC_PORTTYPE_NOTPRESENT, "Not Present" },
47
{ FC_PORTTYPE_NPORT, "NPort (fabric via point-to-point)" },
48
{ FC_PORTTYPE_NLPORT, "NLPort (fabric via loop)" },
49
{ FC_PORTTYPE_LPORT, "LPort (private loop)" },
50
{ FC_PORTTYPE_PTP, "Point-To-Point (direct nport connection)" },
51
{ FC_PORTTYPE_NPIV, "NPIV VPORT" },
53
fc_enum_name_search(port_type, fc_port_type, port_types_table)
54
#define FC_PORTTYPE_MAX_NAMELEN 50
57
* table of /sys port state strings to HBA-API values.
59
struct sa_nameval port_states_table[] = {
60
{ "Not Present", HBA_PORTSTATE_UNKNOWN },
61
{ "Online", HBA_PORTSTATE_ONLINE },
62
{ "Offline", HBA_PORTSTATE_OFFLINE },
63
{ "Blocked", HBA_PORTSTATE_UNKNOWN },
64
{ "Bypassed", HBA_PORTSTATE_BYPASSED },
65
{ "Diagnostics", HBA_PORTSTATE_DIAGNOSTICS },
66
{ "Linkdown", HBA_PORTSTATE_LINKDOWN },
67
{ "Error", HBA_PORTSTATE_ERROR },
68
{ "Loopback", HBA_PORTSTATE_LOOPBACK },
69
{ "Deleted", HBA_PORTSTATE_UNKNOWN },
74
* table of /sys port speed strings to HBA-API values.
76
struct sa_nameval port_speeds_table[] = {
77
{ "10 Gbit", HBA_PORTSPEED_10GBIT },
78
{ "2 Gbit", HBA_PORTSPEED_2GBIT },
79
{ "1 Gbit", HBA_PORTSPEED_1GBIT },
80
{ "Not Negotiated", HBA_PORTSPEED_NOT_NEGOTIATED },
81
{ "Unknown", HBA_PORTSPEED_UNKNOWN },
86
* Code for OpenFC-supported adapters.
90
counting_rports(struct dirent *dp, void *arg)
92
int *count = (int *)arg;
94
if (!strstr(dp->d_name, "rport-"))
101
check_ifmac(struct dirent *dp, void *arg)
103
char *address = (char *)arg;
108
snprintf(hba_dir, sizeof(hba_dir),
109
SYSFS_HBA_DIR "/%s", dp->d_name);
110
i = readlink(hba_dir, buf, sizeof(buf) - 1);
112
printf("readlink %s failed\n", hba_dir);
116
if (strstr(buf, "/virtual/net/"))
117
return 0; /* skip virtual devices */
119
memset(buf, 0, sizeof(buf));
120
rc = sa_sys_read_line(hba_dir, "address", buf, sizeof(buf));
123
len = strnlen(buf, sizeof(buf));
124
if (!strncmp(address, buf, len)) {
125
strncpy(address, dp->d_name, len);
132
* find_phys_if - find the regular network interface name that
133
* has the same mac address as the VLAN interface.
134
* This ifname will be used to find the PCI info
135
* of a VLAN interface.
136
* hba_dir: hba_dir of VLAN interface.
137
* buf: returns ifname of regular network interface.
140
find_phys_if(char *hba_dir, char *buf, size_t len)
144
/* Get the mac address of VLAN interface */
145
rc = sa_sys_read_line(hba_dir, "address", buf, len);
149
* Search for the regular network interface and
150
* return the interface name in the buf.
152
sa_dir_read(SYSFS_HBA_DIR, check_ifmac, buf);
157
sysfs_scan(struct dirent *dp, void *arg)
159
HBA_ADAPTERATTRIBUTES *atp;
160
HBA_PORTATTRIBUTES *pap;
162
struct hba_info hba_info;
163
struct adapter_info *ap;
164
struct port_info *pp;
165
char host_dir[80], hba_dir[80], drv_dir[80];
166
char ifname[20], buf[256];
170
char *saveptr; /* for strtok_r */
172
memset(&hba_info, 0, sizeof(hba_info));
175
* Create a new HBA entry (ap) for the local port
176
* We will create a new HBA entry for each local port.
178
ap = malloc(sizeof(*ap));
180
fprintf(stderr, "%s: malloc failed, errno=0x%x\n",
182
return HBA_STATUS_ERROR;
184
memset(ap, 0, sizeof(*ap));
185
ap->ad_kern_index = atoi(dp->d_name + sizeof("host") - 1);
186
ap->ad_port_count = 1;
188
/* atp points to the HBA attributes structure */
192
* Create a new local port entry
194
pp = malloc(sizeof(*pp));
197
"%s: malloc for local port %d failed,"
198
" errno=0x%x\n", __func__,
199
ap->ad_port_count - 1, errno);
204
memset(pp, 0, sizeof(*pp));
206
pp->ap_index = ap->ad_port_count - 1;
207
pp->ap_kern_hba = atoi(dp->d_name + sizeof("host") - 1);
209
/* pap points to the local port attributes structure */
212
/* Construct the host directory name from the input name */
213
snprintf(host_dir, sizeof(host_dir),
214
SYSFS_HOST_DIR "/%s", dp->d_name);
216
rc = sa_sys_read_line(host_dir, "symbolic_name", buf, sizeof(buf));
218
/* Get PortSymbolicName */
219
sa_strncpy_safe(pap->PortSymbolicName, sizeof(pap->PortSymbolicName),
222
/* Skip the HBA if it isn't OpenFC */
223
cp = strstr(pap->PortSymbolicName, " over ");
228
* See if host_dir is a PCI device directory
229
* If not, try it as a net device.
231
i = readlink(host_dir, buf, sizeof(buf) - 1);
236
if (strstr(buf, "devices/pci") && !strstr(buf, "/net/")) {
237
snprintf(hba_dir, sizeof(hba_dir), "%s/device/..", host_dir);
239
/* assume a net device */
241
sa_strncpy_safe(ifname, sizeof(ifname), cp, strlen(cp));
242
snprintf(hba_dir, sizeof(hba_dir),
243
SYSFS_HBA_DIR "/%s", ifname);
244
i = readlink(hba_dir, buf, sizeof(buf) - 1);
246
printf("readlink %s failed\n", hba_dir);
250
if (strstr(buf, "/virtual/net/")) {
251
memset(buf, 0, sizeof(buf));
252
rc = find_phys_if(hba_dir, buf, sizeof(buf));
255
snprintf(hba_dir, sizeof(hba_dir),
256
SYSFS_HBA_DIR "/%s", buf);
257
i = readlink(hba_dir, buf, sizeof(buf) - 1);
259
printf("readlink %s failed\n", hba_dir);
265
* A sample link value here is like:
266
* ../../devices/pci*.../0000:03:00.0/net/eth2
268
cp = strstr(buf, "/net/");
272
strcat(hba_dir, "/device");
276
* Assume a PCI symlink value is in buf.
277
* Back up to the last path component that looks like a PCI element.
278
* A sample link value is like:
279
* ../../devices/pci*.../0000:03:00.0
283
cp = strrchr(buf, '/');
286
rc = sscanf(cp + 1, "%x:%x:%x.%x",
287
&hba_info.domain, &hba_info.bus,
288
&hba_info.dev, &hba_info.func);
292
} while (cp && cp > buf);
298
* Save the host directory and the hba directory
299
* in local port structure
301
sa_strncpy_safe(pp->host_dir, sizeof(pp->host_dir),
302
host_dir, sizeof(host_dir));
305
rc = sys_read_wwn(pp->host_dir, "node_name", &wwnn);
306
memcpy(&pap->NodeWWN, &wwnn, sizeof(wwnn));
309
rc = sys_read_wwn(pp->host_dir, "port_name", &pap->PortWWN);
312
rc = sa_sys_read_u32(pp->host_dir, "port_id", &pap->PortFcId);
315
rc = sa_sys_read_line(pp->host_dir, "port_type", buf, sizeof(buf));
316
pap->PortType = get_fc_port_type_value(buf);
319
rc = sa_sys_read_line(pp->host_dir, "port_state", buf, sizeof(buf));
320
rc = sa_enum_encode(port_states_table, buf, &pap->PortState);
323
rc = sa_sys_read_line(pp->host_dir, "speed", buf, sizeof(buf));
324
rc = sa_enum_encode(port_speeds_table, buf, &pap->PortSpeed);
326
/* Get PortSupportedSpeed */
327
rc = sa_sys_read_line(pp->host_dir, "supported_speed",
329
rc = sa_enum_encode(port_speeds_table, buf, &pap->PortSupportedSpeed);
331
/* Get PortMaxFrameSize */
332
rc = sa_sys_read_line(pp->host_dir, "maxframe_size", buf, sizeof(buf));
333
sscanf(buf, "%d", &pap->PortMaxFrameSize);
335
/* Get PortSupportedFc4Types */
336
rc = sa_sys_read_line(pp->host_dir, "supported_fc4s", buf, sizeof(buf));
337
sscanf(buf, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
338
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
339
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
340
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
341
&data[0], &data[1], &data[2], &data[3], &data[4], &data[5],
342
&data[6], &data[7], &data[8], &data[9], &data[10], &data[11],
343
&data[12], &data[13], &data[14], &data[15], &data[16],
344
&data[17], &data[18], &data[19], &data[20], &data[21],
345
&data[22], &data[23], &data[24], &data[25], &data[26],
346
&data[27], &data[28], &data[29], &data[30], &data[31]);
347
for (i = 0; i < 32; i++)
348
pap->PortSupportedFc4Types.bits[i] = data[i];
350
/* Get PortActiveFc4Types */
351
rc = sa_sys_read_line(pp->host_dir, "active_fc4s", buf, sizeof(buf));
352
sscanf(buf, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
353
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
354
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
355
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
356
&data[0], &data[1], &data[2], &data[3], &data[4], &data[5],
357
&data[6], &data[7], &data[8], &data[9], &data[10], &data[11],
358
&data[12], &data[13], &data[14], &data[15], &data[16],
359
&data[17], &data[18], &data[19], &data[20], &data[21],
360
&data[22], &data[23], &data[24], &data[25], &data[26],
361
&data[27], &data[28], &data[29], &data[30], &data[31]);
362
for (i = 0; i < 32; i++)
363
pap->PortActiveFc4Types.bits[i] = data[i];
366
rc = sys_read_wwn(pp->host_dir, "fabric_name", &pap->FabricName);
368
/* Get PortSupportedClassofService */
369
rc = sa_sys_read_line(pp->host_dir, "supported_classes",
371
pap->PortSupportedClassofService = *(strstr(buf, "Class") + 6) - '0';
373
/* Get OSDeviceName */
374
sa_strncpy_safe(pap->OSDeviceName, sizeof(pap->OSDeviceName),
375
dp->d_name, sizeof(dp->d_name));
377
/* Get NumberofDiscoveredPorts */
378
snprintf(buf, sizeof(buf), "%s/device", pp->host_dir);
379
sa_dir_read(buf, counting_rports, &pap->NumberofDiscoveredPorts);
382
* Add the local port structure into local port table within
385
if (sa_table_insert(&ap->ad_ports, pp->ap_index, pp) < 0) {
387
"%s: insert of HBA %d port %d failed\n",
388
__func__, ap->ad_kern_index, pp->ap_index);
392
/* Create adapter name */
393
snprintf(buf, sizeof(buf), "fcoe:%s", ifname);
394
ap->ad_name = strdup(buf);
397
rc = sa_sys_read_u32(hba_dir, "vendor", &hba_info.vendor_id);
400
rc = sa_sys_read_u32(hba_dir, "device", &hba_info.device_id);
402
/* Get subsystem_vendor_id */
403
rc = sa_sys_read_u32(hba_dir, "subsystem_vendor",
404
&hba_info.subsystem_vendor_id);
406
/* Get subsystem_device_id */
407
rc = sa_sys_read_u32(hba_dir, "subsystem_device",
408
&hba_info.subsystem_device_id);
410
/* Get device_class */
411
rc = sa_sys_read_u32(hba_dir, "class", &hba_info.device_class);
412
hba_info.device_class = hba_info.device_class>>8;
415
* Get Hardware Information via PCI Library
417
(void) find_pci_device(&hba_info);
419
/* Get Number of Ports */
420
atp->NumberOfPorts = hba_info.NumberOfPorts;
422
/* Get Manufacturer */
423
sa_strncpy_safe(atp->Manufacturer, sizeof(atp->Manufacturer),
424
hba_info.Manufacturer, sizeof(hba_info.Manufacturer));
426
/* Get SerialNumber */
427
sa_strncpy_safe(atp->SerialNumber, sizeof(atp->SerialNumber),
428
hba_info.SerialNumber, sizeof(hba_info.SerialNumber));
431
/* Get ModelDescription */
432
sa_strncpy_safe(atp->ModelDescription, sizeof(atp->ModelDescription),
433
hba_info.ModelDescription,
434
sizeof(hba_info.ModelDescription));
435
if (!strncmp(hba_info.ModelDescription, "Unknown",
436
sizeof(hba_info.ModelDescription))) {
437
snprintf(atp->ModelDescription, sizeof(atp->ModelDescription),
438
"[%04x:%04x]-[%04x:%04x]-(%04x)",
439
hba_info.vendor_id, hba_info.device_id,
440
hba_info.subsystem_vendor_id,
441
hba_info.subsystem_device_id,
442
hba_info.device_class);
446
* If the device is a newly developed product, and
447
* the model description is not in pci.ids yet, use
448
* the model description constructed above as the
451
sa_strncpy_safe(atp->Model, sizeof(atp->Model),
452
atp->ModelDescription,
453
sizeof(atp->ModelDescription));
459
* If the device name has already been added into
460
* the pci.ids file, use the first word of the model
461
* description as the model. If the space after the
462
* first word is not found (new product), use the
463
* model description as the model.
465
sa_strncpy_safe(buf, sizeof(buf), atp->ModelDescription,
466
sizeof(atp->ModelDescription));
467
if (strtok_r(buf, " ", &saveptr))
468
sa_strncpy_safe(atp->Model, sizeof(atp->Model),
469
buf, strnlen(buf, sizeof(buf)));
471
sa_strncpy_safe(atp->Model, sizeof(atp->Model),
472
atp->ModelDescription,
473
sizeof(atp->ModelDescription));
475
/* Get HardwareVersion */
476
sa_strncpy_safe(atp->HardwareVersion, sizeof(atp->HardwareVersion),
477
hba_info.HardwareVersion,
478
sizeof(hba_info.HardwareVersion));
480
/* Get OptionROMVersion (TODO) */
481
sa_strncpy_safe(atp->OptionROMVersion, sizeof(atp->OptionROMVersion),
482
HBA_ROM_VERSION, sizeof(HBA_ROM_VERSION));
484
/* Get FirmwareVersion (TODO) */
485
sa_strncpy_safe(atp->FirmwareVersion, sizeof(atp->FirmwareVersion),
486
HBA_FW_VERSION, sizeof(HBA_FW_VERSION));
488
/* Get VendorSpecificID (TODO) */
489
atp->VendorSpecificID = HBA_VENDOR_SPECIFIC_ID;
491
/* Get DriverVersion */
492
rc = sa_sys_read_line(hba_dir, SYSFS_MODULE_VER,
493
atp->DriverVersion, sizeof(atp->DriverVersion));
495
/* Get NodeSymbolicName */
496
sa_strncpy_safe(atp->NodeSymbolicName, sizeof(atp->NodeSymbolicName),
497
ap->ad_name, sizeof(atp->NodeSymbolicName));
499
/* Get NodeWWN - The NodeWWN is the same as
500
* the NodeWWN of the local port.
502
memcpy((char *)&atp->NodeWWN, (char *)&pap->NodeWWN,
503
sizeof(pap->NodeWWN));
506
snprintf(drv_dir, sizeof(drv_dir), "%s" SYSFS_MODULE , hba_dir);
507
i = readlink(drv_dir, buf, sizeof(buf));
511
if (!strstr(buf, "module")) {
513
* Does not find "module" in the string.
514
* This should not happen. In this case, set
515
* the driver name to "Unknown".
517
driverName = "Unknown";
519
driverName = strstr(buf, "module") + 7;
520
sa_strncpy_safe(atp->DriverName, sizeof(atp->DriverName),
521
driverName, sizeof(atp->DriverName));
524
* Give HBA to library
526
rc = adapter_create(ap);
527
if (rc != HBA_STATUS_OK) {
528
fprintf(stderr, "%s: adapter_create failed, status=%d\n",
530
adapter_destroy(ap); /* free adapter and ports */
542
copy_wwn(HBA_WWN *dest, fc_wwn_t src)
544
dest->wwn[0] = (u_char) (src >> 56);
545
dest->wwn[1] = (u_char) (src >> 48);
546
dest->wwn[2] = (u_char) (src >> 40);
547
dest->wwn[3] = (u_char) (src >> 32);
548
dest->wwn[4] = (u_char) (src >> 24);
549
dest->wwn[5] = (u_char) (src >> 16);
550
dest->wwn[6] = (u_char) (src >> 8);
551
dest->wwn[7] = (u_char) src;
554
/* Test for a non-zero WWN */
556
is_wwn_nonzero(HBA_WWN *wwn)
558
return (wwn->wwn[0] | wwn->wwn[1] | wwn->wwn[2] | wwn->wwn[3] |
559
wwn->wwn[4] | wwn->wwn[5] | wwn->wwn[6] | wwn->wwn[7]) != 0;
563
sys_read_wwn(const char *dir, const char *file, HBA_WWN *wwn)
568
rc = sa_sys_read_u64(dir, file, &val);
574
/* Port Statistics */
576
sysfs_get_port_stats(char *dir, HBA_PORTSTATISTICS *sp)
580
rc = sa_sys_read_u64(dir, "seconds_since_last_reset",
581
(u_int64_t *)&sp->SecondsSinceLastReset);
582
rc |= sa_sys_read_u64(dir, "tx_frames", (u_int64_t *)&sp->TxFrames);
583
rc |= sa_sys_read_u64(dir, "tx_words", (u_int64_t *)&sp->TxWords);
584
rc |= sa_sys_read_u64(dir, "rx_frames", (u_int64_t *)&sp->RxFrames);
585
rc |= sa_sys_read_u64(dir, "rx_words", (u_int64_t *)&sp->RxWords);
586
rc |= sa_sys_read_u64(dir, "lip_count", (u_int64_t *)&sp->LIPCount);
587
rc |= sa_sys_read_u64(dir, "nos_count", (u_int64_t *)&sp->NOSCount);
588
rc |= sa_sys_read_u64(dir, "error_frames",
589
(u_int64_t *)&sp->ErrorFrames);
590
rc |= sa_sys_read_u64(dir, "dumped_frames",
591
(u_int64_t *)&sp->DumpedFrames);
592
rc |= sa_sys_read_u64(dir, "link_failure_count",
593
(u_int64_t *)&sp->LinkFailureCount);
594
rc |= sa_sys_read_u64(dir, "loss_of_sync_count",
595
(u_int64_t *)&sp->LossOfSyncCount);
596
rc |= sa_sys_read_u64(dir, "loss_of_signal_count",
597
(u_int64_t *)&sp->LossOfSignalCount);
598
rc |= sa_sys_read_u64(dir, "prim_seq_protocol_err_count",
599
(u_int64_t *)&sp->PrimitiveSeqProtocolErrCount);
600
rc |= sa_sys_read_u64(dir, "invalid_tx_word_count",
601
(u_int64_t *)&sp->InvalidTxWordCount);
602
rc |= sa_sys_read_u64(dir, "invalid_crc_count",
603
(u_int64_t *)&sp->InvalidCRCCount);
608
/* Port FC-4 Statistics */
610
sysfs_get_port_fc4stats(char *dir, HBA_FC4STATISTICS *fc4sp)
614
rc = sa_sys_read_u64(dir, "fcp_input_requests",
615
(u_int64_t *)&fc4sp->InputRequests);
616
rc |= sa_sys_read_u64(dir, "fcp_output_requests",
617
(u_int64_t *)&fc4sp->OutputRequests);
618
rc |= sa_sys_read_u64(dir, "fcp_control_requests",
619
(u_int64_t *)&fc4sp->ControlRequests);
620
rc |= sa_sys_read_u64(dir, "fcp_input_megabytes",
621
(u_int64_t *)&fc4sp->InputMegabytes);
622
rc |= sa_sys_read_u64(dir, "fcp_output_megabytes",
623
(u_int64_t *)&fc4sp->OutputMegabytes);
628
* Open device and read adapter info if available.
633
sa_dir_read(SYSFS_HOST_DIR, sysfs_scan, NULL);
637
adapter_shutdown(void)
642
get_port_statistics(HBA_HANDLE handle, HBA_UINT32 port, HBA_PORTSTATISTICS *sp)
644
struct port_info *pp;
648
memset(sp, 0xff, sizeof(*sp)); /* unsupported statistics give -1 */
649
pp = adapter_get_port(handle, port);
651
fprintf(stderr, "%s: lookup failed. handle 0x%x port 0x%x\n",
652
__func__, handle, port);
653
return HBA_STATUS_ERROR;
656
snprintf(dir, sizeof(dir), "%s/statistics", pp->host_dir);
657
rc = sysfs_get_port_stats(dir, sp);
659
fprintf(stderr, "%s: sysfs_get_port_stats() failed,"
660
" hba index=%d port index=%d, -rc=0x%x\n",
661
__func__, pp->ap_adapt->ad_kern_index,
663
return HBA_STATUS_ERROR;
665
return HBA_STATUS_OK;
669
* Get FC4 statistics.
672
get_port_fc4_statistics(HBA_HANDLE handle, HBA_WWN wwn,
673
HBA_UINT8 fc4_type, HBA_FC4STATISTICS *sp)
675
struct port_info *pp;
680
memset(sp, 0xff, sizeof(*sp)); /* unsupported statistics give -1 */
682
pp = adapter_get_port_by_wwn(handle, wwn, &count);
684
return HBA_STATUS_ERROR_AMBIGUOUS_WWN;
686
return HBA_STATUS_ERROR_ILLEGAL_WWN;
688
snprintf(dir, sizeof(dir), "%s/statistics", pp->host_dir);
689
rc = sysfs_get_port_fc4stats(dir, sp);
691
fprintf(stderr, "%s: sysfs_get_port_fc4stats() failed,"
692
" hba index=%d port index=%d, -rc=0x%x\n",
693
__func__, pp->ap_adapt->ad_kern_index,
695
return HBA_STATUS_ERROR;
697
return HBA_STATUS_OK;