lkml.org 
[lkml]   [2000]   [Nov]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: Oops with 2.4.0-test10 during ripping an audio cd with cdda2wav
On Fri, Nov 10 2000, Bernd Nottelmann wrote:
> Hi,
>
> I am not sure, if this is a reiserfs related issue, so I send this Oops
> report both to the kernel mailing list and to the reiserfs people
> (kernel has been patched with reiserfs-3.6.18).
>
> During ripping the last song from a cd (a long time song of 9.50 min)
> I was wondering about the time consumption of this process.
> After the cdda2wav process had been finished I found the following
> oops:
>
>
> ---------------------- starts here ----------------------
> ksymoops 2.3.5 on i686 2.4.0-test10. Options used
> -V (default)
> -k /proc/ksyms (default)
> -l /proc/modules (default)
> -o /lib/modules/2.4.0-test10/ (default)
> -m /usr/src/linux/System.map (default)
>
> Warning: You did not tell me where to find symbol information. I will
> assume that the log matches the kernel and modules that are running
> right now and I'll use the default options above for symbol resolution.
> If the current kernel and/or modules do not match the log, you can get
> more accurate output by telling me the kernel version and where to find
> map, modules, ksyms etc. ksymoops -h explains the options.
>
> kernel BUG at slab.c:1542!

[snip]

This looks like cdrom.c:mmc_ioctl, CDROMREADAUDIO, kmalloc'ing too
much memory, which triggers the BUG() in slab.c. I'm not quite sure
how this is happening though, unless cdda2wav sets a negative ra.nframes
(a quick browse on a version I have here shows it does not, maybe you
have a different version).

Is it reproducable? If so, could you try with this patch?

> (Maybe I should mention that the kernel has been compiled with
> gcc-2.95.2, but I think, it is not very important.)

Could be...

--
* Jens Axboe <axboe@suse.de>
* SuSE Labs
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11-pre2/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- /opt/kernel/linux-2.4.0-test11-pre2/drivers/cdrom/cdrom.c Mon Oct 16 21:58:51 2000
+++ linux/drivers/cdrom/cdrom.c Sat Nov 11 05:00:23 2000
@@ -224,11 +224,14 @@
3.11 Jun 12, 2000 - Jens Axboe <axboe@suse.de>
-- Fix bug in getting rpc phase 2 region info.
-- Reinstate "correct" CDROMPLAYTRKIND
-
+
+ 3.12 Oct 18, 2000 - Jens Axboe <axboe@suse.de>
+ -- Use quiet bit on packet commands not known to work
+
-------------------------------------------------------------------------*/

-#define REVISION "Revision: 3.11"
-#define VERSION "Id: cdrom.c 3.11 2000/06/12"
+#define REVISION "Revision: 3.12"
+#define VERSION "Id: cdrom.c 3.12 2000/10/18"

/* I use an error-log mask to give fine grain control over the type of
messages dumped to the system logs. The available masks include: */
@@ -701,6 +704,21 @@
struct cdrom_device_ops *cdo = cdi->ops;
int length;

+ /*
+ * Sanyo changer isn't spec compliant (doesn't use regular change
+ * LOAD_UNLOAD command, and it doesn't implement the mech status
+ * command below
+ */
+ if (cdi->sanyo_slot) {
+ buf->hdr.nslots = 3;
+ buf->hdr.curslot = cdi->sanyo_slot == 3 ? 0 : cdi->sanyo_slot;
+ for (length = 0; length < 3; length++) {
+ buf->slots[length].disc_present = 1;
+ buf->slots[length].change = 0;
+ }
+ return 0;
+ }
+
length = sizeof(struct cdrom_mechstat_header) +
cdi->capacity * sizeof(struct cdrom_slot);

