Commit e8cc7930 authored by Justin T. Gibbs's avatar Justin T. Gibbs

aic7xxx and aic79xx drivers Correct several DV issues:

 o Do not fallback to a wide speed if the device does not support
   wide transfers.

 o Don't bother allocating target instances for wide IDs on narrow
   controllers.

 o Add a few additional diagnostics to aid in tracking down DV bugs.
parent f1265323
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#148 $ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#150 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
...@@ -2321,13 +2321,13 @@ ahd_find_syncrate(struct ahd_softc *ahd, u_int *period, ...@@ -2321,13 +2321,13 @@ ahd_find_syncrate(struct ahd_softc *ahd, u_int *period,
/* Skip all PACED only entries if IU is not available */ /* Skip all PACED only entries if IU is not available */
if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0 if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0
&& maxsync < AHD_SYNCRATE_DT) && *period < AHD_SYNCRATE_DT)
maxsync = AHD_SYNCRATE_DT; *period = AHD_SYNCRATE_DT;
/* Skip all DT only entries if DT is not available */ /* Skip all DT only entries if DT is not available */
if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0 if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
&& maxsync < AHD_SYNCRATE_ULTRA2) && *period < AHD_SYNCRATE_ULTRA2)
maxsync = AHD_SYNCRATE_ULTRA2; *period = AHD_SYNCRATE_ULTRA2;
} }
/* /*
...@@ -5680,7 +5680,8 @@ ahd_init(struct ahd_softc *ahd) ...@@ -5680,7 +5680,8 @@ ahd_init(struct ahd_softc *ahd)
/*lowaddr*/BUS_SPACE_MAXADDR, /*lowaddr*/BUS_SPACE_MAXADDR,
/*highaddr*/BUS_SPACE_MAXADDR, /*highaddr*/BUS_SPACE_MAXADDR,
/*filter*/NULL, /*filterarg*/NULL, /*filter*/NULL, /*filterarg*/NULL,
/*maxsize*/MAXBSIZE, /*nsegments*/AHD_NSEG, /*maxsize*/(AHD_NSEG - 1) * PAGE_SIZE,
/*nsegments*/AHD_NSEG,
/*maxsegsz*/AHD_MAXTRANSFER_SIZE, /*maxsegsz*/AHD_MAXTRANSFER_SIZE,
/*flags*/BUS_DMA_ALLOCNOW, /*flags*/BUS_DMA_ALLOCNOW,
&ahd->buffer_dmat) != 0) { &ahd->buffer_dmat) != 0) {
...@@ -7856,7 +7857,8 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) ...@@ -7856,7 +7857,8 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb)
#ifdef AHD_DEBUG #ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_MISC) != 0) { if ((ahd_debug & AHD_SHOW_MISC) != 0) {
ahd_print_path(ahd, scb); ahd_print_path(ahd, scb);
printf("Handled Residual of %d bytes\n", resid); printf("Handled %sResidual of %d bytes\n",
(scb->flags & SCB_SENSE) ? "Sense " : "", resid);
} }
#endif #endif
} }
......
/* /*
* Adaptec AIC79xx device driver for Linux. * Adaptec AIC79xx device driver for Linux.
* *
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#103 $ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#104 $
* *
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Copyright (c) 1994-2000 Justin T. Gibbs. * Copyright (c) 1994-2000 Justin T. Gibbs.
...@@ -2058,7 +2058,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) ...@@ -2058,7 +2058,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
* negotiation will occur for the first command, and DV * negotiation will occur for the first command, and DV
* will comence should that first command be successful. * will comence should that first command be successful.
*/ */
for (target = 0; target < AHD_NUM_TARGETS; target++) for (target = 0; target < host->max_id; target++)
ahd_linux_alloc_target(ahd, 0, target); ahd_linux_alloc_target(ahd, 0, target);
ahd_intr_enable(ahd, TRUE); ahd_intr_enable(ahd, TRUE);
ahd_linux_start_dv(ahd); ahd_linux_start_dv(ahd);
...@@ -2883,6 +2883,23 @@ ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd, ...@@ -2883,6 +2883,23 @@ ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
break; break;
} }
#ifdef AHD_DEBUG
if (ahd_debug & AHD_SHOW_DV) {
int i;
ahd_print_devinfo(ahd, devinfo);
printf("Inquiry buffer mismatch:");
for (i = 0; i < AHD_LINUX_DV_INQ_LEN; i++) {
if ((i & 0xF) == 0)
printf("\n ");
printf("0x%x:0x0%x ",
((uint8_t *)targ->inq_data)[i],
targ->dv_buffer[i]);
}
printf("\n");
}
#endif
if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
break; break;
...@@ -3525,6 +3542,8 @@ ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) ...@@ -3525,6 +3542,8 @@ ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
targ->dv_next_narrow_period = MAX(period, AHD_SYNCRATE_ULTRA2); targ->dv_next_narrow_period = MAX(period, AHD_SYNCRATE_ULTRA2);
if (targ->dv_next_wide_period == 0) if (targ->dv_next_wide_period == 0)
targ->dv_next_wide_period = period; targ->dv_next_wide_period = period;
if (targ->dv_max_width == 0)
targ->dv_max_width = width;
if (targ->dv_max_ppr_options == 0) if (targ->dv_max_ppr_options == 0)
targ->dv_max_ppr_options = ppr_options; targ->dv_max_ppr_options = ppr_options;
if (targ->dv_last_ppr_options == 0) if (targ->dv_last_ppr_options == 0)
...@@ -3619,7 +3638,7 @@ ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) ...@@ -3619,7 +3638,7 @@ ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
period++; period++;
} }
} else if ((ahd->features & AHD_WIDE) != 0 } else if ((ahd->features & AHD_WIDE) != 0
&& tinfo->user.width != 0 && targ->dv_max_width != 0
&& wide_speed >= fallback_speed && wide_speed >= fallback_speed
&& (targ->dv_next_wide_period <= AHD_ASYNC_XFER_PERIOD && (targ->dv_next_wide_period <= AHD_ASYNC_XFER_PERIOD
|| period >= AHD_ASYNC_XFER_PERIOD)) { || period >= AHD_ASYNC_XFER_PERIOD)) {
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#99 $ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#100 $
* *
*/ */
#ifndef _AIC79XX_LINUX_H_ #ifndef _AIC79XX_LINUX_H_
...@@ -458,10 +458,11 @@ struct ahd_linux_target { ...@@ -458,10 +458,11 @@ struct ahd_linux_target {
/* /*
* The next "fallback" period to use for narrow/wide transfers. * The next "fallback" period to use for narrow/wide transfers.
*/ */
u_int dv_next_narrow_period; uint8_t dv_next_narrow_period;
u_int dv_next_wide_period; uint8_t dv_next_wide_period;
u_int dv_max_ppr_options; uint8_t dv_max_width;
u_int dv_last_ppr_options; uint8_t dv_max_ppr_options;
uint8_t dv_last_ppr_options;
u_int dv_echo_size; u_int dv_echo_size;
ahd_dv_state dv_state; ahd_dv_state dv_state;
u_int dv_state_retry; u_int dv_state_retry;
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#105 $ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#107 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
...@@ -4602,7 +4602,8 @@ ahc_init(struct ahc_softc *ahc) ...@@ -4602,7 +4602,8 @@ ahc_init(struct ahc_softc *ahc)
/*lowaddr*/BUS_SPACE_MAXADDR, /*lowaddr*/BUS_SPACE_MAXADDR,
/*highaddr*/BUS_SPACE_MAXADDR, /*highaddr*/BUS_SPACE_MAXADDR,
/*filter*/NULL, /*filterarg*/NULL, /*filter*/NULL, /*filterarg*/NULL,
/*maxsize*/MAXBSIZE, /*nsegments*/AHC_NSEG, /*maxsize*/(AHC_NSEG - 1) * PAGE_SIZE,
/*nsegments*/AHC_NSEG,
/*maxsegsz*/AHC_MAXTRANSFER_SIZE, /*maxsegsz*/AHC_MAXTRANSFER_SIZE,
/*flags*/BUS_DMA_ALLOCNOW, /*flags*/BUS_DMA_ALLOCNOW,
&ahc->buffer_dmat) != 0) { &ahc->buffer_dmat) != 0) {
...@@ -6275,7 +6276,8 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb) ...@@ -6275,7 +6276,8 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb)
#ifdef AHC_DEBUG #ifdef AHC_DEBUG
if ((ahc_debug & AHC_SHOW_MISC) != 0) { if ((ahc_debug & AHC_SHOW_MISC) != 0) {
ahc_print_path(ahc, scb); ahc_print_path(ahc, scb);
printf("Handled Residual of %d bytes\n", resid); printf("Handled %sResidual of %d bytes\n",
(scb->flags & SCB_SENSE) ? "Sense " : "", resid);
} }
#endif #endif
} }
......
/* /*
* Adaptec AIC7xxx device driver for Linux. * Adaptec AIC7xxx device driver for Linux.
* *
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#166 $ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#167 $
* *
* Copyright (c) 1994 John Aycock * Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science. * The University of Calgary Department of Computer Science.
...@@ -1297,6 +1297,7 @@ Scsi_Host_Template aic7xxx_driver_template = { ...@@ -1297,6 +1297,7 @@ Scsi_Host_Template aic7xxx_driver_template = {
*/ */
.max_sectors = 8192, .max_sectors = 8192,
#endif #endif
#if defined CONFIG_HIGHIO || LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
/* Assume RedHat Distribution with its different HIGHIO conventions. */ /* Assume RedHat Distribution with its different HIGHIO conventions. */
.can_dma_32 = 1, .can_dma_32 = 1,
...@@ -1304,6 +1305,7 @@ Scsi_Host_Template aic7xxx_driver_template = { ...@@ -1304,6 +1305,7 @@ Scsi_Host_Template aic7xxx_driver_template = {
#else #else
.highmem_io = 1, .highmem_io = 1,
#endif #endif
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
.name = "aic7xxx", .name = "aic7xxx",
.slave_alloc = ahc_linux_slave_alloc, .slave_alloc = ahc_linux_slave_alloc,
...@@ -1888,7 +1890,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template) ...@@ -1888,7 +1890,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
* negotiation will occur for the first command, and DV * negotiation will occur for the first command, and DV
* will comence should that first command be successful. * will comence should that first command be successful.
*/ */
for (target = 0; target < AHC_NUM_TARGETS; target++) { for (target = 0; target < host->max_id; target++) {
u_int channel; u_int channel;
channel = 0; channel = 0;
...@@ -2732,6 +2734,22 @@ ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd, ...@@ -2732,6 +2734,22 @@ ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break; break;
} }
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
int i;
ahc_print_devinfo(ahc, devinfo);
printf("Inquiry buffer mismatch:");
for (i = 0; i < AHC_LINUX_DV_INQ_LEN; i++) {
if ((i & 0xF) == 0)
printf("\n ");
printf("0x%x:0x0%x ",
((uint8_t *)targ->inq_data)[i],
targ->dv_buffer[i]);
}
printf("\n");
}
#endif
if (ahc_linux_fallback(ahc, devinfo) != 0) { if (ahc_linux_fallback(ahc, devinfo) != 0) {
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
...@@ -3365,6 +3383,8 @@ ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) ...@@ -3365,6 +3383,8 @@ ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
targ->dv_next_narrow_period = MAX(period, AHC_SYNCRATE_ULTRA2); targ->dv_next_narrow_period = MAX(period, AHC_SYNCRATE_ULTRA2);
if (targ->dv_next_wide_period == 0) if (targ->dv_next_wide_period == 0)
targ->dv_next_wide_period = period; targ->dv_next_wide_period = period;
if (targ->dv_max_width == 0)
targ->dv_max_width = width;
if (targ->dv_max_ppr_options == 0) if (targ->dv_max_ppr_options == 0)
targ->dv_max_ppr_options = ppr_options; targ->dv_max_ppr_options = ppr_options;
if (targ->dv_last_ppr_options == 0) if (targ->dv_last_ppr_options == 0)
...@@ -3459,7 +3479,7 @@ ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) ...@@ -3459,7 +3479,7 @@ ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
period++; period++;
} }
} else if ((ahc->features & AHC_WIDE) != 0 } else if ((ahc->features & AHC_WIDE) != 0
&& tinfo->user.width != 0 && targ->dv_max_width != 0
&& wide_speed >= fallback_speed && wide_speed >= fallback_speed
&& (targ->dv_next_wide_period <= AHC_ASYNC_XFER_PERIOD && (targ->dv_next_wide_period <= AHC_ASYNC_XFER_PERIOD
|| period >= AHC_ASYNC_XFER_PERIOD)) { || period >= AHC_ASYNC_XFER_PERIOD)) {
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#114 $ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#115 $
* *
*/ */
#ifndef _AIC7XXX_LINUX_H_ #ifndef _AIC7XXX_LINUX_H_
...@@ -72,7 +72,6 @@ ...@@ -72,7 +72,6 @@
#endif #endif
#include <linux/module.h> #include <linux/module.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/io.h>
#ifndef KERNEL_VERSION #ifndef KERNEL_VERSION
#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) #define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
...@@ -472,10 +471,11 @@ struct ahc_linux_target { ...@@ -472,10 +471,11 @@ struct ahc_linux_target {
/* /*
* The next "fallback" period to use for narrow/wide transfers. * The next "fallback" period to use for narrow/wide transfers.
*/ */
u_int dv_next_narrow_period; uint8_t dv_next_narrow_period;
u_int dv_next_wide_period; uint8_t dv_next_wide_period;
u_int dv_max_ppr_options; uint8_t dv_max_width;
u_int dv_last_ppr_options; uint8_t dv_max_ppr_options;
uint8_t dv_last_ppr_options;
u_int dv_echo_size; u_int dv_echo_size;
ahc_dv_state dv_state; ahc_dv_state dv_state;
u_int dv_state_retry; u_int dv_state_retry;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment