PnP BIOS driver status
A couple people have asked me about the status of the PnP BIOS driver, so I thought I'd post an update.
History: During the pre-Tosatti 2.4-ac series the driver was hammered into a reliable form. However it never entered the mainline kernel series.
The driver was then stripped down to the core functionality required to make the lspnp and setpnp utilities work. pnpbios_register_driver() and pnpbios_unregister_driver() are still there but aren't used by anything. Additional /proc/ interface files were then added to allow reading of ESCD info.
The latest version of the driver seems nice 'n' stable and can be found in Alan's latest 2.4 patches.
Current 2.5 kernels also contain the driver, but it's a bit out of date. There's a patch in 2.5-dj but that's also out of date. ("Out of date" here means "missing new features and some cleanups".) Once DJ releases a 2.5.6-dj I'll send him a patch to bring his tree up to date. Then he can pass it on to Linus.
Signature · 1 line
Thomas Hood
Quoted 4 lines · Thomas Hood
Current 2.5 kernels also contain the driver, but it's a bit out of date. There's a patch in 2.5-dj but that's also out of date. ("Out of date" here means "missing new features and some cleanups".)
The bits that handle ESCD ? I merged that.
Quoted 2 lines
Once DJ releases a 2.5.6-dj I'll send him a patch
to bring his tree up to date. Then he can pass it on to Linus.
You may have to wait a while. Most of my life just got packed into boxes, and is about to go out the door to a new home. It'll take a week or so to get back on my feet.
Signature · 2 lines
| Dave Jones. http://www.codemonkey.org.uk | SuSE Labs
Quoted 1 line · Dave Jones
The bits that handle ESCD ? I merged that.
Here are the additional bits from the -ac tree, diffed against 2.5.6 + 2.5.5-dj3 patch. The changes include:
- Improve some comments
- Postpone starting the kernel thread (Alan Cox)
- Call kernel thread 'kpnpbiosd' instead of 'kpnpbios'
- Consolidate printing of error messages to save space
- Add __init and __exit tags and return appropriate error codes
- Print slightly more consistent messages
- Get closer to supporting build-as-module
--
Thomas
include/linux/pnpbios.h renamed from include/linux/pnpbios.h_DJ +2 -1
@@ -143,7 +143,8 @@extern int pnpbios_dont_use_current_config;extern void *pnpbios_kmalloc (size_t size,int f);extern int pnpbios_init (void ); -extern void pnpbios_proc_init (void ); +extern int pnpbios_proc_init (void ); +extern void pnpbios_proc_exit (void );extern int pnp_bios_dev_node_info (struct pnp_dev_node_info *data);extern int pnp_bios_get_dev_node (u8 *nodenum,char config,struct pnp_bios_node *data);
drivers/pnp/pnpbios_core.c renamed from drivers/pnp/pnpbios_core.c_DJ +78 -41
326 lines not on this page · raw message
drivers/pnp/pnpbios_proc.c renamed from drivers/pnp/pnpbios_proc.c_DJ +37 -11
101 lines not on this page · raw message
Quoted 14 lines · Thomas Hood
A couple people have asked me about the status of the PnP BIOS driver, so I thought I'd post an update.
History: During the pre-Tosatti 2.4-ac series the driver was hammered into a reliable form. However it never entered the mainline kernel series.
The driver was then stripped down to the core functionality required to make the lspnp and setpnp utilities work.
pnpbios_register_driver()andpnpbios_unregister_driver()are still there but aren't used by anything. Additional/proc/interface files were then added to allow reading of ESCD info.
Quoted 8 lines
The latest version of the driver seems nice 'n' stable and can be found in Alan's latest 2.4 patches.
Current 2.5 kernels also contain the driver, but it's a bit out of date. There's a patch in 2.5-dj but that's also out of date. ("Out of date" here means "missing new features and some cleanups".) Once DJ releases a 2.5.6-dj I'll send him a patch to bring his tree up to date. Then he can pass it on to Linus.
The current driver is not SMP-safe. It is modifying the GDT descriptors outside of the pnp_bios_lock. Also, you can remove the __cli(), as spin_lock_irq() already turns off interrupts.
Signature · 1 line
Brian Gerst
Quoted 1 line · Brian Gerst
The current driver is not SMP-safe.
That's true.
Quoted 3 lines
It is modifying the GDT descriptors
outside of thepnp_bios_lock. Also, you can remove the__cli(), asspin_lock_irq()already turns off interrupts.
I'd welcome a patch like the return of a kidnapped pet.
--
Thomas
Quoted 3 lines
The current driver is not SMP-safe. It is modifying the GDT descriptors outside of the
pnp_bios_lock. Also, you can remove the__cli(), asspin_lock_irq()already turns off interrupts.
The GDT descriptors are private to the PNP BIOS and constant values once set up. No PnPBIOS call is made before the configuration is done.
Seems ok to me - or am I missing something ?
Quoted 9 lines · Alan Cox
Quoted 4 lines
The current driver is not SMP-safe. It is modifying the GDT descriptors outside of the
pnp_bios_lock. Also, you can remove the__cli(), asspin_lock_irq()already turns off interrupts.The GDT descriptors are private to the PNP BIOS and constant values once set up. No PnPBIOS call is made before the configuration is done.
Seems ok to me - or am I missing something ?
Two user processes calling functions through /proc...
Signature · 1 line
Brian Gerst
Quoted 6 lines
Quoted 4 lines
The GDT descriptors are private to the PNP BIOS and constant values once set up. No PnPBIOS call is made before the configuration is done.
Seems ok to me - or am I missing something ?
Two user processes calling functions through /proc...
The GDT descriptors are set up before /proc comes into being. I'm checking 2.4 code here - has someone left old stuff in 2.5 ?
Quoted 10 lines · Alan Cox
Quoted 7 lines
Quoted 5 lines
The GDT descriptors are private to the PNP BIOS and constant values once set up. No PnPBIOS call is made before the configuration is done.
Seems ok to me - or am I missing something ?
Two user processes calling functions through /proc...
The GDT descriptors are set up before /proc comes into being. I'm checking 2.4 code here - has someone left old stuff in 2.5 ?
PNP_TS1 and PNP_TS2 are changed on every call to the bios to point to where the data for the 32-bit code lives.
Signature · 1 line
Brian Gerst
Quoted 5 lines
Quoted 2 lines
The GDT descriptors are set up before /proc comes into being. I'm checking 2.4 code here - has someone left old stuff in 2.5 ?
PNP_TS1andPNP_TS2are changed on every call to the bios to point to where the data for the 32-bit code lives.
Got you - yes Thomas he's absolutely right. The lock needs to be taken by the callers before they set the PNP_TS* entries.
Quoted 2 lines · Alan Cox
Got you - yes Thomas he's absolutely right. The lock needs to be taken by the callers before they set the PNP_TS* entries.
Yep. I'll submit a patch to Alan and update the one I just posted for DJ.
--
Thomas
Here the patch for Alan (which also includes the
kpnpbios -> kpnpbiosd change):
drivers/pnp/pnpbios_core.c renamed from drivers/pnp/pnpbios_core.c_ORIG +48 -7
@@ -139,10 +139,16 @@static spinlock_t pnp_bios_lock; +/* +* call_pnp_bios +* +* Call with the pnp_bios_lock held and with irqs disabled. +* On some boxes IRQ's during PnP BIOS calls are deadly. +*/ +static inline u16 call_pnp_bios (u16 func,u16 arg1,u16 arg2,u16 arg3,u16 arg4,u16 arg5,u16 arg6,u16 arg7) { -unsigned long flags;u16 status;/*
@@ -152,9 +158,6 @@if (pnp_bios_is_utter_crap)return PNP_FUNCTION_NOT_SUPPORTED ; -/* On some boxes IRQ's during PnP BIOS calls are deadly. */ -spin_lock_irqsave (&pnp_bios_lock, flags); -__cli (); __asm__ __volatile__("pushl %%ebp\n\t" "pushl %%edi\n\t"
@@ -184,7 +187,6 @@ "i" (0) : "memory" ); -spin_unlock_irqrestore (&pnp_bios_lock, flags);/* If we get here and this is set then the PnP BIOS faulted on us. */ if (pnp_bios_is_utter_crap)
@@ -220,7 +222,7 @@/* * Call this only after init time */ -static int pnp_bios_present (void ) +static inline int pnp_bios_present (void ) {return (pnp_bios_hdr !=NULL ); }
@@ -254,11 +256,14 @@*/ static int __pnp_bios_dev_node_info (struct pnp_dev_node_info *data) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags);Q2_SET_SEL (PNP_TS1 , data,sizeof (struct pnp_dev_node_info )); status =call_pnp_bios (PNP_GET_NUM_SYS_DEV_NODES ,0 ,PNP_TS1 ,2 ,PNP_TS1 ,PNP_DS ,0 ,0 ); +spin_unlock_irqrestore (&pnp_bios_lock, flags); data->no_nodes &=0xff ;return status; }
@@ -287,14 +292,17 @@*/ static int __pnp_bios_get_dev_node (u8 *nodenum,char boot,struct pnp_bios_node *data) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ;if ( !boot & pnpbios_dont_use_current_config )return PNP_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags);Q2_SET_SEL (PNP_TS1 , nodenum,sizeof (char ));Q2_SET_SEL (PNP_TS2 , data,64 *1024 ); status =call_pnp_bios (PNP_GET_SYS_DEV_NODE ,0 ,PNP_TS1 ,0 ,PNP_TS2 , boot ?2 :1 ,PNP_DS ,0 ); +spin_unlock_irqrestore (&pnp_bios_lock, flags);return status; }
@@ -316,13 +324,16 @@*/ static int __pnp_bios_set_dev_node (u8 nodenum,char boot,struct pnp_bios_node *data) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ;if ( !boot & pnpbios_dont_use_current_config )return PNP_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags);Q2_SET_SEL (PNP_TS1 , data,/* *((u16 *) data)*/ 65536 ); status =call_pnp_bios (PNP_SET_SYS_DEV_NODE , nodenum,0 ,PNP_TS1 , boot ?2 :1 ,PNP_DS ,0 ,0 ); +spin_unlock_irqrestore (&pnp_bios_lock, flags);return status; }
@@ -350,11 +361,14 @@*/ static int pnp_bios_get_event (u16 *event) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags);Q2_SET_SEL (PNP_TS1 , event,sizeof (u16)); status =call_pnp_bios (PNP_GET_EVENT ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); +spin_unlock_irqrestore (&pnp_bios_lock, flags);return status; }#endif
@@ -365,10 +379,13 @@*/ static int pnp_bios_send_message (u16 message) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags); status =call_pnp_bios (PNP_SEND_MESSAGE , message,PNP_DS ,0 ,0 ,0 ,0 ,0 ); +spin_unlock_irqrestore (&pnp_bios_lock, flags);return status; }#endif
@@ -379,11 +396,14 @@*/ static int pnp_bios_dock_station_info (struct pnp_docking_station_info *data) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags);Q2_SET_SEL (PNP_TS1 , data,sizeof (struct pnp_docking_station_info )); status =call_pnp_bios (PNP_GET_DOCKING_STATION_INFORMATION ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); +spin_unlock_irqrestore (&pnp_bios_lock, flags);return status; }#endif
@@ -395,11 +415,14 @@*/ static int pnp_bios_set_stat_res (char *info) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags);Q2_SET_SEL (PNP_TS1 , info, *((u16 *) info)); status =call_pnp_bios (PNP_SET_STATIC_ALLOCED_RES_INFO ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); +spin_unlock_irqrestore (&pnp_bios_lock, flags);return status; }#endif
@@ -410,11 +433,14 @@*/ static int __pnp_bios_get_stat_res (char *info) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags);Q2_SET_SEL (PNP_TS1 , info,64 *1024 ); status =call_pnp_bios (PNP_GET_STATIC_ALLOCED_RES_INFO ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); +spin_unlock_irqrestore (&pnp_bios_lock, flags);return status; }
@@ -433,12 +459,15 @@*/ static int pnp_bios_apm_id_table (char *table,u16 *size) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags);Q2_SET_SEL (PNP_TS1 , table, *size);Q2_SET_SEL (PNP_TS2 , size,sizeof (u16)); status =call_pnp_bios (PNP_GET_APM_ID_TABLE ,0 ,PNP_TS2 ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ); +spin_unlock_irqrestore (&pnp_bios_lock, flags);return status; }#endif
@@ -448,11 +477,14 @@*/ static int __pnp_bios_isapnp_config (struct pnp_isa_config_struc *data) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags);Q2_SET_SEL (PNP_TS1 , data,sizeof (struct pnp_isa_config_struc )); status =call_pnp_bios (PNP_GET_PNP_ISA_CONFIG_STRUC ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); +spin_unlock_irqrestore (&pnp_bios_lock, flags);return status; }
@@ -470,11 +502,14 @@*/ static int __pnp_bios_escd_info (struct escd_info_struc *data) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return ESCD_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags);Q2_SET_SEL (PNP_TS1 , data,sizeof (struct escd_info_struc )); status =call_pnp_bios (PNP_GET_ESCD_INFO ,0 ,PNP_TS1 ,2 ,PNP_TS1 ,4 ,PNP_TS1 ,PNP_DS ); +spin_unlock_irqrestore (&pnp_bios_lock, flags);return status; }
@@ -493,13 +528,16 @@*/ static int __pnp_bios_read_escd (char *data,u32 nvram_base) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return ESCD_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags);Q2_SET_SEL (PNP_TS1 , data,64 *1024 );set_base (gdt[PNP_TS2 >>3 ], nvram_base);set_limit (gdt[PNP_TS2 >>3 ],64 *1024 ); status =call_pnp_bios (PNP_READ_ESCD ,0 ,PNP_TS1 ,PNP_TS2 ,PNP_DS ,0 ,0 ,0 ); +spin_unlock_irqrestore (&pnp_bios_lock, flags);return status; }
@@ -518,13 +556,16 @@*/ static int pnp_bios_write_escd (char *data,u32 nvram_base) { +unsigned long flags;u16 status;if (!pnp_bios_present ())return ESCD_FUNCTION_NOT_SUPPORTED ; +spin_lock_irqsave (&pnp_bios_lock, flags);Q2_SET_SEL (PNP_TS1 , data,64 *1024 );set_base (gdt[PNP_TS2 >>3 ], nvram_base);set_limit (gdt[PNP_TS2 >>3 ],64 *1024 ); status =call_pnp_bios (PNP_WRITE_ESCD ,0 ,PNP_TS1 ,PNP_TS2 ,PNP_DS ,0 ,0 ,0 ); +spin_unlock_irqrestore (&pnp_bios_lock, flags);return status; }#endif
@@ -606,7 +647,7 @@int docked =-1 , d =0 ;daemonize ();reparent_to_init (); -strcpy (current->comm,"kpnpbios" ); +strcpy (current->comm,"kpnpbiosd" );while (!unloading && !signal_pending (current)) {int status;
Alan: I just tried to apply Brian's patch and noticed that it was against 2.5.6. Here is his patch versus 2.4.19-pre2-ac3 with the kpnpbios -> kpnpbiosd change added in.
// Thomas
drivers/pnp/pnpbios_core.c renamed from drivers/pnp/pnpbios_core.c_ORIG +36 -35
@@ -140,7 +140,9 @@static spinlock_t pnp_bios_lock;static inline u16 call_pnp_bios (u16 func,u16 arg1,u16 arg2,u16 arg3, -u16 arg4,u16 arg5,u16 arg6,u16 arg7) +u16 arg4,u16 arg5,u16 arg6,u16 arg7, +void *ts1_base,u32 ts1_size, +void *ts2_base,u32 ts2_size) {unsigned long flags;u16 status;
@@ -154,7 +156,12 @@/* On some boxes IRQ's during PnP BIOS calls are deadly. */ spin_lock_irqsave (&pnp_bios_lock, flags); -__cli (); + +if (ts1_size) +Q2_SET_SEL (PNP_TS1 , ts1_base, ts1_size); +if (ts2_size) +Q2_SET_SEL (PNP_TS2 , ts2_base, ts2_size); + __asm__ __volatile__("pushl %%ebp\n\t" "pushl %%edi\n\t"
@@ -220,7 +227,7 @@/* * Call this only after init time */ -static int pnp_bios_present (void ) +static inline int pnp_bios_present (void ) {return (pnp_bios_hdr !=NULL ); }
@@ -257,8 +264,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,sizeof (struct pnp_dev_node_info )); - status =call_pnp_bios (PNP_GET_NUM_SYS_DEV_NODES ,0 ,PNP_TS1 ,2 ,PNP_TS1 ,PNP_DS ,0 ,0 ); + status =call_pnp_bios (PNP_GET_NUM_SYS_DEV_NODES ,0 ,PNP_TS1 ,2 ,PNP_TS1 ,PNP_DS ,0 ,0 , + data,sizeof (struct pnp_dev_node_info ),0 ,0 ); data->no_nodes &=0xff ;return status; }
@@ -292,9 +299,8 @@return PNP_FUNCTION_NOT_SUPPORTED ;if ( !boot & pnpbios_dont_use_current_config )return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , nodenum,sizeof (char )); -Q2_SET_SEL (PNP_TS2 , data,64 *1024 ); - status =call_pnp_bios (PNP_GET_SYS_DEV_NODE ,0 ,PNP_TS1 ,0 ,PNP_TS2 , boot ?2 :1 ,PNP_DS ,0 ); + status =call_pnp_bios (PNP_GET_SYS_DEV_NODE ,0 ,PNP_TS1 ,0 ,PNP_TS2 , boot ?2 :1 ,PNP_DS ,0 , + nodenum,sizeof (char ), data,65536 );return status; }
@@ -321,8 +327,8 @@return PNP_FUNCTION_NOT_SUPPORTED ;if ( !boot & pnpbios_dont_use_current_config )return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,/* *((u16 *) data)*/ 65536 ); - status =call_pnp_bios (PNP_SET_SYS_DEV_NODE , nodenum,0 ,PNP_TS1 , boot ?2 :1 ,PNP_DS ,0 ,0 ); + status =call_pnp_bios (PNP_SET_SYS_DEV_NODE , nodenum,0 ,PNP_TS1 , boot ?2 :1 ,PNP_DS ,0 ,0 , + data,65536 ,0 ,0 );return status; }
@@ -353,8 +359,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , event,sizeof (u16)); - status =call_pnp_bios (PNP_GET_EVENT ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_GET_EVENT ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 , + event,sizeof (u16),0 ,0 ); return status; }#endif
@@ -368,7 +374,7 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; - status =call_pnp_bios (PNP_SEND_MESSAGE , message,PNP_DS ,0 ,0 ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_SEND_MESSAGE , message,PNP_DS ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ); return status; }#endif
@@ -382,8 +388,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,sizeof (struct pnp_docking_station_info )); - status =call_pnp_bios (PNP_GET_DOCKING_STATION_INFORMATION ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_GET_DOCKING_STATION_INFORMATION ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 , + data,sizeof (struct pnp_docking_station_info ),0 ,0 ); return status; }#endif
@@ -398,8 +404,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , info, *((u16 *) info)); - status =call_pnp_bios (PNP_SET_STATIC_ALLOCED_RES_INFO ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_SET_STATIC_ALLOCED_RES_INFO ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 , + info, *((u16 *) info),0 ,0 ); return status; }#endif
@@ -413,8 +419,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , info,64 *1024 ); - status =call_pnp_bios (PNP_GET_STATIC_ALLOCED_RES_INFO ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_GET_STATIC_ALLOCED_RES_INFO ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 , + info,65536 ,0 ,0 );return status; }
@@ -436,9 +442,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , table, *size); -Q2_SET_SEL (PNP_TS2 , size,sizeof (u16)); - status =call_pnp_bios (PNP_GET_APM_ID_TABLE ,0 ,PNP_TS2 ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ); + status =call_pnp_bios (PNP_GET_APM_ID_TABLE ,0 ,PNP_TS2 ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 , + table, *size, size,sizeof (u16)); return status; }#endif
@@ -451,8 +456,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,sizeof (struct pnp_isa_config_struc )); - status =call_pnp_bios (PNP_GET_PNP_ISA_CONFIG_STRUC ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_GET_PNP_ISA_CONFIG_STRUC ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 , + data,sizeof (struct pnp_isa_config_struc ),0 ,0 );return status; }
@@ -473,8 +478,8 @@u16 status;if (!pnp_bios_present ())return ESCD_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,sizeof (struct escd_info_struc )); - status =call_pnp_bios (PNP_GET_ESCD_INFO ,0 ,PNP_TS1 ,2 ,PNP_TS1 ,4 ,PNP_TS1 ,PNP_DS ); + status =call_pnp_bios (PNP_GET_ESCD_INFO ,0 ,PNP_TS1 ,2 ,PNP_TS1 ,4 ,PNP_TS1 ,PNP_DS , + data,sizeof (struct escd_info_struc ),0 ,0 );return status; }
@@ -496,10 +501,8 @@u16 status;if (!pnp_bios_present ())return ESCD_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,64 *1024 ); -set_base (gdt[PNP_TS2 >>3 ], nvram_base); -set_limit (gdt[PNP_TS2 >>3 ],64 *1024 ); - status =call_pnp_bios (PNP_READ_ESCD ,0 ,PNP_TS1 ,PNP_TS2 ,PNP_DS ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_READ_ESCD ,0 ,PNP_TS1 ,PNP_TS2 ,PNP_DS ,0 ,0 ,0 , + data,65536 , nvram_base,65536 );return status; }
@@ -521,10 +524,8 @@u16 status;if (!pnp_bios_present ())return ESCD_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,64 *1024 ); -set_base (gdt[PNP_TS2 >>3 ], nvram_base); -set_limit (gdt[PNP_TS2 >>3 ],64 *1024 ); - status =call_pnp_bios (PNP_WRITE_ESCD ,0 ,PNP_TS1 ,PNP_TS2 ,PNP_DS ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_WRITE_ESCD ,0 ,PNP_TS1 ,PNP_TS2 ,PNP_DS ,0 ,0 ,0 , + data,65536 , nvram_base,65536 ); return status; }#endif
@@ -606,7 +607,7 @@int docked =-1 , d =0 ;daemonize ();reparent_to_init (); -strcpy (current->comm,"kpnpbios" ); +strcpy (current->comm,"kpnpbiosd" );while (!unloading && !signal_pending (current)) {int status;
Quoted 11 lines · Thomas Hood
Quoted 1 line · Brian Gerst
The current driver is not SMP-safe.
That's true.
Quoted 3 lines
It is modifying the GDT descriptors
outside of thepnp_bios_lock. Also, you can remove the__cli(), asspin_lock_irq()already turns off interrupts.I'd welcome a patch like the return of a kidnapped pet.
How does this patch look? Against 2.5.6
Signature · 1 line
Brian Gerst
drivers/pnp/pnpbios_core.c +34 -33
@@ -141,7 +141,9 @@static spinlock_t pnp_bios_lock;static inline u16 call_pnp_bios (u16 func,u16 arg1,u16 arg2,u16 arg3, -u16 arg4,u16 arg5,u16 arg6,u16 arg7) +u16 arg4,u16 arg5,u16 arg6,u16 arg7, +void *ts1_base,u32 ts1_size, +void *ts2_base,u32 ts2_size) {unsigned long flags;u16 status;
@@ -155,7 +157,12 @@/* On some boxes IRQ's during PnP BIOS calls are deadly. */ spin_lock_irqsave (&pnp_bios_lock, flags); -__cli (); + +if (ts1_size) +Q2_SET_SEL (PNP_TS1 , ts1_base, ts1_size); +if (ts2_size) +Q2_SET_SEL (PNP_TS2 , ts2_base, ts2_size); + __asm__ __volatile__("pushl %%ebp\n\t" "pushl %%edi\n\t"
@@ -253,8 +260,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,sizeof (struct pnp_dev_node_info )); - status =call_pnp_bios (PNP_GET_NUM_SYS_DEV_NODES ,0 ,PNP_TS1 ,2 ,PNP_TS1 ,PNP_DS ,0 ,0 ); + status =call_pnp_bios (PNP_GET_NUM_SYS_DEV_NODES ,0 ,PNP_TS1 ,2 ,PNP_TS1 ,PNP_DS ,0 ,0 , + data,sizeof (struct pnp_dev_node_info ),0 ,0 ); data->no_nodes &=0xff ;return status; }
@@ -288,9 +295,8 @@return PNP_FUNCTION_NOT_SUPPORTED ;if ( !boot & pnpbios_dont_use_current_config )return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , nodenum,sizeof (char )); -Q2_SET_SEL (PNP_TS2 , data,64 *1024 ); - status =call_pnp_bios (PNP_GET_SYS_DEV_NODE ,0 ,PNP_TS1 ,0 ,PNP_TS2 , boot ?2 :1 ,PNP_DS ,0 ); + status =call_pnp_bios (PNP_GET_SYS_DEV_NODE ,0 ,PNP_TS1 ,0 ,PNP_TS2 , boot ?2 :1 ,PNP_DS ,0 , + nodenum,sizeof (char ), data,65536 );return status; }
@@ -317,8 +323,8 @@return PNP_FUNCTION_NOT_SUPPORTED ;if ( !boot & pnpbios_dont_use_current_config )return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,/* *((u16 *) data)*/ 65536 ); - status =call_pnp_bios (PNP_SET_SYS_DEV_NODE , nodenum,0 ,PNP_TS1 , boot ?2 :1 ,PNP_DS ,0 ,0 ); + status =call_pnp_bios (PNP_SET_SYS_DEV_NODE , nodenum,0 ,PNP_TS1 , boot ?2 :1 ,PNP_DS ,0 ,0 , + data,65536 ,0 ,0 );return status; }
@@ -352,8 +358,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , event,sizeof (u16)); - status =call_pnp_bios (PNP_GET_EVENT ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_GET_EVENT ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 , + event,sizeof (u16),0 ,0 ); return status; }#endif
@@ -367,7 +373,7 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; - status =call_pnp_bios (PNP_SEND_MESSAGE , message,PNP_DS ,0 ,0 ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_SEND_MESSAGE , message,PNP_DS ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ); return status; }#endif
@@ -381,8 +387,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,sizeof (struct pnp_docking_station_info )); - status =call_pnp_bios (PNP_GET_DOCKING_STATION_INFORMATION ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_GET_DOCKING_STATION_INFORMATION ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 , + data,sizeof (struct pnp_docking_station_info ),0 ,0 ); return status; }#endif
@@ -397,8 +403,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , info, *((u16 *) info)); - status =call_pnp_bios (PNP_SET_STATIC_ALLOCED_RES_INFO ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_SET_STATIC_ALLOCED_RES_INFO ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 , + info, *((u16 *) info),0 ,0 ); return status; }#endif
@@ -413,8 +419,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , info,64 *1024 ); - status =call_pnp_bios (PNP_GET_STATIC_ALLOCED_RES_INFO ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_GET_STATIC_ALLOCED_RES_INFO ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 , + info,65536 ,0 ,0 ); return status; }#endif
@@ -428,9 +434,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , table, *size); -Q2_SET_SEL (PNP_TS2 , size,sizeof (u16)); - status =call_pnp_bios (PNP_GET_APM_ID_TABLE ,0 ,PNP_TS2 ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ); + status =call_pnp_bios (PNP_GET_APM_ID_TABLE ,0 ,PNP_TS2 ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 , + table, *size, size,sizeof (u16)); return status; }#endif
@@ -444,8 +449,8 @@u16 status;if (!pnp_bios_present ())return PNP_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,sizeof (struct pnp_isa_config_struc )); - status =call_pnp_bios (PNP_GET_PNP_ISA_CONFIG_STRUC ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_GET_PNP_ISA_CONFIG_STRUC ,0 ,PNP_TS1 ,PNP_DS ,0 ,0 ,0 ,0 , + data,sizeof (struct pnp_isa_config_struc ),0 ,0 ); return status; }#endif
@@ -459,8 +464,8 @@u16 status;if (!pnp_bios_present ())return ESCD_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,sizeof (struct escd_info_struc )); - status =call_pnp_bios (PNP_GET_ESCD_INFO ,0 ,PNP_TS1 ,2 ,PNP_TS1 ,4 ,PNP_TS1 ,PNP_DS ); + status =call_pnp_bios (PNP_GET_ESCD_INFO ,0 ,PNP_TS1 ,2 ,PNP_TS1 ,4 ,PNP_TS1 ,PNP_DS , + data,sizeof (struct escd_info_struc ),0 ,0 ); return status; }#endif
@@ -475,10 +480,8 @@u16 status;if (!pnp_bios_present ())return ESCD_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,64 *1024 ); -set_base (gdt[PNP_TS2 >>3 ], nvram_base); -set_limit (gdt[PNP_TS2 >>3 ],64 *1024 ); - status =call_pnp_bios (PNP_READ_ESCD ,0 ,PNP_TS1 ,PNP_TS2 ,PNP_DS ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_READ_ESCD ,0 ,PNP_TS1 ,PNP_TS2 ,PNP_DS ,0 ,0 ,0 , + data,65536 , nvram_base,65536 ); return status; }#endif
@@ -492,10 +495,8 @@u16 status;if (!pnp_bios_present ())return ESCD_FUNCTION_NOT_SUPPORTED ; -Q2_SET_SEL (PNP_TS1 , data,64 *1024 ); -set_base (gdt[PNP_TS2 >>3 ], nvram_base); -set_limit (gdt[PNP_TS2 >>3 ],64 *1024 ); - status =call_pnp_bios (PNP_WRITE_ESCD ,0 ,PNP_TS1 ,PNP_TS2 ,PNP_DS ,0 ,0 ,0 ); + status =call_pnp_bios (PNP_WRITE_ESCD ,0 ,PNP_TS1 ,PNP_TS2 ,PNP_DS ,0 ,0 ,0 , + data,65536 , nvram_base,65536 ); return status; }#endif
Quoted 1 line · Brian Gerst
How does this patch look? Against 2.5.6
Better than mine.
Alan: I suggest applying Brian's patch plus the
change from 'kpnpbios' to 'kpnpbiosd'.
I'll integrate Brian's patch into my patch for David Jones's patch to 2.5.x ... tomorrow.