@@ -767,9 +785,10 @@
/* The Sanyo 3 CD changer uses byte 7 of the
GPCMD_TEST_UNIT_READY to command to switch CDs instead of
using the GPCMD_LOAD_UNLOAD opcode. */
- if (cdi->sanyo_slot && slot) {
+ if (cdi->sanyo_slot && -1 < slot) {
cgc.cmd[0] = GPCMD_TEST_UNIT_READY;
cgc.cmd[7] = slot;
+ cgc.cmd[4] = cgc.cmd[8] = 0;
cdi->sanyo_slot = slot ? slot : 3;
}

@@ -953,6 +972,7 @@
cgc->buffer = (char *) buf;
cgc->buflen = len;
cgc->data_direction = type;
+ cgc->timeout = 5*HZ;
}

/* DVD handling */
@@ -1860,6 +1880,48 @@
return cdo->generic_packet(cdi, &cgc);
}

+static int cdrom_do_cmd(struct cdrom_device_info *cdi,
+ struct cdrom_generic_command *cgc)
+{
+ struct request_sense *usense, sense;
+ unsigned char *ubuf;
+ int ret;
+
+ if (cgc->data_direction == CGC_DATA_UNKNOWN)
+ return -EINVAL;
+
+ if (cgc->buflen < 0 || cgc->buflen >= 131072)
+ return -EINVAL;
+
+ if ((ubuf = cgc->buffer)) {
+ cgc->buffer = kmalloc(cgc->buflen, GFP_KERNEL);
+ if (cgc->buffer == NULL)
+ return -ENOMEM;
+ }
+
+ usense = cgc->sense;
+ cgc->sense = &sense;
+ if (usense && !access_ok(VERIFY_WRITE, usense, sizeof(*usense)))
+ return -EFAULT;
+
+ if (cgc->data_direction == CGC_DATA_READ) {
+ if (!access_ok(VERIFY_READ, ubuf, cgc->buflen))
+ return -EFAULT;
+ } else if (cgc->data_direction == CGC_DATA_WRITE) {
+ if (copy_from_user(cgc->buffer, ubuf, cgc->buflen)) {
+ kfree(cgc->buffer);
+ return -EFAULT;
+ }
+ }
+
+ ret = cdi->ops->generic_packet(cdi, cgc);
+ __copy_to_user(usense, cgc->sense, sizeof(*usense));
+ if (!ret && cgc->data_direction == CGC_DATA_READ)
+ __copy_to_user(ubuf, cgc->buffer, cgc->buflen);
+ kfree(cgc->buffer);
+ return ret;
+}
+
static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
unsigned long arg)
{
@@ -1937,7 +1999,7 @@
return -EINVAL;

/* FIXME: we need upper bound checking, too!! */
- if (lba < 0)
+ if (lba < 0 || ra.nframes <= 0)
return -EINVAL;

/* do max 8 frames at the time */
@@ -2117,52 +2179,11 @@
}

case CDROM_SEND_PACKET: {
- __u8 *userbuf, copy = 0;
- struct request_sense *sense;
if (!CDROM_CAN(CDC_GENERIC_PACKET))
return -ENOSYS;
cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKET\n");
IOCTL_IN(arg, struct cdrom_generic_command, cgc);
- copy = !!cgc.buflen;
- userbuf = cgc.buffer;
- cgc.buffer = NULL;
- sense = cgc.sense;
- if (userbuf != NULL && copy) {
- /* usually commands just copy data one way, i.e.
- * we send a buffer to the drive and the command
- * specifies whether the drive will read or
- * write to that buffer. usually the buffers
- * are very small, so we don't loose that much
- * by doing a redundant copy each time. */
- if (!access_ok(VERIFY_WRITE, userbuf, cgc.buflen)) {
- printk("can't get write perms\n");
- return -EFAULT;
- }
- if (!access_ok(VERIFY_READ, userbuf, cgc.buflen)) {
- printk("can't get read perms\n");
- return -EFAULT;
- }
- }
- /* reasonable limits */
- if (cgc.buflen < 0 || cgc.buflen > 131072) {
- printk("invalid size given\n");
- return -EINVAL;
- }
- if (copy) {
- cgc.buffer = kmalloc(cgc.buflen, GFP_KERNEL);
- if (cgc.buffer == NULL)
- return -ENOMEM;
- __copy_from_user(cgc.buffer, userbuf, cgc.buflen);
- }
- ret = cdo->generic_packet(cdi, &cgc);
- if (copy && !ret)
- __copy_to_user(userbuf, cgc.buffer, cgc.buflen);
- /* copy back sense data */
- if (sense != NULL)
- if (copy_to_user(sense, cgc.sense, sizeof(struct request_sense)))
- ret = -EFAULT;
- kfree(cgc.buffer);
- return ret;
+ return cdrom_do_cmd(cdi, &cgc);
}
case CDROM_NEXT_WRITABLE: {
long next = 0;
@@ -2199,6 +2220,7 @@
cgc.cmd[4] = (track & 0xff00) >> 8;
cgc.cmd[5] = track & 0xff;
cgc.cmd[8] = 8;
+ cgc.quiet = 1;

if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret;
@@ -2220,6 +2242,7 @@
init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DISC_INFO;
cgc.cmd[8] = cgc.buflen = 2;
+ cgc.quiet = 1;

if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret;
@@ -2252,9 +2275,6 @@
if (!CDROM_CAN(CDC_GENERIC_PACKET))
goto use_toc;

- if (!CDROM_CAN(CDC_CD_R | CDC_CD_RW | CDC_DVD_R | CDC_DVD_RAM))
- goto use_toc;
-
if ((ret = cdrom_get_disc_info(dev, &di)))
goto use_toc;

@@ -2556,12 +2576,13 @@
{0}
};

