Collapse sync fib locking into normal i/o locking. The former didn't
protect the registers so it was trivially possible for a sync command and i/o command to fight each other and confuse the controller. Make the sync fib alloc/release functions inline and remove the somewhat worthless AAC_SYNC_LOCK_FORCE flag. Thanks to Adil Katchi for helping me to track this down in RELENG_4.
This commit is contained in:
parent
42d4f8303f
commit
b367b3b6f6
@ -236,7 +236,6 @@ aac_attach(struct aac_softc *sc)
|
||||
/*
|
||||
* Initialize locks
|
||||
*/
|
||||
AAC_LOCK_INIT(&sc->aac_sync_lock, "AAC sync FIB lock");
|
||||
AAC_LOCK_INIT(&sc->aac_aifq_lock, "AAC AIF lock");
|
||||
AAC_LOCK_INIT(&sc->aac_io_lock, "AAC I/O lock");
|
||||
AAC_LOCK_INIT(&sc->aac_container_lock, "AAC container lock");
|
||||
@ -316,7 +315,7 @@ aac_startup(void *arg)
|
||||
/* disconnect ourselves from the intrhook chain */
|
||||
config_intrhook_disestablish(&sc->aac_ich);
|
||||
|
||||
aac_alloc_sync_fib(sc, &fib, 0);
|
||||
aac_alloc_sync_fib(sc, &fib);
|
||||
mi = (struct aac_mntinfo *)&fib->data[0];
|
||||
|
||||
/* loop over possible containers */
|
||||
@ -526,7 +525,7 @@ aac_shutdown(device_t dev)
|
||||
*/
|
||||
device_printf(sc->aac_dev, "shutting down controller...");
|
||||
|
||||
aac_alloc_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE);
|
||||
aac_alloc_sync_fib(sc, &fib);
|
||||
cc = (struct aac_close_command *)&fib->data[0];
|
||||
|
||||
bzero(cc, sizeof(struct aac_close_command));
|
||||
@ -1690,38 +1689,6 @@ aac_sync_command(struct aac_softc *sc, u_int32_t command,
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab the sync fib area.
|
||||
*/
|
||||
int
|
||||
aac_alloc_sync_fib(struct aac_softc *sc, struct aac_fib **fib, int flags)
|
||||
{
|
||||
|
||||
/*
|
||||
* If the force flag is set, the system is shutting down, or in
|
||||
* trouble. Ignore the mutex.
|
||||
*/
|
||||
if (!(flags & AAC_SYNC_LOCK_FORCE))
|
||||
AAC_LOCK_ACQUIRE(&sc->aac_sync_lock);
|
||||
|
||||
*fib = &sc->aac_common->ac_sync_fib;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the sync fib area.
|
||||
*/
|
||||
void
|
||||
aac_release_sync_fib(struct aac_softc *sc)
|
||||
{
|
||||
|
||||
AAC_LOCK_RELEASE(&sc->aac_sync_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a synchronous FIB to the controller and wait for a result.
|
||||
*/
|
||||
int
|
||||
aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
|
||||
struct aac_fib *fib, u_int16_t datasize)
|
||||
@ -2267,7 +2234,7 @@ aac_describe_controller(struct aac_softc *sc)
|
||||
|
||||
debug_called(2);
|
||||
|
||||
aac_alloc_sync_fib(sc, &fib, 0);
|
||||
aac_alloc_sync_fib(sc, &fib);
|
||||
|
||||
fib->data[0] = 0;
|
||||
if (aac_sync_fib(sc, RequestAdapterInfo, 0, fib, 1)) {
|
||||
@ -2588,7 +2555,7 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
|
||||
* doesn't tell us anything else! Re-enumerate the
|
||||
* containers and sort things out.
|
||||
*/
|
||||
aac_alloc_sync_fib(sc, &fib, 0);
|
||||
aac_alloc_sync_fib(sc, &fib);
|
||||
mi = (struct aac_mntinfo *)&fib->data[0];
|
||||
do {
|
||||
/*
|
||||
@ -2883,7 +2850,7 @@ aac_get_bus_info(struct aac_softc *sc)
|
||||
device_t child;
|
||||
int i, found, error;
|
||||
|
||||
aac_alloc_sync_fib(sc, &fib, 0);
|
||||
aac_alloc_sync_fib(sc, &fib);
|
||||
c_cmd = (struct aac_ctcfg *)&fib->data[0];
|
||||
bzero(c_cmd, sizeof(struct aac_ctcfg));
|
||||
|
||||
|
@ -523,7 +523,7 @@ aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb)
|
||||
return (CAM_REQ_ABORTED);
|
||||
}
|
||||
|
||||
aac_alloc_sync_fib(sc, &fib, 0);
|
||||
aac_alloc_sync_fib(sc, &fib);
|
||||
|
||||
vmi = (struct aac_vmioctl *)&fib->data[0];
|
||||
bzero(vmi, sizeof(struct aac_vmioctl));
|
||||
@ -570,7 +570,7 @@ aac_cam_get_tran_settings(struct aac_softc *sc, struct ccb_trans_settings *cts,
|
||||
struct aac_vmi_devinfo_resp *vmi_resp;
|
||||
int error;
|
||||
|
||||
aac_alloc_sync_fib(sc, &fib, 0);
|
||||
aac_alloc_sync_fib(sc, &fib);
|
||||
vmi = (struct aac_vmioctl *)&fib->data[0];
|
||||
bzero(vmi, sizeof(struct aac_vmioctl));
|
||||
|
||||
|
@ -246,7 +246,8 @@ aac_disk_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size
|
||||
}
|
||||
}
|
||||
|
||||
aac_alloc_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE);
|
||||
/* Skip aac_alloc_sync_fib(). We don't want to mess with sleep locks */
|
||||
fib = &sc->aac_common->ac_sync_fib;
|
||||
bw = (struct aac_blockwrite *)&fib->data[0];
|
||||
|
||||
while (length > 0) {
|
||||
|
@ -332,10 +332,10 @@ struct aac_softc
|
||||
TAILQ_HEAD(,aac_container) aac_container_tqh;
|
||||
aac_lock_t aac_container_lock;
|
||||
|
||||
/* Protect the sync fib */
|
||||
#define AAC_SYNC_LOCK_FORCE (1 << 0)
|
||||
aac_lock_t aac_sync_lock;
|
||||
|
||||
/*
|
||||
* The general I/O lock. This protects the sync fib, the lists, the
|
||||
* queues, and the registers.
|
||||
*/
|
||||
aac_lock_t aac_io_lock;
|
||||
|
||||
/* delayed activity infrastructure */
|
||||
@ -395,9 +395,6 @@ extern void aac_startio(struct aac_softc *sc);
|
||||
extern int aac_alloc_command(struct aac_softc *sc,
|
||||
struct aac_command **cmp);
|
||||
extern void aac_release_command(struct aac_command *cm);
|
||||
extern int aac_alloc_sync_fib(struct aac_softc *sc,
|
||||
struct aac_fib **fib, int flags);
|
||||
extern void aac_release_sync_fib(struct aac_softc *sc);
|
||||
extern int aac_sync_fib(struct aac_softc *sc, u_int32_t command,
|
||||
u_int32_t xferstate, struct aac_fib *fib,
|
||||
u_int16_t datasize);
|
||||
@ -574,3 +571,20 @@ aac_print_printf(struct aac_softc *sc)
|
||||
sc->aac_common->ac_printf[0] = 0;
|
||||
AAC_QNOTIFY(sc, AAC_DB_PRINTF);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
aac_alloc_sync_fib(struct aac_softc *sc, struct aac_fib **fib)
|
||||
{
|
||||
|
||||
AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
|
||||
*fib = &sc->aac_common->ac_sync_fib;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
aac_release_sync_fib(struct aac_softc *sc)
|
||||
{
|
||||
|
||||
AAC_LOCK_RELEASE(&sc->aac_io_lock);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user