Linux Device Drivers 3 / Драйверы устройств Линукс (третье издание): 17.7. The Interrupt Handler

Оглавление
Английский оригинал Перевод на русский

Сожалеем, но текст оригинала доступен только зарегистрированным пользователям.

17.7. Обработка прерываний

hardorsoft 26.10.10 в 02:54

0

Управление большинством устройств осуществляется через
прерывания. Аппаратное прерывание процессору сигнализирует об одном
из двух возможных событий: прибытие нового пакета или завершение
передачи пакета. Сетевой интерфейс может так же генерировать
прерывания при ошибках, изменении статуса соединения и т.д.

hardorsoft 26.10.10 в 02:54

0

Обычно обработчик прерывания проверяет регистр состояния
устройства, для определения причины прерывания. Аналогично работает
интерфейс snull, но слово состояния реализовано программно и
находится в dev->priv. Обработчик прерывания сетевого интерфейса
выглядит примерно так:

hardorsoft 26.10.10 в 02:54

0

static void snull_regular_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int statusword;
struct snull_priv *priv;
struct snull_packet *pkt = NULL;
/*
* как обычно проверяем указатель "device"
* чтобы убедится, что это действительно прерывание
* затем присваиваем "struct device *dev"
*/
struct net_device *dev = (struct net_device *)dev_id;
/* ... и проверяем аппаратуру*/
/* paranoid */
if (!dev)
return;
/* блокируем устройство */
priv = netdev_priv(dev);
spin_lock(&priv->lock);
/* Находим слово состояния: настоящее устройство использует */
/* инструкции ввода-вывода */
statusword = priv->status;
priv->status = 0;
if (statusword & SNULL_RX_INTR) {
/* send it to snull_rx for handling */
/* выполняем snull_rx для обработки */
pkt = priv->rx_queue;
if (pkt) {
priv->rx_queue = pkt->next;
snull_rx(dev, pkt);
}
}
if (statusword & SNULL_TX_INTR) {
/* передача завершена, освобождаем skb*/
priv->stats.tx_packets++;
priv->stats.tx_bytes += priv->tx_packetlen;
dev_kfree_skb(priv->skb);
}
/* разблокируем устройство */
spin_unlock(&priv->lock);
if (pkt) snull_release_buffer(pkt); /* выполняется вне блокировки*/
return;
}

hardorsoft 26.10.10 в 02:55

0

В первую очередь, обработчик убеждается в корректном значении
указателя на структуру net_device. Этот указатель приходит как
аргумент.

hardorsoft 26.10.10 в 02:55

0

Рассмотрим происходящее при завершении передачи пакета. В этом
случае обновляется статистика, и вызывается dev_kfree_skb для возврата,
более не нужного, буфера сокета системе. Есть 3 варианта этой функции.

hardorsoft 26.10.10 в 02:55

0

dev_kfree_skb(struct sk_buff *skb);

hardorsoft 26.10.10 в 02:55

0

Эта версия вызывается, если вы точно знаете, что не работаете в
контексте прерывания. Так как snull не имеет аппаратных
прерываний, мы используем эту версию.

hardorsoft 26.10.10 в 02:56

0

dev_kfree_skb_irq(struct sk_buff *skb);

hardorsoft 26.10.10 в 02:56

0

Если вы знаете что работаете в
используйте эту версию функции.

hardorsoft 26.10.10 в 02:56

0

dev_kfree_skb_any(struct sk_buff *skb);

hardorsoft 26.10.10 в 02:56

0

Эта версия может использоваться как в контексте прерывания, так и
вне его.

hardorsoft 26.10.10 в 02:56

0

В конце, если ваш драйвер приостанавливает очередь передачи, как
правило производят и повторный старт netif_wake_queue.

hardorsoft 26.10.10 в 02:57

0

Прием пакетов, в противоположность передачи, не нуждается в
специальной обработке прерывания. Все что требуется это вызов
snull_rx (который мы уже рассмотрели).

hardorsoft 26.10.10 в 02:57

0
Минутку...