Que fait request mem region() et quand cela est nécessaire?

J'étudie l'écriture de pilotes Linux embarqués, et j'ai décidé de lancer quelques GPIO pour m'assurer de comprendre le livre (ldd3, chap9.4.1) correctement.

Je suis capable de contrôler les broches GPIO correctes comme prévu (ce qui en fait haut et bas, j'ai sondé avec un multimètre); cependant, j'ai testé 2 morceaux de code, un avec request_mem_region(), et un sans. Je m'attends à ce que celui sans échouera, mais les deux fonctionnent très bien.

Code avec request_mem_region:

if( request_mem_region( PIN3_CONF_PHYS, MAPPED_SIZE_GPIO_CONF,DEVICE_NAME ) == NULL )
  {
    printk( KERN_ALERT
            "GPIO_140_141_conf_phys error:%s: unable to obtain I/O memory address 0x%08llXn",
            DEVICE_NAME, PIN3_CONF_PHYS );

    return -EBUSY;
  }

pin3_conf = (u32)ioremap( PIN3_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin4_conf = (u32)ioremap( PIN4_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin5_conf = (u32)ioremap( PIN5_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin6_conf = (u32)ioremap( PIN6_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
//-----------------------------------------------------------------
if( request_mem_region( GPIO_BANK5_PHYS, MAPPED_SIZE_GPIO_5,DEVICE_NAME ) == NULL )
  {
    printk( KERN_ALERT
            "error:%s: unable to obtain I/O memory address 0x%08llXn",
            DEVICE_NAME, GPIO_BANK5_PHYS );

    return -EBUSY;
  }

gpio_virt = (u32)ioremap( GPIO_BANK5_PHYS, MAPPED_SIZE_GPIO_5 );

//some iowrite32() functions continue...

Code sans request_mem_region():

pin3_conf = (u32)ioremap( PIN3_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin4_conf = (u32)ioremap( PIN4_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin5_conf = (u32)ioremap( PIN5_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin6_conf = (u32)ioremap( PIN6_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
gpio_virt = (u32)ioremap( GPIO_BANK5_PHYS, MAPPED_SIZE_GPIO_5 );
//some iowrite32() functions continue...

La seule différence que je peux observer dans les deux cas est le résultat de faire un cat /proc/iomem, celui avec request_mem_region() affichera une ligne supplémentaire montrant 49056000-49056097 : GPIO3.

Ma question est pourquoi request_mem_region() est nécessaire puisque je peux toujours communiquer avec l'adresse matérielle avec seulement ioremap()? Alors, quand devons - nous réellement utiliser request_mem_region()?

Merci pour toutes les réponses!

21
demandé sur caf 2011-10-07 06:09:54

2 réponses

request_mem_region indique au noyau que votre pilote va utiliser cette plage d'adresses d'E/S, ce qui empêchera les autres pilotes de faire tout appel se chevauchant vers la même région via request_mem_region. Ce mécanisme ne fait aucune sorte de mappage, c'est un mécanisme de réservation pur, qui repose sur le fait que tous les pilotes de périphériques du noyau doivent être gentils, et ils doivent appeler request_mem_region, vérifier la valeur de retour, et se comporter correctement en cas d'erreur.

Il est donc tout à fait logique que votre code fonctionne sans request_mem_region, c'est juste qu'il ne respecte pas les règles de codage du noyau.

Cependant, votre code n'est pas conforme au style de codage du noyau. De plus, il existe une infrastructure existante pour gérer les GPIO, nommée gpiolib, que vous devez utiliser au lieu de remapper manuellement vos registres bancaires GPIO. Sur quelle plateforme travaillez-vous ?

35
répondu Thomas Petazzoni 2014-02-05 07:16:30

L'utilisation de request_mem_region () et ioremap () dans les pilotes de périphériques est maintenant obsolète. Vous devez utiliser les fonctions "gérées" ci-dessous au lieu de cela, ce qui simplifie le codage du pilote et la gestion des erreurs:

devm_ioremap()
devm_iounmap()
devm_ioremap_resource(), Takes care of both the request and remapping operations

Https://bootlin.com/doc/training/linux-kernel/linux-kernel-slides.pdf diapositive 276

0
répondu jordi oliva 2018-07-12 12:11:22