#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>
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:
}
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);
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;
/*
* sense pointer set.
*/
memcpy(failed->sense, sense, 18);
- sense = failed->sense;
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);
}
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;
}
} else if (!blk_pc_request(rq)) {
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;
rq->errors = -EIO;
}
- if (uptodate == 0)
+ if (uptodate == 0 && rq->bio)
ide_cd_error_cmd(drive, cmd);
/* make sure it's fully ended */
/* 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;
- }
+ } else
+ BUG();
/* prepare sense request for this command */
ide_prep_sense(drive, rq);
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:
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;
}
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 \
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(inode)->data);
+}
+
+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)
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,