]> xenbits.xensource.com Git - xenclient/kernel.git/commitdiff
megaraid_sas 00.00.03.21 mptlinux-4.00.38.02
authort_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:00 +0000 (12:06 +0000)
committert_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:00 +0000 (12:06 +0000)
Taken from CA-23199

drivers/scsi/megaraid/megaraid_sas.c
drivers/scsi/megaraid/megaraid_sas.h

index 873835740d29abcb585b8de31ee93d1ed93fc3f6..5d962779326e9a70a90e58a4b95bd9adb8c4928f 100644 (file)
@@ -2,7 +2,7 @@
  *
  *             Linux MegaRAID driver for SAS based RAID controllers
  *
- * Copyright (c) 2003-2005  LSI Corporation.
+ * Copyright (c) 2003-2005  LSI Logic Corporation.
  *
  *        This program is free software; you can redistribute it and/or
  *        modify it under the terms of the GNU General Public License
@@ -10,7 +10,7 @@
  *        2 of the License, or (at your option) any later version.
  *
  * FILE                : megaraid_sas.c
- * Version     : v00.00.03.15-RH1
+ * Version     : v00.00.03.21
  *
  * Authors:
  *     (email-id : megaraidlinux@lsi.com)
 #include "megaraid_sas.h"
 
 /*
- * Module parameters
+ * Modules parameters
  */
 
 /*
- * poll_mode_io:1- schedule command completion from q cmd
+ * Fast driver load option, skip scanning for physical devices during load.
+ * This would result in physical devices being skipped during driver load
+ * time. These can be later added though, using /proc/scsi/scsi
+ */
+static unsigned int fast_load = 0;
+module_param_named(fast_load, fast_load, int, 0);
+MODULE_PARM_DESC(fast_load,
+       "megasas: Faster loading of the driver, skips physical devices! \
+        (default=0)");
+
+/*
+ * Number of sectors per IO command
+ * Will be set in megasas_init_mfi if user does not provide
+ */
+static unsigned int max_sectors = 0;
+module_param_named(max_sectors, max_sectors, int, 0);
+MODULE_PARM_DESC(max_sectors,
+       "Maximum number of sectors per IO command");
+
+/*
+ * Number of cmds per logical unit
+ */
+static unsigned int cmd_per_lun = MEGASAS_DEFAULT_CMD_PER_LUN;
+module_param_named(cmd_per_lun, cmd_per_lun, int, 0);
+MODULE_PARM_DESC(cmd_per_lun,
+       "Maximum number of commands per logical unit (default=128)");
+
+/*
+ * poll_mode_io:1- schedule complete completion from q cmd
  */
 static unsigned int poll_mode_io;
 module_param_named(poll_mode_io, poll_mode_io, int, 0);
@@ -61,7 +89,7 @@ MODULE_PARM_DESC(poll_mode_io,
 MODULE_LICENSE("GPL");
 MODULE_VERSION(MEGASAS_VERSION);
 MODULE_AUTHOR("megaraidlinux@lsi.com");
-MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
+MODULE_DESCRIPTION("LSI Logic MegaRAID SAS Driver");
 
 /*
  * PCI ID table for all supported controllers
@@ -71,6 +99,7 @@ static struct pci_device_id megasas_pci_table[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064R)},
        /* xscale IOP */
        {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)},
+       {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
        /* ppc IOP */
        {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
        /* xscale IOP, vega */
@@ -198,6 +227,9 @@ megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
         */
        writel(status, &regs->outbound_intr_status);
 
+       /* Dummy readl to force pci flush */
+       readl(&regs->outbound_intr_status);
+       
        return 0;
 }
 
@@ -249,7 +281,7 @@ megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
 }
 
 /**
- * megasas_disable_intr_ppc -  Disable interrupt
+ * megasas_disable_intr_ppc -  Disables interrupt
  * @regs:                      MFI register set
  */
 static inline void
@@ -293,6 +325,9 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
         */
        writel(status, &regs->outbound_doorbell_clear);
 
