ACK: [PATCH 4/4] pci: maxreadreq: don't use lspci to get PCI specific data (LP: #1244676)

IvanHu ivan.hu at canonical.com
Mon Oct 28 06:56:50 UTC 2013


On 10/25/2013 10:12 PM, Colin King wrote:
> From: Colin Ian King <colin.king at canonical.com>
>
> Rather than do some messy parsing of the output from lspci, instead
> just use the raw data from /sys/bus/pci/devices
>
> Signed-off-by: Colin Ian King <colin.king at canonical.com>
> ---
>   src/pci/maxreadreq/maxreadreq.c | 139 +++++++++++++++++++---------------------
>   1 file changed, 66 insertions(+), 73 deletions(-)
>
> diff --git a/src/pci/maxreadreq/maxreadreq.c b/src/pci/maxreadreq/maxreadreq.c
> index b95e579..2af26d5 100644
> --- a/src/pci/maxreadreq/maxreadreq.c
> +++ b/src/pci/maxreadreq/maxreadreq.c
> @@ -27,97 +27,92 @@
>   #include <sys/types.h>
>   #include <sys/stat.h>
>   #include <unistd.h>
> +#include <limits.h>
> +#include <dirent.h>
> +#include <fcntl.h>
> +#include <inttypes.h>
>
>   /*
>    * This test checks if MaxReadReq is set > 128 for non-internal stuff
>    * A too low value hurts performance
>    */
> -
> -static fwts_list *lspci_text;
> -
> -static int maxreadreq_init(fwts_framework *fw)
> -{
> -	int status;
> -
> -	if (fwts_check_executable(fw, fw->lspci, "lspci"))
> -		return FWTS_ERROR;
> -
> -	if (fwts_pipe_exec("lspci -vvv", &lspci_text, &status) != FWTS_OK) {
> -		fwts_log_error(fw, "Failed to execute lspci -vvv.");
> -		return FWTS_ERROR;
> -	}
> -
> -	if (lspci_text == NULL) {
> -		fwts_log_error(fw, "Unexpected empty output from lspci -vvv.");
> -		return FWTS_ERROR;
> -	}
> -
> -	return FWTS_OK;
> -}
> -
> -static int maxreadreq_deinit(fwts_framework *fw)
> -{
> -	FWTS_UNUSED(fw);
> -
> -	if (lspci_text)
> -		fwts_text_list_free(lspci_text);
> -
> -	return FWTS_OK;
> -}
> -
>   static int maxreadreq_test1(fwts_framework *fw)
>   {
> +	DIR *dirp;
> +	struct dirent *entry;
>   	int warnings = 0;
> -	char current_type[512];
> -	char current_device[512];
> -
> -	fwts_list_link *item;
>
> -	if (lspci_text == NULL)
> +	if ((dirp = opendir(FWTS_PCI_DEV_PATH)) == NULL) {
> +		fwts_log_warning(fw, "Could not open %s.", FWTS_PCI_DEV_PATH);
>   		return FWTS_ERROR;
> +	}
>
> -	fwts_list_foreach(item, lspci_text) {
> -		char *line = fwts_text_list_text(item);
> -		int val = 0;
> -		char *c;
> +	while ((entry = readdir(dirp)) != NULL) {
> +		char path[PATH_MAX];
> +		uint8_t config[256];
> +		int fd;
> +		ssize_t n;
> +		uint8_t offset = 0;
>
> -		if (line[0]!=' ' && line[0] != '\t' && strlen(line)>8) {
> -			if (strlen(line) > 500){
> -				fwts_log_warning(fw,
> -					"Too big pci string would overflow "
> -					"current_device buffer Internal "
> -					"plugin, not a firmware bug.");
> -				break;
> -			}
> -			snprintf(current_device, sizeof(current_device), "pci://00:%s", line);
> -			strncpy(current_type, line+8, sizeof(current_type)-1);
> -			current_type[sizeof(current_type)-1] = '\0';
> -			c = strchr(current_type, ':');
> -			if (c)
> -				*c='\0';
> +		if (entry->d_name[0] == '.')
> +			continue;
> +
> +		/* Read Config space */
> +		snprintf(path, sizeof(path), FWTS_PCI_DEV_PATH "/%s/config", entry->d_name);
> +		if ((fd = open(path, O_RDONLY)) < 0) {
> +			fwts_log_warning(fw, "Could not open %s PCI config data\n", entry->d_name);
> +			continue;
>   		}
> -		/* chipset devices are exempt from this check */
> -		if (strcmp(current_type, "PCI bridge")==0)
> +		if ((n = read(fd, config, sizeof(config))) < 0) {
> +			fwts_log_warning(fw, "Could not read %s PCI config data\n", entry->d_name);
> +			close(fd);
>   			continue;
> -		if (strcmp(current_type, "Host bridge")==0)
> +		}
> +		close(fd);
> +
> +		/* Ignore Host Bridge */
> +		if ((config[FWTS_PCI_CONFIG_CLASS_CODE] == FWTS_PCI_CLASS_CODE_BRIDGE_CONTROLLER) &&
> +		    (config[FWTS_PCI_CONFIG_SUBCLASS] == FWTS_PCI_SUBCLASS_CODE_HOST_BRIDGE))
> +			continue;
> +		/* Ignore PCI Bridge */
> +		if ((config[FWTS_PCI_CONFIG_CLASS_CODE] == FWTS_PCI_CLASS_CODE_BRIDGE_CONTROLLER) &&
> +		    (config[FWTS_PCI_CONFIG_SUBCLASS] == FWTS_PCI_SUBCLASS_CODE_PCI_TO_PCI_BRIDGE))
>   			continue;
> -		if (strcmp(current_type, "System peripheral")==0)
> +		/* Ignore System Peripheral */
> +		if ((config[FWTS_PCI_CONFIG_CLASS_CODE] == FWTS_PCI_CLASS_CODE_BASE_SYSTEM_PERIPHERALS) &&
> +		    (config[FWTS_PCI_CONFIG_SUBCLASS] == FWTS_PCI_SUBCLASS_CODE_OTHER_SYSTEM_PERIPHERAL))
>   			continue;
> -		if (strcmp(current_type, "Audio device")==0)
> +		/* Ignore Audio Device */
> +		if ((config[FWTS_PCI_CONFIG_CLASS_CODE] == FWTS_PCI_CLASS_CODE_MULTIMEDIA_CONTROLLER) &&
> +		    (config[FWTS_PCI_CONFIG_SUBCLASS] == FWTS_PCI_SUBCLASS_CODE_AUDIO_DEVICE))
>   			continue;
>
> -		c = strstr(line, "MaxReadReq ");
> -		if (c) {
> -			c += 11;
> -			val = strtoul(c, NULL, 10);
> -			if (val <= 128) {
> -				fwts_log_warning(fw,
> -					"MaxReadReq for %s is low (%d) [%s].",
> -					current_device, val, current_type);
> -				warnings++;
> +		/* config region too small, do next */
> +		if (n < FWTS_PCI_CONFIG_TYPE0_CAPABILITIES_POINTER)
> +			continue;
> +		offset = config[FWTS_PCI_CONFIG_TYPE0_CAPABILITIES_POINTER];
> +
> +		/*
> +		 *  Step through capability structures and
> +		 *  examine MaxReadReq settings
> +		 */
> +		while ((offset != FWTS_PCI_CAPABILITIES_LAST_ID) &&
> +		       (offset > 0) && ((ssize_t)(offset + sizeof(fwts_pcie_capability)) <= n)) {
> +			fwts_pcie_capability *cap = (fwts_pcie_capability *)&config[offset];
> +
> +			if (cap->pcie_cap_id == FWTS_PCI_EXPRESS_CAP_ID) {
> +				uint32_t max_readreq = 128 << ((cap->device_contrl >> 12) & 0x3);
> +				if (max_readreq <= 128) {
> +					fwts_log_warning(fw,
> +						"MaxReadReq for %s is low (%" PRIu32 ").",
> +						entry->d_name, max_readreq);
> +					warnings++;
> +				}
>   			}
> +			offset = cap->next_cap_point;
>   		}
>   	}
> +	closedir(dirp);
>
>   	if (warnings > 0) {
>   		fwts_failed(fw, LOG_LEVEL_LOW,
> @@ -125,7 +120,7 @@ static int maxreadreq_test1(fwts_framework *fw)
>   			"%d devices have low MaxReadReq settings. "
>   			"Firmware may have configured these too low.",
>   			warnings);
> -		fwts_advice(fw,
> +		fwts_advice(fw,
>   			"The MaxReadRequest size is set too low and will affect performance. "
>   			"It will provide excellent bus sharing at the cost of bus data transfer "
>   			"rates. Although not a critical issue, it may be worth considering setting "
> @@ -148,8 +143,6 @@ static fwts_framework_minor_test maxreadreq_tests[] = {
>
>   static fwts_framework_ops maxreadreq_ops = {
>   	.description = "Checks firmware has set PCI Express MaxReadReq to a higher value on non-motherboard devices.",
> -	.init        = maxreadreq_init,
> -	.deinit      = maxreadreq_deinit,
>   	.minor_tests = maxreadreq_tests
>   };
>
>

Acked-by: Ivan Hu <ivan.hu at canonical.com>



More information about the fwts-devel mailing list