block: no need to initialize rq->cmd with blk_get_request
[safe/jmp/linux-2.6] / drivers / cdrom / cdrom.c
index 66d028d..69f26eb 100644 (file)
@@ -302,7 +302,7 @@ module_param(lockdoor, bool, 0);
 module_param(check_media_type, bool, 0);
 module_param(mrw_format_restart, bool, 0);
 
-static DEFINE_SPINLOCK(cdrom_lock);
+static DEFINE_MUTEX(cdrom_mutex);
 
 static const char *mrw_format_status[] = {
        "not mrw",
@@ -337,6 +337,12 @@ static const char *mrw_address_space[] = { "DMA", "GAA" };
 /* used in the audio ioctls */
 #define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret
 
+/*
+ * Another popular OS uses 7 seconds as the hard timeout for default
+ * commands, so it is a good choice for us as well.
+ */
+#define CDROM_DEF_TIMEOUT      (7 * HZ)
+
 /* Not-exported routines. */
 static int open_for_data(struct cdrom_device_info * cdi);
 static int check_for_audio_disc(struct cdrom_device_info * cdi,
@@ -354,10 +360,9 @@ static int cdrom_mrw_exit(struct cdrom_device_info *cdi);
 
 static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di);
 
-#ifdef CONFIG_SYSCTL
 static void cdrom_sysctl_register(void);
-#endif /* CONFIG_SYSCTL */ 
-static struct cdrom_device_info *topCdromPtr;
+
+static LIST_HEAD(cdrom_list);
 
 static int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
                                      struct packet_command *cgc)
@@ -388,13 +393,11 @@ int register_cdrom(struct cdrom_device_info *cdi)
        cdinfo(CD_OPEN, "entering register_cdrom\n"); 
 
        if (cdo->open == NULL || cdo->release == NULL)
-               return -2;
+               return -EINVAL;
        if (!banner_printed) {
                printk(KERN_INFO "Uniform CD-ROM driver " REVISION "\n");
                banner_printed = 1;
-#ifdef CONFIG_SYSCTL
                cdrom_sysctl_register();
-#endif /* CONFIG_SYSCTL */ 
        }
 
        ENSURE(drive_status, CDC_DRIVE_STATUS );
@@ -432,71 +435,63 @@ int register_cdrom(struct cdrom_device_info *cdi)
                cdo->generic_packet = cdrom_dummy_generic_packet;
 
        cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
-       spin_lock(&cdrom_lock);
-       cdi->next = topCdromPtr;        
-       topCdromPtr = cdi;
-       spin_unlock(&cdrom_lock);
+       mutex_lock(&cdrom_mutex);
+       list_add(&cdi->list, &cdrom_list);
+       mutex_unlock(&cdrom_mutex);
        return 0;
 }
 #undef ENSURE
 
