diff options
-rw-r--r-- | usr/src/uts/common/io/sata/adapters/ahci/ahci.c | 264 | ||||
-rw-r--r-- | usr/src/uts/common/sys/sata/adapters/ahci/ahcivar.h | 1 |
2 files changed, 128 insertions, 137 deletions
diff --git a/usr/src/uts/common/io/sata/adapters/ahci/ahci.c b/usr/src/uts/common/io/sata/adapters/ahci/ahci.c index 0ca0ff0144..d9e083a10b 100644 --- a/usr/src/uts/common/io/sata/adapters/ahci/ahci.c +++ b/usr/src/uts/common/io/sata/adapters/ahci/ahci.c @@ -61,7 +61,6 @@ /* * This is the string displayed by modinfo, etc. - * Make sure you keep the version ID up to date! */ static char ahci_ident[] = "ahci driver"; @@ -582,7 +581,7 @@ ahci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) } mutex_enter(&ahci_ctlp->ahcictl_mutex); - ahci_ctlp->ahcictl_flags &= ~ AHCI_SUSPEND; + ahci_ctlp->ahcictl_flags &= ~AHCI_SUSPEND; mutex_exit(&ahci_ctlp->ahcictl_mutex); return (DDI_SUCCESS); @@ -1464,7 +1463,7 @@ ahci_tran_probe_port(dev_info_t *dip, sata_device_t *sd) break; case SATA_DTYPE_PMULT: - ASSERT(AHCI_ADDR_IS_PORT(&addr)||AHCI_ADDR_IS_PMULT(&addr)); + ASSERT(AHCI_ADDR_IS_PORT(&addr) || AHCI_ADDR_IS_PMULT(&addr)); sd->satadev_type = SATA_DTYPE_PMULT; /* Update the number of pmports. */ @@ -1788,9 +1787,6 @@ fail_out: * * If SATA_OPMODE_POLLING flag is set, then we must poll the command * without interrupt, otherwise we can still use the interrupt. - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static int ahci_do_sync_start(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, @@ -1802,6 +1798,8 @@ ahci_do_sync_start(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, int instance = ddi_get_instance(ahci_ctlp->ahcictl_dip); uint8_t port = addrp->aa_port; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_do_sync_start enter: " "port %d:%d spkt 0x%p", port, addrp->aa_pmport, spkt); @@ -1809,7 +1807,7 @@ ahci_do_sync_start(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, ahci_portp->ahciport_flags |= AHCI_PORT_FLAG_POLLING; if ((rval = ahci_deliver_satapkt(ahci_ctlp, ahci_portp, addrp, spkt)) == AHCI_FAILURE) { - ahci_portp->ahciport_flags &= ~ AHCI_PORT_FLAG_POLLING; + ahci_portp->ahciport_flags &= ~AHCI_PORT_FLAG_POLLING; return (rval); } @@ -1883,9 +1881,6 @@ ahci_do_sync_start(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, * algorithm. * 1. REQUEST SENSE or READ LOG EXT command during error recovery process * 2. READ/WRITE PORTMULT command - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static int ahci_claim_free_slot(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, @@ -1895,6 +1890,8 @@ ahci_claim_free_slot(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, uint32_t free_slots; int slot; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_claim_free_slot enter " "ahciport_pending_tags = 0x%x " "ahciport_pending_ncq_tags = 0x%x", @@ -2041,8 +2038,6 @@ out: * Returns: * slot number if we can obtain a slot successfully * otherwise, return AHCI_FAILURE - * - * WARNING!!! ahciport_mutex should be acquired before the function is called. */ static int ahci_deliver_satapkt(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, @@ -2064,6 +2059,8 @@ ahci_deliver_satapkt(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, uint8_t *ptr2; #endif + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + port = addrp->aa_port; pmport = addrp->aa_pmport; @@ -2607,7 +2604,6 @@ ahci_tran_abort(dev_info_t *dip, sata_pkt_t *spkt, int flag) * during the reset operation. * * NOTE: ONLY called by ahci_tran_reset_dport - * WARNING!!! ahciport_mutex should be acquired before the function is called. */ static int ahci_reset_device_reject_pkts(ahci_ctl_t *ahci_ctlp, @@ -2620,6 +2616,8 @@ ahci_reset_device_reject_pkts(ahci_ctl_t *ahci_ctlp, sata_device_t sdevice; int ret; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_reset_device_reject_pkts on port: %d", port); @@ -2706,7 +2704,6 @@ ahci_reset_device_reject_pkts(ahci_ctl_t *ahci_ctlp, * during the reset operation. * * NOTE: ONLY called by ahci_tran_reset_dport - * WARNING!!! ahciport_mutex should be acquired before the function is called. */ static int ahci_reset_pmdevice_reject_pkts(ahci_ctl_t *ahci_ctlp, @@ -2717,6 +2714,8 @@ ahci_reset_pmdevice_reject_pkts(ahci_ctl_t *ahci_ctlp, uint8_t pmport = addrp->aa_pmport; sata_device_t sdevice; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY|AHCIDBG_PMULT, ahci_ctlp, "ahci_reset_pmdevice_reject_pkts at port %d:%d", port, pmport); @@ -2807,8 +2806,6 @@ ahci_reset_pmdevice_reject_pkts(ahci_ctl_t *ahci_ctlp, /* * Used to do port reset and reject all the pending packets on a port during * the reset operation. - * - * WARNING!!! ahciport_mutex should be acquired before the function is called. */ static int ahci_reset_port_reject_pkts(ahci_ctl_t *ahci_ctlp, @@ -2819,6 +2816,8 @@ ahci_reset_port_reject_pkts(ahci_ctl_t *ahci_ctlp, uint32_t finished_tags = 0; uint8_t port = addrp->aa_port; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_reset_port_reject_pkts at port: %d", port); @@ -3262,8 +3261,6 @@ ahci_tran_hotplug_port_deactivate(dev_info_t *dip, sata_device_t *satadev) /* * To be used to mark all the outstanding pkts with SATA_PKT_ABORTED * when a device is unplugged or a port is deactivated. - * - * WARNING!!! ahciport_mutex should be acquired before the function is called. */ static void ahci_reject_all_abort_pkts(ahci_ctl_t *ahci_ctlp, @@ -3272,6 +3269,8 @@ ahci_reject_all_abort_pkts(ahci_ctl_t *ahci_ctlp, uint32_t slot_status = 0; uint32_t abort_tags = 0; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY|AHCIDBG_INTR, ahci_ctlp, "ahci_reject_all_abort_pkts at port: %d", port); @@ -3425,7 +3424,7 @@ ahci_fm_fini(ahci_ctl_t *ahci_ctlp) /* Adjust access and dma attributes for FMA */ accattr.devacc_attr_access = DDI_DEFAULT_ACC; - buffer_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; + buffer_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; rcvd_fis_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; cmd_list_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; cmd_table_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; @@ -3484,23 +3483,33 @@ ahci_fm_ereport(ahci_ctl_t *ahci_ctlp, char *detail) } /* - * Check if all handles are correctly allocated. This function is only called - * by ahci_attach(), so we do not need hold any mutex here. + * Check if all handles are correctly allocated. */ static int ahci_check_all_handle(ahci_ctl_t *ahci_ctlp) { int port; + if (ahci_check_ctl_handle(ahci_ctlp) != DDI_SUCCESS) { return (DDI_FAILURE); } + for (port = 0; port < ahci_ctlp->ahcictl_num_ports; port++) { + ahci_port_t *ahci_portp; + if (!AHCI_PORT_IMPLEMENTED(ahci_ctlp, port)) continue; + + ahci_portp = ahci_ctlp->ahcictl_ports[port]; + + mutex_enter(&ahci_portp->ahciport_mutex); if (ahci_check_port_handle(ahci_ctlp, port) != DDI_SUCCESS) { + mutex_exit(&ahci_portp->ahciport_mutex); return (DDI_FAILURE); } + mutex_exit(&ahci_portp->ahciport_mutex); } + return (DDI_SUCCESS); } @@ -3522,14 +3531,15 @@ ahci_check_ctl_handle(ahci_ctl_t *ahci_ctlp) /* * Check the DMA handles and the access handles of a controller port. - * - * WARNING!!! ahciport_mutex should be acquired before the function is called. */ static int ahci_check_port_handle(ahci_ctl_t *ahci_ctlp, int port) { ahci_port_t *ahci_portp = ahci_ctlp->ahcictl_ports[port]; int slot; + + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + if ((ahci_check_dma_handle(ahci_portp-> ahciport_rcvd_fis_dma_handle) != DDI_FM_OK) || (ahci_check_dma_handle(ahci_portp-> @@ -3540,8 +3550,7 @@ ahci_check_port_handle(ahci_ctl_t *ahci_ctlp, int port) ahciport_cmd_list_acc_handle) != DDI_FM_OK)) { return (DDI_FAILURE); } - for (slot = 0; slot < ahci_ctlp->ahcictl_num_cmd_slots; - slot ++) { + for (slot = 0; slot < ahci_ctlp->ahcictl_num_cmd_slots; slot++) { if (ahci_check_slot_handle(ahci_portp, slot) != DDI_SUCCESS) { return (DDI_FAILURE); @@ -3552,12 +3561,12 @@ ahci_check_port_handle(ahci_ctl_t *ahci_ctlp, int port) /* * Check the DMA handles and the access handles of a cmd table slot. - * - * WARNING!!! ahciport_mutex should be acquired before the function is called. */ static int ahci_check_slot_handle(ahci_port_t *ahci_portp, int slot) { + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + if ((ahci_check_acc_handle(ahci_portp-> ahciport_cmd_tables_acc_handle[slot]) != DDI_FM_OK) || (ahci_check_dma_handle(ahci_portp-> @@ -3658,9 +3667,6 @@ ahci_drain_ports_taskq(ahci_ctl_t *ahci_ctlp) * PM_LEVEL_D0 and DDI_RESUME. The DDI_ATTACH case is different from * other two cases; device signature probing are attempted only during * DDI_ATTACH case. - * - * WARNING!!! Disable the whole controller's interrupts before calling and - * the interrupts will be enabled upon successfully return. */ static int ahci_initialize_controller(ahci_ctl_t *ahci_ctlp) @@ -3672,6 +3678,11 @@ ahci_initialize_controller(ahci_ctl_t *ahci_ctlp) AHCIDBG(AHCIDBG_INIT|AHCIDBG_ENTRY, ahci_ctlp, "ahci_initialize_controller enter", NULL); + /* Disable the whole controller interrupts */ + mutex_enter(&ahci_ctlp->ahcictl_mutex); + ahci_disable_all_intrs(ahci_ctlp); + mutex_exit(&ahci_ctlp->ahcictl_mutex); + /* Initialize the implemented ports and structures */ for (port = 0; port < ahci_ctlp->ahcictl_num_ports; port++) { if (!AHCI_PORT_IMPLEMENTED(ahci_ctlp, port)) { @@ -3760,8 +3771,6 @@ ahci_uninitialize_controller(ahci_ctl_t *ahci_ctlp) * 2. Allocate ahci_pmult_info structure. * * NOTE: Must stop port before the function is called. - * WARNING!!! ahciport_mutex should be acquired before the function is - * called. */ static void ahci_alloc_pmult(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) @@ -3769,6 +3778,8 @@ ahci_alloc_pmult(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) uint32_t port_cmd_status; uint8_t port = ahci_portp->ahciport_port_num; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + port_cmd_status = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle, (uint32_t *)AHCI_PORT_PxCMD(ahci_ctlp, port)); @@ -3802,8 +3813,6 @@ ahci_alloc_pmult(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) * 2. Deallocate ahci_pmult_info structure. * * NOTE: Must stop port before the function is called. - * WARNING!!! ahciport_mutex should be acquired before the function is - * called. */ static void ahci_dealloc_pmult(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) @@ -3811,6 +3820,8 @@ ahci_dealloc_pmult(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) uint32_t port_cmd_status; uint8_t port = ahci_portp->ahciport_port_num; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + port_cmd_status = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle, (uint32_t *)AHCI_PORT_PxCMD(ahci_ctlp, port)); @@ -3835,9 +3846,6 @@ ahci_dealloc_pmult(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) /* * Staggered Spin-up. - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static void ahci_staggered_spin_up(ahci_ctl_t *ahci_ctlp, uint8_t port) @@ -3845,6 +3853,8 @@ ahci_staggered_spin_up(ahci_ctl_t *ahci_ctlp, uint8_t port) uint32_t cap_status; uint32_t port_cmd_status; + ASSERT(MUTEX_HELD(&ahci_ctlp->ahcictl_ports[port]->ahciport_mutex)); + cap_status = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle, (uint32_t *)AHCI_GLOBAL_CAP(ahci_ctlp)); @@ -3869,15 +3879,13 @@ ahci_staggered_spin_up(ahci_ctl_t *ahci_ctlp, uint8_t port) } /* - * The routine is to initialize a port. First put the port in NOTRunning + * The routine is to initialize a port. First put the port in NotRunning * state, then enable port interrupt and clear Serror register. And under * AHCI_ATTACH case, find device signature and then try to start the port. * * Called by * 1. ahci_initialize_controller * 2. ahci_intr_phyrdy_change (hotplug) - * - * WARNING!!! ahciport_mutex should be acquired before the function is called. */ static int ahci_initialize_port(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, @@ -3888,7 +3896,7 @@ ahci_initialize_port(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, boolean_t resuming = B_TRUE; /* processing DDI_RESUME */ int ret; - ASSERT(mutex_owned(&ahci_portp->ahciport_mutex)); + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); /* AHCI_ADDR_PORT: We've no idea of the attached device here. */ ASSERT(AHCI_ADDR_IS_PORT(addrp)); @@ -4289,9 +4297,6 @@ ahci_config_space_init(ahci_ctl_t *ahci_ctlp) /* * Read/Write a register at port multiplier by SATA READ PORTMULT / SATA WRITE * PORTMULT command. SYNC & POLLING mode is used. - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static int ahci_rdwr_pmult(ahci_ctl_t *ahci_ctlp, ahci_addr_t *addrp, @@ -4314,7 +4319,7 @@ ahci_rdwr_pmult(ahci_ctl_t *ahci_ctlp, ahci_addr_t *addrp, ahci_portp = ahci_ctlp->ahcictl_ports[port]; ASSERT(AHCI_ADDR_IS_PMPORT(addrp) || AHCI_ADDR_IS_PMULT(addrp)); - ASSERT(mutex_owned(&ahci_portp->ahciport_mutex)); + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); /* Check the existence of the port multiplier */ if (ahci_portp->ahciport_device_type != SATA_DTYPE_PMULT) @@ -4455,14 +4460,14 @@ ahci_write_pmult(ahci_ctl_t *ahci_ctlp, ahci_addr_t *addrp, * Update sata registers on port multiplier, including GSCR/PSCR registers. * ahci_update_pmult_gscr() * ahci_update_pmult_pscr() - * - * WARNING!!! ahciport_mutex should be acquired before those functions - * get called. */ static int ahci_update_pmult_gscr(ahci_ctl_t *ahci_ctlp, ahci_addr_t *addrp, sata_pmult_gscr_t *sg) { + ASSERT(MUTEX_HELD( + &ahci_ctlp->ahcictl_ports[addrp->aa_port]->ahciport_mutex)); + READ_PMULT(addrp, SATA_PMULT_GSCR0, &sg->gscr0, err); READ_PMULT(addrp, SATA_PMULT_GSCR1, &sg->gscr1, err); READ_PMULT(addrp, SATA_PMULT_GSCR2, &sg->gscr2, err); @@ -4479,6 +4484,8 @@ ahci_update_pmult_pscr(ahci_ctl_t *ahci_ctlp, ahci_addr_t *addrp, sata_device_t *sd) { ASSERT(AHCI_ADDR_IS_PMPORT(addrp)); + ASSERT(MUTEX_HELD( + &ahci_ctlp->ahcictl_ports[addrp->aa_port]->ahciport_mutex)); READ_PMULT(addrp, SATA_PMULT_REG_SSTS, &sd->satadev_scr.sstatus, err); READ_PMULT(addrp, SATA_PMULT_REG_SERR, &sd->satadev_scr.serror, err); @@ -4497,9 +4504,6 @@ err: /* R/W PMULT error */ * Initialize a port multiplier, including * 1. Enable FEATURES register at port multiplier. (SATA Chp.16) * 2. Redefine MASK register. (SATA Chap 16.?) - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static int ahci_initialize_pmult(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, @@ -4509,7 +4513,8 @@ ahci_initialize_pmult(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, uint32_t gscr64; uint8_t port = addrp->aa_port; - ASSERT(mutex_owned(&ahci_portp->ahciport_mutex)); + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_INFO|AHCIDBG_PMULT, ahci_ctlp, "[Initialize] Port-multiplier at port %d.", port); @@ -4576,7 +4581,6 @@ err: /* R/W PMULT error */ * issue a COMRESET, then a software reset to get its signature. * * NOTE: This function should only be called in ahci_probe_pmport() - * WARNING!!! ahciport_mutex should be acquired before the function. */ static int ahci_initialize_pmport(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, @@ -4587,6 +4591,7 @@ ahci_initialize_pmport(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, uint8_t pmport = addrp->aa_pmport; int ret = AHCI_FAILURE; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); ASSERT(AHCI_ADDR_IS_PMPORT(addrp)); AHCIDBG(AHCIDBG_INIT|AHCIDBG_ENTRY, ahci_ctlp, @@ -4710,7 +4715,6 @@ out: * handle hotplug events on port multiplier ports. * * NOTE: Only called from ahci_tran_probe_port() - * WARNING!!! ahciport_mutex should be acquired before the function is called. */ static int ahci_probe_pmult(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, @@ -4724,6 +4728,8 @@ ahci_probe_pmult(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, uint8_t port = addrp->aa_port; int npmport; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + /* The bits in GSCR32 refers to the pmport that has a hot-plug event. */ READ_PMULT(addrp, SATA_PMULT_GSCR32, &gscr32, err); port_hotplug_tags = gscr32 & AHCI_PMPORT_MASK(ahci_portp); @@ -4846,9 +4852,6 @@ err: /* R/W PMULT error */ /* * Probe and initialize a port multiplier port. * A port multiplier port could only be initilaizer here. - * - * WARNING!!! ahcictl_mutex should be acquired before the function - * is called. */ static int ahci_probe_pmport(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, @@ -4858,6 +4861,8 @@ ahci_probe_pmport(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, uint8_t port = addrp->aa_port; ahci_addr_t addr_pmult; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + /* * Check the parent - port multiplier first. */ @@ -4930,9 +4935,6 @@ ahci_probe_pmport(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, * PxCMD.ST to clear PxCI. And before issuing the software reset, * the port must be idle and PxTFD.STS.BSY and PxTFD.STS.DRQ must be * cleared unless command list override (PxCMD.CLO) is supported. - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static int ahci_software_reset(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, @@ -4947,6 +4949,8 @@ ahci_software_reset(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, uint8_t pmport = addrp->aa_pmport; int rval = AHCI_FAILURE; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "port %d:%d device software resetting (FIS)", port, pmport); @@ -5183,8 +5187,9 @@ out: * this FIS, it updates PxTFD.STS and PxTFD.ERR register fields, and updates * the PxSIG register with the signature. * - * WARNING!!! ahciport_mutex should be acquired, and PxCMD.ST should be also - * cleared before the function is called. + * NOTE: It is expected both PxCMD.ST and PxCMD.CR are cleared before the + * function is called. If not, it is assumed the interface is in hung + * condition. */ static int ahci_port_reset(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, @@ -5200,6 +5205,8 @@ ahci_port_reset(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, int loop_count; int instance = ddi_get_instance(ahci_ctlp->ahcictl_dip); + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + /* Target is a port multiplier port? */ if (AHCI_ADDR_IS_PMPORT(addrp)) return (ahci_pmport_reset(ahci_ctlp, ahci_portp, addrp)); @@ -5684,8 +5691,7 @@ ahci_hba_reset(ahci_ctl_t *ahci_ctlp) * physical communication has been established so that the signature could * be retrieved by software reset. * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. And the port interrupt is disabled. + * NOTE: The port interrupts should be disabled before the function is called. */ static void ahci_find_dev_signature(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, @@ -5697,6 +5703,7 @@ ahci_find_dev_signature(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, uint8_t pmport = addrp->aa_pmport; int rval; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); ASSERT(AHCI_ADDR_IS_VALID(addrp)); /* @@ -5866,15 +5873,14 @@ ahci_disable_interface_pm(ahci_ctl_t *ahci_ctlp, uint8_t port) * Software shall not set PxCMD.ST to '1' unless a functional device is * present on the port(as determined by PxTFD.STS.BSY = '0', * PxTFD.STS.DRQ = '0', and PxSSTS.DET = 3h). - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static int ahci_start_port(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, uint8_t port) { uint32_t port_cmd_status; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_start_port: %d enter", port); if (ahci_portp->ahciport_port_state & SATA_PSTATE_FAILED) { @@ -5922,8 +5928,6 @@ ahci_start_port(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, uint8_t port) * Setup PxCLB, PxCLBU, PxFB, and PxFBU for particular port. First, we need * to make sure PxCMD.ST, PxCMD.CR, PxCMD.FRE, and PxCMD.FR are all cleared. * Then set PxCLB, PxCLBU, PxFB, and PxFBU. - * - * WARNING!!! ahciport_mutex should be acquired before the function is called. */ static int ahci_setup_port_base_addresses(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) @@ -5932,6 +5936,8 @@ ahci_setup_port_base_addresses(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) uint32_t port_cmd_status = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle, (uint32_t *)AHCI_PORT_PxCMD(ahci_ctlp, port)); + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + /* Step 1: Make sure both PxCMD.ST and PxCMD.CR are cleared. */ if (port_cmd_status & (AHCI_CMD_STATUS_ST | AHCI_CMD_STATUS_CR)) { if (ahci_put_port_into_notrunning_state(ahci_ctlp, ahci_portp, @@ -6003,9 +6009,6 @@ ahci_setup_port_base_addresses(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) * Allocate the ahci_port_t including Received FIS and Command List. * The argument - port is the physical port number, and not logical * port number seen by the SATA framework. - * - * WARNING!!! ahcictl_mutex should be acquired before the function - * is called. */ static int ahci_alloc_port_state(ahci_ctl_t *ahci_ctlp, uint8_t port) @@ -6014,6 +6017,8 @@ ahci_alloc_port_state(ahci_ctl_t *ahci_ctlp, uint8_t port) ahci_port_t *ahci_portp; char taskq_name[64] = "event_handle_taskq"; + ASSERT(MUTEX_HELD(&ahci_ctlp->ahcictl_mutex)); + ahci_portp = (ahci_port_t *)kmem_zalloc(sizeof (ahci_port_t), KM_SLEEP); @@ -6099,15 +6104,13 @@ err_case1: /* * Reverse of ahci_alloc_port_state(). - * - * WARNING!!! ahcictl_mutex should be acquired before the function - * is called. */ static void ahci_dealloc_port_state(ahci_ctl_t *ahci_ctlp, uint8_t port) { ahci_port_t *ahci_portp = ahci_ctlp->ahcictl_ports[port]; + ASSERT(MUTEX_HELD(&ahci_ctlp->ahcictl_mutex)); ASSERT(ahci_portp != NULL); mutex_enter(&ahci_portp->ahciport_mutex); @@ -6132,9 +6135,6 @@ ahci_dealloc_port_state(ahci_ctl_t *ahci_ctlp, uint8_t port) /* * Allocates memory for the Received FIS Structure - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static int ahci_alloc_rcvd_fis(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) @@ -6143,6 +6143,8 @@ ahci_alloc_rcvd_fis(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) size_t ret_len; uint_t cookie_count; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + rcvd_fis_size = sizeof (ahci_rcvd_fis_t); /* allocate rcvd FIS dma handle. */ @@ -6205,13 +6207,12 @@ ahci_alloc_rcvd_fis(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) /* * Deallocates the Received FIS Structure - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static void ahci_dealloc_rcvd_fis(ahci_port_t *ahci_portp) { + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + /* Unbind the cmd list dma handle first. */ (void) ddi_dma_unbind_handle(ahci_portp->ahciport_rcvd_fis_dma_handle); @@ -6226,9 +6227,6 @@ ahci_dealloc_rcvd_fis(ahci_port_t *ahci_portp) * Allocates memory for the Command List, which contains up to 32 entries. * Each entry contains a command header, which is a 32-byte structure that * includes the pointer to the command table. - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static int ahci_alloc_cmd_list(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) @@ -6237,6 +6235,8 @@ ahci_alloc_cmd_list(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) size_t ret_len; uint_t cookie_count; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + cmd_list_size = ahci_ctlp->ahcictl_num_cmd_slots * sizeof (ahci_cmd_header_t); @@ -6316,13 +6316,12 @@ err_out: /* * Deallocates the Command List - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static void ahci_dealloc_cmd_list(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) { + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + /* First dealloc command table */ ahci_dealloc_cmd_tables(ahci_ctlp, ahci_portp); @@ -6339,9 +6338,6 @@ ahci_dealloc_cmd_list(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) /* * Allocates memory for all Command Tables, which contains Command FIS, * ATAPI Command and Physical Region Descriptor Table. - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static int ahci_alloc_cmd_tables(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) @@ -6351,6 +6347,8 @@ ahci_alloc_cmd_tables(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) uint_t cookie_count; int slot; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_INIT|AHCIDBG_ENTRY, ahci_ctlp, "ahci_alloc_cmd_tables: port %d enter", ahci_portp->ahciport_port_num); @@ -6449,15 +6447,14 @@ err_out: /* * Deallocates memory for all Command Tables. - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static void ahci_dealloc_cmd_tables(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) { int slot; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_dealloc_cmd_tables: %d enter", ahci_portp->ahciport_port_num); @@ -6479,14 +6476,13 @@ ahci_dealloc_cmd_tables(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp) /* * Update SATA registers at controller ports - * - * WARNING!!! ahciport_mutex should be acquired before those functions - * get called. */ static void ahci_update_sata_registers(ahci_ctl_t *ahci_ctlp, uint8_t port, sata_device_t *sd) { + ASSERT(MUTEX_HELD(&ahci_ctlp->ahcictl_ports[port]->ahciport_mutex)); + sd->satadev_scr.sstatus = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle, (uint32_t *)(AHCI_PORT_PxSSTS(ahci_ctlp, port))); @@ -6999,9 +6995,6 @@ ahci_intr_set_device_bits(ahci_ctl_t *ahci_ctlp, /* * NCQ interrupt handler. Called upon a NCQ command is completed. * Only be called from ahci_intr_set_device_bits(). - * - * WARNING!!! ahciport_mutex should be acquired before the function is - * called. */ static int ahci_intr_ncq_events(ahci_ctl_t *ahci_ctlp, @@ -7975,13 +7968,12 @@ ahci_intr_cold_port_detect(ahci_ctl_t *ahci_ctlp, /* * Enable the interrupts for a particular port. - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static void ahci_enable_port_intrs(ahci_ctl_t *ahci_ctlp, uint8_t port) { + ASSERT(MUTEX_HELD(&ahci_ctlp->ahcictl_ports[port]->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_enable_port_intrs enter, port %d", port); @@ -8032,15 +8024,14 @@ ahci_enable_port_intrs(ahci_ctl_t *ahci_ctlp, uint8_t port) /* * Enable interrupts for all the ports. - * - * WARNING!!! ahcictl_mutex should be acquired before the function - * is called. */ static void ahci_enable_all_intrs(ahci_ctl_t *ahci_ctlp) { uint32_t ghc_control; + ASSERT(MUTEX_HELD(&ahci_ctlp->ahcictl_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_enable_all_intrs enter", NULL); ghc_control = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle, @@ -8054,13 +8045,13 @@ ahci_enable_all_intrs(ahci_ctl_t *ahci_ctlp) /* * Disable interrupts for a particular port. - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static void ahci_disable_port_intrs(ahci_ctl_t *ahci_ctlp, uint8_t port) { + ASSERT(ahci_ctlp->ahcictl_flags & AHCI_QUIESCE || + MUTEX_HELD(&ahci_ctlp->ahcictl_ports[port]->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_disable_port_intrs enter, port %d", port); @@ -8073,22 +8064,22 @@ ahci_disable_port_intrs(ahci_ctl_t *ahci_ctlp, uint8_t port) * * The global bit is cleared, then all interrupt sources from all * ports are disabled. - * - * WARNING!!! ahcictl_mutex should be acquired before the function - * is called. */ static void ahci_disable_all_intrs(ahci_ctl_t *ahci_ctlp) { uint32_t ghc_control; + ASSERT(ahci_ctlp->ahcictl_flags & (AHCI_ATTACH | AHCI_QUIESCE) || + MUTEX_HELD(&ahci_ctlp->ahcictl_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_disable_all_intrs enter", NULL); ghc_control = ddi_get32(ahci_ctlp->ahcictl_ahci_acc_handle, (uint32_t *)AHCI_GLOBAL_GHC(ahci_ctlp)); - ghc_control &= ~ AHCI_HBA_GHC_IE; + ghc_control &= ~AHCI_HBA_GHC_IE; ddi_put32(ahci_ctlp->ahcictl_ahci_acc_handle, (uint32_t *)AHCI_GLOBAL_GHC(ahci_ctlp), ghc_control); @@ -8301,7 +8292,7 @@ ahci_add_intrs(ahci_ctl_t *ahci_ctlp, int intr_type) * Removes the registered interrupts irrespective of whether they * were legacy or MSI. * - * WARNING!!! The controller interrupts must be disabled before calling + * NOTE: The controller interrupts must be disabled before calling * this routine. */ static void @@ -8338,9 +8329,6 @@ ahci_rem_intrs(ahci_ctl_t *ahci_ctlp) * This routine tries to put port into P:NotRunning state by clearing * PxCMD.ST. HBA will clear PxCI to 0h, PxSACT to 0h, PxCMD.CCS to 0h * and PxCMD.CR to '0'. - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static int ahci_put_port_into_notrunning_state(ahci_ctl_t *ahci_ctlp, @@ -8349,6 +8337,9 @@ ahci_put_port_into_notrunning_state(ahci_ctl_t *ahci_ctlp, uint32_t port_cmd_status; int loop_count; + ASSERT(ahci_ctlp->ahcictl_flags & AHCI_QUIESCE || + MUTEX_HELD(&ahci_ctlp->ahcictl_ports[port]->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_put_port_into_notrunning_state enter: port %d", port); @@ -8417,11 +8408,6 @@ ahci_put_port_into_notrunning_state(ahci_ctl_t *ahci_ctlp, * + Fatal error recovery * + To abort the timeout packet(s) * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. And ahciport_mutex will be released before the reset - * event is reported to sata module by calling sata_hba_event_notify, - * and then be acquired again later. - * * NOTES!!! During this procedure, PxSERR register will be cleared, and * according to the spec, the clearance of three bits will also clear * three interrupt status bits. @@ -8449,6 +8435,8 @@ ahci_restart_port_wait_till_ready(ahci_ctl_t *ahci_ctlp, int npmport = 0; uint8_t cport = ahci_ctlp->ahcictl_port_to_cport[port]; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_restart_port_wait_till_ready: port %d enter", port); @@ -8578,7 +8566,9 @@ out: * The COMRESET will make port multiplier enter legacy mode. * Issue a software reset to make it work again. */ + ahci_disable_port_intrs(ahci_ctlp, port); ahci_find_dev_signature(ahci_ctlp, ahci_portp, &addr_port); + ahci_enable_port_intrs(ahci_ctlp, port); /* * Following codes are specific for the port multiplier @@ -8692,8 +8682,6 @@ out: * * In all these scenarios, we need to send any pending unfinished * commands up to sata framework. - * - * WARNING!!! ahciport_mutex should be acquired before the function is called. */ static void ahci_mop_commands(ahci_ctl_t *ahci_ctlp, @@ -8712,6 +8700,8 @@ ahci_mop_commands(ahci_ctl_t *ahci_ctlp, int err_retri_cmd_in_progress = 0; int rdwr_pmult_cmd_in_progress = 0; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_ERRS|AHCIDBG_ENTRY, ahci_ctlp, "ahci_mop_commands entered: port: %d slot_status: 0x%x", ahci_portp->ahciport_port_num, slot_status); @@ -9112,7 +9102,7 @@ loop: ahci_portp->ahciport_err_retri_pkt = NULL; /* Remove the flag after READ LOG EXT command is completed */ - ahci_portp->ahciport_flags &= ~ AHCI_PORT_FLAG_RDLOGEXT; + ahci_portp->ahciport_flags &= ~AHCI_PORT_FLAG_RDLOGEXT; if (rdlog_spkt->satapkt_reason == SATA_PKT_COMPLETED) { /* Update the request log data */ @@ -9234,7 +9224,7 @@ loop: ahci_portp->ahciport_err_retri_pkt = NULL; /* Remove the flag after REQUEST SENSE command is completed */ - ahci_portp->ahciport_flags &= ~ AHCI_PORT_FLAG_RQSENSE; + ahci_portp->ahciport_flags &= ~AHCI_PORT_FLAG_RQSENSE; if (rs_spkt->satapkt_reason == SATA_PKT_COMPLETED) { /* Update the request sense data */ @@ -9291,8 +9281,6 @@ loop: * PxIS.HBDS - Host Bus Data Error Status * PxIS.HBFS - Host Bus Fatal Error Status * PxIS.TFES - Task File Error Status - * - * WARNING!!! ahciport_mutex should be acquired before the function is called. */ static void ahci_fatal_error_recovery_handler(ahci_ctl_t *ahci_ctlp, @@ -9313,6 +9301,8 @@ ahci_fatal_error_recovery_handler(ahci_ctl_t *ahci_ctlp, int instance = ddi_get_instance(ahci_ctlp->ahcictl_dip); int rval; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + AHCIDBG(AHCIDBG_ENTRY, ahci_ctlp, "ahci_fatal_error_recovery_handler enter: port %d", port); @@ -9488,9 +9478,6 @@ out: * Nothing will be done when Command-based switching is employed. * * Currently code is neither completed nor tested. - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static void ahci_pmult_error_recovery_handler(ahci_ctl_t *ahci_ctlp, @@ -9503,6 +9490,8 @@ ahci_pmult_error_recovery_handler(ahci_ctl_t *ahci_ctlp, int loop_count = 0; ahci_addr_t addr; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + /* Nothing will be done under Command-based switching. */ if (!(ahci_ctlp->ahcictl_cap & AHCI_CAP_PMULT_FBSS)) return; @@ -10237,6 +10226,8 @@ ahci_quiesce(dev_info_t *dip) ahci_debug_flags = 0; #endif + ahci_ctlp->ahcictl_flags |= AHCI_QUIESCE; + /* disable all the interrupts. */ ahci_disable_all_intrs(ahci_ctlp); @@ -10261,19 +10252,19 @@ ahci_quiesce(dev_info_t *dip) ahci_portp, port); } + ahci_ctlp->ahcictl_flags &= ~AHCI_QUIESCE; + return (DDI_SUCCESS); } /* * The function will add a sata packet to the done queue. - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static void ahci_add_doneq(ahci_port_t *ahci_portp, sata_pkt_t *satapkt, int reason) { ASSERT(satapkt != NULL); + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); /* set the reason for all packets */ satapkt->satapkt_reason = reason; @@ -10288,7 +10279,7 @@ ahci_add_doneq(ahci_port_t *ahci_portp, sata_pkt_t *satapkt, int reason) *ahci_portp->ahciport_doneqtail = satapkt; ahci_portp->ahciport_doneqtail = (sata_pkt_t **)&(satapkt->satapkt_hba_driver_private); - ahci_portp->ahciport_doneq_len ++; + ahci_portp->ahciport_doneq_len++; } else if ((satapkt->satapkt_op_mode & SATA_OPMODE_SYNCH) && ! (satapkt->satapkt_op_mode & SATA_OPMODE_POLLING)) @@ -10301,15 +10292,14 @@ ahci_add_doneq(ahci_port_t *ahci_portp, sata_pkt_t *satapkt, int reason) /* * The function will call completion callback of sata packet on the * completed queue - * - * WARNING!!! ahciport_mutex should be acquired before the function - * is called. */ static void ahci_flush_doneq(ahci_port_t *ahci_portp) { sata_pkt_t *satapkt, *next; + ASSERT(MUTEX_HELD(&ahci_portp->ahciport_mutex)); + if (ahci_portp->ahciport_doneq) { satapkt = ahci_portp->ahciport_doneq; diff --git a/usr/src/uts/common/sys/sata/adapters/ahci/ahcivar.h b/usr/src/uts/common/sys/sata/adapters/ahci/ahcivar.h index b28d0b6464..4e55863414 100644 --- a/usr/src/uts/common/sys/sata/adapters/ahci/ahcivar.h +++ b/usr/src/uts/common/sys/sata/adapters/ahci/ahcivar.h @@ -462,6 +462,7 @@ _NOTE(MUTEX_PROTECTS_DATA(ahci_ctl_t::ahcictl_mutex, #define AHCI_ATTACH 0x1 #define AHCI_DETACH 0x2 #define AHCI_SUSPEND 0x4 +#define AHCI_QUIESCE 0x8 /* Values for ahcictl_cap */ /* PIO Multiple DRQ Block */ |