From: | Peter Avalos <pavalos@xxxxxxxxxxxx> |
Date: | Sun, 30 Dec 2007 21:43:45 -0500 |
I've attempted to bring in some locking for the ahc and ahd drivers from FreeBSD. This is my first attempt with locking mechanisms, and I'd appreciate some input on the attached patch. Doing this brought along some questions: 1. When should you use spinlocks instead of lockmgr locks? Would this code be better with spinlocks? If so, are there any gotchas I need to know about? 2. tsleep->msleep. Did I do that right, or can only spinlocks be used? Thanks, Peter The patch can also be found at: http://www.theshell.com/~pavalos/wip/aic7xxx-locking.patch
commit f40ed99bd885ad0c6ca868dd08b86530e8064870 Author: Peter Avalos <pavalos@theshell.com> Date: Sun Dec 30 21:36:58 2007 -0500 Bring in locking from FreeBSD using lockmgr locks instead of mutexes. diff --git a/sys/dev/disk/aic7xxx/aic7770.c b/sys/dev/disk/aic7xxx/aic7770.c index fcef375..ad91898 100644 --- a/sys/dev/disk/aic7xxx/aic7770.c +++ b/sys/dev/disk/aic7xxx/aic7770.c @@ -254,6 +254,7 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) if (error != 0) return (error); + ahc_lock(ahc); /* * Link this softc in with all other ahc instances. */ @@ -264,6 +265,8 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) */ ahc_outb(ahc, BCTL, ENABLE); + ahc_unlock(ahc); + return (0); } diff --git a/sys/dev/disk/aic7xxx/aic79xx.c b/sys/dev/disk/aic7xxx/aic79xx.c index 834fcf4..bcfbec6 100644 --- a/sys/dev/disk/aic7xxx/aic79xx.c +++ b/sys/dev/disk/aic7xxx/aic79xx.c @@ -5251,6 +5251,7 @@ ahd_alloc(void *platform_arg, char *name) ahd_free(ahd); ahd = NULL; } + ahd_lockinit(ahd); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MEMORY) != 0) { kprintf("%s: scb size = 0x%x, hscb size = 0x%x\n", @@ -5322,22 +5323,6 @@ ahd_softc_insert(struct ahd_softc *ahd) ahd->init_level++; } -/* - * Verify that the passed in softc pointer is for a - * controller that is still configured. - */ -struct ahd_softc * -ahd_find_softc(struct ahd_softc *ahd) -{ - struct ahd_softc *list_ahd; - - TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { - if (list_ahd == ahd) - return (ahd); - } - return (NULL); -} - void ahd_set_unit(struct ahd_softc *ahd, int unit) { @@ -6179,6 +6164,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag); if (next_scb->col_scb != NULL) next_scb->col_scb->col_scb = next_scb; + aic_timer_init(&next_scb->io_timer); ahd_free_scb(ahd, next_scb); hscb++; hscb_busaddr += sizeof(*hscb); @@ -8024,15 +8010,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) static void ahd_reset_poll(void *arg) { - struct ahd_softc *ahd; + struct ahd_softc *ahd = (struct ahd_softc *)arg; u_int scsiseq1; - ahd = ahd_find_softc((struct ahd_softc *)arg); - if (ahd == NULL) { - kprintf("ahd_reset_poll: Instance %p no longer exists\n", arg); - return; - } - ahd_lock(); + ahd_lock(ahd); ahd_pause(ahd); ahd_update_modes(ahd); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); @@ -8041,7 +8022,7 @@ ahd_reset_poll(void *arg) aic_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_MS, ahd_reset_poll, ahd); ahd_unpause(ahd); - ahd_unlock(); + ahd_unlock(ahd); return; } @@ -8051,24 +8032,18 @@ ahd_reset_poll(void *arg) ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP)); ahd_unpause(ahd); ahd->flags &= ~AHD_RESET_POLL_ACTIVE; - ahd_unlock(); aic_release_simq(ahd); + ahd_unlock(ahd); } /**************************** Statistics Processing ***************************/ static void ahd_stat_timer(void *arg) { - struct ahd_softc *ahd; + struct ahd_softc *ahd = (struct ahd_softc *)arg; int enint_coal; - ahd = ahd_find_softc((struct ahd_softc *)arg); - if (ahd == NULL) { - kprintf("ahd_stat_timer: Instance %p no longer exists\n", arg); - return; - } - ahd_lock(); - + ahd_lock(ahd); enint_coal = ahd->hs_mailbox & ENINT_COALESCE; if (ahd->cmdcmplt_total > ahd->int_coalescing_threshold) enint_coal |= ENINT_COALESCE; @@ -8092,7 +8067,7 @@ ahd_stat_timer(void *arg) ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0; aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_MS, ahd_stat_timer, ahd); - ahd_unlock(); + ahd_unlock(ahd); } /****************************** Status Processing *****************************/ @@ -9255,8 +9230,6 @@ ahd_recover_commands(struct ahd_softc *ahd) u_int active_scbptr; u_int last_phase; - ahd_lock(); - /* * Pause the controller and manually flush any * commands that have just completed but that our @@ -9282,7 +9255,6 @@ ahd_recover_commands(struct ahd_softc *ahd) kprintf("%s: Timedout SCBs already complete. " "Interrupts may not be functioning.\n", ahd_name(ahd)); ahd_unpause(ahd); - ahd_unlock(); return; } @@ -9473,7 +9445,6 @@ bus_reset: } ahd_unpause(ahd); - ahd_unlock(); } /* @@ -9889,13 +9860,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) */ if ((ahd->flags & AHD_TARGETROLE) == 0 && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { - u_long s; - kprintf("Configuring Target Mode\n"); - ahd_lock(); if (LIST_FIRST(&ahd->pending_scbs) != NULL) { ccb->ccb_h.status = CAM_BUSY; - ahd_unlock(); return; } ahd->flags |= AHD_TARGETROLE; @@ -9904,7 +9871,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) ahd_pause(ahd); ahd_loadseq(ahd); ahd_restart(ahd); - ahd_unlock(); } cel = &ccb->cel; target = ccb->ccb_h.target_id; @@ -9963,7 +9929,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) } SLIST_INIT(&lstate->accept_tios); SLIST_INIT(&lstate->immed_notifies); - ahd_lock(); ahd_pause(ahd); if (target != CAM_TARGET_WILDCARD) { tstate->enabled_luns[lun] = lstate; @@ -10022,7 +9987,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) ahd_outb(ahd, SCSISEQ1, scsiseq1); } ahd_unpause(ahd); - ahd_unlock(); ccb->ccb_h.status = CAM_REQ_CMP; xpt_print_path(ccb->ccb_h.path); kprintf("Lun now enabled for target mode\n"); @@ -10035,8 +9999,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) return; } - ahd_lock(); - ccb->ccb_h.status = CAM_REQ_CMP; LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) { struct ccb_hdr *ccbh; @@ -10046,7 +10008,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){ kprintf("CTIO pending\n"); ccb->ccb_h.status = CAM_REQ_INVALID; - ahd_unlock(); return; } } @@ -10062,7 +10023,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) } if (ccb->ccb_h.status != CAM_REQ_CMP) { - ahd_unlock(); return; } @@ -10129,7 +10089,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) } } ahd_unpause(ahd); - ahd_unlock(); } #endif } diff --git a/sys/dev/disk/aic7xxx/aic79xx.h b/sys/dev/disk/aic7xxx/aic79xx.h index f4e5bf3..847ae9d 100644 --- a/sys/dev/disk/aic7xxx/aic79xx.h +++ b/sys/dev/disk/aic7xxx/aic79xx.h @@ -640,6 +640,7 @@ struct scb { u_int sg_count;/* How full ahd_dma_seg is */ #define AHD_MAX_LQ_CRC_ERRORS 5 u_int crc_retry_count; + aic_timer_t io_timer; }; TAILQ_HEAD(scb_tailq, scb); @@ -1395,7 +1396,6 @@ void ahd_pause_and_flushwork(struct ahd_softc *ahd); int ahd_suspend(struct ahd_softc *ahd); int ahd_resume(struct ahd_softc *ahd); void ahd_softc_insert(struct ahd_softc *); -struct ahd_softc *ahd_find_softc(struct ahd_softc *ahd); void ahd_set_unit(struct ahd_softc *, int); void ahd_set_name(struct ahd_softc *, char *); struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx); diff --git a/sys/dev/disk/aic7xxx/aic79xx_osm.c b/sys/dev/disk/aic7xxx/aic79xx_osm.c index 360dea5..d20e643 100644 --- a/sys/dev/disk/aic7xxx/aic79xx_osm.c +++ b/sys/dev/disk/aic7xxx/aic79xx_osm.c @@ -126,7 +126,7 @@ ahd_attach(struct ahd_softc *ahd) ahd_controller_info(ahd, ahd_info); kprintf("%s\n", ahd_info); - ahd_lock(); + ahd_lock(ahd); /* * Construct our SIM entry @@ -163,6 +163,7 @@ ahd_attach(struct ahd_softc *ahd) fail: ahd->platform_data->sim = sim; ahd->platform_data->path = path; + ahd_unlock(ahd); if (count != 0) { /* We have to wait until after any system dumps... */ ahd->platform_data->eh = @@ -171,8 +172,6 @@ fail: ahd_intr_enable(ahd, TRUE); } - ahd_unlock(); - return (count); } @@ -185,7 +184,9 @@ ahd_platform_intr(void *arg) struct ahd_softc *ahd; ahd = (struct ahd_softc *)arg; + ahd_lock(ahd); ahd_intr(ahd); + ahd_unlock(ahd); } /* @@ -206,7 +207,7 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) if ((scb->flags & SCB_TIMEDOUT) != 0) LIST_REMOVE(scb, timedout_links); - callout_stop(&ccb->ccb_h.timeout_ch); + callout_stop(&scb->io_timer); if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { bus_dmasync_op_t op; @@ -369,13 +370,11 @@ ahd_action(struct cam_sim *sim, union ccb *ccb) } if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { - ahd_lock(); SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h, sim_links.sle); ccb->ccb_h.status = CAM_REQ_INPROG; if ((ahd->flags & AHD_TQINFIFO_BLOCKED) != 0) ahd_run_tqinfifo(ahd, /*paused*/FALSE); - ahd_unlock(); break; } @@ -409,7 +408,6 @@ ahd_action(struct cam_sim *sim, union ccb *ccb) /* * get an scb to use. */ - ahd_lock(); tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate); if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) == 0 @@ -424,12 +422,10 @@ ahd_action(struct cam_sim *sim, union ccb *ccb) xpt_freeze_simq(sim, /*count*/1); ahd->flags |= AHD_RESOURCE_SHORTAGE; - ahd_unlock(); ccb->ccb_h.status = CAM_REQUEUE_REQ; xpt_done(ccb); return; } - ahd_unlock(); hscb = scb->hscb; @@ -517,20 +513,16 @@ ahd_action(struct cam_sim *sim, union ccb *ccb) } case XPT_SET_TRAN_SETTINGS: { - ahd_lock(); ahd_set_tran_settings(ahd, SIM_SCSI_ID(ahd, sim), SIM_CHANNEL(ahd, sim), &ccb->cts); - ahd_unlock(); xpt_done(ccb); break; } case XPT_GET_TRAN_SETTINGS: /* Get default/user set transfer settings for the target */ { - ahd_lock(); ahd_get_tran_settings(ahd, SIM_SCSI_ID(ahd, sim), SIM_CHANNEL(ahd, sim), &ccb->cts); - ahd_unlock(); xpt_done(ccb); break; } @@ -544,10 +536,8 @@ ahd_action(struct cam_sim *sim, union ccb *ccb) { int found; - ahd_lock(); found = ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim), /*initiate reset*/TRUE); - ahd_unlock(); if (bootverbose) { xpt_print_path(SIM_PATH(ahd, sim)); kprintf("SCSI bus reset delivered. " @@ -976,13 +966,11 @@ ahd_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) * Revert to async/narrow transfers * for the next device. */ - ahd_lock(); ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, AHD_TRANS_GOAL|AHD_TRANS_CUR, /*paused*/FALSE); ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0, /*ppr_options*/0, AHD_TRANS_GOAL|AHD_TRANS_CUR, /*paused*/FALSE); - ahd_unlock(); break; } default: @@ -1012,9 +1000,7 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, aic_set_transaction_status(scb, CAM_REQ_CMP_ERR); if (nsegments != 0) bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap); - ahd_lock(); ahd_free_scb(ahd, scb); - ahd_unlock(); xpt_done(ccb); return; } @@ -1052,8 +1038,6 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, } } - ahd_lock(); - /* * Last time we need to check if this SCB needs to * be aborted. @@ -1063,7 +1047,6 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap); ahd_free_scb(ahd, scb); - ahd_unlock(); xpt_done(ccb); return; } @@ -1112,8 +1095,6 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, } else { ahd_queue_scb(ahd, scb); } - - ahd_unlock(); } static void @@ -1140,6 +1121,7 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim, if (hscb->cdb_len > MAX_CDB_LEN && (ccb_h->flags & CAM_CDB_PHYS) == 0) { + /* * Should CAM start to support CDB sizes * greater than 16 bytes, we could use @@ -1147,9 +1129,7 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim, */ aic_set_transaction_status(scb, CAM_REQ_INVALID); - ahd_lock(); ahd_free_scb(ahd, scb); - ahd_unlock(); xpt_done((union ccb *)csio); return; } @@ -1166,11 +1146,10 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim, } } else { if (hscb->cdb_len > MAX_CDB_LEN) { + aic_set_transaction_status(scb, CAM_REQ_INVALID); - ahd_lock(); ahd_free_scb(ahd, scb); - ahd_unlock(); xpt_done((union ccb *)csio); return; } @@ -1448,16 +1427,11 @@ ahd_detach(device_t dev) device_printf(dev, "detaching device\n"); ahd = device_get_softc(dev); - ahd = ahd_find_softc(ahd); - if (ahd == NULL) { - device_printf(dev, "aic7xxx already detached\n"); - return (ENOENT); - } + ahd_lock(ahd); TAILQ_REMOVE(&ahd_tailq, ahd, links); - ahd_lock(); ahd_intr_enable(ahd, FALSE); bus_teardown_intr(dev, ahd->platform_data->irq, ahd->platform_data->ih); - ahd_unlock(); + ahd_unlock(ahd); ahd_free(ahd); return (0); } @@ -1494,6 +1468,7 @@ static int ahd_modevent(module_t mod, int type, void *data) { /* XXX Deal with busy status on unload. */ + /* XXX Deal with unknown events */ return 0; } diff --git a/sys/dev/disk/aic7xxx/aic79xx_osm.h b/sys/dev/disk/aic7xxx/aic79xx_osm.h index 1e4b4fe..4b74997 100644 --- a/sys/dev/disk/aic7xxx/aic79xx_osm.h +++ b/sys/dev/disk/aic7xxx/aic79xx_osm.h @@ -116,6 +116,17 @@ #define AHD_TARGET_MODE 1 #endif +/***************************** Core Includes **********************************/ +#ifdef AHD_REG_PRETTY_PRINT +#define AIC_DEBUG_REGISTERS 1 +#else +#define AIC_DEBUG_REGISTERS 0 +#endif +#define AIC_CORE_INCLUDE "aic79xx.h" +#define AIC_LIB_PREFIX ahd +#define AIC_CONST_PREFIX AHD +#include "aic_osm_lib.h" + /************************** Softc/SCB Platform Data ***************************/ struct ahd_platform_data { /* @@ -132,22 +143,12 @@ struct ahd_platform_data { void *ih; eventhandler_tag eh; struct thread *recovery_thread; + struct lock lock; }; struct scb_platform_data { }; -/***************************** Core Includes **********************************/ -#ifdef AHD_REG_PRETTY_PRINT -#define AIC_DEBUG_REGISTERS 1 -#else -#define AIC_DEBUG_REGISTERS 0 -#endif -#define AIC_CORE_INCLUDE "aic79xx.h" -#define AIC_LIB_PREFIX ahd -#define AIC_CONST_PREFIX AHD -#include "aic_osm_lib.h" - /*************************** Device Access ************************************/ #define ahd_inb(ahd, port) \ bus_space_read_1((ahd)->tags[(port) >> 8], \ @@ -187,19 +188,26 @@ ahd_flush_device_writes(struct ahd_softc *ahd) /**************************** Locking Primitives ******************************/ /* Lock protecting internal data structures */ -static __inline void ahd_lock(void); -static __inline void ahd_unlock(void); +static __inline void ahd_lockinit(struct ahd_softc *); +static __inline void ahd_lock(struct ahd_softc *); +static __inline void ahd_unlock(struct ahd_softc *); + +static __inline void +ahd_lockinit(struct ahd_softc *ahd) +{ + lockinit(&ahd->platform_data->lock, "ahd_lock", 0, LK_EXCLUSIVE|LK_CANRECURSE); +} static __inline void -ahd_lock(void) +ahd_lock(struct ahd_softc *ahd) { - crit_enter(); + lockmgr(&ahd->platform_data->lock, LK_EXCLUSIVE); } static __inline void -ahd_unlock(void) +ahd_unlock(struct ahd_softc *ahd) { - crit_exit(); + lockmgr(&ahd->platform_data->lock, LK_RELEASE); } /********************************** PCI ***************************************/ diff --git a/sys/dev/disk/aic7xxx/aic79xx_pci.c b/sys/dev/disk/aic7xxx/aic79xx_pci.c index 07e27cf..ee67102 100644 --- a/sys/dev/disk/aic7xxx/aic79xx_pci.c +++ b/sys/dev/disk/aic7xxx/aic79xx_pci.c @@ -416,10 +416,12 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) if (error != 0) return (error); + ahd_lock(ahd); /* * Link this softc in with all other ahd instances. */ ahd_softc_insert(ahd); + ahd_unlock(ahd); return (0); } diff --git a/sys/dev/disk/aic7xxx/aic7xxx.c b/sys/dev/disk/aic7xxx/aic7xxx.c index add0b68..24a279a 100644 --- a/sys/dev/disk/aic7xxx/aic7xxx.c +++ b/sys/dev/disk/aic7xxx/aic7xxx.c @@ -3928,6 +3928,7 @@ ahc_alloc(void *platform_arg, char *name) ahc_free(ahc); ahc = NULL; } + ahc_lockinit(ahc); return (ahc); } @@ -4006,22 +4007,6 @@ ahc_softc_insert(struct ahc_softc *ahc) ahc->init_level++; } -/* - * Verify that the passed in softc pointer is for a - * controller that is still configured. - */ -struct ahc_softc * -ahc_find_softc(struct ahc_softc *ahc) -{ - struct ahc_softc *list_ahc; - - TAILQ_FOREACH(list_ahc, &ahc_tailq, links) { - if (list_ahc == ahc) - return (ahc); - } - return (NULL); -} - void ahc_set_unit(struct ahc_softc *ahc, int unit) { @@ -4574,6 +4559,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc) #endif next_scb->hscb = &scb_data->hscbs[scb_data->numscbs]; next_scb->hscb->tag = ahc->scb_data->numscbs; + aic_timer_init(&next_scb->io_timer); SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, next_scb, links.sle); segs += AHC_NSEG; @@ -6988,8 +6974,6 @@ ahc_recover_commands(struct ahc_softc *ahc) int restart_needed; u_int last_phase; - ahc_lock(); - /* * Pause the controller and manually flush any * commands that have just completed but that our @@ -7009,7 +6993,6 @@ ahc_recover_commands(struct ahc_softc *ahc) kprintf("%s: Timedout SCBs already complete. " "Interrupts may not be functioning.\n", ahc_name(ahc)); ahc_unpause(ahc); - ahc_unlock(); return; } @@ -7262,7 +7245,6 @@ bus_reset: ahc_restart(ahc); else ahc_unpause(ahc); - ahc_unlock(); } /************************* Target Mode ****************************************/ @@ -7399,10 +7381,8 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) ahc_flag saved_flags; kprintf("Configuring Target Mode\n"); - ahc_lock(); if (LIST_FIRST(&ahc->pending_scbs) != NULL) { ccb->ccb_h.status = CAM_BUSY; - ahc_unlock(); return; } saved_flags = ahc->flags; @@ -7423,12 +7403,10 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) ahc->flags = saved_flags; (void)ahc_loadseq(ahc); ahc_restart(ahc); - ahc_unlock(); ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; return; } ahc_restart(ahc); - ahc_unlock(); } cel = &ccb->cel; target = ccb->ccb_h.target_id; @@ -7487,7 +7465,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) } SLIST_INIT(&lstate->accept_tios); SLIST_INIT(&lstate->immed_notifies); - ahc_lock(); ahc_pause(ahc); if (target != CAM_TARGET_WILDCARD) { tstate->enabled_luns[lun] = lstate; @@ -7553,7 +7530,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) ahc_outb(ahc, SCSISEQ, scsiseq); } ahc_unpause(ahc); - ahc_unlock(); ccb->ccb_h.status = CAM_REQ_CMP; xpt_print_path(ccb->ccb_h.path); kprintf("Lun now enabled for target mode\n"); @@ -7566,8 +7542,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) return; } - ahc_lock(); - ccb->ccb_h.status = CAM_REQ_CMP; LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) { struct ccb_hdr *ccbh; @@ -7577,7 +7551,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){ kprintf("CTIO pending\n"); ccb->ccb_h.status = CAM_REQ_INVALID; - ahc_unlock(); return; } } @@ -7593,7 +7566,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) } if (ccb->ccb_h.status != CAM_REQ_CMP) { - ahc_unlock(); return; } @@ -7668,7 +7640,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) } } ahc_unpause(ahc); - ahc_unlock(); } } diff --git a/sys/dev/disk/aic7xxx/aic7xxx.h b/sys/dev/disk/aic7xxx/aic7xxx.h index 77cce33..65a1cb0 100644 --- a/sys/dev/disk/aic7xxx/aic7xxx.h +++ b/sys/dev/disk/aic7xxx/aic7xxx.h @@ -598,6 +598,7 @@ struct scb { struct ahc_dma_seg *sg_list; bus_addr_t sg_list_phys; u_int sg_count;/* How full ahc_dma_seg is */ + aic_timer_t io_timer; }; struct scb_data { @@ -1225,7 +1226,6 @@ void ahc_pause_and_flushwork(struct ahc_softc *ahc); int ahc_suspend(struct ahc_softc *ahc); int ahc_resume(struct ahc_softc *ahc); void ahc_softc_insert(struct ahc_softc *); -struct ahc_softc *ahc_find_softc(struct ahc_softc *ahc); void ahc_set_unit(struct ahc_softc *, int); void ahc_set_name(struct ahc_softc *, char *); int ahc_alloc_scbs(struct ahc_softc *ahc); diff --git a/sys/dev/disk/aic7xxx/aic7xxx_osm.c b/sys/dev/disk/aic7xxx/aic7xxx_osm.c index 8181836..4201d65 100644 --- a/sys/dev/disk/aic7xxx/aic7xxx_osm.c +++ b/sys/dev/disk/aic7xxx/aic7xxx_osm.c @@ -167,7 +167,7 @@ ahc_attach(struct ahc_softc *ahc) ahc_controller_info(ahc, ahc_info); kprintf("%s\n", ahc_info); - ahc_lock(); + ahc_lock(ahc); /* * Attach secondary channel first if the user has @@ -267,6 +267,7 @@ fail: ahc->platform_data->sim_b = sim2; ahc->platform_data->path_b = path2; } + ahc_unlock(ahc); if (count != 0) { /* We have to wait until after any system dumps... */ @@ -276,7 +277,6 @@ fail: ahc_intr_enable(ahc, TRUE); } - ahc_unlock(); return (count); } @@ -289,7 +289,9 @@ ahc_platform_intr(void *arg) struct ahc_softc *ahc; ahc = (struct ahc_softc *)arg; + ahc_lock(ahc); ahc_intr(ahc); + ahc_unlock(ahc); } /* @@ -320,7 +322,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) ahc_run_untagged_queue(ahc, untagged_q); } - callout_stop(&ccb->ccb_h.timeout_ch); + callout_stop(&scb->io_timer); if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { bus_dmasync_op_t op; @@ -384,8 +386,8 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) * so reinstate the timeouts for all other pending * commands. */ - LIST_FOREACH(list_scb, &ahc->pending_scbs, - pending_links) { + LIST_FOREACH(list_scb, &ahc->pending_scbs, + pending_links) { aic_scb_timer_reset(list_scb, aic_get_timeout(scb)); @@ -462,13 +464,11 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) } if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { - ahc_lock(); SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h, sim_links.sle); ccb->ccb_h.status = CAM_REQ_INPROG; if ((ahc->flags & AHC_TQINFIFO_BLOCKED) != 0) ahc_run_tqinfifo(ahc, /*paused*/FALSE); - ahc_unlock(); break; } @@ -498,17 +498,14 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) /* * get an scb to use. */ - ahc_lock(); if ((scb = ahc_get_scb(ahc)) == NULL) { xpt_freeze_simq(sim, /*count*/1); ahc->flags |= AHC_RESOURCE_SHORTAGE; - ahc_unlock(); ccb->ccb_h.status = CAM_REQUEUE_REQ; xpt_done(ccb); return; } - ahc_unlock(); hscb = scb->hscb; @@ -639,8 +636,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) break; } - ahc_lock(); - if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) *discenable |= devinfo.target_mask; @@ -716,7 +711,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) spi->ppr_options, update_type, /*paused*/FALSE); } - ahc_unlock(); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); #else @@ -752,8 +746,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) break; } - ahc_lock(); - if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) { if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) *discenable |= devinfo.target_mask; @@ -834,7 +826,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) ppr_options, update_type, /*paused*/FALSE); } - ahc_unlock(); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); #endif @@ -844,10 +835,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) /* Get default/user set transfer settings for the target */ { - ahc_lock(); ahc_get_tran_settings(ahc, SIM_SCSI_ID(ahc, sim), SIM_CHANNEL(ahc, sim), &ccb->cts); - ahc_unlock(); xpt_done(ccb); break; } @@ -866,10 +855,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) { int found; - ahc_lock(); found = ahc_reset_channel(ahc, SIM_CHANNEL(ahc, sim), /*initiate reset*/TRUE); - ahc_unlock(); if (bootverbose) { xpt_print_path(SIM_PATH(ahc, sim)); kprintf("SCSI bus reset delivered. " @@ -1077,14 +1064,12 @@ ahc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) * Revert to async/narrow transfers * for the next device. */ - ahc_lock(); ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, AHC_TRANS_GOAL|AHC_TRANS_CUR, /*paused*/FALSE); /*period*/0, /*offset*/0, /*ppr_options*/0, AHC_TRANS_GOAL|AHC_TRANS_CUR, /*paused*/FALSE); - ahc_unlock(); break; } default: @@ -1114,9 +1099,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, aic_set_transaction_status(scb, CAM_REQ_CMP_ERR); if (nsegments != 0) bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); - ahc_lock(); ahc_free_scb(ahc, scb); - ahc_unlock(); xpt_done(ccb); return; } @@ -1189,9 +1172,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, CAM_REQ_TOO_BIG); bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); - ahc_lock(); ahc_free_scb(ahc, scb); - ahc_unlock(); xpt_done(ccb); return; } @@ -1214,8 +1195,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, scb->sg_count = nsegments; - ahc_lock(); - /* * Last time we need to check if this SCB needs to * be aborted. @@ -1224,7 +1203,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, if (nsegments != 0) bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); ahc_free_scb(ahc, scb); - ahc_unlock(); xpt_done(ccb); return; } @@ -1275,7 +1253,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe); scb->flags |= SCB_UNTAGGEDQ; if (TAILQ_FIRST(untagged_q) != scb) { - ahc_unlock(); return; } } @@ -1297,8 +1274,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, } else { ahc_queue_scb(ahc, scb); } - - ahc_unlock(); } static void @@ -1330,9 +1305,7 @@ ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim, || (ccb_h->flags & CAM_CDB_PHYS) != 0) { aic_set_transaction_status(scb, CAM_REQ_INVALID); - ahc_lock(); ahc_free_scb(ahc, scb); - ahc_unlock(); xpt_done((union ccb *)csio); return; } @@ -1628,16 +1601,11 @@ ahc_detach(device_t dev) device_printf(dev, "detaching device\n"); ahc = device_get_softc(dev); - ahc = ahc_find_softc(ahc); - if (ahc == NULL) { - device_printf(dev, "aic7xxx already detached\n"); - return (ENOENT); - } + ahc_lock(ahc); TAILQ_REMOVE(&ahc_tailq, ahc, links); - ahc_lock(); ahc_intr_enable(ahc, FALSE); bus_teardown_intr(dev, ahc->platform_data->irq, ahc->platform_data->ih); - ahc_unlock(); + ahc_unlock(ahc); ahc_free(ahc); return (0); } @@ -1674,6 +1642,7 @@ static int ahc_modevent(module_t mod, int type, void *data) { /* XXX Deal with busy status on unload. */ + /* XXX Deal with unknown events */ return 0; } diff --git a/sys/dev/disk/aic7xxx/aic7xxx_osm.h b/sys/dev/disk/aic7xxx/aic7xxx_osm.h index 193bef0..d0c7a97 100644 --- a/sys/dev/disk/aic7xxx/aic7xxx_osm.h +++ b/sys/dev/disk/aic7xxx/aic7xxx_osm.h @@ -126,6 +126,17 @@ extern devclass_t ahc_devclass; /* This driver supports target mode */ #define AHC_TARGET_MODE 1 +/***************************** Core Includes **********************************/ +#ifdef AHC_REG_PRETTY_PRINT +#define AIC_DEBUG_REGISTERS 1 +#else +#define AIC_DEBUG_REGISTERS 0 +#endif +#define AIC_CORE_INCLUDE "aic7xxx.h" +#define AIC_LIB_PREFIX ahc +#define AIC_CONST_PREFIX AHC +#include "aic_osm_lib.h" + /************************** Softc/SCB Platform Data ***************************/ struct ahc_platform_data { /* @@ -144,22 +155,12 @@ struct ahc_platform_data { void *ih; eventhandler_tag eh; struct thread *recovery_thread; + struct lock lock; }; struct scb_platform_data { }; -/***************************** Core Includes **********************************/ -#ifdef AHC_REG_PRETTY_PRINT -#define AIC_DEBUG_REGISTERS 1 -#else -#define AIC_DEBUG_REGISTERS 0 -#endif -#define AIC_CORE_INCLUDE "aic7xxx.h" -#define AIC_LIB_PREFIX ahc -#define AIC_CONST_PREFIX AHC -#include "aic_osm_lib.h" - /*************************** Device Access ************************************/ #define ahc_inb(ahc, port) \ bus_space_read_1((ahc)->tag, (ahc)->bsh, port) @@ -184,19 +185,26 @@ ahc_flush_device_writes(struct ahc_softc *ahc) /**************************** Locking Primitives ******************************/ /* Lock protecting internal data structures */ -static __inline void ahc_lock(void); -static __inline void ahc_unlock(void); +static __inline void ahc_lockinit(struct ahc_softc *); +static __inline void ahc_lock(struct ahc_softc *); +static __inline void ahc_unlock(struct ahc_softc *); + +static __inline void +ahc_lockinit(struct ahc_softc *ahc) +{ + lockinit(&ahc->platform_data->lock, "ahc_lock", 0, LK_EXCLUSIVE|LK_CANRECURSE); +} static __inline void -ahc_lock(void) +ahc_lock(struct ahc_softc *ahc) { - crit_enter_id("ahc"); + lockmgr(&ahc->platform_data->lock, LK_EXCLUSIVE); } static __inline void -ahc_unlock(void) +ahc_unlock(struct ahc_softc *ahc) { - crit_exit_id("ahc"); + lockmgr(&ahc->platform_data->lock, LK_RELEASE); } /************************* Initialization/Teardown ****************************/ diff --git a/sys/dev/disk/aic7xxx/aic7xxx_pci.c b/sys/dev/disk/aic7xxx/aic7xxx_pci.c index c4caf62..2129843 100644 --- a/sys/dev/disk/aic7xxx/aic7xxx_pci.c +++ b/sys/dev/disk/aic7xxx/aic7xxx_pci.c @@ -1045,10 +1045,12 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) if (error != 0) return (error); + ahc_lock(ahc); /* * Link this softc in with all other ahc instances. */ ahc_softc_insert(ahc); + ahc_unlock(ahc); return (0); } diff --git a/sys/dev/disk/aic7xxx/aic_osm_lib.c b/sys/dev/disk/aic7xxx/aic_osm_lib.c index ff2568d..43e050c 100644 --- a/sys/dev/disk/aic7xxx/aic_osm_lib.c +++ b/sys/dev/disk/aic7xxx/aic_osm_lib.c @@ -57,7 +57,7 @@ aic_set_recoveryscb(struct aic_softc *aic, struct scb *scb) union ccb *ccb; ccb = list_scb->io_ctx; - callout_stop(&ccb->ccb_h.timeout_ch); + callout_stop(&scb->io_timer); } } } @@ -68,9 +68,9 @@ aic_platform_timeout(void *arg) struct scb *scb; scb = (struct scb *)arg; - aic_lock(); + aic_lock(scb->aic_softc); aic_timeout(scb); - aic_unlock(); + aic_unlock(scb->aic_softc); } int @@ -92,9 +92,7 @@ void aic_terminate_recovery_thread(struct aic_softc *aic) { - aic_lock(); if (aic->platform_data->recovery_thread == NULL) { - aic_unlock(); return; } aic->flags |= AIC_SHUTDOWN_RECOVERY; @@ -103,8 +101,7 @@ aic_terminate_recovery_thread(struct aic_softc *aic) * Sleep on a slightly different location * for this interlock just for added safety. */ - tsleep(aic->platform_data, 0, "thtrm", 0); - aic_unlock(); + msleep(aic->platform_data, &aic->platform_data->lock, 0, "thtrm", 0); } static void @@ -112,29 +109,21 @@ aic_recovery_thread(void *arg) { struct aic_softc *aic; -#if __FreeBSD_version >= 500000 - mtx_lock(&Giant); -#endif aic = (struct aic_softc *)arg; - aic_lock(); + aic_lock(aic); for (;;) { if (LIST_EMPTY(&aic->timedout_scbs) != 0 && (aic->flags & AIC_SHUTDOWN_RECOVERY) == 0) - tsleep(aic, 0, "idle", 0); + msleep(aic, &aic->platform_data->lock, 0, "idle", 0); if ((aic->flags & AIC_SHUTDOWN_RECOVERY) != 0) break; - aic_unlock(); aic_recover_commands(aic); - aic_lock(); } aic->platform_data->recovery_thread = NULL; wakeup(aic->platform_data); - aic_unlock(); -#if __FreeBSD_version >= 500000 - mtx_unlock(&Giant); -#endif + aic_unlock(aic); kthread_exit(); } diff --git a/sys/dev/disk/aic7xxx/aic_osm_lib.h b/sys/dev/disk/aic7xxx/aic_osm_lib.h index e402ba1..8916fe0 100644 --- a/sys/dev/disk/aic7xxx/aic_osm_lib.h +++ b/sys/dev/disk/aic7xxx/aic_osm_lib.h @@ -39,6 +39,8 @@ /******************************** OS Includes *********************************/ #if __FreeBSD_version >= 500000 #include <sys/mutex.h> +#else +#include <sys/lock.h> #endif /*************************** Library Symbol Mapping ***************************/ @@ -223,8 +225,7 @@ aic_scb_timer_reset(struct scb *scb, u_int msec) time = msec; time *= hz; time /= 1000; - callout_reset(&scb->io_ctx->ccb_h.timeout_ch, time, - aic_platform_timeout, scb); + callout_reset(&scb->io_timer, time, aic_platform_timeout, scb); } static __inline void @@ -233,13 +234,7 @@ aic_scb_timer_start(struct scb *scb) if (AIC_SCB_DATA(scb->aic_softc)->recovery_scbs == 0 && scb->io_ctx->ccb_h.timeout != CAM_TIME_INFINITY) { - uint64_t time; - - time = scb->io_ctx->ccb_h.timeout; - time *= hz; - time /= 1000; - callout_reset(&scb->io_ctx->ccb_h.timeout_ch, time, - aic_platform_timeout, scb); + aic_scb_timer_reset(scb, scb->io_ctx->ccb_h.timeout); } }
Attachment:
pgp00004.pgp
Description: PGP signature