diff options
author | Felix Held <felix-coreboot@felixheld.de> | 2018-07-27 02:31:09 +0200 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2018-07-29 15:06:10 +0000 |
commit | f2ec648fcb6f17382293cbcc69e46c485ee3b786 (patch) | |
tree | ef7e792c2151f825051065a6b1b220404b00d38b /src/device/pnp_device.c | |
parent | 66ce18c508ffff42d290d4316b72d5fd153f8260 (diff) |
device/pnp_device: rewrite pnp_get_ioresource
The rewrite simplifies the code and fixes the limit on the case of IO resources
with the length of 1 byte.
This patch is inspired by the comment of Nico Huber on
Ia99b785dcd9cf56fb236ad7ade54656851f88a5e
If the ones in the mask aren't a continuous block, now a warning message gets
printed.
Change-Id: I0089278f5adf65e8f084580bc5bc1eb2f77b87f7
Signed-off-by: Felix Held <felix-coreboot@felixheld.de>
Reviewed-on: https://review.coreboot.org/27654
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Rudolph <siro@das-labor.org>
Diffstat (limited to 'src/device/pnp_device.c')
-rw-r--r-- | src/device/pnp_device.c | 63 |
1 files changed, 27 insertions, 36 deletions
diff --git a/src/device/pnp_device.c b/src/device/pnp_device.c index 5600231207..09a27487b3 100644 --- a/src/device/pnp_device.c +++ b/src/device/pnp_device.c @@ -7,6 +7,7 @@ * Copyright (C) 2005 Tyan * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan) * Copyright (C) 2013 Nico Huber <nico.h@gmx.de> + * Copyright (C) 2018 Felix Held <felix-coreboot@felixheld.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -194,8 +195,10 @@ struct device_operations pnp_ops = { static void pnp_get_ioresource(struct device *dev, u8 index, u16 mask) { struct resource *resource; - unsigned moving, gran, step; + unsigned int bit; + /* If none of the mask bits is set, the resource would occupy the whole + IO space leading to IO resource conflicts with the other devices */ if (!mask) { printk(BIOS_ERR, "ERROR: device %s index %d has no mask.\n", dev_path(dev), index); @@ -203,43 +206,31 @@ static void pnp_get_ioresource(struct device *dev, u8 index, u16 mask) } resource = new_resource(dev, index); - - /* Initilize the resource. */ - resource->limit = 0xffff; resource->flags |= IORESOURCE_IO; - /* Get the resource size... */ - - moving = mask; - gran = 15; - step = 1 << gran; - - /* Find the first bit that moves. */ - while ((moving & step) == 0) { - gran--; - step >>= 1; - } - - /* Now find the first bit that does not move. */ - while ((moving & step) != 0) { - gran--; - step >>= 1; - } - - /* - * Of the moving bits the last bit in the first group, - * tells us the size of this resource. - */ - if ((moving & step) == 0) { - gran++; - step <<= 1; - } - - /* Set the resource size and alignment. */ - resource->gran = gran; - resource->align = gran; - resource->limit = mask | (step - 1); - resource->size = 1 << gran; + /* Calculate IO region size which is determined by the first one from + the LSB of the mask. */ + for (bit = 0; bit <= 15 && (mask & (1 << bit)) == 0; ++bit) + ; + + resource->gran = bit; + resource->align = bit; + resource->size = 1 << bit; + + /* Calculate IO region address limit which is determined by the first + one from the MSB of the mask. */ + for (bit = 15; bit != 0 && (mask & (1 << bit)) == 0; --bit) + ; + + resource->limit = (1 << (bit + 1)) - 1; + + /* The block of ones in the mask is expected to be continuous. + If there is any zero inbetween the block of ones, it is ignored + in the calculation of the resource size and limit. */ + if (mask != (resource->limit ^ (resource->size - 1))) + printk(BIOS_WARNING, + "WARNING: mask of device %s index %d is wrong.\n", + dev_path(dev), index); } static void get_resources(struct device *dev, struct pnp_info *info) |