1

解決できないように見える kfifo へのポインターを渡す問題に遭遇しました。

背景を少し。FPGA との Gumstix インターフェイス用のカーネル ドライバーの開発を引き継ぎました。このシナリオの FPGA は、基本的に複数のシリアル ストリームを取得し、データに対して何らかの処理を行ってから、GPIO を介して Gumstix で使用できるようにします。これは実際には非常に複雑なプロジェクトであるため、詳細は割愛します。個々のシリアル インターフェイス用のプロトタイプ ドライバーがあります。このドライバーは、これらすべてを組み合わせたものです。

このドライバーの最初のメイン ファイル (gpio.c) では、多くの kfifo が初期化され、次の構造の配列に格納されます。

#define NUM_DEVICES 31
#define DEVICE_FIFO_SIZE 65536

struct fpga_interface {
    ...
    struct kfifo fifos[NUM_DEVICES];
    spinlock_t fifo_locks[NUM_DEVICES];
    ...
};

static struct fpga_interface fpga;

int __init fpga_init_interface(void)
{
    int i;

    info("Initialising\n");

    // KFifo initialisation
    for(i=0; i<NUM_DEVICES; i++)
    {
        if(kfifo_alloc(&(fpga.fifos[i]), DEVICE_FIFO_SIZE, GFP_KERNEL)) {
            printk(KERN_ERR, "Error allocating the KFIFOs\n");
            return 1;
        }

        spin_lock_init(&fpga.fifo_locks[i]);

        info("Initialised KFIFO %d with addr=%x\n", i, &(fpga.fifos[i]));
    }
    ...
    info("Initialised\n");
}

void get_fifo(int dev, struct kfifo* fifo, spinlock_t* lock)
{
    fifo = &(fpga.fifos[dev]);
    lock = &(fpga.fifo_locks[dev]);

    info("Returning the KFIFO for devid=%d, fifo=%x, lock=%x", dev, fifo, lock);
}

次に、別のファイル (primary.c - 特定のインターフェイスを扱う) に次のように記述します。

struct fpga_primary {
    ....
    struct kfifo* fifo;
    spinlock_t* fifo_lock;
...
};

static struct fpga_primary primary;

int fpga_primary_init(void)
{
    info("Starting Primary\n");

    //Get our fifo and fifo lock
    get_fifo(1, primary.fifo, primary.lock_fifo);

    info("Got kfifo_addr=%x, lock_addr=%x\n", primary.fifo, primary.fifo_lock);
    ...
    info("Completed Primary\n");
}

以下は、gumstix のカーネル ログです。

Nov 30 02:28:14 overo [17837.989776] GPIO: Initialising
Nov 30 02:28:14 overo [17837.997497] Initialised KFIFO 0 with addr=bf062bb4
Nov 30 02:28:14 overo [17838.005249] Initialised KFIFO 1 with addr=bf062bc8
Nov 30 02:28:14 overo [17838.012847] Initialised KFIFO 2 with addr=bf062bdc
...
Nov 30 02:28:14 overo [17838.233947] GPIO: Initialised
...
Nov 30 02:28:14 overo [17838.264984] PRIMARY: Starting Primary
Nov 30 02:28:14 overo [17838.272979] GPIO: Returning the KFIFO for devid=1, fifo=bf062bc8, lock=bf062e20
Nov 30 02:28:14 overo [17838.281280] PRIMARY: Got kfifo_addr=0, lock_addr=0
Nov 30 02:28:14 overo [17838.296203] PRIMARY: Completed Primary 

get_fifo(...) の呼び出しが NULL ポインターを返すことに気付くでしょう。これは本当に良くないので、その理由がわかりません。

カーネル バージョン 3.2.0 および Angstrom 2011.03 ツール チェーンを使用して、OpenEmbedded / BitBake 標準環境を使用しています。私はUbuntu 10.04で構築しています。

何か案は?なんらかの理由で、kfifo へのポインターを渡すことが妨げられていると考えています...しかし、これを行うことができない/すべきでない理由について文書化されたものを見つけることができませんでした。 kfifo へのポインターを kifo_ 関数に渡すことを考慮してください。

4

1 に答える 1

2

間違った結果は、関数 void get_fifo(int dev, struct kfifo* fifo, spinlock_t* lock) によるものだと思います。この関数では、結果をローカル変数 fifo と lock; に割り当てます。get_fifo() が戻ると、ローカル変数は無効になります。

したがって、私の提案は次のとおりです。 get_fifo() 関数を次のように宣言します。

    void get_fifo(int dev, struct kfifo** fifo, spinlock_t** lock)
    {
        *fifo = &(fpga.fifos[dev]);
        *lock = &(fpga.fifo_locks[dev]);

        info("Returning the KFIFO for devid=%d, fifo=%x, lock=%x", dev, *fifo, *lock);
    }

関数 int fpga_primary_init(void) で、次のように get_fifo() を呼び出します。

    get_fifo(1, &(primary.fifo), &(primary.lock_fifo));

私はそれがあなたの問題を解決すると思います。

于 2013-05-29T01:44:46.363 に答える