diff options
author | Stephen M. Cameron <scameron@beardog.cce.hp.com> | 2010-06-16 14:51:56 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-27 13:02:03 -0400 |
commit | cba3d38b6cf85bd91b7c6f65f43863d1fd19259c (patch) | |
tree | cac41bceaf3c5a60795f602b55e64ab7173d244d /drivers/scsi/hpsa.c | |
parent | 10f66018088fd0c9fe81b1e328e3264c7b10caa5 (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.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index f8b614b591e4..4f5551b5fe53 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 | ||
3508 | static 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 | */ |
3512 | static void __devinit hpsa_find_board_params(struct ctlr_info *h) | 3524 | static 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); |