From d70af62b5b08e008ef3f86f9ac1fc58b2a1c0083 Mon Sep 17 00:00:00 2001
From: Wen Xiong <wenxiong@linux.vnet.ibm.com>
Date: Wed, 16 Jul 2014 19:54:26 -0500
Subject: [PATCH 12/28] iprutils: Segmentation fault when calling concurrent add/remove GUI

The patch fixes segmentation fault when calling concurrent add/remove GUI
and wrong IOA physical location code in PowerNV environemnt.

signed-off-by: Wen Xiong<wenxiong@linux.vnet.ibm.com>
---
 iprutils/iprconfig.c |    6 ++-
 iprutils/iprlib.c    |   82 +++++++++++++++++++++++++++------------------------
 2 files changed, 48 insertions(+), 40 deletions(-)

Index: b/iprutils/iprconfig.c
===================================================================
--- a/iprutils/iprconfig.c	2015-01-05 19:50:29.590683985 -0600
+++ b/iprutils/iprconfig.c	2015-01-05 19:52:51.920684205 -0600
@@ -2532,7 +2532,8 @@ int get_drive_phy_loc_with_ses_phy_loc(s
 		if (strlen(buffer)) {
 			ipr_strncpy_0(unit_phy_loc, ses->physical_location, PHYSICAL_LOCATION_LENGTH);
 			first_hyphen = strchr(unit_phy_loc, '-');
-			*first_hyphen = '\0';
+			if (first_hyphen != NULL)
+				*first_hyphen = '\0';
 			sprintf(buf, "%s-%s", unit_phy_loc, buffer);
 		}
 		else
@@ -2542,7 +2543,8 @@ int get_drive_phy_loc_with_ses_phy_loc(s
 		if (strlen(ses->ioa->physical_location)) {
 			ipr_strncpy_0(unit_phy_loc, ses->ioa->physical_location, PHYSICAL_LOCATION_LENGTH);
 			first_hyphen = strchr(unit_phy_loc, '-');
-			*first_hyphen = '\0';
+			if (first_hyphen != NULL)
+				*first_hyphen = '\0';
 			sprintf(buf, "%s-%s", unit_phy_loc, buffer);
 		} else
 			sprintf(buf, "%s", "\0");
Index: b/iprutils/iprlib.c
===================================================================
--- a/iprutils/iprlib.c	2015-01-05 19:47:57.560677966 -0600
+++ b/iprutils/iprlib.c	2015-01-05 19:52:51.930684154 -0600
@@ -1931,11 +1931,46 @@ static void ipr_get_pci_slots()
 	char devspec[PATH_MAX], locpath[PATH_MAX];
 	char loc_code[1024], *last_hyphen, *prev_hyphen;
 	int num_slots, i, j, rc, num_attrs;
-	int slot_found = 0;
+	int loc_code_not_found = 0;
 	struct dirent **slotdir, **dirent;
 	struct stat statbuf;
 	struct ipr_ioa *ioa;
 
+	for_each_ioa(ioa)
+		ioa->physical_location[0] = '\0';
+
+	for_each_ioa(ioa) {
+		sprintf(attr, "/sys/bus/pci/devices/%s/devspec",
+			ioa->pci_address);
+		rc = read_attr_file(attr, devspec, PATH_MAX);
+
+		if (rc)
+			continue;
+
+		sprintf(locpath, "/proc/device-tree%s/ibm,loc-code",
+			devspec);
+		rc = read_attr_file(locpath, loc_code,
+				    sizeof(loc_code));
+
+		if (rc) {
+			loc_code_not_found = 1;
+			continue;
+		}
+
+		last_hyphen = strrchr(loc_code, '-');
+		if (last_hyphen && last_hyphen[1] == 'T') {
+			*last_hyphen = '\0';
+			prev_hyphen = strrchr(loc_code, '-');
+			if (prev_hyphen && prev_hyphen[1] != 'C')
+					*last_hyphen = '-';
+			}
+
+		strcpy(ioa->physical_location, loc_code);
+	}
+
+	if (loc_code_not_found == 0)
+		return;
+
 	sprintf(rootslot, "/sys/bus/pci/slots/");
 
 	num_slots = scandir(rootslot, &slotdir, NULL, alphasort);
@@ -1999,45 +2034,16 @@ static void ipr_get_pci_slots()
 		free(slotdir);
 	}
 
-	for_each_ioa(ioa)
-		ioa->physical_location[0] = '\0';
-
 	for_each_ioa(ioa) {
-		slot_found = 0;
-		for (i = 0; i < num_pci_slots; i++) {
-			if (strcmp(pci_slot[i].pci_device, ioa->pci_address) &&
-			    strcmp(pci_slot[i].slot_name, ioa->pci_address))
-				continue;
-			strcpy(ioa->physical_location,
-			       pci_slot[i].physical_name);
-			slot_found = 1;
-			break;
-		}
-		if (!slot_found) {
-			sprintf(attr, "/sys/bus/pci/devices/%s/devspec",
-				ioa->pci_address);
-			rc = read_attr_file(attr, devspec, PATH_MAX);
-
-			if (rc)
-				continue;
-
-			sprintf(locpath, "/proc/device-tree%s/ibm,loc-code",
-				devspec);
-			rc = read_attr_file(locpath, loc_code,
-					    sizeof(loc_code));
-
-			if (rc)
-				continue;
-
-			last_hyphen = strrchr(loc_code, '-');
-			if (last_hyphen && last_hyphen[1] == 'T') {
-				*last_hyphen = '\0';
-				prev_hyphen = strrchr(loc_code, '-');
-				if (prev_hyphen && prev_hyphen[1] != 'C')
-					*last_hyphen = '-';
+		if (strlen(ioa->physical_location) == 0) {
+			for (i = 0; i < num_pci_slots; i++) {
+				if (strcmp(pci_slot[i].pci_device, ioa->pci_address) &&
+				    strcmp(pci_slot[i].slot_name, ioa->pci_address))
+					continue;
+				strcpy(ioa->physical_location,
+				       pci_slot[i].physical_name);
+				break;
 			}
-
-			strcpy(ioa->physical_location, loc_code);
 		}
 	}
 