+       /* Dummy readl to force pci flush */
+       readl(&regs->outbound_doorbell_clear);
+
        return 0;
 }
 /**
@@ -531,11 +566,12 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
  /**
  * megasas_get_frame_count - Computes the number of frames
  * @sge_count          : number of sg elements
+ * @frame_type         : type of frame- io or pthru frame
  *
  * Returns the number of frames required for numnber of sge's (sge_count)
  */
 
-static u32 megasas_get_frame_count(u8 sge_count)
+static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type)
 {
        int num_cnt;
        int sge_bytes;
@@ -546,13 +582,22 @@ static u32 megasas_get_frame_count(u8 sge_count)
            sizeof(struct megasas_sge32);
 
        /*
-       * Main frame can contain 2 SGEs for 64-bit SGLs and
-       * 3 SGEs for 32-bit SGLs
-       */
-       if (IS_DMA64)
-               num_cnt = sge_count - 2;
-       else
-               num_cnt = sge_count - 3;
+        * Main frame can contain 2 SGEs for 64-bit SGLs and
+        * 3 SGEs for 32-bit SGLs for ldio &
+        * 1 SGEs for 64-bit SGLs and
+        * 2 SGEs for 32-bit SGLs for pthru frame
+        */
+       if (unlikely(frame_type == PTHRU_FRAME)) {
+               if (IS_DMA64)
+                       num_cnt = sge_count - 1;
+               else
+                       num_cnt = sge_count - 2;
+       } else {
+               if (IS_DMA64)
+                       num_cnt = sge_count - 2;
+               else
+                       num_cnt = sge_count - 3;
+       }
 
        if(num_cnt>0){
                sge_bytes = sge_sz * num_cnt;
@@ -634,7 +679,8 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
         * Compute the total number of frames this command consumes. FW uses
         * this number to pull sufficient number of frames from host memory.
         */
-       cmd->frame_count = megasas_get_frame_count(pthru->sge_count);
+       cmd->frame_count = megasas_get_frame_count(pthru->sge_count,
+                                                       PTHRU_FRAME);
 
        return cmd->frame_count;
 }
@@ -751,7 +797,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
         * Compute the total number of frames this command consumes. FW uses
         * this number to pull sufficient number of frames from host memory.
         */
-       cmd->frame_count = megasas_get_frame_count(ldio->sge_count);
+       cmd->frame_count = megasas_get_frame_count(ldio->sge_count, IO_FRAME);
 
        return cmd->frame_count;
 }
@@ -881,8 +927,6 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
                 */
                scmd->result = DID_OK << 16;
                goto out_done;
-       default:
-               break;
        }
 
        cmd = megasas_get_cmd(instance);
@@ -957,8 +1001,7 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
        u32 consumer;
        u32 context;
        struct megasas_cmd *cmd;
-       struct megasas_instance *instance =
-                       (struct megasas_instance *)instance_addr;
+       struct megasas_instance *instance = (struct megasas_instance *)instance_addr;
        unsigned long flags;
 
        /* If we have already declared adapter dead, donot complete cmds */
@@ -986,22 +1029,6 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
        *instance->consumer = producer;
 
        spin_unlock_irqrestore(&instance->completion_lock, flags);
-
-       /*
-        * Check if we can restore can_queue
-        */
-       if (instance->flag & MEGASAS_FW_BUSY
-               && time_after(jiffies, instance->last_time + 5 * HZ)
-               && atomic_read(&instance->fw_outstanding) < 17) {
-
-               spin_lock_irqsave(instance->host->host_lock, flags);
-               instance->flag &= ~MEGASAS_FW_BUSY;
-               instance->host->can_queue =
-                               instance->max_fw_cmds - MEGASAS_INT_CMDS;
-
-               spin_unlock_irqrestore(instance->host->host_lock, flags);
-       }
-
 }
 
 /**
@@ -1028,7 +1055,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
                        printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
                               "commands to complete\n",i,outstanding);
                        /*
-                        * Call cmd completion routine. Cmd to be
+                        * Call cmd completion routine. Cmd to be 
                         * be completed directly without depending on isr.
                         */
                        megasas_complete_cmd_dpc((unsigned long)instance);
