Commit 0cbf768e authored by Stephen M. Cameron's avatar Stephen M. Cameron Committed by Christoph Hellwig

hpsa: use atomics for commands_outstanding

Use atomics for commands_outstanding instead of protecting with spin locks.
Signed-off-by: default avatarDon Brace <don.brace@pmcs.com>
Signed-off-by: default avatarStephen M. Cameron <stephenmcameron@gmail.com>
Reviewed-by: default avatarJoe Handzik <joseph.t.handzik@hp.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent a505b86f
...@@ -394,7 +394,8 @@ static ssize_t host_show_commands_outstanding(struct device *dev, ...@@ -394,7 +394,8 @@ static ssize_t host_show_commands_outstanding(struct device *dev,
struct Scsi_Host *shost = class_to_shost(dev); struct Scsi_Host *shost = class_to_shost(dev);
struct ctlr_info *h = shost_to_hba(shost); struct ctlr_info *h = shost_to_hba(shost);
return snprintf(buf, 20, "%d\n", h->commands_outstanding); return snprintf(buf, 20, "%d\n",
atomic_read(&h->commands_outstanding));
} }
static ssize_t host_show_transport_mode(struct device *dev, static ssize_t host_show_transport_mode(struct device *dev,
...@@ -700,7 +701,6 @@ static inline u32 next_command(struct ctlr_info *h, u8 q) ...@@ -700,7 +701,6 @@ static inline u32 next_command(struct ctlr_info *h, u8 q)
{ {
u32 a; u32 a;
struct reply_queue_buffer *rq = &h->reply_queue[q]; struct reply_queue_buffer *rq = &h->reply_queue[q];
unsigned long flags;
if (h->transMethod & CFGTBL_Trans_io_accel1) if (h->transMethod & CFGTBL_Trans_io_accel1)
return h->access.command_completed(h, q); return h->access.command_completed(h, q);
...@@ -711,9 +711,7 @@ static inline u32 next_command(struct ctlr_info *h, u8 q) ...@@ -711,9 +711,7 @@ static inline u32 next_command(struct ctlr_info *h, u8 q)
if ((rq->head[rq->current_entry] & 1) == rq->wraparound) { if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
a = rq->head[rq->current_entry]; a = rq->head[rq->current_entry];
rq->current_entry++; rq->current_entry++;
spin_lock_irqsave(&h->lock, flags); atomic_dec(&h->commands_outstanding);
h->commands_outstanding--;
spin_unlock_irqrestore(&h->lock, flags);
} else { } else {
a = FIFO_EMPTY; a = FIFO_EMPTY;
} }
...@@ -5445,15 +5443,9 @@ static void start_io(struct ctlr_info *h, unsigned long *flags) ...@@ -5445,15 +5443,9 @@ static void start_io(struct ctlr_info *h, unsigned long *flags)
/* Put job onto the completed Q */ /* Put job onto the completed Q */
addQ(&h->cmpQ, c); addQ(&h->cmpQ, c);
atomic_inc(&h->commands_outstanding);
/* Must increment commands_outstanding before unlocking
* and submitting to avoid race checking for fifo full
* condition.
*/
h->commands_outstanding++;
/* Tell the controller execute command */
spin_unlock_irqrestore(&h->lock, *flags); spin_unlock_irqrestore(&h->lock, *flags);
/* Tell the controller execute command */
h->access.submit_command(h, c); h->access.submit_command(h, c);
spin_lock_irqsave(&h->lock, *flags); spin_lock_irqsave(&h->lock, *flags);
} }
...@@ -5499,6 +5491,7 @@ static inline void finish_cmd(struct CommandList *c) ...@@ -5499,6 +5491,7 @@ static inline void finish_cmd(struct CommandList *c)
unsigned long flags; unsigned long flags;
int io_may_be_stalled = 0; int io_may_be_stalled = 0;
struct ctlr_info *h = c->h; struct ctlr_info *h = c->h;
int count;
spin_lock_irqsave(&h->lock, flags); spin_lock_irqsave(&h->lock, flags);
removeQ(c); removeQ(c);
...@@ -5519,11 +5512,10 @@ static inline void finish_cmd(struct CommandList *c) ...@@ -5519,11 +5512,10 @@ static inline void finish_cmd(struct CommandList *c)
* want to get in a cycle where we call start_io every time * want to get in a cycle where we call start_io every time
* through here. * through here.
*/ */
if (unlikely(h->fifo_recently_full) && count = atomic_read(&h->commands_outstanding);
h->commands_outstanding < 5)
io_may_be_stalled = 1;
spin_unlock_irqrestore(&h->lock, flags); spin_unlock_irqrestore(&h->lock, flags);
if (unlikely(h->fifo_recently_full) && count < 5)
io_may_be_stalled = 1;
dial_up_lockup_detection_on_fw_flash_complete(c->h, c); dial_up_lockup_detection_on_fw_flash_complete(c->h, c);
if (likely(c->cmd_type == CMD_IOACCEL1 || c->cmd_type == CMD_SCSI if (likely(c->cmd_type == CMD_IOACCEL1 || c->cmd_type == CMD_SCSI
......
...@@ -118,7 +118,7 @@ struct ctlr_info { ...@@ -118,7 +118,7 @@ struct ctlr_info {
struct CfgTable __iomem *cfgtable; struct CfgTable __iomem *cfgtable;
int interrupts_enabled; int interrupts_enabled;
int max_commands; int max_commands;
int commands_outstanding; atomic_t commands_outstanding;
# define PERF_MODE_INT 0 # define PERF_MODE_INT 0
# define DOORBELL_INT 1 # define DOORBELL_INT 1
# define SIMPLE_MODE_INT 2 # define SIMPLE_MODE_INT 2
...@@ -395,7 +395,7 @@ static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val) ...@@ -395,7 +395,7 @@ static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val)
static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q) static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
{ {
struct reply_queue_buffer *rq = &h->reply_queue[q]; struct reply_queue_buffer *rq = &h->reply_queue[q];
unsigned long flags, register_value = FIFO_EMPTY; unsigned long register_value = FIFO_EMPTY;
/* msi auto clears the interrupt pending bit. */ /* msi auto clears the interrupt pending bit. */
if (!(h->msi_vector || h->msix_vector)) { if (!(h->msi_vector || h->msix_vector)) {
...@@ -413,9 +413,7 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q) ...@@ -413,9 +413,7 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
if ((rq->head[rq->current_entry] & 1) == rq->wraparound) { if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
register_value = rq->head[rq->current_entry]; register_value = rq->head[rq->current_entry];
rq->current_entry++; rq->current_entry++;
spin_lock_irqsave(&h->lock, flags); atomic_dec(&h->commands_outstanding);
h->commands_outstanding--;
spin_unlock_irqrestore(&h->lock, flags);
} else { } else {
register_value = FIFO_EMPTY; register_value = FIFO_EMPTY;
} }
...@@ -433,11 +431,7 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q) ...@@ -433,11 +431,7 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
*/ */
static unsigned long SA5_fifo_full(struct ctlr_info *h) static unsigned long SA5_fifo_full(struct ctlr_info *h)
{ {
if (h->commands_outstanding >= h->max_commands) return atomic_read(&h->commands_outstanding) >= h->max_commands;
return 1;
else
return 0;
} }
/* /*
* returns value read from hardware. * returns value read from hardware.
...@@ -448,13 +442,9 @@ static unsigned long SA5_completed(struct ctlr_info *h, ...@@ -448,13 +442,9 @@ static unsigned long SA5_completed(struct ctlr_info *h,
{ {
unsigned long register_value unsigned long register_value
= readl(h->vaddr + SA5_REPLY_PORT_OFFSET); = 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); atomic_dec(&h->commands_outstanding);
h->commands_outstanding--;
spin_unlock_irqrestore(&h->lock, flags);
}
#ifdef HPSA_DEBUG #ifdef HPSA_DEBUG
if (register_value != FIFO_EMPTY) if (register_value != FIFO_EMPTY)
...@@ -510,7 +500,6 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q) ...@@ -510,7 +500,6 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q)
{ {
u64 register_value; u64 register_value;
struct reply_queue_buffer *rq = &h->reply_queue[q]; struct reply_queue_buffer *rq = &h->reply_queue[q];
unsigned long flags;
BUG_ON(q >= h->nreply_queues); BUG_ON(q >= h->nreply_queues);
...@@ -528,9 +517,7 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q) ...@@ -528,9 +517,7 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q)
wmb(); wmb();
writel((q << 24) | rq->current_entry, h->vaddr + writel((q << 24) | rq->current_entry, h->vaddr +
IOACCEL_MODE1_CONSUMER_INDEX); IOACCEL_MODE1_CONSUMER_INDEX);
spin_lock_irqsave(&h->lock, flags); atomic_dec(&h->commands_outstanding);
h->commands_outstanding--;
spin_unlock_irqrestore(&h->lock, flags);
} }
return (unsigned long) register_value; return (unsigned long) register_value;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment