]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - drivers/scsi/hpsa.h
Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
[mirror_ubuntu-zesty-kernel.git] / drivers / scsi / hpsa.h
index e7d7eaa864d16c4b9c5eae87382babb65effcc54..6577130503490d950c6700251cc3115034f2f80f 100644 (file)
@@ -46,6 +46,11 @@ struct hpsa_scsi_dev_t {
        unsigned char model[16];        /* bytes 16-31 of inquiry data */
        unsigned char raid_level;       /* from inquiry page 0xC1 */
        unsigned char volume_offline;   /* discovered via TUR or VPD */
+       u16 queue_depth;                /* max queue_depth for this device */
+       atomic_t ioaccel_cmds_out;      /* Only used for physical devices
+                                        * counts commands sent to physical
+                                        * device via "ioaccel" path.
+                                        */
        u32 ioaccel_handle;
        int offload_config;             /* I/O accel RAID offload configured */
        int offload_enabled;            /* I/O accel RAID offload enabled */
@@ -54,6 +59,15 @@ struct hpsa_scsi_dev_t {
                                         */
        struct raid_map_data raid_map;  /* I/O accelerator RAID map */
 
+       /*
+        * Pointers from logical drive map indices to the phys drives that
+        * make those logical drives.  Note, multiple logical drives may
+        * share physical drives.  You can have for instance 5 physical
+        * drives with 3 logical drives each using those same 5 physical
+        * disks. We need these pointers for counting i/o's out to physical
+        * devices in order to honor physical device queue depth limits.
+        */
+       struct hpsa_scsi_dev_t *phys_disk[RAID_MAP_MAX_ENTRIES];
 };
 
 struct reply_queue_buffer {
@@ -119,6 +133,7 @@ struct ctlr_info {
        struct CfgTable __iomem *cfgtable;
        int     interrupts_enabled;
        int     max_commands;
+       int last_allocation;
        atomic_t commands_outstanding;
 #      define PERF_MODE_INT    0
 #      define DOORBELL_INT     1
@@ -168,8 +183,7 @@ struct ctlr_info {
 
        /* cap concurrent passthrus at some reasonable maximum */
 #define HPSA_MAX_CONCURRENT_PASSTHRUS (10)
-       spinlock_t passthru_count_lock; /* protects passthru_count */
-       int passthru_count;
+       atomic_t passthru_cmds_avail;
 
        /*
         * Performant mode completion buffers
@@ -193,6 +207,7 @@ struct ctlr_info {
        atomic_t firmware_flash_in_progress;
        u32 __percpu *lockup_detected;
        struct delayed_work monitor_ctlr_work;
+       struct delayed_work rescan_ctlr_work;
        int remove_in_progress;
        /* Address of h->q[x] is passed to intr handler to know which queue */
        u8 q[MAX_REPLY_QUEUES];
@@ -235,8 +250,9 @@ struct ctlr_info {
        spinlock_t offline_device_lock;
        struct list_head offline_device_list;
        int     acciopath_status;
-       int     drv_req_rescan; /* flag for driver to request rescan event */
        int     raid_offload_debug;
+       struct workqueue_struct *resubmit_wq;
+       struct workqueue_struct *rescan_ctlr_wq;
 };
 
 struct offline_device_entry {
@@ -295,6 +311,8 @@ struct offline_device_entry {
  */
 #define SA5_DOORBELL   0x20
 #define SA5_REQUEST_PORT_OFFSET        0x40
+#define SA5_REQUEST_PORT64_LO_OFFSET 0xC0
+#define SA5_REQUEST_PORT64_HI_OFFSET 0xC4
 #define SA5_REPLY_INTR_MASK_OFFSET     0x34
 #define SA5_REPLY_PORT_OFFSET          0x44
 #define SA5_INTR_STATUS                0x30
@@ -351,10 +369,7 @@ static void SA5_submit_command_no_read(struct ctlr_info *h,
 static void SA5_submit_command_ioaccel2(struct ctlr_info *h,
        struct CommandList *c)
 {
-       if (c->cmd_type == CMD_IOACCEL2)
-               writel(c->busaddr, h->vaddr + IOACCEL2_INBOUND_POSTQ_32);
-       else
-               writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
+       writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
 }
 
 /*
@@ -396,19 +411,19 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
        unsigned long register_value = FIFO_EMPTY;
 
        /* msi auto clears the interrupt pending bit. */
-       if (!(h->msi_vector || h->msix_vector)) {
+       if (unlikely(!(h->msi_vector || h->msix_vector))) {
                /* flush the controller write of the reply queue by reading
                 * outbound doorbell status register.
                 */
-               register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
+               (void) readl(h->vaddr + SA5_OUTDB_STATUS);
                writel(SA5_OUTDB_CLEAR_PERF_BIT, h->vaddr + SA5_OUTDB_CLEAR);
                /* Do a read in order to flush the write to the controller
                 * (as per spec.)
                 */
-               register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
+               (void) readl(h->vaddr + SA5_OUTDB_STATUS);
        }
 
-       if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
+       if ((((u32) rq->head[rq->current_entry]) & 1) == rq->wraparound) {
                register_value = rq->head[rq->current_entry];
                rq->current_entry++;
                atomic_dec(&h->commands_outstanding);
@@ -463,9 +478,6 @@ static bool SA5_performant_intr_pending(struct ctlr_info *h)
        if (!register_value)
                return false;
 
-       if (h->msi_vector || h->msix_vector)
-               return true;
-
        /* Read outbound doorbell to flush */
        register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
        return register_value & SA5_OUTDB_STATUS_PERF_BIT;