diff options
author | Matthew Wilcox <matthew@wil.cx> | 2005-05-20 14:15:43 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-05-26 09:41:14 -0400 |
commit | 53222b906903fd861dc24ebccfa07ee125941313 (patch) | |
tree | a39e9a20718d01b67e89c14baa0e11411643c993 /drivers/scsi/sym53c8xx_2/sym_glue.c | |
parent | 7c00ffa314bf0fb0e23858bbebad33b48b6abbb9 (diff) |
[SCSI] sym2 version 2.2.1
sym2 version 2.2.1:
- Fix MMIO BAR detection (Thanks to Bob Picco)
- Fix odd-sized transfers with a wide bus (Thanks to Larry Stephens)
- Write posting fixes (Thanks to Thibaut Varene)
- Change one of the GFP_KERNEL allocations back into a GFP_ATOMIC
- Make CCB_BA() return a script-endian address
- Move range checks and disabling of devices from the queuecommand path
to slave_alloc()
- Remove a warning in sym_setup_cdb()
- Keep a pointer to the scsi_target instead of the scsi_dev in the tcb
- Remove a check for the upper layers passing an oversized cmd
- Replace CAM_REQ_ constants with the Linux DID_ constants
- Replace CAM_DIR_ constants with the Linux DMA_ constants
- Inline sym_read_parisc_pdc() on non-parisc systems
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/sym53c8xx_2/sym_glue.c')
-rw-r--r-- | drivers/scsi/sym53c8xx_2/sym_glue.c | 120 |
1 files changed, 53 insertions, 67 deletions
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 5b07c6ec3ec..be58ffd5a43 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c | |||
@@ -155,10 +155,11 @@ pci_get_base_address(struct pci_dev *pdev, int index, unsigned long *basep) | |||
155 | base = tmp; | 155 | base = tmp; |
156 | if ((tmp & 0x7) == PCI_BASE_ADDRESS_MEM_TYPE_64) { | 156 | if ((tmp & 0x7) == PCI_BASE_ADDRESS_MEM_TYPE_64) { |
157 | pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp); | 157 | pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp); |
158 | if (tmp > 0) | 158 | if (tmp > 0) { |
159 | dev_err(&pdev->dev, | 159 | dev_err(&pdev->dev, |
160 | "BAR %d is 64-bit, disabling\n", index - 1); | 160 | "BAR %d is 64-bit, disabling\n", index - 1); |
161 | base = 0; | 161 | base = 0; |
162 | } | ||
162 | } | 163 | } |
163 | 164 | ||
164 | if ((base & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { | 165 | if ((base & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { |
@@ -389,13 +390,20 @@ static int sym_scatter_no_sglist(struct sym_hcb *np, struct sym_ccb *cp, struct | |||
389 | { | 390 | { |
390 | struct sym_tblmove *data = &cp->phys.data[SYM_CONF_MAX_SG-1]; | 391 | struct sym_tblmove *data = &cp->phys.data[SYM_CONF_MAX_SG-1]; |
391 | int segment; | 392 | int segment; |
393 | unsigned int len = cmd->request_bufflen; | ||
392 | 394 | ||
393 | cp->data_len = cmd->request_bufflen; | 395 | if (len) { |
394 | |||
395 | if (cmd->request_bufflen) { | ||
396 | dma_addr_t baddr = map_scsi_single_data(np, cmd); | 396 | dma_addr_t baddr = map_scsi_single_data(np, cmd); |
397 | if (baddr) { | 397 | if (baddr) { |
398 | sym_build_sge(np, data, baddr, cmd->request_bufflen); | 398 | if (len & 1) { |
399 | struct sym_tcb *tp = &np->target[cp->target]; | ||
400 | if (tp->head.wval & EWS) { | ||
401 | len++; | ||
402 | cp->odd_byte_adjustment++; | ||
403 | } | ||
404 | } | ||
405 | cp->data_len = len; | ||
406 | sym_build_sge(np, data, baddr, len); | ||
399 | segment = 1; | 407 | segment = 1; |
400 | } else { | 408 | } else { |
401 | segment = -2; | 409 | segment = -2; |
@@ -418,6 +426,7 @@ static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd | |||
418 | segment = sym_scatter_no_sglist(np, cp, cmd); | 426 | segment = sym_scatter_no_sglist(np, cp, cmd); |
419 | else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) { | 427 | else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) { |
420 | struct scatterlist *scatter = (struct scatterlist *)cmd->buffer; | 428 | struct scatterlist *scatter = (struct scatterlist *)cmd->buffer; |
429 | struct sym_tcb *tp = &np->target[cp->target]; | ||
421 | struct sym_tblmove *data; | 430 | struct sym_tblmove *data; |
422 | 431 | ||
423 | if (use_sg > SYM_CONF_MAX_SG) { | 432 | if (use_sg > SYM_CONF_MAX_SG) { |
@@ -431,6 +440,11 @@ static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd | |||
431 | dma_addr_t baddr = sg_dma_address(&scatter[segment]); | 440 | dma_addr_t baddr = sg_dma_address(&scatter[segment]); |
432 | unsigned int len = sg_dma_len(&scatter[segment]); | 441 | unsigned int len = sg_dma_len(&scatter[segment]); |
433 | 442 | ||
443 | if ((len & 1) && (tp->head.wval & EWS)) { | ||
444 | len++; | ||
445 | cp->odd_byte_adjustment++; | ||
446 | } | ||
447 | |||
434 | sym_build_sge(np, &data[segment], baddr, len); | 448 | sym_build_sge(np, &data[segment], baddr, len); |
435 | cp->data_len += len; | 449 | cp->data_len += len; |
436 | } | 450 | } |
@@ -456,10 +470,8 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *cmd) | |||
456 | * Minimal checkings, so that we will not | 470 | * Minimal checkings, so that we will not |
457 | * go outside our tables. | 471 | * go outside our tables. |
458 | */ | 472 | */ |
459 | if (sdev->id == np->myaddr || | 473 | if (sdev->id == np->myaddr) { |
460 | sdev->id >= SYM_CONF_MAX_TARGET || | 474 | sym_xpt_done2(np, cmd, DID_NO_CONNECT); |
461 | sdev->lun >= SYM_CONF_MAX_LUN) { | ||
462 | sym_xpt_done2(np, cmd, CAM_DEV_NOT_THERE); | ||
463 | return 0; | 475 | return 0; |
464 | } | 476 | } |
465 | 477 | ||
@@ -469,28 +481,6 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *cmd) | |||
469 | tp = &np->target[sdev->id]; | 481 | tp = &np->target[sdev->id]; |
470 | 482 | ||
471 | /* | 483 | /* |
472 | * Complete the 1st INQUIRY command with error | ||
473 | * condition if the device is flagged NOSCAN | ||
474 | * at BOOT in the NVRAM. This may speed up | ||
475 | * the boot and maintain coherency with BIOS | ||
476 | * device numbering. Clearing the flag allows | ||
477 | * user to rescan skipped devices later. | ||
478 | * We also return error for devices not flagged | ||
479 | * for SCAN LUNS in the NVRAM since some mono-lun | ||
480 | * devices behave badly when asked for some non | ||
481 | * zero LUN. Btw, this is an absolute hack.:-) | ||
482 | */ | ||
483 | if (cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 0x0) { | ||
484 | if ((tp->usrflags & SYM_SCAN_BOOT_DISABLED) || | ||
485 | ((tp->usrflags & SYM_SCAN_LUNS_DISABLED) && | ||
486 | sdev->lun != 0)) { | ||
487 | tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED; | ||
488 | sym_xpt_done2(np, cmd, CAM_DEV_NOT_THERE); | ||
489 | return 0; | ||
490 | } | ||
491 | } | ||
492 | |||
493 | /* | ||
494 | * Select tagged/untagged. | 484 | * Select tagged/untagged. |
495 | */ | 485 | */ |
496 | lp = sym_lp(tp, sdev->lun); | 486 | lp = sym_lp(tp, sdev->lun); |
@@ -511,23 +501,10 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *cmd) | |||
511 | */ | 501 | */ |
512 | static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp) | 502 | static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp) |
513 | { | 503 | { |
514 | u32 cmd_ba; | ||
515 | int cmd_len; | ||
516 | |||
517 | /* | ||
518 | * CDB is 16 bytes max. | ||
519 | */ | ||
520 | if (cmd->cmd_len > sizeof(cp->cdb_buf)) { | ||
521 | sym_set_cam_status(cp->cmd, CAM_REQ_INVALID); | ||
522 | return -1; | ||
523 | } | ||
524 | |||
525 | memcpy(cp->cdb_buf, cmd->cmnd, cmd->cmd_len); | 504 | memcpy(cp->cdb_buf, cmd->cmnd, cmd->cmd_len); |
526 | cmd_ba = CCB_BA (cp, cdb_buf[0]); | ||
527 | cmd_len = cmd->cmd_len; | ||
528 | 505 | ||
529 | cp->phys.cmd.addr = cpu_to_scr(cmd_ba); | 506 | cp->phys.cmd.addr = CCB_BA(cp, cdb_buf[0]); |
530 | cp->phys.cmd.size = cpu_to_scr(cmd_len); | 507 | cp->phys.cmd.size = cpu_to_scr(cmd->cmd_len); |
531 | 508 | ||
532 | return 0; | 509 | return 0; |
533 | } | 510 | } |
@@ -554,10 +531,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s | |||
554 | if (dir != DMA_NONE) { | 531 | if (dir != DMA_NONE) { |
555 | cp->segments = sym_scatter(np, cp, cmd); | 532 | cp->segments = sym_scatter(np, cp, cmd); |
556 | if (cp->segments < 0) { | 533 | if (cp->segments < 0) { |
557 | if (cp->segments == -2) | 534 | sym_set_cam_status(cmd, DID_ERROR); |
558 | sym_set_cam_status(cmd, CAM_RESRC_UNAVAIL); | ||
559 | else | ||
560 | sym_set_cam_status(cmd, CAM_REQ_TOO_BIG); | ||
561 | goto out_abort; | 535 | goto out_abort; |
562 | } | 536 | } |
563 | } else { | 537 | } else { |
@@ -855,7 +829,7 @@ prepare: | |||
855 | ep->to_do = to_do; | 829 | ep->to_do = to_do; |
856 | /* Complete the command with locks held as required by the driver */ | 830 | /* Complete the command with locks held as required by the driver */ |
857 | if (to_do == SYM_EH_DO_COMPLETE) | 831 | if (to_do == SYM_EH_DO_COMPLETE) |
858 | sym_xpt_done2(np, cmd, CAM_REQ_ABORTED); | 832 | sym_xpt_done2(np, cmd, DID_ABORT); |
859 | 833 | ||
860 | /* Wait for completion with locks released, as required by kernel */ | 834 | /* Wait for completion with locks released, as required by kernel */ |
861 | if (to_do == SYM_EH_DO_WAIT) { | 835 | if (to_do == SYM_EH_DO_WAIT) { |
@@ -921,7 +895,7 @@ static void sym_tune_dev_queuing(struct sym_tcb *tp, int lun, u_short reqtags) | |||
921 | lp->s.reqtags = reqtags; | 895 | lp->s.reqtags = reqtags; |
922 | 896 | ||
923 | if (reqtags != oldtags) { | 897 | if (reqtags != oldtags) { |
924 | dev_info(&tp->sdev->sdev_target->dev, | 898 | dev_info(&tp->starget->dev, |
925 | "tagged command queuing %s, command queue depth %d.\n", | 899 | "tagged command queuing %s, command queue depth %d.\n", |
926 | lp->s.reqtags ? "enabled" : "disabled", | 900 | lp->s.reqtags ? "enabled" : "disabled", |
927 | lp->started_limit); | 901 | lp->started_limit); |
@@ -981,22 +955,34 @@ static int device_queue_depth(struct sym_hcb *np, int target, int lun) | |||
981 | return DEF_DEPTH; | 955 | return DEF_DEPTH; |
982 | } | 956 | } |
983 | 957 | ||
984 | static int sym53c8xx_slave_alloc(struct scsi_device *device) | 958 | static int sym53c8xx_slave_alloc(struct scsi_device *sdev) |
985 | { | 959 | { |
986 | struct sym_hcb *np = sym_get_hcb(device->host); | 960 | struct sym_hcb *np; |
987 | struct sym_tcb *tp = &np->target[device->id]; | 961 | struct sym_tcb *tp; |
988 | if (!tp->sdev) | ||
989 | tp->sdev = device; | ||
990 | 962 | ||
991 | return 0; | 963 | if (sdev->id >= SYM_CONF_MAX_TARGET || sdev->lun >= SYM_CONF_MAX_LUN) |
992 | } | 964 | return -ENXIO; |
993 | 965 | ||
994 | static void sym53c8xx_slave_destroy(struct scsi_device *device) | 966 | np = sym_get_hcb(sdev->host); |
995 | { | 967 | tp = &np->target[sdev->id]; |
996 | struct sym_hcb *np = sym_get_hcb(device->host); | 968 | |
997 | struct sym_tcb *tp = &np->target[device->id]; | 969 | /* |
998 | if (tp->sdev == device) | 970 | * Fail the device init if the device is flagged NOSCAN at BOOT in |
999 | tp->sdev = NULL; | 971 | * the NVRAM. This may speed up boot and maintain coherency with |
972 | * BIOS device numbering. Clearing the flag allows the user to | ||
973 | * rescan skipped devices later. We also return an error for | ||
974 | * devices not flagged for SCAN LUNS in the NVRAM since some single | ||
975 | * lun devices behave badly when asked for a non zero LUN. | ||
976 | */ | ||
977 | |||
978 | if ((tp->usrflags & SYM_SCAN_BOOT_DISABLED) || | ||
979 | ((tp->usrflags & SYM_SCAN_LUNS_DISABLED) && sdev->lun != 0)) { | ||
980 | tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED; | ||
981 | return -ENXIO; | ||
982 | } | ||
983 | |||
984 | tp->starget = sdev->sdev_target; | ||
985 | return 0; | ||
1000 | } | 986 | } |
1001 | 987 | ||
1002 | /* | 988 | /* |
@@ -1897,6 +1883,7 @@ static int sym_detach(struct sym_hcb *np, struct pci_dev *pdev) | |||
1897 | */ | 1883 | */ |
1898 | printk("%s: resetting chip\n", sym_name(np)); | 1884 | printk("%s: resetting chip\n", sym_name(np)); |
1899 | OUTB(np, nc_istat, SRST); | 1885 | OUTB(np, nc_istat, SRST); |
1886 | INB(np, nc_mbox1); | ||
1900 | udelay(10); | 1887 | udelay(10); |
1901 | OUTB(np, nc_istat, 0); | 1888 | OUTB(np, nc_istat, 0); |
1902 | 1889 | ||
@@ -1915,7 +1902,6 @@ static struct scsi_host_template sym2_template = { | |||
1915 | .queuecommand = sym53c8xx_queue_command, | 1902 | .queuecommand = sym53c8xx_queue_command, |
1916 | .slave_alloc = sym53c8xx_slave_alloc, | 1903 | .slave_alloc = sym53c8xx_slave_alloc, |
1917 | .slave_configure = sym53c8xx_slave_configure, | 1904 | .slave_configure = sym53c8xx_slave_configure, |
1918 | .slave_destroy = sym53c8xx_slave_destroy, | ||
1919 | .eh_abort_handler = sym53c8xx_eh_abort_handler, | 1905 | .eh_abort_handler = sym53c8xx_eh_abort_handler, |
1920 | .eh_device_reset_handler = sym53c8xx_eh_device_reset_handler, | 1906 | .eh_device_reset_handler = sym53c8xx_eh_device_reset_handler, |
1921 | .eh_bus_reset_handler = sym53c8xx_eh_bus_reset_handler, | 1907 | .eh_bus_reset_handler = sym53c8xx_eh_bus_reset_handler, |