diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-21 17:46:21 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-21 17:46:21 -0700 |
commit | da4f58ffa08a7b7012fab9c205fa0f6ba40fec42 (patch) | |
tree | 76317ee98eadbb8457e045dd0375652b14224451 /drivers/scsi/hpsa.h | |
parent | ba01a87e37d3ca9efe141e2907c2ec3f89490b4f (diff) | |
parent | e34693336564f02b3e2cc09d8b872aef22a154e9 (diff) |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI misc update from James Bottomley:
"The patch contains the usual assortment of driver updates (be2iscsi,
bfa, bnx2i, fcoe, hpsa, isci, lpfc, megaraid, mpt2sas, pm8001, sg)
plus an assortment of other changes and fixes. Also new is the fact
that the isci update is delivered as a git merge (with signed tag)."
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (158 commits)
isci: End the RNC resumption wait when the RNC is destroyed.
isci: Fixed RNC bug that lost the suspension or resumption during destroy
isci: Fix RNC AWAIT_SUSPENSION->INVALIDATING transition.
isci: Manage the IREQ_NO_AUTO_FREE_TAG under scic_lock.
isci: Remove obviated host callback list.
isci: Check IDEV_GONE before performing abort path operations.
isci: Restore the ATAPI device RNC management code.
isci: Don't wait for an RNC suspend if it's being destroyed.
isci: Change the phy control and link reset interface for HW reasons.
isci: Added timeouts to RNC suspensions in the abort path.
isci: Add protocol indicator for TMF requests.
isci: Directly control IREQ_ABORT_PATH_ACTIVE when completing TMFs.
isci: Wait for RNC resumption before leaving the abort path.
isci: Fix RNC suspend call for SCI_RESUMING state.
isci: Manage tag releases differently when aborting tasks.
isci: Callbacks to libsas occur under scic_lock and are synchronized.
isci: When in the abort path, defeat other resume calls until done.
isci: Implement waiting for suspend in the abort path.
isci: Make sure all TCs are terminated and cleaned in LUN reset.
isci: Manage the LLHANG timer enable/disable per-device.
...
Diffstat (limited to 'drivers/scsi/hpsa.h')
-rw-r--r-- | drivers/scsi/hpsa.h | 85 |
1 files changed, 60 insertions, 25 deletions
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 7b28d54fa878..981647989bfd 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -34,7 +34,7 @@ struct access_method { void (*set_intr_mask)(struct ctlr_info *h, unsigned long val); unsigned long (*fifo_full)(struct ctlr_info *h); bool (*intr_pending)(struct ctlr_info *h); - unsigned long (*command_completed)(struct ctlr_info *h); + unsigned long (*command_completed)(struct ctlr_info *h, u8 q); }; struct hpsa_scsi_dev_t { @@ -48,6 +48,13 @@ struct hpsa_scsi_dev_t { unsigned char raid_level; /* from inquiry page 0xC1 */ }; +struct reply_pool { + u64 *head; + size_t size; + u8 wraparound; + u32 current_entry; +}; + struct ctlr_info { int ctlr; char devname[8]; @@ -68,7 +75,7 @@ struct ctlr_info { # define DOORBELL_INT 1 # define SIMPLE_MODE_INT 2 # define MEMQ_MODE_INT 3 - unsigned int intr[4]; + unsigned int intr[MAX_REPLY_QUEUES]; unsigned int msix_vector; unsigned int msi_vector; int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */ @@ -78,7 +85,6 @@ struct ctlr_info { struct list_head reqQ; struct list_head cmpQ; unsigned int Qdepth; - unsigned int maxQsinceinit; unsigned int maxSG; spinlock_t lock; int maxsgentries; @@ -111,20 +117,45 @@ struct ctlr_info { unsigned long transMethod; /* - * Performant mode completion buffer + * Performant mode completion buffers */ u64 *reply_pool; - dma_addr_t reply_pool_dhandle; - u64 *reply_pool_head; size_t reply_pool_size; - unsigned char reply_pool_wraparound; + struct reply_pool reply_queue[MAX_REPLY_QUEUES]; + u8 nreply_queues; + dma_addr_t reply_pool_dhandle; u32 *blockFetchTable; unsigned char *hba_inquiry_data; u64 last_intr_timestamp; u32 last_heartbeat; u64 last_heartbeat_timestamp; + u32 heartbeat_sample_interval; + atomic_t firmware_flash_in_progress; u32 lockup_detected; struct list_head lockup_list; + /* Address of h->q[x] is passed to intr handler to know which queue */ + u8 q[MAX_REPLY_QUEUES]; + u32 TMFSupportFlags; /* cache what task mgmt funcs are supported. */ +#define HPSATMF_BITS_SUPPORTED (1 << 0) +#define HPSATMF_PHYS_LUN_RESET (1 << 1) +#define HPSATMF_PHYS_NEX_RESET (1 << 2) +#define HPSATMF_PHYS_TASK_ABORT (1 << 3) +#define HPSATMF_PHYS_TSET_ABORT (1 << 4) +#define HPSATMF_PHYS_CLEAR_ACA (1 << 5) +#define HPSATMF_PHYS_CLEAR_TSET (1 << 6) +#define HPSATMF_PHYS_QRY_TASK (1 << 7) +#define HPSATMF_PHYS_QRY_TSET (1 << 8) +#define HPSATMF_PHYS_QRY_ASYNC (1 << 9) +#define HPSATMF_MASK_SUPPORTED (1 << 16) +#define HPSATMF_LOG_LUN_RESET (1 << 17) +#define HPSATMF_LOG_NEX_RESET (1 << 18) +#define HPSATMF_LOG_TASK_ABORT (1 << 19) +#define HPSATMF_LOG_TSET_ABORT (1 << 20) +#define HPSATMF_LOG_CLEAR_ACA (1 << 21) +#define HPSATMF_LOG_CLEAR_TSET (1 << 22) +#define HPSATMF_LOG_QRY_TASK (1 << 23) +#define HPSATMF_LOG_QRY_TSET (1 << 24) +#define HPSATMF_LOG_QRY_ASYNC (1 << 25) }; #define HPSA_ABORT_MSG 0 #define HPSA_DEVICE_RESET_MSG 1 @@ -216,9 +247,6 @@ static void SA5_submit_command(struct ctlr_info *h, c->Header.Tag.lower); writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET); (void) readl(h->vaddr + SA5_SCRATCHPAD_OFFSET); - h->commands_outstanding++; - if (h->commands_outstanding > h->max_outstanding) - h->max_outstanding = h->commands_outstanding; } /* @@ -254,16 +282,17 @@ static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val) } } -static unsigned long SA5_performant_completed(struct ctlr_info *h) +static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q) { - unsigned long register_value = FIFO_EMPTY; + struct reply_pool *rq = &h->reply_queue[q]; + unsigned long flags, register_value = FIFO_EMPTY; - /* flush the controller write of the reply queue by reading - * outbound doorbell status register. - */ - register_value = readl(h->vaddr + SA5_OUTDB_STATUS); /* msi auto clears the interrupt pending bit. */ if (!(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); 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.) @@ -271,19 +300,20 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h) register_value = readl(h->vaddr + SA5_OUTDB_STATUS); } - if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) { - register_value = *(h->reply_pool_head); - (h->reply_pool_head)++; + if ((rq->head[rq->current_entry] & 1) == rq->wraparound) { + register_value = rq->head[rq->current_entry]; + rq->current_entry++; + spin_lock_irqsave(&h->lock, flags); h->commands_outstanding--; + spin_unlock_irqrestore(&h->lock, flags); } else { register_value = FIFO_EMPTY; } /* Check for wraparound */ - if (h->reply_pool_head == (h->reply_pool + h->max_commands)) { - h->reply_pool_head = h->reply_pool; - h->reply_pool_wraparound ^= 1; + if (rq->current_entry == h->max_commands) { + rq->current_entry = 0; + rq->wraparound ^= 1; } - return register_value; } @@ -303,13 +333,18 @@ static unsigned long SA5_fifo_full(struct ctlr_info *h) * returns value read from hardware. * returns FIFO_EMPTY if there is nothing to read */ -static unsigned long SA5_completed(struct ctlr_info *h) +static unsigned long SA5_completed(struct ctlr_info *h, + __attribute__((unused)) u8 q) { unsigned long register_value = readl(h->vaddr + SA5_REPLY_PORT_OFFSET); + unsigned long flags; - if (register_value != FIFO_EMPTY) + if (register_value != FIFO_EMPTY) { + spin_lock_irqsave(&h->lock, flags); h->commands_outstanding--; + spin_unlock_irqrestore(&h->lock, flags); + } #ifdef HPSA_DEBUG if (register_value != FIFO_EMPTY) |