-int unregister_cdrom(struct cdrom_device_info *unreg)
+void unregister_cdrom(struct cdrom_device_info *cdi)
 {
-       struct cdrom_device_info *cdi, *prev;
        cdinfo(CD_OPEN, "entering unregister_cdrom\n"); 
 
-       prev = NULL;
-       spin_lock(&cdrom_lock);
-       cdi = topCdromPtr;
-       while (cdi && cdi != unreg) {
-               prev = cdi;
-               cdi = cdi->next;
-       }
-
-       if (cdi == NULL) {
-               spin_unlock(&cdrom_lock);
-               return -2;
-       }
-       if (prev)
-               prev->next = cdi->next;
-       else
-               topCdromPtr = cdi->next;
-
-       spin_unlock(&cdrom_lock);
+       mutex_lock(&cdrom_mutex);
+       list_del(&cdi->list);
+       mutex_unlock(&cdrom_mutex);
 
        if (cdi->exit)
                cdi->exit(cdi);
 
        cdi->ops->n_minors--;
        cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
-       return 0;
 }
 
 int cdrom_get_media_event(struct cdrom_device_info *cdi,
                          struct media_event_desc *med)
 {
        struct packet_command cgc;
-       unsigned char buffer[8];
-       struct event_header *eh = (struct event_header *) buffer;
+       unsigned char *buffer;
+       struct event_header *eh;
+       int ret = 1;
+
+       buffer = kmalloc(8, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
 
-       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+       eh = (struct event_header *)buffer;
+
+       init_cdrom_command(&cgc, buffer, 8, CGC_DATA_READ);
        cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
        cgc.cmd[1] = 1;         /* IMMED */
        cgc.cmd[4] = 1 << 4;    /* media event */
-       cgc.cmd[8] = sizeof(buffer);
+       cgc.cmd[8] = 8;
        cgc.quiet = 1;
 
        if (cdi->ops->generic_packet(cdi, &cgc))
-               return 1;
+               goto err;
 
        if (be16_to_cpu(eh->data_len) < sizeof(*med))
-               return 1;
+               goto err;
 
        if (eh->nea || eh->notification_class != 0x4)
-               return 1;
+               goto err;
 
-       memcpy(med, &buffer[sizeof(*eh)], sizeof(*med));
-       return 0;
+       memcpy(med, buffer + sizeof(*eh), sizeof(*med));
+       ret = 0;
+err:
+       kfree(buffer);
+       return ret;
 }
 
 /*
@@ -506,68 +501,82 @@ int cdrom_get_media_event(struct cdrom_device_info *cdi,
 static int cdrom_mrw_probe_pc(struct cdrom_device_info *cdi)
 {
        struct packet_command cgc;
-       char buffer[16];
+       char *buffer;
+       int ret = 1;
+
+       buffer = kmalloc(16, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
 
-       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+       init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
 
        cgc.timeout = HZ;
        cgc.quiet = 1;
 
        if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC, 0)) {
                cdi->mrw_mode_page = MRW_MODE_PC;
-               return 0;
+               ret = 0;
        } else if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC_PRE1, 0)) {
                cdi->mrw_mode_page = MRW_MODE_PC_PRE1;
-               return 0;
+               ret = 0;
        }
-
-       return 1;
+       kfree(buffer);
+       return ret;
 }
 
 static int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write)
 {
        struct packet_command cgc;
        struct mrw_feature_desc *mfd;
-       unsigned char buffer[16];
+       unsigned char *buffer;
        int ret;
 
        *write = 0;
+       buffer = kmalloc(16, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
 
-       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+       init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
 
        cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
        cgc.cmd[3] = CDF_MRW;
-       cgc.cmd[8] = sizeof(buffer);
+       cgc.cmd[8] = 16;
        cgc.quiet = 1;
 
        if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
-               return ret;
+               goto err;
 
        mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)];
-       if (be16_to_cpu(mfd->feature_code) != CDF_MRW)
-               return 1;
+       if (be16_to_cpu(mfd->feature_code) != CDF_MRW) {
+               ret = 1;
+               goto err;
+       }
        *write = mfd->write;
 
        if ((ret = cdrom_mrw_probe_pc(cdi))) {
                *write = 0;
-               return ret;
        }
-
-       return 0;
+err:
+       kfree(buffer);
+       return ret;
 }
 
 static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
 {
        struct packet_command cgc;
-       unsigned char buffer[12];
+       unsigned char *buffer;
        int ret;
 
        printk(KERN_INFO "cdrom: %sstarting format\n", cont ? "Re" : "");
 
+       buffer = kmalloc(12, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
        /*
         * FmtData bit set (bit 4), format type is 1
         */
-       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_WRITE);
+       init_cdrom_command(&cgc, buffer, 12, CGC_DATA_WRITE);
        cgc.cmd[0] = GPCMD_FORMAT_UNIT;
        cgc.cmd[1] = (1 << 4) | 1;
 
@@ -594,6 +603,7 @@ static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
        if (ret)
                printk(KERN_INFO "cdrom: bgformat failed\n");
 
+       kfree(buffer);
        return ret;
 }
 
