@ -35,7 +35,6 @@
unsigned long hpet_address ;
u8 hpet_blockid ; /* OS timer block num */
u8 hpet_msi_disable ;
u8 hpet_readback_cmp ;
# ifdef CONFIG_PCI_MSI
static unsigned long hpet_num_timers ;
@ -395,23 +394,27 @@ static int hpet_next_event(unsigned long delta,
* at that point and we would wait for the next hpet interrupt
* forever . We found out that reading the CMP register back
* forces the transfer so we can rely on the comparison with
* the counter register below .
* the counter register below . If the read back from the
* compare register does not match the value we programmed
* then we might have a real hardware problem . We can not do
* much about it here , but at least alert the user / admin with
* a prominent warning .
*
* That works fine on those ATI chipsets , but on newer Intel
* chipsets ( ICH9 . . . ) this triggers due to an erratum : Reading
* the comparator immediately following a write is returning
* the old value .
* An erratum on some chipsets ( ICH9 , . . ) , results in
* comparator read immediately following a write returning old
* value . Workaround for this is to read this value second
* time , w hen first read returns old value .
*
* We restrict the read back to the affected ATI chipsets ( set
* by quirks ) and also run it with hpet = verbose for debugging
* purposes .
* In fact the write to the comparator register is delayed up
* to two HPET cycles so the workaround we tried to restrict
* the readback to those known to be borked ATI chipsets
* failed miserably . So we give up on optimizations forever
* and penalize all HPET incarnations unconditionally .
*/
if ( hpet_readback_cmp | | hpet_verbose ) {
u32 cmp = hpet_readl ( HPET_Tn_CMP ( timer ) ) ;
if ( cmp ! = cnt )
if ( unlikely ( ( u32 ) hpet_readl ( HPET_Tn_CMP ( timer ) ) ! = cnt ) ) {
if ( hpet_readl ( HPET_Tn_CMP ( timer ) ) ! = cnt )
printk_once ( KERN_WARNING
" hpet: compare register read back failed. \n " ) ;
" hpet: compare register read back failed. \n " ) ;
}
return ( s32 ) ( hpet_readl ( HPET_COUNTER ) - cnt ) > = 0 ? - ETIME : 0 ;