Blame SOURCES/libhbalinux-fix-non-pci-netdev.patch

ae4d9d
diff --git a/Makefile.am b/Makefile.am
ae4d9d
index 1349e7b..068dc10 100644
ae4d9d
--- a/Makefile.am
ae4d9d
+++ b/Makefile.am
ae4d9d
@@ -1,12 +1,12 @@
ae4d9d
-AM_CFLAGS = $(HBAAPI_CFLAGS) $(PCIACCESS_CFLAGS)
ae4d9d
-AM_LDFLAGS= $(PCIACCESS_LIBS)
ae4d9d
+AM_CFLAGS = $(HBAAPI_CFLAGS) $(PCIACCESS_CFLAGS) $(LIBUDEV_CFLAGS)
ae4d9d
+AM_LDFLAGS= $(PCIACCESS_LIBS) $(LIBUDEV_LIBS)
ae4d9d
 
ae4d9d
 lib_LTLIBRARIES = libhbalinux.la
ae4d9d
 libhbalinux_la_SOURCES = adapt.c adapt_impl.h api_lib.h bind.c bind_impl.h \
ae4d9d
 fc_scsi.h fc_types.h lib.c lport.c net_types.h pci.c rport.c scsi.c sg.c \
ae4d9d
 utils.c utils.h
ae4d9d
 libhbalinux_la_LDFLAGS = -version-info 2:2:0
ae4d9d
-libhbalinux_la_LIBADD = $(PCIACCESS_LIBS)
ae4d9d
+libhbalinux_la_LIBADD = $(PCIACCESS_LIBS) $(LIBUDEV_LIBS)
ae4d9d
 
ae4d9d
 pkgconfigdir = $(libdir)/pkgconfig
ae4d9d
 pkgconfig_DATA = libhbalinux.pc