+#ifdef CONFIG_PROC_FS
/* Make sure that /proc/sys/dev is there */
ctl_table cdrom_root_table[] = {
{CTL_DEV, "dev", NULL, 0, 0555, cdrom_cdrom_table},
{0}
};
-
+#endif /* CONFIG_PROC_FS */
static struct ctl_table_header *cdrom_sysctl_header;

static void cdrom_sysctl_register(void)
@@ -2572,9 +2593,8 @@
return;

cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
-#ifdef CONFIG_PROC_FS
cdrom_root_table->child->de->owner = THIS_MODULE;
-#endif /* CONFIG_PROC_FS */
+
/* set the defaults */
cdrom_sysctl_settings.autoclose = autoclose;
cdrom_sysctl_settings.autoeject = autoeject;
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11-pre2/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c
--- /opt/kernel/linux-2.4.0-test11-pre2/drivers/ide/ide-cd.c Fri Oct 27 08:35:48 2000
+++ linux/drivers/ide/ide-cd.c Sat Nov 11 04:40:06 2000
@@ -285,9 +285,13 @@
* 4.58 May 1, 2000 - Clean up ACER50 stuff.
* - Fix small problem with ide_cdrom_capacity
*
+ * 4.59 Aug 11, 2000 - Fix changer problem in cdrom_read_toc, we weren't
+ * correctly sensing a disc change.
+ * - Rearranged some code
+ *
*************************************************************************/

-#define IDECD_VERSION "4.58"
+#define IDECD_VERSION "4.59"

#include <linux/config.h>
#include <linux/module.h>
@@ -324,41 +328,50 @@
info->nsectors_buffered = 0;
}

+static int cdrom_log_sense(ide_drive_t *drive, struct packet_command *pc,
+ struct request_sense *sense)
+{
+ int log = 0;
+
+ if (sense == NULL || pc->quiet)
+ return 0;
+
+ switch (sense->sense_key) {
+ case NO_SENSE: case RECOVERED_ERROR:
+ break;
+ case NOT_READY:
+ /*
+ * don't care about tray state messages for
+ * e.g. capacity commands or in-progress or
+ * becoming ready
+ */
+ if (sense->asc == 0x3a || sense->asc == 0x04)
+ break;
+ log = 1;
+ break;
+ case UNIT_ATTENTION:
+ /*
+ * Make good and sure we've seen this potential media
+ * change. Some drives (i.e. Creative) fail to present
+ * the correct sense key in the error register.
+ */
+ cdrom_saw_media_change(drive);
+ break;
+ default:
+ log = 1;
+ break;
+ }
+ return log;
+}

