On Friday, March 3, 2017, Andras Pal <apal@xxxxxxxxx> wrote:
> Dear All,
>
> with some experience in low-level C programming, I started to develop a
> kernel module which allows I2C slave EEPROM-alike devices (EEPROMs, FRAMs,
> BBRAMs, etc) to be accessed as block devices. Since the i/o transactions are
> relatively slow (say, 40k/sec), i'm using kernel threads. However, it seems
> that while the read (rq_data_dir(req)) == 0) operations are fine, write
> operations (rq_data_dir != 0) seems to be lost. For instance, if I do `dd
> bs=512 count=32 of=/dev/i2cblk0`, only the first 8 sectors are fetched by
> blk_fetch_request(). I copy the critical/relevant/interesting parts after this
> message. The code is based on drivers/block/nbd.c.
>
> In addition - according to printk()-based debugging - after each write request,
> the kernel starts to access sectors in the order of 0, 24, 8, 56, 120, 64, 32
> (with 8 sectors == 1 page per request). Maybe it seeks for some filesystems...?
> Can this feature be turned off (like setting
> disk->queue->backing_dev_info.ra_pages to zero in order to turn off
> readaheaad)?
>
> thanks in advance, cheers, Andras
>
> /*****************************************************************************/
>
> static int i2cblk_process_io_request(struct i2cblk_device *device,struct request *req)
> {
> int ret;
>
> /* i2cblk_transfer(): this function calls i2c_master_send/recv(), etc. */
>
> ret=i2cblk_transfer(device, blk_rq_pos(req), blk_rq_cur_sectors(req),
Shouldn't you be going over all bio(s)
in this req?
> bio_data(req->bio),
> rq_data_dir(req));
>
> return(ret);
> }
>
> static void i2cblk_request(struct request_queue *q)
> {
> struct request *req;
>
> while ( (req=blk_fetch_request(q)) != NULL )
> { struct i2cblk_device *device;
>
> if ( req->cmd_type != REQ_TYPE_FS )
> { __blk_end_request_all(req, -EIO);
> continue;
> }
>
> /* spin_unlock_irq(q->queue_lock); */
>
> device=req->rq_disk->private_data;
>
> spin_lock_irq(&device->active_lock);
> list_add_tail(&req->queuelist,&device->active_queue);
> spin_unlock_irq(&device->active_lock);
>
> wake_up(&device->active_wq);
>
> /* spin_lock_irq(q->queue_lock); */
> };
>
> }
>
> static void i2cblk_end_request(struct request *req)
> {
> int error;
> struct request_queue *q = req->q;
> unsigned long flags;
>
> error=(req->errors ? -EIO : 0);
>
> spin_lock_irqsave(q->queue_lock, flags);
> __blk_end_request_all(req, error);
> spin_unlock_irqrestore(q->queue_lock, flags);
> }
>
> static void i2cblk_handle_request(struct i2cblk_device *device,struct request *req)
> {
> if ( i2cblk_process_io_request(device,req) )
> req->errors++;
>
> i2cblk_end_request(req);
>
> return;
> }
>
> static int i2cblk_thread(void *data)
> {
> struct i2cblk_device *device = data;
> struct request *req;
>
> while ( ! kthread_should_stop() )
> {
> wait_event_interruptible(device->active_wq,kthread_should_stop() || (!list_empty(&device->active_queue)));
>
> if ( list_empty(&device->active_queue) )
> continue;
>
> spin_lock_irq(&device->active_lock);
> req = list_entry(device->active_queue.next,struct request,queuelist);
> list_del_init(&req->queuelist);
> spin_unlock_irq(&device->active_lock);
>
> i2cblk_handle_request(device,req);
> };
>
> return(0);
> }
>
>
> _______________________________________________
> Kernelnewbies mailing list
> Kernelnewbies@xxxxxxxxxxxxxxxxx
> https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>
--
---P.K.S
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@xxxxxxxxxxxxxxxxx https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies