summaryrefslogtreecommitdiffstats
path: root/sys/dev/advansys/advansys.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/advansys/advansys.c')
-rw-r--r--sys/dev/advansys/advansys.c161
1 files changed, 83 insertions, 78 deletions
diff --git a/sys/dev/advansys/advansys.c b/sys/dev/advansys/advansys.c
index cc18f18..d804b6d 100644
--- a/sys/dev/advansys/advansys.c
+++ b/sys/dev/advansys/advansys.c
@@ -49,6 +49,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/conf.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
@@ -79,6 +80,7 @@ __FBSDID("$FreeBSD$");
static void adv_action(struct cam_sim *sim, union ccb *ccb);
static void adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs,
int nsegments, int error);
+static void adv_intr_locked(struct adv_softc *adv);
static void adv_poll(struct cam_sim *sim);
static void adv_run_doneq(struct adv_softc *adv);
static struct adv_ccb_info *
@@ -97,15 +99,14 @@ static __inline struct adv_ccb_info *
adv_get_ccb_info(struct adv_softc *adv)
{
struct adv_ccb_info *cinfo;
- int opri;
- opri = splcam();
+ if (!dumping)
+ mtx_assert(&adv->lock, MA_OWNED);
if ((cinfo = SLIST_FIRST(&adv->free_ccb_infos)) != NULL) {
SLIST_REMOVE_HEAD(&adv->free_ccb_infos, links);
} else {
cinfo = adv_alloc_ccb_info(adv);
}
- splx(opri);
return (cinfo);
}
@@ -113,12 +114,11 @@ adv_get_ccb_info(struct adv_softc *adv)
static __inline void
adv_free_ccb_info(struct adv_softc *adv, struct adv_ccb_info *cinfo)
{
- int opri;
- opri = splcam();
+ if (!dumping)
+ mtx_assert(&adv->lock, MA_OWNED);
cinfo->state = ACCB_FREE;
SLIST_INSERT_HEAD(&adv->free_ccb_infos, cinfo, links);
- splx(opri);
}
static __inline void
@@ -139,6 +139,9 @@ adv_clear_state(struct adv_softc *adv, union ccb* ccb)
static void
adv_clear_state_really(struct adv_softc *adv, union ccb* ccb)
{
+
+ if (!dumping)
+ mtx_assert(&adv->lock, MA_OWNED);
if ((adv->state & ADV_BUSDMA_BLOCK_CLEARED) != 0)
adv->state &= ~(ADV_BUSDMA_BLOCK_CLEARED|ADV_BUSDMA_BLOCK);
if ((adv->state & ADV_RESOURCE_SHORTAGE) != 0) {
@@ -164,13 +167,14 @@ adv_clear_state_really(struct adv_softc *adv, union ccb* ccb)
*/
ccb_h = LIST_FIRST(&adv->pending_ccbs);
while (ccb_h != NULL) {
- ccb_h->timeout_ch =
- timeout(adv_timeout, (caddr_t)ccb_h,
- (ccb_h->timeout * hz) / 1000);
+ cinfo = ccb_h->ccb_cinfo_ptr;
+ callout_reset(&cinfo->timer,
+ ccb_h->timeout * hz / 1000, adv_timeout,
+ ccb_h);
ccb_h = LIST_NEXT(ccb_h, sim_links.le);
}
adv->state &= ~ADV_IN_TIMEOUT;
- printf("%s: No longer in timeout\n", adv_name(adv));
+ device_printf(adv->dev, "No longer in timeout\n");
}
}
if (adv->state == 0)
@@ -186,15 +190,6 @@ adv_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
*physaddr = segs->ds_addr;
}
-char *
-adv_name(struct adv_softc *adv)
-{
- static char name[10];
-
- snprintf(name, sizeof(name), "adv%d", adv->unit);
- return (name);
-}
-
static void
adv_action(struct cam_sim *sim, union ccb *ccb)
{
@@ -203,6 +198,7 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("adv_action\n"));
adv = (struct adv_softc *)cam_sim_softc(sim);
+ mtx_assert(&adv->lock, MA_OWNED);
switch (ccb->ccb_h.func_code) {
/* Common cases first */
@@ -229,10 +225,8 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
* to a single buffer
*/
if ((ccb_h->flags & CAM_DATA_PHYS) == 0) {
- int s;
int error;
- s = splsoftvm();
error =
bus_dmamap_load(adv->buffer_dmat,
cinfo->dmamap,
@@ -250,7 +244,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
adv_set_state(adv,
ADV_BUSDMA_BLOCK);
}
- splx(s);
} else {
struct bus_dma_segment seg;
@@ -299,7 +292,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
target_bit_vector targ_mask;
struct adv_transinfo *tconf;
u_int update_type;
- int s;
cts = &ccb->cts;
targ_mask = ADV_TID_TO_TARGET_MASK(cts->ccb_h.target_id);
@@ -320,7 +312,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
break;
}
- s = splcam();
scsi = &cts->proto_specific.scsi;
spi = &cts->xport_specific.spi;
if ((update_type & ADV_TRANS_GOAL) != 0) {
@@ -387,7 +378,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
spi->sync_offset, update_type);
}
- splx(s);
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
break;
@@ -400,7 +390,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
struct ccb_trans_settings *cts;
struct adv_transinfo *tconf;
target_bit_vector target_mask;
- int s;
cts = &ccb->cts;
target_mask = ADV_TID_TO_TARGET_MASK(cts->ccb_h.target_id);
@@ -416,7 +405,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
- s = splcam();
if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
tconf = &adv->tinfo[cts->ccb_h.target_id].current;
if ((adv->disc_enable & target_mask) != 0)
@@ -432,7 +420,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
}
spi->sync_period = tconf->period;
spi->sync_offset = tconf->offset;
- splx(s);
spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
spi->valid = CTS_SPI_VALID_SYNC_RATE
| CTS_SPI_VALID_SYNC_OFFSET
@@ -454,13 +441,10 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
}
case XPT_RESET_BUS: /* Reset the specified SCSI bus */
{
- int s;
- s = splcam();
adv_stop_execution(adv);
adv_reset_bus(adv, /*initiate_reset*/TRUE);
adv_start_execution(adv);
- splx(s);
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
@@ -521,13 +505,14 @@ adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs,
struct adv_ccb_info *cinfo;
struct adv_scsi_q scsiq;
struct adv_sg_head sghead;
- int s;
csio = (struct ccb_scsiio *)arg;
ccb_h = &csio->ccb_h;
sim = xpt_path_sim(ccb_h->path);
adv = (struct adv_softc *)cam_sim_softc(sim);
cinfo = (struct adv_ccb_info *)csio->ccb_h.ccb_cinfo_ptr;
+ if (!dumping)
+ mtx_assert(&adv->lock, MA_OWNED);
/*
* Setup our done routine to release the simq on
@@ -596,8 +581,6 @@ adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs,
scsiq.sg_head = NULL;
}
- s = splcam();
-
/*
* Last time we need to check if this SCB needs to
* be aborted.
@@ -608,7 +591,6 @@ adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs,
adv_clear_state(adv, (union ccb *)csio);
adv_free_ccb_info(adv, cinfo);
xpt_done((union ccb *)csio);
- splx(s);
return;
}
@@ -621,16 +603,14 @@ adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs,
adv_clear_state(adv, (union ccb *)csio);
adv_free_ccb_info(adv, cinfo);
xpt_done((union ccb *)csio);
- splx(s);
return;
}
cinfo->state |= ACCB_ACTIVE;
ccb_h->status |= CAM_SIM_QUEUED;
LIST_INSERT_HEAD(&adv->pending_ccbs, ccb_h, sim_links.le);
/* Schedule our timeout */
- ccb_h->timeout_ch =
- timeout(adv_timeout, csio, (ccb_h->timeout * hz)/1000);
- splx(s);
+ callout_reset(&cinfo->timer, ccb_h->timeout * hz /1000, adv_timeout,
+ csio);
}
static struct adv_ccb_info *
@@ -641,11 +621,12 @@ adv_alloc_ccb_info(struct adv_softc *adv)
cinfo = &adv->ccb_infos[adv->ccb_infos_allocated];
cinfo->state = ACCB_FREE;
+ callout_init_mtx(&cinfo->timer, &adv->lock, 0);
error = bus_dmamap_create(adv->buffer_dmat, /*flags*/0,
&cinfo->dmamap);
if (error != 0) {
- printf("%s: Unable to allocate CCB info "
- "dmamap - error %d\n", adv_name(adv), error);
+ device_printf(adv->dev, "Unable to allocate CCB info "
+ "dmamap - error %d\n", error);
return (NULL);
}
adv->ccb_infos_allocated++;
@@ -655,28 +636,28 @@ adv_alloc_ccb_info(struct adv_softc *adv)
static void
adv_destroy_ccb_info(struct adv_softc *adv, struct adv_ccb_info *cinfo)
{
+
+ callout_drain(&cinfo->timer);
bus_dmamap_destroy(adv->buffer_dmat, cinfo->dmamap);
}
void
adv_timeout(void *arg)
{
- int s;
union ccb *ccb;
struct adv_softc *adv;
- struct adv_ccb_info *cinfo;
+ struct adv_ccb_info *cinfo, *cinfo2;
ccb = (union ccb *)arg;
adv = (struct adv_softc *)xpt_path_sim(ccb->ccb_h.path)->softc;
cinfo = (struct adv_ccb_info *)ccb->ccb_h.ccb_cinfo_ptr;
+ mtx_assert(&adv->lock, MA_OWNED);
xpt_print_path(ccb->ccb_h.path);
printf("Timed out\n");
- s = splcam();
/* Have we been taken care of already?? */
if (cinfo == NULL || cinfo->state == ACCB_FREE) {
- splx(s);
return;
}
@@ -702,7 +683,8 @@ adv_timeout(void *arg)
ccb_h = LIST_FIRST(&adv->pending_ccbs);
while (ccb_h != NULL) {
- untimeout(adv_timeout, ccb_h, ccb_h->timeout_ch);
+ cinfo2 = ccb_h->ccb_cinfo_ptr;
+ callout_stop(&cinfo2->timer);
ccb_h = LIST_NEXT(ccb_h, sim_links.le);
}
@@ -713,8 +695,7 @@ adv_timeout(void *arg)
adv_abort_ccb(adv, ccb->ccb_h.target_id,
ccb->ccb_h.target_lun, ccb,
CAM_CMD_TIMEOUT, /*queued_only*/FALSE);
- ccb->ccb_h.timeout_ch =
- timeout(adv_timeout, ccb, 2 * hz);
+ callout_reset(&cinfo->timer, 2 * hz, adv_timeout, ccb);
} else {
/* Our attempt to perform an abort failed, go for a reset */
xpt_print_path(ccb->ccb_h.path);
@@ -724,11 +705,10 @@ adv_timeout(void *arg)
adv_reset_bus(adv, /*initiate_reset*/TRUE);
}
adv_start_execution(adv);
- splx(s);
}
struct adv_softc *
-adv_alloc(device_t dev, bus_space_tag_t tag, bus_space_handle_t bsh)
+adv_alloc(device_t dev, struct resource *res, long offset)
{
struct adv_softc *adv = device_get_softc(dev);
@@ -738,9 +718,9 @@ adv_alloc(device_t dev, bus_space_tag_t tag, bus_space_handle_t bsh)
LIST_INIT(&adv->pending_ccbs);
SLIST_INIT(&adv->free_ccb_infos);
adv->dev = dev;
- adv->unit = device_get_unit(dev);
- adv->tag = tag;
- adv->bsh = bsh;
+ adv->res = res;
+ adv->reg_off = offset;
+ mtx_init(&adv->lock, "adv", NULL, MTX_DEF);
return(adv);
}
@@ -773,6 +753,7 @@ adv_free(struct adv_softc *adv)
if (adv->ccb_infos != NULL)
free(adv->ccb_infos, M_DEVBUF);
case 0:
+ mtx_destroy(&adv->lock);
break;
}
}
@@ -786,6 +767,7 @@ adv_init(struct adv_softc *adv)
u_int16_t config_lsw;
u_int16_t config_msw;
+ mtx_lock(&adv->lock);
adv_lib_init(adv);
/*
@@ -794,14 +776,16 @@ adv_init(struct adv_softc *adv)
adv_write_lram_16(adv, ADV_HALTCODE_W, 0x00FE);
adv_stop_execution(adv);
if (adv_stop_chip(adv) == 0 || adv_is_chip_halted(adv) == 0) {
- printf("adv%d: Unable to halt adapter. Initialization"
- "failed\n", adv->unit);
+ mtx_unlock(&adv->lock);
+ device_printf(adv->dev,
+ "Unable to halt adapter. Initialization failed\n");
return (1);
}
ADV_OUTW(adv, ADV_REG_PROG_COUNTER, ADV_MCODE_START_ADDR);
if (ADV_INW(adv, ADV_REG_PROG_COUNTER) != ADV_MCODE_START_ADDR) {
- printf("adv%d: Unable to set program counter. Initialization"
- "failed\n", adv->unit);
+ mtx_unlock(&adv->lock);
+ device_printf(adv->dev,
+ "Unable to set program counter. Initialization failed\n");
return (1);
}
@@ -876,8 +860,8 @@ adv_init(struct adv_softc *adv)
} else {
u_int8_t sync_data;
- printf("adv%d: Warning EEPROM Checksum mismatch. "
- "Using default device parameters\n", adv->unit);
+ device_printf(adv->dev, "Warning EEPROM Checksum mismatch. "
+ "Using default device parameters\n");
/* Set reasonable defaults since we can't read the EEPROM */
adv->isa_dma_speed = /*ADV_DEF_ISA_DMA_SPEED*/1;
@@ -940,13 +924,15 @@ adv_init(struct adv_softc *adv)
* to be 100% correct.
*/
if (adv_set_eeprom_config(adv, &eeprom_config) != 0)
- printf("%s: WARNING! Failure writing to EEPROM.\n",
- adv_name(adv));
+ device_printf(adv->dev,
+ "WARNING! Failure writing to EEPROM.\n");
#endif
adv_set_chip_scsiid(adv, adv->scsi_id);
- if (adv_init_lram_and_mcode(adv))
+ if (adv_init_lram_and_mcode(adv)) {
+ mtx_unlock(&adv->lock);
return (1);
+ }
adv->disc_enable = adv->user_disc_enable;
@@ -969,10 +955,12 @@ adv_init(struct adv_softc *adv)
}
adv_write_lram_8(adv, ADVV_USE_TAGGED_QNG_B, TARGET_BIT_VECTOR_SET);
adv_write_lram_8(adv, ADVV_CAN_TAGGED_QNG_B, TARGET_BIT_VECTOR_SET);
- printf("adv%d: AdvanSys %s Host Adapter, SCSI ID %d, queue depth %d\n",
- adv->unit, (adv->type & ADV_ULTRA) && (max_sync == 0)
- ? "Ultra SCSI" : "SCSI",
- adv->scsi_id, adv->max_openings);
+ device_printf(adv->dev,
+ "AdvanSys %s Host Adapter, SCSI ID %d, queue depth %d\n",
+ (adv->type & ADV_ULTRA) && (max_sync == 0)
+ ? "Ultra SCSI" : "SCSI",
+ adv->scsi_id, adv->max_openings);
+ mtx_unlock(&adv->lock);
return (0);
}
@@ -980,14 +968,24 @@ void
adv_intr(void *arg)
{
struct adv_softc *adv;
+
+ adv = arg;
+ mtx_lock(&adv->lock);
+ adv_intr_locked(adv);
+ mtx_unlock(&adv->lock);
+}
+
+void
+adv_intr_locked(struct adv_softc *adv)
+{
u_int16_t chipstat;
u_int16_t saved_ram_addr;
u_int8_t ctrl_reg;
u_int8_t saved_ctrl_reg;
u_int8_t host_flag;
- adv = (struct adv_softc *)arg;
-
+ if (!dumping)
+ mtx_assert(&adv->lock, MA_OWNED);
chipstat = ADV_INW(adv, ADV_CHIP_STATUS);
/* Is it for us? */
@@ -1000,7 +998,7 @@ adv_intr(void *arg)
ADV_CC_TEST));
if ((chipstat & (ADV_CSW_SCSI_RESET_LATCH|ADV_CSW_SCSI_RESET_ACTIVE))) {
- printf("Detected Bus Reset\n");
+ device_printf(adv->dev, "Detected Bus Reset\n");
adv_reset_bus(adv, /*initiate_reset*/FALSE);
return;
}
@@ -1128,9 +1126,11 @@ adv_done(struct adv_softc *adv, union ccb *ccb, u_int done_stat,
{
struct adv_ccb_info *cinfo;
+ if (!dumping)
+ mtx_assert(&adv->lock, MA_OWNED);
cinfo = (struct adv_ccb_info *)ccb->ccb_h.ccb_cinfo_ptr;
LIST_REMOVE(&ccb->ccb_h, sim_links.le);
- untimeout(adv_timeout, ccb, ccb->ccb_h.timeout_ch);
+ callout_stop(&cinfo->timer);
if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
bus_dmasync_op_t op;
@@ -1239,7 +1239,7 @@ adv_done(struct adv_softc *adv, union ccb *ccb, u_int done_stat,
case QHSTA_M_MICRO_CODE_ERROR_HALT:
default:
panic("%s: Unhandled Host status error %x",
- adv_name(adv), host_stat);
+ device_get_nameunit(adv->dev), host_stat);
/* NOTREACHED */
}
break;
@@ -1280,7 +1280,8 @@ adv_done(struct adv_softc *adv, union ccb *ccb, u_int done_stat,
static void
adv_poll(struct cam_sim *sim)
{
- adv_intr(cam_sim_softc(sim));
+
+ adv_intr_locked(cam_sim_softc(sim));
}
/*
@@ -1350,7 +1351,7 @@ adv_attach(adv)
/* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT,
/* flags */ BUS_DMA_ALLOCNOW,
/* lockfunc */ busdma_lock_mutex,
- /* lockarg */ &Giant,
+ /* lockarg */ &adv->lock,
&adv->buffer_dmat) != 0) {
return (ENXIO);
}
@@ -1371,7 +1372,7 @@ adv_attach(adv)
/* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT,
/* flags */ 0,
/* lockfunc */ busdma_lock_mutex,
- /* lockarg */ &Giant,
+ /* lockarg */ &adv->lock,
&adv->sense_dmat) != 0) {
return (ENXIO);
}
@@ -1398,8 +1399,8 @@ adv_attach(adv)
* Fire up the chip
*/
if (adv_start_chip(adv) != 1) {
- printf("adv%d: Unable to start on board processor. Aborting.\n",
- adv->unit);
+ device_printf(adv->dev,
+ "Unable to start on board processor. Aborting.\n");
return (ENXIO);
}
@@ -1413,8 +1414,8 @@ adv_attach(adv)
/*
* Construct our SIM entry.
*/
- adv->sim = cam_sim_alloc(adv_action, adv_poll, "adv", adv, adv->unit,
- &Giant, 1, adv->max_openings, devq);
+ adv->sim = cam_sim_alloc(adv_action, adv_poll, "adv", adv,
+ device_get_unit(adv->dev), &adv->lock, 1, adv->max_openings, devq);
if (adv->sim == NULL)
return (ENOMEM);
@@ -1423,8 +1424,10 @@ adv_attach(adv)
*
* XXX Twin Channel EISA Cards???
*/
+ mtx_lock(&adv->lock);
if (xpt_bus_register(adv->sim, adv->dev, 0) != CAM_SUCCESS) {
cam_sim_free(adv->sim, /*free devq*/TRUE);
+ mtx_unlock(&adv->lock);
return (ENXIO);
}
@@ -1433,6 +1436,7 @@ adv_attach(adv)
!= CAM_REQ_CMP) {
xpt_bus_deregister(cam_sim_path(adv->sim));
cam_sim_free(adv->sim, /*free devq*/TRUE);
+ mtx_unlock(&adv->lock);
return (ENXIO);
}
@@ -1442,6 +1446,7 @@ adv_attach(adv)
csa.callback = advasync;
csa.callback_arg = adv;
xpt_action((union ccb *)&csa);
+ mtx_unlock(&adv->lock);
return (0);
}
MODULE_DEPEND(adv, cam, 1, 1, 1);
OpenPOWER on IntegriCloud