diff --git a/[refs] b/[refs] index 1a4637fcd8db..e8f4d24b9ff9 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 4c9773ed7946fc375edba057770f5ef16d8b44fe +refs/heads/master: 02c33b123e59cab5771e52a012aeb810500260a2 diff --git a/trunk/block/blk-core.c b/trunk/block/blk-core.c index cce7a88dc612..07ab75403e1a 100644 --- a/trunk/block/blk-core.c +++ b/trunk/block/blk-core.c @@ -1739,14 +1739,10 @@ static int __end_that_request_first(struct request *req, int error, trace_block_rq_complete(req->q, req); /* - * For fs requests, rq is just carrier of independent bio's - * and each partial completion should be handled separately. - * Reset per-request error on each partial completion. - * - * TODO: tj: This is too subtle. It would be better to let - * low level drivers do what they see fit. + * for a REQ_TYPE_BLOCK_PC request, we want to carry any eventual + * sense key with us all the way through */ - if (blk_fs_request(req)) + if (!blk_pc_request(req)) req->errors = 0; if (error && (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET))) { diff --git a/trunk/drivers/ide/alim15x3.c b/trunk/drivers/ide/alim15x3.c index e59b6dee9ae2..537da1cde16d 100644 --- a/trunk/drivers/ide/alim15x3.c +++ b/trunk/drivers/ide/alim15x3.c @@ -402,23 +402,27 @@ static u8 ali_cable_detect(ide_hwif_t *hwif) return cbl; } -#ifndef CONFIG_SPARC64 +#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) /** * init_hwif_ali15x3 - Initialize the ALI IDE x86 stuff * @hwif: interface to configure * * Obtain the IRQ tables for an ALi based IDE solution on the PC * class platforms. This part of the code isn't applicable to the - * Sparc systems. + * Sparc and PowerPC systems. */ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) { + struct pci_dev *dev = to_pci_dev(hwif->dev); u8 ideic, inmir; s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; int irq = -1; + if (dev->device == PCI_DEVICE_ID_AL_M5229) + hwif->irq = hwif->channel ? 15 : 14; + if (isa_dev) { /* * read IDE interface control @@ -451,7 +455,7 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) } #else #define init_hwif_ali15x3 NULL -#endif /* CONFIG_SPARC64 */ +#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */ /** * init_dma_ali15x3 - set up DMA on ALi15x3 diff --git a/trunk/drivers/ide/at91_ide.c b/trunk/drivers/ide/at91_ide.c index fc0949a8cfde..403d0e4265db 100644 --- a/trunk/drivers/ide/at91_ide.c +++ b/trunk/drivers/ide/at91_ide.c @@ -216,7 +216,6 @@ static const struct ide_port_info at91_ide_port_info __initdata = { .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE | IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS, .pio_mask = ATA_PIO6, - .chipset = ide_generic, }; /* @@ -247,7 +246,8 @@ irqreturn_t at91_irq_handler(int irq, void *dev_id) static int __init at91_ide_probe(struct platform_device *pdev) { int ret; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw; + hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; struct ide_host *host; struct resource *res; unsigned long tf_base = 0, ctl_base = 0; @@ -304,9 +304,10 @@ static int __init at91_ide_probe(struct platform_device *pdev) ide_std_init_ports(&hw, tf_base, ctl_base + 6); hw.irq = board->irq_pin; + hw.chipset = ide_generic; hw.dev = &pdev->dev; - host = ide_host_alloc(&at91_ide_port_info, hws, 1); + host = ide_host_alloc(&at91_ide_port_info, hws); if (!host) { perr("failed to allocate ide host\n"); return -ENOMEM; diff --git a/trunk/drivers/ide/au1xxx-ide.c b/trunk/drivers/ide/au1xxx-ide.c index 58121bd6c115..46013644c965 100644 --- a/trunk/drivers/ide/au1xxx-ide.c +++ b/trunk/drivers/ide/au1xxx-ide.c @@ -449,7 +449,7 @@ static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) } #endif -static void auide_setup_ports(struct ide_hw *hw, _auide_hwif *ahwif) +static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif) { int i; unsigned long *ata_regs = hw->io_ports_array; @@ -499,7 +499,6 @@ static const struct ide_port_info au1xxx_port_info = { #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA .mwdma_mask = ATA_MWDMA2, #endif - .chipset = ide_au1xxx, }; static int au_ide_probe(struct platform_device *dev) @@ -508,7 +507,7 @@ static int au_ide_probe(struct platform_device *dev) struct resource *res; struct ide_host *host; int ret = 0; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) char *mode = "MWDMA2"; @@ -549,8 +548,9 @@ static int au_ide_probe(struct platform_device *dev) auide_setup_ports(&hw, ahwif); hw.irq = ahwif->irq; hw.dev = &dev->dev; + hw.chipset = ide_au1xxx; - ret = ide_host_add(&au1xxx_port_info, hws, 1, &host); + ret = ide_host_add(&au1xxx_port_info, hws, &host); if (ret) goto out; diff --git a/trunk/drivers/ide/buddha.c b/trunk/drivers/ide/buddha.c index e3c6a5913305..d028f8864bc1 100644 --- a/trunk/drivers/ide/buddha.c +++ b/trunk/drivers/ide/buddha.c @@ -121,7 +121,7 @@ static int xsurf_ack_intr(ide_hwif_t *hwif) return 1; } -static void __init buddha_setup_ports(struct ide_hw *hw, unsigned long base, +static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base, unsigned long ctl, unsigned long irq_port, ide_ack_intr_t *ack_intr) { @@ -139,12 +139,13 @@ static void __init buddha_setup_ports(struct ide_hw *hw, unsigned long base, hw->irq = IRQ_AMIGA_PORTS; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static const struct ide_port_info buddha_port_info = { .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, - .chipset = ide_generic, }; /* @@ -160,7 +161,7 @@ static int __init buddha_init(void) while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { unsigned long board; - struct ide_hw hw[MAX_NUM_HWIFS], *hws[MAX_NUM_HWIFS]; + hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { buddha_num_hwifs = BUDDHA_NUM_HWIFS; @@ -224,7 +225,7 @@ static int __init buddha_init(void) hws[i] = &hw[i]; } - ide_host_add(&buddha_port_info, hws, i, NULL); + ide_host_add(&buddha_port_info, hws, NULL); } return 0; diff --git a/trunk/drivers/ide/cmd640.c b/trunk/drivers/ide/cmd640.c index 1683ed5c7329..8890276fef7f 100644 --- a/trunk/drivers/ide/cmd640.c +++ b/trunk/drivers/ide/cmd640.c @@ -708,7 +708,7 @@ static int __init cmd640x_init(void) int second_port_cmd640 = 0, rc; const char *bus_type, *port2; u8 b, cfr; - struct ide_hw hw[2], *hws[2]; + hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; if (cmd640_vlb && probe_for_cmd640_vlb()) { bus_type = "VLB"; @@ -762,9 +762,11 @@ static int __init cmd640x_init(void) ide_std_init_ports(&hw[0], 0x1f0, 0x3f6); hw[0].irq = 14; + hw[0].chipset = ide_cmd640; ide_std_init_ports(&hw[1], 0x170, 0x376); hw[1].irq = 15; + hw[1].chipset = ide_cmd640; printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); @@ -822,8 +824,7 @@ static int __init cmd640x_init(void) cmd640_dump_regs(); #endif - return ide_host_add(&cmd640_port_info, hws, second_port_cmd640 ? 2 : 1, - NULL); + return ide_host_add(&cmd640_port_info, hws, NULL); } module_param_named(probe_vlb, cmd640_vlb, bool, 0); diff --git a/trunk/drivers/ide/cs5520.c b/trunk/drivers/ide/cs5520.c index bd066bb9d611..87987a7d36c9 100644 --- a/trunk/drivers/ide/cs5520.c +++ b/trunk/drivers/ide/cs5520.c @@ -110,7 +110,7 @@ static const struct ide_port_info cyrix_chipset __devinitdata = { static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) { const struct ide_port_info *d = &cyrix_chipset; - struct ide_hw hw[2], *hws[] = { NULL, NULL }; + hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; ide_setup_pci_noise(dev, d); @@ -136,7 +136,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); hw[0].irq = 14; - return ide_host_add(d, hws, 2, NULL); + return ide_host_add(d, hws, NULL); } static const struct pci_device_id cs5520_pci_tbl[] = { diff --git a/trunk/drivers/ide/delkin_cb.c b/trunk/drivers/ide/delkin_cb.c index 1e10eba62ceb..f153b95619bb 100644 --- a/trunk/drivers/ide/delkin_cb.c +++ b/trunk/drivers/ide/delkin_cb.c @@ -68,7 +68,6 @@ static const struct ide_port_info delkin_cb_port_info = { IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, .init_chipset = delkin_cb_init_chipset, - .chipset = ide_pci, }; static int __devinit @@ -77,7 +76,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) struct ide_host *host; unsigned long base; int rc; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; rc = pci_enable_device(dev); if (rc) { @@ -98,8 +97,9 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) ide_std_init_ports(&hw, base + 0x10, base + 0x1e); hw.irq = dev->irq; hw.dev = &dev->dev; + hw.chipset = ide_pci; /* this enables IRQ sharing */ - rc = ide_host_add(&delkin_cb_port_info, hws, 1, &host); + rc = ide_host_add(&delkin_cb_port_info, hws, &host); if (rc) goto out_disable; diff --git a/trunk/drivers/ide/falconide.c b/trunk/drivers/ide/falconide.c index 22fa27389c3b..0e2df6755ec9 100644 --- a/trunk/drivers/ide/falconide.c +++ b/trunk/drivers/ide/falconide.c @@ -111,10 +111,9 @@ static const struct ide_port_info falconide_port_info = { .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, - .chipset = ide_generic, }; -static void __init falconide_setup_ports(struct ide_hw *hw) +static void __init falconide_setup_ports(hw_regs_t *hw) { int i; @@ -129,6 +128,8 @@ static void __init falconide_setup_ports(struct ide_hw *hw) hw->irq = IRQ_MFP_IDE; hw->ack_intr = NULL; + + hw->chipset = ide_generic; } /* @@ -138,7 +139,7 @@ static void __init falconide_setup_ports(struct ide_hw *hw) static int __init falconide_init(void) { struct ide_host *host; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; int rc; if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE)) @@ -153,7 +154,7 @@ static int __init falconide_init(void) falconide_setup_ports(&hw); - host = ide_host_alloc(&falconide_port_info, hws, 1); + host = ide_host_alloc(&falconide_port_info, hws); if (host == NULL) { rc = -ENOMEM; goto err; diff --git a/trunk/drivers/ide/gayle.c b/trunk/drivers/ide/gayle.c index 4451a6a5dfe0..c7119516c5a7 100644 --- a/trunk/drivers/ide/gayle.c +++ b/trunk/drivers/ide/gayle.c @@ -88,7 +88,7 @@ static int gayle_ack_intr_a1200(ide_hwif_t *hwif) return 1; } -static void __init gayle_setup_ports(struct ide_hw *hw, unsigned long base, +static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, unsigned long ctl, unsigned long irq_port, ide_ack_intr_t *ack_intr) { @@ -106,13 +106,14 @@ static void __init gayle_setup_ports(struct ide_hw *hw, unsigned long base, hw->irq = IRQ_AMIGA_PORTS; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static const struct ide_port_info gayle_port_info = { .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, - .chipset = ide_generic, }; /* @@ -125,7 +126,7 @@ static int __init gayle_init(void) unsigned long base, ctrlport, irqport; ide_ack_intr_t *ack_intr; int a4000, i, rc; - struct ide_hw hw[GAYLE_NUM_HWIFS], *hws[GAYLE_NUM_HWIFS]; + hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; if (!MACH_IS_AMIGA) return -ENODEV; @@ -170,7 +171,7 @@ static int __init gayle_init(void) hws[i] = &hw[i]; } - rc = ide_host_add(&gayle_port_info, hws, i, NULL); + rc = ide_host_add(&gayle_port_info, hws, NULL); if (rc) release_mem_region(res_start, res_n); diff --git a/trunk/drivers/ide/icside.c b/trunk/drivers/ide/icside.c index c5269fa1f733..36da913cc553 100644 --- a/trunk/drivers/ide/icside.c +++ b/trunk/drivers/ide/icside.c @@ -381,7 +381,7 @@ static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d) return -EOPNOTSUPP; } -static void icside_setup_ports(struct ide_hw *hw, void __iomem *base, +static void icside_setup_ports(hw_regs_t *hw, void __iomem *base, struct cardinfo *info, struct expansion_card *ec) { unsigned long port = (unsigned long)base + info->dataoffset; @@ -398,11 +398,11 @@ static void icside_setup_ports(struct ide_hw *hw, void __iomem *base, hw->irq = ec->irq; hw->dev = &ec->dev; + hw->chipset = ide_acorn; } static const struct ide_port_info icside_v5_port_info = { .host_flags = IDE_HFLAG_NO_DMA, - .chipset = ide_acorn, }; static int __devinit @@ -410,7 +410,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) { void __iomem *base; struct ide_host *host; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; int ret; base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); @@ -431,7 +431,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec); - host = ide_host_alloc(&icside_v5_port_info, hws, 1); + host = ide_host_alloc(&icside_v5_port_info, hws); if (host == NULL) return -ENODEV; @@ -457,7 +457,6 @@ static const struct ide_port_info icside_v6_port_info __initdata = { .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, .mwdma_mask = ATA_MWDMA2, .swdma_mask = ATA_SWDMA2, - .chipset = ide_acorn, }; static int __devinit @@ -467,7 +466,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) struct ide_host *host; unsigned int sel = 0; int ret; - struct ide_hw hw[2], *hws[] = { &hw[0], &hw[1] }; + hw_regs_t hw[2], *hws[] = { &hw[0], &hw[1], NULL, NULL }; struct ide_port_info d = icside_v6_port_info; ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); @@ -507,7 +506,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec); icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec); - host = ide_host_alloc(&d, hws, 2); + host = ide_host_alloc(&d, hws); if (host == NULL) return -ENODEV; diff --git a/trunk/drivers/ide/ide-4drives.c b/trunk/drivers/ide/ide-4drives.c index 979d342c338a..78aca75a2c48 100644 --- a/trunk/drivers/ide/ide-4drives.c +++ b/trunk/drivers/ide/ide-4drives.c @@ -25,13 +25,12 @@ static const struct ide_port_info ide_4drives_port_info = { .port_ops = &ide_4drives_port_ops, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA | IDE_HFLAG_4DRIVES, - .chipset = ide_4drives, }; static int __init ide_4drives_init(void) { unsigned long base = 0x1f0, ctl = 0x3f6; - struct ide_hw hw, *hws[] = { &hw, &hw }; + hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL }; if (probe_4drives == 0) return -ENODEV; @@ -53,8 +52,9 @@ static int __init ide_4drives_init(void) ide_std_init_ports(&hw, base, ctl); hw.irq = 14; + hw.chipset = ide_4drives; - return ide_host_add(&ide_4drives_port_info, hws, 2, NULL); + return ide_host_add(&ide_4drives_port_info, hws, NULL); } module_init(ide_4drives_init); diff --git a/trunk/drivers/ide/ide-atapi.c b/trunk/drivers/ide/ide-atapi.c index afe5a4323879..7201b176d75b 100644 --- a/trunk/drivers/ide/ide-atapi.c +++ b/trunk/drivers/ide/ide-atapi.c @@ -79,6 +79,34 @@ void ide_init_pc(struct ide_atapi_pc *pc) } EXPORT_SYMBOL_GPL(ide_init_pc); +/* + * Generate a new packet command request in front of the request queue, before + * the current request, so that it will be processed immediately, on the next + * pass through the driver. + */ +static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk, + struct ide_atapi_pc *pc, struct request *rq) +{ + blk_rq_init(NULL, rq); + rq->cmd_type = REQ_TYPE_SPECIAL; + rq->cmd_flags |= REQ_PREEMPT; + rq->buffer = (char *)pc; + rq->rq_disk = disk; + + if (pc->req_xfer) { + rq->data = pc->buf; + rq->data_len = pc->req_xfer; + } + + memcpy(rq->cmd, pc->c, 12); + if (drive->media == ide_tape) + rq->cmd[13] = REQ_IDETAPE_PC1; + + drive->hwif->rq = NULL; + + elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0); +} + /* * Add a special packet command request to the tail of the request queue, * and wait for it to be serviced. @@ -91,21 +119,19 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, rq = blk_get_request(drive->queue, READ, __GFP_WAIT); rq->cmd_type = REQ_TYPE_SPECIAL; - rq->special = (char *)pc; + rq->buffer = (char *)pc; if (pc->req_xfer) { - error = blk_rq_map_kern(drive->queue, rq, pc->buf, pc->req_xfer, - GFP_NOIO); - if (error) - goto put_req; + rq->data = pc->buf; + rq->data_len = pc->req_xfer; } memcpy(rq->cmd, pc->c, 12); if (drive->media == ide_tape) rq->cmd[13] = REQ_IDETAPE_PC1; error = blk_execute_rq(drive->queue, disk, rq, 0); -put_req: blk_put_request(rq); + return error; } EXPORT_SYMBOL_GPL(ide_queue_pc_tail); @@ -165,103 +191,20 @@ void ide_create_request_sense_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc) } EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd); -void ide_prep_sense(ide_drive_t *drive, struct request *rq) -{ - struct request_sense *sense = &drive->sense_data; - struct request *sense_rq = &drive->sense_rq; - unsigned int cmd_len, sense_len; - int err; - - debug_log("%s: enter\n", __func__); - - switch (drive->media) { - case ide_floppy: - cmd_len = 255; - sense_len = 18; - break; - case ide_tape: - cmd_len = 20; - sense_len = 20; - break; - default: - cmd_len = 18; - sense_len = 18; - } - - BUG_ON(sense_len > sizeof(*sense)); - - if (blk_sense_request(rq) || drive->sense_rq_armed) - return; - - memset(sense, 0, sizeof(*sense)); - - blk_rq_init(rq->q, sense_rq); - - err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len, - GFP_NOIO); - if (unlikely(err)) { - if (printk_ratelimit()) - printk(KERN_WARNING "%s: failed to map sense buffer\n", - drive->name); - return; - } - - sense_rq->rq_disk = rq->rq_disk; - sense_rq->cmd[0] = GPCMD_REQUEST_SENSE; - sense_rq->cmd[4] = cmd_len; - sense_rq->cmd_type = REQ_TYPE_SENSE; - sense_rq->cmd_flags |= REQ_PREEMPT; - - if (drive->media == ide_tape) - sense_rq->cmd[13] = REQ_IDETAPE_PC1; - - drive->sense_rq_armed = true; -} -EXPORT_SYMBOL_GPL(ide_prep_sense); - -int ide_queue_sense_rq(ide_drive_t *drive, void *special) -{ - /* deferred failure from ide_prep_sense() */ - if (!drive->sense_rq_armed) { - printk(KERN_WARNING "%s: failed queue sense request\n", - drive->name); - return -ENOMEM; - } - - drive->sense_rq.special = special; - drive->sense_rq_armed = false; - - drive->hwif->rq = NULL; - - elv_add_request(drive->queue, &drive->sense_rq, - ELEVATOR_INSERT_FRONT, 0); - return 0; -} -EXPORT_SYMBOL_GPL(ide_queue_sense_rq); - /* * Called when an error was detected during the last packet command. - * We queue a request sense packet command at the head of the request - * queue. + * We queue a request sense packet command in the head of the request list. */ -void ide_retry_pc(ide_drive_t *drive) +void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk) { - struct request *sense_rq = &drive->sense_rq; + struct request *rq = &drive->request_sense_rq; struct ide_atapi_pc *pc = &drive->request_sense_pc; (void)ide_read_error(drive); - - /* init pc from sense_rq */ - ide_init_pc(pc); - memcpy(pc->c, sense_rq->cmd, 12); - pc->buf = bio_data(sense_rq->bio); /* pointer to mapped address */ - pc->req_xfer = sense_rq->data_len; - + ide_create_request_sense_cmd(drive, pc); if (drive->media == ide_tape) set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); - - if (ide_queue_sense_rq(drive, pc)) - ide_complete_rq(drive, -EIO, blk_rq_bytes(drive->hwif->rq)); + ide_queue_pc_head(drive, disk, pc, rq); } EXPORT_SYMBOL_GPL(ide_retry_pc); @@ -333,6 +276,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) struct ide_cmd *cmd = &hwif->cmd; struct request *rq = hwif->rq; const struct ide_tp_ops *tp_ops = hwif->tp_ops; + xfer_func_t *xferfunc; unsigned int timeout, done; u16 bcount; u8 stat, ireason, dsc = 0; @@ -359,8 +303,11 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) drive->name, rq_data_dir(pc->rq) ? "write" : "read"); pc->flags |= PC_FLAG_DMA_ERROR; - } else + } else { pc->xferred = pc->req_xfer; + if (drive->pc_update_buffers) + drive->pc_update_buffers(drive, pc); + } debug_log("%s: DMA finished\n", drive->name); } @@ -396,7 +343,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) debug_log("[cmd %x]: check condition\n", rq->cmd[0]); /* Retry operation */ - ide_retry_pc(drive); + ide_retry_pc(drive, rq->rq_disk); /* queued, but not started */ return ide_stopped; @@ -406,12 +353,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0) dsc = 1; - /* - * ->pc_callback() might change rq->data_len for - * residual count, cache total length. - */ - done = blk_rq_bytes(rq); - /* Command finished - Call the callback function */ uptodate = drive->pc_callback(drive, dsc); @@ -420,6 +361,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) if (blk_special_request(rq)) { rq->errors = 0; + done = blk_rq_bytes(rq); error = 0; } else { @@ -428,6 +370,11 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) rq->errors = -EIO; } + if (drive->media == ide_tape) + done = ide_rq_bytes(rq); /* FIXME */ + else + done = blk_rq_bytes(rq); + error = uptodate ? 0 : -EIO; } @@ -460,11 +407,21 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) return ide_do_reset(drive); } - done = min_t(unsigned int, bcount, cmd->nleft); - ide_pio_bytes(drive, cmd, write, done); + xferfunc = write ? tp_ops->output_data : tp_ops->input_data; + + if (drive->media == ide_floppy && pc->buf == NULL) { + done = min_t(unsigned int, bcount, cmd->nleft); + ide_pio_bytes(drive, cmd, write, done); + } else if (drive->media == ide_tape && pc->bh) { + done = drive->pc_io_buffers(drive, pc, bcount, write); + } else { + done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred); + xferfunc(drive, NULL, pc->cur_pos, done); + } - /* Update transferred byte count */ + /* Update the current position */ pc->xferred += done; + pc->cur_pos += done; bcount -= done; @@ -642,6 +599,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd) /* We haven't transferred any data yet */ pc->xferred = 0; + pc->cur_pos = pc->buf; valid_tf = IDE_VALID_DEVICE; bcount = ((drive->media == ide_tape) ? diff --git a/trunk/drivers/ide/ide-cd.c b/trunk/drivers/ide/ide-cd.c index a75e4ee1cd17..925eb9e245d1 100644 --- a/trunk/drivers/ide/ide-cd.c +++ b/trunk/drivers/ide/ide-cd.c @@ -206,25 +206,54 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive, ide_cd_log_error(drive->name, failed_command, sense); } +static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, + struct request *failed_command) +{ + struct cdrom_info *info = drive->driver_data; + struct request *rq = &drive->request_sense_rq; + + ide_debug_log(IDE_DBG_SENSE, "enter"); + + if (sense == NULL) + sense = &info->sense_data; + + /* stuff the sense request in front of our current request */ + blk_rq_init(NULL, rq); + rq->cmd_type = REQ_TYPE_ATA_PC; + rq->rq_disk = info->disk; + + rq->data = sense; + rq->cmd[0] = GPCMD_REQUEST_SENSE; + rq->cmd[4] = 18; + rq->data_len = 18; + + rq->cmd_type = REQ_TYPE_SENSE; + rq->cmd_flags |= REQ_PREEMPT; + + /* NOTE! Save the failed command in "rq->buffer" */ + rq->buffer = (void *) failed_command; + + if (failed_command) + ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x", + failed_command->cmd[0]); + + drive->hwif->rq = NULL; + + elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0); +} + static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq) { /* - * For REQ_TYPE_SENSE, "rq->special" points to the original - * failed request. Also, the sense data should be read - * directly from rq which might be different from the original - * sense buffer if it got copied during mapping. + * For REQ_TYPE_SENSE, "rq->buffer" points to the original + * failed request */ - struct request *failed = (struct request *)rq->special; - void *sense = bio_data(rq->bio); + struct request *failed = (struct request *)rq->buffer; + struct cdrom_info *info = drive->driver_data; + void *sense = &info->sense_data; if (failed) { if (failed->sense) { - /* - * Sense is always read into drive->sense_data. - * Copy back if the failed request has its - * sense pointer set. - */ - memcpy(failed->sense, sense, 18); sense = failed->sense; failed->sense_len = rq->sense_len; } @@ -399,7 +428,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) /* if we got a CHECK_CONDITION status, queue a request sense command */ if (stat & ATA_ERR) - return ide_queue_sense_rq(drive, NULL) ? 2 : 1; + cdrom_queue_request_sense(drive, NULL, NULL); return 1; end_request: @@ -413,7 +442,8 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) hwif->rq = NULL; - return ide_queue_sense_rq(drive, rq) ? 2 : 1; + cdrom_queue_request_sense(drive, rq->sense, rq); + return 1; } else return 2; } @@ -473,8 +503,14 @@ static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd) * and some drives don't send them. Sigh. */ if (rq->cmd[0] == GPCMD_REQUEST_SENSE && - cmd->nleft > 0 && cmd->nleft <= 5) - cmd->nleft = 0; + cmd->nleft > 0 && cmd->nleft <= 5) { + unsigned int ofs = cmd->nbytes - cmd->nleft; + + while (cmd->nleft > 0) { + *((u8 *)rq->data + ofs++) = 0; + cmd->nleft--; + } + } } int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, @@ -507,12 +543,8 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, rq->cmd_flags |= cmd_flags; rq->timeout = timeout; if (buffer) { - error = blk_rq_map_kern(drive->queue, rq, buffer, - *bufflen, GFP_NOIO); - if (error) { - blk_put_request(rq); - return error; - } + rq->data = buffer; + rq->data_len = *bufflen; } error = blk_execute_rq(drive->queue, info->disk, rq, 0); @@ -806,10 +838,15 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) drive->dma = 0; /* sg request */ - if (rq->bio) { + if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) { struct request_queue *q = drive->queue; - char *buf = bio_data(rq->bio); unsigned int alignment; + char *buf; + + if (rq->bio) + buf = bio_data(rq->bio); + else + buf = rq->data; drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); @@ -859,9 +896,6 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, goto out_end; } - /* prepare sense request for this command */ - ide_prep_sense(drive, rq); - memset(&cmd, 0, sizeof(cmd)); if (rq_data_dir(rq)) diff --git a/trunk/drivers/ide/ide-cd.h b/trunk/drivers/ide/ide-cd.h index 93a3cf1b0f3f..1d97101099ce 100644 --- a/trunk/drivers/ide/ide-cd.h +++ b/trunk/drivers/ide/ide-cd.h @@ -87,6 +87,10 @@ struct cdrom_info { struct atapi_toc *toc; + /* The result of the last successful request sense command + on this device. */ + struct request_sense sense_data; + u8 max_speed; /* Max speed of the drive. */ u8 current_speed; /* Current speed of the drive. */ diff --git a/trunk/drivers/ide/ide-cs.c b/trunk/drivers/ide/ide-cs.c index 527908ff298c..9e47f3529d55 100644 --- a/trunk/drivers/ide/ide-cs.c +++ b/trunk/drivers/ide/ide-cs.c @@ -155,7 +155,6 @@ static const struct ide_port_info idecs_port_info = { .port_ops = &idecs_port_ops, .host_flags = IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, - .chipset = ide_pci, }; static struct ide_host *idecs_register(unsigned long io, unsigned long ctl, @@ -164,7 +163,7 @@ static struct ide_host *idecs_register(unsigned long io, unsigned long ctl, struct ide_host *host; ide_hwif_t *hwif; int i, rc; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; if (!request_region(io, 8, DRV_NAME)) { printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", @@ -182,9 +181,10 @@ static struct ide_host *idecs_register(unsigned long io, unsigned long ctl, memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, io, ctl); hw.irq = irq; + hw.chipset = ide_pci; hw.dev = &handle->dev; - rc = ide_host_add(&idecs_port_info, hws, 1, &host); + rc = ide_host_add(&idecs_port_info, hws, &host); if (rc) goto out_release; diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c index d345f5f23f01..a9fbe2c31210 100644 --- a/trunk/drivers/ide/ide-disk.c +++ b/trunk/drivers/ide/ide-disk.c @@ -411,6 +411,7 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) cmd->protocol = ATA_PROT_NODATA; rq->cmd_type = REQ_TYPE_ATA_TASKFILE; + rq->cmd_flags |= REQ_SOFTBARRIER; rq->special = cmd; } @@ -428,14 +429,14 @@ static int set_multcount(ide_drive_t *drive, int arg) if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff)) return -EINVAL; - if (drive->special_flags & IDE_SFLAG_SET_MULTMODE) + if (drive->special.b.set_multmode) return -EBUSY; rq = blk_get_request(drive->queue, READ, __GFP_WAIT); rq->cmd_type = REQ_TYPE_ATA_TASKFILE; drive->mult_req = arg; - drive->special_flags |= IDE_SFLAG_SET_MULTMODE; + drive->special.b.set_multmode = 1; error = blk_execute_rq(drive->queue, NULL, rq, 0); blk_put_request(rq); diff --git a/trunk/drivers/ide/ide-dma.c b/trunk/drivers/ide/ide-dma.c index d9123ecae4a9..a0b8cab1d9a6 100644 --- a/trunk/drivers/ide/ide-dma.c +++ b/trunk/drivers/ide/ide-dma.c @@ -510,11 +510,23 @@ ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) /* * un-busy drive etc and make sure request is sane */ + rq = hwif->rq; - if (rq) { - hwif->rq = NULL; - rq->errors = 0; - } + if (!rq) + goto out; + + hwif->rq = NULL; + + rq->errors = 0; + + if (!rq->bio) + goto out; + + rq->sector = rq->bio->bi_sector; + rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; + rq->hard_cur_sectors = rq->current_nr_sectors; + rq->buffer = bio_data(rq->bio); +out: return ret; } diff --git a/trunk/drivers/ide/ide-eh.c b/trunk/drivers/ide/ide-eh.c index 39d589254d41..5d5fb961b5ce 100644 --- a/trunk/drivers/ide/ide-eh.c +++ b/trunk/drivers/ide/ide-eh.c @@ -52,7 +52,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, } if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) - drive->special_flags |= IDE_SFLAG_RECALIBRATE; + drive->special.b.recalibrate = 1; ++rq->errors; @@ -268,8 +268,9 @@ static void ide_disk_pre_reset(ide_drive_t *drive) { int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1; - drive->special_flags = - legacy ? (IDE_SFLAG_SET_GEOMETRY | IDE_SFLAG_RECALIBRATE) : 0; + drive->special.all = 0; + drive->special.b.set_geometry = legacy; + drive->special.b.recalibrate = legacy; drive->mult_count = 0; drive->dev_flags &= ~IDE_DFLAG_PARKED; @@ -279,7 +280,7 @@ static void ide_disk_pre_reset(ide_drive_t *drive) drive->mult_req = 0; if (drive->mult_req != drive->mult_count) - drive->special_flags |= IDE_SFLAG_SET_MULTMODE; + drive->special.b.set_multmode = 1; } static void pre_reset(ide_drive_t *drive) diff --git a/trunk/drivers/ide/ide-floppy.c b/trunk/drivers/ide/ide-floppy.c index 537b7c558033..2b4868d95f8b 100644 --- a/trunk/drivers/ide/ide-floppy.c +++ b/trunk/drivers/ide/ide-floppy.c @@ -134,17 +134,13 @@ static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive, drive->pc = pc; if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) { - unsigned int done = blk_rq_bytes(drive->hwif->rq); - if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR)) ide_floppy_report_error(floppy, pc); - /* Giving up */ pc->error = IDE_DRV_ERROR_GENERAL; drive->failed_pc = NULL; drive->pc_callback(drive, 0); - ide_complete_rq(drive, -EIO, done); return ide_stopped; } @@ -220,13 +216,15 @@ static void idefloppy_blockpc_cmd(struct ide_disk_obj *floppy, ide_init_pc(pc); memcpy(pc->c, rq->cmd, sizeof(pc->c)); pc->rq = rq; - if (rq->data_len) { + if (rq->data_len && rq_data_dir(rq) == WRITE) + pc->flags |= PC_FLAG_WRITING; + pc->buf = rq->data; + if (rq->bio) pc->flags |= PC_FLAG_DMA_OK; - if (rq_data_dir(rq) == WRITE) - pc->flags |= PC_FLAG_WRITING; - } - /* pio will be performed by ide_pio_bytes() which handles sg fine */ - pc->buf = NULL; + /* + * possibly problematic, doesn't look like ide-floppy correctly + * handled scattered requests if dma fails... + */ pc->req_xfer = pc->buf_size = rq->data_len; } @@ -267,8 +265,8 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, } pc = &floppy->queued_pc; idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block); - } else if (blk_special_request(rq) || blk_sense_request(rq)) { - pc = (struct ide_atapi_pc *)rq->special; + } else if (blk_special_request(rq)) { + pc = (struct ide_atapi_pc *) rq->buffer; } else if (blk_pc_request(rq)) { pc = &floppy->queued_pc; idefloppy_blockpc_cmd(floppy, pc, rq); @@ -277,8 +275,6 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, goto out_end; } - ide_prep_sense(drive, rq); - memset(&cmd, 0, sizeof(cmd)); if (rq_data_dir(rq)) diff --git a/trunk/drivers/ide/ide-generic.c b/trunk/drivers/ide/ide-generic.c index 54d7c4685d23..7812ca0be13b 100644 --- a/trunk/drivers/ide/ide-generic.c +++ b/trunk/drivers/ide/ide-generic.c @@ -29,7 +29,6 @@ MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports"); static const struct ide_port_info ide_generic_port_info = { .host_flags = IDE_HFLAG_NO_DMA, - .chipset = ide_generic, }; #ifdef CONFIG_ARM @@ -86,7 +85,7 @@ static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary) static int __init ide_generic_init(void) { - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; unsigned long io_addr; int i, rc = 0, primary = 0, secondary = 0; @@ -133,7 +132,9 @@ static int __init ide_generic_init(void) #else hw.irq = legacy_irqs[i]; #endif - rc = ide_host_add(&ide_generic_port_info, hws, 1, NULL); + hw.chipset = ide_generic; + + rc = ide_host_add(&ide_generic_port_info, hws, NULL); if (rc) { release_region(io_addr + 0x206, 1); release_region(io_addr, 8); diff --git a/trunk/drivers/ide/ide-h8300.c b/trunk/drivers/ide/ide-h8300.c index 520f42c5445a..c06ebdc4a130 100644 --- a/trunk/drivers/ide/ide-h8300.c +++ b/trunk/drivers/ide/ide-h8300.c @@ -64,26 +64,26 @@ static const struct ide_tp_ops h8300_tp_ops = { #define H8300_IDE_GAP (2) -static inline void hw_setup(struct ide_hw *hw) +static inline void hw_setup(hw_regs_t *hw) { int i; - memset(hw, 0, sizeof(*hw)); + memset(hw, 0, sizeof(hw_regs_t)); for (i = 0; i <= 7; i++) hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i; hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT; hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ; + hw->chipset = ide_generic; } static const struct ide_port_info h8300_port_info = { .tp_ops = &h8300_tp_ops, .host_flags = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA, - .chipset = ide_generic, }; static int __init h8300_ide_init(void) { - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n"); @@ -96,7 +96,7 @@ static int __init h8300_ide_init(void) hw_setup(&hw); - return ide_host_add(&h8300_port_info, hws, 1, NULL); + return ide_host_add(&h8300_port_info, hws, NULL); out_busy: printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n"); diff --git a/trunk/drivers/ide/ide-io.c b/trunk/drivers/ide/ide-io.c index 9654bd34cf52..6415a2e2ba87 100644 --- a/trunk/drivers/ide/ide-io.c +++ b/trunk/drivers/ide/ide-io.c @@ -184,42 +184,29 @@ static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf) tf->command = ATA_CMD_SET_MULTI; } -/** - * do_special - issue some special commands - * @drive: drive the command is for - * - * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS, - * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive. - */ - -static ide_startstop_t do_special(ide_drive_t *drive) +static ide_startstop_t ide_disk_special(ide_drive_t *drive) { + special_t *s = &drive->special; struct ide_cmd cmd; -#ifdef DEBUG - printk(KERN_DEBUG "%s: %s: 0x%02x\n", drive->name, __func__, - drive->special_flags); -#endif - if (drive->media != ide_disk) { - drive->special_flags = 0; - drive->mult_req = 0; - return ide_stopped; - } - memset(&cmd, 0, sizeof(cmd)); cmd.protocol = ATA_PROT_NODATA; - if (drive->special_flags & IDE_SFLAG_SET_GEOMETRY) { - drive->special_flags &= ~IDE_SFLAG_SET_GEOMETRY; + if (s->b.set_geometry) { + s->b.set_geometry = 0; ide_tf_set_specify_cmd(drive, &cmd.tf); - } else if (drive->special_flags & IDE_SFLAG_RECALIBRATE) { - drive->special_flags &= ~IDE_SFLAG_RECALIBRATE; + } else if (s->b.recalibrate) { + s->b.recalibrate = 0; ide_tf_set_restore_cmd(drive, &cmd.tf); - } else if (drive->special_flags & IDE_SFLAG_SET_MULTMODE) { - drive->special_flags &= ~IDE_SFLAG_SET_MULTMODE; + } else if (s->b.set_multmode) { + s->b.set_multmode = 0; ide_tf_set_setmult_cmd(drive, &cmd.tf); - } else - BUG(); + } else if (s->all) { + int special = s->all; + s->all = 0; + printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); + return ide_stopped; + } cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; @@ -230,13 +217,45 @@ static ide_startstop_t do_special(ide_drive_t *drive) return ide_started; } +/** + * do_special - issue some special commands + * @drive: drive the command is for + * + * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS, + * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive. + * + * It used to do much more, but has been scaled back. + */ + +static ide_startstop_t do_special (ide_drive_t *drive) +{ + special_t *s = &drive->special; + +#ifdef DEBUG + printk("%s: do_special: 0x%02x\n", drive->name, s->all); +#endif + if (drive->media == ide_disk) + return ide_disk_special(drive); + + s->all = 0; + drive->mult_req = 0; + return ide_stopped; +} + void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd) { ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; struct request *rq = cmd->rq; - cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); + if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { + sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE); + cmd->sg_nents = 1; + } else if (!rq->bio) { + sg_init_one(sg, rq->data, rq->data_len); + cmd->sg_nents = 1; + } else + cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); } EXPORT_SYMBOL_GPL(ide_map_sg); @@ -339,8 +358,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) printk(KERN_ERR "%s: drive not ready for command\n", drive->name); return startstop; } - - if (drive->special_flags == 0) { + if (!drive->special.all) { struct ide_driver *drv; /* @@ -353,7 +371,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) return execute_drive_cmd(drive, rq); else if (blk_pm_request(rq)) { - struct request_pm_state *pm = rq->special; + struct request_pm_state *pm = rq->data; #ifdef DEBUG_PM printk("%s: start_power_step(step: %d)\n", drive->name, pm->pm_step); @@ -466,9 +484,6 @@ void do_ide_request(struct request_queue *q) spin_unlock_irq(q->queue_lock); - /* HLD do_request() callback might sleep, make sure it's okay */ - might_sleep(); - if (ide_lock_host(host, hwif)) goto plug_device_2; diff --git a/trunk/drivers/ide/ide-ioctls.c b/trunk/drivers/ide/ide-ioctls.c index 5991b23793f2..c1c25ebbaa1f 100644 --- a/trunk/drivers/ide/ide-ioctls.c +++ b/trunk/drivers/ide/ide-ioctls.c @@ -231,6 +231,7 @@ static int generic_drive_reset(ide_drive_t *drive) rq->cmd_type = REQ_TYPE_SPECIAL; rq->cmd_len = 1; rq->cmd[0] = REQ_DRIVE_RESET; + rq->cmd_flags |= REQ_SOFTBARRIER; if (blk_execute_rq(drive->queue, NULL, rq, 1)) ret = rq->errors; blk_put_request(rq); diff --git a/trunk/drivers/ide/ide-legacy.c b/trunk/drivers/ide/ide-legacy.c index b9654a7bb7be..8c5dcbf22547 100644 --- a/trunk/drivers/ide/ide-legacy.c +++ b/trunk/drivers/ide/ide-legacy.c @@ -1,7 +1,7 @@ #include #include -static void ide_legacy_init_one(struct ide_hw **hws, struct ide_hw *hw, +static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw, u8 port_no, const struct ide_port_info *d, unsigned long config) { @@ -33,6 +33,7 @@ static void ide_legacy_init_one(struct ide_hw **hws, struct ide_hw *hw, ide_std_init_ports(hw, base, ctl); hw->irq = irq; + hw->chipset = d->chipset; hw->config = config; hws[port_no] = hw; @@ -40,7 +41,7 @@ static void ide_legacy_init_one(struct ide_hw **hws, struct ide_hw *hw, int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) { - struct ide_hw hw[2], *hws[] = { NULL, NULL }; + hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; memset(&hw, 0, sizeof(hw)); @@ -52,6 +53,6 @@ int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) (d->host_flags & IDE_HFLAG_SINGLE)) return -ENOENT; - return ide_host_add(d, hws, 2, NULL); + return ide_host_add(d, hws, NULL); } EXPORT_SYMBOL_GPL(ide_legacy_device_add); diff --git a/trunk/drivers/ide/ide-park.c b/trunk/drivers/ide/ide-park.c index a914023d6d03..310d03f2b5b7 100644 --- a/trunk/drivers/ide/ide-park.c +++ b/trunk/drivers/ide/ide-park.c @@ -24,8 +24,11 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) start_queue = 1; spin_unlock_irq(&hwif->lock); - if (start_queue) - blk_run_queue(q); + if (start_queue) { + spin_lock_irq(q->queue_lock); + blk_start_queueing(q); + spin_unlock_irq(q->queue_lock); + } return; } spin_unlock_irq(&hwif->lock); diff --git a/trunk/drivers/ide/ide-pci-generic.c b/trunk/drivers/ide/ide-pci-generic.c index 61111fd27130..39d4e01f5c9c 100644 --- a/trunk/drivers/ide/ide-pci-generic.c +++ b/trunk/drivers/ide/ide-pci-generic.c @@ -33,6 +33,16 @@ static int ide_generic_all; /* Set to claim all devices */ module_param_named(all_generic_ide, ide_generic_all, bool, 0444); MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers."); +static void netcell_quirkproc(ide_drive_t *drive) +{ + /* mark words 85-87 as valid */ + drive->id[ATA_ID_CSF_DEFAULT] |= 0x4000; +} + +static const struct ide_port_ops netcell_port_ops = { + .quirkproc = netcell_quirkproc, +}; + #define DECLARE_GENERIC_PCI_DEV(extra_flags) \ { \ .name = DRV_NAME, \ @@ -74,6 +84,7 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = { { /* 6: Revolution */ .name = DRV_NAME, + .port_ops = &netcell_port_ops, .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | IDE_HFLAG_TRUST_BIOS_FOR_DMA | IDE_HFLAG_OFF_BOARD, diff --git a/trunk/drivers/ide/ide-pm.c b/trunk/drivers/ide/ide-pm.c index ba1488bd8430..0d8a151c0a01 100644 --- a/trunk/drivers/ide/ide-pm.c +++ b/trunk/drivers/ide/ide-pm.c @@ -7,6 +7,7 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) ide_hwif_t *hwif = drive->hwif; struct request *rq; struct request_pm_state rqpm; + struct ide_cmd cmd; int ret; /* call ACPI _GTM only once */ @@ -14,9 +15,11 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) ide_acpi_get_timing(hwif); memset(&rqpm, 0, sizeof(rqpm)); + memset(&cmd, 0, sizeof(cmd)); rq = blk_get_request(drive->queue, READ, __GFP_WAIT); rq->cmd_type = REQ_TYPE_PM_SUSPEND; - rq->special = &rqpm; + rq->special = &cmd; + rq->data = &rqpm; rqpm.pm_step = IDE_PM_START_SUSPEND; if (mesg.event == PM_EVENT_PRETHAW) mesg.event = PM_EVENT_FREEZE; @@ -38,6 +41,7 @@ int generic_ide_resume(struct device *dev) ide_hwif_t *hwif = drive->hwif; struct request *rq; struct request_pm_state rqpm; + struct ide_cmd cmd; int err; /* call ACPI _PS0 / _STM only once */ @@ -49,10 +53,12 @@ int generic_ide_resume(struct device *dev) ide_acpi_exec_tfs(drive); memset(&rqpm, 0, sizeof(rqpm)); + memset(&cmd, 0, sizeof(cmd)); rq = blk_get_request(drive->queue, READ, __GFP_WAIT); rq->cmd_type = REQ_TYPE_PM_RESUME; rq->cmd_flags |= REQ_PREEMPT; - rq->special = &rqpm; + rq->special = &cmd; + rq->data = &rqpm; rqpm.pm_step = IDE_PM_START_RESUME; rqpm.pm_state = PM_EVENT_ON; @@ -71,7 +77,7 @@ int generic_ide_resume(struct device *dev) void ide_complete_power_step(ide_drive_t *drive, struct request *rq) { - struct request_pm_state *pm = rq->special; + struct request_pm_state *pm = rq->data; #ifdef DEBUG_PM printk(KERN_INFO "%s: complete_power_step(step: %d)\n", @@ -101,8 +107,10 @@ void ide_complete_power_step(ide_drive_t *drive, struct request *rq) ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) { - struct request_pm_state *pm = rq->special; - struct ide_cmd cmd = { }; + struct request_pm_state *pm = rq->data; + struct ide_cmd *cmd = rq->special; + + memset(cmd, 0, sizeof(*cmd)); switch (pm->pm_step) { case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ @@ -115,12 +123,12 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) return ide_stopped; } if (ata_id_flush_ext_enabled(drive->id)) - cmd.tf.command = ATA_CMD_FLUSH_EXT; + cmd->tf.command = ATA_CMD_FLUSH_EXT; else - cmd.tf.command = ATA_CMD_FLUSH; + cmd->tf.command = ATA_CMD_FLUSH; goto out_do_tf; case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ - cmd.tf.command = ATA_CMD_STANDBYNOW1; + cmd->tf.command = ATA_CMD_STANDBYNOW1; goto out_do_tf; case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ ide_set_max_pio(drive); @@ -133,7 +141,7 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) ide_complete_power_step(drive, rq); return ide_stopped; case IDE_PM_IDLE: /* Resume step 2 (idle) */ - cmd.tf.command = ATA_CMD_IDLEIMMEDIATE; + cmd->tf.command = ATA_CMD_IDLEIMMEDIATE; goto out_do_tf; case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */ /* @@ -155,11 +163,11 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) return ide_stopped; out_do_tf: - cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; - cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; - cmd.protocol = ATA_PROT_NODATA; + cmd->valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; + cmd->valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; + cmd->protocol = ATA_PROT_NODATA; - return do_rw_taskfile(drive, &cmd); + return do_rw_taskfile(drive, cmd); } /** @@ -173,7 +181,7 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq) { struct request_queue *q = drive->queue; - struct request_pm_state *pm = rq->special; + struct request_pm_state *pm = rq->data; unsigned long flags; ide_complete_power_step(drive, rq); @@ -199,7 +207,7 @@ void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq) void ide_check_pm_state(ide_drive_t *drive, struct request *rq) { - struct request_pm_state *pm = rq->special; + struct request_pm_state *pm = rq->data; if (blk_pm_suspend_request(rq) && pm->pm_step == IDE_PM_START_SUSPEND) diff --git a/trunk/drivers/ide/ide-pnp.c b/trunk/drivers/ide/ide-pnp.c index 017b1df3b805..6e80b774e88a 100644 --- a/trunk/drivers/ide/ide-pnp.c +++ b/trunk/drivers/ide/ide-pnp.c @@ -29,7 +29,6 @@ static struct pnp_device_id idepnp_devices[] = { static const struct ide_port_info ide_pnp_port_info = { .host_flags = IDE_HFLAG_NO_DMA, - .chipset = ide_generic, }; static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) @@ -37,7 +36,7 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) struct ide_host *host; unsigned long base, ctl; int rc; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; printk(KERN_INFO DRV_NAME ": generic PnP IDE interface\n"); @@ -63,8 +62,9 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, base, ctl); hw.irq = pnp_irq(dev, 0); + hw.chipset = ide_generic; - rc = ide_host_add(&ide_pnp_port_info, hws, 1, &host); + rc = ide_host_add(&ide_pnp_port_info, hws, &host); if (rc) goto out; diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c index 89574b0bd56d..c895ed52b2e8 100644 --- a/trunk/drivers/ide/ide-probe.c +++ b/trunk/drivers/ide/ide-probe.c @@ -97,7 +97,7 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) drive->mult_req = id[ATA_ID_MULTSECT] & 0xff; if (drive->mult_req) - drive->special_flags |= IDE_SFLAG_SET_MULTMODE; + drive->special.b.set_multmode = 1; } } @@ -1035,15 +1035,6 @@ static void ide_port_init_devices(ide_hwif_t *hwif) if (port_ops && port_ops->init_dev) port_ops->init_dev(drive); } - - ide_port_for_each_dev(i, drive, hwif) { - /* - * default to PIO Mode 0 before we figure out - * the most suited mode for the attached device - */ - if (port_ops && port_ops->set_pio_mode) - port_ops->set_pio_mode(drive, 0); - } } static void ide_init_port(ide_hwif_t *hwif, unsigned int port, @@ -1051,7 +1042,8 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, { hwif->channel = port; - hwif->chipset = d->chipset ? d->chipset : ide_pci; + if (d->chipset) + hwif->chipset = d->chipset; if (d->init_iops) d->init_iops(hwif); @@ -1140,8 +1132,8 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif) drive->hwif = hwif; drive->ready_stat = ATA_DRDY; drive->bad_wstat = BAD_W_STAT; - drive->special_flags = IDE_SFLAG_RECALIBRATE | - IDE_SFLAG_SET_GEOMETRY; + drive->special.b.recalibrate = 1; + drive->special.b.set_geometry = 1; drive->name[0] = 'h'; drive->name[1] = 'd'; drive->name[2] = 'a' + j; @@ -1176,10 +1168,11 @@ static void ide_init_port_data(ide_hwif_t *hwif, unsigned int index) ide_port_init_devices_data(hwif); } -static void ide_init_port_hw(ide_hwif_t *hwif, struct ide_hw *hw) +static void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw) { memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports)); hwif->irq = hw->irq; + hwif->chipset = hw->chipset; hwif->dev = hw->dev; hwif->gendev.parent = hw->parent ? hw->parent : hw->dev; hwif->ack_intr = hw->ack_intr; @@ -1264,8 +1257,7 @@ static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) return -ENOMEM; } -struct ide_host *ide_host_alloc(const struct ide_port_info *d, - struct ide_hw **hws, unsigned int n_ports) +struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) { struct ide_host *host; struct device *dev = hws[0] ? hws[0]->dev : NULL; @@ -1276,7 +1268,7 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, if (host == NULL) return NULL; - for (i = 0; i < n_ports; i++) { + for (i = 0; i < MAX_HOST_PORTS; i++) { ide_hwif_t *hwif; int idx; @@ -1352,7 +1344,7 @@ static void ide_disable_port(ide_hwif_t *hwif) } int ide_host_register(struct ide_host *host, const struct ide_port_info *d, - struct ide_hw **hws) + hw_regs_t **hws) { ide_hwif_t *hwif, *mate = NULL; int i, j = 0; @@ -1446,13 +1438,13 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, } EXPORT_SYMBOL_GPL(ide_host_register); -int ide_host_add(const struct ide_port_info *d, struct ide_hw **hws, - unsigned int n_ports, struct ide_host **hostp) +int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws, + struct ide_host **hostp) { struct ide_host *host; int rc; - host = ide_host_alloc(d, hws, n_ports); + host = ide_host_alloc(d, hws); if (host == NULL) return -ENOMEM; diff --git a/trunk/drivers/ide/ide-tape.c b/trunk/drivers/ide/ide-tape.c index 203bbeac182f..3a53e0834cf7 100644 --- a/trunk/drivers/ide/ide-tape.c +++ b/trunk/drivers/ide/ide-tape.c @@ -131,6 +131,13 @@ enum { IDETAPE_DIR_WRITE = (1 << 2), }; +struct idetape_bh { + u32 b_size; + atomic_t b_count; + struct idetape_bh *b_reqnext; + char *b_data; +}; + /* Tape door status */ #define DOOR_UNLOCKED 0 #define DOOR_LOCKED 1 @@ -212,12 +219,18 @@ typedef struct ide_tape_obj { /* Data buffer size chosen based on the tape's recommendation */ int buffer_size; - /* Staging buffer of buffer_size bytes */ - void *buf; - /* The read/write cursor */ - void *cur; - /* The number of valid bytes in buf */ - size_t valid; + /* merge buffer */ + struct idetape_bh *merge_bh; + /* size of the merge buffer */ + int merge_bh_size; + /* pointer to current buffer head within the merge buffer */ + struct idetape_bh *bh; + char *b_data; + int b_count; + + int pages_per_buffer; + /* Wasted space in each stage */ + int excess_bh_size; /* Measures average tape speed */ unsigned long avg_time; @@ -284,6 +297,84 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) return tape; } +static int idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, + unsigned int bcount) +{ + struct idetape_bh *bh = pc->bh; + int count; + + while (bcount) { + if (bh == NULL) + break; + count = min( + (unsigned int)(bh->b_size - atomic_read(&bh->b_count)), + bcount); + drive->hwif->tp_ops->input_data(drive, NULL, bh->b_data + + atomic_read(&bh->b_count), count); + bcount -= count; + atomic_add(count, &bh->b_count); + if (atomic_read(&bh->b_count) == bh->b_size) { + bh = bh->b_reqnext; + if (bh) + atomic_set(&bh->b_count, 0); + } + } + + pc->bh = bh; + + return bcount; +} + +static int idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, + unsigned int bcount) +{ + struct idetape_bh *bh = pc->bh; + int count; + + while (bcount) { + if (bh == NULL) + break; + count = min((unsigned int)pc->b_count, (unsigned int)bcount); + drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count); + bcount -= count; + pc->b_data += count; + pc->b_count -= count; + if (!pc->b_count) { + bh = bh->b_reqnext; + pc->bh = bh; + if (bh) { + pc->b_data = bh->b_data; + pc->b_count = atomic_read(&bh->b_count); + } + } + } + + return bcount; +} + +static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) +{ + struct idetape_bh *bh = pc->bh; + int count; + unsigned int bcount = pc->xferred; + + if (pc->flags & PC_FLAG_WRITING) + return; + while (bcount) { + if (bh == NULL) { + printk(KERN_ERR "ide-tape: bh == NULL in %s\n", + __func__); + return; + } + count = min((unsigned int)bh->b_size, (unsigned int)bcount); + atomic_set(&bh->b_count, count); + if (atomic_read(&bh->b_count) == bh->b_size) + bh = bh->b_reqnext; + bcount -= count; + } + pc->bh = bh; +} + /* * called on each failed packet command retry to analyze the request sense. We * currently do not utilize this information. @@ -301,10 +392,12 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) pc->c[0], tape->sense_key, tape->asc, tape->ascq); /* Correct pc->xferred by asking the tape. */ - if (pc->flags & PC_FLAG_DMA_ERROR) + if (pc->flags & PC_FLAG_DMA_ERROR) { pc->xferred = pc->req_xfer - tape->blk_size * get_unaligned_be32(&sense[3]); + idetape_update_buffers(drive, pc); + } /* * If error was the result of a zero-length read or write command, @@ -343,6 +436,29 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) } } +/* Free data buffers completely. */ +static void ide_tape_kfree_buffer(idetape_tape_t *tape) +{ + struct idetape_bh *prev_bh, *bh = tape->merge_bh; + + while (bh) { + u32 size = bh->b_size; + + while (size) { + unsigned int order = fls(size >> PAGE_SHIFT)-1; + + if (bh->b_data) + free_pages((unsigned long)bh->b_data, order); + + size &= (order-1); + bh->b_data += (1 << order) * PAGE_SIZE; + } + prev_bh = bh; + bh = bh->b_reqnext; + kfree(prev_bh); + } +} + static void ide_tape_handle_dsc(ide_drive_t *); static int ide_tape_callback(ide_drive_t *drive, int dsc) @@ -380,7 +496,7 @@ static int ide_tape_callback(ide_drive_t *drive, int dsc) } tape->first_frame += blocks; - rq->data_len -= blocks * tape->blk_size; + rq->current_nr_sectors -= blocks; if (pc->error) { uptodate = 0; @@ -442,6 +558,19 @@ static void ide_tape_handle_dsc(ide_drive_t *drive) idetape_postpone_request(drive); } +static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, + unsigned int bcount, int write) +{ + unsigned int bleft; + + if (write) + bleft = idetape_output_buffers(drive, pc, bcount); + else + bleft = idetape_input_buffers(drive, pc, bcount); + + return bcount - bleft; +} + /* * Packet Command Interface * @@ -493,8 +622,6 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive, if (pc->retries > IDETAPE_MAX_PC_RETRIES || (pc->flags & PC_FLAG_ABORT)) { - unsigned int done = blk_rq_bytes(drive->hwif->rq); - /* * We will "abort" retrying a packet command in case legitimate * error code was received (crossing a filemark, or end of the @@ -514,10 +641,8 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive, /* Giving up */ pc->error = IDE_DRV_ERROR_GENERAL; } - drive->failed_pc = NULL; drive->pc_callback(drive, 0); - ide_complete_rq(drive, -EIO, done); return ide_stopped; } debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]); @@ -570,7 +695,7 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive) printk(KERN_ERR "ide-tape: %s: I/O error, ", tape->name); /* Retry operation */ - ide_retry_pc(drive); + ide_retry_pc(drive, tape->disk); return ide_stopped; } pc->error = 0; @@ -586,22 +711,27 @@ static void ide_tape_create_rw_cmd(idetape_tape_t *tape, struct ide_atapi_pc *pc, struct request *rq, u8 opcode) { - unsigned int length = rq->nr_sectors; + struct idetape_bh *bh = (struct idetape_bh *)rq->special; + unsigned int length = rq->current_nr_sectors; ide_init_pc(pc); put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]); pc->c[1] = 1; + pc->bh = bh; pc->buf = NULL; pc->buf_size = length * tape->blk_size; pc->req_xfer = pc->buf_size; if (pc->req_xfer == tape->buffer_size) pc->flags |= PC_FLAG_DMA_OK; - if (opcode == READ_6) + if (opcode == READ_6) { pc->c[0] = READ_6; - else if (opcode == WRITE_6) { + atomic_set(&bh->b_count, 0); + } else if (opcode == WRITE_6) { pc->c[0] = WRITE_6; pc->flags |= PC_FLAG_WRITING; + pc->b_data = bh->b_data; + pc->b_count = atomic_read(&bh->b_count); } memcpy(rq->cmd, pc->c, 12); @@ -617,10 +747,12 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, struct ide_cmd cmd; u8 stat; - debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu\n", - (unsigned long long)rq->sector, rq->nr_sectors); + debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu," + " current_nr_sectors: %u\n", + (unsigned long long)rq->sector, rq->nr_sectors, + rq->current_nr_sectors); - if (!(blk_special_request(rq) || blk_sense_request(rq))) { + if (!blk_special_request(rq)) { /* We do not support buffer cache originated requests. */ printk(KERN_NOTICE "ide-tape: %s: Unsupported request in " "request queue (%d)\n", drive->name, rq->cmd_type); @@ -696,7 +828,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, goto out; } if (rq->cmd[13] & REQ_IDETAPE_PC1) { - pc = (struct ide_atapi_pc *)rq->special; + pc = (struct ide_atapi_pc *) rq->buffer; rq->cmd[13] &= ~(REQ_IDETAPE_PC1); rq->cmd[13] |= REQ_IDETAPE_PC2; goto out; @@ -708,9 +840,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, BUG(); out: - /* prepare sense request for this command */ - ide_prep_sense(drive, rq); - memset(&cmd, 0, sizeof(cmd)); if (rq_data_dir(rq)) @@ -718,12 +847,169 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, cmd.rq = rq; - ide_init_sg_cmd(&cmd, pc->req_xfer); - ide_map_sg(drive, &cmd); - return ide_tape_issue_pc(drive, &cmd, pc); } +/* + * The function below uses __get_free_pages to allocate a data buffer of size + * tape->buffer_size (or a bit more). We attempt to combine sequential pages as + * much as possible. + * + * It returns a pointer to the newly allocated buffer, or NULL in case of + * failure. + */ +static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape, + int full, int clear) +{ + struct idetape_bh *prev_bh, *bh, *merge_bh; + int pages = tape->pages_per_buffer; + unsigned int order, b_allocd; + char *b_data = NULL; + + merge_bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); + bh = merge_bh; + if (bh == NULL) + goto abort; + + order = fls(pages) - 1; + bh->b_data = (char *) __get_free_pages(GFP_KERNEL, order); + if (!bh->b_data) + goto abort; + b_allocd = (1 << order) * PAGE_SIZE; + pages &= (order-1); + + if (clear) + memset(bh->b_data, 0, b_allocd); + bh->b_reqnext = NULL; + bh->b_size = b_allocd; + atomic_set(&bh->b_count, full ? bh->b_size : 0); + + while (pages) { + order = fls(pages) - 1; + b_data = (char *) __get_free_pages(GFP_KERNEL, order); + if (!b_data) + goto abort; + b_allocd = (1 << order) * PAGE_SIZE; + + if (clear) + memset(b_data, 0, b_allocd); + + /* newly allocated page frames below buffer header or ...*/ + if (bh->b_data == b_data + b_allocd) { + bh->b_size += b_allocd; + bh->b_data -= b_allocd; + if (full) + atomic_add(b_allocd, &bh->b_count); + continue; + } + /* they are above the header */ + if (b_data == bh->b_data + bh->b_size) { + bh->b_size += b_allocd; + if (full) + atomic_add(b_allocd, &bh->b_count); + continue; + } + prev_bh = bh; + bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); + if (!bh) { + free_pages((unsigned long) b_data, order); + goto abort; + } + bh->b_reqnext = NULL; + bh->b_data = b_data; + bh->b_size = b_allocd; + atomic_set(&bh->b_count, full ? bh->b_size : 0); + prev_bh->b_reqnext = bh; + + pages &= (order-1); + } + + bh->b_size -= tape->excess_bh_size; + if (full) + atomic_sub(tape->excess_bh_size, &bh->b_count); + return merge_bh; +abort: + ide_tape_kfree_buffer(tape); + return NULL; +} + +static int idetape_copy_stage_from_user(idetape_tape_t *tape, + const char __user *buf, int n) +{ + struct idetape_bh *bh = tape->bh; + int count; + int ret = 0; + + while (n) { + if (bh == NULL) { + printk(KERN_ERR "ide-tape: bh == NULL in %s\n", + __func__); + return 1; + } + count = min((unsigned int) + (bh->b_size - atomic_read(&bh->b_count)), + (unsigned int)n); + if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, + count)) + ret = 1; + n -= count; + atomic_add(count, &bh->b_count); + buf += count; + if (atomic_read(&bh->b_count) == bh->b_size) { + bh = bh->b_reqnext; + if (bh) + atomic_set(&bh->b_count, 0); + } + } + tape->bh = bh; + return ret; +} + +static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf, + int n) +{ + struct idetape_bh *bh = tape->bh; + int count; + int ret = 0; + + while (n) { + if (bh == NULL) { + printk(KERN_ERR "ide-tape: bh == NULL in %s\n", + __func__); + return 1; + } + count = min(tape->b_count, n); + if (copy_to_user(buf, tape->b_data, count)) + ret = 1; + n -= count; + tape->b_data += count; + tape->b_count -= count; + buf += count; + if (!tape->b_count) { + bh = bh->b_reqnext; + tape->bh = bh; + if (bh) { + tape->b_data = bh->b_data; + tape->b_count = atomic_read(&bh->b_count); + } + } + } + return ret; +} + +static void idetape_init_merge_buffer(idetape_tape_t *tape) +{ + struct idetape_bh *bh = tape->merge_bh; + tape->bh = tape->merge_bh; + + if (tape->chrdev_dir == IDETAPE_DIR_WRITE) + atomic_set(&bh->b_count, 0); + else { + tape->b_data = bh->b_data; + tape->b_count = atomic_read(&bh->b_count); + } +} + /* * Write a filemark if write_filemark=1. Flush the device buffers without * writing a filemark otherwise. @@ -821,10 +1107,10 @@ static void __ide_tape_discard_merge_buffer(ide_drive_t *drive) return; clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags); - tape->valid = 0; - if (tape->buf != NULL) { - kfree(tape->buf); - tape->buf = NULL; + tape->merge_bh_size = 0; + if (tape->merge_bh != NULL) { + ide_tape_kfree_buffer(tape); + tape->merge_bh = NULL; } tape->chrdev_dir = IDETAPE_DIR_NONE; @@ -878,44 +1164,36 @@ static void ide_tape_discard_merge_buffer(ide_drive_t *drive, * Generate a read/write request for the block device interface and wait for it * to be serviced. */ -static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int size) +static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, + struct idetape_bh *bh) { idetape_tape_t *tape = drive->driver_data; struct request *rq; - int ret; + int ret, errors; debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd); - BUG_ON(cmd != REQ_IDETAPE_READ && cmd != REQ_IDETAPE_WRITE); - BUG_ON(size < 0 || size % tape->blk_size); rq = blk_get_request(drive->queue, READ, __GFP_WAIT); rq->cmd_type = REQ_TYPE_SPECIAL; rq->cmd[13] = cmd; rq->rq_disk = tape->disk; + rq->special = (void *)bh; rq->sector = tape->first_frame; - - if (size) { - ret = blk_rq_map_kern(drive->queue, rq, tape->buf, size, - __GFP_WAIT); - if (ret) - goto out_put; - } - + rq->nr_sectors = blocks; + rq->current_nr_sectors = blocks; blk_execute_rq(drive->queue, tape->disk, rq, 0); - /* calculate the number of transferred bytes and update buffer state */ - size -= rq->data_len; - tape->cur = tape->buf; - if (cmd == REQ_IDETAPE_READ) - tape->valid = size; - else - tape->valid = 0; - - ret = size; - if (rq->errors == IDE_DRV_ERROR_GENERAL) - ret = -EIO; -out_put: + errors = rq->errors; + ret = tape->blk_size * (blocks - rq->current_nr_sectors); blk_put_request(rq); + + if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0) + return 0; + + if (tape->merge_bh) + idetape_init_merge_buffer(tape); + if (errors == IDE_DRV_ERROR_GENERAL) + return -EIO; return ret; } @@ -952,87 +1230,153 @@ static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd) pc->flags |= PC_FLAG_WAIT_FOR_DSC; } +/* Queue up a character device originated write request. */ +static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks) +{ + idetape_tape_t *tape = drive->driver_data; + + debug_log(DBG_CHRDEV, "Enter %s\n", __func__); + + return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, + blocks, tape->merge_bh); +} + static void ide_tape_flush_merge_buffer(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; + int blocks, min; + struct idetape_bh *bh; if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer" " but we are not writing.\n"); return; } - if (tape->buf) { - size_t aligned = roundup(tape->valid, tape->blk_size); - - memset(tape->cur, 0, aligned - tape->valid); - idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, aligned); - kfree(tape->buf); - tape->buf = NULL; + if (tape->merge_bh_size > tape->buffer_size) { + printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n"); + tape->merge_bh_size = tape->buffer_size; + } + if (tape->merge_bh_size) { + blocks = tape->merge_bh_size / tape->blk_size; + if (tape->merge_bh_size % tape->blk_size) { + unsigned int i; + + blocks++; + i = tape->blk_size - tape->merge_bh_size % + tape->blk_size; + bh = tape->bh->b_reqnext; + while (bh) { + atomic_set(&bh->b_count, 0); + bh = bh->b_reqnext; + } + bh = tape->bh; + while (i) { + if (bh == NULL) { + printk(KERN_INFO "ide-tape: bug," + " bh NULL\n"); + break; + } + min = min(i, (unsigned int)(bh->b_size - + atomic_read(&bh->b_count))); + memset(bh->b_data + atomic_read(&bh->b_count), + 0, min); + atomic_add(min, &bh->b_count); + i -= min; + bh = bh->b_reqnext; + } + } + (void) idetape_add_chrdev_write_request(drive, blocks); + tape->merge_bh_size = 0; + } + if (tape->merge_bh != NULL) { + ide_tape_kfree_buffer(tape); + tape->merge_bh = NULL; } tape->chrdev_dir = IDETAPE_DIR_NONE; } -static int idetape_init_rw(ide_drive_t *drive, int dir) +static int idetape_init_read(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - int rc; - - BUG_ON(dir != IDETAPE_DIR_READ && dir != IDETAPE_DIR_WRITE); + int bytes_read; - if (tape->chrdev_dir == dir) - return 0; + /* Initialize read operation */ + if (tape->chrdev_dir != IDETAPE_DIR_READ) { + if (tape->chrdev_dir == IDETAPE_DIR_WRITE) { + ide_tape_flush_merge_buffer(drive); + idetape_flush_tape_buffers(drive); + } + if (tape->merge_bh || tape->merge_bh_size) { + printk(KERN_ERR "ide-tape: merge_bh_size should be" + " 0 now\n"); + tape->merge_bh_size = 0; + } + tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0); + if (!tape->merge_bh) + return -ENOMEM; + tape->chrdev_dir = IDETAPE_DIR_READ; - if (tape->chrdev_dir == IDETAPE_DIR_READ) - ide_tape_discard_merge_buffer(drive, 1); - else if (tape->chrdev_dir == IDETAPE_DIR_WRITE) { - ide_tape_flush_merge_buffer(drive); - idetape_flush_tape_buffers(drive); + /* + * Issue a read 0 command to ensure that DSC handshake is + * switched from completion mode to buffer available mode. + * No point in issuing this if DSC overlap isn't supported, some + * drives (Seagate STT3401A) will return an error. + */ + if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { + bytes_read = idetape_queue_rw_tail(drive, + REQ_IDETAPE_READ, 0, + tape->merge_bh); + if (bytes_read < 0) { + ide_tape_kfree_buffer(tape); + tape->merge_bh = NULL; + tape->chrdev_dir = IDETAPE_DIR_NONE; + return bytes_read; + } + } } - if (tape->buf || tape->valid) { - printk(KERN_ERR "ide-tape: valid should be 0 now\n"); - tape->valid = 0; - } + return 0; +} - tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL); - if (!tape->buf) - return -ENOMEM; - tape->chrdev_dir = dir; - tape->cur = tape->buf; +/* called from idetape_chrdev_read() to service a chrdev read request. */ +static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks) +{ + idetape_tape_t *tape = drive->driver_data; - /* - * Issue a 0 rw command to ensure that DSC handshake is - * switched from completion mode to buffer available mode. No - * point in issuing this if DSC overlap isn't supported, some - * drives (Seagate STT3401A) will return an error. - */ - if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { - int cmd = dir == IDETAPE_DIR_READ ? REQ_IDETAPE_READ - : REQ_IDETAPE_WRITE; - - rc = idetape_queue_rw_tail(drive, cmd, 0); - if (rc < 0) { - kfree(tape->buf); - tape->buf = NULL; - tape->chrdev_dir = IDETAPE_DIR_NONE; - return rc; - } - } + debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks); - return 0; + /* If we are at a filemark, return a read length of 0 */ + if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) + return 0; + + idetape_init_read(drive); + + return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks, + tape->merge_bh); } static void idetape_pad_zeros(ide_drive_t *drive, int bcount) { idetape_tape_t *tape = drive->driver_data; - - memset(tape->buf, 0, tape->buffer_size); + struct idetape_bh *bh; + int blocks; while (bcount) { - unsigned int count = min(tape->buffer_size, bcount); + unsigned int count; - idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, count); + bh = tape->merge_bh; + count = min(tape->buffer_size, bcount); bcount -= count; + blocks = count / tape->blk_size; + while (count) { + atomic_set(&bh->b_count, + min(count, (unsigned int)bh->b_size)); + memset(bh->b_data, 0, atomic_read(&bh->b_count)); + count -= atomic_read(&bh->b_count); + bh = bh->b_reqnext; + } + idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks, + tape->merge_bh); } } @@ -1112,7 +1456,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op, } if (tape->chrdev_dir == IDETAPE_DIR_READ) { - tape->valid = 0; + tape->merge_bh_size = 0; if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) ++count; ide_tape_discard_merge_buffer(drive, 0); @@ -1161,9 +1505,9 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, { struct ide_tape_obj *tape = file->private_data; ide_drive_t *drive = tape->drive; - size_t done = 0; + ssize_t bytes_read, temp, actually_read = 0, rc; ssize_t ret = 0; - int rc; + u16 ctl = *(u16 *)&tape->caps[12]; debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); @@ -1173,43 +1517,49 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, (count % tape->blk_size) == 0) tape->user_bs_factor = count / tape->blk_size; } - - rc = idetape_init_rw(drive, IDETAPE_DIR_READ); + rc = idetape_init_read(drive); if (rc < 0) return rc; - - while (done < count) { - size_t todo; - - /* refill if staging buffer is empty */ - if (!tape->valid) { - /* If we are at a filemark, nothing more to read */ - if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) - break; - /* read */ - if (idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, - tape->buffer_size) <= 0) - break; - } - - /* copy out */ - todo = min_t(size_t, count - done, tape->valid); - if (copy_to_user(buf + done, tape->cur, todo)) + if (count == 0) + return (0); + if (tape->merge_bh_size) { + actually_read = min((unsigned int)(tape->merge_bh_size), + (unsigned int)count); + if (idetape_copy_stage_to_user(tape, buf, actually_read)) ret = -EFAULT; - - tape->cur += todo; - tape->valid -= todo; - done += todo; + buf += actually_read; + tape->merge_bh_size -= actually_read; + count -= actually_read; } - - if (!done && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) { + while (count >= tape->buffer_size) { + bytes_read = idetape_add_chrdev_read_request(drive, ctl); + if (bytes_read <= 0) + goto finish; + if (idetape_copy_stage_to_user(tape, buf, bytes_read)) + ret = -EFAULT; + buf += bytes_read; + count -= bytes_read; + actually_read += bytes_read; + } + if (count) { + bytes_read = idetape_add_chrdev_read_request(drive, ctl); + if (bytes_read <= 0) + goto finish; + temp = min((unsigned long)count, (unsigned long)bytes_read); + if (idetape_copy_stage_to_user(tape, buf, temp)) + ret = -EFAULT; + actually_read += temp; + tape->merge_bh_size = bytes_read-temp; + } +finish: + if (!actually_read && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) { debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name); idetape_space_over_filemarks(drive, MTFSF, 1); return 0; } - return ret ? ret : done; + return ret ? ret : actually_read; } static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, @@ -1217,9 +1567,9 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, { struct ide_tape_obj *tape = file->private_data; ide_drive_t *drive = tape->drive; - size_t done = 0; + ssize_t actually_written = 0; ssize_t ret = 0; - int rc; + u16 ctl = *(u16 *)&tape->caps[12]; /* The drive is write protected. */ if (tape->write_prot) @@ -1228,31 +1578,80 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); /* Initialize write operation */ - rc = idetape_init_rw(drive, IDETAPE_DIR_WRITE); - if (rc < 0) - return rc; - - while (done < count) { - size_t todo; - - /* flush if staging buffer is full */ - if (tape->valid == tape->buffer_size && - idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, - tape->buffer_size) <= 0) - return rc; + if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { + if (tape->chrdev_dir == IDETAPE_DIR_READ) + ide_tape_discard_merge_buffer(drive, 1); + if (tape->merge_bh || tape->merge_bh_size) { + printk(KERN_ERR "ide-tape: merge_bh_size " + "should be 0 now\n"); + tape->merge_bh_size = 0; + } + tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0); + if (!tape->merge_bh) + return -ENOMEM; + tape->chrdev_dir = IDETAPE_DIR_WRITE; + idetape_init_merge_buffer(tape); - /* copy in */ - todo = min_t(size_t, count - done, - tape->buffer_size - tape->valid); - if (copy_from_user(tape->cur, buf + done, todo)) + /* + * Issue a write 0 command to ensure that DSC handshake is + * switched from completion mode to buffer available mode. No + * point in issuing this if DSC overlap isn't supported, some + * drives (Seagate STT3401A) will return an error. + */ + if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { + ssize_t retval = idetape_queue_rw_tail(drive, + REQ_IDETAPE_WRITE, 0, + tape->merge_bh); + if (retval < 0) { + ide_tape_kfree_buffer(tape); + tape->merge_bh = NULL; + tape->chrdev_dir = IDETAPE_DIR_NONE; + return retval; + } + } + } + if (count == 0) + return (0); + if (tape->merge_bh_size) { + if (tape->merge_bh_size >= tape->buffer_size) { + printk(KERN_ERR "ide-tape: bug: merge buf too big\n"); + tape->merge_bh_size = 0; + } + actually_written = min((unsigned int) + (tape->buffer_size - tape->merge_bh_size), + (unsigned int)count); + if (idetape_copy_stage_from_user(tape, buf, actually_written)) + ret = -EFAULT; + buf += actually_written; + tape->merge_bh_size += actually_written; + count -= actually_written; + + if (tape->merge_bh_size == tape->buffer_size) { + ssize_t retval; + tape->merge_bh_size = 0; + retval = idetape_add_chrdev_write_request(drive, ctl); + if (retval <= 0) + return (retval); + } + } + while (count >= tape->buffer_size) { + ssize_t retval; + if (idetape_copy_stage_from_user(tape, buf, tape->buffer_size)) ret = -EFAULT; - - tape->cur += todo; - tape->valid += todo; - done += todo; + buf += tape->buffer_size; + count -= tape->buffer_size; + retval = idetape_add_chrdev_write_request(drive, ctl); + actually_written += tape->buffer_size; + if (retval <= 0) + return (retval); } - - return ret ? ret : done; + if (count) { + actually_written += count; + if (idetape_copy_stage_from_user(tape, buf, count)) + ret = -EFAULT; + tape->merge_bh_size += count; + } + return ret ? ret : actually_written; } static int idetape_write_filemark(ide_drive_t *drive) @@ -1413,7 +1812,7 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file, idetape_flush_tape_buffers(drive); } if (cmd == MTIOCGET || cmd == MTIOCPOS) { - block_offset = tape->valid / + block_offset = tape->merge_bh_size / (tape->blk_size * tape->user_bs_factor); position = idetape_read_position(drive); if (position < 0) @@ -1561,12 +1960,12 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor) idetape_tape_t *tape = drive->driver_data; ide_tape_flush_merge_buffer(drive); - tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL); - if (tape->buf != NULL) { + tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1, 0); + if (tape->merge_bh != NULL) { idetape_pad_zeros(drive, tape->blk_size * (tape->user_bs_factor - 1)); - kfree(tape->buf); - tape->buf = NULL; + ide_tape_kfree_buffer(tape); + tape->merge_bh = NULL; } idetape_write_filemark(drive); idetape_flush_tape_buffers(drive); @@ -1760,6 +2159,8 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) u16 *ctl = (u16 *)&tape->caps[12]; drive->pc_callback = ide_tape_callback; + drive->pc_update_buffers = idetape_update_buffers; + drive->pc_io_buffers = ide_tape_io_buffers; drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP; @@ -1790,6 +2191,11 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) tape->buffer_size = *ctl * tape->blk_size; } buffer_size = tape->buffer_size; + tape->pages_per_buffer = buffer_size / PAGE_SIZE; + if (buffer_size % PAGE_SIZE) { + tape->pages_per_buffer++; + tape->excess_bh_size = PAGE_SIZE - buffer_size % PAGE_SIZE; + } /* select the "best" DSC read/write polling freq */ speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]); @@ -1832,7 +2238,7 @@ static void ide_tape_release(struct device *dev) ide_drive_t *drive = tape->drive; struct gendisk *g = tape->disk; - BUG_ON(tape->valid); + BUG_ON(tape->merge_bh_size); drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP; drive->driver_data = NULL; diff --git a/trunk/drivers/ide/ide-taskfile.c b/trunk/drivers/ide/ide-taskfile.c index 8cab3c26acda..4aa6223c11be 100644 --- a/trunk/drivers/ide/ide-taskfile.c +++ b/trunk/drivers/ide/ide-taskfile.c @@ -166,7 +166,7 @@ static ide_startstop_t task_no_data_intr(ide_drive_t *drive) if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { if (custom && tf->command == ATA_CMD_SET_MULTI) { drive->mult_req = drive->mult_count = 0; - drive->special_flags |= IDE_SFLAG_RECALIBRATE; + drive->special.b.recalibrate = 1; (void)ide_dump_status(drive, __func__, stat); return ide_stopped; } else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) { @@ -424,9 +424,7 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf, rq = blk_get_request(drive->queue, READ, __GFP_WAIT); rq->cmd_type = REQ_TYPE_ATA_TASKFILE; - - if (cmd->tf_flags & IDE_TFLAG_WRITE) - rq->cmd_flags |= REQ_RW; + rq->buffer = buf; /* * (ks) We transfer currently only whole sectors. @@ -434,20 +432,18 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf, * if we would find a solution to transfer any size. * To support special commands like READ LONG. */ - if (nsect) { - error = blk_rq_map_kern(drive->queue, rq, buf, - nsect * SECTOR_SIZE, __GFP_WAIT); - if (error) - goto put_req; - } + rq->hard_nr_sectors = rq->nr_sectors = nsect; + rq->hard_cur_sectors = rq->current_nr_sectors = nsect; + + if (cmd->tf_flags & IDE_TFLAG_WRITE) + rq->cmd_flags |= REQ_RW; rq->special = cmd; cmd->rq = rq; error = blk_execute_rq(drive->queue, NULL, rq, 0); - -put_req: blk_put_request(rq); + return error; } diff --git a/trunk/drivers/ide/ide_platform.c b/trunk/drivers/ide/ide_platform.c index ee9b55ecc62b..051b4ab0f359 100644 --- a/trunk/drivers/ide/ide_platform.c +++ b/trunk/drivers/ide/ide_platform.c @@ -21,7 +21,7 @@ #include #include -static void __devinit plat_ide_setup_ports(struct ide_hw *hw, +static void __devinit plat_ide_setup_ports(hw_regs_t *hw, void __iomem *base, void __iomem *ctrl, struct pata_platform_info *pdata, @@ -40,11 +40,12 @@ static void __devinit plat_ide_setup_ports(struct ide_hw *hw, hw->io_ports.ctl_addr = (unsigned long)ctrl; hw->irq = irq; + + hw->chipset = ide_generic; } static const struct ide_port_info platform_ide_port_info = { .host_flags = IDE_HFLAG_NO_DMA, - .chipset = ide_generic, }; static int __devinit plat_ide_probe(struct platform_device *pdev) @@ -54,7 +55,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) struct pata_platform_info *pdata; struct ide_host *host; int ret = 0, mmio = 0; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; struct ide_port_info d = platform_ide_port_info; pdata = pdev->dev.platform_data; @@ -98,7 +99,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) if (mmio) d.host_flags |= IDE_HFLAG_MMIO; - ret = ide_host_add(&d, hws, 1, &host); + ret = ide_host_add(&d, hws, &host); if (ret) goto out; diff --git a/trunk/drivers/ide/macide.c b/trunk/drivers/ide/macide.c index 1447c8c90565..4b1718e83283 100644 --- a/trunk/drivers/ide/macide.c +++ b/trunk/drivers/ide/macide.c @@ -62,7 +62,7 @@ int macide_ack_intr(ide_hwif_t* hwif) return 0; } -static void __init macide_setup_ports(struct ide_hw *hw, unsigned long base, +static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base, int irq, ide_ack_intr_t *ack_intr) { int i; @@ -76,12 +76,13 @@ static void __init macide_setup_ports(struct ide_hw *hw, unsigned long base, hw->irq = irq; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static const struct ide_port_info macide_port_info = { .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, - .chipset = ide_generic, }; static const char *mac_ide_name[] = @@ -96,7 +97,7 @@ static int __init macide_init(void) ide_ack_intr_t *ack_intr; unsigned long base; int irq; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; if (!MACH_IS_MAC) return -ENODEV; @@ -126,7 +127,7 @@ static int __init macide_init(void) macide_setup_ports(&hw, base, irq, ack_intr); - return ide_host_add(&macide_port_info, hws, 1, NULL); + return ide_host_add(&macide_port_info, hws, NULL); } module_init(macide_init); diff --git a/trunk/drivers/ide/palm_bk3710.c b/trunk/drivers/ide/palm_bk3710.c index 3c1dc0152153..09d813d313f4 100644 --- a/trunk/drivers/ide/palm_bk3710.c +++ b/trunk/drivers/ide/palm_bk3710.c @@ -306,7 +306,6 @@ static struct ide_port_info __devinitdata palm_bk3710_port_info = { .host_flags = IDE_HFLAG_MMIO, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, - .chipset = ide_palm3710, }; static int __init palm_bk3710_probe(struct platform_device *pdev) @@ -316,7 +315,7 @@ static int __init palm_bk3710_probe(struct platform_device *pdev) void __iomem *base; unsigned long rate, mem_size; int i, rc; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; clk = clk_get(&pdev->dev, "IDECLK"); if (IS_ERR(clk)) @@ -364,12 +363,13 @@ static int __init palm_bk3710_probe(struct platform_device *pdev) (base + IDE_PALM_ATA_PRI_CTL_OFFSET); hw.irq = irq->start; hw.dev = &pdev->dev; + hw.chipset = ide_palm3710; palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 : ATA_UDMA5; /* Register the IDE interface with Linux */ - rc = ide_host_add(&palm_bk3710_port_info, hws, 1, NULL); + rc = ide_host_add(&palm_bk3710_port_info, hws, NULL); if (rc) goto out; diff --git a/trunk/drivers/ide/pdc202xx_old.c b/trunk/drivers/ide/pdc202xx_old.c index 248a54bd2386..b3bc96f930a6 100644 --- a/trunk/drivers/ide/pdc202xx_old.c +++ b/trunk/drivers/ide/pdc202xx_old.c @@ -1,6 +1,6 @@ /* * Copyright (C) 1998-2002 Andre Hedrick - * Copyright (C) 2006-2007 MontaVista Software, Inc. + * Copyright (C) 2006-2007, 2009 MontaVista Software, Inc. * Copyright (C) 2007 Bartlomiej Zolnierkiewicz * * Portions Copyright (C) 1999 Promise Technology, Inc. @@ -227,28 +227,19 @@ static int pdc202xx_dma_test_irq(ide_drive_t *drive) return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ } -static void pdc202xx_reset_host (ide_hwif_t *hwif) +static void pdc202xx_reset(ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; unsigned long high_16 = hwif->extra_base - 16; u8 udma_speed_flag = inb(high_16 | 0x001f); + printk(KERN_WARNING "PDC202xx: software reset...\n"); + outb(udma_speed_flag | 0x10, high_16 | 0x001f); mdelay(100); outb(udma_speed_flag & ~0x10, high_16 | 0x001f); mdelay(2000); /* 2 seconds ?! */ - printk(KERN_WARNING "PDC202XX: %s channel reset.\n", - hwif->channel ? "Secondary" : "Primary"); -} - -static void pdc202xx_reset (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - ide_hwif_t *mate = hwif->mate; - - pdc202xx_reset_host(hwif); - pdc202xx_reset_host(mate); - ide_set_max_pio(drive); } @@ -328,9 +319,8 @@ static const struct ide_dma_ops pdc20246_dma_ops = { .dma_start = ide_dma_start, .dma_end = ide_dma_end, .dma_test_irq = pdc202xx_dma_test_irq, - .dma_lost_irq = pdc202xx_dma_lost_irq, + .dma_lost_irq = ide_dma_lost_irq, .dma_timer_expiry = ide_dma_sff_timer_expiry, - .dma_clear = pdc202xx_reset, .dma_sff_read_status = ide_dma_sff_read_status, }; diff --git a/trunk/drivers/ide/pmac.c b/trunk/drivers/ide/pmac.c index 97642a7a79c4..f76e4e6b408f 100644 --- a/trunk/drivers/ide/pmac.c +++ b/trunk/drivers/ide/pmac.c @@ -1023,14 +1023,13 @@ static const struct ide_port_info pmac_port_info = { * Setup, register & probe an IDE channel driven by this driver, this is * called by one of the 2 probe functions (macio or PCI). */ -static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, - struct ide_hw *hw) +static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw) { struct device_node *np = pmif->node; const int *bidp; struct ide_host *host; ide_hwif_t *hwif; - struct ide_hw *hws[] = { hw }; + hw_regs_t *hws[] = { hw, NULL, NULL, NULL }; struct ide_port_info d = pmac_port_info; int rc; @@ -1078,7 +1077,7 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, /* Make sure we have sane timings */ sanitize_timings(pmif); - host = ide_host_alloc(&d, hws, 1); + host = ide_host_alloc(&d, hws); if (host == NULL) return -ENOMEM; hwif = host->ports[0]; @@ -1125,7 +1124,7 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, return 0; } -static void __devinit pmac_ide_init_ports(struct ide_hw *hw, unsigned long base) +static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base) { int i; @@ -1145,7 +1144,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) unsigned long regbase; pmac_ide_hwif_t *pmif; int irq, rc; - struct ide_hw hw; + hw_regs_t hw; pmif = kzalloc(sizeof(*pmif), GFP_KERNEL); if (pmif == NULL) @@ -1269,7 +1268,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) void __iomem *base; unsigned long rbase, rlen; int rc; - struct ide_hw hw; + hw_regs_t hw; np = pci_device_to_OF_node(pdev); if (np == NULL) { diff --git a/trunk/drivers/ide/q40ide.c b/trunk/drivers/ide/q40ide.c index ab49a97023d9..c79346679244 100644 --- a/trunk/drivers/ide/q40ide.c +++ b/trunk/drivers/ide/q40ide.c @@ -51,11 +51,11 @@ static int q40ide_default_irq(unsigned long base) /* * Addresses are pretranslated for Q40 ISA access. */ -static void q40_ide_setup_ports(struct ide_hw *hw, unsigned long base, +static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base, ide_ack_intr_t *ack_intr, int irq) { - memset(hw, 0, sizeof(*hw)); + memset(hw, 0, sizeof(hw_regs_t)); /* BIG FAT WARNING: assumption: only DATA port is ever used in 16 bit mode */ hw->io_ports.data_addr = Q40_ISA_IO_W(base); @@ -70,6 +70,8 @@ static void q40_ide_setup_ports(struct ide_hw *hw, unsigned long base, hw->irq = irq; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static void q40ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, @@ -117,7 +119,6 @@ static const struct ide_port_info q40ide_port_info = { .tp_ops = &q40ide_tp_ops, .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, - .chipset = ide_generic, }; /* @@ -135,7 +136,7 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={ static int __init q40ide_init(void) { int i; - struct ide_hw hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL }; + hw_regs_t hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; if (!MACH_IS_Q40) return -ENODEV; @@ -162,7 +163,7 @@ static int __init q40ide_init(void) hws[i] = &hw[i]; } - return ide_host_add(&q40ide_port_info, hws, Q40IDE_NUM_HWIFS, NULL); + return ide_host_add(&q40ide_port_info, hws, NULL); } module_init(q40ide_init); diff --git a/trunk/drivers/ide/rapide.c b/trunk/drivers/ide/rapide.c index 00f54248f41f..d5003ca69801 100644 --- a/trunk/drivers/ide/rapide.c +++ b/trunk/drivers/ide/rapide.c @@ -13,10 +13,9 @@ static const struct ide_port_info rapide_port_info = { .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, - .chipset = ide_generic, }; -static void rapide_setup_ports(struct ide_hw *hw, void __iomem *base, +static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base, void __iomem *ctrl, unsigned int sz, int irq) { unsigned long port = (unsigned long)base; @@ -36,7 +35,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) void __iomem *base; struct ide_host *host; int ret; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; ret = ecard_request_resources(ec); if (ret) @@ -50,9 +49,10 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) memset(&hw, 0, sizeof(hw)); rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq); + hw.chipset = ide_generic; hw.dev = &ec->dev; - ret = ide_host_add(&rapide_port_info, hws, 1, &host); + ret = ide_host_add(&rapide_port_info, hws, &host); if (ret) goto release; diff --git a/trunk/drivers/ide/scc_pata.c b/trunk/drivers/ide/scc_pata.c index 1104bb301eb9..5be41f25204f 100644 --- a/trunk/drivers/ide/scc_pata.c +++ b/trunk/drivers/ide/scc_pata.c @@ -559,7 +559,7 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev, { struct scc_ports *ports = pci_get_drvdata(dev); struct ide_host *host; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; int i, rc; memset(&hw, 0, sizeof(hw)); @@ -567,8 +567,9 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev, hw.io_ports_array[i] = ports->dma + 0x20 + i * 4; hw.irq = dev->irq; hw.dev = &dev->dev; + hw.chipset = ide_pci; - rc = ide_host_add(d, hws, 1, &host); + rc = ide_host_add(d, hws, &host); if (rc) return rc; @@ -822,7 +823,6 @@ static const struct ide_port_info scc_chipset __devinitdata = { .host_flags = IDE_HFLAG_SINGLE, .irq_flags = IRQF_SHARED, .pio_mask = ATA_PIO4, - .chipset = ide_pci, }; /** diff --git a/trunk/drivers/ide/setup-pci.c b/trunk/drivers/ide/setup-pci.c index 5314edffc303..7a3a12d6e638 100644 --- a/trunk/drivers/ide/setup-pci.c +++ b/trunk/drivers/ide/setup-pci.c @@ -301,11 +301,11 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info * } /** - * ide_hw_configure - configure a struct ide_hw instance + * ide_hw_configure - configure a hw_regs_t instance * @dev: PCI device holding interface * @d: IDE port info * @port: port number - * @hw: struct ide_hw instance corresponding to this port + * @hw: hw_regs_t instance corresponding to this port * * Perform the initial set up for the hardware interface structure. This * is done per interface port rather than per PCI device. There may be @@ -315,7 +315,7 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info * */ static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, - unsigned int port, struct ide_hw *hw) + unsigned int port, hw_regs_t *hw) { unsigned long ctl = 0, base = 0; @@ -344,6 +344,7 @@ static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, memset(hw, 0, sizeof(*hw)); hw->dev = &dev->dev; + hw->chipset = d->chipset ? d->chipset : ide_pci; ide_std_init_ports(hw, base, ctl | 2); return 0; @@ -445,8 +446,8 @@ static int ide_setup_pci_controller(struct pci_dev *dev, * ide_pci_setup_ports - configure ports/devices on PCI IDE * @dev: PCI device * @d: IDE port info - * @hw: struct ide_hw instances corresponding to this PCI IDE device - * @hws: struct ide_hw pointers table to update + * @hw: hw_regs_t instances corresponding to this PCI IDE device + * @hws: hw_regs_t pointers table to update * * Scan the interfaces attached to this device and do any * necessary per port setup. Attach the devices and ask the @@ -458,7 +459,7 @@ static int ide_setup_pci_controller(struct pci_dev *dev, */ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, - struct ide_hw *hw, struct ide_hw **hws) + hw_regs_t *hw, hw_regs_t **hws) { int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port; u8 tmp; @@ -538,7 +539,7 @@ int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, void *priv) { struct ide_host *host; - struct ide_hw hw[2], *hws[] = { NULL, NULL }; + hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; int ret; ret = ide_setup_pci_controller(dev, d, 1); @@ -547,7 +548,7 @@ int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); - host = ide_host_alloc(d, hws, 2); + host = ide_host_alloc(d, hws); if (host == NULL) { ret = -ENOMEM; goto out; @@ -586,7 +587,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, struct pci_dev *pdev[] = { dev1, dev2 }; struct ide_host *host; int ret, i; - struct ide_hw hw[4], *hws[] = { NULL, NULL, NULL, NULL }; + hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; for (i = 0; i < 2; i++) { ret = ide_setup_pci_controller(pdev[i], d, !i); @@ -596,7 +597,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]); } - host = ide_host_alloc(d, hws, 4); + host = ide_host_alloc(d, hws); if (host == NULL) { ret = -ENOMEM; goto out; diff --git a/trunk/drivers/ide/sgiioc4.c b/trunk/drivers/ide/sgiioc4.c index 5f37f168f944..e5d2a48a84de 100644 --- a/trunk/drivers/ide/sgiioc4.c +++ b/trunk/drivers/ide/sgiioc4.c @@ -91,7 +91,7 @@ typedef struct { static void -sgiioc4_init_hwif_ports(struct ide_hw *hw, unsigned long data_port, +sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port, unsigned long ctrl_port, unsigned long irq_port) { unsigned long reg = data_port; @@ -546,7 +546,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) unsigned long cmd_base, irqport; unsigned long bar0, cmd_phys_base, ctl; void __iomem *virt_base; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; int rc; /* Get the CmdBlk and CtrlBlk Base Registers */ @@ -575,12 +575,13 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) memset(&hw, 0, sizeof(hw)); sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport); hw.irq = dev->irq; + hw.chipset = ide_pci; hw.dev = &dev->dev; /* Initializing chipset IRQ Registers */ writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); - rc = ide_host_add(&sgiioc4_port_info, hws, 1, NULL); + rc = ide_host_add(&sgiioc4_port_info, hws, NULL); if (!rc) return 0; diff --git a/trunk/drivers/ide/siimage.c b/trunk/drivers/ide/siimage.c index bd82d228608c..e4973cd1fba9 100644 --- a/trunk/drivers/ide/siimage.c +++ b/trunk/drivers/ide/siimage.c @@ -451,8 +451,8 @@ static int sil_sata_reset_poll(ide_drive_t *drive) static void sil_sata_pre_reset(ide_drive_t *drive) { if (drive->media == ide_disk) { - drive->special_flags &= - ~(IDE_SFLAG_SET_GEOMETRY | IDE_SFLAG_RECALIBRATE); + drive->special.b.set_geometry = 0; + drive->special.b.recalibrate = 0; } } diff --git a/trunk/drivers/ide/tx4938ide.c b/trunk/drivers/ide/tx4938ide.c index ea89fddeed91..e33d764e2945 100644 --- a/trunk/drivers/ide/tx4938ide.c +++ b/trunk/drivers/ide/tx4938ide.c @@ -130,7 +130,8 @@ static const struct ide_port_info tx4938ide_port_info __initdata = { static int __init tx4938ide_probe(struct platform_device *pdev) { - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw; + hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; struct ide_host *host; struct resource *res; struct tx4938ide_platform_info *pdata = pdev->dev.platform_data; @@ -182,7 +183,7 @@ static int __init tx4938ide_probe(struct platform_device *pdev) tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, 0); else d.port_ops = NULL; - ret = ide_host_add(&d, hws, 1, &host); + ret = ide_host_add(&d, hws, &host); if (!ret) platform_set_drvdata(pdev, host); return ret; diff --git a/trunk/drivers/ide/tx4939ide.c b/trunk/drivers/ide/tx4939ide.c index 9f73fd43d1f4..564422d23976 100644 --- a/trunk/drivers/ide/tx4939ide.c +++ b/trunk/drivers/ide/tx4939ide.c @@ -537,7 +537,8 @@ static const struct ide_port_info tx4939ide_port_info __initdata = { static int __init tx4939ide_probe(struct platform_device *pdev) { - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw; + hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; struct ide_host *host; struct resource *res; int irq, ret; @@ -580,7 +581,7 @@ static int __init tx4939ide_probe(struct platform_device *pdev) hw.dev = &pdev->dev; pr_info("TX4939 IDE interface (base %#lx, irq %d)\n", mapbase, irq); - host = ide_host_alloc(&tx4939ide_port_info, hws, 1); + host = ide_host_alloc(&tx4939ide_port_info, hws); if (!host) return -ENOMEM; /* use extra_base for base address of the all registers */ diff --git a/trunk/fs/partitions/check.c b/trunk/fs/partitions/check.c index 99e33ef40be4..137a708bb215 100644 --- a/trunk/fs/partitions/check.c +++ b/trunk/fs/partitions/check.c @@ -564,7 +564,8 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) * creating invalid block devices */ printk(KERN_WARNING - "%s: p%d size %llu limited to end of disk\n", + "%s: p%d size %llu exceeds device capacity, " + "limited to end of disk\n", disk->disk_name, p, (unsigned long long) size); size = get_capacity(disk) - from; } diff --git a/trunk/include/linux/ide.h b/trunk/include/linux/ide.h index 015955632091..9fed365a598b 100644 --- a/trunk/include/linux/ide.h +++ b/trunk/include/linux/ide.h @@ -26,9 +26,6 @@ #include #include -/* for request_sense */ -#include - #if defined(CONFIG_CRIS) || defined(CONFIG_FRV) || defined(CONFIG_MN10300) # define SUPPORT_VLB_SYNC 0 #else @@ -178,7 +175,7 @@ typedef u8 hwif_chipset_t; /* * Structure to hold all information about the location of this port */ -struct ide_hw { +typedef struct hw_regs_s { union { struct ide_io_ports io_ports; unsigned long io_ports_array[IDE_NR_PORTS]; @@ -186,11 +183,12 @@ struct ide_hw { int irq; /* our irq number */ ide_ack_intr_t *ack_intr; /* acknowledge interrupt */ + hwif_chipset_t chipset; struct device *dev, *parent; unsigned long config; -}; +} hw_regs_t; -static inline void ide_std_init_ports(struct ide_hw *hw, +static inline void ide_std_init_ports(hw_regs_t *hw, unsigned long io_addr, unsigned long ctl_addr) { @@ -217,12 +215,21 @@ static inline void ide_std_init_ports(struct ide_hw *hw, /* * Special Driver Flags + * + * set_geometry : respecify drive geometry + * recalibrate : seek to cyl 0 + * set_multmode : set multmode count + * reserved : unused */ -enum { - IDE_SFLAG_SET_GEOMETRY = (1 << 0), - IDE_SFLAG_RECALIBRATE = (1 << 1), - IDE_SFLAG_SET_MULTMODE = (1 << 2), -}; +typedef union { + unsigned all : 8; + struct { + unsigned set_geometry : 1; + unsigned recalibrate : 1; + unsigned set_multmode : 1; + unsigned reserved : 5; + } b; +} special_t; /* * Status returned from various ide_ functions @@ -317,6 +324,7 @@ struct ide_cmd { unsigned int cursg_ofs; struct request *rq; /* copy of request */ + void *special; /* valid_t generally */ }; /* ATAPI packet command flags */ @@ -352,7 +360,11 @@ struct ide_atapi_pc { /* data buffer */ u8 *buf; + /* current buffer position */ + u8 *cur_pos; int buf_size; + /* missing/available data on the current buffer */ + int b_count; /* the corresponding request */ struct request *rq; @@ -365,6 +377,10 @@ struct ide_atapi_pc { */ u8 pc_buf[IDE_PC_BUFFER_SIZE]; + /* idetape only */ + struct idetape_bh *bh; + char *b_data; + unsigned long timeout; }; @@ -520,7 +536,7 @@ struct ide_drive_s { unsigned long sleep; /* sleep until this time */ unsigned long timeout; /* max time to wait for irq */ - u8 special_flags; /* special action flags */ + special_t special; /* special action flags */ u8 select; /* basic drive/head select reg value */ u8 retry_pio; /* retrying dma capable host in pio */ @@ -577,16 +593,16 @@ struct ide_drive_s { /* callback for packet commands */ int (*pc_callback)(struct ide_drive_s *, int); + void (*pc_update_buffers)(struct ide_drive_s *, struct ide_atapi_pc *); + int (*pc_io_buffers)(struct ide_drive_s *, struct ide_atapi_pc *, + unsigned int, int); + ide_startstop_t (*irq_handler)(struct ide_drive_s *); unsigned long atapi_flags; struct ide_atapi_pc request_sense_pc; - - /* current sense rq and buffer */ - bool sense_rq_armed; - struct request sense_rq; - struct request_sense sense_data; + struct request request_sense_rq; }; typedef struct ide_drive_s ide_drive_t; @@ -1158,10 +1174,7 @@ int ide_do_test_unit_ready(ide_drive_t *, struct gendisk *); int ide_do_start_stop(ide_drive_t *, struct gendisk *, int); int ide_set_media_lock(ide_drive_t *, struct gendisk *, int); void ide_create_request_sense_cmd(ide_drive_t *, struct ide_atapi_pc *); -void ide_retry_pc(ide_drive_t *drive); - -void ide_prep_sense(ide_drive_t *drive, struct request *rq); -int ide_queue_sense_rq(ide_drive_t *drive, void *special); +void ide_retry_pc(ide_drive_t *, struct gendisk *); int ide_cd_expiry(ide_drive_t *); @@ -1212,7 +1225,7 @@ static inline int ide_pci_is_in_compatibility_mode(struct pci_dev *dev) } void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, - struct ide_hw *, struct ide_hw **); + hw_regs_t *, hw_regs_t **); void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *); #ifdef CONFIG_BLK_DEV_IDEDMA_PCI @@ -1456,12 +1469,11 @@ void ide_undecoded_slave(ide_drive_t *); void ide_port_apply_params(ide_hwif_t *); int ide_sysfs_register_port(ide_hwif_t *); -struct ide_host *ide_host_alloc(const struct ide_port_info *, struct ide_hw **, - unsigned int); +struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **); void ide_host_free(struct ide_host *); int ide_host_register(struct ide_host *, const struct ide_port_info *, - struct ide_hw **); -int ide_host_add(const struct ide_port_info *, struct ide_hw **, unsigned int, + hw_regs_t **); +int ide_host_add(const struct ide_port_info *, hw_regs_t **, struct ide_host **); void ide_host_remove(struct ide_host *); int ide_legacy_device_add(const struct ide_port_info *, unsigned long);