Menu:


 

Get the best of the Toshiba R840-139

In order to write the World Trip's blog during the trip, I decided to buy a new laptop that fits my following needs:

  • Intel architecture
  • Good CPU performance (not an Atom)
  • Mat non-reflective screen with LED backlighting
  • 13-14" max with the highest resolution possible
  • Keyboard with standard layout (some constructors takes pleasure to move some fundamental key in unexpected places)
  • Low consumption and 6-cells battery

The goal is having a pretty comfortable machine with a very good autonomy since sometimes I could have no electricity for several days.

With the help of a friend, I choose and bought the Toshiba R840-139 laptop.

Power consumption optimization

For stability, quality and ethical reason, I installed a Debian Squeeze and started working on the important part : the autonomy. I did all the customization available for the 2.6.32 kernel provided by this Debian release. Finally, installing manually the catalyst driver for the Radeon HD 6450 I was able to get a consumption between 9.7 and 10.0 watts which is not so bad. However, I didn't get the 7 hours of autonomy announced by the constructor. What a shame !

Talking with a good friend, I figured out that I should be able to get a power consumption around 8.5-9.0 watts with a more recent kernel. Getting a more recent kernel should give me access to the last non-working device too : the SD card reader Ricoh Co Ltd Device e823. In order to easily be able to fix some eventual kernel issues I cloned the linux kernel git repository (3.2.0-rc6 and 7 ...), compiled and added an entry in my grub configuration file.

With the same kernel options I used with the 2.6.32 release, I got a very bad power consumption of 14 to 15 watts where I got 9.7 to 10.0 watts with the old release. Very disappointed, I started looking at the kernel log and noticed that :

ACPI _OSC control for PCIe not granted, disabling ASPM

Adding the pcie_aspm=force kernel command line parameter, I finally get the 8.5-9.0 watts power consumption and optimizing the kernel power configuration I am not able to slow down to 7.6 to 8.0 watts which leads to more than 8 hours of autonomy with the standard battery :)

Here my power management configuration from /etc/rc.local:

# Power Management settings
# Modules parameter
echo powersave > /sys/module/pcie_aspm/parameters/policy
echo 1 > /sys/module/snd_hda_intel/parameters/power_save
echo 1 > /sys/module/usbcore/parameters/autosuspend

# SATA Power Management
echo min_power > /sys/class/scsi_host/host0/link_power_management_policy
echo min_power > /sys/class/scsi_host/host1/link_power_management_policy

# PCI Power Management
for file in $(find /sys -name control) ; do echo -n auto > $file ; done

