LINUX.ORG.RU

Отключается обработка прерывания в 2.6.Х


0

0

Добры день.

Есть одноплатный компьютер на AMD Geode GX-466 с ISA шиной.
На ISA висит плата, к которой написан драйвер для Linux.
Эта железяка использует 10 прерывание. Пересобрано ядро под это
железо, собран busybox со всякими дополнениями на базе Slackware 12.0.

До определенного времени все работает нормально.
Но по приходу 100000 по счету прерывания ядро выключает 10 прерывание. Железо это прерывание продолжает генерить.

Вылезло это на ядре 2.6, на 2.4 все работало нормально.

Помогите плз рабобраться, с чем это может быть связано? Это проблема железа, ядра или драйвера?

Вся информация и отрывок кода драйвера ниже:

# uname -a
Linux b2-server 2.6.21.5 #5 Tue Feb 19 15:01:42 MSK 2008 i586 unknown

# cat /etc/slackware-version
Slackware 12.0.0

# cat /proc/cpuinfo
processor       : 0
vendor_id       : Geode by NSC
cpu family      : 5
model           : 5
model name      : Geode(TM) Integrated Processor by National Semi
stepping        : 2
cpu MHz         : 332.068
cache size      : 32 KB
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 1
wp              : yes
flags           : fpu de pse tsc msr cx8 pge cmov mmx mmxext 3dnowext 3dnow
bogomips        : 665.41
clflush size    : 32

# cat /proc/interrupts
           CPU0
  0:    5236436    XT-PIC-XT        timer
  1:          2    XT-PIC-XT        i8042
  2:          0    XT-PIC-XT        cascade
  4:     298120    XT-PIC-XT        serial
  8:          0    XT-PIC-XT        rtc
 10:     100000    XT-PIC-XT        MTK board  // престает работать именно на 100000
 11:    3403498    XT-PIC-XT        eth0
 12:          4    XT-PIC-XT        i8042
 14:          3    XT-PIC-XT        ide0
NMI:          0
LOC:          0
ERR:          1
MIS:          0

# dmesg

// ............

// ВСЕ РАБОТАЕТ НОРМАЛНО, НО
// ПОЧТИ С САМОГО НАЧАЛА В dmesg СЫПЕТСЯ СЛЕДУЮЩЕЕ:

irq event 10: bogus return value a
 [<c012ae4e>] __report_bad_irq+0x36/0x75
 [<c012aec2>] note_interrupt+0x35/0x1b7
 [<c012a6d2>] handle_IRQ_event+0x1a/0x3f
 [<c012b71c>] handle_level_irq+0x70/0x94
 [<c0104f54>] do_IRQ+0x57/0x73
 [<c0103587>] common_interrupt+0x23/0x28
 [<c012ab43>] setup_irq+0x14e/0x183
 [<c0116cc0>] __request_region+0x4f/0x6f
 [<c8814755>] mtk_interrupt+0x0/0x58b [mtk]
 [<c012abed>] request_irq+0x75/0x90
 [<c88146f9>] open_mtk+0xbc/0x118 [mtk]
 [<c8814755>] mtk_interrupt+0x0/0x58b [mtk]
 [<c0145961>] chrdev_open+0xc2/0xe7
 [<c014589f>] chrdev_open+0x0/0xe7
 [<c01427aa>] __dentry_open+0xb4/0x160
 [<c01428cb>] nameidata_to_filp+0x24/0x33
 [<c0142911>] do_filp_open+0x37/0x3e
 [<c014295f>] do_sys_open+0x47/0xcf
 [<c0142a20>] sys_open+0x1c/0x1e
 [<c0102bec>] syscall_call+0x7/0xb
 [<c02b0000>] call_connect_status+0x6f/0xa1
 =======================
handlers:
[<c8814755>] (mtk_interrupt+0x0/0x58b [mtk])
irq event 10: bogus return value 57
 [<c012ae4e>] __report_bad_irq+0x36/0x75
 [<c012aec2>] note_interrupt+0x35/0x1b7
 [<c012a6d2>] handle_IRQ_event+0x1a/0x3f
 [<c012b71c>] handle_level_irq+0x70/0x94
 [<c0104f54>] do_IRQ+0x57/0x73
 [<c012c09a>] file_read_actor+0x0/0xf2
 [<c0103587>] common_interrupt+0x23/0x28
 [<c0143b0f>] do_sync_read+0xc7/0x10a
 [<c01357c9>] __handle_mm_fault+0x273/0x69c
 [<c01207ac>] autoremove_wake_function+0x0/0x35
 [<c010e908>] do_page_fault+0x0/0x514
 [<c0143a48>] do_sync_read+0x0/0x10a
 [<c0144285>] vfs_read+0x8a/0x10d
 [<c01469d2>] kernel_read+0x37/0x48
 [<c01653ba>] load_elf_binary+0xa1f/0x1356
 [<c01428cb>] nameidata_to_filp+0x24/0x33
 [<c01d68ed>] copy_from_user+0x2b/0x57
 [<c01467c8>] copy_strings+0x170/0x1b7
 [<c014688c>] search_binary_handler+0x56/0x156
 [<c0147c3a>] do_execve+0x130/0x19e
 [<c0101639>] sys_execve+0x31/0x5f
 [<c0102bec>] syscall_call+0x7/0xb
 [<c02b0000>] call_connect_status+0x6f/0xa1
 =======================
