diff options
author | randyf <none@none> | 2007-10-20 16:00:42 -0700 |
---|---|---|
committer | randyf <none@none> | 2007-10-20 16:00:42 -0700 |
commit | 2df1fe9ca32bb227b9158c67f5c00b54c20b10fd (patch) | |
tree | 358c576f885c00d42a760d9e35e5b66e77209fe2 /usr/src/uts/common/io/sata | |
parent | 10b3fbf593a6678eec9b50a01903ef4eb73111e4 (diff) | |
download | illumos-joyent-2df1fe9ca32bb227b9158c67f5c00b54c20b10fd.tar.gz |
PSARC/2005/469 X86 Energy Star compliance
PSARC/2006/632 PSMI extension for state save and restore
6330209 nge needs to support DDI_SUSPEND/DDI_RESUME
6381827 Suspend to RAM on x86
6393154 audio810 needs to support DDI_SUSPEND/DDI_RESUME
6397047 fd, fdc needs to support Suspend/Resume
6401974 cannot enter S3 with ohci PME enable set on Tyan 2865 with Sun or Tyan 2.01 BIOS
6422613 memscrubber doesn't re-acquire lock before CALLB_CPR_EXIT
6455736 ata/dadk/cmdk should support DDI_SUSPEND/DDI_RESUME
6511370 CPR on SPARC regression
6586018 TODOP Macros in i86pc/sys/machclock.h not in sun4u/sun4v equivilent (Sparc only)
6610124 It takes more than 3 minutes after printing "pci_pre_resume nv_sata:0"
6617143 powerd/pmconfig emits a different default message for an existing on or off action.
--HG--
rename : usr/src/cmd/power/power.conf => usr/src/cmd/power/power.conf.sparc
Diffstat (limited to 'usr/src/uts/common/io/sata')
-rw-r--r-- | usr/src/uts/common/io/sata/adapters/nv_sata/nv_sata.c | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/usr/src/uts/common/io/sata/adapters/nv_sata/nv_sata.c b/usr/src/uts/common/io/sata/adapters/nv_sata/nv_sata.c index fa303ca9b5..f6d5870c5c 100644 --- a/usr/src/uts/common/io/sata/adapters/nv_sata/nv_sata.c +++ b/usr/src/uts/common/io/sata/adapters/nv_sata/nv_sata.c @@ -138,6 +138,7 @@ static void nv_read_signature(nv_port_t *nvp); static void mcp55_set_intr(nv_port_t *nvp, int flag); static void mcp04_set_intr(nv_port_t *nvp, int flag); static void nv_resume(nv_port_t *nvp); +static void nv_suspend(nv_port_t *nvp); static int nv_start_sync(nv_port_t *nvp, sata_pkt_t *spkt); static int nv_abort_active(nv_port_t *nvp, sata_pkt_t *spkt, int abort_reason); static void nv_copy_registers(nv_port_t *nvp, sata_device_t *sd, @@ -400,7 +401,7 @@ nv_get8(ddi_acc_handle_t handle, uint8_t *dev_addr) static int nv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { - int status, attach_state, intr_types, bar, i; + int status, attach_state, intr_types, bar, i, command; int inst = ddi_get_instance(dip); ddi_acc_handle_t pci_conf_handle; nv_ctl_t *nvc; @@ -439,6 +440,20 @@ nv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) attach_state |= ATTACH_PROGRESS_CONF_HANDLE; + /* + * If a device is attached after a suspend/resume, sometimes + * the command register is zero, as it might not be set by + * BIOS or a parent. Set it again here. + */ + command = pci_config_get16(pci_conf_handle, PCI_CONF_COMM); + + if (command == 0) { + cmn_err(CE_WARN, "nv_sata%d: restoring PCI command" + " register", inst); + pci_config_put16(pci_conf_handle, PCI_CONF_COMM, + PCI_COMM_IO|PCI_COMM_MAE|PCI_COMM_ME); + } + subclass = pci_config_get8(pci_conf_handle, PCI_CONF_SUBCLASS); if (subclass & PCI_MASS_RAID) { @@ -585,7 +600,6 @@ nv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) NVLOG((NVDBG_INIT, nvc, NULL, "nv_attach(): DDI_RESUME inst %d", inst)); - nvc->nvc_state &= ~NV_CTRL_SUSPEND; for (i = 0; i < NV_MAX_PORTS(nvc); i++) { @@ -716,6 +730,11 @@ nv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) * the current state. */ NVLOG((NVDBG_INIT, nvc, NULL, "nv_detach: DDI_SUSPEND")); + + for (i = 0; i < NV_MAX_PORTS(nvc); i++) { + nv_suspend(&(nvc->nvc_port[i])); + } + nvc->nvc_state |= NV_CTRL_SUSPEND; return (DDI_SUCCESS); @@ -1226,7 +1245,7 @@ nv_start_sync(nv_port_t *nvp, sata_pkt_t *spkt) (*(nvc->nvc_set_intr))(nvp, NV_INTR_ENABLE); NVLOG((NVDBG_SYNC, nvp->nvp_ctlp, nvp, "nv_sata_satapkt_sync:" - " done % reason %d", ret)); + " done % reason %d", ret)); return (ret); } @@ -2725,7 +2744,7 @@ mcp55_dma_setup_intr(nv_ctl_t *nvc, nv_port_t *nvp) MCP_SATA_AE_NCQ_SDEV_DMA_SETUP_TAG_SHIFT}; nv_cmn_err(CE_PANIC, nvc, nvp, - "this is should not be executed at all until NCQ"); + "this is should not be executed at all until NCQ"); mutex_enter(&nvp->nvp_mutex); @@ -4576,6 +4595,38 @@ nv_resume(nv_port_t *nvp) * nv_reset(nvp); */ + nv_reset(nvp); + + mutex_exit(&nvp->nvp_mutex); +} + +/* + * The PM functions for suspend and resume are incomplete and need additional + * work. It may or may not work in the current state. + */ +static void +nv_suspend(nv_port_t *nvp) +{ + NVLOG((NVDBG_INIT, nvp->nvp_ctlp, nvp, "nv_suspend()")); + + mutex_enter(&nvp->nvp_mutex); + + if (nvp->nvp_state & NV_PORT_INACTIVE) { + mutex_exit(&nvp->nvp_mutex); + + return; + } + + (*(nvp->nvp_ctlp->nvc_set_intr))(nvp, NV_INTR_DISABLE); + + /* + * power may have been removed to the port and the + * drive, and/or a drive may have been added or removed. + * Force a reset which will cause a probe and re-establish + * any state needed on the drive. + * nv_reset(nvp); + */ + mutex_exit(&nvp->nvp_mutex); } |