mirror of
https://github.com/torvalds/linux.git
synced 2024-12-02 09:01:34 +00:00
[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
|
||||
int "Initial bus reset delay in milli-seconds"
|
||||
depends on SCSI_AIC79XX
|
||||
default "15000"
|
||||
default "5000"
|
||||
---help---
|
||||
The number of milliseconds to delay after an initial bus reset.
|
||||
The bus settle delay following all error recovery actions is
|
||||
dictated by the SCSI layer and is not affected by this value.
|
||||
|
||||
Default: 15000 (15 seconds)
|
||||
Default: 5000 (5 seconds)
|
||||
|
||||
config AIC79XX_BUILD_FIRMWARE
|
||||
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);
|
||||
scb->flags |= SCB_SENSE;
|
||||
ahd_queue_scb(ahd, scb);
|
||||
/*
|
||||
* Ensure we have enough time to actually
|
||||
* retrieve the sense.
|
||||
*/
|
||||
ahd_scb_timer_reset(scb, 5 * 1000000);
|
||||
break;
|
||||
}
|
||||
case SCSI_STATUS_OK:
|
||||
|
@ -1089,7 +1089,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
|
||||
return (ENOMEM);
|
||||
|
||||
*((struct ahd_softc **)host->hostdata) = ahd;
|
||||
ahd_lock(ahd, &s);
|
||||
ahd->platform_data->host = host;
|
||||
host->can_queue = AHD_MAX_QUEUE;
|
||||
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_channel = 0;
|
||||
host->sg_tablesize = AHD_NSEG;
|
||||
ahd_lock(ahd, &s);
|
||||
ahd_set_unit(ahd, ahd_linux_unit++);
|
||||
ahd_unlock(ahd, &s);
|
||||
sprintf(buf, "scsi%d", host->host_no);
|
||||
new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
|
||||
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;
|
||||
ahd_linux_initialize_scsi_bus(ahd);
|
||||
ahd_intr_enable(ahd, TRUE);
|
||||
ahd_unlock(ahd, &s);
|
||||
|
||||
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 numtarg;
|
||||
unsigned long s;
|
||||
|
||||
target_id = 0;
|
||||
numtarg = 0;
|
||||
@ -1156,6 +1157,8 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
|
||||
else
|
||||
numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
|
||||
|
||||
ahd_lock(ahd, &s);
|
||||
|
||||
/*
|
||||
* Force negotiation to async for all targets that
|
||||
* 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,
|
||||
tinfo, AHD_NEG_ALWAYS);
|
||||
}
|
||||
ahd_unlock(ahd, &s);
|
||||
/* Give the bus some time to recover */
|
||||
if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
|
||||
ahd_freeze_simq(ahd);
|
||||
init_timer(&ahd->platform_data->reset_timer);
|
||||
ahd->platform_data->reset_timer.data = (u_long)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);
|
||||
msleep(AIC79XX_RESET_DELAY);
|
||||
ahd_release_simq(ahd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2050,6 +2049,9 @@ ahd_linux_sem_timeout(u_long arg)
|
||||
void
|
||||
ahd_freeze_simq(struct ahd_softc *ahd)
|
||||
{
|
||||
unsigned long s;
|
||||
|
||||
ahd_lock(ahd, &s);
|
||||
ahd->platform_data->qfrozen++;
|
||||
if (ahd->platform_data->qfrozen == 1) {
|
||||
scsi_block_requests(ahd->platform_data->host);
|
||||
@ -2057,6 +2059,7 @@ ahd_freeze_simq(struct ahd_softc *ahd)
|
||||
CAM_LUN_WILDCARD, SCB_LIST_NULL,
|
||||
ROLE_INITIATOR, CAM_REQUEUE_REQ);
|
||||
}
|
||||
ahd_unlock(ahd, &s);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2361,8 +2364,9 @@ done:
|
||||
ahd_name(ahd), dev->active);
|
||||
retval = FAILED;
|
||||
}
|
||||
}
|
||||
ahd_unlock(ahd, &flags);
|
||||
} else
|
||||
ahd_unlock(ahd, &flags);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
|
@ -228,7 +228,6 @@ typedef struct timer_list ahd_timer_t;
|
||||
typedef void ahd_linux_callback_t (u_long);
|
||||
static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
|
||||
ahd_callback_t *func, void *arg);
|
||||
static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);
|
||||
|
||||
static __inline void
|
||||
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);
|
||||
}
|
||||
|
||||
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 ************************************/
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
@ -389,7 +382,6 @@ struct ahd_platform_data {
|
||||
|
||||
spinlock_t spin_lock;
|
||||
u_int qfrozen;
|
||||
struct timer_list reset_timer;
|
||||
struct semaphore eh_sem;
|
||||
struct Scsi_Host *host; /* pointer to scsi host */
|
||||
#define AHD_LINUX_NOIRQ ((uint32_t)~0)
|
||||
|
Loading…
Reference in New Issue
Block a user