-
Ben Avison authored
The operation state machine is now polled both when the HAL device's specified interrupt fires, and also on TickerV. TickerV is the minimum requirement to enable background transfers, since some state changes (not least timeouts) won't generate a device interrupt, so would otherwise never complete. Some existing implementations of HAL devices don't specify the interrupt number correctly. If we were to enable interrupts in the SD controller for these, we wouldn't be acking the correct interrupt in the interrupt controller. The kernel's default interrupt handler traditionally disabled unhandled interrupt sources, but this no longer seems to work and we end up in an infinite loop as kernel interrupt dispatch unwinds with the interrupt still pending. Even if this were fixed, failing to ack a genuine interrupt would still be undesirable behaviour in the case of shared interrupt lines, because then the other interrupts sharing the line would be collateral damage. To avoid this pitfall in the case where a new SDIODriver is loaded on an old HAL, we check for a new minor HAL device version number which indicates the interrupt number is known to be good. If the version number is too old, we implement background transfers using TickerV alone. Be warned that this can be quite slow - each operation wil typically then take 10 ms or longer. To improve foreground transfer performance in these cases, or with certain controllers (such as the BCM2835 "SDHOST" controller) that commonly change state without generating an interrupt, we also retain a poll loop during foreground transfers. To avoid a race condition between this poll loop and interrupt dispatch, which can cause deadlock in the uniprocessor case or an SMP case where the foreground transfer is being performed on the same core as the interrupt handler, the `doing_poll` mutex is upgraded to a spinrw write lock. Because this lock type disables IRQs on the local core, this in turn has an impact on interrupt latency during a foreground operation. To partially address this, the rate of polling is throttled (to an arbitrarily chosen 100,000 polls per second) rather than just being as fast as possible, as previously. Add a test program (implemented as a module to *RMRun) to measure the comparative speed of an example SD command issued as both foreground and background operations. To ensure this is safe for all devices, the command used is CMD0_GO_IDLE_STATE - but note that this will leave the device in question dormant, so you probably want to execute it from a non-SDFS filing system. Example timings for a Raspberry Pi driving the memory card bus look like this: SDIODriver HAL Controller Foreground frequency Background frequency Old Any SDHCI ~57,000 0 (never completes) New Old SDHCI ~37,000 100 New New SDHCI ~44,000 ~46,000 New New SDHOST ~63,000 100
81c583d7