diff options
Diffstat (limited to 'drivers/ide/ide-cd.c')
| -rw-r--r-- | drivers/ide/ide-cd.c | 428 |
1 files changed, 184 insertions, 244 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 925eb9e245d..0b510bafd90 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -30,6 +30,7 @@ #include <linux/kernel.h> #include <linux/delay.h> #include <linux/timer.h> +#include <linux/seq_file.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/errno.h> @@ -42,7 +43,6 @@ /* For SCSI -> ATAPI command conversion */ #include <scsi/scsi.h> -#include <linux/irq.h> #include <linux/io.h> #include <asm/byteorder.h> #include <linux/uaccess.h> @@ -50,6 +50,7 @@ #include "ide-cd.h" +static DEFINE_MUTEX(ide_cd_mutex); static DEFINE_MUTEX(idecd_ref_mutex); static void ide_cd_release(struct device *); @@ -92,16 +93,16 @@ static void cdrom_saw_media_change(ide_drive_t *drive) drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID; } -static int cdrom_log_sense(ide_drive_t *drive, struct request *rq, - struct request_sense *sense) +static int cdrom_log_sense(ide_drive_t *drive, struct request *rq) { + struct request_sense *sense = &drive->sense_data; int log = 0; - ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key); - if (!sense || !rq || (rq->cmd_flags & REQ_QUIET)) return 0; + ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key); + switch (sense->sense_key) { case NO_SENSE: case RECOVERED_ERROR: @@ -140,12 +141,12 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq, } static void cdrom_analyze_sense_data(ide_drive_t *drive, - struct request *failed_command, - struct request_sense *sense) + struct request *failed_command) { + struct request_sense *sense = &drive->sense_data; + struct cdrom_info *info = drive->driver_data; unsigned long sector; unsigned long bio_sectors; - struct cdrom_info *info = drive->driver_data; ide_debug_log(IDE_DBG_SENSE, "error_code: 0x%x, sense_key: 0x%x", sense->error_code, sense->sense_key); @@ -154,7 +155,7 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive, ide_debug_log(IDE_DBG_SENSE, "failed cmd: 0x%x", failed_command->cmd[0]); - if (!cdrom_log_sense(drive, failed_command, sense)) + if (!cdrom_log_sense(drive, failed_command)) return; /* @@ -175,14 +176,14 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive, if (!sense->valid) break; if (failed_command == NULL || - !blk_fs_request(failed_command)) + failed_command->cmd_type != REQ_TYPE_FS) break; sector = (sense->information[0] << 24) | (sense->information[1] << 16) | (sense->information[2] << 8) | (sense->information[3]); - if (drive->queue->hardsect_size == 2048) + if (queue_logical_block_size(drive->queue) == 2048) /* device sector size is 2K */ sector <<= 2; @@ -206,63 +207,33 @@ 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->buffer" points to the original - * failed request + * 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. */ - struct request *failed = (struct request *)rq->buffer; - struct cdrom_info *info = drive->driver_data; - void *sense = &info->sense_data; + struct request *failed = (struct request *)rq->special; + void *sense = bio_data(rq->bio); if (failed) { if (failed->sense) { - sense = 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); failed->sense_len = rq->sense_len; } - cdrom_analyze_sense_data(drive, failed, sense); + cdrom_analyze_sense_data(drive, failed); if (ide_end_rq(drive, failed, -EIO, blk_rq_bytes(failed))) BUG(); } else - cdrom_analyze_sense_data(drive, NULL, sense); + cdrom_analyze_sense_data(drive, NULL); } @@ -286,17 +257,10 @@ static int ide_cd_breathe(ide_drive_t *drive, struct request *rq) if (time_after(jiffies, info->write_timeout)) return 0; else { - struct request_queue *q = drive->queue; - unsigned long flags; - /* - * take a breather relying on the unplug timer to kick us again + * take a breather */ - - spin_lock_irqsave(q->queue_lock, flags); - blk_plug_device(q); - spin_unlock_irqrestore(q->queue_lock, flags); - + blk_delay_queue(drive->queue, 1); return 1; } } @@ -321,7 +285,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) "stat 0x%x", rq->cmd[0], rq->cmd_type, err, stat); - if (blk_sense_request(rq)) { + if (rq->cmd_type == REQ_TYPE_SENSE) { /* * We got an error trying to get sense info from the drive * (probably while trying to recover from a former error). @@ -332,7 +296,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) } /* if we have an error, pass CHECK_CONDITION as the SCSI status byte */ - if (blk_pc_request(rq) && !rq->errors) + if (rq->cmd_type == REQ_TYPE_BLOCK_PC && !rq->errors) rq->errors = SAM_STAT_CHECK_CONDITION; if (blk_noretry_request(rq)) @@ -340,13 +304,14 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) switch (sense_key) { case NOT_READY: - if (blk_fs_request(rq) && rq_data_dir(rq) == WRITE) { + if (rq->cmd_type == REQ_TYPE_FS && rq_data_dir(rq) == WRITE) { if (ide_cd_breathe(drive, rq)) return 1; } else { cdrom_saw_media_change(drive); - if (blk_fs_request(rq) && !blk_rq_quiet(rq)) + if (rq->cmd_type == REQ_TYPE_FS && + !(rq->cmd_flags & REQ_QUIET)) printk(KERN_ERR PFX "%s: tray open\n", drive->name); } @@ -355,7 +320,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) case UNIT_ATTENTION: cdrom_saw_media_change(drive); - if (blk_fs_request(rq) == 0) + if (rq->cmd_type != REQ_TYPE_FS) return 0; /* @@ -381,7 +346,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) * No point in retrying after an illegal request or data * protect error. */ - if (!blk_rq_quiet(rq)) + if (!(rq->cmd_flags & REQ_QUIET)) ide_dump_status(drive, "command error", stat); do_end_request = 1; break; @@ -390,20 +355,20 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) * No point in re-trying a zillion times on a bad sector. * If we got here the error is not correctable. */ - if (!blk_rq_quiet(rq)) + if (!(rq->cmd_flags & REQ_QUIET)) ide_dump_status(drive, "media error " "(bad sector)", stat); do_end_request = 1; break; case BLANK_CHECK: /* disk appears blank? */ - if (!blk_rq_quiet(rq)) + if (!(rq->cmd_flags & REQ_QUIET)) ide_dump_status(drive, "media error (blank)", stat); do_end_request = 1; break; default: - if (blk_fs_request(rq) == 0) + if (rq->cmd_type != REQ_TYPE_FS) break; if (err & ~ATA_ABORTED) { /* go to the default handler for other errors */ @@ -414,7 +379,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) do_end_request = 1; } - if (blk_fs_request(rq) == 0) { + if (rq->cmd_type != REQ_TYPE_FS) { rq->cmd_flags |= REQ_FAILED; do_end_request = 1; } @@ -428,70 +393,17 @@ 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) - cdrom_queue_request_sense(drive, NULL, NULL); + return ide_queue_sense_rq(drive, NULL) ? 2 : 1; return 1; end_request: if (stat & ATA_ERR) { - struct request_queue *q = drive->queue; - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - blkdev_dequeue_request(rq); - spin_unlock_irqrestore(q->queue_lock, flags); - hwif->rq = NULL; - - cdrom_queue_request_sense(drive, rq->sense, rq); - return 1; + return ide_queue_sense_rq(drive, rq) ? 2 : 1; } else return 2; } -/* - * Check the contents of the interrupt reason register from the cdrom - * and attempt to recover if there are problems. Returns 0 if everything's - * ok; nonzero if the request has been terminated. - */ -static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq, - int len, int ireason, int rw) -{ - ide_hwif_t *hwif = drive->hwif; - - ide_debug_log(IDE_DBG_FUNC, "ireason: 0x%x, rw: 0x%x", ireason, rw); - - /* - * ireason == 0: the drive wants to receive data from us - * ireason == 2: the drive is expecting to transfer data to us - */ - if (ireason == (!rw << 1)) - return 0; - else if (ireason == (rw << 1)) { - - /* whoops... */ - printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n", - drive->name, __func__); - - ide_pad_transfer(drive, rw, len); - } else if (rw == 0 && ireason == 1) { - /* - * Some drives (ASUS) seem to tell us that status info is - * available. Just get it and ignore. - */ - (void)hwif->tp_ops->read_status(hwif); - return 0; - } else { - /* drive wants a command packet, or invalid ireason... */ - printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n", - drive->name, __func__, ireason); - } - - if (rq->cmd_type == REQ_TYPE_ATA_PC) - rq->cmd_flags |= REQ_FAILED; - - return -1; -} - static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd) { struct request *rq = cmd->rq; @@ -503,14 +415,8 @@ 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) { - unsigned int ofs = cmd->nbytes - cmd->nleft; - - while (cmd->nleft > 0) { - *((u8 *)rq->data + ofs++) = 0; - cmd->nleft--; - } - } + cmd->nleft > 0 && cmd->nleft <= 5) + cmd->nleft = 0; } int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, @@ -543,14 +449,18 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, rq->cmd_flags |= cmd_flags; rq->timeout = timeout; if (buffer) { - rq->data = buffer; - rq->data_len = *bufflen; + error = blk_rq_map_kern(drive->queue, rq, buffer, + *bufflen, GFP_NOIO); + if (error) { + blk_put_request(rq); + return error; + } } error = blk_execute_rq(drive->queue, info->disk, rq, 0); if (buffer) - *bufflen = rq->data_len; + *bufflen = rq->resid_len; flags = rq->cmd_flags; blk_put_request(rq); @@ -590,15 +500,22 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, return (flags & REQ_FAILED) ? -EIO : 0; } -static void ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd) +/* + * returns true if rq has been completed + */ +static bool ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd) { unsigned int nr_bytes = cmd->nbytes - cmd->nleft; if (cmd->tf_flags & IDE_TFLAG_WRITE) nr_bytes -= cmd->last_xfer_len; - if (nr_bytes > 0) + if (nr_bytes > 0) { ide_complete_rq(drive, 0, nr_bytes); + return true; + } + + return false; } static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) @@ -608,8 +525,8 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) struct request *rq = hwif->rq; ide_expiry_t *expiry = NULL; int dma_error = 0, dma, thislen, uptodate = 0; - int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0, nsectors; - int sense = blk_sense_request(rq); + int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0; + int sense = (rq->cmd_type == REQ_TYPE_SENSE); unsigned int timeout; u16 len; u8 ireason, stat; @@ -652,7 +569,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) ide_read_bcount_and_ireason(drive, &len, &ireason); - thislen = blk_fs_request(rq) ? len : cmd->nleft; + thislen = (rq->cmd_type == REQ_TYPE_FS) ? len : cmd->nleft; if (thislen > len) thislen = len; @@ -661,7 +578,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) /* If DRQ is clear, the command has completed. */ if ((stat & ATA_DRQ) == 0) { - if (blk_fs_request(rq)) { + if (rq->cmd_type == REQ_TYPE_FS) { /* * If we're not done reading/writing, complain. * Otherwise, complete the command normally. @@ -675,18 +592,27 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) rq->cmd_flags |= REQ_FAILED; uptodate = 0; } - } else if (!blk_pc_request(rq)) { + } else if (rq->cmd_type != REQ_TYPE_BLOCK_PC) { ide_cd_request_sense_fixup(drive, cmd); - /* complain if we still have data left to transfer */ + uptodate = cmd->nleft ? 0 : 1; - if (uptodate == 0) + + /* + * suck out the remaining bytes from the drive in an + * attempt to complete the data xfer. (see BZ#13399) + */ + if (!(stat & ATA_ERR) && !uptodate && thislen) { + ide_pio_bytes(drive, cmd, write, thislen); + uptodate = cmd->nleft ? 0 : 1; + } + + if (!uptodate) rq->cmd_flags |= REQ_FAILED; } goto out_end; } - /* check which way to transfer data */ - rc = ide_cd_check_ireason(drive, rq, len, ireason, write); + rc = ide_check_ireason(drive, rq, len, ireason, write); if (rc) goto out_end; @@ -715,7 +641,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) /* pad, if necessary */ if (len > 0) { - if (blk_fs_request(rq) == 0 || write == 0) + if (rq->cmd_type != REQ_TYPE_FS || write == 0) ide_pad_transfer(drive, write, len); else { printk(KERN_ERR PFX "%s: confused, missing data\n", @@ -724,11 +650,11 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) } } - if (blk_pc_request(rq)) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { timeout = rq->timeout; } else { timeout = ATAPI_WAIT_PC; - if (!blk_fs_request(rq)) + if (rq->cmd_type != REQ_TYPE_FS) expiry = ide_cd_expiry; } @@ -737,20 +663,15 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) return ide_started; out_end: - if (blk_pc_request(rq) && rc == 0) { - unsigned int dlen = rq->data_len; - - rq->data_len = 0; - - if (blk_end_request(rq, 0, dlen)) - BUG(); - + if (rq->cmd_type == REQ_TYPE_BLOCK_PC && rc == 0) { + rq->resid_len = 0; + blk_end_request_all(rq, 0); hwif->rq = NULL; } else { if (sense && uptodate) ide_cd_complete_failed_rq(drive, rq); - if (blk_fs_request(rq)) { + if (rq->cmd_type == REQ_TYPE_FS) { if (cmd->nleft == 0) uptodate = 1; } else { @@ -758,25 +679,18 @@ out_end: rq->errors = -EIO; } - if (uptodate == 0) - ide_cd_error_cmd(drive, cmd); + if (uptodate == 0 && rq->bio) + if (ide_cd_error_cmd(drive, cmd)) + return ide_stopped; /* make sure it's fully ended */ - if (blk_pc_request(rq)) - nsectors = (rq->data_len + 511) >> 9; - else - nsectors = rq->hard_nr_sectors; - - if (nsectors == 0) - nsectors = 1; - - if (blk_fs_request(rq) == 0) { - rq->data_len -= (cmd->nbytes - cmd->nleft); + if (rq->cmd_type != REQ_TYPE_FS) { + rq->resid_len -= cmd->nbytes - cmd->nleft; if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE)) - rq->data_len += cmd->last_xfer_len; + rq->resid_len += cmd->last_xfer_len; } - ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9); + ide_complete_rq(drive, uptodate ? 0 : -EIO, blk_rq_bytes(rq)); if (sense && rc == 2) ide_error(drive, "request sense failure", stat); @@ -790,7 +704,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) struct request_queue *q = drive->queue; int write = rq_data_dir(rq) == WRITE; unsigned short sectors_per_frame = - queue_hardsect_size(q) >> SECTOR_BITS; + queue_logical_block_size(q) >> SECTOR_BITS; ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, rq->cmd_flags: 0x%x, " "secs_per_frame: %u", @@ -809,8 +723,8 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) } /* fs requests *must* be hardware frame aligned */ - if ((rq->nr_sectors & (sectors_per_frame - 1)) || - (rq->sector & (sectors_per_frame - 1))) + if ((blk_rq_sectors(rq) & (sectors_per_frame - 1)) || + (blk_rq_pos(rq) & (sectors_per_frame - 1))) return ide_stopped; /* use DMA, if possible */ @@ -830,7 +744,7 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) ide_debug_log(IDE_DBG_PC, "rq->cmd[0]: 0x%x, rq->cmd_type: 0x%x", rq->cmd[0], rq->cmd_type); - if (blk_pc_request(rq)) + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) rq->cmd_flags |= REQ_QUIET; else rq->cmd_flags &= ~REQ_FAILED; @@ -838,15 +752,10 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) drive->dma = 0; /* sg request */ - if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) { + if (rq->bio) { 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); @@ -858,7 +767,7 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) */ alignment = queue_dma_alignment(q) | q->dma_pad_mask; if ((unsigned long)buf & alignment - || rq->data_len & q->dma_pad_mask + || blk_rq_bytes(rq) & q->dma_pad_mask || object_is_on_stack(buf)) drive->dma = 0; } @@ -868,7 +777,8 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, sector_t block) { struct ide_cmd cmd; - int uptodate = 0, nsectors; + int uptodate = 0; + unsigned int nsectors; ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, block: %llu", rq->cmd[0], (unsigned long long)block); @@ -876,26 +786,30 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, if (drive->debug_mask & IDE_DBG_RQ) blk_dump_rq_flags(rq, "ide_cd_do_request"); - if (blk_fs_request(rq)) { + switch (rq->cmd_type) { + case REQ_TYPE_FS: if (cdrom_start_rw(drive, rq) == ide_stopped) goto out_end; - } else if (blk_sense_request(rq) || blk_pc_request(rq) || - rq->cmd_type == REQ_TYPE_ATA_PC) { + break; + case REQ_TYPE_SENSE: + case REQ_TYPE_BLOCK_PC: + case REQ_TYPE_ATA_PC: if (!rq->timeout) rq->timeout = ATAPI_WAIT_PC; cdrom_do_block_pc(drive, rq); - } else if (blk_special_request(rq)) { + break; + case REQ_TYPE_SPECIAL: /* right now this can only be a reset... */ uptodate = 1; goto out_end; - } else { - blk_dump_rq_flags(rq, DRV_NAME " bad flags"); - if (rq->errors == 0) - rq->errors = -EIO; - goto out_end; + default: + BUG(); } + /* prepare sense request for this command */ + ide_prep_sense(drive, rq); + memset(&cmd, 0, sizeof(cmd)); if (rq_data_dir(rq)) @@ -903,15 +817,14 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, cmd.rq = rq; - if (blk_fs_request(rq) || rq->data_len) { - ide_init_sg_cmd(&cmd, blk_fs_request(rq) ? (rq->nr_sectors << 9) - : rq->data_len); + if (rq->cmd_type == REQ_TYPE_FS || blk_rq_bytes(rq)) { + ide_init_sg_cmd(&cmd, blk_rq_bytes(rq)); ide_map_sg(drive, &cmd); } return ide_issue_pc(drive, &cmd); out_end: - nsectors = rq->hard_nr_sectors; + nsectors = blk_rq_sectors(rq); if (nsectors == 0) nsectors = 1; @@ -982,9 +895,12 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, return stat; /* - * Sanity check the given block size + * Sanity check the given block size, in so far as making + * sure the sectors_per_frame we give to the caller won't + * end up being bogus. */ blocklen = be32_to_cpu(capbuf.blocklen); + blocklen = (blocklen >> SECTOR_BITS) << SECTOR_BITS; switch (blocklen) { case 512: case 1024: @@ -992,10 +908,9 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, case 4096: break; default: - printk(KERN_ERR PFX "%s: weird block size %u\n", + printk_once(KERN_ERR PFX "%s: weird block size %u; " + "setting default block size to 2048\n", drive->name, blocklen); - printk(KERN_ERR PFX "%s: default to 2kb block size\n", - drive->name); blocklen = 2048; break; } @@ -1077,8 +992,8 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) /* save a private copy of the TOC capacity for error handling */ drive->probed_capacity = toc->capacity * sectors_per_frame; - blk_queue_hardsect_size(drive->queue, - sectors_per_frame << SECTOR_BITS); + blk_queue_logical_block_size(drive->queue, + sectors_per_frame << SECTOR_BITS); /* first read just the header, so we know how long the TOC is */ stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr, @@ -1240,8 +1155,8 @@ void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf) ide_debug_log(IDE_DBG_PROBE, "curspeed: %u, maxspeed: %u", curspeed, maxspeed); - cd->current_speed = (curspeed + (176/2)) / 176; - cd->max_speed = (maxspeed + (176/2)) / 176; + cd->current_speed = DIV_ROUND_CLOSEST(curspeed, 176); + cd->max_speed = DIV_ROUND_CLOSEST(maxspeed, 176); } #define IDE_CD_CAPABILITIES \ @@ -1255,7 +1170,7 @@ static struct cdrom_device_ops ide_cdrom_dops = { .open = ide_cdrom_open_real, .release = ide_cdrom_release_real, .drive_status = ide_cdrom_drive_status, - .media_changed = ide_cdrom_check_media_change_real, + .check_events = ide_cdrom_check_events_real, .tray_move = ide_cdrom_tray_move, .lock_door = ide_cdrom_lock_door, .select_speed = ide_cdrom_select_speed, @@ -1394,9 +1309,9 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive) /* standard prep_rq_fn that builds 10 byte cmds */ static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq) { - int hard_sect = queue_hardsect_size(q); - long block = (long)rq->hard_sector / (hard_sect >> 9); - unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9); + int hard_sect = queue_logical_block_size(q); + long block = (long)blk_rq_pos(rq) / (hard_sect >> 9); + unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9); memset(rq->cmd, 0, BLK_MAX_CDB); @@ -1458,9 +1373,9 @@ static int ide_cdrom_prep_pc(struct request *rq) static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq) { - if (blk_fs_request(rq)) + if (rq->cmd_type == REQ_TYPE_FS) return ide_cdrom_prep_fs(q, rq); - else if (blk_pc_request(rq)) + else if (rq->cmd_type == REQ_TYPE_BLOCK_PC) return ide_cdrom_prep_pc(rq); return 0; @@ -1483,19 +1398,30 @@ static sector_t ide_cdrom_capacity(ide_drive_t *drive) return capacity * sectors_per_frame; } -static int proc_idecd_read_capacity(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int idecd_capacity_proc_show(struct seq_file *m, void *v) { - ide_drive_t *drive = data; - int len; + ide_drive_t *drive = m->private; - len = sprintf(page, "%llu\n", (long long)ide_cdrom_capacity(drive)); - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); + seq_printf(m, "%llu\n", (long long)ide_cdrom_capacity(drive)); + return 0; } +static int idecd_capacity_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, idecd_capacity_proc_show, PDE_DATA(inode)); +} + +static const struct file_operations idecd_capacity_proc_fops = { + .owner = THIS_MODULE, + .open = idecd_capacity_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static ide_proc_entry_t idecd_proc[] = { - { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL }, - { NULL, 0, NULL, NULL } + { "capacity", S_IFREG|S_IRUGO, &idecd_capacity_proc_fops }, + {} }; static ide_proc_entry_t *ide_cd_proc_entries(ide_drive_t *drive) @@ -1581,8 +1507,6 @@ static int ide_cdrom_setup(ide_drive_t *drive) blk_queue_dma_alignment(q, 31); blk_queue_update_dma_pad(q, 15); - q->unplug_delay = max((1 * HZ) / 1000, 1); - drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; drive->atapi_flags = IDE_AFLAG_NO_EJECT | ide_cd_flags(id); @@ -1599,7 +1523,7 @@ static int ide_cdrom_setup(ide_drive_t *drive) nslots = ide_cdrom_probe_capabilities(drive); - blk_queue_hardsect_size(q, CD_FRAMESIZE); + blk_queue_logical_block_size(q, CD_FRAMESIZE); if (ide_cdrom_register(drive, nslots)) { printk(KERN_ERR PFX "%s: %s failed to register device with the" @@ -1666,29 +1590,31 @@ static struct ide_driver ide_cdrom_driver = { static int idecd_open(struct block_device *bdev, fmode_t mode) { - struct cdrom_info *info = ide_cd_get(bdev->bd_disk); - int rc = -ENOMEM; + struct cdrom_info *info; + int rc = -ENXIO; + mutex_lock(&ide_cd_mutex); + info = ide_cd_get(bdev->bd_disk); if (!info) - return -ENXIO; + goto out; rc = cdrom_open(&info->devinfo, bdev, mode); - if (rc < 0) ide_cd_put(info); - +out: + mutex_unlock(&ide_cd_mutex); return rc; } -static int idecd_release(struct gendisk *disk, fmode_t mode) +static void idecd_release(struct gendisk *disk, fmode_t mode) { struct cdrom_info *info = ide_drv_g(disk, cdrom_info); + mutex_lock(&ide_cd_mutex); cdrom_release(&info->devinfo, mode); ide_cd_put(info); - - return 0; + mutex_unlock(&ide_cd_mutex); } static int idecd_set_spindown(struct cdrom_device_info *cdi, unsigned long arg) @@ -1730,7 +1656,7 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg) return 0; } -static int idecd_ioctl(struct block_device *bdev, fmode_t mode, +static int idecd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct cdrom_info *info = ide_drv_g(bdev->bd_disk, cdrom_info); @@ -1752,10 +1678,24 @@ static int idecd_ioctl(struct block_device *bdev, fmode_t mode, return err; } -static int idecd_media_changed(struct gendisk *disk) +static int idecd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + int ret; + + mutex_lock(&ide_cd_mutex); + ret = idecd_locked_ioctl(bdev, mode, cmd, arg); + mutex_unlock(&ide_cd_mutex); + + return ret; +} + + +static unsigned int idecd_check_events(struct gendisk *disk, + unsigned int clearing) { struct cdrom_info *info = ide_drv_g(disk, cdrom_info); - return cdrom_media_changed(&info->devinfo); + return cdrom_check_events(&info->devinfo, clearing); } static int idecd_revalidate_disk(struct gendisk *disk) @@ -1768,12 +1708,12 @@ static int idecd_revalidate_disk(struct gendisk *disk) return 0; } -static struct block_device_operations idecd_ops = { +static const struct block_device_operations idecd_ops = { .owner = THIS_MODULE, .open = idecd_open, .release = idecd_release, - .locked_ioctl = idecd_ioctl, - .media_changed = idecd_media_changed, + .ioctl = idecd_ioctl, + .check_events = idecd_check_events, .revalidate_disk = idecd_revalidate_disk }; @@ -1816,7 +1756,7 @@ static int ide_cd_probe(ide_drive_t *drive) info->dev.parent = &drive->gendev; info->dev.release = ide_cd_release; - dev_set_name(&info->dev, dev_name(&drive->gendev)); + dev_set_name(&info->dev, "%s", dev_name(&drive->gendev)); if (device_register(&info->dev)) goto out_free_disk; @@ -1839,7 +1779,7 @@ static int ide_cd_probe(ide_drive_t *drive) ide_cd_read_toc(drive, &sense); g->fops = &idecd_ops; - g->flags |= GENHD_FL_REMOVABLE; + g->flags |= GENHD_FL_REMOVABLE | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE; add_disk(g); return 0; |