# USB Power Management
for file in $(find /sys -name autosuspend) ; do echo 1 > $file ;done
for file in /sys/bus/usb/devices/*/power/level ; do echo auto > $file ; done

# Disk power management
echo 1500 > /proc/sys/vm/dirty_writeback_centisecs

# Scheduler power policy
echo 1 > /sys/devices/system/cpu/sched_mc_power_savings
echo 1 > /sys/devices/system/cpu/sched_smt_power_savings

# Disable CDROM device polling
hal-disable-polling --device /dev/cdrom

# Turn Wifi radio off at boot time
iwconfig wlan0 txpower off

# Ethernet configuration
ethtool -s eth0 wol d                 # Disable WOL
ethtool -s eth0 autoneg off speed 100 # Limit to 100 Mbit network by default

# HDD Power Management
hdparm -S 0 /dev/sda

Here, my kernel command line parameters:

snd_hda_intel.power_save=1 usbcore.autosuspend=2 pcie_aspm.policy=powersave pcie_aspm=force

ACPI RTC_EN bug leads to unexpected wakeup on 3.2.0 kernel

Last point but a very important one in fact. With, the 3.2.0-rc7 kernel, I noticed that after shutting down the system, the laptop waked up by itself during the following five minutes. For me there was two major possibilities:

  1. A magic packet was received. I unplugged the Ethernet cable and got the same unexpected wakeup.
  2. The wakeup was due to a RTC alarm. Looking at /proc/driver/rtc I figured out that when I shutdown the system an RTC alarm is set in the future (300 seconds exactly) with AIE disabled. This is the consequence of some ioctl calls by the hwclock command which ask for saving the wall clock to hardware clock. Which is in fact quite a good idea.

I took a look at the ACPI 4.0a official specification about the RTC wakeup. There is a dedicated bit in the PM1 event register which enable/disable the RTC wakeup. I dumped the current value on my system and this bit was set to 0 which should prevent from a RTC wakeup, strange ... In order, to ensure this bit wasn't set by an ACPI method during the shutdown I modified the kernel acpi_enter_sleep_state_prep() function to force this bit to zero just after the last called ACPI method, GTS, and just before the sleep control register bit are set to shutdown the machine. The laptop continued to wakeup after shutting down ...

So, I figured out that it's either a firmware bug, either an hardware bug that I could not fix. Therefore, I started trying to work on the Linux RTC part. I discovered that in order to deactivate an alarm, the rtc_alarm_disable() function sets a disabled alarm 300 seconds in the future instead of using the more appropriate alarm_irq_enable() RTC device callback. Moreover, the rtc_timer_do_work() try to disable the alarm even when there is no reason to do so.

I wrote the following patch and submitted it to the RTC linux mailing list (rtc: Fix unexpected poweron and unnecessary alarm disabling) and to the RTC linux maintainer. This patch fixes this very annoying issue but the RTC linux maintainer and RTC linux mailing list is quite calm and nobody answered me for now. So wait&see. If you encounter the same bug, I suggest you use the following patch (if not merged anymore):

diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 3bcc7cf..9299415 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -778,16 +778,8 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
 
 static void rtc_alarm_disable(struct rtc_device *rtc)
 {
-       struct rtc_wkalrm alarm;
-       struct rtc_time tm;
-
-       __rtc_read_time(rtc, &tm);
-
-       alarm.time = rtc_ktime_to_tm(ktime_add(rtc_tm_to_ktime(tm),
-                                    ktime_set(300, 0)));
-       alarm.enabled = 0;
-
-       ___rtc_set_alarm(rtc, &alarm);
+       if (rtc->ops && rtc->ops->alarm_irq_enable)
+               rtc->ops->alarm_irq_enable(rtc->dev.parent, false);
 }
 
 /**
@@ -835,7 +827,7 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
  */
 void rtc_timer_do_work(struct work_struct *work)
 {
-       struct rtc_timer *timer;
+       struct rtc_timer *timer = NULL;
        struct timerqueue_node *next;
        ktime_t now;
        struct rtc_time tm;
@@ -876,7 +868,7 @@ again:
                err = __rtc_set_alarm(rtc, &alarm);
                if (err == -ETIME)
                        goto again;
-       } else
+       } else if (timer && timer->enabled == 0)
                rtc_alarm_disable(rtc);
 
        mutex_unlock(&rtc->ops_lock);
 

IPv6 at home with a non IPv6 ISP

After a entire week working on IPv6 at work, I decided to use this fresh knowledge to enable IPv6 on my home network and provide access to my home server on both IPv4 and IPv6.

Obviously, my ISP does not provide me a IPv6 connection to the Internet. So I registered to Tunnel-Broker.net to get an IPv6 tunnel access over my IPv4 connection and an IPv6 block allocation for my internal network. Configuring the tunnel is pretty simple with the ip command line tool:

# Configure IPv6 tunnel (Tunnel-Broker.net)
ip tunnel add he-ipv6 mode sit remote 216.66.84.42 local 192.168.0.11 ttl 255
ip link set he-ipv6 up
ip addr add 2001:470:1f12:3ba::2/64 dev he-ipv6
ip route add ::/0 dev he-ipv6

I put this configuration in my /etc/rc.local file. So my server which acts as my router too is now connected to the IPv6 world:

$ ping6 2a00:1450:8007::68
PING 2a00:1450:8007::68(2a00:1450:8007::68) 56 data bytes
64 bytes from 2a00:1450:8007::68: icmp_seq=1 ttl=56 time=43.5 ms
64 bytes from 2a00:1450:8007::68: icmp_seq=2 ttl=56 time=47.7 ms
64 bytes from 2a00:1450:8007::68: icmp_seq=3 ttl=56 time=41.9 ms
  C-c C-c
--- 2a00:1450:8007::68 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 41.981/44.430/47.715/2.414 ms

Time to do some real test : The http://ipv6-test.com/speedtest/ speed test show me no big difference between my IPv4 direct connection and my IPv6 tunnel. Of course, there is a rate difference due to the tunneling operation but not so significantly. Furthermore, now this website is accessible with the www6.jerryland.fr IPv6 only domain name too. I cannot use the www.jerryland.fr domain name due to my ISP which cannot give me static address and so I have to deal with CNAME and dyndns ...

