summaryrefslogtreecommitdiffstats
path: root/sys/dev/twa
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2007-10-09 17:43:57 +0000
committerscottl <scottl@FreeBSD.org>2007-10-09 17:43:57 +0000
commit14e26607a4e9b3c0e753e6147f5c694a3852681a (patch)
tree0a6f47e0b56078f5f11728ccdc3d57a67da1375f /sys/dev/twa
parentf415c5c6969c1dce8c2f39f697a61c2efe489fea (diff)
downloadFreeBSD-src-14e26607a4e9b3c0e753e6147f5c694a3852681a.zip
FreeBSD-src-14e26607a4e9b3c0e753e6147f5c694a3852681a.tar.gz
Update to version 3.70.03.007 from the vendor. This adds support for new
SAS-enabled cards. It also makes the driver MPSAFE, eliminating some problems that resulted from CAM becoming MPSAFE. Many thanks to 3Ware/AMCC for continuing to support FreeBSD. Submitted by: Manjunath Ranganathaiah Approved by: re
Diffstat (limited to 'sys/dev/twa')
-rw-r--r--sys/dev/twa/tw_cl_init.c8
-rw-r--r--sys/dev/twa/tw_cl_intr.c6
-rw-r--r--sys/dev/twa/tw_cl_io.c15
-rw-r--r--sys/dev/twa/tw_cl_misc.c12
-rw-r--r--sys/dev/twa/tw_cl_share.h2
-rw-r--r--sys/dev/twa/tw_osl.h5
-rw-r--r--sys/dev/twa/tw_osl_cam.c88
-rw-r--r--sys/dev/twa/tw_osl_freebsd.c14
-rw-r--r--sys/dev/twa/tw_osl_share.h2
9 files changed, 89 insertions, 63 deletions
diff --git a/sys/dev/twa/tw_cl_init.c b/sys/dev/twa/tw_cl_init.c
index c7ac898..52864b2 100644
--- a/sys/dev/twa/tw_cl_init.c
+++ b/sys/dev/twa/tw_cl_init.c
@@ -32,6 +32,7 @@
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
+ * Modifications by: Manjunath Ranganathaiah
*/
@@ -65,7 +66,8 @@ tw_cl_ctlr_supported(TW_INT32 vendor_id, TW_INT32 device_id)
if ((vendor_id == TW_CL_VENDOR_ID) &&
((device_id == TW_CL_DEVICE_ID_9K) ||
(device_id == TW_CL_DEVICE_ID_9K_X) ||
- (device_id == TW_CL_DEVICE_ID_9K_E)))
+ (device_id == TW_CL_DEVICE_ID_9K_E) ||
+ (device_id == TW_CL_DEVICE_ID_9K_SA)))
return(TW_CL_TRUE);
return(TW_CL_FALSE);
}
@@ -116,6 +118,7 @@ tw_cl_get_pci_bar_info(TW_INT32 device_id, TW_INT32 bar_type,
case TW_CL_DEVICE_ID_9K_X:
case TW_CL_DEVICE_ID_9K_E:
+ case TW_CL_DEVICE_ID_9K_SA:
switch(bar_type) {
case TW_CL_BAR_TYPE_IO:
*bar_num = 2;
@@ -332,7 +335,8 @@ tw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags,
if ((ctlr->flags & TW_CL_64BIT_ADDRESSES) &&
((ctlr->device_id == TW_CL_DEVICE_ID_9K) ||
(ctlr->device_id == TW_CL_DEVICE_ID_9K_X) ||
- (ctlr->device_id == TW_CL_DEVICE_ID_9K_E))) {
+ (ctlr->device_id == TW_CL_DEVICE_ID_9K_E) ||
+ (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA))) {
ctlr->state |= TW_CLI_CTLR_STATE_G66_WORKAROUND_NEEDED;
ctlr->intr_lock = ctlr->io_lock;
} else {
diff --git a/sys/dev/twa/tw_cl_intr.c b/sys/dev/twa/tw_cl_intr.c
index 864af35..44b4c14 100644
--- a/sys/dev/twa/tw_cl_intr.c
+++ b/sys/dev/twa/tw_cl_intr.c
@@ -32,6 +32,7 @@
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
+ * Modifications by: Manjunath Ranganathaiah
*/
@@ -74,6 +75,11 @@ tw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle)
if (ctlr == NULL)
goto out;
+ /* If we get an interrupt while resetting, it is a shared
+ one for another device, so just bail */
+ if (ctlr->state & TW_CLI_CTLR_STATE_RESET_IN_PROGRESS)
+ goto out;
+
/*
* Synchronize access between writes to command and control registers
* in 64-bit environments, on G66.
diff --git a/sys/dev/twa/tw_cl_io.c b/sys/dev/twa/tw_cl_io.c
index 49ffbe3..162b1ea 100644
--- a/sys/dev/twa/tw_cl_io.c
+++ b/sys/dev/twa/tw_cl_io.c
@@ -32,6 +32,7 @@
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
+ * Modifications by: Manjunath Ranganathaiah
*/
@@ -178,7 +179,8 @@ tw_cli_submit_cmd(struct tw_cli_req_context *req)
tw_osl_get_lock(ctlr_handle, ctlr->io_lock);
/* For 9650SE first write low 4 bytes */
- if (ctlr->device_id == TW_CL_DEVICE_ID_9K_E)
+ if ((ctlr->device_id == TW_CL_DEVICE_ID_9K_E) ||
+ (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA))
tw_osl_write_reg(ctlr_handle,
TWA_COMMAND_QUEUE_OFFSET_LOW,
(TW_UINT32)(req->cmd_pkt_phys + sizeof(struct tw_cl_command_header)), 4);
@@ -220,7 +222,8 @@ tw_cli_submit_cmd(struct tw_cli_req_context *req)
req->state = TW_CLI_REQ_STATE_BUSY;
tw_cli_req_q_insert_tail(req, TW_CLI_BUSY_Q);
- if (ctlr->device_id == TW_CL_DEVICE_ID_9K_E) {
+ if ((ctlr->device_id == TW_CL_DEVICE_ID_9K_E) ||
+ (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA)) {
/* Now write the high 4 bytes */
tw_osl_write_reg(ctlr_handle,
TWA_COMMAND_QUEUE_OFFSET_HIGH,
@@ -352,7 +355,10 @@ tw_cl_fw_passthru(struct tw_cl_ctlr_handle *ctlr_handle,
(TW_UINT8)(TW_CL_SWAP16(req->request_id));
if ((sgl_offset =
GET_SGL_OFF(cmd_7k->generic.sgl_off__opcode))) {
- sgl = (((TW_UINT32 *)cmd_7k) + sgl_offset);
+ if (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA)
+ sgl = (((TW_UINT32 *)cmd_7k) + cmd_7k->generic.size);
+ else
+ sgl = (((TW_UINT32 *)cmd_7k) + sgl_offset);
cmd_7k->generic.size += pt_req->sgl_entries *
((ctlr->flags & TW_CL_64BIT_ADDRESSES) ? 3 : 2);
}
@@ -1173,7 +1179,8 @@ tw_cli_soft_reset(struct tw_cli_ctlr_context *ctlr)
TW_CLI_SOFT_RESET(ctlr_handle);
if ((ctlr->device_id == TW_CL_DEVICE_ID_9K_X) ||
- (ctlr->device_id == TW_CL_DEVICE_ID_9K_E)) {
+ (ctlr->device_id == TW_CL_DEVICE_ID_9K_E) ||
+ (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA)) {
/*
* There's a hardware bug in the G133 ASIC, which can lead to
* PCI parity errors and hangs, if the host accesses any
diff --git a/sys/dev/twa/tw_cl_misc.c b/sys/dev/twa/tw_cl_misc.c
index 5948b1d..1ee8120 100644
--- a/sys/dev/twa/tw_cl_misc.c
+++ b/sys/dev/twa/tw_cl_misc.c
@@ -32,6 +32,7 @@
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
+ * Modifications by: Manjunath Ranganathaiah
*/
@@ -760,6 +761,12 @@ tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg)
TW_INT8 desc[200];
tw_osl_memzero(desc, 200);
+
+ /* Skip queue error msgs during 9650SE/9690SA reset */
+ if (((ctlr->device_id != TW_CL_DEVICE_ID_9K_E) &&
+ (ctlr->device_id != TW_CL_DEVICE_ID_9K_SA)) ||
+ ((ctlr->state & TW_CLI_CTLR_STATE_RESET_IN_PROGRESS) == 0) ||
+ ((status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) == 0))
tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
0x1302, 0x1, TW_CL_SEVERITY_ERROR_STRING,
@@ -809,7 +816,10 @@ tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg)
}
if (status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) {
- if (ctlr->device_id != TW_CL_DEVICE_ID_9K_E)
+ /* Skip queue error msgs during 9650SE/9690SA reset */
+ if (((ctlr->device_id != TW_CL_DEVICE_ID_9K_E) &&
+ (ctlr->device_id != TW_CL_DEVICE_ID_9K_SA)) ||
+ ((ctlr->state & TW_CLI_CTLR_STATE_RESET_IN_PROGRESS) == 0))
tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
0x1305, 0x1, TW_CL_SEVERITY_ERROR_STRING,
diff --git a/sys/dev/twa/tw_cl_share.h b/sys/dev/twa/tw_cl_share.h
index bb9daa4..265ff77 100644
--- a/sys/dev/twa/tw_cl_share.h
+++ b/sys/dev/twa/tw_cl_share.h
@@ -32,6 +32,7 @@
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
+ * Modifications by: Manjunath Ranganathaiah
*/
@@ -54,6 +55,7 @@
#define TW_CL_DEVICE_ID_9K 0x1002 /* 9000 PCI series device id */
#define TW_CL_DEVICE_ID_9K_X 0x1003 /* 9000 PCI-X series device id */
#define TW_CL_DEVICE_ID_9K_E 0x1004 /* 9000 PCIe series device id */
+#define TW_CL_DEVICE_ID_9K_SA 0x1005 /* 9000 PCIe SAS series device id */
#define TW_CL_BAR_TYPE_IO 1 /* I/O base address */
#define TW_CL_BAR_TYPE_MEM 2 /* memory base address */
diff --git a/sys/dev/twa/tw_osl.h b/sys/dev/twa/tw_osl.h
index 7c26828..5718311 100644
--- a/sys/dev/twa/tw_osl.h
+++ b/sys/dev/twa/tw_osl.h
@@ -32,6 +32,7 @@
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
+ * Modifications by: Manjunath Ranganathaiah
*/
@@ -52,7 +53,7 @@
#define TW_OSLI_MAX_NUM_IOS TW_CL_MAX_SIMULTANEOUS_REQUESTS
#define TW_OSLI_MAX_NUM_AENS 0x100
-//#define TW_OSLI_DEFERRED_INTR_USED
+#define TW_OSLI_DEFERRED_INTR_USED
/* Possible values of req->state. */
#define TW_OSLI_REQ_STATE_INIT 0x0 /* being initialized */
@@ -143,6 +144,8 @@ struct twa_softc {
struct mtx *io_lock;/* ptr to general purpose lock */
struct mtx q_lock_handle; /* queue manipulation lock */
struct mtx *q_lock;/* ptr to queue manipulation lock */
+ struct mtx sim_lock_handle;/* sim lock shared with cam */
+ struct mtx *sim_lock;/* ptr to sim lock */
#ifdef TW_OSL_DEBUG
struct tw_osli_q_stats q_stats[TW_OSLI_Q_COUNT];/* queue statistics */
diff --git a/sys/dev/twa/tw_osl_cam.c b/sys/dev/twa/tw_osl_cam.c
index aaa1d51..b7a085f 100644
--- a/sys/dev/twa/tw_osl_cam.c
+++ b/sys/dev/twa/tw_osl_cam.c
@@ -32,6 +32,7 @@
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
+ * Modifications by: Manjunath Ranganathaiah
*/
@@ -54,8 +55,6 @@
static TW_VOID twa_action(struct cam_sim *sim, union ccb *ccb);
static TW_VOID twa_poll(struct cam_sim *sim);
-static TW_VOID twa_async(TW_VOID *callback_arg, TW_UINT32 code,
- struct cam_path *path, TW_VOID *arg);
static TW_VOID twa_timeout(TW_VOID *arg);
static TW_VOID twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
@@ -77,7 +76,6 @@ TW_INT32
tw_osli_cam_attach(struct twa_softc *sc)
{
struct cam_devq *devq;
- struct ccb_setasync csa;
TW_INT32 error;
tw_osli_dbg_dprintf(3, sc, "entered");
@@ -103,7 +101,7 @@ tw_osli_cam_attach(struct twa_softc *sc)
*/
tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
- device_get_unit(sc->bus_dev), &Giant,
+ device_get_unit(sc->bus_dev), sc->sim_lock,
TW_OSLI_MAX_NUM_IOS - 1, 1, devq);
if (sc->sim == NULL) {
cam_simq_free(devq);
@@ -120,7 +118,7 @@ tw_osli_cam_attach(struct twa_softc *sc)
* Register the bus.
*/
tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
- mtx_lock(&Giant);
+ mtx_lock(sc->sim_lock);
if (xpt_bus_register(sc->sim, sc->bus_dev, 0) != CAM_SUCCESS) {
cam_sim_free(sc->sim, TRUE);
sc->sim = NULL; /* so cam_detach will not try to free it */
@@ -130,7 +128,7 @@ tw_osli_cam_attach(struct twa_softc *sc)
0x2102,
"Failed to register the bus",
ENXIO);
- mtx_unlock(&Giant);
+ mtx_unlock(sc->sim_lock);
return(ENXIO);
}
@@ -148,18 +146,12 @@ tw_osli_cam_attach(struct twa_softc *sc)
0x2103,
"Failed to create path",
ENXIO);
- mtx_unlock(&Giant);
+ mtx_unlock(sc->sim_lock);
return(ENXIO);
}
tw_osli_dbg_dprintf(3, sc, "Calling xpt_setup_ccb");
- xpt_setup_ccb(&csa.ccb_h, sc->path, 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE;
- csa.callback = twa_async;
- csa.callback_arg = sc;
- xpt_action((union ccb *)&csa);
- mtx_unlock(&Giant);
+ mtx_unlock(sc->sim_lock);
tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan");
/*
@@ -193,7 +185,16 @@ tw_osli_cam_detach(struct twa_softc *sc)
{
tw_osli_dbg_dprintf(3, sc, "entered");
- mtx_lock(&Giant);
+#ifdef TW_OSLI_DEFERRED_INTR_USED
+ /* - drain the taskqueue
+ Ctrl is already went down so, no more enqueuetask will
+ happen . Don't hold any locks, that task might need.
+ */
+
+ taskqueue_drain(taskqueue_fast, &(sc->deferred_intr_callback));
+#endif
+ mtx_lock(sc->sim_lock);
+
if (sc->path)
xpt_free_path(sc->path);
if (sc->sim) {
@@ -201,7 +202,8 @@ tw_osli_cam_detach(struct twa_softc *sc)
/* Passing TRUE to cam_sim_free will free the devq as well. */
cam_sim_free(sc->sim, TRUE);
}
- mtx_unlock(&Giant);
+ /* It's ok have 1 hold count while destroying the mutex */
+ mtx_destroy(sc->sim_lock);
}
@@ -395,6 +397,7 @@ twa_action(struct cam_sim *sim, union ccb *ccb)
"Received Reset Bus request from CAM",
" ");
+ mtx_unlock(sc->sim_lock);
if (tw_cl_reset_ctlr(&sc->ctlr_handle)) {
tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
@@ -406,6 +409,7 @@ twa_action(struct cam_sim *sim, union ccb *ccb)
else
ccb_h->status = CAM_REQ_CMP;
+ mtx_lock(sc->sim_lock);
xpt_done(ccb);
break;
@@ -521,33 +525,6 @@ twa_poll(struct cam_sim *sim)
/*
- * Function name: twa_async
- * Description: Driver entry point for CAM to notify driver of special
- * events. We don't use this for now.
- *
- * Input: callback_arg -- ptr to per ctlr structure
- * code -- code associated with the event
- * path -- cam path
- * arg --
- * Output: None
- * Return value: 0 -- success
- * non-zero-- failure
- */
-TW_VOID
-twa_async(TW_VOID *callback_arg, TW_UINT32 code,
- struct cam_path *path, TW_VOID *arg)
-{
-#ifdef TW_OSL_DEBUG
- struct twa_softc *sc = (struct twa_softc *)callback_arg;
-#endif /* TW_OSL_DEBUG */
-
- tw_osli_dbg_dprintf(3, sc, "sc = %p, code = %x, path = %p, arg = %p",
- sc, code, path, arg);
-}
-
-
-
-/*
* Function name: twa_timeout
* Description: Driver entry point for being alerted on a request
* timing out.
@@ -595,20 +572,26 @@ tw_osli_request_bus_scan(struct twa_softc *sc)
if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
return(ENOMEM);
bzero(ccb, sizeof(union ccb));
- mtx_lock(&Giant);
+ mtx_lock(sc->sim_lock);
if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim),
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
free(ccb, M_TEMP);
- mtx_unlock(&Giant);
+ mtx_unlock(sc->sim_lock);
return(EIO);
}
+ /* Release simq at the end of a reset */
+ if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) {
+ xpt_release_simq(sc->sim, 1);
+ sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
+ }
+
xpt_setup_ccb(&ccb->ccb_h, path, 5);
ccb->ccb_h.func_code = XPT_SCAN_BUS;
ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
ccb->crcn.flags = CAM_FLAG_NONE;
xpt_action(ccb);
- mtx_unlock(&Giant);
+ mtx_unlock(sc->sim_lock);
return(0);
}
@@ -673,10 +656,13 @@ tw_osli_allow_new_requests(struct twa_softc *sc, TW_VOID *ccb)
TW_VOID
tw_osli_disallow_new_requests(struct twa_softc *sc)
{
- mtx_lock(&Giant);
- xpt_freeze_simq(sc->sim, 1);
- mtx_unlock(&Giant);
- sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
+ /* Don't double freeze if already frozen */
+ if ((sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) == 0) {
+ mtx_lock(sc->sim_lock);
+ xpt_freeze_simq(sc->sim, 1);
+ mtx_unlock(sc->sim_lock);
+ sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
+ }
}
@@ -813,7 +799,9 @@ tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
}
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+ mtx_lock(sc->sim_lock);
xpt_done(ccb);
+ mtx_unlock(sc->sim_lock);
if (! req->error_code)
/* twa_action will free the request otherwise */
tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
diff --git a/sys/dev/twa/tw_osl_freebsd.c b/sys/dev/twa/tw_osl_freebsd.c
index 98ac6cc..4b098ae 100644
--- a/sys/dev/twa/tw_osl_freebsd.c
+++ b/sys/dev/twa/tw_osl_freebsd.c
@@ -34,6 +34,7 @@
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
+ * Modifications by: Manjunath Ranganathaiah
*/
@@ -281,6 +282,8 @@ twa_attach(device_t dev)
mtx_init(sc->io_lock, "tw_osl_io_lock", NULL, MTX_SPIN);
sc->q_lock = &(sc->q_lock_handle);
mtx_init(sc->q_lock, "tw_osl_q_lock", NULL, MTX_SPIN);
+ sc->sim_lock = &(sc->sim_lock_handle);
+ mtx_init(sc->sim_lock, "tw_osl_sim_lock", NULL, MTX_DEF | MTX_RECURSE);
sysctl_ctx_init(&sc->sysctl_ctxt);
sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctxt,
@@ -359,10 +362,11 @@ twa_attach(device_t dev)
return(ENXIO);
}
if ((error = bus_setup_intr(sc->bus_dev, sc->irq_res,
- INTR_TYPE_CAM,
#ifdef TW_OSLI_DEFERRED_INTR_USED
+ INTR_TYPE_CAM | INTR_FAST,
twa_pci_intr_fast, NULL,
#else
+ INTR_TYPE_CAM | INTR_MPSAFE,
NULL, twa_pci_intr,
#endif
sc, &sc->intr_handle))) {
@@ -877,7 +881,8 @@ twa_pci_intr_fast(TW_VOID *arg)
tw_osli_dbg_dprintf(10, sc, "entered");
if (tw_cl_interrupt(&(sc->ctlr_handle))) {
- tw_cl_deferred_interrupt(&(sc->ctlr_handle));
+ taskqueue_enqueue_fast(taskqueue_fast,
+ &(sc->deferred_intr_callback));
return(FILTER_HANDLED);
}
return(FILTER_STRAY);
@@ -1051,10 +1056,11 @@ tw_osli_fw_passthru(struct twa_softc *sc, TW_INT8 *buf)
/*
* Don't touch req after a reset. It (and any
* associated data) will already have been
- * freed by the callback. Just return.
+ * unmapped by the callback.
*/
user_buf->driver_pkt.os_status = error;
- return(ETIMEDOUT);
+ error = ETIMEDOUT;
+ goto fw_passthru_err;
}
/*
* Either the request got completed, or we were woken up by a
diff --git a/sys/dev/twa/tw_osl_share.h b/sys/dev/twa/tw_osl_share.h
index 0cfc90d..08276d0 100644
--- a/sys/dev/twa/tw_osl_share.h
+++ b/sys/dev/twa/tw_osl_share.h
@@ -75,7 +75,7 @@
#define TW_OSL_ENCLOSURE_SUPPORT
#endif
-#define TW_OSL_DRIVER_VERSION_STRING "3.70.03.007"
+#define TW_OSL_DRIVER_VERSION_STRING "3.70.05.001"
#define TW_OSL_CAN_SLEEP
OpenPOWER on IntegriCloud