From: | Peter Avalos <pavalos@xxxxxxxxxxxx> |
Date: | Tue, 1 Jan 2008 21:15:08 -0500 |
Mail-followup-to: | kernel@crater.dragonflybsd.org |
Here's my latest patch. The difference from the last is that I interlocked the tsleeps and asserted that the serializer is held in the interrupt handler. 1. Do the tsleep interlocks look right? 2. Did I use lwkt_serialize_handler_enable/disable properly? 3. Generally, does this patch look right? Thanks, Peter http://www.theshell.com/~pavalos/wip/aic7xxx-locking3.patch
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..47f3565 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); @@ -7019,6 +7005,9 @@ ahd_intr_enable(struct ahd_softc *ahd, int enable) { u_int hcntrl; + if (enable) + lwkt_serialize_handler_enable(&ahd->platform_data->serializer); + hcntrl = ahd_inb(ahd, HCNTRL); hcntrl &= ~INTEN; ahd->pause &= ~INTEN; @@ -7029,6 +7018,8 @@ ahd_intr_enable(struct ahd_softc *ahd, int enable) ahd->unpause |= INTEN; } ahd_outb(ahd, HCNTRL, hcntrl); + if (!enable) + lwkt_serialize_handler_disable(&ahd->platform_data->serializer); } void @@ -8024,15 +8015,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 +8027,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 +8037,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 +8072,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 +9235,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 +9260,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 +9450,6 @@ bus_reset: } ahd_unpause(ahd); - ahd_unlock(); } /* @@ -9889,13 +9865,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 +9876,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 +9934,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 +9992,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 +10004,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 +10013,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 +10028,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 +10094,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..3c38a89 100644 --- a/sys/dev/disk/aic7xxx/aic79xx_osm.c +++ b/sys/dev/disk/aic7xxx/aic79xx_osm.c @@ -94,9 +94,9 @@ ahd_map_int(struct ahd_softc *ahd) int error; /* Hook up our interrupt handler */ - error = bus_setup_intr(ahd->dev_softc, ahd->platform_data->irq, - 0, ahd_platform_intr, ahd, - &ahd->platform_data->ih, NULL); + error = bus_setup_intr(ahd->dev_softc, ahd->platform_data->irq, 0, + ahd_platform_intr, ahd, &ahd->platform_data->ih, + &ahd->platform_data->serializer); if (error != 0) device_printf(ahd->dev_softc, "bus_setup_intr() failed: %d\n", error); @@ -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,6 +184,7 @@ ahd_platform_intr(void *arg) struct ahd_softc *ahd; ahd = (struct ahd_softc *)arg; + ASSERT_SERIALIZED(&ahd->platform_data->serializer); ahd_intr(ahd); } @@ -206,7 +206,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 +369,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 +407,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 +421,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 +512,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 +535,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 +965,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 +999,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 +1037,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 +1046,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 +1094,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 +1120,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 +1128,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 +1145,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 +1426,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 +1467,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..994a616 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 lwkt_serialize serializer; }; 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) +{ + lwkt_serialize_init(&ahd->platform_data->serializer); +} static __inline void -ahd_lock(void) +ahd_lock(struct ahd_softc *ahd) { - crit_enter(); + lwkt_serialize_enter(&ahd->platform_data->serializer); } static __inline void -ahd_unlock(void) +ahd_unlock(struct ahd_softc *ahd) { - crit_exit(); + lwkt_serialize_exit(&ahd->platform_data->serializer); } /********************************** 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..febc516 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; @@ -5147,6 +5133,9 @@ ahc_intr_enable(struct ahc_softc *ahc, int enable) { u_int hcntrl; + if (enable) + lwkt_serialize_handler_enable(&ahc->platform_data->serializer); + hcntrl = ahc_inb(ahc, HCNTRL); hcntrl &= ~INTEN; ahc->pause &= ~INTEN; @@ -5157,6 +5146,8 @@ ahc_intr_enable(struct ahc_softc *ahc, int enable) ahc->unpause |= INTEN; } ahc_outb(ahc, HCNTRL, hcntrl); + if (!enable) + lwkt_serialize_handler_disable(&ahc->platform_data->serializer); } /* @@ -6988,8 +6979,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 +6998,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 +7250,6 @@ bus_reset: ahc_restart(ahc); else ahc_unpause(ahc); - ahc_unlock(); } /************************* Target Mode ****************************************/ @@ -7399,10 +7386,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 +7408,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 +7470,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 +7535,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 +7547,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 +7556,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 +7571,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 +7645,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..0b66a6d 100644 --- a/sys/dev/disk/aic7xxx/aic7xxx_osm.c +++ b/sys/dev/disk/aic7xxx/aic7xxx_osm.c @@ -106,9 +106,9 @@ ahc_map_int(struct ahc_softc *ahc) ahc->platform_data->irq_res_type = SYS_RES_IRQ; /* Hook up our interrupt handler */ - error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq, - 0, ahc_platform_intr, ahc, - &ahc->platform_data->ih, NULL); + error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq, 0, + ahc_platform_intr, ahc, &ahc->platform_data->ih, + &ahc->platform_data->serializer); if (error != 0) device_printf(ahc->dev_softc, "bus_setup_intr() failed: %d\n", @@ -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,6 +289,7 @@ ahc_platform_intr(void *arg) struct ahc_softc *ahc; ahc = (struct ahc_softc *)arg; + ASSERT_SERIALIZED(&ahc->platform_data->serializer); ahc_intr(ahc); } @@ -320,7 +321,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 +385,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 +463,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 +497,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 +635,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 +710,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) /*paused*/FALSE); } - ahc_unlock(); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); #else @@ -752,8 +745,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 +825,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 +834,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 +854,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 +1063,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); ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL, /*period*/0, /*offset*/0, /*ppr_options*/0, AHC_TRANS_GOAL|AHC_TRANS_CUR, /*paused*/FALSE); - ahc_unlock(); break; } default: @@ -1114,9 +1098,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 +1171,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 +1194,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 +1202,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 +1252,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 +1273,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 +1304,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 +1600,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 +1641,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..a73fc7a 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 lwkt_serialize serializer; }; 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) +{ + lwkt_serialize_init(&ahc->platform_data->serializer); +} static __inline void -ahc_lock(void) +ahc_lock(struct ahc_softc *ahc) { - crit_enter_id("ahc"); + lwkt_serialize_enter(&ahc->platform_data->serializer); } static __inline void -ahc_unlock(void) +ahc_unlock(struct ahc_softc *ahc) { - crit_exit_id("ahc"); + lwkt_serialize_exit(&ahc->platform_data->serializer); } /************************* 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..35ff4ae 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,12 @@ aic_terminate_recovery_thread(struct aic_softc *aic) * Sleep on a slightly different location * for this interlock just for added safety. */ + crit_enter(); + aic_lock(aic); + tsleep_interlock(aic->platform_data); + aic_unlock(aic); tsleep(aic->platform_data, 0, "thtrm", 0); - aic_unlock(); + crit_exit(); } static void @@ -112,29 +114,27 @@ 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) + && (aic->flags & AIC_SHUTDOWN_RECOVERY) == 0) { + crit_enter(); + tsleep_interlock(aic); + aic_unlock(aic); tsleep(aic, 0, "idle", 0); + crit_exit(); + aic_lock(aic); + } 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..ce4e153 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/serialize.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:
pgp00001.pgp
Description: PGP signature