How do I target a specific driver for libata kernel parameter modding?

I'm running a 22-disk setup, 19 of those in a ZFS array, 15 of those backed by three port multipliers attached to SATA controllers driven by the sata_sil24 module. When running full speed (SATA2, 3 Gbps), the operation is pretty quirky. Simple read errors will throw an entire port multiplier into spasms for a long time, sometimes with pretty awful results. Booting with kernel parameter libata.force=1.5G to force SATA controllers into "legacy" speeds completely fixes all issues with the port multipliers. Thing is, my ZFS pool is backed by a fast cache SSD on my ICH10R controller. Another SSD on this same controller holds the system.

Doing libata.force=1.5G immediately shaves about 100 MB/s off the transfer rate of my SSDs. For the root drive, that's not such a big deal, but for the ZFS cache SSD, it is. It effectively makes the entire zpool slower for sustained transfers than it would've been without the cache drive. Random access and fs tree lookups, of course still benefit. Listing the module options for sata_sil24, no such option exists.

How to pass the libata.force=1.5G parameter on to just the three SATA controllers being backed by the sata_sil24 module?


Ah! I found out!

At http://www.kernel.org/doc/Documentation/kernel-parameters.txt, it states,

    libata.force=   [LIBATA] Force configurations.  The format is comma
        separated list of "[ID:]VAL" where ID is
        PORT[.DEVICE].  PORT and DEVICE are decimal numbers
        matching port, link or device.  Basically, it matches
        the ATA ID string printed on console by libata.  If
        the whole ID part is omitted, the last PORT and DEVICE
        values are used.  If ID hasn't been specified yet, the
        configuration applies to all ports, links and devices.

        If only DEVICE is omitted, the parameter applies to
        the port and all links and devices behind it.  DEVICE
        number of 0 either selects the first device or the
        first fan-out link behind PMP device.  It does not
        select the host link.  DEVICE number of 15 selects the
        host link and device attached to it.

        The VAL specifies the configuration to force.  As long
        as there's no ambiguity shortcut notation is allowed.
        For example, both 1.5 and 1.5G would work for 1.5Gbps.
        The following configurations can be forced.

        * Cable type: 40c, 80c, short40c, unk, ign or sata.
          Any ID with matching PORT is used.

        * SATA link speed limit: 1.5Gbps or 3.0Gbps.

        * Transfer mode: pio[0-7], mwdma[0-4] and udma[0-7].
          udma[/][16,25,33,44,66,100,133] notation is also
          allowed.

        * [no]ncq: Turn on or off NCQ.

        * nohrst, nosrst, norst: suppress hard, soft
                      and both resets.

        * dump_id: dump IDENTIFY data.

        If there are multiple matching configurations changing
        the same attribute, the last one is used.

So, the tricky part is finding out which port X and device Y (dmesg ataX.YY) is which controller and drive. I think - that notation matches PORT[.DEVICE], but there's also the W:X:Y:Z notation. I'm guessing ataX.YY :)

Luckily, I just did this mapping manually last week (trying to identify a drive that was throwing spasms and resetting a host controller), so I have an exhaustive list already :) I couldn't find anywhere that the mappings from sdX to ataX.Y or W:X:Y:Z where listed, so I ended up simply yanking out SATA cables and watching which ataX.YY messages appeared in /var/log/messages ;)

So, in my setup, it seems I need to do

libata.force=1:1.5G,2:1.5G,3:1.5G

Gonna have to try that out as soon as my ZFS scrub finishes, and report back :) Awesome! Hope this helps someone else :)