Skip to contentSkip to conversation

Request for Info: DMA timeout rq->buffer = NULL ?

DISCUSSION Prarit Bhargava 1 participant 1 message Dec 30, 2004 libata

lore
Share & tools
lore
#0 lore raw

I've come across a situation which appears to be an issue where a request has had a DMA timeout and then been reissued in PIO mode. The core issue is that the function ide_dma_timeout_retry sets the rq->buffer = NULL. Later on, when this request is retried in PIO mode we hit a BUG() because of the NULL rq->buffer pointer.

I'm wondering exactly why rq->buffer = NULL?

I'm on 2 processor IA64 platform using the SGI IOC4 IDE driver.

Details are as follows:

A request is created, bogus request = 0xe00000307a98cf18 .

The request is issued to the drive. For some reason it's timer fires waiting for DMA.

ide-io.c:1264: ide_timer_expiry is called because of the timeout

ide-io.c:1334 ide_dma_timeout_retry is called.

ide-io.c:1204: ide_dma_timeout_retry

This function puts the drive into PIO mode and turns off DMA. The drive is un-busy'd. Part of this procedure is to NULL out the rq->buffer.

ide-io.c:1346: ide_do_request is called

ide-io.c;1055: ide_do_request

The request is re-issued with the drive in PIO mode and the busted rq->buffer = NULL request.

ide-io.c:1178: start_request is called.

ide-io.c:837: start_request

ide-io.c:920: (DRIVER(drive)->do_request(drive, rq, block)) is called.

This resolves to a call to ide-cd.c:2048:ide_do_rw_cdrom.

ide-cd.c;2048: ide_do_rw_cdrom

ide-cd.c:2071:cdrom_start_read is called

ide-cd.c:1411:cdrom_start_read

ide-cd.c:1421:restore_request is called

ide-cd.c:1393:restore_request

This function calculates rq->hard_cur_sectors, etc., based on the values of rq->buffer. The problem is that rq->buffer = NULL. Obviously, all calculations in this function are bogus.

ide-cd.c:1441: cdrom_start_packet_command is issued with the bogus request, and with cdrom_read_intr as the interrupt handler.

Sometime later, an interrupt occurs and ide-cd.c:1110:cdrom_read_intr runs.

ide-cd.c:1110:cdrom_read_intr

ide-cd.c:1129:cdrom_decode_status is called

ide-cd.c:711:cdrom_decode_status

ide-cd.c:870:cdrom_queue_request_sense is called

ide-cd.c:573 cdrom_queue_request_sense

This function adds a new request (I will refer to this as the sense request) 0xe00000307be66960, to the queue which simply will query the CDROM for sense.

The sense request stores the bogus request on line 592:

       rq->buffer = (void *) 0xe00000307a98cf18;

This function issues the command directly to the drive and preempts any existing commands.

Eventually a cdrom_pc_intr occurs which returns the sense request.

Another cdrom_pc_intr occurs in order to remove the sense request, 0xe00000307be66960, from the queue.

ide-cd.c:1449:cdrom_pc_intr

ide-cd.c:1482: cdrom_end_request called

ide-cd.c:653:cdrom_end_request

((rq->flags & REQ_SENSE) && uptodate) = 1 and the value of failed is the bogus request.

ide-cd.c:678:ide_end_dequeued_request called

ide-io.c:206: ide_end_dequeued_request

This function has been called with the bogus request, and a negative value for nr_sectors. As you climb through the code, the return in this function depends on the return value from drivers/block/ll_rw_blk.c:2798:__end_that_request_first .

In this function, nr_bytes = nr_sectors << 9. However, nr_bytes and nr_sectors are negative numbers because of the bogus request value of rq->nr_hard_sectors being munged earlier on.

This causes a return of 1 from __end_that_request_first.
...

We're totally out in the weeds here. __end_that_request_first is coded correctly and correctly returns 1 ("not done") all the way up to ide_end_dequeued_request ... and then you hit

ide-cd.c:679:BUG()