@@ -653,16 +663,17 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
 {
        struct packet_command cgc;
        struct mode_page_header *mph;
-       char buffer[16];
+       char *buffer;
        int ret, offset, size;
 
-       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+       buffer = kmalloc(16, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
 
-       cgc.buffer = buffer;
-       cgc.buflen = sizeof(buffer);
+       init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
 
        if ((ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0)))
-               return ret;
+               goto err;
 
        mph = (struct mode_page_header *) buffer;
        offset = be16_to_cpu(mph->desc_length);
@@ -672,55 +683,70 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
        cgc.buflen = size;
 
        if ((ret = cdrom_mode_select(cdi, &cgc)))
-               return ret;
+               goto err;
 
        printk(KERN_INFO "cdrom: %s: mrw address space %s selected\n", cdi->name, mrw_address_space[space]);
-       return 0;
+       ret = 0;
+err:
+       kfree(buffer);
+       return ret;
 }
 
 static int cdrom_get_random_writable(struct cdrom_device_info *cdi,
                              struct rwrt_feature_desc *rfd)
 {
        struct packet_command cgc;
-       char buffer[24];
+       char *buffer;
        int ret;
 
-       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+       buffer = kmalloc(24, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       init_cdrom_command(&cgc, buffer, 24, CGC_DATA_READ);
 
        cgc.cmd[0] = GPCMD_GET_CONFIGURATION;   /* often 0x46 */
        cgc.cmd[3] = CDF_RWRT;                  /* often 0x0020 */
-       cgc.cmd[8] = sizeof(buffer);            /* often 0x18 */
+       cgc.cmd[8] = 24;                        /* often 0x18 */
        cgc.quiet = 1;
 
        if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
-               return ret;
+               goto err;
 
        memcpy(rfd, &buffer[sizeof(struct feature_header)], sizeof (*rfd));
-       return 0;
+       ret = 0;
+err:
+       kfree(buffer);
+       return ret;
 }
 
 static int cdrom_has_defect_mgt(struct cdrom_device_info *cdi)
 {
        struct packet_command cgc;
-       char buffer[16];
+       char *buffer;
        __be16 *feature_code;
        int ret;
 
-       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+       buffer = kmalloc(16, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
 
        cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
        cgc.cmd[3] = CDF_HWDM;
-       cgc.cmd[8] = sizeof(buffer);
+       cgc.cmd[8] = 16;
        cgc.quiet = 1;
 
        if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
-               return ret;
+               goto err;
 
        feature_code = (__be16 *) &buffer[sizeof(struct feature_header)];
        if (be16_to_cpu(*feature_code) == CDF_HWDM)
-               return 0;
-
-       return 1;
+               ret = 0;
+err:
+       kfree(buffer);
+       return ret;
 }
 
 
@@ -811,10 +837,14 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi)
 static int mo_open_write(struct cdrom_device_info *cdi)
 {
        struct packet_command cgc;
-       char buffer[255];
+       char *buffer;
        int ret;
 
-       init_cdrom_command(&cgc, &buffer, 4, CGC_DATA_READ);
+       buffer = kmalloc(255, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       init_cdrom_command(&cgc, buffer, 4, CGC_DATA_READ);
        cgc.quiet = 1;
 
        /*
@@ -831,10 +861,15 @@ static int mo_open_write(struct cdrom_device_info *cdi)
        }
 
        /* drive gave us no info, let the user go ahead */
-       if (ret)
-               return 0;
+       if (ret) {
+               ret = 0;
+               goto err;
+       }
 
-       return buffer[3] & 0x80;
+       ret = buffer[3] & 0x80;
+err:
+       kfree(buffer);
+       return ret;
 }
 
 static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
@@ -857,15 +892,19 @@ static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
 static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
 {
        struct packet_command cgc;
-       char buffer[32];
+       char *buffer;
        int ret, mmc3_profile;
 
-       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+       buffer = kmalloc(32, GFP_KERNEL);
+       if (!buffer)
+               return;
+
+       init_cdrom_command(&cgc, buffer, 32, CGC_DATA_READ);
 
        cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
        cgc.cmd[1] = 0;
        cgc.cmd[2] = cgc.cmd[3] = 0;            /* Starting Feature Number */
-       cgc.cmd[8] = sizeof(buffer);            /* Allocation Length */
+       cgc.cmd[8] = 32;                        /* Allocation Length */
        cgc.quiet = 1;
 
        if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
@@ -874,6 +913,7 @@ static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
                mmc3_profile = (buffer[6] << 8) | buffer[7];
 
        cdi->mmc3_profile = mmc3_profile;
+       kfree(buffer);
 }
 
 static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi)
@@ -1026,6 +1066,10 @@ int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp)
        check_disk_change(ip->i_bdev);
        return 0;
 err_release:
+       if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
+               cdi->ops->lock_door(cdi, 0);
+               cdinfo(CD_OPEN, "door unlocked.\n");
+       }
        cdi->ops->release(cdi);
 err:
        cdi->use_count--;
@@ -1097,7 +1141,7 @@ int open_for_data(struct cdrom_device_info * cdi)
                       is the default case! */
                    cdinfo(CD_OPEN, "bummer. wrong media type.\n"); 
                    cdinfo(CD_WARNING, "pid %d must open device O_NONBLOCK!\n",
-                                       (unsigned int)current->pid); 
+                                       (unsigned int)task_pid_nr(current));
                    ret=-EMEDIUMTYPE;
                    goto clean_up_and_return;
                }
@@ -1142,8 +1186,8 @@ clean_up_and_return:
 /* This code is similar to that in open_for_data. The routine is called
    whenever an audio play operation is requested.
 */
