summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/sata
diff options
context:
space:
mode:
authorrandyf <none@none>2007-10-20 16:00:42 -0700
committerrandyf <none@none>2007-10-20 16:00:42 -0700
commit2df1fe9ca32bb227b9158c67f5c00b54c20b10fd (patch)
tree358c576f885c00d42a760d9e35e5b66e77209fe2 /usr/src/uts/common/io/sata
parent10b3fbf593a6678eec9b50a01903ef4eb73111e4 (diff)
downloadillumos-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.c59
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);
}