@@ -1085,7 +1112,7 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
        return ret_val;
 }
 
-/**
+ /**
  * megasas_reset_timer - quiesce the adapter if required
  * @scmd:              scsi cmnd
  *
@@ -1218,20 +1245,54 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
        megasas_return_cmd(instance, cmd);
 }
 
+static struct megasas_instance *megasas_lookup_instance(u16 host_no)
+{
+       int i;
+
+       for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+
+               if ((megasas_mgmt_info.instance[i]) &&
+                   (megasas_mgmt_info.instance[i]->host->host_no == host_no))
+                       return megasas_mgmt_info.instance[i];
+       }
+
+       return NULL;
+}
+
+static int megasas_slave_alloc(struct scsi_device *sdev) {
+       struct megasas_instance *instance ;
+       int tmp_fastload = fast_load;
+       instance = megasas_lookup_instance(sdev->host->host_no);
+
+       if (tmp_fastload && sdev->channel < MEGASAS_MAX_PD_CHANNELS) {
+               if ((sdev->id == MEGASAS_MAX_DEV_PER_CHANNEL -1) &&
+                       (sdev->channel == MEGASAS_MAX_PD_CHANNELS - 1)) {
+                       /* If fast load option was set and scan for last device is
+                        * over, reset the fast_load flag so that during a possible
+                        * next scan, devices can be made available
+                        */
+                       fast_load = 0;
+               }
+               return -ENXIO;
+       }
+
+       return 0;
+}
+
 /*
  * Scsi host template for megaraid_sas driver
  */
 static struct scsi_host_template megasas_template = {
 
        .module = THIS_MODULE,
-       .name = "LSI SAS based MegaRAID driver",
+       .name = "LSI Logic SAS based MegaRAID driver",
        .proc_name = "megaraid_sas",
        .slave_configure = megasas_slave_configure,
+       .slave_alloc = megasas_slave_alloc,
        .queuecommand = megasas_queue_command,
        .eh_device_reset_handler = megasas_reset_device,
        .eh_bus_reset_handler = megasas_reset_bus_host,
        .eh_host_reset_handler = megasas_reset_bus_host,
-       .proc_info = (void *) RH_EXTENDED_MAGIC,
        .eh_timed_out = megasas_reset_timer,
        .bios_param = megasas_bios_param,
        .use_clustering = ENABLE_CLUSTERING,
@@ -1335,6 +1396,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
 {
        int exception = 0;
        struct megasas_header *hdr = &cmd->frame->hdr;
+       unsigned long flags;
 
        if (cmd->scmd)
                cmd->scmd->SCp.ptr = NULL;
@@ -1447,6 +1509,22 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
                       hdr->cmd);
                break;
        }
+       
+       /*
+        * Check if we can restore can_queue
+        */
+       if (instance->flag & MEGASAS_FW_BUSY
+               && time_after(jiffies, instance->last_time + 5 * HZ)
+               && atomic_read(&instance->fw_outstanding) < 17) {
+
+               spin_lock_irqsave(instance->host->host_lock, flags);
+               instance->flag &= ~MEGASAS_FW_BUSY;
+               instance->host->can_queue =
+                               instance->max_fw_cmds - MEGASAS_INT_CMDS;
+
+               spin_unlock_irqrestore(instance->host->host_lock, flags);
+       }
+       
 }
 
 /**
@@ -1479,7 +1557,7 @@ out_done:
 /**
  * megasas_isr - isr entry point
  */
-static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs)
+static irqreturn_t megasas_isr(int irq, void *devp)
 {
        return megasas_deplete_reply_queue((struct megasas_instance *)devp,
                                           DID_OK);
@@ -1952,7 +2030,7 @@ megasas_issue_init_mfi(struct megasas_instance *instance)
        memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
        memset(initq_info, 0, sizeof(struct megasas_init_queue_info));
        init_frame->context = context;
-
+       
        initq_info->reply_queue_entries = instance->max_fw_cmds + 1;
        initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h;
 
@@ -1966,16 +2044,16 @@ megasas_issue_init_mfi(struct megasas_instance *instance)
        init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
 
        /*
-        * disable the intr before firing the init frame to FW
-        */
+        * disable the intr before firing the init frame to FW 
+        */     
        instance->instancet->disable_intr(instance->reg_set);
-
+       
        /*
         * Issue the init frame in polled mode
         */
 
        if (megasas_issue_polled(instance, cmd)) {
-               printk(KERN_ERR "megasas: Failed to init firmware\n");
+               printk(KERN_DEBUG "megasas: Failed to init firmware\n");
                megasas_return_cmd(instance, cmd);
                goto fail_fw_init;
        }
@@ -1984,8 +2062,8 @@ megasas_issue_init_mfi(struct megasas_instance *instance)
 
        return 0;
 
-fail_fw_init:
-       return -EINVAL;
+       fail_fw_init:
+               return -EINVAL;
 }
 
 /**
@@ -2006,19 +2084,19 @@ megasas_start_timer(struct megasas_instance *instance,
        timer->data = (unsigned long)instance;
        timer->function = fn;
        add_timer(timer);
-}
+ }
 
 /**
  * megasas_io_completion_timer - Timer fn
  * @instance_addr:     Address of adapter soft state
  *
- * Schedules tasklet for cmd completion
+ * Schedules tasklet for cmd completion 
  * if poll_mode_io is set
  */
 static void
 megasas_io_completion_timer(unsigned long instance_addr)
 {
-       struct megasas_instance *instance =
+       struct megasas_instance *instance = 
                        (struct megasas_instance *)instance_addr;
 
        if (atomic_read(&instance->fw_outstanding))
@@ -2052,7 +2130,7 @@ static int megasas_init_mfi(struct megasas_instance *instance)
         */
        instance->base_addr = pci_resource_start(instance->pdev, 0);
 
-       if (pci_request_regions(instance->pdev, "megasas: LSI")) {
+       if (pci_request_regions(instance->pdev, "megasas: LSI Logic")) {
                printk(KERN_DEBUG "megasas: IO memory region busy!\n");
                return -EBUSY;
        }
@@ -2069,6 +2147,7 @@ static int megasas_init_mfi(struct megasas_instance *instance)
        switch(instance->pdev->device)
        {
                case PCI_DEVICE_ID_LSI_SAS1078R:        
+               case PCI_DEVICE_ID_LSI_SAS1078DE:       
                        instance->instancet = &megasas_instance_template_ppc;
                        break;
                case PCI_DEVICE_ID_LSI_SAS1064R:
@@ -2122,7 +2201,7 @@ static int megasas_init_mfi(struct megasas_instance *instance)
                printk(KERN_DEBUG "megasas: Out of DMA mem for reply queue\n");
                goto fail_reply_queue;
        }
-
+       
        if (megasas_issue_init_mfi(instance))
                goto fail_fw_init;
 
@@ -2147,17 +2226,17 @@ static int megasas_init_mfi(struct megasas_instance *instance)
                tmp_sectors = (max_sectors_1 < max_sectors_2)
                    ? max_sectors_1 : max_sectors_2;
        }
-
        instance->max_sectors_per_req = instance->max_num_sge *
-                                               PAGE_SIZE / 512;
+                   PAGE_SIZE / 512;
        if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
                instance->max_sectors_per_req = tmp_sectors;
 
        kfree(ctrl_info);
 
         /*
-        * Setup tasklet for cmd completion
-        */
+       * Setup tasklet for cmd completion
+       */
 
        tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
                         (unsigned long)instance);
