aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/pnpacpi/rsparser.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2008-06-27 18:56:57 -0400
committerAndi Kleen <andi@basil.nowhere.org>2008-07-16 17:27:05 -0400
commitaee3ad815dd291a7193ab01da0f1a30c84d00061 (patch)
treeb0549b2a98ddfe6734e1e5f7cedd3958eec18503 /drivers/pnp/pnpacpi/rsparser.c
parent20bfdbba7212d19613b93dcea93f26cb65af91fe (diff)
PNP: replace pnp_resource_table with dynamically allocated resources
PNP used to have a fixed-size pnp_resource_table for tracking the resources used by a device. This table often overflowed, so we've had to increase the table size, which wastes memory because most devices have very few resources. This patch replaces the table with a linked list of resources where the entries are allocated on demand. This removes messages like these: pnpacpi: exceeded the max number of IO resources 00:01: too many I/O port resources References: http://bugzilla.kernel.org/show_bug.cgi?id=9535 http://bugzilla.kernel.org/show_bug.cgi?id=9740 http://lkml.org/lkml/2007/11/30/110 This patch also changes the way PNP uses the IORESOURCE_UNSET, IORESOURCE_AUTO, and IORESOURCE_DISABLED flags. Prior to this patch, the pnp_resource_table entries used the flags like this: IORESOURCE_UNSET This table entry is unused and available for use. When this flag is set, we shouldn't look at anything else in the resource structure. This flag is set when a resource table entry is initialized. IORESOURCE_AUTO This resource was assigned automatically by pnp_assign_{io,mem,etc}(). This flag is set when a resource table entry is initialized and cleared whenever we discover a resource setting by reading an ISAPNP config register, parsing a PNPBIOS resource data stream, parsing an ACPI _CRS list, or interpreting a sysfs "set" command. Resources marked IORESOURCE_AUTO are reinitialized and marked as IORESOURCE_UNSET by pnp_clean_resource_table() in these cases: - before we attempt to assign resources automatically, - if we fail to assign resources automatically, - after disabling a device IORESOURCE_DISABLED Set by pnp_assign_{io,mem,etc}() when automatic assignment fails. Also set by PNPBIOS and PNPACPI for: - invalid IRQs or GSI registration failures - invalid DMA channels - I/O ports above 0x10000 - mem ranges with negative length After this patch, there is no pnp_resource_table, and the resource list entries use the flags like this: IORESOURCE_UNSET This flag is no longer used in PNP. Instead of keeping IORESOURCE_UNSET entries in the resource list, we remove entries from the list and free them. IORESOURCE_AUTO No change in meaning: it still means the resource was assigned automatically by pnp_assign_{port,mem,etc}(), but these functions now set the bit explicitly. We still "clean" a device's resource list in the same places, but rather than reinitializing IORESOURCE_AUTO entries, we just remove them from the list. Note that IORESOURCE_AUTO entries are always at the end of the list, so removing them doesn't reorder other list entries. This is because non-IORESOURCE_AUTO entries are added by the ISAPNP, PNPBIOS, or PNPACPI "get resources" methods and by the sysfs "set" command. In each of these cases, we completely free the resource list first. IORESOURCE_DISABLED In addition to the cases where we used to set this flag, ISAPNP now adds an IORESOURCE_DISABLED resource when it reads a configuration register with a "disabled" value. Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Len Brown <len.brown@intel.com> Signed-off-by: Andi Kleen <ak@linux.intel.com>
Diffstat (limited to 'drivers/pnp/pnpacpi/rsparser.c')
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c131
1 files changed, 88 insertions, 43 deletions
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 46c791adb894..9a45c25b46d2 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -806,6 +806,13 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev,
806 struct acpi_resource_irq *irq = &resource->data.irq; 806 struct acpi_resource_irq *irq = &resource->data.irq;
807 int triggering, polarity, shareable; 807 int triggering, polarity, shareable;
808 808
809 if (!pnp_resource_enabled(p)) {
810 irq->interrupt_count = 0;
811 dev_dbg(&dev->dev, " encode irq (%s)\n",
812 p ? "disabled" : "missing");
813 return;
814 }
815
809 decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); 816 decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
810 irq->triggering = triggering; 817 irq->triggering = triggering;
811 irq->polarity = polarity; 818 irq->polarity = polarity;
@@ -828,6 +835,13 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
828 struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; 835 struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
829 int triggering, polarity, shareable; 836 int triggering, polarity, shareable;
830 837
838 if (!pnp_resource_enabled(p)) {
839 extended_irq->interrupt_count = 0;
840 dev_dbg(&dev->dev, " encode extended irq (%s)\n",
841 p ? "disabled" : "missing");
842 return;
843 }
844
831 decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); 845 decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
832 extended_irq->producer_consumer = ACPI_CONSUMER; 846 extended_irq->producer_consumer = ACPI_CONSUMER;
833 extended_irq->triggering = triggering; 847 extended_irq->triggering = triggering;
@@ -848,6 +862,13 @@ static void pnpacpi_encode_dma(struct pnp_dev *dev,
848{ 862{
849 struct acpi_resource_dma *dma = &resource->data.dma; 863 struct acpi_resource_dma *dma = &resource->data.dma;
850 864
865 if (!pnp_resource_enabled(p)) {
866 dma->channel_count = 0;
867 dev_dbg(&dev->dev, " encode dma (%s)\n",
868 p ? "disabled" : "missing");
869 return;
870 }
871
851 /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ 872 /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
852 switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { 873 switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
853 case IORESOURCE_DMA_TYPEA: 874 case IORESOURCE_DMA_TYPEA:
@@ -889,17 +910,21 @@ static void pnpacpi_encode_io(struct pnp_dev *dev,
889{ 910{
890 struct acpi_resource_io *io = &resource->data.io; 911 struct acpi_resource_io *io = &resource->data.io;
891 912
892 /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ 913 if (pnp_resource_enabled(p)) {
893 io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ? 914 /* Note: pnp_assign_port copies pnp_port->flags into p->flags */
894 ACPI_DECODE_16 : ACPI_DECODE_10; 915 io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
895 io->minimum = p->start; 916 ACPI_DECODE_16 : ACPI_DECODE_10;
896 io->maximum = p->end; 917 io->minimum = p->start;
897 io->alignment = 0; /* Correct? */ 918 io->maximum = p->end;
898 io->address_length = p->end - p->start + 1; 919 io->alignment = 0; /* Correct? */
899 920 io->address_length = p->end - p->start + 1;
900 dev_dbg(&dev->dev, " encode io %#llx-%#llx decode %#x\n", 921 } else {
901 (unsigned long long) p->start, (unsigned long long) p->end, 922 io->minimum = 0;
902 io->io_decode); 923 io->address_length = 0;
924 }
925
926 dev_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum,
927 io->minimum + io->address_length - 1, io->io_decode);
903} 928}
904 929
905static void pnpacpi_encode_fixed_io(struct pnp_dev *dev, 930static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
@@ -908,11 +933,16 @@ static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
908{ 933{
909 struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io; 934 struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;
910 935
911 fixed_io->address = p->start; 936 if (pnp_resource_enabled(p)) {
912 fixed_io->address_length = p->end - p->start + 1; 937 fixed_io->address = p->start;
938 fixed_io->address_length = p->end - p->start + 1;
939 } else {
940 fixed_io->address = 0;
941 fixed_io->address_length = 0;
942 }
913 943
914 dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n", 944 dev_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address,
915 (unsigned long long) p->start, (unsigned long long) p->end); 945 fixed_io->address + fixed_io->address_length - 1);
916} 946}
917 947
918static void pnpacpi_encode_mem24(struct pnp_dev *dev, 948static void pnpacpi_encode_mem24(struct pnp_dev *dev,
@@ -921,17 +951,22 @@ static void pnpacpi_encode_mem24(struct pnp_dev *dev,
921{ 951{
922 struct acpi_resource_memory24 *memory24 = &resource->data.memory24; 952 struct acpi_resource_memory24 *memory24 = &resource->data.memory24;
923 953
924 /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ 954 if (pnp_resource_enabled(p)) {
925 memory24->write_protect = 955 /* Note: pnp_assign_mem copies pnp_mem->flags into p->flags */
926 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 956 memory24->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
927 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 957 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
928 memory24->minimum = p->start; 958 memory24->minimum = p->start;
929 memory24->maximum = p->end; 959 memory24->maximum = p->end;
930 memory24->alignment = 0; 960 memory24->alignment = 0;
931 memory24->address_length = p->end - p->start + 1; 961 memory24->address_length = p->end - p->start + 1;
932 962 } else {
933 dev_dbg(&dev->dev, " encode mem24 %#llx-%#llx write_protect %#x\n", 963 memory24->minimum = 0;
934 (unsigned long long) p->start, (unsigned long long) p->end, 964 memory24->address_length = 0;
965 }
966
967 dev_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n",
968 memory24->minimum,
969 memory24->minimum + memory24->address_length - 1,
935 memory24->write_protect); 970 memory24->write_protect);
936} 971}
937 972
@@ -941,16 +976,21 @@ static void pnpacpi_encode_mem32(struct pnp_dev *dev,
941{ 976{
942 struct acpi_resource_memory32 *memory32 = &resource->data.memory32; 977 struct acpi_resource_memory32 *memory32 = &resource->data.memory32;
943 978
944 memory32->write_protect = 979 if (pnp_resource_enabled(p)) {
945 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 980 memory32->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
946 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 981 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
947 memory32->minimum = p->start; 982 memory32->minimum = p->start;
948 memory32->maximum = p->end; 983 memory32->maximum = p->end;
949 memory32->alignment = 0; 984 memory32->alignment = 0;
950 memory32->address_length = p->end - p->start + 1; 985 memory32->address_length = p->end - p->start + 1;
986 } else {
987 memory32->minimum = 0;
988 memory32->alignment = 0;
989 }
951 990
952 dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx write_protect %#x\n", 991 dev_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n",
953 (unsigned long long) p->start, (unsigned long long) p->end, 992 memory32->minimum,
993 memory32->minimum + memory32->address_length - 1,
954 memory32->write_protect); 994 memory32->write_protect);
955} 995}
956 996
@@ -960,15 +1000,20 @@ static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
960{ 1000{
961 struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32; 1001 struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;
962 1002
963 fixed_memory32->write_protect = 1003 if (pnp_resource_enabled(p)) {
964 (p->flags & IORESOURCE_MEM_WRITEABLE) ? 1004 fixed_memory32->write_protect =
965 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; 1005 p->flags & IORESOURCE_MEM_WRITEABLE ?
966 fixed_memory32->address = p->start; 1006 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
967 fixed_memory32->address_length = p->end - p->start + 1; 1007 fixed_memory32->address = p->start;
1008 fixed_memory32->address_length = p->end - p->start + 1;
1009 } else {
1010 fixed_memory32->address = 0;
1011 fixed_memory32->address_length = 0;
1012 }
968 1013
969 dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx " 1014 dev_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n",
970 "write_protect %#x\n", 1015 fixed_memory32->address,
971 (unsigned long long) p->start, (unsigned long long) p->end, 1016 fixed_memory32->address + fixed_memory32->address_length - 1,
972 fixed_memory32->write_protect); 1017 fixed_memory32->write_protect);
973} 1018}
974 1019