2012-04-28 13 views
20

Tengo un dispositivo con almacenamiento flash SPI Me gustaría utilizar un sistema de archivos UBIFS en ese dispositivo flash como mi rootfs. El problema que estoy enfrentando es que el módulo UBI se inicializa antes de que el módulo SPI se inicialice. Debido a esto, cuando UBI se carga, no se puede conectar al dispositivo UBI que le dije (a través de la línea de comandos del núcleo), por lo que no hay rootfs. La salida de la consola a continuación ilustra esto.¿Cómo determina Linux el orden de las llamadas al módulo init?

He estado buceando en la fuente lo suficiente como para ver que init/main.c tiene una función do_initcalls() que simplemente llama a una lista de punteros a funciones. Esos indicadores de función apuntan a todas las funciones module_init() de los módulos que están incorporados en el kernel. Esos punteros de función se colocan en una sección especial en el núcleo binario, por lo que este orden se elige en tiempo de compilación. Sin embargo, todavía no he descubierto cómo se determina ese orden.

[ 0.482500] UBI error: ubi_init: UBI error: cannot initialize UBI, error -19 
    [ 0.492500] atmel_spi atmel_spi.0: Using dma0chan0 (tx) and dma0chan1 (rx) for DMA transfers 
    [ 0.500000] atmel_spi atmel_spi.0: Atmel SPI Controller at 0xf0000000 (irq 13) 
    [ 0.507500] m25p80 spi0.1: mx25l25635e (32768 Kbytes) 
    [ 0.512500] Creating 7 MTD partitions on "jedec_flash": 
    [ 0.520000] 0x000000000000-0x000000020000 : "loader" 
    [ 0.527500] 0x000000020000-0x000000060000 : "u-boot" 
    [ 0.537500] 0x000000060000-0x000000080000 : "u-boot-env" 
    [ 0.547500] 0x000000080000-0x000000280000 : "kernel0" 
    [ 0.557500] 0x000000280000-0x000000480000 : "kernel1" 
    [ 0.567500] 0x000000480000-0x000001240000 : "fs" 
    [ 0.575000] 0x000001240000-0x000002000000 : "play" 
    [ 0.590000] AT91SAM9 Watchdog enabled (heartbeat=15 sec, nowayout=0) 
    [ 0.607500] TCP cubic registered 
    [ 0.615000] VFS: Cannot open root device "ubi0:root0" or unknown-block(0,0) 
    [ 0.622500] Please append a correct "root=" boot option; here are the available partitions: 
    [ 0.630000] 1f00    128 mtdblock0 (driver?) 
    [ 0.635000] 1f01    256 mtdblock1 (driver?) 
    [ 0.640000] 1f02    128 mtdblock2 (driver?) 
    [ 0.645000] 1f03   2048 mtdblock3 (driver?) 
    [ 0.650000] 1f04   2048 mtdblock4 (driver?) 
    [ 0.655000] 1f05   14080 mtdblock5 (driver?) 
    [ 0.660000] 1f06   14080 mtdblock6 (driver?) 
    [ 0.665000] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) 
+0

He encuentra en posición de migración a [así], porque a pesar de esto no puede requiere modificación del código fuente, requiere al menos trucos de Kbuild. También [así] es donde están los expertos. Sospecho que no debes depender de un pedido en particular y que el controlador de UBI no debe intentar acceder a ningún dispositivo hasta que se le indique que monte algo. – Gilles

+0

posible duplicado de [LINUX: orden de la carga del módulo enlazado estáticamente] (http://stackoverflow.com/questions/5669647/linux-order-of-statically-linked-module-loading) que sugiere que debe asegurarse de que los módulos ocurrir en el (árbol de) makefiles en el orden de inicialización deseado. –

+0

Puede haber una solución alternativa al problema usando 'EPROBE_DEFER'; Estaré revisando eso. –

Respuesta

0

Podría estar equivocado, así que por favor verifique si esto es correcto.
Intente compilar todos los controladores que necesita como módulos (M) y ponga los módulos a cargar en/etc/modules, en el orden correcto, esto podría resolver su problema. Para ser precisos, porque está haciendo esto antes de su rootfs está montado, el paso anterior debería hacerse en el disco de inicio. (Tengo un escenario similar y tengo que cargar algunos módulos en el orden correcto, para ser capaz de descifrar un fs)

espero que esto ayude
ciaociao
Sergio

+1

No funcionará compilarlos como módulos separados porque pondría los módulos en el sistema de archivos raíz. Estos módulos de los que estoy hablando son para montar el sistema de archivos raíz. –

+0

@ ShawnJ.Goff: edité la publicación, ya que me di cuenta de que olvidé mencionar un detalle importante. La parte initramfs :) – sergico

+0

Un initramfs no es una opción, aumenta el tamaño de mi compilación en una cantidad inaceptable. –

32

Las rutinas de inicialización para un módulo que es inicializado por el kernel (cuando están enlazados estáticamente en el kernel) están envueltos en una macro initcall() que indica cuando en la secuencia de inicio se deben ejecutar.

Vea el archivo de inclusión: include/linux/init.h para obtener una lista de las macros y su orden.

el orden especificado existe:

  • early_initcall
  • pure_initcall
  • core_initcall
  • postcore_initcall
  • arch_initcall
  • subsys_initcall
  • fs_initcall
  • rootfs_initcall
  • device_initcall
  • late_initcall

mayoría de estos tienen una fase "initcall_sync(), que se utiliza para esperar a la finalización de todas las rutinas de inicialización del módulo dentro de esa fase. Las macros se usan para construir una tabla de punteros de función para cada fase, que se llaman en secuencia por do_initcalls().

Si "module_init()" se usa para ajustar la función de inicialización, entonces por defecto initcall() coloca la llamada en la fase de "dispositivo" de inicialización. Dentro de esa fase, los artículos se ordenan por orden de enlace. Esto significa que la tabla se crea por el orden de las funciones según se encuentran por el vinculador.

Usted puede ser capaz de mover una inicialización a una fase anterior, cambiando que macro initcall envuelve la función de los módulos de la inicialización, pero tenga cuidado porque hay dependencias de orden entre los distintos módulos. Otro método de que cambia el orden de inicialización (dentro de una fase) sería ajustar el orden del enlace para el módulo en el kernel.

0

@Tim Bird ya ha contestado - me gustaría mostrar cómo cambiar el orden de un módulo: -

pure_initcall(fn)   --> Loaded first 
core_initcall(fn)   
core_initcall_sync(fn)  
postcore_initcall(fn)  
postcore_initcall_sync(fn) 
arch_initcall(fn)   
arch_initcall_sync(fn)  
subsys_initcall(fn)  
subsys_initcall_sync(fn) 
fs_initcall(fn)   
fs_initcall_sync(fn)  
rootfs_initcall(fn)  
device_initcall(fn)  
device_initcall_sync(fn) 
late_initcall(fn)   
late_initcall_sync(fn) --> Loaded last 

Usage - Replace fn by the module init function pointer, example for i2c core driver: 
....... 
postcore_initcall(i2c_init); // To delay i2c core loading use subsys_initcall(i2c_init)     
module_exit(i2c_exit); 
....... 
Cuestiones relacionadas