]> Pileus Git - ~andy/linux/blobdiff - drivers/scsi/aacraid/aachba.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen...
[~andy/linux] / drivers / scsi / aacraid / aachba.c
index bfd0e64964accc6e8317c50338725d4fc8db6ad5..f1504beb2788c5bf6212fb52de25b8d0bc43712e 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/slab.h>
 #include <linux/completion.h>
 #include <linux/blkdev.h>
-#include <asm/semaphore.h>
 #include <asm/uaccess.h>
 #include <linux/highmem.h> /* For flush_kernel_dcache_page */
 
@@ -144,51 +143,77 @@ static char *aac_get_status_string(u32 status);
  */
 
 static int nondasd = -1;
-static int aac_cache = 0;
+static int aac_cache;
 static int dacmode = -1;
-
+int aac_msi;
 int aac_commit = -1;
 int startup_timeout = 180;
 int aif_timeout = 120;
 
 module_param(nondasd, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
+MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices."
+       " 0=off, 1=on");
 module_param_named(cache, aac_cache, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(cache, "Disable Queue Flush commands:\n\tbit 0 - Disable FUA in WRITE SCSI commands\n\tbit 1 - Disable SYNCHRONIZE_CACHE SCSI command\n\tbit 2 - Disable only if Battery not protecting Cache");
+MODULE_PARM_DESC(cache, "Disable Queue Flush commands:\n"
+       "\tbit 0 - Disable FUA in WRITE SCSI commands\n"
+       "\tbit 1 - Disable SYNCHRONIZE_CACHE SCSI command\n"
+       "\tbit 2 - Disable only if Battery not protecting Cache");
 module_param(dacmode, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on");
+MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC."
+       " 0=off, 1=on");
 module_param_named(commit, aac_commit, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");
+MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the"
+       " adapter for foreign arrays.\n"
+       "This is typically needed in systems that do not have a BIOS."
+       " 0=off, 1=on");
+module_param_named(msi, aac_msi, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(msi, "IRQ handling."
+       " 0=PIC(default), 1=MSI, 2=MSI-X(unsupported, uses MSI)");
 module_param(startup_timeout, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for adapter to have it's kernel up and\nrunning. This is typically adjusted for large systems that do not have a BIOS.");
+MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for"
+       " adapter to have it's kernel up and\n"
+       "running. This is typically adjusted for large systems that do not"
+       " have a BIOS.");
 module_param(aif_timeout, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(aif_timeout, "The duration of time in seconds to wait for applications to pick up AIFs before\nderegistering them. This is typically adjusted for heavily burdened systems.");
+MODULE_PARM_DESC(aif_timeout, "The duration of time in seconds to wait for"
+       " applications to pick up AIFs before\n"
+       "deregistering them. This is typically adjusted for heavily burdened"
+       " systems.");
 
 int numacb = -1;
 module_param(numacb, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid values are 512 and down. Default is to use suggestion from Firmware.");
+MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control"
+       " blocks (FIB) allocated. Valid values are 512 and down. Default is"
+       " to use suggestion from Firmware.");
 
 int acbsize = -1;
 module_param(acbsize, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware.");
+MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB)"
+       " size. Valid values are 512, 2048, 4096 and 8192. Default is to use"
+       " suggestion from Firmware.");
 
 int update_interval = 30 * 60;
 module_param(update_interval, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(update_interval, "Interval in seconds between time sync updates issued to adapter.");
+MODULE_PARM_DESC(update_interval, "Interval in seconds between time sync"
+       " updates issued to adapter.");
 
 int check_interval = 24 * 60 * 60;
 module_param(check_interval, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health checks.");
+MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health"
+       " checks.");
 
 int aac_check_reset = 1;
 module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(aac_check_reset, "If adapter fails health check, reset the adapter. a value of -1 forces the reset to adapters programmed to ignore it.");
+MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the"
+       " adapter. a value of -1 forces the reset to adapters programmed to"
+       " ignore it.");
 
 int expose_physicals = -1;
 module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on");
+MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays."
+       " -1=protect 0=off, 1=on");
 
-int aac_reset_devices = 0;
+int aac_reset_devices;
 module_param_named(reset_devices, aac_reset_devices, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(reset_devices, "Force an adapter reset at initialization.");
 
@@ -353,24 +378,6 @@ int aac_get_containers(struct aac_dev *dev)
        return status;
 }
 
-static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
-{
-       void *buf;
-       int transfer_len;
-       struct scatterlist *sg = scsi_sglist(scsicmd);
-
-       buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
-       transfer_len = min(sg->length, len + offset);
-
-       transfer_len -= offset;
-       if (buf && transfer_len > 0)
-               memcpy(buf + offset, data, transfer_len);
-
-       flush_kernel_dcache_page(kmap_atomic_to_page(buf - sg->offset));
-       kunmap_atomic(buf - sg->offset, KM_IRQ0);
-
-}
-
 static void get_container_name_callback(void *context, struct fib * fibptr)
 {
        struct aac_get_name_resp * get_name_reply;
@@ -393,14 +400,17 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
                while (*sp == ' ')
                        ++sp;
                if (*sp) {
+                       struct inquiry_data inq;
                        char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];
                        int count = sizeof(d);
                        char *dp = d;
                        do {
                                *dp++ = (*sp) ? *sp++ : ' ';
                        } while (--count > 0);
-                       aac_internal_transfer(scsicmd, d,
-                         offsetof(struct inquiry_data, inqd_pid), sizeof(d));
+
+                       scsi_sg_copy_to_buffer(scsicmd, &inq, sizeof(inq));
+                       memcpy(inq.inqd_pid, d, sizeof(d));
+                       scsi_sg_copy_from_buffer(scsicmd, &inq, sizeof(inq));
                }
        }
 
