aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/hpsa.c
diff options
context:
space:
mode:
authorStephen M. Cameron <scameron@beardog.cce.hp.com>2010-06-16 14:51:56 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-27 13:02:03 -0400
commitcba3d38b6cf85bd91b7c6f65f43863d1fd19259c (patch)
treecac41bceaf3c5a60795f602b55e64ab7173d244d /drivers/scsi/hpsa.c
parent10f66018088fd0c9fe81b1e328e3264c7b10caa5 (diff)
[SCSI] hpsa: sanitize max commands
Some controllers might try to tell us they support 0 commands in performant mode. This is a lie told by buggy firmware. We have to be wary of this lest we try to allocate a negative number of command blocks, which will be treated as unsigned, and get an out of memory condition. Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/hpsa.c')
-rw-r--r--drivers/scsi/hpsa.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index f8b614b591e..4f5551b5fe5 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3505,13 +3505,25 @@ static int __devinit hpsa_find_cfgtables(struct ctlr_info *h)
3505 return 0; 3505 return 0;
3506} 3506}
3507 3507
3508static void __devinit hpsa_get_max_perf_mode_cmds(struct ctlr_info *h)
3509{
3510 h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands));
3511 if (h->max_commands < 16) {
3512 dev_warn(&h->pdev->dev, "Controller reports "
3513 "max supported commands of %d, an obvious lie. "
3514 "Using 16. Ensure that firmware is up to date.\n",
3515 h->max_commands);
3516 h->max_commands = 16;
3517 }
3518}
3519
3508/* Interrogate the hardware for some limits: 3520/* Interrogate the hardware for some limits:
3509 * max commands, max SG elements without chaining, and with chaining, 3521 * max commands, max SG elements without chaining, and with chaining,
3510 * SG chain block size, etc. 3522 * SG chain block size, etc.
3511 */ 3523 */
3512static void __devinit hpsa_find_board_params(struct ctlr_info *h) 3524static void __devinit hpsa_find_board_params(struct ctlr_info *h)
3513{ 3525{
3514 h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); 3526 hpsa_get_max_perf_mode_cmds(h);
3515 h->nr_cmds = h->max_commands - 4; /* Allow room for some ioctls */ 3527 h->nr_cmds = h->max_commands - 4; /* Allow room for some ioctls */
3516 h->maxsgentries = readl(&(h->cfgtable->MaxScatterGatherElements)); 3528 h->maxsgentries = readl(&(h->cfgtable->MaxScatterGatherElements));
3517 /* 3529 /*
@@ -4056,7 +4068,7 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
4056 if (!(trans_support & PERFORMANT_MODE)) 4068 if (!(trans_support & PERFORMANT_MODE))
4057 return; 4069 return;
4058 4070
4059 h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); 4071 hpsa_get_max_perf_mode_cmds(h);
4060 h->max_sg_entries = 32; 4072 h->max_sg_entries = 32;
4061 /* Performant mode ring buffer and supporting data structures */ 4073 /* Performant mode ring buffer and supporting data structures */
4062 h->reply_pool_size = h->max_commands * sizeof(u64); 4074 h->reply_pool_size = h->max_commands * sizeof(u64);