After that I wanted to enable IPv6 in my local network using the IPv6 address block that has been assigned to me by Tunnel-Broker.net. I wanted a Stateless autoconfiguration so I installed radvd on my server/router with the following configuration (/etc/radvd.conf):

interface eth0
{
    AdvSendAdvert on;

    MinRtrAdvInterval 5;
    MaxRtrAdvInterval 15;

    prefix 2001:470:cb8d::/64
    {
        AdvOnLink on;
        AdvAutonomous on;
    };

    RDNSS 2001:470:20::2 {
    };
};

After starting this service I do a "ip addr show eth0" on my laptop and got a new IPv6 address :). By default, Linux assign address using the MAC address of the interface which does not look good from privacy point of view. So I enabled the privacy mode with the following command on my laptop:

sudo sysctl -w net.ipv6.conf.eth0.use_tempaddr=1

After that I had to enable routing on server/router, so I added the following line in my rc.local:

# Configure local IPv6 network
ip addr add 2001:470:cb8d::1 dev eth0
ip route add 2001:470:cb8d::/64 dev eth0

# Configure IPv6 forwarding
sysctl -w net.ipv6.conf.all.forwarding=1

And now, all my local network machines are IPv6 connected !

 

Emacs apply format on region

One friend reports me a frequently encountered need: fill a rectangle or insert lines with an formatted incremental value on each line. Imagine that we want to efficiently generate the following C code using GNU/Emacs:

unsigned int array[] =
{
    0x00000100, 0x10000104, 0x20000108, 0x3000010c, 0x40000110,
    0x50000114, 0x60000118, 0x7000011c, 0x80000120, 0x90000124,
    0xA0000128
};
First we write the first, the second line and the last line. Then we call the format-insert-lines() with the following arguments:
  • Format: " 0x%.8x,",
  • Start from: "256",
  • Step value: "4",
  • Line(s) number: "10".

We obtain:

unsigned int array[] =
{
    0x00000100,
    0x00000104,
    0x00000108,
    0x0000010c,
    0x00000110,
    0x00000114,
    0x00000118,
    0x0000011c,
    0x00000120,
    0x00000124,
    0x00000128
};
Now, we select the first "0" column and call the format-rectangle-default() function (see code bellow) with "%X" as argument:
unsigned int array[] =
{
    0x00000100,
    0x10000104,
    0x20000108,
    0x3000010c,
    0x40000110,
    0x50000114,
    0x60000118,
    0x7000011c,
    0x80000120,
    0x90000124,
    0xA0000128
};

Finally, select the data part and call the fill-paragraph() function to obtain the expected result.

The following code is now available in my my-tools.el package.

(defvar format-rectangle-current 0 "Internal global variable")
(defcustom format-rectangle-default-start-value 0 "Default start value")
(defcustom format-rectangle-default-step 1 "Default inc step")

(defun format-rectangle-line (startcol endcol args)
  (let ((format (first args))
        (step (second args)))
    (move-to-column startcol t)
    (delete-region (point) (progn (move-to-column endcol t) (point)))
    (insert (format format format-rectangle-current))
    (setq format-rectangle-current (+ format-rectangle-current step))))