-int check_for_audio_disc(struct cdrom_device_info * cdi,
-                        struct cdrom_device_ops * cdo)
+static int check_for_audio_disc(struct cdrom_device_info * cdi,
+                               struct cdrom_device_ops * cdo)
 {
         int ret;
        tracktype tracks;
@@ -1196,25 +1240,26 @@ int check_for_audio_disc(struct cdrom_device_info * cdi,
        return 0;
 }
 
-/* Admittedly, the logic below could be performed in a nicer way. */
 int cdrom_release(struct cdrom_device_info *cdi, struct file *fp)
 {
        struct cdrom_device_ops *cdo = cdi->ops;
        int opened_for_data;
 
-       cdinfo(CD_CLOSE, "entering cdrom_release\n"); 
+       cdinfo(CD_CLOSE, "entering cdrom_release\n");
 
        if (cdi->use_count > 0)
                cdi->use_count--;
-       if (cdi->use_count == 0)
+
+       if (cdi->use_count == 0) {
                cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
-       if (cdi->use_count == 0)
                cdrom_dvd_rw_close_write(cdi);
-       if (cdi->use_count == 0 &&
-           (cdo->capability & CDC_LOCK) && !keeplocked) {
-               cdinfo(CD_CLOSE, "Unlocking door!\n");
-               cdo->lock_door(cdi, 0);
+
+               if ((cdo->capability & CDC_LOCK) && !keeplocked) {
+                       cdinfo(CD_CLOSE, "Unlocking door!\n");
+                       cdo->lock_door(cdi, 0);
+               }
        }
+
        opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
                !(fp && fp->f_flags & O_NONBLOCK);
 
@@ -1528,7 +1573,7 @@ void init_cdrom_command(struct packet_command *cgc, void *buf, int len,
        cgc->buffer = (char *) buf;
        cgc->buflen = len;
        cgc->data_direction = type;
-       cgc->timeout = 5*HZ;
+       cgc->timeout = CDROM_DEF_TIMEOUT;
 }
 
 /* DVD handling */
@@ -1583,12 +1628,15 @@ static void setup_send_key(struct packet_command *cgc, unsigned agid, unsigned t
 static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
 {
        int ret;
-       u_char buf[20];
+       u_char *buf;
        struct packet_command cgc;
        struct cdrom_device_ops *cdo = cdi->ops;
-       rpc_state_t rpc_state;
+       rpc_state_t *rpc_state;
+
+       buf = kzalloc(20, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
 
-       memset(buf, 0, sizeof(buf));
        init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ);
 
        switch (ai->type) {
@@ -1599,7 +1647,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                setup_report_key(&cgc, ai->lsa.agid, 0);
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       return ret;
+                       goto err;
 
                ai->lsa.agid = buf[7] >> 6;
                /* Returning data, let host change state */
@@ -1610,7 +1658,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                setup_report_key(&cgc, ai->lsk.agid, 2);
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       return ret;
+                       goto err;
 
                copy_key(ai->lsk.key, &buf[4]);
                /* Returning data, let host change state */
@@ -1621,7 +1669,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                setup_report_key(&cgc, ai->lsc.agid, 1);
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       return ret;
+                       goto err;
 
                copy_chal(ai->lsc.chal, &buf[4]);
                /* Returning data, let host change state */
@@ -1638,7 +1686,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                cgc.cmd[2] = ai->lstk.lba >> 24;
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       return ret;
+                       goto err;
 
                ai->lstk.cpm = (buf[4] >> 7) & 1;
                ai->lstk.cp_sec = (buf[4] >> 6) & 1;
@@ -1652,7 +1700,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                setup_report_key(&cgc, ai->lsasf.agid, 5);
                
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       return ret;
+                       goto err;
 
                ai->lsasf.asf = buf[7] & 1;
                break;
@@ -1665,7 +1713,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                copy_chal(&buf[4], ai->hsc.chal);
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       return ret;
+                       goto err;
 
                ai->type = DVD_LU_SEND_KEY1;
                break;
@@ -1678,7 +1726,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
 
                if ((ret = cdo->generic_packet(cdi, &cgc))) {
                        ai->type = DVD_AUTH_FAILURE;
-                       return ret;
+                       goto err;
                }
                ai->type = DVD_AUTH_ESTABLISHED;
                break;
@@ -1689,24 +1737,23 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n"); 
                setup_report_key(&cgc, ai->lsa.agid, 0x3f);
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       return ret;
+                       goto err;
                break;
 
        /* Get region settings */
        case DVD_LU_SEND_RPC_STATE:
                cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
                setup_report_key(&cgc, 0, 8);
-               memset(&rpc_state, 0, sizeof(rpc_state_t));
-               cgc.buffer = (char *) &rpc_state;
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       return ret;
+                       goto err;
 
-               ai->lrpcs.type = rpc_state.type_code;
-               ai->lrpcs.vra = rpc_state.vra;
-               ai->lrpcs.ucca = rpc_state.ucca;
-               ai->lrpcs.region_mask = rpc_state.region_mask;
-               ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme;
+               rpc_state = (rpc_state_t *)buf;
+               ai->lrpcs.type = rpc_state->type_code;
+               ai->lrpcs.vra = rpc_state->vra;
+               ai->lrpcs.ucca = rpc_state->ucca;
+               ai->lrpcs.region_mask = rpc_state->region_mask;
+               ai->lrpcs.rpc_scheme = rpc_state->rpc_scheme;
                break;
 
        /* Set region settings */
@@ -1717,20 +1764,23 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                buf[4] = ai->hrpcs.pdrc;
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       return ret;
+                       goto err;
                break;
 
        default:
                cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type);
-               return -ENOTTY;
+               ret = -ENOTTY;
+               goto err;
        }
-
-       return 0;
+       ret = 0;
+err:
+       kfree(buf);
+       return ret;
 }
 
 static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
 {
-       unsigned char buf[21], *base;
+       unsigned char *buf, *base;
        struct dvd_layer *layer;
        struct packet_command cgc;
        struct cdrom_device_ops *cdo = cdi->ops;
@@ -1739,7 +1789,11 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
        if (layer_num >= DVD_LAYERS)
                return -EINVAL;
 
-       init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
+       buf = kmalloc(21, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       init_cdrom_command(&cgc, buf, 21, CGC_DATA_READ);
        cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
        cgc.cmd[6] = layer_num;
        cgc.cmd[7] = s->type;
@@ -1751,7 +1805,7 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
        cgc.quiet = 1;
 
        if ((ret = cdo->generic_packet(cdi, &cgc)))
-               return ret;
+               goto err;
 
        base = &buf[4];
        layer = &s->physical.layer[layer_num];
@@ -1775,17 +1829,24 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
        layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];
        layer->bca = base[16] >> 7;
 
-       return 0;
+       ret = 0;
+err:
+       kfree(buf);
+       return ret;
 }
 
 static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
 {
        int ret;
-       u_char buf[8];
+       u_char *buf;
        struct packet_command cgc;
        struct cdrom_device_ops *cdo = cdi->ops;
 
-       init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
+       buf = kmalloc(8, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       init_cdrom_command(&cgc, buf, 8, CGC_DATA_READ);
        cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
        cgc.cmd[6] = s->copyright.layer_num;
        cgc.cmd[7] = s->type;
@@ -1793,12 +1854,15 @@ static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
        cgc.cmd[9] = cgc.buflen & 0xff;
 
        if ((ret = cdo->generic_packet(cdi, &cgc)))
-               return ret;
+               goto err;
 
        s->copyright.cpst = buf[4];
        s->copyright.rmi = buf[5];
 
-       return 0;
+       ret = 0;
+err:
+       kfree(buf);
+       return ret;
 }
 
 static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
@@ -1830,26 +1894,33 @@ static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
 static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s)
 {
        int ret;
-       u_char buf[4 + 188];
+       u_char *buf;
        struct packet_command cgc;
        struct cdrom_device_ops *cdo = cdi->ops;
 
-       init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
+       buf = kmalloc(4 + 188, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       init_cdrom_command(&cgc, buf, 4 + 188, CGC_DATA_READ);
        cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
        cgc.cmd[7] = s->type;
        cgc.cmd[9] = cgc.buflen & 0xff;
 
        if ((ret = cdo->generic_packet(cdi, &cgc)))
-               return ret;
+               goto err;
 
        s->bca.len = buf[0] << 8 | buf[1];
        if (s->bca.len < 12 || s->bca.len > 188) {
                cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len);
-               return -EIO;
+               ret = -EIO;
+               goto err;
        }
        memcpy(s->bca.value, &buf[4], s->bca.len);
-
-       return 0;
+       ret = 0;
+err:
+       kfree(buf);
+       return ret;
 }
 
 static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s)
@@ -1949,9 +2020,13 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
 {
        struct cdrom_device_ops *cdo = cdi->ops;
        struct packet_command cgc;
-       char buffer[32];
+       char *buffer;
        int ret;
 
+       buffer = kmalloc(32, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
        init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
        cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
        cgc.cmd[1] = 2;     /* MSF addressing */
@@ -1960,7 +2035,7 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
        cgc.cmd[8] = 16;
 
        if ((ret = cdo->generic_packet(cdi, &cgc)))
-               return ret;
+               goto err;
 
        subchnl->cdsc_audiostatus = cgc.buffer[1];
        subchnl->cdsc_format = CDROM_MSF;
@@ -1975,7 +2050,10 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
        subchnl->cdsc_absaddr.msf.second = cgc.buffer[10];
        subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11];
 
-       return 0;
+       ret = 0;
+err:
+       kfree(buffer);
+       return ret;
 }
 
 /*
@@ -2088,7 +2166,7 @@ out:
 static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
                               int lba, int nframes)
 {
-       request_queue_t *q = cdi->disk->queue;
+       struct request_queue *q = cdi->disk->queue;
        struct request *rq;
        struct bio *bio;
        unsigned int len;
@@ -2116,7 +2194,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
                if (ret)
                        break;
 
-               memset(rq->cmd, 0, sizeof(rq->cmd));
                rq->cmd[0] = GPCMD_READ_CD;
                rq->cmd[1] = 1 << 2;
                rq->cmd[2] = (lba >> 24) & 0xff;
@@ -2378,7 +2455,7 @@ static int cdrom_ioctl_reset(struct cdrom_device_info *cdi,
                return -EACCES;
        if (!CDROM_CAN(CDC_RESET))
                return -ENOSYS;
-       invalidate_bdev(bdev, 0);
+       invalidate_bdev(bdev);
        return cdi->ops->reset(cdi);
 }
 
@@ -2689,11 +2766,12 @@ int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi,
 {
        void __user *argp = (void __user *)arg;
        int ret;
+       struct gendisk *disk = ip->i_bdev->bd_disk;
 
        /*
         * Try the generic SCSI command ioctl's first.
         */
-       ret = scsi_cmd_ioctl(file, ip->i_bdev->bd_disk, cmd, argp);
+       ret = scsi_cmd_ioctl(file, disk->queue, disk, cmd, argp);
        if (ret != -ENOTTY)
                return ret;
 
@@ -2776,12 +2854,6 @@ int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi,
        return -ENOSYS;
 }
 
-static inline
-int msf_to_lba(char m, char s, char f)
-{
-       return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
-}
-
 /*
  * Required when we need to use READ_10 to issue other than 2048 block
  * reads
@@ -3283,103 +3355,137 @@ static struct cdrom_sysctl_settings {
        int     check;                  /* check media type */
 } cdrom_sysctl_settings;
 