@@ -2413,6 +2492,30 @@ static int megasas_start_aen(struct megasas_instance *instance)
                                    class_locale.word);
 }
 
+static ssize_t
+sysfs_max_sectors_read(struct kobject *kobj, char *buf,
+                       loff_t off, size_t count)
+{
+       struct Scsi_Host *host = class_to_shost(container_of(kobj,
+                                       struct class_device, kobj));
+       struct megasas_instance *instance = 
+                               (struct megasas_instance *)host->hostdata;
+
+       count = sprintf(buf,"%u\n", instance->max_sectors_per_req);
+
+       return count+1;
+}
+
+static struct bin_attribute sysfs_max_sectors_attr = {
+       .attr = {
+               .name = "max_sectors",
+               .mode = S_IRUSR|S_IRGRP|S_IROTH,
+               .owner = THIS_MODULE,
+       },
+       .size = 7,
+       .read = sysfs_max_sectors_read,
+};
+
 /**
  * megasas_io_attach - Attaches this driver to SCSI mid-layer
  * @instance:          Adapter soft state
@@ -2420,6 +2523,7 @@ static int megasas_start_aen(struct megasas_instance *instance)
 static int megasas_io_attach(struct megasas_instance *instance)
 {
        struct Scsi_Host *host = instance->host;
+       int error;
 
        /*
         * Export parameters required by SCSI mid-layer
@@ -2429,8 +2533,35 @@ static int megasas_io_attach(struct megasas_instance *instance)
        host->can_queue = instance->max_fw_cmds - MEGASAS_INT_CMDS;
        host->this_id = instance->init_id;
        host->sg_tablesize = instance->max_num_sge;
+
+       /*
+        * Check if the module parameter value for max_sectors can be used
+        */
+       if (max_sectors && max_sectors < instance->max_sectors_per_req)
+               instance->max_sectors_per_req = max_sectors;
+       else {
+               if (max_sectors)
+                       printk(KERN_INFO "megasas: max_sectors should be > 0 and"
+                               "<= %d\n",instance->max_sectors_per_req);
+       }
+
        host->max_sectors = instance->max_sectors_per_req;
-       host->cmd_per_lun = MEGASAS_DEFAULT_CMD_PER_LUN;
+
+       /*
+        * Check if the module parameter value for cmd_per_lun can be used
+        */
+       instance->cmd_per_lun = MEGASAS_DEFAULT_CMD_PER_LUN;
+       if (cmd_per_lun && cmd_per_lun <= MEGASAS_DEFAULT_CMD_PER_LUN)
+               instance->cmd_per_lun = cmd_per_lun;
+       else
+               printk(KERN_INFO "megasas: cmd_per_lun should be > 0 and"
+                               "<= %d\n",MEGASAS_DEFAULT_CMD_PER_LUN);
+               
+       host->cmd_per_lun = instance->cmd_per_lun;
+
+       printk(KERN_DEBUG "megasas: max_sectors : 0x%x, cmd_per_lun : 0x%x\n",
+                       instance->max_sectors_per_req, instance->cmd_per_lun);
+
        host->max_channel = MEGASAS_MAX_CHANNELS - 1;
        host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
        host->max_lun = MEGASAS_MAX_LUN;
@@ -2444,11 +2575,26 @@ static int megasas_io_attach(struct megasas_instance *instance)
                return -ENODEV;
        }
 
+       /*
+        * Create sysfs entries for module paramaters
+        */
+       error = sysfs_create_bin_file(&instance->host->shost_classdev.kobj,
+                       &sysfs_max_sectors_attr);
+       if (error) {
+               printk(KERN_INFO "megasas: Error in creating the sysfs entry"
+                               " max_sectors.\n");
+               goto out_remove_host;
+       }
+
        /*
         * Trigger SCSI to scan our drives
         */
        scsi_scan_host(host);
        return 0;
+
+out_remove_host:
+       scsi_remove_host(host);
+       return error;
 }
 
 static int
