diff options
author | Tejun Heo <htejun@gmail.com> | 2007-11-22 04:46:57 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-11-23 19:23:55 -0500 |
commit | 93e2618e0cee1f5b5a4cfc1b7521939318dbf5bb (patch) | |
tree | e535579b3e39c603f81e0144dbf744d0204c6975 /drivers/ata | |
parent | 0706efd61edfcf958c2c19669aa65c2180ec3ba0 (diff) |
sata_sil24: fix sg table sizing
sil24 unnecessarily used LIBATA_MAX_PRD and ATAPI sg table was short
by one entry which might cause very obscure problems. This patch
updates sg table sizing such that
* One full page is used for PRB + sg table. On 4k page,
this results in 253 sg's.
* Make ATAPI sg block properly sized.
* Make build fail if command block size doesn't equal PAGE_SIZE.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/sata_sil24.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 187dcb02c681..96fd5260446d 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c | |||
@@ -63,6 +63,21 @@ enum { | |||
63 | SIL24_HOST_BAR = 0, | 63 | SIL24_HOST_BAR = 0, |
64 | SIL24_PORT_BAR = 2, | 64 | SIL24_PORT_BAR = 2, |
65 | 65 | ||
66 | /* sil24 fetches in chunks of 64bytes. The first block | ||
67 | * contains the PRB and two SGEs. From the second block, it's | ||
68 | * consisted of four SGEs and called SGT. Calculate the | ||
69 | * number of SGTs that fit into one page. | ||
70 | */ | ||
71 | SIL24_PRB_SZ = sizeof(struct sil24_prb) | ||
72 | + 2 * sizeof(struct sil24_sge), | ||
73 | SIL24_MAX_SGT = (PAGE_SIZE - SIL24_PRB_SZ) | ||
74 | / (4 * sizeof(struct sil24_sge)), | ||
75 | |||
76 | /* This will give us one unused SGEs for ATA. This extra SGE | ||
77 | * will be used to store CDB for ATAPI devices. | ||
78 | */ | ||
79 | SIL24_MAX_SGE = 4 * SIL24_MAX_SGT + 1, | ||
80 | |||
66 | /* | 81 | /* |
67 | * Global controller registers (128 bytes @ BAR0) | 82 | * Global controller registers (128 bytes @ BAR0) |
68 | */ | 83 | */ |
@@ -247,13 +262,13 @@ enum { | |||
247 | 262 | ||
248 | struct sil24_ata_block { | 263 | struct sil24_ata_block { |
249 | struct sil24_prb prb; | 264 | struct sil24_prb prb; |
250 | struct sil24_sge sge[LIBATA_MAX_PRD]; | 265 | struct sil24_sge sge[SIL24_MAX_SGE]; |
251 | }; | 266 | }; |
252 | 267 | ||
253 | struct sil24_atapi_block { | 268 | struct sil24_atapi_block { |
254 | struct sil24_prb prb; | 269 | struct sil24_prb prb; |
255 | u8 cdb[16]; | 270 | u8 cdb[16]; |
256 | struct sil24_sge sge[LIBATA_MAX_PRD - 1]; | 271 | struct sil24_sge sge[SIL24_MAX_SGE]; |
257 | }; | 272 | }; |
258 | 273 | ||
259 | union sil24_cmd_block { | 274 | union sil24_cmd_block { |
@@ -378,7 +393,7 @@ static struct scsi_host_template sil24_sht = { | |||
378 | .change_queue_depth = ata_scsi_change_queue_depth, | 393 | .change_queue_depth = ata_scsi_change_queue_depth, |
379 | .can_queue = SIL24_MAX_CMDS, | 394 | .can_queue = SIL24_MAX_CMDS, |
380 | .this_id = ATA_SHT_THIS_ID, | 395 | .this_id = ATA_SHT_THIS_ID, |
381 | .sg_tablesize = LIBATA_MAX_PRD, | 396 | .sg_tablesize = SIL24_MAX_SGE, |
382 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 397 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
383 | .emulated = ATA_SHT_EMULATED, | 398 | .emulated = ATA_SHT_EMULATED, |
384 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 399 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -1284,6 +1299,7 @@ static void sil24_init_controller(struct ata_host *host) | |||
1284 | 1299 | ||
1285 | static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 1300 | static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
1286 | { | 1301 | { |
1302 | extern int __MARKER__sil24_cmd_block_is_sized_wrongly; | ||
1287 | static int printed_version; | 1303 | static int printed_version; |
1288 | struct ata_port_info pi = sil24_port_info[ent->driver_data]; | 1304 | struct ata_port_info pi = sil24_port_info[ent->driver_data]; |
1289 | const struct ata_port_info *ppi[] = { &pi, NULL }; | 1305 | const struct ata_port_info *ppi[] = { &pi, NULL }; |
@@ -1292,6 +1308,10 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1292 | int i, rc; | 1308 | int i, rc; |
1293 | u32 tmp; | 1309 | u32 tmp; |
1294 | 1310 | ||
1311 | /* cause link error if sil24_cmd_block is sized wrongly */ | ||
1312 | if (sizeof(union sil24_cmd_block) != PAGE_SIZE) | ||
1313 | __MARKER__sil24_cmd_block_is_sized_wrongly = 1; | ||
1314 | |||
1295 | if (!printed_version++) | 1315 | if (!printed_version++) |
1296 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); | 1316 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); |
1297 | 1317 | ||