Page 6 of 7 FirstFirst ... 4567 LastLast
Results 51 to 60 of 65

Thread: MBA 11" 2012 with 12.04

  1. #51
    Join Date
    May 2008
    Beans
    745

    Re: MBA 11" 2012 with 12.04

    Hi adamski,

    Quote Originally Posted by adamski99 View Post
    1. With both this and the code from my last post i get quite a high error status 0x0e returned in send cmd, but seems to recover fairly quickly without a resend, the send_command() does not fail here for me.
    Ah. So it seems the resend should not be done in so many cases,
    after all.

    2. I get quite a high fail rate in the send_argument() routine. A fail every 5-10seconds when doing lots of reads. This rate falls drastically (no errors in 10mins) if i increase the min wait used in the send_command() routine to 0x0100 (separate min waits for arg and cmd). The high error status rate in send_command() goes away as well.
    Which could be because of the resend, if I interpret this
    correctly.

    I have a theory as to why we are seeing three distinctly
    different behaviors, summarized in the patch below. The patch
    seems to be essentially the same as yours.

    It would be great to see that this one works, and I would very
    much like to have your email, for proper credits.

    Thanks!

    Code:
    From 4aa5d755bab1690540aef9893cb35f29ee58414a Mon Sep 17 00:00:00 2001
    From: Henrik Rydberg <rydberg@euromail.se>
    Date: Wed, 25 Jul 2012 09:39:35 +0200
    Subject: [PATCH] hwmon: (applesmc) Decode send_command() status codes
    
    It appears as if the the way commands are sent to the smc have changed
    over the years, and the mid-2012 macbooks have further accentuated
    this problem. However, the most likely explanation is that we are
    experiencing a timeout and a shift in smc speed.
    
    We should first wait for the line to settle, which was the most
    frequent response on the old slow machines. Then, if the smc is busy,
    we need to try again later by resending the command. This was the most
    likely response until 2012. Now, with a shorter wait time, we are
    again most likely to poll while the smc is settling, which is why we
    see such high failure rates on the mid-2012 models.
    
    This patch takes the command status bits into account, which seems to
    work for all models.
    ---
     drivers/hwmon/applesmc.c | 16 ++++++++++++----
     1 file changed, 12 insertions(+), 4 deletions(-)
    
    diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
    index 4d937a1..583377b 100644
    --- a/drivers/hwmon/applesmc.c
    +++ b/drivers/hwmon/applesmc.c
    @@ -182,18 +182,26 @@ static int __wait_status(u8 val)
     }
     
     /*
    - * special treatment of command port - on newer macbooks, it seems necessary
    - * to resend the command byte before polling the status again. Callers must
    + * special treatment of command port - the low bits determine if we should
    + * resend the command byte before polling the status again. Callers must
      * hold applesmc_lock.
      */
     static int send_command(u8 cmd)
     {
    +	u8 status;
     	int us;
    +	outb(cmd, APPLESMC_CMD_PORT);
     	for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
    -		outb(cmd, APPLESMC_CMD_PORT);
     		udelay(us);
    -		if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
    +		status = inb(APPLESMC_CMD_PORT);
    +		/* wait for smc to settle */
    +		if (status & 0x03)
    +			continue;
    +		/* ready for argument */
    +		if (status & 0x04)
     			return 0;
    +		/* failed, resend */
    +		outb(cmd, APPLESMC_CMD_PORT);
     	}
     	return -EIO;
     }
    -- 
    1.7.11.3

  2. #52
    Join Date
    Jul 2012
    Beans
    3

    Re: MBA 11" 2012 with 12.04

    This patch also works on my MBP9,2, thanks, adamski & kosumi; there are no more send_command errors.

    I still get many send_argument errors, though. Just for the sake of completeness, here's what I did yesterday to solve the problem.
    I don't outb again in send_command but just return if the status is 0x08; and in read_smc(), I have
    Code:
    static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) {
        int i;
    #define SEND_CMDARG_TRIES 3
        for (i=0; i<SEND_CMDARG_TRIES; i++) {
            if (send_command(cmd)) {
                pr_warn("read arg fail %d - send_command(0x%2X) (key=\"%.4s\")\n",
                    i+1, cmd, key);
                continue;
            }
            if (send_argument(key)) {
                pr_warn("read arg fail %d - send_argument(\"%.4s\")\n", i+1, key);
            } else {
                break;
            }
        }
        if (i==SEND_CMDARG_TRIES) return -EIO;
    This takes care of the (required?) command resend before again calling send_argument. I never had more than one retry with the above construction.
    Best,
    Hubert

  3. #53
    Join Date
    Jun 2006
    Beans
    28
    Distro
    Ubuntu 12.10 Quantal Quetzal

    Re: MBA 11" 2012 with 12.04

    Has anyone got UEFI grub working? I get a black screen, though I can get a working display by plugging in and unplugging an external monitor.

  4. #54
    Join Date
    Jun 2006
    Beans
    28
    Distro
    Ubuntu 12.10 Quantal Quetzal

    Re: MBA 11" 2012 with 12.04

    It seems the 3.2.0-26 kernel works but the 3.2.0-27 doesn't. I will try a newer kernel tomorrow.

  5. #55
    Join Date
    May 2008
    Beans
    745

    Re: MBA 11" 2012 with 12.04

    adamski, myselph,

    Thanks for the feedback. It seems all writes should be treated
    the same way, which also affects what status is important during
    reads. Also, as adamski pointed out several times, additional
    timing is important. They way it is incorporated in the patch
    below means we do not have to sacrifice general read speed.

    Tested to work successfully on the MBA3,1 and the much more
    tricky MBA1,1. Please give it a try.

    Cheers!

    Code:
    From 7f83e1bc2d41d2346c4ddc6aa5ef0cf0a9a586f6 Mon Sep 17 00:00:00 2001
    From: Henrik Rydberg <rydberg@euromail.se>
    Date: Thu, 26 Jul 2012 09:40:49 +0200
    Subject: [PATCH] hwmon: (applesmc) Decode and act on read/write status codes
    
    The behavior of the SMC has changed several times over the years,
    causing read failures in the driver. It seems the problem can be
    explained by a shift in SMC speed combined with improper action on
    status codes.
    
    We should first wait for the SMC to settle, which was the most
    frequent response on the old slow machines. Then, if the SMC is busy,
    we need to try again later by resending the command. This was the most
    likely response until 2012. Now, with a shorter wait time, we are
    again most likely to poll while the SMC is settling, and as a result
    we see high failure rates on the mid-2012 models.
    
    With the distinction between busy and failure, we can also wait longer
    before retrying without sacrificing speed.  This seems to bring
    failures down to virtually zero.
    
    Tested on: MBA1,1 MBA3,1
    
    Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
    ---
     drivers/hwmon/applesmc.c | 66 ++++++++++++++++++++++++++++++------------------
     1 file changed, 42 insertions(+), 24 deletions(-)
    
    diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
    index 4d937a1..50b1814 100644
    --- a/drivers/hwmon/applesmc.c
    +++ b/drivers/hwmon/applesmc.c
    @@ -55,9 +55,9 @@
     
     /* wait up to 32 ms for a status change. */
     #define APPLESMC_MIN_WAIT	0x0010
    +#define APPLESMC_RETRY_WAIT	0x0100
     #define APPLESMC_MAX_WAIT	0x8000
     
    -#define APPLESMC_STATUS_MASK	0x0f
     #define APPLESMC_READ_CMD	0x10
     #define APPLESMC_WRITE_CMD	0x11
     #define APPLESMC_GET_KEY_BY_INDEX_CMD	0x12
    @@ -162,51 +162,64 @@ static unsigned int key_at_index;
     static struct workqueue_struct *applesmc_led_wq;
     
     /*
    - * __wait_status - Wait up to 32ms for the status port to get a certain value
    - * (masked with 0x0f), returning zero if the value is obtained.  Callers must
    + * wait_read - Wait for a byte to appear on SMC port. Callers must
      * hold applesmc_lock.
      */
    -static int __wait_status(u8 val)
    +static int wait_read(void)
     {
    +	u8 status;
     	int us;
    -
    -	val = val & APPLESMC_STATUS_MASK;
    -
     	for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
     		udelay(us);
    -		if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val)
    +		status = inb(APPLESMC_CMD_PORT);
    +		/* read: wait for smc to settle */
    +		if (status & 0x01)
     			return 0;
     	}
     
    +	pr_warn("wait_read() fail: 0x%02x\n", status);
     	return -EIO;
     }
     
     /*
    - * special treatment of command port - on newer macbooks, it seems necessary
    - * to resend the command byte before polling the status again. Callers must
    - * hold applesmc_lock.
    + * send_byte - Write to SMC port, retrying when necessary. Callers
    + * must hold applesmc_lock.
      */
    -static int send_command(u8 cmd)
    +static int send_byte(u8 cmd, u16 port)
     {
    +	u8 status;
     	int us;
    +	outb(cmd, port);
     	for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
    -		outb(cmd, APPLESMC_CMD_PORT);
     		udelay(us);
    -		if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
    +		status = inb(APPLESMC_CMD_PORT);
    +		/* write: wait for smc to settle */
    +		if (status & 0x02)
    +			continue;
    +		/* ready: cmd accepted, return */
    +		if (status & 0x04)
     			return 0;
    +		/* busy: long wait and resend */
    +		udelay(APPLESMC_RETRY_WAIT);
    +		outb(cmd, port);
     	}
    +
    +	pr_warn("send_byte(0x%02x, 0x%04x) fail: 0x%02x\n", cmd, port, status);
     	return -EIO;
     }
     
    +static int send_command(u8 cmd)
    +{
    +	return send_byte(cmd, APPLESMC_CMD_PORT);
    +}
    +
     static int send_argument(const char *key)
     {
     	int i;
     
    -	for (i = 0; i < 4; i++) {
    -		outb(key[i], APPLESMC_DATA_PORT);
    -		if (__wait_status(0x04))
    +	for (i = 0; i < 4; i++)
    +		if (send_byte(key[i], APPLESMC_DATA_PORT))
     			return -EIO;
    -	}
     	return 0;
     }
     
    @@ -219,11 +232,14 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
     		return -EIO;
     	}
     
    -	outb(len, APPLESMC_DATA_PORT);
    +	if (send_byte(len, APPLESMC_DATA_PORT)) {
    +		pr_warn("%.4s: read len fail\n", key);
    +		return -EIO;
    +	}
     
     	for (i = 0; i < len; i++) {
    -		if (__wait_status(0x05)) {
    -			pr_warn("%.4s: read data fail\n", key);
    +		if (wait_read()) {
    +			pr_warn("%.4s: read data[%d] fail\n", key, i);
     			return -EIO;
     		}
     		buffer[i] = inb(APPLESMC_DATA_PORT);
    @@ -241,14 +257,16 @@ static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
     		return -EIO;
     	}
     
    -	outb(len, APPLESMC_DATA_PORT);
    +	if (send_byte(len, APPLESMC_DATA_PORT)) {
    +		pr_warn("%.4s: write len fail\n", key);
    +		return -EIO;
    +	}
     
     	for (i = 0; i < len; i++) {
    -		if (__wait_status(0x04)) {
    +		if (send_byte(buffer[i], APPLESMC_DATA_PORT)) {
     			pr_warn("%s: write data fail\n", key);
     			return -EIO;
     		}
    -		outb(buffer[i], APPLESMC_DATA_PORT);
     	}
     
     	return 0;
    -- 
    1.7.11.3

  6. #56
    Join Date
    Jul 2012
    Beans
    3

    Re: MBA 11" 2012 with 12.04

    Thanks for the code, kosumi, this works great here. I did a stress test where I perform many reads (infinite while loop with cat on temperature sensors in two terminals) and did not get any read errors (just one write error in five minutes coming from macfanctld running at the same time). So I checked on write errors, and I got write errors when performing a write stress test:
    Code:
    while [ 0 -eq 0 ]; do echo 0 > /sys/class/hwmon/hwmon0/device/fan1_manual; done
    but that's a pretty exotic test scenario. What happens on a fail is that in send_byte, the initial status goes from 0x44 to 0x40 after the outb and remains there until the loop ends. This only happens under heavy load, so I guess we can ignore it - or insert something like
    Code:
    if (!(status & 0x0f)) break;
    Just a brief note on the command resend - if it happens in the last iteration of the loop, there's no status check and an error will occur nonetheless, so maybe you could insert something like
    Code:
            /* busy: long wait and resend */
            if ((us<<1) >= APPLESMC_MAX_WAIT) break; //last iteration;
            udelay(APPLESMC_RETRY_WAIT);
            outb(cmd, port);
    So, on my MBP9,2, your changes seem to solve all the problems I had. Thanks a lot to you and adamski!
    Hubert

  7. #57
    Join Date
    May 2008
    Beans
    745

    Re: MBA 11" 2012 with 12.04

    Quote Originally Posted by mschinca View Post
    Hi all,
    I'm running 12.04 on a 13" MBA 5,2 (Mid 2012) with 3.2.0 stock kernel and latest applesmc from PPA. I am booting with noapic parameter.
    Everything looks fine, I turned keyboard backlight on manually as desribed by @adamski99.
    I just want to report my temperatures after 1 hour uptime, are those values safe?
    http://paste.ubuntu.com/1109202/
    I'm not using manual fan control, should I?

    Best regards.
    Looks ok (the 129 is actually -2). Check the mactel repo for a fresh update.

    Thanks.

  8. #58
    Join Date
    May 2008
    Beans
    745

    Re: MBA 11" 2012 with 12.04

    Quote Originally Posted by myselph View Post
    Thanks for the code, kosumi, this works great here. I did a stress test where I perform many reads (infinite while loop with cat on temperature sensors in two terminals) and did not get any read errors (just one write error in five minutes coming from macfanctld running at the same time). So I checked on write errors, and I got write errors when performing a write stress test:
    Code:
    while [ 0 -eq 0 ]; do echo 0 > /sys/class/hwmon/hwmon0/device/fan1_manual; done
    but that's a pretty exotic test scenario. What happens on a fail is that in send_byte, the initial status goes from 0x44 to 0x40 after the outb and remains there until the loop ends. This only happens under heavy load, so I guess we can ignore it - or insert something like
    Code:
    if (!(status & 0x0f)) break;
    Just a brief note on the command resend - if it happens in the last iteration of the loop, there's no status check and an error will occur nonetheless, so maybe you could insert something like
    Code:
            /* busy: long wait and resend */
            if ((us<<1) >= APPLESMC_MAX_WAIT) break; //last iteration;
            udelay(APPLESMC_RETRY_WAIT);
            outb(cmd, port);
    So, on my MBP9,2, your changes seem to solve all the problems I had. Thanks a lot to you and adamski!
    Hubert
    Thanks for that, Hubert. I added a timeout break and your Tested-by and will push it upstream once I get a few more positive reactions. Great work, everyone.

    PS. I uploaded the new applesmc version to the mactel ppa.

  9. #59
    Join Date
    Apr 2006
    Beans
    4

    Re: MBA 11" 2012 with 12.04

    Quote Originally Posted by jhodapp View Post
    One thing I'm running into is that quite often, booting into Linux from rEFIt into Grub doesn't restore screen brightness, so it'll boot into Grub and then into Ubuntu with a completely darkened screen. I know that it's fully booting because I can see the screen contents if I shine a flashlight on it. I'm not quite sure what the cause of this is.
    I'm getting the same here. Doesn't happen all the time, and I have to keep rebooting/powering off until the screen kicks in. I do not even see the grub menu.

    Other than that, everything seems to work great.

  10. #60
    Join Date
    Dec 2007
    Beans
    3

    Re: MBA 11" 2012 with 12.04

    Quote Originally Posted by barryf View Post
    I'm getting the same here. Doesn't happen all the time, and I have to keep rebooting/powering off until the screen kicks in. I do not even see the grub menu.

    Other than that, everything seems to work great.
    I figured out that if you wait for a little while (~30+ seconds) in rEFIt, then the screen brightness is restored every time for me. It seems that rEFIt does some controller initialization that the Linux kernel is not doing (or shouldn't do). I'd be curious if you can confirm that this works for you too? Obviously not an ideal solution, but at least more predictable to get into Ubuntu.

Page 6 of 7 FirstFirst ... 4567 LastLast

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •