vserver 1.9.5.x5
[linux-2.6.git] / drivers / s390 / scsi / zfcp_aux.c
index 8841457..007f915 100644 (file)
@@ -12,6 +12,7 @@
  *            Wolfgang Taphorn
  *            Stefan Bader <stefan.bader@de.ibm.com>
  *            Heiko Carstens <heiko.carstens@de.ibm.com>
+ *            Andreas Herrmann <aherrman@de.ibm.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,8 +29,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_AUX_REVISION "$Revision: 1.129 $"
+#define ZFCP_AUX_REVISION "$Revision: 1.145 $"
 
 #include "zfcp_ext.h"
 
@@ -45,7 +45,6 @@ static int __init  zfcp_module_init(void);
 static void zfcp_ns_gid_pn_handler(unsigned long);
 
 /* miscellaneous */
-
 static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
 static inline void zfcp_sg_list_free(struct zfcp_sg_list *);
 static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
@@ -60,7 +59,7 @@ static int zfcp_cfdc_dev_ioctl(struct inode *, struct file *,
 #define ZFCP_CFDC_IOC \
        _IOWR(ZFCP_CFDC_IOC_MAGIC, 0, struct zfcp_cfdc_sense_data)
 
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
 static struct ioctl_trans zfcp_ioctl_trans = {ZFCP_CFDC_IOC, (void*) sys_ioctl};
 #endif
 
@@ -80,6 +79,7 @@ static struct miscdevice zfcp_cfdc_misc = {
 module_init(zfcp_module_init);
 
 MODULE_AUTHOR("Heiko Carstens <heiko.carstens@de.ibm.com>, "
+             "Andreas Herrman <aherrman@de.ibm.com>, "
              "Martin Peschke <mpeschke@de.ibm.com>, "
              "Raimund Schroeder <raimund.schroeder@de.ibm.com>, "
              "Wolfgang Taphorn <taphorn@de.ibm.com>, "
@@ -145,7 +145,7 @@ zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req,
        int i;
        unsigned long flags;
 
-       write_lock_irqsave(&adapter->cmd_dbf_lock, flags);
+       spin_lock_irqsave(&adapter->dbf_lock, flags);
        if (zfcp_fsf_req_is_scsi_cmnd(fsf_req)) {
                scsi_cmnd = fsf_req->data.send_fcp_command_task.scsi_cmnd;
                debug_text_event(adapter->cmd_dbf, level, "fsferror");
@@ -164,7 +164,7 @@ zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req,
                                    (char *) add_data + i,
                                    min(ZFCP_CMD_DBF_LENGTH, add_length - i));
        }
-       write_unlock_irqrestore(&adapter->cmd_dbf_lock, flags);
+       spin_unlock_irqrestore(&adapter->dbf_lock, flags);
 }
 
 /* XXX additionally log unit if available */
@@ -181,7 +181,7 @@ zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd)
        adapter = (struct zfcp_adapter *) scsi_cmnd->device->host->hostdata[0];
        req_data = (union zfcp_req_data *) scsi_cmnd->host_scribble;
        fsf_req = (req_data ? req_data->send_fcp_command_task.fsf_req : NULL);
-       write_lock_irqsave(&adapter->cmd_dbf_lock, flags);
+       spin_lock_irqsave(&adapter->dbf_lock, flags);
        debug_text_event(adapter->cmd_dbf, level, "hostbyte");
        debug_text_event(adapter->cmd_dbf, level, text);
        debug_event(adapter->cmd_dbf, level, &scsi_cmnd->result, sizeof (u32));
@@ -198,7 +198,7 @@ zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd)
                debug_text_event(adapter->cmd_dbf, level, "");
                debug_text_event(adapter->cmd_dbf, level, "");
        }
-       write_unlock_irqrestore(&adapter->cmd_dbf_lock, flags);
+       spin_unlock_irqrestore(&adapter->dbf_lock, flags);
 }
 
 void
@@ -278,7 +278,7 @@ zfcp_init_device_configure(void)
                goto out_unit;
        up(&zfcp_data.config_sema);
        ccw_device_set_online(adapter->ccw_device);
-       wait_event(unit->scsi_add_wq, atomic_read(&unit->scsi_add_work) == 0);
+       zfcp_erp_wait(adapter);
        down(&zfcp_data.config_sema);
        zfcp_unit_put(unit);
  out_unit:
@@ -308,14 +308,13 @@ zfcp_module_init(void)
        if (!zfcp_transport_template)
                return -ENODEV;
 
-#ifdef CONFIG_S390_SUPPORT
        retval = register_ioctl32_conversion(zfcp_ioctl_trans.cmd,
                                             zfcp_ioctl_trans.handler);
        if (retval != 0) {
                ZFCP_LOG_INFO("registration of ioctl32 conversion failed\n");
-               goto out_ioctl32;
+               goto out;
        }
-#endif
+
        retval = misc_register(&zfcp_cfdc_misc);
        if (retval != 0) {
                ZFCP_LOG_INFO("registration of misc device "
@@ -350,11 +349,7 @@ zfcp_module_init(void)
  out_ccw_register:
        misc_deregister(&zfcp_cfdc_misc);
  out_misc_register:
-#ifdef CONFIG_S390_SUPPORT
        unregister_ioctl32_conversion(zfcp_ioctl_trans.cmd);
- out_ioctl32:
-#endif
-
  out:
        return retval;
 }
@@ -379,7 +374,7 @@ static int
 zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
                     unsigned int command, unsigned long buffer)
 {
-       struct zfcp_cfdc_sense_data sense_data, __user *sense_data_user;
+       struct zfcp_cfdc_sense_data *sense_data, __user *sense_data_user;
        struct zfcp_adapter *adapter = NULL;
        struct zfcp_fsf_req *fsf_req = NULL;
        struct zfcp_sg_list *sg_list = NULL;
@@ -387,6 +382,12 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
        char *bus_id = NULL;
        int retval = 0;
 
+       sense_data = kmalloc(sizeof(struct zfcp_cfdc_sense_data), GFP_KERNEL);
+       if (sense_data == NULL) {
+               retval = -ENOMEM;
+               goto out;
+       }
+
        sg_list = kmalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL);
        if (sg_list == NULL) {
                retval = -ENOMEM;
@@ -406,21 +407,21 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
                goto out;
        }
 
-       retval = copy_from_user(&sense_data, sense_data_user,
+       retval = copy_from_user(sense_data, sense_data_user,
                                sizeof(struct zfcp_cfdc_sense_data));
        if (retval) {
                retval = -EFAULT;
                goto out;
        }
 
-       if (sense_data.signature != ZFCP_CFDC_SIGNATURE) {
+       if (sense_data->signature != ZFCP_CFDC_SIGNATURE) {
                ZFCP_LOG_INFO("invalid sense data request signature 0x%08x\n",
                              ZFCP_CFDC_SIGNATURE);
                retval = -EINVAL;
                goto out;
        }
 
-       switch (sense_data.command) {
+       switch (sense_data->command) {
 
        case ZFCP_CFDC_CMND_DOWNLOAD_NORMAL:
                fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
@@ -449,7 +450,7 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
 
        default:
                ZFCP_LOG_INFO("invalid command code 0x%08x\n",
-                             sense_data.command);
+                             sense_data->command);
                retval = -EINVAL;
                goto out;
        }
@@ -460,9 +461,9 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
                goto out;
        }
        snprintf(bus_id, BUS_ID_SIZE, "%d.%d.%04x",
-               (sense_data.devno >> 24),
-               (sense_data.devno >> 16) & 0xFF,
-               (sense_data.devno & 0xFFFF));
+               (sense_data->devno >> 24),
+               (sense_data->devno >> 16) & 0xFF,
+               (sense_data->devno & 0xFFFF));
 
        read_lock_irq(&zfcp_data.config_lock);
        adapter = zfcp_get_adapter_by_busid(bus_id);
@@ -478,7 +479,7 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
                goto out;
        }
 
-       if (sense_data.command & ZFCP_CFDC_WITH_CONTROL_FILE) {
+       if (sense_data->command & ZFCP_CFDC_WITH_CONTROL_FILE) {
                retval = zfcp_sg_list_alloc(sg_list,
                                            ZFCP_CFDC_MAX_CONTROL_FILE_SIZE);
                if (retval) {
@@ -487,8 +488,8 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
                }
        }
 
-       if ((sense_data.command & ZFCP_CFDC_DOWNLOAD) &&
-           (sense_data.command & ZFCP_CFDC_WITH_CONTROL_FILE)) {
+       if ((sense_data->command & ZFCP_CFDC_DOWNLOAD) &&
+           (sense_data->command & ZFCP_CFDC_WITH_CONTROL_FILE)) {
                retval = zfcp_sg_list_copy_from_user(
                        sg_list, &sense_data_user->control_file,
                        ZFCP_CFDC_MAX_CONTROL_FILE_SIZE);
@@ -498,19 +499,10 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
                }
        }
 
-       retval = zfcp_fsf_control_file(
-               adapter, &fsf_req, fsf_command, option, sg_list);
-       if (retval == -EOPNOTSUPP) {
-               ZFCP_LOG_INFO("adapter does not support cfdc\n");
-               goto out;
-       } else if (retval != 0) {
-               ZFCP_LOG_INFO("initiation of cfdc up/download failed\n");
-               retval = -EPERM;
+       retval = zfcp_fsf_control_file(adapter, &fsf_req, fsf_command,
+                                      option, sg_list);
+       if (retval)
                goto out;
-       }
-
-       wait_event(fsf_req->completion_wq,
-                  fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
 
        if ((fsf_req->qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
            (fsf_req->qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
@@ -518,20 +510,20 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
                goto out;
        }
 
-       sense_data.fsf_status = fsf_req->qtcb->header.fsf_status;
-       memcpy(&sense_data.fsf_status_qual,
+       sense_data->fsf_status = fsf_req->qtcb->header.fsf_status;
+       memcpy(&sense_data->fsf_status_qual,
               &fsf_req->qtcb->header.fsf_status_qual,
               sizeof(union fsf_status_qual));
-       memcpy(&sense_data.payloads, &fsf_req->qtcb->bottom.support.els, 256);
+       memcpy(&sense_data->payloads, &fsf_req->qtcb->bottom.support.els, 256);
 
-       retval = copy_to_user(sense_data_user, &sense_data,
+       retval = copy_to_user(sense_data_user, sense_data,
                sizeof(struct zfcp_cfdc_sense_data));
        if (retval) {
                retval = -EFAULT;
                goto out;
        }
 
-       if (sense_data.command & ZFCP_CFDC_UPLOAD) {
+       if (sense_data->command & ZFCP_CFDC_UPLOAD) {
                retval = zfcp_sg_list_copy_to_user(
                        &sense_data_user->control_file, sg_list,
                        ZFCP_CFDC_MAX_CONTROL_FILE_SIZE);
@@ -553,6 +545,9 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
                kfree(sg_list);
        }
 
+       if (sense_data != NULL)
+               kfree(sense_data);
+
        return retval;
 }
 
@@ -588,18 +583,19 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
                retval = -ENOMEM;
                goto out;
        }
+       memset(sg_list->sg, sg_list->count * sizeof(struct scatterlist), 0);
 
        for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) {
                sg->length = min(size, PAGE_SIZE);
                sg->offset = 0;
                address = (void *) get_zeroed_page(GFP_KERNEL);
-               zfcp_address_to_sg(address, sg);
-               if (sg->page == NULL) {
+               if (address == NULL) {
                        sg_list->count = i;
                        zfcp_sg_list_free(sg_list);
                        retval = -ENOMEM;
                        goto out;
                }
+               zfcp_address_to_sg(address, sg);
                size -= sg->length;
        }
 
@@ -624,7 +620,7 @@ zfcp_sg_list_free(struct zfcp_sg_list *sg_list)
        BUG_ON(sg_list == NULL);
 
        for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++)
-               __free_pages(sg->page, 0);
+               free_page((unsigned long) zfcp_sg_to_address(sg));
 
        sg_list->count = 0;
        kfree(sg_list->sg);
@@ -865,7 +861,6 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
                return NULL;
        memset(unit, 0, sizeof (struct zfcp_unit));
 
-       init_waitqueue_head(&unit->scsi_add_wq);
        /* initialise reference count stuff */
        atomic_set(&unit->refcount, 0);
        init_waitqueue_head(&unit->remove_wq);
@@ -1039,11 +1034,11 @@ zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
        char dbf_name[20];
 
        /* debug feature area which records SCSI command failures (hostbyte) */
-       rwlock_init(&adapter->cmd_dbf_lock);
+       spin_lock_init(&adapter->dbf_lock);
+
        sprintf(dbf_name, ZFCP_CMD_DBF_NAME "%s",
                zfcp_get_busid_by_adapter(adapter));
-       adapter->cmd_dbf = debug_register(dbf_name,
-                                         ZFCP_CMD_DBF_INDEX,
+       adapter->cmd_dbf = debug_register(dbf_name, ZFCP_CMD_DBF_INDEX,
                                          ZFCP_CMD_DBF_AREAS,
                                          ZFCP_CMD_DBF_LENGTH);
        debug_register_view(adapter->cmd_dbf, &debug_hex_ascii_view);
@@ -1052,40 +1047,38 @@ zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
        /* debug feature area which records SCSI command aborts */
        sprintf(dbf_name, ZFCP_ABORT_DBF_NAME "%s",
                zfcp_get_busid_by_adapter(adapter));
-       adapter->abort_dbf = debug_register(dbf_name,
-                                           ZFCP_ABORT_DBF_INDEX,
+       adapter->abort_dbf = debug_register(dbf_name, ZFCP_ABORT_DBF_INDEX,
                                            ZFCP_ABORT_DBF_AREAS,
                                            ZFCP_ABORT_DBF_LENGTH);
        debug_register_view(adapter->abort_dbf, &debug_hex_ascii_view);
        debug_set_level(adapter->abort_dbf, ZFCP_ABORT_DBF_LEVEL);
 
-       /* debug feature area which records SCSI command aborts */
+       /* debug feature area which records incoming ELS commands */
        sprintf(dbf_name, ZFCP_IN_ELS_DBF_NAME "%s",
                zfcp_get_busid_by_adapter(adapter));
-       adapter->in_els_dbf = debug_register(dbf_name,
-                                            ZFCP_IN_ELS_DBF_INDEX,
+       adapter->in_els_dbf = debug_register(dbf_name, ZFCP_IN_ELS_DBF_INDEX,
                                             ZFCP_IN_ELS_DBF_AREAS,
                                             ZFCP_IN_ELS_DBF_LENGTH);
        debug_register_view(adapter->in_els_dbf, &debug_hex_ascii_view);
        debug_set_level(adapter->in_els_dbf, ZFCP_IN_ELS_DBF_LEVEL);
 
-
        /* debug feature area which records erp events */
        sprintf(dbf_name, ZFCP_ERP_DBF_NAME "%s",
                zfcp_get_busid_by_adapter(adapter));
-       adapter->erp_dbf = debug_register(dbf_name,
-                                         ZFCP_ERP_DBF_INDEX,
+       adapter->erp_dbf = debug_register(dbf_name, ZFCP_ERP_DBF_INDEX,
                                          ZFCP_ERP_DBF_AREAS,
                                          ZFCP_ERP_DBF_LENGTH);
        debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
        debug_set_level(adapter->erp_dbf, ZFCP_ERP_DBF_LEVEL);
 
-       if (adapter->cmd_dbf && adapter->abort_dbf &&
-           adapter->in_els_dbf && adapter->erp_dbf)
-               return 0;
+       if (!(adapter->cmd_dbf && adapter->abort_dbf &&
+             adapter->in_els_dbf && adapter->erp_dbf)) {
+               zfcp_adapter_debug_unregister(adapter);
+               return -ENOMEM;
+       }
+
+       return 0;
 
-       zfcp_adapter_debug_unregister(adapter);
-       return -ENOMEM;
 }
 
 /**
@@ -1095,10 +1088,14 @@ zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
 void
 zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
 {
-       debug_unregister(adapter->erp_dbf);
-       debug_unregister(adapter->cmd_dbf);
-       debug_unregister(adapter->abort_dbf);
-       debug_unregister(adapter->in_els_dbf);
+       debug_unregister(adapter->abort_dbf);
+       debug_unregister(adapter->cmd_dbf);
+       debug_unregister(adapter->erp_dbf);
+       debug_unregister(adapter->in_els_dbf);
+       adapter->abort_dbf = NULL;
+       adapter->cmd_dbf = NULL;
+       adapter->erp_dbf = NULL;
+       adapter->in_els_dbf = NULL;
 }
 
 void
@@ -1651,7 +1648,6 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req)
                zfcp_fsf_incoming_els_rscn(adapter, status_buffer);
        else
                zfcp_fsf_incoming_els_unknown(adapter, status_buffer);
-
 }