+enum cdrom_print_option {
+       CTL_NAME,
+       CTL_SPEED,
+       CTL_SLOTS,
+       CTL_CAPABILITY
+};
+
+static int cdrom_print_info(const char *header, int val, char *info,
+                               int *pos, enum cdrom_print_option option)
+{
+       const int max_size = sizeof(cdrom_sysctl_settings.info);
+       struct cdrom_device_info *cdi;
+       int ret;
+
+       ret = scnprintf(info + *pos, max_size - *pos, header);
+       if (!ret)
+               return 1;
+
+       *pos += ret;
+
+       list_for_each_entry(cdi, &cdrom_list, list) {
+               switch (option) {
+               case CTL_NAME:
+                       ret = scnprintf(info + *pos, max_size - *pos,
+                                       "\t%s", cdi->name);
+                       break;
+               case CTL_SPEED:
+                       ret = scnprintf(info + *pos, max_size - *pos,
+                                       "\t%d", cdi->speed);
+                       break;
+               case CTL_SLOTS:
+                       ret = scnprintf(info + *pos, max_size - *pos,
+                                       "\t%d", cdi->capacity);
+                       break;
+               case CTL_CAPABILITY:
+                       ret = scnprintf(info + *pos, max_size - *pos,
+                                       "\t%d", CDROM_CAN(val) != 0);
+                       break;
+               default:
+                       printk(KERN_INFO "cdrom: invalid option%d\n", option);
+                       return 1;
+               }
+               if (!ret)
+                       return 1;
+               *pos += ret;
+       }
+
+       return 0;
+}
+
 static int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
                            void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-        int pos;
