From: Sascha Wildner Date: Thu, 29 Nov 2012 17:20:48 +0000 (+0100) Subject: bt(4): Sync with FreeBSD. X-Git-Tag: v3.4.0rc~775 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/cf5a2d8858313285c4fbe3ea5d711eb1b6f922a3 bt(4): Sync with FreeBSD. Main change is making it MPSAFE. Taken-from: FreeBSD --- diff --git a/share/man/man4/bt.4 b/share/man/man4/bt.4 index d911014213..586f8a855e 100644 --- a/share/man/man4/bt.4 +++ b/share/man/man4/bt.4 @@ -33,28 +33,32 @@ .Nm bt .Nd Buslogic/Mylex MultiMaster SCSI host adapter driver .Sh SYNOPSIS -.Cd device scbus -.Cd device bt +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device scbus" +.Cd "device bt" +.Ed .Sh DESCRIPTION This driver provides access to the .Tn SCSI bus connected to a Buslogic/Mylex MultiMaster or compatible controller: .Bd -ragged -offset indent -.Bl -column "BT-956CD " "PCI " "Commands " Description MultiMaster "W" Series Host Adapters: -.Pp -.Em "Adapter Bus Commands Description" -BT-948 PCI 192 ULtra SCSI-3 -BT-958 PCI 192 Wide ULtra SCSI-3 -BT-958D PCI 192 Wide Differential ULtra SCSI-3 +.Bl -column "BT-956CD " "PCI " "Commands " "Description" +.Em "Adapter" Ta Em "Bus" Ta Em "Commands" Ta Em "Description" +BT-948 PCI 192 Ultra SCSI-3 +BT-958 PCI 192 Wide Ultra SCSI-3 +BT-958D PCI 192 Wide Differential Ultra SCSI-3 .El -.Bl -column "BT-956CD " "PCI " "Commands " Description -MultiMaster "C" Series Host Adapters: .Pp -.Em "Adapter Bus Commands Description" -BT-946C PCI 100 Fast SCSI-2 -BT-956C PCI 100 Wide Fast SCSI-2 -BT-956CD PCI 100 Wide Differential Fast SCSI-2 +MultiMaster "C" Series Host Adapters: +.Bl -column "BT-956CD " "PCI " "Commands " "Description" +.Em "Adapter" Ta Em "Bus" Ta Em "Commands" Ta Em "Description" +BT-946C PCI 100 Fast SCSI-2 +BT-956C PCI 100 Wide Fast SCSI-2 +BT-956CD PCI 100 Wide Differential Fast SCSI-2 .El .Ed .Pp @@ -65,7 +69,8 @@ Tagged queueing is supported on 'W' series adapters and 'C' series adapters with firmware of rev 4.42 and higher. .Pp Boards with certain firmware revisions may lock up under heavy load to -certain devices, especially if tagged queueing is used. Should you encounter +certain devices, especially if tagged queueing is used. +Should you encounter a problem with your adapter, contact Mylex technical support and ensure you have the latest firmware for your controller. .Sh FILES @@ -93,7 +98,8 @@ patch kit. .An Julian Elischer wrote a driver for the Multimaster cards that appeared in the .Bx 386 -patch kit. The driver was rewritten by +patch kit. +The driver was rewritten by .An Justin T. Gibbs to take advantage of new board features and work with the CAM SCSI framework in .Fx 3.0 . @@ -101,6 +107,7 @@ to take advantage of new board features and work with the CAM SCSI framework in Special thanks to .An Leonard N. Zubkoff for writing such a complete and well documented Mylex/BusLogic MultiMaster -driver for Linux. Support in this driver for the wide range of MultiMaster +driver for Linux. +Support in this driver for the wide range of MultiMaster controllers and firmware revisions, with their otherwise undocumented quirks, would not have been possible without his efforts. diff --git a/sys/dev/disk/buslogic/bt.c b/sys/dev/disk/buslogic/bt.c index ea5c30b348..5d2c3da80c 100644 --- a/sys/dev/disk/buslogic/bt.c +++ b/sys/dev/disk/buslogic/bt.c @@ -1,4 +1,4 @@ -/* +/*- * Generic driver for the BusLogic MultiMaster SCSI host adapters * Product specific probe and attach routines can be found in: * sys/dev/buslogic/bt_pci.c BT-946, BT-948, BT-956, BT-958 cards @@ -27,7 +27,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/buslogic/bt.c,v 1.25.2.1 2000/08/02 22:32:26 peter Exp $ + * $FreeBSD: src/sys/dev/buslogic/bt.c,v 1.54 2012/11/17 01:51:40 svnexp Exp $ */ /* @@ -43,13 +43,11 @@ #include #include #include +#include #include #include #include -#include -#include - #include #include #include @@ -60,7 +58,7 @@ #include #include -#include "btreg.h" +#include /* MailBox Management functions */ static __inline void btnextinbox(struct bt_softc *bt); @@ -105,7 +103,7 @@ static __inline struct bt_ccb * btccbptov(struct bt_softc *bt, u_int32_t ccb_addr) { return (bt->bt_ccb_array + - ((struct bt_ccb*)(uintptr_t)ccb_addr-(struct bt_ccb*)(uintptr_t)bt->bt_ccb_physbase)); + ((struct bt_ccb*)(uintptr_t)ccb_addr - (struct bt_ccb*)(uintptr_t)bt->bt_ccb_physbase)); } static __inline u_int32_t @@ -134,6 +132,7 @@ static void btallocccbs(struct bt_softc *bt); static bus_dmamap_callback_t btexecuteccb; static void btdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code); +static void bt_intr_locked(struct bt_softc *bt); /* Host adapter command functions */ static int btreset(struct bt_softc* bt, int hard_reset); @@ -155,9 +154,8 @@ static void btaction(struct cam_sim *sim, union ccb *ccb); static void btpoll(struct cam_sim *sim); /* Our timeout handler */ -timeout_t bttimeout; +static void bttimeout(void *arg); -u_long bt_unit = 0; /* Exported functions */ void @@ -170,12 +168,10 @@ bt_init_softc(device_t dev, struct resource *port, LIST_INIT(&bt->pending_ccbs); SLIST_INIT(&bt->sg_maps); bt->dev = dev; - bt->unit = device_get_unit(dev); bt->port = port; bt->irq = irq; bt->drq = drq; - bt->tag = rman_get_bustag(port); - bt->bsh = rman_get_bushandle(port); + lockinit(&bt->lock, "bt", 0, LK_CANRECURSE); } void @@ -208,25 +204,33 @@ bt_free_softc(device_t dev) } case 7: bus_dmamap_unload(bt->ccb_dmat, bt->ccb_dmamap); + /* FALLTHROUGH */ case 6: bus_dmamem_free(bt->ccb_dmat, bt->bt_ccb_array, bt->ccb_dmamap); bus_dmamap_destroy(bt->ccb_dmat, bt->ccb_dmamap); + /* FALLTHROUGH */ case 5: bus_dma_tag_destroy(bt->ccb_dmat); + /* FALLTHROUGH */ case 4: bus_dmamap_unload(bt->mailbox_dmat, bt->mailbox_dmamap); + /* FALLTHROUGH */ case 3: bus_dmamem_free(bt->mailbox_dmat, bt->in_boxes, bt->mailbox_dmamap); bus_dmamap_destroy(bt->mailbox_dmat, bt->mailbox_dmamap); + /* FALLTHROUGH */ case 2: bus_dma_tag_destroy(bt->buffer_dmat); + /* FALLTHROUGH */ case 1: bus_dma_tag_destroy(bt->mailbox_dmat); + /* FALLTHROUGH */ case 0: break; } + lockuninit(&bt->lock); } /* @@ -276,7 +280,9 @@ bt_probe(device_t dev) * adapter and attempt to fetch the extended setup * information. This should filter out all 1542 cards. */ + lockmgr(&bt->lock, LK_EXCLUSIVE); if ((error = btreset(bt, /*hard_reset*/TRUE)) != 0) { + lockmgr(&bt->lock, LK_RELEASE); if (bootverbose) device_printf(dev, "Failed Reset\n"); return (ENXIO); @@ -286,6 +292,7 @@ bt_probe(device_t dev) error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, ¶m, /*parmlen*/1, (u_int8_t*)&esetup_info, sizeof(esetup_info), DEFAULT_CMD_TIMEOUT); + lockmgr(&bt->lock, LK_RELEASE); if (error != 0) { return (ENXIO); } @@ -307,10 +314,12 @@ bt_fetch_adapter_info(device_t dev) u_int8_t length_param; /* First record the firmware version */ + lockmgr(&bt->lock, LK_EXCLUSIVE); error = bt_cmd(bt, BOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0, (u_int8_t*)&board_id, sizeof(board_id), DEFAULT_CMD_TIMEOUT); if (error != 0) { + lockmgr(&bt->lock, LK_RELEASE); device_printf(dev, "bt_fetch_adapter_info - Failed Get Board Info\n"); return (error); } @@ -329,6 +338,7 @@ bt_fetch_adapter_info(device_t dev) (u_int8_t*)&bt->firmware_ver[3], 1, DEFAULT_CMD_TIMEOUT); if (error != 0) { + lockmgr(&bt->lock, LK_RELEASE); device_printf(dev, "bt_fetch_adapter_info - Failed Get " "Firmware 3rd Digit\n"); @@ -345,6 +355,7 @@ bt_fetch_adapter_info(device_t dev) (u_int8_t*)&bt->firmware_ver[4], 1, DEFAULT_CMD_TIMEOUT); if (error != 0) { + lockmgr(&bt->lock, LK_RELEASE); device_printf(dev, "bt_fetch_adapter_info - Failed Get " "Firmware 4th Digit\n"); @@ -377,6 +388,7 @@ bt_fetch_adapter_info(device_t dev) (u_int8_t*)&esetup_info, sizeof(esetup_info), DEFAULT_CMD_TIMEOUT); if (error != 0) { + lockmgr(&bt->lock, LK_RELEASE); return (error); } @@ -398,6 +410,7 @@ bt_fetch_adapter_info(device_t dev) (u_int8_t*)&model_data, sizeof(model_data), DEFAULT_CMD_TIMEOUT); if (error != 0) { + lockmgr(&bt->lock, LK_RELEASE); device_printf(dev, "bt_fetch_adapter_info - Failed Inquire " "Model Number\n"); @@ -484,6 +497,7 @@ bt_fetch_adapter_info(device_t dev) sizeof(auto_scsi_data), DEFAULT_CMD_TIMEOUT); if (error != 0) { + lockmgr(&bt->lock, LK_RELEASE); device_printf(dev, "bt_fetch_adapter_info - Failed " "Get Auto SCSI Info\n"); @@ -519,6 +533,7 @@ bt_fetch_adapter_info(device_t dev) sizeof(setup_info), DEFAULT_CMD_TIMEOUT); if (error != 0) { + lockmgr(&bt->lock, LK_RELEASE); device_printf(dev, "bt_fetch_adapter_info - Failed " "Get Setup Info\n"); @@ -546,6 +561,7 @@ bt_fetch_adapter_info(device_t dev) error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, (u_int8_t*)&config_data, sizeof(config_data), DEFAULT_CMD_TIMEOUT); + lockmgr(&bt->lock, LK_RELEASE); if (error != 0) { device_printf(dev, "bt_fetch_adapter_info - Failed Get Config\n"); @@ -592,35 +608,44 @@ bt_init(device_t dev) */ /* DMA tag for mapping buffers into device visible space. */ - if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/1, /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/MAXBSIZE, /*nsegments*/BT_NSEG, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/BUS_DMA_ALLOCNOW, - &bt->buffer_dmat) != 0) { + if (bus_dma_tag_create( /* parent */ bt->parent_dmat, + /* alignment */ 1, + /* boundary */ 0, + /* lowaddr */ BUS_SPACE_MAXADDR, + /* highaddr */ BUS_SPACE_MAXADDR, + /* filter */ NULL, + /* filterarg */ NULL, + /* maxsize */ MAXBSIZE, + /* nsegments */ BT_NSEG, + /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, + /* flags */ BUS_DMA_ALLOCNOW, + &bt->buffer_dmat) != 0) { goto error_exit; } bt->init_level++; /* DMA tag for our mailboxes */ - if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/1, /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - bt->num_boxes * (sizeof(bt_mbox_in_t) - + sizeof(bt_mbox_out_t)), - /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, &bt->mailbox_dmat) != 0) { + if (bus_dma_tag_create( /* parent */ bt->parent_dmat, + /* alignment */ 1, + /* boundary */ 0, + /* lowaddr */ BUS_SPACE_MAXADDR, + /* highaddr */ BUS_SPACE_MAXADDR, + /* filter */ NULL, + /* filterarg */ NULL, + /* maxsize */ bt->num_boxes * + (sizeof(bt_mbox_in_t) + + sizeof(bt_mbox_out_t)), + /* nsegments */ 1, + /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, + /* flags */ 0, + &bt->mailbox_dmat) != 0) { goto error_exit; } bt->init_level++; /* Allocation for our mailboxes */ - if (bus_dmamem_alloc(bt->mailbox_dmat, (void *)&bt->out_boxes, + if (bus_dmamem_alloc(bt->mailbox_dmat, (void **)&bt->out_boxes, BUS_DMA_NOWAIT, &bt->mailbox_dmamap) != 0) { goto error_exit; } @@ -638,24 +663,31 @@ bt_init(device_t dev) bt->in_boxes = (bt_mbox_in_t *)&bt->out_boxes[bt->num_boxes]; + lockmgr(&bt->lock, LK_EXCLUSIVE); btinitmboxes(bt); + lockmgr(&bt->lock, LK_RELEASE); /* DMA tag for our ccb structures */ - if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/1, /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - bt->max_ccbs * sizeof(struct bt_ccb), - /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, &bt->ccb_dmat) != 0) { + if (bus_dma_tag_create( /* parent */ bt->parent_dmat, + /* alignment */ 1, + /* boundary */ 0, + /* lowaddr */ BUS_SPACE_MAXADDR, + /* highaddr */ BUS_SPACE_MAXADDR, + /* filter */ NULL, + /* filterarg */ NULL, + /* maxsize */ bt->max_ccbs * + sizeof(struct bt_ccb), + /* nsegments */ 1, + /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, + /* flags */ 0, + &bt->ccb_dmat) != 0) { goto error_exit; } bt->init_level++; /* Allocation for our ccbs */ - if (bus_dmamem_alloc(bt->ccb_dmat, (void *)&bt->bt_ccb_array, + if (bus_dmamem_alloc(bt->ccb_dmat, (void **)&bt->bt_ccb_array, BUS_DMA_NOWAIT, &bt->ccb_dmamap) != 0) { goto error_exit; } @@ -671,13 +703,18 @@ bt_init(device_t dev) bt->init_level++; /* DMA tag for our S/G structures. We allocate in page sized chunks */ - if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/1, /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - PAGE_SIZE, /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, &bt->sg_dmat) != 0) { + if (bus_dma_tag_create( /* parent */ bt->parent_dmat, + /* alignment */ 1, + /* boundary */ 0, + /* lowaddr */ BUS_SPACE_MAXADDR, + /* highaddr */ BUS_SPACE_MAXADDR, + /* filter */ NULL, + /* filterarg */ NULL, + /* maxsize */ PAGE_SIZE, + /* nsegments */ 1, + /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, + /* flags */ 0, + &bt->sg_dmat) != 0) { goto error_exit; } @@ -694,7 +731,7 @@ bt_init(device_t dev) } /* - * Note that we are going and return (to probe) + * Note that we are going and return (to attach) */ return 0; @@ -730,14 +767,16 @@ bt_attach(device_t dev) /* * Construct our SIM entry */ - bt->sim = cam_sim_alloc(btaction, btpoll, "bt", bt, bt->unit, - &sim_mplock, 2, tagged_dev_openings, devq); + bt->sim = cam_sim_alloc(btaction, btpoll, "bt", bt, + device_get_unit(bt->dev), &bt->lock, 2, tagged_dev_openings, devq); cam_simq_release(devq); if (bt->sim == NULL) return (ENOMEM); - + + lockmgr(&bt->lock, LK_EXCLUSIVE); if (xpt_bus_register(bt->sim, 0) != CAM_SUCCESS) { cam_sim_free(bt->sim); + lockmgr(&bt->lock, LK_RELEASE); return (ENXIO); } @@ -746,14 +785,16 @@ bt_attach(device_t dev) CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(bt->sim)); cam_sim_free(bt->sim); + lockmgr(&bt->lock, LK_RELEASE); return (ENXIO); } + lockmgr(&bt->lock, LK_RELEASE); /* * Setup interrupt. */ - error = bus_setup_intr(dev, bt->irq, 0, - bt_intr, bt, &bt->ih, NULL); + error = bus_setup_intr(dev, bt->irq, + INTR_MPSAFE, bt_intr, bt, &bt->ih, NULL); if (error) { device_printf(dev, "bus_setup_intr() failed: %d\n", error); return (error); @@ -781,7 +822,7 @@ btallocccbs(struct bt_softc *bt) sg_map = kmalloc(sizeof(*sg_map), M_DEVBUF, M_WAITOK); /* Allocate S/G space for the next batch of CCBS */ - if (bus_dmamem_alloc(bt->sg_dmat, (void *)&sg_map->sg_vaddr, + if (bus_dmamem_alloc(bt->sg_dmat, (void **)&sg_map->sg_vaddr, BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { kfree(sg_map, M_DEVBUF); goto error_exit; @@ -802,6 +843,7 @@ btallocccbs(struct bt_softc *bt) next_ccb->sg_list = segs; next_ccb->sg_list_phys = physaddr; next_ccb->flags = BCCB_FREE; + callout_init_mp(&next_ccb->timer); error = bus_dmamap_create(bt->buffer_dmat, /*flags*/0, &next_ccb->dmamap); if (error != 0) @@ -829,7 +871,8 @@ error_exit: static __inline void btfreeccb(struct bt_softc *bt, struct bt_ccb *bccb) { - crit_enter(); + if (!dumping) + KKASSERT(lockowned(&bt->lock)); if ((bccb->flags & BCCB_ACTIVE) != 0) LIST_REMOVE(&bccb->ccb->ccb_h, sim_links.le); if (bt->resource_shortage != 0 @@ -840,7 +883,6 @@ btfreeccb(struct bt_softc *bt, struct bt_ccb *bccb) bccb->flags = BCCB_FREE; SLIST_INSERT_HEAD(&bt->free_bt_ccbs, bccb, links); bt->active_ccbs--; - crit_exit(); } static __inline struct bt_ccb* @@ -848,7 +890,8 @@ btgetccb(struct bt_softc *bt) { struct bt_ccb* bccb; - crit_enter(); + if (!dumping) + KKASSERT(lockowned(&bt->lock)); if ((bccb = SLIST_FIRST(&bt->free_bt_ccbs)) != NULL) { SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); bt->active_ccbs++; @@ -860,7 +903,6 @@ btgetccb(struct bt_softc *bt) bt->active_ccbs++; } } - crit_exit(); return (bccb); } @@ -873,7 +915,8 @@ btaction(struct cam_sim *sim, union ccb *ccb) CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("btaction\n")); bt = (struct bt_softc *)cam_sim_softc(sim); - + KKASSERT(lockowned(&bt->lock)); + switch (ccb->ccb_h.func_code) { /* Common cases first */ case XPT_SCSI_IO: /* Execute the requested I/O operation */ @@ -886,9 +929,7 @@ btaction(struct cam_sim *sim, union ccb *ccb) * get a bccb to use. */ if ((bccb = btgetccb(bt)) == NULL) { - crit_enter(); bt->resource_shortage = TRUE; - crit_exit(); xpt_freeze_simq(bt->sim, /*count*/1); ccb->ccb_h.status = CAM_REQUEUE_REQ; xpt_done(ccb); @@ -972,7 +1013,6 @@ btaction(struct cam_sim *sim, union ccb *ccb) if ((ccbh->flags & CAM_DATA_PHYS)==0) { int error; - crit_enter(); error = bus_dmamap_load( bt->buffer_dmat, bccb->dmamap, @@ -994,7 +1034,6 @@ btaction(struct cam_sim *sim, union ccb *ccb) csio->ccb_h.status |= CAM_RELEASE_SIMQ; } - crit_exit(); } else { struct bus_dma_segment seg; @@ -1255,8 +1294,6 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) bccb->hccb.data_addr = 0; } - crit_enter(); - /* * Last time we need to check if this CCB needs to * be aborted. @@ -1266,7 +1303,6 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); btfreeccb(bt, bccb); xpt_done(ccb); - crit_exit(); return; } @@ -1274,7 +1310,7 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) ccb->ccb_h.status |= CAM_SIM_QUEUED; LIST_INSERT_HEAD(&bt->pending_ccbs, &ccb->ccb_h, sim_links.le); - callout_reset(&ccb->ccb_h.timeout_ch, (ccb->ccb_h.timeout * hz) / 1000, + callout_reset(&bccb->timer, (ccb->ccb_h.timeout * hz) / 1000, bttimeout, bccb); /* Tell the adapter about this command */ @@ -1291,7 +1327,7 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) "Encountered busy mailbox with %d out of %d " "commands active!!!\n", bt->active_ccbs, bt->max_ccbs); - callout_stop(&ccb->ccb_h.timeout_ch); + callout_stop(&bccb->timer); if (nseg != 0) bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); btfreeccb(bt, bccb); @@ -1299,22 +1335,29 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) xpt_freeze_simq(bt->sim, /*count*/1); ccb->ccb_h.status = CAM_REQUEUE_REQ; xpt_done(ccb); - crit_exit(); return; } bt->cur_outbox->action_code = BMBO_START; bt_outb(bt, COMMAND_REG, BOP_START_MBOX); btnextoutbox(bt); - crit_exit(); } void bt_intr(void *arg) { struct bt_softc *bt; + + bt = arg; + lockmgr(&bt->lock, LK_EXCLUSIVE); + bt_intr_locked(bt); + lockmgr(&bt->lock, LK_RELEASE); +} + +void +bt_intr_locked(struct bt_softc *bt) +{ u_int intstat; - bt = (struct bt_softc *)arg; while (((intstat = bt_inb(bt, INTSTAT_REG)) & INTR_PENDING) != 0) { if ((intstat & CMD_COMPLETE) != 0) { @@ -1400,7 +1443,7 @@ btdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code) ccb_h = LIST_NEXT(ccb_h, sim_links.le); btdone(bt, pending_bccb, BMBI_ERROR); } else { - callout_reset(&ccb_h->timeout_ch, + callout_reset(&pending_bccb->timer, (ccb_h->timeout * hz) / 1000, bttimeout, pending_bccb); ccb_h = LIST_NEXT(ccb_h, sim_links.le); @@ -1410,7 +1453,7 @@ btdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code) return; } - callout_stop(&ccb->ccb_h.timeout_ch); + callout_stop(&bccb->timer); switch (comp_code) { case BMBI_FREE: @@ -1593,8 +1636,9 @@ btreset(struct bt_softc* bt, int hard_reset) } if (timeout == 0) { if (bootverbose) - kprintf("%s: btreset - Diagnostic Active failed to " - "assert. status = 0x%x\n", bt_name(bt), status); + device_printf(bt->dev, + "btreset - Diagnostic Active failed to " + "assert. status = 0x%x\n", status); return (ETIMEDOUT); } @@ -1621,20 +1665,22 @@ btreset(struct bt_softc* bt, int hard_reset) DELAY(100); } if (timeout == 0) { - kprintf("%s: btreset - Host adapter failed to come ready. " - "status = 0x%x\n", bt_name(bt), status); + device_printf(bt->dev, + "btreset - Host adapter failed to come ready. " + "status = 0x%x\n", status); return (ETIMEDOUT); } /* If the diagnostics failed, tell the user */ if ((status & DIAG_FAIL) != 0 || (status & HA_READY) == 0) { - kprintf("%s: btreset - Adapter failed diagnostics\n", - bt_name(bt)); + device_printf(bt->dev, + "btreset - Adapter failed diagnostics\n"); if ((status & DATAIN_REG_READY) != 0) - kprintf("%s: btreset - Host Adapter Error code = 0x%x\n", - bt_name(bt), bt_inb(bt, DATAIN_REG)); + device_printf(bt->dev, + "btreset - Host Adapter Error code = 0x%x\n", + bt_inb(bt, DATAIN_REG)); return (ENXIO); } @@ -1704,8 +1750,9 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len, DELAY(100); } if (timeout == 0) { - kprintf("%s: bt_cmd: Timeout waiting for adapter ready, " - "status = 0x%x\n", bt_name(bt), status); + device_printf(bt->dev, + "bt_cmd: Timeout waiting for adapter ready, " + "status = 0x%x\n", status); return (ETIMEDOUT); } @@ -1715,16 +1762,14 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len, bt_outb(bt, COMMAND_REG, opcode); /* - * Wait for up to 1sec for each byte of the the + * Wait for up to 1sec for each byte of the * parameter list sent to be sent. */ timeout = 10000; while (param_len && --timeout) { DELAY(100); - crit_enter(); status = bt_inb(bt, STATUS_REG); intstat = bt_inb(bt, INTSTAT_REG); - crit_exit(); if ((intstat & (INTR_PENDING|CMD_COMPLETE)) == (INTR_PENDING|CMD_COMPLETE)) { @@ -1746,8 +1791,8 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len, } } if (timeout == 0) { - kprintf("%s: bt_cmd: Timeout sending parameters, " - "status = 0x%x\n", bt_name(bt), status); + device_printf(bt->dev, "bt_cmd: Timeout sending parameters, " + "status = 0x%x\n", status); cmd_complete = 1; saved_status = status; error = ETIMEDOUT; @@ -1757,8 +1802,6 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len, * Wait for the command to complete. */ while (cmd_complete == 0 && --cmd_timeout) { - - crit_enter(); status = bt_inb(bt, STATUS_REG); intstat = bt_inb(bt, INTSTAT_REG); /* @@ -1770,8 +1813,7 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len, */ if ((intstat & (INTR_PENDING|IMB_LOADED)) == (INTR_PENDING|IMB_LOADED)) - bt_intr(bt); - crit_exit(); + bt_intr_locked(bt); if (bt->command_cmp != 0) { /* @@ -1805,9 +1847,9 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len, if (reply_len < reply_buf_size) { *reply_data++ = data; } else { - kprintf("%s: bt_cmd - Discarded reply data byte " - "for opcode 0x%x\n", bt_name(bt), - opcode); + device_printf(bt->dev, + "bt_cmd - Discarded reply data byte " + "for opcode 0x%x\n", opcode); } /* * Reset timeout to ensure at least a second @@ -1824,20 +1866,18 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len, DELAY(100); } if (cmd_timeout == 0) { - kprintf("%s: bt_cmd: Timeout waiting for command (%x) " - "to complete.\n%s: status = 0x%x, intstat = 0x%x, " - "rlen %d\n", bt_name(bt), opcode, - bt_name(bt), status, intstat, reply_len); + device_printf(bt->dev, + "bt_cmd: Timeout waiting for command (%x) " + "to complete.\n", opcode); + device_printf(bt->dev, "status = 0x%x, intstat = 0x%x, " + "rlen %d\n", status, intstat, reply_len); error = (ETIMEDOUT); } /* - * Clear any pending interrupts. Block interrupts so our - * interrupt handler is not re-entered. + * Clear any pending interrupts. */ - crit_enter(); - bt_intr(bt); - crit_exit(); + bt_intr_locked(bt); if (error != 0) return (error); @@ -1853,7 +1893,7 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len, * reset above), perform a soft reset. */ if (bootverbose) - kprintf("%s: Invalid Command 0x%x\n", bt_name(bt), + device_printf(bt->dev, "Invalid Command 0x%x\n", opcode); DELAY(1000); status = bt_inb(bt, STATUS_REG); @@ -1921,8 +1961,8 @@ btinitmboxes(struct bt_softc *bt) { kprintf("btinitmboxes: Unable to enable strict RR\n"); error = 0; } else if (bootverbose) { - kprintf("%s: Using Strict Round Robin Mailbox Mode\n", - bt_name(bt)); + device_printf(bt->dev, + "Using Strict Round Robin Mailbox Mode\n"); } } @@ -1969,8 +2009,9 @@ btfetchtransinfo(struct bt_softc *bt, struct ccb_trans_settings *cts) DEFAULT_CMD_TIMEOUT); if (error != 0) { - kprintf("%s: btfetchtransinfo - Inquire Setup Info Failed %x\n", - bt_name(bt), error); + device_printf(bt->dev, + "btfetchtransinfo - Inquire Setup Info Failed %x\n", + error); return; } @@ -2024,8 +2065,9 @@ btfetchtransinfo(struct bt_softc *bt, struct ccb_trans_settings *cts) DEFAULT_CMD_TIMEOUT); if (error != 0) { - kprintf("%s: btfetchtransinfo - Inquire Sync " - "Info Failed 0x%x\n", bt_name(bt), error); + device_printf(bt->dev, + "btfetchtransinfo - Inquire Sync " + "Info Failed 0x%x\n", error); return; } sync_period = sync_info.sync_rate[target] * 100; @@ -2086,7 +2128,7 @@ btmapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error) static void btpoll(struct cam_sim *sim) { - bt_intr(cam_sim_softc(sim)); + bt_intr_locked(cam_sim_softc(sim)); } void @@ -2099,16 +2141,15 @@ bttimeout(void *arg) bccb = (struct bt_ccb *)arg; ccb = bccb->ccb; bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr; + lockmgr(&bt->lock, LK_EXCLUSIVE); xpt_print_path(ccb->ccb_h.path); kprintf("CCB %p - timed out\n", (void *)bccb); - crit_enter(); - if ((bccb->flags & BCCB_ACTIVE) == 0) { xpt_print_path(ccb->ccb_h.path); kprintf("CCB %p - timed out CCB already completed\n", (void *)bccb); - crit_exit(); + lockmgr(&bt->lock, LK_RELEASE); return; } @@ -2135,7 +2176,7 @@ bttimeout(void *arg) struct bt_ccb *pending_bccb; pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr; - callout_stop(&ccb_h->timeout_ch); + callout_stop(&pending_bccb->timer); ccb_h = LIST_NEXT(ccb_h, sim_links.le); } } @@ -2158,7 +2199,7 @@ bttimeout(void *arg) */ ccb->ccb_h.status = CAM_CMD_TIMEOUT; btreset(bt, /*hardreset*/TRUE); - kprintf("%s: No longer in timeout\n", bt_name(bt)); + device_printf(bt->dev, "No longer in timeout\n"); } else { /* * Send a Bus Device Reset message: @@ -2172,7 +2213,7 @@ bttimeout(void *arg) * later which will attempt a bus reset. */ bccb->flags |= BCCB_DEVICE_RESET; - callout_reset(&ccb->ccb_h.timeout_ch, 2 * hz, bttimeout, bccb); + callout_reset(&bccb->timer, 2 * hz, bttimeout, bccb); bt->recovery_bccb->hccb.opcode = INITIATOR_BUS_DEV_RESET; @@ -2189,7 +2230,8 @@ bttimeout(void *arg) bt_outb(bt, COMMAND_REG, BOP_START_MBOX); btnextoutbox(bt); } - - crit_exit(); + lockmgr(&bt->lock, LK_RELEASE); } +MODULE_VERSION(bt, 1); +MODULE_DEPEND(bt, cam, 1, 1, 1); diff --git a/sys/dev/disk/buslogic/bt_pci.c b/sys/dev/disk/buslogic/bt_pci.c index 30c1cf9a8f..b6e5bd0282 100644 --- a/sys/dev/disk/buslogic/bt_pci.c +++ b/sys/dev/disk/buslogic/bt_pci.c @@ -1,4 +1,4 @@ -/* +/*- * Product specific probe and attach routines for: * Buslogic BT946, BT948, BT956, BT958 SCSI controllers * @@ -26,12 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/buslogic/bt_pci.c,v 1.11 2000/01/17 12:38:00 nyan Exp $ + * $FreeBSD: src/sys/dev/buslogic/bt_pci.c,v 1.25 2012/11/17 01:51:40 svnexp Exp $ */ #include #include #include +#include #include #include #include @@ -41,8 +42,8 @@ #include "btreg.h" -#define BT_PCI_IOADDR PCIR_MAPS -#define BT_PCI_MEMADDR PCIR_MAPS + 4 +#define BT_PCI_IOADDR PCIR_BAR(0) +#define BT_PCI_MEMADDR PCIR_BAR(1) #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040104Bul #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul @@ -60,23 +61,21 @@ bt_pci_alloc_resources(device_t dev) if (command & PCIM_CMD_MEMEN) { type = SYS_RES_MEMORY; rid = BT_PCI_MEMADDR; - regs = bus_alloc_resource(dev, type, &rid, - 0, ~0, 1, RF_ACTIVE); + regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); } #else if (!regs && (command & PCIM_CMD_PORTEN)) { type = SYS_RES_IOPORT; rid = BT_PCI_IOADDR; - regs = bus_alloc_resource(dev, type, &rid, - 0, ~0, 1, RF_ACTIVE); + regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); } #endif if (!regs) return (ENOMEM); zero = 0; - irq = bus_alloc_resource(dev, SYS_RES_IRQ, &zero, - 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); + irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &zero, + RF_ACTIVE | RF_SHAREABLE); if (!irq) { bus_release_resource(dev, type, rid, regs); return (ENOMEM); @@ -132,36 +131,28 @@ bt_pci_attach(device_t dev) /* Allocate a dmatag for our CCB DMA maps */ /* XXX Should be a child of the PCI bus dma tag */ - if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/1, /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, - /*nsegments*/BUS_SPACE_UNRESTRICTED, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, &bt->parent_dmat) != 0) { + if (bus_dma_tag_create( /* parent */ NULL, + /* alignemnt */ 1, + /* boundary */ 0, + /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, + /* highaddr */ BUS_SPACE_MAXADDR, + /* filter */ NULL, + /* filterarg */ NULL, + /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, + /* nsegments */ ~0, + /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, + /* flags */ 0, + &bt->parent_dmat) != 0) { bt_pci_release_resources(dev); return (ENOMEM); } - /* - * Protect ourself from spurrious interrupts during - * intialization and attach. We should really rely - * on interrupts during attach, but we don't have - * access to our interrupts during ISA probes, so until - * that changes, we mask our interrupts during attach - * too. - */ - crit_enter(); - if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) { bt_pci_release_resources(dev); - crit_exit(); return (ENXIO); } error = bt_attach(dev); - crit_exit(); if (error) { bt_pci_release_resources(dev); @@ -188,3 +179,4 @@ static driver_t bt_pci_driver = { static devclass_t bt_devclass; DRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, NULL, NULL); +MODULE_DEPEND(bt, pci, 1, 1, 1); diff --git a/sys/dev/disk/buslogic/btreg.h b/sys/dev/disk/buslogic/btreg.h index f3d43bf189..683d35e84f 100644 --- a/sys/dev/disk/buslogic/btreg.h +++ b/sys/dev/disk/buslogic/btreg.h @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/buslogic/btreg.h,v 1.10.2.2 2001/09/03 02:45:22 peter Exp $ + * $FreeBSD: src/sys/dev/buslogic/btreg.h,v 1.18 2012/11/17 01:51:40 svnexp Exp $ */ #ifndef _BTREG_H_ @@ -558,6 +558,7 @@ struct bt_ccb { u_int32_t flags; union ccb *ccb; bus_dmamap_t dmamap; + struct callout timer; bt_sg_t *sg_list; u_int32_t sg_list_phys; }; @@ -575,8 +576,7 @@ struct bt_softc { struct resource *irq; struct resource *drq; void *ih; - bus_space_tag_t tag; - bus_space_handle_t bsh; + struct lock lock; struct cam_sim *sim; struct cam_path *path; bt_mbox_out_t *cur_outbox; @@ -612,7 +612,6 @@ struct bt_softc { u_int num_ccbs; /* Number of CCBs malloc'd */ u_int max_ccbs; /* Maximum allocatable CCBs */ u_int max_sg; - u_int unit; u_int scsi_id; u_int32_t extended_trans :1, wide_bus :1, @@ -639,8 +638,6 @@ struct bt_softc { char model[5]; }; -extern u_long bt_unit; - #define BT_TEMP_UNIT 0xFF /* Unit for probes */ void bt_init_softc(device_t dev, struct resource *port, @@ -661,10 +658,10 @@ int bt_cmd(struct bt_softc *bt, bt_op_t opcode, #define bt_name(bt) device_get_nameunit(bt->dev) -#define bt_inb(bt, port) \ - bus_space_read_1((bt)->tag, (bt)->bsh, port) +#define bt_inb(bt, reg) \ + bus_read_1((bt)->port, reg) -#define bt_outb(bt, port, value) \ - bus_space_write_1((bt)->tag, (bt)->bsh, port, value) +#define bt_outb(bt, reg, value) \ + bus_write_1((bt)->port, reg, value) #endif /* _BT_H_ */