summaryrefslogtreecommitdiffstats
path: root/sys/dev/isp/isp_pci.c
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2011-08-13 23:34:17 +0000
committermjacob <mjacob@FreeBSD.org>2011-08-13 23:34:17 +0000
commitd7243f9f08159a162ce3b28842403e797017d945 (patch)
tree7a9f66897f6ceee6c235848200b5e35de741d51b /sys/dev/isp/isp_pci.c
parentd76f0381941fb96e2cbcfd52036dbf6e4f9363a9 (diff)
downloadFreeBSD-src-d7243f9f08159a162ce3b28842403e797017d945.zip
FreeBSD-src-d7243f9f08159a162ce3b28842403e797017d945.tar.gz
Most of these changes to isp are to allow for isp.ko unloading.
We also revive loop down freezes. We also externaliz within isp isp_prt_endcmd so something outside the core module can print something about a command completing. Also some work in progress to assist in handling timed out commands better. Partially Sponsored by: Panasas Approved by: re (kib) MFC after: 1 month
Diffstat (limited to 'sys/dev/isp/isp_pci.c')
-rw-r--r--sys/dev/isp/isp_pci.c80
1 files changed, 52 insertions, 28 deletions
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 5eb0739..b6b23fa 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -347,7 +347,11 @@ static int isp_pci_detach (device_t);
struct isp_pcisoftc {
ispsoftc_t pci_isp;
device_t pci_dev;
- struct resource * pci_reg;
+ struct resource * regs;
+ void * irq;
+ int iqd;
+ int rtp;
+ int rgd;
void * ih;
int16_t pci_poff[_NREG_BLKS];
bus_dma_tag_t dmat;
@@ -645,8 +649,7 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
static int
isp_pci_attach(device_t dev)
{
- struct resource *regs, *irq;
- int rtp, rgd, iqd, i, m1, m2, locksetup = 0;
+ int i, m1, m2, locksetup = 0;
int isp_nvports = 0;
uint32_t data, cmd, linesz, did;
struct isp_pcisoftc *pcs;
@@ -687,32 +690,31 @@ isp_pci_attach(device_t dev)
isp_get_pci_options(dev, &m1, &m2);
linesz = PCI_DFLT_LNSZ;
- irq = regs = NULL;
- rgd = rtp = iqd = 0;
+ pcs->irq = pcs->regs = NULL;
+ pcs->rgd = pcs->rtp = pcs->iqd = 0;
cmd = pci_read_config(dev, PCIR_COMMAND, 2);
if (cmd & m1) {
- rtp = (m1 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
- rgd = (m1 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
- regs = bus_alloc_resource_any(dev, rtp, &rgd, RF_ACTIVE);
+ pcs->rtp = (m1 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
+ pcs->rgd = (m1 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
+ pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, RF_ACTIVE);
}
- if (regs == NULL && (cmd & m2)) {
- rtp = (m2 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
- rgd = (m2 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
- regs = bus_alloc_resource_any(dev, rtp, &rgd, RF_ACTIVE);
+ if (pcs->regs == NULL && (cmd & m2)) {
+ pcs->rtp = (m2 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
+ pcs->rgd = (m2 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
+ pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, RF_ACTIVE);
}
- if (regs == NULL) {
+ if (pcs->regs == NULL) {
device_printf(dev, "unable to map any ports\n");
goto bad;
}
if (bootverbose) {
- device_printf(dev, "using %s space register mapping\n", (rgd == IO_MAP_REG)? "I/O" : "Memory");
+ device_printf(dev, "using %s space register mapping\n", (pcs->rgd == IO_MAP_REG)? "I/O" : "Memory");
}
- isp->isp_bus_tag = rman_get_bustag(regs);
- isp->isp_bus_handle = rman_get_bushandle(regs);
+ isp->isp_bus_tag = rman_get_bustag(pcs->regs);
+ isp->isp_bus_handle = rman_get_bushandle(pcs->regs);
pcs->pci_dev = dev;
- pcs->pci_reg = regs;
pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF;
pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF;
@@ -931,13 +933,13 @@ isp_pci_attach(device_t dev)
pcs->msicount = 1;
}
if (pci_alloc_msi(dev, &pcs->msicount) == 0) {
- iqd = 1;
+ pcs->iqd = 1;
} else {
- iqd = 0;
+ pcs->iqd = 0;
}
}
- irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, RF_ACTIVE | RF_SHAREABLE);
- if (irq == NULL) {
+ pcs->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &pcs->iqd, RF_ACTIVE | RF_SHAREABLE);
+ if (pcs->irq == NULL) {
device_printf(dev, "could not allocate interrupt\n");
goto bad;
}
@@ -946,7 +948,7 @@ isp_pci_attach(device_t dev)
mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF);
locksetup++;
- if (isp_setup_intr(dev, irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) {
+ if (isp_setup_intr(dev, pcs->irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) {
device_printf(dev, "could not setup interrupt\n");
goto bad;
}
@@ -982,19 +984,19 @@ isp_pci_attach(device_t dev)
bad:
if (pcs->ih) {
- (void) bus_teardown_intr(dev, irq, pcs->ih);
+ (void) bus_teardown_intr(dev, pcs->irq, pcs->ih);
}
if (locksetup) {
mtx_destroy(&isp->isp_osinfo.lock);
}
- if (irq) {
- (void) bus_release_resource(dev, SYS_RES_IRQ, iqd, irq);
+ if (pcs->irq) {
+ (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq);
}
if (pcs->msicount) {
pci_release_msi(dev);
}
- if (regs) {
- (void) bus_release_resource(dev, rtp, rgd, regs);
+ if (pcs->regs) {
+ (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs);
}
if (pcs->pci_isp.isp_param) {
free(pcs->pci_isp.isp_param, M_DEVBUF);
@@ -1012,14 +1014,36 @@ isp_pci_detach(device_t dev)
{
struct isp_pcisoftc *pcs;
ispsoftc_t *isp;
+ int status;
pcs = device_get_softc(dev);
if (pcs == NULL) {
return (ENXIO);
}
isp = (ispsoftc_t *) pcs;
- ISP_DISABLE_INTS(isp);
+ status = isp_detach(isp);
+ if (status)
+ return (status);
+ ISP_LOCK(isp);
+ isp_uninit(isp);
+ if (pcs->ih) {
+ (void) bus_teardown_intr(dev, pcs->irq, pcs->ih);
+ }
+ ISP_UNLOCK(isp);
mtx_destroy(&isp->isp_osinfo.lock);
+ (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq);
+ if (pcs->msicount) {
+ pci_release_msi(dev);
+ }
+ (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs);
+ if (pcs->pci_isp.isp_param) {
+ free(pcs->pci_isp.isp_param, M_DEVBUF);
+ pcs->pci_isp.isp_param = NULL;
+ }
+ if (pcs->pci_isp.isp_osinfo.pc.ptr) {
+ free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF);
+ pcs->pci_isp.isp_osinfo.pc.ptr = NULL;
+ }
return (0);
}
OpenPOWER on IntegriCloud