-       struct cdrom_device_info *cdi;
+       int pos;
        char *info = cdrom_sysctl_settings.info;
+       const int max_size = sizeof(cdrom_sysctl_settings.info);
        
        if (!*lenp || (*ppos && !write)) {
                *lenp = 0;
                return 0;
        }
 
+       mutex_lock(&cdrom_mutex);
+
        pos = sprintf(info, "CD-ROM information, " VERSION "\n");
        
-       pos += sprintf(info+pos, "\ndrive name:\t");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%s", cdi->name);
-
-       pos += sprintf(info+pos, "\ndrive speed:\t");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", cdi->speed);
-
-       pos += sprintf(info+pos, "\ndrive # of slots:");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", cdi->capacity);
-
-       pos += sprintf(info+pos, "\nCan close tray:\t");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CLOSE_TRAY) != 0);
-
-       pos += sprintf(info+pos, "\nCan open tray:\t");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_OPEN_TRAY) != 0);
-
-       pos += sprintf(info+pos, "\nCan lock tray:\t");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_LOCK) != 0);
-
-       pos += sprintf(info+pos, "\nCan change speed:");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_SPEED) != 0);
-
-       pos += sprintf(info+pos, "\nCan select disk:");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_DISC) != 0);
-
-       pos += sprintf(info+pos, "\nCan read multisession:");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MULTI_SESSION) != 0);
-
-       pos += sprintf(info+pos, "\nCan read MCN:\t");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MCN) != 0);
-
-       pos += sprintf(info+pos, "\nReports media changed:");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MEDIA_CHANGED) != 0);
-
-       pos += sprintf(info+pos, "\nCan play audio:\t");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_PLAY_AUDIO) != 0);
-
-       pos += sprintf(info+pos, "\nCan write CD-R:\t");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_R) != 0);
-
-       pos += sprintf(info+pos, "\nCan write CD-RW:");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_RW) != 0);
-
-       pos += sprintf(info+pos, "\nCan read DVD:\t");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD) != 0);
-
-       pos += sprintf(info+pos, "\nCan write DVD-R:");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_R) != 0);
-
-       pos += sprintf(info+pos, "\nCan write DVD-RAM:");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
-
-       pos += sprintf(info+pos, "\nCan read MRW:\t");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW) != 0);
-
-       pos += sprintf(info+pos, "\nCan write MRW:\t");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW_W) != 0);
-
-       pos += sprintf(info+pos, "\nCan write RAM:\t");
-       for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-           pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_RAM) != 0);
-
-       strcpy(info+pos,"\n\n");
-               
-        return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
+       if (cdrom_print_info("\ndrive name:\t", 0, info, &pos, CTL_NAME))
+               goto done;
+       if (cdrom_print_info("\ndrive speed:\t", 0, info, &pos, CTL_SPEED))
+               goto done;
+       if (cdrom_print_info("\ndrive # of slots:", 0, info, &pos, CTL_SLOTS))
+               goto done;
+       if (cdrom_print_info("\nCan close tray:\t",
+                               CDC_CLOSE_TRAY, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan open tray:\t",
+                               CDC_OPEN_TRAY, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan lock tray:\t",
+                               CDC_LOCK, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan change speed:",
+                               CDC_SELECT_SPEED, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan select disk:",
+                               CDC_SELECT_DISC, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan read multisession:",
+                               CDC_MULTI_SESSION, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan read MCN:\t",
+                               CDC_MCN, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nReports media changed:",
+                               CDC_MEDIA_CHANGED, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan play audio:\t",
+                               CDC_PLAY_AUDIO, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan write CD-R:\t",
+                               CDC_CD_R, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan write CD-RW:",
+                               CDC_CD_RW, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan read DVD:\t",
+                               CDC_DVD, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan write DVD-R:",
+                               CDC_DVD_R, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan write DVD-RAM:",
+                               CDC_DVD_RAM, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan read MRW:\t",
+                               CDC_MRW, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan write MRW:\t",
+                               CDC_MRW_W, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (cdrom_print_info("\nCan write RAM:\t",
+                               CDC_RAM, info, &pos, CTL_CAPABILITY))
+               goto done;
+       if (!scnprintf(info + pos, max_size - pos, "\n\n"))
+               goto done;
+doit:
+       mutex_unlock(&cdrom_mutex);
+       return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
+done:
+       printk(KERN_INFO "cdrom: info buffer too small\n");
+       goto doit;
 }
 
 /* Unfortunately, per device settings are not implemented through
@@ -3390,7 +3496,8 @@ static void cdrom_update_settings(void)
 {
        struct cdrom_device_info *cdi;
 
-       for (cdi = topCdromPtr; cdi != NULL; cdi = cdi->next) {
+       mutex_lock(&cdrom_mutex);
+       list_for_each_entry(cdi, &cdrom_list, list) {
                if (autoclose && CDROM_CAN(CDC_CLOSE_TRAY))
                        cdi->options |= CDO_AUTO_CLOSE;
                else if (!autoclose)
@@ -3408,52 +3515,25 @@ static void cdrom_update_settings(void)
                else
                        cdi->options &= ~CDO_CHECK_TYPE;
        }
+       mutex_unlock(&cdrom_mutex);
 }
 
 static int cdrom_sysctl_handler(ctl_table *ctl, int write, struct file * filp,
                                void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-       int *valp = ctl->data;
-       int val = *valp;
        int ret;
        
        ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
 
-       if (write && *valp != val) {
+       if (write) {
        
                /* we only care for 1 or 0. */
-               if (*valp)
-                       *valp = 1;
-               else
-                       *valp = 0;
+               autoclose        = !!cdrom_sysctl_settings.autoclose;
+               autoeject        = !!cdrom_sysctl_settings.autoeject;
+               debug            = !!cdrom_sysctl_settings.debug;
+               lockdoor         = !!cdrom_sysctl_settings.lock;
+               check_media_type = !!cdrom_sysctl_settings.check;
 
-               switch (ctl->ctl_name) {
-               case DEV_CDROM_AUTOCLOSE: {
-                       if (valp == &cdrom_sysctl_settings.autoclose)
-                               autoclose = cdrom_sysctl_settings.autoclose;
-                       break;
-                       }
-               case DEV_CDROM_AUTOEJECT: {
-                       if (valp == &cdrom_sysctl_settings.autoeject)
-                               autoeject = cdrom_sysctl_settings.autoeject;
-                       break;
-                       }
-               case DEV_CDROM_DEBUG: {
-                       if (valp == &cdrom_sysctl_settings.debug)
-                               debug = cdrom_sysctl_settings.debug;
-                       break;
-                       }
-               case DEV_CDROM_LOCK: {
-                       if (valp == &cdrom_sysctl_settings.lock)
-                               lockdoor = cdrom_sysctl_settings.lock;
-                       break;
-                       }
-               case DEV_CDROM_CHECK_MEDIA: {
-                       if (valp == &cdrom_sysctl_settings.check)
-                               check_media_type = cdrom_sysctl_settings.check;
-                       break;
-                       }
-               }
                /* update the option flags according to the changes. we
                   don't have per device options through sysctl yet,
                   but we will have and then this will disappear. */
@@ -3466,7 +3546,6 @@ static int cdrom_sysctl_handler(ctl_table *ctl, int write, struct file * filp,
 /* Place files in /proc/sys/dev/cdrom */
 static ctl_table cdrom_table[] = {
        {
-               .ctl_name       = DEV_CDROM_INFO,
                .procname       = "info",
                .data           = &cdrom_sysctl_settings.info, 
                .maxlen         = CDROM_STR_SIZE,
@@ -3474,7 +3553,6 @@ static ctl_table cdrom_table[] = {
                .proc_handler   = &cdrom_sysctl_info,
        },
        {
-               .ctl_name       = DEV_CDROM_AUTOCLOSE,
                .procname       = "autoclose",
                .data           = &cdrom_sysctl_settings.autoclose,
                .maxlen         = sizeof(int),
@@ -3482,7 +3560,6 @@ static ctl_table cdrom_table[] = {
                .proc_handler   = &cdrom_sysctl_handler,
        },
        {
-               .ctl_name       = DEV_CDROM_AUTOEJECT,
                .procname       = "autoeject",
                .data           = &cdrom_sysctl_settings.autoeject,
                .maxlen         = sizeof(int),
@@ -3490,7 +3567,6 @@ static ctl_table cdrom_table[] = {
                .proc_handler   = &cdrom_sysctl_handler,
        },
        {
-               .ctl_name       = DEV_CDROM_DEBUG,
                .procname       = "debug",
                .data           = &cdrom_sysctl_settings.debug,
                .maxlen         = sizeof(int),
@@ -3498,7 +3574,6 @@ static ctl_table cdrom_table[] = {
                .proc_handler   = &cdrom_sysctl_handler,
        },
        {
-               .ctl_name       = DEV_CDROM_LOCK,
                .procname       = "lock",
                .data           = &cdrom_sysctl_settings.lock,
                .maxlen         = sizeof(int),
@@ -3506,7 +3581,6 @@ static ctl_table cdrom_table[] = {
                .proc_handler   = &cdrom_sysctl_handler,
        },
        {
-               .ctl_name       = DEV_CDROM_CHECK_MEDIA,
                .procname       = "check_media",
                .data           = &cdrom_sysctl_settings.check,
                .maxlen         = sizeof(int),
@@ -3547,9 +3621,7 @@ static void cdrom_sysctl_register(void)
        if (initialized == 1)
                return;
 
-       cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
-       if (cdrom_root_table->ctl_name && cdrom_root_table->child->de)
-               cdrom_root_table->child->de->owner = THIS_MODULE;
+       cdrom_sysctl_header = register_sysctl_table(cdrom_root_table);
 
        /* set the defaults */
        cdrom_sysctl_settings.autoclose = autoclose;
@@ -3567,22 +3639,29 @@ static void cdrom_sysctl_unregister(void)
                unregister_sysctl_table(cdrom_sysctl_header);
 }
 
+#else /* CONFIG_SYSCTL */
+
+static void cdrom_sysctl_register(void)
+{
+}
+
+static void cdrom_sysctl_unregister(void)
+{
+}
+
 #endif /* CONFIG_SYSCTL */
 
 static int __init cdrom_init(void)
 {
-#ifdef CONFIG_SYSCTL
        cdrom_sysctl_register();
-#endif
+
        return 0;
 }
 
 static void __exit cdrom_exit(void)
 {
        printk(KERN_INFO "Uniform CD-ROM driver unloaded\n");
-#ifdef CONFIG_SYSCTL
        cdrom_sysctl_unregister();
-#endif
 }
 
 module_init(cdrom_init);