2017-01-20 4 views
0

J'essaie d'enregistrer correctement l'interruption dans le noyau pour l'interface utilisateur. Étonnamment, je n'ai pas trouvé beaucoup d'exemples dans le noyau pour cela.Gestion des interruptions dans le périphérique de caractères

gestionnaire irq

static irqreturn_t irq_handler(int irq, void *dev_id) 
{ 
    struct el_irq_dev *el_irq = &el_irq_devices[0]; 
    printk("irq in\n"); 

    spin_lock(&el->my_lock,flags); 

    clear_interrupt() 

    some_buffer[buf_wr] = ch; 
    el_irq->buf_wr++; 
    if (el_irqbuf_wr >= 16) 
     el_irqbuf_wr = 0; 


    spin_unlock(&el->my_lock,flags); 
    wake_up_interruptible(&el->pollw); 



return IRQ_HANDLED; 

}

ioctl pour attendre des interruptions

static long el_device_ioctl(struct file *filp, 
     unsigned int ioctl_num, 
     unsigned long ioctl_param) 
{ 
    struct el_irq_dev *el_irq = &el_irq_devices[0]; 
switch (ioctl_num) { 
case IOCTL_WAIT_IRQ:  <<<---- using ioctl (no poll) to wait on interrupt 
    wait_event_interruptible(el_irq->pollw, &el_irq->buf_wr != &el_irq->buf_rd) ; 
    spin_lock(&el_irq->my_lock); 
    if (el_irq->buf_wr != &el_irq->buf_rd) 
    { 
     my_value=some_buffer[el_irq->buf_rd]; 
     el_irq->buf_rd++; 
     if (el_irq->buf_rd >= 16) 
      el_irq->buf_rd = 0; 
    } 

    spin_unlock(&el_irq->my_lock); 
    copy_to_user(ioctl_param,&my_value,sizeof(my_value)); 

default: 
     break; 
    } 
    return 0; 
} 

Ma question est:

  1. Faut-il mettre le clair des interruptions (clear_interrupt ()) dans fpga dans l'interruption avant ou après le wake_up? Pouvons-nous mettre l'interruption d'effacement dans le gestionnaire d'espace utilisateur (IOCTL_WAIT_IRQ) ​​au lieu d'effacer l'interruption dans le gestionnaire d'interruption ?
  2. Comme vous pouvez le voir dans le code, j'utilise un tampon cyclique afin de gérer les cas où le gestionnaire d'espace utilisateur manque d'interruptions. Est-ce vraiment nécessaire ou pouvons-nous supposer qu'il n'y a pas de manque? En d'autres termes, est-il raisonnable de supposer qu'il ne devrait jamais être manqué d'interruptions? de sorte que l'appel ioctl ne devrait jamais voir plus de 1 interruption en attente? Si oui, peut-être que je n'ai pas besoin de mécanisme de tampon entre le gestionnaire d'interruption et le gestionnaire ioctl.

Merci, Ran

+0

Pourquoi avez-vous besoin de tout ce en premier lieu? – 0andriy

+0

Nous avons l'espace mémoire fpga, et plutôt faire la plupart des pilotes dans l'espace utilisateur à la place, et juste signaler l'interruption à l'espace utilisateur du noyau – ransh

+0

Quel type de mémoire? Objectif général? Pourquoi ne pas utiliser DMA dans le pilote du noyau pour cela? – 0andriy

Répondre

1

Réponse courte.

  1. Il me semble raisonnable d'effacer les interruptions dans le gestionnaire d'espace utilisateur. Cela a du sens de le faire le plus tard possible, après tout le travail, tant que vous vérifiez à nouveau qu'il n'y a plus de travail à faire (un peu plus de travail est peut-être arrivé juste avant la compensation).
  2. Le gestionnaire d'espace utilisateur peut en effet manquer des interruptions, par ex. si plusieurs arrivent entre les appels à IOCTL_WAIT_IRQ. Les interruptions peuvent également être "ratées" dans un certain sens, mais si plusieurs tâches arrivent avant que les interruptions soient effacées. La pile (matériel et logiciel) doit être conçue de telle sorte que ce n'est pas un problème. Une interruption devrait simplement signaler qu'il y a du travail à faire, et le gestionnaire d'espace utilisateur devrait être capable de faire tout le travail en suspens avant de revenir.
  3. Vous devriez probablement utiliser spin_lock_irqsave() dans votre code IOCtl [1].

[1] http://www.makelinux.net/ldd3/chp-5-sect-5

+0

Merci pour la réponse détaillée. Est-il raisonnable de supposer qu'il ne devrait jamais y avoir d'interruptions manqués? c'est-à-dire que l'ioctl ne devrait jamais voir plus d'une interruption en attente? Si oui - peut-être que je n'ai pas besoin de mécanisme de tampon entre le gestionnaire d'interruption et l'ioctl – ransh

+0

Vous ne savez pas exactement ce que vous entendez par "interruptions manqués" ici. Le plus simple est de faire en sorte que le gestionnaire IOCtl (ne vous préoccupez pas de mes majuscules, il existe plusieurs variantes) retourne dès qu'il y a eu au moins une interruption depuis le dernier clear_interrupts().Mais le gestionnaire d'espace utilisateur devrait supposer qu'il y a eu plusieurs interruptions depuis la dernière fois que le IOCtl est retourné, et il devrait y avoir un moyen pour le gestionnaire d'espace utilisateur de découvrir tout le travail que ces interruptions signalaient. – michaeljt

+0

donc je suppose que le mécanisme de tampon que j'ai utilisé dans cet exemple (some_buffer), est tout à fait essentiel. – ransh