static
void cdrom_analyze_sense_data(ide_drive_t *drive,
struct packet_command *failed_command,
struct request_sense *sense)
{
- if (sense->sense_key == NOT_READY ||
- sense->sense_key == UNIT_ATTENTION) {
- /* Make good and sure we've seen this potential media change.
- Some drives (i.e. Creative) fail to present the correct
- sense key in the error register. */
- cdrom_saw_media_change (drive);
-
-
- /* Don't print not ready or unit attention errors for
- READ_SUBCHANNEL. Workman (and probably other programs)
- uses this command to poll the drive, and we don't want
- to fill the syslog with useless errors. */
- if (failed_command &&
- (failed_command->c[0] == GPCMD_READ_SUBCHANNEL ||
- failed_command->c[0] == GPCMD_TEST_UNIT_READY))
- return;
- }

- if (sense->error_code == 0x70 && sense->sense_key == 0x02
- && ((sense->asc == 0x3a && sense->ascq == 0x00) ||
- (sense->asc == 0x04 && sense->ascq == 0x01)))
- {
- /*
- * Suppress the following errors:
- * "Medium not present", "in progress of becoming ready",
- * and "writing" to keep the noise level down to a dull roar.
- */
+ if (!cdrom_log_sense(drive, failed_command, sense))
return;
- }

/*
* If a read toc is executed for a CD-R or CD-RW medium where
@@ -590,7 +603,7 @@
cdrom_saw_media_change (drive);
/*printk("%s: media changed\n",drive->name);*/
return 0;
- } else {
+ } else if (!pc->quiet) {
/* Otherwise, print an error. */
ide_dump_status(drive, "packet command error", stat);
}
@@ -726,26 +739,27 @@
or there's data ready. */
static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
unsigned char *cmd_buf, int cmd_len,
- ide_handler_t *handler)
+ ide_handler_t *handler,
+ unsigned int timeout)
{
+ ide_startstop_t startstop;
+
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
/* Here we should have been called after receiving an interrupt
from the device. DRQ should how be set. */
int stat_dum;
- ide_startstop_t startstop;

/* Check for errors. */
if (cdrom_decode_status (&startstop, drive, DRQ_STAT, &stat_dum))
return startstop;
} else {
- ide_startstop_t startstop;
/* Otherwise, we must wait for DRQ to get set. */
if (ide_wait_stat (&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY))
return startstop;
}

/* Arm the interrupt handler. */
- ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry);
+ ide_set_handler (drive, handler, timeout, cdrom_timer_expiry);

/* Send the command to the device. */
atapi_output_bytes (drive, cmd_buf, cmd_len);
@@ -1090,7 +1104,7 @@

/* Send the command to the drive and return. */
return cdrom_transfer_packet_command(drive, pc.c, sizeof(pc.c),
- &cdrom_read_intr);
+ &cdrom_read_intr, WAIT_CMD);
}


@@ -1111,7 +1125,13 @@

if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) {
if (--retry == 0) {
+ /*
+ * this condition is far too common, to bother
+ * users about it
+ */
+#if 0
printk("%s: disabled DSC seek overlap\n", drive->name);
+#endif
drive->dsc_overlap = 0;
}
}
@@ -1133,7 +1153,7 @@
memset (&pc.c, 0, sizeof (pc.c));
pc.c[0] = GPCMD_SEEK;
put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]);
- return cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_seek_intr);
+ return cdrom_transfer_packet_command(drive, pc.c, sizeof(pc.c), &cdrom_seek_intr, WAIT_CMD);
}

static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
@@ -1308,9 +1328,12 @@
struct request *rq = HWGROUP(drive)->rq;
struct packet_command *pc = (struct packet_command *)rq->buffer;

+ if (!pc->timeout)
+ pc->timeout = WAIT_CMD;
+
/* Send the command to the drive and return. */
- return cdrom_transfer_packet_command (drive, pc->c,
- sizeof (pc->c), &cdrom_pc_intr);
+ return cdrom_transfer_packet_command(drive, pc->c, sizeof(pc->c),
+ &cdrom_pc_intr, pc->timeout);
}


