diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/umem.c | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 6b7c02d6360d..c378e285d708 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c | |||
@@ -113,6 +113,8 @@ struct cardinfo { | |||
113 | * have been written | 113 | * have been written |
114 | */ | 114 | */ |
115 | struct bio *bio, *currentbio, **biotail; | 115 | struct bio *bio, *currentbio, **biotail; |
116 | int current_idx; | ||
117 | sector_t current_sector; | ||
116 | 118 | ||
117 | struct request_queue *queue; | 119 | struct request_queue *queue; |
118 | 120 | ||
@@ -121,6 +123,7 @@ struct cardinfo { | |||
121 | struct mm_dma_desc *desc; | 123 | struct mm_dma_desc *desc; |
122 | int cnt, headcnt; | 124 | int cnt, headcnt; |
123 | struct bio *bio, **biotail; | 125 | struct bio *bio, **biotail; |
126 | int idx; | ||
124 | } mm_pages[2]; | 127 | } mm_pages[2]; |
125 | #define DESC_PER_PAGE ((PAGE_SIZE*2)/sizeof(struct mm_dma_desc)) | 128 | #define DESC_PER_PAGE ((PAGE_SIZE*2)/sizeof(struct mm_dma_desc)) |
126 | 129 | ||
@@ -380,12 +383,16 @@ static int add_bio(struct cardinfo *card) | |||
380 | dma_addr_t dma_handle; | 383 | dma_addr_t dma_handle; |
381 | int offset; | 384 | int offset; |
382 | struct bio *bio; | 385 | struct bio *bio; |
386 | struct bio_vec *vec; | ||
387 | int idx; | ||
383 | int rw; | 388 | int rw; |
384 | int len; | 389 | int len; |
385 | 390 | ||
386 | bio = card->currentbio; | 391 | bio = card->currentbio; |
387 | if (!bio && card->bio) { | 392 | if (!bio && card->bio) { |
388 | card->currentbio = card->bio; | 393 | card->currentbio = card->bio; |
394 | card->current_idx = card->bio->bi_idx; | ||
395 | card->current_sector = card->bio->bi_sector; | ||
389 | card->bio = card->bio->bi_next; | 396 | card->bio = card->bio->bi_next; |
390 | if (card->bio == NULL) | 397 | if (card->bio == NULL) |
391 | card->biotail = &card->bio; | 398 | card->biotail = &card->bio; |
@@ -394,15 +401,17 @@ static int add_bio(struct cardinfo *card) | |||
394 | } | 401 | } |
395 | if (!bio) | 402 | if (!bio) |
396 | return 0; | 403 | return 0; |
404 | idx = card->current_idx; | ||
397 | 405 | ||
398 | rw = bio_rw(bio); | 406 | rw = bio_rw(bio); |
399 | if (card->mm_pages[card->Ready].cnt >= DESC_PER_PAGE) | 407 | if (card->mm_pages[card->Ready].cnt >= DESC_PER_PAGE) |
400 | return 0; | 408 | return 0; |
401 | 409 | ||
402 | len = bio_iovec(bio)->bv_len; | 410 | vec = bio_iovec_idx(bio, idx); |
403 | dma_handle = pci_map_page(card->dev, | 411 | len = vec->bv_len; |
404 | bio_page(bio), | 412 | dma_handle = pci_map_page(card->dev, |
405 | bio_offset(bio), | 413 | vec->bv_page, |
414 | vec->bv_offset, | ||
406 | len, | 415 | len, |
407 | (rw==READ) ? | 416 | (rw==READ) ? |
408 | PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); | 417 | PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); |
@@ -410,6 +419,8 @@ static int add_bio(struct cardinfo *card) | |||
410 | p = &card->mm_pages[card->Ready]; | 419 | p = &card->mm_pages[card->Ready]; |
411 | desc = &p->desc[p->cnt]; | 420 | desc = &p->desc[p->cnt]; |
412 | p->cnt++; | 421 | p->cnt++; |
422 | if (p->bio == NULL) | ||
423 | p->idx = idx; | ||
413 | if ((p->biotail) != &bio->bi_next) { | 424 | if ((p->biotail) != &bio->bi_next) { |
414 | *(p->biotail) = bio; | 425 | *(p->biotail) = bio; |
415 | p->biotail = &(bio->bi_next); | 426 | p->biotail = &(bio->bi_next); |
@@ -419,7 +430,7 @@ static int add_bio(struct cardinfo *card) | |||
419 | desc->data_dma_handle = dma_handle; | 430 | desc->data_dma_handle = dma_handle; |
420 | 431 | ||
421 | desc->pci_addr = cpu_to_le64((u64)desc->data_dma_handle); | 432 | desc->pci_addr = cpu_to_le64((u64)desc->data_dma_handle); |
422 | desc->local_addr= cpu_to_le64(bio->bi_sector << 9); | 433 | desc->local_addr = cpu_to_le64(card->current_sector << 9); |
423 | desc->transfer_size = cpu_to_le32(len); | 434 | desc->transfer_size = cpu_to_le32(len); |
424 | offset = ( ((char*)&desc->sem_control_bits) - ((char*)p->desc)); | 435 | offset = ( ((char*)&desc->sem_control_bits) - ((char*)p->desc)); |
425 | desc->sem_addr = cpu_to_le64((u64)(p->page_dma+offset)); | 436 | desc->sem_addr = cpu_to_le64((u64)(p->page_dma+offset)); |
@@ -435,10 +446,10 @@ static int add_bio(struct cardinfo *card) | |||
435 | desc->control_bits |= cpu_to_le32(DMASCR_TRANSFER_READ); | 446 | desc->control_bits |= cpu_to_le32(DMASCR_TRANSFER_READ); |
436 | desc->sem_control_bits = desc->control_bits; | 447 | desc->sem_control_bits = desc->control_bits; |
437 | 448 | ||
438 | bio->bi_sector += (len>>9); | 449 | card->current_sector += (len >> 9); |
439 | bio->bi_size -= len; | 450 | idx++; |
440 | bio->bi_idx++; | 451 | card->current_idx = idx; |
441 | if (bio->bi_idx >= bio->bi_vcnt) | 452 | if (idx >= bio->bi_vcnt) |
442 | card->currentbio = NULL; | 453 | card->currentbio = NULL; |
443 | 454 | ||
444 | return 1; | 455 | return 1; |
@@ -474,10 +485,12 @@ static void process_page(unsigned long data) | |||
474 | last=1; | 485 | last=1; |
475 | } | 486 | } |
476 | page->headcnt++; | 487 | page->headcnt++; |
477 | idx = bio->bi_phys_segments; | 488 | idx = page->idx; |
478 | bio->bi_phys_segments++; | 489 | page->idx++; |
479 | if (bio->bi_phys_segments >= bio->bi_vcnt) | 490 | if (page->idx >= bio->bi_vcnt) { |
480 | page->bio = bio->bi_next; | 491 | page->bio = bio->bi_next; |
492 | page->idx = page->bio->bi_idx; | ||
493 | } | ||
481 | 494 | ||
482 | pci_unmap_page(card->dev, desc->data_dma_handle, | 495 | pci_unmap_page(card->dev, desc->data_dma_handle, |
483 | bio_iovec_idx(bio,idx)->bv_len, | 496 | bio_iovec_idx(bio,idx)->bv_len, |
@@ -547,7 +560,6 @@ static int mm_make_request(struct request_queue *q, struct bio *bio) | |||
547 | pr_debug("mm_make_request %llu %u\n", | 560 | pr_debug("mm_make_request %llu %u\n", |
548 | (unsigned long long)bio->bi_sector, bio->bi_size); | 561 | (unsigned long long)bio->bi_sector, bio->bi_size); |
549 | 562 | ||
550 | bio->bi_phys_segments = bio->bi_idx; /* count of completed segments*/ | ||
551 | spin_lock_irq(&card->lock); | 563 | spin_lock_irq(&card->lock); |
552 | *card->biotail = bio; | 564 | *card->biotail = bio; |
553 | bio->bi_next = NULL; | 565 | bio->bi_next = NULL; |