diff options
author | Stephen M. Cameron <stephenmcameron@gmail.com> | 2014-11-14 18:27:29 -0500 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-11-20 03:11:27 -0500 |
commit | 4c413128a6ff3af013bd1d82860a7ee60f93fb28 (patch) | |
tree | 24f139f6e806b5942134bf02a1b3fa43d0777c93 /drivers/scsi/hpsa.c | |
parent | 4fa604e13bb2a6ef6e89224c80d96af385f533c3 (diff) |
hpsa: remove spin lock around command allocation
It is already using atomic test_and_set_bit to do the
allocation.
There is some microscopic chance of starvation, but it is
so microscopic that it should never happen in reality.
Signed-off-by: Don Brace <don.brace@pmcs.com>
Reviewed-by: Webb Scales <webbnh@hp.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/hpsa.c')
-rw-r--r-- | drivers/scsi/hpsa.c | 36 |
1 files changed, 23 insertions, 13 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 36db63f63143..3569f4201942 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c | |||
@@ -4607,19 +4607,32 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h) | |||
4607 | int i; | 4607 | int i; |
4608 | union u64bit temp64; | 4608 | union u64bit temp64; |
4609 | dma_addr_t cmd_dma_handle, err_dma_handle; | 4609 | dma_addr_t cmd_dma_handle, err_dma_handle; |
4610 | unsigned long flags; | 4610 | int loopcount; |
4611 | |||
4612 | /* There is some *extremely* small but non-zero chance that that | ||
4613 | * multiple threads could get in here, and one thread could | ||
4614 | * be scanning through the list of bits looking for a free | ||
4615 | * one, but the free ones are always behind him, and other | ||
4616 | * threads sneak in behind him and eat them before he can | ||
4617 | * get to them, so that while there is always a free one, a | ||
4618 | * very unlucky thread might be starved anyway, never able to | ||
4619 | * beat the other threads. In reality, this happens so | ||
4620 | * infrequently as to be indistinguishable from never. | ||
4621 | */ | ||
4611 | 4622 | ||
4612 | spin_lock_irqsave(&h->lock, flags); | 4623 | loopcount = 0; |
4613 | do { | 4624 | do { |
4614 | i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds); | 4625 | i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds); |
4615 | if (i == h->nr_cmds) { | 4626 | if (i == h->nr_cmds) |
4616 | spin_unlock_irqrestore(&h->lock, flags); | 4627 | i = 0; |
4617 | return NULL; | 4628 | loopcount++; |
4618 | } | 4629 | } while (test_and_set_bit(i & (BITS_PER_LONG - 1), |
4619 | } while (test_and_set_bit | 4630 | h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0 && |
4620 | (i & (BITS_PER_LONG - 1), | 4631 | loopcount < 10); |
4621 | h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0); | 4632 | |
4622 | spin_unlock_irqrestore(&h->lock, flags); | 4633 | /* Thread got starved? We do not expect this to ever happen. */ |
4634 | if (loopcount >= 10) | ||
4635 | return NULL; | ||
4623 | 4636 | ||
4624 | c = h->cmd_pool + i; | 4637 | c = h->cmd_pool + i; |
4625 | memset(c, 0, sizeof(*c)); | 4638 | memset(c, 0, sizeof(*c)); |
@@ -4679,13 +4692,10 @@ static struct CommandList *cmd_special_alloc(struct ctlr_info *h) | |||
4679 | static void cmd_free(struct ctlr_info *h, struct CommandList *c) | 4692 | static void cmd_free(struct ctlr_info *h, struct CommandList *c) |
4680 | { | 4693 | { |
4681 | int i; | 4694 | int i; |
4682 | unsigned long flags; | ||
4683 | 4695 | ||
4684 | i = c - h->cmd_pool; | 4696 | i = c - h->cmd_pool; |
4685 | spin_lock_irqsave(&h->lock, flags); | ||
4686 | clear_bit(i & (BITS_PER_LONG - 1), | 4697 | clear_bit(i & (BITS_PER_LONG - 1), |
4687 | h->cmd_pool_bits + (i / BITS_PER_LONG)); | 4698 | h->cmd_pool_bits + (i / BITS_PER_LONG)); |
4688 | spin_unlock_irqrestore(&h->lock, flags); | ||
4689 | } | 4699 | } |
4690 | 4700 | ||
4691 | static void cmd_special_free(struct ctlr_info *h, struct CommandList *c) | 4701 | static void cmd_special_free(struct ctlr_info *h, struct CommandList *c) |