@@ -1335,8 +1358,12 @@
static
void cdrom_sleep (int time)
{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(time);
+ int sleep = time;
+
+ do {
+ set_current_state(TASK_INTERRUPTIBLE);
+ sleep = schedule_timeout(sleep);
+ } while (sleep);
}

static
@@ -1372,7 +1399,7 @@
/* The drive is in the process of loading
a disk. Retry, but wait a little to give
the drive time to complete the load. */
- cdrom_sleep (HZ);
+ cdrom_sleep(2 * HZ);
} else {
/* Otherwise, don't retry. */
retries = 0;
@@ -1841,9 +1868,9 @@
memset(&pc, 0, sizeof (pc));
pc.sense = &sense;

- pc.c[0] = GPCMD_PLAY_AUDIO_10;
- put_unaligned(cpu_to_be32(lba_start), (unsigned int *) &pc.c[2]);
- put_unaligned(cpu_to_be16(lba_end - lba_start), (unsigned int *) &pc.c[7]);
+ pc.c[0] = GPCMD_PLAY_AUDIO_MSF;
+ lba_to_msf(lba_start, &pc.c[3], &pc.c[4], &pc.c[5]);
+ lba_to_msf(lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]);

return cdrom_queue_packet_command(drive, &pc);
}
@@ -1886,6 +1913,11 @@
struct packet_command pc;
ide_drive_t *drive = (ide_drive_t*) cdi->handle;

+ if (cgc->timeout <= 0) {
+ printk("No timeout from %p, setting default\n", __builtin_return_address(0));
+ cgc->timeout = WAIT_CMD;
+ }
+
/* here we queue the commands from the uniform CD-ROM
layer. the packet must be complete, as we do not
touch it at all. */
@@ -1893,14 +1925,10 @@
memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE);
pc.buffer = cgc->buffer;
pc.buflen = cgc->buflen;
- cgc->stat = cdrom_queue_packet_command(drive, &pc);
-
- /*
- * FIXME: copy sense, don't just assign pointer!!
- */
- cgc->sense = pc.sense;
-
- return cgc->stat;
+ pc.quiet = cgc->quiet;
+ pc.timeout = cgc->timeout;
+ pc.sense = cgc->sense;
+ return cgc->stat = cdrom_queue_packet_command(drive, &pc);
}

static
@@ -1956,6 +1984,7 @@
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct cdrom_info *info = drive->driver_data;
+ int stat;

