[SCSI] aic79xx: Fix timer handling
Fix the timer handling in aic79xx to use the SCSI-ML provided handling instead of implementing our own. It also fixes a deadlock in the command recovery code. Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
d60256b1b3
commit
eb22184954
|
@ -37,13 +37,13 @@ config AIC79XX_CMDS_PER_DEVICE
|
||||||
config AIC79XX_RESET_DELAY_MS
|
config AIC79XX_RESET_DELAY_MS
|
||||||
int "Initial bus reset delay in milli-seconds"
|
int "Initial bus reset delay in milli-seconds"
|
||||||
depends on SCSI_AIC79XX
|
depends on SCSI_AIC79XX
|
||||||
default "15000"
|
default "5000"
|
||||||
---help---
|
---help---
|
||||||
The number of milliseconds to delay after an initial bus reset.
|
The number of milliseconds to delay after an initial bus reset.
|
||||||
The bus settle delay following all error recovery actions is
|
The bus settle delay following all error recovery actions is
|
||||||
dictated by the SCSI layer and is not affected by this value.
|
dictated by the SCSI layer and is not affected by this value.
|
||||||
|
|
||||||
Default: 15000 (15 seconds)
|
Default: 5000 (5 seconds)
|
||||||
|
|
||||||
config AIC79XX_BUILD_FIRMWARE
|
config AIC79XX_BUILD_FIRMWARE
|
||||||
bool "Build Adapter Firmware with Kernel Build"
|
bool "Build Adapter Firmware with Kernel Build"
|
||||||
|
|
|
@ -8273,11 +8273,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
|
||||||
ahd_setup_data_scb(ahd, scb);
|
ahd_setup_data_scb(ahd, scb);
|
||||||
scb->flags |= SCB_SENSE;
|
scb->flags |= SCB_SENSE;
|
||||||
ahd_queue_scb(ahd, scb);
|
ahd_queue_scb(ahd, scb);
|
||||||
/*
|
|
||||||
* Ensure we have enough time to actually
|
|
||||||
* retrieve the sense.
|
|
||||||
*/
|
|
||||||
ahd_scb_timer_reset(scb, 5 * 1000000);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCSI_STATUS_OK:
|
case SCSI_STATUS_OK:
|
||||||
|
|
|
@ -1089,7 +1089,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
|
||||||
return (ENOMEM);
|
return (ENOMEM);
|
||||||
|
|
||||||
*((struct ahd_softc **)host->hostdata) = ahd;
|
*((struct ahd_softc **)host->hostdata) = ahd;
|
||||||
ahd_lock(ahd, &s);
|
|
||||||
ahd->platform_data->host = host;
|
ahd->platform_data->host = host;
|
||||||
host->can_queue = AHD_MAX_QUEUE;
|
host->can_queue = AHD_MAX_QUEUE;
|
||||||
host->cmd_per_lun = 2;
|
host->cmd_per_lun = 2;
|
||||||
|
@ -1100,7 +1099,9 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
|
||||||
host->max_lun = AHD_NUM_LUNS;
|
host->max_lun = AHD_NUM_LUNS;
|
||||||
host->max_channel = 0;
|
host->max_channel = 0;
|
||||||
host->sg_tablesize = AHD_NSEG;
|
host->sg_tablesize = AHD_NSEG;
|
||||||
|
ahd_lock(ahd, &s);
|
||||||
ahd_set_unit(ahd, ahd_linux_unit++);
|
ahd_set_unit(ahd, ahd_linux_unit++);
|
||||||
|
ahd_unlock(ahd, &s);
|
||||||
sprintf(buf, "scsi%d", host->host_no);
|
sprintf(buf, "scsi%d", host->host_no);
|
||||||
new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
|
new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
|
||||||
if (new_name != NULL) {
|
if (new_name != NULL) {
|
||||||
|
@ -1110,7 +1111,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
|
||||||
host->unique_id = ahd->unit;
|
host->unique_id = ahd->unit;
|
||||||
ahd_linux_initialize_scsi_bus(ahd);
|
ahd_linux_initialize_scsi_bus(ahd);
|
||||||
ahd_intr_enable(ahd, TRUE);
|
ahd_intr_enable(ahd, TRUE);
|
||||||
ahd_unlock(ahd, &s);
|
|
||||||
|
|
||||||
host->transportt = ahd_linux_transport_template;
|
host->transportt = ahd_linux_transport_template;
|
||||||
|
|
||||||
|
@ -1144,6 +1144,7 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
|
||||||
{
|
{
|
||||||
u_int target_id;
|
u_int target_id;
|
||||||
u_int numtarg;
|
u_int numtarg;
|
||||||
|
unsigned long s;
|
||||||
|
|
||||||
target_id = 0;
|
target_id = 0;
|
||||||
numtarg = 0;
|
numtarg = 0;
|
||||||
|
@ -1156,6 +1157,8 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
|
||||||
else
|
else
|
||||||
numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
|
numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
|
||||||
|
|
||||||
|
ahd_lock(ahd, &s);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force negotiation to async for all targets that
|
* Force negotiation to async for all targets that
|
||||||
* will not see an initial bus reset.
|
* will not see an initial bus reset.
|
||||||
|
@ -1172,16 +1175,12 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
|
||||||
ahd_update_neg_request(ahd, &devinfo, tstate,
|
ahd_update_neg_request(ahd, &devinfo, tstate,
|
||||||
tinfo, AHD_NEG_ALWAYS);
|
tinfo, AHD_NEG_ALWAYS);
|
||||||
}
|
}
|
||||||
|
ahd_unlock(ahd, &s);
|
||||||
/* Give the bus some time to recover */
|
/* Give the bus some time to recover */
|
||||||
if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
|
if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
|
||||||
ahd_freeze_simq(ahd);
|
ahd_freeze_simq(ahd);
|
||||||
init_timer(&ahd->platform_data->reset_timer);
|
msleep(AIC79XX_RESET_DELAY);
|
||||||
ahd->platform_data->reset_timer.data = (u_long)ahd;
|
ahd_release_simq(ahd);
|
||||||
ahd->platform_data->reset_timer.expires =
|
|
||||||
jiffies + (AIC79XX_RESET_DELAY * HZ)/1000;
|
|
||||||
ahd->platform_data->reset_timer.function =
|
|
||||||
(ahd_linux_callback_t *)ahd_release_simq;
|
|
||||||
add_timer(&ahd->platform_data->reset_timer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2050,6 +2049,9 @@ ahd_linux_sem_timeout(u_long arg)
|
||||||
void
|
void
|
||||||
ahd_freeze_simq(struct ahd_softc *ahd)
|
ahd_freeze_simq(struct ahd_softc *ahd)
|
||||||
{
|
{
|
||||||
|
unsigned long s;
|
||||||
|
|
||||||
|
ahd_lock(ahd, &s);
|
||||||
ahd->platform_data->qfrozen++;
|
ahd->platform_data->qfrozen++;
|
||||||
if (ahd->platform_data->qfrozen == 1) {
|
if (ahd->platform_data->qfrozen == 1) {
|
||||||
scsi_block_requests(ahd->platform_data->host);
|
scsi_block_requests(ahd->platform_data->host);
|
||||||
|
@ -2057,6 +2059,7 @@ ahd_freeze_simq(struct ahd_softc *ahd)
|
||||||
CAM_LUN_WILDCARD, SCB_LIST_NULL,
|
CAM_LUN_WILDCARD, SCB_LIST_NULL,
|
||||||
ROLE_INITIATOR, CAM_REQUEUE_REQ);
|
ROLE_INITIATOR, CAM_REQUEUE_REQ);
|
||||||
}
|
}
|
||||||
|
ahd_unlock(ahd, &s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2361,8 +2364,9 @@ done:
|
||||||
ahd_name(ahd), dev->active);
|
ahd_name(ahd), dev->active);
|
||||||
retval = FAILED;
|
retval = FAILED;
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
ahd_unlock(ahd, &flags);
|
ahd_unlock(ahd, &flags);
|
||||||
|
|
||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -228,7 +228,6 @@ typedef struct timer_list ahd_timer_t;
|
||||||
typedef void ahd_linux_callback_t (u_long);
|
typedef void ahd_linux_callback_t (u_long);
|
||||||
static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
|
static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
|
||||||
ahd_callback_t *func, void *arg);
|
ahd_callback_t *func, void *arg);
|
||||||
static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);
|
|
||||||
|
|
||||||
static __inline void
|
static __inline void
|
||||||
ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
|
ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
|
||||||
|
@ -243,12 +242,6 @@ ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
|
||||||
add_timer(timer);
|
add_timer(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline void
|
|
||||||
ahd_scb_timer_reset(struct scb *scb, u_int usec)
|
|
||||||
{
|
|
||||||
mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************** SMP support ************************************/
|
/***************************** SMP support ************************************/
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
|
|
||||||
|
@ -389,7 +382,6 @@ struct ahd_platform_data {
|
||||||
|
|
||||||
spinlock_t spin_lock;
|
spinlock_t spin_lock;
|
||||||
u_int qfrozen;
|
u_int qfrozen;
|
||||||
struct timer_list reset_timer;
|
|
||||||
struct semaphore eh_sem;
|
struct semaphore eh_sem;
|
||||||
struct Scsi_Host *host; /* pointer to scsi host */
|
struct Scsi_Host *host; /* pointer to scsi host */
|
||||||
#define AHD_LINUX_NOIRQ ((uint32_t)~0)
|
#define AHD_LINUX_NOIRQ ((uint32_t)~0)
|
||||||
|
|
Loading…
Reference in New Issue