diff options
author | jhb <jhb@FreeBSD.org> | 2014-11-13 22:00:18 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2014-11-13 22:00:18 +0000 |
commit | 1c95a6b2b42a794c0e10a916c8b3d6a2d852a9fe (patch) | |
tree | 57e3c7bdb3f074d155877b7cd7f6aa6d57f05716 /sys/dev/iir/iir_pci.c | |
parent | 484c1c2bfa2e6b4f999d8a0f3e4d3145c60dc361 (diff) | |
download | FreeBSD-src-1c95a6b2b42a794c0e10a916c8b3d6a2d852a9fe.zip FreeBSD-src-1c95a6b2b42a794c0e10a916c8b3d6a2d852a9fe.tar.gz |
Lock iir(4) and mark it MPSAFE.
- Add a per-device mutex to the softc and use it for bus_dma tags,
CAM SIMs, callouts, and interrupt handler.
- Switch from timeout(9) to callout(9).
- Add a separate global mutex to protect the global event buffer ring.
- Return completed index from iir_intr_locked() and remove the global
gdt_wait_* variables.
- Remove global list of gdt softcs and replace its use with
devclass_get_device().
- Use si_drv1 to store softc pointer in the SDEV_PER_HBA case instead
of minor numbers.
- Do math on osreldate instead of dubious char math on osrelease[]
that didn't work on 10.0+.
- Use bus_*() instead of bus_space_*().
- Use device_printf() instead of printf() with a unit number.
Tested by: no one
Diffstat (limited to 'sys/dev/iir/iir_pci.c')
-rw-r--r-- | sys/dev/iir/iir_pci.c | 170 |
1 files changed, 72 insertions, 98 deletions
diff --git a/sys/dev/iir/iir_pci.c b/sys/dev/iir/iir_pci.c index ec54d49..42e1c81 100644 --- a/sys/dev/iir/iir_pci.c +++ b/sys/dev/iir/iir_pci.c @@ -183,15 +183,18 @@ static int iir_pci_attach(device_t dev) { struct gdt_softc *gdt; - struct resource *io = NULL, *irq = NULL; + struct resource *irq = NULL; int retries, rid, error = 0; void *ih; u_int8_t protocol; - + + gdt = device_get_softc(dev); + mtx_init(&gdt->sc_lock, "iir", NULL, MTX_DEF); + /* map DPMEM */ rid = PCI_DPMEM; - io = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - if (io == NULL) { + gdt->sc_dpmem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (gdt->sc_dpmem == NULL) { device_printf(dev, "can't allocate register resources\n"); error = ENOMEM; goto err; @@ -207,12 +210,8 @@ iir_pci_attach(device_t dev) goto err; } - gdt = device_get_softc(dev); gdt->sc_devnode = dev; gdt->sc_init_level = 0; - gdt->sc_dpmemt = rman_get_bustag(io); - gdt->sc_dpmemh = rman_get_bushandle(io); - gdt->sc_dpmembase = rman_get_start(io); gdt->sc_hanum = device_get_unit(dev); gdt->sc_bus = pci_get_bus(dev); gdt->sc_slot = pci_get_slot(dev); @@ -227,85 +226,70 @@ iir_pci_attach(device_t dev) /* initialize RP controller */ /* check and reset interface area */ - bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC, - htole32(GDT_MPR_MAGIC)); - if (bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC) != - htole32(GDT_MPR_MAGIC)) { - printf("cannot access DPMEM at 0x%jx (shadowed?)\n", - (uintmax_t)gdt->sc_dpmembase); + bus_write_4(gdt->sc_dpmem, GDT_MPR_IC, htole32(GDT_MPR_MAGIC)); + if (bus_read_4(gdt->sc_dpmem, GDT_MPR_IC) != htole32(GDT_MPR_MAGIC)) { + device_printf(dev, "cannot access DPMEM at 0x%lx (shadowed?)\n", + rman_get_start(gdt->sc_dpmem)); error = ENXIO; goto err; } - bus_space_set_region_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_I960_SZ, htole32(0), - GDT_MPR_SZ >> 2); + bus_set_region_4(gdt->sc_dpmem, GDT_I960_SZ, htole32(0), GDT_MPR_SZ >> 2); /* Disable everything */ - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EDOOR_EN, - bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_EDOOR_EN) | 4); - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR, 0xff); - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS, - 0); - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_CMD_INDEX, - 0); - - bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO, - htole32(gdt->sc_dpmembase)); - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX, - 0xff); - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1); + bus_write_1(gdt->sc_dpmem, GDT_EDOOR_EN, + bus_read_1(gdt->sc_dpmem, GDT_EDOOR_EN) | 4); + bus_write_1(gdt->sc_dpmem, GDT_MPR_EDOOR, 0xff); + bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS, 0); + bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_CMD_INDEX, 0); + + bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO, + htole32(rman_get_start(gdt->sc_dpmem))); + bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_CMD_INDX, 0xff); + bus_write_1(gdt->sc_dpmem, GDT_MPR_LDOOR, 1); DELAY(20); retries = GDT_RETRIES; - while (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_MPR_IC + GDT_S_STATUS) != 0xff) { + while (bus_read_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS) != 0xff) { if (--retries == 0) { - printf("DEINIT failed\n"); + device_printf(dev, "DEINIT failed\n"); error = ENXIO; goto err; } DELAY(1); } - protocol = (uint8_t)le32toh(bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_MPR_IC + GDT_S_INFO)); - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS, - 0); + protocol = (uint8_t)le32toh(bus_read_4(gdt->sc_dpmem, + GDT_MPR_IC + GDT_S_INFO)); + bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS, 0); if (protocol != GDT_PROTOCOL_VERSION) { - printf("unsupported protocol %d\n", protocol); + device_printf(dev, "unsupported protocol %d\n", protocol); error = ENXIO; goto err; } - /* special commnd to controller BIOS */ - bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO, - htole32(0)); - bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_MPR_IC + GDT_S_INFO + sizeof (u_int32_t), htole32(0)); - bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_MPR_IC + GDT_S_INFO + 2 * sizeof (u_int32_t), - htole32(1)); - bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_MPR_IC + GDT_S_INFO + 3 * sizeof (u_int32_t), - htole32(0)); - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX, - 0xfe); - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1); + /* special command to controller BIOS */ + bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO, htole32(0)); + bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO + sizeof (u_int32_t), + htole32(0)); + bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO + 2 * sizeof (u_int32_t), + htole32(1)); + bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO + 3 * sizeof (u_int32_t), + htole32(0)); + bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_CMD_INDX, 0xfe); + bus_write_1(gdt->sc_dpmem, GDT_MPR_LDOOR, 1); DELAY(20); retries = GDT_RETRIES; - while (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_MPR_IC + GDT_S_STATUS) != 0xfe) { + while (bus_read_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS) != 0xfe) { if (--retries == 0) { - printf("initialization error\n"); + device_printf(dev, "initialization error\n"); error = ENXIO; goto err; } DELAY(1); } - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS, - 0); + bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS, 0); gdt->sc_ic_all_size = GDT_MPR_SZ; @@ -326,7 +310,7 @@ iir_pci_attach(device_t dev) /*nsegments*/GDT_MAXSG, /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, /*flags*/0, /*lockfunc*/busdma_lock_mutex, - /*lockarg*/&Giant, &gdt->sc_parent_dmat) != 0) { + /*lockarg*/&gdt->sc_lock, &gdt->sc_parent_dmat) != 0) { error = ENXIO; goto err; } @@ -342,7 +326,7 @@ iir_pci_attach(device_t dev) iir_attach(gdt); /* associate interrupt handler */ - if (bus_setup_intr( dev, irq, INTR_TYPE_CAM, + if (bus_setup_intr(dev, irq, INTR_TYPE_CAM | INTR_MPSAFE, NULL, iir_intr, gdt, &ih )) { device_printf(dev, "Unable to register interrupt handler\n"); error = ENXIO; @@ -355,10 +339,11 @@ iir_pci_attach(device_t dev) err: if (irq) bus_release_resource( dev, SYS_RES_IRQ, 0, irq ); -/* - if (io) - bus_release_resource( dev, SYS_RES_MEMORY, rid, io ); -*/ + + if (gdt->sc_dpmem) + bus_release_resource( dev, SYS_RES_MEMORY, rid, gdt->sc_dpmem ); + mtx_destroy(&gdt->sc_lock); + return (error); } @@ -371,11 +356,9 @@ gdt_pci_enable_intr(struct gdt_softc *gdt) switch(GDT_CLASS(gdt)) { case GDT_MPR: - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_MPR_EDOOR, 0xff); - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EDOOR_EN, - bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_EDOOR_EN) & ~4); + bus_write_1(gdt->sc_dpmem, GDT_MPR_EDOOR, 0xff); + bus_write_1(gdt->sc_dpmem, GDT_EDOOR_EN, + bus_read_1(gdt->sc_dpmem, GDT_EDOOR_EN) & ~4); break; } } @@ -396,15 +379,14 @@ gdt_mpr_copy_cmd(struct gdt_softc *gdt, struct gdt_ccb *gccb) gdt->sc_cmd_off += cp_count; - bus_space_write_region_4(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_MPR_IC + GDT_DPR_CMD + dp_offset, - (u_int32_t *)gccb->gc_cmd, cp_count >> 2); - bus_space_write_2(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_MPR_IC + GDT_COMM_QUEUE + cmd_no * GDT_COMM_Q_SZ + GDT_OFFSET, - htole16(GDT_DPMEM_COMMAND_OFFSET + dp_offset)); - bus_space_write_2(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_MPR_IC + GDT_COMM_QUEUE + cmd_no * GDT_COMM_Q_SZ + GDT_SERV_ID, - htole16(gccb->gc_service)); + bus_write_region_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_DPR_CMD + dp_offset, + (u_int32_t *)gccb->gc_cmd, cp_count >> 2); + bus_write_2(gdt->sc_dpmem, + GDT_MPR_IC + GDT_COMM_QUEUE + cmd_no * GDT_COMM_Q_SZ + GDT_OFFSET, + htole16(GDT_DPMEM_COMMAND_OFFSET + dp_offset)); + bus_write_2(gdt->sc_dpmem, + GDT_MPR_IC + GDT_COMM_QUEUE + cmd_no * GDT_COMM_Q_SZ + GDT_SERV_ID, + htole16(gccb->gc_service)); } u_int8_t @@ -412,7 +394,7 @@ gdt_mpr_get_status(struct gdt_softc *gdt) { GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_get_status(%p) ", gdt)); - return bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR); + return bus_read_1(gdt->sc_dpmem, GDT_MPR_EDOOR); } void @@ -422,39 +404,32 @@ gdt_mpr_intr(struct gdt_softc *gdt, struct gdt_intr_ctx *ctx) GDT_DPRINTF(GDT_D_INTR, ("gdt_mpr_intr(%p) ", gdt)); - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR, 0xff); + bus_write_1(gdt->sc_dpmem, GDT_MPR_EDOOR, 0xff); if (ctx->istatus & 0x80) { /* error flag */ ctx->istatus &= ~0x80; - ctx->cmd_status = bus_space_read_2(gdt->sc_dpmemt, - gdt->sc_dpmemh, GDT_MPR_STATUS); + ctx->cmd_status = bus_read_2(gdt->sc_dpmem, GDT_MPR_STATUS); } else /* no error */ ctx->cmd_status = GDT_S_OK; - ctx->info = - bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_INFO); - ctx->service = - bus_space_read_2(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_SERVICE); - ctx->info2 = - bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_MPR_INFO + sizeof (u_int32_t)); + ctx->info = bus_read_4(gdt->sc_dpmem, GDT_MPR_INFO); + ctx->service = bus_read_2(gdt->sc_dpmem, GDT_MPR_SERVICE); + ctx->info2 = bus_read_4(gdt->sc_dpmem, GDT_MPR_INFO + sizeof (u_int32_t)); /* event string */ if (ctx->istatus == GDT_ASYNCINDEX) { if (ctx->service != GDT_SCREENSERVICE && (gdt->sc_fw_vers & 0xff) >= 0x1a) { - gdt->sc_dvr.severity = - bus_space_read_1(gdt->sc_dpmemt,gdt->sc_dpmemh, GDT_SEVERITY); + gdt->sc_dvr.severity = bus_read_1(gdt->sc_dpmem, GDT_SEVERITY); for (i = 0; i < 256; ++i) { - gdt->sc_dvr.event_string[i] = - bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_EVT_BUF + i); + gdt->sc_dvr.event_string[i] = bus_read_1(gdt->sc_dpmem, + GDT_EVT_BUF + i); if (gdt->sc_dvr.event_string[i] == 0) break; } } } - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_SEMA1, 0); + bus_write_1(gdt->sc_dpmem, GDT_MPR_SEMA1, 0); } void @@ -462,7 +437,7 @@ gdt_mpr_release_event(struct gdt_softc *gdt) { GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_release_event(%p) ", gdt)); - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1); + bus_write_1(gdt->sc_dpmem, GDT_MPR_LDOOR, 1); } void @@ -470,7 +445,7 @@ gdt_mpr_set_sema0(struct gdt_softc *gdt) { GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_set_sema0(%p) ", gdt)); - bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_SEMA0, 1); + bus_write_1(gdt->sc_dpmem, GDT_MPR_SEMA0, 1); } int @@ -478,6 +453,5 @@ gdt_mpr_test_busy(struct gdt_softc *gdt) { GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_test_busy(%p) ", gdt)); - return (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, - GDT_MPR_SEMA0) & 1); + return (bus_read_1(gdt->sc_dpmem, GDT_MPR_SEMA0) & 1); } |