USB: cdc_acm: Fix memory leak after hangup
[safe/jmp/linux-2.6] / drivers / scsi / sr_ioctl.c
index 5d02ff4..291236e 100644 (file)
@@ -1,5 +1,4 @@
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/errno.h>
@@ -192,7 +191,7 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
        SDev = cd->device;
 
        if (!sense) {
-               sense = kmalloc(sizeof(*sense), GFP_KERNEL);
+               sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
                if (!sense) {
                        err = -ENOMEM;
                        goto out;
@@ -208,7 +207,7 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
        memset(sense, 0, sizeof(*sense));
        result = scsi_execute(SDev, cgc->cmd, cgc->data_direction,
                              cgc->buffer, cgc->buflen, (char *)sense,
-                             cgc->timeout, IOCTL_RETRIES, 0);
+                             cgc->timeout, IOCTL_RETRIES, 0, NULL);
 
        scsi_normalize_sense((char *)sense, sizeof(*sense), &sshdr);
 
@@ -276,18 +275,6 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
 /* ---------------------------------------------------------------------- */
 /* interface to cdrom.c                                                   */
 
-static int test_unit_ready(Scsi_CD *cd)
-{
-       struct packet_command cgc;
-
-       memset(&cgc, 0, sizeof(struct packet_command));
-       cgc.cmd[0] = GPCMD_TEST_UNIT_READY;
-       cgc.quiet = 1;
-       cgc.data_direction = DMA_NONE;
-       cgc.timeout = IOCTL_TIMEOUT;
-       return sr_do_ioctl(cd, &cgc);
-}
-
 int sr_tray_move(struct cdrom_device_info *cdi, int pos)
 {
        Scsi_CD *cd = cdi->handle;
@@ -311,14 +298,50 @@ int sr_lock_door(struct cdrom_device_info *cdi, int lock)
 
 int sr_drive_status(struct cdrom_device_info *cdi, int slot)
 {
+       struct scsi_cd *cd = cdi->handle;
+       struct scsi_sense_hdr sshdr;
+       struct media_event_desc med;
+
        if (CDSL_CURRENT != slot) {
                /* we have no changer support */
                return -EINVAL;
        }
-       if (0 == test_unit_ready(cdi->handle))
+       if (0 == sr_test_unit_ready(cd->device, &sshdr))
                return CDS_DISC_OK;
 
-       return CDS_TRAY_OPEN;
+       /* SK/ASC/ASCQ of 2/4/1 means "unit is becoming ready" */
+       if (scsi_sense_valid(&sshdr) && sshdr.sense_key == NOT_READY
+                       && sshdr.asc == 0x04 && sshdr.ascq == 0x01)
+               return CDS_DRIVE_NOT_READY;
+
+       if (!cdrom_get_media_event(cdi, &med)) {
+               if (med.media_present)
+                       return CDS_DISC_OK;
+               else if (med.door_open)
+                       return CDS_TRAY_OPEN;
+               else
+                       return CDS_NO_DISC;
+       }
+
+       /*
+        * 0x04 is format in progress .. but there must be a disc present!
+        */
+       if (sshdr.sense_key == NOT_READY && sshdr.asc == 0x04)
+               return CDS_DISC_OK;
+
+       /*
+        * If not using Mt Fuji extended media tray reports,
+        * just return TRAY_OPEN since ATAPI doesn't provide
+        * any other way to detect this...
+        */
+       if (scsi_sense_valid(&sshdr) &&
+           /* 0x3a is medium not present */
+           sshdr.asc == 0x3a)
+               return CDS_NO_DISC;
+       else
+               return CDS_TRAY_OPEN;
+
+       return CDS_DRIVE_NOT_READY;
 }
 
 int sr_disk_status(struct cdrom_device_info *cdi)
@@ -546,7 +569,7 @@ int sr_is_xa(Scsi_CD *cd)
        if (!xa_test)
                return 0;
 
-       raw_sector = (unsigned char *) kmalloc(2048, GFP_KERNEL | SR_GFP_DMA(cd));
+       raw_sector = kmalloc(2048, GFP_KERNEL | SR_GFP_DMA(cd));
        if (!raw_sector)
                return -ENOMEM;
        if (0 == sr_read_sector(cd, cd->ms_offset + 16,
@@ -562,22 +585,3 @@ int sr_is_xa(Scsi_CD *cd)
 #endif
        return is_xa;
 }
-
-int sr_dev_ioctl(struct cdrom_device_info *cdi,
-                unsigned int cmd, unsigned long arg)
-{
-       Scsi_CD *cd = cdi->handle;
-       int ret;
-       
-       ret = scsi_nonblockable_ioctl(cd->device, cmd,
-                                     (void __user *)arg, NULL);
-       /*
-        * ENODEV means that we didn't recognise the ioctl, or that we
-        * cannot execute it in the current device state.  In either
-        * case fall through to scsi_ioctl, which will return ENDOEV again
-        * if it doesn't recognise the ioctl
-        */
-       if (ret != -ENODEV)
-               return ret;
-       return scsi_ioctl(cd->device, cmd, (void __user *)arg);
-}