diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/hpsa.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 410910762fc..1133b5fda0e 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3826,7 +3826,26 @@ static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h) { int i; unsigned long register_value; - int bft[8] = {5, 6, 8, 10, 12, 20, 28, 35}; /* for scatter/gathers */ + + /* This is a bit complicated. There are 8 registers on + * the controller which we write to to tell it 8 different + * sizes of commands which there may be. It's a way of + * reducing the DMA done to fetch each command. Encoded into + * each command's tag are 3 bits which communicate to the controller + * which of the eight sizes that command fits within. The size of + * each command depends on how many scatter gather entries there are. + * Each SG entry requires 16 bytes. The eight registers are programmed + * with the number of 16-byte blocks a command of that size requires. + * The smallest command possible requires 5 such 16 byte blocks. + * the largest command possible requires MAXSGENTRIES + 4 16-byte + * blocks. Note, this only extends to the SG entries contained + * within the command block, and does not extend to chained blocks + * of SG elements. bft[] contains the eight values we write to + * the registers. They are not evenly distributed, but have more + * sizes for small commands, and fewer sizes for larger commands. + */ + int bft[8] = {5, 6, 8, 10, 12, 20, 28, MAXSGENTRIES + 4}; + BUILD_BUG_ON(28 > MAXSGENTRIES + 4); /* 5 = 1 s/g entry or 4k * 6 = 2 s/g entry or 8k * 8 = 4 s/g entry or 16k |