@@ -783,6 +783,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
783783 unsigned long tmp ;
784784 int ret = 0 ;
785785
786+ if (t -> rdata )
787+ memset (t -> rdata , 0 , t -> rlen );
788+
786789 /* start transaction */
787790 spin_lock_irqsave (& ec -> lock , tmp );
788791 /* Enable GPE for command processing (IBF=0/OBF=1) */
@@ -819,8 +822,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
819822
820823 if (!ec || (!t ) || (t -> wlen && !t -> wdata ) || (t -> rlen && !t -> rdata ))
821824 return - EINVAL ;
822- if (t -> rdata )
823- memset (t -> rdata , 0 , t -> rlen );
824825
825826 mutex_lock (& ec -> mutex );
826827 if (ec -> global_lock ) {
@@ -847,7 +848,7 @@ static int acpi_ec_burst_enable(struct acpi_ec *ec)
847848 .wdata = NULL , .rdata = & d ,
848849 .wlen = 0 , .rlen = 1 };
849850
850- return acpi_ec_transaction (ec , & t );
851+ return acpi_ec_transaction_unlocked (ec , & t );
851852}
852853
853854static int acpi_ec_burst_disable (struct acpi_ec * ec )
@@ -857,7 +858,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec)
857858 .wlen = 0 , .rlen = 0 };
858859
859860 return (acpi_ec_read_status (ec ) & ACPI_EC_FLAG_BURST ) ?
860- acpi_ec_transaction (ec , & t ) : 0 ;
861+ acpi_ec_transaction_unlocked (ec , & t ) : 0 ;
861862}
862863
863864static int acpi_ec_read (struct acpi_ec * ec , u8 address , u8 * data )
@@ -873,6 +874,19 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
873874 return result ;
874875}
875876
877+ static int acpi_ec_read_unlocked (struct acpi_ec * ec , u8 address , u8 * data )
878+ {
879+ int result ;
880+ u8 d ;
881+ struct transaction t = {.command = ACPI_EC_COMMAND_READ ,
882+ .wdata = & address , .rdata = & d ,
883+ .wlen = 1 , .rlen = 1 };
884+
885+ result = acpi_ec_transaction_unlocked (ec , & t );
886+ * data = d ;
887+ return result ;
888+ }
889+
876890static int acpi_ec_write (struct acpi_ec * ec , u8 address , u8 data )
877891{
878892 u8 wdata [2 ] = { address , data };
@@ -883,6 +897,16 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
883897 return acpi_ec_transaction (ec , & t );
884898}
885899
900+ static int acpi_ec_write_unlocked (struct acpi_ec * ec , u8 address , u8 data )
901+ {
902+ u8 wdata [2 ] = { address , data };
903+ struct transaction t = {.command = ACPI_EC_COMMAND_WRITE ,
904+ .wdata = wdata , .rdata = NULL ,
905+ .wlen = 2 , .rlen = 0 };
906+
907+ return acpi_ec_transaction_unlocked (ec , & t );
908+ }
909+
886910int ec_read (u8 addr , u8 * val )
887911{
888912 int err ;
@@ -1323,27 +1347,46 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
13231347 struct acpi_ec * ec = handler_context ;
13241348 int result = 0 , i , bytes = bits / 8 ;
13251349 u8 * value = (u8 * )value64 ;
1350+ u32 glk ;
13261351
13271352 if ((address > 0xFF ) || !value || !handler_context )
13281353 return AE_BAD_PARAMETER ;
13291354
13301355 if (function != ACPI_READ && function != ACPI_WRITE )
13311356 return AE_BAD_PARAMETER ;
13321357
1358+ mutex_lock (& ec -> mutex );
1359+
1360+ if (ec -> global_lock ) {
1361+ acpi_status status ;
1362+
1363+ status = acpi_acquire_global_lock (ACPI_EC_UDELAY_GLK , & glk );
1364+ if (ACPI_FAILURE (status )) {
1365+ result = - ENODEV ;
1366+ goto unlock ;
1367+ }
1368+ }
1369+
13331370 if (ec -> busy_polling || bits > 8 )
13341371 acpi_ec_burst_enable (ec );
13351372
13361373 for (i = 0 ; i < bytes ; ++ i , ++ address , ++ value ) {
13371374 result = (function == ACPI_READ ) ?
1338- acpi_ec_read (ec , address , value ) :
1339- acpi_ec_write (ec , address , * value );
1375+ acpi_ec_read_unlocked (ec , address , value ) :
1376+ acpi_ec_write_unlocked (ec , address , * value );
13401377 if (result < 0 )
13411378 break ;
13421379 }
13431380
13441381 if (ec -> busy_polling || bits > 8 )
13451382 acpi_ec_burst_disable (ec );
13461383
1384+ if (ec -> global_lock )
1385+ acpi_release_global_lock (glk );
1386+
1387+ unlock :
1388+ mutex_unlock (& ec -> mutex );
1389+
13471390 switch (result ) {
13481391 case - EINVAL :
13491392 return AE_BAD_PARAMETER ;
0 commit comments