10

I'm trying to rescue data from an SDHC card using ddrescue:

while true ; do ddrescue -d /dev/mmcblk0p1 mmc.img mmc.log ; done

The controller, I'm not sure if it's the one on the card or the one in my laptop, seems to return errors for all sectors (which shows up in syslog) after a certain number of bad sectors have been read (which don't show up in syslog), I found that popping the card out and into the slot again resets this and reports good sectors as good again until too many bad sectors have been read, and so on.

Currently I'm using this loop, keeping an eye on ddrescue's status output, resetting the card manually. Is there a way to reset the controller without removing the card, so the rescue process can run unattended?

Maybe this is related, but in this Dell laptop, for the reader to even notice a card has been inserted it must be done during boot or using echo 1 > /sys/bus/pci/rescan, but only once, after that the reader PCI device appears, and everything works as expected:

07:00.0 System peripheral: JMicron Technology Corp. SD/MMC Host Controller (rev 30)
        Subsystem: Dell Device 046e
        Flags: bus master, fast devsel, latency 0, IRQ 16
        Memory at f0600000 (32-bit, non-prefetchable) [size=256]
        Capabilities: [a4] Power Management version 3
        Capabilities: [80] Express Endpoint, MSI 00
        Capabilities: [94] MSI: Enable- Count=1/1 Maskable- 64bit-
        Kernel driver in use: sdhci-pci

Relevant syslog:

# pop in card
mmc0: new SDHC card at address b368
mmcblk0: mmc0:b368 NCard 15.0 GiB (ro)
mmcblk0: p1
# ddrescue begins to read, error count increases, until at some point:
mmcblk0: error -110 transferring data, sector 12854624, nr 1, cmd response 0x900, card status 0x0
end_request: I/O error, dev mmcblk0, sector 12854624
mmcblk0: error -110 transferring data, sector 12854625, nr 1, cmd response 0x900, card status 0x0
end_request: I/O error, dev mmcblk0, sector 12854625
mmcblk0: error -110 transferring data, sector 12854626, nr 1, cmd response 0x900, card status 0x0
end_request: I/O error, dev mmcblk0, sector 12854626
mmcblk0: error -110 transferring data, sector 12854627, nr 1, cmd response 0x900, card status 0x0
end_request: I/O error, dev mmcblk0, sector 12854627
mmcblk0: error -110 transferring data, sector 12854628, nr 1, cmd response 0x900, card status 0x0
end_request: I/O error, dev mmcblk0, sector 12854628
# time since last successful read increases, pop out card
mmc0: Card removed during transfer!
mmc0: Resetting controller.
mmcblk0: error -123 sending status command, retrying
mmcblk0: error -123 sending status command, retrying
mmcblk0: error -123 sending status command, aborting
mmc0: card b368 removed
# GOTO 10

I also tried using a USB card reader, instead of generating these errors in syslog, it just disappears and needs to be re-plugged to continue.


It seems reloading the sdhci_pci module does the trick, but I wonder if there's a less brute-force option to do this:

while sleep 1 ; do
    ddrescue -d -T 1 /dev/mmcblk0p1 mmc.img mmc.log 
    modprobe -r sdhci_pci
    modprobe sdhci_pci
done

2 Answers 2

6

I had the same issue (I/O errors as shown above) after changing SD-cards on the fly in an embedded device (Kobo eBook Reader). It would not detect the new card, its capacity, and so on and instead expect the old card to be still present.

Reloading a module was not possible since the driver was built-in. device/delete or host/scan was not available. Setting a "removable" module parameter did not make it work.

The solution in my case was to unbind, and subsequently bind, the driver for the MMC block device.

# blockdev --getsize64 /dev/mmcblk0
3965190144
# readlink /sys/block/mmcblk0
../devices/platform/mxsdhci.2/mmc_host/mmc0/mmc0:af9e/block/mmcblk0
# echo mxsdhci.2 > /sys/bus/platform/drivers/mxsdhci/unbind
~~~ change card ~~~
# echo mxsdhci.2 > /sys/bus/platform/drivers/mxsdhci/bind
# blockdev --getsize64 /dev/mmcblk0
8168931328

The nice thing is this only affects the device you're interested in. If there's another card in the external slot (same driver, /dev/mmcblk1) it is unaffected.

1
  • 1
    This also works for "non-removable" cards like eMMC, so if you have a GPIO to power them on/off you can use this same trick.
    – Compholio
    Feb 22, 2022 at 0:16
2

You could try resetting a SATA device using the following steps:

Assuming the device is named: /dev/mmcblk0p1.

  1. Find out which controller the device is attached to (we’ll need this later):

    $ readlink /sys/block/mmcblk0p1
     ../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/mmcblk0p1
    

    NOTE: The interesting part if the answer is host1, which identifies the controller.

  2. Disconnect the device

    $ echo 1 > /sys/block/mmcblk0p1/device/delete
    

    NOTE: This will remove the device from the bus (logically). Look in dmesg for confirmation.

  3. Rescan the controller

    $ echo "- - -" > /sys/class/scsi_host/host1/scan
    

    NOTE: host1 is the identifier from step one. Again, dmesg should show the device being rediscovered.

References

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.