PNP: convert resource options to unified dynamic list, v1
Subsystems (3)
cover PNP: convert resource options to unified dynamic list, v1
This patch series converts the PNP resource option structures to a unified linked list. This preserves resource order, which is important for some devices. There's more detail in the comments for the last patch.
Any comments would be welcome.
This depends on some patches that are in -mm, but not yet upstream. In mmotm, these would probably go after pnp-dont-sort-by-type-in-sys-resources.patch
Bjorn
PATCH 1/15 serial: when guessing, check only active resources, not options
Given a completely unknown PNP device, if it happens to have a modem-like string in its name and it matches a COM port address, we assume it's a modem.
We used to check the address against all the possible resource options for the device. But the device is already configured and enabled, so we only need to check the resources it is actually using. If we matched an address that wasn't currently enabled, we would fail anyway as soon as we attempted to touch the device at that address.
This removes a reference to the struct pnp_dev.{independent,dependent} fields, which I will soon make private to the PNP subsystem.
drivers/serial/8250_pnp.c +11 -17
@@ -383,22 +383,19 @@ static int __devinit check_name(char *nareturn 0 ; } -static int __devinit check_resources (struct pnp_option *option) +static int __devinit check_resources (struct pnp_dev *dev) { -struct pnp_option *tmp; -if (!option) +resource_size_t port, size; + +if (!pnp_port_valid (dev,0 ))return 0 ; -for (tmp = option; tmp; tmp = tmp->next) { -struct pnp_port *port; -for (port = tmp->port; port; port = port->next) -if ((port->size ==8 ) && - ((port->min ==0x2f8 ) || - (port->min ==0x3f8 ) || - (port->min ==0x2e8 ) || - (port->min ==0x3e8 ))) -return 1 ; - } + port =pnp_port_start (dev,0 ); + size =pnp_port_len (dev,0 ); + +if (size ==8 && + (port ==0x2f8 || port ==0x3f8 || port ==0x2e8 || port ==0x3e8 )) +return 1 ;return 0 ; }
@@ -420,10 +417,7 @@ static int __devinit serial_pnp_guess_bo (dev->card && check_name(dev->card->name))))return -ENODEV ; -if (check_resources (dev->independent)) -return 0 ; - -if (check_resources (dev->dependent)) +if (check_resources (dev))return 0 ;return -ENODEV ;
Re: [patch 01/15] serial: when guessing, check only active resources, not options
Quoted 11 lines · Bjorn Helgaas
Given a completely unknown PNP device, if it happens to have a modem-like string in its name and it matches a COM port address, we assume it's a modem.
We used to check the address against all the possible resource options for the device. But the device is already configured and enabled, so we only need to check the resources it is actually using. If we matched an address that wasn't currently enabled, we would fail anyway as soon as we attempted to touch the device at that address.
Quoted 4 lines
This removes a reference to the struct pnp_dev.{independent,dependent} fields, which I will soon make private to the PNP subsystem.
Signed-off-by Bjorn Helgaas <[email protected]>
This isn't quite right it seems. Or changes behaviour at least:
Quoted 39 lines
Index:
work10/drivers/serial/8250_pnp.c
===================================================================drivers/serial/8250_pnp.c +10
-13@@ -383,22 +383,19 @@ static int __devinit check_name(char *nareturn 0 ; } -static int __devinit check_resources (struct pnp_option *option) +static int __devinit check_resources (struct pnp_dev *dev) { -struct pnp_option *tmp; -if (!option) +resource_size_t port, size; + +if (!pnp_port_valid (dev,0 ))return 0 ; -for (tmp = option; tmp; tmp = tmp->next) { -struct pnp_port *port; -for (port = tmp->port; port; port = port->next) -if ((port->size ==8 ) && - ((port->min ==0x2f8 ) || - (port->min ==0x3f8 ) || - (port->min ==0x2e8 ) || - (port->min ==0x3e8 ))) -return 1 ; - } + port =pnp_port_start (dev,0 ); + size =pnp_port_len (dev,0 ); + +if (size ==8 && + (port ==0x2f8 || port ==0x3f8 || port ==0x2e8 || port ==0x3e8 )) +return 1 ;return 0 ; }@@ -420,10 +417,7 @@ static int __devinit serial_pnp_guess_bo (dev->card && check_name(dev->card->name))))
drivers/serial/8250_pnp.c static int __devinit serial_pnp_guess_bo · line 423
Quoted 10 lines
drivers/serial/8250_pnp.c +1
-4return -ENODEV ; -if (check_resources (dev->independent)) -return 0 ; - -if (check_resources (dev->dependent)) +if (check_resources (dev))return 0 ;return -ENODEV ;
We used to cry "modem" if the device _could_ be configured using a COM address while after this change we'd only do so if it _was_ configured using one.
My old analog modem for example had 5 dependent sets -- the first with the regular COM port addresses (0x3f8, 0x2f8, 0x3e8, 0x2e8) and a 5th one listing a port range of (IIRC, something like that at least) 0x100 to 0xff8.
So say I'd have a PC with the regular two onboard COM ports at COM1 and COM2 (0x3f8 and 0x2f8) and an additional serial controller providing COM3 and COM4 (0x3e8 and 0x2e8). My modem would then be configured to use 0x100 and this code would no longer trigger while it did use to.
Not that I care deeply or anything but whomever wrote this did no doubt intend it to work this way...
Rene.
Re: [patch 01/15] serial: when guessing, check only active resources, not options
Quoted 9 lines · Rene Herman
We used to cry "modem" if the device _could_ be configured using a COM address while after this change we'd only do so if it _was_ configured using one.
My old analog modem for example had 5 dependent sets -- the first with the regular COM port addresses (
0x3f8,0x2f8,0x3e8,0x2e8) and a 5th one listing a port range of (IIRC, something like that at least)0x100to0xff8.
Quoted 4 lines
So say I'd have a PC with the regular two onboard COM ports at COM1 and COM2 (
0x3f8and0x2f8) and an additional serial controller providing COM3 and COM4 (0x3e8and0x2e8). My modem would then be configured to use0x100and this code would no longer trigger while it did use to.
Ah, you're right. That scenario hadn't occurred to me. Let me see if I can figure out a way to make that work again.
Bjorn
PATCH 2/15 PNP: whitespace/coding style fixes
In reply to Bjorn HelgaasNo functional change; just make a couple declarations consistent with the rest of the file.
drivers/pnp/interface.c +8 -7
@@ -216,12 +216,12 @@ static ssize_t pnp_show_options(struct d struct device_attribute *attr, char *buf) { struct pnp_dev *dev = to_pnp_dev(dmdev); +pnp_info_buffer_t *buffer;struct pnp_option *independent = dev->independent;struct pnp_option *dependent = dev->dependent;int ret, dep =1 ; -pnp_info_buffer_t *buffer = (pnp_info_buffer_t *) -pnp_alloc (sizeof (pnp_info_buffer_t)); + buffer =pnp_alloc (sizeof (pnp_info_buffer_t));if (!buffer)return -ENOMEM ;
@@ -248,17 +248,18 @@ static ssize_t pnp_show_current_resource char *buf) {struct pnp_dev *dev =to_pnp_dev (dmdev); +pnp_info_buffer_t *buffer;struct pnp_resource *pnp_res;struct resource *res;int ret; -pnp_info_buffer_t *buffer;if (!dev)return -EINVAL ; - buffer = (pnp_info_buffer_t *)pnp_alloc (sizeof (pnp_info_buffer_t)); + buffer =pnp_alloc (sizeof (pnp_info_buffer_t));if (!buffer)return -ENOMEM ; + buffer->len =PAGE_SIZE ; buffer->buffer = buf; buffer->curr = buffer->buffer;
@@ -295,9 +296,9 @@ static ssize_t pnp_show_current_resourcereturn ret; } -static ssize_t -pnp_set_current_resources (struct device *dmdev,struct device_attribute *attr, -const char *ubuf,size_t count) +static ssize_t pnp_set_current_resources (struct device *dmdev, +struct device_attribute *attr, +const char *ubuf,size_t count) {struct pnp_dev *dev =to_pnp_dev (dmdev);char *buf = (void *)ubuf;
Re: [patch 02/15] PNP: whitespace/coding style fixes
Quoted 4 lines · Bjorn Helgaas
No functional change; just make a couple declarations consistent with the rest of the file.
Signed-off-by Bjorn Helgaas <[email protected]>
By the way, noticed recently that Acked-by might not be the right tag given that I'm not in any formal acking path or anything; feel free to translate them into any tag of your liking. They're meant as "looked at this and agree".
Rene.
PATCH 3/15 PNP: define PNP-specific IORESOURCE_IO_* flags alongside IRQ, DMA, MEM
In reply to Bjorn HelgaasPNP previously defined PNP_PORT_FLAG_16BITADDR and PNP_PORT_FLAG_FIXED in a private header file, but put those flags in struct resource.flags fields. Better to make them IORESOURCE_IO_* flags like the existing IRQ, DMA, and MEM flags.
--- include/linux/ioport.h | 10 +++++++--- include/linux/pnp.h | 3 --- drivers/pnp/interface.c | 2 +- drivers/pnp/isapnp/core.c | 4 ++-- drivers/pnp/pnpacpi/rsparser.c | 10 +++++----- drivers/pnp/pnpbios/rsparser.c | 4 ++-- 6 files changed, 17 insertions(+), 16 deletions(-)
include/linux/ioport.h +5 -1
@@ -76,7 +76,7 @@ struct resource_list {#define IORESOURCE_DMA_TYPEB (2<<6)#define IORESOURCE_DMA_TYPEF (3<<6) -/* ISA PnP memory I/O specific bits (IORESOURCE_BITS) */ +/* ISA PnP memory specific bits (IORESOURCE_BITS) */ #define IORESOURCE_MEM_WRITEABLE (1<<0)/* dup: IORESOURCE_READONLY */ #define IORESOURCE_MEM_CACHEABLE (1<<1)/* dup: IORESOURCE_CACHEABLE */ #define IORESOURCE_MEM_RANGELENGTH (1<<2)/* dup: IORESOURCE_RANGELENGTH */
@@ -88,6 +88,10 @@ struct resource_list {#define IORESOURCE_MEM_SHADOWABLE (1<<5)/* dup: IORESOURCE_SHADOWABLE */ #define IORESOURCE_MEM_EXPANSIONROM (1<<6) +/* ISA PnP I/O specific bits (IORESOURCE_BITS) */ +#define IORESOURCE_IO_16BIT_ADDR (1<<0) +#define IORESOURCE_IO_FIXED (1<<1) +/* PCI ROM control bits (IORESOURCE_BITS) */ #define IORESOURCE_ROM_ENABLE (1<<0)/* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */ #define IORESOURCE_ROM_SHADOW (1<<1)/* ROM is copy at C000:0 */
include/linux/pnp.h +0 -3
@@ -175,9 +175,6 @@ static inline int pnp_dma_valid(struct p } -#define PNP_PORT_FLAG_16BITADDR (1<<0) -#define PNP_PORT_FLAG_FIXED (1<<1) -struct pnp_port {unsigned short min;/* min base number */ unsigned short max;/* max base number */
drivers/pnp/interface.c +1 -1
@@ -57,7 +57,7 @@ static void pnp_print_port(pnp_info_buff"%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n" , space, port->min, port->max, port->align ? (port->align -1 ) :0 , port->size, - port->flags & PNP_PORT_FLAG_16BITADDR ? 16 : 10); + port->flags & IORESOURCE_IO_16BIT_ADDR ? 16 : 10); } static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space,
drivers/pnp/isapnp/core.c +2 -2
@@ -486,7 +486,7 @@ static void __init isapnp_parse_port_res port->max = (tmp[4 ] <<8 ) | tmp[3 ]; port->align = tmp[5 ]; port->size = tmp[6 ]; - port->flags = tmp[0 ] ?PNP_PORT_FLAG_16BITADDR :0 ; + port->flags = tmp[0 ] ?IORESOURCE_IO_16BIT_ADDR :0 ;pnp_register_port_resource (dev, option, port); }
@@ -507,7 +507,7 @@ static void __init isapnp_parse_fixed_po port->min = port->max = (tmp[1 ] <<8 ) | tmp[0 ]; port->size = tmp[2 ]; port->align =0 ; - port->flags =PNP_PORT_FLAG_FIXED ; + port->flags =IORESOURCE_IO_FIXED ;pnp_register_port_resource (dev, option, port); }
drivers/pnp/pnpacpi/rsparser.c +5 -5
@@ -178,7 +178,7 @@ static void pnpacpi_parse_allocated_ioreu64 end = start + len -1 ;if (io_decode ==ACPI_DECODE_16 ) - flags |=PNP_PORT_FLAG_16BITADDR ; + flags |=IORESOURCE_IO_16BIT_ADDR ;if (len ==0 || end >=0x10003 ) flags |=IORESOURCE_DISABLED ;
@@ -451,7 +451,7 @@ static __init void pnpacpi_parse_port_op port->align = io->alignment; port->size = io->address_length; port->flags =ACPI_DECODE_16 == io->io_decode ? -PNP_PORT_FLAG_16BITADDR :0 ; +IORESOURCE_IO_16BIT_ADDR :0 ;pnp_register_port_resource (dev, option, port); }
@@ -469,7 +469,7 @@ static __init void pnpacpi_parse_fixed_p port->min = port->max = io->address; port->size = io->address_length; port->align =0 ; - port->flags =PNP_PORT_FLAG_FIXED ; + port->flags =IORESOURCE_IO_FIXED ;pnp_register_port_resource (dev, option, port); }
@@ -575,7 +575,7 @@ static __init void pnpacpi_parse_address port->min = port->max = p->minimum; port->size = p->address_length; port->align =0 ; - port->flags =PNP_PORT_FLAG_FIXED ; + port->flags =IORESOURCE_IO_FIXED ;pnp_register_port_resource (dev, option, port); } }
@@ -890,7 +890,7 @@ static void pnpacpi_encode_io(struct pnpstruct acpi_resource_io *io = &resource->data.io;/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ - io->io_decode = (p->flags &PNP_PORT_FLAG_16BITADDR ) ? + io->io_decode = (p->flags &IORESOURCE_IO_16BIT_ADDR ) ?ACPI_DECODE_16 :ACPI_DECODE_10 ; io->minimum = p->start; io->maximum = p->end;
drivers/pnp/pnpbios/rsparser.c +2 -2
@@ -310,7 +310,7 @@ static __init void pnpbios_parse_port_op port->max = (p[5 ] <<8 ) | p[4 ]; port->align = p[6 ]; port->size = p[7 ]; - port->flags = p[1 ] ?PNP_PORT_FLAG_16BITADDR :0 ; + port->flags = p[1 ] ?IORESOURCE_IO_16BIT_ADDR :0 ;pnp_register_port_resource (dev, option, port); }
@@ -326,7 +326,7 @@ static __init void pnpbios_parse_fixed_p port->min = port->max = (p[2 ] <<8 ) | p[1 ]; port->size = p[3 ]; port->align =0 ; - port->flags =PNP_PORT_FLAG_FIXED ; + port->flags =IORESOURCE_IO_FIXED ;pnp_register_port_resource (dev, option, port); }
Re: [patch 03/15] PNP: define PNP-specific IORESOURCE_IO_* flags alongside IRQ, DMA, MEM
Quoted 6 lines · Bjorn Helgaas
PNP previously defined
PNP_PORT_FLAG_16BITADDRandPNP_PORT_FLAG_FIXEDin a private header file, but put those flags in struct resource.flags fields. Better to make them IORESOURCE_IO_* flags like the existing IRQ, DMA, and MEM flags.Signed-off-by Bjorn Helgaas <[email protected]>
Wondered a bit since only PnPACPI seems to directly encode those flags to a res->flags (as opposed to a port->flags) but pnp_assign_port() copies them over verbatim indeed...
Rene.
PATCH 4/15 PNP: make resource option structures private to PNP subsystem
In reply to Bjorn HelgaasNothing outside the PNP subsystem should need access to a device's resource options, so this patch moves the option structure declarations to a private header file.
drivers/pnp/base.h +48 -0
@@ -19,6 +19,54 @@ void pnp_remove_card(struct pnp_card *caint pnp_add_card_device (struct pnp_card *card,struct pnp_dev *dev);void pnp_remove_card_device (struct pnp_dev *dev); +struct pnp_port { +unsigned short min;/* min base number */ +unsigned short max;/* max base number */ +unsigned char align;/* align boundary */ +unsigned char size;/* size of range */ +unsigned char flags;/* port flags */ +unsigned char pad;/* pad */ +struct pnp_port *next;/* next port */ +}; + +#define PNP_IRQ_NR 256 +struct pnp_irq { + DECLARE_BITMAP(map, PNP_IRQ_NR); /* bitmask for IRQ lines */ +unsigned char flags;/* IRQ flags */ +unsigned char pad;/* pad */ +struct pnp_irq *next;/* next IRQ */ +}; + +struct pnp_dma { +unsigned char map;/* bitmask for DMA channels */ +unsigned char flags;/* DMA flags */ +struct pnp_dma *next;/* next port */ +}; + +struct pnp_mem { +unsigned int min;/* min base number */ +unsigned int max;/* max base number */ +unsigned int align;/* align boundary */ +unsigned int size;/* size of range */ +unsigned char flags;/* memory flags */ +unsigned char pad;/* pad */ +struct pnp_mem *next;/* next memory resource */ +}; + +#define PNP_RES_PRIORITY_PREFERRED 0 +#define PNP_RES_PRIORITY_ACCEPTABLE 1 +#define PNP_RES_PRIORITY_FUNCTIONAL 2 +#define PNP_RES_PRIORITY_INVALID 65535 + +struct pnp_option { +unsigned short priority;/* priority */ +struct pnp_port *port;/* first port */ +struct pnp_irq *irq;/* first IRQ */ +struct pnp_dma *dma;/* first DMA */ +struct pnp_mem *mem;/* first memory resource */ +struct pnp_option *next;/* used to chain dependent resources */ +}; +struct pnp_option *pnp_build_option (int priority);struct pnp_option *pnp_register_independent_option (struct pnp_dev *dev); struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
include/linux/pnp.h +0 -48
54 lines not on this page · raw message
Re: [patch 04/15] PNP: make resource option structures private to PNP subsystem
Quoted 5 lines · Bjorn Helgaas
Nothing outside the PNP subsystem should need access to a device's resource options, so this patch moves the option structure declarations to a private header file.
Signed-off-by Bjorn Helgaas <[email protected]>
I guess this is dependent on the 8250_pnp note I sent earlier.
Rene.
PATCH 5/15 PNP: introduce pnp_irq_mask_t typedef
In reply to Bjorn HelgaasThis adds a typedef for the IRQ bitmap, which should cause no functional change, but will make it easier to pass a pointer to a bitmap to pnp_register_irq_resource().
drivers/pnp/base.h +3 -1
@@ -30,8 +30,10 @@ struct pnp_port { };#define PNP_IRQ_NR 256 +typedef struct { DECLARE_BITMAP(bits, PNP_IRQ_NR); } pnp_irq_mask_t; +struct pnp_irq { - DECLARE_BITMAP(map, PNP_IRQ_NR); /* bitmask for IRQ lines */ +pnp_irq_mask_t map;/* bitmap for IRQ lines */ unsigned char flags;/* IRQ flags */ unsigned char pad;/* pad */ struct pnp_irq *next;/* next IRQ */
drivers/pnp/resource.c +2 -2
@@ -98,13 +98,13 @@ int pnp_register_irq_resource(struct pnpint i;for (i =0 ; i <16 ; i++) -if (test_bit (i, data->map)) +if (test_bit (i, data->map.bits)) pcibios_penalize_isa_irq(i, 0); }#endif #ifdef DEBUG -bitmap_scnprintf (buf,sizeof (buf), data->map,PNP_IRQ_NR ); +bitmap_scnprintf (buf,sizeof (buf), data->map.bits,PNP_IRQ_NR );dev_dbg (&dev->dev," irq bitmask %s flags %#x\n" , buf, data->flags);#endif
drivers/pnp/manager.c +3 -3
@@ -128,20 +128,20 @@ static int pnp_assign_irq(struct pnp_dev res->start =-1 ; res->end =-1 ; -if (bitmap_empty (rule->map,PNP_IRQ_NR )) { +if (bitmap_empty (rule->map.bits,PNP_IRQ_NR )) { res->flags |=IORESOURCE_DISABLED ;dev_dbg (&dev->dev," irq %d disabled\n" , idx); goto __add; }/* TBD: need check for >16 IRQ */ - res->start =find_next_bit (rule->map,PNP_IRQ_NR ,16 ); + res->start =find_next_bit (rule->map.bits,PNP_IRQ_NR ,16 );if (res->start <PNP_IRQ_NR ) { res->end = res->start; goto __add; }for (i =0 ; i <16 ; i++) { -if (test_bit (xtab[i], rule->map)) { +if (test_bit (xtab[i], rule->map.bits)) { res->start = res->end = xtab[i];if (pnp_check_irq (dev, res)) goto __add;
drivers/pnp/interface.c +2 -2
@@ -67,7 +67,7 @@ static void pnp_print_irq(pnp_info_buffepnp_printf (buffer,"%sirq " , space);for (i =0 ; i <PNP_IRQ_NR ; i++) -if (test_bit (i, irq->map)) { +if (test_bit (i, irq->map.bits)) {if (!first) {pnp_printf (buffer,"," ); }else {
@@ -78,7 +78,7 @@ static void pnp_print_irq(pnp_info_buffeelse pnp_printf (buffer,"%i" , i); } -if (bitmap_empty (irq->map,PNP_IRQ_NR )) +if (bitmap_empty (irq->map.bits,PNP_IRQ_NR ))pnp_printf (buffer,"<none>" );if (irq->flags &IORESOURCE_IRQ_HIGHEDGE )pnp_printf (buffer," High-Edge" );
drivers/pnp/isapnp/core.c +1 -1
@@ -441,7 +441,7 @@ static void __init isapnp_parse_irq_resoif (!irq)return ; bits = (tmp[1 ] <<8 ) | tmp[0 ]; -bitmap_copy (irq->map, &bits,16 ); +bitmap_copy (irq->map.bits, &bits,16 );if (size >2 ) irq->flags = tmp[2 ];else
drivers/pnp/pnpacpi/rsparser.c +2 -2
@@ -408,7 +408,7 @@ static __init void pnpacpi_parse_irq_optfor (i =0 ; i < p->interrupt_count; i++)if (p->interrupts[i]) -__set_bit (p->interrupts[i], irq->map); +__set_bit (p->interrupts[i], irq->map.bits); irq->flags =irq_flags (p->triggering, p->polarity, p->sharable);pnp_register_irq_resource (dev, option, irq);
@@ -429,7 +429,7 @@ static __init void pnpacpi_parse_ext_irqfor (i =0 ; i < p->interrupt_count; i++)if (p->interrupts[i]) -__set_bit (p->interrupts[i], irq->map); +__set_bit (p->interrupts[i], irq->map.bits); irq->flags =irq_flags (p->triggering, p->polarity, p->sharable);pnp_register_irq_resource (dev, option, irq);
drivers/pnp/quirks.c +2 -2
@@ -68,7 +68,7 @@ static void quirk_cmi8330_resources(strufor (irq = res->irq; irq; irq = irq->next) {// Valid irqs are 5, 7, 10 tmp =0x04A0 ; -bitmap_copy (irq->map, &tmp,16 );// 0000 0100 1010 0000 +bitmap_copy (irq->map.bits, &tmp,16 );// 0000 0100 1010 0000 }for (dma = res->dma; dma; dma = dma->next)// Valid 8bit dma channels are 1,3
@@ -187,7 +187,7 @@ static void quirk_ad1815_mpu_resources(sif (!copy)break ; -memcpy (copy->map, irq->map,sizeof copy->map); +bitmap_copy (copy->map.bits, irq->map.bits,PNP_IRQ_NR ); copy->flags = irq->flags; copy->next = res->irq;/* Yes, this is NULL */
drivers/pnp/pnpbios/rsparser.c +1 -1
@@ -275,7 +275,7 @@ static __init void pnpbios_parse_irq_optif (!irq)return ; bits = (p[2 ] <<8 ) | p[1 ]; -bitmap_copy (irq->map, &bits,16 ); +bitmap_copy (irq->map.bits, &bits,16 );if (size >2 ) irq->flags = p[3 ];else
Re: [patch 05/15] PNP: introduce pnp_irq_mask_t typedef
Quoted 5 lines · Bjorn Helgaas
This adds a typedef for the IRQ bitmap, which should cause no functional change, but will make it easier to pass a pointer to a bitmap to
pnp_register_irq_resource().Signed-off-by Bjorn Helgaas <[email protected]>
Rene.
PATCH 6/15 PNP: increase I/O port & memory option address sizes
In reply to Bjorn HelgaasACPI Address Space Descriptors can be up to 64 bits wide. We should keep track of the whole thing when parsing resource options, so this patch changes PNP port and mem option fields from "unsigned short" and "unsigned int" to "resource_size_t".
--- drivers/pnp/base.h | 16 ++++++++-------- drivers/pnp/interface.c | 17 +++++++++++------ drivers/pnp/resource.c | 14 ++++++++++---- 3 files changed, 29 insertions(+), 18 deletions(-)
drivers/pnp/base.h +8 -8
@@ -20,10 +20,10 @@ int pnp_add_card_device(struct pnp_cardvoid pnp_remove_card_device (struct pnp_dev *dev);struct pnp_port { -unsigned short min;/* min base number */ -unsigned short max;/* max base number */ -unsigned char align;/* align boundary */ -unsigned char size;/* size of range */ +resource_size_t min;/* min base number */ +resource_size_t max;/* max base number */ +resource_size_t align;/* align boundary */ +resource_size_t size;/* size of range */ unsigned char flags;/* port flags */ unsigned char pad;/* pad */ struct pnp_port *next;/* next port */
@@ -46,10 +46,10 @@ struct pnp_dma { };struct pnp_mem { -unsigned int min;/* min base number */ -unsigned int max;/* max base number */ -unsigned int align;/* align boundary */ -unsigned int size;/* size of range */ +resource_size_t min;/* min base number */ +resource_size_t max;/* max base number */ +resource_size_t align;/* align boundary */ +resource_size_t size;/* size of range */ unsigned char flags;/* memory flags */ unsigned char pad;/* pad */ struct pnp_mem *next;/* next memory resource */
drivers/pnp/interface.c +11 -6
@@ -53,10 +53,12 @@ static int pnp_printf(pnp_info_buffer_tstatic void pnp_print_port (pnp_info_buffer_t * buffer,char *space,struct pnp_port *port) { -pnp_printf (buffer, -"%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n" , - space, port->min, port->max, - port->align ? (port->align -1 ) :0 , port->size, +pnp_printf (buffer,"%sport %#llx-%#llx, align %#llx, size %#llx, " +"%i-bit address decoding\n" , space, + (unsigned long long ) port->min, + (unsigned long long ) port->max, + port->align ? ((unsigned long long ) port->align -1 ) :0 , + (unsigned long long ) port->size, port->flags &IORESOURCE_IO_16BIT_ADDR ?16 :10 ); }
@@ -148,8 +150,11 @@ static void pnp_print_mem(pnp_info_buffe {char *s; -pnp_printf (buffer,"%sMemory 0x%x-0x%x, align 0x%x, size 0x%x" , - space, mem->min, mem->max, mem->align, mem->size); +pnp_printf (buffer,"%sMemory %#llx-%#llx, align %#llx, size %#llx" , + space, (unsigned long long ) mem->min, + (unsigned long long ) mem->max, + (unsigned long long ) mem->align, + (unsigned long long ) mem->size);if (mem->flags &IORESOURCE_MEM_WRITEABLE )pnp_printf (buffer,", writeable" );if (mem->flags &IORESOURCE_MEM_CACHEABLE )
drivers/pnp/resource.c +10 -4
@@ -143,8 +143,11 @@ int pnp_register_port_resource(struct pn option->port = data;dev_dbg (&dev->dev," io " -"min %#x max %#x align %d size %d flags %#x\n" , - data->min, data->max, data->align, data->size, data->flags); +"min %#llx max %#llx align %lld size %lld flags %#x\n" , + (unsigned long long ) data->min, + (unsigned long long ) data->max, + (unsigned long long ) data->align, + (unsigned long long ) data->size, data->flags);return 0 ; }
@@ -162,8 +165,11 @@ int pnp_register_mem_resource(struct pnp option->mem = data;dev_dbg (&dev->dev," mem " -"min %#x max %#x align %d size %d flags %#x\n" , - data->min, data->max, data->align, data->size, data->flags); +"min %#llx max %#llx align %lld size %lld flags %#x\n" , + (unsigned long long ) data->min, + (unsigned long long ) data->max, + (unsigned long long ) data->align, + (unsigned long long ) data->size, data->flags);return 0 ; }
Re: [patch 06/15] PNP: increase I/O port & memory option address sizes
Quoted 7 lines · Bjorn Helgaas
ACPI Address Space Descriptors can be up to 64 bits wide. We should keep track of the whole thing when parsing resource options, so this patch changes PNP port and mem option fields from "unsigned short" and "unsigned int" to "
resource_size_t".Signed-off-by Bjorn Helgaas <[email protected]>
Rene.
PATCH 7/15 PNP: improve resource assignment debug
In reply to Bjorn HelgaasWhen we fail to assign an I/O or MEM resource, include the min/max in the debug output to help match it with the options.
drivers/pnp/manager.c +8 -2
@@ -47,7 +47,10 @@ static int pnp_assign_port(struct pnp_de res->start += rule->align; res->end = res->start + rule->size -1 ;if (res->start > rule->max || !rule->align) { -dev_dbg (&dev->dev," couldn't assign io %d\n" , idx); +dev_dbg (&dev->dev," couldn't assign io %d " +"(min %#llx max %#llx)\n" , idx, + (unsigned long long ) rule->min, + (unsigned long long ) rule->max);return 0 ; } }
@@ -96,7 +99,10 @@ static int pnp_assign_mem(struct pnp_dev res->start += rule->align; res->end = res->start + rule->size -1 ;if (res->start > rule->max || !rule->align) { -dev_dbg (&dev->dev," couldn't assign mem %d\n" , idx); +dev_dbg (&dev->dev," couldn't assign mem %d " +"(min %#llx max %#llx)\n" , idx, + (unsigned long long ) rule->min, + (unsigned long long ) rule->max);return 0 ; } }
Re: [patch 07/15] PNP: improve resource assignment debug
Quoted 4 lines · Bjorn Helgaas
When we fail to assign an I/O or MEM resource, include the min/max in the debug output to help match it with the options.
Signed-off-by Bjorn Helgaas <[email protected]>
Rene.
PATCH 8/15 PNP: in debug resource dump, make empty list obvious
In reply to Bjorn HelgaasIf the resource list is empty, say that explicitly. Previously, it was confusing because often the heading was followed by zero resource lines, then some "add resource" lines from auto-assignment, so the "add" lines looked like current resources.
drivers/pnp/support.c +6 -1
@@ -77,7 +77,12 @@ void dbg_pnp_show_resources(struct pnp_dstruct pnp_resource *pnp_res;struct resource *res; -dev_dbg (&dev->dev,"current resources: %s\n" , desc); +if (list_empty (&dev->resources)) { +dev_dbg (&dev->dev,"%s: no current resources\n" , desc); +return ; + } + +dev_dbg (&dev->dev,"%s: current resources:\n" , desc);list_for_each_entry (pnp_res, &dev->resources, list) { res = &pnp_res->res;
Re: [patch 08/15] PNP: in debug resource dump, make empty list obvious
Quoted 6 lines · Bjorn Helgaas
If the resource list is empty, say that explicitly. Previously, it was confusing because often the heading was followed by zero resource lines, then some "add resource" lines from auto-assignment, so the "add" lines looked like current resources.
Signed-off-by Bjorn Helgaas <[email protected]>
Rene.
PATCH 9/15 PNP: make resource assignment functions return 0 (success) or -EBUSY (failure)
In reply to Bjorn HelgaasThis patch doesn't change any behavior; it just makes the return values more conventional.
This changes pnp_assign_dma() from a void function to one that returns an int, just like the other assignment functions. For now, at least, pnp_assign_dma() always returns 0 (success), so it appears to never fail, just like before.
drivers/pnp/manager.c +22 -19
@@ -26,7 +26,7 @@ static int pnp_assign_port(struct pnp_dedev_dbg (&dev->dev," io %d already set to %#llx-%#llx " "flags %#lx\n" , idx, (unsigned long long ) res->start, (unsigned long long ) res->end, res->flags); -return 1 ; +return 0 ; } res = &local_res;
@@ -51,13 +51,13 @@ static int pnp_assign_port(struct pnp_de"(min %#llx max %#llx)\n" , idx, (unsigned long long ) rule->min, (unsigned long long) rule->max); -return 0 ; +return -EBUSY ; } } __add:pnp_add_io_resource (dev, res->start, res->end, res->flags); -return 1 ; +return 0 ; }static int pnp_assign_mem (struct pnp_dev *dev,struct pnp_mem *rule,int idx)
@@ -69,7 +69,7 @@ static int pnp_assign_mem(struct pnp_devdev_dbg (&dev->dev," mem %d already set to %#llx-%#llx " "flags %#lx\n" , idx, (unsigned long long ) res->start, (unsigned long long ) res->end, res->flags); -return 1 ; +return 0 ; } res = &local_res;
@@ -103,13 +103,13 @@ static int pnp_assign_mem(struct pnp_dev"(min %#llx max %#llx)\n" , idx, (unsigned long long ) rule->min, (unsigned long long) rule->max); -return 0 ; +return -EBUSY ; } } __add:pnp_add_mem_resource (dev, res->start, res->end, res->flags); -return 1 ; +return 0 ; }static int pnp_assign_irq (struct pnp_dev *dev,struct pnp_irq *rule,int idx)
@@ -126,7 +126,7 @@ static int pnp_assign_irq(struct pnp_devif (res) {dev_dbg (&dev->dev," irq %d already set to %d flags %#lx\n" , idx, (int ) res->start, res->flags); -return 1 ; +return 0 ; } res = &local_res;
@@ -154,14 +154,14 @@ static int pnp_assign_irq(struct pnp_dev } }dev_dbg (&dev->dev," couldn't assign irq %d\n" , idx); -return 0 ; +return -EBUSY ; __add:pnp_add_irq_resource (dev, res->start, res->flags); -return 1 ; +return 0 ; } -static void pnp_assign_dma (struct pnp_dev *dev,struct pnp_dma *rule,int idx) +static int pnp_assign_dma (struct pnp_dev *dev,struct pnp_dma *rule,int idx) {struct resource *res, local_res;int i;
@@ -175,7 +175,7 @@ static void pnp_assign_dma(struct pnp_deif (res) {dev_dbg (&dev->dev," dma %d already set to %d flags %#lx\n" , idx, (int ) res->start, res->flags); -return ; +return 0 ; } res = &local_res;
@@ -198,6 +198,7 @@ static void pnp_assign_dma(struct pnp_de __add:pnp_add_dma_resource (dev, res->start, res->flags); +return 0 ; }void pnp_init_resources (struct pnp_dev *dev)
@@ -243,25 +244,26 @@ static int pnp_assign_resources(struct p irq = dev->independent->irq; dma = dev->independent->dma;while (port) { -if (!pnp_assign_port (dev, port, nport)) +if (pnp_assign_port (dev, port, nport) <0 ) goto fail; nport++; port = port->next; }while (mem) { -if (!pnp_assign_mem (dev, mem, nmem)) +if (pnp_assign_mem (dev, mem, nmem) <0 ) goto fail; nmem++; mem = mem->next; }while (irq) { -if (!pnp_assign_irq (dev, irq, nirq)) +if (pnp_assign_irq (dev, irq, nirq) <0 ) goto fail; nirq++; irq = irq->next; }while (dma) { -pnp_assign_dma (dev, dma, ndma); +if (pnp_assign_dma (dev, dma, ndma) <0 ) + goto fail; ndma++; dma = dma->next; }
@@ -281,25 +283,26 @@ static int pnp_assign_resources(struct p irq = dep->irq; dma = dep->dma;while (port) { -if (!pnp_assign_port (dev, port, nport)) +if (pnp_assign_port (dev, port, nport) <0 ) goto fail; nport++; port = port->next; }while (mem) { -if (!pnp_assign_mem (dev, mem, nmem)) +if (pnp_assign_mem (dev, mem, nmem) <0 ) goto fail; nmem++; mem = mem->next; }while (irq) { -if (!pnp_assign_irq (dev, irq, nirq)) +if (pnp_assign_irq (dev, irq, nirq) <0 ) goto fail; nirq++; irq = irq->next; }while (dma) { -pnp_assign_dma (dev, dma, ndma); +if (pnp_assign_dma (dev, dma, ndma) <0 ) + goto fail; ndma++; dma = dma->next; }
Re: [patch 09/15] PNP: make resource assignment functions return 0 (success) or -EBUSY (failure)
Quoted 9 lines · Bjorn Helgaas
This patch doesn't change any behavior; it just makes the return values more conventional.
This changes
pnp_assign_dma()from a void function to one that returns an int, just like the other assignment functions. For now, at least,pnp_assign_dma()always returns 0 (success), so it appears to never fail, just like before.Signed-off-by Bjorn Helgaas <[email protected]>
I believe it would a bit nicer to (as long as we're pretending it matters in the first place) pass the return value back up from pnp_check_foo() instead of returning -EBUSY always but <shrug>
Rene.
PATCH 10/15 PNP: remove redundant pnp_can_configure() check
In reply to Bjorn Helgaaspnp_assign_resources() is static and the only caller checks pnp_can_configure() before calling it, so no need to do it again.
drivers/pnp/manager.c +0 -3
@@ -231,9 +231,6 @@ static int pnp_assign_resources(struct pstruct pnp_dma *dma;int nport =0 , nmem =0 , nirq =0 , ndma =0 ; -if (!pnp_can_configure (dev)) -return -ENODEV ; -dbg_pnp_show_resources (dev,"before pnp_assign_resources" );mutex_lock (&pnp_res_mutex);pnp_clean_resource_table (dev);
Re: [patch 10/15] PNP: remove redundant pnp_can_configure() check
Quoted 5 lines · Bjorn Helgaas
pnp_assign_resources()is static and the only caller checkspnp_can_configure()before calling it, so no need to do it again.Signed-off-by Bjorn Helgaas <[email protected]>
Rene.
PATCH 11/15 PNP: centralize resource option allocations
In reply to Bjorn HelgaasThis patch moves all the option allocations (pnp_mem, pnp_port, etc) into the pnp_register_{mem,port,irq,dma}_resource() functions. This will make it easier to rework the option data structures.
The non-trivial part of this patch is the IRQ handling. The backends have to allocate a local pnp_irq_mask_t bitmap, populate it, and pass a pointer to pnp_register_irq_resource().
--- drivers/pnp/base.h | 12 ++- drivers/pnp/isapnp/core.c | 115 +++++++++++++------------------ drivers/pnp/pnpacpi/rsparser.c | 149 +++++++++++++---------------------------- drivers/pnp/pnpbios/rsparser.c | 112 ++++++++++++------------------ drivers/pnp/resource.c | 58 +++++++++++++-- 5 files changed, 200 insertions(+), 246 deletions(-)
drivers/pnp/base.h +8 -4
@@ -74,13 +74,17 @@ struct pnp_option *pnp_register_independstruct pnp_option *pnp_register_dependent_option (struct pnp_dev *dev,int priority);int pnp_register_irq_resource (struct pnp_dev *dev,struct pnp_option *option, -struct pnp_irq *data); +pnp_irq_mask_t *map,unsigned char flags);int pnp_register_dma_resource (struct pnp_dev *dev,struct pnp_option *option, -struct pnp_dma *data); +unsigned char map,unsigned char flags);int pnp_register_port_resource (struct pnp_dev *dev,struct pnp_option *option, -struct pnp_port *data); +resource_size_t min,resource_size_t max, +resource_size_t align,resource_size_t size, +unsigned char flags);int pnp_register_mem_resource (struct pnp_dev *dev,struct pnp_option *option, -struct pnp_mem *data); +resource_size_t min,resource_size_t max, +resource_size_t align,resource_size_t size, +unsigned char flags);void pnp_init_resources (struct pnp_dev *dev);void pnp_fixup_device (struct pnp_dev *dev);
drivers/pnp/isapnp/core.c +48 -67
174 lines not on this page · raw message
drivers/pnp/pnpacpi/rsparser.c +49 -100
246 lines not on this page · raw message
drivers/pnp/pnpbios/rsparser.c +47 -65
163 lines not on this page · raw message
drivers/pnp/resource.c +48 -10
88 lines not on this page · raw message
Re: [patch 11/15] PNP: centralize resource option allocations
Quoted 9 lines · Bjorn Helgaas
This patch moves all the option allocations (
pnp_mem,pnp_port, etc) into the pnp_register_{mem,port,irq,dma}_resource() functions. This will make it easier to rework the option data structures.The non-trivial part of this patch is the IRQ handling. The backends have to allocate a local
pnp_irq_mask_tbitmap, populate it, and pass a pointer topnp_register_irq_resource().Signed-off-by Bjorn Helgaas <[email protected]>
[ ... ]
Quoted 16 lines
Index:
work10/drivers/pnp/isapnp/core.c
===================================================================drivers/pnp/isapnp/core.c +3
-2@@ -433,20 +433,23 @@ static void __init isapnp_parse_irq_reso int size) {unsigned char tmp[3 ]; -struct pnp_irq *irq;unsigned long bits; +int i; +pnp_irq_mask_t map; +unsigned char flags =IORESOURCE_IRQ_HIGHEDGE ;isapnp_peek (tmp, size); - irq =kzalloc (sizeof (struct pnp_irq ),GFP_KERNEL );
drivers/pnp/isapnp/core.c static void __init isapnp_parse_irq_reso · line 448
Quoted 10 lines
drivers/pnp/isapnp/core.c +6
-3-if (!irq) -return ; bits = (tmp[1 ] <<8 ) | tmp[0 ]; -bitmap_copy (irq->map.bits, &bits,16 ); + +bitmap_zero (map.bits,PNP_IRQ_NR ); +for (i =0 ; i <15 ; i++) +if (bits & (1 << i)) +__set_bit (i, map.bits); +
for (i = 0; i < 16; i++) (16 instead of 15) it would seem.
And why not simply:
bitmap_zero(map.bits, PNP_IRQ_NR);bitmap_copy(map.bits, &bits, 16);
That last bit of the comment same for pnpbios_parse_irq_option(). Should
be fine, no?
drivers/pnp/isapnp/core.c static void __init isapnp_parse_irq_reso · line 453
Quoted 6 lines
drivers/pnp/isapnp/core.c +1
-1static __init void pnpbios_parse_port_option (struct pnp_dev *dev,unsigned char *p,int size,struct pnp_option *option) { -struct pnp_port *port; +resource_size_t min, max, align, len, flags;
unsigned char flags;
All the rest:
Rene.
Re: [patch 11/15] PNP: centralize resource option allocations
Quoted 28 lines · Rene Herman
Quoted 9 lines · Bjorn Helgaas
This patch moves all the option allocations (
pnp_mem,pnp_port, etc) into the pnp_register_{mem,port,irq,dma}_resource() functions. This will make it easier to rework the option data structures.The non-trivial part of this patch is the IRQ handling. The backends have to allocate a local
pnp_irq_mask_tbitmap, populate it, and pass a pointer topnp_register_irq_resource().Signed-off-by Bjorn Helgaas <[email protected]>[ ... ]
Quoted 14 lines
Index:
work10/drivers/pnp/isapnp/core.c
===================================================================drivers/pnp/isapnp/core.c +3
-1@@ -433,20 +433,23 @@ static void __init isapnp_parse_irq_reso int size) {unsigned char tmp[3 ]; -struct pnp_irq *irq;unsigned long bits; +int i; +pnp_irq_mask_t map; +unsigned char flags =IORESOURCE_IRQ_HIGHEDGE ;
Quoted 14 lines
drivers/pnp/isapnp/core.c static void __init isapnp_parse_irq_reso · line 448
Quoted 12 lines
drivers/pnp/isapnp/core.c +6
-4isapnp_peek (tmp, size); - irq =kzalloc (sizeof (struct pnp_irq ),GFP_KERNEL ); -if (!irq) -return ; bits = (tmp[1 ] <<8 ) | tmp[0 ]; -bitmap_copy (irq->map.bits, &bits,16 ); + +bitmap_zero (map.bits,PNP_IRQ_NR ); +for (i =0 ; i <15 ; i++) +if (bits & (1 << i)) +__set_bit (i, map.bits); +for (i = 0; i < 16; i++) (16 instead of 15) it would seem.
Oops, typo on my part.
Quoted 7 lines
And why not simply:
bitmap_zero(map.bits, PNP_IRQ_NR);bitmap_copy(map.bits, &bits, 16);That last bit of the comment same for
pnpbios_parse_irq_option(). Should
be fine, no?
I suppose it should be fine. It's just that I was new to the bitmap functions and nervous about copying between bitmaps of different sizes and getting bits in the correct places. But I'll try to get over my paranoia :-)
Bjorn
PATCH 12/15 PNPACPI: ignore _PRS interrupt numbers larger than PNP_IRQ_NR
In reply to Bjorn HelgaasACPI Extended Interrupt Descriptors can encode 32-bit interrupt numbers, so an interrupt number may exceed the size of the bitmap we use to track possible IRQ settings.
To avoid corrupting memory, complain and ignore too-large interrupt numbers.
There's similar code in pnpacpi_parse_irq_option(), but I didn't change that because the small IRQ descriptor can only encode IRQs 0-15, which do not exceed bitmap size.
In the future, we could handle IRQ numbers greater than PNP_IRQ_NR by replacing the bitmap with a table or list.
drivers/pnp/pnpacpi/rsparser.c +10 -3
@@ -421,9 +421,16 @@ static __init void pnpacpi_parse_ext_irqreturn ;bitmap_zero (map.bits,PNP_IRQ_NR ); -for (i =0 ; i < p->interrupt_count; i++) -if (p->interrupts[i]) -__set_bit (p->interrupts[i], map.bits); +for (i =0 ; i < p->interrupt_count; i++) { +if (p->interrupts[i]) { +if (p->interrupts[i] <PNP_IRQ_NR ) +__set_bit (p->interrupts[i], map.bits); +else +dev_err (&dev->dev,"ignoring IRQ %d option " +"(too large for %d entry bitmap)\n" , + p->interrupts[i],PNP_IRQ_NR ); + } + } flags =irq_flags (p->triggering, p->polarity, p->sharable);pnp_register_irq_resource (dev, option, &map, flags);
Re: [patch 12/15] PNPACPI: ignore _PRS interrupt numbers larger than PNP_IRQ_NR
Quoted 7 lines · Bjorn Helgaas
ACPI Extended Interrupt Descriptors can encode 32-bit interrupt numbers, so an interrupt number may exceed the size of the bitmap we use to track possible IRQ settings.
To avoid corrupting memory, complain and ignore too-large interrupt numbers.
Quoted 8 lines
There's similar code in
pnpacpi_parse_irq_option(), but I didn't change that because the small IRQ descriptor can only encode IRQs 0-15, which do not exceed bitmap size.In the future, we could handle IRQ numbers greater than
PNP_IRQ_NRby replacing the bitmap with a table or list.Signed-off-by Bjorn Helgaas <[email protected]>
Rene.
PATCH 13/15 PNP: rename pnp_register_*_resource() local variables
In reply to Bjorn HelgaasNo functional change; just rename "data" to something more descriptive.
drivers/pnp/resource.c +47 -47
@@ -80,40 +80,40 @@ struct pnp_option *pnp_register_dependenint pnp_register_irq_resource (struct pnp_dev *dev,struct pnp_option *option,pnp_irq_mask_t *map,unsigned char flags) { -struct pnp_irq *data, *ptr; +struct pnp_irq *irq, *ptr;#ifdef DEBUG char buf[PNP_IRQ_NR ];/* hex-encoded, so this is overkill but safe */ #endif - data =kzalloc (sizeof (struct pnp_irq ),GFP_KERNEL ); -if (!data) + irq =kzalloc (sizeof (struct pnp_irq ),GFP_KERNEL ); +if (!irq)return -ENOMEM ; - data->map = *map; - data->flags = flags; + irq->map = *map; + irq->flags = flags; ptr = option->irq;while (ptr && ptr->next) ptr = ptr->next;if (ptr) - ptr->next = data; + ptr->next = irq;else - option->irq = data; + option->irq = irq;#ifdef CONFIG_PCI {int i;for (i =0 ; i <16 ; i++) -if (test_bit (i, data->map.bits)) +if (test_bit (i, irq->map.bits))pcibios_penalize_isa_irq (i,0 ); }#endif #ifdef DEBUG -bitmap_scnprintf (buf,sizeof (buf), data->map.bits,PNP_IRQ_NR ); +bitmap_scnprintf (buf,sizeof (buf), irq->map.bits,PNP_IRQ_NR );dev_dbg (&dev->dev," irq bitmask %s flags %#x\n" , buf, - data->flags); + irq->flags);#endif return 0 ; }
@@ -121,25 +121,25 @@ int pnp_register_irq_resource(struct pnpint pnp_register_dma_resource (struct pnp_dev *dev,struct pnp_option *option,unsigned char map,unsigned char flags) { -struct pnp_dma *data, *ptr; +struct pnp_dma *dma, *ptr; - data =kzalloc (sizeof (struct pnp_dma ),GFP_KERNEL ); -if (!data) + dma =kzalloc (sizeof (struct pnp_dma ),GFP_KERNEL ); +if (!dma)return -ENOMEM ; - data->map = map; - data->flags = flags; + dma->map = map; + dma->flags = flags; ptr = option->dma;while (ptr && ptr->next) ptr = ptr->next;if (ptr) - ptr->next = data; + ptr->next = dma;else - option->dma = data; + option->dma = dma; -dev_dbg (&dev->dev," dma bitmask %#x flags %#x\n" , data->map, - data->flags); +dev_dbg (&dev->dev," dma bitmask %#x flags %#x\n" , dma->map, + dma->flags);return 0 ; }
@@ -148,32 +148,32 @@ int pnp_register_port_resource(struct pn resource_size_t align, resource_size_t size, unsigned char flags) { - struct pnp_port *data, *ptr; + struct pnp_port *port, *ptr; - data =kzalloc (sizeof (struct pnp_port ),GFP_KERNEL ); -if (!data) + port =kzalloc (sizeof (struct pnp_port ),GFP_KERNEL ); +if (!port)return -ENOMEM ; - data->min = min; - data->max = max; - data->align = align; - data->size = size; - data->flags = flags; + port->min = min; + port->max = max; + port->align = align; + port->size = size; + port->flags = flags; ptr = option->port;while (ptr && ptr->next) ptr = ptr->next;if (ptr) - ptr->next = data; + ptr->next = port;else - option->port = data; + option->port = port;dev_dbg (&dev->dev," io " "min %#llx max %#llx align %lld size %lld flags %#x\n" , - (unsigned long long ) data->min, - (unsigned long long ) data->max, - (unsigned long long ) data->align, - (unsigned long long ) data->size, data->flags); + (unsigned long long ) port->min, + (unsigned long long ) port->max, + (unsigned long long ) port->align, + (unsigned long long ) port->size, port->flags);return 0 ; }
@@ -182,32 +182,32 @@ int pnp_register_mem_resource(struct pnp resource_size_t align, resource_size_t size, unsigned char flags) { - struct pnp_mem *data, *ptr; + struct pnp_mem *mem, *ptr; - data =kzalloc (sizeof (struct pnp_mem ),GFP_KERNEL ); -if (!data) + mem =kzalloc (sizeof (struct pnp_mem ),GFP_KERNEL ); +if (!mem)return -ENOMEM ; - data->min = min; - data->max = max; - data->align = align; - data->size = size; - data->flags = flags; + mem->min = min; + mem->max = max; + mem->align = align; + mem->size = size; + mem->flags = flags; ptr = option->mem;while (ptr && ptr->next) ptr = ptr->next;if (ptr) - ptr->next = data; + ptr->next = mem;else - option->mem = data; + option->mem = mem;dev_dbg (&dev->dev," mem " "min %#llx max %#llx align %lld size %lld flags %#x\n" , - (unsigned long long ) data->min, - (unsigned long long ) data->max, - (unsigned long long ) data->align, - (unsigned long long ) data->size, data->flags); + (unsigned long long ) mem->min, + (unsigned long long ) mem->max, + (unsigned long long ) mem->align, + (unsigned long long ) mem->size, mem->flags);return 0 ; }
Re: [patch 13/15] PNP: rename pnp_register_*_resource() local variables
Quoted 4 lines · Bjorn Helgaas
No functional change; just rename "data" to something more descriptive.
Signed-off-by Bjorn Helgaas <[email protected]>
(last 2 after sleep)
Rene.
PATCH 14/15 PNP: support optional IRQ resources
In reply to Bjorn HelgaasThis patch adds an IORESOURCE_IRQ_OPTIONAL flag for use when assigning resources to a device. If the flag is set and we are unable to assign an IRQ to the device, we can leave the IRQ disabled but allow the overall resource allocation to succeed.
Some devices request an IRQ, but can run without an IRQ (possibly with degraded performance). This flag lets us run the device without the IRQ instead of just leaving the device disabled.
This is a reimplementation of this previous change by Rene Herman <[email protected]>:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3b73a223661ed137c5d3d2635f954382e94f5a43
I reimplemented this for two reasons:
- to prepare for converting all resource options into a single linked list, as opposed to the per-resource-type lists we have now, and
- to preserve the order and number of resource options.
In PNPBIOS and ACPI, we configure a device by giving firmware a list of resource assignments. It is important that this list has exactly the same number of resources, in the same order, as the "template" list we got from the firmware in the first place.
The problem of a sound card being left disabled for want of an IRQ was reported by Uwe Bugla <[email protected]>.
include/linux/ioport.h +1 -0
@@ -59,6 +59,7 @@ struct resource_list {#define IORESOURCE_IRQ_HIGHLEVEL (1<<2)#define IORESOURCE_IRQ_LOWLEVEL (1<<3)#define IORESOURCE_IRQ_SHAREABLE (1<<4) +#define IORESOURCE_IRQ_OPTIONAL (1<<5)/* ISA PnP DMA specific bits (IORESOURCE_BITS) */ #define IORESOURCE_DMA_TYPE_MASK (3<<0)
drivers/pnp/manager.c +9 -0
@@ -153,6 +153,15 @@ static int pnp_assign_irq(struct pnp_dev goto __add; } } + +if (rule->flags &IORESOURCE_IRQ_OPTIONAL ) { + res->start =-1 ; + res->end =-1 ; + res->flags |=IORESOURCE_DISABLED ; +dev_dbg (&dev->dev," irq %d disabled (optional)\n" , idx); + goto __add; + } +dev_dbg (&dev->dev," couldn't assign irq %d\n" , idx);return -EBUSY ;
drivers/pnp/quirks.c +27 -42
111 lines not on this page · raw message
Re: [patch 14/15] PNP: support optional IRQ resources
Quoted 19 lines · Bjorn Helgaas
This patch adds an
IORESOURCE_IRQ_OPTIONALflag for use when assigning resources to a device. If the flag is set and we are unable to assign an IRQ to the device, we can leave the IRQ disabled but allow the overall resource allocation to succeed.Some devices request an IRQ, but can run without an IRQ (possibly with degraded performance). This flag lets us run the device without the IRQ instead of just leaving the device disabled.
This is a reimplementation of this previous change by Rene Herman <[email protected]>:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3b73a223661ed137c5d3d2635f954382e94f5a43I reimplemented this for two reasons:
- to prepare for converting all resource options into a single linked list, as opposed to the per-resource-type lists we have now, and
- to preserve the order and number of resource options.
Quoted 8 lines
In PNPBIOS and ACPI, we configure a device by giving firmware a list of resource assignments. It is important that this list has exactly the same number of resources, in the same order, as the "template" list we got from the firmware in the first place.
The problem of a sound card being left disabled for want of an IRQ was reported by Uwe Bugla <[email protected]>.
Nit -- the soundcard itself isn't left disabled, just its MPU401. It's only the fact that ALSA mentions this fact which triggered the report.
Quoted 7 lines
Signed-off-by Bjorn Helgaas <[email protected]>Index:
work10/include/linux/ioport.h
===================================================================
include/linux/ioport.h struct resource_list { · line 65
Quoted 7 lines
include/linux/ioport.h +1
-0@@ -59,6 +59,7 @@ struct resource_list {#define IORESOURCE_IRQ_HIGHLEVEL (1<<2)#define IORESOURCE_IRQ_LOWLEVEL (1<<3)#define IORESOURCE_IRQ_SHAREABLE (1<<4) +#define IORESOURCE_IRQ_OPTIONAL (1<<5)/* ISA PnP DMA specific bits (IORESOURCE_BITS) */ #define IORESOURCE_DMA_TYPE_MASK (3<<0)
Andrew scooped up a patch from a previous reaction of mine that deleted the "ISA " from these comments. I tend to use comments as a great way of avoiding actually reading code (I'm silly like that) and so as to be burned a _bit_ less by it, I think it's good if they're accurate. In this case for example, one might be tempted to assume these bits were specific to drivers/pnp/isapnp.
<snip>
Quoted 31 lines
include/linux/ioport.h +0
-20@@ -164,10 +176,6 @@ static void quirk_ad1815_mpu_resources(sstruct pnp_option *res;struct pnp_irq *irq; -/* -* Distribute the independent IRQ over the dependent options -*/ - res = dev->independent;if (!res)return ;@@ -176,33 +184,10 @@ static void quirk_ad1815_mpu_resources(sif (!irq || irq->next)return ; - res = dev->dependent; -if (!res) -return ; - -while (1 ) { -struct pnp_irq *copy; - - copy =pnp_alloc (sizeof *copy); -if (!copy) -break ; - -bitmap_copy (copy->map.bits, irq->map.bits,PNP_IRQ_NR ); - copy->flags = irq->flags; - - copy->next = res->irq;/* Yes, this is NULL */ - res->irq = copy;
include/linux/ioport.h static void quirk_ad1815_mpu_resources(s · line 190
Quoted 10 lines
include/linux/ioport.h +2
-6- -if (!res->next) -break ; - res = res->next; - } -kfree (irq); + irq->flags |=IORESOURCE_IRQ_OPTIONAL ; +dev_info (&dev->dev,"made independent IRQ optional\n" ); res->next =quirk_isapnp_mpu_options (dev);
As commented yesterday, this line should just go. We don't need to clone here (we do for the other two PNP IDs, so the cloning can't go entirely).
The actual (slight) problem with it not working is in 15/15...
include/linux/ioport.h static void quirk_ad1815_mpu_resources(s · line 193
Quoted 6 lines
include/linux/ioport.h +0
-3- - res = dev->independent; - res->irq =NULL ; }static void quirk_isapnp_mpu_resources (struct pnp_dev *dev)
Rene.
Re: [patch 14/15] PNP: support optional IRQ resources
Quoted 10 lines · Rene Herman
Quoted 10 lines
Index:
work10/include/linux/ioport.h
===================================================================include/linux/ioport.h +1
-0@@ -59,6 +59,7 @@ struct resource_list {#define IORESOURCE_IRQ_HIGHLEVEL (1<<2)#define IORESOURCE_IRQ_LOWLEVEL (1<<3)#define IORESOURCE_IRQ_SHAREABLE (1<<4) +#define IORESOURCE_IRQ_OPTIONAL (1<<5)
Quoted 9 lines
include/linux/ioport.h struct resource_list { · line 65
Quoted 2 lines
include/linux/ioport.h +0
-0/* ISA PnP DMA specific bits (IORESOURCE_BITS) */ #define IORESOURCE_DMA_TYPE_MASK (3<<0)Andrew scooped up a patch from a previous reaction of mine that deleted the "ISA " from these comments. I tend to use comments as a great way of avoiding actually reading code (I'm silly like that) and so as to be burned a _bit_ less by it, I think it's good if they're accurate. In this case for example, one might be tempted to assume these bits were specific to
drivers/pnp/isapnp.
Yes, I see that's pnpacpi-fix-irq-flag-decoding-comment-fix.patch in mmotm. How about if I incorporate that in my series (the one Andrew hasn't yet picked up), since your patch will otherwise conflict with it?
Bjorn
Re: [patch 14/15] PNP: support optional IRQ resources
Quoted 11 lines · Bjorn Helgaas
Quoted 10 lines · Rene Herman
Quoted 10 lines
Index:
work10/include/linux/ioport.h
===================================================================include/linux/ioport.h +1
-0@@ -59,6 +59,7 @@ struct resource_list {#define IORESOURCE_IRQ_HIGHLEVEL (1<<2)#define IORESOURCE_IRQ_LOWLEVEL (1<<3)#define IORESOURCE_IRQ_SHAREABLE (1<<4) +#define IORESOURCE_IRQ_OPTIONAL (1<<5)
Quoted 8 lines
Quoted 3 lines
include/linux/ioport.h struct resource_list { · line 65
Quoted 2 lines
include/linux/ioport.h +0
-0/* ISA PnP DMA specific bits (IORESOURCE_BITS) */ #define IORESOURCE_DMA_TYPE_MASK (3<<0)Andrew scooped up a patch from a previous reaction of mine that deleted the "ISA " from these comments. I tend to use comments as a great way of avoiding actually reading code (I'm silly like that) and so as to be burned a _bit_ less by it, I think it's good if they're accurate. In this case for example, one might be tempted to assume these bits were specific to
drivers/pnp/isapnp.Yes, I see that's pnpacpi-fix-irq-flag-decoding-comment-fix.patch in mmotm. How about if I incorporate that in my series (the one Andrew hasn't yet picked up), since your patch will otherwise conflict with it?
Yep, that would be good.
Rene.
PATCH 15/15 PNP: convert resource options to single linked list
In reply to Bjorn HelgaasISAPNP, PNPBIOS, and ACPI describe the "possible resource settings" of a device, i.e., the possibilities an OS bus driver has when it assigns I/O port, MMIO, and other resources to the device.
PNP used to maintain this "possible resource setting" information in one independent option structure and a list of dependent option structures for each device. Each of these option structures had lists of I/O, memory, IRQ, and DMA resources, for example:
dev
independent options
ind-io0 -> ind-io1 ...
ind-mem0 -> ind-mem1 ...
...
dependent option set 0
dep0-io0 -> dep0-io1 ...
dep0-mem0 -> dep0-mem1 ...
...
dependent option set 1
dep1-io0 -> dep1-io1 ...
dep1-mem0 -> dep1-mem1 ...
...
...This data structure was designed for ISAPNP, where the OS configures device resource settings by writing directly to configuration registers. The OS can write the registers in arbitrary order much like it writes PCI BARs.
However, for PNPBIOS and ACPI devices, the OS uses firmware interfaces that perform device configuration, and it is important to pass the desired settings to those interfaces in the correct order. The OS learns the correct order by using firmware interfaces that return the "current resource settings" and "possible resource settings," but the option structures above doesn't store the ordering information.
This patch replaces the independent and dependent lists with a single list of options. For example, a device might have possible resource settings like this:
dev
options
ind-io0 -> dep0-io0 -> dep1->io0 -> ind-io1 ...All the possible settings are in the same list, in the order they come from the firmware "possible resource settings" list. Each entry is tagged with an independent/dependent flag. Dependent entries also have a "set number" and an optional priority value. All dependent entries must be assigned from the same set. For example, the OS can use all the entries from dependent set 0, or all the entries from dependent set 1, but it cannot use some entries from set 0 and some from set 1.
Prior to this patch PNP didn't keep track of the order of this list, and it assigned all independent options first, then all dependent ones. Using the example above, that resulted in a "desired configuration" list like this:
ind->io0 -> ind->io1 -> depN-io0 ...
instead of the list the firmware expects, which looks like this:
ind->io0 -> depN-io0 -> ind-io1 ...
This reordering results in problems like the one I tried unsuccessfully to fix here:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=41a5311465b9de6d18e78b733a2c6e1b33e89be8
--- drivers/pnp/base.h | 89 +++++++++--- drivers/pnp/core.c | 4 drivers/pnp/interface.c | 75 ++++------ drivers/pnp/isapnp/core.c | 68 ++++----- drivers/pnp/manager.c | 137 +++++-------------- drivers/pnp/pnpacpi/rsparser.c | 93 +++++-------- drivers/pnp/pnpbios/rsparser.c | 64 ++++----- drivers/pnp/quirks.c | 288 ++++++++++++++++++++++------------------- drivers/pnp/resource.c | 205 +++++------------------------ drivers/pnp/support.c | 79 +++++++++++ include/linux/pnp.h | 6 11 files changed, 524 insertions(+), 584 deletions(-)
drivers/pnp/base.h +67 -22
@@ -1,3 +1,8 @@ +/* +* (c) Copyright 2008 Hewlett-Packard Development Company, L.P. +* Bjorn Helgaas <[email protected]> +*/ +extern spinlock_t pnp_lock;void *pnp_alloc (long size);
@@ -25,8 +30,6 @@ struct pnp_port {resource_size_t align;/* align boundary */ resource_size_t size;/* size of range */ unsigned char flags;/* port flags */ -unsigned char pad;/* pad */ -struct pnp_port *next;/* next port */ };#define PNP_IRQ_NR 256
@@ -35,14 +38,11 @@ typedef struct { DECLARE_BITMAP(bits, PNstruct pnp_irq {pnp_irq_mask_t map;/* bitmap for IRQ lines */ unsigned char flags;/* IRQ flags */ -unsigned char pad;/* pad */ -struct pnp_irq *next;/* next IRQ */ };struct pnp_dma {unsigned char map;/* bitmask for DMA channels */ unsigned char flags;/* DMA flags */ -struct pnp_dma *next;/* next port */ };struct pnp_mem {
@@ -51,8 +51,6 @@ struct pnp_mem {resource_size_t align;/* align boundary */ resource_size_t size;/* size of range */ unsigned char flags;/* memory flags */ -unsigned char pad;/* pad */ -struct pnp_mem *next;/* next memory resource */ };#define PNP_RES_PRIORITY_PREFERRED 0
@@ -60,35 +58,82 @@ struct pnp_mem {#define PNP_RES_PRIORITY_FUNCTIONAL 2#define PNP_RES_PRIORITY_INVALID 65535 +#define PNP_OPTION_DEPENDENT 0x80000000 +#define PNP_OPTION_SET_MASK 0xff +#define PNP_OPTION_SET_SHIFT 16 +#define PNP_OPTION_PRIORITY_MASK 0xffff +#define PNP_OPTION_PRIORITY_SHIFT 0 +struct pnp_option { -unsigned short priority;/* priority */ -struct pnp_port *port;/* first port */ -struct pnp_irq *irq;/* first IRQ */ -struct pnp_dma *dma;/* first DMA */ -struct pnp_mem *mem;/* first memory resource */ -struct pnp_option *next;/* used to chain dependent resources */ +struct list_head list; +unsigned int flags;/* independent/dependent, set, priority */ + +unsigned long type;/* IORESOURCE_{IO,MEM,IRQ,DMA} */ +union { +struct pnp_port port; +struct pnp_irq irq; +struct pnp_dma dma; +struct pnp_mem mem; + } u; }; -struct pnp_option *pnp_build_option (int priority); -struct pnp_option *pnp_register_independent_option (struct pnp_dev *dev); -struct pnp_option *pnp_register_dependent_option (struct pnp_dev *dev, -int priority); -int pnp_register_irq_resource (struct pnp_dev *dev,struct pnp_option *option, +int pnp_register_irq_resource (struct pnp_dev *dev,unsigned int option_flags,pnp_irq_mask_t *map,unsigned char flags); -int pnp_register_dma_resource (struct pnp_dev *dev,struct pnp_option *option, +int pnp_register_dma_resource (struct pnp_dev *dev,unsigned int option_flags,unsigned char map,unsigned char flags); -int pnp_register_port_resource (struct pnp_dev *dev,struct pnp_option *option, +int pnp_register_port_resource (struct pnp_dev *dev,unsigned int option_flags,resource_size_t min,resource_size_t max,resource_size_t align,resource_size_t size,unsigned char flags); -int pnp_register_mem_resource (struct pnp_dev *dev,struct pnp_option *option, +int pnp_register_mem_resource (struct pnp_dev *dev,unsigned int option_flags,resource_size_t min,resource_size_t max,resource_size_t align,resource_size_t size,unsigned char flags); + +static inline int pnp_option_is_dependent (struct pnp_option *option) +{ +return option->flags &PNP_OPTION_DEPENDENT ?1 :0 ; +} + +static inline unsigned int pnp_option_set (struct pnp_option *option) +{ +return (option->flags >>PNP_OPTION_SET_SHIFT ) &PNP_OPTION_SET_MASK ; +} + +static inline unsigned int pnp_option_priority (struct pnp_option *option) +{ +return (option->flags >>PNP_OPTION_PRIORITY_SHIFT ) & +PNP_OPTION_PRIORITY_MASK ; +} + +static inline unsigned int pnp_independent_option (void ) +{ +return 0 ; +} + +static inline unsigned int pnp_dependent_option (struct pnp_dev *dev, +int priority) +{ +unsigned int flags; + + flags =PNP_OPTION_DEPENDENT | + ((dev->num_dependent_sets &PNP_OPTION_SET_MASK ) << +PNP_OPTION_SET_SHIFT ) | + ((priority &PNP_OPTION_PRIORITY_MASK ) << +PNP_OPTION_PRIORITY_SHIFT ); + + dev->num_dependent_sets++; + +return flags; +} + +char *pnp_option_priority_name (struct pnp_option *option); +void dbg_pnp_show_option (struct pnp_dev *dev,struct pnp_option *option); +void pnp_init_resources (struct pnp_dev *dev);void pnp_fixup_device (struct pnp_dev *dev); -void pnp_free_option (struct pnp_option *option); +void pnp_free_options (struct pnp_dev *dev);int __pnp_add_device (struct pnp_dev *dev);void __pnp_remove_device (struct pnp_dev *dev);
drivers/pnp/core.c +2 -2
@@ -118,10 +118,9 @@ static void pnp_release_device(struct de {struct pnp_dev *dev =to_pnp_dev (dmdev); -pnp_free_option (dev->independent); -pnp_free_option (dev->dependent);pnp_free_ids (dev);pnp_free_resources (dev); +pnp_free_options (dev);kfree (dev); }
@@ -135,6 +134,7 @@ struct pnp_dev *pnp_alloc_dev(struct pnpreturn NULL ;INIT_LIST_HEAD (&dev->resources); +INIT_LIST_HEAD (&dev->options); dev->protocol = protocol; dev->number = id; dev->dma_mask =DMA_24BIT_MASK ;
drivers/pnp/interface.c +35 -40
103 lines not on this page · raw message
drivers/pnp/isapnp/core.c +31 -37
216 lines not on this page · raw message
drivers/pnp/manager.c +41 -99
178 lines not on this page · raw message
drivers/pnp/pnpacpi/rsparser.c +40 -53
244 lines not on this page · raw message
drivers/pnp/pnpbios/rsparser.c +30 -34
190 lines not on this page · raw message
drivers/pnp/quirks.c +155 -133
359 lines not on this page · raw message
drivers/pnp/resource.c +42 -163
289 lines not on this page · raw message
drivers/pnp/support.c +79 -0
88 lines not on this page · raw message
include/linux/pnp.h +4 -2
@@ -1,6 +1,8 @@/* * Linux Plug and Play Support * Copyright by Adam Belay <[email protected]> +* (c) Copyright 2008 Hewlett-Packard Development Company, L.P. +* Bjorn Helgaas <[email protected]> */ #ifndef _LINUX_PNP_H
@@ -242,9 +244,9 @@ struct pnp_dev {int active;int capabilities; -struct pnp_option *independent; -struct pnp_option *dependent; +unsigned int num_dependent_sets;struct list_head resources; +struct list_head options;char name[PNP_NAME_LEN ];/* contains a human-readable name */ int flags;/* used by protocols */
Re: [patch 15/15] PNP: convert resource options to single linked list
Quoted 36 lines · Bjorn Helgaas
ISAPNP, PNPBIOS, and ACPI describe the "possible resource settings" of a device, i.e., the possibilities an OS bus driver has when it assigns I/O port, MMIO, and other resources to the device.
PNP used to maintain this "possible resource setting" information in one independent option structure and a list of dependent option structures for each device. Each of these option structures had lists of I/O, memory, IRQ, and DMA resources, for example:
dev
independent options ind-io0 -> ind-io1 ... ind-mem0 -> ind-mem1 ... ... dependent option set 0 dep0-io0 -> dep0-io1 ... dep0-mem0 -> dep0-mem1 ... ... dependent option set 1 dep1-io0 -> dep1-io1 ... dep1-mem0 -> dep1-mem1 ... ... ...This data structure was designed for ISAPNP, where the OS configures device resource settings by writing directly to configuration registers. The OS can write the registers in arbitrary order much like it writes PCI BARs.
However, for PNPBIOS and ACPI devices, the OS uses firmware interfaces that perform device configuration, and it is important to pass the desired settings to those interfaces in the correct order. The OS learns the correct order by using firmware interfaces that return the "current resource settings" and "possible resource settings," but the option structures above doesn't store the ordering information.
Quoted 7 lines
This patch replaces the independent and dependent lists with a single list of options. For example, a device might have possible resource settings like this:
dev
options ind-io0 -> dep0-io0 -> dep1->io0 -> ind-io1 ...
Just for the record -- due to an ISAPnP bug, ISAPnP doesn't actually at the moment deal with independents following dependents at all (it does not reset the option to independent upon seeing an _STAG_ENDDEP tag) and the rework actually fixes this bug. The ISAPnP spec does recommend that independents precede dependents, but does not guarantee.
Might be good to mention this in the log though? In the unlikely event that some piece of ISAPnP hardware out there actually changes behaviour (to "fixed" ...) that might be a hint in looking at it.
<snip>
drivers/pnp/base.h struct pnp_mem { · line 65
Quoted 5 lines
drivers/pnp/base.h +5
-0+#define PNP_OPTION_DEPENDENT 0x80000000 +#define PNP_OPTION_SET_MASK 0xff +#define PNP_OPTION_SET_SHIFT 16 +#define PNP_OPTION_PRIORITY_MASK 0xffff +#define PNP_OPTION_PRIORITY_SHIFT 0
I checked, and ISAPnP and PnPBIOS definitely limit the priority to 8-bit and ACPI seems to as well meaning the (only) reason for using 16 would be the RES_PRIORITY_INVALID value.
I have on the other hand not encountered text limiting the number of dependents sets to 255 nor do I believe the old code enforced this?
Yes, I suppose this is exceedingly unlikely to be a practical issue.
<snip>
Quoted 4 lines
static void pnp_print_option(pnp_info_buffer_t * buffer, char *space,
drivers/pnp/interface.c +1
-1- struct pnp_option *option, int dep) + struct pnp_option *option)
drivers/pnp/interface.c static void pnp_print_mem(pnp_info_buffe · line 198
Quoted 10 lines
drivers/pnp/interface.c +10
-0+switch (option->type) { +case IORESOURCE_IO : +pnp_print_port (buffer, space, &option->u.port); +break ; +case IORESOURCE_MEM : +pnp_print_mem (buffer, space, &option->u.mem); +break ; +case IORESOURCE_IRQ : +pnp_print_irq (buffer, space, &option->u.irq); +break ;
I believe it would be good if pnp_print_irq() now also displayed "(optional)" if the flag is set.
Quoted 5 lines
drivers/pnp/isapnp/core.c +0
-1@@ -659,26 +654,24 @@ static int __init isapnp_create_device(s priority =0x100 | tmp[0 ]; size =0 ; } - option =pnp_register_dependent_option (dev, priority);
drivers/pnp/isapnp/core.c static int __init isapnp_create_device(s · line 662
Quoted 10 lines
drivers/pnp/isapnp/core.c +2
-4-if (!option) -return 1 ; + option_flags =pnp_dependent_option (dev, priority);break ;case _STAG_ENDDEP:if (size !=0 ) goto __skip; - priority =0 ; -dev_dbg (&dev->dev,"end dependent options\n" ); + option_flags =pnp_independent_option ();
(here is the bugfix)
Quoted 100 lines
drivers/pnp/manager.c +25
-68-static int pnp_assign_resources (struct pnp_dev *dev,int depnum) +static int pnp_assign_resources (struct pnp_dev *dev,int set) { -struct pnp_port *port; -struct pnp_mem *mem; -struct pnp_irq *irq; -struct pnp_dma *dma; +struct pnp_option *option;int nport =0 , nmem =0 , nirq =0 , ndma =0 ; +int ret =0 ; -dbg_pnp_show_resources (dev,"before pnp_assign_resources" ); +dev_dbg (&dev->dev,"pnp_assign_resources, try dependent set %d\n" , set);mutex_lock (&pnp_res_mutex);pnp_clean_resource_table (dev); -if (dev->independent) { -dev_dbg (&dev->dev,"assigning independent options\n" ); - port = dev->independent->port; - mem = dev->independent->mem; - irq = dev->independent->irq; - dma = dev->independent->dma; -while (port) { -if (pnp_assign_port (dev, port, nport) <0 ) - goto fail; - nport++; - port = port->next; - } -while (mem) { -if (pnp_assign_mem (dev, mem, nmem) <0 ) - goto fail; - nmem++; - mem = mem->next; - } -while (irq) { -if (pnp_assign_irq (dev, irq, nirq) <0 ) - goto fail; - nirq++; - irq = irq->next; - } -while (dma) { -if (pnp_assign_dma (dev, dma, ndma) <0 ) - goto fail; - ndma++; - dma = dma->next; - } - } -if (depnum) { -struct pnp_option *dep; -int i; - -dev_dbg (&dev->dev,"assigning dependent option %d\n" , depnum); -for (i =1 , dep = dev->dependent; i < depnum; - i++, dep = dep->next) -if (!dep) - goto fail; - port = dep->port; - mem = dep->mem; - irq = dep->irq; - dma = dep->dma; -while (port) { -if (pnp_assign_port (dev, port, nport) <0 ) - goto fail; - nport++; - port = port->next; - } -while (mem) { -if (pnp_assign_mem (dev, mem, nmem) <0 ) - goto fail; - nmem++; - mem = mem->next; - } -while (irq) { -if (pnp_assign_irq (dev, irq, nirq) <0 ) - goto fail; - nirq++; - irq = irq->next; +list_for_each_entry (option, &dev->options, list) { +if (pnp_option_is_dependent (option) && +pnp_option_set (option) != set) +continue ; + +switch (option->type) { +case IORESOURCE_IO : + ret =pnp_assign_port (dev, &option->u.port, nport++); +break ; +case IORESOURCE_MEM : + ret =pnp_assign_mem (dev, &option->u.mem, nmem++); +break ; +case IORESOURCE_IRQ : + ret =pnp_assign_irq (dev, &option->u.irq, nirq++); +break ; +case IORESOURCE_DMA : + ret =pnp_assign_dma (dev, &option->u.dma, ndma++); +break ; +default : + ret = -EINVAL ; +break ; } -while (dma) {
drivers/pnp/manager.c static void pnp_clean_resource_table(str · line 269
Quoted 10 lines
drivers/pnp/manager.c +3
-7-if (pnp_assign_dma (dev, dma, ndma) <0 ) - goto fail; - ndma++; - dma = dma->next; - } - }else if (dev->dependent) - goto fail; +if (ret <0 ) +break ; + }
Mmm. Previously when it failed halfway through it re-cleared the resources (at label fail). Does it want to do so now also?
Quoted 26 lines
drivers/pnp/manager.c +6
-10mutex_unlock (&pnp_res_mutex); -dbg_pnp_show_resources (dev,"after pnp_assign_resources" ); -return 1 ; - -fail: -pnp_clean_resource_table (dev); -mutex_unlock (&pnp_res_mutex); -dbg_pnp_show_resources (dev,"after pnp_assign_resources (failed)" ); -return 0 ; +if (ret ==0 ) +dbg_pnp_show_resources (dev,"pnp_assign_resources succeeded" ); +else +dev_dbg (&dev->dev,"pnp_assign_resources failed (%d)\n" , ret); +return ret; }/** @@ -332,29 +282,21 @@ fail:*/ int pnp_auto_config_dev (struct pnp_dev *dev) { -struct pnp_option *dep; -int i =1 ; +int i, ret =0 ;if (!pnp_can_configure (dev)) {
drivers/pnp/manager.c fail: · line 295
Quoted 10 lines
drivers/pnp/manager.c +3
-2dev_dbg (&dev->dev,"configuration not supported\n" );return -ENODEV ; } -if (!dev->dependent) { -if (pnp_assign_resources (dev,0 )) +for (i =0 ; i ==0 || i < dev->num_dependent_sets; i++) { + ret =pnp_assign_resources (dev, i); +if (ret ==0 )return 0 ;
Eeeew. Perhaps:
i = 0;
do {
ret = pnp_assign_resources(dev, i);
if (ret == 0)
return 0;
} while (++i < dev->num_dependent_sets);<snip>
Quoted 70 lines
Index:
work10/drivers/pnp/quirks.c
===================================================================drivers/pnp/quirks.c +36
-14@@ -5,6 +5,8 @@* when building up the resource structure for the first time. * * Copyright (c) 2000 Peter Denison <[email protected]> +* (c) Copyright 2008 Hewlett-Packard Development Company, L.P. +* Bjorn Helgaas <[email protected]> * * Heavily based on PCI quirks handling which is * @@ -20,188 +22,208 @@#include <linux/kallsyms.h> #include "base.h" +static void quirk_awe32_add_ports (struct pnp_dev *dev, +struct pnp_option *option, +unsigned int offset) +{ +struct pnp_option *new_option; + + new_option =kmalloc (sizeof (struct pnp_option ),GFP_KERNEL ); +if (!new_option) { +dev_err (&dev->dev,"couldn't add ioport region to option set " +"%d\n" ,pnp_option_set (option)); +return ; + } + + *new_option = *option; + new_option->u.port.min += offset; + new_option->u.port.max += offset; +list_add (&new_option->list, &option->list); + +dev_info (&dev->dev,"added ioport region %#llx-%#llx to set %d\n" , + (unsigned long long ) new_option->u.port.min, + (unsigned long long ) new_option->u.port.max, +pnp_option_set (option)); +} +static void quirk_awe32_resources (struct pnp_dev *dev) { -struct pnp_port *port, *port2, *port3; -struct pnp_option *res = dev->dependent; +struct pnp_option *option; +unsigned int set = ~0 ;/* -* Unfortunately the isapnp_add_port_resource is too tightly bound -* into the PnP discovery sequence, and cannot be used. Link in the -* two extra ports (at offset 0x400 and 0x800 from the one given) by -* hand. +* Add two extra ioport regions (at offset 0x400 and 0x800 from the +* one given) to every dependent option set. */ -for (; res; res = res->next) { - port2 =pnp_alloc (sizeof (struct pnp_port )); -if (!port2) -return ; - port3 =pnp_alloc (sizeof (struct pnp_port )); -if (!port3) { -kfree (port2); -return ; +list_for_each_entry (option, &dev->options, list) { +if (pnp_option_is_dependent (option) && +pnp_option_set (option) != set) { + set =pnp_option_set (option); +quirk_awe32_add_ports (dev, option,0x800 ); +quirk_awe32_add_ports (dev, option,0x400 );
drivers/pnp/quirks.c line 51
Quoted 10 lines
drivers/pnp/quirks.c +0
-9} - port = res->port; -memcpy (port2, port,sizeof (struct pnp_port )); -memcpy (port3, port,sizeof (struct pnp_port )); - port->next = port2; - port2->next = port3; - port2->min +=0x400 ; - port2->max +=0x400 ; - port3->min +=0x800 ; - port3->max +=0x800 ;
Why do you do 0x800, 0x400 in that order? Shouldn't it just be 0x400, 0x800 to mimick the old order?
Quoted 34 lines
drivers/pnp/quirks.c +11
-16-dev_info (&dev->dev, -"AWE32 quirk - added ioports 0x%lx and 0x%lx\n" , - (unsigned long )port2->min, - (unsigned long )port3->min); } }static void quirk_cmi8330_resources (struct pnp_dev *dev) { -struct pnp_option *res = dev->dependent; -unsigned long tmp; - -for (; res; res = res->next) { - -struct pnp_irq *irq; -struct pnp_dma *dma; +struct pnp_option *option; +struct pnp_irq *irq; +struct pnp_dma *dma; -for (irq = res->irq; irq; irq = irq->next) {// Valid irqs are 5, 7, 10 - tmp =0x04A0 ; -bitmap_copy (irq->map.bits, &tmp,16 );// 0000 0100 1010 0000 - } +list_for_each_entry (option, &dev->options, list) { +if (!pnp_option_is_dependent (option)) +continue ; -for (dma = res->dma; dma; dma = dma->next)// Valid 8bit dma channels are 1,3 +if (option->type ==IORESOURCE_IRQ ) { + irq = &option->u.irq; +bitmap_zero (irq->map.bits,PNP_IRQ_NR ); +__set_bit (5 , irq->map.bits); +__set_bit (7 , irq->map.bits);
drivers/pnp/quirks.c line 91
Quoted 10 lines
drivers/pnp/quirks.c +8
-1+__set_bit (10 , irq->map.bits); +dev_info (&dev->dev,"set possible IRQs in " +"option set %d to 5, 7, 10\n" , +pnp_option_set (option)); + }else if (option->type ==IORESOURCE_DMA ) { + dma = &option->u.dma;if ((dma->flags &IORESOURCE_DMA_TYPE_MASK ) == -IORESOURCE_DMA_8BIT ) +IORESOURCE_DMA_8BIT && + dma->map !=0x000A ) {
It's a char, so 0x0A? 0x000A makes it looks like it's 16-bit.
drivers/pnp/quirks.c line 96
Quoted 5 lines
drivers/pnp/quirks.c +4
-0+dev_info (&dev->dev,"changing possible " +"DMA channel mask in option set %d " +"from %#x to 0xA (1, 3)\n" , +pnp_option_set (option), dma->map); dma->map =0x000A ;
And here...
Quoted 10 lines
drivers/pnp/quirks.c +3
-2+ } + } } -dev_info (&dev->dev,"CMI8330 quirk - forced possible IRQs to 5, 7, 10 " -"and DMA channels to 1, 3\n" ); }static void quirk_sb16audio_resources (struct pnp_dev *dev) { +struct pnp_option *option;
drivers/pnp/quirks.c line 112
Quoted 10 lines
drivers/pnp/quirks.c +1
-2+unsigned int prev_option_flags = ~0 , n =0 ;struct pnp_port *port; -struct pnp_option *res = dev->dependent; -int changed =0 ;/* * The default range on the mpu port for these devices is 0x388-0x388. * Here we increase that range so that two such cards can be * auto-configured. */
While you're there -- s/mpu/OPL/.
Quoted 12 lines
drivers/pnp/quirks.c +10
-1+static void quirk_ad1815_mpu_resources (struct pnp_dev *dev) { -struct pnp_option *res; +struct pnp_option *option, *irq_option =NULL ; +unsigned int independent_irqs =0 ; + +list_for_each_entry (option, &dev->options, list) { +if (option->type ==IORESOURCE_IRQ && + !pnp_option_is_dependent (option)) { + independent_irqs++; + irq_option = option; + }
drivers/pnp/quirks.c line 223
Quoted 10 lines
drivers/pnp/quirks.c +3
-4+ } - res = dev->dependent; -if (!res) +if (independent_irqs !=1 )return ; -while (res->next) - res = res->next; + irq_option->flags |=IORESOURCE_IRQ_OPTIONAL ;
You're in maze of unsigned variables, all named flags...
irq_option->u.irq.flags |= IORESOURCE_IRQ_OPTIONAL;
This was the thing that made things not work when I tested -- on an AD1815...
drivers/pnp/quirks.c line 226
Quoted 4 lines
drivers/pnp/quirks.c +2
-1+dev_info (&dev->dev,"made independent IRQ optional\n" ); - res->next =quirk_isapnp_mpu_options (dev); +quirk_add_irq_optional_dependent_sets (dev);
And as before, this one be gone.
The other quirks look good -- but I have the hardware and will test them specifically.
Quoted 23 lines
Index:
work10/drivers/pnp/resource.c
===================================================================drivers/pnp/resource.c +5
-2@@ -3,6 +3,8 @@* * based on isapnp.c resource management (c) Jaroslav Kysela <[email protected]> * Copyright 2003 Adam Belay <[email protected]> +* (c) Copyright 2008 Hewlett-Packard Development Company, L.P. +* Bjorn Helgaas <[email protected]> */ #include <linux/module.h> @@ -28,78 +30,37 @@ static int pnp_reserve_mem[16] = {[0 ...* option registration */ -struct pnp_option *pnp_build_option (int priority) +struct pnp_option *pnp_build_option (struct pnp_dev *dev, +unsigned long type, +unsigned int option_flags) { -struct pnp_option *option =pnp_alloc (sizeof (struct pnp_option ));
drivers/pnp/resource.c static int pnp_reserve_mem[16] = {[0 ... · line 41
Quoted 10 lines
drivers/pnp/resource.c +2
-4+struct pnp_option *option; + option =kzalloc (sizeof (struct pnp_option ),GFP_KERNEL );if (!option)return NULL ; - option->priority = priority &0xff ; -/* make sure the priority is valid */ -if (option->priority >PNP_RES_PRIORITY_FUNCTIONAL ) - option->priority =PNP_RES_PRIORITY_INVALID ;
Dropping this made the 0x100 | prio ISAPnP/PnPBIOS bug appear. That 0x100 should go anyway but perhaps this limiting is still a good idea?
drivers/pnp/resource.c static int pnp_reserve_mem[16] = {[0 ... · line 48
Quoted 6 lines
drivers/pnp/resource.c +3
-0+ option->flags = option_flags; + option->type = type; +list_add_tail (&option->list, &dev->options);return option; }
Rene.
Re: [patch 15/15] PNP: convert resource options to single linked list
Quoted 11 lines · Rene Herman
On 31-05-08 00:49, Bjorn Helgaas wrote:
Just for the record -- due to an ISAPnP bug, ISAPnP doesn't actually at the moment deal with independents following dependents at all (it does not reset the option to independent upon seeing an
_STAG_ENDDEPtag) and the rework actually fixes this bug. The ISAPnP spec does recommend that independents precede dependents, but does not guarantee.Might be good to mention this in the log though? In the unlikely event that some piece of ISAPnP hardware out there actually changes behaviour (to "fixed" ...) that might be a hint in looking at it.
I split that bugfix into a separate patch; thanks for pointing this out.
Quoted 10 lines
drivers/pnp/base.h struct pnp_mem { · line 65
Quoted 5 lines
drivers/pnp/base.h +5
-0+#define PNP_OPTION_DEPENDENT 0x80000000 +#define PNP_OPTION_SET_MASK 0xff +#define PNP_OPTION_SET_SHIFT 16 +#define PNP_OPTION_PRIORITY_MASK 0xffff +#define PNP_OPTION_PRIORITY_SHIFT 0I checked, and ISAPnP and PnPBIOS definitely limit the priority to 8-bit and ACPI seems to as well meaning the (only) reason for using 16 would be the
RES_PRIORITY_INVALIDvalue.
Quoted 4 lines
I have on the other hand not encountered text limiting the number of dependents sets to 255 nor do I believe the old code enforced this?
Yes, I suppose this is exceedingly unlikely to be a practical issue.
That's definitely backwards. I reversed the sizes, so we'll have 8 bits for the priority byte (including compatibility/performance/ robustness) and 16 bits for the dependent set number. Actually, I made the priority field 12 bits so we'd have space to keep PNP_RES_PRIORITY_INVALID as a truly out-of-band value.
Quoted 4 lines
Quoted 3 lines
static void pnp_print_option(pnp_info_buffer_t * buffer, char *space,
drivers/pnp/interface.c +1
-1- struct pnp_option *option, int dep) + struct pnp_option *option)
Quoted 13 lines
drivers/pnp/interface.c static void pnp_print_mem(pnp_info_buffe · line 198
Quoted 10 lines
drivers/pnp/interface.c +10
-0+switch (option->type) { +case IORESOURCE_IO : +pnp_print_port (buffer, space, &option->u.port); +break ; +case IORESOURCE_MEM : +pnp_print_mem (buffer, space, &option->u.mem); +break ; +case IORESOURCE_IRQ : +pnp_print_irq (buffer, space, &option->u.irq); +break ;I believe it would be good if
pnp_print_irq()now also displayed "(optional)" if the flag is set.
I agree; I added this to the patch that added IORESOURCE_IRQ_OPTIONAL.
Quoted 9 lines
Quoted 9 lines
drivers/pnp/isapnp/core.c +1
-3@@ -659,26 +654,24 @@ static int __init isapnp_create_device(s priority =0x100 | tmp[0 ]; size =0 ; } - option =pnp_register_dependent_option (dev, priority); -if (!option) -return 1 ; + option_flags =pnp_dependent_option (dev, priority);break ;
Quoted 8 lines
drivers/pnp/isapnp/core.c static int __init isapnp_create_device(s · line 662
Quoted 6 lines
drivers/pnp/isapnp/core.c +1
-2case _STAG_ENDDEP:if (size !=0 ) goto __skip; - priority =0 ; -dev_dbg (&dev->dev,"end dependent options\n" ); + option_flags =pnp_independent_option ();(here is the bugfix)
Yep, I split into a separate patch as mentioned above.
Quoted 6 lines
drivers/pnp/manager.c static void pnp_clean_resource_table(str · line 236
Quoted 4 lines
drivers/pnp/manager.c +1
-1-static int pnp_assign_resources (struct pnp_dev *dev,int depnum) +static int pnp_assign_resources (struct pnp_dev *dev,int set) {Mmm. Previously when it failed halfway through it re-cleared the resources (at label fail). Does it want to do so now also?
Yes, I suppose so. I can't remember why I removed that, but it shouldn't hurt, so I added it back.
Quoted 39 lines
Quoted 26 lines
drivers/pnp/manager.c +6
-10mutex_unlock (&pnp_res_mutex); -dbg_pnp_show_resources (dev,"after pnp_assign_resources" ); -return 1 ; - -fail: -pnp_clean_resource_table (dev); -mutex_unlock (&pnp_res_mutex); -dbg_pnp_show_resources (dev,"after pnp_assign_resources (failed)" ); -return 0 ; +if (ret ==0 ) +dbg_pnp_show_resources (dev,"pnp_assign_resources succeeded" ); +else +dev_dbg (&dev->dev,"pnp_assign_resources failed (%d)\n" , ret); +return ret; }/** @@ -332,29 +282,21 @@ fail:*/ int pnp_auto_config_dev (struct pnp_dev *dev) { -struct pnp_option *dep; -int i =1 ; +int i, ret =0 ;if (!pnp_can_configure (dev)) {drivers/pnp/manager.c fail: · line 295
Quoted 10 lines
drivers/pnp/manager.c +3
-2dev_dbg (&dev->dev,"configuration not supported\n" );return -ENODEV ; } -if (!dev->dependent) { -if (pnp_assign_resources (dev,0 )) +for (i =0 ; i ==0 || i < dev->num_dependent_sets; i++) { + ret =pnp_assign_resources (dev, i); +if (ret ==0 )return 0 ;Eeeew. Perhaps:
Quoted 6 lines
i = 0;
do { ret = pnp_assign_resources(dev, i); if (ret == 0) return 0; } while (++i < dev->num_dependent_sets);
Heh :-) I vacillated on that one because I have a personal aversion to "do { ... } while ()", especially with a pre-increment. How would you feel about this alternative?
ret = pnp_assign_resources(dev, 0);
if (ret == 0)
return 0;
for (i = 1; i < dev->num_dependent_sets; i++) {
ret = pnp_assign_resources(dev, i);
if (ret == 0)
return 0;
}Quoted 7 lines
drivers/pnp/quirks.c line 51
Quoted 4 lines
drivers/pnp/quirks.c +0
-4- port2->min +=0x400 ; - port2->max +=0x400 ; - port3->min +=0x800 ; - port3->max +=0x800 ;Why do you do
0x800,0x400in that order? Shouldn't it just be0x400,0x800to mimick the old order?
I think they do end up in the correct order because I'm passing the same list_head to both list_add() calls, e.g., we'll have something like this:
io -> ...
io -> (io + 0x800) -> ...
io -> (io + 0x400) -> (io + 0x800) -> ...Quoted 9 lines
drivers/pnp/quirks.c line 91
Quoted 6 lines
drivers/pnp/quirks.c +4
-1+ }else if (option->type ==IORESOURCE_DMA ) { + dma = &option->u.dma;if ((dma->flags &IORESOURCE_DMA_TYPE_MASK ) == -IORESOURCE_DMA_8BIT ) +IORESOURCE_DMA_8BIT && + dma->map !=0x000A ) {It's a char, so
0x0A?0x000Amakes it looks like it's 16-bit.
Quoted 7 lines
drivers/pnp/quirks.c line 96
Quoted 5 lines
drivers/pnp/quirks.c +4
-0+dev_info (&dev->dev,"changing possible " +"DMA channel mask in option set %d " +"from %#x to 0xA (1, 3)\n" , +pnp_option_set (option), dma->map); dma->map =0x000A ;And here...
Makes sense; I changed this as well as the dev_info() formats.
Quoted 7 lines
drivers/pnp/quirks.c line 112
Quoted 5 lines
drivers/pnp/quirks.c +0
-0/* * The default range on the mpu port for these devices is 0x388-0x388. * Here we increase that range so that two such cards can be * auto-configured. */ While you're there -- s/mpu/OPL/.
Done.
Quoted 25 lines
Quoted 12 lines
drivers/pnp/quirks.c +10
-1+static void quirk_ad1815_mpu_resources (struct pnp_dev *dev) { -struct pnp_option *res; +struct pnp_option *option, *irq_option =NULL ; +unsigned int independent_irqs =0 ; + +list_for_each_entry (option, &dev->options, list) { +if (option->type ==IORESOURCE_IRQ && + !pnp_option_is_dependent (option)) { + independent_irqs++; + irq_option = option; + }drivers/pnp/quirks.c line 223
Quoted 10 lines
drivers/pnp/quirks.c +3
-4+ } - res = dev->dependent; -if (!res) +if (independent_irqs !=1 )return ; -while (res->next) - res = res->next; + irq_option->flags |=IORESOURCE_IRQ_OPTIONAL ;You're in maze of unsigned variables, all named flags...
Quoted 4 lines
irq_option->u.irq.flags|=IORESOURCE_IRQ_OPTIONAL;This was the thing that made things not work when I tested -- on an AD1815...
Ah, of course, thanks. I changed "irq_option" to a "struct pnp_irq *irq" like I should have done to begin with.
Quoted 6 lines
drivers/pnp/quirks.c line 226
Quoted 4 lines
drivers/pnp/quirks.c +2
-1+dev_info (&dev->dev,"made independent IRQ optional\n" ); - res->next =quirk_isapnp_mpu_options (dev); +quirk_add_irq_optional_dependent_sets (dev);And as before, this one be gone.
OK, great. I wasn't sure I had understood those quirks correctly, so thanks for pointing this out.
Quoted 12 lines
Quoted 12 lines
drivers/pnp/resource.c +5
-2-struct pnp_option *pnp_build_option (int priority) +struct pnp_option *pnp_build_option (struct pnp_dev *dev, +unsigned long type, +unsigned int option_flags) { -struct pnp_option *option =pnp_alloc (sizeof (struct pnp_option )); +struct pnp_option *option; + option =kzalloc (sizeof (struct pnp_option ),GFP_KERNEL );if (!option)return NULL ;
Quoted 7 lines
drivers/pnp/resource.c static int pnp_reserve_mem[16] = {[0 ... · line 41
Quoted 4 lines
drivers/pnp/resource.c +0
-4- option->priority = priority &0xff ; -/* make sure the priority is valid */ -if (option->priority >PNP_RES_PRIORITY_FUNCTIONAL ) - option->priority =PNP_RES_PRIORITY_INVALID ;Dropping this made the
0x100| prio ISAPnP/PnPBIOS bug appear. That0x100should go anyway but perhaps this limiting is still a good idea?
Yes; I added the check back to pnp_dependent_option().
PNP_RES_PRIORITY_INVALID was previously 65536, which requires a 16-bit field. I changed it to 0xfff to fit in the 12-bit field I mentioned earlier.
I need to go back over all your comments and make sure I've addressed them all, then I'll post the revised patches, hopefully tomorrow.
Thanks again for all your work reviewing and testing these. It's been incredibly useful.
Bjorn
Re: [patch 15/15] PNP: convert resource options to single linked list
Quoted 5 lines · Bjorn Helgaas
That's definitely backwards. I reversed the sizes, so we'll have 8 bits for the priority byte (including compatibility/performance/ robustness) and 16 bits for the dependent set number. Actually, I made the priority field 12 bits so we'd have space to keep
PNP_RES_PRIORITY_INVALIDas a truly out-of-band value.
Sounds perfect.
Quoted 17 lines
Quoted 6 lines
drivers/pnp/manager.c fail: · line 295
Quoted 4 lines
drivers/pnp/manager.c +3
-0+for (i =0 ; i ==0 || i < dev->num_dependent_sets; i++) { + ret =pnp_assign_resources (dev, i); +if (ret ==0 )return 0 ;Eeeew. Perhaps:
Quoted 6 lines
i = 0;
do { ret = pnp_assign_resources(dev, i); if (ret == 0) return 0; } while (++i < dev->num_dependent_sets);Heh :-) I vacillated on that one because I have a personal aversion to "do { ... } while ()", especially with a pre-increment. How would you feel about this alternative?
Quoted 9 lines
ret = pnp_assign_resources(dev, 0);
if (ret == 0)
return 0;
for (i = 1; i < dev->num_dependent_sets; i++) {
ret = pnp_assign_resources(dev, i);
if (ret == 0)
return 0;
}You could fix the pre-increment by sticking a i++ inside the loop body but there's no arguing with personal aversions...
Yes, I think the latter is better. Straight-forward and clear.
Quoted 9 lines
Quoted 1 line
Why do you do
0x800,0x400in that order? Shouldn't it just be0x400,0x800to mimick the old order?I think they do end up in the correct order because I'm passing the same
list_headto bothlist_add()calls, e.g., we'll have something like this:io -> ... io -> (io + 0x800) -> ... io -> (io + 0x400) -> (io + 0x800) -> ...
Yep. Just needed to see it happen once in the quirk testing I just now did.
Quoted 5 lines
I need to go back over all your comments and make sure I've addressed them all, then I'll post the revised patches, hopefully tomorrow.
Thanks again for all your work reviewing and testing these. It's been incredibly useful.
I've been impressed by this work. This is a good redesign of PnP with a fully bisectable way to get there. And PnP was in need of some work...
Rene.
Re: [patch 15/15] PNP: convert resource options to single linked list
In reply to Rene HermanQuoted 1 line · Rene Herman
The other quirks look good -- but I have the hardware and will test them specifically.
The other quirks are good (In the sense that they work as before. The comments below doubting them have nothing to do with Bjorn reworking them). The options display is with the 0x100 | prio thing fixed locally already.
== 1 == quirk_awe32_resources, CTL0022:
* pre-quirk:
Dependent: 00 - Priority preferred
port 0x620-0x620, align 0x0, size 0x4, 16-bit address decoding
Dependent: 01 - Priority acceptable
port 0x620-0x680, align 0x1f, size 0x4, 16-bit address decoding
* post-quirk:
Dependent: 00 - Priority preferred
port 0x620-0x620, align 0x0, size 0x4, 16-bit address decoding port 0xa20-0xa20, align 0x0, size 0x4, 16-bit address decoding port 0xe20-0xe20, align 0x0, size 0x4, 16-bit address decoding
Dependent: 01 - Priority acceptable
port 0x620-0x680, align 0x1f, size 0x4, 16-bit address decoding port 0xa20-0xa80, align 0x1f, size 0x4, 16-bit address decoding port 0xe20-0xe80, align 0x1f, size 0x4, 16-bit address decoding
I actually expect this quirk to be totally bogus. This adds ports which isapnp_set_resources is then going to try to program into hardware which wouldn't be expecting them. The ALSA driver only references port0 (the 0x620 one) and hardcodes the two other ports at +0x400 and +0x800 itself. I expect the issue is simply that the offsetted ones alias and somebody once thought this could be a way to just reserve those or something.
It's been there since the dawning of time though. Will look at some other time. Things work fine.
== 2 == quirk_cmi8330_resources, @X@0001 (Invalid ID!)
* pre-quirk:
Dependent: 00 - Priority preferred
port 0x220-0x220, align 0x0, size 0x10, 10-bit address decoding irq 5 High-Edge
dma 1 8-bit byte-count compatible
dma 5 16-bit word-count compatible
Dependent: 01 - Priority acceptable
port 0x220-0x240, align 0x1f, size 0x10, 10-bit address decoding irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
dma 5,7 16-bit word-count compatible
Dependent: 02 - Priority acceptable
port 0x220-0x240, align 0x1f, size 0x10, 10-bit address decoding irq 5,7,2/9,10,11,12 High-Edge
dma 0,1,3 8-bit byte-count compatible
dma 5,7 16-bit word-count compatible
* post-quirk:
Dependent: 00 - Priority preferred
port 0x220-0x220, align 0x0, size 0x10, 10-bit address decoding irq 5,7,10 High-Edge
dma 1,3 8-bit byte-count compatible
dma 5 16-bit word-count compatible
Dependent: 01 - Priority acceptable
port 0x220-0x240, align 0x1f, size 0x10, 10-bit address decoding irq 5,7,10 High-Edge
dma 1,3 8-bit byte-count compatible
dma 5,7 16-bit word-count compatible
Dependent: 02 - Priority acceptable
port 0x220-0x240, align 0x1f, size 0x10, 10-bit address decoding irq 5,7,10 High-Edge
dma 1,3 8-bit byte-count compatible
dma 5,7 16-bit word-count compatible
I'll need to verify if this wasn't just someone with a busted DMA channel 0 and too few free interrupts. Unlikely quirk...
== 3 == quirk_sb16audio_resources, CTL0042:
* pre-quirk:
Dependent: 00 - Priority preferred
irq 5 High-Edge
dma 1 8-bit byte-count compatible
dma 5 16-bit word-count compatible
port 0x220-0x220, align 0x0, size 0x10, 16-bit address decoding port 0x330-0x330, align 0x0, size 0x2, 16-bit address decoding port 0x388-0x388, align 0x0, size 0x4, 16-bit address decoding
Dependent: 01 - Priority acceptable
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
dma 5,6,7 16-bit word-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding port 0x300-0x330, align 0x2f, size 0x2, 16-bit address decoding port 0x388-0x388, align 0x0, size 0x4, 16-bit address decoding
Dependent: 02 - Priority acceptable
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
dma 5,6,7 16-bit word-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding port 0x300-0x330, align 0x2f, size 0x2, 16-bit address decoding
Dependent: 03 - Priority acceptable
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
dma 5,6,7 16-bit word-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding
Dependent: 04 - Priority acceptable
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding port 0x300-0x330, align 0x2f, size 0x2, 16-bit address decoding port 0x388-0x388, align 0x0, size 0x4, 16-bit address decoding
Dependent: 05 - Priority acceptable
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding port 0x300-0x330, align 0x2f, size 0x2, 16-bit address decoding
Dependent: 06 - Priority acceptable
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding
Dependent: 07 - Priority functional
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
dma 5,6,7 16-bit word-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding port 0x300-0x330, align 0xf, size 0x2, 16-bit address decoding port 0x388-0x394, align 0x3, size 0x4, 16-bit address decoding
* post-quirk:
Dependent: 00 - Priority preferred
irq 5 High-Edge
dma 1 8-bit byte-count compatible
dma 5 16-bit word-count compatible
port 0x220-0x220, align 0x0, size 0x10, 16-bit address decoding port 0x330-0x330, align 0x0, size 0x2, 16-bit address decoding port 0x388-0x3f8, align 0x0, size 0x4, 16-bit address decoding
Dependent: 01 - Priority acceptable
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
dma 5,6,7 16-bit word-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding port 0x300-0x330, align 0x2f, size 0x2, 16-bit address decoding port 0x388-0x3f8, align 0x0, size 0x4, 16-bit address decoding
Dependent: 02 - Priority acceptable
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
dma 5,6,7 16-bit word-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding port 0x300-0x330, align 0x2f, size 0x2, 16-bit address decoding
Dependent: 03 - Priority acceptable
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
dma 5,6,7 16-bit word-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding
Dependent: 04 - Priority acceptable
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding port 0x300-0x330, align 0x2f, size 0x2, 16-bit address decoding port 0x388-0x3f8, align 0x0, size 0x4, 16-bit address decoding
Dependent: 05 - Priority acceptable
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding port 0x300-0x330, align 0x2f, size 0x2, 16-bit address decoding
Dependent: 06 - Priority acceptable
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding
Dependent: 07 - Priority functional
irq 5,7,2/9,10 High-Edge
dma 0,1,3 8-bit byte-count compatible
dma 5,6,7 16-bit word-count compatible
port 0x220-0x280, align 0x1f, size 0x10, 16-bit address decoding port 0x300-0x330, align 0xf, size 0x2, 16-bit address decoding port 0x388-0x394, align 0x3, size 0x4, 16-bit address decoding
I'll need to verify if the OPL chip in fact works when not on 0x388 (to 0x394 as set 7 allows for) or if this was just someone believing it would. I haven't tested all supported IDs (I might have them all) but if there are none that do _not_ allow the OPL to be completely absent as this CTL0042 (an early Soundblaster AWE64) does, this quirk should just go anyway.
=== 4 === quirk_ad1815_mpu_resources, ADS7151
These results are with the dependent cloning already removed locally.
* pre-quirk:
irq 5,7,2/9,11,12 High-Edge
Dependent: 00 - Priority preferred
port 0x330-0x330, align 0x0, size 0x2, 10-bit address decoding
Dependent: 01 - Priority acceptable
port 0x300-0x300, align 0x0, size 0x2, 10-bit address decoding
Dependent: 02 - Priority functional
port 0x100-0x3fe, align 0x1, size 0x2, 10-bit address decoding
* post-quirk:
irq 5,7,2/9,11,12 High-Edge
Dependent: 00 - Priority preferred
port 0x330-0x330, align 0x0, size 0x2, 10-bit address decoding
Dependent: 01 - Priority acceptable
port 0x300-0x300, align 0x0, size 0x2, 10-bit address decoding
Dependent: 02 - Priority functional
port 0x100-0x3fe, align 0x1, size 0x2, 10-bit address decoding
See why that "(optional)" flag display is good? :-) I ofcourse tested things and the flag works great...
== 5 == quirk_add_irq_optional_dependent_sets, ADS7181
* pre-quirk:
Dependent: 00 - Priority preferred
irq 2/9 High-Edge
port 0x330-0x330, align 0xf, size 0x2, 16-bit address decoding
Dependent: 01 - Priority acceptable
irq 2/9 High-Edge
port 0x300-0x330, align 0xf, size 0x2, 16-bit address decoding
Dependent: 02 - Priority functional
irq 2/9,10,11 High-Edge
port 0x300-0x330, align 0xf, size 0x2, 16-bit address decoding
* post-quirk:
Dependent: 00 - Priority preferred
irq 2/9 High-Edge
port 0x330-0x330, align 0xf, size 0x2, 16-bit address decoding
Dependent: 01 - Priority acceptable
irq 2/9 High-Edge
port 0x300-0x330, align 0xf, size 0x2, 16-bit address decoding
Dependent: 02 - Priority functional
irq 2/9,10,11 High-Edge
port 0x300-0x330, align 0xf, size 0x2, 16-bit address decoding
Dependent: 03 - Priority functional
irq 2/9 High-Edge
port 0x330-0x330, align 0xf, size 0x2, 16-bit address decoding
Dependent: 04 - Priority functional
irq 2/9 High-Edge
port 0x300-0x330, align 0xf, size 0x2, 16-bit address decoding
Dependent: 05 - Priority functional
irq 2/9,10,11 High-Edge
port 0x300-0x330, align 0xf, size 0x2, 16-bit address decoding
Again needs the flag display to make sense but as intended and works fine.
The PCI one didn't change here...
Rene.
Re: [patch 15/15] PNP: convert resource options to single linked list
On 04-06-08 01:52, Rene Herman wrote:
Mmm. If you care for it:
Quoted 54 lines
=== 4 ===
quirk_ad1815_mpu_resources, ADS7151These results are with the dependent cloning already removed locally.
* pre-quirk:
irq 5,7,2/9,11,12 High-Edge
Dependent: 00 - Priority preferred
port 0x330-0x330, align0x0, size0x2, 10-bit address decoding
Dependent: 01 - Priority acceptable
port 0x300-0x300, align0x0, size0x2, 10-bit address decoding
Dependent: 02 - Priority functional
port 0x100-0x3fe, align0x1, size0x2, 10-bit address decoding* post-quirk:
irq 5,7,2/9,11,12 High-Edge
Dependent: 00 - Priority preferred
port 0x330-0x330, align0x0, size0x2, 10-bit address decoding
Dependent: 01 - Priority acceptable
port 0x300-0x300, align0x0, size0x2, 10-bit address decoding
Dependent: 02 - Priority functional
port 0x100-0x3fe, align0x1, size0x2, 10-bit address decodingSee why that "(optional)" flag display is good? :-) I ofcourse tested things and the flag works great...
== 5 ==
quirk_add_irq_optional_dependent_sets, ADS7181* pre-quirk:
Dependent: 00 - Priority preferred
irq 2/9 High-Edge
port 0x330-0x330, align0xf, size0x2, 16-bit address decoding
Dependent: 01 - Priority acceptable
irq 2/9 High-Edge
port 0x300-0x330, align0xf, size0x2, 16-bit address decoding
Dependent: 02 - Priority functional
irq 2/9,10,11 High-Edge
port 0x300-0x330, align0xf, size0x2, 16-bit address decoding* post-quirk:
Dependent: 00 - Priority preferred
irq 2/9 High-Edge
port 0x330-0x330, align0xf, size0x2, 16-bit address decoding
Dependent: 01 - Priority acceptable
irq 2/9 High-Edge
port 0x300-0x330, align0xf, size0x2, 16-bit address decoding
Dependent: 02 - Priority functional
irq 2/9,10,11 High-Edge
port 0x300-0x330, align0xf, size0x2, 16-bit address decoding
Dependent: 03 - Priority functional
Quoted 8 lines
irq 2/9 High-Edge
port 0x330-0x330, align0xf, size0x2, 16-bit address decoding
Dependent: 04 - Priority functional
irq 2/9 High-Edge
port 0x300-0x330, align0xf, size0x2, 16-bit address decoding
Dependent: 05 - Priority functional
irq 2/9,10,11 High-Edge
port 0x300-0x330, align0xf, size0x2, 16-bit address decoding
ADS7181 in fact might as well delete the IRQ from the dependents and add
"irq 2/9,10,11 High-Edge Optinal" in front as an independent same as ADS7151. That way, all the cloning can go.
I'll probably place that on top if you don't, but you might already want to since it loses all that code. Only difference would be that if IRQ 9 is taken and 10 free, the new situation would grab 330/10 while the old would've taken 300/10, but that's in fact better...
Rene.
Re: [patch 15/15] PNP: convert resource options to single linked list
Quoted 5 lines · Rene Herman
On 04-06-08 01:52, Rene Herman wrote:
ADS7181 in fact might as well delete the IRQ from the dependents and add "irq 2/9,10,11 High-Edge Optinal" in front as an independent same as ADS7151. That way, all the cloning can go.
We currently clone for AZT0002 as well as ADS7181. Can we do the same for both? It would be nice to get rid of the cloning code if we can.
Bjorn
Re: [patch 15/15] PNP: convert resource options to single linked list
Quoted 9 lines · Bjorn Helgaas
Quoted 4 lines · Rene Herman
On 04-06-08 01:52, Rene Herman wrote:
ADS7181 in fact might as well delete the IRQ from the dependents and add
"irq 2/9,10,11 High-Edge Optinal" in front as an independent same as ADS7151. That way, all the cloning can go.We currently clone for AZT0002 as well as ADS7181. Can we do the same for both? It would be nice to get rid of the cloning code if we can.
Yes. AZT0002 (the MPU401 on an AZT2320 chip) is the exact same as ADS7181 (the MPU401 on an AD1816 chip).
IORESOURCE_IRQ_OPTIONAL clears the path for doing things better. I see its dependent 2 can then just go entirely in fact.
Hardware says:
Dependent: 00 - Priority preferred
irq 2/9 High-Edge
port 0x330-0x330, align 0xf, size 0x2, 16-bit address decoding
Dependent: 01 - Priority acceptable
irq 2/9 High-Edge
port 0x300-0x330, align 0xf, size 0x2, 16-bit address decoding
Dependent: 02 - Priority functional
irq 2/9,10,11 High-Edge
port 0x300-0x330, align 0xf, size 0x2, 16-bit address decoding
We want it to end up as:
irq 2/9,10,11 High-Edge (Optional)
Dependent: 00 - Priority preferred
port 0x330-0x330, align 0xf, size 0x2, 16-bit address decoding
Dependent: 01 - Priority acceptable
port 0x300-0x330, align 0xf, size 0x2, 16-bit address decoding
So walk dependents deleting IRQs, except last dependent IRQ which is cloned into a new independent (inserted in front would be best for ISAPnP since the spec does recommend this) while making it optional and then just delete the last dependent completely (it would be same as the previous dependent after all).
Rene.
Re: [patch 15/15] PNP: convert resource options to single linked list
Quoted 39 lines · Rene Herman
Quoted 10 lines · Bjorn Helgaas
Quoted 5 lines · Rene Herman
On 04-06-08 01:52, Rene Herman wrote:
ADS7181 in fact might as well delete the IRQ from the dependents and add "irq 2/9,10,11 High-Edge Optinal" in front as an independent same as ADS7151. That way, all the cloning can go.
We currently clone for AZT0002 as well as ADS7181. Can we do the same for both? It would be nice to get rid of the cloning code if we can.
Yes. AZT0002 (the MPU401 on an AZT2320 chip) is the exact same as ADS7181 (the MPU401 on an AD1816 chip).
IORESOURCE_IRQ_OPTIONALclears the path for doing things better. I see its dependent 2 can then just go entirely in fact.Hardware says:
Dependent: 00 - Priority preferred
irq 2/9 High-Edge
port 0x330-0x330, align0xf, size0x2, 16-bit address decoding
Dependent: 01 - Priority acceptable
irq 2/9 High-Edge
port 0x300-0x330, align0xf, size0x2, 16-bit address decoding
Dependent: 02 - Priority functional
irq 2/9,10,11 High-Edge
port 0x300-0x330, align0xf, size0x2, 16-bit address decodingWe want it to end up as:
irq 2/9,10,11 High-Edge (Optional)
Dependent: 00 - Priority preferred
port 0x330-0x330, align0xf, size0x2, 16-bit address decoding
Dependent: 01 - Priority acceptable
port 0x300-0x330, align0xf, size0x2, 16-bit address decoding
Quoted 5 lines
So walk dependents deleting IRQs, except last dependent IRQ which is cloned into a new independent (inserted in front would be best for ISAPnP since the spec does recommend this) while making it optional and then just delete the last dependent completely (it would be same as the previous dependent after all).
That would probably simplify things a bit. Although in the general case, I suppose we'd want to make sure the options we delete are a subset of the independent one we add. Will look at this more tomorrow.
Bjorn
Re: [patch 15/15] PNP: convert resource options to single linked list
In reply to Bjorn HelgaasOn 31-05-08 00:49, Bjorn Helgaas wrote:
Forgot this comment:
Quoted 83 lines
drivers/pnp/quirks.c +31
-44+static struct pnp_option *pnp_clone_dependent_set (struct pnp_dev *dev, +unsigned int set) { -struct pnp_option *head =NULL ; -struct pnp_option *prev =NULL ; -struct pnp_option *res; - -/* -* Build a functional IRQ-optional variant of each MPU option. -*/ - -for (res = dev->dependent; res; res = res->next) { -struct pnp_option *curr; -struct pnp_port *port; -struct pnp_port *copy_port; -struct pnp_irq *irq; -struct pnp_irq *copy_irq; - - port = res->port; - irq = res->irq; -if (!port || !irq) -continue ; +struct pnp_option *tail =NULL , *first_new_option =NULL ; +struct pnp_option *option, *new_option; +unsigned int flags; + +list_for_each_entry (option, &dev->options, list) { +if (pnp_option_is_dependent (option)) + tail = option; + } +if (!tail) { +dev_err (&dev->dev,"no dependent option sets\n" ); +return NULL ; + } - copy_port =pnp_alloc (sizeof *copy_port); -if (!copy_port) -break ; - - copy_irq =pnp_alloc (sizeof *copy_irq); -if (!copy_irq) { -kfree (copy_port); -break ; - } + flags =pnp_dependent_option (dev,PNP_RES_PRIORITY_FUNCTIONAL ); +list_for_each_entry (option, &dev->options, list) { +if (pnp_option_is_dependent (option) && +pnp_option_set (option) == set) { + new_option =kmalloc (sizeof (struct pnp_option ), +GFP_KERNEL ); +if (!new_option) { +dev_err (&dev->dev,"couldn't clone dependent " +"set %d\n" , set); +return NULL ; + } - *copy_port = *port; - copy_port->next =NULL ; + *new_option = *option; + new_option->flags = flags; +if (!first_new_option) + first_new_option = new_option; - *copy_irq = *irq; - copy_irq->flags |=IORESOURCE_IRQ_OPTIONAL ; - copy_irq->next =NULL ; - - curr =pnp_build_option (PNP_RES_PRIORITY_FUNCTIONAL ); -if (!curr) { -kfree (copy_port); -kfree (copy_irq); -break ; +list_add (&new_option->list, &tail->list); + tail = new_option; } - curr->port = copy_port; - curr->irq = copy_irq; - -if (prev) - prev->next = curr;
drivers/pnp/quirks.c line 176
Quoted 10 lines
drivers/pnp/quirks.c +1
-6-else - head = curr; - prev = curr; } -if (head) -dev_info (&dev->dev,"adding IRQ-optional MPU options\n" ); -return head; +return first_new_option; }
This works, but I did the "disconnected chain build" that I did due to finding it particularly clumsy to add to the dependent chain while walking it.
This avoids actual problems due to num_sets = dev->num_dependents_sets in caller and the pnp_option_set(option) == set in the loop (not unlike the first version of the original checked for a present irq) but it's again checking the options it just added itself.
If you feel that's perfectly fine then <shrug> but thought I'd still remark on it in case it wasn't intentional.
Rene.
Re: [patch 15/15] PNP: convert resource options to single linked list
Quoted 102 lines · Rene Herman
On 31-05-08 00:49, Bjorn Helgaas wrote:
Forgot this comment:
Quoted 83 lines
drivers/pnp/quirks.c +31
-44+static struct pnp_option *pnp_clone_dependent_set (struct pnp_dev *dev, +unsigned int set) { -struct pnp_option *head =NULL ; -struct pnp_option *prev =NULL ; -struct pnp_option *res; - -/* -* Build a functional IRQ-optional variant of each MPU option. -*/ - -for (res = dev->dependent; res; res = res->next) { -struct pnp_option *curr; -struct pnp_port *port; -struct pnp_port *copy_port; -struct pnp_irq *irq; -struct pnp_irq *copy_irq; - - port = res->port; - irq = res->irq; -if (!port || !irq) -continue ; +struct pnp_option *tail =NULL , *first_new_option =NULL ; +struct pnp_option *option, *new_option; +unsigned int flags; + +list_for_each_entry (option, &dev->options, list) { +if (pnp_option_is_dependent (option)) + tail = option; + } +if (!tail) { +dev_err (&dev->dev,"no dependent option sets\n" ); +return NULL ; + } - copy_port =pnp_alloc (sizeof *copy_port); -if (!copy_port) -break ; - - copy_irq =pnp_alloc (sizeof *copy_irq); -if (!copy_irq) { -kfree (copy_port); -break ; - } + flags =pnp_dependent_option (dev,PNP_RES_PRIORITY_FUNCTIONAL ); +list_for_each_entry (option, &dev->options, list) { +if (pnp_option_is_dependent (option) && +pnp_option_set (option) == set) { + new_option =kmalloc (sizeof (struct pnp_option ), +GFP_KERNEL ); +if (!new_option) { +dev_err (&dev->dev,"couldn't clone dependent " +"set %d\n" , set); +return NULL ; + } - *copy_port = *port; - copy_port->next =NULL ; + *new_option = *option; + new_option->flags = flags; +if (!first_new_option) + first_new_option = new_option; - *copy_irq = *irq; - copy_irq->flags |=IORESOURCE_IRQ_OPTIONAL ; - copy_irq->next =NULL ; - - curr =pnp_build_option (PNP_RES_PRIORITY_FUNCTIONAL ); -if (!curr) { -kfree (copy_port); -kfree (copy_irq); -break ; +list_add (&new_option->list, &tail->list); + tail = new_option; } - curr->port = copy_port; - curr->irq = copy_irq; - -if (prev) - prev->next = curr;drivers/pnp/quirks.c line 176
Quoted 10 lines
drivers/pnp/quirks.c +1
-6-else - head = curr; - prev = curr; } -if (head) -dev_info (&dev->dev,"adding IRQ-optional MPU options\n" ); -return head; +return first_new_option; }This works, but I did the "disconnected chain build" that I did due to finding it particularly clumsy to add to the dependent chain while walking it.
Quoted 7 lines
This avoids actual problems due to
num_sets=dev->num_dependents_setsin caller and thepnp_option_set(option)== set in the loop (not unlike the first version of the original checked for a present irq) but it's again checking the options it just added itself.If you feel that's perfectly fine then <shrug> but thought I'd still remark on it in case it wasn't intentional.
Hmmm... I think I see what you mean. It should work as-is, but maybe it'd be more elegant to build the new list separately and use list_splice to insert it.
Guess I'll wait for you to confirm whether we can rip out the list clone altogether before trying this out.
Bjorn
Quoted 10 lines · Bjorn Helgaas
This patch series converts the PNP resource option structures to a unified linked list. This preserves resource order, which is important for some devices. There's more detail in the comments for the last patch.
Any comments would be welcome.
This depends on some patches that are in -mm, but not yet upstream. In mmotm, these would probably go after pnp-dont-sort-by-type-in-sys-resources.patch
Will look at this in more detail but as first testing feedback -- I need this on top.
Both ISAPnP and PnPBIOS for some or other reason set the priority to 0x100 | prio after which that 0x100 is immediately masked of again in pnp_build_option() leaving just the prio. Your new scheme reserves 16 bits for the priority though meaning the 0x100 survives causing it to be considered "invalid" by at least pnp_option_priority_name() for example.
There cannot be any currently valid reason for the 0x100 it seems given that it's immediately masked of again in pnp_build_option() so let's just get rid of it...
drivers/pnp/isapnp/core.c +2 -2
@@ -648,10 +648,10 @@ static int __init isapnp_create_device(struct pnp_card *card,case _STAG_STARTDEP:if (size >1 ) goto __skip; - priority =0x100 |PNP_RES_PRIORITY_ACCEPTABLE ; + priority =PNP_RES_PRIORITY_ACCEPTABLE ;if (size >0 ) {isapnp_peek (tmp, size); - priority =0x100 | tmp[0 ]; + priority = tmp[0 ]; size =0 ; } option_flags =pnp_dependent_option (dev, priority);
drivers/pnp/pnpbios/rsparser.c +2 -2
@@ -393,9 +393,9 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,case SMALL_TAG_STARTDEP :if (len >1 ) goto len_err; - priority =0x100 |PNP_RES_PRIORITY_ACCEPTABLE ; + priority =PNP_RES_PRIORITY_ACCEPTABLE ;if (len >0 ) - priority =0x100 | p[1 ]; + priority = p[1 ]; option_flags =pnp_dependent_option (dev, priority);break ;
Quoted 22 lines · Rene Herman
Quoted 10 lines · Bjorn Helgaas
This patch series converts the PNP resource option structures to a unified linked list. This preserves resource order, which is important for some devices. There's more detail in the comments for the last patch.
Any comments would be welcome.
This depends on some patches that are in -mm, but not yet upstream. In mmotm, these would probably go after pnp-dont-sort-by-type-in-sys-resources.patch
Will look at this in more detail but as first testing feedback -- I need this on top.
Both ISAPnP and PnPBIOS for some or other reason set the priority to
0x100| prio after which that0x100is immediately masked of again inpnp_build_option()leaving just the prio. Your new scheme reserves 16 bits for the priority though meaning the0x100survives causing it to be considered "invalid" by at leastpnp_option_priority_name()for example.
Quoted 3 lines
There cannot be any currently valid reason for the
0x100it seems given that it's immediately masked of again inpnp_build_option()so let's just get rid of it...
I agree, that bit looks superfluous. I added a patch to remove it. Thanks,
Bjorn