@@ -785,7 +795,7 @@ static void get_container_serial_callback(void *context, struct fib * fibptr)
                sp[2] = 0;
                sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X",
                  le32_to_cpu(get_serial_reply->uid));
-               aac_internal_transfer(scsicmd, sp, 0, sizeof(sp));
+               scsi_sg_copy_from_buffer(scsicmd, sp, sizeof(sp));
        }
 
        scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
@@ -1315,7 +1325,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
                          (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid),
                          dev->supplement_adapter_info.VpdInfo.Tsid);
                }
-               if (!aac_check_reset || ((aac_check_reset != 1) &&
+               if (!aac_check_reset || ((aac_check_reset == 1) &&
                  (dev->supplement_adapter_info.SupportedOptions2 &
                  AAC_OPTION_IGNORE_RESET))) {
                        printk(KERN_INFO "%s%d: Reset Adapter Ignored\n",
@@ -1353,13 +1363,14 @@ int aac_get_adapter_info(struct aac_dev* dev)
 
        if (nondasd != -1)
                dev->nondasd_support = (nondasd!=0);
-       if(dev->nondasd_support != 0) {
+       if (dev->nondasd_support && !dev->in_reset)
                printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id);
-       }
 
        dev->dac_support = 0;
        if( (sizeof(dma_addr_t) > 4) && (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){
-               printk(KERN_INFO "%s%d: 64bit support enabled.\n", dev->name, dev->id);
+               if (!dev->in_reset)
+                       printk(KERN_INFO "%s%d: 64bit support enabled.\n",
+                               dev->name, dev->id);
                dev->dac_support = 1;
        }
 
@@ -1369,8 +1380,9 @@ int aac_get_adapter_info(struct aac_dev* dev)
        if(dev->dac_support != 0) {
                if (!pci_set_dma_mask(dev->pdev, DMA_64BIT_MASK) &&
                        !pci_set_consistent_dma_mask(dev->pdev, DMA_64BIT_MASK)) {
-                       printk(KERN_INFO"%s%d: 64 Bit DAC enabled\n",
-                               dev->name, dev->id);
+                       if (!dev->in_reset)
+                               printk(KERN_INFO"%s%d: 64 Bit DAC enabled\n",
+                                       dev->name, dev->id);
                } else if (!pci_set_dma_mask(dev->pdev, DMA_32BIT_MASK) &&
                        !pci_set_consistent_dma_mask(dev->pdev, DMA_32BIT_MASK)) {
                        printk(KERN_INFO"%s%d: DMA mask set failed, 64 Bit DAC disabled\n",
@@ -1958,8 +1970,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                                arr[4] = 0x0;
                                arr[5] = 0x80;
                                arr[1] = scsicmd->cmnd[2];
-                               aac_internal_transfer(scsicmd, &inq_data, 0,
-                                 sizeof(inq_data));
+                               scsi_sg_copy_from_buffer(scsicmd, &inq_data,
+                                                        sizeof(inq_data));
                                scsicmd->result = DID_OK << 16 |
                                  COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
                        } else if (scsicmd->cmnd[2] == 0x80) {
@@ -1967,8 +1979,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                                arr[3] = setinqserial(dev, &arr[4],
                                  scmd_id(scsicmd));
                                arr[1] = scsicmd->cmnd[2];
-                               aac_internal_transfer(scsicmd, &inq_data, 0,
-                                 sizeof(inq_data));
+                               scsi_sg_copy_from_buffer(scsicmd, &inq_data,
+                                                        sizeof(inq_data));
                                return aac_get_container_serial(scsicmd);
                        } else {
                                /* vpd page not implemented */
@@ -1999,7 +2011,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                if (cid == host->this_id) {
                        setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types));
                        inq_data.inqd_pdt = INQD_PDT_PROC;      /* Processor device */
-                       aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
+                       scsi_sg_copy_from_buffer(scsicmd, &inq_data,
+                                                sizeof(inq_data));
                        scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
                        scsicmd->scsi_done(scsicmd);
                        return 0;
@@ -2008,7 +2021,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                        return -1;
                setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
                inq_data.inqd_pdt = INQD_PDT_DA;        /* Direct/random access device */
-               aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
+               scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data));
                return aac_get_container_name(scsicmd);
        }
        case SERVICE_ACTION_IN:
@@ -2019,6 +2032,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
        {
                u64 capacity;
                char cp[13];
+               unsigned int alloc_len;
 
                dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n"));
                capacity = fsa_dev_ptr[cid].size - 1;
@@ -2035,18 +2049,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                cp[10] = 2;
                cp[11] = 0;
                cp[12] = 0;
-               aac_internal_transfer(scsicmd, cp, 0,
-                 min_t(size_t, scsicmd->cmnd[13], sizeof(cp)));
-               if (sizeof(cp) < scsicmd->cmnd[13]) {
-                       unsigned int len, offset = sizeof(cp);
 
-                       memset(cp, 0, offset);
-                       do {
-                               len = min_t(size_t, scsicmd->cmnd[13] - offset,
-                                               sizeof(cp));
-                               aac_internal_transfer(scsicmd, cp, offset, len);
-                       } while ((offset += len) < scsicmd->cmnd[13]);
-               }
+               alloc_len = ((scsicmd->cmnd[10] << 24)
+                            + (scsicmd->cmnd[11] << 16)
+                            + (scsicmd->cmnd[12] << 8) + scsicmd->cmnd[13]);
+
+               alloc_len = min_t(size_t, alloc_len, sizeof(cp));
+               scsi_sg_copy_from_buffer(scsicmd, cp, alloc_len);
+               if (alloc_len < scsi_bufflen(scsicmd))
+                       scsi_set_resid(scsicmd,
+                                      scsi_bufflen(scsicmd) - alloc_len);
 
                /* Do not cache partition table for arrays */
                scsicmd->device->removable = 1;
@@ -2076,7 +2088,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                cp[5] = 0;
                cp[6] = 2;
                cp[7] = 0;
-               aac_internal_transfer(scsicmd, cp, 0, sizeof(cp));
+               scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp));
                /* Do not cache partition table for arrays */
                scsicmd->device->removable = 1;
 
@@ -2111,7 +2123,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                        if (mode_buf_length > scsicmd->cmnd[4])
                                mode_buf_length = scsicmd->cmnd[4];
                }
-               aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
+               scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
                scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
                scsicmd->scsi_done(scsicmd);
 
@@ -2146,7 +2158,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                        if (mode_buf_length > scsicmd->cmnd[8])
                                mode_buf_length = scsicmd->cmnd[8];
                }
-               aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
+               scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
 
                scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
                scsicmd->scsi_done(scsicmd);