switch (cmd) {
/*
@@ -1963,10 +1992,11 @@
* atapi doesn't support it
*/
case CDROMPLAYTRKIND: {
- int stat, lba_start, lba_end;
+ unsigned long lba_start, lba_end;
struct cdrom_ti *ti = (struct cdrom_ti *)arg;
struct atapi_toc_entry *first_toc, *last_toc;

+ printk("Play from track %d to %d\n", ti->cdti_trk0, ti->cdti_trk1);
stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
if (stat)
return stat;
@@ -1980,6 +2010,8 @@
lba_start = first_toc->addr.lba;
lba_end = last_toc->addr.lba;

+ printk("lba %lu to lba %lu\n", lba_start, lba_end);
+
if (lba_end <= lba_start)
return -EINVAL;

@@ -1987,7 +2019,6 @@
}

case CDROMREADTOCHDR: {
- int stat;
struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
struct atapi_toc *toc;

@@ -2003,7 +2034,6 @@
}

case CDROMREADTOCENTRY: {
- int stat;
struct cdrom_tocentry *tocentry = (struct cdrom_tocentry*) arg;
struct atapi_toc_entry *toce;

diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11-pre2/drivers/ide/ide-cd.h linux/drivers/ide/ide-cd.h
--- /opt/kernel/linux-2.4.0-test11-pre2/drivers/ide/ide-cd.h Tue Oct 31 20:19:19 2000
+++ linux/drivers/ide/ide-cd.h Sat Nov 11 04:38:30 2000
@@ -106,6 +106,7 @@
int buflen;
int stat;
int quiet;
+ int timeout;
struct request_sense *sense;
unsigned char c[12];
};
@@ -628,7 +629,9 @@
"Logical unit not ready - in progress [sic] of becoming ready" },
{ 0x020402, "Logical unit not ready - initializing command required" },
{ 0x020403, "Logical unit not ready - manual intervention required" },
- { 0x020404, "In process of becoming ready - writing" },
+ { 0x020404, "Logical unit not ready - format in progress" },
+ { 0x020407, "Logical unit not ready - operation in progress" },
+ { 0x020408, "Logical unit not ready - long write in progress" },
{ 0x020600, "No reference position found (media may be upside down)" },
{ 0x023000, "Incompatible medium installed" },
{ 0x023a00, "Medium not present" },
@@ -678,7 +681,6 @@
{ 0x04b600, "Media load mechanism failed" },
{ 0x051a00, "Parameter list length error" },
{ 0x052000, "Invalid command operation code" },
- { 0x052c00, "Command sequence error" },
{ 0x052100, "Logical block address out of range" },
{ 0x052102, "Invalid address for write" },
{ 0x052400, "Invalid field in command packet" },
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11-pre2/drivers/scsi/constants.c linux/drivers/scsi/constants.c
--- /opt/kernel/linux-2.4.0-test11-pre2/drivers/scsi/constants.c Tue Mar 14 07:15:03 2000
+++ linux/drivers/scsi/constants.c Sat Nov 11 04:16:51 2000
@@ -776,7 +776,7 @@
printk("%s%s: sns = %2x %2x\n", devclass,
kdevname(dev), sense_buffer[0], sense_buffer[2]);

- printk("Non-extended sense class %d code 0x%0x ", sense_class, code);
+ printk("Non-extended sense class %d code 0x%0x\n", sense_class, code);
s = 4;
}

diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11-pre2/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- /opt/kernel/linux-2.4.0-test11-pre2/drivers/scsi/sr.c Mon Oct 30 23:44:29 2000
+++ linux/drivers/scsi/sr.c Sat Nov 11 04:27:53 2000
@@ -587,7 +587,7 @@
cmd[2] = 0x2a;
cmd[4] = 128;
cmd[3] = cmd[5] = 0;
- rc = sr_do_ioctl(i, cmd, buffer, 128, 1, SCSI_DATA_READ);
+ rc = sr_do_ioctl(i, cmd, buffer, 128, 1, SCSI_DATA_READ, NULL);