@@ -2728,7 +2874,7 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
 /**
  * megasas_suspend -   driver suspend entry point
  * @pdev:              PCI device structure
- * @state:             state
+ * @state:                             
  */
 static int __devinit
 megasas_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -2746,10 +2892,12 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
        megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
        tasklet_kill(&instance->isr_tasklet);
 
-       pci_set_drvdata(instance->pdev, instance);
+       pci_set_drvdata(instance->pdev, instance); 
        instance->instancet->disable_intr(instance->reg_set);
        free_irq(instance->pdev->irq, instance);
 
+       scsi_host_put(host);
+
        pci_save_state(pdev);
        pci_disable_device(pdev);
 
@@ -2768,7 +2916,7 @@ megasas_resume(struct pci_dev *pdev)
        int rval;
        struct Scsi_Host *host;
        struct megasas_instance *instance;
-
+       
        instance = pci_get_drvdata(pdev);
        host = instance->host;
        pci_set_power_state(pdev, PCI_D0);
@@ -2797,7 +2945,7 @@ megasas_resume(struct pci_dev *pdev)
        *instance->producer = 0;
        *instance->consumer = 0;
 
-       atomic_set(&instance->fw_outstanding, 0);
+       atomic_set(&instance->fw_outstanding,0);
 
        /*
         * We expect the FW state to be READY
@@ -2809,18 +2957,23 @@ megasas_resume(struct pci_dev *pdev)
                goto fail_init_mfi;
 
        tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
-               (unsigned long)instance);
+                        (unsigned long)instance);      
        /*
         * Register IRQ
         */
        if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED,
-               "megasas", instance)) {
+               "megasas",instance)) {
                printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
                goto fail_irq;
        }
 
        instance->instancet->enable_intr(instance->reg_set);
 
+       /*
+        * Store instance in PCI softstate
+        */
+       pci_set_drvdata(pdev, instance);
+
        /*
         * Initiate AEN (Asynchronous Event Notification)
         */
@@ -2832,11 +2985,11 @@ megasas_resume(struct pci_dev *pdev)
                megasas_start_timer(instance, &instance->io_completion_timer,
                                megasas_io_completion_timer,
                                MEGASAS_COMPLETION_TIMER_INTERVAL);
-
-       return 0;
-
-fail_irq:
-fail_init_mfi:
+       
+       return 0;       
+       
+      fail_irq:
+      fail_init_mfi:
 
        if (instance->evt_detail)
                pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
@@ -2850,8 +3003,8 @@ fail_init_mfi:
                pci_free_consistent(pdev, sizeof(u32), instance->consumer,
                                    instance->consumer_h);
        scsi_host_put(host);
-fail_set_dma_mask:
-fail_ready_state:
+      fail_set_dma_mask:
+      fail_ready_state:
        pci_disable_device(pdev);
 
        return -ENODEV;
@@ -2873,6 +3026,7 @@ static void megasas_detach_one(struct pci_dev *pdev)
        if (poll_mode_io)
                del_timer_sync(&instance->io_completion_timer);
 
+       sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_max_sectors_attr);
        scsi_remove_host(instance->host);
        megasas_flush_cache(instance);
        megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
