diff options
| -rw-r--r-- | drivers/scsi/gdth.c | 228 | ||||
| -rw-r--r-- | drivers/scsi/gdth.h | 7 |
2 files changed, 109 insertions, 126 deletions
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index a68004b0d90b..0153d1d8b12e 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c | |||
| @@ -85,11 +85,11 @@ | |||
| 85 | 85 | ||
| 86 | /* The meaning of the Scsi_Pointer members in this driver is as follows: | 86 | /* The meaning of the Scsi_Pointer members in this driver is as follows: |
| 87 | * ptr: Chaining | 87 | * ptr: Chaining |
| 88 | * this_residual: unused | 88 | * this_residual: gdth_bufflen |
| 89 | * buffer: unused | 89 | * buffer: gdth_sglist |
| 90 | * dma_handle: will drop in !use_sg patch. | 90 | * dma_handle: unused |
| 91 | * buffers_residual: unused | 91 | * buffers_residual: gdth_sg_count |
| 92 | * Status: DMA mem. mappings (FIXME: drop in !use_sg patch.) | 92 | * Status: unused |
| 93 | * Message: unused | 93 | * Message: unused |
| 94 | * have_data_in: unused | 94 | * have_data_in: unused |
| 95 | * sent_command: unused | 95 | * sent_command: unused |
| @@ -132,6 +132,7 @@ | |||
| 132 | #include <asm/uaccess.h> | 132 | #include <asm/uaccess.h> |
| 133 | #include <linux/spinlock.h> | 133 | #include <linux/spinlock.h> |
| 134 | #include <linux/blkdev.h> | 134 | #include <linux/blkdev.h> |
| 135 | #include <linux/scatterlist.h> | ||
| 135 | 136 | ||
| 136 | #include "scsi.h" | 137 | #include "scsi.h" |
| 137 | #include <scsi/scsi_host.h> | 138 | #include <scsi/scsi_host.h> |
| @@ -159,7 +160,7 @@ static void gdth_readapp_event(gdth_ha_str *ha, unchar application, | |||
| 159 | static void gdth_clear_events(void); | 160 | static void gdth_clear_events(void); |
| 160 | 161 | ||
| 161 | static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, | 162 | static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, |
| 162 | char *buffer,ushort count); | 163 | char *buffer, ushort count, int to_buffer); |
| 163 | static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp); | 164 | static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp); |
| 164 | static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive); | 165 | static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive); |
| 165 | 166 | ||
| @@ -373,6 +374,47 @@ static const struct file_operations gdth_fops = { | |||
| 373 | .release = gdth_close, | 374 | .release = gdth_close, |
| 374 | }; | 375 | }; |
| 375 | 376 | ||
| 377 | /* | ||
| 378 | * gdth scsi_command access wrappers. | ||
| 379 | * below 6 functions are used throughout the driver to access scsi_command's | ||
| 380 | * io parameters. The reason we do not use the regular accessors from | ||
| 381 | * scsi_cmnd.h is because of gdth_execute(). Since it is unrecommended for | ||
| 382 | * llds to directly set scsi_cmnd's IO members. This driver will use SCp | ||
| 383 | * members for IO parameters, and will copy scsi_cmnd's members to Scp | ||
| 384 | * members in queuecommand. For internal commands through gdth_execute() | ||
| 385 | * SCp's members will be set directly. | ||
| 386 | */ | ||
| 387 | static inline unsigned gdth_bufflen(struct scsi_cmnd *cmd) | ||
| 388 | { | ||
| 389 | return (unsigned)cmd->SCp.this_residual; | ||
| 390 | } | ||
| 391 | |||
| 392 | static inline void gdth_set_bufflen(struct scsi_cmnd *cmd, unsigned bufflen) | ||
| 393 | { | ||
| 394 | cmd->SCp.this_residual = bufflen; | ||
| 395 | } | ||
| 396 | |||
| 397 | static inline unsigned gdth_sg_count(struct scsi_cmnd *cmd) | ||
| 398 | { | ||
| 399 | return (unsigned)cmd->SCp.buffers_residual; | ||
| 400 | } | ||
| 401 | |||
| 402 | static inline void gdth_set_sg_count(struct scsi_cmnd *cmd, unsigned sg_count) | ||
| 403 | { | ||
| 404 | cmd->SCp.buffers_residual = sg_count; | ||
| 405 | } | ||
| 406 | |||
| 407 | static inline struct scatterlist *gdth_sglist(struct scsi_cmnd *cmd) | ||
| 408 | { | ||
| 409 | return cmd->SCp.buffer; | ||
| 410 | } | ||
| 411 | |||
| 412 | static inline void gdth_set_sglist(struct scsi_cmnd *cmd, | ||
| 413 | struct scatterlist *sglist) | ||
| 414 | { | ||
| 415 | cmd->SCp.buffer = sglist; | ||
| 416 | } | ||
| 417 | |||
| 376 | #include "gdth_proc.h" | 418 | #include "gdth_proc.h" |
| 377 | #include "gdth_proc.c" | 419 | #include "gdth_proc.c" |
| 378 | 420 | ||
| @@ -452,6 +494,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, | |||
| 452 | gdth_ha_str *ha = shost_priv(sdev->host); | 494 | gdth_ha_str *ha = shost_priv(sdev->host); |
| 453 | Scsi_Cmnd *scp; | 495 | Scsi_Cmnd *scp; |
| 454 | struct gdth_cmndinfo cmndinfo; | 496 | struct gdth_cmndinfo cmndinfo; |
| 497 | struct scatterlist one_sg; | ||
| 455 | DECLARE_COMPLETION_ONSTACK(wait); | 498 | DECLARE_COMPLETION_ONSTACK(wait); |
| 456 | int rval; | 499 | int rval; |
| 457 | 500 | ||
| @@ -465,7 +508,10 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, | |||
| 465 | /* use request field to save the ptr. to completion struct. */ | 508 | /* use request field to save the ptr. to completion struct. */ |
| 466 | scp->request = (struct request *)&wait; | 509 | scp->request = (struct request *)&wait; |
| 467 | scp->timeout_per_command = timeout*HZ; | 510 | scp->timeout_per_command = timeout*HZ; |
| 468 | scp->request_buffer = gdtcmd; | 511 | sg_init_one(&one_sg, gdtcmd, sizeof(*gdtcmd)); |
| 512 | gdth_set_sglist(scp, &one_sg); | ||
| 513 | gdth_set_sg_count(scp, 1); | ||
| 514 | gdth_set_bufflen(scp, sizeof(*gdtcmd)); | ||
| 469 | scp->cmd_len = 12; | 515 | scp->cmd_len = 12; |
| 470 | memcpy(scp->cmnd, cmnd, 12); | 516 | memcpy(scp->cmnd, cmnd, 12); |
| 471 | cmndinfo.priority = IOCTL_PRI; | 517 | cmndinfo.priority = IOCTL_PRI; |
| @@ -2303,24 +2349,28 @@ static void gdth_next(gdth_ha_str *ha) | |||
| 2303 | ha->hanum, cmd_index); | 2349 | ha->hanum, cmd_index); |
| 2304 | } | 2350 | } |
| 2305 | } | 2351 | } |
| 2306 | 2352 | ||
| 2353 | /* | ||
| 2354 | * gdth_copy_internal_data() - copy to/from a buffer onto a scsi_cmnd's | ||
| 2355 | * buffers, kmap_atomic() as needed. | ||
| 2356 | */ | ||
| 2307 | static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, | 2357 | static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, |
| 2308 | char *buffer,ushort count) | 2358 | char *buffer, ushort count, int to_buffer) |
| 2309 | { | 2359 | { |
| 2310 | ushort cpcount,i; | 2360 | ushort cpcount,i, max_sg = gdth_sg_count(scp); |
| 2311 | ushort cpsum,cpnow; | 2361 | ushort cpsum,cpnow; |
| 2312 | struct scatterlist *sl; | 2362 | struct scatterlist *sl; |
| 2313 | char *address; | 2363 | char *address; |
| 2314 | 2364 | ||
| 2315 | cpcount = count<=(ushort)scp->request_bufflen ? count:(ushort)scp->request_bufflen; | 2365 | cpcount = min_t(ushort, count, gdth_bufflen(scp)); |
| 2316 | 2366 | ||
| 2317 | if (scp->use_sg) { | 2367 | if (cpcount) { |
| 2318 | sl = (struct scatterlist *)scp->request_buffer; | 2368 | cpsum=0; |
| 2319 | for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) { | 2369 | scsi_for_each_sg(scp, sl, max_sg, i) { |
| 2320 | unsigned long flags; | 2370 | unsigned long flags; |
| 2321 | cpnow = (ushort)sl->length; | 2371 | cpnow = (ushort)sl->length; |
| 2322 | TRACE(("copy_internal() now %d sum %d count %d %d\n", | 2372 | TRACE(("copy_internal() now %d sum %d count %d %d\n", |
| 2323 | cpnow,cpsum,cpcount,(ushort)scp->bufflen)); | 2373 | cpnow, cpsum, cpcount, gdth_bufflen(scp))); |
| 2324 | if (cpsum+cpnow > cpcount) | 2374 | if (cpsum+cpnow > cpcount) |
| 2325 | cpnow = cpcount - cpsum; | 2375 | cpnow = cpcount - cpsum; |
| 2326 | cpsum += cpnow; | 2376 | cpsum += cpnow; |
| @@ -2331,7 +2381,10 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, | |||
| 2331 | } | 2381 | } |
| 2332 | local_irq_save(flags); | 2382 | local_irq_save(flags); |
| 2333 | address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset; | 2383 | address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset; |
| 2334 | memcpy(address,buffer,cpnow); | 2384 | if (to_buffer) |
| 2385 | memcpy(buffer, address, cpnow); | ||
| 2386 | else | ||
| 2387 | memcpy(address, buffer, cpnow); | ||
| 2335 | flush_dcache_page(sl->page); | 2388 | flush_dcache_page(sl->page); |
| 2336 | kunmap_atomic(address, KM_BIO_SRC_IRQ); | 2389 | kunmap_atomic(address, KM_BIO_SRC_IRQ); |
| 2337 | local_irq_restore(flags); | 2390 | local_irq_restore(flags); |
| @@ -2339,9 +2392,10 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, | |||
| 2339 | break; | 2392 | break; |
| 2340 | buffer += cpnow; | 2393 | buffer += cpnow; |
| 2341 | } | 2394 | } |
| 2342 | } else { | 2395 | } else if (count) { |
| 2343 | TRACE(("copy_internal() count %d\n",cpcount)); | 2396 | printk("GDT-HA %d: SCSI command with no buffers but data transfer expected!\n", |
| 2344 | memcpy((char*)scp->request_buffer,buffer,cpcount); | 2397 | ha->hanum); |
| 2398 | WARN_ON(1); | ||
| 2345 | } | 2399 | } |
| 2346 | } | 2400 | } |
| 2347 | 2401 | ||
| @@ -2384,7 +2438,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
| 2384 | strcpy(inq.vendor,ha->oem_name); | 2438 | strcpy(inq.vendor,ha->oem_name); |
| 2385 | sprintf(inq.product,"Host Drive #%02d",t); | 2439 | sprintf(inq.product,"Host Drive #%02d",t); |
| 2386 | strcpy(inq.revision," "); | 2440 | strcpy(inq.revision," "); |
| 2387 | gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data)); | 2441 | gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data), 0); |
| 2388 | break; | 2442 | break; |
| 2389 | 2443 | ||
| 2390 | case REQUEST_SENSE: | 2444 | case REQUEST_SENSE: |
| @@ -2394,7 +2448,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
| 2394 | sd.key = NO_SENSE; | 2448 | sd.key = NO_SENSE; |
| 2395 | sd.info = 0; | 2449 | sd.info = 0; |
| 2396 | sd.add_length= 0; | 2450 | sd.add_length= 0; |
| 2397 | gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data)); | 2451 | gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data), 0); |
| 2398 | break; | 2452 | break; |
| 2399 | 2453 | ||
| 2400 | case MODE_SENSE: | 2454 | case MODE_SENSE: |
| @@ -2406,7 +2460,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
| 2406 | mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; | 2460 | mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; |
| 2407 | mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; | 2461 | mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; |
| 2408 | mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); | 2462 | mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); |
| 2409 | gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data)); | 2463 | gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data), 0); |
| 2410 | break; | 2464 | break; |
| 2411 | 2465 | ||
| 2412 | case READ_CAPACITY: | 2466 | case READ_CAPACITY: |
| @@ -2416,7 +2470,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
| 2416 | else | 2470 | else |
| 2417 | rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1); | 2471 | rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1); |
| 2418 | rdc.block_length = cpu_to_be32(SECTOR_SIZE); | 2472 | rdc.block_length = cpu_to_be32(SECTOR_SIZE); |
| 2419 | gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data)); | 2473 | gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data), 0); |
| 2420 | break; | 2474 | break; |
| 2421 | 2475 | ||
| 2422 | case SERVICE_ACTION_IN: | 2476 | case SERVICE_ACTION_IN: |
| @@ -2428,7 +2482,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
| 2428 | rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1); | 2482 | rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1); |
| 2429 | rdc16.block_length = cpu_to_be32(SECTOR_SIZE); | 2483 | rdc16.block_length = cpu_to_be32(SECTOR_SIZE); |
| 2430 | gdth_copy_internal_data(ha, scp, (char*)&rdc16, | 2484 | gdth_copy_internal_data(ha, scp, (char*)&rdc16, |
| 2431 | sizeof(gdth_rdcap16_data)); | 2485 | sizeof(gdth_rdcap16_data), 0); |
| 2432 | } else { | 2486 | } else { |
| 2433 | scp->result = DID_ABORT << 16; | 2487 | scp->result = DID_ABORT << 16; |
| 2434 | } | 2488 | } |
| @@ -2451,13 +2505,9 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive) | |||
| 2451 | { | 2505 | { |
| 2452 | register gdth_cmd_str *cmdp; | 2506 | register gdth_cmd_str *cmdp; |
| 2453 | struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); | 2507 | struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); |
| 2454 | struct scatterlist *sl; | ||
| 2455 | ulong32 cnt, blockcnt; | 2508 | ulong32 cnt, blockcnt; |
| 2456 | ulong64 no, blockno; | 2509 | ulong64 no, blockno; |
| 2457 | dma_addr_t phys_addr; | ||
| 2458 | int i, cmd_index, read_write, sgcnt, mode64; | 2510 | int i, cmd_index, read_write, sgcnt, mode64; |
| 2459 | struct page *page; | ||
| 2460 | ulong offset; | ||
| 2461 | 2511 | ||
| 2462 | cmdp = ha->pccb; | 2512 | cmdp = ha->pccb; |
| 2463 | TRACE(("gdth_fill_cache_cmd() cmd 0x%x cmdsize %d hdrive %d\n", | 2513 | TRACE(("gdth_fill_cache_cmd() cmd 0x%x cmdsize %d hdrive %d\n", |
| @@ -2546,17 +2596,17 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive) | |||
| 2546 | cmdp->u.cache.BlockCnt = blockcnt; | 2596 | cmdp->u.cache.BlockCnt = blockcnt; |
| 2547 | } | 2597 | } |
| 2548 | 2598 | ||
| 2549 | if (scp->use_sg) { | 2599 | if (gdth_bufflen(scp)) { |
| 2550 | sl = (struct scatterlist *)scp->request_buffer; | ||
| 2551 | sgcnt = scp->use_sg; | ||
| 2552 | scp->SCp.Status = GDTH_MAP_SG; | ||
| 2553 | cmndinfo->dma_dir = (read_write == 1 ? | 2600 | cmndinfo->dma_dir = (read_write == 1 ? |
| 2554 | PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); | 2601 | PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); |
| 2555 | sgcnt = pci_map_sg(ha->pdev, sl, scp->use_sg, cmndinfo->dma_dir); | 2602 | sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp), |
| 2603 | cmndinfo->dma_dir); | ||
| 2556 | if (mode64) { | 2604 | if (mode64) { |
| 2605 | struct scatterlist *sl; | ||
| 2606 | |||
| 2557 | cmdp->u.cache64.DestAddr= (ulong64)-1; | 2607 | cmdp->u.cache64.DestAddr= (ulong64)-1; |
| 2558 | cmdp->u.cache64.sg_canz = sgcnt; | 2608 | cmdp->u.cache64.sg_canz = sgcnt; |
| 2559 | for (i=0; i<sgcnt; ++i,++sl) { | 2609 | scsi_for_each_sg(scp, sl, sgcnt, i) { |
| 2560 | cmdp->u.cache64.sg_lst[i].sg_ptr = sg_dma_address(sl); | 2610 | cmdp->u.cache64.sg_lst[i].sg_ptr = sg_dma_address(sl); |
| 2561 | #ifdef GDTH_DMA_STATISTICS | 2611 | #ifdef GDTH_DMA_STATISTICS |
| 2562 | if (cmdp->u.cache64.sg_lst[i].sg_ptr > (ulong64)0xffffffff) | 2612 | if (cmdp->u.cache64.sg_lst[i].sg_ptr > (ulong64)0xffffffff) |
| @@ -2567,9 +2617,11 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive) | |||
| 2567 | cmdp->u.cache64.sg_lst[i].sg_len = sg_dma_len(sl); | 2617 | cmdp->u.cache64.sg_lst[i].sg_len = sg_dma_len(sl); |
| 2568 | } | 2618 | } |
| 2569 | } else { | 2619 | } else { |
| 2620 | struct scatterlist *sl; | ||
| 2621 | |||
| 2570 | cmdp->u.cache.DestAddr= 0xffffffff; | 2622 | cmdp->u.cache.DestAddr= 0xffffffff; |
| 2571 | cmdp->u.cache.sg_canz = sgcnt; | 2623 | cmdp->u.cache.sg_canz = sgcnt; |
| 2572 | for (i=0; i<sgcnt; ++i,++sl) { | 2624 | scsi_for_each_sg(scp, sl, sgcnt, i) { |
| 2573 | cmdp->u.cache.sg_lst[i].sg_ptr = sg_dma_address(sl); | 2625 | cmdp->u.cache.sg_lst[i].sg_ptr = sg_dma_address(sl); |
| 2574 | #ifdef GDTH_DMA_STATISTICS | 2626 | #ifdef GDTH_DMA_STATISTICS |
| 2575 | ha->dma32_cnt++; | 2627 | ha->dma32_cnt++; |
| @@ -2585,38 +2637,6 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive) | |||
| 2585 | } | 2637 | } |
| 2586 | #endif | 2638 | #endif |
| 2587 | 2639 | ||
| 2588 | } else if (scp->request_bufflen) { | ||
| 2589 | scp->SCp.Status = GDTH_MAP_SINGLE; | ||
| 2590 | cmndinfo->dma_dir = (read_write == 1 ? | ||
| 2591 | PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); | ||
| 2592 | page = virt_to_page(scp->request_buffer); | ||
| 2593 | offset = (ulong)scp->request_buffer & ~PAGE_MASK; | ||
| 2594 | phys_addr = pci_map_page(ha->pdev,page,offset, | ||
| 2595 | scp->request_bufflen, cmndinfo->dma_dir); | ||
| 2596 | scp->SCp.dma_handle = phys_addr; | ||
| 2597 | if (mode64) { | ||
| 2598 | if (ha->cache_feat & SCATTER_GATHER) { | ||
| 2599 | cmdp->u.cache64.DestAddr = (ulong64)-1; | ||
| 2600 | cmdp->u.cache64.sg_canz = 1; | ||
| 2601 | cmdp->u.cache64.sg_lst[0].sg_ptr = phys_addr; | ||
| 2602 | cmdp->u.cache64.sg_lst[0].sg_len = scp->request_bufflen; | ||
| 2603 | cmdp->u.cache64.sg_lst[1].sg_len = 0; | ||
| 2604 | } else { | ||
| 2605 | cmdp->u.cache64.DestAddr = phys_addr; | ||
| 2606 | cmdp->u.cache64.sg_canz= 0; | ||
| 2607 | } | ||
| 2608 | } else { | ||
| 2609 | if (ha->cache_feat & SCATTER_GATHER) { | ||
| 2610 | cmdp->u.cache.DestAddr = 0xffffffff; | ||
| 2611 | cmdp->u.cache.sg_canz = 1; | ||
| 2612 | cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr; | ||
| 2613 | cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen; | ||
| 2614 | cmdp->u.cache.sg_lst[1].sg_len = 0; | ||
| 2615 | } else { | ||
| 2616 | cmdp->u.cache.DestAddr = phys_addr; | ||
| 2617 | cmdp->u.cache.sg_canz= 0; | ||
| 2618 | } | ||
| 2619 | } | ||
| 2620 | } | 2640 | } |
| 2621 | } | 2641 | } |
| 2622 | /* evaluate command size, check space */ | 2642 | /* evaluate command size, check space */ |
| @@ -2659,9 +2679,8 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive) | |||
| 2659 | static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) | 2679 | static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) |
| 2660 | { | 2680 | { |
| 2661 | register gdth_cmd_str *cmdp; | 2681 | register gdth_cmd_str *cmdp; |
| 2662 | struct scatterlist *sl; | ||
| 2663 | ushort i; | 2682 | ushort i; |
| 2664 | dma_addr_t phys_addr, sense_paddr; | 2683 | dma_addr_t sense_paddr; |
| 2665 | int cmd_index, sgcnt, mode64; | 2684 | int cmd_index, sgcnt, mode64; |
| 2666 | unchar t,l; | 2685 | unchar t,l; |
| 2667 | struct page *page; | 2686 | struct page *page; |
| @@ -2727,7 +2746,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) | |||
| 2727 | cmdp->u.raw64.lun = l; | 2746 | cmdp->u.raw64.lun = l; |
| 2728 | cmdp->u.raw64.bus = b; | 2747 | cmdp->u.raw64.bus = b; |
| 2729 | cmdp->u.raw64.priority = 0; | 2748 | cmdp->u.raw64.priority = 0; |
| 2730 | cmdp->u.raw64.sdlen = scp->request_bufflen; | 2749 | cmdp->u.raw64.sdlen = gdth_bufflen(scp); |
| 2731 | cmdp->u.raw64.sense_len = 16; | 2750 | cmdp->u.raw64.sense_len = 16; |
| 2732 | cmdp->u.raw64.sense_data = sense_paddr; | 2751 | cmdp->u.raw64.sense_data = sense_paddr; |
| 2733 | cmdp->u.raw64.direction = | 2752 | cmdp->u.raw64.direction = |
| @@ -2744,7 +2763,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) | |||
| 2744 | cmdp->u.raw.bus = b; | 2763 | cmdp->u.raw.bus = b; |
| 2745 | cmdp->u.raw.priority = 0; | 2764 | cmdp->u.raw.priority = 0; |
| 2746 | cmdp->u.raw.link_p = 0; | 2765 | cmdp->u.raw.link_p = 0; |
| 2747 | cmdp->u.raw.sdlen = scp->request_bufflen; | 2766 | cmdp->u.raw.sdlen = gdth_bufflen(scp); |
| 2748 | cmdp->u.raw.sense_len = 16; | 2767 | cmdp->u.raw.sense_len = 16; |
| 2749 | cmdp->u.raw.sense_data = sense_paddr; | 2768 | cmdp->u.raw.sense_data = sense_paddr; |
| 2750 | cmdp->u.raw.direction = | 2769 | cmdp->u.raw.direction = |
| @@ -2753,16 +2772,16 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) | |||
| 2753 | cmdp->u.raw.sg_ranz = 0; | 2772 | cmdp->u.raw.sg_ranz = 0; |
| 2754 | } | 2773 | } |
| 2755 | 2774 | ||
| 2756 | if (scp->use_sg) { | 2775 | if (gdth_bufflen(scp)) { |
| 2757 | sl = (struct scatterlist *)scp->request_buffer; | ||
| 2758 | sgcnt = scp->use_sg; | ||
| 2759 | scp->SCp.Status = GDTH_MAP_SG; | ||
| 2760 | cmndinfo->dma_dir = PCI_DMA_BIDIRECTIONAL; | 2776 | cmndinfo->dma_dir = PCI_DMA_BIDIRECTIONAL; |
| 2761 | sgcnt = pci_map_sg(ha->pdev,sl, scp->use_sg, cmndinfo->dma_dir); | 2777 | sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp), |
| 2778 | cmndinfo->dma_dir); | ||
| 2762 | if (mode64) { | 2779 | if (mode64) { |
| 2780 | struct scatterlist *sl; | ||
| 2781 | |||
| 2763 | cmdp->u.raw64.sdata = (ulong64)-1; | 2782 | cmdp->u.raw64.sdata = (ulong64)-1; |
| 2764 | cmdp->u.raw64.sg_ranz = sgcnt; | 2783 | cmdp->u.raw64.sg_ranz = sgcnt; |
| 2765 | for (i=0; i<sgcnt; ++i,++sl) { | 2784 | scsi_for_each_sg(scp, sl, sgcnt, i) { |
| 2766 | cmdp->u.raw64.sg_lst[i].sg_ptr = sg_dma_address(sl); | 2785 | cmdp->u.raw64.sg_lst[i].sg_ptr = sg_dma_address(sl); |
| 2767 | #ifdef GDTH_DMA_STATISTICS | 2786 | #ifdef GDTH_DMA_STATISTICS |
| 2768 | if (cmdp->u.raw64.sg_lst[i].sg_ptr > (ulong64)0xffffffff) | 2787 | if (cmdp->u.raw64.sg_lst[i].sg_ptr > (ulong64)0xffffffff) |
| @@ -2773,9 +2792,11 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) | |||
| 2773 | cmdp->u.raw64.sg_lst[i].sg_len = sg_dma_len(sl); | 2792 | cmdp->u.raw64.sg_lst[i].sg_len = sg_dma_len(sl); |
| 2774 | } | 2793 | } |
| 2775 | } else { | 2794 | } else { |
| 2795 | struct scatterlist *sl; | ||
| 2796 | |||
| 2776 | cmdp->u.raw.sdata = 0xffffffff; | 2797 | cmdp->u.raw.sdata = 0xffffffff; |
| 2777 | cmdp->u.raw.sg_ranz = sgcnt; | 2798 | cmdp->u.raw.sg_ranz = sgcnt; |
| 2778 | for (i=0; i<sgcnt; ++i,++sl) { | 2799 | scsi_for_each_sg(scp, sl, sgcnt, i) { |
| 2779 | cmdp->u.raw.sg_lst[i].sg_ptr = sg_dma_address(sl); | 2800 | cmdp->u.raw.sg_lst[i].sg_ptr = sg_dma_address(sl); |
| 2780 | #ifdef GDTH_DMA_STATISTICS | 2801 | #ifdef GDTH_DMA_STATISTICS |
| 2781 | ha->dma32_cnt++; | 2802 | ha->dma32_cnt++; |
| @@ -2791,38 +2812,6 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) | |||
| 2791 | } | 2812 | } |
| 2792 | #endif | 2813 | #endif |
| 2793 | 2814 | ||
| 2794 | } else if (scp->request_bufflen) { | ||
| 2795 | scp->SCp.Status = GDTH_MAP_SINGLE; | ||
| 2796 | cmndinfo->dma_dir = PCI_DMA_BIDIRECTIONAL; | ||
| 2797 | page = virt_to_page(scp->request_buffer); | ||
| 2798 | offset = (ulong)scp->request_buffer & ~PAGE_MASK; | ||
| 2799 | phys_addr = pci_map_page(ha->pdev,page,offset, | ||
| 2800 | scp->request_bufflen, cmndinfo->dma_dir); | ||
| 2801 | scp->SCp.dma_handle = phys_addr; | ||
| 2802 | |||
| 2803 | if (mode64) { | ||
| 2804 | if (ha->raw_feat & SCATTER_GATHER) { | ||
| 2805 | cmdp->u.raw64.sdata = (ulong64)-1; | ||
| 2806 | cmdp->u.raw64.sg_ranz= 1; | ||
| 2807 | cmdp->u.raw64.sg_lst[0].sg_ptr = phys_addr; | ||
| 2808 | cmdp->u.raw64.sg_lst[0].sg_len = scp->request_bufflen; | ||
| 2809 | cmdp->u.raw64.sg_lst[1].sg_len = 0; | ||
| 2810 | } else { | ||
| 2811 | cmdp->u.raw64.sdata = phys_addr; | ||
| 2812 | cmdp->u.raw64.sg_ranz= 0; | ||
| 2813 | } | ||
| 2814 | } else { | ||
| 2815 | if (ha->raw_feat & SCATTER_GATHER) { | ||
| 2816 | cmdp->u.raw.sdata = 0xffffffff; | ||
| 2817 | cmdp->u.raw.sg_ranz= 1; | ||
| 2818 | cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr; | ||
| 2819 | cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen; | ||
| 2820 | cmdp->u.raw.sg_lst[1].sg_len = 0; | ||
| 2821 | } else { | ||
| 2822 | cmdp->u.raw.sdata = phys_addr; | ||
| 2823 | cmdp->u.raw.sg_ranz= 0; | ||
| 2824 | } | ||
| 2825 | } | ||
| 2826 | } | 2815 | } |
| 2827 | if (mode64) { | 2816 | if (mode64) { |
| 2828 | TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", | 2817 | TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", |
| @@ -2871,7 +2860,7 @@ static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
| 2871 | if (ha->type==GDT_EISA && ha->cmd_cnt>0) | 2860 | if (ha->type==GDT_EISA && ha->cmd_cnt>0) |
| 2872 | return 0; | 2861 | return 0; |
| 2873 | 2862 | ||
| 2874 | memcpy( cmdp, scp->request_buffer, sizeof(gdth_cmd_str)); | 2863 | gdth_copy_internal_data(ha, scp, (char *)cmdp, sizeof(gdth_cmd_str), 1); |
| 2875 | cmdp->RequestBuffer = scp; | 2864 | cmdp->RequestBuffer = scp; |
| 2876 | 2865 | ||
| 2877 | /* search free command index */ | 2866 | /* search free command index */ |
| @@ -3404,12 +3393,10 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, | |||
| 3404 | /* retry */ | 3393 | /* retry */ |
| 3405 | return 2; | 3394 | return 2; |
| 3406 | } | 3395 | } |
| 3407 | if (scp->SCp.Status == GDTH_MAP_SG) | 3396 | if (gdth_bufflen(scp)) |
| 3408 | pci_unmap_sg(ha->pdev,scp->request_buffer, | 3397 | pci_unmap_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp), |
| 3409 | scp->use_sg, cmndinfo->dma_dir); | 3398 | cmndinfo->dma_dir); |
| 3410 | else if (scp->SCp.Status == GDTH_MAP_SINGLE) | 3399 | |
| 3411 | pci_unmap_page(ha->pdev,scp->SCp.dma_handle, | ||
| 3412 | scp->request_bufflen, cmndinfo->dma_dir); | ||
| 3413 | if (cmndinfo->sense_paddr) | 3400 | if (cmndinfo->sense_paddr) |
| 3414 | pci_unmap_page(ha->pdev, cmndinfo->sense_paddr, 16, | 3401 | pci_unmap_page(ha->pdev, cmndinfo->sense_paddr, 16, |
| 3415 | PCI_DMA_FROMDEVICE); | 3402 | PCI_DMA_FROMDEVICE); |
| @@ -4046,6 +4033,11 @@ static int gdth_queuecommand(struct scsi_cmnd *scp, | |||
| 4046 | scp->scsi_done = done; | 4033 | scp->scsi_done = done; |
| 4047 | gdth_update_timeout(scp, scp->timeout_per_command * 6); | 4034 | gdth_update_timeout(scp, scp->timeout_per_command * 6); |
| 4048 | cmndinfo->priority = DEFAULT_PRI; | 4035 | cmndinfo->priority = DEFAULT_PRI; |
| 4036 | |||
| 4037 | gdth_set_bufflen(scp, scsi_bufflen(scp)); | ||
| 4038 | gdth_set_sg_count(scp, scsi_sg_count(scp)); | ||
| 4039 | gdth_set_sglist(scp, scsi_sglist(scp)); | ||
| 4040 | |||
| 4049 | return __gdth_queuecommand(ha, scp, cmndinfo); | 4041 | return __gdth_queuecommand(ha, scp, cmndinfo); |
| 4050 | } | 4042 | } |
| 4051 | 4043 | ||
| @@ -4056,7 +4048,6 @@ static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp, | |||
| 4056 | cmndinfo->wait_for_completion = 1; | 4048 | cmndinfo->wait_for_completion = 1; |
| 4057 | cmndinfo->phase = -1; | 4049 | cmndinfo->phase = -1; |
| 4058 | cmndinfo->OpCode = -1; | 4050 | cmndinfo->OpCode = -1; |
| 4059 | scp->SCp.Status = GDTH_MAP_NONE; | ||
| 4060 | 4051 | ||
| 4061 | #ifdef GDTH_STATISTICS | 4052 | #ifdef GDTH_STATISTICS |
| 4062 | ++act_ios; | 4053 | ++act_ios; |
| @@ -4626,7 +4617,6 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, | |||
| 4626 | return -ENOMEM; | 4617 | return -ENOMEM; |
| 4627 | scp->device = ha->sdev; | 4618 | scp->device = ha->sdev; |
| 4628 | scp->cmd_len = 12; | 4619 | scp->cmd_len = 12; |
| 4629 | scp->use_sg = 0; | ||
| 4630 | scp->device->channel = res.number; | 4620 | scp->device->channel = res.number; |
| 4631 | rval = gdth_eh_bus_reset(scp); | 4621 | rval = gdth_eh_bus_reset(scp); |
| 4632 | res.status = (rval == SUCCESS ? S_OK : S_GENERR); | 4622 | res.status = (rval == SUCCESS ? S_OK : S_GENERR); |
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index 25803a8f31de..1434c6b0297c 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h | |||
| @@ -303,15 +303,8 @@ | |||
| 303 | #define MAILBOXREG 0x0c90 /* mailbox reg. (16 bytes) */ | 303 | #define MAILBOXREG 0x0c90 /* mailbox reg. (16 bytes) */ |
| 304 | #define EISAREG 0x0cc0 /* EISA configuration */ | 304 | #define EISAREG 0x0cc0 /* EISA configuration */ |
| 305 | 305 | ||
| 306 | /* DMA memory mappings */ | ||
| 307 | #define GDTH_MAP_NONE 0 | ||
| 308 | #define GDTH_MAP_SINGLE 1 | ||
| 309 | #define GDTH_MAP_SG 2 | ||
| 310 | #define GDTH_MAP_IOCTL 3 | ||
| 311 | |||
| 312 | /* other defines */ | 306 | /* other defines */ |
| 313 | #define LINUX_OS 8 /* used for cache optim. */ | 307 | #define LINUX_OS 8 /* used for cache optim. */ |
| 314 | #define SCATTER_GATHER 1 /* s/g feature */ | ||
| 315 | #define SECS32 0x1f /* round capacity */ | 308 | #define SECS32 0x1f /* round capacity */ |
| 316 | #define BIOS_ID_OFFS 0x10 /* offset contr-ID in ISABIOS */ | 309 | #define BIOS_ID_OFFS 0x10 /* offset contr-ID in ISABIOS */ |
| 317 | #define LOCALBOARD 0 /* board node always 0 */ | 310 | #define LOCALBOARD 0 /* board node always 0 */ |