if (-EINVAL == rc) {
/* failed, drive has'nt this mode page */
@@ -655,53 +655,12 @@
*/
static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc)
{
- Scsi_Request *SRpnt;
Scsi_Device *device = scsi_CDs[MINOR(cdi->dev)].device;
- unsigned char *buffer = cgc->buffer;
- int buflen;

- /* get the device */
- SRpnt = scsi_allocate_request(device);
- if (SRpnt == NULL)
- return -ENODEV; /* this just doesn't seem right /axboe */
-
- /* use buffer for ISA DMA */
- buflen = (cgc->buflen + 511) & ~511;
- if (cgc->buffer && SRpnt->sr_host->unchecked_isa_dma &&
- (virt_to_phys(cgc->buffer) + cgc->buflen - 1 > ISA_DMA_THRESHOLD)) {
- buffer = scsi_malloc(buflen);
- if (buffer == NULL) {
- printk("sr: SCSI DMA pool exhausted.");
- return -ENOMEM;
- }
- memcpy(buffer, cgc->buffer, cgc->buflen);
- }
/* set the LUN */
cgc->cmd[1] |= device->lun << 5;

- /* do the locking and issue the command */
- SRpnt->sr_request.rq_dev = cdi->dev;
- /* scsi_wait_req sets the command length */
- SRpnt->sr_cmd_len = 0;
-
- SRpnt->sr_data_direction = cgc->data_direction;
- scsi_wait_req(SRpnt, (void *) cgc->cmd, (void *) buffer, cgc->buflen,
- SR_TIMEOUT, MAX_RETRIES);
-
- if ((cgc->stat = SRpnt->sr_result))
- cgc->sense = (struct request_sense *) SRpnt->sr_sense_buffer;
-
- /* release */
- SRpnt->sr_request.rq_dev = MKDEV(0, 0);
- scsi_release_request(SRpnt);
- SRpnt = NULL;
-
- /* write DMA buffer back if used */
- if (buffer && (buffer != cgc->buffer)) {
- memcpy(cgc->buffer, buffer, cgc->buflen);
- scsi_free(buffer, buflen);
- }
-
+ cgc->stat = sr_do_ioctl(MINOR(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense);

return cgc->stat;
}
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11-pre2/drivers/scsi/sr.h linux/drivers/scsi/sr.h
--- /opt/kernel/linux-2.4.0-test11-pre2/drivers/scsi/sr.h Thu Feb 17 05:21:45 2000
+++ linux/drivers/scsi/sr.h Sat Nov 11 04:29:12 2000
@@ -36,7 +36,7 @@

extern Scsi_CD *scsi_CDs;

-int sr_do_ioctl(int, unsigned char *, void *, unsigned, int, int);
+int sr_do_ioctl(int, unsigned char *, void *, unsigned, int, int, struct request_sense *);

int sr_lock_door(struct cdrom_device_info *, int);
int sr_tray_move(struct cdrom_device_info *, int);
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11-pre2/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- /opt/kernel/linux-2.4.0-test11-pre2/drivers/scsi/sr_ioctl.c Sat Nov 11 04:55:05 2000
+++ linux/drivers/scsi/sr_ioctl.c Sat Nov 11 04:41:38 2000
@@ -34,7 +34,7 @@
error code is. Normally the UNIT_ATTENTION code will automatically
clear after one error */

-int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflength, int quiet, int readwrite)
+int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflength, int quiet, int readwrite, struct request_sense *sense)
{
Scsi_Request *SRpnt;
Scsi_Device *SDev;
@@ -132,7 +132,10 @@
err = -EIO;
}
}
- result = SRpnt->sr_result;
+
+ if (sense)
+ memcpy(sense, SRpnt->sr_sense_buffer, sizeof(*sense));
+
/* Wake up a process waiting for device */
scsi_release_request(SRpnt);
SRpnt = NULL;
@@ -149,7 +152,7 @@
sr_cmd[0] = GPCMD_TEST_UNIT_READY;
sr_cmd[1] = ((scsi_CDs[minor].device->lun) << 5);
sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
- return sr_do_ioctl(minor, sr_cmd, NULL, 0, 1, SCSI_DATA_NONE);
+ return sr_do_ioctl(minor, sr_cmd, NULL, 0, 1, SCSI_DATA_NONE, NULL);
}

int sr_tray_move(struct cdrom_device_info *cdi, int pos)
@@ -161,7 +164,7 @@
sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
sr_cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ;

- return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE);
+ return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
}

int sr_lock_door(struct cdrom_device_info *cdi, int lock)
@@ -238,7 +241,7 @@
sr_cmd[8] = 24;
sr_cmd[9] = 0;

- result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ);
+ result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL);

memcpy(mcn->medium_catalog_number, buffer + 9, 13);
mcn->medium_catalog_number[13] = 0;
@@ -267,7 +270,7 @@
sr_cmd[2] = (speed >> 8) & 0xff; /* MSB for speed (in kbytes/sec) */
sr_cmd[3] = speed & 0xff; /* LSB */

- if (sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE))
+ if (sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL))
return -EIO;
return 0;
}
@@ -296,7 +299,7 @@
sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
sr_cmd[8] = 12; /* LSB of length */

- result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1, SCSI_DATA_READ);
+ result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);

tochdr->cdth_trk0 = buffer[2];
tochdr->cdth_trk1 = buffer[3];
@@ -315,7 +318,7 @@
sr_cmd[6] = tocentry->cdte_track;
sr_cmd[8] = 12; /* LSB of length */

- result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0, SCSI_DATA_READ);
+ result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0, SCSI_DATA_READ, NULL);