ae4d9d
diff --git a/adapt_impl.h b/adapt_impl.h
ae4d9d
index d86c2f8..9d9a347 100644
ae4d9d
--- a/adapt_impl.h
ae4d9d
+++ b/adapt_impl.h
ae4d9d
@@ -151,7 +151,7 @@ HBA_STATUS scsi_report_luns_v2(HBA_HANDLE, HBA_WWN, HBA_WWN,
ae4d9d
 HBA_STATUS sg_issue_inquiry(const char *, HBA_UINT8, HBA_UINT8,
ae4d9d
 		void *, HBA_UINT32 *, HBA_UINT8 *, void *, HBA_UINT32 *);
ae4d9d
 
ae4d9d
-void adapter_init(void);
ae4d9d
+int adapter_init(void);
ae4d9d
 void adapter_shutdown(void);
ae4d9d
 
ae4d9d
 /* struct port_stats; */
ae4d9d
diff --git a/configure.ac b/configure.ac
ae4d9d
index 8dadf29..758cadb 100644
ae4d9d
--- a/configure.ac
ae4d9d
+++ b/configure.ac
ae4d9d
@@ -13,6 +13,10 @@ AC_SUBST(PCIACCESS_LIBS)
ae4d9d
 PKG_CHECK_MODULES(HBAAPI, HBAAPI)
ae4d9d
 AC_SUBST(HBAAPI_CFLAGS)
ae4d9d
 
ae4d9d
+PKG_CHECK_MODULES(LIBUDEV, libudev)
ae4d9d
+AC_SUBST(LIBUDEV_CFLAGS)
ae4d9d
+AC_SUBST(LIBUDEV_LIBS)
ae4d9d
+
ae4d9d
 AC_CONFIG_FILES([Makefile libhbalinux.spec libhbalinux.pc])
ae4d9d
 AC_OUTPUT
ae4d9d
 
ae4d9d
diff --git a/libhbalinux.spec.in b/libhbalinux.spec.in
ae4d9d
index 344c166..4690da9 100644
ae4d9d
--- a/libhbalinux.spec.in
ae4d9d
+++ b/libhbalinux.spec.in
ae4d9d
@@ -9,7 +9,7 @@ URL:            http://www.open-fcoe.org
ae4d9d
 Source0:        http://www.open-fcoe.org/openfc/%{name}-%{version}.tar.gz
ae4d9d
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
ae4d9d
 
ae4d9d
-BuildRequires:  libHBAAPI-devel libpciaccess-devel
ae4d9d
+BuildRequires:  libHBAAPI-devel libpciaccess-devel systemd-devel
ae4d9d
 Requires:       libHBAAPI
ae4d9d
 
ae4d9d
 %description
ae4d9d
diff --git a/lport.c b/lport.c
ae4d9d
index bc34078..695bdc6 100644
ae4d9d
--- a/lport.c
ae4d9d
+++ b/lport.c
ae4d9d
@@ -20,6 +20,8 @@
ae4d9d
 #include "api_lib.h"
ae4d9d
 #include "adapt_impl.h"
ae4d9d
 
ae4d9d
+#include <libudev.h>
ae4d9d
+
ae4d9d
 #ifndef HBA_STATUS_ERROR_ILLEGAL_FCID
ae4d9d
 #define HBA_STATUS_ERROR_ILLEGAL_FCID 33	/* defined after HBA-API 2.2 */
ae4d9d
 #endif
ae4d9d
@@ -88,18 +90,16 @@ struct sa_nameval port_speeds_table[] = {
ae4d9d
  * and convert them to bitmasks for the HBA_PORTSPEED supported
ae4d9d
  * Format expected: "1 Gbit[, 10 Gbit]", etc.
ae4d9d
  */
ae4d9d
-static int sys_read_speed(const char *dir, const char *file, char *buf,
ae4d9d
-			  size_t buflen, HBA_PORTSPEED *speeds)
ae4d9d
+static int sys_read_speed(const char *speedstr, HBA_PORTSPEED *speeds)
ae4d9d
 {
ae4d9d
 	int rc = 0;
ae4d9d
 	u_int32_t val = 0;
ae4d9d
 	int len = 0;
ae4d9d
-	char *cp;
ae4d9d
+	const char *cp;
ae4d9d
 	struct sa_nameval *tp = port_speeds_table;
ae4d9d
 
ae4d9d
-	rc = sa_sys_read_line(dir, file, buf, buflen);
ae4d9d
-	if (rc == 0 && strstr(buf, "Unknown") == NULL) {
ae4d9d
-		for (cp = buf; *cp != '\0';) {
ae4d9d
+	if (rc == 0 && strstr(speedstr, "Unknown") == NULL) {
ae4d9d
+		for (cp = speedstr; *cp != '\0';) {
ae4d9d
 			for (; tp->nv_name != NULL; tp++) {
ae4d9d
 				len = strlen(tp->nv_name);
ae4d9d
 				if (strncasecmp(tp->nv_name, cp, len) == 0) {
ae4d9d
@@ -140,69 +140,189 @@ counting_rports(struct dirent *dp, void *arg)
ae4d9d
 	return HBA_STATUS_OK;
ae4d9d
 }
ae4d9d
 
ae4d9d
-static int
ae4d9d
-check_ifindex(struct dirent *dp, void *arg)
ae4d9d
+static void 
ae4d9d
+sysfs_scan_pci(struct udev_device *pci,
ae4d9d
+	struct hba_info *hba_info,
ae4d9d
+	HBA_ADAPTERATTRIBUTES *atp
ae4d9d
+	)
ae4d9d
 {
ae4d9d
-	char *ifindex = (char *)arg;
ae4d9d
-	char hba_dir[256];
ae4d9d
+	const char *attr;
ae4d9d
+	const char *hba_dir;
ae4d9d
 	char buf[256];
ae4d9d
-	int rc;
ae4d9d
-
ae4d9d
-	snprintf(hba_dir, sizeof(hba_dir),
ae4d9d
-		 SYSFS_HBA_DIR "/%s", dp->d_name);
ae4d9d
-	memset(buf, 0, sizeof(buf));
ae4d9d
-	rc = sa_sys_read_line(hba_dir, "ifindex", buf, sizeof(buf) - 1);
ae4d9d
-	if (rc)
ae4d9d
-		return 0;
ae4d9d
-	if (!strncmp(ifindex, buf, sizeof(buf))) {
ae4d9d
-		strcpy(arg, dp->d_name);
ae4d9d
-		return 1;
ae4d9d
+	char *saveptr;	/* for strtok_r */
ae4d9d
+
ae4d9d
+	/* Get vendor_id */
ae4d9d
+	attr = udev_device_get_sysattr_value(pci, "vendor");
ae4d9d
+	hba_info->vendor_id = strtoul(attr, NULL, 0);
ae4d9d
+
ae4d9d
+	/* Get device_id */
ae4d9d
+	attr = udev_device_get_sysattr_value(pci, "device");
ae4d9d
+	hba_info->device_id = strtoul(attr, NULL, 0);
ae4d9d
+
ae4d9d
+	/* Get subsystem_vendor_id */
ae4d9d
+	attr = udev_device_get_sysattr_value(pci, "subsystem_vendor");
ae4d9d
+	hba_info->subsystem_vendor_id = strtoul(attr, NULL, 0);
ae4d9d
+
ae4d9d
+	/* Get subsystem_device_id */
ae4d9d
+	attr = udev_device_get_sysattr_value(pci, "subsystem_device");
ae4d9d
+	hba_info->subsystem_device_id = strtoul(attr, NULL, 0);
ae4d9d
+
ae4d9d
+	/* Get device_class */
ae4d9d
+	attr = udev_device_get_sysattr_value(pci, "class");
ae4d9d
+	hba_info->device_class = strtoul(attr, NULL, 0);
ae4d9d
+	hba_info->device_class = hba_info->device_class>>8;
ae4d9d
+
ae4d9d
+	/*
ae4d9d
+	 * Get Hardware Information via PCI Library
ae4d9d
+	 */
ae4d9d
+
ae4d9d
+	sscanf(udev_device_get_sysname(pci), "%x:%x:%x:%x",
ae4d9d
+			&hba_info->domain, &hba_info->bus,
ae4d9d
+			&hba_info->dev, &hba_info->func);
ae4d9d
+	(void) find_pci_device(hba_info);
ae4d9d
+
ae4d9d
+	/* Get Number of Ports */
ae4d9d
+	atp->NumberOfPorts = hba_info->NumberOfPorts;
ae4d9d
+
ae4d9d
+	/* Get Manufacturer */
ae4d9d
+	sa_strncpy_safe(atp->Manufacturer, sizeof(atp->Manufacturer),
ae4d9d
+			hba_info->Manufacturer, sizeof(hba_info->Manufacturer));
ae4d9d
+
ae4d9d
+	/* Get SerialNumber */
ae4d9d
+	sa_strncpy_safe(atp->SerialNumber, sizeof(atp->SerialNumber),
ae4d9d
+			hba_info->SerialNumber, sizeof(hba_info->SerialNumber));
ae4d9d
+
ae4d9d
+
ae4d9d
+	/* Get ModelDescription */
ae4d9d
+	sa_strncpy_safe(atp->ModelDescription, sizeof(atp->ModelDescription),
ae4d9d
+			hba_info->ModelDescription,
ae4d9d
+			sizeof(hba_info->ModelDescription));
ae4d9d
+	if (!strncmp(hba_info->ModelDescription, "Unknown",
ae4d9d
+		 sizeof(hba_info->ModelDescription))) {
ae4d9d
+		snprintf(atp->ModelDescription, sizeof(atp->ModelDescription),
ae4d9d
+			"[%04x:%04x]-[%04x:%04x]-(%04x)",
ae4d9d
+			hba_info->vendor_id, hba_info->device_id,
ae4d9d
+			hba_info->subsystem_vendor_id,
ae4d9d
+			hba_info->subsystem_device_id,
ae4d9d
+			hba_info->device_class);
ae4d9d
+		/*
ae4d9d
+		 * Get Model
ae4d9d
+		 *
ae4d9d
+		 * If the device is a newly developed product, and
ae4d9d
+		 * the model description is not in pci.ids yet, use
ae4d9d
+		 * the model description constructed above as the
ae4d9d
+		 * model string.
ae4d9d
+		 */
ae4d9d
+		sa_strncpy_safe(atp->Model, sizeof(atp->Model),
ae4d9d
+				atp->ModelDescription,
ae4d9d
+				sizeof(atp->ModelDescription));
ae4d9d
 	}
ae4d9d
-	return 0;
ae4d9d
+
ae4d9d
+	/*
ae4d9d
+	 * Get Model
ae4d9d
+	 *
ae4d9d
+	 * If the device name has already been added into
ae4d9d
+	 * the pci.ids file, use the first word of the model
ae4d9d
+	 * description as the model. If the space after the
ae4d9d
+	 * first word is not found (new product), use the
ae4d9d
+	 * model description as the model.
ae4d9d
+	 */
ae4d9d
+	sa_strncpy_safe(buf, sizeof(buf), atp->ModelDescription,
ae4d9d
+			sizeof(atp->ModelDescription));
ae4d9d
+	if (strtok_r(buf, " ", &saveptr))
ae4d9d
+		sa_strncpy_safe(atp->Model, sizeof(atp->Model),
ae4d9d
+				buf, strnlen(buf, sizeof(buf)));
ae4d9d
+	else
ae4d9d
+		sa_strncpy_safe(atp->Model, sizeof(atp->Model),
ae4d9d
+				atp->ModelDescription,
ae4d9d
+				sizeof(atp->ModelDescription));
ae4d9d
+
ae4d9d
+	/* Get HardwareVersion */
ae4d9d
+	sa_strncpy_safe(atp->HardwareVersion, sizeof(atp->HardwareVersion),
ae4d9d
+			hba_info->HardwareVersion,
ae4d9d
+			sizeof(hba_info->HardwareVersion));
ae4d9d
+
ae4d9d
+	/* Get OptionROMVersion (TODO) */
ae4d9d
+	sa_strncpy_safe(atp->OptionROMVersion, sizeof(atp->OptionROMVersion),
ae4d9d
+			HBA_ROM_VERSION, sizeof(HBA_ROM_VERSION));
ae4d9d
+
ae4d9d
+	/* Get FirmwareVersion (TODO) */
ae4d9d
+	sa_strncpy_safe(atp->FirmwareVersion, sizeof(atp->FirmwareVersion),
ae4d9d
+			HBA_FW_VERSION, sizeof(HBA_FW_VERSION));
ae4d9d
+
ae4d9d
+	/* Get VendorSpecificID (TODO) */
ae4d9d
+	atp->VendorSpecificID = HBA_VENDOR_SPECIFIC_ID;
ae4d9d
+
ae4d9d
+	/* Get DriverVersion */
ae4d9d
+	hba_dir = udev_device_get_syspath(pci);
ae4d9d
+	sa_sys_read_line(hba_dir, SYSFS_MODULE_VER,
ae4d9d
+			atp->DriverVersion, sizeof(atp->DriverVersion));
ae4d9d
 }
ae4d9d
 
ae4d9d
-/*
ae4d9d
- * find_phys_if - find the regular network interface name that
ae4d9d
- *                has the ifindex that matches the specified iflink.
ae4d9d
- *                This ifname will be used to find the PCI info
ae4d9d
- *                of a VLAN interface.
ae4d9d
- * hba_dir: hba_dir of VLAN interface.
ae4d9d
- * buf: returns ifname of regular network interface.
ae4d9d
- */
ae4d9d
-static int
ae4d9d
-find_phys_if(char *hba_dir, char *buf, size_t len)
ae4d9d
+struct udev_device *
ae4d9d
+find_netdev_by_ifindex(struct udev *udev, const char *ifindex)
ae4d9d
 {
ae4d9d
-	int rc;
ae4d9d
+	struct udev_enumerate *ue;
ae4d9d
+	struct udev_list_entry *head;
ae4d9d
+	struct udev_device *newnet = NULL;
ae4d9d
 
ae4d9d
-	rc = sa_sys_read_line(hba_dir, "iflink", buf, len);
ae4d9d
-	if (rc)
ae4d9d
-		return 1;
ae4d9d
-	/*
ae4d9d
-	 * Search for the regular network interface and
ae4d9d
-	 * return the interface name in the buf.
ae4d9d
-	 */
ae4d9d
-	sa_dir_read(SYSFS_HBA_DIR, check_ifindex, buf);
ae4d9d
-	return 0;
ae4d9d
+	ue = udev_enumerate_new(udev);
ae4d9d
+	udev_enumerate_add_match_subsystem(ue, "net");
ae4d9d
+	udev_enumerate_add_match_sysattr(ue, "ifindex", ifindex); 
ae4d9d
+	udev_enumerate_scan_devices(ue);
ae4d9d
+	/* enumerate returns a list, but there should only ever be one device
ae4d9d
+	 * with a given ifindex */
ae4d9d
+	head = udev_enumerate_get_list_entry(ue);
ae4d9d
+	if (head)
ae4d9d
+		newnet = udev_device_new_from_syspath(udev, udev_list_entry_get_name(head));
ae4d9d
+	udev_enumerate_unref(ue);
ae4d9d
+	return newnet;
ae4d9d
+}
ae4d9d
+
ae4d9d
+struct udev_device *
ae4d9d
+find_phys_if(struct udev_device *net)
ae4d9d
+{
ae4d9d
+	const char *ifindex;
ae4d9d
+	const char *iflink;
ae4d9d
+	struct udev *udev;
ae4d9d
+	struct udev_device *lower = NULL;
ae4d9d
+
ae4d9d
+	ifindex = udev_device_get_sysattr_value(net, "ifindex");
ae4d9d
+	iflink = udev_device_get_sysattr_value(net, "iflink");
ae4d9d
+	if (strcmp(ifindex, iflink)) {
ae4d9d
+		udev = udev_device_get_udev(net);
ae4d9d
+		lower = find_netdev_by_ifindex(udev, iflink);
ae4d9d
+	}
ae4d9d
+	if (lower) {
ae4d9d
+		return lower;
ae4d9d
+	} else {
ae4d9d
+		udev_device_ref(net);
ae4d9d
+		return net;
ae4d9d
+	}
ae4d9d
 }
ae4d9d
 
ae4d9d
 static int
ae4d9d
-sysfs_scan(struct dirent *dp, void *arg)
ae4d9d
+sysfs_scan(struct udev_device *fc_host)
ae4d9d
 {
ae4d9d
 	HBA_ADAPTERATTRIBUTES *atp;
ae4d9d
 	HBA_PORTATTRIBUTES *pap;
ae4d9d
-	HBA_WWN wwnn;
ae4d9d
+	uint64_t wwnn;
ae4d9d
 	struct hba_info hba_info;
ae4d9d
 	struct adapter_info *ap;
ae4d9d
 	struct port_info *pp;
ae4d9d
-	char host_dir[80], hba_dir[80], drv_dir[80];
ae4d9d
-	char dev_dir[128];
ae4d9d
+	const char *hba_dir;
ae4d9d
+	char drv_dir[80];
ae4d9d
 	char ifname[20], buf[256];
ae4d9d
 	char *driverName;
ae4d9d
 	int data[32], rc, i;
ae4d9d
 	char *cp;
ae4d9d
-	char *saveptr;	/* for strtok_r */
ae4d9d
-	unsigned int ifindex;
ae4d9d
-	unsigned int iflink;
ae4d9d
+
ae4d9d
+	const char *sysname = udev_device_get_sysname(fc_host);
ae4d9d
+	const char *syspath = udev_device_get_syspath(fc_host);
ae4d9d
+	struct udev_device *pci;
ae4d9d
+	struct udev_device *net;
ae4d9d
+	const char *ptr = NULL;
ae4d9d
+	const char *attr;
ae4d9d
 
ae4d9d
 	memset(&hba_info, 0, sizeof(hba_info));
ae4d9d
 
ae4d9d
@@ -217,7 +337,7 @@ sysfs_scan(struct dirent *dp, void *arg)
ae4d9d
 		return HBA_STATUS_ERROR;
ae4d9d
 	}
ae4d9d
 	memset(ap, 0, sizeof(*ap));
ae4d9d
-	ap->ad_kern_index = atoi(dp->d_name + sizeof("host") - 1);
ae4d9d
+	ap->ad_kern_index = atoi(sysname + sizeof("host") - 1);
ae4d9d
 	ap->ad_port_count = 1;
ae4d9d
 
ae4d9d
 	/* atp points to the HBA attributes structure */
ae4d9d
@@ -239,137 +359,76 @@ sysfs_scan(struct dirent *dp, void *arg)
ae4d9d
 	memset(pp, 0, sizeof(*pp));
ae4d9d
 	pp->ap_adapt = ap;
ae4d9d
 	pp->ap_index = ap->ad_port_count - 1;
ae4d9d
-	pp->ap_kern_hba = atoi(dp->d_name + sizeof("host") - 1);
ae4d9d
+	pp->ap_kern_hba = atoi(sysname + sizeof("host") - 1);
ae4d9d
 
ae4d9d
 	/* pap points to the local port attributes structure */
ae4d9d
 	pap = &pp->ap_attr;
ae4d9d
 
ae4d9d
-	/* Construct the host directory name from the input name */
ae4d9d
-	snprintf(host_dir, sizeof(host_dir),
ae4d9d
-		SYSFS_HOST_DIR "/%s", dp->d_name);
ae4d9d
-
ae4d9d
-	rc = sa_sys_read_line(host_dir, "symbolic_name", buf, sizeof(buf));
ae4d9d
-
ae4d9d
 	/* Get PortSymbolicName */
ae4d9d
+	ptr = udev_device_get_sysattr_value(fc_host, "symbolic_name");
ae4d9d
 	sa_strncpy_safe(pap->PortSymbolicName, sizeof(pap->PortSymbolicName),
ae4d9d
-			buf, sizeof(buf));
ae4d9d
+			ptr, strlen(ptr));
ae4d9d
 
ae4d9d
 	/* Skip the HBA if it isn't OpenFC */
ae4d9d
 	cp = strstr(pap->PortSymbolicName, " over ");
ae4d9d
 	if (!cp)
ae4d9d
 		goto skip;
ae4d9d
 
ae4d9d
-	/*
ae4d9d
-	 * See if <host_dir>/device is a PCI symlink.
ae4d9d
-	 * If not, try it as a net device.
ae4d9d
-	 */
ae4d9d
-	snprintf(dev_dir, sizeof(dev_dir), "%s/device", host_dir);
ae4d9d
-	i = readlink(dev_dir, buf, sizeof(buf) - 1);
ae4d9d
-	if (i < 0)
ae4d9d
-		i = 0;
ae4d9d
-	buf[i] = '\0';
ae4d9d
-
ae4d9d
-	if (strstr(buf, "devices/pci") && !strstr(buf, "/net/")) {
ae4d9d
-		snprintf(hba_dir, sizeof(hba_dir), "%s/device/..", host_dir);
ae4d9d
-	} else {
ae4d9d
-		/* assume a net device */
ae4d9d
-		cp += 6;
ae4d9d
-		sa_strncpy_safe(ifname, sizeof(ifname), cp, strlen(cp));
ae4d9d
-		snprintf(hba_dir, sizeof(hba_dir),
ae4d9d
-			 SYSFS_HBA_DIR "/%s", ifname);
ae4d9d
-		/*
ae4d9d
-		 * Try as VLAN device or other virtual net device.
ae4d9d
-		 * If this is the case, ifindex and iflink will be different.
ae4d9d
-		 * iflink is the ifindex of the physical device.
ae4d9d
-		 */
ae4d9d
-		rc = sa_sys_read_u32(hba_dir, "ifindex", &ifindex);
ae4d9d
-		if (rc < 0)
ae4d9d
-			goto skip;
ae4d9d
-		rc = sa_sys_read_u32(hba_dir, "iflink", &iflink);
ae4d9d
-		if (rc < 0)
ae4d9d
-			goto skip;
ae4d9d
-		if (ifindex != iflink) {
ae4d9d
-			rc = find_phys_if(hba_dir, buf, sizeof(buf));
ae4d9d
-			if (rc)
ae4d9d
-				goto skip;
ae4d9d
-			strncpy(ifname, buf, sizeof(ifname));
ae4d9d
-		}
ae4d9d
-
ae4d9d
-		snprintf(hba_dir, sizeof(hba_dir),
ae4d9d
-			 SYSFS_HBA_DIR "/%s/device", ifname);
ae4d9d
-		i = readlink(hba_dir, buf, sizeof(buf) - 1);
ae4d9d
-		if (i < 0)
ae4d9d
-			goto skip;
ae4d9d
-		buf[i] = '\0';
ae4d9d
+	pci = udev_device_get_parent_with_subsystem_devtype(fc_host, "pci", NULL);
ae4d9d
+	net = udev_device_get_parent_with_subsystem_devtype(fc_host, "net", NULL);
ae4d9d
+	if (!pci && net) {
ae4d9d
+		/* check for a vlan device, stacked on a real PCI network device */
ae4d9d
+		net = find_phys_if(net);
ae4d9d
+		pci = udev_device_get_parent_with_subsystem_devtype(net, "pci", NULL);
ae4d9d
 	}
ae4d9d
 
ae4d9d
 	/*
ae4d9d
-	 * Assume a PCI symlink value is in buf.
ae4d9d
-	 * Back up to the last path component that looks like a PCI element.
ae4d9d
-	 * A sample link value is like:
ae4d9d
-	 *	../../devices/pci*.../0000:03:00.0
ae4d9d
-	 */
ae4d9d
-	rc = 0;
ae4d9d
-	do {
ae4d9d
-		cp = strrchr(buf, '/');
ae4d9d
-		if (!cp)
ae4d9d
-			break;
ae4d9d
-		rc = sscanf(cp + 1, "%x:%x:%x.%x",
ae4d9d
-			    &hba_info.domain, &hba_info.bus,
ae4d9d
-			    &hba_info.dev, &hba_info.func);
ae4d9d
-		if (rc == 4)
ae4d9d
-			break;
ae4d9d
-		*cp = '\0';
ae4d9d
-	} while (cp && cp > buf);
ae4d9d
-
ae4d9d
-	if (rc != 4)
ae4d9d
-		goto skip;
ae4d9d
-
ae4d9d
-	/*
ae4d9d
 	 * Save the host directory and the hba directory
ae4d9d
 	 * in local port structure
ae4d9d
 	 */
ae4d9d
 	sa_strncpy_safe(pp->host_dir, sizeof(pp->host_dir),
ae4d9d
-			host_dir, sizeof(host_dir));
ae4d9d
+			syspath, strlen(syspath));
ae4d9d
 
ae4d9d
 	/* Get NodeWWN */
ae4d9d
-	rc = sys_read_wwn(pp->host_dir, "node_name", &wwnn);
ae4d9d
-	memcpy(&pap->NodeWWN, &wwnn, sizeof(wwnn));
ae4d9d
+	attr = udev_device_get_sysattr_value(fc_host, "node_name");
ae4d9d
+	wwnn = strtoull(attr, NULL, 16);
ae4d9d
+	copy_wwn(&pap->NodeWWN, wwnn);
ae4d9d
 
ae4d9d
 	/* Get PortWWN */
ae4d9d
-	rc = sys_read_wwn(pp->host_dir, "port_name", &pap->PortWWN);
ae4d9d
+	attr = udev_device_get_sysattr_value(fc_host, "port_name");
ae4d9d
+	wwnn = strtoull(attr, NULL, 16);
ae4d9d
+	copy_wwn(&pap->PortWWN, wwnn);
ae4d9d
 
ae4d9d
 	/* Get PortFcId */
ae4d9d
-	rc = sa_sys_read_u32(pp->host_dir, "port_id", &pap->PortFcId);
ae4d9d
+	attr = udev_device_get_sysattr_value(fc_host, "port_id");
ae4d9d
+	pap->PortFcId = strtoul(attr, NULL, 0);
ae4d9d
 
ae4d9d
 	/* Get PortType */
ae4d9d
-	rc = sa_sys_read_line(pp->host_dir, "port_type", buf, sizeof(buf));
ae4d9d
-	rc = sa_enum_encode(port_types_table, buf, &pap->PortType);
ae4d9d
+	attr = udev_device_get_sysattr_value(fc_host, "port_type");
ae4d9d
+	rc = sa_enum_encode(port_types_table, attr, &pap->PortType);
ae4d9d
 
ae4d9d
 	/* Get PortState */
ae4d9d
-	rc = sa_sys_read_line(pp->host_dir, "port_state", buf, sizeof(buf));
ae4d9d
-	rc = sa_enum_encode(port_states_table, buf, &pap->PortState);
ae4d9d
+	attr = udev_device_get_sysattr_value(fc_host, "port_state");
ae4d9d
+	rc = sa_enum_encode(port_states_table, attr, &pap->PortState);
ae4d9d
 
ae4d9d
 	/* Get PortSpeed */
ae4d9d
-	rc = sys_read_speed(pp->host_dir, "speed",
ae4d9d
-				buf, sizeof(buf),
ae4d9d
-				&pap->PortSpeed);
ae4d9d
+	attr = udev_device_get_sysattr_value(fc_host, "speed");
ae4d9d
+	rc = sys_read_speed(attr, &pap->PortSpeed);
ae4d9d
 
ae4d9d
 	/* Get PortSupportedSpeed */
ae4d9d
-	rc = sys_read_speed(pp->host_dir, "supported_speeds",
ae4d9d
-				buf, sizeof(buf),
ae4d9d
-				&pap->PortSupportedSpeed);
ae4d9d
+	attr = udev_device_get_sysattr_value(fc_host, "supported_speeds");
ae4d9d
+	rc = sys_read_speed(attr, &pap->PortSupportedSpeed);
ae4d9d
 
ae4d9d
 	/* Get PortMaxFrameSize */
ae4d9d
-	rc = sa_sys_read_line(pp->host_dir, "maxframe_size", buf, sizeof(buf));
ae4d9d
-	sscanf(buf, "%d", &pap->PortMaxFrameSize);
ae4d9d
+	attr = udev_device_get_sysattr_value(fc_host, "maxframe_size");
ae4d9d
+	sscanf(attr, "%d", &pap->PortMaxFrameSize);
ae4d9d
 
ae4d9d
 	/* Get PortSupportedFc4Types */
ae4d9d
-	rc = sa_sys_read_line(pp->host_dir, "supported_fc4s", buf, sizeof(buf));
ae4d9d
-	sscanf(buf, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
ae4d9d
-		    "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
ae4d9d
-		    "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
ae4d9d
-		    "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
ae4d9d
+	attr = udev_device_get_sysattr_value(fc_host, "supported_fc4s");
ae4d9d
+	sscanf(attr, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
ae4d9d
+		     "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
ae4d9d
+		     "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
ae4d9d
+		     "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
ae4d9d
 		&data[0], &data[1], &data[2], &data[3], &data[4], &data[5],
ae4d9d
 		&data[6], &data[7], &data[8], &data[9], &data[10], &data[11],
ae4d9d
 		&data[12], &data[13], &data[14], &data[15], &data[16],
ae4d9d
@@ -380,11 +439,11 @@ sysfs_scan(struct dirent *dp, void *arg)
ae4d9d
 		pap->PortSupportedFc4Types.bits[i] = data[i];
ae4d9d
 
ae4d9d
 	/* Get PortActiveFc4Types */
ae4d9d
-	rc = sa_sys_read_line(pp->host_dir, "active_fc4s", buf, sizeof(buf));
ae4d9d
-	sscanf(buf, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
ae4d9d
-		    "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
ae4d9d
-		    "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
ae4d9d
-		    "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
ae4d9d
+	attr = udev_device_get_sysattr_value(fc_host, "active_fc4s");
ae4d9d
+	sscanf(attr, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
ae4d9d
+		     "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
ae4d9d
+		     "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
ae4d9d
+		     "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
ae4d9d
 		&data[0], &data[1], &data[2], &data[3], &data[4], &data[5],
ae4d9d
 		&data[6], &data[7], &data[8], &data[9], &data[10], &data[11],
ae4d9d
 		&data[12], &data[13], &data[14], &data[15], &data[16],
ae4d9d
@@ -395,19 +454,19 @@ sysfs_scan(struct dirent *dp, void *arg)
ae4d9d
 		pap->PortActiveFc4Types.bits[i] = data[i];
ae4d9d
 
ae4d9d
 	/* Get FabricName */
ae4d9d
-	rc = sys_read_wwn(pp->host_dir, "fabric_name", &pap->FabricName);
ae4d9d
+	attr = udev_device_get_sysattr_value(fc_host, "fabric_name");
ae4d9d
+	wwnn = strtoull(attr, NULL, 16);
ae4d9d
+	copy_wwn(&pap->FabricName, wwnn);
ae4d9d
 
ae4d9d
 	/* Get PortSupportedClassofService */
ae4d9d
-	rc = sa_sys_read_line(pp->host_dir, "supported_classes",
ae4d9d
-				buf, sizeof(buf));
ae4d9d
-
ae4d9d
-	cp = strstr(buf, "Class");
ae4d9d
+	attr = udev_device_get_sysattr_value(fc_host, "supported_classes");
ae4d9d
+	cp = strstr(attr, "Class");
ae4d9d
 	if (cp)
ae4d9d
 		pap->PortSupportedClassofService = *(cp + 6) - '0';
ae4d9d
 
ae4d9d
 	/* Get OSDeviceName */
ae4d9d
 	sa_strncpy_safe(pap->OSDeviceName, sizeof(pap->OSDeviceName),
ae4d9d
-			dp->d_name, sizeof(dp->d_name));
ae4d9d
+			sysname, sizeof(sysname));
ae4d9d
 
ae4d9d
 	/* Get NumberofDiscoveredPorts */
ae4d9d
 	snprintf(buf, sizeof(buf), "%s/device", pp->host_dir);
ae4d9d
@@ -428,104 +487,8 @@ sysfs_scan(struct dirent *dp, void *arg)
ae4d9d
 	snprintf(buf, sizeof(buf), "fcoe:%s", ifname);
ae4d9d
 	ap->ad_name = strdup(buf);
ae4d9d
 
ae4d9d
-	/* Get vendor_id */
ae4d9d
-	rc = sa_sys_read_u32(hba_dir, "vendor", &hba_info.vendor_id);
ae4d9d
-
ae4d9d
-	/* Get device_id */
ae4d9d
-	rc = sa_sys_read_u32(hba_dir, "device", &hba_info.device_id);
ae4d9d
-
ae4d9d
-	/* Get subsystem_vendor_id */
ae4d9d
-	rc = sa_sys_read_u32(hba_dir, "subsystem_vendor",
ae4d9d
-				&hba_info.subsystem_vendor_id);
ae4d9d
-
ae4d9d
-	/* Get subsystem_device_id */
ae4d9d
-	rc = sa_sys_read_u32(hba_dir, "subsystem_device",
ae4d9d
-				&hba_info.subsystem_device_id);
ae4d9d
-
ae4d9d
-	/* Get device_class */
ae4d9d
-	rc = sa_sys_read_u32(hba_dir, "class", &hba_info.device_class);
ae4d9d
-	hba_info.device_class = hba_info.device_class>>8;
ae4d9d
-
ae4d9d
-	/*
ae4d9d
-	 * Get Hardware Information via PCI Library
ae4d9d
-	 */
ae4d9d
-	(void) find_pci_device(&hba_info);
ae4d9d
-
ae4d9d
-	/* Get Number of Ports */
ae4d9d
-	atp->NumberOfPorts = hba_info.NumberOfPorts;
ae4d9d
-
ae4d9d
-	/* Get Manufacturer */
ae4d9d
-	sa_strncpy_safe(atp->Manufacturer, sizeof(atp->Manufacturer),
ae4d9d
-			hba_info.Manufacturer, sizeof(hba_info.Manufacturer));
ae4d9d
-
ae4d9d
-	/* Get SerialNumber */
ae4d9d
-	sa_strncpy_safe(atp->SerialNumber, sizeof(atp->SerialNumber),
ae4d9d
-			hba_info.SerialNumber, sizeof(hba_info.SerialNumber));
ae4d9d
-
ae4d9d
-
ae4d9d
-	/* Get ModelDescription */
ae4d9d
-	sa_strncpy_safe(atp->ModelDescription, sizeof(atp->ModelDescription),
ae4d9d
-			hba_info.ModelDescription,
ae4d9d
-			sizeof(hba_info.ModelDescription));
ae4d9d
-	if (!strncmp(hba_info.ModelDescription, "Unknown",
ae4d9d
-		 sizeof(hba_info.ModelDescription))) {
ae4d9d
-		snprintf(atp->ModelDescription, sizeof(atp->ModelDescription),
ae4d9d
-			"[%04x:%04x]-[%04x:%04x]-(%04x)",
ae4d9d
-			hba_info.vendor_id, hba_info.device_id,
ae4d9d
-			hba_info.subsystem_vendor_id,
ae4d9d
-			hba_info.subsystem_device_id,
ae4d9d
-			hba_info.device_class);
ae4d9d
-		/*
ae4d9d
-		 * Get Model
ae4d9d
-		 *
ae4d9d
-		 * If the device is a newly developed product, and
ae4d9d
-		 * the model description is not in pci.ids yet, use
ae4d9d
-		 * the model description constructed above as the
ae4d9d
-		 * model string.
ae4d9d
-		 */
ae4d9d
-		sa_strncpy_safe(atp->Model, sizeof(atp->Model),
ae4d9d
-				atp->ModelDescription,
ae4d9d
-				sizeof(atp->ModelDescription));
ae4d9d
-	}
ae4d9d
-
ae4d9d
-	/*
ae4d9d
-	 * Get Model
ae4d9d
-	 *
ae4d9d
-	 * If the device name has already been added into
ae4d9d
-	 * the pci.ids file, use the first word of the model
ae4d9d
-	 * description as the model. If the space after the
ae4d9d
-	 * first word is not found (new product), use the
ae4d9d
-	 * model description as the model.
ae4d9d
-	 */
ae4d9d
-	sa_strncpy_safe(buf, sizeof(buf), atp->ModelDescription,
ae4d9d
-			sizeof(atp->ModelDescription));
ae4d9d
-	if (strtok_r(buf, " ", &saveptr))
ae4d9d
-		sa_strncpy_safe(atp->Model, sizeof(atp->Model),
ae4d9d
-				buf, strnlen(buf, sizeof(buf)));
ae4d9d
-	else
ae4d9d
-		sa_strncpy_safe(atp->Model, sizeof(atp->Model),
ae4d9d
-				atp->ModelDescription,
ae4d9d
-				sizeof(atp->ModelDescription));
ae4d9d
-
ae4d9d
-	/* Get HardwareVersion */
ae4d9d
-	sa_strncpy_safe(atp->HardwareVersion, sizeof(atp->HardwareVersion),
ae4d9d
-			hba_info.HardwareVersion,
ae4d9d
-			sizeof(hba_info.HardwareVersion));
ae4d9d
-
ae4d9d
-	/* Get OptionROMVersion (TODO) */
ae4d9d
-	sa_strncpy_safe(atp->OptionROMVersion, sizeof(atp->OptionROMVersion),
ae4d9d
-			HBA_ROM_VERSION, sizeof(HBA_ROM_VERSION));
ae4d9d
-
ae4d9d
-	/* Get FirmwareVersion (TODO) */
ae4d9d
-	sa_strncpy_safe(atp->FirmwareVersion, sizeof(atp->FirmwareVersion),
ae4d9d
-			HBA_FW_VERSION, sizeof(HBA_FW_VERSION));
ae4d9d
-
ae4d9d
-	/* Get VendorSpecificID (TODO) */
ae4d9d
-	atp->VendorSpecificID = HBA_VENDOR_SPECIFIC_ID;
ae4d9d
-
ae4d9d
-	/* Get DriverVersion */
ae4d9d
-	rc = sa_sys_read_line(hba_dir, SYSFS_MODULE_VER,
ae4d9d
-			atp->DriverVersion, sizeof(atp->DriverVersion));
ae4d9d
+	if (pci)
ae4d9d
+		sysfs_scan_pci(pci, &hba_info, atp);
ae4d9d
 
ae4d9d
 	/* Get NodeSymbolicName */
ae4d9d
 	sa_strncpy_safe(atp->NodeSymbolicName, sizeof(atp->NodeSymbolicName),
ae4d9d
@@ -538,6 +501,7 @@ sysfs_scan(struct dirent *dp, void *arg)
ae4d9d
 		sizeof(pap->NodeWWN));
ae4d9d
 
ae4d9d
 	/* Get DriverName */
ae4d9d
+	hba_dir = udev_device_get_syspath(pci);
ae4d9d
 	snprintf(drv_dir, sizeof(drv_dir), "%s" SYSFS_MODULE , hba_dir);
ae4d9d
 	i = readlink(drv_dir, buf, sizeof(buf));
ae4d9d
 	if (i < 0)
ae4d9d
@@ -662,10 +626,48 @@ sysfs_get_port_fc4stats(char *dir, HBA_FC4STATISTICS *fc4sp)
ae4d9d
 /*
ae4d9d
  * Open device and read adapter info if available.
ae4d9d
  */
ae4d9d
-void
ae4d9d
+int
ae4d9d
 adapter_init(void)
ae4d9d
 {
ae4d9d
-	sa_dir_read(SYSFS_HOST_DIR, sysfs_scan, NULL);
ae4d9d
+	struct udev *udev;
ae4d9d
+	struct udev_enumerate *ue;
ae4d9d
+	struct udev_list_entry *head, *ul;
ae4d9d
+	struct udev_device *fc_host;
ae4d9d
+	const char *syspath;
ae4d9d
+	int re = 0;
ae4d9d
+
ae4d9d
+	udev = udev_new();
ae4d9d
+	if (!udev) {
ae4d9d
+		return -ENOMEM;
ae4d9d
+	}
ae4d9d
+	ue = udev_enumerate_new(udev);
ae4d9d
+	if (!ue) {
ae4d9d
+		re = -ENOMEM;
ae4d9d
+		goto err_enum_new;
ae4d9d
+	}
ae4d9d
+	re = udev_enumerate_add_match_subsystem(ue, "fc_host");
ae4d9d
+	if (re) {
ae4d9d
+		goto err_add_match;
ae4d9d
+	}
ae4d9d
+	re = udev_enumerate_scan_devices(ue);
ae4d9d
+	if (re) {
ae4d9d
+		goto err_scan_devs;
ae4d9d
+	}
ae4d9d
+	head = udev_enumerate_get_list_entry(ue);
ae4d9d
+	udev_list_entry_foreach(ul, head) {
ae4d9d
+		syspath = udev_list_entry_get_name(ul);
ae4d9d
+		fc_host = udev_device_new_from_syspath(udev, syspath);
ae4d9d
+		if (!fc_host)
ae4d9d
+			continue;
ae4d9d
+		sysfs_scan(fc_host);
ae4d9d
+		udev_device_unref(fc_host);
ae4d9d
+	}
ae4d9d
+err_scan_devs:
ae4d9d
+err_add_match:
ae4d9d
+	udev_enumerate_unref(ue);
ae4d9d
+err_enum_new:
ae4d9d
+	udev_unref(udev);
ae4d9d
+	return re;
ae4d9d
 }
ae4d9d
 
ae4d9d
 void