From: Hans de Goede <hdegoede@redhat.com>
To: Adrian Hunter <adrian.hunter@intel.com>,
Ulf Hansson <ulf.hansson@linaro.org>
Cc: linux-mmc@vger.kernel.org
Subject: Re: [PATCH v3] mmc: sdhci-pci: Add DMI quirk for missing CD GPIO on Vexia Edu Atla 10 tablet
Date: Mon, 18 Nov 2024 12:53:57 +0100 [thread overview]
Message-ID: <5535807c-ce12-45a7-a7ea-44c03474e692@redhat.com> (raw)
In-Reply-To: <686a5c43-ac82-4506-ade8-e666a538abd5@intel.com>
Hi,
On 18-Nov-24 11:10 AM, Adrian Hunter wrote:
> On 16/11/24 13:25, Hans de Goede wrote:
>> Hi Adrian,
>>
>> On 15-Nov-24 8:33 AM, Adrian Hunter wrote:
>>> On 14/11/24 17:56, Hans de Goede wrote:
>>>> The Vexia Edu Atla 10 tablet distributed to schools in the Spanish
>>>> Andalucía region has no ACPI fwnode associated with the SDHCI controller
>>>> for its microsd-slot and thus has no ACPI GPIO resource info.
>>>>
>>>> This causes the following error to be logged and the slot to not work:
>>>> [ 10.572113] sdhci-pci 0000:00:12.0: failed to setup card detect gpio
>>>>
>>>> Add a DMI quirk table for providing gpiod_lookup_tables with manually
>>>> provided CD GPIO info and use this DMI table to provide the CD GPIO info
>>>> on this tablet. This fixes the microsd-slot not working.
>>>>
>>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>> ---
>>>> Changes in v3:
>>>> - Add a cd_gpio_override pointer to sdhci_pci_fixes
>>>> - Add sdhci_pci_add_gpio_lookup_table() helper which kmemdup-s a const
>>>> struct gpiod_lookup_table to avoid races when using async probing
>>>>
>>>> Changes in v2:
>>>> - Make sdhci_pci_dmi_cd_gpio_overrides static const instead of just const
>>>> - Drop duplicate #include <linux/dmi.h> (already there at the end)
>>>> ---
>>>> drivers/mmc/host/sdhci-pci-core.c | 67 +++++++++++++++++++++++++++++++
>>>> drivers/mmc/host/sdhci-pci.h | 1 +
>>>> 2 files changed, 68 insertions(+)
>>>>
>>>> diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
>>>> index ed45ed0bdafd..a2ddbe3d8742 100644
>>>> --- a/drivers/mmc/host/sdhci-pci-core.c
>>>> +++ b/drivers/mmc/host/sdhci-pci-core.c
>>>> @@ -21,6 +21,7 @@
>>>> #include <linux/io.h>
>>>> #include <linux/iopoll.h>
>>>> #include <linux/gpio.h>
>>>> +#include <linux/gpio/machine.h>
>>>> #include <linux/pm_runtime.h>
>>>> #include <linux/pm_qos.h>
>>>> #include <linux/debugfs.h>
>>>> @@ -1235,6 +1236,29 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
>>>> .priv_size = sizeof(struct intel_host),
>>>> };
>>>>
>>>> +/* DMI quirks for devices with missing or broken CD GPIO info */
>>>> +static const struct gpiod_lookup_table vexia_edu_atla10_cd_gpios = {
>>>> + .dev_id = "0000:00:12.0",
>>>> + .table = {
>>>> + GPIO_LOOKUP("INT33FC:00", 38, "cd", GPIO_ACTIVE_HIGH),
>>>> + { }
>>>> + },
>>>> +};
>>>
>>> This is good but I feel like we should make it more difficult
>>> to get the size wrong. Could introduce another struct to hold
>>> the size:
>>>
>>> struct sdhci_pci_gpio_data {
>>> const struct gpiod_lookup_table *gpios;
>>> size_t size;
>>> };
>>>
>>> static const struct sdhci_pci_gpio_data vexia_edu_atla10_cd_gpio_data = {
>>> .gpios = &vexia_edu_atla10_cd_gpios,
>>> .size = sizeof(vexia_edu_atla10_cd_gpios),
>>> };
>>>
>>> So:
>>> .driver_data = (void *)&vexia_edu_atla10_cd_gpio_data,
>>> and
>>> struct sdhci_pci_gpio_data *data;
>>> ...
>>> data = dmi_id->driver_data;
>>>
>>> cd_gpio_lookup_table = kmemdup(data->gpios, data->size, GFP_KERNEL);
>>
>> Interesting idea. But I'm afraid that sizeof(variable-name) on a struct
>> with a flexible array member returns the same as just sizeof(struct struct-name)
>> I added the following debug print to verify this:
>>
>> static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
>> {
>> + pr_info("sizeof(vexia_edu_atla10_cd_gpios) %lu sizeof(struct gpiod_lookup_table) %lu\n",
>> + sizeof(vexia_edu_atla10_cd_gpios), sizeof(struct gpiod_lookup_table));
>> byt_probe_slot(slot);
>> slot->host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY |
>> MMC_CAP_AGGRESSIVE_PM | MMC_CAP_CD_WAKE;
>>
>> And that prints:
>>
>> [ 10.459681] sizeof(vexia_edu_atla10_cd_gpios) 24 sizeof(struct gpiod_lookup_table) 24
>>
>> So using sizeof(vexia_edu_atla10_cd_gpios) to get the size including the 2
>> flexible array members does not work since sizeof() does not take into
>> account the size of the flexible array members.
>
> Thanks for spotting that!
>
> Perhaps we should check the table size then?
> e.g.
> struct gpiod_lookup_table *table;
> size_t count;
>
> ...
>
> table = dmi_id->driver_data;
> for (count = 0; table->table[count].key; count++)
> ;
> if (count != 1)
> return ERR_PTR(-EINVAL);
That works for me, but why not just use the found count instead of
returning -EINVAL ?
Regards,
Hans
>
>>>
>>>> +
>>>> +static const struct dmi_system_id sdhci_intel_byt_cd_gpio_override[] = {
>>>> + {
>>>> + /* Vexia Edu Atla 10 tablet 9V version */
>>>> + .matches = {
>>>> + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
>>>> + DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
>>>> + /* Above strings are too generic, also match on BIOS date */
>>>> + DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"),
>>>> + },
>>>> + .driver_data = (void *)&vexia_edu_atla10_cd_gpios,
>>>> + },
>>>> + { }
>>>> +};
>>>> +
>>>> static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
>>>> #ifdef CONFIG_PM_SLEEP
>>>> .resume = byt_resume,
>>>> @@ -1253,6 +1277,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
>>>> .add_host = byt_add_host,
>>>> .remove_slot = byt_remove_slot,
>>>> .ops = &sdhci_intel_byt_ops,
>>>> + .cd_gpio_override = sdhci_intel_byt_cd_gpio_override,
>>>> .priv_size = sizeof(struct intel_host),
>>>> };
>>>>
>>>> @@ -2054,6 +2079,37 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = {
>>>> * *
>>>> \*****************************************************************************/
>>>>
>>>> +static struct gpiod_lookup_table *sdhci_pci_add_gpio_lookup_table(
>>>> + struct sdhci_pci_chip *chip)
>>>
>>> Let's not line wrap until 100 columns
>>>
>>>> +{
>>>> + struct gpiod_lookup_table *cd_gpio_lookup_table;
>>>> + const struct dmi_system_id *dmi_id = NULL;
>>>> +
>>>> + if (chip->fixes && chip->fixes->cd_gpio_override)
>>>> + dmi_id = dmi_first_match(chip->fixes->cd_gpio_override);
>>>> +
>>>> + if (!dmi_id)
>>>> + return NULL;
>>>> +
>>>> + cd_gpio_lookup_table = kmemdup(dmi_id->driver_data,
>>>> + /* 1 GPIO lookup entry + 1 terminating entry */
>>>> + struct_size(cd_gpio_lookup_table, table, 2),
>>>> + GFP_KERNEL);
>>>> + if (!cd_gpio_lookup_table)
>>>> + return ERR_PTR(-ENOMEM);
>>>> +
>>>> + gpiod_add_lookup_table(cd_gpio_lookup_table);
>>>> + return cd_gpio_lookup_table;
>>>> +}
>>>> +
>>>> +static void sdhci_pci_remove_gpio_lookup_table(struct gpiod_lookup_table *lookup_table)
>>>> +{
>>>> + if (lookup_table) {
>>>> + gpiod_remove_lookup_table(lookup_table);
>>>> + kfree(lookup_table);
>>>> + }
>>>> +}
>>>> +
>>>> static struct sdhci_pci_slot *sdhci_pci_probe_slot(
>>>> struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar,
>>>> int slotno)
>>>> @@ -2129,8 +2185,19 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
>>>> device_init_wakeup(&pdev->dev, true);
>>>>
>>>> if (slot->cd_idx >= 0) {
>>>> + struct gpiod_lookup_table *cd_gpio_lookup_table;
>>>> +
>>>> + cd_gpio_lookup_table = sdhci_pci_add_gpio_lookup_table(chip);
>>>> + if (IS_ERR(cd_gpio_lookup_table)) {
>>>> + ret = PTR_ERR(cd_gpio_lookup_table);
>>>> + goto remove;
>>>> + }
>>>> +
>>>> ret = mmc_gpiod_request_cd(host->mmc, "cd", slot->cd_idx,
>>>> slot->cd_override_level, 0);
>>>> +
>>>> + sdhci_pci_remove_gpio_lookup_table(cd_gpio_lookup_table);
>>>> +
>>>> if (ret && ret != -EPROBE_DEFER)
>>>> ret = mmc_gpiod_request_cd(host->mmc, NULL,
>>>> slot->cd_idx,
>>>> diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
>>>> index 153704f812ed..4973fa859217 100644
>>>> --- a/drivers/mmc/host/sdhci-pci.h
>>>> +++ b/drivers/mmc/host/sdhci-pci.h
>>>> @@ -156,6 +156,7 @@ struct sdhci_pci_fixes {
>>>> #endif
>>>>
>>>> const struct sdhci_ops *ops;
>>>> + const struct dmi_system_id *cd_gpio_override;
>>>> size_t priv_size;
>>>> };
>>>>
>>>
>>
>
next prev parent reply other threads:[~2024-11-18 11:54 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-14 15:56 [PATCH v3] mmc: sdhci-pci: Add DMI quirk for missing CD GPIO on Vexia Edu Atla 10 tablet Hans de Goede
2024-11-15 7:33 ` Adrian Hunter
2024-11-16 11:25 ` Hans de Goede
2024-11-18 10:10 ` Adrian Hunter
2024-11-18 11:53 ` Hans de Goede [this message]
2024-11-18 12:11 ` Adrian Hunter
2024-11-18 12:12 ` Hans de Goede
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5535807c-ce12-45a7-a7ea-44c03474e692@redhat.com \
--to=hdegoede@redhat.com \
--cc=adrian.hunter@intel.com \
--cc=linux-mmc@vger.kernel.org \
--cc=ulf.hansson@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.