tocentry->cdte_ctrl = buffer[5] & 0xf;
tocentry->cdte_adr = buffer[5] >> 4;
@@ -341,7 +344,7 @@
sr_cmd[7] = ti->cdti_trk1;
sr_cmd[8] = ti->cdti_ind1;

- result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0, SCSI_DATA_NONE);
+ result = sr_do_ioctl(target, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
break;
}

@@ -402,7 +405,7 @@
cmd[9] = 0x10;
break;
}
- return sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ);
+ return sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL);
}

/*
@@ -440,7 +443,7 @@
cmd[4] = (unsigned char) (lba >> 8) & 0xff;
cmd[5] = (unsigned char) lba & 0xff;
cmd[8] = 1;
- rc = sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ);
+ rc = sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL);

return rc;
}
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11-pre2/drivers/scsi/sr_vendor.c linux/drivers/scsi/sr_vendor.c
--- /opt/kernel/linux-2.4.0-test11-pre2/drivers/scsi/sr_vendor.c Thu Feb 17 05:21:45 2000
+++ linux/drivers/scsi/sr_vendor.c Sat Nov 11 04:28:19 2000
@@ -132,7 +132,7 @@
modesel->density = density;
modesel->block_length_med = (blocklength >> 8) & 0xff;
modesel->block_length_lo = blocklength & 0xff;
- if (0 == (rc = sr_do_ioctl(minor, cmd, buffer, sizeof(*modesel), 0, SCSI_DATA_WRITE))) {
+ if (0 == (rc = sr_do_ioctl(minor, cmd, buffer, sizeof(*modesel), 0, SCSI_DATA_WRITE, NULL))) {
scsi_CDs[minor].device->sector_size = blocklength;
}
#ifdef DEBUG
@@ -176,7 +176,7 @@
cmd[1] = (scsi_CDs[minor].device->lun << 5);
cmd[8] = 12;
cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ);
+ rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
if (rc != 0)
break;
if ((buffer[0] << 8) + buffer[1] < 0x0a) {
@@ -200,7 +200,7 @@
cmd[0] = 0xde;
cmd[1] = (scsi_CDs[minor].device->lun << 5) | 0x03;
cmd[2] = 0xb0;
- rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 1, SCSI_DATA_READ);
+ rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 1, SCSI_DATA_READ, NULL);
if (rc != 0)
break;
if (buffer[14] != 0 && buffer[14] != 0xb0) {
@@ -224,7 +224,7 @@
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = 0xc7;
cmd[1] = (scsi_CDs[minor].device->lun << 5) | 3;
- rc = sr_do_ioctl(minor, cmd, buffer, 4, 1, SCSI_DATA_READ);
+ rc = sr_do_ioctl(minor, cmd, buffer, 4, 1, SCSI_DATA_READ, NULL);
if (rc == -EINVAL) {
printk(KERN_INFO "sr%d: Hmm, seems the drive "
"doesn't support multisession CD's\n", minor);
@@ -249,7 +249,7 @@
cmd[1] = (scsi_CDs[minor].device->lun << 5);
cmd[8] = 0x04;
cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 1, SCSI_DATA_READ);
+ rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 1, SCSI_DATA_READ, NULL);
if (rc != 0) {
break;
}
@@ -263,7 +263,7 @@
cmd[6] = rc & 0x7f; /* number of last session */
cmd[8] = 0x0c;
cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ);
+ rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
if (rc != 0) {
break;
}
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11-pre2/include/linux/cdrom.h linux/include/linux/cdrom.h
--- /opt/kernel/linux-2.4.0-test11-pre2/include/linux/cdrom.h Tue Oct 31 20:18:07 2000
+++ linux/include/linux/cdrom.h Sat Nov 11 04:30:14 2000
@@ -280,7 +280,9 @@
int stat;
struct request_sense *sense;
unsigned char data_direction;
- void *reserved[3];
+ int quiet;
+ int timeout;
+ void *reserved[1];
};

\
 
 \ /
  Last update: 2005-03-22 12:45    [W:0.083 / U:0.128 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site