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), 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