diff options
author | James Bottomley <James.Bottomley@steeleye.com> | 2005-05-08 17:00:15 -0400 |
---|---|---|
committer | James Bottomley <jejb@titanic.(none)> | 2005-05-20 16:54:33 -0400 |
commit | fad01ef88d2a27303757924c1fc013b31fe9a76b (patch) | |
tree | 8f1fe69d0610117452335a4b5224c856c8f2d256 /drivers/scsi/aic7xxx | |
parent | 62a8612972eaea804e1e42c63ee403cd4e14cc35 (diff) |
[SCSI] correct aic7xxx period setting routines
This is similar to the previous sym2 problem. For Domain Validation to
work we can't allow any period setting to turn wide on if it was
previously off.
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aic7xxx')
-rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm.c | 71 |
1 files changed, 37 insertions, 34 deletions
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index d978e4a3e973..0ed9ccc3091e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -3346,6 +3346,32 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc) | |||
3346 | 3346 | ||
3347 | static void ahc_linux_exit(void); | 3347 | static void ahc_linux_exit(void); |
3348 | 3348 | ||
3349 | static void ahc_linux_get_width(struct scsi_target *starget) | ||
3350 | { | ||
3351 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
3352 | struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata); | ||
3353 | struct ahc_tmode_tstate *tstate; | ||
3354 | struct ahc_initiator_tinfo *tinfo | ||
3355 | = ahc_fetch_transinfo(ahc, | ||
3356 | starget->channel + 'A', | ||
3357 | shost->this_id, starget->id, &tstate); | ||
3358 | spi_width(starget) = tinfo->curr.width; | ||
3359 | } | ||
3360 | |||
3361 | static void ahc_linux_set_width(struct scsi_target *starget, int width) | ||
3362 | { | ||
3363 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
3364 | struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata); | ||
3365 | struct ahc_devinfo devinfo; | ||
3366 | unsigned long flags; | ||
3367 | |||
3368 | ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
3369 | starget->channel + 'A', ROLE_INITIATOR); | ||
3370 | ahc_lock(ahc, &flags); | ||
3371 | ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE); | ||
3372 | ahc_unlock(ahc, &flags); | ||
3373 | } | ||
3374 | |||
3349 | static void ahc_linux_get_period(struct scsi_target *starget) | 3375 | static void ahc_linux_get_period(struct scsi_target *starget) |
3350 | { | 3376 | { |
3351 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 3377 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
@@ -3378,6 +3404,14 @@ static void ahc_linux_set_period(struct scsi_target *starget, int period) | |||
3378 | 3404 | ||
3379 | ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | 3405 | ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, |
3380 | starget->channel + 'A', ROLE_INITIATOR); | 3406 | starget->channel + 'A', ROLE_INITIATOR); |
3407 | |||
3408 | /* all PPR requests apart from QAS require wide transfers */ | ||
3409 | if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) { | ||
3410 | ahc_linux_get_width(starget); | ||
3411 | if (spi_width(starget) == 0) | ||
3412 | ppr_options &= MSG_EXT_PPR_QAS_REQ; | ||
3413 | } | ||
3414 | |||
3381 | syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT); | 3415 | syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT); |
3382 | ahc_lock(ahc, &flags); | 3416 | ahc_lock(ahc, &flags); |
3383 | ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset, | 3417 | ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset, |
@@ -3425,32 +3459,6 @@ static void ahc_linux_set_offset(struct scsi_target *starget, int offset) | |||
3425 | ahc_unlock(ahc, &flags); | 3459 | ahc_unlock(ahc, &flags); |
3426 | } | 3460 | } |
3427 | 3461 | ||
3428 | static void ahc_linux_get_width(struct scsi_target *starget) | ||
3429 | { | ||
3430 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
3431 | struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata); | ||
3432 | struct ahc_tmode_tstate *tstate; | ||
3433 | struct ahc_initiator_tinfo *tinfo | ||
3434 | = ahc_fetch_transinfo(ahc, | ||
3435 | starget->channel + 'A', | ||
3436 | shost->this_id, starget->id, &tstate); | ||
3437 | spi_width(starget) = tinfo->curr.width; | ||
3438 | } | ||
3439 | |||
3440 | static void ahc_linux_set_width(struct scsi_target *starget, int width) | ||
3441 | { | ||
3442 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
3443 | struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata); | ||
3444 | struct ahc_devinfo devinfo; | ||
3445 | unsigned long flags; | ||
3446 | |||
3447 | ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | ||
3448 | starget->channel + 'A', ROLE_INITIATOR); | ||
3449 | ahc_lock(ahc, &flags); | ||
3450 | ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE); | ||
3451 | ahc_unlock(ahc, &flags); | ||
3452 | } | ||
3453 | |||
3454 | static void ahc_linux_get_dt(struct scsi_target *starget) | 3462 | static void ahc_linux_get_dt(struct scsi_target *starget) |
3455 | { | 3463 | { |
3456 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 3464 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
@@ -3481,8 +3489,7 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt) | |||
3481 | 3489 | ||
3482 | ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | 3490 | ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, |
3483 | starget->channel + 'A', ROLE_INITIATOR); | 3491 | starget->channel + 'A', ROLE_INITIATOR); |
3484 | syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, | 3492 | syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,AHC_SYNCRATE_DT); |
3485 | dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2); | ||
3486 | ahc_lock(ahc, &flags); | 3493 | ahc_lock(ahc, &flags); |
3487 | ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset, | 3494 | ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset, |
3488 | ppr_options, AHC_TRANS_GOAL, FALSE); | 3495 | ppr_options, AHC_TRANS_GOAL, FALSE); |
@@ -3514,7 +3521,6 @@ static void ahc_linux_set_qas(struct scsi_target *starget, int qas) | |||
3514 | unsigned int ppr_options = tinfo->curr.ppr_options | 3521 | unsigned int ppr_options = tinfo->curr.ppr_options |
3515 | & ~MSG_EXT_PPR_QAS_REQ; | 3522 | & ~MSG_EXT_PPR_QAS_REQ; |
3516 | unsigned int period = tinfo->curr.period; | 3523 | unsigned int period = tinfo->curr.period; |
3517 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
3518 | unsigned long flags; | 3524 | unsigned long flags; |
3519 | struct ahc_syncrate *syncrate; | 3525 | struct ahc_syncrate *syncrate; |
3520 | 3526 | ||
@@ -3523,8 +3529,7 @@ static void ahc_linux_set_qas(struct scsi_target *starget, int qas) | |||
3523 | 3529 | ||
3524 | ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | 3530 | ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, |
3525 | starget->channel + 'A', ROLE_INITIATOR); | 3531 | starget->channel + 'A', ROLE_INITIATOR); |
3526 | syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, | 3532 | syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT); |
3527 | dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2); | ||
3528 | ahc_lock(ahc, &flags); | 3533 | ahc_lock(ahc, &flags); |
3529 | ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset, | 3534 | ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset, |
3530 | ppr_options, AHC_TRANS_GOAL, FALSE); | 3535 | ppr_options, AHC_TRANS_GOAL, FALSE); |
@@ -3556,7 +3561,6 @@ static void ahc_linux_set_iu(struct scsi_target *starget, int iu) | |||
3556 | unsigned int ppr_options = tinfo->curr.ppr_options | 3561 | unsigned int ppr_options = tinfo->curr.ppr_options |
3557 | & ~MSG_EXT_PPR_IU_REQ; | 3562 | & ~MSG_EXT_PPR_IU_REQ; |
3558 | unsigned int period = tinfo->curr.period; | 3563 | unsigned int period = tinfo->curr.period; |
3559 | unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; | ||
3560 | unsigned long flags; | 3564 | unsigned long flags; |
3561 | struct ahc_syncrate *syncrate; | 3565 | struct ahc_syncrate *syncrate; |
3562 | 3566 | ||
@@ -3565,8 +3569,7 @@ static void ahc_linux_set_iu(struct scsi_target *starget, int iu) | |||
3565 | 3569 | ||
3566 | ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, | 3570 | ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, |
3567 | starget->channel + 'A', ROLE_INITIATOR); | 3571 | starget->channel + 'A', ROLE_INITIATOR); |
3568 | syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, | 3572 | syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT); |
3569 | dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2); | ||
3570 | ahc_lock(ahc, &flags); | 3573 | ahc_lock(ahc, &flags); |
3571 | ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset, | 3574 | ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset, |
3572 | ppr_options, AHC_TRANS_GOAL, FALSE); | 3575 | ppr_options, AHC_TRANS_GOAL, FALSE); |