Index of /~baker/devices/projects/pendawchi

[ICO]NameLast modifiedSizeDescription

[DIR]Parent Directory  -
[   ]Makefile13-Jul-2008 13:09 391
[TXT]diff13-Jul-2008 13:16 175K
[TXT]hrt.base.c13-Jul-2008 13:16 108K
[TXT]hrt.c13-Jul-2008 13:09 87K
[TXT]hrt.h13-Jul-2008 13:09 2.6K
[TXT]hrt_load13-Jul-2008 13:09 1.1K
[TXT]hrt_unload13-Jul-2008 13:09 253
[   ]pendawchi.tgz17-Jul-2008 13:01 154K
[DIR]src/13-Jul-2008 15:15 -
[DIR]test/13-Jul-2008 13:09 -

chenzhangsu-pixelsmart-report.html
Linux Kernel & Device Driver Programming

Project 4 - The Standardization of the PixelSmart Driver

By Peng Chen, Chi Zhang, and DaWei Su
Summer 2008

in this page

Overview

In this project, we are aiming to improve an existing PixelSmart/HRT Frame Grabber driver. This PixelSmart Frame Grabber driver was firstly developed by some students in Summer 2003. Over the past several years, various students have been improving the driver to make it work for different hardware configurations (grey/color card, pci/isa mode)and support more functionalities (such as Video For Linux 2 (V4l2) ioctl operations). However, the existing drivers still leave some problems unsolved, which enable us to further improve it. In our project, we try to fix the following shortcomings of the existing driver.
  • The driver does not implement the V4L2 IOCTL operations in a standard way.
  • The driver does not implement the I2C support in a standard way.
  • The driver dose not manage video buffers by using functions offered by the Linux kernel. Instead, it uses a range of self-defined functions to manage and maintain the video buffer.
  • The performance of the driver is poor under some modes.
  • The existing driver code has some problems such as abundant code, possible mutex lock problem, and incorrect operation of tasklet handler.
  • In a word, the previous implementations of the PixelSmart Frame Grabber driver cannot fit into the trends/standards adopted by the most video device drivers in 2.6.25+ kernel source code. We want to implement the driver in a more standard way.

    The baseline PixelSmart/HRT driver

    In our project, we used the driver developed by Chen Jie, Chen Ke, and Sai Lakshminaraayana in Summer 2007 as our starting driver. This driver could support both grey and color PixelSmart/HRT Frame Grabber cards and work under both PCI and ISA mode. Some IOCTL operations specified in the V4L2 API specification are also implemented by the driver. However, this implementation is not that perfect and has its weaknesses that we just mentioned in the overview section.

    A brief log of the project

    Week 2 - Pin down the project topic Week 3 - Study the existing driver Week 4 - Continue to study the existing driver Week 5 - Study some video drivers in the kernel source code Week 6 - Coding Week 7 - Debugging and Testing Week 8 - Writing the final project report


    What we have accomplished

    For all the above improvement we use a test program to verify all changes made to the driver. In the test program, user could test devices with different hardware configuration combinations (color, grey, ISA, and PCI) with three kinds of I/O methods: read, streaming I/O memory mapping, and streaming I/O user pointers. select function is used for monitoring the device, once data is available, images will be displayed. The old test program using tight read also works well on the driver. The test program source code can be found here.

    Implementation keynotes

    Video Buffer Management

    In the kernel source code the struct videobuf_buffer and videobuf_queue are defined in videobuf-core.h to manage video buffer. As we can see from videobuf_buffer, two list_head type members queue and stream are embedded in it, which are used to link video_buffer to 2 lists: one list called queue links all empty video buffer used in streaming I/O mode; the other list called stream is used in videobuf_queue to link all video buffers created in streaming I/O mode. Typically, in the video driver (whatever the video type is) a device specific video buffer is created and the first member of this specific video buffer is of videobuf_buffer type. Since file handler is introduced in the video device driver, whenever the driver perform an open operation an instance of file handler structure will created, in which it contains a member of videobuf_queue type. Not all I/O methods will use videobuf_queue, read operation is such a case, the file handler only need to provide a videobuf_buffer pointer in the read case.

    The device will eventually fill the video buffers either created via memory mapping or passed through user pointers or read operations. Therefore, in the device driver the device specific structure will contain a member of list_head type that links all the available free video buffers through queue list as we mentioned in the above paragraph. Once the data generated by the device finish dumping into a video buffer, the filled buffer will be removed from the queue list, but still in the stream list and driver will also wakeup corresponding sleep processes waiting for data. Once user applications get the data, this buffer will be finally removed from the stream list.

    struct videobuf_buffer {
            unsigned int            i;
            u32                     magic;
    
            /* info about the buffer */
            unsigned int            width;
            unsigned int            height;
            unsigned int            bytesperline; /* use only if != 0 */
            unsigned long           size;
            unsigned int            input;
            enum v4l2_field         field;
            enum videobuf_state     state;
            struct list_head        stream;  /* QBUF/DQBUF list */
    
            /* touched by irq handler */
            struct list_head        queue;
            wait_queue_head_t       done;
            unsigned int            field_count;
            struct timeval          ts;
    
            /* Memory type */
            enum v4l2_memory        memory;
    
            /* buffer size */
            size_t                  bsize;
    
            /* buffer offset (mmap + overlay) */
            size_t                  boff;
    
            /* buffer addr (userland ptr!) */
            unsigned long           baddr;
    
            /* for mmap'ed buffers */
            struct videobuf_mapping *map;
    
            /* Private pointer to allow specific methods to store their data */
            int                     privsize;
            void                    *priv;
    };
    struct videobuf_queue {
            struct mutex               vb_lock;
            spinlock_t                 *irqlock;
            void                       *dev; /* on pci, points to struct pci_dev */
    
            enum v4l2_buf_type         type;
            unsigned int               inputs; /* for V4L2_BUF_FLAG_INPUT */
            unsigned int               msize;
            enum v4l2_field            field;
            enum v4l2_field            last;   /* for field=V4L2_FIELD_ALTERNATE */
            struct videobuf_buffer     *bufs[VIDEO_MAX_FRAME];
            struct videobuf_queue_ops  *ops;
            struct videobuf_qtype_ops  *int_ops;
    
            unsigned int               streaming:1;
            unsigned int               reading:1;
            unsigned int               is_mmapped:1;
    
            /* capture via mmap() + ioctl(QBUF/DQBUF) */
            struct list_head           stream;
    
            /* capture via read() */
            unsigned int               read_off;
            struct videobuf_buffer     *read_buf;
    
            /* driver private data */
            void                       *priv_data;
    };
    
    Non-DMA Issue

    Because the PixelSmart/HRT Frame Grabber cards used in the project do not support DMA operations, it is necessary to use no-DMA version video buffer support functions defined in videobuf-vmalloc.c. Another interesting issue raised by non-DMA support is the difficulty to directly use the user space based video buffers in user pointers streaming I/O mode. This is because the device could not directly copy data from device space into user space for the lack of user process context information. We solved this problem by creating a transitional video buffer in the kernel space and first copy device data to this transitional buffer, then copy data to the user provided buffer. The shortcoming of this solution is a potential performance loss, however, since the bottleneck of the driver performance is copying data from the device to kernel space buffer, this solution will not influence the performance too much and our testing results also confirm this conclusion.

    Performance Issue

    In the old driver, the operation of copying data from device buffer to kernel buffer is accomplished by using memcpy and additional step is taken to empty device buffer by using memset. However, under the current kernel 2.6.25+, the memcpy is modified to transfer only one byte each time instead of four bytes in the older kernel. As a result, the performance of this device-to-kernel copying suffers from this modification. On the other side, we find out that the additional step in the old driver to empty the device buffer is unnecessary. Therefore, in the new driver implementation, we remove memset operations, which leads to a huge performance improvement (the actual performance gaining is given in "What we have accomplished" section).


    Future works


    Workload distribution


    Source code


    Version history

    V1.0 Chi

    Others