diff mbox

[1/6] ACPI/EC: Cleanup transaction wakeup code

Message ID 22c0b29810135db8762604f216ca8ea1c66fbdf0.1421234254.git.lv.zheng@intel.com (mailing list archive)
State Accepted, archived
Delegated to: Rafael Wysocki
Headers show

Commit Message

Lv Zheng Jan. 14, 2015, 11:28 a.m. UTC
This patch moves transaction wakeup code into advance_transaction().
No functional changes.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
 drivers/acpi/ec.c |   17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

Comments

Rafael J. Wysocki Jan. 21, 2015, 10:17 p.m. UTC | #1
On Wednesday, January 14, 2015 07:28:22 PM Lv Zheng wrote:
> This patch moves transaction wakeup code into advance_transaction().
> No functional changes.
> 
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> ---
>  drivers/acpi/ec.c |   17 +++++++++--------
>  1 file changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
> index 1b5853f..3e19123 100644
> --- a/drivers/acpi/ec.c
> +++ b/drivers/acpi/ec.c
> @@ -200,7 +200,7 @@ static int ec_transaction_completed(struct acpi_ec *ec)
>  	return ret;
>  }
>  
> -static bool advance_transaction(struct acpi_ec *ec)
> +static void advance_transaction(struct acpi_ec *ec)
>  {
>  	struct transaction *t;
>  	u8 status;
> @@ -235,7 +235,7 @@ static bool advance_transaction(struct acpi_ec *ec)
>  			t->flags |= ACPI_EC_COMMAND_COMPLETE;
>  			wakeup = true;
>  		}
> -		return wakeup;
> +		goto out;
>  	} else {
>  		if (EC_FLAGS_QUERY_HANDSHAKE &&
>  		    !(status & ACPI_EC_FLAG_SCI) &&
> @@ -251,7 +251,7 @@ static bool advance_transaction(struct acpi_ec *ec)
>  			t->flags |= ACPI_EC_COMMAND_POLL;
>  		} else
>  			goto err;
> -		return wakeup;
> +		goto out;
>  	}
>  err:
>  	/*
> @@ -262,14 +262,16 @@ err:
>  		if (in_interrupt() && t)
>  			++t->irq_count;
>  	}
> -	return wakeup;
> +out:
> +	if (wakeup && in_interrupt())
> +		wake_up(&ec->wait);
>  }
>  
>  static void start_transaction(struct acpi_ec *ec)
>  {
>  	ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0;
>  	ec->curr->flags = 0;
> -	(void)advance_transaction(ec);
> +	advance_transaction(ec);

Well, this looks like a functional change, because we wouldn't call
wake_up(&ec->wait) here before.

>  }
>  
>  static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data);
> @@ -304,7 +306,7 @@ static int ec_poll(struct acpi_ec *ec)
>  					return 0;
>  			}
>  			spin_lock_irqsave(&ec->lock, flags);
> -			(void)advance_transaction(ec);
> +			advance_transaction(ec);

Ditto.

Or am I missing anything?

>  			spin_unlock_irqrestore(&ec->lock, flags);
>  		} while (time_before(jiffies, delay));
>  		pr_debug("controller reset, restart transaction\n");
> @@ -688,8 +690,7 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
>  	struct acpi_ec *ec = data;
>  
>  	spin_lock_irqsave(&ec->lock, flags);
> -	if (advance_transaction(ec))
> -		wake_up(&ec->wait);
> +	advance_transaction(ec);
>  	spin_unlock_irqrestore(&ec->lock, flags);
>  	ec_check_sci(ec, acpi_ec_read_status(ec));
>  	return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
>
Lv Zheng Jan. 22, 2015, 6:37 a.m. UTC | #2
SGksIFJhZmFlbA0KDQo+IEZyb206IFJhZmFlbCBKLiBXeXNvY2tpIFttYWlsdG86cmp3QHJqd3lz
b2NraS5uZXRdDQo+IFNlbnQ6IFRodXJzZGF5LCBKYW51YXJ5IDIyLCAyMDE1IDY6MTcgQU0NCj4g
DQo+IE9uIFdlZG5lc2RheSwgSmFudWFyeSAxNCwgMjAxNSAwNzoyODoyMiBQTSBMdiBaaGVuZyB3
cm90ZToNCj4gPiBUaGlzIHBhdGNoIG1vdmVzIHRyYW5zYWN0aW9uIHdha2V1cCBjb2RlIGludG8g
YWR2YW5jZV90cmFuc2FjdGlvbigpLg0KPiA+IE5vIGZ1bmN0aW9uYWwgY2hhbmdlcy4NCj4gPg0K
PiA+IFNpZ25lZC1vZmYtYnk6IEx2IFpoZW5nIDxsdi56aGVuZ0BpbnRlbC5jb20+DQo+ID4gLS0t
DQo+ID4gIGRyaXZlcnMvYWNwaS9lYy5jIHwgICAxNyArKysrKysrKystLS0tLS0tLQ0KPiA+ICAx
IGZpbGUgY2hhbmdlZCwgOSBpbnNlcnRpb25zKCspLCA4IGRlbGV0aW9ucygtKQ0KPiA+DQo+ID4g
ZGlmZiAtLWdpdCBhL2RyaXZlcnMvYWNwaS9lYy5jIGIvZHJpdmVycy9hY3BpL2VjLmMNCj4gPiBp
bmRleCAxYjU4NTNmLi4zZTE5MTIzIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvYWNwaS9lYy5j
DQo+ID4gKysrIGIvZHJpdmVycy9hY3BpL2VjLmMNCj4gPiBAQCAtMjAwLDcgKzIwMCw3IEBAIHN0
YXRpYyBpbnQgZWNfdHJhbnNhY3Rpb25fY29tcGxldGVkKHN0cnVjdCBhY3BpX2VjICplYykNCj4g
PiAgCXJldHVybiByZXQ7DQo+ID4gIH0NCj4gPg0KPiA+IC1zdGF0aWMgYm9vbCBhZHZhbmNlX3Ry
YW5zYWN0aW9uKHN0cnVjdCBhY3BpX2VjICplYykNCj4gPiArc3RhdGljIHZvaWQgYWR2YW5jZV90
cmFuc2FjdGlvbihzdHJ1Y3QgYWNwaV9lYyAqZWMpDQo+ID4gIHsNCj4gPiAgCXN0cnVjdCB0cmFu
c2FjdGlvbiAqdDsNCj4gPiAgCXU4IHN0YXR1czsNCj4gPiBAQCAtMjM1LDcgKzIzNSw3IEBAIHN0
YXRpYyBib29sIGFkdmFuY2VfdHJhbnNhY3Rpb24oc3RydWN0IGFjcGlfZWMgKmVjKQ0KPiA+ICAJ
CQl0LT5mbGFncyB8PSBBQ1BJX0VDX0NPTU1BTkRfQ09NUExFVEU7DQo+ID4gIAkJCXdha2V1cCA9
IHRydWU7DQo+ID4gIAkJfQ0KPiA+IC0JCXJldHVybiB3YWtldXA7DQo+ID4gKwkJZ290byBvdXQ7
DQo+ID4gIAl9IGVsc2Ugew0KPiA+ICAJCWlmIChFQ19GTEFHU19RVUVSWV9IQU5EU0hBS0UgJiYN
Cj4gPiAgCQkgICAgIShzdGF0dXMgJiBBQ1BJX0VDX0ZMQUdfU0NJKSAmJg0KPiA+IEBAIC0yNTEs
NyArMjUxLDcgQEAgc3RhdGljIGJvb2wgYWR2YW5jZV90cmFuc2FjdGlvbihzdHJ1Y3QgYWNwaV9l
YyAqZWMpDQo+ID4gIAkJCXQtPmZsYWdzIHw9IEFDUElfRUNfQ09NTUFORF9QT0xMOw0KPiA+ICAJ
CX0gZWxzZQ0KPiA+ICAJCQlnb3RvIGVycjsNCj4gPiAtCQlyZXR1cm4gd2FrZXVwOw0KPiA+ICsJ
CWdvdG8gb3V0Ow0KPiA+ICAJfQ0KPiA+ICBlcnI6DQo+ID4gIAkvKg0KPiA+IEBAIC0yNjIsMTQg
KzI2MiwxNiBAQCBlcnI6DQo+ID4gIAkJaWYgKGluX2ludGVycnVwdCgpICYmIHQpDQo+ID4gIAkJ
CSsrdC0+aXJxX2NvdW50Ow0KPiA+ICAJfQ0KPiA+IC0JcmV0dXJuIHdha2V1cDsNCj4gPiArb3V0
Og0KPiA+ICsJaWYgKHdha2V1cCAmJiBpbl9pbnRlcnJ1cHQoKSkNCj4gPiArCQl3YWtlX3VwKCZl
Yy0+d2FpdCk7DQo+ID4gIH0NCj4gPg0KPiA+ICBzdGF0aWMgdm9pZCBzdGFydF90cmFuc2FjdGlv
bihzdHJ1Y3QgYWNwaV9lYyAqZWMpDQo+ID4gIHsNCj4gPiAgCWVjLT5jdXJyLT5pcnFfY291bnQg
PSBlYy0+Y3Vyci0+d2kgPSBlYy0+Y3Vyci0+cmkgPSAwOw0KPiA+ICAJZWMtPmN1cnItPmZsYWdz
ID0gMDsNCj4gPiAtCSh2b2lkKWFkdmFuY2VfdHJhbnNhY3Rpb24oZWMpOw0KPiA+ICsJYWR2YW5j
ZV90cmFuc2FjdGlvbihlYyk7DQo+IA0KPiBXZWxsLCB0aGlzIGxvb2tzIGxpa2UgYSBmdW5jdGlv
bmFsIGNoYW5nZSwgYmVjYXVzZSB3ZSB3b3VsZG4ndCBjYWxsDQo+IHdha2VfdXAoJmVjLT53YWl0
KSBoZXJlIGJlZm9yZS4NCg0KQWgsIFllcy4NCkJ1dCBoZXJlLCBzaW5jZSB0aGUgb25seSBhZHZh
bmNlbWVudCB0aGF0IGNhbiBoYXBwZW4gaGVyZSBpcyB0byBzZW5kIHRoZSBFQyBjb21tYW5kIGFu
ZCB0aGVyZSBhcmUgYWx3YXlzIGZ1cnRoZXIgYWR2YW5jZW1lbnRzIHVudGlsIHRyYW5zYWN0aW9u
IGNvbXBsZXRpb24sIHRoZSB3YWtlX3VwKCkgd29uJ3QgYmUgaW52b2tlZCBhdCB0aGlzIHBvaW50
Lg0KU28gSU1PLCB0aGVyZSBpcyBubyBmdW5jdGlvbmFsIGNoYW5nZXMgaGVyZS4NCg0KPiANCj4g
PiAgfQ0KPiA+DQo+ID4gIHN0YXRpYyBpbnQgYWNwaV9lY19zeW5jX3F1ZXJ5KHN0cnVjdCBhY3Bp
X2VjICplYywgdTggKmRhdGEpOw0KPiA+IEBAIC0zMDQsNyArMzA2LDcgQEAgc3RhdGljIGludCBl
Y19wb2xsKHN0cnVjdCBhY3BpX2VjICplYykNCj4gPiAgCQkJCQlyZXR1cm4gMDsNCj4gPiAgCQkJ
fQ0KPiA+ICAJCQlzcGluX2xvY2tfaXJxc2F2ZSgmZWMtPmxvY2ssIGZsYWdzKTsNCj4gPiAtCQkJ
KHZvaWQpYWR2YW5jZV90cmFuc2FjdGlvbihlYyk7DQo+ID4gKwkJCWFkdmFuY2VfdHJhbnNhY3Rp
b24oZWMpOw0KPiANCj4gRGl0dG8uDQoNClllcy4gSSBjaGFuZ2VkIHRoaXMgbG9naWMuDQoNCkJ5
IGludm9raW5nIHdha2VfdXAoKSBoZXJlLCB3ZSBjYW4gYnJlYWsgdGhlIGVjX3BvbGwoKSBsb29w
Lg0KQmVjYXVzZSBpZiB0aGUgdHJhbnNhY3Rpb24gaGFzIGNvbXBsZXRlZCBkdWUgdG8gdGhlIHBv
bGxpbmcgYWR2YW5jZW1lbnQsIHdlIHJlYWxseSBkb24ndCBuZWVkIHRvIHdhaXQgZm9yIGFub3Ro
ZXIgaW50ZXJydXB0Lg0KU28gdGhpcyBuZXcgbG9naWMgbWFrZXMgdGhpcyBwYXRjaCBtb3JlIGxp
a2UgYSByYWNlIGZpeCwgbm90IGEgc2ltcGxlIGNsZWFudXAuDQpBbmQgSU1PLCBpdCBtaWdodCBh
bHNvIGJlIGEgc3RhYmxlIG1hdGVyaWFsLg0KSSBkaWRuJ3Qgbm90aWNlIHRoaXMgcmFjZSBidWcg
YmVjYXVzZSB0aGVyZSBpcyBubyBidWcgcmVwb3J0IGFnYWluc3QgdGhpcy4NCg0KU2hvdWxkIEkg
Y2hhbmdlIHRoZSBkZXNjcmlwdGlvbiBhcm91bmQgdGhpcyBhbmQgcmUtc2VuZCB0aGUgcGF0Y2g/
DQoNClRoYW5rcyBhbmQgYmVzdCByZWdhcmRzDQotTHYNCg0KPiANCj4gT3IgYW0gSSBtaXNzaW5n
IGFueXRoaW5nPw0KPiANCj4gPiAgCQkJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmZWMtPmxvY2ss
IGZsYWdzKTsNCj4gPiAgCQl9IHdoaWxlICh0aW1lX2JlZm9yZShqaWZmaWVzLCBkZWxheSkpOw0K
PiA+ICAJCXByX2RlYnVnKCJjb250cm9sbGVyIHJlc2V0LCByZXN0YXJ0IHRyYW5zYWN0aW9uXG4i
KTsNCj4gPiBAQCAtNjg4LDggKzY5MCw3IEBAIHN0YXRpYyB1MzIgYWNwaV9lY19ncGVfaGFuZGxl
cihhY3BpX2hhbmRsZSBncGVfZGV2aWNlLA0KPiA+ICAJc3RydWN0IGFjcGlfZWMgKmVjID0gZGF0
YTsNCj4gPg0KPiA+ICAJc3Bpbl9sb2NrX2lycXNhdmUoJmVjLT5sb2NrLCBmbGFncyk7DQo+ID4g
LQlpZiAoYWR2YW5jZV90cmFuc2FjdGlvbihlYykpDQo+ID4gLQkJd2FrZV91cCgmZWMtPndhaXQp
Ow0KPiA+ICsJYWR2YW5jZV90cmFuc2FjdGlvbihlYyk7DQo+ID4gIAlzcGluX3VubG9ja19pcnFy
ZXN0b3JlKCZlYy0+bG9jaywgZmxhZ3MpOw0KPiA+ICAJZWNfY2hlY2tfc2NpKGVjLCBhY3BpX2Vj
X3JlYWRfc3RhdHVzKGVjKSk7DQo+ID4gIAlyZXR1cm4gQUNQSV9JTlRFUlJVUFRfSEFORExFRCB8
IEFDUElfUkVFTkFCTEVfR1BFOw0KPiA+DQo+IA0KPiAtLQ0KPiBJIHNwZWFrIG9ubHkgZm9yIG15
c2VsZi4NCj4gUmFmYWVsIEouIFd5c29ja2ksIEludGVsIE9wZW4gU291cmNlIFRlY2hub2xvZ3kg
Q2VudGVyLg0K
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael J. Wysocki Jan. 22, 2015, 4 p.m. UTC | #3
On Thursday, January 22, 2015 06:37:28 AM Zheng, Lv wrote:
> Hi, Rafael
> 
> > From: Rafael J. Wysocki [mailto:rjw@rjwysocki.net]
> > Sent: Thursday, January 22, 2015 6:17 AM
> > 
> > On Wednesday, January 14, 2015 07:28:22 PM Lv Zheng wrote:
> > > This patch moves transaction wakeup code into advance_transaction().
> > > No functional changes.
> > >
> > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > > ---
> > >  drivers/acpi/ec.c |   17 +++++++++--------
> > >  1 file changed, 9 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
> > > index 1b5853f..3e19123 100644
> > > --- a/drivers/acpi/ec.c
> > > +++ b/drivers/acpi/ec.c
> > > @@ -200,7 +200,7 @@ static int ec_transaction_completed(struct acpi_ec *ec)
> > >  	return ret;
> > >  }
> > >
> > > -static bool advance_transaction(struct acpi_ec *ec)
> > > +static void advance_transaction(struct acpi_ec *ec)
> > >  {
> > >  	struct transaction *t;
> > >  	u8 status;
> > > @@ -235,7 +235,7 @@ static bool advance_transaction(struct acpi_ec *ec)
> > >  			t->flags |= ACPI_EC_COMMAND_COMPLETE;
> > >  			wakeup = true;
> > >  		}
> > > -		return wakeup;
> > > +		goto out;
> > >  	} else {
> > >  		if (EC_FLAGS_QUERY_HANDSHAKE &&
> > >  		    !(status & ACPI_EC_FLAG_SCI) &&
> > > @@ -251,7 +251,7 @@ static bool advance_transaction(struct acpi_ec *ec)
> > >  			t->flags |= ACPI_EC_COMMAND_POLL;
> > >  		} else
> > >  			goto err;
> > > -		return wakeup;
> > > +		goto out;
> > >  	}
> > >  err:
> > >  	/*
> > > @@ -262,14 +262,16 @@ err:
> > >  		if (in_interrupt() && t)
> > >  			++t->irq_count;
> > >  	}
> > > -	return wakeup;
> > > +out:
> > > +	if (wakeup && in_interrupt())
> > > +		wake_up(&ec->wait);
> > >  }
> > >
> > >  static void start_transaction(struct acpi_ec *ec)
> > >  {
> > >  	ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0;
> > >  	ec->curr->flags = 0;
> > > -	(void)advance_transaction(ec);
> > > +	advance_transaction(ec);
> > 
> > Well, this looks like a functional change, because we wouldn't call
> > wake_up(&ec->wait) here before.
> 
> Ah, Yes.
> But here, since the only advancement that can happen here is to send the EC command and there are always further advancements until transaction completion, the wake_up() won't be invoked at this point.
> So IMO, there is no functional changes here.
> 
> > 
> > >  }
> > >
> > >  static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data);
> > > @@ -304,7 +306,7 @@ static int ec_poll(struct acpi_ec *ec)
> > >  					return 0;
> > >  			}
> > >  			spin_lock_irqsave(&ec->lock, flags);
> > > -			(void)advance_transaction(ec);
> > > +			advance_transaction(ec);
> > 
> > Ditto.
> 
> Yes. I changed this logic.
> 
> By invoking wake_up() here, we can break the ec_poll() loop.
> Because if the transaction has completed due to the polling advancement, we really don't need to wait for another interrupt.
> So this new logic makes this patch more like a race fix, not a simple cleanup.
> And IMO, it might also be a stable material.
> I didn't notice this race bug because there is no bug report against this.
> 
> Should I change the description around this and re-send the patch?

Yes, please.
Lv Zheng Jan. 23, 2015, 2:18 a.m. UTC | #4
Hi, Rafael

I'm sorry something is wrong in my previous reply.
Let me correct it.

> From: Rafael J. Wysocki [mailto:rjw@rjwysocki.net]

> Sent: Friday, January 23, 2015 12:01 AM

> 

> On Thursday, January 22, 2015 06:37:28 AM Zheng, Lv wrote:

> > Hi, Rafael

> >

> > > From: Rafael J. Wysocki [mailto:rjw@rjwysocki.net]

> > > Sent: Thursday, January 22, 2015 6:17 AM

> > >

> > > On Wednesday, January 14, 2015 07:28:22 PM Lv Zheng wrote:


<skip>

> > > > @@ -262,14 +262,16 @@ err:

> > > >  		if (in_interrupt() && t)

> > > >  			++t->irq_count;

> > > >  	}

> > > > -	return wakeup;

> > > > +out:

> > > > +	if (wakeup && in_interrupt())

> > > > +		wake_up(&ec->wait);

> > > >  }

> > > >


I forgot this diff block.
The wake_up() is still invoked for the advance_transaction() invoked in
the GPE handler because of in_interrupt() check.
For the 2 task context invocations, wake_up() won't be invoked.

> > > >  static void start_transaction(struct acpi_ec *ec)

> > > >  {

> > > >  	ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0;

> > > >  	ec->curr->flags = 0;

> > > > -	(void)advance_transaction(ec);

> > > > +	advance_transaction(ec);

> > > >  }

> > > >

> > > >  static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data);

> > >

> > > Well, this looks like a functional change, because we wouldn't call

> > > wake_up(&ec->wait) here before.

> >

> > Ah, Yes.

> > But here, since the only advancement that can happen here is to send

> > the EC command and there are always further advancements

> > until transaction completion, the wake_up() won't be invoked at this point.

> > So IMO, there is no functional changes here.


Thus I didn't change the logic here.

> > > > @@ -304,7 +306,7 @@ static int ec_poll(struct acpi_ec *ec)

> > > >  					return 0;

> > > >  			}

> > > >  			spin_lock_irqsave(&ec->lock, flags);

> > > > -			(void)advance_transaction(ec);

> > > > +			advance_transaction(ec);

> > >

> > > Ditto.

> >

> > Yes. I changed this logic.


And I didn't change the logic here.

> > By invoking wake_up() here, we can break the ec_poll() loop.

> > Because if the transaction has completed due to the polling advancement, we really don't need to wait for another interrupt.


This statement is also wrong.
After checking include/linux/wait.h I realized that we originally broke
ec_poll() loop because of ec_transaction_complete() check.

See include/linux/wait.h:
The condition is checked in __wait_cond_timeout() prior than doing
__wait_event_timeout() which may put the task in the wait queue.
So if the condition is matched, wait_event_timeout() just returns.

For the above 2 advance_transaction() invocations, they are both
invoked in the task that might be put into the wait queue.
But at this point, the task is already in the run queue, so wake_up()
takes no effect to this and wait_event_timeout() can break ec_poll()
because of the condition check (ec_transaction_complete()).

As a conclusion, in fact, even there is no in_interrupt() check made
before wake_up(), the modification can still be a no-op.

> > So this new logic makes this patch more like a race fix, not a simple cleanup.

> > And IMO, it might also be a stable material.

> > I didn't notice this race bug because there is no bug report against this.


There is no bug because ec_poll() is broken with ec_transaction_complete()
check. Thus this is not a bug fix and cannot be a stable candidate.

> > Should I change the description around this and re-send the patch?


Thus I needn't change the description for this patch.

> Yes, please.


It seems I needn't to change anything.
So it might not be suitable to re-send the patchset because of the above discussion.
My bad sorry for the mistake.

Could you help to check the rest patches of this revision.
Thanks in advance.

Best regards
-Lv
Rafael J. Wysocki Jan. 23, 2015, 3:22 p.m. UTC | #5
On Friday, January 23, 2015 02:18:10 AM Zheng, Lv wrote:
> Hi, Rafael
> 
> I'm sorry something is wrong in my previous reply.
> Let me correct it.
> 
> > From: Rafael J. Wysocki [mailto:rjw@rjwysocki.net]
> > Sent: Friday, January 23, 2015 12:01 AM
> > 
> > On Thursday, January 22, 2015 06:37:28 AM Zheng, Lv wrote:
> > > Hi, Rafael
> > >
> > > > From: Rafael J. Wysocki [mailto:rjw@rjwysocki.net]
> > > > Sent: Thursday, January 22, 2015 6:17 AM
> > > >
> > > > On Wednesday, January 14, 2015 07:28:22 PM Lv Zheng wrote:
> 
> <skip>
> 
> > > > > @@ -262,14 +262,16 @@ err:
> > > > >  		if (in_interrupt() && t)
> > > > >  			++t->irq_count;
> > > > >  	}
> > > > > -	return wakeup;
> > > > > +out:
> > > > > +	if (wakeup && in_interrupt())
> > > > > +		wake_up(&ec->wait);
> > > > >  }
> > > > >
> 
> I forgot this diff block.
> The wake_up() is still invoked for the advance_transaction() invoked in
> the GPE handler because of in_interrupt() check.
> For the 2 task context invocations, wake_up() won't be invoked.
> 
> > > > >  static void start_transaction(struct acpi_ec *ec)
> > > > >  {
> > > > >  	ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0;
> > > > >  	ec->curr->flags = 0;
> > > > > -	(void)advance_transaction(ec);
> > > > > +	advance_transaction(ec);
> > > > >  }
> > > > >
> > > > >  static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data);
> > > >
> > > > Well, this looks like a functional change, because we wouldn't call
> > > > wake_up(&ec->wait) here before.
> > >
> > > Ah, Yes.
> > > But here, since the only advancement that can happen here is to send
> > > the EC command and there are always further advancements
> > > until transaction completion, the wake_up() won't be invoked at this point.
> > > So IMO, there is no functional changes here.
> 
> Thus I didn't change the logic here.
> 
> > > > > @@ -304,7 +306,7 @@ static int ec_poll(struct acpi_ec *ec)
> > > > >  					return 0;
> > > > >  			}
> > > > >  			spin_lock_irqsave(&ec->lock, flags);
> > > > > -			(void)advance_transaction(ec);
> > > > > +			advance_transaction(ec);
> > > >
> > > > Ditto.
> > >
> > > Yes. I changed this logic.
> 
> And I didn't change the logic here.
> 
> > > By invoking wake_up() here, we can break the ec_poll() loop.
> > > Because if the transaction has completed due to the polling advancement, we really don't need to wait for another interrupt.
> 
> This statement is also wrong.
> After checking include/linux/wait.h I realized that we originally broke
> ec_poll() loop because of ec_transaction_complete() check.
> 
> See include/linux/wait.h:
> The condition is checked in __wait_cond_timeout() prior than doing
> __wait_event_timeout() which may put the task in the wait queue.
> So if the condition is matched, wait_event_timeout() just returns.
> 
> For the above 2 advance_transaction() invocations, they are both
> invoked in the task that might be put into the wait queue.
> But at this point, the task is already in the run queue, so wake_up()
> takes no effect to this and wait_event_timeout() can break ec_poll()
> because of the condition check (ec_transaction_complete()).
> 
> As a conclusion, in fact, even there is no in_interrupt() check made
> before wake_up(), the modification can still be a no-op.
> 
> > > So this new logic makes this patch more like a race fix, not a simple cleanup.
> > > And IMO, it might also be a stable material.
> > > I didn't notice this race bug because there is no bug report against this.
> 
> There is no bug because ec_poll() is broken with ec_transaction_complete()
> check. Thus this is not a bug fix and cannot be a stable candidate.
> 
> > > Should I change the description around this and re-send the patch?
> 
> Thus I needn't change the description for this patch.
> 
> > Yes, please.
> 
> It seems I needn't to change anything.

OK, I see.  Thanks for the analysis.

> So it might not be suitable to re-send the patchset because of the above discussion.
> My bad sorry for the mistake.
> 
> Could you help to check the rest patches of this revision.

I will, thanks!
diff mbox

Patch

diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 1b5853f..3e19123 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -200,7 +200,7 @@  static int ec_transaction_completed(struct acpi_ec *ec)
 	return ret;
 }
 
-static bool advance_transaction(struct acpi_ec *ec)
+static void advance_transaction(struct acpi_ec *ec)
 {
 	struct transaction *t;
 	u8 status;
@@ -235,7 +235,7 @@  static bool advance_transaction(struct acpi_ec *ec)
 			t->flags |= ACPI_EC_COMMAND_COMPLETE;
 			wakeup = true;
 		}
-		return wakeup;
+		goto out;
 	} else {
 		if (EC_FLAGS_QUERY_HANDSHAKE &&
 		    !(status & ACPI_EC_FLAG_SCI) &&
@@ -251,7 +251,7 @@  static bool advance_transaction(struct acpi_ec *ec)
 			t->flags |= ACPI_EC_COMMAND_POLL;
 		} else
 			goto err;
-		return wakeup;
+		goto out;
 	}
 err:
 	/*
@@ -262,14 +262,16 @@  err:
 		if (in_interrupt() && t)
 			++t->irq_count;
 	}
-	return wakeup;
+out:
+	if (wakeup && in_interrupt())
+		wake_up(&ec->wait);
 }
 
 static void start_transaction(struct acpi_ec *ec)
 {
 	ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0;
 	ec->curr->flags = 0;
-	(void)advance_transaction(ec);
+	advance_transaction(ec);
 }
 
 static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data);
@@ -304,7 +306,7 @@  static int ec_poll(struct acpi_ec *ec)
 					return 0;
 			}
 			spin_lock_irqsave(&ec->lock, flags);
-			(void)advance_transaction(ec);
+			advance_transaction(ec);
 			spin_unlock_irqrestore(&ec->lock, flags);
 		} while (time_before(jiffies, delay));
 		pr_debug("controller reset, restart transaction\n");
@@ -688,8 +690,7 @@  static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
 	struct acpi_ec *ec = data;
 
 	spin_lock_irqsave(&ec->lock, flags);
-	if (advance_transaction(ec))
-		wake_up(&ec->wait);
+	advance_transaction(ec);
 	spin_unlock_irqrestore(&ec->lock, flags);
 	ec_check_sci(ec, acpi_ec_read_status(ec));
 	return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;