@@ -2925,6 +3079,7 @@ static void megasas_shutdown(struct pci_dev *pdev)
 {
        struct megasas_instance *instance = pci_get_drvdata(pdev);
        megasas_flush_cache(instance);
+       megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
 }
 
 /**
@@ -2997,6 +3152,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
        void *sense = NULL;
        dma_addr_t sense_handle;
        u32 *sense_ptr;
+       unsigned long *sense_buff;
 
        memset(kbuff_arr, 0, sizeof(kbuff_arr));
 
@@ -3101,17 +3257,24 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
         */
        if (ioc->sense_len) {
                /*
-                * sense_ptr points to the location that has the user
+                * sense_buff points to the location that has the user
                 * sense buffer address
                 */
+               sense_buff = (unsigned long *) ((unsigned long)ioc->frame.raw +
+                                       ioc->sense_off);
                sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw +
-                                    ioc->sense_off);
-
+                                       ioc->sense_off);
+#if defined(__ia64__)
+               if (copy_to_user((void __user *)((unsigned long)(*sense_buff)),
+#else
                if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
-                                sense, ioc->sense_len)) {
-                       error = -EFAULT;
-                       goto out;
-               }
+#endif
+                                 sense, ioc->sense_len)) {
+                        printk(KERN_ERR "megasas: Failed to copy out to user"
+                               "sense data\n");
+                        error = -EFAULT;
+                        goto out;
+                }
        }
 
        /*
@@ -3139,20 +3302,6 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
        return error;
 }
 
-static struct megasas_instance *megasas_lookup_instance(u16 host_no)
-{
-       int i;
-
-       for (i = 0; i < megasas_mgmt_info.max_index; i++) {
-
-               if ((megasas_mgmt_info.instance[i]) &&
-                   (megasas_mgmt_info.instance[i]->host->host_no == host_no))
-                       return megasas_mgmt_info.instance[i];
-       }
-
-       return NULL;
-}
-
 static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
 {
        struct megasas_iocpacket __user *user_ioc =
@@ -3343,7 +3492,7 @@ static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
 static ssize_t
 megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf)
 {
-       return sprintf(buf, "%u\n", megasas_dbg_lvl);
+       return sprintf(buf,"%u\n",megasas_dbg_lvl);
 }
 
 static ssize_t
@@ -3363,19 +3512,18 @@ static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl,
 static ssize_t
 megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf)
 {
-       return sprintf(buf, "%u\n", poll_mode_io);
+       return sprintf(buf,"%u\n",poll_mode_io);
 }
 
 static ssize_t
-megasas_sysfs_set_poll_mode_io(struct device_driver *dd, const char *buf,
-                               size_t count)
+megasas_sysfs_set_poll_mode_io(struct device_driver *dd, const char *buf, size_t count)
 {
        int retval = count;
        int tmp = poll_mode_io;
        int i;
        struct megasas_instance *instance;
 
-       if (sscanf(buf, "%u", &poll_mode_io) < 1) {
+       if(sscanf(buf,"%u",&poll_mode_io) < 1){
                printk(KERN_ERR "megasas: could not set poll_mode_io\n");
                retval = -EINVAL;
        }
@@ -3393,13 +3541,13 @@ megasas_sysfs_set_poll_mode_io(struct device_driver *dd, const char *buf,
                for (i = 0; i < megasas_mgmt_info.max_index; i++) {
                        instance = megasas_mgmt_info.instance[i];
                        if (instance) {
-                               megasas_start_timer(instance,
-                                       &instance->io_completion_timer,
+                               megasas_start_timer(instance, &instance->io_completion_timer,
                                        megasas_io_completion_timer,
                                        MEGASAS_COMPLETION_TIMER_INTERVAL);
                        }
                }
-       } else {
+       }
+       else {
                /*
                 * Delete timers for all adapters
                 */
@@ -3414,9 +3562,8 @@ out:
        return retval;
 }
 
