PnP Card Services - 2.5.49
Subsystems (5)
PATCH 1/1 PnP Card Services - 2.5.49
The truth is the current PnP Layer is not flexable enough to easily handle PnP Sound cards that need several PnP devices, one for midi, control, etc. This patch provides management for groups of devices, called cards. Each card has an EISA ID. These IDs are now kept entirely seperate from the pnp device matching functions. A new bus is created, "pnp_card". This bus is used to manage PnP cards. For more information read the comments in the new file /drivers/pnp/card.c. Official documentation will be out later but card.c should introduce the concepts.
I believe this patch will be a big improvement for PnP driver developers. Currently the ALSA opl3sa2 sound driver has been converted as example. I didn't get around to the remove function yet and I was hoping Jaroslav would give me some insight here. There are many solutions, one might be to store the idx number in driver_data. I didn't want to make too many design changes to the ALSA driver so I decided to leave it open for now.
I'm interested in any questions or comments.
Thanks,
Adam
In addition this patch contains a couple suggestions from Greg and many important bug fixes.
also there's a fix from Luca. Here's the relevant portion of the original message:
In drivers/pnp/pnpbios/core.c each array is accessed with an index that overflow the size of the array. IMHO we didn't see any corruption because we end up writing on the next member (ie: ->port[8] is ->irq[0]) which is resetted to a sane value in the next cycle.
This patch should apply against 2.5.50 as well, considering only a couple pnp changes were made by Alan. If it doesn't, please let me know.
drivers/input/gameport/ns558.c +0 -1
@@ -237,7 +237,6 @@static struct pnp_driver ns558_pnp_driver = { .name ="ns558" , - .card_id_table =NULL , .id_table = pnp_devids, .probe = ns558_pnp_probe, };
drivers/parport/parport_pc.c +1 -2
@@ -2970,7 +2970,7 @@#endif /* CONFIG_PCI */ #ifdef CONFIG_PNP -static const struct pnp_id pnp_dev_table[] = { +static const struct pnp_device_id pnp_dev_table[] = {/* Standard LPT Printer Port */ {.id ="PNP0400" , .driver_data =0 }, /* ECP Printer Port */
@@ -2981,7 +2981,6 @@/* we only need the pnp layer to activate the device, at least for now */ static struct pnp_driver parport_pc_pnp_driver = { .name ="parport_pc" , - .card_id_table =NULL , .id_table = pnp_dev_table, };#else
drivers/pnp/Kconfig +12 -3
@@ -2,7 +2,7 @@ # Plug and Play configuration # -menu "Plug and Play configuration" +menu "Plug and Play support" config PNP bool "Plug and Play support"
@@ -30,11 +30,20 @@ If unsure, say Y. +config PNP_CARD + bool "Plug and Play card services" + depends on PNP + help + Select Y if you want the PnP Layer to manage cards. Cards are groups + of PnP devices. Some drivers, especially PnP sound card drivers, use + these cards. If you want to use the protocol ISAPNP you will need to + say Y here. + config PNP_DEBUG bool "PnP Debug Messages" depends on PNP help - Say Y if you want the Plug and Play Layer to print debug messages. + Say Y if you want the Plug and Play Layer to print debug messages. This is useful if you are developing a PnP driver or troubleshooting. comment "Protocols"
@@ -42,7 +51,7 @@ config ISAPNP bool "ISA Plug and Play support (EXPERIMENTAL)" - depends on PNP && EXPERIMENTAL + depends on PNP && EXPERIMENTAL && PNP_CARD help Say Y here if you would like support for ISA Plug and Play devices. Some information is in <file:Documentation/isapnp.txt>.
drivers/pnp/Makefile +4 -2
@@ -2,11 +2,13 @@ # Makefile for the Linux Plug-and-Play Support. # -obj-y := core.o driver.o resource.o interface.o quirks.o names.o system.o +pnp-card-$(CONFIG_PNP_CARD) = card.o + +obj-y := core.o driver.o resource.o interface.o quirks.o names.o system.o $(pnp-card-y) obj-$(CONFIG_PNPBIOS) += pnpbios/ obj-$(CONFIG_ISAPNP) += isapnp/ -export-objs := core.o driver.o resource.o +export-objs := core.o driver.o resource.o $(pnp-card-y) include $(TOPDIR)/Rules.make
drivers/pnp/base.h +2 -1
@@ -4,5 +4,6 @@extern int pnp_interface_attach_device (struct pnp_dev *dev);extern void pnp_name_device (struct pnp_dev *dev);extern void pnp_fixup_device (struct pnp_dev *dev); -extern void pnp_free_ids (struct pnp_dev *dev);extern void pnp_free_resources (struct pnp_resources *resources); +extern int __pnp_add_device (struct pnp_dev *dev); +extern void __pnp_remove_device (struct pnp_dev *dev);
drivers/pnp/card.c +342 -0
342 lines not on this page · raw message
drivers/pnp/core.c +48 -39
158 lines not on this page · raw message
drivers/pnp/driver.c +28 -59
151 lines not on this page · raw message
drivers/pnp/interface.c +4 -4
@@ -320,13 +320,13 @@static ssize_t pnp_show_current_ids (struct device *dmdev,char *buf,size_t count,loff_t off) {char *str = buf; -struct list_head * pos;struct pnp_dev *dev =to_pnp_dev (dmdev); +struct pnp_id * pos = dev->id;if (off)return 0 ; -list_for_each (pos,&dev->ids) { -struct pnp_id * cur =to_pnp_id (pos); - str +=sprintf (str,"%s\n" , cur->id); +while (pos) { + str +=sprintf (str,"%s\n" , pos->id); + pos = pos->next; }return (str - buf); }
drivers/pnp/isapnp/Makefile +2 -2
@@ -2,10 +2,10 @@ # Makefile for the kernel ISAPNP driver. # -export-objs := core.o compat.o +export-objs := core.o isapnp-proc-$(CONFIG_PROC_FS) = proc.o -obj-y := core.o compat.o $(isapnp-proc-y) +obj-y := core.o $(isapnp-proc-y) include $(TOPDIR)/Rules.make
drivers/pnp/isapnp/core.c +9 -30
@@ -449,13 +449,13 @@ dev =isapnp_alloc (sizeof (struct pnp_dev ));if (!dev)return NULL ; -pnp_init_device (dev); dev->number = number;isapnp_parse_id (dev, (tmp[1 ] <<8 ) | tmp[0 ], (tmp[3 ] <<8 ) | tmp[2 ]); dev->regs = tmp[4 ]; dev->card = card;if (size >5 ) dev->regs |= tmp[5 ] <<8 ; + dev->protocol = &isapnp_protocol;return dev; }
@@ -640,7 +640,7 @@return 1 ;if (pnp_build_resource (dev,0 ) ==NULL )return 1 ; -list_add_tail (&dev->card_list, &card->devices); +pnpc_add_device (card,dev);while (1 ) {if (isapnp_read_tag (&type, &size)<0 )return 1 ;
@@ -653,7 +653,7 @@if ((dev =isapnp_parse_device (card, size, number++)) ==NULL )return 1 ;pnp_build_resource (dev,0 ); -list_add_tail (&dev->card_list, &card->devices); +pnpc_add_device (card,dev); size =0 ; skip =0 ; }else {
@@ -848,7 +848,7 @@ device &0x0f , (device >>12 ) &0x0f , (device >> 8) & 0x0f); -list_add_tail (&id->id_list,&card->ids); +pnpc_add_id (id,card); }/*
@@ -879,12 +879,11 @@ ; else if (checksum == 0x00 || checksum != header[8]) /* not valid CSN */continue ; -if ((card =isapnp_alloc (sizeof (struct pci_bus ))) ==NULL ) +if ((card =isapnp_alloc (sizeof (struct pnp_card ))) ==NULL )continue ; card->number = csn;INIT_LIST_HEAD (&card->devices); -INIT_LIST_HEAD (&card->ids);isapnp_parse_card_id (card, (header[1 ] <<8 ) | header[0 ], (header[3 ] <<8 ) | header[2 ]); card->serial = (header[7 ] <<24 ) | (header[6 ] <<16 ) | (header[5 ] <<8 ) | header[4 ]; isapnp_checksum_value =0x00 ;
@@ -892,8 +891,8 @@if (isapnp_checksum_value !=0x00 )printk (KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n" , csn, isapnp_checksum_value); card->checksum = isapnp_checksum_value; - -list_add_tail (&card->node, &isapnp_cards); + card->protocol = &isapnp_protocol; +pnpc_add_card (card); }return 0 ; }
@@ -1061,25 +1060,6 @@ .disable = isapnp_disable_resources, }; -static inline int isapnp_init_device_tree (void ) -{ - -struct pnp_card *card; - -isapnp_for_each_card (card) { -struct list_head *devlist; -for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) { -struct pnp_dev *dev =card_to_pnp_dev (devlist); -snprintf (dev->dev.name,sizeof (dev->dev.name),"%s" , dev->name); - dev->card = card; - dev->protocol = &isapnp_protocol; -pnp_add_device (dev); - } - } - -return 0 ; -} -int __init isapnp_init (void ) {int cards;
@@ -1104,7 +1084,7 @@return -EBUSY ; } -if (pnp_protocol_register (&isapnp_protocol)<0 ) +if (pnp_register_protocol (&isapnp_protocol)<0 )return -EBUSY ;/*
@@ -1143,7 +1123,7 @@isapnp_build_device_list (); cards =0 ; -isapnp_for_each_card (card) { +protocol_for_each_card (&isapnp_protocol,card) { cards++;if (isapnp_verbose) {struct list_head *devlist;
@@ -1162,7 +1142,6 @@printk (KERN_INFO "isapnp: No Plug & Play card found\n" ); } -isapnp_init_device_tree ();isapnp_proc_init ();return 0 ; }
drivers/pnp/isapnp/proc.c +1 -1
@@ -146,7 +146,7 @@ {struct pnp_dev *dev; isapnp_proc_bus_dir =proc_mkdir ("isapnp" , proc_bus); -isapnp_for_each_dev (dev) { +protocol_for_each_dev (&isapnp_protocol,dev) {isapnp_proc_attach_device (dev); }return 0 ;
drivers/pnp/names.c +1 -1
@@ -32,7 +32,7 @@int i;char *name = dev->name;for (i=0 ; i<sizeof (pnp_id_eisaid)/sizeof (pnp_id_eisaid[0 ]); i++){ -if (compare_pnp_id (&dev->ids,pnp_id_eisaid[i])){ +if (compare_pnp_id (dev->id,pnp_id_eisaid[i])){sprintf (name,"%s" , pnp_id_names[i]);return ; }
drivers/pnp/pnpbios/core.c +6 -7
@@ -1342,13 +1342,13 @@memset (config,0 ,sizeof (struct pnp_cfg ));if (!dev || !dev->active)return -EINVAL ; -for (i=0 ; i <=8 ; i++) +for (i=0 ; i <8 ; i++) config->port[i] = &port; -for (i=0 ; i <=4 ; i++) +for (i=0 ; i <4 ; i++) config->mem[i] = &mem; -for (i=0 ; i <=2 ; i++) +for (i=0 ; i <2 ; i++) config->irq[i] = &irq; -for (i=0 ; i <=2 ; i++) +for (i=0 ; i <2 ; i++) config->dma[i] = &dma; dev->active =0 ;
@@ -1385,7 +1385,7 @@struct list_head * pos;struct pnp_dev * pnp_dev; list_for_each (pos, &pnpbios_protocol.devices){ - pnp_dev = list_entry(pos, struct pnp_dev, dev_list); + pnp_dev = list_entry(pos, struct pnp_dev, protocol_list);if (dev->number == pnp_dev->number)return -1 ; }
@@ -1435,7 +1435,6 @@if (!dev_id)break ;memset (dev_id,0 ,sizeof (struct pnp_id )); -pnp_init_device (dev); dev->number = thisnodenum;memcpy (dev->name,"Unknown Device" ,13 ); dev->name[14 ] ='\0' ;
@@ -1556,7 +1555,7 @@ }if (!pnp_bios_present ())return -ENODEV ; -pnp_protocol_register (&pnpbios_protocol); +pnp_register_protocol (&pnpbios_protocol);build_devlist ();/*if ( ! dont_reserve_resources )*/ /*reserve_resources();*/
drivers/pnp/quirks.c +1 -1
@@ -157,7 +157,7 @@int i =0 ;while (*pnp_fixups[i].id) { -if (compare_pnp_id (&dev->ids,pnp_fixups[i].id)) { +if (compare_pnp_id (dev->id,pnp_fixups[i].id)) {pnp_dbg ("Calling quirk for %s" , dev->dev.bus_id); pnp_fixups[i].quirk_function (dev);
drivers/pnp/system.c +2 -8
@@ -13,12 +13,7 @@#include <linux/kernel.h> #include <linux/ioport.h> -static const struct pnp_id pnp_card_table[] = { - {"ANYDEVS" ,0 }, - {"" ,0 } -}; - -static const struct pnp_id pnp_dev_table[] = { +static const struct pnp_device_id pnp_dev_table[] = {/* General ID for reserving resources */ {"PNP0c02" ,0 },/* memory controller */
@@ -101,7 +96,7 @@return ; } -static int system_pnp_probe (struct pnp_dev * dev,const struct pnp_id *card_id,const struct pnp_id *dev_id) +static int system_pnp_probe (struct pnp_dev * dev,const struct pnp_device_id *dev_id) {reserve_resources_of_dev (dev);return 0 ;
@@ -109,7 +104,6 @@static struct pnp_driver system_pnp_driver = { .name ="system" , - .card_id_table = pnp_card_table, .id_table = pnp_dev_table, .probe = system_pnp_probe, .remove =NULL ,
drivers/serial/8250_pnp.c +2 -8
@@ -33,12 +33,7 @@#define UNKNOWN_DEV 0x3000 -static const struct pnp_id pnp_card_table[] = { - {"ANYDEVS" ,0 }, - {"" ,0 } -}; - -static const struct pnp_id pnp_dev_table[] = { +static const struct pnp_device_id pnp_dev_table[] = {/* Archtek America Corp. */ /* Archtek SmartLink Modem 3334BT Plug & Play */ {"AAC000F" ,0 },
@@ -386,7 +381,7 @@ }static int -serial_pnp_probe (struct pnp_dev * dev,const struct pnp_id *card_id,const struct pnp_id *dev_id) +serial_pnp_probe (struct pnp_dev * dev,const struct pnp_device_id *dev_id) {struct serial_struct serial_req;int ret, line, flags = dev_id->driver_data;
@@ -421,7 +416,6 @@static struct pnp_driver serial_pnp_driver = { .name ="serial" , - .card_id_table = pnp_card_table, .id_table = pnp_dev_table, .probe = serial_pnp_probe, .remove = serial_pnp_remove,
include/linux/pnp.h +125 -33
275 lines not on this page · raw message
sound/isa/opl3sa2.c +52 -79
237 lines not on this page · raw message
sound/oss/opl3sa2.c +1 -3
@@ -843,8 +843,7 @@MODULE_DEVICE_TABLE (pnp, pnp_opl3sa2_list); -static int opl3sa2_pnp_probe (struct pnp_dev *dev,const struct pnp_id *card_id, -const struct pnp_id *dev_id) +static int opl3sa2_pnp_probe (struct pnp_dev *dev,const struct pnp_id *dev_id) {int card = opl3sa2_cards_num;if (opl3sa2_cards_num ==OPL3SA2_CARDS_MAX )
@@ -883,7 +882,6 @@static struct pnp_driver opl3sa2_driver = { .name ="opl3sa2" , - .card_id_table =NULL , .id_table = pnp_opl3sa2_list, .probe = opl3sa2_pnp_probe, };
Quoted 3 lines
This patch should apply against 2.5.50 as well, considering only a couple pnp changes were made by Alan. If it doesn't, please let me know.
Actually that's not entirely correct. It will apply against the latest pnp bk tree at bk://linuxusb.bkbits.net/pnp-2.5. This is because the last set of pnp changes have not yet been included in the main tree.
Thanks,
Adam