Que fait réellement request_mem_region () et quand est-il nécessaire?

J’étudie l’écriture de pilote Linux intégré et j’ai décidé de renvoyer quelques GPIO pour m’assurer de bien comprendre le livre (LDD3, chap9.4.1) .

Je suis capable de contrôler les broches GPIO correctes comme prévu (le rendant 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 l’un sans échoue, 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%08llX\n", 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%08llX\n", 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 la commande cat /proc/iomem , celle avec request_mem_region() affichera une ligne supplémentaire indiquant 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!

request_mem_region indique au kernel que votre pilote va utiliser cette plage d’adresses d’E / S, ce qui empêchera les autres pilotes d’appeler de manière chevauchante l’appel de la même région via request_mem_region . Ce mécanisme ne fait aucun type de mappage, c’est un mécanisme de réservation pur qui repose sur le fait que tous les pilotes de périphérique du kernel doivent être agréables, qu’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 simplement qu’il ne respecte pas les règles de codage du kernel.

Cependant, votre code n’est pas conforme au style de codage du kernel. 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 de banque GPIO. Sur quelle plateforme travaillez-vous?

L’utilisation de request_mem_region () et ioremap () dans les pilotes de périphérique est maintenant obsolète. Vous devez utiliser les fonctions “gérées” ci-dessous, qui simplifient le codage des pilotes 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