(defun format-rectangle (start end format start-value step)
  "Apply format on each line in region"
  (interactive "r\nsFormat: \nnStart from: \nnStep value: ")
  (setq format-rectangle-current start-value)
  (apply-on-rectangle 'format-rectangle-line start end (list format step)))

(defun format-rectangle-default (start end format)
  "Apply format on each line in region with default values"
  (interactive "r\nsFormat: ")
  (format-rectangle start end format format-rectangle-default-start-value format-rectangle-default-step))

(defun format-insert-lines (format start-value step nb)
  "Insert NB formatted lines"
  (interactive "sFormat: \nnStart from: \nnStep value: \nnLine(s) number: ")
  (loop for current from start-value to (+ (* nb step) start-value) by step do
        (insert (format format current) "\n")))

(defun format-insert-lines-default (format nb)
  "Insert NB formatted lines with default values"
  (interactive "sFormat: \nnLine(s) number: ")
  (format-insert-lines format format-rectangle-default-start-value format-rectangle-default-step nb))
 

Emacs move lines

This week, at work, I was looking for a way to move one line up and down avoiding the cut and paste habit. I found a solution on the web: MoveLine. So I integrated it in my temporary "test.el" file like I do usually.

Later, I need to move several lines at one time. So I returned on the Web and found MoveRegion.

But this time I wasn't completely satisfied. For me, moving one line or a complete region is the same thing and I didn't want to call different functions for the "same purpose". Moreover, I wanted that a region with some lines partially selected was moved including the whole lines. So, I wrote the following function:

(defun move-lines (n)
  "Move the current lines up or down by N lines.
When no region is active, it move the current line.
Otherwise, it move the whole lines included by the
active region and keep it active."
  (interactive "p")
  (let ((start (if (use-region-p) (region-beginning) (line-beginning-position)))
        (end (if (use-region-p) (region-end) (progn (forward-line 1) (point)))))
    (when (use-region-p)
      ;; Modify region to include the whole lines
      (when (not (eq start (progn (goto-char start) (line-beginning-position))))
        (setq start (line-beginning-position)))
      (when (not (eq end (progn (goto-char end) (line-beginning-position))))
        (setq end (progn (forward-line 1) (line-beginning-position)))))
    (let ((lines (delete-and-extract-region start end)))
      (forward-line n)
      (if (use-region-p)
          (progn (push-mark (point))
                 (insert lines)
                 (setq deactivate-mark nil))
        (save-excursion (insert lines))))))

(global-set-key (kbd "S-M-<up>") (lambda () (interactive) (move-lines -1)))
(global-set-key (kbd "S-M-<down>") (lambda () (interactive) (move-lines 1)))
 

Emacs Activity management

Since, I'm using GNU/Emacs as my desktop environment, I note that I usually manage different window configuration for different purpose (my development window configuration is different than the one I use when I read mail). Switching between these window configuration is complicated, boring and moreover a waste of time : unacceptable !

For example, frequently I quit my current activity (like developing, or web surfing) to manage my mails. Doing it, I destroyed my current window configuration. To get back my previous configuration, I have to manually restore all the window configuration and buffers.

Recently, I discovered the winner-mode which really help me in a relatively efficient way. Using the [Control-C][Left] shortcut several times, I can get back my working environment. However, if I want to go back my read mail environment I have to manually restore my preferred mail window configuration, boring ...

Looking on the Internet, I discovered that GNU/Emacs can store and restore window configuration using registers. This helps me for a while, but the need to store the current window configuration before jumping to another is a shame.

So I take time to think about it and I finally understood that what I really need is an "activity manager" like the one I was simulating using multiple desktop in classic desktop environment like Gnome or KDE. But instead of simulated it, I can easily make a true "activity manager" in my sense, thanks to GNU/Emacs ;)

So I make the activity package on the following principles:

  • An activity consists of a function to start it and an special window configuration ;
  • The "activity manager" shall allow me to arbitrary start an activity, and another, and another and finally go back to the first activity ;
  • It shall allow me to manage my activities in a stack fashion too so I can push and pop activities ;

The activity package manages a list of available activities:

(defcustom available-activities '(("default" 110 nil))
  "Available activities."
  :group 'activity)

By default, the "default" activity is the only one available and correspond to current activity. An activity is defined by a tuple constituted by a name ("default"), a register number for the window configuration save and restore operation (110) and a function called when starting the activity (nil). Adding a new activity is as simple as what I do in my GNUS mail configuration file:

(require 'activity)
(add-to-list 'available-activities '("mail" 109 gnus))

or, in my jabber configuration file:

(require 'activity)
(defun my-jabber-activity ()
  (delete-other-windows)
  (jabber-connect-all)
  (display-buffer "*-jabber-roster-*"))
(add-to-list 'available-activities '("jabber" 108 my-jabber-activity))

The activity package provides the following functions:

  • activity-push stores the current activity window configuration, push the activity on the activities stack and:
    • if the asked for activity wasn't previous started, start it ;
    • otherwise, it restore the asked for activity window configuration ;
  • activity-pop restores the previous activity if any ;
  • toggle-activity starts an activity if it's not the current activity, restore the previous activity otherwise ;
  • activity-show-stack display the current activity stack in the message area ;

The toggle-activity function is very convenient. It can be bound to a unique shortcut which enable/disable an activity. For example:

(global-set-key (kbd "C-! m") (lambda () (interactive) (toggle-activity "mail")))

Moreover, since GNU/Emacs manages all the buffer in the same way, I can use a jabber chat buffer or a mail article in my "default" activity, awesome ! (which desktop environment provides this as simple ?).

Download

The activity package can be downloaded from my git repository (see activity.el):

$ git clone git://git.jerryland.fr/emacs-config.git
 

Emacs GNUS google contact mail address completion

I'm not a Google addict, but like many people, I finally accept the idea of managing my contacts using my gmail account for many reasons.

Now, I have a androphone and my gmail contact list is clean. So, 3 months ago, when I decided to use Emacs GNUS to manage my mails, I was looking for a way to use my gmail contacts list.

Last week-end, I wrote a small Emacs package working on the googlecl tools. It provides a mail address completion function using your gmail account contact list.

HOWTO

First, you need to install the googlecl package adapted with your GNU/Linux distribution.

Second, the following command should successfully be executed.

$ google contacts list
[...]

If you encounter accentuated character errors you should take a look at Issue 279 - googlecl - crash listing contacts and check your console character encoding settings (UTF-8 rocks).

When the google contacts list runs successfully, you can load the following emacs package and use the gcl-contact-complete function. Personally, I bound it to the C-tab key in my ".emacs".

;; gcl-contacts
(global-set-key [C-tab] 'gcl-contact-complete)
(require 'gcl-contacts)

Source code

I'm a newbie in elisp programming, so every comments are welcome.

And yes I know, I should provide a git access instead of quoting my source code ...

(defcustom gcl-contact-buffer "*gcl-contact*"
  "contacts list"
  :group 'gcl-contacts
  :type 'string)

(defvar gcl--contact-cur-point nil)
(defvar gcl--first-location nil)
(defvar gcl--last-location nil)
(defvar gcl--cur-pattern nil)

(defun gcl-contact-buffer-clean ()
  "Clean the gcl-contact-buffer"
  (save-excursion
    (while (search-forward "N/A" nil t)
      (delete-region (line-beginning-position)
                     (save-excursion (forward-line 1) (point)))))
  (save-excursion
    (while (search-forward-regexp "; [a-z]+ " nil t)
      (replace-match "|")
      (insert (buffer-substring (line-beginning-position)
                                (save-excursion (search-backward ","))))
      (insert " <")))
  (save-excursion (replace-string "|" "\n"))
  (save-excursion (replace-regexp ",[a-z]+ " " <"))
  (save-excursion (replace-string "," " <"))
  (save-excursion (replace-regexp "$" ">")))

(defun gcl-contact-delete-duplicates ()
  "Remove duplicates contact information in the gcl-contact-buffer"
  (save-excursion
    (while (= 0 (forward-line 1))
      (save-excursion
        (let ((info (buffer-substring (line-beginning-position)
                                      (line-end-position))))
          (if (= 0 (forward-line 1))
              (while (search-forward info nil t)
                (delete-region (line-beginning-position)
                               (save-excursion (forward-line 1) (point))))))))))

(defun gcl-contact-buffer-build ()
  "Build the contacts list used for completion"
  (setenv "PYTHONIOENCODING" "utf8")
  (with-current-buffer (get-buffer-create gcl-contact-buffer)
    (delete-region (point-min) (point-max)))
  (call-process "google" nil gcl-contact-buffer t "contacts" "list")
  (with-current-buffer (get-buffer-create gcl-contact-buffer)
    (beginning-of-buffer)
    (gcl-contact-buffer-clean)
    (gcl-contact-delete-duplicates)
    (setq gcl--contact-cur-point (point-min))))

(defun gcl-contact-get ()
  (let ((contact (buffer-substring (line-beginning-position)
                                   (line-end-position))))
    (forward-line 1)
    (setq gcl--contact-cur-point (line-beginning-position))
    contact))

(defun gcl-get-next-expansion ()
  (with-current-buffer (get-buffer gcl-contact-buffer)
    (goto-char gcl--contact-cur-point)
    (if (search-forward gcl--cur-pattern nil t)
        (gcl-contact-get)
      (progn
        (beginning-of-buffer)
        (setq gcl--contact-cur-point (point-min))
        (message "No completion found")
        nil))))

(defun gcl-contact-complete ()
  (interactive)
  (if (eq nil (get-buffer gcl-contact-buffer))
      (gcl-contact-buffer-build))
  (if (or (eq nil gcl--last-location)
          (not (= (point) gcl--last-location)))
      (progn
        (setq gcl--cur-pattern (thing-at-point 'word))
        (setq gcl--last-location (point))
        (save-excursion
          (backward-word)
          (setq gcl--first-location (point)))
        (setq gcl--contact-cur-point (point-min))))
  (let* ((expansion (gcl-get-next-expansion))
         (result (if (eq nil expansion) gcl--cur-pattern expansion)))
    (delete-region gcl--first-location gcl--last-location)
    (insert result)
    (setq gcl--last-location (point))))

(provide 'gcl-contacts)

Archives