handlers:
[<c8814755>] (mtk_interrupt+0x0/0x58b [mtk])

// далее несколько раз повторяются аналогичные сообщения

// И НА 100000 ПРЕРЫВАНИИ (несколько часов работы):

irq 10: nobody cared (try booting with the "irqpoll" option)
 [<c012ae4e>] __report_bad_irq+0x36/0x75
 [<c012b007>] note_interrupt+0x17a/0x1b7
 [<c011ec68>] __rcu_process_callbacks+0xcf/0x12e
 [<c012a6d2>] handle_IRQ_event+0x1a/0x3f
 [<c012b71c>] handle_level_irq+0x70/0x94
 [<c0104f54>] do_IRQ+0x57/0x73
 [<c02be3c8>] __sched_text_start+0x490/0x4f3
 [<c0103587>] common_interrupt+0x23/0x28
 [<c0101bb4>] default_idle+0x0/0x39
 [<c0101bdb>] default_idle+0x27/0x39
 [<c01013f1>] cpu_idle+0x37/0x4c
 [<c037cad1>] start_kernel+0x335/0x33d
 [<c037c42f>] unknown_bootoption+0x0/0x205
 =======================
handlers:
[<c8814755>] (mtk_interrupt+0x0/0x58b [mtk])
Disabling IRQ #10


Кусок кода драйвера:

#define MTK_INT_ON()    mtkint_allowed = 1
#define MTK_INT_OFF()   mtkint_allowed = 0

static void mtk_interrupt(int irq, void *dummy, struct pt_regs *fp) {

  if (!mtkint_allowed)
    return;

  MTK_INT_OFF();
  
  // обработка прерывания
  
  MTK_INT_ON();
}

// ....

static int open_mtk(struct inode *inode, struct file *file) {

  try_module_get(THIS_MODULE);
  printk(KERN_INFO "Open request\n");
  if (mtk.active++)
      return 0;

  // .......

  printk("Mtk board active\n");
  if (request_irq(MTK_IRQ, mtk_interrupt, 0, "MTK board", mtk_interrupt)) {
      printk(KERN_INFO "mtk: request IRQ failed.\n");
      module_put(THIS_MODULE);
      return -EIO;
  }

  // .......

  MTK_HWINT_ON();
  return 0;
}

// .........

struct file_operations mtk_board_fops =
{
  read: read_mtk,
  write: write_mtk,
  ioctl: mtk_ioctl,
  open: open_mtk,
  release: release_mtk,
  fasync: fasync_mtk
};

int mtk_init(void) {
  MTK_HWINT_OFF();
  if (register_chrdev(DRV_MAJOR, "mtk", &mtk_board_fops)) {
      printk("mtk: unable to get major = %d\n", DRV_MAJOR);
      return -EBUSY;
  } else {
      printk(KERN_INFO "mtk: installed.\n");

      // ............

      return 0;
    }
}

module_init(mtk_init);
module_exit(mtk_cleanup);
MODULE_LICENSE("GPL");

Всем спасибо заранее.
★★

Ой, блин... Как это вообще в ядре живет то? Запомните и повторяйте как мантру: "обработчик прерывания обязан иметь тип irqreturn_t и возвращать соответствующее значение", в вашем случае IRQ_HANDLED. У вас ядро именно на это ругается. Вместо MTK_INT_OFF и MTK_INT_ON использовать irq disable/enable функции, а вообще лучше вынести в bottom-half. Это то, что на поверхности.

А на последок почитать LDDv3 и ещё какой литературы по предмету.

jr_A
()
Ответ на: комментарий от jr_A

Спасибо большое. Сейчас буду пробовать...

ps:

> Как это вообще в ядре живет то

Сам удивляюсь :)

Это было написано еще для 2.2, потом правилось для 2.4. А для 2.6 правил все это один товаришь, вроде заработало... Обязательно скажу ему, чтобы он больше ничего так не правил :) Потом не было времени трогать то, что вроде работает. Придется все же трогать...

Сравнил ldd2 и ldd3 и правда в 2.4 handler имеет тип void а в 2.6 irqreturn_t.

Пойду переписывать...

samson ★★
() автор топика
Ответ на: комментарий от samson

Кстати и цифра 100000 не случайна. Именно при возникновении такого (почти) количества ложных прерываний ядро отключает линию считая что аппаратура глючит. Подробно об этом сказано в Understanding Linux Kernel .

karak
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.