-static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO,
-                       megasas_sysfs_show_poll_mode_io,
-                       megasas_sysfs_set_poll_mode_io);
+static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO, megasas_sysfs_show_poll_mode_io,
+                  megasas_sysfs_set_poll_mode_io);
 
 /**
  * megasas_init - Driver load entry point
@@ -3474,6 +3621,7 @@ static int __init megasas_init(void)
                goto err_dcf_poll_mode_io;
 
        return rval;
+
 err_dcf_poll_mode_io:
        driver_remove_file(&megasas_pci_driver.driver,
                           &driver_attr_dbg_lvl);
@@ -3495,13 +3643,12 @@ err_pcidrv:
 static void __exit megasas_exit(void)
 {
        driver_remove_file(&megasas_pci_driver.driver,
-                       &driver_attr_poll_mode_io);
-       driver_remove_file(&megasas_pci_driver.driver,
-                       &driver_attr_dbg_lvl);
+                          &driver_attr_poll_mode_io);
        driver_remove_file(&megasas_pci_driver.driver,
-                       &driver_attr_release_date);
+                          &driver_attr_dbg_lvl);
        driver_remove_file(&megasas_pci_driver.driver,
-                       &driver_attr_version);
+                          &driver_attr_release_date);
+       driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
 
        pci_unregister_driver(&megasas_pci_driver);
        unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
index b26f430e103453faef7c099a7a84b9600339254d..1a89505f86989e11694ff2c896908727b828767e 100644 (file)
@@ -2,7 +2,7 @@
  *
  *             Linux MegaRAID driver for SAS based RAID controllers
  *
- * Copyright (c) 2003-2005  LSI Corporation.
+ * Copyright (c) 2003-2005  LSI Logic Corporation.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION                                "00.00.03.15-RH1"
-#define MEGASAS_RELDATE                                "Nov 21, 2007"
-#define MEGASAS_EXT_VERSION                    "Wed Nov. 21 10:29:45 PST 2007"
+#define MEGASAS_VERSION                                "00.00.03.21"
+#define MEGASAS_RELDATE                                "June 12, 2008"
+#define MEGASAS_EXT_VERSION                    "Thu June 12 09:41:51 PST 2008"
 
 /*
  * Device IDs
  */
 #define        PCI_DEVICE_ID_LSI_SAS1078R              0x0060
+#define        PCI_DEVICE_ID_LSI_SAS1078DE             0x007C
 #define        PCI_DEVICE_ID_LSI_VERDE_ZCR             0x0413
 
 /*
@@ -543,6 +544,10 @@ struct megasas_ctrl_info {
 #define MEGASAS_DBG_LVL                                1
 #define MEGASAS_FW_BUSY                                1
 
+/* Frame Type */
+#define IO_FRAME                               0
+#define PTHRU_FRAME                            1
+
 /*
  * When SCSI mid-layer calls driver's reset routine, driver waits for
  * MEGASAS_RESET_WAIT_TIME seconds for all outstanding IO to complete. Note
@@ -553,7 +558,9 @@ struct megasas_ctrl_info {
 #define MEGASAS_RESET_WAIT_TIME                        180
 #define MEGASAS_INTERNAL_CMD_WAIT_TIME         180
 #define        MEGASAS_RESET_NOTICE_INTERVAL           5
+
 #define MEGASAS_IOCTL_CMD                      0
+
 #define MEGASAS_DEFAULT_CMD_TIMEOUT            90
 
 /*
@@ -573,7 +580,7 @@ struct megasas_ctrl_info {
 
 #define MFI_OB_INTR_STATUS_MASK                        0x00000002
 #define MFI_POLL_TIMEOUT_SECS                  60
-#define MEGASAS_COMPLETION_TIMER_INTERVAL      (HZ/10)
+#define MEGASAS_COMPLETION_TIMER_INTERVAL      (HZ)/10
 
 #define MFI_REPLY_1078_MESSAGE_INTERRUPT       0x80000000
 
@@ -1082,11 +1089,11 @@ struct megasas_instance {
        u16 max_num_sge;
        u16 max_fw_cmds;
        u32 max_sectors_per_req;
+       u32 cmd_per_lun;
 
        struct megasas_cmd **cmd_list;
        struct list_head cmd_pool;
        spinlock_t cmd_pool_lock;
-       /* used to synch producer, consumer ptrs */
        spinlock_t completion_lock;
        struct dma_pool *frame_dma_pool;
        struct dma_pool *sense_dma_pool;
@@ -1107,13 +1114,13 @@ struct megasas_instance {
 
        atomic_t fw_outstanding;
        u32 hw_crit_error;
-
+       
        struct megasas_instance_template *instancet;
        struct tasklet_struct isr_tasklet;
 
        u8 flag;
        unsigned long last_time;
-
+       
        struct timer_list io_completion_timer;
 };